@illusions-lab/mdi 2.0.7 → 2.0.9
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 +62 -3
- package/dist/chunk-FA5R33XH.js +383 -0
- package/dist/index.cjs +347 -7
- package/dist/index.d.cts +148 -3
- package/dist/index.d.ts +148 -3
- package/dist/index.js +30 -47
- package/dist/node.cjs +160 -0
- package/dist/node.d.cts +41 -0
- package/dist/node.d.ts +41 -0
- package/dist/node.js +97 -0
- package/package.json +46 -36
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
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
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -24,15 +34,26 @@ __export(index_exports, {
|
|
|
24
34
|
MDI_SPEC_VERSION: () => MDI_SPEC_VERSION,
|
|
25
35
|
parse: () => parse,
|
|
26
36
|
parseMdiSyntax: () => parseMdiSyntax,
|
|
37
|
+
prepareRender: () => prepareRender,
|
|
27
38
|
renderDocx: () => renderDocx,
|
|
39
|
+
renderDocxWithDiagnostics: () => renderDocxWithDiagnostics,
|
|
40
|
+
renderDocxWithProfile: () => renderDocxWithProfile,
|
|
28
41
|
renderEpub: () => renderEpub,
|
|
42
|
+
renderEpubWithDiagnostics: () => renderEpubWithDiagnostics,
|
|
43
|
+
renderEpubWithProfile: () => renderEpubWithProfile,
|
|
29
44
|
renderHtml: () => renderHtml,
|
|
45
|
+
renderHtmlWithDiagnostics: () => renderHtmlWithDiagnostics,
|
|
30
46
|
renderText: () => renderText,
|
|
31
47
|
renderTextFormat: () => renderTextFormat,
|
|
32
|
-
|
|
48
|
+
renderTextFormatWithDiagnostics: () => renderTextFormatWithDiagnostics,
|
|
49
|
+
renderTextWithDiagnostics: () => renderTextWithDiagnostics,
|
|
50
|
+
serializeMdi: () => serializeMdi,
|
|
51
|
+
toPublicationMdast: () => toPublicationMdast
|
|
33
52
|
});
|
|
34
53
|
module.exports = __toCommonJS(index_exports);
|
|
35
54
|
var import_mdi_core = require("@illusions-lab/mdi-core");
|
|
55
|
+
var import_mdi_export_profile = require("@illusions-lab/mdi-export-profile");
|
|
56
|
+
var import_yaml = require("yaml");
|
|
36
57
|
var MDI_SPEC_VERSION = "2.0";
|
|
37
58
|
var MDI_IR_VERSION = "1.0";
|
|
38
59
|
function parse(source) {
|
|
@@ -43,18 +64,322 @@ function parse(source) {
|
|
|
43
64
|
}
|
|
44
65
|
return result;
|
|
45
66
|
}
|
|
46
|
-
function renderHtml(source) {
|
|
47
|
-
|
|
48
|
-
|
|
67
|
+
function renderHtml(source, options) {
|
|
68
|
+
assertSource(source);
|
|
69
|
+
assertHtmlOptions(options);
|
|
70
|
+
const html = (0, import_mdi_core.renderHtml)(source);
|
|
71
|
+
return options?.bodyOnly ? htmlBody(html) : html;
|
|
72
|
+
}
|
|
73
|
+
function renderHtmlWithDiagnostics(source, options) {
|
|
74
|
+
assertSource(source);
|
|
75
|
+
assertHtmlOptions(options);
|
|
76
|
+
return renderWithDiagnostics(source, () => renderHtml(source, options));
|
|
77
|
+
}
|
|
78
|
+
function prepareRender(source) {
|
|
79
|
+
return parse(source);
|
|
49
80
|
}
|
|
50
|
-
function renderEpub(source) {
|
|
81
|
+
function renderEpub(source, options) {
|
|
51
82
|
if (typeof source !== "string") throw new TypeError("source must be a string");
|
|
83
|
+
if (options !== void 0) {
|
|
84
|
+
assertEpubOptions(options);
|
|
85
|
+
return renderEpubWithProfile(source, options);
|
|
86
|
+
}
|
|
52
87
|
return (0, import_mdi_core.renderEpub)(source);
|
|
53
88
|
}
|
|
54
|
-
function
|
|
89
|
+
function renderEpubWithDiagnostics(source, options) {
|
|
90
|
+
return options === void 0 ? renderWithDiagnostics(source, () => renderEpub(source)) : renderWithDiagnosticsAsync(source, () => renderEpub(source, options));
|
|
91
|
+
}
|
|
92
|
+
function renderDocx(source, profile) {
|
|
55
93
|
if (typeof source !== "string") throw new TypeError("source must be a string");
|
|
94
|
+
if (profile !== void 0) {
|
|
95
|
+
assertPlainObject(profile, "profile");
|
|
96
|
+
return renderDocxWithProfile(source, profile);
|
|
97
|
+
}
|
|
56
98
|
return (0, import_mdi_core.renderDocx)(source);
|
|
57
99
|
}
|
|
100
|
+
function renderDocxWithDiagnostics(source, profile) {
|
|
101
|
+
return profile === void 0 ? renderWithDiagnostics(source, () => renderDocx(source)) : renderWithDiagnosticsAsync(source, () => renderDocx(source, profile));
|
|
102
|
+
}
|
|
103
|
+
async function renderEpubWithProfile(source, options = {}) {
|
|
104
|
+
assertSource(source);
|
|
105
|
+
assertEpubOptions(options);
|
|
106
|
+
const { mdiToEpub } = await import("@illusions-lab/mdi-to-epub");
|
|
107
|
+
const normalized = normalizeEpubOptions(options);
|
|
108
|
+
(0, import_mdi_export_profile.requireLayoutSystem)(normalized.profile);
|
|
109
|
+
return mdiToEpub(toPublicationMdast(parse(source).document), normalized);
|
|
110
|
+
}
|
|
111
|
+
async function renderDocxWithProfile(source, profile = {}) {
|
|
112
|
+
assertSource(source);
|
|
113
|
+
assertPlainObject(profile, "profile");
|
|
114
|
+
prepareNodeDocxImport();
|
|
115
|
+
const { mdiToDocx } = await import("@illusions-lab/mdi-to-docx");
|
|
116
|
+
const normalized = normalizeDocxProfile(profile);
|
|
117
|
+
(0, import_mdi_export_profile.requireLayoutSystem)(normalized);
|
|
118
|
+
return mdiToDocx(toPublicationMdast(parse(source).document), normalized);
|
|
119
|
+
}
|
|
120
|
+
function prepareNodeDocxImport() {
|
|
121
|
+
const nodeProcess = globalThis.process;
|
|
122
|
+
if (nodeProcess?.release?.name === "node" && !nodeProcess.execArgv?.some((argument) => argument.startsWith("--localstorage-file="))) {
|
|
123
|
+
const descriptor = Object.getOwnPropertyDescriptor(globalThis, "localStorage");
|
|
124
|
+
if (descriptor?.configurable && descriptor.get)
|
|
125
|
+
Object.defineProperty(globalThis, "localStorage", {
|
|
126
|
+
value: void 0,
|
|
127
|
+
configurable: true
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function toPublicationMdast(document) {
|
|
132
|
+
const children = document.children.map(toPublicationMdastNode);
|
|
133
|
+
const tree = { type: "root", children };
|
|
134
|
+
if (document.frontmatter) {
|
|
135
|
+
children.unshift({ type: "yaml", value: document.frontmatter.raw });
|
|
136
|
+
const frontmatter = publicationFrontmatter(document.frontmatter.raw);
|
|
137
|
+
tree.data ??= {};
|
|
138
|
+
tree.data.frontmatter = frontmatter;
|
|
139
|
+
}
|
|
140
|
+
return tree;
|
|
141
|
+
}
|
|
142
|
+
function toPublicationMdastNode(node) {
|
|
143
|
+
const { span: _span, children, ...rest } = node;
|
|
144
|
+
const mapped = { ...rest };
|
|
145
|
+
if (children) mapped.children = children.map(toPublicationMdastNode);
|
|
146
|
+
switch (node.type) {
|
|
147
|
+
case "ruby": {
|
|
148
|
+
const ruby = node.ruby;
|
|
149
|
+
return { ...mapped, type: "mdiRuby", ruby: ruby.value };
|
|
150
|
+
}
|
|
151
|
+
case "tcy":
|
|
152
|
+
return { ...mapped, type: "mdiTcy" };
|
|
153
|
+
case "break":
|
|
154
|
+
return { ...mapped, type: "mdiBreak" };
|
|
155
|
+
case "em":
|
|
156
|
+
return { ...mapped, type: "mdiEm" };
|
|
157
|
+
case "noBreak":
|
|
158
|
+
return { ...mapped, type: "mdiNoBreak" };
|
|
159
|
+
case "warichu":
|
|
160
|
+
return { ...mapped, type: "mdiWarichu" };
|
|
161
|
+
case "kern":
|
|
162
|
+
return { ...mapped, type: "mdiKern" };
|
|
163
|
+
case "blank":
|
|
164
|
+
return { ...mapped, type: "mdiBlank" };
|
|
165
|
+
case "pagebreak": {
|
|
166
|
+
if (mapped.variant === null) delete mapped.variant;
|
|
167
|
+
return { ...mapped, type: "mdiPagebreak" };
|
|
168
|
+
}
|
|
169
|
+
case "paragraph": {
|
|
170
|
+
const data = {};
|
|
171
|
+
if (typeof mapped.indent === "number") data.mdiIndent = mapped.indent;
|
|
172
|
+
if (typeof mapped.bottom === "number") data.mdiBottom = mapped.bottom;
|
|
173
|
+
delete mapped.indent;
|
|
174
|
+
delete mapped.bottom;
|
|
175
|
+
if (Object.keys(data).length) mapped.data = data;
|
|
176
|
+
return mapped;
|
|
177
|
+
}
|
|
178
|
+
default:
|
|
179
|
+
return mapped;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function publicationFrontmatter(raw) {
|
|
183
|
+
let value;
|
|
184
|
+
try {
|
|
185
|
+
value = (0, import_yaml.parse)(raw);
|
|
186
|
+
} catch {
|
|
187
|
+
value = void 0;
|
|
188
|
+
}
|
|
189
|
+
const source = isRecord(value) ? value : {};
|
|
190
|
+
const writingMode = source["writing-mode"] === "vertical" ? "vertical" : "horizontal";
|
|
191
|
+
return {
|
|
192
|
+
mdi: stringValue(source.mdi) ?? "2.0",
|
|
193
|
+
title: stringValue(source.title),
|
|
194
|
+
author: stringValue(source.author),
|
|
195
|
+
lang: stringValue(source.lang) ?? "ja",
|
|
196
|
+
date: stringValue(source.date),
|
|
197
|
+
writingMode,
|
|
198
|
+
pageProgression: source["page-progression"] === "ltr" || source["page-progression"] === "rtl" ? source["page-progression"] : writingMode === "vertical" ? "rtl" : "ltr"
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function isRecord(value) {
|
|
202
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
203
|
+
}
|
|
204
|
+
function stringValue(value) {
|
|
205
|
+
return typeof value === "string" ? value : void 0;
|
|
206
|
+
}
|
|
207
|
+
function renderWithDiagnostics(source, render) {
|
|
208
|
+
const parsed = parse(source);
|
|
209
|
+
return {
|
|
210
|
+
output: render(),
|
|
211
|
+
document: parsed.document,
|
|
212
|
+
diagnostics: parsed.diagnostics,
|
|
213
|
+
headings: headingsFromDocument(parsed.document)
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
async function renderWithDiagnosticsAsync(source, render) {
|
|
217
|
+
const parsed = parse(source);
|
|
218
|
+
return {
|
|
219
|
+
output: await render(),
|
|
220
|
+
document: parsed.document,
|
|
221
|
+
diagnostics: parsed.diagnostics,
|
|
222
|
+
headings: headingsFromDocument(parsed.document)
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function assertSource(source) {
|
|
226
|
+
if (typeof source !== "string") throw new TypeError("source must be a string");
|
|
227
|
+
}
|
|
228
|
+
function assertHtmlOptions(options) {
|
|
229
|
+
if (options === void 0) return;
|
|
230
|
+
assertPlainObject(options, "options");
|
|
231
|
+
if (options.bodyOnly !== void 0 && typeof options.bodyOnly !== "boolean") {
|
|
232
|
+
throw new TypeError("options.bodyOnly must be a boolean");
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function htmlBody(html) {
|
|
236
|
+
const match = /<body(?:\s[^>]*)?>([\s\S]*)<\/body>/i.exec(html);
|
|
237
|
+
if (!match) throw new Error("Rust HTML renderer returned a document without a body");
|
|
238
|
+
return match[1];
|
|
239
|
+
}
|
|
240
|
+
function headingsFromDocument(document) {
|
|
241
|
+
const headings = [];
|
|
242
|
+
visitNodes(document.children, (node) => {
|
|
243
|
+
if (node.type !== "heading" || !isHeadingDepth(node.depth)) return;
|
|
244
|
+
headings.push({
|
|
245
|
+
depth: node.depth,
|
|
246
|
+
text: plainNodeText(node),
|
|
247
|
+
span: node.span,
|
|
248
|
+
node
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
return headings;
|
|
252
|
+
}
|
|
253
|
+
function visitNodes(nodes, visit) {
|
|
254
|
+
for (const node of nodes) {
|
|
255
|
+
visit(node);
|
|
256
|
+
if (node.children) visitNodes(node.children, visit);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function isHeadingDepth(value) {
|
|
260
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= 6;
|
|
261
|
+
}
|
|
262
|
+
function plainNodeText(node) {
|
|
263
|
+
if (node.type === "ruby" && typeof node.base === "string") return node.base;
|
|
264
|
+
const value = node.value;
|
|
265
|
+
const ownText = typeof value === "string" ? value : "";
|
|
266
|
+
return ownText + (node.children?.map(plainNodeText).join("") ?? "");
|
|
267
|
+
}
|
|
268
|
+
function assertPlainObject(value, label) {
|
|
269
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
270
|
+
throw new TypeError(`${label} must be an object`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function assertEpubOptions(options) {
|
|
274
|
+
assertPlainObject(options, "options");
|
|
275
|
+
if (options.cover !== void 0) {
|
|
276
|
+
assertPlainObject(options.cover, "options.cover");
|
|
277
|
+
if (!(options.cover.data instanceof Uint8Array)) {
|
|
278
|
+
throw new TypeError("options.cover.data must be a Uint8Array");
|
|
279
|
+
}
|
|
280
|
+
if (options.cover.mediaType !== "image/jpeg" && options.cover.mediaType !== "image/png") {
|
|
281
|
+
throw new TypeError("options.cover.mediaType must be image/jpeg or image/png");
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if (options.coverImage !== void 0 && !(options.coverImage instanceof Uint8Array)) {
|
|
285
|
+
throw new TypeError("options.coverImage must be a Uint8Array");
|
|
286
|
+
}
|
|
287
|
+
if (options.coverMediaType !== void 0 && options.coverMediaType !== "image/jpeg" && options.coverMediaType !== "image/png") {
|
|
288
|
+
throw new TypeError("options.coverMediaType must be image/jpeg or image/png");
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function normalizeEpubOptions(options) {
|
|
292
|
+
const {
|
|
293
|
+
title,
|
|
294
|
+
author,
|
|
295
|
+
publisher,
|
|
296
|
+
identifier,
|
|
297
|
+
language,
|
|
298
|
+
date,
|
|
299
|
+
verticalWriting,
|
|
300
|
+
fontFamily,
|
|
301
|
+
fontSize,
|
|
302
|
+
lineSpacing,
|
|
303
|
+
textIndent,
|
|
304
|
+
fullwidthSpaceIndent,
|
|
305
|
+
gridMode,
|
|
306
|
+
chapterSplitLevel,
|
|
307
|
+
coverImage,
|
|
308
|
+
coverMediaType,
|
|
309
|
+
cover,
|
|
310
|
+
profile
|
|
311
|
+
} = options;
|
|
312
|
+
const metadata = { ...profile?.metadata, ...defined({ title, author, publisher, identifier, language, date }) };
|
|
313
|
+
const writingMode = verticalWriting === void 0 ? void 0 : verticalWriting ? "vertical" : "horizontal";
|
|
314
|
+
const typesetting = {
|
|
315
|
+
...profile?.typesetting,
|
|
316
|
+
...defined({
|
|
317
|
+
writingMode,
|
|
318
|
+
fontFamily,
|
|
319
|
+
fontSize,
|
|
320
|
+
lineSpacing,
|
|
321
|
+
textIndentEm: textIndent,
|
|
322
|
+
fullwidthSpaceIndent
|
|
323
|
+
})
|
|
324
|
+
};
|
|
325
|
+
const epub = { ...profile?.epub, ...defined({ chapterSplitLevel }) };
|
|
326
|
+
return {
|
|
327
|
+
profile: {
|
|
328
|
+
...profile,
|
|
329
|
+
metadata,
|
|
330
|
+
typesetting,
|
|
331
|
+
epub,
|
|
332
|
+
pagination: { ...profile?.pagination, ...defined({ gridMode }) }
|
|
333
|
+
},
|
|
334
|
+
cover: cover ?? (coverImage ? { data: coverImage, mediaType: coverMediaType ?? "image/png" } : void 0)
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
function normalizeDocxProfile(profile) {
|
|
338
|
+
const {
|
|
339
|
+
title,
|
|
340
|
+
author,
|
|
341
|
+
publisher,
|
|
342
|
+
identifier,
|
|
343
|
+
language,
|
|
344
|
+
date,
|
|
345
|
+
verticalWriting,
|
|
346
|
+
fontFamily,
|
|
347
|
+
fontSize,
|
|
348
|
+
lineSpacing,
|
|
349
|
+
textIndent,
|
|
350
|
+
pageSize,
|
|
351
|
+
landscape,
|
|
352
|
+
gridMode,
|
|
353
|
+
charactersPerLine,
|
|
354
|
+
linesPerPage,
|
|
355
|
+
margins,
|
|
356
|
+
fullwidthSpaceIndent,
|
|
357
|
+
showPageNumbers,
|
|
358
|
+
pageNumberPosition,
|
|
359
|
+
pageNumberFormat,
|
|
360
|
+
...nested
|
|
361
|
+
} = profile;
|
|
362
|
+
const writingMode = verticalWriting === void 0 ? void 0 : verticalWriting ? "vertical" : "horizontal";
|
|
363
|
+
return {
|
|
364
|
+
...nested,
|
|
365
|
+
metadata: { ...nested.metadata, ...defined({ title, author, publisher, identifier, language, date }) },
|
|
366
|
+
typesetting: {
|
|
367
|
+
...nested.typesetting,
|
|
368
|
+
...defined({ writingMode, fontFamily, fontSize, lineSpacing, textIndentEm: textIndent, fullwidthSpaceIndent })
|
|
369
|
+
},
|
|
370
|
+
pagination: {
|
|
371
|
+
...nested.pagination,
|
|
372
|
+
...defined({ pageSize, landscape, gridMode, charactersPerLine, linesPerPage, margins }),
|
|
373
|
+
pageNumbers: {
|
|
374
|
+
...nested.pagination?.pageNumbers,
|
|
375
|
+
...defined({ enabled: showPageNumbers, position: pageNumberPosition, format: pageNumberFormat })
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
function defined(value) {
|
|
381
|
+
return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== void 0));
|
|
382
|
+
}
|
|
58
383
|
function serializeMdi(source) {
|
|
59
384
|
if (typeof source !== "string") throw new TypeError("source must be a string");
|
|
60
385
|
return (0, import_mdi_core.serializeMdi)(source);
|
|
@@ -63,12 +388,18 @@ function renderText(source) {
|
|
|
63
388
|
if (typeof source !== "string") throw new TypeError("source must be a string");
|
|
64
389
|
return (0, import_mdi_core.renderText)(source);
|
|
65
390
|
}
|
|
391
|
+
function renderTextWithDiagnostics(source) {
|
|
392
|
+
return renderWithDiagnostics(source, () => renderText(source));
|
|
393
|
+
}
|
|
66
394
|
function renderTextFormat(source, format, indentPrefix = "") {
|
|
67
395
|
if (typeof source !== "string" || typeof indentPrefix !== "string") {
|
|
68
396
|
throw new TypeError("source and indentPrefix must be strings");
|
|
69
397
|
}
|
|
70
398
|
return (0, import_mdi_core.renderTextFormat)(source, format, indentPrefix);
|
|
71
399
|
}
|
|
400
|
+
function renderTextFormatWithDiagnostics(source, format, indentPrefix = "") {
|
|
401
|
+
return renderWithDiagnostics(source, () => renderTextFormat(source, format, indentPrefix));
|
|
402
|
+
}
|
|
72
403
|
var parseMdiSyntax = parse;
|
|
73
404
|
// Annotate the CommonJS export names for ESM import in node:
|
|
74
405
|
0 && (module.exports = {
|
|
@@ -76,10 +407,19 @@ var parseMdiSyntax = parse;
|
|
|
76
407
|
MDI_SPEC_VERSION,
|
|
77
408
|
parse,
|
|
78
409
|
parseMdiSyntax,
|
|
410
|
+
prepareRender,
|
|
79
411
|
renderDocx,
|
|
412
|
+
renderDocxWithDiagnostics,
|
|
413
|
+
renderDocxWithProfile,
|
|
80
414
|
renderEpub,
|
|
415
|
+
renderEpubWithDiagnostics,
|
|
416
|
+
renderEpubWithProfile,
|
|
81
417
|
renderHtml,
|
|
418
|
+
renderHtmlWithDiagnostics,
|
|
82
419
|
renderText,
|
|
83
420
|
renderTextFormat,
|
|
84
|
-
|
|
421
|
+
renderTextFormatWithDiagnostics,
|
|
422
|
+
renderTextWithDiagnostics,
|
|
423
|
+
serializeMdi,
|
|
424
|
+
toPublicationMdast
|
|
85
425
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,68 @@
|
|
|
1
|
+
import { EpubExportOptions, EpubCover } from '@illusions-lab/mdi-to-epub';
|
|
2
|
+
export { EpubCover, EpubExportOptions } from '@illusions-lab/mdi-to-epub';
|
|
3
|
+
import { ExportProfile } from '@illusions-lab/mdi-export-profile';
|
|
4
|
+
export { ExportProfile } from '@illusions-lab/mdi-export-profile';
|
|
5
|
+
import { Root } from 'mdast';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Options for a configured EPUB export. The profile controls metadata,
|
|
9
|
+
* chapter splitting and typography; `cover` supplies the actual image data.
|
|
10
|
+
*/
|
|
11
|
+
type MdiEpubExportOptions = EpubExportOptions & {
|
|
12
|
+
/** Ergonomic aliases merged into `profile.metadata`. */
|
|
13
|
+
title?: string;
|
|
14
|
+
author?: string;
|
|
15
|
+
publisher?: string;
|
|
16
|
+
identifier?: string;
|
|
17
|
+
language?: string;
|
|
18
|
+
date?: string;
|
|
19
|
+
/** Ergonomic aliases merged into `profile.typesetting` and `profile.epub`. */
|
|
20
|
+
verticalWriting?: boolean;
|
|
21
|
+
fontFamily?: string;
|
|
22
|
+
/** Body type size in typographic points. */
|
|
23
|
+
fontSize?: number;
|
|
24
|
+
/** Baseline multiplier, for example 1.5 for one-and-a-half spacing. */
|
|
25
|
+
lineSpacing?: number;
|
|
26
|
+
textIndent?: number;
|
|
27
|
+
/** Use an ideographic-space-compatible first-line indent. */
|
|
28
|
+
fullwidthSpaceIndent?: boolean;
|
|
29
|
+
/** EPUB has no fixed pages; use `typographic` when overriding type metrics. */
|
|
30
|
+
gridMode?: "strict" | "typographic";
|
|
31
|
+
chapterSplitLevel?: "h1" | "h2" | "h3" | "none";
|
|
32
|
+
/** Shorthand for `cover: { data: coverImage, mediaType: coverMediaType }`. */
|
|
33
|
+
coverImage?: Uint8Array;
|
|
34
|
+
coverMediaType?: EpubCover["mediaType"];
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Profile for a configured DOCX export, including page geometry and numbering.
|
|
38
|
+
*/
|
|
39
|
+
type MdiDocxExportProfile = ExportProfile & {
|
|
40
|
+
title?: string;
|
|
41
|
+
author?: string;
|
|
42
|
+
publisher?: string;
|
|
43
|
+
identifier?: string;
|
|
44
|
+
language?: string;
|
|
45
|
+
date?: string;
|
|
46
|
+
verticalWriting?: boolean;
|
|
47
|
+
fontFamily?: string;
|
|
48
|
+
/** Point size; requires a publication adapter that supports it. */
|
|
49
|
+
fontSize?: number;
|
|
50
|
+
/** Line-height multiplier; requires a publication adapter that supports it. */
|
|
51
|
+
lineSpacing?: number;
|
|
52
|
+
textIndent?: number;
|
|
53
|
+
pageSize?: NonNullable<ExportProfile["pagination"]>["pageSize"];
|
|
54
|
+
landscape?: boolean;
|
|
55
|
+
/** `strict` enforces the character/line grid; `typographic` prioritizes explicit type metrics. */
|
|
56
|
+
gridMode?: "strict" | "typographic";
|
|
57
|
+
charactersPerLine?: number;
|
|
58
|
+
linesPerPage?: number;
|
|
59
|
+
margins?: NonNullable<NonNullable<ExportProfile["pagination"]>["margins"]>;
|
|
60
|
+
/** Emit literal ideographic spaces for first-line indentation in DOCX. */
|
|
61
|
+
fullwidthSpaceIndent?: boolean;
|
|
62
|
+
showPageNumbers?: boolean;
|
|
63
|
+
pageNumberPosition?: NonNullable<NonNullable<ExportProfile["pagination"]>["pageNumbers"]>["position"];
|
|
64
|
+
pageNumberFormat?: NonNullable<NonNullable<ExportProfile["pagination"]>["pageNumbers"]>["format"];
|
|
65
|
+
};
|
|
1
66
|
/** MDI specification version implemented by this binding. */
|
|
2
67
|
declare const MDI_SPEC_VERSION: "2.0";
|
|
3
68
|
/** Version of the complete Rust-owned document IR. */
|
|
@@ -48,6 +113,27 @@ interface MdiDocument {
|
|
|
48
113
|
frontmatter?: MdiFrontmatter;
|
|
49
114
|
children: MdiNode[];
|
|
50
115
|
}
|
|
116
|
+
/** A source-backed heading available to host navigation and chapter UIs. */
|
|
117
|
+
interface MdiHeading {
|
|
118
|
+
depth: 1 | 2 | 3 | 4 | 5 | 6;
|
|
119
|
+
/** Plain, source-order text. Inline MDI is represented by `node` as well. */
|
|
120
|
+
text: string;
|
|
121
|
+
span?: MdiSourceSpan;
|
|
122
|
+
/** The complete Rust-owned heading node, including inline children. */
|
|
123
|
+
node: MdiNode;
|
|
124
|
+
}
|
|
125
|
+
/** HTML output controls that do not alter MDI semantics. */
|
|
126
|
+
interface MdiHtmlRenderOptions {
|
|
127
|
+
/** Return the semantic contents of `<body>` rather than a standalone page. */
|
|
128
|
+
bodyOnly?: boolean;
|
|
129
|
+
}
|
|
130
|
+
/** A parsed document retained with renderer output for UI diagnostics. */
|
|
131
|
+
interface MdiRenderResult<T> {
|
|
132
|
+
output: T;
|
|
133
|
+
document: MdiDocument;
|
|
134
|
+
diagnostics: MdiDiagnostic[];
|
|
135
|
+
headings: MdiHeading[];
|
|
136
|
+
}
|
|
51
137
|
/**
|
|
52
138
|
* Versioned result returned by the Rust parser.
|
|
53
139
|
*
|
|
@@ -68,20 +154,79 @@ type MdiSyntaxDocument = MdiDocument;
|
|
|
68
154
|
* language-neutral document IR. JavaScript performs no grammar work.
|
|
69
155
|
*/
|
|
70
156
|
declare function parse(source: string): MdiSyntaxParseResult;
|
|
71
|
-
/** Render complete `.mdi` source to standalone HTML in Rust. */
|
|
72
|
-
declare function renderHtml(source: string): string;
|
|
157
|
+
/** Render complete `.mdi` source to standalone semantic HTML in Rust. */
|
|
158
|
+
declare function renderHtml(source: string, options?: MdiHtmlRenderOptions): string;
|
|
159
|
+
/**
|
|
160
|
+
* Render HTML while retaining the Rust parser result that made the semantic
|
|
161
|
+
* decisions. Use this in editors: warnings and source spans remain available
|
|
162
|
+
* instead of being silently discarded, and `headings` can drive navigation or
|
|
163
|
+
* chapter controls without scraping generated HTML.
|
|
164
|
+
*
|
|
165
|
+
* The low-level Rust ABI currently accepts source for rendering, rather than a
|
|
166
|
+
* serializable IR handle. This helper therefore validates with the same Rust
|
|
167
|
+
* parser immediately before rendering and returns that exact parse result.
|
|
168
|
+
*/
|
|
169
|
+
declare function renderHtmlWithDiagnostics(source: string, options?: MdiHtmlRenderOptions): MdiRenderResult<string>;
|
|
170
|
+
/**
|
|
171
|
+
* Parse once for a host workflow that needs stable diagnostics and source
|
|
172
|
+
* spans before selecting one of the renderer APIs. The returned document is
|
|
173
|
+
* Rust-owned IR and must not be mutated as an input to a renderer.
|
|
174
|
+
*/
|
|
175
|
+
declare function prepareRender(source: string): MdiSyntaxParseResult;
|
|
73
176
|
/** Build a baseline EPUB 3 archive from complete source in Rust. */
|
|
74
177
|
declare function renderEpub(source: string): Uint8Array;
|
|
178
|
+
/**
|
|
179
|
+
* Build a profile-configured EPUB 3 archive. This overload is asynchronous
|
|
180
|
+
* because archive generation is performed by the Node.js publication adapter.
|
|
181
|
+
*/
|
|
182
|
+
declare function renderEpub(source: string, options: MdiEpubExportOptions): Promise<Uint8Array>;
|
|
183
|
+
/** Build a baseline Rust EPUB while retaining diagnostics for an export UI. */
|
|
184
|
+
declare function renderEpubWithDiagnostics(source: string): MdiRenderResult<Uint8Array>;
|
|
185
|
+
declare function renderEpubWithDiagnostics(source: string, options: MdiEpubExportOptions): Promise<MdiRenderResult<Uint8Array>>;
|
|
75
186
|
/** Build a baseline DOCX archive from complete source in Rust. */
|
|
76
187
|
declare function renderDocx(source: string): Uint8Array;
|
|
188
|
+
/**
|
|
189
|
+
* Build a profile-configured DOCX archive. This overload is asynchronous
|
|
190
|
+
* because archive generation is performed by the Node.js publication adapter.
|
|
191
|
+
*/
|
|
192
|
+
declare function renderDocx(source: string, profile: MdiDocxExportProfile): Promise<Uint8Array>;
|
|
193
|
+
/** Build a baseline Rust DOCX while retaining diagnostics for an export UI. */
|
|
194
|
+
declare function renderDocxWithDiagnostics(source: string): MdiRenderResult<Uint8Array>;
|
|
195
|
+
declare function renderDocxWithDiagnostics(source: string, profile: MdiDocxExportProfile): Promise<MdiRenderResult<Uint8Array>>;
|
|
196
|
+
/**
|
|
197
|
+
* Build a configured EPUB using the same profile schema as the dedicated
|
|
198
|
+
* publication adapters. Unlike the one-argument {@link renderEpub}, this
|
|
199
|
+
* returns a Promise and supports cover art, metadata, chapters and vertical
|
|
200
|
+
* writing.
|
|
201
|
+
*/
|
|
202
|
+
declare function renderEpubWithProfile(source: string, options?: MdiEpubExportOptions): Promise<Uint8Array>;
|
|
203
|
+
/**
|
|
204
|
+
* Build a configured DOCX using the shared print profile. The profile
|
|
205
|
+
* supports metadata, writing mode, paper size, margins and page numbers.
|
|
206
|
+
*/
|
|
207
|
+
declare function renderDocxWithProfile(source: string, profile?: MdiDocxExportProfile): Promise<Uint8Array>;
|
|
208
|
+
/**
|
|
209
|
+
* Map the Rust-owned IR to mdast for the publication adapters. This is a
|
|
210
|
+
* structural conversion only: all grammar decisions have already been made
|
|
211
|
+
* by {@link parse}, so it never reparses MDI source in JavaScript.
|
|
212
|
+
*/
|
|
213
|
+
/**
|
|
214
|
+
* Convert a Rust-owned MDI document IR into mdast for publication adapters.
|
|
215
|
+
* This performs no parsing and preserves the adapter node conventions.
|
|
216
|
+
*/
|
|
217
|
+
declare function toPublicationMdast(document: MdiDocument): Root;
|
|
77
218
|
/** Parse and normalize complete `.mdi` source with Rust's serializer. */
|
|
78
219
|
declare function serializeMdi(source: string): string;
|
|
79
220
|
/** Render complete `.mdi` source to deterministic plain text in Rust. */
|
|
80
221
|
declare function renderText(source: string): string;
|
|
222
|
+
/** Render plain text without discarding Rust diagnostics and source spans. */
|
|
223
|
+
declare function renderTextWithDiagnostics(source: string): MdiRenderResult<string>;
|
|
81
224
|
type MdiTextFormat = "txt" | "txt-ruby" | "narou" | "kakuyomu" | "aozora";
|
|
82
225
|
/** Render a named publication-text convention through Rust. */
|
|
83
226
|
declare function renderTextFormat(source: string, format: MdiTextFormat, indentPrefix?: string): string;
|
|
227
|
+
/** Render a named text format without discarding Rust diagnostics and spans. */
|
|
228
|
+
declare function renderTextFormatWithDiagnostics(source: string, format: MdiTextFormat, indentPrefix?: string): MdiRenderResult<string>;
|
|
84
229
|
/** @deprecated Use {@link parse}; it now parses the complete document. */
|
|
85
230
|
declare const parseMdiSyntax: typeof parse;
|
|
86
231
|
|
|
87
|
-
export { MDI_IR_VERSION, MDI_SPEC_VERSION, type MdiDiagnostic, type MdiDocument, type MdiFrontmatter, type MdiNode, type MdiParserCapabilities, type MdiRubyReading, type MdiSourceSpan, type MdiSyntaxDocument, type MdiSyntaxParseResult, type MdiTextFormat, parse, parseMdiSyntax, renderDocx, renderEpub, renderHtml, renderText, renderTextFormat, serializeMdi };
|
|
232
|
+
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 MdiRenderResult, type MdiRubyReading, type MdiSourceSpan, type MdiSyntaxDocument, type MdiSyntaxParseResult, type MdiTextFormat, parse, parseMdiSyntax, prepareRender, renderDocx, renderDocxWithDiagnostics, renderDocxWithProfile, renderEpub, renderEpubWithDiagnostics, renderEpubWithProfile, renderHtml, renderHtmlWithDiagnostics, renderText, renderTextFormat, renderTextFormatWithDiagnostics, renderTextWithDiagnostics, serializeMdi, toPublicationMdast };
|