@illusions-lab/mdi 2.0.19 → 2.0.21

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 CHANGED
@@ -87,15 +87,32 @@ such as `3:18` count one-based Unicode grapheme clusters; ruby readings are a
87
87
  separate annotation channel anchored to the base-text range.
88
88
 
89
89
  ```ts
90
- import { getMdiTextBlocks, sourceSpansForTextRange } from "@illusions-lab/mdi";
90
+ import { getMdiTextBlocks, resolveMdiSourceSpan, resolveMdiSourceSpans, sourceSpansForTextRange } from "@illusions-lab/mdi";
91
91
 
92
92
  const result = getMdiTextBlocks("{東京|とうきょう}");
93
93
  const block = result.blocks[0];
94
94
  console.log(block.text); // 東京
95
95
  console.log(block.annotations[0].anchor); // { start: "1:1", end: "1:3" }
96
96
  console.log(sourceSpansForTextRange(block, { start: "1:1", end: "1:3" }));
97
+ console.log(resolveMdiSourceSpan("{東京|とうきょう}", { startByte: 1, endByte: 7 }));
98
+ console.log(resolveMdiSourceSpans("same same", [{ startByte: 0, endByte: 4 }, { startByte: 5, endByte: 9 }]));
97
99
  ```
98
100
 
101
+ `resolveMdiSourceSpan` accepts half-open UTF-8 byte offsets and returns ordered
102
+ `blockText` and `annotation` matches in canonical grapheme coordinates.
103
+ `coverage` is `complete`, `partial`, or `none`; each match is `exact` only when
104
+ its complete forward source coverage equals the requested span. Ruby base text
105
+ and readings are separate channels, and annotation indexes are zero-based.
106
+ Zero-width spans are valid and return no matches. Pure Markdown/MDI delimiters,
107
+ synthetic separators, and unmapped text do not acquire invented ranges, though
108
+ a delimiter token already owned by one projected grapheme (such as an explicit
109
+ break) can match. Reverse and forward mapping are therefore not generally
110
+ bijective, especially for annotations, multi-byte token mappings, partial
111
+ graphemes, discontinuous runs, and synthetic or unmapped text.
112
+ For multiple lookups against one document, use `resolveMdiSourceSpans`. It
113
+ validates the full array, performs one Rust parse/projection, and preserves
114
+ input order; repeated calls to the singular convenience API each parse anew.
115
+
99
116
  Each source-derived grapheme is represented by a `sourceMap.runs` boundary;
100
117
  table tabs/newlines and multi-paragraph joiners appear in `synthetic` and do
101
118
  not receive invented source spans. `parseMdiTextPosition`,
@@ -3,6 +3,7 @@ import * as mdiCore from "@illusions-lab/mdi-core";
3
3
  import { parse as parseYaml } from "yaml";
4
4
  var {
5
5
  getMdiTextBlocksJson,
6
+ resolveMdiSourceSpansJson,
6
7
  parseMdiSyntaxJson,
7
8
  renderHtml: renderHtmlFromRust,
8
9
  renderEpub: renderEpubFromRust,
@@ -42,6 +43,58 @@ function getMdiTextBlocks(source) {
42
43
  }
43
44
  return result;
44
45
  }
46
+ function resolveMdiSourceSpan(source, span) {
47
+ return resolveMdiSourceSpans(source, [span])[0];
48
+ }
49
+ function resolveMdiSourceSpans(source, spans) {
50
+ if (typeof source !== "string") throw new TypeError("source must be a string");
51
+ if (!Array.isArray(spans)) throw new TypeError("spans must be an array");
52
+ if (spans.length === 0) return [];
53
+ const utf8 = utf8SourceBoundaries(source);
54
+ for (const [index, span] of spans.entries()) {
55
+ assertSourceSpanInput(span, `spans[${index}]`);
56
+ if (span.startByte > span.endByte) {
57
+ throw new RangeError(`spans[${index}].startByte must not exceed endByte`);
58
+ }
59
+ if (span.endByte > utf8.length) {
60
+ throw new RangeError(`spans[${index}] falls outside the UTF-8 source length`);
61
+ }
62
+ if (!utf8.boundaries.has(span.startByte) || !utf8.boundaries.has(span.endByte)) {
63
+ throw new RangeError(`spans[${index}] endpoints must be UTF-8 code-point boundaries`);
64
+ }
65
+ }
66
+ const results = JSON.parse(
67
+ resolveMdiSourceSpansJson(source, JSON.stringify(spans))
68
+ );
69
+ for (const result of results) {
70
+ if (result.projectionVersion !== MDI_TEXT_PROJECTION_VERSION) {
71
+ throw new Error(`Unsupported MDI text projection version: ${String(result.projectionVersion)}`);
72
+ }
73
+ }
74
+ return results;
75
+ }
76
+ function assertSourceSpanInput(span, name = "span") {
77
+ if (!span || typeof span !== "object" || Array.isArray(span)) {
78
+ throw new TypeError(`${name} must be an object`);
79
+ }
80
+ if (typeof span.startByte !== "number" || typeof span.endByte !== "number") {
81
+ throw new TypeError(`${name}.startByte and ${name}.endByte must be numbers`);
82
+ }
83
+ const isUint32 = (value) => Number.isInteger(value) && value >= 0 && value <= 4294967295;
84
+ if (!isUint32(span.startByte) || !isUint32(span.endByte)) {
85
+ throw new RangeError(`${name}.startByte and ${name}.endByte must be uint32 values`);
86
+ }
87
+ }
88
+ function utf8SourceBoundaries(source) {
89
+ let length = 0;
90
+ const boundaries = /* @__PURE__ */ new Set([0]);
91
+ for (const character of source) {
92
+ const codePoint = character.codePointAt(0);
93
+ length += codePoint <= 127 ? 1 : codePoint <= 2047 ? 2 : codePoint <= 65535 ? 3 : 4;
94
+ boundaries.add(length);
95
+ }
96
+ return { length, boundaries };
97
+ }
45
98
  function parseMdiTextPosition(position) {
46
99
  if (typeof position !== "string") throw new TypeError("position must be a string");
47
100
  const match = /^([1-9]\d*):([1-9]\d*)$/.exec(position);
@@ -457,6 +510,8 @@ export {
457
510
  MDI_TEXT_PROJECTION_VERSION,
458
511
  parse,
459
512
  getMdiTextBlocks,
513
+ resolveMdiSourceSpan,
514
+ resolveMdiSourceSpans,
460
515
  parseMdiTextPosition,
461
516
  formatMdiTextPosition,
462
517
  formatMdiTextRange,
package/dist/index.cjs CHANGED
@@ -53,6 +53,8 @@ __export(index_exports, {
53
53
  renderTextFormat: () => renderTextFormat,
54
54
  renderTextFormatWithDiagnostics: () => renderTextFormatWithDiagnostics,
55
55
  renderTextWithDiagnostics: () => renderTextWithDiagnostics,
56
+ resolveMdiSourceSpan: () => resolveMdiSourceSpan,
57
+ resolveMdiSourceSpans: () => resolveMdiSourceSpans,
56
58
  serializeMdi: () => serializeMdi,
57
59
  sourceSpansForTextRange: () => sourceSpansForTextRange,
58
60
  toPublicationMdast: () => toPublicationMdast
@@ -62,6 +64,7 @@ var mdiCore = __toESM(require("@illusions-lab/mdi-core"), 1);
62
64
  var import_yaml = require("yaml");
63
65
  var {
64
66
  getMdiTextBlocksJson,
67
+ resolveMdiSourceSpansJson,
65
68
  parseMdiSyntaxJson,
66
69
  renderHtml: renderHtmlFromRust,
67
70
  renderEpub: renderEpubFromRust,
@@ -101,6 +104,58 @@ function getMdiTextBlocks(source) {
101
104
  }
102
105
  return result;
103
106
  }
107
+ function resolveMdiSourceSpan(source, span) {
108
+ return resolveMdiSourceSpans(source, [span])[0];
109
+ }
110
+ function resolveMdiSourceSpans(source, spans) {
111
+ if (typeof source !== "string") throw new TypeError("source must be a string");
112
+ if (!Array.isArray(spans)) throw new TypeError("spans must be an array");
113
+ if (spans.length === 0) return [];
114
+ const utf8 = utf8SourceBoundaries(source);
115
+ for (const [index, span] of spans.entries()) {
116
+ assertSourceSpanInput(span, `spans[${index}]`);
117
+ if (span.startByte > span.endByte) {
118
+ throw new RangeError(`spans[${index}].startByte must not exceed endByte`);
119
+ }
120
+ if (span.endByte > utf8.length) {
121
+ throw new RangeError(`spans[${index}] falls outside the UTF-8 source length`);
122
+ }
123
+ if (!utf8.boundaries.has(span.startByte) || !utf8.boundaries.has(span.endByte)) {
124
+ throw new RangeError(`spans[${index}] endpoints must be UTF-8 code-point boundaries`);
125
+ }
126
+ }
127
+ const results = JSON.parse(
128
+ resolveMdiSourceSpansJson(source, JSON.stringify(spans))
129
+ );
130
+ for (const result of results) {
131
+ if (result.projectionVersion !== MDI_TEXT_PROJECTION_VERSION) {
132
+ throw new Error(`Unsupported MDI text projection version: ${String(result.projectionVersion)}`);
133
+ }
134
+ }
135
+ return results;
136
+ }
137
+ function assertSourceSpanInput(span, name = "span") {
138
+ if (!span || typeof span !== "object" || Array.isArray(span)) {
139
+ throw new TypeError(`${name} must be an object`);
140
+ }
141
+ if (typeof span.startByte !== "number" || typeof span.endByte !== "number") {
142
+ throw new TypeError(`${name}.startByte and ${name}.endByte must be numbers`);
143
+ }
144
+ const isUint32 = (value) => Number.isInteger(value) && value >= 0 && value <= 4294967295;
145
+ if (!isUint32(span.startByte) || !isUint32(span.endByte)) {
146
+ throw new RangeError(`${name}.startByte and ${name}.endByte must be uint32 values`);
147
+ }
148
+ }
149
+ function utf8SourceBoundaries(source) {
150
+ let length = 0;
151
+ const boundaries = /* @__PURE__ */ new Set([0]);
152
+ for (const character of source) {
153
+ const codePoint = character.codePointAt(0);
154
+ length += codePoint <= 127 ? 1 : codePoint <= 2047 ? 2 : codePoint <= 65535 ? 3 : 4;
155
+ boundaries.add(length);
156
+ }
157
+ return { length, boundaries };
158
+ }
104
159
  function parseMdiTextPosition(position) {
105
160
  if (typeof position !== "string") throw new TypeError("position must be a string");
106
161
  const match = /^([1-9]\d*):([1-9]\d*)$/.exec(position);
@@ -533,6 +588,8 @@ var parseMdiSyntax = parse;
533
588
  renderTextFormat,
534
589
  renderTextFormatWithDiagnostics,
535
590
  renderTextWithDiagnostics,
591
+ resolveMdiSourceSpan,
592
+ resolveMdiSourceSpans,
536
593
  serializeMdi,
537
594
  sourceSpansForTextRange,
538
595
  toPublicationMdast
package/dist/index.d.cts CHANGED
@@ -142,6 +142,29 @@ interface MdiTextBlocksResult {
142
142
  document: MdiDocument;
143
143
  diagnostics: MdiDiagnostic[];
144
144
  }
145
+ type MdiSourceSpanCoverage = "complete" | "partial" | "none";
146
+ type MdiSourceSpanRelation = "exact" | "overlap";
147
+ interface MdiSourceSpanBlockTextMatch {
148
+ kind: "blockText";
149
+ blockIndex: number;
150
+ range: MdiTextRange;
151
+ relation: MdiSourceSpanRelation;
152
+ }
153
+ interface MdiSourceSpanAnnotationMatch {
154
+ kind: "annotation";
155
+ blockIndex: number;
156
+ /** Zero-based index in the containing block's annotations array. */
157
+ annotationIndex: number;
158
+ range: MdiTextRange;
159
+ relation: MdiSourceSpanRelation;
160
+ }
161
+ type MdiSourceSpanTextMatch = MdiSourceSpanBlockTextMatch | MdiSourceSpanAnnotationMatch;
162
+ interface MdiSourceSpanTextResolution {
163
+ projectionVersion: "1.0";
164
+ sourceSpan: MdiSourceSpan;
165
+ coverage: MdiSourceSpanCoverage;
166
+ matches: MdiSourceSpanTextMatch[];
167
+ }
145
168
  interface MdiDiagnostic {
146
169
  severity: "warning" | "error";
147
170
  code: string;
@@ -236,6 +259,16 @@ declare function parse(source: string): MdiSyntaxParseResult;
236
259
  * and grapheme-precise UTF-8 source maps alongside the complete document IR.
237
260
  */
238
261
  declare function getMdiTextBlocks(source: string): MdiTextBlocksResult;
262
+ /**
263
+ * Resolve a half-open UTF-8 source span to all mapped canonical block and
264
+ * annotation ranges. Mapping semantics are implemented exclusively in Rust.
265
+ */
266
+ declare function resolveMdiSourceSpan(source: string, span: MdiSourceSpan): MdiSourceSpanTextResolution;
267
+ /**
268
+ * Resolve many half-open UTF-8 source spans with one Rust parse/projection.
269
+ * The returned resolutions preserve input order.
270
+ */
271
+ declare function resolveMdiSourceSpans(source: string, spans: readonly MdiSourceSpan[]): MdiSourceSpanTextResolution[];
239
272
  /** Parse and validate a canonical one-based `block:character` position. */
240
273
  declare function parseMdiTextPosition(position: string): MdiTextPositionValue;
241
274
  /** Format a validated one-based text position. */
@@ -317,4 +350,4 @@ declare function renderTextFormatWithDiagnostics(source: string, format: MdiText
317
350
  /** @deprecated Use {@link parse}; it now parses the complete document. */
318
351
  declare const parseMdiSyntax: typeof parse;
319
352
 
320
- export { MDI_IR_VERSION, MDI_SPEC_VERSION, MDI_TEXT_PROJECTION_VERSION, type MdiAnnotationSourceMap, type MdiDiagnostic, type MdiDocument, type MdiDocxExportProfile, type MdiEpubExportOptions, type MdiFrontmatter, type MdiHeading, type MdiHtmlRenderOptions, type MdiNode, type MdiParserCapabilities, type MdiPublicationFrontmatter, type MdiPublicationRoot, type MdiRenderResult, type MdiRubyReading, type MdiSourceSpan, type MdiSyntaxDocument, type MdiSyntaxParseResult, type MdiTextAnnotation, type MdiTextBlock, type MdiTextBlocksResult, type MdiTextFormat, type MdiTextPosition, type MdiTextPositionValue, type MdiTextRange, type MdiTextSourceMap, type MdiTextSourceRun, formatMdiTextPosition, formatMdiTextRange, getMdiTextBlocks, initializeMdi, parse, parseMdiSyntax, parseMdiTextPosition, prepareRender, renderDocx, renderDocxWithDiagnostics, renderDocxWithProfile, renderEpub, renderEpubWithDiagnostics, renderEpubWithProfile, renderHtml, renderHtmlWithDiagnostics, renderText, renderTextFormat, renderTextFormatWithDiagnostics, renderTextWithDiagnostics, serializeMdi, sourceSpansForTextRange, toPublicationMdast };
353
+ export { MDI_IR_VERSION, MDI_SPEC_VERSION, MDI_TEXT_PROJECTION_VERSION, type MdiAnnotationSourceMap, type MdiDiagnostic, type MdiDocument, type MdiDocxExportProfile, type MdiEpubExportOptions, type MdiFrontmatter, type MdiHeading, type MdiHtmlRenderOptions, type MdiNode, type MdiParserCapabilities, type MdiPublicationFrontmatter, type MdiPublicationRoot, type MdiRenderResult, type MdiRubyReading, type MdiSourceSpan, type MdiSourceSpanAnnotationMatch, type MdiSourceSpanBlockTextMatch, type MdiSourceSpanCoverage, type MdiSourceSpanRelation, type MdiSourceSpanTextMatch, type MdiSourceSpanTextResolution, type MdiSyntaxDocument, type MdiSyntaxParseResult, type MdiTextAnnotation, type MdiTextBlock, type MdiTextBlocksResult, type MdiTextFormat, type MdiTextPosition, type MdiTextPositionValue, type MdiTextRange, type MdiTextSourceMap, type MdiTextSourceRun, formatMdiTextPosition, formatMdiTextRange, getMdiTextBlocks, initializeMdi, parse, parseMdiSyntax, parseMdiTextPosition, prepareRender, renderDocx, renderDocxWithDiagnostics, renderDocxWithProfile, renderEpub, renderEpubWithDiagnostics, renderEpubWithProfile, renderHtml, renderHtmlWithDiagnostics, renderText, renderTextFormat, renderTextFormatWithDiagnostics, renderTextWithDiagnostics, resolveMdiSourceSpan, resolveMdiSourceSpans, serializeMdi, sourceSpansForTextRange, toPublicationMdast };
package/dist/index.d.ts CHANGED
@@ -142,6 +142,29 @@ interface MdiTextBlocksResult {
142
142
  document: MdiDocument;
143
143
  diagnostics: MdiDiagnostic[];
144
144
  }
145
+ type MdiSourceSpanCoverage = "complete" | "partial" | "none";
146
+ type MdiSourceSpanRelation = "exact" | "overlap";
147
+ interface MdiSourceSpanBlockTextMatch {
148
+ kind: "blockText";
149
+ blockIndex: number;
150
+ range: MdiTextRange;
151
+ relation: MdiSourceSpanRelation;
152
+ }
153
+ interface MdiSourceSpanAnnotationMatch {
154
+ kind: "annotation";
155
+ blockIndex: number;
156
+ /** Zero-based index in the containing block's annotations array. */
157
+ annotationIndex: number;
158
+ range: MdiTextRange;
159
+ relation: MdiSourceSpanRelation;
160
+ }
161
+ type MdiSourceSpanTextMatch = MdiSourceSpanBlockTextMatch | MdiSourceSpanAnnotationMatch;
162
+ interface MdiSourceSpanTextResolution {
163
+ projectionVersion: "1.0";
164
+ sourceSpan: MdiSourceSpan;
165
+ coverage: MdiSourceSpanCoverage;
166
+ matches: MdiSourceSpanTextMatch[];
167
+ }
145
168
  interface MdiDiagnostic {
146
169
  severity: "warning" | "error";
147
170
  code: string;
@@ -236,6 +259,16 @@ declare function parse(source: string): MdiSyntaxParseResult;
236
259
  * and grapheme-precise UTF-8 source maps alongside the complete document IR.
237
260
  */
238
261
  declare function getMdiTextBlocks(source: string): MdiTextBlocksResult;
262
+ /**
263
+ * Resolve a half-open UTF-8 source span to all mapped canonical block and
264
+ * annotation ranges. Mapping semantics are implemented exclusively in Rust.
265
+ */
266
+ declare function resolveMdiSourceSpan(source: string, span: MdiSourceSpan): MdiSourceSpanTextResolution;
267
+ /**
268
+ * Resolve many half-open UTF-8 source spans with one Rust parse/projection.
269
+ * The returned resolutions preserve input order.
270
+ */
271
+ declare function resolveMdiSourceSpans(source: string, spans: readonly MdiSourceSpan[]): MdiSourceSpanTextResolution[];
239
272
  /** Parse and validate a canonical one-based `block:character` position. */
240
273
  declare function parseMdiTextPosition(position: string): MdiTextPositionValue;
241
274
  /** Format a validated one-based text position. */
@@ -317,4 +350,4 @@ declare function renderTextFormatWithDiagnostics(source: string, format: MdiText
317
350
  /** @deprecated Use {@link parse}; it now parses the complete document. */
318
351
  declare const parseMdiSyntax: typeof parse;
319
352
 
320
- export { MDI_IR_VERSION, MDI_SPEC_VERSION, MDI_TEXT_PROJECTION_VERSION, type MdiAnnotationSourceMap, type MdiDiagnostic, type MdiDocument, type MdiDocxExportProfile, type MdiEpubExportOptions, type MdiFrontmatter, type MdiHeading, type MdiHtmlRenderOptions, type MdiNode, type MdiParserCapabilities, type MdiPublicationFrontmatter, type MdiPublicationRoot, type MdiRenderResult, type MdiRubyReading, type MdiSourceSpan, type MdiSyntaxDocument, type MdiSyntaxParseResult, type MdiTextAnnotation, type MdiTextBlock, type MdiTextBlocksResult, type MdiTextFormat, type MdiTextPosition, type MdiTextPositionValue, type MdiTextRange, type MdiTextSourceMap, type MdiTextSourceRun, formatMdiTextPosition, formatMdiTextRange, getMdiTextBlocks, initializeMdi, parse, parseMdiSyntax, parseMdiTextPosition, prepareRender, renderDocx, renderDocxWithDiagnostics, renderDocxWithProfile, renderEpub, renderEpubWithDiagnostics, renderEpubWithProfile, renderHtml, renderHtmlWithDiagnostics, renderText, renderTextFormat, renderTextFormatWithDiagnostics, renderTextWithDiagnostics, serializeMdi, sourceSpansForTextRange, toPublicationMdast };
353
+ export { MDI_IR_VERSION, MDI_SPEC_VERSION, MDI_TEXT_PROJECTION_VERSION, type MdiAnnotationSourceMap, type MdiDiagnostic, type MdiDocument, type MdiDocxExportProfile, type MdiEpubExportOptions, type MdiFrontmatter, type MdiHeading, type MdiHtmlRenderOptions, type MdiNode, type MdiParserCapabilities, type MdiPublicationFrontmatter, type MdiPublicationRoot, type MdiRenderResult, type MdiRubyReading, type MdiSourceSpan, type MdiSourceSpanAnnotationMatch, type MdiSourceSpanBlockTextMatch, type MdiSourceSpanCoverage, type MdiSourceSpanRelation, type MdiSourceSpanTextMatch, type MdiSourceSpanTextResolution, type MdiSyntaxDocument, type MdiSyntaxParseResult, type MdiTextAnnotation, type MdiTextBlock, type MdiTextBlocksResult, type MdiTextFormat, type MdiTextPosition, type MdiTextPositionValue, type MdiTextRange, type MdiTextSourceMap, type MdiTextSourceRun, formatMdiTextPosition, formatMdiTextRange, getMdiTextBlocks, initializeMdi, parse, parseMdiSyntax, parseMdiTextPosition, prepareRender, renderDocx, renderDocxWithDiagnostics, renderDocxWithProfile, renderEpub, renderEpubWithDiagnostics, renderEpubWithProfile, renderHtml, renderHtmlWithDiagnostics, renderText, renderTextFormat, renderTextFormatWithDiagnostics, renderTextWithDiagnostics, resolveMdiSourceSpan, resolveMdiSourceSpans, serializeMdi, sourceSpansForTextRange, toPublicationMdast };
package/dist/index.js CHANGED
@@ -22,10 +22,12 @@ import {
22
22
  renderTextFormat,
23
23
  renderTextFormatWithDiagnostics,
24
24
  renderTextWithDiagnostics,
25
+ resolveMdiSourceSpan,
26
+ resolveMdiSourceSpans,
25
27
  serializeMdi,
26
28
  sourceSpansForTextRange,
27
29
  toPublicationMdast
28
- } from "./chunk-JTDOLXFG.js";
30
+ } from "./chunk-GMS5SFZO.js";
29
31
  export {
30
32
  MDI_IR_VERSION,
31
33
  MDI_SPEC_VERSION,
@@ -50,6 +52,8 @@ export {
50
52
  renderTextFormat,
51
53
  renderTextFormatWithDiagnostics,
52
54
  renderTextWithDiagnostics,
55
+ resolveMdiSourceSpan,
56
+ resolveMdiSourceSpans,
53
57
  serializeMdi,
54
58
  sourceSpansForTextRange,
55
59
  toPublicationMdast
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/internal/mdast.ts
31
+ var mdast_exports = {};
32
+ __export(mdast_exports, {
33
+ MDI_MDAST_PROVENANCE_VERSION: () => MDI_MDAST_PROVENANCE_VERSION,
34
+ parseForMdast: () => parseForMdast
35
+ });
36
+ module.exports = __toCommonJS(mdast_exports);
37
+ var import_mdi_core = require("@illusions-lab/mdi-core");
38
+
39
+ // src/index.ts
40
+ var mdiCore = __toESM(require("@illusions-lab/mdi-core"), 1);
41
+ var import_yaml = require("yaml");
42
+ var {
43
+ getMdiTextBlocksJson,
44
+ resolveMdiSourceSpansJson,
45
+ parseMdiSyntaxJson,
46
+ renderHtml: renderHtmlFromRust,
47
+ renderEpub: renderEpubFromRust,
48
+ renderEpubWithProfile: renderEpubWithProfileFromRust,
49
+ renderDocx: renderDocxFromRust,
50
+ renderDocxWithProfile: renderDocxWithProfileFromRust,
51
+ renderText: renderTextFromRust,
52
+ renderTextFormat: renderTextFormatFromRust,
53
+ resolveExportProfileJson: resolveExportProfileJsonFromRust,
54
+ serializeMdi: serializeMdiFromRust
55
+ } = mdiCore;
56
+ var MDI_IR_VERSION = "1.0";
57
+
58
+ // src/internal/mdast.ts
59
+ var MDI_MDAST_PROVENANCE_VERSION = "1.0";
60
+ function parseForMdast(source) {
61
+ if (typeof source !== "string") throw new TypeError("source must be a string");
62
+ const result = JSON.parse((0, import_mdi_core.parseMdiMdastJson)(source));
63
+ if (result.irVersion !== MDI_IR_VERSION) {
64
+ throw new Error(`Unsupported MDI IR version: ${String(result.irVersion)}`);
65
+ }
66
+ return result;
67
+ }
68
+ // Annotate the CommonJS export names for ESM import in node:
69
+ 0 && (module.exports = {
70
+ MDI_MDAST_PROVENANCE_VERSION,
71
+ parseForMdast
72
+ });
@@ -0,0 +1,56 @@
1
+ import { MdiDocument, MdiFrontmatter, MdiSourceSpan, MdiTextRange, MdiNode, MDI_IR_VERSION, MDI_SPEC_VERSION, MdiParserCapabilities, MdiDiagnostic } from '../index.cjs';
2
+ import '@illusions-lab/mdi-to-epub';
3
+ import '@illusions-lab/mdi-export-profile';
4
+ import 'mdast';
5
+
6
+ /** Version of Rust-owned transient mdast provenance records. */
7
+ declare const MDI_MDAST_PROVENANCE_VERSION: "1.0";
8
+ /** A projection target assigned by Rust to a source-backed IR construct. */
9
+ type MdiMdastProvenanceTarget = {
10
+ blockIndex: number;
11
+ channel: "blockText";
12
+ range: MdiTextRange;
13
+ } | {
14
+ blockIndex: number;
15
+ channel: "annotation";
16
+ annotationIndex: number;
17
+ range: MdiTextRange;
18
+ };
19
+ /**
20
+ * Transient identity and projection metadata emitted by Rust for mdast
21
+ * adapters. `construct.path` is valid only for this parse result; it is not a
22
+ * persisted document ID and must not be inferred from text or order.
23
+ */
24
+ interface MdiMdastProvenance {
25
+ version: typeof MDI_MDAST_PROVENANCE_VERSION;
26
+ construct: {
27
+ path: string;
28
+ type: string;
29
+ };
30
+ span: MdiSourceSpan | null;
31
+ role: "container" | "textBearing";
32
+ status: "sourceBacked" | "synthetic" | "unmapped";
33
+ targets: MdiMdastProvenanceTarget[];
34
+ }
35
+ type MdiMdastNode = Omit<MdiNode, "children"> & {
36
+ mdiProvenance?: MdiMdastProvenance;
37
+ children?: MdiMdastNode[];
38
+ };
39
+ type MdiMdastFrontmatter = MdiFrontmatter & {
40
+ mdiProvenance: MdiMdastProvenance;
41
+ };
42
+ type MdiMdastDocument = Omit<MdiDocument, "frontmatter" | "children"> & {
43
+ frontmatter?: MdiMdastFrontmatter;
44
+ children: MdiMdastNode[];
45
+ };
46
+ interface MdiMdastParseResult {
47
+ irVersion: typeof MDI_IR_VERSION;
48
+ syntaxVersion: typeof MDI_SPEC_VERSION;
49
+ capabilities: MdiParserCapabilities;
50
+ document: MdiMdastDocument;
51
+ diagnostics: MdiDiagnostic[];
52
+ }
53
+ /** Rust-backed transport exclusively for mdast adapters. */
54
+ declare function parseForMdast(source: string): MdiMdastParseResult;
55
+
56
+ export { MDI_MDAST_PROVENANCE_VERSION, type MdiMdastDocument, type MdiMdastFrontmatter, type MdiMdastNode, type MdiMdastParseResult, type MdiMdastProvenance, type MdiMdastProvenanceTarget, parseForMdast };
@@ -0,0 +1,56 @@
1
+ import { MdiDocument, MdiFrontmatter, MdiSourceSpan, MdiTextRange, MdiNode, MDI_IR_VERSION, MDI_SPEC_VERSION, MdiParserCapabilities, MdiDiagnostic } from '../index.js';
2
+ import '@illusions-lab/mdi-to-epub';
3
+ import '@illusions-lab/mdi-export-profile';
4
+ import 'mdast';
5
+
6
+ /** Version of Rust-owned transient mdast provenance records. */
7
+ declare const MDI_MDAST_PROVENANCE_VERSION: "1.0";
8
+ /** A projection target assigned by Rust to a source-backed IR construct. */
9
+ type MdiMdastProvenanceTarget = {
10
+ blockIndex: number;
11
+ channel: "blockText";
12
+ range: MdiTextRange;
13
+ } | {
14
+ blockIndex: number;
15
+ channel: "annotation";
16
+ annotationIndex: number;
17
+ range: MdiTextRange;
18
+ };
19
+ /**
20
+ * Transient identity and projection metadata emitted by Rust for mdast
21
+ * adapters. `construct.path` is valid only for this parse result; it is not a
22
+ * persisted document ID and must not be inferred from text or order.
23
+ */
24
+ interface MdiMdastProvenance {
25
+ version: typeof MDI_MDAST_PROVENANCE_VERSION;
26
+ construct: {
27
+ path: string;
28
+ type: string;
29
+ };
30
+ span: MdiSourceSpan | null;
31
+ role: "container" | "textBearing";
32
+ status: "sourceBacked" | "synthetic" | "unmapped";
33
+ targets: MdiMdastProvenanceTarget[];
34
+ }
35
+ type MdiMdastNode = Omit<MdiNode, "children"> & {
36
+ mdiProvenance?: MdiMdastProvenance;
37
+ children?: MdiMdastNode[];
38
+ };
39
+ type MdiMdastFrontmatter = MdiFrontmatter & {
40
+ mdiProvenance: MdiMdastProvenance;
41
+ };
42
+ type MdiMdastDocument = Omit<MdiDocument, "frontmatter" | "children"> & {
43
+ frontmatter?: MdiMdastFrontmatter;
44
+ children: MdiMdastNode[];
45
+ };
46
+ interface MdiMdastParseResult {
47
+ irVersion: typeof MDI_IR_VERSION;
48
+ syntaxVersion: typeof MDI_SPEC_VERSION;
49
+ capabilities: MdiParserCapabilities;
50
+ document: MdiMdastDocument;
51
+ diagnostics: MdiDiagnostic[];
52
+ }
53
+ /** Rust-backed transport exclusively for mdast adapters. */
54
+ declare function parseForMdast(source: string): MdiMdastParseResult;
55
+
56
+ export { MDI_MDAST_PROVENANCE_VERSION, type MdiMdastDocument, type MdiMdastFrontmatter, type MdiMdastNode, type MdiMdastParseResult, type MdiMdastProvenance, type MdiMdastProvenanceTarget, parseForMdast };
@@ -0,0 +1,19 @@
1
+ import {
2
+ MDI_IR_VERSION
3
+ } from "../chunk-GMS5SFZO.js";
4
+
5
+ // src/internal/mdast.ts
6
+ import { parseMdiMdastJson } from "@illusions-lab/mdi-core";
7
+ var MDI_MDAST_PROVENANCE_VERSION = "1.0";
8
+ function parseForMdast(source) {
9
+ if (typeof source !== "string") throw new TypeError("source must be a string");
10
+ const result = JSON.parse(parseMdiMdastJson(source));
11
+ if (result.irVersion !== MDI_IR_VERSION) {
12
+ throw new Error(`Unsupported MDI IR version: ${String(result.irVersion)}`);
13
+ }
14
+ return result;
15
+ }
16
+ export {
17
+ MDI_MDAST_PROVENANCE_VERSION,
18
+ parseForMdast
19
+ };
package/dist/node.cjs CHANGED
@@ -42,6 +42,7 @@ var mdiCore = __toESM(require("@illusions-lab/mdi-core"), 1);
42
42
  var import_yaml = require("yaml");
43
43
  var {
44
44
  getMdiTextBlocksJson,
45
+ resolveMdiSourceSpansJson,
45
46
  parseMdiSyntaxJson,
46
47
  renderHtml: renderHtmlFromRust,
47
48
  renderEpub: renderEpubFromRust,
package/dist/node.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  parse,
3
3
  renderHtml
4
- } from "./chunk-JTDOLXFG.js";
4
+ } from "./chunk-GMS5SFZO.js";
5
5
 
6
6
  // src/node.ts
7
7
  import {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@illusions-lab/mdi",
3
- "version": "2.0.19",
3
+ "version": "2.0.21",
4
4
  "description": "Thin JavaScript binding for the Rust-authoritative MDI parser",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -21,20 +21,24 @@
21
21
  "./node": {
22
22
  "types": "./dist/node.d.ts",
23
23
  "default": "./dist/node.js"
24
+ },
25
+ "./internal/mdast": {
26
+ "types": "./dist/internal/mdast.d.ts",
27
+ "default": "./dist/internal/mdast.js"
24
28
  }
25
29
  },
26
30
  "files": [
27
31
  "dist"
28
32
  ],
29
33
  "scripts": {
30
- "build": "tsup src/index.ts src/node.ts --format esm,cjs --dts",
34
+ "build": "tsup src/index.ts src/node.ts src/internal/mdast.ts --format esm,cjs --dts",
31
35
  "test": "vitest run --passWithNoTests",
32
36
  "typecheck": "tsc --noEmit"
33
37
  },
34
38
  "dependencies": {
35
- "@illusions-lab/mdi-core": "^2.0.19",
36
- "@illusions-lab/mdi-export-profile": "^2.0.24",
37
- "@illusions-lab/mdi-to-epub": "^2.0.34",
39
+ "@illusions-lab/mdi-core": "^2.0.21",
40
+ "@illusions-lab/mdi-export-profile": "^2.0.26",
41
+ "@illusions-lab/mdi-to-epub": "^2.0.36",
38
42
  "@types/mdast": "^4.0.0",
39
43
  "yaml": "^2.0.0"
40
44
  },