@ai-markdown/remark-mark-highlight 1.0.1

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/LICENSE ADDED
@@ -0,0 +1,32 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Brian Lee
4
+
5
+ This package is a first-party continuation of two MIT-licensed, unmaintained
6
+ upstreams whose tokenizer this implementation derives from. Their copyright
7
+ notices are reproduced verbatim as required by the MIT license:
8
+
9
+ - remark-mark-highlight (https://github.com/widcardw/remark-mark-highlight):
10
+ Copyright (c) 2024 widcardw
11
+ - remark-highlight-mark / micromark-extension-highlight-mark /
12
+ mdast-util-highlight-mark
13
+ (https://github.com/shlroland/remark-highlight-mark):
14
+ Copyright (c) 2024 remark-highlight-mark
15
+
16
+ Permission is hereby granted, free of charge, to any person obtaining a copy
17
+ of this software and associated documentation files (the "Software"), to deal
18
+ in the Software without restriction, including without limitation the rights
19
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20
+ copies of the Software, and to permit persons to whom the Software is
21
+ furnished to do so, subject to the following conditions:
22
+
23
+ The above copyright notice and this permission notice shall be included in all
24
+ copies or substantial portions of the Software.
25
+
26
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # @ai-markdown/remark-mark-highlight
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@ai-markdown/remark-mark-highlight?logo=npm&color=cb3837)](https://www.npmjs.com/package/@ai-markdown/remark-mark-highlight)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@ai-markdown/remark-mark-highlight?color=blue)](https://www.npmjs.com/package/@ai-markdown/remark-mark-highlight)
5
+ [![minzipped size](https://img.shields.io/bundlephobia/minzip/@ai-markdown/remark-mark-highlight?label=minzip)](https://bundlephobia.com/package/@ai-markdown/remark-mark-highlight)
6
+ [![types](https://img.shields.io/npm/types/@ai-markdown/remark-mark-highlight?logo=typescript&logoColor=white&color=3178c6)](https://www.typescriptlang.org/)
7
+
8
+ [![Node ≥20](https://img.shields.io/badge/Node-%E2%89%A520-339933?logo=nodedotjs&logoColor=white)](https://nodejs.org/)
9
+ [![ESM + CJS](https://img.shields.io/badge/module-ESM%20%2B%20CJS-f7df1e?logo=javascript&logoColor=black)](#install)
10
+ [![remark plugin](https://img.shields.io/badge/remark-plugin-2c1e60?logo=markdown&logoColor=white)](https://github.com/remarkjs/remark)
11
+ [![license](https://img.shields.io/npm/l/@ai-markdown/remark-mark-highlight?color=green)](https://github.com/ai-markdown/ai-markdown/blob/main/packages/remark-mark-highlight/LICENSE)
12
+
13
+ [![CI](https://img.shields.io/github/actions/workflow/status/ai-markdown/ai-markdown/ci.yml?branch=main&label=CI&logo=githubactions&logoColor=white)](https://github.com/ai-markdown/ai-markdown/actions/workflows/ci.yml)
14
+ [![Release](https://img.shields.io/github/actions/workflow/status/ai-markdown/ai-markdown/release.yml?label=release&logo=githubactions&logoColor=white)](https://github.com/ai-markdown/ai-markdown/actions/workflows/release.yml)
15
+ [![part of ai-markdown](https://img.shields.io/badge/monorepo-ai--markdown-8a2be2?logo=github)](https://github.com/ai-markdown/ai-markdown)
16
+
17
+ A [remark](https://github.com/remarkjs/remark) syntax plugin for highlighted text. `==text==` becomes an mdast `mark` node whose `data.hName` tells remark-rehype to produce `<mark>text</mark>`. The package registers both parsing and Markdown serialization extensions; it does not provide CSS or an HTML sanitizer.
18
+
19
+ Use the named `remarkMarkHighlight` export with unified. The alias `remarkMark` retains the upstream export name, and lower-level micromark/mdast extensions are available for custom pipelines. The core renderer already enables this capability through its sealed `highlight` plugin, so core users do not need to register this package separately.
20
+
21
+ First-party continuation of the unmaintained [`remark-mark-highlight`](https://www.npmjs.com/package/remark-mark-highlight), used internally by [`@ai-markdown/react`](https://github.com/ai-markdown/ai-markdown/blob/main/packages/react)'s sealed `highlight` engine plugin — published standalone because it is useful outside this repo, and because the upstream's ESM-only exports map broke bare-Node CJS `require()` consumers.
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ npm install @ai-markdown/remark-mark-highlight
27
+ ```
28
+
29
+ Dual ESM/CJS build: both `import` and `require` work, types included for both.
30
+
31
+ ## Use
32
+
33
+ A parse-only processor produces an mdast tree. Call `parse` and `run` rather than `process`, since there is no compiler in this first pipeline:
34
+
35
+ ```ts
36
+ import { unified } from 'unified';
37
+ import remarkParse from 'remark-parse';
38
+ import { remarkMarkHighlight } from '@ai-markdown/remark-mark-highlight';
39
+
40
+ const processor = unified().use(remarkParse).use(remarkMarkHighlight);
41
+ const tree = processor.runSync(processor.parse('==hi=='));
42
+ // tree contains: { type: 'mark', data: { hName: 'mark' }, children: [...] }
43
+ ```
44
+
45
+ To render HTML, add the conversion and serialization stages (install their packages alongside unified and remark-parse):
46
+
47
+ ```ts
48
+ import { unified } from 'unified';
49
+ import remarkParse from 'remark-parse';
50
+ import remarkRehype from 'remark-rehype';
51
+ import rehypeStringify from 'rehype-stringify';
52
+ import { remarkMarkHighlight } from '@ai-markdown/remark-mark-highlight';
53
+
54
+ const html = unified()
55
+ .use(remarkParse)
56
+ .use(remarkMarkHighlight)
57
+ .use(remarkRehype)
58
+ .use(rehypeStringify)
59
+ .processSync('==**bold** inside==');
60
+
61
+ console.log(String(html));
62
+ // <p><mark><strong>bold</strong> inside</mark></p>
63
+ ```
64
+
65
+ No custom mdast-to-hast handler is required. If your full application pipeline uses rehype-sanitize, include `mark` in its allowed tags; the React adapter's default schema already does. For Markdown output, replace the HTML stages with remark-stringify. The plugin supplies the corresponding `==` serialization rules, including the escaping behavior described below.
66
+
67
+ ## Syntax at a glance
68
+
69
+ | Markdown | mdast | HTML |
70
+ | --------------------------- | ------------------------------------------------------------ | ------------------------------------------- |
71
+ | `==text==` | `{ type: 'mark', children: [text] }` | `<mark>text</mark>` |
72
+ | `==**bold** inside==` | `mark` → `strong` → `text` (nesting follows attention rules) | `<mark><strong>bold</strong> inside</mark>` |
73
+ | `\==not a mark==` | plain text | `==not a mark==` |
74
+ | `` `==code==` `` | `inlineCode` (code spans win) | `<code>==code==</code>` |
75
+ | `=single=` / `===triple===` | plain text (exactly two `=` open/close) | unchanged |
76
+
77
+ Works with `remark-rehype` out of the box (`data.hName = 'mark'`); no custom handler needed. If you sanitize with `rehype-sanitize`, allow the `mark` tag (the `@ai-markdown/react` default schema already does).
78
+
79
+ ## Compatibility
80
+
81
+ | | |
82
+ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
83
+ | unified / remark | remark 15+ (micromark 4, mdast-util-from-markdown 2, mdast-util-to-markdown 2) |
84
+ | Node | ≥ 20 |
85
+ | Module formats | ESM and CJS with types for both — the upstream's ESM-only exports map broke bare-Node `require()`, which is one reason this fork exists |
86
+ | Types | `Mark` is registered in mdast's `PhrasingContentMap` and `RootContentMap`, so `mark` nodes type-check inside paragraphs |
87
+
88
+ ## Behavior contract
89
+
90
+ - Attention-style tokenizer (same family as GFM strikethrough): exactly two `=`, standard flanking rules, nesting with emphasis/strong, escapes and code spans respected, spans may contain line endings. Interplay with other attention extensions (e.g. GFM strikethrough) follows micromark's shared attention machinery but is not part of the pinned corpus, which runs the plugin without GFM.
91
+ - **Byte-compatible with `remark-mark-highlight@0.1.1`**: a 50-case parity corpus (mdast with positions + hast), generated against the upstream before this package replaced it, runs in CI. Behavior changes would be a semver-major of this package.
92
+
93
+ ## Footguns
94
+
95
+ - **Loading the plugin changes how `remark-stringify` escapes `=`.** The serializer registers `=` as unsafe in phrasing content (so `==` spans survive round-trips), which escapes _every_ phrasing `=` — `let a = b` serializes as `let a \= b`. This matches the upstream's behavior and only affects stringify output, never parsing or rendering.
96
+
97
+ ## API
98
+
99
+ | Export | What |
100
+ | ------------------------------------------------------- | -------------------------------------------------------------------------------------- |
101
+ | `remarkMarkHighlight` | The remark plugin (also aliased as `remarkMark`, the upstream's export name) |
102
+ | `markHighlight()` | The raw micromark extension |
103
+ | `markHighlightFromMarkdown` / `markHighlightToMarkdown` | The mdast from/to-markdown extensions |
104
+ | `Mark` (type) | The mdast node interface (`type: 'mark'`), registered in mdast's phrasing-content maps |
105
+
106
+ ## Versioning
107
+
108
+ This package versions independently of the `@ai-markdown/react` release train — core depends on it through a normal semver range.
109
+
110
+ ## Integration boundaries and verification
111
+
112
+ The delimiter must be exactly two equals signs with valid attention-style flanking. A single or triple run remains text; code spans and escapes take precedence, and nested strong/emphasis can appear inside a mark. This package does not itself relax delimiter flanking for CJK text or replace the separate CJK plugins used by core.
113
+
114
+ Importing the plugin's types registers `Mark` in mdast's content maps. The resulting node is phrasing content with children, so a tree visitor should recurse rather than assume a single text child. `data.hName` carries the HTML element mapping; removing that data in an intervening transform changes how the next stage renders the node.
115
+
116
+ The pinned 50-case parity corpus compares positional mdast and hast with `remark-mark-highlight@0.1.1`. It covers this plugin's standalone behavior; interactions with additional attention extensions such as GFM are not implied by that parity claim. Test your complete plugin combination if you depend on a particular nesting rule.
117
+
118
+ For repository work, run `pnpm --filter @ai-markdown/remark-mark-highlight test` and the package build. When changing syntax or serialization, include both a parsed-tree example and a round-trip example: escaping every phrasing equals sign is an existing serializer contract, even where the source is not a highlight span. This package has independent semver, so its behavior changes are not automatically governed by the React adapter's version number.
119
+
120
+ ## License
121
+
122
+ MIT. Derived from the MIT-licensed `remark-mark-highlight` and `micromark-extension-highlight-mark` / `mdast-util-highlight-mark`; see [LICENSE](https://github.com/ai-markdown/ai-markdown/blob/main/packages/remark-mark-highlight/LICENSE) for attribution.
package/dist/index.cjs ADDED
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ markHighlight: () => markHighlight,
24
+ markHighlightFromMarkdown: () => markHighlightFromMarkdown,
25
+ markHighlightToMarkdown: () => markHighlightToMarkdown,
26
+ remarkMark: () => remarkMarkHighlight,
27
+ remarkMarkHighlight: () => remarkMarkHighlight
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/syntax.ts
32
+ var import_micromark_util_chunked = require("micromark-util-chunked");
33
+ var import_micromark_util_classify_character = require("micromark-util-classify-character");
34
+ var import_micromark_util_resolve_all = require("micromark-util-resolve-all");
35
+ var import_micromark_util_symbol = require("micromark-util-symbol");
36
+ var SEQUENCE_TEMPORARY = "highlightSequenceTemporary";
37
+ var SEQUENCE = "highlightSequence";
38
+ var HIGHLIGHT = "highlight";
39
+ var HIGHLIGHT_TEXT = "highlightText";
40
+ function markHighlight() {
41
+ const tokenizer = {
42
+ name: "highlight",
43
+ tokenize: tokenizeHighlight,
44
+ resolveAll: resolveAllHighlight
45
+ };
46
+ return {
47
+ text: { [import_micromark_util_symbol.codes.equalsTo]: tokenizer },
48
+ insideSpan: { null: [tokenizer] },
49
+ attentionMarkers: { null: [import_micromark_util_symbol.codes.equalsTo] }
50
+ };
51
+ function resolveAllHighlight(events, context) {
52
+ let index = -1;
53
+ while (++index < events.length) {
54
+ if (events[index][0] === "enter" && events[index][1].type === SEQUENCE_TEMPORARY && events[index][1]._close) {
55
+ let open = index;
56
+ while (open--) {
57
+ if (events[open][0] === "exit" && events[open][1].type === SEQUENCE_TEMPORARY && events[open][1]._open && // Sequences are all length 2, but keep the equal-length guard the
58
+ // upstreams carry — it is part of the pinned behavior.
59
+ events[index][1].end.offset - events[index][1].start.offset === events[open][1].end.offset - events[open][1].start.offset) {
60
+ events[index][1].type = SEQUENCE;
61
+ events[open][1].type = SEQUENCE;
62
+ const highlight = {
63
+ type: HIGHLIGHT,
64
+ start: Object.assign({}, events[open][1].start),
65
+ end: Object.assign({}, events[index][1].end)
66
+ };
67
+ const text = {
68
+ type: HIGHLIGHT_TEXT,
69
+ start: Object.assign({}, events[open][1].end),
70
+ end: Object.assign({}, events[index][1].start)
71
+ };
72
+ const nextEvents = [
73
+ ["enter", highlight, context],
74
+ ["enter", events[open][1], context],
75
+ ["exit", events[open][1], context],
76
+ ["enter", text, context]
77
+ ];
78
+ const insideSpan = context.parser.constructs.insideSpan.null;
79
+ if (insideSpan) {
80
+ (0, import_micromark_util_chunked.splice)(nextEvents, nextEvents.length, 0, (0, import_micromark_util_resolve_all.resolveAll)(insideSpan, events.slice(open + 1, index), context));
81
+ }
82
+ (0, import_micromark_util_chunked.splice)(nextEvents, nextEvents.length, 0, [
83
+ ["exit", text, context],
84
+ ["enter", events[index][1], context],
85
+ ["exit", events[index][1], context],
86
+ ["exit", highlight, context]
87
+ ]);
88
+ (0, import_micromark_util_chunked.splice)(events, open - 1, index - open + 3, nextEvents);
89
+ index = open + nextEvents.length - 2;
90
+ break;
91
+ }
92
+ }
93
+ }
94
+ }
95
+ index = -1;
96
+ while (++index < events.length) {
97
+ if (events[index][1].type === SEQUENCE_TEMPORARY) {
98
+ events[index][1].type = import_micromark_util_symbol.types.data;
99
+ }
100
+ }
101
+ return events;
102
+ }
103
+ function tokenizeHighlight(effects, ok, nok) {
104
+ const previous = this.previous;
105
+ const events = this.events;
106
+ let size = 0;
107
+ return start;
108
+ function start(code) {
109
+ if (previous === import_micromark_util_symbol.codes.equalsTo && events[events.length - 1][1].type !== import_micromark_util_symbol.types.characterEscape) {
110
+ return nok(code);
111
+ }
112
+ effects.enter(SEQUENCE_TEMPORARY);
113
+ return more(code);
114
+ }
115
+ function more(code) {
116
+ const before = (0, import_micromark_util_classify_character.classifyCharacter)(previous);
117
+ if (code === import_micromark_util_symbol.codes.equalsTo) {
118
+ if (size > 1) return nok(code);
119
+ effects.consume(code);
120
+ size++;
121
+ return more;
122
+ }
123
+ if (size < 2) return nok(code);
124
+ const token = effects.exit(SEQUENCE_TEMPORARY);
125
+ const after = (0, import_micromark_util_classify_character.classifyCharacter)(code);
126
+ token._open = !after || after === import_micromark_util_symbol.constants.attentionSideAfter && Boolean(before);
127
+ token._close = !before || before === import_micromark_util_symbol.constants.attentionSideAfter && Boolean(after);
128
+ return ok(code);
129
+ }
130
+ }
131
+ }
132
+
133
+ // src/mdast.ts
134
+ var constructsWithoutEquals = [
135
+ "autolink",
136
+ "destinationLiteral",
137
+ "destinationRaw",
138
+ "reference",
139
+ "titleQuote",
140
+ "titleApostrophe"
141
+ ];
142
+ function enterMark(token) {
143
+ this.enter({ type: "mark", children: [], data: { hName: "mark" } }, token);
144
+ }
145
+ function exitMark(token) {
146
+ this.exit(token);
147
+ }
148
+ var markHighlightFromMarkdown = {
149
+ canContainEols: ["mark"],
150
+ enter: { highlight: enterMark },
151
+ exit: { highlight: exitMark }
152
+ };
153
+ var handleMark = function(node, _, state, info) {
154
+ const tracker = state.createTracker(info);
155
+ const exit = state.enter("highlight");
156
+ let value = tracker.move("==");
157
+ value += state.containerPhrasing(node, { ...tracker.current(), before: value, after: "=" });
158
+ value += tracker.move("==");
159
+ exit();
160
+ return value;
161
+ };
162
+ handleMark.peek = function() {
163
+ return "=";
164
+ };
165
+ var markHighlightToMarkdown = {
166
+ unsafe: [{ character: "=", inConstruct: "phrasing", notInConstruct: constructsWithoutEquals }],
167
+ handlers: { mark: handleMark }
168
+ };
169
+
170
+ // src/index.ts
171
+ function remarkMarkHighlight() {
172
+ const data = this.data();
173
+ add("micromarkExtensions", markHighlight());
174
+ add("fromMarkdownExtensions", markHighlightFromMarkdown);
175
+ add("toMarkdownExtensions", markHighlightToMarkdown);
176
+ function add(field, value) {
177
+ (data[field] ??= []).push(value);
178
+ }
179
+ }
180
+ // Annotate the CommonJS export names for ESM import in node:
181
+ 0 && (module.exports = {
182
+ markHighlight,
183
+ markHighlightFromMarkdown,
184
+ markHighlightToMarkdown,
185
+ remarkMark,
186
+ remarkMarkHighlight
187
+ });
188
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/syntax.ts","../src/mdast.ts"],"sourcesContent":["/**\n * `@ai-markdown/remark-mark-highlight` — remark plugin for `==mark==`\n * highlight syntax. First-party continuation of the unmaintained\n * `remark-mark-highlight`, byte-compatible with its 0.1.1 output (pinned by\n * the parity corpus) and shipping the dual ESM/CJS build the upstream\n * lacked.\n *\n * ```ts\n * import { remarkMarkHighlight } from '@ai-markdown/remark-mark-highlight';\n *\n * unified().use(remarkParse).use(remarkMarkHighlight)\n * // ==text== → mdast `mark` node → <mark>text</mark>\n * ```\n *\n * @module @ai-markdown/remark-mark-highlight\n */\n\nimport type { Processor } from 'unified';\nimport { markHighlight } from './syntax.js';\nimport { markHighlightFromMarkdown, markHighlightToMarkdown } from './mdast.js';\n\n/** remark plugin enabling `==mark==` highlight syntax. */\nexport function remarkMarkHighlight(this: Processor): undefined {\n const data = this.data() as Record<string, unknown[] | undefined>;\n\n add('micromarkExtensions', markHighlight());\n add('fromMarkdownExtensions', markHighlightFromMarkdown);\n add('toMarkdownExtensions', markHighlightToMarkdown);\n\n function add(field: string, value: unknown): void {\n (data[field] ??= []).push(value);\n }\n}\n\n/** Drop-in alias matching the upstream `remark-mark-highlight` export name. */\nexport { remarkMarkHighlight as remarkMark };\n\nexport { markHighlight } from './syntax.js';\nexport { markHighlightFromMarkdown, markHighlightToMarkdown, type Mark } from './mdast.js';\n","/**\n * micromark extension for `==mark==` highlight syntax.\n *\n * Attention-style tokenizer modeled on `micromark-extension-gfm-strikethrough`,\n * derived from the (MIT, unmaintained) upstreams `remark-mark-highlight` and\n * `micromark-extension-highlight-mark` — both ship this same tokenizer; this\n * package is its maintained continuation. Parse behavior (mdast + hast) is\n * pinned byte-for-byte against `remark-mark-highlight@0.1.1` by the parity\n * corpus in `parity.test.ts` (`test/fixtures/baseline-0.1.1.json`, generated\n * BEFORE the swap so it stays an independent oracle).\n *\n * Sequence length is exactly two `=`; open/close classification follows the\n * standard attention flanking rules via `classifyCharacter`.\n *\n * @module syntax\n */\n\nimport { splice } from 'micromark-util-chunked';\nimport { classifyCharacter } from 'micromark-util-classify-character';\nimport { resolveAll } from 'micromark-util-resolve-all';\nimport { codes, constants, types } from 'micromark-util-symbol';\nimport type { Construct, Event, Extension, State, Token, TokenizeContext, Tokenizer } from 'micromark-util-types';\n\ndeclare module 'micromark-util-types' {\n interface TokenTypeMap {\n highlight: 'highlight';\n highlightText: 'highlightText';\n highlightSequence: 'highlightSequence';\n highlightSequenceTemporary: 'highlightSequenceTemporary';\n }\n}\n\nconst SEQUENCE_TEMPORARY = 'highlightSequenceTemporary';\nconst SEQUENCE = 'highlightSequence';\nconst HIGHLIGHT = 'highlight';\nconst HIGHLIGHT_TEXT = 'highlightText';\n\n/** Create the micromark extension enabling `==mark==` highlight syntax. */\nexport function markHighlight(): Extension {\n const tokenizer: Construct = {\n name: 'highlight',\n tokenize: tokenizeHighlight,\n resolveAll: resolveAllHighlight,\n };\n\n return {\n text: { [codes.equalsTo]: tokenizer },\n insideSpan: { null: [tokenizer] },\n attentionMarkers: { null: [codes.equalsTo] },\n };\n\n /** Pair open/close sequences into highlight tokens; demote leftovers to data. */\n function resolveAllHighlight(events: Event[], context: TokenizeContext): Event[] {\n let index = -1;\n\n while (++index < events.length) {\n if (events[index][0] === 'enter' && events[index][1].type === SEQUENCE_TEMPORARY && events[index][1]._close) {\n let open = index;\n while (open--) {\n if (\n events[open][0] === 'exit' &&\n events[open][1].type === SEQUENCE_TEMPORARY &&\n events[open][1]._open &&\n // Sequences are all length 2, but keep the equal-length guard the\n // upstreams carry — it is part of the pinned behavior.\n events[index][1].end.offset - events[index][1].start.offset ===\n events[open][1].end.offset - events[open][1].start.offset\n ) {\n events[index][1].type = SEQUENCE;\n events[open][1].type = SEQUENCE;\n\n const highlight: Token = {\n type: HIGHLIGHT,\n start: Object.assign({}, events[open][1].start),\n end: Object.assign({}, events[index][1].end),\n };\n const text: Token = {\n type: HIGHLIGHT_TEXT,\n start: Object.assign({}, events[open][1].end),\n end: Object.assign({}, events[index][1].start),\n };\n\n const nextEvents: Event[] = [\n ['enter', highlight, context],\n ['enter', events[open][1], context],\n ['exit', events[open][1], context],\n ['enter', text, context],\n ];\n const insideSpan = context.parser.constructs.insideSpan.null;\n if (insideSpan) {\n splice(nextEvents, nextEvents.length, 0, resolveAll(insideSpan, events.slice(open + 1, index), context));\n }\n splice(nextEvents, nextEvents.length, 0, [\n ['exit', text, context],\n ['enter', events[index][1], context],\n ['exit', events[index][1], context],\n ['exit', highlight, context],\n ]);\n\n splice(events, open - 1, index - open + 3, nextEvents);\n index = open + nextEvents.length - 2;\n break;\n }\n }\n }\n }\n\n index = -1;\n while (++index < events.length) {\n if (events[index][1].type === SEQUENCE_TEMPORARY) {\n events[index][1].type = types.data;\n }\n }\n\n return events;\n }\n\n function tokenizeHighlight(this: TokenizeContext, effects: Parameters<Tokenizer>[0], ok: State, nok: State): State {\n const previous = this.previous;\n const events = this.events;\n let size = 0;\n\n return start;\n\n function start(code: Parameters<State>[0]): State | undefined {\n // A `=` directly before us that is not an escape means we are inside a\n // longer run the construct already rejected — do not re-enter.\n if (previous === codes.equalsTo && events[events.length - 1][1].type !== types.characterEscape) {\n return nok(code);\n }\n effects.enter(SEQUENCE_TEMPORARY);\n return more(code);\n }\n\n function more(code: Parameters<State>[0]): State | undefined {\n const before = classifyCharacter(previous);\n\n if (code === codes.equalsTo) {\n // A third `=` is not a highlight sequence.\n if (size > 1) return nok(code);\n effects.consume(code);\n size++;\n return more;\n }\n\n if (size < 2) return nok(code);\n\n const token = effects.exit(SEQUENCE_TEMPORARY);\n const after = classifyCharacter(code);\n token._open = !after || (after === constants.attentionSideAfter && Boolean(before));\n token._close = !before || (before === constants.attentionSideAfter && Boolean(after));\n return ok(code);\n }\n }\n}\n","/**\n * mdast extensions for `==mark==` highlight: from-markdown (build a `mark`\n * node rendered as `<mark>` via `data.hName`, so no custom hast handler is\n * needed downstream) and to-markdown (serialize back to `==…==`).\n *\n * The node shape (from-markdown direction: mdast + hast) is pinned against\n * `remark-mark-highlight@0.1.1` by the parity corpus (`parity.test.ts`);\n * the to-markdown direction is covered by round-trip smokes only — the\n * baseline fixture records no upstream serializer output.\n *\n * @module mdast\n */\n\nimport type { Data, Parent, PhrasingContent } from 'mdast';\nimport type { CompileContext, Extension as FromMarkdownExtension, Token } from 'mdast-util-from-markdown';\nimport type { ConstructName, Handle as ToMarkdownHandle, Options as ToMarkdownExtension } from 'mdast-util-to-markdown';\n\n/** A `==highlight==` span, rendered as `<mark>` through `data.hName`.\n * `data` stays assignable to mdast's `Data` (hProperties/hChildren etc.) so\n * generic tree visitors that write those fields still compile on `mark`. */\nexport interface Mark extends Parent {\n type: 'mark';\n children: PhrasingContent[];\n data?: Data & { hName?: 'mark' };\n}\n\ndeclare module 'mdast' {\n interface PhrasingContentMap {\n mark: Mark;\n }\n interface RootContentMap {\n mark: Mark;\n }\n}\n\ndeclare module 'mdast-util-to-markdown' {\n interface ConstructNameMap {\n highlight: 'highlight';\n }\n}\n\n/** Constructs inside which a `=` needs no escaping when serializing. */\nconst constructsWithoutEquals: ConstructName[] = [\n 'autolink',\n 'destinationLiteral',\n 'destinationRaw',\n 'reference',\n 'titleQuote',\n 'titleApostrophe',\n];\n\nfunction enterMark(this: CompileContext, token: Token): undefined {\n this.enter({ type: 'mark', children: [], data: { hName: 'mark' } }, token);\n}\n\nfunction exitMark(this: CompileContext, token: Token): undefined {\n this.exit(token);\n}\n\n/** From-markdown extension: map `highlight` tokens to `mark` nodes. */\nexport const markHighlightFromMarkdown: FromMarkdownExtension = {\n canContainEols: ['mark'],\n enter: { highlight: enterMark },\n exit: { highlight: exitMark },\n};\n\nconst handleMark: ToMarkdownHandle = function (node: Mark, _, state, info) {\n const tracker = state.createTracker(info);\n const exit = state.enter('highlight');\n let value = tracker.move('==');\n value += state.containerPhrasing(node, { ...tracker.current(), before: value, after: '=' });\n value += tracker.move('==');\n exit();\n return value;\n};\n\n(handleMark as ToMarkdownHandle & { peek(): string }).peek = function (): string {\n return '=';\n};\n\n/** To-markdown extension: serialize `mark` nodes back to `==…==`. */\nexport const markHighlightToMarkdown: ToMarkdownExtension = {\n unsafe: [{ character: '=', inConstruct: 'phrasing', notInConstruct: constructsWithoutEquals }],\n handlers: { mark: handleMark },\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,96 @@
1
+ import { Processor } from 'unified';
2
+ import { Extension } from 'micromark-util-types';
3
+ import { Parent, PhrasingContent, Data } from 'mdast';
4
+ import { Extension as Extension$1 } from 'mdast-util-from-markdown';
5
+ import { Options } from 'mdast-util-to-markdown';
6
+
7
+ /**
8
+ * micromark extension for `==mark==` highlight syntax.
9
+ *
10
+ * Attention-style tokenizer modeled on `micromark-extension-gfm-strikethrough`,
11
+ * derived from the (MIT, unmaintained) upstreams `remark-mark-highlight` and
12
+ * `micromark-extension-highlight-mark` — both ship this same tokenizer; this
13
+ * package is its maintained continuation. Parse behavior (mdast + hast) is
14
+ * pinned byte-for-byte against `remark-mark-highlight@0.1.1` by the parity
15
+ * corpus in `parity.test.ts` (`test/fixtures/baseline-0.1.1.json`, generated
16
+ * BEFORE the swap so it stays an independent oracle).
17
+ *
18
+ * Sequence length is exactly two `=`; open/close classification follows the
19
+ * standard attention flanking rules via `classifyCharacter`.
20
+ *
21
+ * @module syntax
22
+ */
23
+
24
+ declare module 'micromark-util-types' {
25
+ interface TokenTypeMap {
26
+ highlight: 'highlight';
27
+ highlightText: 'highlightText';
28
+ highlightSequence: 'highlightSequence';
29
+ highlightSequenceTemporary: 'highlightSequenceTemporary';
30
+ }
31
+ }
32
+ /** Create the micromark extension enabling `==mark==` highlight syntax. */
33
+ declare function markHighlight(): Extension;
34
+
35
+ /**
36
+ * mdast extensions for `==mark==` highlight: from-markdown (build a `mark`
37
+ * node rendered as `<mark>` via `data.hName`, so no custom hast handler is
38
+ * needed downstream) and to-markdown (serialize back to `==…==`).
39
+ *
40
+ * The node shape (from-markdown direction: mdast + hast) is pinned against
41
+ * `remark-mark-highlight@0.1.1` by the parity corpus (`parity.test.ts`);
42
+ * the to-markdown direction is covered by round-trip smokes only — the
43
+ * baseline fixture records no upstream serializer output.
44
+ *
45
+ * @module mdast
46
+ */
47
+
48
+ /** A `==highlight==` span, rendered as `<mark>` through `data.hName`.
49
+ * `data` stays assignable to mdast's `Data` (hProperties/hChildren etc.) so
50
+ * generic tree visitors that write those fields still compile on `mark`. */
51
+ interface Mark extends Parent {
52
+ type: 'mark';
53
+ children: PhrasingContent[];
54
+ data?: Data & {
55
+ hName?: 'mark';
56
+ };
57
+ }
58
+ declare module 'mdast' {
59
+ interface PhrasingContentMap {
60
+ mark: Mark;
61
+ }
62
+ interface RootContentMap {
63
+ mark: Mark;
64
+ }
65
+ }
66
+ declare module 'mdast-util-to-markdown' {
67
+ interface ConstructNameMap {
68
+ highlight: 'highlight';
69
+ }
70
+ }
71
+ /** From-markdown extension: map `highlight` tokens to `mark` nodes. */
72
+ declare const markHighlightFromMarkdown: Extension$1;
73
+ /** To-markdown extension: serialize `mark` nodes back to `==…==`. */
74
+ declare const markHighlightToMarkdown: Options;
75
+
76
+ /**
77
+ * `@ai-markdown/remark-mark-highlight` — remark plugin for `==mark==`
78
+ * highlight syntax. First-party continuation of the unmaintained
79
+ * `remark-mark-highlight`, byte-compatible with its 0.1.1 output (pinned by
80
+ * the parity corpus) and shipping the dual ESM/CJS build the upstream
81
+ * lacked.
82
+ *
83
+ * ```ts
84
+ * import { remarkMarkHighlight } from '@ai-markdown/remark-mark-highlight';
85
+ *
86
+ * unified().use(remarkParse).use(remarkMarkHighlight)
87
+ * // ==text== → mdast `mark` node → <mark>text</mark>
88
+ * ```
89
+ *
90
+ * @module @ai-markdown/remark-mark-highlight
91
+ */
92
+
93
+ /** remark plugin enabling `==mark==` highlight syntax. */
94
+ declare function remarkMarkHighlight(this: Processor): undefined;
95
+
96
+ export { type Mark, markHighlight, markHighlightFromMarkdown, markHighlightToMarkdown, remarkMarkHighlight as remarkMark, remarkMarkHighlight };
@@ -0,0 +1,96 @@
1
+ import { Processor } from 'unified';
2
+ import { Extension } from 'micromark-util-types';
3
+ import { Parent, PhrasingContent, Data } from 'mdast';
4
+ import { Extension as Extension$1 } from 'mdast-util-from-markdown';
5
+ import { Options } from 'mdast-util-to-markdown';
6
+
7
+ /**
8
+ * micromark extension for `==mark==` highlight syntax.
9
+ *
10
+ * Attention-style tokenizer modeled on `micromark-extension-gfm-strikethrough`,
11
+ * derived from the (MIT, unmaintained) upstreams `remark-mark-highlight` and
12
+ * `micromark-extension-highlight-mark` — both ship this same tokenizer; this
13
+ * package is its maintained continuation. Parse behavior (mdast + hast) is
14
+ * pinned byte-for-byte against `remark-mark-highlight@0.1.1` by the parity
15
+ * corpus in `parity.test.ts` (`test/fixtures/baseline-0.1.1.json`, generated
16
+ * BEFORE the swap so it stays an independent oracle).
17
+ *
18
+ * Sequence length is exactly two `=`; open/close classification follows the
19
+ * standard attention flanking rules via `classifyCharacter`.
20
+ *
21
+ * @module syntax
22
+ */
23
+
24
+ declare module 'micromark-util-types' {
25
+ interface TokenTypeMap {
26
+ highlight: 'highlight';
27
+ highlightText: 'highlightText';
28
+ highlightSequence: 'highlightSequence';
29
+ highlightSequenceTemporary: 'highlightSequenceTemporary';
30
+ }
31
+ }
32
+ /** Create the micromark extension enabling `==mark==` highlight syntax. */
33
+ declare function markHighlight(): Extension;
34
+
35
+ /**
36
+ * mdast extensions for `==mark==` highlight: from-markdown (build a `mark`
37
+ * node rendered as `<mark>` via `data.hName`, so no custom hast handler is
38
+ * needed downstream) and to-markdown (serialize back to `==…==`).
39
+ *
40
+ * The node shape (from-markdown direction: mdast + hast) is pinned against
41
+ * `remark-mark-highlight@0.1.1` by the parity corpus (`parity.test.ts`);
42
+ * the to-markdown direction is covered by round-trip smokes only — the
43
+ * baseline fixture records no upstream serializer output.
44
+ *
45
+ * @module mdast
46
+ */
47
+
48
+ /** A `==highlight==` span, rendered as `<mark>` through `data.hName`.
49
+ * `data` stays assignable to mdast's `Data` (hProperties/hChildren etc.) so
50
+ * generic tree visitors that write those fields still compile on `mark`. */
51
+ interface Mark extends Parent {
52
+ type: 'mark';
53
+ children: PhrasingContent[];
54
+ data?: Data & {
55
+ hName?: 'mark';
56
+ };
57
+ }
58
+ declare module 'mdast' {
59
+ interface PhrasingContentMap {
60
+ mark: Mark;
61
+ }
62
+ interface RootContentMap {
63
+ mark: Mark;
64
+ }
65
+ }
66
+ declare module 'mdast-util-to-markdown' {
67
+ interface ConstructNameMap {
68
+ highlight: 'highlight';
69
+ }
70
+ }
71
+ /** From-markdown extension: map `highlight` tokens to `mark` nodes. */
72
+ declare const markHighlightFromMarkdown: Extension$1;
73
+ /** To-markdown extension: serialize `mark` nodes back to `==…==`. */
74
+ declare const markHighlightToMarkdown: Options;
75
+
76
+ /**
77
+ * `@ai-markdown/remark-mark-highlight` — remark plugin for `==mark==`
78
+ * highlight syntax. First-party continuation of the unmaintained
79
+ * `remark-mark-highlight`, byte-compatible with its 0.1.1 output (pinned by
80
+ * the parity corpus) and shipping the dual ESM/CJS build the upstream
81
+ * lacked.
82
+ *
83
+ * ```ts
84
+ * import { remarkMarkHighlight } from '@ai-markdown/remark-mark-highlight';
85
+ *
86
+ * unified().use(remarkParse).use(remarkMarkHighlight)
87
+ * // ==text== → mdast `mark` node → <mark>text</mark>
88
+ * ```
89
+ *
90
+ * @module @ai-markdown/remark-mark-highlight
91
+ */
92
+
93
+ /** remark plugin enabling `==mark==` highlight syntax. */
94
+ declare function remarkMarkHighlight(this: Processor): undefined;
95
+
96
+ export { type Mark, markHighlight, markHighlightFromMarkdown, markHighlightToMarkdown, remarkMarkHighlight as remarkMark, remarkMarkHighlight };
package/dist/index.js ADDED
@@ -0,0 +1,157 @@
1
+ // src/syntax.ts
2
+ import { splice } from "micromark-util-chunked";
3
+ import { classifyCharacter } from "micromark-util-classify-character";
4
+ import { resolveAll } from "micromark-util-resolve-all";
5
+ import { codes, constants, types } from "micromark-util-symbol";
6
+ var SEQUENCE_TEMPORARY = "highlightSequenceTemporary";
7
+ var SEQUENCE = "highlightSequence";
8
+ var HIGHLIGHT = "highlight";
9
+ var HIGHLIGHT_TEXT = "highlightText";
10
+ function markHighlight() {
11
+ const tokenizer = {
12
+ name: "highlight",
13
+ tokenize: tokenizeHighlight,
14
+ resolveAll: resolveAllHighlight
15
+ };
16
+ return {
17
+ text: { [codes.equalsTo]: tokenizer },
18
+ insideSpan: { null: [tokenizer] },
19
+ attentionMarkers: { null: [codes.equalsTo] }
20
+ };
21
+ function resolveAllHighlight(events, context) {
22
+ let index = -1;
23
+ while (++index < events.length) {
24
+ if (events[index][0] === "enter" && events[index][1].type === SEQUENCE_TEMPORARY && events[index][1]._close) {
25
+ let open = index;
26
+ while (open--) {
27
+ if (events[open][0] === "exit" && events[open][1].type === SEQUENCE_TEMPORARY && events[open][1]._open && // Sequences are all length 2, but keep the equal-length guard the
28
+ // upstreams carry — it is part of the pinned behavior.
29
+ events[index][1].end.offset - events[index][1].start.offset === events[open][1].end.offset - events[open][1].start.offset) {
30
+ events[index][1].type = SEQUENCE;
31
+ events[open][1].type = SEQUENCE;
32
+ const highlight = {
33
+ type: HIGHLIGHT,
34
+ start: Object.assign({}, events[open][1].start),
35
+ end: Object.assign({}, events[index][1].end)
36
+ };
37
+ const text = {
38
+ type: HIGHLIGHT_TEXT,
39
+ start: Object.assign({}, events[open][1].end),
40
+ end: Object.assign({}, events[index][1].start)
41
+ };
42
+ const nextEvents = [
43
+ ["enter", highlight, context],
44
+ ["enter", events[open][1], context],
45
+ ["exit", events[open][1], context],
46
+ ["enter", text, context]
47
+ ];
48
+ const insideSpan = context.parser.constructs.insideSpan.null;
49
+ if (insideSpan) {
50
+ splice(nextEvents, nextEvents.length, 0, resolveAll(insideSpan, events.slice(open + 1, index), context));
51
+ }
52
+ splice(nextEvents, nextEvents.length, 0, [
53
+ ["exit", text, context],
54
+ ["enter", events[index][1], context],
55
+ ["exit", events[index][1], context],
56
+ ["exit", highlight, context]
57
+ ]);
58
+ splice(events, open - 1, index - open + 3, nextEvents);
59
+ index = open + nextEvents.length - 2;
60
+ break;
61
+ }
62
+ }
63
+ }
64
+ }
65
+ index = -1;
66
+ while (++index < events.length) {
67
+ if (events[index][1].type === SEQUENCE_TEMPORARY) {
68
+ events[index][1].type = types.data;
69
+ }
70
+ }
71
+ return events;
72
+ }
73
+ function tokenizeHighlight(effects, ok, nok) {
74
+ const previous = this.previous;
75
+ const events = this.events;
76
+ let size = 0;
77
+ return start;
78
+ function start(code) {
79
+ if (previous === codes.equalsTo && events[events.length - 1][1].type !== types.characterEscape) {
80
+ return nok(code);
81
+ }
82
+ effects.enter(SEQUENCE_TEMPORARY);
83
+ return more(code);
84
+ }
85
+ function more(code) {
86
+ const before = classifyCharacter(previous);
87
+ if (code === codes.equalsTo) {
88
+ if (size > 1) return nok(code);
89
+ effects.consume(code);
90
+ size++;
91
+ return more;
92
+ }
93
+ if (size < 2) return nok(code);
94
+ const token = effects.exit(SEQUENCE_TEMPORARY);
95
+ const after = classifyCharacter(code);
96
+ token._open = !after || after === constants.attentionSideAfter && Boolean(before);
97
+ token._close = !before || before === constants.attentionSideAfter && Boolean(after);
98
+ return ok(code);
99
+ }
100
+ }
101
+ }
102
+
103
+ // src/mdast.ts
104
+ var constructsWithoutEquals = [
105
+ "autolink",
106
+ "destinationLiteral",
107
+ "destinationRaw",
108
+ "reference",
109
+ "titleQuote",
110
+ "titleApostrophe"
111
+ ];
112
+ function enterMark(token) {
113
+ this.enter({ type: "mark", children: [], data: { hName: "mark" } }, token);
114
+ }
115
+ function exitMark(token) {
116
+ this.exit(token);
117
+ }
118
+ var markHighlightFromMarkdown = {
119
+ canContainEols: ["mark"],
120
+ enter: { highlight: enterMark },
121
+ exit: { highlight: exitMark }
122
+ };
123
+ var handleMark = function(node, _, state, info) {
124
+ const tracker = state.createTracker(info);
125
+ const exit = state.enter("highlight");
126
+ let value = tracker.move("==");
127
+ value += state.containerPhrasing(node, { ...tracker.current(), before: value, after: "=" });
128
+ value += tracker.move("==");
129
+ exit();
130
+ return value;
131
+ };
132
+ handleMark.peek = function() {
133
+ return "=";
134
+ };
135
+ var markHighlightToMarkdown = {
136
+ unsafe: [{ character: "=", inConstruct: "phrasing", notInConstruct: constructsWithoutEquals }],
137
+ handlers: { mark: handleMark }
138
+ };
139
+
140
+ // src/index.ts
141
+ function remarkMarkHighlight() {
142
+ const data = this.data();
143
+ add("micromarkExtensions", markHighlight());
144
+ add("fromMarkdownExtensions", markHighlightFromMarkdown);
145
+ add("toMarkdownExtensions", markHighlightToMarkdown);
146
+ function add(field, value) {
147
+ (data[field] ??= []).push(value);
148
+ }
149
+ }
150
+ export {
151
+ markHighlight,
152
+ markHighlightFromMarkdown,
153
+ markHighlightToMarkdown,
154
+ remarkMarkHighlight as remarkMark,
155
+ remarkMarkHighlight
156
+ };
157
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/syntax.ts","../src/mdast.ts","../src/index.ts"],"sourcesContent":["/**\n * micromark extension for `==mark==` highlight syntax.\n *\n * Attention-style tokenizer modeled on `micromark-extension-gfm-strikethrough`,\n * derived from the (MIT, unmaintained) upstreams `remark-mark-highlight` and\n * `micromark-extension-highlight-mark` — both ship this same tokenizer; this\n * package is its maintained continuation. Parse behavior (mdast + hast) is\n * pinned byte-for-byte against `remark-mark-highlight@0.1.1` by the parity\n * corpus in `parity.test.ts` (`test/fixtures/baseline-0.1.1.json`, generated\n * BEFORE the swap so it stays an independent oracle).\n *\n * Sequence length is exactly two `=`; open/close classification follows the\n * standard attention flanking rules via `classifyCharacter`.\n *\n * @module syntax\n */\n\nimport { splice } from 'micromark-util-chunked';\nimport { classifyCharacter } from 'micromark-util-classify-character';\nimport { resolveAll } from 'micromark-util-resolve-all';\nimport { codes, constants, types } from 'micromark-util-symbol';\nimport type { Construct, Event, Extension, State, Token, TokenizeContext, Tokenizer } from 'micromark-util-types';\n\ndeclare module 'micromark-util-types' {\n interface TokenTypeMap {\n highlight: 'highlight';\n highlightText: 'highlightText';\n highlightSequence: 'highlightSequence';\n highlightSequenceTemporary: 'highlightSequenceTemporary';\n }\n}\n\nconst SEQUENCE_TEMPORARY = 'highlightSequenceTemporary';\nconst SEQUENCE = 'highlightSequence';\nconst HIGHLIGHT = 'highlight';\nconst HIGHLIGHT_TEXT = 'highlightText';\n\n/** Create the micromark extension enabling `==mark==` highlight syntax. */\nexport function markHighlight(): Extension {\n const tokenizer: Construct = {\n name: 'highlight',\n tokenize: tokenizeHighlight,\n resolveAll: resolveAllHighlight,\n };\n\n return {\n text: { [codes.equalsTo]: tokenizer },\n insideSpan: { null: [tokenizer] },\n attentionMarkers: { null: [codes.equalsTo] },\n };\n\n /** Pair open/close sequences into highlight tokens; demote leftovers to data. */\n function resolveAllHighlight(events: Event[], context: TokenizeContext): Event[] {\n let index = -1;\n\n while (++index < events.length) {\n if (events[index][0] === 'enter' && events[index][1].type === SEQUENCE_TEMPORARY && events[index][1]._close) {\n let open = index;\n while (open--) {\n if (\n events[open][0] === 'exit' &&\n events[open][1].type === SEQUENCE_TEMPORARY &&\n events[open][1]._open &&\n // Sequences are all length 2, but keep the equal-length guard the\n // upstreams carry — it is part of the pinned behavior.\n events[index][1].end.offset - events[index][1].start.offset ===\n events[open][1].end.offset - events[open][1].start.offset\n ) {\n events[index][1].type = SEQUENCE;\n events[open][1].type = SEQUENCE;\n\n const highlight: Token = {\n type: HIGHLIGHT,\n start: Object.assign({}, events[open][1].start),\n end: Object.assign({}, events[index][1].end),\n };\n const text: Token = {\n type: HIGHLIGHT_TEXT,\n start: Object.assign({}, events[open][1].end),\n end: Object.assign({}, events[index][1].start),\n };\n\n const nextEvents: Event[] = [\n ['enter', highlight, context],\n ['enter', events[open][1], context],\n ['exit', events[open][1], context],\n ['enter', text, context],\n ];\n const insideSpan = context.parser.constructs.insideSpan.null;\n if (insideSpan) {\n splice(nextEvents, nextEvents.length, 0, resolveAll(insideSpan, events.slice(open + 1, index), context));\n }\n splice(nextEvents, nextEvents.length, 0, [\n ['exit', text, context],\n ['enter', events[index][1], context],\n ['exit', events[index][1], context],\n ['exit', highlight, context],\n ]);\n\n splice(events, open - 1, index - open + 3, nextEvents);\n index = open + nextEvents.length - 2;\n break;\n }\n }\n }\n }\n\n index = -1;\n while (++index < events.length) {\n if (events[index][1].type === SEQUENCE_TEMPORARY) {\n events[index][1].type = types.data;\n }\n }\n\n return events;\n }\n\n function tokenizeHighlight(this: TokenizeContext, effects: Parameters<Tokenizer>[0], ok: State, nok: State): State {\n const previous = this.previous;\n const events = this.events;\n let size = 0;\n\n return start;\n\n function start(code: Parameters<State>[0]): State | undefined {\n // A `=` directly before us that is not an escape means we are inside a\n // longer run the construct already rejected — do not re-enter.\n if (previous === codes.equalsTo && events[events.length - 1][1].type !== types.characterEscape) {\n return nok(code);\n }\n effects.enter(SEQUENCE_TEMPORARY);\n return more(code);\n }\n\n function more(code: Parameters<State>[0]): State | undefined {\n const before = classifyCharacter(previous);\n\n if (code === codes.equalsTo) {\n // A third `=` is not a highlight sequence.\n if (size > 1) return nok(code);\n effects.consume(code);\n size++;\n return more;\n }\n\n if (size < 2) return nok(code);\n\n const token = effects.exit(SEQUENCE_TEMPORARY);\n const after = classifyCharacter(code);\n token._open = !after || (after === constants.attentionSideAfter && Boolean(before));\n token._close = !before || (before === constants.attentionSideAfter && Boolean(after));\n return ok(code);\n }\n }\n}\n","/**\n * mdast extensions for `==mark==` highlight: from-markdown (build a `mark`\n * node rendered as `<mark>` via `data.hName`, so no custom hast handler is\n * needed downstream) and to-markdown (serialize back to `==…==`).\n *\n * The node shape (from-markdown direction: mdast + hast) is pinned against\n * `remark-mark-highlight@0.1.1` by the parity corpus (`parity.test.ts`);\n * the to-markdown direction is covered by round-trip smokes only — the\n * baseline fixture records no upstream serializer output.\n *\n * @module mdast\n */\n\nimport type { Data, Parent, PhrasingContent } from 'mdast';\nimport type { CompileContext, Extension as FromMarkdownExtension, Token } from 'mdast-util-from-markdown';\nimport type { ConstructName, Handle as ToMarkdownHandle, Options as ToMarkdownExtension } from 'mdast-util-to-markdown';\n\n/** A `==highlight==` span, rendered as `<mark>` through `data.hName`.\n * `data` stays assignable to mdast's `Data` (hProperties/hChildren etc.) so\n * generic tree visitors that write those fields still compile on `mark`. */\nexport interface Mark extends Parent {\n type: 'mark';\n children: PhrasingContent[];\n data?: Data & { hName?: 'mark' };\n}\n\ndeclare module 'mdast' {\n interface PhrasingContentMap {\n mark: Mark;\n }\n interface RootContentMap {\n mark: Mark;\n }\n}\n\ndeclare module 'mdast-util-to-markdown' {\n interface ConstructNameMap {\n highlight: 'highlight';\n }\n}\n\n/** Constructs inside which a `=` needs no escaping when serializing. */\nconst constructsWithoutEquals: ConstructName[] = [\n 'autolink',\n 'destinationLiteral',\n 'destinationRaw',\n 'reference',\n 'titleQuote',\n 'titleApostrophe',\n];\n\nfunction enterMark(this: CompileContext, token: Token): undefined {\n this.enter({ type: 'mark', children: [], data: { hName: 'mark' } }, token);\n}\n\nfunction exitMark(this: CompileContext, token: Token): undefined {\n this.exit(token);\n}\n\n/** From-markdown extension: map `highlight` tokens to `mark` nodes. */\nexport const markHighlightFromMarkdown: FromMarkdownExtension = {\n canContainEols: ['mark'],\n enter: { highlight: enterMark },\n exit: { highlight: exitMark },\n};\n\nconst handleMark: ToMarkdownHandle = function (node: Mark, _, state, info) {\n const tracker = state.createTracker(info);\n const exit = state.enter('highlight');\n let value = tracker.move('==');\n value += state.containerPhrasing(node, { ...tracker.current(), before: value, after: '=' });\n value += tracker.move('==');\n exit();\n return value;\n};\n\n(handleMark as ToMarkdownHandle & { peek(): string }).peek = function (): string {\n return '=';\n};\n\n/** To-markdown extension: serialize `mark` nodes back to `==…==`. */\nexport const markHighlightToMarkdown: ToMarkdownExtension = {\n unsafe: [{ character: '=', inConstruct: 'phrasing', notInConstruct: constructsWithoutEquals }],\n handlers: { mark: handleMark },\n};\n","/**\n * `@ai-markdown/remark-mark-highlight` — remark plugin for `==mark==`\n * highlight syntax. First-party continuation of the unmaintained\n * `remark-mark-highlight`, byte-compatible with its 0.1.1 output (pinned by\n * the parity corpus) and shipping the dual ESM/CJS build the upstream\n * lacked.\n *\n * ```ts\n * import { remarkMarkHighlight } from '@ai-markdown/remark-mark-highlight';\n *\n * unified().use(remarkParse).use(remarkMarkHighlight)\n * // ==text== → mdast `mark` node → <mark>text</mark>\n * ```\n *\n * @module @ai-markdown/remark-mark-highlight\n */\n\nimport type { Processor } from 'unified';\nimport { markHighlight } from './syntax.js';\nimport { markHighlightFromMarkdown, markHighlightToMarkdown } from './mdast.js';\n\n/** remark plugin enabling `==mark==` highlight syntax. */\nexport function remarkMarkHighlight(this: Processor): undefined {\n const data = this.data() as Record<string, unknown[] | undefined>;\n\n add('micromarkExtensions', markHighlight());\n add('fromMarkdownExtensions', markHighlightFromMarkdown);\n add('toMarkdownExtensions', markHighlightToMarkdown);\n\n function add(field: string, value: unknown): void {\n (data[field] ??= []).push(value);\n }\n}\n\n/** Drop-in alias matching the upstream `remark-mark-highlight` export name. */\nexport { remarkMarkHighlight as remarkMark };\n\nexport { markHighlight } from './syntax.js';\nexport { markHighlightFromMarkdown, markHighlightToMarkdown, type Mark } from './mdast.js';\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@ai-markdown/remark-mark-highlight",
3
+ "version": "1.0.1",
4
+ "description": "remark plugin for ==mark== highlight syntax — first-party successor to remark-mark-highlight, with dual ESM/CJS output.",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "type": "module",
9
+ "license": "MIT",
10
+ "engines": {
11
+ "node": ">=20"
12
+ },
13
+ "author": "Brian Lee <aiephoenixbl@gmail.com> (https://github.com/AIEPhoenix)",
14
+ "homepage": "https://github.com/ai-markdown/ai-markdown/tree/main/packages/remark-mark-highlight#readme",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/ai-markdown/ai-markdown.git",
18
+ "directory": "packages/remark-mark-highlight"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/ai-markdown/ai-markdown/issues"
22
+ },
23
+ "keywords": [
24
+ "remark",
25
+ "remark-plugin",
26
+ "remark-mark-highlight",
27
+ "micromark",
28
+ "micromark-extension",
29
+ "mdast",
30
+ "mdast-util",
31
+ "unified",
32
+ "markdown",
33
+ "mark",
34
+ "highlight",
35
+ "==mark==",
36
+ "typescript"
37
+ ],
38
+ "sideEffects": false,
39
+ "main": "./dist/index.cjs",
40
+ "module": "./dist/index.js",
41
+ "types": "./dist/index.d.ts",
42
+ "files": [
43
+ "dist"
44
+ ],
45
+ "exports": {
46
+ ".": {
47
+ "types": {
48
+ "import": "./dist/index.d.ts",
49
+ "require": "./dist/index.d.cts"
50
+ },
51
+ "import": "./dist/index.js",
52
+ "require": "./dist/index.cjs"
53
+ },
54
+ "./package.json": "./package.json"
55
+ },
56
+ "dependencies": {
57
+ "@types/mdast": "^4.0.4",
58
+ "mdast-util-from-markdown": "^2.0.2",
59
+ "mdast-util-to-markdown": "^2.1.2",
60
+ "micromark-util-chunked": "^2.0.1",
61
+ "micromark-util-classify-character": "^2.0.1",
62
+ "micromark-util-resolve-all": "^2.0.1",
63
+ "micromark-util-symbol": "^2.0.1",
64
+ "micromark-util-types": "^2.0.2",
65
+ "unified": "^11.0.5"
66
+ },
67
+ "devDependencies": {
68
+ "mdast-util-to-hast": "^13.2.1",
69
+ "remark-gfm": "^4.0.1",
70
+ "remark-parse": "^11.0.0",
71
+ "remark-stringify": "^11.0.0",
72
+ "@types/node": "^25.9.5"
73
+ },
74
+ "scripts": {
75
+ "build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsup && node scripts/assert-dist-clean.mjs",
76
+ "test": "vitest --run",
77
+ "typecheck": "tsc --noEmit -p tsconfig.json"
78
+ }
79
+ }