@inkandswitch/patchwork-pkg-base 0.0.98 → 0.0.100
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/chat/dist/index.js +1 -1
- package/packages/comments-view/dist/assets/{main-51fB7vpU.js → main-wSSvAVfi.js} +22 -4
- package/packages/comments-view/dist/assets/main-wSSvAVfi.js.map +1 -0
- package/packages/comments-view/dist/index.js +3 -3
- package/packages/drafts/dist/assets/main-CG9HOCai.js +11 -0
- package/packages/embed/dist/assets/{tool-Cg7zrpH9.js → tool-D58NGTZ7.js} +4 -2
- package/packages/embed/dist/assets/tool-D58NGTZ7.js.map +1 -0
- package/packages/embed/dist/index.js +1 -1
- package/packages/file/dist/index.js +24 -25
- package/packages/file/dist/index.js.map +1 -1
- package/packages/file/dist/{tool-D5jQjo2l.js → tool-UKWDK93W.js} +1740 -1742
- package/packages/file/dist/{tool-D5jQjo2l.js.map → tool-UKWDK93W.js.map} +1 -1
- package/packages/file/dist/{typescript-language-server-BOT6JPPD.js → typescript-language-server-BgBx0vSF.js} +2 -2
- package/packages/file/dist/{typescript-language-server-BOT6JPPD.js.map → typescript-language-server-BgBx0vSF.js.map} +1 -1
- package/packages/folder/dist/index.js +1 -1
- package/packages/folder/dist/{tool-JSQNX2I6.js → tool-WAWTPB4A.js} +2 -2
- package/packages/folder/dist/{tool-JSQNX2I6.js.map → tool-WAWTPB4A.js.map} +1 -1
- package/packages/history-view/dist/assets/{HistoryTimeline-OAiVykO2.js → HistoryTimeline-COYNGORP.js} +4 -4
- package/packages/history-view/dist/assets/{HistoryTimeline-OAiVykO2.js.map → HistoryTimeline-COYNGORP.js.map} +1 -1
- package/packages/history-view/dist/assets/{index-CWHr7XoV.js → index-C1gYt7m5.js} +2 -2
- package/packages/history-view/dist/assets/{index-CWHr7XoV.js.map → index-C1gYt7m5.js.map} +1 -1
- package/packages/history-view/dist/index.js +1 -1
- package/packages/llm-host/dist/LlmConfigTray-DdZHZT4F.js +615 -0
- package/packages/llm-host/dist/index.js +1 -1
- package/packages/packages/dist/index.js +17 -0
- package/packages/sideboard/dist/{chunk-QLI3ZN4W.js → chunk-73XN2I2U.js} +3 -3
- package/packages/sideboard/dist/chunk-NS3ADG2Z.js +2 -0
- package/packages/sideboard/dist/chunk-NS3ADG2Z.js.map +7 -0
- package/packages/sideboard/dist/{chunk-3HE5SPGR.js → chunk-OFWMAVKQ.js} +2 -2
- package/packages/sideboard/dist/{create-new-menu-PDAHMB7O.js → create-new-menu-4VNS2UFI.js} +2 -2
- package/packages/sideboard/dist/document-list-panel-SCICIJCF.js +2 -0
- package/packages/sideboard/dist/index.css +1 -1
- package/packages/sideboard/dist/index.css.map +2 -2
- package/packages/sideboard/dist/index.js +1 -1
- package/packages/sideboard/dist/{item-menu-VIMMKF26.js → item-menu-3JUJN3MS.js} +2 -2
- package/packages/sideboard/dist/sideboard/sideboard.js +1 -1
- package/packages/sync-indicator/dist/assets/SyncIndicator-B2ag1OoZ.js +1 -1
- package/packages/theming/dist/{active-theme-ZEJCS5RM.js → active-theme-BMSIQXBV.js} +2 -2
- package/packages/theming/dist/{chunk-FLDRNDLY.js → chunk-Z3JB7ERH.js} +2 -2
- package/packages/theming/dist/main.js +3 -3
- package/packages/theming/dist/{theme-L3L6DYF3.css → theme-7OG2K56L.css} +2 -0
- package/packages/theming/dist/{theme-titlebar-HAEXLVMW.js → theme-titlebar-YIFJINPJ.js} +2 -2
- package/packages/theming/dist/{theme-tray-XYB4LGZ6.js → theme-tray-7J247NRY.js} +33 -13
- package/packages/theming/dist/theme-tray-7J247NRY.js.map +7 -0
- package/packages/theming/dist/tool.js +1 -1
- package/plugin-registry-url +1 -1
- package/packages/comments-view/dist/assets/main-51fB7vpU.js.map +0 -1
- package/packages/embed/dist/assets/tool-Cg7zrpH9.js.map +0 -1
- package/packages/llm-host/dist/LlmConfigTray-CkM9XUX1.js +0 -600
- package/packages/sideboard/dist/chunk-6LWWNFKU.js +0 -2
- package/packages/sideboard/dist/chunk-6LWWNFKU.js.map +0 -7
- package/packages/sideboard/dist/document-list-panel-C7R2SL7S.js +0 -2
- package/packages/theming/dist/theme-tray-XYB4LGZ6.js.map +0 -7
- /package/packages/sideboard/dist/{chunk-QLI3ZN4W.js.map → chunk-73XN2I2U.js.map} +0 -0
- /package/packages/sideboard/dist/{chunk-3HE5SPGR.js.map → chunk-OFWMAVKQ.js.map} +0 -0
- /package/packages/sideboard/dist/{create-new-menu-PDAHMB7O.js.map → create-new-menu-4VNS2UFI.js.map} +0 -0
- /package/packages/sideboard/dist/{document-list-panel-C7R2SL7S.js.map → document-list-panel-SCICIJCF.js.map} +0 -0
- /package/packages/sideboard/dist/{item-menu-VIMMKF26.js.map → item-menu-3JUJN3MS.js.map} +0 -0
- /package/packages/theming/dist/{active-theme-ZEJCS5RM.js.map → active-theme-BMSIQXBV.js.map} +0 -0
- /package/packages/theming/dist/{chunk-FLDRNDLY.js.map → chunk-Z3JB7ERH.js.map} +0 -0
- /package/packages/theming/dist/{theme-titlebar-HAEXLVMW.js.map → theme-titlebar-YIFJINPJ.js.map} +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
try {
|
|
4
4
|
if (typeof document != "undefined") {
|
|
5
5
|
var elementStyle = document.createElement("style");
|
|
6
|
-
elementStyle.appendChild(document.createTextNode("@layer package {\n :root,\n :host,\n [theme] {\n --embed-frame-bg: var(--editor-fill, white);\n --embed-frame-fg: var(--editor-line, black);\n --embed-frame-muted: var(--editor-line-offset-30, #666);\n --embed-frame-border: var(--editor-fill-offset-20, #ddd);\n --embed-frame-hover: var(--editor-fill-offset-10, #f4f4f4);\n --embed-frame-highlight: var(--editor-fill-offset-10, #f0f0f0);\n --embed-frame-family: var(--editor-family-sans, system-ui, sans-serif);\n }\n}\n\n.embed-frame {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--embed-frame-bg);\n color: var(--embed-frame-fg);\n font-family: var(--embed-frame-family);\n}\n\n.embed-frame .header {\n display: flex;\n align-items: center;\n gap: var(--studio-space-sm, 0.5rem);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-bottom: 1px solid var(--embed-frame-border);\n flex-shrink: 0;\n}\n\n.embed-frame .title {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n font-size: 0.85em;\n cursor: default;\n}\n\n.embed-frame .title[data-renamable] {\n cursor: text;\n}\n\n.embed-frame .rename-input {\n flex: 1;\n min-width: 0;\n font: inherit;\n font-size: 0.85em;\n color: inherit;\n background: none;\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-sm, 4px);\n padding: 0 var(--studio-space-2xs, 0.25rem);\n outline: none;\n}\n\n.embed-frame .version {\n font-size: 0.7em;\n color: var(--embed-frame-muted);\n flex-shrink: 0;\n}\n\n.embed-frame .tool-btn {\n display: inline-flex;\n align-items: center;\n height: 20px;\n padding: 0 var(--studio-space-sm, 0.5rem);\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-round, 9999px);\n background: none;\n color: var(--embed-frame-muted);\n font: inherit;\n font-size: 0.75em;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n max-width: 10rem;\n overflow: hidden;\n text-overflow: ellipsis;\n flex-shrink: 0;\n transition: background var(--studio-transition-fast, 0.1s ease);\n}\n\n.embed-frame .tool-btn:hover {\n background: var(--embed-frame-hover);\n color: var(--embed-frame-fg);\n}\n\n.embed-frame .open-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border: none;\n background: none;\n color: inherit;\n padding: 0;\n cursor: pointer;\n opacity: 0.7;\n flex-shrink: 0;\n}\n\n.embed-frame .open-btn:hover {\n opacity: 1;\n}\n\n.embed-frame .content {\n flex: 1;\n min-height: 0;\n position: relative;\n}\n\n.embed-frame .content > patchwork-view {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.embed-frame .tool-menu[popover] {\n position: fixed;\n inset: unset;\n margin: 0;\n padding: 0;\n min-width: 180px;\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-sm, 4px);\n background: var(--embed-frame-bg);\n color: var(--embed-frame-fg);\n box-shadow: var(--studio-shadow-sm, 0 2px 8px rgba(0, 0, 0, 0.08));\n overflow: hidden;\n font-family: var(--embed-frame-family);\n font-size: 0.85em;\n}\n\n.embed-frame .tool-menu .list {\n max-height: 200px;\n overflow-y: auto;\n padding: var(--studio-space-2xs, 0.25rem);\n}\n\n.embed-frame .tool-menu .item {\n display: block;\n width: 100%;\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border: none;\n border-radius: var(--studio-radius-sm, 4px);\n background: none;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.embed-frame .tool-menu .item:hover {\n background: var(--embed-frame-highlight);\n}\n\n.embed-frame .tool-menu .item[data-current] {\n font-weight: 600;\n}"));
|
|
6
|
+
elementStyle.appendChild(document.createTextNode("@layer package {\n :root,\n :host,\n [theme] {\n --embed-frame-bg: var(--editor-fill, white);\n --embed-frame-fg: var(--editor-line, black);\n --embed-frame-muted: var(--editor-line-offset-30, #666);\n --embed-frame-border: var(--editor-fill-offset-20, #ddd);\n --embed-frame-hover: var(--editor-fill-offset-10, #f4f4f4);\n --embed-frame-highlight: var(--editor-fill-offset-10, #f0f0f0);\n --embed-frame-family: var(--editor-family-sans, system-ui, sans-serif);\n }\n}\n\n.embed-frame {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--embed-frame-bg);\n color: var(--embed-frame-fg);\n font-family: var(--embed-frame-family);\n}\n\n.embed-frame .header {\n display: flex;\n align-items: center;\n gap: var(--studio-space-sm, 0.5rem);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-bottom: 1px solid var(--embed-frame-border);\n flex-shrink: 0;\n}\n\n.embed-frame .title {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n font-size: 0.85em;\n cursor: default;\n}\n\n.embed-frame .title[data-renamable] {\n cursor: text;\n}\n\n.embed-frame .rename-input {\n flex: 1;\n min-width: 0;\n font: inherit;\n font-size: 0.85em;\n color: inherit;\n background: none;\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-sm, 4px);\n padding: 0 var(--studio-space-2xs, 0.25rem);\n outline: none;\n}\n\n.embed-frame .version {\n font-size: 0.7em;\n color: var(--embed-frame-muted);\n flex-shrink: 0;\n}\n\n.embed-frame .tool-btn {\n display: inline-flex;\n align-items: center;\n height: 20px;\n padding: 0 var(--studio-space-sm, 0.5rem);\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-round, 9999px);\n background: none;\n color: var(--embed-frame-muted);\n font: inherit;\n font-size: 0.75em;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n max-width: 10rem;\n overflow: hidden;\n text-overflow: ellipsis;\n flex-shrink: 0;\n transition: background var(--studio-transition-fast, 0.1s ease);\n}\n\n.embed-frame .tool-btn:hover {\n background: var(--embed-frame-hover);\n color: var(--embed-frame-fg);\n}\n\n.embed-frame .open-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border: none;\n background: none;\n color: inherit;\n padding: 0;\n cursor: pointer;\n opacity: 0.7;\n flex-shrink: 0;\n}\n\n.embed-frame .open-btn:hover {\n opacity: 1;\n}\n\n.embed-frame .content {\n flex: 1;\n min-height: 0;\n position: relative;\n}\n\n.embed-frame .content > patchwork-view {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.embed-frame .tool-menu[popover] {\n position: fixed;\n inset: unset;\n margin: 0;\n padding: 0;\n min-width: 180px;\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-sm, 4px);\n background: var(--embed-frame-bg);\n color: var(--embed-frame-fg);\n box-shadow: var(--studio-shadow-sm, 0 2px 8px rgba(0, 0, 0, 0.08));\n overflow: hidden;\n font-family: var(--embed-frame-family);\n font-size: 0.85em;\n /* Grows out of the tool button (origin set in tool.tsx). Closing is instant. */\n transition:\n opacity 150ms var(--studio-ease-out, cubic-bezier(0.23, 1, 0.32, 1)),\n transform 150ms var(--studio-ease-out, cubic-bezier(0.23, 1, 0.32, 1));\n}\n@starting-style {\n .embed-frame .tool-menu[popover]:popover-open {\n opacity: 0;\n transform: scale(0.97);\n }\n}\n\n.embed-frame .tool-menu .list {\n max-height: 200px;\n overflow-y: auto;\n padding: var(--studio-space-2xs, 0.25rem);\n}\n\n.embed-frame .tool-menu .item {\n display: block;\n width: 100%;\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border: none;\n border-radius: var(--studio-radius-sm, 4px);\n background: none;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.embed-frame .tool-menu .item:hover {\n background: var(--embed-frame-highlight);\n}\n\n.embed-frame .tool-menu .item[data-current] {\n font-weight: 600;\n}"));
|
|
7
7
|
document.head.appendChild(elementStyle);
|
|
8
8
|
}
|
|
9
9
|
} catch (e) {
|
|
@@ -102,9 +102,11 @@ function Frame(props) {
|
|
|
102
102
|
if (rect.left + menuWidth > window.innerWidth - 8) {
|
|
103
103
|
menuEl.style.left = "";
|
|
104
104
|
menuEl.style.right = `${window.innerWidth - rect.right}px`;
|
|
105
|
+
menuEl.style.transformOrigin = "top right";
|
|
105
106
|
} else {
|
|
106
107
|
menuEl.style.right = "";
|
|
107
108
|
menuEl.style.left = `${rect.left}px`;
|
|
109
|
+
menuEl.style.transformOrigin = "top left";
|
|
108
110
|
}
|
|
109
111
|
menuEl.showPopover();
|
|
110
112
|
}
|
|
@@ -233,4 +235,4 @@ delegateEvents(["click", "keydown"]);
|
|
|
233
235
|
export {
|
|
234
236
|
EmbedFrame as default
|
|
235
237
|
};
|
|
236
|
-
//# sourceMappingURL=tool-
|
|
238
|
+
//# sourceMappingURL=tool-D58NGTZ7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-D58NGTZ7.js","sources":["../../src/tool.tsx"],"sourcesContent":["// Embed frame: chrome (title, tool picker, open button) around a nested\n// <patchwork-view>. Hosts mount it via <patchwork-view tool-id=\"embed\">, pin\n// the inner tool with the `embed-tool-id` attribute, and persist picks by\n// listening for the bubbling `patchwork:embed-tool-changed` event.\n\nimport {\n getFallbackTool,\n getRegistry,\n getSupportedToolsForType,\n isLoadedPlugin,\n type DatatypeImplementation,\n type ToolDescription,\n type ToolImplementation,\n} from \"@inkandswitch/patchwork-plugins\";\nimport { getType } from \"@inkandswitch/patchwork-filesystem\";\nimport { openDocument } from \"@inkandswitch/patchwork-elements\";\nimport type { DocHandle } from \"@automerge/automerge-repo\";\nimport { createEffect, createSignal, For, onCleanup, Show } from \"solid-js\";\nimport { render } from \"solid-js/web\";\nimport { version } from \"../package.json\";\nimport \"./embed.css\";\n\nconst EMBED_TOOL_ID = \"embed\";\n\nconst EmbedFrame: ToolImplementation<any> = (handle, element) =>\n render(() => <Frame handle={handle} element={element} />, element);\n\nexport default EmbedFrame;\n\ntype FrameProps = {\n handle: DocHandle<any>;\n element: HTMLElement;\n};\n\nfunction Frame(props: FrameProps) {\n // Static per mount (the render contract passes them once); safe to unwrap.\n const { handle, element } = props;\n\n // `element` is the inner <patchwork-view-legacy>; hosts set `embed-tool-id`\n // on the outer <patchwork-view>, so check there too.\n const [pinnedToolId, setPinnedToolId] = createSignal(\n element.getAttribute(\"embed-tool-id\") ||\n element.closest(\"patchwork-view\")?.getAttribute(\"embed-tool-id\") ||\n null\n );\n const [doc, setDoc] = createSignal<any>(handle.doc(), { equals: false });\n const [datatype, setDatatype] =\n createSignal<DatatypeImplementation<any> | null>(null);\n const [renaming, setRenaming] = createSignal(false);\n const [menuOpen, setMenuOpen] = createSignal(false);\n\n const onDocChange = () => setDoc(handle.doc());\n handle.on(\"change\", onDocChange);\n onCleanup(() => handle.off(\"change\", onDocChange));\n void loadDatatype();\n\n let menuEl!: HTMLDivElement;\n let toolButtonEl!: HTMLButtonElement;\n\n const title = () => {\n try {\n return datatype()?.getTitle(doc()) || \"Untitled\";\n } catch {\n // getTitle throws on unexpected doc shapes\n return \"Untitled\";\n }\n };\n\n const canRename = () => Boolean(datatype()?.setTitle);\n\n // With no pinned tool the nested view renders the doc's fallback tool, so\n // surface that as the selection rather than a special \"unselected\" state.\n const effectiveToolId = () => {\n datatype(); // re-check once the datatype (and the tools it ships) loaded\n if (pinnedToolId()) return pinnedToolId();\n try {\n return getFallbackTool(doc())?.id ?? null;\n } catch {\n return null;\n }\n };\n\n const toolName = () => {\n const toolId = effectiveToolId();\n if (!toolId) return \"\";\n const tool = getRegistry<ToolDescription>(\"patchwork:tool\").get(toolId);\n return tool?.name ?? toolId;\n };\n\n function setTool(toolId: string): void {\n if (!toolId || toolId === pinnedToolId()) return;\n setPinnedToolId(toolId);\n element.dispatchEvent(\n new CustomEvent(\"patchwork:embed-tool-changed\", {\n detail: { url: handle.url, toolId },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n function finishRename(commit: boolean, value: string): void {\n if (!renaming()) return;\n setRenaming(false);\n const trimmed = value.trim();\n if (commit && trimmed && trimmed !== title()) {\n handle.change((d: any) => datatype()!.setTitle!(d, trimmed));\n }\n }\n\n function toggleMenu(): void {\n if (menuEl.matches(\":popover-open\")) {\n menuEl.hidePopover();\n return;\n }\n setMenuOpen(true);\n const rect = toolButtonEl.getBoundingClientRect();\n const menuWidth = Math.max(rect.width, 180);\n menuEl.style.top = `${rect.bottom + 2}px`;\n menuEl.style.minWidth = `${menuWidth}px`;\n if (rect.left + menuWidth > window.innerWidth - 8) {\n menuEl.style.left = \"\";\n menuEl.style.right = `${window.innerWidth - rect.right}px`;\n menuEl.style.transformOrigin = \"top right\";\n } else {\n menuEl.style.right = \"\";\n menuEl.style.left = `${rect.left}px`;\n menuEl.style.transformOrigin = \"top left\";\n }\n menuEl.showPopover();\n }\n\n function listTools(): ToolDescription[] {\n const d = doc();\n const type = d && getType(d);\n if (!type) return [];\n const list = getSupportedToolsForType(type).filter(\n (t) => !t.unlisted && !t.forTitleBar && t.id !== EMBED_TOOL_ID\n );\n // Datatype-specific tools before the generic wildcard ones.\n list.sort((a, b) => Number(isWildcard(a)) - Number(isWildcard(b)));\n return list;\n }\n\n // Built imperatively rather than as JSX so we don't have to teach Solid's\n // JSX types about the custom element.\n const nestedView = document.createElement(\"patchwork-view\");\n nestedView.setAttribute(\"doc-url\", handle.url);\n createEffect(() => {\n const toolId = pinnedToolId();\n if (toolId) nestedView.setAttribute(\"tool-id\", toolId);\n else nestedView.removeAttribute(\"tool-id\");\n });\n\n // Load the datatype (for getTitle/setTitle and its tools).\n async function loadDatatype(): Promise<void> {\n const d = handle.doc();\n const type = d && getType(d);\n if (!type) return;\n const registry = getRegistry(\"patchwork:datatype\");\n try {\n await registry.load(type);\n } catch {\n // datatype unavailable; keep the fallbacks\n }\n const loaded = registry.get(type);\n if (loaded && isLoadedPlugin(loaded)) {\n setDatatype(() => loaded.module as DatatypeImplementation<any>);\n }\n }\n\n return (\n <div class=\"embed-frame\">\n <div class=\"header\">\n <Show\n when={!renaming()}\n fallback={\n <input\n class=\"rename-input\"\n value={title()}\n ref={(el) =>\n queueMicrotask(() => {\n el.focus();\n el.select();\n })\n }\n onKeyDown={(e) => {\n e.stopPropagation();\n if (e.key === \"Enter\") finishRename(true, e.currentTarget.value);\n if (e.key === \"Escape\")\n finishRename(false, e.currentTarget.value);\n }}\n onBlur={(e) => finishRename(true, e.currentTarget.value)}\n />\n }\n >\n <span\n class=\"title\"\n data-renamable={canRename() ? \"\" : undefined}\n title={canRename() ? \"Click to rename\" : undefined}\n onClick={() => canRename() && setRenaming(true)}\n >\n {title()}\n </span>\n </Show>\n {/* Deploy check: which build is actually running. */}\n <span class=\"version\">v{version}</span>\n <button\n class=\"tool-btn\"\n title={\"Open with\\u2026\"}\n ref={toolButtonEl}\n onClick={toggleMenu}\n >\n {toolName()}\n </button>\n <button\n class=\"open-btn\"\n title=\"Open document\"\n innerHTML={openIcon}\n onClick={() =>\n openDocument(element, handle.url, pinnedToolId() || undefined)\n }\n />\n </div>\n <div class=\"content\">{nestedView}</div>\n <div\n class=\"tool-menu\"\n popover=\"auto\"\n ref={(el) => {\n menuEl = el;\n // Unrender the item list while closed.\n el.addEventListener(\"toggle\", (e) => {\n if ((e as { newState?: string }).newState === \"closed\") {\n setMenuOpen(false);\n }\n });\n }}\n >\n <Show when={menuOpen()}>\n <div class=\"list\">\n <For each={listTools()}>\n {(tool) => (\n <button\n class=\"item\"\n data-current={tool.id === effectiveToolId() ? \"\" : undefined}\n onClick={() => {\n menuEl.hidePopover();\n setTool(tool.id);\n }}\n >\n {tool.name || tool.id}\n </button>\n )}\n </For>\n </div>\n </Show>\n </div>\n </div>\n );\n}\n\nfunction isWildcard(tool: ToolDescription): boolean {\n return (\n tool.supportedDatatypes === \"*\" ||\n (Array.isArray(tool.supportedDatatypes) &&\n tool.supportedDatatypes.includes(\"*\"))\n );\n}\n\nconst openIcon = `<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n\t<path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"></path>\n\t<polyline points=\"15 3 21 3 21 9\"></polyline>\n\t<line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"></line>\n</svg>`;\n"],"names":["EMBED_TOOL_ID","EmbedFrame","handle","element","render","_$createComponent","Frame","props","pinnedToolId","setPinnedToolId","createSignal","getAttribute","closest","doc","setDoc","equals","datatype","setDatatype","renaming","setRenaming","menuOpen","setMenuOpen","onDocChange","on","onCleanup","off","loadDatatype","menuEl","toolButtonEl","title","getTitle","canRename","Boolean","setTitle","effectiveToolId","getFallbackTool","id","toolName","toolId","tool","getRegistry","get","name","setTool","dispatchEvent","CustomEvent","detail","url","bubbles","composed","finishRename","commit","value","trimmed","trim","change","d","toggleMenu","matches","hidePopover","rect","getBoundingClientRect","menuWidth","Math","max","width","style","top","bottom","minWidth","left","window","innerWidth","right","transformOrigin","showPopover","listTools","type","getType","list","getSupportedToolsForType","filter","t","unlisted","forTitleBar","sort","a","b","Number","isWildcard","nestedView","document","createElement","setAttribute","createEffect","removeAttribute","registry","load","loaded","isLoadedPlugin","module","_el$","_tmpl$3","_el$2","firstChild","_el$4","_el$6","nextSibling","_el$7","_el$8","_el$9","_$insert","Show","when","fallback","_el$1","_tmpl$4","addEventListener","e","currentTarget","$$keydown","stopPropagation","key","_$use","el","queueMicrotask","focus","select","_$effect","children","_el$3","_tmpl$","$$click","_p$","_v$","undefined","_v$2","_$setAttribute","version","_ref$","openDocument","innerHTML","openIcon","newState","_el$0","_tmpl$2","For","each","_el$10","_tmpl$5","supportedDatatypes","Array","isArray","includes","_$delegateEvents"],"mappings":"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"}
|
|
@@ -82,7 +82,7 @@ const plugins = [
|
|
|
82
82
|
unlisted: true,
|
|
83
83
|
async load() {
|
|
84
84
|
return (await __vitePreload(async () => {
|
|
85
|
-
const { default: __vite_default__ } = await import("./assets/tool-
|
|
85
|
+
const { default: __vite_default__ } = await import("./assets/tool-D58NGTZ7.js");
|
|
86
86
|
return { default: __vite_default__ };
|
|
87
87
|
}, true ? [] : void 0, import.meta.url)).default;
|
|
88
88
|
}
|
|
@@ -36,13 +36,13 @@ function F(t, e) {
|
|
|
36
36
|
function y(t) {
|
|
37
37
|
return t.content instanceof Uint8Array;
|
|
38
38
|
}
|
|
39
|
-
function
|
|
39
|
+
function U(t) {
|
|
40
40
|
return typeof t.content == "string";
|
|
41
41
|
}
|
|
42
|
-
const g = (t) => typeof t == "object" && t !== null && !(t instanceof Uint8Array) && typeof t.val == "string",
|
|
42
|
+
const g = (t) => typeof t == "object" && t !== null && !(t instanceof Uint8Array) && typeof t.val == "string", E = (t) => l(t.content) || g(t.content), I = (t) => y(t) && !F(t.content, t.content.length), x = (t) => {
|
|
43
43
|
const e = t == null ? void 0 : t.content;
|
|
44
44
|
return typeof e == "string" ? e : g(e) ? e.val : l(e) ? e.toString() : e instanceof Uint8Array ? new TextDecoder().decode(e) : "";
|
|
45
|
-
},
|
|
45
|
+
}, L = (t) => {
|
|
46
46
|
if (y(t))
|
|
47
47
|
return t.content;
|
|
48
48
|
if (typeof t.content == "string")
|
|
@@ -50,7 +50,7 @@ const g = (t) => typeof t == "object" && t !== null && !(t instanceof Uint8Array
|
|
|
50
50
|
if ("toString" in t.content && typeof t.content.toString == "function")
|
|
51
51
|
return t.content.toString();
|
|
52
52
|
throw new Error("Unsupported file content type");
|
|
53
|
-
},
|
|
53
|
+
}, h = {
|
|
54
54
|
init(t) {
|
|
55
55
|
t.name = "", t.extension = "", t.mimeType = "", t.content = "";
|
|
56
56
|
},
|
|
@@ -70,7 +70,7 @@ const g = (t) => typeof t == "object" && t !== null && !(t instanceof Uint8Array
|
|
|
70
70
|
setTitle(t, e) {
|
|
71
71
|
t.name = e;
|
|
72
72
|
}
|
|
73
|
-
},
|
|
73
|
+
}, T = ["mp4", "webm", "ogg"], S = [
|
|
74
74
|
"svg",
|
|
75
75
|
"png",
|
|
76
76
|
"jpg",
|
|
@@ -78,19 +78,19 @@ const g = (t) => typeof t == "object" && t !== null && !(t instanceof Uint8Array
|
|
|
78
78
|
"gif",
|
|
79
79
|
"webp",
|
|
80
80
|
"bmp"
|
|
81
|
-
],
|
|
81
|
+
], N = (t) => {
|
|
82
82
|
var e;
|
|
83
|
-
return
|
|
84
|
-
},
|
|
83
|
+
return S.includes((e = t.extension) == null ? void 0 : e.toLowerCase());
|
|
84
|
+
}, b = (t) => {
|
|
85
85
|
var e;
|
|
86
|
-
return
|
|
87
|
-
},
|
|
86
|
+
return T.includes((e = t.extension) == null ? void 0 : e.toLowerCase());
|
|
87
|
+
}, v = (t, e) => {
|
|
88
88
|
if (t instanceof Uint8Array)
|
|
89
89
|
return URL.createObjectURL(
|
|
90
90
|
new Blob([t], e ? { type: e } : {})
|
|
91
91
|
);
|
|
92
92
|
};
|
|
93
|
-
function
|
|
93
|
+
function O(t, e) {
|
|
94
94
|
const i = t instanceof ArrayBuffer ? new Uint8Array(t) : t, o = e instanceof ArrayBuffer ? new Uint8Array(e) : e;
|
|
95
95
|
if (i.byteLength !== o.byteLength)
|
|
96
96
|
return !1;
|
|
@@ -112,7 +112,7 @@ const k = [
|
|
|
112
112
|
icon: "File",
|
|
113
113
|
unlisted: !0,
|
|
114
114
|
async load() {
|
|
115
|
-
return
|
|
115
|
+
return h;
|
|
116
116
|
}
|
|
117
117
|
},
|
|
118
118
|
{
|
|
@@ -122,7 +122,7 @@ const k = [
|
|
|
122
122
|
icon: "File",
|
|
123
123
|
supportedDatatypes: ["file"],
|
|
124
124
|
async load() {
|
|
125
|
-
return (await import("./tool-
|
|
125
|
+
return (await import("./tool-UKWDK93W.js").then((t) => t.t)).FileTool;
|
|
126
126
|
}
|
|
127
127
|
},
|
|
128
128
|
{
|
|
@@ -146,20 +146,19 @@ const k = [
|
|
|
146
146
|
}
|
|
147
147
|
];
|
|
148
148
|
export {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
v as
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
U as getFileContents,
|
|
149
|
+
h as FileDatatype,
|
|
150
|
+
S as IMAGE_EXTENSIONS,
|
|
151
|
+
T as VIDEO_EXTENSIONS,
|
|
152
|
+
O as compareBuffers,
|
|
153
|
+
v as createBinaryUrl,
|
|
154
|
+
x as fileText,
|
|
155
|
+
L as getFileContents,
|
|
157
156
|
y as isBinaryFileDoc,
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
N as isImageFile,
|
|
158
|
+
E as isImmutableStringFileDoc,
|
|
160
159
|
I as isTextBytesFileDoc,
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
U as isTextFileDoc,
|
|
161
|
+
b as isVideoFile,
|
|
163
162
|
k as plugins
|
|
164
163
|
};
|
|
165
164
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
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":";AAGA,MAAMA,IAAY,KAEZC,IAAa,CAAC,IAAM,IAAM,IAAM,IAAM,EAAI;AAEzC,SAASC,EACdC,GACAC,GACS;AAET,MAAIA,MAAc;AAChB,WAAO;AAGT,MAAIC,IAAkB;AACtB,QAAMC,IAAa,KAAK,IAAIF,GAAWJ,CAAS;AAmChD,MA/BEI,KAAa,KACbD,EAAW,CAAC,MAAM,OAClBA,EAAW,CAAC,MAAM,OAClBA,EAAW,CAAC,MAAM,OAOlBC,KAAa,KACbD,EAAW,CAAC,MAAM,KAClBA,EAAW,CAAC,MAAM,KAClBA,EAAW,CAAC,MAAM,OAClBA,EAAW,CAAC,MAAM,OAOlBC,KAAa,KACbD,EAAW,CAAC,MAAM,OAClBA,EAAW,CAAC,MAAM,OAClBA,EAAW,CAAC,MAAM,KAClBA,EAAW,CAAC,MAAM,KAOlBC,KAAa,KACbD,EAAW,CAAC,MAAM,OAClBA,EAAW,CAAC,MAAM,MAClBA,EAAW,CAAC,MAAM,OAClBA,EAAW,CAAC,MAAM;AAElB,WAAO;AAGT,MAAIG,KAAc,KAAKL,EAAW,MAAM,CAACM,GAAMC,MAAML,EAAWK,CAAC,MAAMD,CAAI;AAEzE,WAAO;AAST,MALIH,KAAa,KAAKD,EAAW,CAAC,MAAM,OAAQA,EAAW,CAAC,MAAM,OAK9DC,KAAa,KAAKD,EAAW,CAAC,MAAM,OAAQA,EAAW,CAAC,MAAM;AAChE,WAAO;AAGT,WAASK,IAAI,GAAGA,IAAIF,GAAYE,KAAK;AACnC,QAAIL,EAAWK,CAAC,MAAM;AAEpB,aAAO;SAENL,EAAWK,CAAC,IAAI,KAAKL,EAAWK,CAAC,IAAI,QACrCL,EAAWK,CAAC,IAAI,MAAML,EAAWK,CAAC,IAAI,MACvC;AAEA,UACEL,EAAWK,CAAC,KAAK,OACjBL,EAAWK,CAAC,KAAK,OACjBA,IAAI,IAAIF;AAGR,YADAE,KACIL,EAAWK,CAAC,KAAK,OAAQL,EAAWK,CAAC,KAAK;AAC5C;AAAA,iBAGFL,EAAWK,CAAC,KAAK,OACjBL,EAAWK,CAAC,KAAK,OACjBA,IAAI,IAAIF;AAGR,YADAE,KAEEL,EAAWK,CAAC,KAAK,OACjBL,EAAWK,CAAC,KAAK,OACjBL,EAAWK,IAAI,CAAC,KAAK,OACrBL,EAAWK,IAAI,CAAC,KAAK,KACrB;AACA,UAAAA;AACA;AAAA,QACF;AAAA,iBAEAL,EAAWK,CAAC,KAAK,OACjBL,EAAWK,CAAC,KAAK,OACjBA,IAAI,IAAIF,MAERE,KAEEL,EAAWK,CAAC,KAAK,OACjBL,EAAWK,CAAC,KAAK,OACjBL,EAAWK,IAAI,CAAC,KAAK,OACrBL,EAAWK,IAAI,CAAC,KAAK,OACrBL,EAAWK,IAAI,CAAC,KAAK,OACrBL,EAAWK,IAAI,CAAC,KAAK,MACrB;AACA,QAAAA,KAAK;AACL;AAAA,MACF;AAKF,UAFAH,KAEIG,KAAK,MAAOH,IAAkB,MAAOC,IAAa;AACpD,eAAO;AAAA,IAEX;AAAA,EACF;AAEA,SAAKD,IAAkB,MAAOC,IAAa;AAK7C;ACxIO,SAASG,EAAgBC,GAAoC;AACnE,SAAOA,EAAI,mBAAmB;AAC/B;AAEO,SAASC,EAAcD,GAAkC;AAC/D,SAAO,OAAOA,EAAI,WAAY;AAC/B;AAKA,MAAME,IAA0B,CAACC,MAChC,OAAOA,KAAY,YACnBA,MAAY,QACZ,EAAEA,aAAmB,eACrB,OAAQA,EAA4B,OAAQ,UAEhCC,IAA2B,CAACJ,MACjCK,EAAkBL,EAAI,OAAO,KAAKE,EAAwBF,EAAI,OAAO,GAKhEM,IAAqB,CAACN,MAClCD,EAAgBC,CAAG,KAAK,CAACR,EAAcQ,EAAI,SAASA,EAAI,QAAQ,MAAM,GAI1DO,IAAW,CAACP,MAAqC;AAC7D,QAAMG,IAAUH,KAAA,gBAAAA,EAAK;AACrB,SAAI,OAAOG,KAAY,WAAiBA,IACpCD,EAAwBC,CAAO,IAAUA,EAAQ,MACjDE,EAAkBF,CAAO,IAAUA,EAAQ,SAAA,IAC3CA,aAAmB,aAAmB,IAAI,YAAA,EAAc,OAAOA,CAAO,IACnE;AACR,GAGaK,IAAkB,CAACR,MAAsC;AACrE,MAAID,EAAgBC,CAAG;AACtB,WAAOA,EAAI;AACZ,MAAW,OAAOA,EAAI,WAAY;AACjC,WAAOA,EAAI;AACZ,MACC,cAAcA,EAAI,WAClB,OAAOA,EAAI,QAAQ,YAAY;AAG/B,WADgBA,EAAI,QACL,SAAA;AAEf,QAAM,IAAI,MAAM,+BAA+B;AAEjD,GAGaS,IAAe;AAAA,EAC3B,KAAKT,GAAc;AAClB,IAAAA,EAAI,OAAO,IACXA,EAAI,YAAY,IAChBA,EAAI,WAAW,IACfA,EAAI,UAAU;AAAA,EACf;AAAA,EAEA,SAASA,GAAcU,GAAe;AACrC,IAAAV,EAAI,OAAOU;AAAA,EACZ;AAAA,EAEA,SAASV,GAAc;AACtB,WAAOA,EAAI,QAAQ;AAAA,EACpB;AACD,GCvEaW,IAAkB;AAAA,EAC9B,KAAKX,GAAc;AAClB,IAAAA,EAAI,OAAO,IACXA,EAAI,YAAY,IAChBA,EAAI,WAAW,IACfA,EAAI,UAAU;AAAA,EACf;AAAA,EAEA,SAASA,GAAc;AACtB,WAAOA,EAAI,QAAQ;AAAA,EACpB;AAAA,EAEA,SAASA,GAAcU,GAAe;AACrC,IAAAV,EAAI,OAAOU;AAAA,EACZ;AACD,GCSaE,IAAkC,KC3BlCC,IAAmB,CAAC,OAAO,QAAQ,KAAK,GACxCC,IAAmB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAEaC,IAAc,CAACf,MAA6B;;AACxD,SAAOc,EAAiB,UAASE,IAAAhB,EAAI,cAAJ,gBAAAgB,EAAe,aAAa;AAC9D,GAEaC,IAAc,CAACjB,MAA6B;;AACxD,SAAOa,EAAiB,UAASG,IAAAhB,EAAI,cAAJ,gBAAAgB,EAAe,aAAa;AAC9D,GAMaE,IAAkB,CAC9BC,GACAC,MACwB;AACxB,MAAMD,aAAiB;AAIvB,WAAO,IAAI;AAAA,MACV,IAAI,KAAK,CAACA,CAAiB,GAAGC,IAAW,EAAC,MAAMA,EAAA,IAAY,CAAA,CAAE;AAAA,IAAA;AAEhE;AASO,SAASC,EACfC,GACAC,GACU;AAEV,QAAMC,IAAKF,aAAgB,cAAc,IAAI,WAAWA,CAAI,IAAIA,GAC1DG,IAAKF,aAAgB,cAAc,IAAI,WAAWA,CAAI,IAAIA;AAEhE,MAAIC,EAAG,eAAeC,EAAG;AACxB,WAAO;AAIR,QAAMC,IAAM,IAAI,SAASF,EAAG,QAAQA,EAAG,YAAYA,EAAG,UAAU,GAC1DG,IAAM,IAAI,SAASF,EAAG,QAAQA,EAAG,YAAYA,EAAG,UAAU,GAE1DG,IAAMJ,EAAG,YACTK,IAAYD,IAAM,GAClBE,KAASF,IAAMC,KAAa;AAGlC,WAAS/B,IAAI,GAAGA,IAAIgC,GAAOhC;AAC1B,QAAI4B,EAAI,YAAY5B,IAAI,GAAG,EAAI,MAAM6B,EAAI,YAAY7B,IAAI,GAAG,EAAI;AAC/D,aAAO;AAKT,QAAMiC,IAAYH,IAAMC;AACxB,WAAS/B,IAAI,GAAGA,IAAI+B,GAAW/B;AAC9B,QAAI0B,EAAGO,IAAYjC,CAAC,MAAM2B,EAAGM,IAAYjC,CAAC;AACzC,aAAO;AAIT,SAAO;AACR;ACvEO,MAAMkC,IAAU;AAAA,EACtB;AAAA,IACC,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAM,OAAO;AACZ,aAAOvB;AAAA,IACR;AAAA,EAAA;AAAA,EAED;AAAA,IACC,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,oBAAoB,CAAC,MAAM;AAAA,IAC3B,MAAM,OAAO;AACZ,cAAQ,MAAM,OAAO,oBAAQ,EAAA,KAAA,CAAAwB,MAAAA,EAAA,CAAA,GAAG;AAAA,IACjC;AAAA,EAAA;AAAA,EAED;AAAA,IACC,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM,OAAO;AACZ,aAAOtB;AAAA,IACR;AAAA,EAAA;AAAA,EAED;AAAA,IACC,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,oBAAoB,CAAC,UAAU;AAAA,IAC/B,MAAM,OAAO;AACZ,cAAQ,MAAM,OAAO,6BAAiB,GAAG;AAAA,IAC1C;AAAA,EAAA;AAEF;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/isBinaryFile.ts","../src/datatype.ts","../src/new-file-datatype.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","// 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","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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"}
|