Move from file IDs to file paths (with retrocompatibility)
This commit is contained in:
		
							parent
							
								
									56cf62f1eb
								
							
						
					
					
						commit
						a2503d5def
					
				
					 7 changed files with 62 additions and 49 deletions
				
			
		|  | @ -1,15 +1,15 @@ | |||
| function copyEditLink(fileID) { | ||||
|     navigator.clipboard.writeText(getEditLink(fileID)); | ||||
| function copyEditLink(path) { | ||||
|     navigator.clipboard.writeText(getEditLink(path)); | ||||
| } | ||||
| function copyImageLink(fileID) { | ||||
|     navigator.clipboard.writeText(``); | ||||
| function copyImageLink(path) { | ||||
|     navigator.clipboard.writeText(`})`); | ||||
| } | ||||
| 
 | ||||
| function refreshPage() { | ||||
|     window.location.reload(); | ||||
| } | ||||
| 
 | ||||
| function addButton(document, fileID) { | ||||
| function addButton(document, path) { | ||||
| 
 | ||||
|     // Add floating button
 | ||||
|     const floatingButton = document.createElement('button'); | ||||
|  | @ -22,8 +22,8 @@ function addButton(document, fileID) { | |||
|     popupMenu.id = 'popupMenu'; | ||||
|     popupMenu.innerHTML = ` | ||||
|                         <button onclick="refreshPage()">Refresh</button> | ||||
|                         <button onclick="copyEditLink('${fileID}')">Copy Direct Edit Link</button> | ||||
|                         <button onclick="copyImageLink('${fileID}')">Copy Image Link</button> | ||||
|                         <button onclick="copyEditLink('${path}')">Copy Direct Edit Link</button> | ||||
|                         <button onclick="copyImageLink('${path}')">Copy Image Link</button> | ||||
|                     `;
 | ||||
|     document.body.appendChild(popupMenu); | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,9 +27,9 @@ async function getFile(path) { | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| async function getSVG(fileID) { | ||||
| async function getSVG(path) { | ||||
| 
 | ||||
|     const resp = await getFile("/data/assets/" + fileID + '.svg'); | ||||
|     const resp = await getFile(path); | ||||
|     if(resp == null) { | ||||
|         return FALLBACK; | ||||
|     } | ||||
|  | @ -37,10 +37,10 @@ async function getSVG(fileID) { | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| function getEditLink(fileID) { | ||||
| function getEditLink(path) { | ||||
|     const data = encodeURIComponent( | ||||
|         JSON.stringify({ | ||||
|             id: fileID | ||||
|             path: path, | ||||
|         }) | ||||
|     ) | ||||
|     return `siyuan://plugins/siyuan-jsdraw-pluginwhiteboard/?icon=iconDraw&title=Drawing&data=${data}`; | ||||
|  |  | |||
|  | @ -5,18 +5,22 @@ | |||
|         <script src="button.js"></script> | ||||
|         <script> | ||||
|             const urlParams = new URLSearchParams(window.location.search); | ||||
|             const fileID = urlParams.get('id'); | ||||
|             let path = urlParams.get('path'); | ||||
|             if(path === null) { | ||||
|                 const fileID = urlParams.get('id'); // legacy support | ||||
|                 path = "/data/assets/" + fileID + ".svg"; | ||||
|             } | ||||
| 
 | ||||
|             document.addEventListener('DOMContentLoaded', async () => { | ||||
|                 const editLink = document.createElement('a'); | ||||
|                 editLink.href = getEditLink(fileID); | ||||
|                 editLink.href = getEditLink(path); | ||||
|                 document.body.appendChild(editLink); | ||||
| 
 | ||||
|                 const htmlContainer = document.createElement('div'); | ||||
|                 htmlContainer.innerHTML = await getSVG(fileID); | ||||
|                 htmlContainer.innerHTML = await getSVG(path); | ||||
|                 editLink.appendChild(htmlContainer); | ||||
| 
 | ||||
|                 addButton(document, fileID); | ||||
|                 addButton(document, path); | ||||
|             }); | ||||
|         </script> | ||||
|         <link rel="stylesheet" href="index.css"> | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| export const SVG_MIME = "image/svg+xml"; | ||||
| export const JSON_MIME = "application/json"; | ||||
| export const DATA_PATH = "/data/assets"; | ||||
| export const DATA_PATH = "/data/assets/"; | ||||
| export const STORAGE_PATH = "/data/storage/petal/siyuan-jsdraw-plugin"; | ||||
| export const TOOLBAR_PATH = STORAGE_PATH + "/toolbar.json"; | ||||
| export const CONFIG_PATH = STORAGE_PATH + "/conf.json"; | ||||
| export const EMBED_PATH = "/plugins/siyuan-jsdraw-plugin/webapp/?id="; | ||||
| export const EMBED_PATH = "/plugins/siyuan-jsdraw-plugin/webapp/?path="; | ||||
|  | @ -6,22 +6,22 @@ import {getFile, saveFile} from "@/file"; | |||
| import {JSON_MIME, SVG_MIME, TOOLBAR_PATH} from "@/const"; | ||||
| import {idToPath} from "@/helper"; | ||||
| 
 | ||||
| export function openEditorTab(p: Plugin, fileID: string) { | ||||
| export function openEditorTab(p: Plugin, path: string) { | ||||
|     openTab({ | ||||
|         app: p.app, | ||||
|         custom: { | ||||
|             title: 'Drawing', | ||||
|             icon: 'iconDraw', | ||||
|             id: "siyuan-jsdraw-pluginwhiteboard", | ||||
|             data: { id: fileID } | ||||
|             data: { path: path } | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| async function saveCallback(editor: Editor, fileID: string, saveButton: BaseWidget) { | ||||
| async function saveCallback(editor: Editor, path: string, saveButton: BaseWidget) { | ||||
|     const svgElem = editor.toSVG(); | ||||
|     try { | ||||
|         saveFile(idToPath(fileID), SVG_MIME, svgElem.outerHTML); | ||||
|         saveFile(path, SVG_MIME, svgElem.outerHTML); | ||||
|         saveButton.setDisabled(true); | ||||
|         setTimeout(() => { // @todo improve save button feedback
 | ||||
|             saveButton.setDisabled(false); | ||||
|  | @ -36,11 +36,15 @@ async function saveCallback(editor: Editor, fileID: string, saveButton: BaseWidg | |||
| 
 | ||||
| export function createEditor(i: ITabModel) { | ||||
| 
 | ||||
|     const fileID = i.data.id; | ||||
|     let path = i.data.path; | ||||
|     if(path == null) { | ||||
|         const fileID = i.data.id; // legacy compatibility
 | ||||
|         if (fileID == null) { | ||||
|         alert("File ID missing - couldn't open file.") | ||||
|             alert("File ID and path missing - couldn't open file.") | ||||
|             return; | ||||
|         } | ||||
|         path = idToPath(fileID); | ||||
|     } | ||||
| 
 | ||||
|     const editor = new Editor(i.element, { | ||||
|         iconProvider: new MaterialIconProvider(), | ||||
|  | @ -55,14 +59,14 @@ export function createEditor(i: ITabModel) { | |||
|         } | ||||
|     }); | ||||
|     // restore drawing
 | ||||
|     getFile(idToPath(fileID)).then(svg => { | ||||
|     getFile(path).then(svg => { | ||||
|         if(svg != null) { | ||||
|             editor.loadFromSVG(svg); | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     // save logic
 | ||||
|     const saveButton = toolbar.addSaveButton(() => saveCallback(editor, fileID, saveButton)); | ||||
|     const saveButton = toolbar.addSaveButton(() => saveCallback(editor, path, saveButton)); | ||||
| 
 | ||||
|     // save toolbar config on tool change (toolbar state is not saved in SVGs!)
 | ||||
|     editor.notifier.on(EditorEventType.ToolUpdated, () => { | ||||
|  |  | |||
|  | @ -45,14 +45,14 @@ export function generateSiyuanId() { | |||
| } | ||||
| 
 | ||||
| export function idToPath(id: string) { | ||||
|     return DATA_PATH + '/' + id + '.svg'; | ||||
|     return DATA_PATH + id + '.svg'; | ||||
| } | ||||
| 
 | ||||
| //    [Edit](siyuan://plugins/siyuan-jsdraw-pluginwhiteboard/?icon=iconDraw&title=Drawing&data={"id":"${id}"})
 | ||||
| //     
 | ||||
| export function getPreviewHTML(id: string): string { | ||||
| export function getPreviewHTML(path: string): string { | ||||
|     return ` | ||||
|     <iframe src="${EMBED_PATH + id}&antiCache=0"></iframe> | ||||
|     <iframe src="${EMBED_PATH + path}&antiCache=0"></iframe> | ||||
|     ` | ||||
| } | ||||
| 
 | ||||
|  | @ -60,12 +60,7 @@ export function getPreviewHTML(id: string): string { | |||
| export function findImgSrc(element: HTMLElement): string | null { | ||||
|     // Base case: if current element is an image
 | ||||
|     if (element.tagName === 'IMG') { | ||||
|         const fullSrc = (element as HTMLImageElement).src; | ||||
|         // Extract the path after host:port using URL API
 | ||||
|         const url = new URL(fullSrc); | ||||
|         return url.pathname.startsWith('/assets/') | ||||
|             ? url.pathname.substring(1) // Remove leading slash
 | ||||
|             : null; | ||||
|         return (element as HTMLImageElement).src; | ||||
|     } | ||||
| 
 | ||||
|     // Recursively check children
 | ||||
|  | @ -79,12 +74,15 @@ export function findImgSrc(element: HTMLElement): string | null { | |||
|     return null; | ||||
| } | ||||
| 
 | ||||
| export function extractFileID(imgSrc: string | null): string | null { | ||||
| export function imgSrcToAbsolutePath(imgSrc: string | null): string | null { | ||||
|     if (!imgSrc) return null; | ||||
| 
 | ||||
|     const [pathPart] = imgSrc.split('?'); | ||||
|     // Match pattern: assets/{fileID}.svg
 | ||||
|     const match = pathPart.match(/^assets\/([^\/]+)\.svg$/i); | ||||
|     const url = new URL(imgSrc); | ||||
|     imgSrc = decodeURIComponent(url.pathname); | ||||
| 
 | ||||
|     if(imgSrc.startsWith('/assets/')) { | ||||
|         return "/data" + imgSrc; | ||||
|     } | ||||
|     return null | ||||
| 
 | ||||
|     return match?.[1] || null; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										23
									
								
								src/index.ts
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								src/index.ts
									
										
									
									
									
								
							|  | @ -1,6 +1,14 @@ | |||
| import {Plugin, Protyle} from 'siyuan'; | ||||
| import {getPreviewHTML, loadIcons, getMenuHTML, generateSiyuanId, findImgSrc, extractFileID} from "@/helper"; | ||||
| import { | ||||
|     getPreviewHTML, | ||||
|     loadIcons, | ||||
|     getMenuHTML, | ||||
|     generateSiyuanId, | ||||
|     findImgSrc, | ||||
|     imgSrcToAbsolutePath | ||||
| } from "@/helper"; | ||||
| import {createEditor, openEditorTab} from "@/editorTab"; | ||||
| import {DATA_PATH} from "@/const"; | ||||
| 
 | ||||
| export default class DrawJSPlugin extends Plugin { | ||||
|     onload() { | ||||
|  | @ -18,23 +26,22 @@ export default class DrawJSPlugin extends Plugin { | |||
|             filter: ["Insert Drawing", "Add drawing", "whiteboard", "freehand", "graphics", "jsdraw"], | ||||
|             html: getMenuHTML("iconDraw", this.i18n.insertDrawing), | ||||
|             callback: (protyle: Protyle) => { | ||||
|                 const uid = generateSiyuanId(); | ||||
|                 protyle.insert(getPreviewHTML(uid), true, false); | ||||
|                 openEditorTab(this, uid); | ||||
|                 const path = DATA_PATH + generateSiyuanId() + ".svg"; | ||||
|                 protyle.insert(getPreviewHTML(path), true, false); | ||||
|                 openEditorTab(this, path); | ||||
|             } | ||||
|         }]; | ||||
| 
 | ||||
|         this.eventBus.on("open-menu-image", (e: any) => { | ||||
|             const fileID = extractFileID(findImgSrc(e.detail.element)); | ||||
|             if(fileID === null) { | ||||
|             const path = imgSrcToAbsolutePath(findImgSrc(e.detail.element)); | ||||
|             if(path === null) { | ||||
|                 return; | ||||
|             } | ||||
|             console.log("got ID" + fileID); | ||||
|             e.detail.menu.addItem({ | ||||
|                 icon: "iconDraw", | ||||
|                 label: "Edit with js-draw", | ||||
|                 click: () => { | ||||
|                     openEditorTab(this, fileID); | ||||
|                     openEditorTab(this, path); | ||||
|                 } | ||||
|             }) | ||||
|         }) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue