@inkandswitch/patchwork-pkg-base 0.0.94 → 0.0.95

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.
@@ -1 +1 @@
1
- automerge:4YKoGpUYW4XwEjpTnmPobL2EQJ5H
1
+ automerge:4TsHuZDmT7W3J3e1d54imZfg4Uu7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkandswitch/patchwork-pkg-base",
3
- "version": "0.0.94",
3
+ "version": "0.0.95",
4
4
  "type": "module",
5
5
  "description": "Base packages for the Patchwork system",
6
6
  "repository": {
@@ -1,42 +1,76 @@
1
1
  import { isImmutableString as l } from "@automerge/automerge-repo/slim";
2
- function y(e) {
3
- return e.content instanceof Uint8Array;
2
+ const w = 512, u = [37, 80, 68, 70, 45];
3
+ function F(t, e) {
4
+ if (e === 0)
5
+ return !1;
6
+ let i = 0;
7
+ const o = Math.min(e, w);
8
+ if (e >= 3 && t[0] === 239 && t[1] === 187 && t[2] === 191 || e >= 4 && t[0] === 0 && t[1] === 0 && t[2] === 254 && t[3] === 255 || e >= 4 && t[0] === 255 && t[1] === 254 && t[2] === 0 && t[3] === 0 || e >= 4 && t[0] === 132 && t[1] === 49 && t[2] === 149 && t[3] === 51)
9
+ return !1;
10
+ if (o >= 5 && u.every((n, s) => t[s] === n))
11
+ return !0;
12
+ if (e >= 2 && t[0] === 254 && t[1] === 255 || e >= 2 && t[0] === 255 && t[1] === 254)
13
+ return !1;
14
+ for (let n = 0; n < o; n++) {
15
+ if (t[n] === 0)
16
+ return !0;
17
+ if ((t[n] < 7 || t[n] > 14) && (t[n] < 32 || t[n] > 127)) {
18
+ if (t[n] >= 192 && t[n] <= 223 && n + 1 < o) {
19
+ if (n++, t[n] >= 128 && t[n] <= 191)
20
+ continue;
21
+ } else if (t[n] >= 224 && t[n] <= 239 && n + 2 < o) {
22
+ if (n++, t[n] >= 128 && t[n] <= 191 && t[n + 1] >= 128 && t[n + 1] <= 191) {
23
+ n++;
24
+ continue;
25
+ }
26
+ } else if (t[n] >= 240 && t[n] <= 247 && n + 3 < o && (n++, t[n] >= 128 && t[n] <= 191 && t[n + 1] >= 128 && t[n + 1] <= 191 && t[n + 2] >= 128 && t[n + 2] <= 191)) {
27
+ n += 2;
28
+ continue;
29
+ }
30
+ if (i++, n >= 32 && i * 100 / o > 10)
31
+ return !0;
32
+ }
33
+ }
34
+ return i * 100 / o > 10;
35
+ }
36
+ function y(t) {
37
+ return t.content instanceof Uint8Array;
4
38
  }
5
- function b(e) {
6
- return typeof e.content == "string";
39
+ function S(t) {
40
+ return typeof t.content == "string";
7
41
  }
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))
13
- return e.content;
14
- if (typeof e.content == "string")
15
- return e.content;
16
- if ("toString" in e.content && typeof e.content.toString == "function")
17
- return e.content.toString();
42
+ const g = (t) => typeof t == "object" && t !== null && !(t instanceof Uint8Array) && typeof t.val == "string", A = (t) => l(t.content) || g(t.content), I = (t) => y(t) && !F(t.content, t.content.length), N = (t) => {
43
+ const e = t == null ? void 0 : t.content;
44
+ return typeof e == "string" ? e : g(e) ? e.val : l(e) ? e.toString() : e instanceof Uint8Array ? new TextDecoder().decode(e) : "";
45
+ }, U = (t) => {
46
+ if (y(t))
47
+ return t.content;
48
+ if (typeof t.content == "string")
49
+ return t.content;
50
+ if ("toString" in t.content && typeof t.content.toString == "function")
51
+ return t.content.toString();
18
52
  throw new Error("Unsupported file content type");
19
- }, g = {
20
- init(e) {
21
- e.name = "", e.extension = "", e.mimeType = "", e.content = "";
53
+ }, T = {
54
+ init(t) {
55
+ t.name = "", t.extension = "", t.mimeType = "", t.content = "";
22
56
  },
23
- setTitle(e, t) {
24
- e.name = t;
57
+ setTitle(t, e) {
58
+ t.name = e;
25
59
  },
26
- getTitle(e) {
27
- return e.name || "Untitled File";
60
+ getTitle(t) {
61
+ return t.name || "Untitled File";
28
62
  }
29
- }, m = {
30
- init(e) {
31
- e.name = "", e.extension = "", e.mimeType = "", e.content = "";
63
+ }, D = {
64
+ init(t) {
65
+ t.name = "", t.extension = "", t.mimeType = "", t.content = "";
32
66
  },
33
- getTitle(e) {
34
- return e.name || "New File";
67
+ getTitle(t) {
68
+ return t.name || "New File";
35
69
  },
36
- setTitle(e, t) {
37
- e.name = t;
70
+ setTitle(t, e) {
71
+ t.name = e;
38
72
  }
39
- }, D = 1e5, w = ["mp4", "webm", "ogg"], F = [
73
+ }, x = 1e5, h = ["mp4", "webm", "ogg"], E = [
40
74
  "svg",
41
75
  "png",
42
76
  "jpg",
@@ -44,33 +78,33 @@ const c = (e) => typeof e == "object" && e !== null && !(e instanceof Uint8Array
44
78
  "gif",
45
79
  "webp",
46
80
  "bmp"
47
- ], E = (e) => {
48
- var t;
49
- return F.includes((t = e.extension) == null ? void 0 : t.toLowerCase());
50
- }, I = (e) => {
51
- var t;
52
- return w.includes((t = e.extension) == null ? void 0 : t.toLowerCase());
53
- }, N = (e, t) => {
54
- if (e instanceof Uint8Array)
81
+ ], O = (t) => {
82
+ var e;
83
+ return E.includes((e = t.extension) == null ? void 0 : e.toLowerCase());
84
+ }, _ = (t) => {
85
+ var e;
86
+ return h.includes((e = t.extension) == null ? void 0 : e.toLowerCase());
87
+ }, b = (t, e) => {
88
+ if (t instanceof Uint8Array)
55
89
  return URL.createObjectURL(
56
- new Blob([e], t ? { type: t } : {})
90
+ new Blob([t], e ? { type: e } : {})
57
91
  );
58
92
  };
59
- function U(e, t) {
60
- const i = e instanceof ArrayBuffer ? new Uint8Array(e) : e, r = t instanceof ArrayBuffer ? new Uint8Array(t) : t;
61
- if (i.byteLength !== r.byteLength)
93
+ function v(t, e) {
94
+ const i = t instanceof ArrayBuffer ? new Uint8Array(t) : t, o = e instanceof ArrayBuffer ? new Uint8Array(e) : e;
95
+ if (i.byteLength !== o.byteLength)
62
96
  return !1;
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))
97
+ const n = new DataView(i.buffer, i.byteOffset, i.byteLength), s = new DataView(o.buffer, o.byteOffset, o.byteLength), a = i.byteLength, c = a % 8, m = (a - c) / 8;
98
+ for (let r = 0; r < m; r++)
99
+ if (n.getBigInt64(r * 8, !0) !== s.getBigInt64(r * 8, !0))
66
100
  return !1;
67
- const a = o - s;
68
- for (let n = 0; n < s; n++)
69
- if (i[a + n] !== r[a + n])
101
+ const p = a - c;
102
+ for (let r = 0; r < c; r++)
103
+ if (i[p + r] !== o[p + r])
70
104
  return !1;
71
105
  return !0;
72
106
  }
73
- const B = [
107
+ const k = [
74
108
  {
75
109
  type: "patchwork:datatype",
76
110
  id: "file",
@@ -78,7 +112,7 @@ const B = [
78
112
  icon: "File",
79
113
  unlisted: !0,
80
114
  async load() {
81
- return g;
115
+ return T;
82
116
  }
83
117
  },
84
118
  {
@@ -88,7 +122,7 @@ const B = [
88
122
  icon: "File",
89
123
  supportedDatatypes: ["file"],
90
124
  async load() {
91
- return (await import("./tool-P7kqRAMZ.js").then((e) => e.t)).FileTool;
125
+ return (await import("./tool-DsPzbh8B.js").then((t) => t.t)).FileTool;
92
126
  }
93
127
  },
94
128
  {
@@ -97,7 +131,7 @@ const B = [
97
131
  name: "New File",
98
132
  icon: "FilePlus",
99
133
  async load() {
100
- return m;
134
+ return D;
101
135
  }
102
136
  },
103
137
  {
@@ -112,19 +146,20 @@ const B = [
112
146
  }
113
147
  ];
114
148
  export {
115
- g as FileDatatype,
116
- F as IMAGE_EXTENSIONS,
117
- D as LONG_TEXT_FILE_LENGTH_THRESHOLD,
118
- w as VIDEO_EXTENSIONS,
119
- U as compareBuffers,
120
- N as createBinaryUrl,
121
- S as fileText,
122
- h as getFileContents,
149
+ T as FileDatatype,
150
+ E as IMAGE_EXTENSIONS,
151
+ x as LONG_TEXT_FILE_LENGTH_THRESHOLD,
152
+ h as VIDEO_EXTENSIONS,
153
+ v as compareBuffers,
154
+ b as createBinaryUrl,
155
+ N as fileText,
156
+ U as getFileContents,
123
157
  y as isBinaryFileDoc,
124
- E as isImageFile,
125
- L as isImmutableStringFileDoc,
126
- b as isTextFileDoc,
127
- I as isVideoFile,
128
- B as plugins
158
+ O as isImageFile,
159
+ A as isImmutableStringFileDoc,
160
+ I as isTextBytesFileDoc,
161
+ S as isTextFileDoc,
162
+ _ as isVideoFile,
163
+ k as plugins
129
164
  };
130
165
  //# 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\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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"}
1
+ {"version":3,"file":"index.js","sources":["../src/isBinaryFile.ts","../src/datatype.ts","../src/new-file-datatype.ts","../src/types.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["// This function was extracted from\n// https://github.com/gjtorikian/isBinaryFile/blob/main/src/index.ts#L158\n\nconst MAX_BYTES = 512;\n\nconst PDF_HEADER = [0x25, 0x50, 0x44, 0x46, 0x2d];\n\nexport function isBinaryCheck(\n fileBuffer: Uint8Array,\n bytesRead: number\n): boolean {\n // empty file. no clue what it is.\n if (bytesRead === 0) {\n return false;\n }\n\n let suspiciousBytes = 0;\n const totalBytes = Math.min(bytesRead, MAX_BYTES);\n\n // UTF-8 BOM\n if (\n bytesRead >= 3 &&\n fileBuffer[0] === 0xef &&\n fileBuffer[1] === 0xbb &&\n fileBuffer[2] === 0xbf\n ) {\n return false;\n }\n\n // UTF-32 BOM\n if (\n bytesRead >= 4 &&\n fileBuffer[0] === 0x00 &&\n fileBuffer[1] === 0x00 &&\n fileBuffer[2] === 0xfe &&\n fileBuffer[3] === 0xff\n ) {\n return false;\n }\n\n // UTF-32 LE BOM\n if (\n bytesRead >= 4 &&\n fileBuffer[0] === 0xff &&\n fileBuffer[1] === 0xfe &&\n fileBuffer[2] === 0x00 &&\n fileBuffer[3] === 0x00\n ) {\n return false;\n }\n\n // GB BOM\n if (\n bytesRead >= 4 &&\n fileBuffer[0] === 0x84 &&\n fileBuffer[1] === 0x31 &&\n fileBuffer[2] === 0x95 &&\n fileBuffer[3] === 0x33\n ) {\n return false;\n }\n\n if (totalBytes >= 5 && PDF_HEADER.every((byte, i) => fileBuffer[i] === byte)) {\n /* PDF. This is binary. */\n return true;\n }\n\n // UTF-16 BE BOM\n if (bytesRead >= 2 && fileBuffer[0] === 0xfe && fileBuffer[1] === 0xff) {\n return false;\n }\n\n // UTF-16 LE BOM\n if (bytesRead >= 2 && fileBuffer[0] === 0xff && fileBuffer[1] === 0xfe) {\n return false;\n }\n\n for (let i = 0; i < totalBytes; i++) {\n if (fileBuffer[i] === 0) {\n // NULL byte--it's binary!\n return true;\n } else if (\n (fileBuffer[i] < 7 || fileBuffer[i] > 14) &&\n (fileBuffer[i] < 32 || fileBuffer[i] > 127)\n ) {\n // UTF-8 detection\n if (\n fileBuffer[i] >= 0xc0 &&\n fileBuffer[i] <= 0xdf &&\n i + 1 < totalBytes\n ) {\n i++;\n if (fileBuffer[i] >= 0x80 && fileBuffer[i] <= 0xbf) {\n continue;\n }\n } else if (\n fileBuffer[i] >= 0xe0 &&\n fileBuffer[i] <= 0xef &&\n i + 2 < totalBytes\n ) {\n i++;\n if (\n fileBuffer[i] >= 0x80 &&\n fileBuffer[i] <= 0xbf &&\n fileBuffer[i + 1] >= 0x80 &&\n fileBuffer[i + 1] <= 0xbf\n ) {\n i++;\n continue;\n }\n } else if (\n fileBuffer[i] >= 0xf0 &&\n fileBuffer[i] <= 0xf7 &&\n i + 3 < totalBytes\n ) {\n i++;\n if (\n fileBuffer[i] >= 0x80 &&\n fileBuffer[i] <= 0xbf &&\n fileBuffer[i + 1] >= 0x80 &&\n fileBuffer[i + 1] <= 0xbf &&\n fileBuffer[i + 2] >= 0x80 &&\n fileBuffer[i + 2] <= 0xbf\n ) {\n i += 2;\n continue;\n }\n }\n\n suspiciousBytes++;\n // Read at least 32 fileBuffer before making a decision\n if (i >= 32 && (suspiciousBytes * 100) / totalBytes > 10) {\n return true;\n }\n }\n }\n\n if ((suspiciousBytes * 100) / totalBytes > 10) {\n return true;\n }\n\n return false;\n}\n","// File datatype implementation\n\nimport {isImmutableString} from \"@automerge/automerge-repo/slim\"\nimport {BinaryFileDoc, FileDoc, TextFileDoc} from \"./types\"\nimport {isBinaryCheck} from \"./isBinaryFile\"\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// Text that was stored as bytes (e.g. synced in by a tool that didn't know it\n// was text). It can be shown, but not edited as text.\nexport const isTextBytesFileDoc = (doc: FileDoc): boolean =>\n\tisBinaryFileDoc(doc) && !isBinaryCheck(doc.content, doc.content.length)\n\n// The text of a text file, whichever way it's stored (a string, an\n// ImmutableString, a cloned one, or UTF-8 bytes).\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\tif (content instanceof Uint8Array) return new TextDecoder().decode(content)\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":["MAX_BYTES","PDF_HEADER","isBinaryCheck","fileBuffer","bytesRead","suspiciousBytes","totalBytes","byte","i","isBinaryFileDoc","doc","isTextFileDoc","isClonedImmutableString","content","isImmutableStringFileDoc","isImmutableString","isTextBytesFileDoc","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","startByte","plugins","n"],"mappings":"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"}