@riebeckite/plugin-code-annotations 0.0.21 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -104
- package/README_ja.md +28 -104
- package/dist/index.d.ts +3 -15
- package/dist/index.js +110 -299
- package/dist/src/annotations.d.ts +12 -45
- package/dist/src/rehype.d.ts +2 -8
- package/dist/src/remark.d.ts +1 -16
- package/dist/src/types.d.ts +0 -41
- package/package.json +7 -11
- package/dist/src/options.d.ts +0 -10
- package/style.css +0 -36
package/README.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# @riebeckite/plugin-code-annotations
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
<!-- Generated from docs/docs/plugins/code-annotations.md. Edit the canonical documentation in docs/docs/plugins and run `pnpm docs:sync`. -->
|
|
4
|
+
|
|
5
|
+
Renders code diffs with the language syntax highlighter and Riebeckite's code
|
|
6
|
+
block UI.
|
|
6
7
|
|
|
7
8
|
[日本語](./README_ja.md)
|
|
8
9
|
|
|
@@ -13,126 +14,55 @@ import { defineConfig } from "@riebeckite/core";
|
|
|
13
14
|
import { codeAnnotations } from "@riebeckite/plugin-code-annotations";
|
|
14
15
|
|
|
15
16
|
export default defineConfig({
|
|
16
|
-
// ...
|
|
17
17
|
plugins: [codeAnnotations()],
|
|
18
18
|
});
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
Use it with `@riebeckite/plugin-code-enhance` to retain syntax highlighting,
|
|
22
|
+
line numbers, the language label, and copy controls.
|
|
23
23
|
|
|
24
24
|
## Syntax
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
````md
|
|
31
|
-
```js {2,4-5}
|
|
32
|
-
const a = 1;
|
|
33
|
-
const b = 2;
|
|
34
|
-
const c = 3;
|
|
35
|
-
const d = 4;
|
|
36
|
-
const e = 5;
|
|
37
|
-
```
|
|
38
|
-
````
|
|
39
|
-
|
|
40
|
-
Lines `2`, `4`, and `5` receive `rb-code__line--highlighted`.
|
|
41
|
-
|
|
42
|
-
### Focus
|
|
43
|
-
|
|
44
|
-
Use the `focus` meta group, or an inline `[!code focus]` marker. An optional
|
|
45
|
-
count focuses the current line and the following lines.
|
|
46
|
-
|
|
47
|
-
````md
|
|
48
|
-
```js focus:{2}
|
|
49
|
-
const a = 1;
|
|
50
|
-
const b = 2;
|
|
51
|
-
```
|
|
52
|
-
````
|
|
53
|
-
|
|
54
|
-
````md
|
|
55
|
-
```js
|
|
56
|
-
const a = 1; // [!code focus]
|
|
57
|
-
const b = 2;
|
|
58
|
-
```
|
|
59
|
-
````
|
|
60
|
-
|
|
61
|
-
`.rb-code__line--focused` is applied. `[!code focus:3]` focuses three lines
|
|
62
|
-
starting at the marker.
|
|
63
|
-
|
|
64
|
-
### Diff
|
|
65
|
-
|
|
66
|
-
````md
|
|
67
|
-
```js
|
|
68
|
-
const kept = true;
|
|
69
|
-
const added = true; // [!code ++]
|
|
70
|
-
const removed = false; // [!code --]
|
|
71
|
-
```
|
|
72
|
-
````
|
|
73
|
-
|
|
74
|
-
The marker comment is removed from the rendered text, and the line receives
|
|
75
|
-
`rb-code__line--added` or `rb-code__line--removed`.
|
|
76
|
-
|
|
77
|
-
### Explicit highlight marker
|
|
26
|
+
Use `diff` as the fence language and put the target language after it. Lines
|
|
27
|
+
starting with `+` are additions, lines starting with `-` are removals, and all
|
|
28
|
+
other lines are unchanged.
|
|
78
29
|
|
|
79
30
|
````md
|
|
80
|
-
```js
|
|
81
|
-
const
|
|
31
|
+
```diff js
|
|
32
|
+
+ const message = "Hello";
|
|
33
|
+
- const message = "World";
|
|
34
|
+
const unchanged = true;
|
|
82
35
|
```
|
|
83
36
|
````
|
|
84
37
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
## Options
|
|
90
|
-
|
|
91
|
-
| Option | Type | Default | Description |
|
|
92
|
-
| ------ | ---- | ------- | ----------- |
|
|
93
|
-
| `className` | `string` | `"rb-code"` | Class on the block root (`<pre>` or `rehype-pretty-code` `<figure>`) |
|
|
94
|
-
| `lineClassName` | `string` | `"rb-code__line"` | Class on generated line wrappers |
|
|
95
|
-
| `highlightClassName` | `string` | `"rb-code__line--highlighted"` | Class for highlighted lines |
|
|
96
|
-
| `addedClassName` | `string` | `"rb-code__line--added"` | Class for `[!code ++]` lines |
|
|
97
|
-
| `removedClassName` | `string` | `"rb-code__line--removed"` | Class for `[!code --]` lines |
|
|
98
|
-
| `focusClassName` | `string` | `"rb-code__line--focused"` | Class for focused lines |
|
|
99
|
-
| `language` | `string` | unset | Only annotate blocks of this language |
|
|
100
|
-
|
|
101
|
-
```ts
|
|
102
|
-
codeAnnotations({ highlightClassName: "is-highlighted" });
|
|
103
|
-
```
|
|
38
|
+
The `+` and `-` markers are rendered separately from the code, so Shiki
|
|
39
|
+
highlights the JavaScript, TypeScript, Python, JSON, or other target language
|
|
40
|
+
without treating the marker as source code. The copy button copies the visible
|
|
41
|
+
diff, including its markers.
|
|
104
42
|
|
|
105
|
-
|
|
43
|
+
An empty, malformed, or missing target language leaves the fence as an ordinary
|
|
44
|
+
`diff` code block. A target language that the syntax highlighter does not know
|
|
45
|
+
falls back to its normal unhighlighted rendering and does not fail the build.
|
|
106
46
|
|
|
107
|
-
|
|
108
|
-
`@riebeckite/plugin-code-enhance`. It detects both raw `<pre><code>` text and
|
|
109
|
-
the `.line` wrappers emitted by `rehype-pretty-code`:
|
|
47
|
+
## Integration
|
|
110
48
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
Because `rehype-pretty-code` substitutes the `<code>` element, the plan is also
|
|
117
|
-
mirrored into the preserved fence meta, so annotations still apply after
|
|
118
|
-
code-enhance runs. Place `codeAnnotations()` after `codeEnhance()` in the
|
|
119
|
-
plugins array; the plugin uses `order: 10` to run after code-enhance's
|
|
120
|
-
highlighting regardless.
|
|
49
|
+
The plugin transforms Markdown in its remark phase, records each line marker in
|
|
50
|
+
fence metadata, then restores the markers and the existing
|
|
51
|
+
`rr-code__line--add` / `rr-code__line--remove` classes in its rehype phase.
|
|
52
|
+
`code-enhance` supplies the line wrappers and all code block UI. The plugin does
|
|
53
|
+
not import it, so the two packages remain independently configurable.
|
|
121
54
|
|
|
122
55
|
## Exports
|
|
123
56
|
|
|
124
|
-
- `codeAnnotations(
|
|
125
|
-
- `remarkCodeAnnotations(
|
|
126
|
-
- `rehypeCodeAnnotations(
|
|
127
|
-
- `
|
|
128
|
-
- `
|
|
129
|
-
- `
|
|
130
|
-
- `
|
|
131
|
-
- Types: `CodeAnnotationsOptions`, `ResolvedCodeAnnotationsOptions`,
|
|
132
|
-
`CodeAnnotationPlan`, `CodeAnnotationKind`
|
|
57
|
+
- `codeAnnotations()` / `codeAnnotationsPlugin()` — plugin factory
|
|
58
|
+
- `remarkCodeAnnotations()` — Markdown transform
|
|
59
|
+
- `rehypeCodeAnnotations()` — HTML transform
|
|
60
|
+
- `collectCodeDiff(code)` — separates diff markers from source text
|
|
61
|
+
- `serializeCodeDiff(plan)` / `deserializeCodeDiff(value)` — line-plan helpers
|
|
62
|
+
- `encodeCodeDiffMeta(plan)` / `extractCodeDiffMeta(meta)` — metadata helpers
|
|
63
|
+
- Types: `CodeDiffPlan`, `DiffMarker`
|
|
133
64
|
|
|
134
65
|
## See also
|
|
135
66
|
|
|
136
|
-
- [Plugin guide](
|
|
67
|
+
- [Plugin guide](https://github.com/Rerurate514/riebeckite/blob/main/docs/docs/reference/plugin-api.md)
|
|
137
68
|
- [`@riebeckite/plugin-code-enhance`](../code-enhance/README.md)
|
|
138
|
-
|
package/README_ja.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# @riebeckite/plugin-code-annotations
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
`@riebeckite/plugin-code-enhance` の行ラッパーの両方で動作します。
|
|
3
|
+
<!-- Generated from docs/docs/plugins/code-annotations.ja.md. Edit the canonical documentation in docs/docs/plugins and run `pnpm docs:sync`. -->
|
|
4
|
+
|
|
5
|
+
差分のコードブロックを、対象言語のシンタックスハイライトとRiebeckiteのコードブロックUIで表示します。
|
|
7
6
|
|
|
8
7
|
[English](./README.md)
|
|
9
8
|
|
|
@@ -14,124 +13,49 @@ import { defineConfig } from "@riebeckite/core";
|
|
|
14
13
|
import { codeAnnotations } from "@riebeckite/plugin-code-annotations";
|
|
15
14
|
|
|
16
15
|
export default defineConfig({
|
|
17
|
-
// ...
|
|
18
16
|
plugins: [codeAnnotations()],
|
|
19
17
|
});
|
|
20
18
|
```
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
シンタックスハイライト、行番号、言語ラベル、コピー操作を使う場合は、
|
|
21
|
+
`@riebeckite/plugin-code-enhance` と併用してください。
|
|
24
22
|
|
|
25
23
|
## 書き方
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
言語の後ろに波括弧で行範囲を書きます。Docusaurus や VitePress と同じ記法です。
|
|
30
|
-
|
|
31
|
-
````md
|
|
32
|
-
```js {2,4-5}
|
|
33
|
-
const a = 1;
|
|
34
|
-
const b = 2;
|
|
35
|
-
const c = 3;
|
|
36
|
-
const d = 4;
|
|
37
|
-
const e = 5;
|
|
38
|
-
```
|
|
39
|
-
````
|
|
40
|
-
|
|
41
|
-
2、4、5 行目に `rb-code__line--highlighted` が付きます。
|
|
42
|
-
|
|
43
|
-
### フォーカス
|
|
44
|
-
|
|
45
|
-
`focus` メタ、またはインラインの `[!code focus]` を使います。行数を指定すると
|
|
46
|
-
その行から続く行までをまとめてフォーカスします。
|
|
47
|
-
|
|
48
|
-
````md
|
|
49
|
-
```js focus:{2}
|
|
50
|
-
const a = 1;
|
|
51
|
-
const b = 2;
|
|
52
|
-
```
|
|
53
|
-
````
|
|
54
|
-
|
|
55
|
-
````md
|
|
56
|
-
```js
|
|
57
|
-
const a = 1; // [!code focus]
|
|
58
|
-
const b = 2;
|
|
59
|
-
```
|
|
60
|
-
````
|
|
61
|
-
|
|
62
|
-
`rb-code__line--focused` が付きます。`[!code focus:3]` なら 3 行分です。
|
|
63
|
-
|
|
64
|
-
### 差分
|
|
65
|
-
|
|
66
|
-
````md
|
|
67
|
-
```js
|
|
68
|
-
const kept = true;
|
|
69
|
-
const added = true; // [!code ++]
|
|
70
|
-
const removed = false; // [!code --]
|
|
71
|
-
```
|
|
72
|
-
````
|
|
73
|
-
|
|
74
|
-
マーカーのコメントは表示テキストから取り除かれ、行には
|
|
75
|
-
`rb-code__line--added` または `rb-code__line--removed` が付きます。
|
|
76
|
-
|
|
77
|
-
### 明示的な強調マーカー
|
|
25
|
+
コードフェンスの言語に `diff` を指定し、その後に対象言語を書きます。`+` で始まる行は追加、
|
|
26
|
+
`-` で始まる行は削除、それ以外は変更のない行として扱います。
|
|
78
27
|
|
|
79
28
|
````md
|
|
80
|
-
```js
|
|
81
|
-
const
|
|
29
|
+
```diff js
|
|
30
|
+
+ const message = "Hello";
|
|
31
|
+
- const message = "World";
|
|
32
|
+
const unchanged = true;
|
|
82
33
|
```
|
|
83
34
|
````
|
|
84
35
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
## オプション
|
|
89
|
-
|
|
90
|
-
| オプション | 既定値 | 内容 |
|
|
91
|
-
| --- | --- | --- |
|
|
92
|
-
| `className` | `"rb-code"` | ブロック直下(`<pre>` または `rehype-pretty-code` の `<figure>`)に付くクラス |
|
|
93
|
-
| `lineClassName` | `"rb-code__line"` | 生成する行ラッパーのクラス |
|
|
94
|
-
| `highlightClassName` | `"rb-code__line--highlighted"` | 強調行のクラス |
|
|
95
|
-
| `addedClassName` | `"rb-code__line--added"` | `[!code ++]` 行のクラス |
|
|
96
|
-
| `removedClassName` | `"rb-code__line--removed"` | `[!code --]` 行のクラス |
|
|
97
|
-
| `focusClassName` | `"rb-code__line--focused"` | フォーカス行のクラス |
|
|
98
|
-
| `language` | 未設定 | 指定した言語のブロックだけを対象にする |
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
codeAnnotations({ highlightClassName: "is-highlighted" });
|
|
102
|
-
```
|
|
36
|
+
`+` と `-` はコード本体とは別に描画されます。そのためJavaScript、TypeScript、Python、JSON
|
|
37
|
+
などのシンタックスハイライトを妨げません。コピー操作では、表示された差分と同じくマーカーも含めてコピーします。
|
|
103
38
|
|
|
104
|
-
|
|
39
|
+
対象言語が空、形式が不正、または指定されていないフェンスは、通常の `diff` コードブロックとして扱います。
|
|
40
|
+
シンタックスハイライトが対応していない言語を指定しても、ハイライトなしで表示され、ビルドは失敗しません。
|
|
105
41
|
|
|
106
|
-
|
|
107
|
-
`@riebeckite/plugin-code-enhance` を import せず、依存もしません。素の
|
|
108
|
-
`<pre><code>` のテキストと、`rehype-pretty-code` が出力する `.line` ラッパーの
|
|
109
|
-
両方を検出します。
|
|
42
|
+
## 連携
|
|
110
43
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
-
|
|
114
|
-
`<span class="rb-code__line" data-line="N">` に分割します。
|
|
44
|
+
このプラグインはremark段階で差分マーカーをコード本体から分離し、フェンスメタ情報に記録します。rehype段階では、
|
|
45
|
+
マーカーと既存の `rr-code__line--add` / `rr-code__line--remove` クラスを戻します。行ラッパーやコードブロックUIは
|
|
46
|
+
`code-enhance` が提供します。両パッケージはimportで依存していないため、個別に設定できます。
|
|
115
47
|
|
|
116
|
-
|
|
117
|
-
フェンスメタにも複製します。これにより code-enhance の後でも注釈が適用されます。
|
|
118
|
-
プラグイン配列では `codeEnhance()` の後に `codeAnnotations()` を置いてください。
|
|
119
|
-
`order: 10` により、順序に関わらず強調処理の後に実行されます。
|
|
48
|
+
## 公開API
|
|
120
49
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
- `
|
|
124
|
-
- `
|
|
125
|
-
- `
|
|
126
|
-
- `
|
|
127
|
-
-
|
|
128
|
-
- `collectCodeAnnotations(meta, code)` — メタとインラインマーカーをまとめて解析
|
|
129
|
-
- `resolveCodeAnnotationsOptions(options?)` — 既定値を補完
|
|
130
|
-
- 型: `CodeAnnotationsOptions`、`ResolvedCodeAnnotationsOptions`、
|
|
131
|
-
`CodeAnnotationPlan`、`CodeAnnotationKind`
|
|
50
|
+
- `codeAnnotations()` / `codeAnnotationsPlugin()` — プラグインファクトリ
|
|
51
|
+
- `remarkCodeAnnotations()` — Markdown変換
|
|
52
|
+
- `rehypeCodeAnnotations()` — HTML変換
|
|
53
|
+
- `collectCodeDiff(code)` — 差分マーカーとコード本体を分離
|
|
54
|
+
- `serializeCodeDiff(plan)` / `deserializeCodeDiff(value)` — 行情報の変換
|
|
55
|
+
- `encodeCodeDiffMeta(plan)` / `extractCodeDiffMeta(meta)` — メタ情報の変換
|
|
56
|
+
- 型: `CodeDiffPlan`、`DiffMarker`
|
|
132
57
|
|
|
133
58
|
## 関連資料
|
|
134
59
|
|
|
135
|
-
- [プラグインシステム](
|
|
60
|
+
- [プラグインシステム](https://github.com/Rerurate514/riebeckite/blob/main/docs/docs/reference/plugin-api.ja.md)
|
|
136
61
|
- [`@riebeckite/plugin-code-enhance`](../code-enhance/README_ja.md)
|
|
137
|
-
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export { ANNOTATIONS_META_PREFIX, collectCodeAnnotations, createEmptyPlan, deserializeAnnotations, encodeAnnotationsMeta, extractAnnotationsMeta, hasAnnotations, parseCodeAnnotations, parseLineRanges, serializeAnnotations, stripInlineCodeAnnotation, } from "./src/annotations.js";
|
|
4
|
-
export { DEFAULT_CODE_ANNOTATIONS_OPTIONS, resolveCodeAnnotationsOptions, } from "./src/options.js";
|
|
1
|
+
export type { CodeDiffPlan, DiffMarker } from "./src/annotations.js";
|
|
2
|
+
export { appendCodeDiffMeta, collectCodeDiff, deserializeCodeDiff, encodeCodeDiffMeta, extractCodeDiffMeta, removeCodeDiffMeta, serializeCodeDiff, } from "./src/annotations.js";
|
|
5
3
|
export { rehypeCodeAnnotations } from "./src/rehype.js";
|
|
6
4
|
export { remarkCodeAnnotations } from "./src/remark.js";
|
|
7
|
-
export
|
|
8
|
-
/**
|
|
9
|
-
* VitePress/Docusaurus-style code block annotations: line highlighting from
|
|
10
|
-
* fence meta and inline `[!code ...]` marker comments for focus, highlight,
|
|
11
|
-
* and diff lines.
|
|
12
|
-
*
|
|
13
|
-
* Runs after `@riebeckite/plugin-code-enhance` (via `order`) so it can annotate
|
|
14
|
-
* the line wrappers produced by `rehype-pretty-code` instead of re-wrapping
|
|
15
|
-
* them. It never imports or depends on code-enhance.
|
|
16
|
-
*/
|
|
17
|
-
export declare function codeAnnotations(options?: CodeAnnotationsOptions): import("@riebeckite/core").RiebeckitePlugin<import("./index.js").ResolvedCodeAnnotationsOptions>;
|
|
5
|
+
export declare function codeAnnotations(): import("@riebeckite/core").RiebeckitePlugin<unknown>;
|
|
18
6
|
export declare const codeAnnotationsPlugin: typeof codeAnnotations;
|
package/dist/index.js
CHANGED
|
@@ -1,188 +1,55 @@
|
|
|
1
1
|
// index.ts
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
// src/options.ts
|
|
5
|
-
var DEFAULT_CODE_ANNOTATIONS_OPTIONS = {
|
|
6
|
-
className: "rb-code",
|
|
7
|
-
lineClassName: "rb-code__line",
|
|
8
|
-
highlightClassName: "rb-code__line--highlighted",
|
|
9
|
-
addedClassName: "rb-code__line--added",
|
|
10
|
-
removedClassName: "rb-code__line--removed",
|
|
11
|
-
focusClassName: "rb-code__line--focused"
|
|
12
|
-
};
|
|
13
|
-
function resolveCodeAnnotationsOptions(options = {}) {
|
|
14
|
-
const resolved = {
|
|
15
|
-
className: options.className ?? DEFAULT_CODE_ANNOTATIONS_OPTIONS.className,
|
|
16
|
-
lineClassName: options.lineClassName ?? DEFAULT_CODE_ANNOTATIONS_OPTIONS.lineClassName,
|
|
17
|
-
highlightClassName: options.highlightClassName ?? DEFAULT_CODE_ANNOTATIONS_OPTIONS.highlightClassName,
|
|
18
|
-
addedClassName: options.addedClassName ?? DEFAULT_CODE_ANNOTATIONS_OPTIONS.addedClassName,
|
|
19
|
-
removedClassName: options.removedClassName ?? DEFAULT_CODE_ANNOTATIONS_OPTIONS.removedClassName,
|
|
20
|
-
focusClassName: options.focusClassName ?? DEFAULT_CODE_ANNOTATIONS_OPTIONS.focusClassName
|
|
21
|
-
};
|
|
22
|
-
const language = options.language?.trim();
|
|
23
|
-
if (language) resolved.language = language;
|
|
24
|
-
return resolved;
|
|
25
|
-
}
|
|
2
|
+
import { definePlugin } from "@riebeckite/core";
|
|
26
3
|
|
|
27
4
|
// src/annotations.ts
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
];
|
|
36
|
-
var FOCUS_META_PATTERN = /(?:^|\s)focus[:=]\{([^}]*)\}/g;
|
|
37
|
-
var HIGHLIGHT_META_PATTERN = /\{([^{}]*)\}/g;
|
|
38
|
-
var INLINE_ANNOTATION_PATTERN = /([ \t]*)(?:(?:\/\/|#|--)[ \t]*\[!code[ \t]+(focus|highlight|\+\+|--)(?::(\d+))?\]|<!--[ \t]*\[!code[ \t]+(focus|highlight|\+\+|--)(?::(\d+))?[ \t]*\][ \t]*-->)[ \t]*$/;
|
|
39
|
-
function createEmptyPlan() {
|
|
40
|
-
return { highlight: [], added: [], removed: [], focus: [] };
|
|
41
|
-
}
|
|
42
|
-
function parseCodeAnnotations(meta) {
|
|
43
|
-
const plan = createEmptyPlan();
|
|
44
|
-
if (typeof meta !== "string" || meta.length === 0) return plan;
|
|
45
|
-
const rest = meta.replace(FOCUS_META_PATTERN, (_match, body) => {
|
|
46
|
-
addRanges(plan.focus, parseLineRanges(body));
|
|
47
|
-
return " ";
|
|
48
|
-
});
|
|
49
|
-
for (const match of rest.matchAll(HIGHLIGHT_META_PATTERN)) {
|
|
50
|
-
addRanges(plan.highlight, parseLineRanges(match[1] ?? ""));
|
|
51
|
-
}
|
|
52
|
-
return normalizePlan(plan);
|
|
53
|
-
}
|
|
54
|
-
function parseLineRanges(spec) {
|
|
55
|
-
const lines = [];
|
|
56
|
-
for (const part of spec.split(",")) {
|
|
57
|
-
const trimmed = part.trim();
|
|
58
|
-
if (trimmed === "") continue;
|
|
59
|
-
const range = /^(\d+)\s*-\s*(\d+)$/.exec(trimmed);
|
|
60
|
-
if (range) {
|
|
61
|
-
const first = Number(range[1]);
|
|
62
|
-
const second = Number(range[2]);
|
|
63
|
-
const from = Math.min(first, second);
|
|
64
|
-
const to = Math.max(first, second);
|
|
65
|
-
for (let line = from; line <= to; line += 1) lines.push(line);
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
if (/^\d+$/.test(trimmed)) lines.push(Number(trimmed));
|
|
69
|
-
}
|
|
70
|
-
return lines;
|
|
71
|
-
}
|
|
72
|
-
function stripInlineCodeAnnotation(line) {
|
|
73
|
-
const match = INLINE_ANNOTATION_PATTERN.exec(line);
|
|
74
|
-
if (!match) return { line, annotation: null };
|
|
75
|
-
const kind = normalizeKind(match[2] ?? match[4]);
|
|
76
|
-
if (!kind) return { line, annotation: null };
|
|
77
|
-
const rawCount = match[3] ?? match[5];
|
|
78
|
-
const parsedCount = rawCount === void 0 ? 1 : Number(rawCount);
|
|
79
|
-
const lineCount = Number.isFinite(parsedCount) ? Math.max(1, parsedCount) : 1;
|
|
80
|
-
const index = match.index ?? line.length;
|
|
81
|
-
const stripped = line.slice(0, index).replace(/[ \t]+$/, "");
|
|
82
|
-
return { line: stripped, annotation: { kind, lineCount } };
|
|
83
|
-
}
|
|
84
|
-
function collectCodeAnnotations(meta, code) {
|
|
85
|
-
const plan = parseCodeAnnotations(meta);
|
|
86
|
-
const strippedLines = [];
|
|
87
|
-
scanMarkdownFenceLines(code).forEach(({ value: rawLine, inFence }, index) => {
|
|
88
|
-
const { line, annotation } = inFence ? { line: rawLine, annotation: null } : stripInlineCodeAnnotation(rawLine);
|
|
89
|
-
strippedLines.push(line);
|
|
90
|
-
if (!annotation) return;
|
|
91
|
-
const lineNumber = index + 1;
|
|
92
|
-
if (annotation.kind === "focus") {
|
|
93
|
-
for (let focused = lineNumber; focused < lineNumber + annotation.lineCount; focused += 1) {
|
|
94
|
-
plan.focus.push(focused);
|
|
95
|
-
}
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
plan[annotation.kind].push(lineNumber);
|
|
5
|
+
var DIFF_META_PREFIX = "rb-diff=";
|
|
6
|
+
function collectCodeDiff(code) {
|
|
7
|
+
const markers = [];
|
|
8
|
+
const lines = code.split("\n").map((line) => {
|
|
9
|
+
const marker = line.startsWith("+") || line.startsWith("-") ? line[0] : null;
|
|
10
|
+
markers.push(marker);
|
|
11
|
+
return marker ? line.slice(1) : line;
|
|
99
12
|
});
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
plan: hasAnnotations2 ? normalizePlan(plan) : createEmptyPlan(),
|
|
103
|
-
code: strippedLines.join("\n"),
|
|
104
|
-
hasAnnotations: hasAnnotations2
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
function normalizePlan(plan) {
|
|
108
|
-
return {
|
|
109
|
-
highlight: normalizeLines(plan.highlight),
|
|
110
|
-
added: normalizeLines(plan.added),
|
|
111
|
-
removed: normalizeLines(plan.removed),
|
|
112
|
-
focus: normalizeLines(plan.focus)
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
function hasAnnotations(plan) {
|
|
116
|
-
if (!plan) return false;
|
|
117
|
-
return ANNOTATION_KEYS.some((key) => plan[key].length > 0);
|
|
13
|
+
return { code: lines.join("\n"), plan: { markers } };
|
|
118
14
|
}
|
|
119
|
-
function
|
|
120
|
-
return JSON.stringify(
|
|
15
|
+
function serializeCodeDiff(plan) {
|
|
16
|
+
return JSON.stringify(plan);
|
|
121
17
|
}
|
|
122
|
-
function
|
|
18
|
+
function deserializeCodeDiff(value) {
|
|
123
19
|
if (typeof value !== "string" || value === "") return null;
|
|
124
20
|
try {
|
|
125
|
-
|
|
21
|
+
const parsed = JSON.parse(value);
|
|
22
|
+
if (!Array.isArray(parsed.markers)) return null;
|
|
23
|
+
return {
|
|
24
|
+
markers: parsed.markers.map(
|
|
25
|
+
(marker) => marker === "+" || marker === "-" ? marker : null
|
|
26
|
+
)
|
|
27
|
+
};
|
|
126
28
|
} catch {
|
|
127
29
|
return null;
|
|
128
30
|
}
|
|
129
31
|
}
|
|
130
|
-
function
|
|
131
|
-
return `${
|
|
132
|
-
serializeAnnotations(plan)
|
|
133
|
-
)}`;
|
|
32
|
+
function encodeCodeDiffMeta(plan) {
|
|
33
|
+
return `${DIFF_META_PREFIX}${encodeURIComponent(serializeCodeDiff(plan))}`;
|
|
134
34
|
}
|
|
135
|
-
function
|
|
136
|
-
const token = encodeAnnotationsMeta(plan);
|
|
137
|
-
const base = typeof meta === "string" ? meta.trim() : "";
|
|
138
|
-
return base === "" ? token : `${base} ${token}`;
|
|
139
|
-
}
|
|
140
|
-
function extractAnnotationsMeta(meta) {
|
|
35
|
+
function extractCodeDiffMeta(meta) {
|
|
141
36
|
if (typeof meta !== "string") return null;
|
|
142
|
-
const match = meta.match(/(?:^|\s)rb-
|
|
37
|
+
const match = meta.match(/(?:^|\s)rb-diff=([^\s]+)/);
|
|
143
38
|
if (!match) return null;
|
|
144
39
|
try {
|
|
145
|
-
return
|
|
40
|
+
return deserializeCodeDiff(decodeURIComponent(match[1]));
|
|
146
41
|
} catch {
|
|
147
42
|
return null;
|
|
148
43
|
}
|
|
149
44
|
}
|
|
150
|
-
function
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
function coercePlan(value) {
|
|
155
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
const record = value;
|
|
159
|
-
return {
|
|
160
|
-
highlight: coerceLines(record.highlight),
|
|
161
|
-
added: coerceLines(record.added),
|
|
162
|
-
removed: coerceLines(record.removed),
|
|
163
|
-
focus: coerceLines(record.focus)
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
function coerceLines(value) {
|
|
167
|
-
if (!Array.isArray(value)) return [];
|
|
168
|
-
return value.filter(
|
|
169
|
-
(entry) => typeof entry === "number" && Number.isFinite(entry) && entry > 0
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
function addRanges(target, ranges) {
|
|
173
|
-
target.push(...ranges);
|
|
174
|
-
}
|
|
175
|
-
function normalizeLines(lines) {
|
|
176
|
-
return [...new Set(lines.filter((line) => line > 0))].sort(
|
|
177
|
-
(left, right) => left - right
|
|
178
|
-
);
|
|
45
|
+
function appendCodeDiffMeta(meta, plan) {
|
|
46
|
+
const token = encodeCodeDiffMeta(plan);
|
|
47
|
+
const base = typeof meta === "string" ? meta.trim() : "";
|
|
48
|
+
return base === "" ? token : `${base} ${token}`;
|
|
179
49
|
}
|
|
180
|
-
function
|
|
181
|
-
if (
|
|
182
|
-
|
|
183
|
-
if (kind === "focus") return "focus";
|
|
184
|
-
if (kind === "highlight") return "highlight";
|
|
185
|
-
return null;
|
|
50
|
+
function removeCodeDiffMeta(meta) {
|
|
51
|
+
if (typeof meta !== "string") return "";
|
|
52
|
+
return meta.replace(/(?:^|\s)rb-diff=[^\s]+/g, " ").trim().replace(/\s+/g, " ");
|
|
186
53
|
}
|
|
187
54
|
|
|
188
55
|
// src/hast.ts
|
|
@@ -214,19 +81,6 @@ function getBooleanProperty(node, key) {
|
|
|
214
81
|
const value = getProperty(node, key);
|
|
215
82
|
return value === true || value === "true" || value === "";
|
|
216
83
|
}
|
|
217
|
-
function hasProperty(node, key) {
|
|
218
|
-
return getProperty(node, key) !== void 0;
|
|
219
|
-
}
|
|
220
|
-
function getClassNameList(node) {
|
|
221
|
-
const value = node.properties?.className;
|
|
222
|
-
if (Array.isArray(value)) {
|
|
223
|
-
return value.filter((entry) => typeof entry === "string");
|
|
224
|
-
}
|
|
225
|
-
if (typeof value === "string") {
|
|
226
|
-
return value.split(/\s+/).filter(Boolean);
|
|
227
|
-
}
|
|
228
|
-
return [];
|
|
229
|
-
}
|
|
230
84
|
function mergeClassName(current, next) {
|
|
231
85
|
const currentClass = Array.isArray(current) ? current.join(" ") : typeof current === "string" ? current : "";
|
|
232
86
|
if (next === "") return currentClass;
|
|
@@ -239,12 +93,6 @@ function getDataMeta(node) {
|
|
|
239
93
|
const meta = data.meta;
|
|
240
94
|
return typeof meta === "string" ? meta : null;
|
|
241
95
|
}
|
|
242
|
-
function getTextContent(node) {
|
|
243
|
-
if (node.type === "text" && "value" in node && typeof node.value === "string") {
|
|
244
|
-
return node.value;
|
|
245
|
-
}
|
|
246
|
-
return getChildren(node).map(getTextContent).join("");
|
|
247
|
-
}
|
|
248
96
|
function getProperty(node, key) {
|
|
249
97
|
const value = node.properties?.[key];
|
|
250
98
|
if (value !== void 0) return value;
|
|
@@ -261,19 +109,37 @@ function getChildren(node) {
|
|
|
261
109
|
}
|
|
262
110
|
|
|
263
111
|
// src/rehype.ts
|
|
264
|
-
function rehypeCodeAnnotations(
|
|
112
|
+
function rehypeCodeAnnotations() {
|
|
265
113
|
return (tree) => {
|
|
266
114
|
visitElementTree(tree, (node, ancestors) => {
|
|
267
115
|
if (node.tagName !== "code") return;
|
|
268
|
-
const
|
|
269
|
-
if (
|
|
270
|
-
const pre = parent;
|
|
116
|
+
const pre = ancestors[ancestors.length - 1];
|
|
117
|
+
if (pre?.tagName !== "pre") return;
|
|
271
118
|
const figure = findFigure(ancestors);
|
|
272
119
|
const plan = readPlan(node, pre, figure);
|
|
273
|
-
|
|
274
|
-
if (
|
|
275
|
-
|
|
276
|
-
|
|
120
|
+
stripDiffFromProperties(node);
|
|
121
|
+
if (!plan) return;
|
|
122
|
+
const lines = getLineElements(node);
|
|
123
|
+
const codeLines = lines.length > 0 ? lines : wrapCodeLines(node);
|
|
124
|
+
codeLines.forEach((line, index) => {
|
|
125
|
+
const marker = plan.markers[index];
|
|
126
|
+
if (!marker) return;
|
|
127
|
+
line.properties = {
|
|
128
|
+
...line.properties,
|
|
129
|
+
className: mergeClassName(
|
|
130
|
+
line.properties?.className,
|
|
131
|
+
marker === "+" ? "rr-code__line--add" : "rr-code__line--remove"
|
|
132
|
+
)
|
|
133
|
+
};
|
|
134
|
+
line.children = [
|
|
135
|
+
element(
|
|
136
|
+
"span",
|
|
137
|
+
{ className: "rr-code__diff-marker", ariaHidden: "true" },
|
|
138
|
+
[text(marker)]
|
|
139
|
+
),
|
|
140
|
+
...line.children ?? []
|
|
141
|
+
];
|
|
142
|
+
});
|
|
277
143
|
});
|
|
278
144
|
};
|
|
279
145
|
}
|
|
@@ -286,169 +152,114 @@ function findFigure(ancestors) {
|
|
|
286
152
|
return null;
|
|
287
153
|
}
|
|
288
154
|
function readPlan(code, pre, figure) {
|
|
289
|
-
const fromAttribute =
|
|
290
|
-
getStringProperty(code, "
|
|
155
|
+
const fromAttribute = deserializeCodeDiff(
|
|
156
|
+
getStringProperty(code, "dataRbCodeDiff") ?? getStringProperty(code, "data-rb-code-diff")
|
|
291
157
|
);
|
|
292
158
|
if (fromAttribute) return fromAttribute;
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
159
|
+
for (const meta of [
|
|
160
|
+
getDataMeta(figure),
|
|
161
|
+
getDataMeta(pre),
|
|
162
|
+
getDataMeta(code)
|
|
163
|
+
]) {
|
|
164
|
+
const plan = extractCodeDiffMeta(meta);
|
|
296
165
|
if (plan) return plan;
|
|
297
166
|
}
|
|
298
167
|
return null;
|
|
299
168
|
}
|
|
300
|
-
function
|
|
169
|
+
function stripDiffFromProperties(code) {
|
|
301
170
|
if (!code.properties) return;
|
|
302
|
-
delete code.properties["data-rb-code-
|
|
303
|
-
delete code.properties.
|
|
171
|
+
delete code.properties["data-rb-code-diff"];
|
|
172
|
+
delete code.properties.dataRbCodeDiff;
|
|
304
173
|
for (const key of ["data-meta", "dataMeta"]) {
|
|
305
174
|
const value = code.properties[key];
|
|
306
175
|
if (typeof value !== "string") continue;
|
|
307
|
-
const stripped =
|
|
176
|
+
const stripped = removeCodeDiffMeta(value);
|
|
308
177
|
if (stripped !== "") code.properties[key] = stripped;
|
|
309
178
|
else delete code.properties[key];
|
|
310
179
|
}
|
|
311
180
|
}
|
|
312
|
-
function applyPlan(code, pre, figure, plan, options) {
|
|
313
|
-
const root = figure && getBooleanProperty(figure, "dataRehypePrettyCodeFigure") ? figure : pre;
|
|
314
|
-
root.properties = {
|
|
315
|
-
...root.properties,
|
|
316
|
-
className: mergeClassName(root.properties?.className, options.className)
|
|
317
|
-
};
|
|
318
|
-
const lines = getLineElements(code);
|
|
319
|
-
if (lines.length > 0) {
|
|
320
|
-
lines.forEach((line, index) => {
|
|
321
|
-
applyLineClasses(line, index + 1, plan, options);
|
|
322
|
-
});
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
const rawLines = getTextContent(code).replace(/\n$/, "").split("\n");
|
|
326
|
-
const children = [];
|
|
327
|
-
rawLines.forEach((lineText, index) => {
|
|
328
|
-
const classNames = [
|
|
329
|
-
options.lineClassName,
|
|
330
|
-
...annotationClassNames(index + 1, plan, options)
|
|
331
|
-
];
|
|
332
|
-
children.push(
|
|
333
|
-
element(
|
|
334
|
-
"span",
|
|
335
|
-
{
|
|
336
|
-
className: classNames.join(" "),
|
|
337
|
-
dataLine: String(index + 1)
|
|
338
|
-
},
|
|
339
|
-
[text(lineText)]
|
|
340
|
-
)
|
|
341
|
-
);
|
|
342
|
-
if (index < rawLines.length - 1) children.push(text("\n"));
|
|
343
|
-
});
|
|
344
|
-
code.children = children;
|
|
345
|
-
}
|
|
346
|
-
function applyLineClasses(line, lineNumber, plan, options) {
|
|
347
|
-
for (const name of annotationClassNames(lineNumber, plan, options)) {
|
|
348
|
-
line.properties = {
|
|
349
|
-
...line.properties,
|
|
350
|
-
className: mergeClassName(line.properties?.className, name)
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
function annotationClassNames(lineNumber, plan, options) {
|
|
355
|
-
const names = [];
|
|
356
|
-
if (plan.highlight.includes(lineNumber)) {
|
|
357
|
-
names.push(options.highlightClassName);
|
|
358
|
-
}
|
|
359
|
-
if (plan.added.includes(lineNumber)) names.push(options.addedClassName);
|
|
360
|
-
if (plan.removed.includes(lineNumber)) names.push(options.removedClassName);
|
|
361
|
-
if (plan.focus.includes(lineNumber)) names.push(options.focusClassName);
|
|
362
|
-
return names;
|
|
363
|
-
}
|
|
364
181
|
function getLineElements(code) {
|
|
365
182
|
return (code.children ?? []).filter(isElementNode).filter((child) => {
|
|
366
183
|
if (child.tagName !== "span") return false;
|
|
367
|
-
|
|
368
|
-
const classNames = getClassNameList(child);
|
|
369
|
-
return classNames.includes("line") || classNames.some((name) => name.endsWith("__line"));
|
|
184
|
+
return getBooleanProperty(child, "dataLine");
|
|
370
185
|
});
|
|
371
186
|
}
|
|
372
|
-
function
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
187
|
+
function wrapCodeLines(code) {
|
|
188
|
+
const lines = (code.children ?? []).filter((child) => child.type === "text").flatMap(
|
|
189
|
+
(child) => child.value.replace(/\n$/, "").split("\n")
|
|
190
|
+
);
|
|
191
|
+
const wrapped = lines.map(
|
|
192
|
+
(line, index) => element(
|
|
193
|
+
"span",
|
|
194
|
+
{ className: "rr-code__line", dataLine: String(index + 1) },
|
|
195
|
+
[text(line)]
|
|
196
|
+
)
|
|
197
|
+
);
|
|
198
|
+
code.children = wrapped.flatMap(
|
|
199
|
+
(line, index) => index < wrapped.length - 1 ? [line, text("\n")] : [line]
|
|
200
|
+
);
|
|
201
|
+
return wrapped;
|
|
383
202
|
}
|
|
384
203
|
|
|
385
204
|
// src/remark.ts
|
|
386
|
-
function remarkCodeAnnotations(
|
|
205
|
+
function remarkCodeAnnotations() {
|
|
387
206
|
return (tree) => {
|
|
388
207
|
visitMdast(tree, (node) => {
|
|
389
|
-
if (node.type !== "code" || typeof node.value !== "string")
|
|
390
|
-
if (options.language !== void 0 && node.lang !== options.language) {
|
|
208
|
+
if (node.type !== "code" || node.lang !== "diff" || typeof node.value !== "string") {
|
|
391
209
|
return;
|
|
392
210
|
}
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
);
|
|
398
|
-
if (!hasAnnotations2) return;
|
|
211
|
+
const language = parseTargetLanguage(node.meta);
|
|
212
|
+
if (!language) return;
|
|
213
|
+
const { code, plan } = collectCodeDiff(node.value);
|
|
214
|
+
node.lang = language;
|
|
399
215
|
node.value = code;
|
|
400
216
|
const hProperties = {
|
|
401
217
|
...node.data?.hProperties
|
|
402
218
|
};
|
|
403
|
-
hProperties["data-rb-code-
|
|
404
|
-
|
|
405
|
-
hProperties["data-meta"] = typeof existingMeta === "string" && existingMeta !== "" ? appendAnnotationsMeta(existingMeta, plan) : encodeAnnotationsMeta(plan);
|
|
219
|
+
hProperties["data-rb-code-diff"] = serializeCodeDiff(plan);
|
|
220
|
+
hProperties["data-meta"] = appendCodeDiffMeta(node.meta, plan);
|
|
406
221
|
node.data = { ...node.data ?? {}, hProperties };
|
|
407
222
|
});
|
|
408
223
|
};
|
|
409
224
|
}
|
|
225
|
+
function parseTargetLanguage(meta) {
|
|
226
|
+
if (typeof meta !== "string") return null;
|
|
227
|
+
const language = meta.trim().split(/\s+/, 1)[0];
|
|
228
|
+
return language && /^[\w#+.-]+$/.test(language) ? language : null;
|
|
229
|
+
}
|
|
410
230
|
function visitMdast(node, visitor) {
|
|
411
231
|
visitor(node);
|
|
412
232
|
for (const child of node.children ?? []) visitMdast(child, visitor);
|
|
413
233
|
}
|
|
414
234
|
|
|
415
235
|
// index.ts
|
|
416
|
-
function codeAnnotations(
|
|
417
|
-
const resolved = resolveCodeAnnotationsOptions(options);
|
|
236
|
+
function codeAnnotations() {
|
|
418
237
|
return definePlugin({
|
|
419
238
|
name: "code-annotations",
|
|
420
239
|
order: 10,
|
|
421
240
|
processedContentCache: {
|
|
422
|
-
version: "code-annotations-
|
|
241
|
+
version: "code-annotations-v2",
|
|
423
242
|
dependencyMode: "none"
|
|
424
243
|
},
|
|
425
|
-
options: resolved,
|
|
426
244
|
extendMarkdownPipeline: (pipeline) => {
|
|
427
|
-
pipeline.use(remarkCodeAnnotations
|
|
245
|
+
pipeline.use(remarkCodeAnnotations);
|
|
428
246
|
},
|
|
429
247
|
extendHtmlPipeline: (pipeline) => {
|
|
430
|
-
pipeline.use(rehypeCodeAnnotations
|
|
431
|
-
}
|
|
432
|
-
assets: [createStyleAsset("code-annotations")]
|
|
248
|
+
pipeline.use(rehypeCodeAnnotations);
|
|
249
|
+
}
|
|
433
250
|
});
|
|
434
251
|
}
|
|
435
252
|
var codeAnnotationsPlugin = codeAnnotations;
|
|
436
253
|
export {
|
|
437
|
-
|
|
438
|
-
DEFAULT_CODE_ANNOTATIONS_OPTIONS,
|
|
254
|
+
appendCodeDiffMeta,
|
|
439
255
|
codeAnnotations,
|
|
440
256
|
codeAnnotationsPlugin,
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
extractAnnotationsMeta,
|
|
446
|
-
hasAnnotations,
|
|
447
|
-
parseCodeAnnotations,
|
|
448
|
-
parseLineRanges,
|
|
257
|
+
collectCodeDiff,
|
|
258
|
+
deserializeCodeDiff,
|
|
259
|
+
encodeCodeDiffMeta,
|
|
260
|
+
extractCodeDiffMeta,
|
|
449
261
|
rehypeCodeAnnotations,
|
|
450
262
|
remarkCodeAnnotations,
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
stripInlineCodeAnnotation
|
|
263
|
+
removeCodeDiffMeta,
|
|
264
|
+
serializeCodeDiff
|
|
454
265
|
};
|
|
@@ -1,48 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Parse the highlight/focus specifiers of a code fence meta string.
|
|
7
|
-
*
|
|
8
|
-
* Docusaurus-style `{1,3-5}` groups become `highlight` lines. An optional
|
|
9
|
-
* `focus:{1,2}` (or `focus={1,2}`) group becomes `focus` lines. Inline marker
|
|
10
|
-
* comments are not part of the meta string and are handled by
|
|
11
|
-
* {@link collectCodeAnnotations}.
|
|
12
|
-
*/
|
|
13
|
-
export declare function parseCodeAnnotations(meta: string | null | undefined): CodeAnnotationPlan;
|
|
14
|
-
/**
|
|
15
|
-
* Parse a numeric range list such as `1,3-5` into sorted 1-based line numbers.
|
|
16
|
-
*/
|
|
17
|
-
export declare function parseLineRanges(spec: string): number[];
|
|
18
|
-
export type InlineCodeAnnotation = {
|
|
19
|
-
kind: CodeAnnotationKind;
|
|
20
|
-
lineCount: number;
|
|
1
|
+
export declare const DIFF_META_PREFIX = "rb-diff=";
|
|
2
|
+
export type DiffMarker = "+" | "-" | null;
|
|
3
|
+
export type CodeDiffPlan = {
|
|
4
|
+
markers: DiffMarker[];
|
|
21
5
|
};
|
|
22
|
-
|
|
23
|
-
* Remove a trailing `[!code ...]` marker comment from a line and report what
|
|
24
|
-
* it annotated. The comment prefix may be `//`, `#`, `--`, or an HTML comment.
|
|
25
|
-
*/
|
|
26
|
-
export declare function stripInlineCodeAnnotation(line: string): {
|
|
27
|
-
line: string;
|
|
28
|
-
annotation: InlineCodeAnnotation | null;
|
|
29
|
-
};
|
|
30
|
-
export type CollectedCodeAnnotations = {
|
|
31
|
-
plan: CodeAnnotationPlan;
|
|
6
|
+
export declare function collectCodeDiff(code: string): {
|
|
32
7
|
code: string;
|
|
33
|
-
|
|
8
|
+
plan: CodeDiffPlan;
|
|
34
9
|
};
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export declare function
|
|
40
|
-
export declare function
|
|
41
|
-
export declare function hasAnnotations(plan: CodeAnnotationPlan | null): boolean;
|
|
42
|
-
export declare function serializeAnnotations(plan: CodeAnnotationPlan): string;
|
|
43
|
-
export declare function deserializeAnnotations(value: unknown): CodeAnnotationPlan | null;
|
|
44
|
-
export declare function encodeAnnotationsMeta(plan: CodeAnnotationPlan): string;
|
|
45
|
-
export declare function appendAnnotationsMeta(meta: string | null | undefined, plan: CodeAnnotationPlan): string;
|
|
46
|
-
export declare function extractAnnotationsMeta(meta: string | null | undefined): CodeAnnotationPlan | null;
|
|
47
|
-
/** Remove an embedded plan token, keeping any surrounding fence meta. */
|
|
48
|
-
export declare function removeAnnotationsMeta(meta: string | null | undefined): string;
|
|
10
|
+
export declare function serializeCodeDiff(plan: CodeDiffPlan): string;
|
|
11
|
+
export declare function deserializeCodeDiff(value: unknown): CodeDiffPlan | null;
|
|
12
|
+
export declare function encodeCodeDiffMeta(plan: CodeDiffPlan): string;
|
|
13
|
+
export declare function extractCodeDiffMeta(meta: string | null | undefined): CodeDiffPlan | null;
|
|
14
|
+
export declare function appendCodeDiffMeta(meta: string | null | undefined, plan: CodeDiffPlan): string;
|
|
15
|
+
export declare function removeCodeDiffMeta(meta: string | null | undefined): string;
|
package/dist/src/rehype.d.ts
CHANGED
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
import type { HastNode
|
|
2
|
-
|
|
3
|
-
* Materializes annotation plans recorded by {@link remarkCodeAnnotations}.
|
|
4
|
-
* Reuses existing per-line wrappers (for example the ones emitted by
|
|
5
|
-
* `rehype-pretty-code` through `@riebeckite/plugin-code-enhance`) and falls
|
|
6
|
-
* back to wrapping raw `<code>` text into `rb-code__line` spans.
|
|
7
|
-
*/
|
|
8
|
-
export declare function rehypeCodeAnnotations(options?: ResolvedCodeAnnotationsOptions): (tree: HastNode) => void;
|
|
1
|
+
import type { HastNode } from "./types.js";
|
|
2
|
+
export declare function rehypeCodeAnnotations(): (tree: HastNode) => void;
|
package/dist/src/remark.d.ts
CHANGED
|
@@ -1,16 +1 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Reads the fence meta and inline `[!code ...]` markers of every code block,
|
|
4
|
-
* strips the marker comments from the code text, and records the resulting
|
|
5
|
-
* plan for the rehype stage.
|
|
6
|
-
*
|
|
7
|
-
* The plan travels through two properties:
|
|
8
|
-
*
|
|
9
|
-
* - `data-rb-code-annotations` is the primary channel and is read directly for
|
|
10
|
-
* plain `<pre><code>` blocks.
|
|
11
|
-
* - `data-meta` carries an encoded copy because
|
|
12
|
-
* `rehype-pretty-code` (used by `@riebeckite/plugin-code-enhance`) replaces
|
|
13
|
-
* the `<code>` element and drops its properties. code-enhance already reads
|
|
14
|
-
* `data-meta`, so the copy survives on the generated `<figure>`.
|
|
15
|
-
*/
|
|
16
|
-
export declare function remarkCodeAnnotations(options?: ResolvedCodeAnnotationsOptions): (tree: unknown) => void;
|
|
1
|
+
export declare function remarkCodeAnnotations(): (tree: unknown) => void;
|
package/dist/src/types.d.ts
CHANGED
|
@@ -1,44 +1,3 @@
|
|
|
1
|
-
export type CodeAnnotationsOptions = {
|
|
2
|
-
/**
|
|
3
|
-
* Class applied to the code block root (`<pre>` or the
|
|
4
|
-
* `rehype-pretty-code` `<figure>`). Defaults to `"rb-code"`.
|
|
5
|
-
*/
|
|
6
|
-
className?: string;
|
|
7
|
-
/**
|
|
8
|
-
* Class applied to each generated line wrapper. Defaults to
|
|
9
|
-
* `"rb-code__line"`. Existing line wrappers are not re-classed.
|
|
10
|
-
*/
|
|
11
|
-
lineClassName?: string;
|
|
12
|
-
/** Class applied to highlighted lines. Defaults to `"rb-code__line--highlighted"`. */
|
|
13
|
-
highlightClassName?: string;
|
|
14
|
-
/** Class applied to `++` lines. Defaults to `"rb-code__line--added"`. */
|
|
15
|
-
addedClassName?: string;
|
|
16
|
-
/** Class applied to `--` lines. Defaults to `"rb-code__line--removed"`. */
|
|
17
|
-
removedClassName?: string;
|
|
18
|
-
/** Class applied to focused lines. Defaults to `"rb-code__line--focused"`. */
|
|
19
|
-
focusClassName?: string;
|
|
20
|
-
/**
|
|
21
|
-
* When set, annotations are only applied to code blocks whose detected
|
|
22
|
-
* language matches this value. Unset by default.
|
|
23
|
-
*/
|
|
24
|
-
language?: string;
|
|
25
|
-
};
|
|
26
|
-
export type ResolvedCodeAnnotationsOptions = {
|
|
27
|
-
className: string;
|
|
28
|
-
lineClassName: string;
|
|
29
|
-
highlightClassName: string;
|
|
30
|
-
addedClassName: string;
|
|
31
|
-
removedClassName: string;
|
|
32
|
-
focusClassName: string;
|
|
33
|
-
language?: string;
|
|
34
|
-
};
|
|
35
|
-
export type CodeAnnotationPlan = {
|
|
36
|
-
highlight: number[];
|
|
37
|
-
added: number[];
|
|
38
|
-
removed: number[];
|
|
39
|
-
focus: number[];
|
|
40
|
-
};
|
|
41
|
-
export type CodeAnnotationKind = "highlight" | "added" | "removed" | "focus";
|
|
42
1
|
export type ElementNode = {
|
|
43
2
|
type: string;
|
|
44
3
|
tagName?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/plugin-code-annotations",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -11,15 +11,14 @@
|
|
|
11
11
|
"import": "./dist/index.js",
|
|
12
12
|
"source": "./index.ts",
|
|
13
13
|
"default": "./dist/index.js"
|
|
14
|
-
}
|
|
15
|
-
"./style.css": "./style.css"
|
|
14
|
+
}
|
|
16
15
|
},
|
|
17
16
|
"dependencies": {
|
|
18
|
-
"@riebeckite/core": "0.0.
|
|
17
|
+
"@riebeckite/core": "0.0.23"
|
|
19
18
|
},
|
|
20
19
|
"devDependencies": {
|
|
21
20
|
"tsx": "^4.22.4",
|
|
22
|
-
"@riebeckite/test": "0.0.
|
|
21
|
+
"@riebeckite/test": "0.0.23"
|
|
23
22
|
},
|
|
24
23
|
"publishConfig": {
|
|
25
24
|
"access": "public"
|
|
@@ -28,8 +27,7 @@
|
|
|
28
27
|
"LICENSE",
|
|
29
28
|
"README.md",
|
|
30
29
|
"README_ja.md",
|
|
31
|
-
"dist"
|
|
32
|
-
"style.css"
|
|
30
|
+
"dist"
|
|
33
31
|
],
|
|
34
32
|
"repository": {
|
|
35
33
|
"type": "git",
|
|
@@ -40,7 +38,7 @@
|
|
|
40
38
|
"bugs": {
|
|
41
39
|
"url": "https://github.com/Rerurate514/riebeckite/issues"
|
|
42
40
|
},
|
|
43
|
-
"description": "
|
|
41
|
+
"description": "Syntax-highlighted diff code fences for Riebeckite.",
|
|
44
42
|
"keywords": [
|
|
45
43
|
"riebeckite",
|
|
46
44
|
"plugin",
|
|
@@ -50,9 +48,7 @@
|
|
|
50
48
|
"engines": {
|
|
51
49
|
"node": "^20.19.0 || >=22.12.0"
|
|
52
50
|
},
|
|
53
|
-
"sideEffects":
|
|
54
|
-
"./style.css"
|
|
55
|
-
],
|
|
51
|
+
"sideEffects": false,
|
|
56
52
|
"scripts": {
|
|
57
53
|
"build": "node ../../../scripts/build_package.mjs",
|
|
58
54
|
"test": "node --import tsx --test \"test/*.test.ts\""
|
package/dist/src/options.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { CodeAnnotationsOptions, ResolvedCodeAnnotationsOptions } from "./types.js";
|
|
2
|
-
export declare const DEFAULT_CODE_ANNOTATIONS_OPTIONS: {
|
|
3
|
-
readonly className: "rb-code";
|
|
4
|
-
readonly lineClassName: "rb-code__line";
|
|
5
|
-
readonly highlightClassName: "rb-code__line--highlighted";
|
|
6
|
-
readonly addedClassName: "rb-code__line--added";
|
|
7
|
-
readonly removedClassName: "rb-code__line--removed";
|
|
8
|
-
readonly focusClassName: "rb-code__line--focused";
|
|
9
|
-
};
|
|
10
|
-
export declare function resolveCodeAnnotationsOptions(options?: CodeAnnotationsOptions): ResolvedCodeAnnotationsOptions;
|
package/style.css
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
.rb-code {
|
|
2
|
-
--rb-code-annotation-accent: var(--rb-color-accent, #686868);
|
|
3
|
-
position: relative;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
.rb-code__line {
|
|
7
|
-
display: block;
|
|
8
|
-
min-width: 100%;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.rb-code__line--highlighted {
|
|
12
|
-
background: color-mix(
|
|
13
|
-
in srgb,
|
|
14
|
-
var(--rb-code-annotation-accent) 14%,
|
|
15
|
-
transparent
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.rb-code__line--added {
|
|
20
|
-
background: color-mix(in srgb, #1f883d 14%, transparent);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
.rb-code__line--removed {
|
|
24
|
-
background: color-mix(in srgb, #cf222e 14%, transparent);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.rb-code__line--focused {
|
|
28
|
-
background: color-mix(
|
|
29
|
-
in srgb,
|
|
30
|
-
var(--rb-code-annotation-accent) 10%,
|
|
31
|
-
transparent
|
|
32
|
-
);
|
|
33
|
-
outline: 1px solid
|
|
34
|
-
color-mix(in srgb, var(--rb-code-annotation-accent) 45%, transparent);
|
|
35
|
-
outline-offset: -1px;
|
|
36
|
-
}
|