@illusions-lab/mdi 2.0.18 → 2.0.20
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 +40 -0
- package/dist/{chunk-WEJ62HS6.js → chunk-GMS5SFZO.js} +149 -0
- package/dist/index.cjs +157 -0
- package/dist/index.d.cts +103 -1
- package/dist/index.d.ts +103 -1
- package/dist/index.js +17 -1
- package/dist/node.cjs +2 -0
- package/dist/node.js +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -79,6 +79,46 @@ Applications should treat the IR version as a wire-protocol version. They
|
|
|
79
79
|
must not infer grammar rules from object shapes or silently accept an
|
|
80
80
|
unsupported version.
|
|
81
81
|
|
|
82
|
+
## Searchable text blocks
|
|
83
|
+
|
|
84
|
+
`getMdiTextBlocks(source)` returns Rust-projected heading, paragraph, list,
|
|
85
|
+
blockquote, code, table, footnote, and HTML text in source order. Positions
|
|
86
|
+
such as `3:18` count one-based Unicode grapheme clusters; ruby readings are a
|
|
87
|
+
separate annotation channel anchored to the base-text range.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { getMdiTextBlocks, resolveMdiSourceSpan, resolveMdiSourceSpans, sourceSpansForTextRange } from "@illusions-lab/mdi";
|
|
91
|
+
|
|
92
|
+
const result = getMdiTextBlocks("{東京|とうきょう}");
|
|
93
|
+
const block = result.blocks[0];
|
|
94
|
+
console.log(block.text); // 東京
|
|
95
|
+
console.log(block.annotations[0].anchor); // { start: "1:1", end: "1:3" }
|
|
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 }]));
|
|
99
|
+
```
|
|
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
|
+
|
|
116
|
+
Each source-derived grapheme is represented by a `sourceMap.runs` boundary;
|
|
117
|
+
table tabs/newlines and multi-paragraph joiners appear in `synthetic` and do
|
|
118
|
+
not receive invented source spans. `parseMdiTextPosition`,
|
|
119
|
+
`formatMdiTextPosition`, and `formatMdiTextRange` provide stateless coordinate
|
|
120
|
+
helpers.
|
|
121
|
+
|
|
82
122
|
## Rendering
|
|
83
123
|
|
|
84
124
|
Rendering starts from the same Rust IR. Canonical MDI, plain text, HTML, EPUB,
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import * as mdiCore from "@illusions-lab/mdi-core";
|
|
3
3
|
import { parse as parseYaml } from "yaml";
|
|
4
4
|
var {
|
|
5
|
+
getMdiTextBlocksJson,
|
|
6
|
+
resolveMdiSourceSpansJson,
|
|
5
7
|
parseMdiSyntaxJson,
|
|
6
8
|
renderHtml: renderHtmlFromRust,
|
|
7
9
|
renderEpub: renderEpubFromRust,
|
|
@@ -24,6 +26,7 @@ function requireLayoutSystem(profile) {
|
|
|
24
26
|
}
|
|
25
27
|
var MDI_SPEC_VERSION = "2.0";
|
|
26
28
|
var MDI_IR_VERSION = "1.0";
|
|
29
|
+
var MDI_TEXT_PROJECTION_VERSION = "1.0";
|
|
27
30
|
function parse(source) {
|
|
28
31
|
if (typeof source !== "string") throw new TypeError("source must be a string");
|
|
29
32
|
const result = JSON.parse(parseMdiSyntaxJson(source));
|
|
@@ -32,6 +35,144 @@ function parse(source) {
|
|
|
32
35
|
}
|
|
33
36
|
return result;
|
|
34
37
|
}
|
|
38
|
+
function getMdiTextBlocks(source) {
|
|
39
|
+
if (typeof source !== "string") throw new TypeError("source must be a string");
|
|
40
|
+
const result = JSON.parse(getMdiTextBlocksJson(source));
|
|
41
|
+
if (result.projectionVersion !== MDI_TEXT_PROJECTION_VERSION) {
|
|
42
|
+
throw new Error(`Unsupported MDI text projection version: ${String(result.projectionVersion)}`);
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
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
|
+
}
|
|
98
|
+
function parseMdiTextPosition(position) {
|
|
99
|
+
if (typeof position !== "string") throw new TypeError("position must be a string");
|
|
100
|
+
const match = /^([1-9]\d*):([1-9]\d*)$/.exec(position);
|
|
101
|
+
if (!match) throw new RangeError(`Invalid MDI text position: ${position}`);
|
|
102
|
+
const block = Number(match[1]);
|
|
103
|
+
const character = Number(match[2]);
|
|
104
|
+
if (!Number.isSafeInteger(block) || !Number.isSafeInteger(character)) {
|
|
105
|
+
throw new RangeError(`Invalid MDI text position: ${position}`);
|
|
106
|
+
}
|
|
107
|
+
return { block, character };
|
|
108
|
+
}
|
|
109
|
+
function formatMdiTextPosition(position) {
|
|
110
|
+
if (!position || typeof position !== "object") {
|
|
111
|
+
throw new TypeError("position must be an object");
|
|
112
|
+
}
|
|
113
|
+
if (!isPositiveSafeInteger(position.block) || !isPositiveSafeInteger(position.character)) {
|
|
114
|
+
throw new RangeError("position.block and position.character must be positive safe integers");
|
|
115
|
+
}
|
|
116
|
+
return `${position.block}:${position.character}`;
|
|
117
|
+
}
|
|
118
|
+
function formatMdiTextRange(range) {
|
|
119
|
+
if (!range || typeof range !== "object") throw new TypeError("range must be an object");
|
|
120
|
+
const start = parseMdiTextPosition(range.start);
|
|
121
|
+
const end = parseMdiTextPosition(range.end);
|
|
122
|
+
if (start.block !== end.block || end.character < start.character) {
|
|
123
|
+
throw new RangeError("range must be ordered within one text block");
|
|
124
|
+
}
|
|
125
|
+
return `${range.start}-${range.end}`;
|
|
126
|
+
}
|
|
127
|
+
function sourceSpansForTextRange(block, range) {
|
|
128
|
+
if (!block || typeof block !== "object") throw new TypeError("block must be an object");
|
|
129
|
+
const start = parseMdiTextPosition(range.start);
|
|
130
|
+
const end = parseMdiTextPosition(range.end);
|
|
131
|
+
if (start.block !== block.index || end.block !== block.index) {
|
|
132
|
+
throw new RangeError("range must belong to the supplied text block");
|
|
133
|
+
}
|
|
134
|
+
const blockEnd = parseMdiTextPosition(block.range.end).character;
|
|
135
|
+
if (end.character < start.character || start.character < 1 || end.character > blockEnd) {
|
|
136
|
+
throw new RangeError("range falls outside the supplied text block");
|
|
137
|
+
}
|
|
138
|
+
const spans = [];
|
|
139
|
+
let previousRunEnd = 1;
|
|
140
|
+
for (const run of block.sourceMap.runs) {
|
|
141
|
+
const runStartPosition = parseMdiTextPosition(run.range.start);
|
|
142
|
+
const runEndPosition = parseMdiTextPosition(run.range.end);
|
|
143
|
+
const runStart = runStartPosition.character;
|
|
144
|
+
const runEnd = runEndPosition.character;
|
|
145
|
+
const invalidRange = runStartPosition.block !== block.index || runEndPosition.block !== block.index || runEnd < runStart || runStart < previousRunEnd || runEnd > blockEnd;
|
|
146
|
+
const invalidBoundaries = run.sourceBoundaries.length !== runEnd - runStart + 1 || run.sourceBoundaries.some((boundary) => !Number.isSafeInteger(boundary) || boundary < 0) || run.sourceBoundaries.some((boundary, index) => index > 0 && boundary < run.sourceBoundaries[index - 1]) || block.span !== void 0 && run.sourceBoundaries.some(
|
|
147
|
+
(boundary) => boundary < block.span.startByte || boundary > block.span.endByte
|
|
148
|
+
);
|
|
149
|
+
if (invalidRange || invalidBoundaries) {
|
|
150
|
+
throw new Error("Invalid MDI text source run");
|
|
151
|
+
}
|
|
152
|
+
previousRunEnd = runEnd;
|
|
153
|
+
const overlapStart = Math.max(start.character, runStart);
|
|
154
|
+
const overlapEnd = Math.min(end.character, runEnd);
|
|
155
|
+
for (let character = overlapStart; character < overlapEnd; character += 1) {
|
|
156
|
+
const offset = character - runStart;
|
|
157
|
+
appendMergedSourceSpan(spans, {
|
|
158
|
+
startByte: run.sourceBoundaries[offset],
|
|
159
|
+
endByte: run.sourceBoundaries[offset + 1]
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return spans;
|
|
164
|
+
}
|
|
165
|
+
function appendMergedSourceSpan(spans, next) {
|
|
166
|
+
const previous = spans.at(-1);
|
|
167
|
+
if (previous?.endByte === next.startByte) {
|
|
168
|
+
previous.endByte = next.endByte;
|
|
169
|
+
} else {
|
|
170
|
+
spans.push(next);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function isPositiveSafeInteger(value) {
|
|
174
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
|
|
175
|
+
}
|
|
35
176
|
function renderHtml(source, options) {
|
|
36
177
|
assertSource(source);
|
|
37
178
|
assertHtmlOptions(options);
|
|
@@ -366,7 +507,15 @@ export {
|
|
|
366
507
|
initializeMdi,
|
|
367
508
|
MDI_SPEC_VERSION,
|
|
368
509
|
MDI_IR_VERSION,
|
|
510
|
+
MDI_TEXT_PROJECTION_VERSION,
|
|
369
511
|
parse,
|
|
512
|
+
getMdiTextBlocks,
|
|
513
|
+
resolveMdiSourceSpan,
|
|
514
|
+
resolveMdiSourceSpans,
|
|
515
|
+
parseMdiTextPosition,
|
|
516
|
+
formatMdiTextPosition,
|
|
517
|
+
formatMdiTextRange,
|
|
518
|
+
sourceSpansForTextRange,
|
|
370
519
|
renderHtml,
|
|
371
520
|
renderHtmlWithDiagnostics,
|
|
372
521
|
prepareRender,
|
package/dist/index.cjs
CHANGED
|
@@ -32,9 +32,14 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
MDI_IR_VERSION: () => MDI_IR_VERSION,
|
|
34
34
|
MDI_SPEC_VERSION: () => MDI_SPEC_VERSION,
|
|
35
|
+
MDI_TEXT_PROJECTION_VERSION: () => MDI_TEXT_PROJECTION_VERSION,
|
|
36
|
+
formatMdiTextPosition: () => formatMdiTextPosition,
|
|
37
|
+
formatMdiTextRange: () => formatMdiTextRange,
|
|
38
|
+
getMdiTextBlocks: () => getMdiTextBlocks,
|
|
35
39
|
initializeMdi: () => initializeMdi,
|
|
36
40
|
parse: () => parse,
|
|
37
41
|
parseMdiSyntax: () => parseMdiSyntax,
|
|
42
|
+
parseMdiTextPosition: () => parseMdiTextPosition,
|
|
38
43
|
prepareRender: () => prepareRender,
|
|
39
44
|
renderDocx: () => renderDocx,
|
|
40
45
|
renderDocxWithDiagnostics: () => renderDocxWithDiagnostics,
|
|
@@ -48,13 +53,18 @@ __export(index_exports, {
|
|
|
48
53
|
renderTextFormat: () => renderTextFormat,
|
|
49
54
|
renderTextFormatWithDiagnostics: () => renderTextFormatWithDiagnostics,
|
|
50
55
|
renderTextWithDiagnostics: () => renderTextWithDiagnostics,
|
|
56
|
+
resolveMdiSourceSpan: () => resolveMdiSourceSpan,
|
|
57
|
+
resolveMdiSourceSpans: () => resolveMdiSourceSpans,
|
|
51
58
|
serializeMdi: () => serializeMdi,
|
|
59
|
+
sourceSpansForTextRange: () => sourceSpansForTextRange,
|
|
52
60
|
toPublicationMdast: () => toPublicationMdast
|
|
53
61
|
});
|
|
54
62
|
module.exports = __toCommonJS(index_exports);
|
|
55
63
|
var mdiCore = __toESM(require("@illusions-lab/mdi-core"), 1);
|
|
56
64
|
var import_yaml = require("yaml");
|
|
57
65
|
var {
|
|
66
|
+
getMdiTextBlocksJson,
|
|
67
|
+
resolveMdiSourceSpansJson,
|
|
58
68
|
parseMdiSyntaxJson,
|
|
59
69
|
renderHtml: renderHtmlFromRust,
|
|
60
70
|
renderEpub: renderEpubFromRust,
|
|
@@ -77,6 +87,7 @@ function requireLayoutSystem(profile) {
|
|
|
77
87
|
}
|
|
78
88
|
var MDI_SPEC_VERSION = "2.0";
|
|
79
89
|
var MDI_IR_VERSION = "1.0";
|
|
90
|
+
var MDI_TEXT_PROJECTION_VERSION = "1.0";
|
|
80
91
|
function parse(source) {
|
|
81
92
|
if (typeof source !== "string") throw new TypeError("source must be a string");
|
|
82
93
|
const result = JSON.parse(parseMdiSyntaxJson(source));
|
|
@@ -85,6 +96,144 @@ function parse(source) {
|
|
|
85
96
|
}
|
|
86
97
|
return result;
|
|
87
98
|
}
|
|
99
|
+
function getMdiTextBlocks(source) {
|
|
100
|
+
if (typeof source !== "string") throw new TypeError("source must be a string");
|
|
101
|
+
const result = JSON.parse(getMdiTextBlocksJson(source));
|
|
102
|
+
if (result.projectionVersion !== MDI_TEXT_PROJECTION_VERSION) {
|
|
103
|
+
throw new Error(`Unsupported MDI text projection version: ${String(result.projectionVersion)}`);
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
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
|
+
}
|
|
159
|
+
function parseMdiTextPosition(position) {
|
|
160
|
+
if (typeof position !== "string") throw new TypeError("position must be a string");
|
|
161
|
+
const match = /^([1-9]\d*):([1-9]\d*)$/.exec(position);
|
|
162
|
+
if (!match) throw new RangeError(`Invalid MDI text position: ${position}`);
|
|
163
|
+
const block = Number(match[1]);
|
|
164
|
+
const character = Number(match[2]);
|
|
165
|
+
if (!Number.isSafeInteger(block) || !Number.isSafeInteger(character)) {
|
|
166
|
+
throw new RangeError(`Invalid MDI text position: ${position}`);
|
|
167
|
+
}
|
|
168
|
+
return { block, character };
|
|
169
|
+
}
|
|
170
|
+
function formatMdiTextPosition(position) {
|
|
171
|
+
if (!position || typeof position !== "object") {
|
|
172
|
+
throw new TypeError("position must be an object");
|
|
173
|
+
}
|
|
174
|
+
if (!isPositiveSafeInteger(position.block) || !isPositiveSafeInteger(position.character)) {
|
|
175
|
+
throw new RangeError("position.block and position.character must be positive safe integers");
|
|
176
|
+
}
|
|
177
|
+
return `${position.block}:${position.character}`;
|
|
178
|
+
}
|
|
179
|
+
function formatMdiTextRange(range) {
|
|
180
|
+
if (!range || typeof range !== "object") throw new TypeError("range must be an object");
|
|
181
|
+
const start = parseMdiTextPosition(range.start);
|
|
182
|
+
const end = parseMdiTextPosition(range.end);
|
|
183
|
+
if (start.block !== end.block || end.character < start.character) {
|
|
184
|
+
throw new RangeError("range must be ordered within one text block");
|
|
185
|
+
}
|
|
186
|
+
return `${range.start}-${range.end}`;
|
|
187
|
+
}
|
|
188
|
+
function sourceSpansForTextRange(block, range) {
|
|
189
|
+
if (!block || typeof block !== "object") throw new TypeError("block must be an object");
|
|
190
|
+
const start = parseMdiTextPosition(range.start);
|
|
191
|
+
const end = parseMdiTextPosition(range.end);
|
|
192
|
+
if (start.block !== block.index || end.block !== block.index) {
|
|
193
|
+
throw new RangeError("range must belong to the supplied text block");
|
|
194
|
+
}
|
|
195
|
+
const blockEnd = parseMdiTextPosition(block.range.end).character;
|
|
196
|
+
if (end.character < start.character || start.character < 1 || end.character > blockEnd) {
|
|
197
|
+
throw new RangeError("range falls outside the supplied text block");
|
|
198
|
+
}
|
|
199
|
+
const spans = [];
|
|
200
|
+
let previousRunEnd = 1;
|
|
201
|
+
for (const run of block.sourceMap.runs) {
|
|
202
|
+
const runStartPosition = parseMdiTextPosition(run.range.start);
|
|
203
|
+
const runEndPosition = parseMdiTextPosition(run.range.end);
|
|
204
|
+
const runStart = runStartPosition.character;
|
|
205
|
+
const runEnd = runEndPosition.character;
|
|
206
|
+
const invalidRange = runStartPosition.block !== block.index || runEndPosition.block !== block.index || runEnd < runStart || runStart < previousRunEnd || runEnd > blockEnd;
|
|
207
|
+
const invalidBoundaries = run.sourceBoundaries.length !== runEnd - runStart + 1 || run.sourceBoundaries.some((boundary) => !Number.isSafeInteger(boundary) || boundary < 0) || run.sourceBoundaries.some((boundary, index) => index > 0 && boundary < run.sourceBoundaries[index - 1]) || block.span !== void 0 && run.sourceBoundaries.some(
|
|
208
|
+
(boundary) => boundary < block.span.startByte || boundary > block.span.endByte
|
|
209
|
+
);
|
|
210
|
+
if (invalidRange || invalidBoundaries) {
|
|
211
|
+
throw new Error("Invalid MDI text source run");
|
|
212
|
+
}
|
|
213
|
+
previousRunEnd = runEnd;
|
|
214
|
+
const overlapStart = Math.max(start.character, runStart);
|
|
215
|
+
const overlapEnd = Math.min(end.character, runEnd);
|
|
216
|
+
for (let character = overlapStart; character < overlapEnd; character += 1) {
|
|
217
|
+
const offset = character - runStart;
|
|
218
|
+
appendMergedSourceSpan(spans, {
|
|
219
|
+
startByte: run.sourceBoundaries[offset],
|
|
220
|
+
endByte: run.sourceBoundaries[offset + 1]
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return spans;
|
|
225
|
+
}
|
|
226
|
+
function appendMergedSourceSpan(spans, next) {
|
|
227
|
+
const previous = spans.at(-1);
|
|
228
|
+
if (previous?.endByte === next.startByte) {
|
|
229
|
+
previous.endByte = next.endByte;
|
|
230
|
+
} else {
|
|
231
|
+
spans.push(next);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function isPositiveSafeInteger(value) {
|
|
235
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
|
|
236
|
+
}
|
|
88
237
|
function renderHtml(source, options) {
|
|
89
238
|
assertSource(source);
|
|
90
239
|
assertHtmlOptions(options);
|
|
@@ -418,9 +567,14 @@ var parseMdiSyntax = parse;
|
|
|
418
567
|
0 && (module.exports = {
|
|
419
568
|
MDI_IR_VERSION,
|
|
420
569
|
MDI_SPEC_VERSION,
|
|
570
|
+
MDI_TEXT_PROJECTION_VERSION,
|
|
571
|
+
formatMdiTextPosition,
|
|
572
|
+
formatMdiTextRange,
|
|
573
|
+
getMdiTextBlocks,
|
|
421
574
|
initializeMdi,
|
|
422
575
|
parse,
|
|
423
576
|
parseMdiSyntax,
|
|
577
|
+
parseMdiTextPosition,
|
|
424
578
|
prepareRender,
|
|
425
579
|
renderDocx,
|
|
426
580
|
renderDocxWithDiagnostics,
|
|
@@ -434,6 +588,9 @@ var parseMdiSyntax = parse;
|
|
|
434
588
|
renderTextFormat,
|
|
435
589
|
renderTextFormatWithDiagnostics,
|
|
436
590
|
renderTextWithDiagnostics,
|
|
591
|
+
resolveMdiSourceSpan,
|
|
592
|
+
resolveMdiSourceSpans,
|
|
437
593
|
serializeMdi,
|
|
594
|
+
sourceSpansForTextRange,
|
|
438
595
|
toPublicationMdast
|
|
439
596
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -76,6 +76,8 @@ type MdiDocxExportProfile = ExportProfile & {
|
|
|
76
76
|
declare const MDI_SPEC_VERSION: "2.0";
|
|
77
77
|
/** Version of the complete Rust-owned document IR. */
|
|
78
78
|
declare const MDI_IR_VERSION: "1.0";
|
|
79
|
+
/** Version of the Rust-owned searchable text projection. */
|
|
80
|
+
declare const MDI_TEXT_PROJECTION_VERSION: "1.0";
|
|
79
81
|
interface MdiParserCapabilities {
|
|
80
82
|
mdi: boolean;
|
|
81
83
|
commonMark: boolean;
|
|
@@ -89,6 +91,80 @@ interface MdiSourceSpan {
|
|
|
89
91
|
/** Exclusive UTF-8 byte offset. */
|
|
90
92
|
endByte: number;
|
|
91
93
|
}
|
|
94
|
+
/** A canonical one-based `block:grapheme` text position. */
|
|
95
|
+
type MdiTextPosition = `${number}:${number}`;
|
|
96
|
+
interface MdiTextPositionValue {
|
|
97
|
+
block: number;
|
|
98
|
+
character: number;
|
|
99
|
+
}
|
|
100
|
+
interface MdiTextRange {
|
|
101
|
+
/** Inclusive. */
|
|
102
|
+
start: MdiTextPosition;
|
|
103
|
+
/** Exclusive. */
|
|
104
|
+
end: MdiTextPosition;
|
|
105
|
+
}
|
|
106
|
+
interface MdiTextSourceRun {
|
|
107
|
+
range: MdiTextRange;
|
|
108
|
+
/** One UTF-8 source boundary per grapheme, plus the final boundary. */
|
|
109
|
+
sourceBoundaries: number[];
|
|
110
|
+
}
|
|
111
|
+
interface MdiTextSourceMap {
|
|
112
|
+
runs: MdiTextSourceRun[];
|
|
113
|
+
synthetic: MdiTextRange[];
|
|
114
|
+
unmapped: MdiTextRange[];
|
|
115
|
+
}
|
|
116
|
+
type MdiAnnotationSourceMap = MdiTextSourceMap;
|
|
117
|
+
interface MdiTextAnnotation {
|
|
118
|
+
kind: "rubyReading";
|
|
119
|
+
text: string;
|
|
120
|
+
anchor: MdiTextRange;
|
|
121
|
+
span?: MdiSourceSpan;
|
|
122
|
+
sourceMap: MdiAnnotationSourceMap;
|
|
123
|
+
}
|
|
124
|
+
interface MdiTextBlock {
|
|
125
|
+
/** One-based source-order block number. */
|
|
126
|
+
index: number;
|
|
127
|
+
kind: "heading" | "paragraph" | "listItem" | "blockquote" | "code" | "table" | "footnote" | "html" | "other";
|
|
128
|
+
text: string;
|
|
129
|
+
range: MdiTextRange;
|
|
130
|
+
span?: MdiSourceSpan;
|
|
131
|
+
sourceMap: MdiTextSourceMap;
|
|
132
|
+
annotations: MdiTextAnnotation[];
|
|
133
|
+
node: MdiNode;
|
|
134
|
+
}
|
|
135
|
+
interface MdiTextBlocksResult {
|
|
136
|
+
projectionVersion: "1.0";
|
|
137
|
+
positionEncoding: "unicode-grapheme-cluster-1-based";
|
|
138
|
+
irVersion: typeof MDI_IR_VERSION;
|
|
139
|
+
syntaxVersion: typeof MDI_SPEC_VERSION;
|
|
140
|
+
capabilities: MdiParserCapabilities;
|
|
141
|
+
blocks: MdiTextBlock[];
|
|
142
|
+
document: MdiDocument;
|
|
143
|
+
diagnostics: MdiDiagnostic[];
|
|
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
|
+
}
|
|
92
168
|
interface MdiDiagnostic {
|
|
93
169
|
severity: "warning" | "error";
|
|
94
170
|
code: string;
|
|
@@ -178,6 +254,32 @@ type MdiSyntaxDocument = MdiDocument;
|
|
|
178
254
|
* language-neutral document IR. JavaScript performs no grammar work.
|
|
179
255
|
*/
|
|
180
256
|
declare function parse(source: string): MdiSyntaxParseResult;
|
|
257
|
+
/**
|
|
258
|
+
* Parse once in Rust and return source-order plaintext blocks, annotations,
|
|
259
|
+
* and grapheme-precise UTF-8 source maps alongside the complete document IR.
|
|
260
|
+
*/
|
|
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[];
|
|
272
|
+
/** Parse and validate a canonical one-based `block:character` position. */
|
|
273
|
+
declare function parseMdiTextPosition(position: string): MdiTextPositionValue;
|
|
274
|
+
/** Format a validated one-based text position. */
|
|
275
|
+
declare function formatMdiTextPosition(position: MdiTextPositionValue): MdiTextPosition;
|
|
276
|
+
/** Format a canonical full `start-end` range such as `3:18-3:24`. */
|
|
277
|
+
declare function formatMdiTextRange(range: MdiTextRange): string;
|
|
278
|
+
/**
|
|
279
|
+
* Resolve a text range to its source-derived UTF-8 spans. Synthetic table or
|
|
280
|
+
* paragraph separators are deliberately omitted.
|
|
281
|
+
*/
|
|
282
|
+
declare function sourceSpansForTextRange(block: MdiTextBlock, range: MdiTextRange): MdiSourceSpan[];
|
|
181
283
|
/** Render complete `.mdi` source to standalone semantic HTML in Rust. */
|
|
182
284
|
declare function renderHtml(source: string, options?: MdiHtmlRenderOptions): string;
|
|
183
285
|
/**
|
|
@@ -248,4 +350,4 @@ declare function renderTextFormatWithDiagnostics(source: string, format: MdiText
|
|
|
248
350
|
/** @deprecated Use {@link parse}; it now parses the complete document. */
|
|
249
351
|
declare const parseMdiSyntax: typeof parse;
|
|
250
352
|
|
|
251
|
-
export { MDI_IR_VERSION, MDI_SPEC_VERSION, 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 MdiTextFormat, initializeMdi, parse, parseMdiSyntax, prepareRender, renderDocx, renderDocxWithDiagnostics, renderDocxWithProfile, renderEpub, renderEpubWithDiagnostics, renderEpubWithProfile, renderHtml, renderHtmlWithDiagnostics, renderText, renderTextFormat, renderTextFormatWithDiagnostics, renderTextWithDiagnostics, serializeMdi, 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
|
@@ -76,6 +76,8 @@ type MdiDocxExportProfile = ExportProfile & {
|
|
|
76
76
|
declare const MDI_SPEC_VERSION: "2.0";
|
|
77
77
|
/** Version of the complete Rust-owned document IR. */
|
|
78
78
|
declare const MDI_IR_VERSION: "1.0";
|
|
79
|
+
/** Version of the Rust-owned searchable text projection. */
|
|
80
|
+
declare const MDI_TEXT_PROJECTION_VERSION: "1.0";
|
|
79
81
|
interface MdiParserCapabilities {
|
|
80
82
|
mdi: boolean;
|
|
81
83
|
commonMark: boolean;
|
|
@@ -89,6 +91,80 @@ interface MdiSourceSpan {
|
|
|
89
91
|
/** Exclusive UTF-8 byte offset. */
|
|
90
92
|
endByte: number;
|
|
91
93
|
}
|
|
94
|
+
/** A canonical one-based `block:grapheme` text position. */
|
|
95
|
+
type MdiTextPosition = `${number}:${number}`;
|
|
96
|
+
interface MdiTextPositionValue {
|
|
97
|
+
block: number;
|
|
98
|
+
character: number;
|
|
99
|
+
}
|
|
100
|
+
interface MdiTextRange {
|
|
101
|
+
/** Inclusive. */
|
|
102
|
+
start: MdiTextPosition;
|
|
103
|
+
/** Exclusive. */
|
|
104
|
+
end: MdiTextPosition;
|
|
105
|
+
}
|
|
106
|
+
interface MdiTextSourceRun {
|
|
107
|
+
range: MdiTextRange;
|
|
108
|
+
/** One UTF-8 source boundary per grapheme, plus the final boundary. */
|
|
109
|
+
sourceBoundaries: number[];
|
|
110
|
+
}
|
|
111
|
+
interface MdiTextSourceMap {
|
|
112
|
+
runs: MdiTextSourceRun[];
|
|
113
|
+
synthetic: MdiTextRange[];
|
|
114
|
+
unmapped: MdiTextRange[];
|
|
115
|
+
}
|
|
116
|
+
type MdiAnnotationSourceMap = MdiTextSourceMap;
|
|
117
|
+
interface MdiTextAnnotation {
|
|
118
|
+
kind: "rubyReading";
|
|
119
|
+
text: string;
|
|
120
|
+
anchor: MdiTextRange;
|
|
121
|
+
span?: MdiSourceSpan;
|
|
122
|
+
sourceMap: MdiAnnotationSourceMap;
|
|
123
|
+
}
|
|
124
|
+
interface MdiTextBlock {
|
|
125
|
+
/** One-based source-order block number. */
|
|
126
|
+
index: number;
|
|
127
|
+
kind: "heading" | "paragraph" | "listItem" | "blockquote" | "code" | "table" | "footnote" | "html" | "other";
|
|
128
|
+
text: string;
|
|
129
|
+
range: MdiTextRange;
|
|
130
|
+
span?: MdiSourceSpan;
|
|
131
|
+
sourceMap: MdiTextSourceMap;
|
|
132
|
+
annotations: MdiTextAnnotation[];
|
|
133
|
+
node: MdiNode;
|
|
134
|
+
}
|
|
135
|
+
interface MdiTextBlocksResult {
|
|
136
|
+
projectionVersion: "1.0";
|
|
137
|
+
positionEncoding: "unicode-grapheme-cluster-1-based";
|
|
138
|
+
irVersion: typeof MDI_IR_VERSION;
|
|
139
|
+
syntaxVersion: typeof MDI_SPEC_VERSION;
|
|
140
|
+
capabilities: MdiParserCapabilities;
|
|
141
|
+
blocks: MdiTextBlock[];
|
|
142
|
+
document: MdiDocument;
|
|
143
|
+
diagnostics: MdiDiagnostic[];
|
|
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
|
+
}
|
|
92
168
|
interface MdiDiagnostic {
|
|
93
169
|
severity: "warning" | "error";
|
|
94
170
|
code: string;
|
|
@@ -178,6 +254,32 @@ type MdiSyntaxDocument = MdiDocument;
|
|
|
178
254
|
* language-neutral document IR. JavaScript performs no grammar work.
|
|
179
255
|
*/
|
|
180
256
|
declare function parse(source: string): MdiSyntaxParseResult;
|
|
257
|
+
/**
|
|
258
|
+
* Parse once in Rust and return source-order plaintext blocks, annotations,
|
|
259
|
+
* and grapheme-precise UTF-8 source maps alongside the complete document IR.
|
|
260
|
+
*/
|
|
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[];
|
|
272
|
+
/** Parse and validate a canonical one-based `block:character` position. */
|
|
273
|
+
declare function parseMdiTextPosition(position: string): MdiTextPositionValue;
|
|
274
|
+
/** Format a validated one-based text position. */
|
|
275
|
+
declare function formatMdiTextPosition(position: MdiTextPositionValue): MdiTextPosition;
|
|
276
|
+
/** Format a canonical full `start-end` range such as `3:18-3:24`. */
|
|
277
|
+
declare function formatMdiTextRange(range: MdiTextRange): string;
|
|
278
|
+
/**
|
|
279
|
+
* Resolve a text range to its source-derived UTF-8 spans. Synthetic table or
|
|
280
|
+
* paragraph separators are deliberately omitted.
|
|
281
|
+
*/
|
|
282
|
+
declare function sourceSpansForTextRange(block: MdiTextBlock, range: MdiTextRange): MdiSourceSpan[];
|
|
181
283
|
/** Render complete `.mdi` source to standalone semantic HTML in Rust. */
|
|
182
284
|
declare function renderHtml(source: string, options?: MdiHtmlRenderOptions): string;
|
|
183
285
|
/**
|
|
@@ -248,4 +350,4 @@ declare function renderTextFormatWithDiagnostics(source: string, format: MdiText
|
|
|
248
350
|
/** @deprecated Use {@link parse}; it now parses the complete document. */
|
|
249
351
|
declare const parseMdiSyntax: typeof parse;
|
|
250
352
|
|
|
251
|
-
export { MDI_IR_VERSION, MDI_SPEC_VERSION, 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 MdiTextFormat, initializeMdi, parse, parseMdiSyntax, prepareRender, renderDocx, renderDocxWithDiagnostics, renderDocxWithProfile, renderEpub, renderEpubWithDiagnostics, renderEpubWithProfile, renderHtml, renderHtmlWithDiagnostics, renderText, renderTextFormat, renderTextFormatWithDiagnostics, renderTextWithDiagnostics, serializeMdi, 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
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MDI_IR_VERSION,
|
|
3
3
|
MDI_SPEC_VERSION,
|
|
4
|
+
MDI_TEXT_PROJECTION_VERSION,
|
|
5
|
+
formatMdiTextPosition,
|
|
6
|
+
formatMdiTextRange,
|
|
7
|
+
getMdiTextBlocks,
|
|
4
8
|
initializeMdi,
|
|
5
9
|
parse,
|
|
6
10
|
parseMdiSyntax,
|
|
11
|
+
parseMdiTextPosition,
|
|
7
12
|
prepareRender,
|
|
8
13
|
renderDocx,
|
|
9
14
|
renderDocxWithDiagnostics,
|
|
@@ -17,15 +22,23 @@ import {
|
|
|
17
22
|
renderTextFormat,
|
|
18
23
|
renderTextFormatWithDiagnostics,
|
|
19
24
|
renderTextWithDiagnostics,
|
|
25
|
+
resolveMdiSourceSpan,
|
|
26
|
+
resolveMdiSourceSpans,
|
|
20
27
|
serializeMdi,
|
|
28
|
+
sourceSpansForTextRange,
|
|
21
29
|
toPublicationMdast
|
|
22
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-GMS5SFZO.js";
|
|
23
31
|
export {
|
|
24
32
|
MDI_IR_VERSION,
|
|
25
33
|
MDI_SPEC_VERSION,
|
|
34
|
+
MDI_TEXT_PROJECTION_VERSION,
|
|
35
|
+
formatMdiTextPosition,
|
|
36
|
+
formatMdiTextRange,
|
|
37
|
+
getMdiTextBlocks,
|
|
26
38
|
initializeMdi,
|
|
27
39
|
parse,
|
|
28
40
|
parseMdiSyntax,
|
|
41
|
+
parseMdiTextPosition,
|
|
29
42
|
prepareRender,
|
|
30
43
|
renderDocx,
|
|
31
44
|
renderDocxWithDiagnostics,
|
|
@@ -39,6 +52,9 @@ export {
|
|
|
39
52
|
renderTextFormat,
|
|
40
53
|
renderTextFormatWithDiagnostics,
|
|
41
54
|
renderTextWithDiagnostics,
|
|
55
|
+
resolveMdiSourceSpan,
|
|
56
|
+
resolveMdiSourceSpans,
|
|
42
57
|
serializeMdi,
|
|
58
|
+
sourceSpansForTextRange,
|
|
43
59
|
toPublicationMdast
|
|
44
60
|
};
|
package/dist/node.cjs
CHANGED
|
@@ -41,6 +41,8 @@ module.exports = __toCommonJS(node_exports);
|
|
|
41
41
|
var mdiCore = __toESM(require("@illusions-lab/mdi-core"), 1);
|
|
42
42
|
var import_yaml = require("yaml");
|
|
43
43
|
var {
|
|
44
|
+
getMdiTextBlocksJson,
|
|
45
|
+
resolveMdiSourceSpansJson,
|
|
44
46
|
parseMdiSyntaxJson,
|
|
45
47
|
renderHtml: renderHtmlFromRust,
|
|
46
48
|
renderEpub: renderEpubFromRust,
|
package/dist/node.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@illusions-lab/mdi",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.20",
|
|
4
4
|
"description": "Thin JavaScript binding for the Rust-authoritative MDI parser",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"typecheck": "tsc --noEmit"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@illusions-lab/mdi-core": "^2.0.
|
|
36
|
-
"@illusions-lab/mdi-export-profile": "^2.0.
|
|
37
|
-
"@illusions-lab/mdi-to-epub": "^2.0.
|
|
35
|
+
"@illusions-lab/mdi-core": "^2.0.20",
|
|
36
|
+
"@illusions-lab/mdi-export-profile": "^2.0.25",
|
|
37
|
+
"@illusions-lab/mdi-to-epub": "^2.0.35",
|
|
38
38
|
"@types/mdast": "^4.0.0",
|
|
39
39
|
"yaml": "^2.0.0"
|
|
40
40
|
},
|