diff --git a/public/webapp/button.js b/public/webapp/button.js index 5aa902d..8be8fd4 100644 --- a/public/webapp/button.js +++ b/public/webapp/button.js @@ -2,7 +2,7 @@ function copyEditLink(path) { navigator.clipboard.writeText(getEditLink(path)); } function copyImageLink(path) { - navigator.clipboard.writeText(`![Drawing](${path.replace("/data/", "")})`); + navigator.clipboard.writeText(`![Drawing](${path})`); } function refreshPage() { diff --git a/public/webapp/draw.js b/public/webapp/draw.js index baaf005..187dab2 100644 --- a/public/webapp/draw.js +++ b/public/webapp/draw.js @@ -29,7 +29,7 @@ async function getFile(path) { async function getSVG(path) { - const resp = await getFile(path); + const resp = await getFile("/data/" + path); if(resp == null) { return FALLBACK; } diff --git a/public/webapp/index.html b/public/webapp/index.html index c40fb79..cb4343c 100644 --- a/public/webapp/index.html +++ b/public/webapp/index.html @@ -8,7 +8,7 @@ let path = urlParams.get('path'); if(path === null) { const fileID = urlParams.get('id'); // legacy support - path = "/data/assets/" + fileID + ".svg"; + path = "assets/" + fileID + ".svg"; } document.addEventListener('DOMContentLoaded', async () => { diff --git a/src/const.ts b/src/const.ts index 9e5c04e..437af37 100644 --- a/src/const.ts +++ b/src/const.ts @@ -1,7 +1,8 @@ export const SVG_MIME = "image/svg+xml"; export const JSON_MIME = "application/json"; -export const DATA_PATH = "/data/assets/"; -export const STORAGE_PATH = "/data/storage/petal/siyuan-jsdraw-plugin"; +export const DATA_PATH = "/data/"; +export const ASSETS_PATH = "assets/"; +export const STORAGE_PATH = DATA_PATH + "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/?path="; \ No newline at end of file diff --git a/src/editorTab.ts b/src/editorTab.ts index 0399dad..97f2cbc 100644 --- a/src/editorTab.ts +++ b/src/editorTab.ts @@ -3,7 +3,7 @@ import Editor, {BaseWidget, EditorEventType} from "js-draw"; import { MaterialIconProvider } from '@js-draw/material-icons'; import 'js-draw/styles'; import {getFile, saveFile} from "@/file"; -import {JSON_MIME, SVG_MIME, TOOLBAR_PATH} from "@/const"; +import {DATA_PATH, JSON_MIME, SVG_MIME, TOOLBAR_PATH} from "@/const"; import {idToPath} from "@/helper"; export function openEditorTab(p: Plugin, path: string) { @@ -21,7 +21,7 @@ export function openEditorTab(p: Plugin, path: string) { async function saveCallback(editor: Editor, path: string, saveButton: BaseWidget) { const svgElem = editor.toSVG(); try { - saveFile(path, SVG_MIME, svgElem.outerHTML); + saveFile(DATA_PATH + path, SVG_MIME, svgElem.outerHTML); saveButton.setDisabled(true); setTimeout(() => { // @todo improve save button feedback saveButton.setDisabled(false); @@ -59,7 +59,7 @@ export function createEditor(i: ITabModel) { } }); // restore drawing - getFile(path).then(svg => { + getFile(DATA_PATH + path).then(svg => { if(svg != null) { editor.loadFromSVG(svg); } diff --git a/src/helper.ts b/src/helper.ts index 7e132ac..d956158 100644 --- a/src/helper.ts +++ b/src/helper.ts @@ -74,15 +74,20 @@ export function findImgSrc(element: HTMLElement): string | null { return null; } -export function imgSrcToAbsolutePath(imgSrc: string | null): string | null { +export function imgSrcToPath(imgSrc: string | null): string | null { if (!imgSrc) return null; const url = new URL(imgSrc); imgSrc = decodeURIComponent(url.pathname); if(imgSrc.startsWith('/assets/')) { - return "/data" + imgSrc; + return imgSrc.substring(1); } return null } + +// Helper to safely escape regex special characters +export function escapeRegExp(string: string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 851d6e5..b5d4e90 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,10 +5,10 @@ import { getMenuHTML, generateSiyuanId, findImgSrc, - imgSrcToAbsolutePath + imgSrcToPath } from "@/helper"; import {createEditor, openEditorTab} from "@/editorTab"; -import {DATA_PATH} from "@/const"; +import {ASSETS_PATH} from "@/const"; export default class DrawJSPlugin extends Plugin { onload() { @@ -26,14 +26,14 @@ 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 path = DATA_PATH + generateSiyuanId() + ".svg"; + const path = ASSETS_PATH + generateSiyuanId() + ".svg"; protyle.insert(getPreviewHTML(path), true, false); openEditorTab(this, path); } }]; this.eventBus.on("open-menu-image", (e: any) => { - const path = imgSrcToAbsolutePath(findImgSrc(e.detail.element)); + const path = imgSrcToPath(findImgSrc(e.detail.element)); if(path === null) { return; } diff --git a/src/protyle.ts b/src/protyle.ts new file mode 100644 index 0000000..500874a --- /dev/null +++ b/src/protyle.ts @@ -0,0 +1,46 @@ +import {getBlockByID, sql, updateBlock} from "@/api"; +import {escapeRegExp} from "@/helper"; + +export async function findImageBlocks(src: string) { + + const sqlQuery = ` + SELECT id, markdown + FROM blocks + WHERE markdown like '%${src}%' + `; + + try { + return await sql(sqlQuery); + } catch (error) { + console.error('Error searching for image blocks:', error); + return []; + } + +} +export async function replaceBlockContent( + blockId: string, + searchStr: string, + replaceStr: string +): Promise { + try { + + const block = await getBlockByID(blockId); + if (!block) { + throw new Error('Block not found'); + } + + const originalContent = block.markdown; + const newContent = originalContent.replace(escapeRegExp(searchStr), replaceStr); + + if (newContent === originalContent) { + return false; + } + + await updateBlock('markdown', newContent, blockId); + return true; + + } catch (error) { + console.error('Failed to replace block content:', error); + return false; + } +}