@aicayzer/inkkit 0.0.18 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +4 -2
- package/README.md +11 -7
- package/dist/THIRD-PARTY-NOTICES.txt +2742 -0
- package/dist/chunks/core-CYp5ONPO.js +56519 -0
- package/dist/chunks/highlight-BW9W8PtS.js +14122 -0
- package/dist/core.d.ts +2 -5
- package/dist/core.js +2 -2
- package/dist/editor.d.ts +229 -47
- package/dist/index.js +5 -3
- package/dist/style.css +231 -202
- package/dist/types.d.ts +143 -18
- package/package.json +16 -13
- package/dist/autolink.d.ts +0 -1
- package/dist/autolink.js +0 -18
- package/dist/callouts.d.ts +0 -25
- package/dist/callouts.js +0 -288
- package/dist/clipboard.d.ts +0 -11
- package/dist/clipboard.js +0 -261
- package/dist/code-fences.d.ts +0 -8
- package/dist/code-fences.js +0 -171
- package/dist/comments.d.ts +0 -76
- package/dist/comments.js +0 -545
- package/dist/cursor.d.ts +0 -2
- package/dist/cursor.js +0 -40
- package/dist/decorations.d.ts +0 -2
- package/dist/decorations.js +0 -67
- package/dist/dialect.d.ts +0 -9
- package/dist/dialect.js +0 -446
- package/dist/drop-placement.d.ts +0 -19
- package/dist/drop-placement.js +0 -47
- package/dist/editor.js +0 -2673
- package/dist/files.d.ts +0 -40
- package/dist/files.js +0 -133
- package/dist/highlight.d.ts +0 -1
- package/dist/highlight.js +0 -136
- package/dist/html-import.d.ts +0 -13
- package/dist/html-import.js +0 -477
- package/dist/image-blocks.d.ts +0 -86
- package/dist/image-blocks.js +0 -329
- package/dist/images.d.ts +0 -51
- package/dist/images.js +0 -398
- package/dist/inline-highlight.d.ts +0 -6
- package/dist/inline-highlight.js +0 -112
- package/dist/labels.d.ts +0 -36
- package/dist/labels.js +0 -34
- package/dist/link-safety.d.ts +0 -17
- package/dist/link-safety.js +0 -29
- package/dist/linked-syntax.d.ts +0 -48
- package/dist/linked-syntax.js +0 -320
- package/dist/literals.d.ts +0 -20
- package/dist/literals.js +0 -216
- package/dist/mermaid.d.ts +0 -28
- package/dist/mermaid.js +0 -404
- package/dist/outline.d.ts +0 -22
- package/dist/outline.js +0 -79
- package/dist/paste-html.d.ts +0 -31
- package/dist/paste-html.js +0 -462
- package/dist/paste.d.ts +0 -33
- package/dist/paste.js +0 -591
- package/dist/portable-files.d.ts +0 -10
- package/dist/portable-files.js +0 -36
- package/dist/preserve.d.ts +0 -38
- package/dist/preserve.js +0 -1396
- package/dist/print.d.ts +0 -7
- package/dist/print.js +0 -406
- package/dist/reference-clipboard.d.ts +0 -8
- package/dist/reference-clipboard.js +0 -201
- package/dist/references.d.ts +0 -16
- package/dist/references.js +0 -418
- package/dist/scroll.d.ts +0 -15
- package/dist/scroll.js +0 -27
- package/dist/search.d.ts +0 -15
- package/dist/search.js +0 -202
- package/dist/selection.d.ts +0 -1
- package/dist/selection.js +0 -59
- package/dist/source.d.ts +0 -16
- package/dist/source.js +0 -57
- package/dist/spreadsheet.d.ts +0 -8
- package/dist/spreadsheet.js +0 -289
- package/dist/table-alignment.d.ts +0 -2
- package/dist/table-alignment.js +0 -46
- package/dist/tables.d.ts +0 -27
- package/dist/tables.js +0 -344
- package/dist/tasks.d.ts +0 -3
- package/dist/tasks.js +0 -51
- package/dist/text-ranges.d.ts +0 -29
- package/dist/text-ranges.js +0 -256
- package/dist/types.js +0 -8
- package/dist/wiki-view.d.ts +0 -21
- package/dist/wiki-view.js +0 -78
package/dist/print.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Fragment, Schema } from '@milkdown/kit/prose/model';
|
|
2
|
-
import { type DocumentContext, type ImageAdapter, type FileAdapter, type PrintableDocument } from './types.js';
|
|
3
|
-
type PrintableContent = Pick<PrintableDocument, 'html' | 'styles' | 'assets' | 'warnings'>;
|
|
4
|
-
export declare function printableText(text: string): PrintableContent;
|
|
5
|
-
export declare function hasAuthoredImagesInLiterals(content: Fragment, parse: (source: string) => unknown): boolean;
|
|
6
|
-
export declare function printableMarkdown(content: Fragment, schema: Schema, adapter: ImageAdapter | undefined, context: DocumentContext, files?: FileAdapter, signal?: AbortSignal): Promise<PrintableContent>;
|
|
7
|
-
export {};
|
package/dist/print.js
DELETED
|
@@ -1,406 +0,0 @@
|
|
|
1
|
-
import { clipboardContent } from './clipboard.js';
|
|
2
|
-
import { shareableFragment } from './comments.js';
|
|
3
|
-
import { isSafeLinkTarget } from './link-safety.js';
|
|
4
|
-
import { fileReference } from './linked-syntax.js';
|
|
5
|
-
import { sourceFrontmatter } from './literals.js';
|
|
6
|
-
import { diagramImage, renderDiagram } from './mermaid.js';
|
|
7
|
-
import { portableFile, portableFileImage } from './portable-files.js';
|
|
8
|
-
import { withFileSignal } from './files.js';
|
|
9
|
-
import { InkKitError, } from './types.js';
|
|
10
|
-
const styles = `
|
|
11
|
-
:root { color-scheme: light; font: 11pt/1.5 Arial, sans-serif; }
|
|
12
|
-
html, body { margin: 0; padding: 0; height: auto; overflow: visible; background: white; color: #222; }
|
|
13
|
-
.inkkit-print-document { padding: 1rem; overflow-wrap: anywhere; }
|
|
14
|
-
h1, h2, h3, h4, h5, h6 { line-height: 1.25; break-after: avoid; }
|
|
15
|
-
p, ul, ol, blockquote, pre, table, figure { margin-block: 0 1em; }
|
|
16
|
-
li > p { margin-bottom: .35em; }
|
|
17
|
-
li > ul, li > ol { margin-bottom: .35em; }
|
|
18
|
-
a { color: inherit; text-decoration: underline; }
|
|
19
|
-
mark { color: inherit; background: #fff0a8; print-color-adjust: exact; }
|
|
20
|
-
code, pre { font-family: ui-monospace, Menlo, monospace; }
|
|
21
|
-
pre { white-space: pre-wrap; overflow-wrap: anywhere; overflow: visible; padding: .65em; border: 1px solid #ddd; font-size: .9em; }
|
|
22
|
-
.inkkit-print-literal { padding: 0; border: 0; font-size: 1em; tab-size: 4; }
|
|
23
|
-
blockquote { margin-inline: 0; padding-inline-start: 1em; border-inline-start: 3px solid #aaa; }
|
|
24
|
-
.inkkit-callout { padding: .65em 1em; border-inline-start: 3px solid #777; }
|
|
25
|
-
.inkkit-callout-title { display: block; margin-bottom: .4em; }
|
|
26
|
-
.inkkit-callout-body { display: block; }
|
|
27
|
-
.inkkit-print-footnote { border-inline-start: 2px solid #aaa; padding-inline-start: 1em; margin-bottom: 1em; }
|
|
28
|
-
sup { font-size: .75em; }
|
|
29
|
-
.inkkit-print-task-marker { font-family: ui-monospace, Menlo, monospace; }
|
|
30
|
-
table { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: .95em; }
|
|
31
|
-
th, td { border: 1px solid #aaa; padding: .4em .6em; vertical-align: top; overflow-wrap: anywhere; }
|
|
32
|
-
th { font-weight: bold; }
|
|
33
|
-
th p, td p { margin: 0; }
|
|
34
|
-
thead { display: table-header-group; }
|
|
35
|
-
tfoot { display: table-footer-group; }
|
|
36
|
-
tr { break-inside: avoid; }
|
|
37
|
-
img { max-width: 100%; height: auto; }
|
|
38
|
-
figure { margin-inline: 0; }
|
|
39
|
-
.inkkit-print-diagram img { display: block; }
|
|
40
|
-
figure, img { break-inside: avoid; }
|
|
41
|
-
hr { border: 0; border-top: 1px solid #aaa; }
|
|
42
|
-
@page { margin: 18mm; }
|
|
43
|
-
@media print {
|
|
44
|
-
.inkkit-print-document { padding: 0; }
|
|
45
|
-
img { max-height: 90vh; object-fit: contain; }
|
|
46
|
-
}
|
|
47
|
-
`.trim();
|
|
48
|
-
function documentOutput(content, assets = [], warnings = []) {
|
|
49
|
-
const page = document.implementation.createHTMLDocument('');
|
|
50
|
-
page.head.textContent = '';
|
|
51
|
-
const charset = page.createElement('meta');
|
|
52
|
-
charset.setAttribute('charset', 'utf-8');
|
|
53
|
-
const style = page.createElement('style');
|
|
54
|
-
style.textContent = styles;
|
|
55
|
-
page.head.append(charset, style);
|
|
56
|
-
const main = page.createElement('main');
|
|
57
|
-
main.className = 'inkkit-print-document';
|
|
58
|
-
while (content.firstChild)
|
|
59
|
-
main.appendChild(content.firstChild);
|
|
60
|
-
page.body.append(main);
|
|
61
|
-
return {
|
|
62
|
-
html: '<!DOCTYPE html>\n' + page.documentElement.outerHTML,
|
|
63
|
-
styles,
|
|
64
|
-
assets,
|
|
65
|
-
warnings,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
export function printableText(text) {
|
|
69
|
-
const container = document.createElement('div');
|
|
70
|
-
const pre = document.createElement('pre');
|
|
71
|
-
pre.className = 'inkkit-print-literal';
|
|
72
|
-
pre.textContent = text;
|
|
73
|
-
container.append(pre);
|
|
74
|
-
return documentOutput(container);
|
|
75
|
-
}
|
|
76
|
-
export function hasAuthoredImagesInLiterals(content, parse) {
|
|
77
|
-
const hasImage = (value) => {
|
|
78
|
-
if (!value || typeof value !== 'object')
|
|
79
|
-
return false;
|
|
80
|
-
const node = value;
|
|
81
|
-
if (node.type === 'image')
|
|
82
|
-
return true;
|
|
83
|
-
if (['html', 'code', 'inlineCode', 'imageReference'].includes(String(node.type)))
|
|
84
|
-
return false;
|
|
85
|
-
return Array.isArray(node.children) && node.children.some(hasImage);
|
|
86
|
-
};
|
|
87
|
-
let found = false;
|
|
88
|
-
shareableFragment(content).descendants((node) => {
|
|
89
|
-
if (found)
|
|
90
|
-
return false;
|
|
91
|
-
if (node.type.name !== 'literal_markdown')
|
|
92
|
-
return true;
|
|
93
|
-
const source = node.textContent.replace(/^\uFEFF/, '');
|
|
94
|
-
const body = source.slice(sourceFrontmatter(source)?.length ?? 0);
|
|
95
|
-
if (body && hasImage(parse(body)))
|
|
96
|
-
found = true;
|
|
97
|
-
return false;
|
|
98
|
-
});
|
|
99
|
-
return found;
|
|
100
|
-
}
|
|
101
|
-
function matchesSignature(bytes, mimeType) {
|
|
102
|
-
const ascii = (start, end) => String.fromCharCode(...bytes.subarray(start, end));
|
|
103
|
-
switch (mimeType) {
|
|
104
|
-
case 'image/png':
|
|
105
|
-
return (bytes.length >= 24 &&
|
|
106
|
-
[137, 80, 78, 71, 13, 10, 26, 10].every((byte, index) => bytes[index] === byte) &&
|
|
107
|
-
ascii(12, 16) === 'IHDR');
|
|
108
|
-
case 'image/jpeg':
|
|
109
|
-
return (bytes.length >= 4 &&
|
|
110
|
-
bytes[0] === 255 &&
|
|
111
|
-
bytes[1] === 216 &&
|
|
112
|
-
bytes[2] === 255);
|
|
113
|
-
case 'image/gif':
|
|
114
|
-
return bytes.length >= 10 && /^(GIF87a|GIF89a)$/.test(ascii(0, 6));
|
|
115
|
-
case 'image/webp':
|
|
116
|
-
return (bytes.length >= 12 && ascii(0, 4) === 'RIFF' && ascii(8, 12) === 'WEBP');
|
|
117
|
-
case 'image/avif':
|
|
118
|
-
return (bytes.length >= 16 &&
|
|
119
|
-
ascii(4, 8) === 'ftyp' &&
|
|
120
|
-
/avif|avis/.test(ascii(8, 32)));
|
|
121
|
-
case 'image/bmp':
|
|
122
|
-
return bytes.length >= 26 && ascii(0, 2) === 'BM';
|
|
123
|
-
case 'image/tiff':
|
|
124
|
-
return (bytes.length >= 8 &&
|
|
125
|
-
(ascii(0, 4) === 'II*\0' || ascii(0, 4) === 'MM\0*'));
|
|
126
|
-
default:
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
async function validatedImage(input, signal) {
|
|
131
|
-
signal.throwIfAborted();
|
|
132
|
-
const image = {
|
|
133
|
-
bytes: new Uint8Array(input.bytes),
|
|
134
|
-
mimeType: input.mimeType.toLowerCase(),
|
|
135
|
-
};
|
|
136
|
-
if (!matchesSignature(image.bytes, image.mimeType))
|
|
137
|
-
throw new Error('The portable image bytes do not match a supported image format.');
|
|
138
|
-
const url = URL.createObjectURL(new Blob([image.bytes], { type: image.mimeType }));
|
|
139
|
-
try {
|
|
140
|
-
await new Promise((resolve, reject) => {
|
|
141
|
-
const decoder = new Image();
|
|
142
|
-
const timeout = setTimeout(() => {
|
|
143
|
-
decoder.src = '';
|
|
144
|
-
finish(new Error('The portable image could not be decoded.'));
|
|
145
|
-
}, 10000);
|
|
146
|
-
const finish = (error) => {
|
|
147
|
-
clearTimeout(timeout);
|
|
148
|
-
decoder.onload = decoder.onerror = null;
|
|
149
|
-
signal.removeEventListener('abort', cancelled);
|
|
150
|
-
if (error)
|
|
151
|
-
reject(error);
|
|
152
|
-
else
|
|
153
|
-
resolve();
|
|
154
|
-
};
|
|
155
|
-
const cancelled = () => {
|
|
156
|
-
decoder.src = '';
|
|
157
|
-
finish(new DOMException('Image export cancelled', 'AbortError'));
|
|
158
|
-
};
|
|
159
|
-
signal.addEventListener('abort', cancelled, { once: true });
|
|
160
|
-
decoder.onload = () => finish(decoder.naturalWidth > 0 && decoder.naturalHeight > 0
|
|
161
|
-
? undefined
|
|
162
|
-
: new Error('The portable image has no usable dimensions.'));
|
|
163
|
-
decoder.onerror = () => finish(new Error('The portable image could not be decoded.'));
|
|
164
|
-
decoder.src = url;
|
|
165
|
-
});
|
|
166
|
-
return image;
|
|
167
|
-
}
|
|
168
|
-
finally {
|
|
169
|
-
URL.revokeObjectURL(url);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
function dataURL(image) {
|
|
173
|
-
let binary = '';
|
|
174
|
-
for (const byte of image.bytes)
|
|
175
|
-
binary += String.fromCharCode(byte);
|
|
176
|
-
return `data:${image.mimeType};base64,${btoa(binary)}`;
|
|
177
|
-
}
|
|
178
|
-
const semanticTags = new Set([
|
|
179
|
-
'DIV',
|
|
180
|
-
'P',
|
|
181
|
-
'SPAN',
|
|
182
|
-
'STRONG',
|
|
183
|
-
'EM',
|
|
184
|
-
'DEL',
|
|
185
|
-
'S',
|
|
186
|
-
'MARK',
|
|
187
|
-
'A',
|
|
188
|
-
'SUP',
|
|
189
|
-
'SUB',
|
|
190
|
-
'PRE',
|
|
191
|
-
'CODE',
|
|
192
|
-
'BLOCKQUOTE',
|
|
193
|
-
'H1',
|
|
194
|
-
'H2',
|
|
195
|
-
'H3',
|
|
196
|
-
'H4',
|
|
197
|
-
'H5',
|
|
198
|
-
'H6',
|
|
199
|
-
'UL',
|
|
200
|
-
'OL',
|
|
201
|
-
'LI',
|
|
202
|
-
'TABLE',
|
|
203
|
-
'THEAD',
|
|
204
|
-
'TBODY',
|
|
205
|
-
'TFOOT',
|
|
206
|
-
'TR',
|
|
207
|
-
'TH',
|
|
208
|
-
'TD',
|
|
209
|
-
'HR',
|
|
210
|
-
'BR',
|
|
211
|
-
'IMG',
|
|
212
|
-
'FIGURE',
|
|
213
|
-
'FIGCAPTION',
|
|
214
|
-
]);
|
|
215
|
-
const printClasses = new Set([
|
|
216
|
-
'inkkit-callout',
|
|
217
|
-
'inkkit-callout-title',
|
|
218
|
-
'inkkit-callout-body',
|
|
219
|
-
'inkkit-print-footnote',
|
|
220
|
-
'inkkit-print-task-marker',
|
|
221
|
-
'inkkit-print-diagram',
|
|
222
|
-
]);
|
|
223
|
-
function safeLink(value) {
|
|
224
|
-
if (value.includes('\\') || !isSafeLinkTarget(value))
|
|
225
|
-
return undefined;
|
|
226
|
-
const href = value.trim();
|
|
227
|
-
if (!href)
|
|
228
|
-
return undefined;
|
|
229
|
-
return href.replaceAll(' ', '%20');
|
|
230
|
-
}
|
|
231
|
-
function cleanSemantics(container, localIDs) {
|
|
232
|
-
for (const element of container.querySelectorAll('*')) {
|
|
233
|
-
if (!semanticTags.has(element.tagName)) {
|
|
234
|
-
if (/^(SCRIPT|STYLE|LINK|META|IFRAME|OBJECT|EMBED|BUTTON|INPUT|TEXTAREA|SELECT)$/.test(element.tagName))
|
|
235
|
-
element.remove();
|
|
236
|
-
else
|
|
237
|
-
element.replaceWith(...Array.from(element.childNodes));
|
|
238
|
-
continue;
|
|
239
|
-
}
|
|
240
|
-
const classes = Array.from(element.classList).filter((name) => printClasses.has(name));
|
|
241
|
-
const href = element.tagName === 'A' ? element.getAttribute('href') : null;
|
|
242
|
-
const src = element.tagName === 'IMG' ? element.getAttribute('src') : null;
|
|
243
|
-
const alt = element.tagName === 'IMG' ? element.getAttribute('alt') : null;
|
|
244
|
-
const width = element.tagName === 'IMG' ? element.getAttribute('width') : null;
|
|
245
|
-
const title = element.getAttribute('title');
|
|
246
|
-
const id = element.getAttribute('id');
|
|
247
|
-
const order = element.tagName === 'OL' ? element.getAttribute('start') : null;
|
|
248
|
-
const alignment = element instanceof HTMLElement ? element.style.textAlign : '';
|
|
249
|
-
for (const attribute of [...element.attributes])
|
|
250
|
-
element.removeAttribute(attribute.name);
|
|
251
|
-
if (classes.length)
|
|
252
|
-
element.setAttribute('class', classes.join(' '));
|
|
253
|
-
const destination = href == null ? undefined : safeLink(href);
|
|
254
|
-
if (destination != null)
|
|
255
|
-
element.setAttribute('href', destination);
|
|
256
|
-
if (src &&
|
|
257
|
-
/^data:image\/(png|jpeg|gif|webp|avif|bmp|tiff);base64,[A-Za-z0-9+/=]+$/.test(src))
|
|
258
|
-
element.setAttribute('src', src);
|
|
259
|
-
if (alt != null)
|
|
260
|
-
element.setAttribute('alt', alt);
|
|
261
|
-
if (width && /^\d+$/.test(width))
|
|
262
|
-
element.setAttribute('width', width);
|
|
263
|
-
if (title)
|
|
264
|
-
element.setAttribute('title', title);
|
|
265
|
-
if (id && localIDs.has(id))
|
|
266
|
-
element.setAttribute('id', id);
|
|
267
|
-
if (order && /^\d+$/.test(order))
|
|
268
|
-
element.setAttribute('start', order);
|
|
269
|
-
if (/^(left|center|right)$/.test(alignment) &&
|
|
270
|
-
/^(TH|TD)$/.test(element.tagName))
|
|
271
|
-
element.setAttribute('style', `text-align: ${alignment}`);
|
|
272
|
-
}
|
|
273
|
-
const walker = document.createTreeWalker(container, NodeFilter.SHOW_COMMENT);
|
|
274
|
-
const comments = [];
|
|
275
|
-
while (walker.nextNode())
|
|
276
|
-
comments.push(walker.currentNode);
|
|
277
|
-
for (const comment of comments)
|
|
278
|
-
comment.parentNode?.removeChild(comment);
|
|
279
|
-
}
|
|
280
|
-
export async function printableMarkdown(content, schema, adapter, context, files, signal = new AbortController().signal) {
|
|
281
|
-
signal.throwIfAborted();
|
|
282
|
-
content = shareableFragment(content);
|
|
283
|
-
const container = document.createElement('div');
|
|
284
|
-
container.innerHTML = clipboardContent(content, schema).html;
|
|
285
|
-
const references = [];
|
|
286
|
-
const tasks = [];
|
|
287
|
-
content.descendants((node) => {
|
|
288
|
-
if (node.type.name === 'image')
|
|
289
|
-
references.push(node);
|
|
290
|
-
if (node.type.name === 'list_item')
|
|
291
|
-
tasks.push(node.attrs.checked ?? null);
|
|
292
|
-
});
|
|
293
|
-
for (const [index, item] of [...container.querySelectorAll('li')].entries()) {
|
|
294
|
-
if (tasks[index] == null)
|
|
295
|
-
continue;
|
|
296
|
-
const marker = document.createElement('span');
|
|
297
|
-
marker.className = 'inkkit-print-task-marker';
|
|
298
|
-
marker.textContent = tasks[index] ? '[x] ' : '[ ] ';
|
|
299
|
-
(item.firstElementChild?.tagName === 'P'
|
|
300
|
-
? item.firstElementChild
|
|
301
|
-
: item).prepend(marker);
|
|
302
|
-
}
|
|
303
|
-
const footnotes = new Map();
|
|
304
|
-
const localIDs = new Set();
|
|
305
|
-
for (const [index, definition] of [
|
|
306
|
-
...container.querySelectorAll('[data-inkkit-footnote-definition]'),
|
|
307
|
-
].entries()) {
|
|
308
|
-
const identifier = definition.getAttribute('data-inkkit-footnote-definition');
|
|
309
|
-
const id = `inkkit-print-note-${index + 1}`;
|
|
310
|
-
localIDs.add(id);
|
|
311
|
-
if (!footnotes.has(identifier))
|
|
312
|
-
footnotes.set(identifier, id);
|
|
313
|
-
definition.setAttribute('id', id);
|
|
314
|
-
definition.className = 'inkkit-print-footnote';
|
|
315
|
-
}
|
|
316
|
-
for (const reference of container.querySelectorAll('[data-inkkit-footnote-reference]')) {
|
|
317
|
-
const id = footnotes.get(reference.getAttribute('data-inkkit-footnote-reference'));
|
|
318
|
-
if (!id)
|
|
319
|
-
continue;
|
|
320
|
-
const link = document.createElement('a');
|
|
321
|
-
link.setAttribute('href', `#${id}`);
|
|
322
|
-
link.textContent = reference.textContent;
|
|
323
|
-
reference.replaceChildren(link);
|
|
324
|
-
}
|
|
325
|
-
const images = new Map();
|
|
326
|
-
const warnings = [];
|
|
327
|
-
for (const [index, element] of [
|
|
328
|
-
...container.querySelectorAll('img'),
|
|
329
|
-
].entries()) {
|
|
330
|
-
const node = references[index];
|
|
331
|
-
try {
|
|
332
|
-
if (!node)
|
|
333
|
-
throw new Error('The authored image is unavailable.');
|
|
334
|
-
const reference = fileReference(node);
|
|
335
|
-
const file = files
|
|
336
|
-
? await portableFile(node, files, context, signal)
|
|
337
|
-
: undefined;
|
|
338
|
-
if (file && file.presentation.kind !== 'image') {
|
|
339
|
-
const fallback = document.createElement('span');
|
|
340
|
-
fallback.textContent = file.description;
|
|
341
|
-
element.replaceWith(fallback);
|
|
342
|
-
const unavailable = file.presentation.kind === 'missing' ||
|
|
343
|
-
file.presentation.kind === 'error';
|
|
344
|
-
warnings.push({
|
|
345
|
-
code: unavailable ? 'attachment-unavailable' : 'attachment-fallback',
|
|
346
|
-
message: unavailable
|
|
347
|
-
? `${file.label} is unavailable; its description is printed.`
|
|
348
|
-
: `${file.label} is printed as a ${file.presentation.kind === 'pdf' ? 'PDF' : file.presentation.kind} description.`,
|
|
349
|
-
});
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
if (!file && !adapter)
|
|
353
|
-
throw new Error('The authored image is unavailable.');
|
|
354
|
-
const image = await validatedImage(file
|
|
355
|
-
? await portableFileImage(file, files, adapter, context, signal)
|
|
356
|
-
: await withFileSignal(adapter.exportImage(reference.reference, { ...context }), signal), signal);
|
|
357
|
-
signal.throwIfAborted();
|
|
358
|
-
images.set(element, image);
|
|
359
|
-
element.setAttribute('src', dataURL(image));
|
|
360
|
-
element.setAttribute('alt', file?.label || reference.label || '');
|
|
361
|
-
if (reference.width != null && reference.width > 0)
|
|
362
|
-
element.setAttribute('width', String(Math.min(4096, reference.width)));
|
|
363
|
-
}
|
|
364
|
-
catch (error) {
|
|
365
|
-
signal.throwIfAborted();
|
|
366
|
-
throw new InkKitError('image-unavailable', error instanceof Error
|
|
367
|
-
? error.message
|
|
368
|
-
: 'The authored image is unavailable.');
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
for (const code of container.querySelectorAll('pre[data-language="mermaid"] > code')) {
|
|
372
|
-
const source = code.textContent ?? '';
|
|
373
|
-
try {
|
|
374
|
-
await withFileSignal(renderDiagram(source), signal);
|
|
375
|
-
}
|
|
376
|
-
catch (error) {
|
|
377
|
-
signal.throwIfAborted();
|
|
378
|
-
const message = `${error instanceof Error ? error.message : 'This diagram could not be rendered.'} The source is printed below.`;
|
|
379
|
-
warnings.push({ code: 'diagram-unavailable', message });
|
|
380
|
-
const warning = document.createElement('p');
|
|
381
|
-
warning.textContent = message;
|
|
382
|
-
code.parentElement.before(warning);
|
|
383
|
-
continue;
|
|
384
|
-
}
|
|
385
|
-
try {
|
|
386
|
-
const image = await validatedImage(await withFileSignal(diagramImage(source), signal), signal);
|
|
387
|
-
const figure = document.createElement('figure');
|
|
388
|
-
figure.className = 'inkkit-print-diagram';
|
|
389
|
-
const element = document.createElement('img');
|
|
390
|
-
element.setAttribute('src', dataURL(image));
|
|
391
|
-
element.setAttribute('alt', 'Mermaid diagram');
|
|
392
|
-
figure.append(element);
|
|
393
|
-
images.set(element, image);
|
|
394
|
-
code.parentElement.replaceWith(figure);
|
|
395
|
-
}
|
|
396
|
-
catch (error) {
|
|
397
|
-
throw new InkKitError('diagram-unavailable', error instanceof Error
|
|
398
|
-
? error.message
|
|
399
|
-
: 'The diagram image is unavailable.');
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
cleanSemantics(container, localIDs);
|
|
403
|
-
const assets = [...container.querySelectorAll('img')].map((element) => images.get(element));
|
|
404
|
-
signal.throwIfAborted();
|
|
405
|
-
return documentOutput(container, assets, warnings);
|
|
406
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { Ctx } from '@milkdown/kit/ctx';
|
|
2
|
-
import { Fragment, type Node } from '@milkdown/kit/prose/model';
|
|
3
|
-
export declare function selectionContent(doc: Node, content: Fragment): Fragment;
|
|
4
|
-
export declare function selectionMarkdown(ctx: Ctx, doc: Node, content: Fragment): string;
|
|
5
|
-
export declare function referenceMetadata(ctx: Ctx, doc: Node, content: Fragment): string | undefined;
|
|
6
|
-
export declare function avoidReferenceCollisions(incoming: Node, destination: Node): Node;
|
|
7
|
-
export declare function markdownFromHTML(html: string): string | undefined;
|
|
8
|
-
export declare function withReferenceMetadata(html: string, markdown: string): string;
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import { Fragment } from '@milkdown/kit/prose/model';
|
|
2
|
-
import { serialize } from './dialect.js';
|
|
3
|
-
import { normaliseLabel } from './references.js';
|
|
4
|
-
import { shareableFragment } from './comments.js';
|
|
5
|
-
function key(node) {
|
|
6
|
-
if (node.type.name === 'reference_definition')
|
|
7
|
-
return `link:${node.attrs.identifier}`;
|
|
8
|
-
if (node.type.name === 'footnote_definition')
|
|
9
|
-
return `footnote:${node.attrs.identifier}`;
|
|
10
|
-
return undefined;
|
|
11
|
-
}
|
|
12
|
-
function used(content) {
|
|
13
|
-
const result = new Set();
|
|
14
|
-
content.descendants((node) => {
|
|
15
|
-
if (node.type.name === 'footnote_reference')
|
|
16
|
-
result.add(`footnote:${node.attrs.identifier}`);
|
|
17
|
-
for (const mark of node.marks)
|
|
18
|
-
if (mark.type.name === 'link' && mark.attrs.identifier)
|
|
19
|
-
result.add(`link:${mark.attrs.identifier}`);
|
|
20
|
-
});
|
|
21
|
-
return result;
|
|
22
|
-
}
|
|
23
|
-
export function selectionContent(doc, content) {
|
|
24
|
-
const definitions = new Map();
|
|
25
|
-
doc.descendants((node) => {
|
|
26
|
-
const id = key(node);
|
|
27
|
-
if (id && !definitions.has(id))
|
|
28
|
-
definitions.set(id, node);
|
|
29
|
-
});
|
|
30
|
-
const required = used(content);
|
|
31
|
-
for (const id of required) {
|
|
32
|
-
const definition = definitions.get(id);
|
|
33
|
-
if (definition)
|
|
34
|
-
for (const dependency of used(definition.content))
|
|
35
|
-
required.add(dependency);
|
|
36
|
-
}
|
|
37
|
-
const complete = (node) => {
|
|
38
|
-
const id = key(node);
|
|
39
|
-
if (id && required.has(id) && definitions.has(id))
|
|
40
|
-
return definitions.get(id);
|
|
41
|
-
if (node.isText)
|
|
42
|
-
return node;
|
|
43
|
-
const children = [];
|
|
44
|
-
node.forEach((child) => children.push(complete(child)));
|
|
45
|
-
return node.copy(Fragment.fromArray(children));
|
|
46
|
-
};
|
|
47
|
-
const selected = [];
|
|
48
|
-
content.forEach((node) => selected.push(complete(node)));
|
|
49
|
-
content = Fragment.fromArray(selected);
|
|
50
|
-
const included = new Set();
|
|
51
|
-
content.descendants((node) => {
|
|
52
|
-
const id = key(node);
|
|
53
|
-
if (id)
|
|
54
|
-
included.add(id);
|
|
55
|
-
});
|
|
56
|
-
const extra = [];
|
|
57
|
-
for (const id of required) {
|
|
58
|
-
if (included.has(id))
|
|
59
|
-
continue;
|
|
60
|
-
const definition = definitions.get(id);
|
|
61
|
-
if (!definition)
|
|
62
|
-
continue;
|
|
63
|
-
included.add(id);
|
|
64
|
-
extra.push(definition);
|
|
65
|
-
for (const dependency of used(definition.content))
|
|
66
|
-
required.add(dependency);
|
|
67
|
-
}
|
|
68
|
-
return content.append(Fragment.fromArray(extra));
|
|
69
|
-
}
|
|
70
|
-
export function selectionMarkdown(ctx, doc, content) {
|
|
71
|
-
return serialize(ctx, doc.type.create(null, selectionContent(doc, content)));
|
|
72
|
-
}
|
|
73
|
-
export function referenceMetadata(ctx, doc, content) {
|
|
74
|
-
doc = doc.copy(shareableFragment(doc.content));
|
|
75
|
-
content = shareableFragment(content);
|
|
76
|
-
let references = false, index = 0;
|
|
77
|
-
const rewrite = (node) => {
|
|
78
|
-
if (key(node) ||
|
|
79
|
-
node.type.name === 'footnote_reference' ||
|
|
80
|
-
node.marks.some((mark) => mark.type.name === 'link' && mark.attrs.identifier))
|
|
81
|
-
references = true;
|
|
82
|
-
if (node.type.name === 'image')
|
|
83
|
-
return node.type.create({ ...node.attrs, src: `inkkit-clipboard-image:${index++}` }, null, node.marks);
|
|
84
|
-
if (node.isText)
|
|
85
|
-
return node;
|
|
86
|
-
const children = [];
|
|
87
|
-
node.forEach((child) => children.push(rewrite(child)));
|
|
88
|
-
return node.copy(Fragment.fromArray(children));
|
|
89
|
-
};
|
|
90
|
-
const valid = content.firstChild?.isInline
|
|
91
|
-
? Fragment.from(doc.type.schema.nodes.paragraph.create(null, content))
|
|
92
|
-
: content;
|
|
93
|
-
const copied = rewrite(doc.type.create(null, selectionContent(doc, valid)));
|
|
94
|
-
return references ? serialize(ctx, copied) : undefined;
|
|
95
|
-
}
|
|
96
|
-
function allLabels(doc) {
|
|
97
|
-
const labels = new Map([
|
|
98
|
-
['link', new Set()],
|
|
99
|
-
['footnote', new Set()],
|
|
100
|
-
]);
|
|
101
|
-
doc.descendants((node) => {
|
|
102
|
-
if (isCode(node))
|
|
103
|
-
return false;
|
|
104
|
-
const id = key(node);
|
|
105
|
-
if (id) {
|
|
106
|
-
const separator = id.indexOf(':');
|
|
107
|
-
labels.get(id.slice(0, separator)).add(id.slice(separator + 1));
|
|
108
|
-
}
|
|
109
|
-
if (node.type.name === 'footnote_reference')
|
|
110
|
-
labels.get('footnote').add(node.attrs.identifier);
|
|
111
|
-
for (const mark of node.marks)
|
|
112
|
-
if (mark.type.name === 'link' && mark.attrs.identifier)
|
|
113
|
-
labels.get('link').add(mark.attrs.identifier);
|
|
114
|
-
if (node.isText) {
|
|
115
|
-
for (const match of node.text.matchAll(rawReferences))
|
|
116
|
-
labels
|
|
117
|
-
.get(match[1].startsWith('^') ? 'footnote' : 'link')
|
|
118
|
-
.add(normaliseLabel(match[1].startsWith('^')
|
|
119
|
-
? match[1].slice(1)
|
|
120
|
-
: match[2] || match[1]));
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
return labels;
|
|
124
|
-
}
|
|
125
|
-
const rawReferences = /(?<![\\!])\[([^\]]+)\](?:\[([^\]]*)\])?(?!\()/g;
|
|
126
|
-
function isCode(node) {
|
|
127
|
-
return (node.type.name.startsWith('comment_') ||
|
|
128
|
-
node.type.name === 'code_block' ||
|
|
129
|
-
node.marks.some((mark) => mark.type.name === 'inlineCode'));
|
|
130
|
-
}
|
|
131
|
-
// Rename only the incoming document. Definitions belong to the insertion's undo transaction.
|
|
132
|
-
export function avoidReferenceCollisions(incoming, destination) {
|
|
133
|
-
const occupied = allLabels(destination);
|
|
134
|
-
const incomingLabels = allLabels(incoming);
|
|
135
|
-
const replacements = new Map();
|
|
136
|
-
for (const [kind, labels] of incomingLabels) {
|
|
137
|
-
const reserved = new Set([...occupied.get(kind), ...labels]);
|
|
138
|
-
for (const identifier of labels) {
|
|
139
|
-
if (!occupied.get(kind).has(identifier))
|
|
140
|
-
continue;
|
|
141
|
-
let suffix = 2;
|
|
142
|
-
while (reserved.has(normaliseLabel(`${identifier}-${suffix}`)))
|
|
143
|
-
suffix++;
|
|
144
|
-
const label = `${identifier}-${suffix}`;
|
|
145
|
-
reserved.add(normaliseLabel(label));
|
|
146
|
-
replacements.set(`${kind}:${identifier}`, label);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
if (!replacements.size)
|
|
150
|
-
return incoming;
|
|
151
|
-
const rewrite = (node) => {
|
|
152
|
-
if (isCode(node))
|
|
153
|
-
return node;
|
|
154
|
-
const kind = node.type.name.startsWith('footnote_') ? 'footnote' : 'link';
|
|
155
|
-
const label = replacements.get(`${kind}:${node.attrs.identifier}`);
|
|
156
|
-
const attrs = label
|
|
157
|
-
? { ...node.attrs, label, identifier: normaliseLabel(label) }
|
|
158
|
-
: node.attrs;
|
|
159
|
-
const marks = node.marks.map((mark) => {
|
|
160
|
-
const replacement = replacements.get(`link:${mark.attrs.identifier}`);
|
|
161
|
-
return replacement && mark.type.name === 'link'
|
|
162
|
-
? mark.type.create({
|
|
163
|
-
...mark.attrs,
|
|
164
|
-
label: replacement,
|
|
165
|
-
identifier: normaliseLabel(replacement),
|
|
166
|
-
referenceType: 'full',
|
|
167
|
-
})
|
|
168
|
-
: mark;
|
|
169
|
-
});
|
|
170
|
-
if (node.isText) {
|
|
171
|
-
const text = node.text.replace(rawReferences, (raw, display, reference) => {
|
|
172
|
-
const footnote = display.startsWith('^')
|
|
173
|
-
? display.slice(1)
|
|
174
|
-
: undefined;
|
|
175
|
-
const replacement = replacements.get(`${footnote ? 'footnote' : 'link'}:${normaliseLabel(footnote ?? (reference || display))}`);
|
|
176
|
-
return replacement
|
|
177
|
-
? footnote
|
|
178
|
-
? `[^${replacement}]`
|
|
179
|
-
: `[${display}][${replacement}]`
|
|
180
|
-
: raw;
|
|
181
|
-
});
|
|
182
|
-
return node.type.schema.text(text, marks);
|
|
183
|
-
}
|
|
184
|
-
const children = [];
|
|
185
|
-
node.forEach((child) => children.push(rewrite(child)));
|
|
186
|
-
return node.type.create(attrs, children, marks);
|
|
187
|
-
};
|
|
188
|
-
return rewrite(incoming);
|
|
189
|
-
}
|
|
190
|
-
export function markdownFromHTML(html) {
|
|
191
|
-
const template = document.createElement('template');
|
|
192
|
-
template.innerHTML = html;
|
|
193
|
-
const element = template.content.querySelector('[data-inkkit-markdown]');
|
|
194
|
-
return element?.getAttribute('data-inkkit-markdown') ?? undefined;
|
|
195
|
-
}
|
|
196
|
-
export function withReferenceMetadata(html, markdown) {
|
|
197
|
-
const container = document.createElement('div');
|
|
198
|
-
container.setAttribute('data-inkkit-markdown', markdown);
|
|
199
|
-
container.innerHTML = html;
|
|
200
|
-
return container.outerHTML;
|
|
201
|
-
}
|
package/dist/references.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { Node as ProseNode } from '@milkdown/kit/prose/model';
|
|
2
|
-
export declare function normaliseLabel(label: string): string;
|
|
3
|
-
export interface LocatedDefinition {
|
|
4
|
-
node: ProseNode;
|
|
5
|
-
pos: number;
|
|
6
|
-
}
|
|
7
|
-
export declare const referenceDefinitions: (doc: ProseNode) => Map<string, LocatedDefinition>;
|
|
8
|
-
export declare const footnoteDefinitions: (doc: ProseNode) => Map<string, LocatedDefinition>;
|
|
9
|
-
/** Replaces each line break, with the whitespace around it, by one space. */
|
|
10
|
-
export declare function singleLine(value: string): string;
|
|
11
|
-
export declare const remarkReferencesPlugin: import("@milkdown/kit/utils").$Remark<"inkkitReferences", unknown>;
|
|
12
|
-
export declare const referenceLinks: import("@milkdown/kit/utils").$MarkSchema<"link">;
|
|
13
|
-
export declare const referenceDefinition: import("@milkdown/kit/utils").$Node;
|
|
14
|
-
export declare const footnoteReference: import("@milkdown/kit/utils").$Node;
|
|
15
|
-
export declare const footnoteDefinition: import("@milkdown/kit/utils").$Node;
|
|
16
|
-
export declare const references: (import("@milkdown/kit/utils").$Ctx<import("@milkdown/kit/utils").GetMarkSchema, "link"> | import("@milkdown/kit/utils").$Mark | import("@milkdown/kit/utils").$Node | import("@milkdown/kit/utils").$Prose)[];
|