@mdzip/editor 1.2.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 (50) hide show
  1. package/README.md +126 -0
  2. package/dist/archive-utils.d.ts +35 -0
  3. package/dist/archive-utils.d.ts.map +1 -0
  4. package/dist/archive-utils.js +148 -0
  5. package/dist/archive-utils.js.map +1 -0
  6. package/dist/browser.d.ts +7 -0
  7. package/dist/browser.d.ts.map +1 -0
  8. package/dist/browser.js +108 -0
  9. package/dist/browser.js.map +1 -0
  10. package/dist/diff.d.ts +36 -0
  11. package/dist/diff.d.ts.map +1 -0
  12. package/dist/diff.js +100 -0
  13. package/dist/diff.js.map +1 -0
  14. package/dist/icons/md-markdown.d.ts +3 -0
  15. package/dist/icons/md-markdown.d.ts.map +1 -0
  16. package/dist/icons/md-markdown.js +35 -0
  17. package/dist/icons/md-markdown.js.map +1 -0
  18. package/dist/index.d.ts +11 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +10 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/metadata.d.ts +9 -0
  23. package/dist/metadata.d.ts.map +1 -0
  24. package/dist/metadata.js +21 -0
  25. package/dist/metadata.js.map +1 -0
  26. package/dist/rendering.d.ts +20 -0
  27. package/dist/rendering.d.ts.map +1 -0
  28. package/dist/rendering.js +83 -0
  29. package/dist/rendering.js.map +1 -0
  30. package/dist/theme.d.ts +14 -0
  31. package/dist/theme.d.ts.map +1 -0
  32. package/dist/theme.js +96 -0
  33. package/dist/theme.js.map +1 -0
  34. package/dist/view-css.d.ts +2 -0
  35. package/dist/view-css.d.ts.map +1 -0
  36. package/dist/view-css.js +1281 -0
  37. package/dist/view-css.js.map +1 -0
  38. package/dist/view.d.ts +237 -0
  39. package/dist/view.d.ts.map +1 -0
  40. package/dist/view.js +1857 -0
  41. package/dist/view.js.map +1 -0
  42. package/dist/workspace-view.d.ts +20 -0
  43. package/dist/workspace-view.d.ts.map +1 -0
  44. package/dist/workspace-view.js +200 -0
  45. package/dist/workspace-view.js.map +1 -0
  46. package/dist/workspace.d.ts +131 -0
  47. package/dist/workspace.d.ts.map +1 -0
  48. package/dist/workspace.js +555 -0
  49. package/dist/workspace.js.map +1 -0
  50. package/package.json +40 -0
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # @mdzip/editor
2
+
3
+ Framework-independent MDZip workspace engine and browser view.
4
+
5
+ `@mdzip/editor` provides reusable helpers for opening `.mdz` archives, rendering Markdown previews, editing archive contents, comparing archive inventories, and embedding a configurable MDZip workspace UI.
6
+
7
+ ## Install
8
+
9
+ ```sh
10
+ npm install @mdzip/editor
11
+ ```
12
+
13
+ ## Basic Usage
14
+
15
+ ```ts
16
+ import { MdzipWorkspaceView } from '@mdzip/editor';
17
+
18
+ const view = new MdzipWorkspaceView(container, {
19
+ controls: 'viewer',
20
+ initialLayout: 'preview',
21
+ onFailed(error) {
22
+ console.error(error);
23
+ }
24
+ });
25
+
26
+ await view.open(bytes, {
27
+ mode: 'read-only',
28
+ fileName: 'document.mdz'
29
+ });
30
+ ```
31
+
32
+ Regular Markdown is also supported:
33
+
34
+ ```ts
35
+ await view.open(markdownBytes, {
36
+ mode: 'editable',
37
+ fileName: 'notes.md'
38
+ });
39
+ ```
40
+
41
+ The filename normally selects the source format. Pass `sourceFormat:
42
+ 'markdown'` or `sourceFormat: 'mdz'` to override detection.
43
+
44
+ Normalized `mdzip-core-js` workspaces can be opened without an initial archive
45
+ rebuild:
46
+
47
+ ```ts
48
+ await view.openWorkspace(workspace, {
49
+ mode: 'editable',
50
+ fileName: 'document.mdz'
51
+ });
52
+ ```
53
+
54
+ ## Editor Mode
55
+
56
+ ```ts
57
+ const view = new MdzipWorkspaceView(container, {
58
+ controls: 'standalone-editor',
59
+ async onSaved(bytes) {
60
+ await persist(bytes);
61
+ view.markPersisted();
62
+ }
63
+ });
64
+
65
+ await view.open(bytes, {
66
+ mode: 'editable',
67
+ fileName: 'document.mdz'
68
+ });
69
+ ```
70
+
71
+ When `onSaved` is omitted, the built-in Save button downloads the current file
72
+ in the browser. When `onSaved` is provided, the host owns persistence and must
73
+ call `markPersisted()` after a successful write. Failed writes should leave the
74
+ workspace dirty.
75
+
76
+ ## Control Presets
77
+
78
+ - `preview`: clean document preview with no toolbar or package navigation.
79
+ - `viewer`: read-only viewer controls, including navigation, layout switching, and zoom.
80
+ - `standalone-editor`: full editor controls, including save.
81
+ - `hosted-editor`: editor controls without an embedded save button, for hosts such as VS Code that own persistence.
82
+
83
+ ## Host Persistence
84
+
85
+ Desktop hosts can flush pending editor content, persist the returned bytes, and
86
+ only then acknowledge a successful write:
87
+
88
+ ```ts
89
+ const snapshot = await view.flush();
90
+ if (snapshot) {
91
+ await nativeSave(snapshot.bytes);
92
+ view.markPersisted();
93
+ }
94
+ ```
95
+
96
+ `flush()` deliberately leaves `dirty` set until `markPersisted()` is called.
97
+ `serialize()` and `getCurrentSnapshot()` provide non-acknowledging alternatives.
98
+
99
+ Structured callbacks are available for workspace, document, asset, manifest,
100
+ selection, dirty, validation, and snapshot changes. Asset hosts can also call
101
+ `addAsset()`, `replaceAsset()`, `removeAsset()`, and `listAssets()`.
102
+
103
+ `MdzipRenderingService` uses `defaultSafeMarkdownRenderer` when no renderer is
104
+ injected. The default renderer sanitizes generated HTML and unsafe URL schemes.
105
+
106
+ ## Developer Guide
107
+
108
+ See the [Developer Guide](https://github.com/mdzip-project/@mdzip/editor/blob/main/docs/developer-guide.md)
109
+ for granular host controls, height requirements, lifecycle events, persistence,
110
+ theming, and Raw, Angular, React, and Vue examples.
111
+
112
+ See the [Theming Guide](https://github.com/mdzip-project/@mdzip/editor/blob/main/docs/theming.md)
113
+ for custom theme examples and the complete CSS variable reference.
114
+
115
+ ## Archive Helpers
116
+
117
+ ```ts
118
+ import {
119
+ openMdzArchive,
120
+ readCanonicalMarkdown,
121
+ createArchiveInventory,
122
+ diffArchiveInventories
123
+ } from '@mdzip/editor';
124
+ ```
125
+
126
+ These helpers are built on `mdzip-core-js` and are suitable for framework wrappers, desktop hosts, browser apps, and extension integrations.
@@ -0,0 +1,35 @@
1
+ import { type MdzManifest, type MdzValidationResult, type MdzWorkspace } from 'mdzip-core-js';
2
+ export interface ArchiveEntry {
3
+ path: string;
4
+ isMarkdown: boolean;
5
+ isImage: boolean;
6
+ isDirectory: boolean;
7
+ }
8
+ export interface OpenedArchive {
9
+ paths: ArchiveEntry[];
10
+ entryPoint: string;
11
+ manifest: MdzManifest | null;
12
+ markdownText: string;
13
+ images: Map<string, string>;
14
+ orphanedAssetPaths: string[];
15
+ validation: MdzValidationResult;
16
+ }
17
+ export interface NewArchiveAsset {
18
+ archivePath: string;
19
+ fileBytes: Uint8Array;
20
+ }
21
+ export declare function openMdzArchive(bytes: Uint8Array): Promise<OpenedArchive>;
22
+ export declare function openedArchiveFromWorkspace(workspace: MdzWorkspace): Promise<OpenedArchive>;
23
+ export declare function updateMarkdownInArchive(existingBytes: Uint8Array, entryPointPath: string, newMarkdown: string): Promise<Uint8Array>;
24
+ export declare function updateBinaryInArchive(existingBytes: Uint8Array, archivePath: string, fileBytes: Uint8Array): Promise<Uint8Array>;
25
+ export declare function removeFilesFromArchive(existingBytes: Uint8Array, archivePaths: string[]): Promise<Uint8Array>;
26
+ export declare function findOrphanedAssetPathsInArchive(existingBytes: Uint8Array, entryPoint?: string): Promise<string[]>;
27
+ export declare function readBinaryFileFromArchive(existingBytes: Uint8Array, archivePath: string): Promise<Uint8Array>;
28
+ export declare function readTextFileFromArchive(existingBytes: Uint8Array, archivePath: string): Promise<string>;
29
+ export declare function buildNewArchive(markdownContent: string): Promise<Blob>;
30
+ export declare function buildNewArchiveWithTitle(markdownContent: string, title: string): Promise<Blob>;
31
+ export declare function buildNewArchiveBytesWithTitle(markdownContent: string, title: string, assets?: readonly NewArchiveAsset[]): Promise<Uint8Array>;
32
+ export declare function updateManifestTitleInArchive(existingBytes: Uint8Array, newTitle: string): Promise<Uint8Array>;
33
+ export declare function isImagePath(path: string): boolean;
34
+ export declare function blobToBytes(blob: Blob): Promise<Uint8Array>;
35
+ //# sourceMappingURL=archive-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-utils.d.ts","sourceRoot":"","sources":["../src/archive-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,UAAU,EAAE,mBAAmB,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,CAI9E;AAED,wBAAsB,0BAA0B,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAsDhG;AAED,wBAAsB,uBAAuB,CAC3C,aAAa,EAAE,UAAU,EACzB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CAGrB;AAED,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,UAAU,EACzB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,UAAU,CAAC,CAGrB;AAED,wBAAsB,sBAAsB,CAC1C,aAAa,EAAE,UAAU,EACzB,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,UAAU,CAAC,CAGrB;AAED,wBAAsB,+BAA+B,CACnD,aAAa,EAAE,UAAU,EACzB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC,CAMnB;AAED,wBAAsB,yBAAyB,CAC7C,aAAa,EAAE,UAAU,EACzB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CAOrB;AAED,wBAAsB,uBAAuB,CAC3C,aAAa,EAAE,UAAU,EACzB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED,wBAAsB,eAAe,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5E;AAED,wBAAsB,wBAAwB,CAC5C,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,wBAAsB,6BAA6B,CACjD,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,SAAS,eAAe,EAAO,GACtC,OAAO,CAAC,UAAU,CAAC,CASrB;AAED,wBAAsB,4BAA4B,CAChD,aAAa,EAAE,UAAU,EACzB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC,CAarB;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGjD;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAEjE"}
@@ -0,0 +1,148 @@
1
+ import { MDZ_IMAGE_MIME_TYPES, MdzArchiveCore, MdzPackagerCore } from 'mdzip-core-js';
2
+ export async function openMdzArchive(bytes) {
3
+ return openedArchiveFromWorkspace(await MdzArchiveCore.openWorkspace(bytes, {
4
+ includeOrphanedAssetAnalysis: true
5
+ }));
6
+ }
7
+ export async function openedArchiveFromWorkspace(workspace) {
8
+ const entryPoint = workspace.entryPoint
9
+ ?? workspace.documents.find((document) => document.isEntryPoint)?.path
10
+ ?? workspace.documents[0]?.path
11
+ ?? 'index.md';
12
+ const markdownText = workspace.documents.find((document) => document.path.toLowerCase() === entryPoint.toLowerCase())?.text ?? '';
13
+ const paths = [
14
+ ...workspace.documents.map((document) => ({
15
+ path: document.path,
16
+ isMarkdown: true,
17
+ isImage: false,
18
+ isDirectory: false
19
+ })),
20
+ ...(workspace.manifest ? [{
21
+ path: 'manifest.json',
22
+ isMarkdown: false,
23
+ isImage: false,
24
+ isDirectory: false
25
+ }] : []),
26
+ ...workspace.assets.map((asset) => ({
27
+ path: asset.path,
28
+ isMarkdown: false,
29
+ isImage: asset.kind === 'image',
30
+ isDirectory: false
31
+ }))
32
+ ].sort((a, b) => a.path.localeCompare(b.path, undefined, { sensitivity: 'base' }));
33
+ const images = new Map();
34
+ for (const asset of workspace.assets) {
35
+ if (asset.kind !== 'image') {
36
+ continue;
37
+ }
38
+ if (asset.readDataUri) {
39
+ images.set(asset.path, await asset.readDataUri());
40
+ continue;
41
+ }
42
+ const bytes = asset.bytes
43
+ ? await binarySourceToBytes(asset.bytes)
44
+ : await asset.readBytes?.();
45
+ if (bytes) {
46
+ images.set(asset.path, `data:${asset.mimeType};base64,${bytesToBase64(bytes)}`);
47
+ }
48
+ }
49
+ return {
50
+ paths,
51
+ entryPoint,
52
+ manifest: workspace.manifest,
53
+ markdownText,
54
+ images,
55
+ orphanedAssetPaths: workspace.orphanedAssets?.orphanedAssetPaths ?? [],
56
+ validation: workspace.validation
57
+ };
58
+ }
59
+ export async function updateMarkdownInArchive(existingBytes, entryPointPath, newMarkdown) {
60
+ const result = await MdzArchiveCore.addFile(existingBytes, entryPointPath, newMarkdown);
61
+ return blobToBytes(result.blob);
62
+ }
63
+ export async function updateBinaryInArchive(existingBytes, archivePath, fileBytes) {
64
+ const result = await MdzArchiveCore.addFile(existingBytes, archivePath, fileBytes);
65
+ return blobToBytes(result.blob);
66
+ }
67
+ export async function removeFilesFromArchive(existingBytes, archivePaths) {
68
+ const result = await MdzArchiveCore.removeFiles(existingBytes, archivePaths);
69
+ return blobToBytes(result.blob);
70
+ }
71
+ export async function findOrphanedAssetPathsInArchive(existingBytes, entryPoint) {
72
+ const result = await MdzArchiveCore.findOrphanedAssets(existingBytes, entryPoint ? { entryPoint } : undefined);
73
+ return result.orphanedAssetPaths;
74
+ }
75
+ export async function readBinaryFileFromArchive(existingBytes, archivePath) {
76
+ const archive = await MdzArchiveCore.open(existingBytes);
77
+ try {
78
+ return await archive.readBytes(archivePath);
79
+ }
80
+ catch {
81
+ throw new Error(`Archive file "${archivePath}" not found.`);
82
+ }
83
+ }
84
+ export async function readTextFileFromArchive(existingBytes, archivePath) {
85
+ const archive = await MdzArchiveCore.open(existingBytes);
86
+ try {
87
+ return await archive.readText(archivePath);
88
+ }
89
+ catch {
90
+ throw new Error(`Archive file "${archivePath}" not found.`);
91
+ }
92
+ }
93
+ export async function buildNewArchive(markdownContent) {
94
+ return buildNewArchiveWithTitle(markdownContent, 'document');
95
+ }
96
+ export async function buildNewArchiveWithTitle(markdownContent, title) {
97
+ const result = await MdzPackagerCore.buildArchive([{ path: 'index.md', text: markdownContent }], 'document', {
98
+ createIndex: false,
99
+ mapFiles: false,
100
+ filters: MdzPackagerCore.DEFAULT_FILTERS,
101
+ mode: 'document',
102
+ entryPoint: 'index.md',
103
+ title
104
+ });
105
+ return result.blob;
106
+ }
107
+ export async function buildNewArchiveBytesWithTitle(markdownContent, title, assets = []) {
108
+ const blob = await buildNewArchiveWithTitle(markdownContent, title);
109
+ let bytes = await blobToBytes(blob);
110
+ for (const asset of assets) {
111
+ bytes = await updateBinaryInArchive(bytes, asset.archivePath, asset.fileBytes);
112
+ }
113
+ return bytes;
114
+ }
115
+ export async function updateManifestTitleInArchive(existingBytes, newTitle) {
116
+ const archive = await MdzArchiveCore.open(existingBytes);
117
+ const manifest = await archive.readManifest();
118
+ if (!manifest) {
119
+ throw new Error('Cannot set title: manifest.json is missing.');
120
+ }
121
+ const result = await MdzArchiveCore.addFile(existingBytes, 'manifest.json', JSON.stringify({ ...manifest, title: newTitle }, null, 2));
122
+ return blobToBytes(result.blob);
123
+ }
124
+ export function isImagePath(path) {
125
+ const ext = path.split('.').pop()?.toLowerCase() ?? '';
126
+ return ext in MDZ_IMAGE_MIME_TYPES;
127
+ }
128
+ export async function blobToBytes(blob) {
129
+ return new Uint8Array(await blob.arrayBuffer());
130
+ }
131
+ async function binarySourceToBytes(source) {
132
+ if (source instanceof Uint8Array) {
133
+ return source;
134
+ }
135
+ if (source instanceof ArrayBuffer) {
136
+ return new Uint8Array(source);
137
+ }
138
+ return blobToBytes(source);
139
+ }
140
+ function bytesToBase64(bytes) {
141
+ let binary = '';
142
+ const chunkSize = 0x8000;
143
+ for (let index = 0; index < bytes.length; index += chunkSize) {
144
+ binary += String.fromCharCode(...bytes.subarray(index, index + chunkSize));
145
+ }
146
+ return btoa(binary);
147
+ }
148
+ //# sourceMappingURL=archive-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-utils.js","sourceRoot":"","sources":["../src/archive-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface ClipboardImagePayload {
2
+ bytes: Uint8Array;
3
+ mimeType: string;
4
+ }
5
+ export declare function browserClipboardHasImage(clipboard: DataTransfer | null): boolean;
6
+ export declare function readBrowserClipboardImage(clipboard: DataTransfer | null): Promise<ClipboardImagePayload | null>;
7
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,YAAY,GAAG,IAAI,GAAG,OAAO,CAchF;AAED,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,YAAY,GAAG,IAAI,GAC7B,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAiDvC"}
@@ -0,0 +1,108 @@
1
+ export function browserClipboardHasImage(clipboard) {
2
+ if (!clipboard) {
3
+ return false;
4
+ }
5
+ if (Array.from(clipboard.files || []).some((file) => isBrowserImageFile(file))) {
6
+ return true;
7
+ }
8
+ if (Array.from(clipboard.items || []).some((item) => item.type.startsWith('image/'))) {
9
+ return true;
10
+ }
11
+ return extractDataUrlFromClipboardData(clipboard) !== null;
12
+ }
13
+ export async function readBrowserClipboardImage(clipboard) {
14
+ if (clipboard) {
15
+ const fileFromFiles = Array.from(clipboard.files || []).find((file) => isBrowserImageFile(file));
16
+ if (fileFromFiles) {
17
+ return {
18
+ bytes: new Uint8Array(await fileFromFiles.arrayBuffer()),
19
+ mimeType: fileFromFiles.type || 'image/png'
20
+ };
21
+ }
22
+ for (const item of Array.from(clipboard.items || [])) {
23
+ const file = item.kind === 'file' || item.type.startsWith('image/') ? item.getAsFile() : null;
24
+ if (isBrowserImageFile(file)) {
25
+ return {
26
+ bytes: new Uint8Array(await file.arrayBuffer()),
27
+ mimeType: file.type || item.type || `image/${imageExtensionFromFileName(file.name)}`
28
+ };
29
+ }
30
+ }
31
+ const dataUrl = extractDataUrlFromClipboardData(clipboard);
32
+ if (dataUrl) {
33
+ return {
34
+ bytes: bytesFromDataUrl(dataUrl),
35
+ mimeType: mimeTypeFromDataUrl(dataUrl)
36
+ };
37
+ }
38
+ }
39
+ if (typeof navigator !== 'undefined' && navigator.clipboard && typeof navigator.clipboard.read === 'function') {
40
+ try {
41
+ const clipboardItems = await navigator.clipboard.read();
42
+ for (const clipboardItem of clipboardItems) {
43
+ const imageType = clipboardItem.types.find((type) => type.startsWith('image/'));
44
+ if (!imageType) {
45
+ continue;
46
+ }
47
+ const blob = await clipboardItem.getType(imageType);
48
+ return {
49
+ bytes: new Uint8Array(await blob.arrayBuffer()),
50
+ mimeType: imageType
51
+ };
52
+ }
53
+ }
54
+ catch {
55
+ // Normal paste should continue when async clipboard access is blocked.
56
+ }
57
+ }
58
+ return null;
59
+ }
60
+ function isBrowserImageFile(file) {
61
+ if (!file) {
62
+ return false;
63
+ }
64
+ if (file.type.startsWith('image/')) {
65
+ return true;
66
+ }
67
+ return /\.(png|jpe?g|gif|webp|svg)$/i.test(file.name);
68
+ }
69
+ function extractDataUrlFromClipboardData(clipboard) {
70
+ const html = clipboard.getData('text/html');
71
+ if (html) {
72
+ const htmlMatch = html.match(/src=["'](data:image\/[a-zA-Z0-9.+-]+;base64,[^"']+)["']/i);
73
+ if (htmlMatch?.[1]) {
74
+ return htmlMatch[1];
75
+ }
76
+ }
77
+ const text = clipboard.getData('text/plain');
78
+ if (text && /^data:image\/[a-zA-Z0-9.+-]+;base64,/.test(text.trim())) {
79
+ return text.trim();
80
+ }
81
+ return null;
82
+ }
83
+ function bytesFromDataUrl(dataUrl) {
84
+ const base64 = dataUrl.split(',')[1] ?? '';
85
+ const binary = atob(base64);
86
+ const bytes = new Uint8Array(binary.length);
87
+ for (let index = 0; index < binary.length; index += 1) {
88
+ bytes[index] = binary.charCodeAt(index);
89
+ }
90
+ return bytes;
91
+ }
92
+ function mimeTypeFromDataUrl(dataUrl) {
93
+ const match = dataUrl.match(/^data:(image\/[a-zA-Z0-9.+-]+);base64,/i);
94
+ return match?.[1]?.toLowerCase() ?? 'image/png';
95
+ }
96
+ function imageExtensionFromFileName(name) {
97
+ const lower = name.toLowerCase();
98
+ if (lower.endsWith('.jpg') || lower.endsWith('.jpeg'))
99
+ return 'jpeg';
100
+ if (lower.endsWith('.gif'))
101
+ return 'gif';
102
+ if (lower.endsWith('.webp'))
103
+ return 'webp';
104
+ if (lower.endsWith('.svg'))
105
+ return 'svg+xml';
106
+ return 'png';
107
+ }
108
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
package/dist/diff.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ import { type MdzManifest } from 'mdzip-core-js';
2
+ export interface CanonicalMarkdownReadResult {
3
+ entryPoint: string;
4
+ markdown: string;
5
+ manifest: MdzManifest | null;
6
+ }
7
+ export declare function readCanonicalMarkdown(bytes: Uint8Array): Promise<CanonicalMarkdownReadResult>;
8
+ export type ArchiveInventoryEntryKind = 'markdown' | 'manifest' | 'image' | 'file';
9
+ export interface ArchiveInventoryEntry {
10
+ path: string;
11
+ kind: ArchiveInventoryEntryKind;
12
+ size: number;
13
+ hash: string;
14
+ }
15
+ export interface ArchiveInventory {
16
+ entries: ArchiveInventoryEntry[];
17
+ entryPoint: string;
18
+ manifest: MdzManifest | null;
19
+ }
20
+ export declare function createArchiveInventory(bytes: Uint8Array): Promise<ArchiveInventory>;
21
+ export type ArchiveInventoryDiffStatus = 'added' | 'removed' | 'changed' | 'unchanged';
22
+ export interface ArchiveInventoryDiffEntry {
23
+ path: string;
24
+ status: ArchiveInventoryDiffStatus;
25
+ kind: ArchiveInventoryEntryKind;
26
+ before?: ArchiveInventoryEntry;
27
+ after?: ArchiveInventoryEntry;
28
+ }
29
+ export interface ArchiveInventoryDiff {
30
+ entries: ArchiveInventoryDiffEntry[];
31
+ changedCount: number;
32
+ addedCount: number;
33
+ removedCount: number;
34
+ }
35
+ export declare function diffArchiveInventories(before: ArchiveInventory, after: ArchiveInventory): ArchiveInventoryDiff;
36
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAGjE,MAAM,WAAW,2BAA2B;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9B;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,2BAA2B,CAAC,CAOtC;AAED,MAAM,MAAM,yBAAyB,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAEnF,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,yBAAyB,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9B;AAED,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,gBAAgB,CAAC,CAiC3B;AAED,MAAM,MAAM,0BAA0B,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAEvF,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,0BAA0B,CAAC;IACnC,IAAI,EAAE,yBAAyB,CAAC;IAChC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,yBAAyB,EAAE,CAAC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,gBAAgB,GACtB,oBAAoB,CA8DtB"}
package/dist/diff.js ADDED
@@ -0,0 +1,100 @@
1
+ import { MdzArchiveCore } from 'mdzip-core-js';
2
+ import { isMdzipManifestPath } from './workspace-view.js';
3
+ export async function readCanonicalMarkdown(bytes) {
4
+ const archive = await MdzArchiveCore.open(bytes);
5
+ const entryPoint = await archive.resolveEntryPoint();
6
+ const manifest = await archive.readManifest();
7
+ const markdown = await archive.readText(entryPoint);
8
+ return { entryPoint, markdown, manifest };
9
+ }
10
+ export async function createArchiveInventory(bytes) {
11
+ const archive = await MdzArchiveCore.open(bytes);
12
+ const entryPoint = await archive.resolveEntryPoint();
13
+ const manifest = await archive.readManifest();
14
+ const archiveEntries = archive.listEntries();
15
+ const entries = [];
16
+ for (const entry of archiveEntries) {
17
+ const entryBytes = await archive.readBytes(entry.path);
18
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
19
+ const hashBuffer = await globalThis.crypto.subtle.digest('SHA-256', entryBytes);
20
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
21
+ const hash = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
22
+ let kind = 'file';
23
+ if (isMdzipManifestPath(entry.path)) {
24
+ kind = 'manifest';
25
+ }
26
+ else if (entry.isMarkdown) {
27
+ kind = 'markdown';
28
+ }
29
+ else if (entry.isImage) {
30
+ kind = 'image';
31
+ }
32
+ entries.push({
33
+ path: entry.path,
34
+ kind,
35
+ size: entryBytes.length,
36
+ hash,
37
+ });
38
+ }
39
+ return { entries, entryPoint, manifest };
40
+ }
41
+ export function diffArchiveInventories(before, after) {
42
+ const beforeMap = new Map(before.entries.map(e => [e.path, e]));
43
+ const seenPaths = new Set();
44
+ const entries = [];
45
+ let addedCount = 0;
46
+ let removedCount = 0;
47
+ let changedCount = 0;
48
+ // Walk after entries
49
+ for (const afterEntry of after.entries) {
50
+ seenPaths.add(afterEntry.path);
51
+ const beforeEntry = beforeMap.get(afterEntry.path);
52
+ if (!beforeEntry) {
53
+ // Added
54
+ entries.push({
55
+ path: afterEntry.path,
56
+ status: 'added',
57
+ kind: afterEntry.kind,
58
+ after: afterEntry,
59
+ });
60
+ addedCount++;
61
+ }
62
+ else if (beforeEntry.hash !== afterEntry.hash) {
63
+ // Changed
64
+ entries.push({
65
+ path: afterEntry.path,
66
+ status: 'changed',
67
+ kind: afterEntry.kind,
68
+ before: beforeEntry,
69
+ after: afterEntry,
70
+ });
71
+ changedCount++;
72
+ }
73
+ else {
74
+ // Unchanged
75
+ entries.push({
76
+ path: afterEntry.path,
77
+ status: 'unchanged',
78
+ kind: afterEntry.kind,
79
+ before: beforeEntry,
80
+ after: afterEntry,
81
+ });
82
+ }
83
+ }
84
+ // Walk before entries for removed
85
+ for (const beforeEntry of before.entries) {
86
+ if (!seenPaths.has(beforeEntry.path)) {
87
+ entries.push({
88
+ path: beforeEntry.path,
89
+ status: 'removed',
90
+ kind: beforeEntry.kind,
91
+ before: beforeEntry,
92
+ });
93
+ removedCount++;
94
+ }
95
+ }
96
+ // Sort by path
97
+ entries.sort((a, b) => a.path.localeCompare(b.path));
98
+ return { entries, changedCount, addedCount, removedCount };
99
+ }
100
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAoB,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAQ1D,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,KAAiB;IAEjB,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,iBAAiB,EAAE,CAAC;IACrD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAEpD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAC5C,CAAC;AAiBD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,KAAiB;IAEjB,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,iBAAiB,EAAE,CAAC;IACrD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC;IAC9C,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAE7C,MAAM,OAAO,GAA4B,EAAE,CAAC;IAE5C,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvD,iEAAiE;QACjE,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,UAA0B,CAAC,CAAC;QAChG,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAE1E,IAAI,IAAI,GAA8B,MAAM,CAAC;QAC7C,IAAI,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,IAAI,GAAG,UAAU,CAAC;QACpB,CAAC;aAAM,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YAC5B,IAAI,GAAG,UAAU,CAAC;QACpB,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YACzB,IAAI,GAAG,OAAO,CAAC;QACjB,CAAC;QAED,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI;YACJ,IAAI,EAAE,UAAU,CAAC,MAAM;YACvB,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;AAC3C,CAAC;AAmBD,MAAM,UAAU,sBAAsB,CACpC,MAAwB,EACxB,KAAuB;IAEvB,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,OAAO,GAAgC,EAAE,CAAC;IAEhD,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,qBAAqB;IACrB,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACvC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAEnD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,QAAQ;YACR,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,UAAU,CAAC,IAAI;gBACrB,MAAM,EAAE,OAAO;gBACf,IAAI,EAAE,UAAU,CAAC,IAAI;gBACrB,KAAK,EAAE,UAAU;aAClB,CAAC,CAAC;YACH,UAAU,EAAE,CAAC;QACf,CAAC;aAAM,IAAI,WAAW,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;YAChD,UAAU;YACV,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,UAAU,CAAC,IAAI;gBACrB,MAAM,EAAE,SAAS;gBACjB,IAAI,EAAE,UAAU,CAAC,IAAI;gBACrB,MAAM,EAAE,WAAW;gBACnB,KAAK,EAAE,UAAU;aAClB,CAAC,CAAC;YACH,YAAY,EAAE,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,YAAY;YACZ,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,UAAU,CAAC,IAAI;gBACrB,MAAM,EAAE,WAAW;gBACnB,IAAI,EAAE,UAAU,CAAC,IAAI;gBACrB,MAAM,EAAE,WAAW;gBACnB,KAAK,EAAE,UAAU;aAClB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACzC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,WAAW,CAAC,IAAI;gBACtB,MAAM,EAAE,SAAS;gBACjB,IAAI,EAAE,WAAW,CAAC,IAAI;gBACtB,MAAM,EAAE,WAAW;aACpB,CAAC,CAAC;YACH,YAAY,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAED,eAAe;IACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAErD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type LucideIconNode = [tag: string, attrs: Record<string, string | number | undefined>][];
2
+ export declare const MD_MARKDOWN_ICON: LucideIconNode;
3
+ //# sourceMappingURL=md-markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"md-markdown.d.ts","sourceRoot":"","sources":["../../src/icons/md-markdown.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC,EAAE,CAAC;AAEjG,eAAO,MAAM,gBAAgB,EAAE,cAiC9B,CAAC"}
@@ -0,0 +1,35 @@
1
+ export const MD_MARKDOWN_ICON = [
2
+ [
3
+ "rect",
4
+ {
5
+ "x": "2",
6
+ "y": "5",
7
+ "width": "21",
8
+ "height": "14",
9
+ "rx": "2",
10
+ "stroke-width": "1.75"
11
+ }
12
+ ],
13
+ [
14
+ "path",
15
+ {
16
+ "d": "M5.85 15.15v-6.3L9 12.63l3.15-3.78v6.3",
17
+ "stroke-width": "1.75"
18
+ }
19
+ ],
20
+ [
21
+ "path",
22
+ {
23
+ "d": "M17.55 8.9v5.25",
24
+ "stroke-width": "1.75"
25
+ }
26
+ ],
27
+ [
28
+ "path",
29
+ {
30
+ "d": "M15.4 13 17.55 15.15 19.7 13",
31
+ "stroke-width": "1.75"
32
+ }
33
+ ]
34
+ ];
35
+ //# sourceMappingURL=md-markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"md-markdown.js","sourceRoot":"","sources":["../../src/icons/md-markdown.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,gBAAgB,GAAmB;IAC9C;QACE,MAAM;QACN;YACE,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG;YACR,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,GAAG;YACT,cAAc,EAAE,MAAM;SACvB;KACF;IACD;QACE,MAAM;QACN;YACE,GAAG,EAAE,wCAAwC;YAC7C,cAAc,EAAE,MAAM;SACvB;KACF;IACD;QACE,MAAM;QACN;YACE,GAAG,EAAE,iBAAiB;YACtB,cAAc,EAAE,MAAM;SACvB;KACF;IACD;QACE,MAAM;QACN;YACE,GAAG,EAAE,8BAA8B;YACnC,cAAc,EAAE,MAAM;SACvB;KACF;CACF,CAAC"}