From e9a9961b6158c29ac42c25dba8443eb86306996b Mon Sep 17 00:00:00 2001 From: MassiveBox Date: Thu, 3 Apr 2025 15:51:33 +0200 Subject: [PATCH] Auto-refresh images on edit Only for Markdown images, not drawing blocks, since those will eventually be deprecated. --- src/const.ts | 3 ++- src/editorTab.ts | 2 ++ src/protyle.ts | 31 ++++++++++++++++++++++++++++--- tsconfig.json | 2 +- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/const.ts b/src/const.ts index 437af37..2f8e88a 100644 --- a/src/const.ts +++ b/src/const.ts @@ -5,4 +5,5 @@ 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 +export const EMBED_PATH = "/plugins/siyuan-jsdraw-plugin/webapp/?path="; +export const DUMMY_HOST = "https://dummy.host/"; \ No newline at end of file diff --git a/src/editorTab.ts b/src/editorTab.ts index 97f2cbc..c00b9db 100644 --- a/src/editorTab.ts +++ b/src/editorTab.ts @@ -5,6 +5,7 @@ import 'js-draw/styles'; import {getFile, saveFile} from "@/file"; import {DATA_PATH, JSON_MIME, SVG_MIME, TOOLBAR_PATH} from "@/const"; import {idToPath} from "@/helper"; +import {replaceAntiCacheID} from "@/protyle"; export function openEditorTab(p: Plugin, path: string) { openTab({ @@ -22,6 +23,7 @@ async function saveCallback(editor: Editor, path: string, saveButton: BaseWidget const svgElem = editor.toSVG(); try { saveFile(DATA_PATH + path, SVG_MIME, svgElem.outerHTML); + await replaceAntiCacheID(path); saveButton.setDisabled(true); setTimeout(() => { // @todo improve save button feedback saveButton.setDisabled(false); diff --git a/src/protyle.ts b/src/protyle.ts index 500874a..cda24f9 100644 --- a/src/protyle.ts +++ b/src/protyle.ts @@ -1,12 +1,12 @@ import {getBlockByID, sql, updateBlock} from "@/api"; -import {escapeRegExp} from "@/helper"; +import {DUMMY_HOST} from "@/const"; export async function findImageBlocks(src: string) { const sqlQuery = ` SELECT id, markdown FROM blocks - WHERE markdown like '%${src}%' + WHERE markdown like '%](${src}%' // "](" is to check it's an image src `; try { @@ -30,7 +30,7 @@ export async function replaceBlockContent( } const originalContent = block.markdown; - const newContent = originalContent.replace(escapeRegExp(searchStr), replaceStr); + const newContent = originalContent.replaceAll(searchStr, replaceStr); if (newContent === originalContent) { return false; @@ -44,3 +44,28 @@ export async function replaceBlockContent( return false; } } + +export async function replaceAntiCacheID(src: string) { + + const search = encodeURI(src); // the API uses URI-encoded + // find blocks containing that image + const blocks = await findImageBlocks(search); + + for(const block of blocks) { + + // get all the image sources, with parameters + const markdown = block.markdown; + const imageRegex = /!\[.*?\]\((.*?)\)/g; // only get images + const sources = Array.from(markdown.matchAll(imageRegex)) + .map(match => match[1]) + .filter(source => source.startsWith(search)) // discard other images + + for(const source of sources) { + const url = new URL(source, DUMMY_HOST); + url.searchParams.set('antiCache', Date.now().toString()); // set or replace antiCache + const newSource = url.href.replace(DUMMY_HOST, ''); + await replaceBlockContent(block.id, source, newSource); + } + } + +} diff --git a/tsconfig.json b/tsconfig.json index 0fcc1ad..e2dedbd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ "useDefineForClassFields": true, "module": "ESNext", "lib": [ - "ES2020", + "ES2021", "DOM", "DOM.Iterable" ],