Internal file paths are now Markdown image paths
In the last commit, file paths were implemented to be the full path for the API, however that is not necessary. Before this change: /data/assets/filename.svg After: assets/filename.svg The new method is what SiYuan uses for Markdown images, like 
This commit is contained in:
parent
a2503d5def
commit
5e51589ffa
8 changed files with 66 additions and 14 deletions
|
@ -2,7 +2,7 @@ function copyEditLink(path) {
|
||||||
navigator.clipboard.writeText(getEditLink(path));
|
navigator.clipboard.writeText(getEditLink(path));
|
||||||
}
|
}
|
||||||
function copyImageLink(path) {
|
function copyImageLink(path) {
|
||||||
navigator.clipboard.writeText(`})`);
|
navigator.clipboard.writeText(``);
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshPage() {
|
function refreshPage() {
|
||||||
|
|
|
@ -29,7 +29,7 @@ async function getFile(path) {
|
||||||
|
|
||||||
async function getSVG(path) {
|
async function getSVG(path) {
|
||||||
|
|
||||||
const resp = await getFile(path);
|
const resp = await getFile("/data/" + path);
|
||||||
if(resp == null) {
|
if(resp == null) {
|
||||||
return FALLBACK;
|
return FALLBACK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
let path = urlParams.get('path');
|
let path = urlParams.get('path');
|
||||||
if(path === null) {
|
if(path === null) {
|
||||||
const fileID = urlParams.get('id'); // legacy support
|
const fileID = urlParams.get('id'); // legacy support
|
||||||
path = "/data/assets/" + fileID + ".svg";
|
path = "assets/" + fileID + ".svg";
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
export const SVG_MIME = "image/svg+xml";
|
export const SVG_MIME = "image/svg+xml";
|
||||||
export const JSON_MIME = "application/json";
|
export const JSON_MIME = "application/json";
|
||||||
export const DATA_PATH = "/data/assets/";
|
export const DATA_PATH = "/data/";
|
||||||
export const STORAGE_PATH = "/data/storage/petal/siyuan-jsdraw-plugin";
|
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 TOOLBAR_PATH = STORAGE_PATH + "/toolbar.json";
|
||||||
export const CONFIG_PATH = STORAGE_PATH + "/conf.json";
|
export const CONFIG_PATH = STORAGE_PATH + "/conf.json";
|
||||||
export const EMBED_PATH = "/plugins/siyuan-jsdraw-plugin/webapp/?path=";
|
export const EMBED_PATH = "/plugins/siyuan-jsdraw-plugin/webapp/?path=";
|
|
@ -3,7 +3,7 @@ import Editor, {BaseWidget, EditorEventType} from "js-draw";
|
||||||
import { MaterialIconProvider } from '@js-draw/material-icons';
|
import { MaterialIconProvider } from '@js-draw/material-icons';
|
||||||
import 'js-draw/styles';
|
import 'js-draw/styles';
|
||||||
import {getFile, saveFile} from "@/file";
|
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";
|
import {idToPath} from "@/helper";
|
||||||
|
|
||||||
export function openEditorTab(p: Plugin, path: string) {
|
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) {
|
async function saveCallback(editor: Editor, path: string, saveButton: BaseWidget) {
|
||||||
const svgElem = editor.toSVG();
|
const svgElem = editor.toSVG();
|
||||||
try {
|
try {
|
||||||
saveFile(path, SVG_MIME, svgElem.outerHTML);
|
saveFile(DATA_PATH + path, SVG_MIME, svgElem.outerHTML);
|
||||||
saveButton.setDisabled(true);
|
saveButton.setDisabled(true);
|
||||||
setTimeout(() => { // @todo improve save button feedback
|
setTimeout(() => { // @todo improve save button feedback
|
||||||
saveButton.setDisabled(false);
|
saveButton.setDisabled(false);
|
||||||
|
@ -59,7 +59,7 @@ export function createEditor(i: ITabModel) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// restore drawing
|
// restore drawing
|
||||||
getFile(path).then(svg => {
|
getFile(DATA_PATH + path).then(svg => {
|
||||||
if(svg != null) {
|
if(svg != null) {
|
||||||
editor.loadFromSVG(svg);
|
editor.loadFromSVG(svg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,15 +74,20 @@ export function findImgSrc(element: HTMLElement): string | null {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function imgSrcToAbsolutePath(imgSrc: string | null): string | null {
|
export function imgSrcToPath(imgSrc: string | null): string | null {
|
||||||
if (!imgSrc) return null;
|
if (!imgSrc) return null;
|
||||||
|
|
||||||
const url = new URL(imgSrc);
|
const url = new URL(imgSrc);
|
||||||
imgSrc = decodeURIComponent(url.pathname);
|
imgSrc = decodeURIComponent(url.pathname);
|
||||||
|
|
||||||
if(imgSrc.startsWith('/assets/')) {
|
if(imgSrc.startsWith('/assets/')) {
|
||||||
return "/data" + imgSrc;
|
return imgSrc.substring(1);
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper to safely escape regex special characters
|
||||||
|
export function escapeRegExp(string: string) {
|
||||||
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
}
|
|
@ -5,10 +5,10 @@ import {
|
||||||
getMenuHTML,
|
getMenuHTML,
|
||||||
generateSiyuanId,
|
generateSiyuanId,
|
||||||
findImgSrc,
|
findImgSrc,
|
||||||
imgSrcToAbsolutePath
|
imgSrcToPath
|
||||||
} from "@/helper";
|
} from "@/helper";
|
||||||
import {createEditor, openEditorTab} from "@/editorTab";
|
import {createEditor, openEditorTab} from "@/editorTab";
|
||||||
import {DATA_PATH} from "@/const";
|
import {ASSETS_PATH} from "@/const";
|
||||||
|
|
||||||
export default class DrawJSPlugin extends Plugin {
|
export default class DrawJSPlugin extends Plugin {
|
||||||
onload() {
|
onload() {
|
||||||
|
@ -26,14 +26,14 @@ export default class DrawJSPlugin extends Plugin {
|
||||||
filter: ["Insert Drawing", "Add drawing", "whiteboard", "freehand", "graphics", "jsdraw"],
|
filter: ["Insert Drawing", "Add drawing", "whiteboard", "freehand", "graphics", "jsdraw"],
|
||||||
html: getMenuHTML("iconDraw", this.i18n.insertDrawing),
|
html: getMenuHTML("iconDraw", this.i18n.insertDrawing),
|
||||||
callback: (protyle: Protyle) => {
|
callback: (protyle: Protyle) => {
|
||||||
const path = DATA_PATH + generateSiyuanId() + ".svg";
|
const path = ASSETS_PATH + generateSiyuanId() + ".svg";
|
||||||
protyle.insert(getPreviewHTML(path), true, false);
|
protyle.insert(getPreviewHTML(path), true, false);
|
||||||
openEditorTab(this, path);
|
openEditorTab(this, path);
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
this.eventBus.on("open-menu-image", (e: any) => {
|
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) {
|
if(path === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
46
src/protyle.ts
Normal file
46
src/protyle.ts
Normal file
|
@ -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<boolean> {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue