@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.
Files changed (90) hide show
  1. package/NOTICE +4 -2
  2. package/README.md +11 -7
  3. package/dist/THIRD-PARTY-NOTICES.txt +2742 -0
  4. package/dist/chunks/core-CYp5ONPO.js +56519 -0
  5. package/dist/chunks/highlight-BW9W8PtS.js +14122 -0
  6. package/dist/core.d.ts +2 -5
  7. package/dist/core.js +2 -2
  8. package/dist/editor.d.ts +229 -47
  9. package/dist/index.js +5 -3
  10. package/dist/style.css +231 -202
  11. package/dist/types.d.ts +143 -18
  12. package/package.json +16 -13
  13. package/dist/autolink.d.ts +0 -1
  14. package/dist/autolink.js +0 -18
  15. package/dist/callouts.d.ts +0 -25
  16. package/dist/callouts.js +0 -288
  17. package/dist/clipboard.d.ts +0 -11
  18. package/dist/clipboard.js +0 -261
  19. package/dist/code-fences.d.ts +0 -8
  20. package/dist/code-fences.js +0 -171
  21. package/dist/comments.d.ts +0 -76
  22. package/dist/comments.js +0 -545
  23. package/dist/cursor.d.ts +0 -2
  24. package/dist/cursor.js +0 -40
  25. package/dist/decorations.d.ts +0 -2
  26. package/dist/decorations.js +0 -67
  27. package/dist/dialect.d.ts +0 -9
  28. package/dist/dialect.js +0 -446
  29. package/dist/drop-placement.d.ts +0 -19
  30. package/dist/drop-placement.js +0 -47
  31. package/dist/editor.js +0 -2673
  32. package/dist/files.d.ts +0 -40
  33. package/dist/files.js +0 -133
  34. package/dist/highlight.d.ts +0 -1
  35. package/dist/highlight.js +0 -136
  36. package/dist/html-import.d.ts +0 -13
  37. package/dist/html-import.js +0 -477
  38. package/dist/image-blocks.d.ts +0 -86
  39. package/dist/image-blocks.js +0 -329
  40. package/dist/images.d.ts +0 -51
  41. package/dist/images.js +0 -398
  42. package/dist/inline-highlight.d.ts +0 -6
  43. package/dist/inline-highlight.js +0 -112
  44. package/dist/labels.d.ts +0 -36
  45. package/dist/labels.js +0 -34
  46. package/dist/link-safety.d.ts +0 -17
  47. package/dist/link-safety.js +0 -29
  48. package/dist/linked-syntax.d.ts +0 -48
  49. package/dist/linked-syntax.js +0 -320
  50. package/dist/literals.d.ts +0 -20
  51. package/dist/literals.js +0 -216
  52. package/dist/mermaid.d.ts +0 -28
  53. package/dist/mermaid.js +0 -404
  54. package/dist/outline.d.ts +0 -22
  55. package/dist/outline.js +0 -79
  56. package/dist/paste-html.d.ts +0 -31
  57. package/dist/paste-html.js +0 -462
  58. package/dist/paste.d.ts +0 -33
  59. package/dist/paste.js +0 -591
  60. package/dist/portable-files.d.ts +0 -10
  61. package/dist/portable-files.js +0 -36
  62. package/dist/preserve.d.ts +0 -38
  63. package/dist/preserve.js +0 -1396
  64. package/dist/print.d.ts +0 -7
  65. package/dist/print.js +0 -406
  66. package/dist/reference-clipboard.d.ts +0 -8
  67. package/dist/reference-clipboard.js +0 -201
  68. package/dist/references.d.ts +0 -16
  69. package/dist/references.js +0 -418
  70. package/dist/scroll.d.ts +0 -15
  71. package/dist/scroll.js +0 -27
  72. package/dist/search.d.ts +0 -15
  73. package/dist/search.js +0 -202
  74. package/dist/selection.d.ts +0 -1
  75. package/dist/selection.js +0 -59
  76. package/dist/source.d.ts +0 -16
  77. package/dist/source.js +0 -57
  78. package/dist/spreadsheet.d.ts +0 -8
  79. package/dist/spreadsheet.js +0 -289
  80. package/dist/table-alignment.d.ts +0 -2
  81. package/dist/table-alignment.js +0 -46
  82. package/dist/tables.d.ts +0 -27
  83. package/dist/tables.js +0 -344
  84. package/dist/tasks.d.ts +0 -3
  85. package/dist/tasks.js +0 -51
  86. package/dist/text-ranges.d.ts +0 -29
  87. package/dist/text-ranges.js +0 -256
  88. package/dist/types.js +0 -8
  89. package/dist/wiki-view.d.ts +0 -21
  90. package/dist/wiki-view.js +0 -78
package/dist/callouts.js DELETED
@@ -1,288 +0,0 @@
1
- import { $node, $prose, $remark } from '@milkdown/kit/utils';
2
- import { editorLabels } from './labels.js';
3
- import { singleLine } from './references.js';
4
- import { remarkCtx } from '@milkdown/kit/core';
5
- import { Plugin, PluginKey } from '@milkdown/kit/prose/state';
6
- import { defaultHandlers } from 'mdast-util-to-markdown';
7
- const kinds = new Set(['NOTE', 'TIP', 'IMPORTANT', 'WARNING', 'CAUTION']);
8
- export function revealCalloutAncestors(view, position) {
9
- const node = view.domAtPos(position).node;
10
- let element = node instanceof HTMLElement ? node : node.parentElement;
11
- while (element && element !== view.dom) {
12
- if (element.getAttribute('data-inkkit-folded') === 'true')
13
- element
14
- .querySelector(':scope > .inkkit-callout-header > [data-inkkit-callout-toggle]')
15
- ?.click();
16
- element = element.parentElement;
17
- }
18
- }
19
- function plainHeader(processor, source) {
20
- const node = processor.parse(source).children[0];
21
- return node?.type === 'paragraph' &&
22
- node.children.length === 1 &&
23
- node.children[0]?.type === 'text'
24
- ? node.children[0].value
25
- : undefined;
26
- }
27
- const calloutHandler = (untyped, parent, state, info) => {
28
- const node = untyped;
29
- const body = defaultHandlers.blockquote({ type: 'blockquote', children: node.children }, parent, state, info);
30
- const title = node.titleSource ?? node.title;
31
- return `> ${node.marker}${node.fold}${title ? ` ${title}` : ''}\n${body}`;
32
- };
33
- function remarkCallouts() {
34
- const processor = this;
35
- const data = this.data();
36
- (data.toMarkdownExtensions ??= []).push({
37
- handlers: { inkkitCallout: calloutHandler },
38
- });
39
- return (tree, file) => {
40
- const source = String(file.value).replace(/^\uFEFF/, '');
41
- const visit = (node) => {
42
- if (node.type === 'blockquote') {
43
- const start = node.position?.start.offset, end = node.position?.end.offset;
44
- const raw = start == null || end == null ? '' : source.slice(start, end);
45
- const header = /^>[ \t]*([\s\S]*?)(?:\r?\n|$)/.exec(raw)?.[1] ?? '';
46
- if (header.startsWith('[!')) {
47
- const match = /^(\[!([A-Za-z]+)\])([+-]?)(?:[ \t]+([^\r\n]*))?$/.exec(header);
48
- const first = node.children[0];
49
- const decodedHeader = plainHeader(processor, header);
50
- // A bounded header occupies one unformatted line; other variants stay source.
51
- if (!match ||
52
- decodedHeader == null ||
53
- !kinds.has(match[2].toUpperCase()) ||
54
- /^[+-](?:[ \t]|[+-])/.test(match[4] ?? '') ||
55
- first?.type !== 'paragraph' ||
56
- first.children[0]?.type !== 'text')
57
- return {
58
- type: 'inkkitLiteral',
59
- value: raw,
60
- position: node.position,
61
- };
62
- const text = first.children[0];
63
- // Entities can decode to newlines without ending the authored header line.
64
- const ending = /^\r?\n/.exec(text.value.slice(decodedHeader.length));
65
- const lineEnd = ending ? decodedHeader.length : -1;
66
- if (lineEnd < 0 && first.children.length > 1)
67
- return {
68
- type: 'inkkitLiteral',
69
- value: raw,
70
- position: node.position,
71
- };
72
- const children = [...node.children];
73
- if (lineEnd >= 0) {
74
- const remaining = text.value.slice(lineEnd + ending[0].length);
75
- const firstStart = text.position?.start.offset;
76
- const token = firstStart == null
77
- ? ''
78
- : source.slice(firstStart, text.position?.end.offset);
79
- const boundary = /\r?\n[ \t]*>[ \t]?/.exec(token);
80
- const bodyStart = firstStart == null || !boundary
81
- ? undefined
82
- : firstStart + boundary.index + boundary[0].length;
83
- const point = bodyStart == null
84
- ? undefined
85
- : {
86
- line: source.slice(0, bodyStart).split('\n').length,
87
- column: bodyStart - source.lastIndexOf('\n', bodyStart - 1),
88
- offset: bodyStart,
89
- };
90
- children[0] = {
91
- ...first,
92
- children: [
93
- ...(remaining
94
- ? [
95
- {
96
- ...text,
97
- value: remaining,
98
- position: point && text.position
99
- ? { start: point, end: text.position.end }
100
- : undefined,
101
- },
102
- ]
103
- : []),
104
- ...first.children.slice(1),
105
- ],
106
- };
107
- }
108
- else
109
- children.shift();
110
- if (!children.length)
111
- children.push({ type: 'paragraph', children: [] });
112
- return {
113
- type: 'inkkitCallout',
114
- kind: match[2].toUpperCase(),
115
- marker: match[1],
116
- fold: match[3],
117
- title: decodedHeader
118
- .slice(header.length - (match[4]?.length ?? 0))
119
- .trimEnd(),
120
- titleSource: match[4]?.trimEnd() ?? '',
121
- children: children.map((child) => visit(child)),
122
- position: node.position,
123
- };
124
- }
125
- }
126
- if ('children' in node)
127
- node.children = node.children.map((child) => visit(child));
128
- return node;
129
- };
130
- tree.children = tree.children.map((node) => visit(node));
131
- };
132
- }
133
- export const remarkCalloutsPlugin = $remark('inkkitCallouts', () => remarkCallouts);
134
- export const calloutSchema = $node('inkkit_callout', (ctx) => ({
135
- group: 'block',
136
- content: 'block+',
137
- defining: true,
138
- attrs: {
139
- kind: { default: 'NOTE' },
140
- marker: { default: '[!NOTE]' },
141
- fold: { default: '' },
142
- title: { default: '' },
143
- titleSource: { default: null },
144
- },
145
- parseDOM: [
146
- {
147
- tag: 'blockquote[data-inkkit-callout]',
148
- priority: 100,
149
- contentElement: '.inkkit-callout-body',
150
- getAttrs: (dom) => {
151
- const kind = (dom.getAttribute('data-inkkit-callout') ?? '').toUpperCase();
152
- const marker = dom.getAttribute('data-inkkit-marker') ?? `[!${kind}]`;
153
- const fold = dom.getAttribute('data-inkkit-fold') ?? '';
154
- // A title read from the visible text is written with its punctuation
155
- // escaped, so it reads back as the same plain text.
156
- const visibleTitle = singleLine(dom.querySelector('.inkkit-callout-title')?.textContent ?? '').trim();
157
- const titleSource = dom.getAttribute('data-inkkit-title') ??
158
- visibleTitle.replace(/[!-/:-@[-`{-~]/g, '\\$&');
159
- const titleHeader = plainHeader(ctx.get(remarkCtx), `${marker} ${titleSource}`);
160
- if (!kinds.has(kind) ||
161
- !/^\[![A-Za-z]+\]$/.test(marker) ||
162
- marker.slice(2, -1).toUpperCase() !== kind ||
163
- !['', '+', '-'].includes(fold) ||
164
- /[\r\n]/.test(titleSource) ||
165
- titleHeader == null)
166
- return false;
167
- return {
168
- kind,
169
- marker,
170
- fold,
171
- title: titleHeader.slice(marker.length + 1).trimEnd(),
172
- titleSource,
173
- };
174
- },
175
- },
176
- ],
177
- toDOM: (node) => [
178
- 'blockquote',
179
- {
180
- class: 'inkkit-callout',
181
- 'data-inkkit-callout': node.attrs.kind,
182
- 'data-inkkit-marker': node.attrs.marker,
183
- 'data-inkkit-fold': node.attrs.fold,
184
- 'data-inkkit-title': node.attrs.titleSource ?? node.attrs.title,
185
- },
186
- [
187
- 'strong',
188
- { class: 'inkkit-callout-title' },
189
- node.attrs.title ||
190
- String(node.attrs.kind)
191
- .toLowerCase()
192
- .replace(/^./, (letter) => letter.toUpperCase()),
193
- ],
194
- ['div', { class: 'inkkit-callout-body' }, 0],
195
- ],
196
- parseMarkdown: {
197
- match: (node) => node.type === 'inkkitCallout',
198
- runner(state, node, type) {
199
- state.openNode(type, {
200
- kind: node.kind,
201
- marker: node.marker,
202
- fold: node.fold,
203
- title: node.title,
204
- titleSource: node.titleSource,
205
- });
206
- state.next(node.children);
207
- state.closeNode();
208
- },
209
- },
210
- toMarkdown: {
211
- match: (node) => node.type.name === 'inkkit_callout',
212
- runner(state, node) {
213
- state.openNode('inkkitCallout', undefined, { ...node.attrs });
214
- state.next(node.content);
215
- state.closeNode();
216
- },
217
- },
218
- }));
219
- export const calloutView = $prose((ctx) => new Plugin({
220
- key: new PluginKey('inkkitCalloutView'),
221
- props: {
222
- nodeViews: {
223
- inkkit_callout(node, view) {
224
- const dom = document.createElement('blockquote');
225
- dom.className = 'inkkit-callout';
226
- dom.setAttribute('data-inkkit-callout', String(node.attrs.kind));
227
- const header = document.createElement('div');
228
- header.className = 'inkkit-callout-header';
229
- header.contentEditable = 'false';
230
- const title = document.createElement('strong');
231
- title.className = 'inkkit-callout-title';
232
- const contentDOM = document.createElement('div');
233
- contentDOM.className = 'inkkit-callout-body';
234
- let folded = node.attrs.fold === '-';
235
- const button = document.createElement('button');
236
- button.type = 'button';
237
- button.setAttribute('data-inkkit-callout-toggle', '');
238
- const render = () => {
239
- title.textContent =
240
- node.attrs.title ||
241
- String(node.attrs.kind)
242
- .toLowerCase()
243
- .replace(/^./, (letter) => letter.toUpperCase());
244
- dom.setAttribute('data-inkkit-folded', String(folded));
245
- view.dom.dispatchEvent(new Event('inkkit-media-policy'));
246
- button.hidden = !node.attrs.fold;
247
- button.setAttribute('aria-expanded', String(!folded));
248
- button.setAttribute('aria-label', `${folded ? editorLabels(ctx).expandCallout : editorLabels(ctx).collapseCallout} ${title.textContent}`);
249
- button.textContent = folded
250
- ? editorLabels(ctx).expandCallout
251
- : editorLabels(ctx).collapseCallout;
252
- };
253
- const toggle = () => {
254
- folded = !folded;
255
- render();
256
- };
257
- button.addEventListener('click', toggle);
258
- button.addEventListener('keydown', (event) => {
259
- if (event.key === 'Enter' || event.key === ' ') {
260
- event.preventDefault();
261
- event.stopPropagation();
262
- toggle();
263
- }
264
- });
265
- header.append(title, button);
266
- dom.append(header, contentDOM);
267
- render();
268
- return {
269
- dom,
270
- contentDOM,
271
- update(next) {
272
- if (next.type !== node.type)
273
- return false;
274
- if (next.attrs.fold !== node.attrs.fold)
275
- folded = next.attrs.fold === '-';
276
- node = next;
277
- render();
278
- return true;
279
- },
280
- stopEvent: (event) => header.contains(event.target),
281
- ignoreMutation: (mutation) => mutation.type !== 'selection' &&
282
- !contentDOM.contains(mutation.target),
283
- };
284
- },
285
- },
286
- },
287
- }));
288
- export const callouts = [calloutSchema, calloutView].flat();
@@ -1,11 +0,0 @@
1
- import { type Fragment, type Schema } from '@milkdown/kit/prose/model';
2
- import type { ClipboardOutput, DocumentContext, ImageAdapter, FileAdapter } from './types.js';
3
- export interface ClipboardContent {
4
- text: string;
5
- html: string;
6
- }
7
- export declare function clipboardText(content: Fragment, missingImages?: ReadonlySet<string>, fileDescriptions?: ReadonlyMap<object, string>): string;
8
- export declare function clipboardContent(content: Fragment, schema: Schema): ClipboardContent;
9
- export declare const visibleClipboard: import("@milkdown/kit/utils").$Prose;
10
- /** Export a frozen document fragment; presentation URLs never enter the clipboard. */
11
- export declare function portableClipboard(content: Fragment, schema: Schema, markdown: string, adapter: ImageAdapter | undefined, context: DocumentContext, completeDiagrams?: ReadonlySet<string>, files?: FileAdapter, signal?: AbortSignal): Promise<ClipboardOutput>;
package/dist/clipboard.js DELETED
@@ -1,261 +0,0 @@
1
- import { DOMSerializer, } from '@milkdown/kit/prose/model';
2
- import { Plugin, PluginKey } from '@milkdown/kit/prose/state';
3
- import { $prose } from '@milkdown/kit/utils';
4
- import { shareableFragment } from './comments.js';
5
- import { diagramImage } from './mermaid.js';
6
- import { fileReference } from './linked-syntax.js';
7
- import { portableFile, portableFileImage } from './portable-files.js';
8
- import { withFileSignal } from './files.js';
9
- // Clipboard text is the visible document, not Markdown serialization: escaping
10
- // punctuation or trailing spaces here leaks source syntax into other apps.
11
- export function clipboardText(content, missingImages = new Set(), fileDescriptions = new Map()) {
12
- content = shareableFragment(content);
13
- const blocks = [];
14
- content.forEach((node) => {
15
- if (node.type.name !== 'reference_definition')
16
- blocks.push(nodeText(node, missingImages, fileDescriptions));
17
- });
18
- const inline = content.firstChild?.isInline ?? false;
19
- return blocks.join(inline ? '' : '\n\n');
20
- }
21
- function nodeText(node, missingImages, fileDescriptions) {
22
- if (node.type.name === 'inkkit_wiki_link')
23
- return String(node.attrs.label || node.attrs.target || 'Link');
24
- if (node.type.name === 'inkkit_callout')
25
- return `${node.attrs.title ||
26
- String(node.attrs.kind)
27
- .toLowerCase()
28
- .replace(/^./, (letter) => letter.toUpperCase())}\n${clipboardText(node.content, missingImages, fileDescriptions)}`;
29
- if (node.type.name === 'reference_definition')
30
- return '';
31
- if (node.type.name === 'footnote_reference')
32
- return `[${node.attrs.label}]`;
33
- if (node.type.name === 'footnote_definition')
34
- return `[${node.attrs.label}] ${clipboardText(node.content, missingImages, fileDescriptions)}`;
35
- if (node.isText)
36
- return node.text ?? '';
37
- if (node.type.name === 'hardbreak' || node.type.name === 'hard_break')
38
- return '\n';
39
- if (node.type.name === 'bullet_list' || node.type.name === 'ordered_list') {
40
- const items = [];
41
- node.forEach((item, _offset, index) => {
42
- const marker = node.type.name === 'ordered_list'
43
- ? `${Number(node.attrs.order ?? 1) + index}. `
44
- : '- ';
45
- const task = item.attrs.checked == null ? '' : item.attrs.checked ? '[x] ' : '[ ] ';
46
- const prefix = marker + task;
47
- const indent = ' '.repeat(marker.length);
48
- const blocks = [];
49
- item.forEach((child, _childOffset, childIndex) => {
50
- const text = nodeText(child, missingImages, fileDescriptions);
51
- const nestedList = child.type.name === 'bullet_list' ||
52
- child.type.name === 'ordered_list';
53
- const lines = text.split('\n');
54
- const indented = lines
55
- .map((line, lineIndex) => childIndex === 0 && lineIndex === 0 ? prefix + line : indent + line)
56
- .join('\n');
57
- // Nested lists follow their parent directly; subsequent paragraphs keep
58
- // their blank line and every continuation stays inside its list item.
59
- blocks.push((childIndex > 0 && !nestedList ? '\n' : '') + indented);
60
- });
61
- items.push(blocks.length ? blocks.join('\n') : prefix.trimEnd());
62
- });
63
- return items.join('\n');
64
- }
65
- if (node.type.name === 'image') {
66
- const description = fileDescriptions.get(node.attrs);
67
- if (description != null)
68
- return description;
69
- const alt = fileReference(node).label || 'Image';
70
- return missingImages.has(String(node.attrs.src ?? ''))
71
- ? `[${alt}: image unavailable]`
72
- : alt;
73
- }
74
- if (node.type.name === 'table') {
75
- const rows = [];
76
- node.forEach((row) => {
77
- const cells = [];
78
- row.forEach((cell) => cells.push(clipboardText(cell.content, missingImages, fileDescriptions)));
79
- rows.push(cells.join('\t'));
80
- });
81
- return rows.join('\n');
82
- }
83
- return clipboardText(node.content, missingImages, fileDescriptions);
84
- }
85
- export function clipboardContent(content, schema) {
86
- content = shareableFragment(content);
87
- const container = document.createElement('div');
88
- const serializer = DOMSerializer.fromSchema(schema);
89
- // Construct image elements without a source so detached clipboard DOM never
90
- // fetches authored references or temporary presentation URLs.
91
- const safe = new DOMSerializer({
92
- ...serializer.nodes,
93
- inkkit_wiki_link: (node) => [
94
- 'span',
95
- String(node.attrs.label || node.attrs.target || 'Link'),
96
- ],
97
- image: (node) => [
98
- 'img',
99
- {
100
- alt: String(node.attrs.alt ?? ''),
101
- title: String(node.attrs.title ?? ''),
102
- },
103
- ],
104
- }, serializer.marks);
105
- container.append(safe.serializeFragment(content));
106
- for (const definition of container.querySelectorAll('[data-inkkit-reference-definition]'))
107
- definition.remove();
108
- for (const reference of container.querySelectorAll('[data-inkkit-footnote-reference]')) {
109
- reference.removeAttribute('tabindex');
110
- reference.removeAttribute('role');
111
- }
112
- for (const definition of container.querySelectorAll('[data-inkkit-footnote-definition]')) {
113
- const label = document.createElement('span');
114
- label.textContent = `[${definition.getAttribute('data-inkkit-label')}] `;
115
- definition.prepend(label);
116
- }
117
- return { text: clipboardText(content), html: container.innerHTML };
118
- }
119
- export const visibleClipboard = $prose(() => new Plugin({
120
- key: new PluginKey('visibleClipboard'),
121
- props: {
122
- clipboardTextSerializer: (slice) => clipboardText(slice.content),
123
- },
124
- }));
125
- /** Export a frozen document fragment; presentation URLs never enter the clipboard. */
126
- export async function portableClipboard(content, schema, markdown, adapter, context, completeDiagrams, files, signal = new AbortController().signal) {
127
- signal.throwIfAborted();
128
- content = shareableFragment(content);
129
- const base = clipboardContent(content, schema);
130
- const container = document.createElement('div');
131
- container.innerHTML = base.html;
132
- const images = [];
133
- const references = [];
134
- const fileDescriptions = new Map();
135
- content.descendants((node) => {
136
- if (node.type.name === 'image')
137
- references.push(node);
138
- });
139
- const captured = [...container.querySelectorAll('img')].map((element, index) => {
140
- const node = references[index];
141
- const reference = String(node?.attrs.src ?? '');
142
- const { label: authoredAlt, width } = fileReference(node);
143
- const alt = authoredAlt || 'Image';
144
- if (width != null && width > 0)
145
- element.setAttribute('width', String(Math.min(4096, width)));
146
- element.removeAttribute('src');
147
- element.removeAttribute('srcset');
148
- return { element, node, reference, alt };
149
- });
150
- await Promise.all(captured.map(async ({ element, node, reference, alt }, index) => {
151
- let label = alt;
152
- element.setAttribute('data-inkkit-image-slot', String(index));
153
- element.setAttribute('data-inkkit-authored-image-slot', String(index));
154
- try {
155
- const file = files
156
- ? await portableFile(node, files, context, signal)
157
- : undefined;
158
- if (file && file.presentation.kind !== 'image') {
159
- const fallback = document.createElement('span');
160
- fallback.textContent = file.description;
161
- element.replaceWith(fallback);
162
- fileDescriptions.set(node.attrs, file.description);
163
- return;
164
- }
165
- label = file?.label || alt;
166
- if (!files && !adapter)
167
- throw new Error('The image is unavailable.');
168
- const input = file
169
- ? await portableFileImage(file, files, adapter, context, signal)
170
- : await withFileSignal(adapter.exportImage(reference, { ...context }), signal);
171
- signal.throwIfAborted();
172
- const image = { ...input, bytes: new Uint8Array(input.bytes) };
173
- if (!/^image\/(png|jpeg|gif|webp|avif|bmp|tiff)$/i.test(image.mimeType))
174
- throw new Error('The image format cannot be exported.');
175
- let binary = '';
176
- for (const byte of image.bytes)
177
- binary += String.fromCharCode(byte);
178
- const portable = `data:${image.mimeType};base64,${btoa(binary)}`;
179
- element.setAttribute('src', portable);
180
- element.setAttribute('alt', label);
181
- fileDescriptions.set(node.attrs, label);
182
- images[index] = { reference, alt: label, image };
183
- }
184
- catch (error) {
185
- signal.throwIfAborted();
186
- const message = error instanceof Error ? error.message : 'The image is unavailable.';
187
- const warning = document.createElement('span');
188
- warning.textContent = `[${label}: image unavailable]`;
189
- element.replaceWith(warning);
190
- fileDescriptions.set(node.attrs, warning.textContent);
191
- images[index] = { reference, alt: label, error: message };
192
- }
193
- }));
194
- const diagrams = [];
195
- for (const code of container.querySelectorAll('pre[data-language="mermaid"] > code')) {
196
- const source = code.textContent ?? '';
197
- if (completeDiagrams && !completeDiagrams.has(source))
198
- continue;
199
- const result = { source };
200
- diagrams.push(result);
201
- try {
202
- const image = await withFileSignal(diagramImage(source), signal);
203
- let binary = '';
204
- for (const byte of image.bytes)
205
- binary += String.fromCharCode(byte);
206
- const figure = document.createElement('figure');
207
- figure.setAttribute('data-inkkit-mermaid', source);
208
- const fence = code.parentElement.getAttribute('data-inkkit-fence');
209
- if (fence)
210
- figure.setAttribute('data-inkkit-fence', fence);
211
- const element = document.createElement('img');
212
- element.src = `data:image/png;base64,${btoa(binary)}`;
213
- element.alt = `Mermaid diagram: ${source}`;
214
- figure.append(element);
215
- code.parentElement.replaceWith(figure);
216
- result.image = image;
217
- }
218
- catch (error) {
219
- signal.throwIfAborted();
220
- result.error =
221
- error instanceof Error
222
- ? error.message
223
- : 'The diagram could not be exported.';
224
- const warning = document.createElement('p');
225
- warning.setAttribute('data-inkkit-diagram-error', '');
226
- warning.textContent = `Diagram unavailable: ${result.error}`;
227
- code.parentElement.before(warning);
228
- }
229
- }
230
- // Native attachment slots follow DOM order, including generated diagrams.
231
- const orderedImages = [];
232
- for (const element of container.querySelectorAll('img')) {
233
- const diagram = element.closest('[data-inkkit-mermaid]');
234
- const item = diagram
235
- ? {
236
- reference: '',
237
- alt: element.alt,
238
- image: diagrams.find((entry) => entry.source === diagram.getAttribute('data-inkkit-mermaid')).image,
239
- }
240
- : images[Number(element.getAttribute('data-inkkit-image-slot'))];
241
- element.setAttribute('data-inkkit-image-slot', String(orderedImages.length));
242
- orderedImages.push(item);
243
- }
244
- // Scriptable links and event attributes are not part of semantic rich text.
245
- for (const element of container.querySelectorAll('*')) {
246
- for (const attribute of [...element.attributes])
247
- if (attribute.name.startsWith('on') ||
248
- ((attribute.name === 'href' || attribute.name === 'src') &&
249
- /^javascript:/i.test(attribute.value)))
250
- element.removeAttribute(attribute.name);
251
- }
252
- const missing = new Set(images.filter((image) => image?.error).map((image) => image.reference));
253
- signal.throwIfAborted();
254
- return {
255
- text: clipboardText(content, missing, fileDescriptions),
256
- html: container.innerHTML,
257
- markdown,
258
- images: [...orderedImages, ...images.filter((image) => image?.error)],
259
- diagrams,
260
- };
261
- }
@@ -1,8 +0,0 @@
1
- import { type Options } from 'mdast-util-to-markdown';
2
- import type { Ctx } from '@milkdown/kit/ctx';
3
- import type { Node as ProseNode } from '@milkdown/kit/prose/model';
4
- export declare const remarkCodeFences: import("@milkdown/kit/utils").$Remark<"codeFences", unknown>;
5
- export declare const preservingCodeBlocks: import("@milkdown/kit/utils").$NodeSchema<"code_block">;
6
- export declare const fencedCodeHandler: NonNullable<Options['handlers']>['code'];
7
- export declare function restoreCodeEndings(ctx: Ctx, doc: ProseNode, markdown: string): string;
8
- export declare function finalCodeEnding(doc: ProseNode): string | undefined;