@aicayzer/inkkit 0.0.17 → 0.1.0

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 (81) hide show
  1. package/NOTICE +4 -2
  2. package/README.md +12 -6
  3. package/dist/THIRD-PARTY-NOTICES.txt +2742 -0
  4. package/dist/chunks/core-vtCr4MBS.js +56503 -0
  5. package/dist/chunks/highlight-Daj2fv_u.js +14122 -0
  6. package/dist/core.d.ts +4 -0
  7. package/dist/core.js +2 -0
  8. package/dist/editor.d.ts +261 -48
  9. package/dist/index.d.ts +1 -7
  10. package/dist/index.js +5 -2
  11. package/dist/style.css +242 -221
  12. package/dist/types.d.ts +143 -18
  13. package/package.json +26 -15
  14. package/dist/autolink.d.ts +0 -1
  15. package/dist/autolink.js +0 -18
  16. package/dist/callouts.d.ts +0 -26
  17. package/dist/callouts.js +0 -311
  18. package/dist/clipboard.d.ts +0 -11
  19. package/dist/clipboard.js +0 -261
  20. package/dist/code-fences.d.ts +0 -8
  21. package/dist/code-fences.js +0 -166
  22. package/dist/comments.d.ts +0 -55
  23. package/dist/comments.js +0 -494
  24. package/dist/decorations.d.ts +0 -2
  25. package/dist/decorations.js +0 -67
  26. package/dist/dialect.d.ts +0 -9
  27. package/dist/dialect.js +0 -358
  28. package/dist/editor.js +0 -2441
  29. package/dist/files.d.ts +0 -40
  30. package/dist/files.js +0 -133
  31. package/dist/highlight.d.ts +0 -1
  32. package/dist/highlight.js +0 -136
  33. package/dist/image-blocks.d.ts +0 -71
  34. package/dist/image-blocks.js +0 -286
  35. package/dist/images.d.ts +0 -51
  36. package/dist/images.js +0 -398
  37. package/dist/inline-highlight.d.ts +0 -6
  38. package/dist/inline-highlight.js +0 -112
  39. package/dist/labels.d.ts +0 -36
  40. package/dist/labels.js +0 -34
  41. package/dist/linked-syntax.d.ts +0 -48
  42. package/dist/linked-syntax.js +0 -320
  43. package/dist/literals.d.ts +0 -19
  44. package/dist/literals.js +0 -211
  45. package/dist/mermaid.d.ts +0 -8
  46. package/dist/mermaid.js +0 -321
  47. package/dist/outline.d.ts +0 -22
  48. package/dist/outline.js +0 -79
  49. package/dist/paste-html.d.ts +0 -23
  50. package/dist/paste-html.js +0 -441
  51. package/dist/paste.d.ts +0 -26
  52. package/dist/paste.js +0 -482
  53. package/dist/portable-files.d.ts +0 -10
  54. package/dist/portable-files.js +0 -36
  55. package/dist/preserve.d.ts +0 -21
  56. package/dist/preserve.js +0 -757
  57. package/dist/print.d.ts +0 -7
  58. package/dist/print.js +0 -409
  59. package/dist/reference-clipboard.d.ts +0 -8
  60. package/dist/reference-clipboard.js +0 -201
  61. package/dist/references.d.ts +0 -14
  62. package/dist/references.js +0 -368
  63. package/dist/search.d.ts +0 -15
  64. package/dist/search.js +0 -202
  65. package/dist/selection.d.ts +0 -1
  66. package/dist/selection.js +0 -59
  67. package/dist/source.d.ts +0 -16
  68. package/dist/source.js +0 -57
  69. package/dist/spreadsheet.d.ts +0 -3
  70. package/dist/spreadsheet.js +0 -275
  71. package/dist/table-alignment.d.ts +0 -2
  72. package/dist/table-alignment.js +0 -46
  73. package/dist/tables.d.ts +0 -27
  74. package/dist/tables.js +0 -322
  75. package/dist/tasks.d.ts +0 -3
  76. package/dist/tasks.js +0 -51
  77. package/dist/text-ranges.d.ts +0 -29
  78. package/dist/text-ranges.js +0 -256
  79. package/dist/types.js +0 -8
  80. package/dist/wiki-view.d.ts +0 -21
  81. package/dist/wiki-view.js +0 -78
package/dist/callouts.js DELETED
@@ -1,311 +0,0 @@
1
- import { $node, $prose, $remark } from '@milkdown/kit/utils';
2
- import { editorLabels } from './labels.js';
3
- import { remarkCtx } from '@milkdown/kit/core';
4
- import { Plugin, PluginKey } from '@milkdown/kit/prose/state';
5
- import { defaultHandlers } from 'mdast-util-to-markdown';
6
- const kinds = new Set(['NOTE', 'TIP', 'IMPORTANT', 'WARNING', 'CAUTION']);
7
- export function revealCalloutAncestors(view, position) {
8
- const node = view.domAtPos(position).node;
9
- let element = node instanceof HTMLElement ? node : node.parentElement;
10
- while (element && element !== view.dom) {
11
- if (element.getAttribute('data-inkkit-folded') === 'true')
12
- element
13
- .querySelector(':scope > .inkkit-callout-header > [data-inkkit-callout-toggle]')
14
- ?.click();
15
- element = element.parentElement;
16
- }
17
- }
18
- function plainHeader(processor, source) {
19
- const node = processor.parse(source).children[0];
20
- return node?.type === 'paragraph' &&
21
- node.children.length === 1 &&
22
- node.children[0]?.type === 'text'
23
- ? node.children[0].value
24
- : undefined;
25
- }
26
- const calloutHandler = (untyped, parent, state, info) => {
27
- const node = untyped;
28
- const body = defaultHandlers.blockquote({ type: 'blockquote', children: node.children }, parent, state, info);
29
- const title = node.titleSource ?? node.title;
30
- return `> ${node.marker}${node.fold}${title ? ` ${title}` : ''}\n${body}`;
31
- };
32
- function remarkCallouts() {
33
- const processor = this;
34
- const data = this.data();
35
- (data.toMarkdownExtensions ??= []).push({
36
- handlers: { inkkitCallout: calloutHandler },
37
- });
38
- return (tree, file) => {
39
- const source = String(file.value).replace(/^\uFEFF/, '');
40
- const visit = (node, parent, index) => {
41
- if (node.type === 'blockquote') {
42
- const start = node.position?.start.offset, end = node.position?.end.offset;
43
- const raw = start == null || end == null ? '' : source.slice(start, end);
44
- const header = /^>[ \t]*([\s\S]*?)(?:\r?\n|$)/.exec(raw)?.[1] ?? '';
45
- if (header.startsWith('[!')) {
46
- const match = /^(\[!([A-Za-z]+)\])([+-]?)(?:[ \t]+([^\r\n]*))?$/.exec(header);
47
- const first = node.children[0];
48
- const decodedHeader = plainHeader(processor, header);
49
- // A bounded header occupies one unformatted line; other variants stay source.
50
- if (!match ||
51
- decodedHeader == null ||
52
- !kinds.has(match[2].toUpperCase()) ||
53
- /^[+-](?:[ \t]|[+-])/.test(match[4] ?? '') ||
54
- first?.type !== 'paragraph' ||
55
- first.children[0]?.type !== 'text')
56
- return {
57
- type: 'inkkitLiteral',
58
- value: raw,
59
- position: node.position,
60
- };
61
- const text = first.children[0];
62
- // Entities can decode to newlines without ending the authored header line.
63
- const ending = /^\r?\n/.exec(text.value.slice(decodedHeader.length));
64
- const lineEnd = ending ? decodedHeader.length : -1;
65
- if (lineEnd < 0 && first.children.length > 1)
66
- return {
67
- type: 'inkkitLiteral',
68
- value: raw,
69
- position: node.position,
70
- };
71
- const children = [...node.children];
72
- if (lineEnd >= 0) {
73
- const remaining = text.value.slice(lineEnd + ending[0].length);
74
- const firstStart = text.position?.start.offset;
75
- const token = firstStart == null
76
- ? ''
77
- : source.slice(firstStart, text.position?.end.offset);
78
- const boundary = /\r?\n[ \t]*>[ \t]?/.exec(token);
79
- const bodyStart = firstStart == null || !boundary
80
- ? undefined
81
- : firstStart + boundary.index + boundary[0].length;
82
- const point = bodyStart == null
83
- ? undefined
84
- : {
85
- line: source.slice(0, bodyStart).split('\n').length,
86
- column: bodyStart - source.lastIndexOf('\n', bodyStart - 1),
87
- offset: bodyStart,
88
- };
89
- children[0] = {
90
- ...first,
91
- children: [
92
- ...(remaining
93
- ? [
94
- {
95
- ...text,
96
- value: remaining,
97
- position: point && text.position
98
- ? { start: point, end: text.position.end }
99
- : undefined,
100
- },
101
- ]
102
- : []),
103
- ...first.children.slice(1),
104
- ],
105
- };
106
- }
107
- else
108
- children.shift();
109
- if (!children.length)
110
- children.push({ type: 'paragraph', children: [] });
111
- return {
112
- type: 'inkkitCallout',
113
- kind: match[2].toUpperCase(),
114
- marker: match[1],
115
- fold: match[3],
116
- title: decodedHeader
117
- .slice(header.length - (match[4]?.length ?? 0))
118
- .trimEnd(),
119
- titleSource: match[4]?.trimEnd() ?? '',
120
- listPlaceholder: parent?.type === 'listItem' && index === 0,
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, index) => visit(child, node, index));
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
- listPlaceholder: { default: false },
145
- },
146
- parseDOM: [
147
- {
148
- tag: 'blockquote[data-inkkit-callout]',
149
- priority: 100,
150
- contentElement: '.inkkit-callout-body',
151
- getAttrs: (dom) => {
152
- const kind = (dom.getAttribute('data-inkkit-callout') ?? '').toUpperCase();
153
- const marker = dom.getAttribute('data-inkkit-marker') ?? `[!${kind}]`;
154
- const fold = dom.getAttribute('data-inkkit-fold') ?? '';
155
- const titleSource = dom.getAttribute('data-inkkit-title');
156
- const placeholder = dom.getAttribute('data-inkkit-list-placeholder');
157
- const previous = dom.previousElementSibling;
158
- const titleHeader = titleSource == null
159
- ? undefined
160
- : plainHeader(ctx.get(remarkCtx), `${marker} ${titleSource}`);
161
- if (!kinds.has(kind) ||
162
- !/^\[![A-Za-z]+\]$/.test(marker) ||
163
- marker.slice(2, -1).toUpperCase() !== kind ||
164
- !['', '+', '-'].includes(fold) ||
165
- (titleSource != null &&
166
- (/[\r\n]/.test(titleSource) || titleHeader == null)))
167
- return false;
168
- return {
169
- kind,
170
- marker,
171
- fold,
172
- title: titleHeader == null
173
- ? (dom.querySelector('.inkkit-callout-title')?.textContent ?? '')
174
- : titleHeader.slice(marker.length + 1).trimEnd(),
175
- titleSource,
176
- listPlaceholder: placeholder == null
177
- ? dom.parentElement?.tagName === 'LI' &&
178
- (!previous ||
179
- (previous.tagName === 'P' &&
180
- !previous.textContent &&
181
- !previous.childElementCount))
182
- : placeholder === 'true',
183
- };
184
- },
185
- },
186
- ],
187
- toDOM: (node) => [
188
- 'blockquote',
189
- {
190
- class: 'inkkit-callout',
191
- 'data-inkkit-callout': node.attrs.kind,
192
- 'data-inkkit-marker': node.attrs.marker,
193
- 'data-inkkit-fold': node.attrs.fold,
194
- 'data-inkkit-title': node.attrs.titleSource ?? node.attrs.title,
195
- 'data-inkkit-list-placeholder': String(node.attrs.listPlaceholder),
196
- },
197
- [
198
- 'strong',
199
- { class: 'inkkit-callout-title' },
200
- node.attrs.title ||
201
- String(node.attrs.kind)
202
- .toLowerCase()
203
- .replace(/^./, (letter) => letter.toUpperCase()),
204
- ],
205
- ['div', { class: 'inkkit-callout-body' }, 0],
206
- ],
207
- parseMarkdown: {
208
- match: (node) => node.type === 'inkkitCallout',
209
- runner(state, node, type) {
210
- state.openNode(type, {
211
- kind: node.kind,
212
- marker: node.marker,
213
- fold: node.fold,
214
- title: node.title,
215
- titleSource: node.titleSource,
216
- listPlaceholder: node.listPlaceholder,
217
- });
218
- state.next(node.children);
219
- state.closeNode();
220
- },
221
- },
222
- toMarkdown: {
223
- match: (node) => node.type.name === 'inkkit_callout',
224
- runner(state, node) {
225
- const parent = state.top();
226
- const first = parent?.children?.[0];
227
- // Lists require a leading paragraph even when their authored first block is a callout.
228
- if (node.attrs.listPlaceholder &&
229
- parent?.type === 'listItem' &&
230
- parent.children?.length === 1 &&
231
- first?.type === 'paragraph' &&
232
- first.children?.length === 1 &&
233
- first.children[0]?.type === 'html' &&
234
- first.children[0].value === '<br />')
235
- parent.children = [];
236
- state.openNode('inkkitCallout', undefined, { ...node.attrs });
237
- state.next(node.content);
238
- state.closeNode();
239
- },
240
- },
241
- }));
242
- export const calloutView = $prose((ctx) => new Plugin({
243
- key: new PluginKey('inkkitCalloutView'),
244
- props: {
245
- nodeViews: {
246
- inkkit_callout(node, view) {
247
- const dom = document.createElement('blockquote');
248
- dom.className = 'inkkit-callout';
249
- dom.setAttribute('data-inkkit-callout', String(node.attrs.kind));
250
- const header = document.createElement('div');
251
- header.className = 'inkkit-callout-header';
252
- header.contentEditable = 'false';
253
- const title = document.createElement('strong');
254
- title.className = 'inkkit-callout-title';
255
- const contentDOM = document.createElement('div');
256
- contentDOM.className = 'inkkit-callout-body';
257
- let folded = node.attrs.fold === '-';
258
- const button = document.createElement('button');
259
- button.type = 'button';
260
- button.setAttribute('data-inkkit-callout-toggle', '');
261
- const render = () => {
262
- title.textContent =
263
- node.attrs.title ||
264
- String(node.attrs.kind)
265
- .toLowerCase()
266
- .replace(/^./, (letter) => letter.toUpperCase());
267
- dom.setAttribute('data-inkkit-folded', String(folded));
268
- view.dom.dispatchEvent(new Event('inkkit-media-policy'));
269
- button.hidden = !node.attrs.fold;
270
- button.setAttribute('aria-expanded', String(!folded));
271
- button.setAttribute('aria-label', `${folded ? editorLabels(ctx).expandCallout : editorLabels(ctx).collapseCallout} ${title.textContent}`);
272
- button.textContent = folded
273
- ? editorLabels(ctx).expandCallout
274
- : editorLabels(ctx).collapseCallout;
275
- };
276
- const toggle = () => {
277
- folded = !folded;
278
- render();
279
- };
280
- button.addEventListener('click', toggle);
281
- button.addEventListener('keydown', (event) => {
282
- if (event.key === 'Enter' || event.key === ' ') {
283
- event.preventDefault();
284
- event.stopPropagation();
285
- toggle();
286
- }
287
- });
288
- header.append(title, button);
289
- dom.append(header, contentDOM);
290
- render();
291
- return {
292
- dom,
293
- contentDOM,
294
- update(next) {
295
- if (next.type !== node.type)
296
- return false;
297
- if (next.attrs.fold !== node.attrs.fold)
298
- folded = next.attrs.fold === '-';
299
- node = next;
300
- render();
301
- return true;
302
- },
303
- stopEvent: (event) => header.contains(event.target),
304
- ignoreMutation: (mutation) => mutation.type !== 'selection' &&
305
- !contentDOM.contains(mutation.target),
306
- };
307
- },
308
- },
309
- },
310
- }));
311
- 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;