@inkandswitch/patchwork-pkg-base 0.0.86 → 0.0.88
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/module-settings-url +1 -1
- package/package.json +1 -1
- package/packages/file/dist/assets/tsgo-worker-BDQ8_wHH.js +4 -0
- package/packages/file/dist/assets/tsgo-worker-BDQ8_wHH.js.map +4 -0
- package/packages/file/dist/assets/wasm_exec-pYYJXccF.js +440 -0
- package/packages/file/dist/assets/wasm_exec-pYYJXccF.js.map +1 -0
- package/packages/file/dist/index.js +36 -32
- package/packages/file/dist/index.js.map +1 -1
- package/packages/file/dist/{tool-DdWP0SYf.js → tool-B3O4i8l2.js} +2759 -3006
- package/packages/file/dist/tool-B3O4i8l2.js.map +1 -0
- package/packages/file/dist/typescript-language-server-oTU8pKzb.js +3408 -0
- package/packages/file/dist/typescript-language-server-oTU8pKzb.js.map +1 -0
- package/packages/file/package.json +3 -3
- package/plugin-registry-url +1 -1
- package/packages/file/dist/index-CW1_LDsW.js +0 -827
- package/packages/file/dist/index-CW1_LDsW.js.map +0 -1
- package/packages/file/dist/tool-DdWP0SYf.js.map +0 -1
- package/packages/file/dist/ts-env-B6QylQR-.js +0 -67681
- package/packages/file/dist/ts-env-B6QylQR-.js.map +0 -1
- package/packages/file/dist/typescript-CWj5JjVs.js +0 -159802
- package/packages/file/dist/typescript-CWj5JjVs.js.map +0 -1
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import { isImmutableString as
|
|
2
|
-
function
|
|
1
|
+
import { isImmutableString as l } from "@automerge/automerge-repo/slim";
|
|
2
|
+
function y(e) {
|
|
3
3
|
return e.content instanceof Uint8Array;
|
|
4
4
|
}
|
|
5
|
-
function
|
|
5
|
+
function b(e) {
|
|
6
6
|
return typeof e.content == "string";
|
|
7
7
|
}
|
|
8
|
-
const L = (e) =>
|
|
9
|
-
|
|
8
|
+
const c = (e) => typeof e == "object" && e !== null && !(e instanceof Uint8Array) && typeof e.val == "string", L = (e) => l(e.content) || c(e.content), S = (e) => {
|
|
9
|
+
const t = e == null ? void 0 : e.content;
|
|
10
|
+
return typeof t == "string" ? t : c(t) ? t.val : l(t) ? t.toString() : "";
|
|
11
|
+
}, h = (e) => {
|
|
12
|
+
if (y(e))
|
|
10
13
|
return e.content;
|
|
11
14
|
if (typeof e.content == "string")
|
|
12
15
|
return e.content;
|
|
13
16
|
if ("toString" in e.content && typeof e.content.toString == "function")
|
|
14
17
|
return e.content.toString();
|
|
15
18
|
throw new Error("Unsupported file content type");
|
|
16
|
-
},
|
|
19
|
+
}, g = {
|
|
17
20
|
init(e) {
|
|
18
21
|
e.name = "", e.extension = "", e.mimeType = "", e.content = "";
|
|
19
22
|
},
|
|
@@ -23,7 +26,7 @@ const L = (e) => p(e.content), b = (e) => {
|
|
|
23
26
|
getTitle(e) {
|
|
24
27
|
return e.name || "Untitled File";
|
|
25
28
|
}
|
|
26
|
-
},
|
|
29
|
+
}, m = {
|
|
27
30
|
init(e) {
|
|
28
31
|
e.name = "", e.extension = "", e.mimeType = "", e.content = "";
|
|
29
32
|
},
|
|
@@ -33,7 +36,7 @@ const L = (e) => p(e.content), b = (e) => {
|
|
|
33
36
|
setTitle(e, t) {
|
|
34
37
|
e.name = t;
|
|
35
38
|
}
|
|
36
|
-
},
|
|
39
|
+
}, D = 1e5, w = ["mp4", "webm", "ogg"], F = [
|
|
37
40
|
"svg",
|
|
38
41
|
"png",
|
|
39
42
|
"jpg",
|
|
@@ -41,10 +44,10 @@ const L = (e) => p(e.content), b = (e) => {
|
|
|
41
44
|
"gif",
|
|
42
45
|
"webp",
|
|
43
46
|
"bmp"
|
|
44
|
-
],
|
|
47
|
+
], E = (e) => {
|
|
45
48
|
var t;
|
|
46
|
-
return
|
|
47
|
-
},
|
|
49
|
+
return F.includes((t = e.extension) == null ? void 0 : t.toLowerCase());
|
|
50
|
+
}, I = (e) => {
|
|
48
51
|
var t;
|
|
49
52
|
return w.includes((t = e.extension) == null ? void 0 : t.toLowerCase());
|
|
50
53
|
}, N = (e, t) => {
|
|
@@ -53,21 +56,21 @@ const L = (e) => p(e.content), b = (e) => {
|
|
|
53
56
|
new Blob([e], t ? { type: t } : {})
|
|
54
57
|
);
|
|
55
58
|
};
|
|
56
|
-
function
|
|
59
|
+
function U(e, t) {
|
|
57
60
|
const i = e instanceof ArrayBuffer ? new Uint8Array(e) : e, r = t instanceof ArrayBuffer ? new Uint8Array(t) : t;
|
|
58
61
|
if (i.byteLength !== r.byteLength)
|
|
59
62
|
return !1;
|
|
60
|
-
const
|
|
61
|
-
for (let n = 0; n <
|
|
62
|
-
if (
|
|
63
|
+
const f = new DataView(i.buffer, i.byteOffset, i.byteLength), u = new DataView(r.buffer, r.byteOffset, r.byteLength), o = i.byteLength, s = o % 8, p = (o - s) / 8;
|
|
64
|
+
for (let n = 0; n < p; n++)
|
|
65
|
+
if (f.getBigInt64(n * 8, !0) !== u.getBigInt64(n * 8, !0))
|
|
63
66
|
return !1;
|
|
64
|
-
const
|
|
65
|
-
for (let n = 0; n <
|
|
66
|
-
if (i[
|
|
67
|
+
const a = o - s;
|
|
68
|
+
for (let n = 0; n < s; n++)
|
|
69
|
+
if (i[a + n] !== r[a + n])
|
|
67
70
|
return !1;
|
|
68
71
|
return !0;
|
|
69
72
|
}
|
|
70
|
-
const
|
|
73
|
+
const B = [
|
|
71
74
|
{
|
|
72
75
|
type: "patchwork:datatype",
|
|
73
76
|
id: "file",
|
|
@@ -75,7 +78,7 @@ const I = [
|
|
|
75
78
|
icon: "File",
|
|
76
79
|
unlisted: !0,
|
|
77
80
|
async load() {
|
|
78
|
-
return
|
|
81
|
+
return g;
|
|
79
82
|
}
|
|
80
83
|
},
|
|
81
84
|
{
|
|
@@ -85,7 +88,7 @@ const I = [
|
|
|
85
88
|
icon: "File",
|
|
86
89
|
supportedDatatypes: ["file"],
|
|
87
90
|
async load() {
|
|
88
|
-
return (await import("./tool-
|
|
91
|
+
return (await import("./tool-B3O4i8l2.js").then((e) => e.t)).FileTool;
|
|
89
92
|
}
|
|
90
93
|
},
|
|
91
94
|
{
|
|
@@ -94,7 +97,7 @@ const I = [
|
|
|
94
97
|
name: "New File",
|
|
95
98
|
icon: "FilePlus",
|
|
96
99
|
async load() {
|
|
97
|
-
return
|
|
100
|
+
return m;
|
|
98
101
|
}
|
|
99
102
|
},
|
|
100
103
|
{
|
|
@@ -109,18 +112,19 @@ const I = [
|
|
|
109
112
|
}
|
|
110
113
|
];
|
|
111
114
|
export {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
g as FileDatatype,
|
|
116
|
+
F as IMAGE_EXTENSIONS,
|
|
117
|
+
D as LONG_TEXT_FILE_LENGTH_THRESHOLD,
|
|
115
118
|
w as VIDEO_EXTENSIONS,
|
|
116
|
-
|
|
119
|
+
U as compareBuffers,
|
|
117
120
|
N as createBinaryUrl,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
+
S as fileText,
|
|
122
|
+
h as getFileContents,
|
|
123
|
+
y as isBinaryFileDoc,
|
|
124
|
+
E as isImageFile,
|
|
121
125
|
L as isImmutableStringFileDoc,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
b as isTextFileDoc,
|
|
127
|
+
I as isVideoFile,
|
|
128
|
+
B as plugins
|
|
125
129
|
};
|
|
126
130
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/datatype.ts","../src/new-file-datatype.ts","../src/types.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["// File datatype implementation\n\nimport {isImmutableString} from \"@automerge/automerge-repo/slim\"\nimport {BinaryFileDoc, FileDoc, TextFileDoc} from \"./types\"\n\nexport function isBinaryFileDoc(doc: FileDoc): doc is BinaryFileDoc {\n\treturn doc.content instanceof Uint8Array\n}\n\nexport function isTextFileDoc(doc: FileDoc): doc is TextFileDoc {\n\treturn typeof doc.content === \"string\"\n}\n\nexport const isImmutableStringFileDoc = (doc: FileDoc): boolean => {\n\treturn isImmutableString(doc.content)\n}\n\n// Get file contents as string or Uint8Array\nexport const getFileContents = (doc: FileDoc): string | Uint8Array => {\n\tif (isBinaryFileDoc(doc)) {\n\t\treturn doc.content\n\t} else if (typeof doc.content === \"string\") {\n\t\treturn doc.content\n\t} else if (\n\t\t\"toString\" in doc.content &&\n\t\ttypeof doc.content.toString == \"function\"\n\t) {\n\t\tconst content = doc.content\n\t\treturn content.toString()\n\t} else {\n\t\tthrow new Error(\"Unsupported file content type\")\n\t}\n}\n\n// Datatype implementation\nexport const FileDatatype = {\n\tinit(doc: FileDoc) {\n\t\tdoc.name = \"\"\n\t\tdoc.extension = \"\"\n\t\tdoc.mimeType = \"\"\n\t\tdoc.content = \"\"\n\t},\n\n\tsetTitle(doc: FileDoc, title: string) {\n\t\tdoc.name = title\n\t},\n\n\tgetTitle(doc: FileDoc) {\n\t\treturn doc.name || \"Untitled File\"\n\t},\n}\n","// \"New File\" datatype — a listed datatype that acts as a creation prompt.\n// Once the user enters a filename, the doc flips to type \"file\".\n\nimport type {FileDoc} from \"./types\"\n\nexport const NewFileDatatype = {\n\tinit(doc: FileDoc) {\n\t\tdoc.name = \"\"\n\t\tdoc.extension = \"\"\n\t\tdoc.mimeType = \"\"\n\t\tdoc.content = \"\"\n\t},\n\n\tgetTitle(doc: FileDoc) {\n\t\treturn doc.name || \"New File\"\n\t},\n\n\tsetTitle(doc: FileDoc, title: string) {\n\t\tdoc.name = title\n\t},\n}\n","// File document types\n\nimport type {ImmutableString} from \"@automerge/automerge-repo/slim\"\nimport type {UnixFileEntry} from \"@inkandswitch/patchwork-filesystem\"\n\nexport type TextFileDoc = {\n\tname: string\n\textension: string\n\tmimeType: string\n\tcontent: string\n}\n\nexport type BinaryFileDoc = {\n\tname: string\n\textension: string\n\tmimeType: string\n\tcontent: Uint8Array\n}\n\nexport type ImmutableStringFileDoc = {\n\tname: string\n\textension: string\n\tmimeType: string\n\tcontent: ImmutableString\n}\n\nexport type FileDoc = UnixFileEntry\n\n// Conservatively use LongTextFileContent for text files longer than 100KB.\nexport const LONG_TEXT_FILE_LENGTH_THRESHOLD = 100000\n","// Utility functions for file handling\n\nexport const VIDEO_EXTENSIONS = [\"mp4\", \"webm\", \"ogg\"]\nexport const IMAGE_EXTENSIONS = [\n\t\"svg\",\n\t\"png\",\n\t\"jpg\",\n\t\"jpeg\",\n\t\"gif\",\n\t\"webp\",\n\t\"bmp\",\n]\n\nexport const isImageFile = (doc: {extension: string}) => {\n\treturn IMAGE_EXTENSIONS.includes(doc.extension?.toLowerCase())\n}\n\nexport const isVideoFile = (doc: {extension: string}) => {\n\treturn VIDEO_EXTENSIONS.includes(doc.extension?.toLowerCase())\n}\n\n// An object URL carries the blob's type as its Content-Type. Without one the\n// browser resolves the response as text/plain, which is fine for <img> (it\n// sniffs the bytes) but means an <iframe> renders a PDF as source instead of\n// handing it to the built-in viewer.\nexport const createBinaryUrl = (\n\tvalue: Uint8Array | undefined,\n\tmimeType?: string\n): string | undefined => {\n\tif (!(value instanceof Uint8Array)) {\n\t\treturn undefined\n\t}\n\n\treturn URL.createObjectURL(\n\t\tnew Blob([value as BlobPart], mimeType ? {type: mimeType} : {})\n\t)\n}\n\n/**\n * Efficiently compares two array buffers or typed arrays for equality.\n * Optimized for large buffers (10MB+) by comparing in 64-bit chunks.\n * @param {ArrayBuffer|Uint8Array} buf1 First buffer to compare\n * @param {ArrayBuffer|Uint8Array} buf2 Second buffer to compare\n * @returns {boolean} True if buffers are identical, false otherwise\n */\nexport function compareBuffers(\n\tbuf1: ArrayBuffer | Uint8Array,\n\tbuf2: ArrayBuffer | Uint8Array\n): boolean {\n\t// Convert ArrayBuffers to Uint8Arrays if needed\n\tconst a1 = buf1 instanceof ArrayBuffer ? new Uint8Array(buf1) : buf1\n\tconst a2 = buf2 instanceof ArrayBuffer ? new Uint8Array(buf2) : buf2\n\n\tif (a1.byteLength !== a2.byteLength) {\n\t\treturn false\n\t}\n\n\t// Use DataView for fast 64-bit comparisons\n\tconst dv1 = new DataView(a1.buffer, a1.byteOffset, a1.byteLength)\n\tconst dv2 = new DataView(a2.buffer, a2.byteOffset, a2.byteLength)\n\n\tconst len = a1.byteLength\n\tconst remainder = len % 8\n\tconst loops = (len - remainder) / 8\n\n\t// Compare 8 bytes at a time using BigInt64\n\tfor (let i = 0; i < loops; i++) {\n\t\tif (dv1.getBigInt64(i * 8, true) !== dv2.getBigInt64(i * 8, true)) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t// Compare any remaining bytes individually\n\tconst startByte = len - remainder\n\tfor (let i = 0; i < remainder; i++) {\n\t\tif (a1[startByte + i] !== a2[startByte + i]) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n","// File plugin for Patchwork\n// Bundleless plugin that supports viewing and editing various file types\n\nimport {FileDatatype} from \"./datatype\"\nimport {NewFileDatatype} from \"./new-file-datatype\"\n\nexport * from \"./types\"\nexport * from \"./datatype\"\nexport * from \"./utils\"\n\nexport const plugins = [\n\t{\n\t\ttype: \"patchwork:datatype\",\n\t\tid: \"file\",\n\t\tname: \"File\",\n\t\ticon: \"File\",\n\t\tunlisted: true,\n\t\tasync load() {\n\t\t\treturn FileDatatype\n\t\t},\n\t},\n\t{\n\t\ttype: \"patchwork:tool\",\n\t\tid: \"file\",\n\t\tname: \"File\",\n\t\ticon: \"File\",\n\t\tsupportedDatatypes: [\"file\"],\n\t\tasync load() {\n\t\t\treturn (await import(\"./tool\")).FileTool\n\t\t},\n\t},\n\t{\n\t\ttype: \"patchwork:datatype\",\n\t\tid: \"new-file\",\n\t\tname: \"New File\",\n\t\ticon: \"FilePlus\",\n\t\tasync load() {\n\t\t\treturn NewFileDatatype\n\t\t},\n\t},\n\t{\n\t\ttype: \"patchwork:tool\",\n\t\tid: \"new-file\",\n\t\tname: \"New File\",\n\t\ticon: \"FilePlus\",\n\t\tsupportedDatatypes: [\"new-file\"],\n\t\tasync load() {\n\t\t\treturn (await import(\"./new-file-tool\")).NewFileTool\n\t\t},\n\t},\n]\n"],"names":["isBinaryFileDoc","doc","isTextFileDoc","isImmutableStringFileDoc","isImmutableString","getFileContents","FileDatatype","title","NewFileDatatype","LONG_TEXT_FILE_LENGTH_THRESHOLD","VIDEO_EXTENSIONS","IMAGE_EXTENSIONS","isImageFile","_a","isVideoFile","createBinaryUrl","value","mimeType","compareBuffers","buf1","buf2","a1","a2","dv1","dv2","len","remainder","loops","i","startByte","plugins","n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/datatype.ts","../src/new-file-datatype.ts","../src/types.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["// File datatype implementation\n\nimport {isImmutableString} from \"@automerge/automerge-repo/slim\"\nimport {BinaryFileDoc, FileDoc, TextFileDoc} from \"./types\"\n\nexport function isBinaryFileDoc(doc: FileDoc): doc is BinaryFileDoc {\n\treturn doc.content instanceof Uint8Array\n}\n\nexport function isTextFileDoc(doc: FileDoc): doc is TextFileDoc {\n\treturn typeof doc.content === \"string\"\n}\n\n// An ImmutableString that's been through structuredClone (as solid-automerge's\n// document projection does) loses its symbol marker and its prototype and\n// comes out as a plain {val: \"...\"}, so that counts as one too.\nconst isClonedImmutableString = (content: unknown): content is {val: string} =>\n\ttypeof content === \"object\" &&\n\tcontent !== null &&\n\t!(content instanceof Uint8Array) &&\n\ttypeof (content as {val?: unknown}).val === \"string\"\n\nexport const isImmutableStringFileDoc = (doc: FileDoc): boolean => {\n\treturn isImmutableString(doc.content) || isClonedImmutableString(doc.content)\n}\n\n// The text of a text file, whichever way it's stored (a string, an\n// ImmutableString, or a cloned one).\nexport const fileText = (doc: FileDoc | undefined): string => {\n\tconst content = doc?.content as unknown\n\tif (typeof content === \"string\") return content\n\tif (isClonedImmutableString(content)) return content.val\n\tif (isImmutableString(content)) return content.toString()\n\treturn \"\"\n}\n\n// Get file contents as string or Uint8Array\nexport const getFileContents = (doc: FileDoc): string | Uint8Array => {\n\tif (isBinaryFileDoc(doc)) {\n\t\treturn doc.content\n\t} else if (typeof doc.content === \"string\") {\n\t\treturn doc.content\n\t} else if (\n\t\t\"toString\" in doc.content &&\n\t\ttypeof doc.content.toString == \"function\"\n\t) {\n\t\tconst content = doc.content\n\t\treturn content.toString()\n\t} else {\n\t\tthrow new Error(\"Unsupported file content type\")\n\t}\n}\n\n// Datatype implementation\nexport const FileDatatype = {\n\tinit(doc: FileDoc) {\n\t\tdoc.name = \"\"\n\t\tdoc.extension = \"\"\n\t\tdoc.mimeType = \"\"\n\t\tdoc.content = \"\"\n\t},\n\n\tsetTitle(doc: FileDoc, title: string) {\n\t\tdoc.name = title\n\t},\n\n\tgetTitle(doc: FileDoc) {\n\t\treturn doc.name || \"Untitled File\"\n\t},\n}\n","// \"New File\" datatype — a listed datatype that acts as a creation prompt.\n// Once the user enters a filename, the doc flips to type \"file\".\n\nimport type {FileDoc} from \"./types\"\n\nexport const NewFileDatatype = {\n\tinit(doc: FileDoc) {\n\t\tdoc.name = \"\"\n\t\tdoc.extension = \"\"\n\t\tdoc.mimeType = \"\"\n\t\tdoc.content = \"\"\n\t},\n\n\tgetTitle(doc: FileDoc) {\n\t\treturn doc.name || \"New File\"\n\t},\n\n\tsetTitle(doc: FileDoc, title: string) {\n\t\tdoc.name = title\n\t},\n}\n","// File document types\n\nimport type {ImmutableString} from \"@automerge/automerge-repo/slim\"\nimport type {UnixFileEntry} from \"@inkandswitch/patchwork-filesystem\"\n\nexport type TextFileDoc = {\n\tname: string\n\textension: string\n\tmimeType: string\n\tcontent: string\n}\n\nexport type BinaryFileDoc = {\n\tname: string\n\textension: string\n\tmimeType: string\n\tcontent: Uint8Array\n}\n\nexport type ImmutableStringFileDoc = {\n\tname: string\n\textension: string\n\tmimeType: string\n\tcontent: ImmutableString\n}\n\nexport type FileDoc = UnixFileEntry\n\n// Conservatively use LongTextFileContent for text files longer than 100KB.\nexport const LONG_TEXT_FILE_LENGTH_THRESHOLD = 100000\n","// Utility functions for file handling\n\nexport const VIDEO_EXTENSIONS = [\"mp4\", \"webm\", \"ogg\"]\nexport const IMAGE_EXTENSIONS = [\n\t\"svg\",\n\t\"png\",\n\t\"jpg\",\n\t\"jpeg\",\n\t\"gif\",\n\t\"webp\",\n\t\"bmp\",\n]\n\nexport const isImageFile = (doc: {extension: string}) => {\n\treturn IMAGE_EXTENSIONS.includes(doc.extension?.toLowerCase())\n}\n\nexport const isVideoFile = (doc: {extension: string}) => {\n\treturn VIDEO_EXTENSIONS.includes(doc.extension?.toLowerCase())\n}\n\n// An object URL carries the blob's type as its Content-Type. Without one the\n// browser resolves the response as text/plain, which is fine for <img> (it\n// sniffs the bytes) but means an <iframe> renders a PDF as source instead of\n// handing it to the built-in viewer.\nexport const createBinaryUrl = (\n\tvalue: Uint8Array | undefined,\n\tmimeType?: string\n): string | undefined => {\n\tif (!(value instanceof Uint8Array)) {\n\t\treturn undefined\n\t}\n\n\treturn URL.createObjectURL(\n\t\tnew Blob([value as BlobPart], mimeType ? {type: mimeType} : {})\n\t)\n}\n\n/**\n * Efficiently compares two array buffers or typed arrays for equality.\n * Optimized for large buffers (10MB+) by comparing in 64-bit chunks.\n * @param {ArrayBuffer|Uint8Array} buf1 First buffer to compare\n * @param {ArrayBuffer|Uint8Array} buf2 Second buffer to compare\n * @returns {boolean} True if buffers are identical, false otherwise\n */\nexport function compareBuffers(\n\tbuf1: ArrayBuffer | Uint8Array,\n\tbuf2: ArrayBuffer | Uint8Array\n): boolean {\n\t// Convert ArrayBuffers to Uint8Arrays if needed\n\tconst a1 = buf1 instanceof ArrayBuffer ? new Uint8Array(buf1) : buf1\n\tconst a2 = buf2 instanceof ArrayBuffer ? new Uint8Array(buf2) : buf2\n\n\tif (a1.byteLength !== a2.byteLength) {\n\t\treturn false\n\t}\n\n\t// Use DataView for fast 64-bit comparisons\n\tconst dv1 = new DataView(a1.buffer, a1.byteOffset, a1.byteLength)\n\tconst dv2 = new DataView(a2.buffer, a2.byteOffset, a2.byteLength)\n\n\tconst len = a1.byteLength\n\tconst remainder = len % 8\n\tconst loops = (len - remainder) / 8\n\n\t// Compare 8 bytes at a time using BigInt64\n\tfor (let i = 0; i < loops; i++) {\n\t\tif (dv1.getBigInt64(i * 8, true) !== dv2.getBigInt64(i * 8, true)) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t// Compare any remaining bytes individually\n\tconst startByte = len - remainder\n\tfor (let i = 0; i < remainder; i++) {\n\t\tif (a1[startByte + i] !== a2[startByte + i]) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n","// File plugin for Patchwork\n// Bundleless plugin that supports viewing and editing various file types\n\nimport {FileDatatype} from \"./datatype\"\nimport {NewFileDatatype} from \"./new-file-datatype\"\n\nexport * from \"./types\"\nexport * from \"./datatype\"\nexport * from \"./utils\"\n\nexport const plugins = [\n\t{\n\t\ttype: \"patchwork:datatype\",\n\t\tid: \"file\",\n\t\tname: \"File\",\n\t\ticon: \"File\",\n\t\tunlisted: true,\n\t\tasync load() {\n\t\t\treturn FileDatatype\n\t\t},\n\t},\n\t{\n\t\ttype: \"patchwork:tool\",\n\t\tid: \"file\",\n\t\tname: \"File\",\n\t\ticon: \"File\",\n\t\tsupportedDatatypes: [\"file\"],\n\t\tasync load() {\n\t\t\treturn (await import(\"./tool\")).FileTool\n\t\t},\n\t},\n\t{\n\t\ttype: \"patchwork:datatype\",\n\t\tid: \"new-file\",\n\t\tname: \"New File\",\n\t\ticon: \"FilePlus\",\n\t\tasync load() {\n\t\t\treturn NewFileDatatype\n\t\t},\n\t},\n\t{\n\t\ttype: \"patchwork:tool\",\n\t\tid: \"new-file\",\n\t\tname: \"New File\",\n\t\ticon: \"FilePlus\",\n\t\tsupportedDatatypes: [\"new-file\"],\n\t\tasync load() {\n\t\t\treturn (await import(\"./new-file-tool\")).NewFileTool\n\t\t},\n\t},\n]\n"],"names":["isBinaryFileDoc","doc","isTextFileDoc","isClonedImmutableString","content","isImmutableStringFileDoc","isImmutableString","fileText","getFileContents","FileDatatype","title","NewFileDatatype","LONG_TEXT_FILE_LENGTH_THRESHOLD","VIDEO_EXTENSIONS","IMAGE_EXTENSIONS","isImageFile","_a","isVideoFile","createBinaryUrl","value","mimeType","compareBuffers","buf1","buf2","a1","a2","dv1","dv2","len","remainder","loops","i","startByte","plugins","n"],"mappings":"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"}
|