Skip to content

Commit 22a7de1

Browse files
authored
feat: add an expressive-code plugin to support marks in code block (#62)
* feat: add expressive-code plugin for marks in code block * feat: load cxx-mark-plugin in astro config * fix: remove redundant empty line * style: reformat code * fix: move expressive-code options to ec.config.mjs * style: reformat code * fix: fix incorrect behavior when content contains '*' * style: use camelCase; rename expos to e, since we will possibly never add new markers * feat: add doc for cxx mark feature
1 parent 181aa7e commit 22a7de1

File tree

5 files changed

+150
-0
lines changed

5 files changed

+150
-0
lines changed

ec.config.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// @ts-check
2+
import { pluginCxxMark } from "./src/plugins/expressive-code/cxx-mark.ts";
3+
4+
/** @type {import('@astrojs/starlight/expressive-code').StarlightExpressiveCodeOptions} */
5+
export default {
6+
plugins: [pluginCxxMark()],
7+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
```cpp cxx-mark
2+
// syntax of for statement
3+
/*$s:attr*//*$opt*/ for ( /*$s:init-statement*/ /*$s:condition*//*$opt*/ ; /*$s:expression*//*$opt*/ ) /*$s:statement*/
4+
5+
// exposition only alias template of conditionally const type
6+
template< bool Const, class T >
7+
using /*$e:maybe-const*/ = std::conditional_t<Const, const T, T>;
8+
```

src/content/docs/development/guide/doc-everything.mdx

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,75 @@ import declDocExample3 from "@src/assets/examples/development/guide/decl-doc-3.m
139139
Don't forget the `autorevSince` attribute on the `DeclDoc` component! Presence of this attribute allows [autorev](./revision#autorev) to automatically show and hide the `DeclDoc` component according to the user-selected revision.
140140
</Aside>
141141

142+
## Code block inline markers
143+
144+
Special comments can be embedded within Markdown code blocks to specify part of codes has special meanings. Enable this feature by adding `cxx-mark` after the language name of code block's opening fence:
145+
146+
import cxxMarkExample1 from "@src/assets/examples/development/guide/cxx-mark-1.mdx?raw";
147+
148+
<Code code={cxxMarkExample1} lang="mdx" />
149+
150+
<Card title="Preview">
151+
```cpp cxx-mark
152+
// syntax of for statement
153+
/*$s:attr*//*$opt*/ for ( /*$s:init-statement*/ /*$s:condition*//*$opt*/ ; /*$s:expression*//*$opt*/ ) /*$s:statement*/
154+
155+
// exposition only alias template of conditionally const type
156+
template< bool Const, class T >
157+
using /*$e:maybe-const*/ = std::conditional_t<Const, const T, T>;
158+
```
159+
</Card>
160+
161+
Three kinds of markers are supported:
162+
163+
<DeclDoc>
164+
<Decl slot="decl">
165+
```
166+
/*$s:something*/
167+
```
168+
</Decl>
169+
170+
Marks part of code to be a syntax notation.
171+
172+
Rendered as:
173+
174+
```cpp cxx-mark
175+
/*$s:something*/
176+
```
177+
</DeclDoc>
178+
179+
<DeclDoc>
180+
<Decl slot="decl">
181+
```
182+
/*$e:something*/
183+
```
184+
</Decl>
185+
186+
Marks part of code to be exposition only.
187+
188+
Rendered as:
189+
190+
```cpp cxx-mark
191+
/*$e:something*/
192+
```
193+
</DeclDoc>
194+
195+
<DeclDoc>
196+
<Decl slot="decl">
197+
```
198+
something/*$opt*/
199+
```
200+
</Decl>
201+
202+
Mark the previous part of code (often a syntax notation) to be optional.
203+
204+
Rendered as:
205+
206+
```cpp cxx-mark
207+
something/*$opt*/
208+
```
209+
</DeclDoc>
210+
142211
## Description list
143212

144213
### Basic Usage
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import {
2+
definePlugin,
3+
InlineStyleAnnotation,
4+
type ExpressiveCodePlugin,
5+
} from "@astrojs/starlight/expressive-code";
6+
7+
export function pluginCxxMark(): ExpressiveCodePlugin {
8+
return definePlugin({
9+
name: "CXX mark",
10+
hooks: {
11+
postprocessAnalyzedCode: (context) => {
12+
context.codeBlock.getLines().forEach((line) => {
13+
if (context.codeBlock.meta.includes("cxx-mark")) {
14+
const matches = [
15+
...line.text.matchAll(/\/\*\$(.+?)\*\//g),
16+
].reverse();
17+
matches.forEach((match) => {
18+
const begin = match.index;
19+
const end = begin + match[0].length;
20+
if (match[1].startsWith("s:")) {
21+
line.addAnnotation(
22+
new InlineStyleAnnotation({
23+
inlineRange: {
24+
columnStart: begin,
25+
columnEnd: end,
26+
},
27+
// color of syntax notation should be same with comments
28+
italic: true,
29+
})
30+
);
31+
line.editText(begin, end, match[0].slice(5, -2));
32+
} else if (match[1].startsWith("e:")) {
33+
line.addAnnotation(
34+
new InlineStyleAnnotation({
35+
inlineRange: {
36+
columnStart: begin,
37+
columnEnd: end,
38+
},
39+
color: "var(--cppdoc-color-cxx-mark-exposition)",
40+
italic: true,
41+
})
42+
);
43+
line.editText(begin + 2, begin + 5, "");
44+
} else if (match[1] == "opt") {
45+
const newStr = "(optional)";
46+
line.editText(begin, end, newStr);
47+
line.addAnnotation(
48+
new InlineStyleAnnotation({
49+
inlineRange: {
50+
columnStart: begin,
51+
columnEnd: begin + newStr.length,
52+
},
53+
color: "var(--cppdoc-color-cxx-mark-optional)",
54+
})
55+
);
56+
}
57+
});
58+
}
59+
});
60+
},
61+
},
62+
});
63+
}

src/styles/custom.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
--cppdoc-color-ill-formed: var(--sl-color-red);
1818
--cppdoc-color-ifndr: var(--sl-color-red);
1919

20+
--cppdoc-color-cxx-mark-exposition: #ff0000;
21+
--cppdoc-color-cxx-mark-optional: var(--sl-color-green);
22+
2023
--sl-sidebar-width: 22rem;
2124
}
2225

0 commit comments

Comments
 (0)