diff --git a/src/EmbeddedFileLoader.ts b/src/EmbeddedFileLoader.ts index 6120783..b253605 100644 --- a/src/EmbeddedFileLoader.ts +++ b/src/EmbeddedFileLoader.ts @@ -1,9 +1,7 @@ -import { file } from "@babel/types"; -import { exportToBlob } from "@zsviczian/excalidraw"; import { FileId } from "@zsviczian/excalidraw/types/element/types"; import { BinaryFileData, DataURL } from "@zsviczian/excalidraw/types/types"; -import { App, Notice, TFile } from "obsidian"; -import { fileid, IMAGE_TYPES } from "./constants"; +import { App, MarkdownRenderer, Notice, TFile } from "obsidian"; +import { CASCADIA_FONT, fileid, FRONTMATTER_KEY_FONT, IMAGE_TYPES, VIRGIL_FONT } from "./constants"; import { ExcalidrawData } from "./ExcalidrawData"; import ExcalidrawView, { ExportSettings } from "./ExcalidrawView"; import { t } from "./lang/helpers"; @@ -111,8 +109,8 @@ export class EmbeddedFilesLoader { this.processedFiles.set(file.path,count+1); let hasSVGwithBitmap = false; const app = this.plugin.app; - const isExcalidrawFile = this.plugin.ea.isExcalidrawFile(file); - if (!(IMAGE_TYPES.contains(file.extension) || isExcalidrawFile)) { + const isExcalidrawFile = this.plugin.isExcalidrawFile(file); + if (!(IMAGE_TYPES.contains(file.extension) || isExcalidrawFile || file.extension==="md")) { return null; } const ab = await app.vault.readBinary(file); @@ -151,12 +149,23 @@ export class EmbeddedFilesLoader { case "jpeg":mimeType = "image/jpeg";break; case "jpg": mimeType = "image/jpeg";break; case "gif": mimeType = "image/gif";break; - case "svg": mimeType = "image/svg+xml";break; + case "svg": + case "md" : mimeType = "image/svg+xml";break; default: mimeType = "application/octet-stream"; } } - const dataURL = excalidrawSVG ?? (file.extension==="svg" ? await getSVGData(app,file) : await getDataURL(ab,mimeType)); - const size = await getImageSize(excalidrawSVG??app.vault.getResourcePath(file)); + const dataURL = excalidrawSVG + ?? (file.extension==="svg" + ? await getSVGData(app,file) + : (file.extension==="md" + ? await convertMarkdownToSVG(this.plugin,file) + : await getDataURL(ab,mimeType) + )); + const size = await getImageSize(excalidrawSVG + ?? (file.extension==="md" + ? dataURL + : app.vault.getResourcePath(file) + )); return { mimeType, fileId: await generateIdFromFile(ab), @@ -241,6 +250,55 @@ const getSVGData = async (app: App, file: TFile): Promise => { return svgToBase64(svg) as DataURL; } +const mdSVGwidth = 640; +const mdSVGmaxHeight = 800; +const convertMarkdownToSVG = async (plugin: ExcalidrawPlugin, file: TFile): Promise => { + const text = await plugin.app.vault.cachedRead(file); + const fileCache = plugin.app.metadataCache.getFileCache(file); + let fontName = "Virgil"; + let fontBase64 = VIRGIL_FONT; + if (fileCache?.frontmatter && fileCache.frontmatter[FRONTMATTER_KEY_FONT]!=null) { + const font = fileCache.frontmatter[FRONTMATTER_KEY_FONT]; + switch(font){ + case "Virgil": fontName = "Virgil";fontBase64 = VIRGIL_FONT; break; + case "Cascadia": fontName = "Cascadia";fontBase64 = CASCADIA_FONT; break; + default: + const f = plugin.app.metadataCache.getFirstLinkpathDest(font,file.path); + if(f) { + const ab = await plugin.app.vault.readBinary(f); + const mimeType="application/font-woff"; + fontName = f.basename; + fontBase64 = ` @font-face {font-family: "${fontName}";src: url("${await getDataURL(ab,mimeType)}") format("${f.extension}");}`; + } + } + } + + const span = createEl("span"); + span.setAttribute("xmlns","http://www.w3.org/1999/xhtml"); + span.setAttribute("style","font-family: "+fontName+";"); + await MarkdownRenderer.renderMarkdown(text,span,file.path,plugin); + span.querySelectorAll(":scope > *[class^='frontmatter']").forEach((el)=>span.removeChild(el)); + const xml = new XMLSerializer().serializeToString(span); + let svgStyle = ' width="'+mdSVGwidth+'px" height="100%"'; + let foreignObjectStyle = ' width="'+mdSVGwidth+'px" height="100%"'; + let svg= '' + + xml+''; + const parser = new DOMParser(); + const doc = parser.parseFromString(svg,"image/svg+xml"); + const svgEl = doc.firstElementChild; + const div = createDiv(); + div.appendChild(svgEl); + document.body.appendChild(div); + const height = svgEl.firstElementChild.scrollHeight; + const svgHeight = height <= mdSVGmaxHeight ? height : mdSVGmaxHeight; + document.body.removeChild(div); + svgStyle = ' width="'+mdSVGwidth+'px" height="'+svgHeight+'px"'; + foreignObjectStyle = ' width="'+mdSVGwidth+'px" height="'+svgHeight+'px"'; + svg= '' + + xml+''; + return svgToBase64(svg) as DataURL; +} + const getDataURL = async (file: ArrayBuffer,mimeType: string): Promise => { return new Promise((resolve, reject) => { const reader = new FileReader(); diff --git a/src/ExcalidrawView.ts b/src/ExcalidrawView.ts index 47e6b20..26591b9 100644 --- a/src/ExcalidrawView.ts +++ b/src/ExcalidrawView.ts @@ -348,6 +348,7 @@ export default class ExcalidrawView extends TextFileView { this.addAction(DISK_ICON_NAME,t("FORCE_SAVE"),async (ev)=> { await this.save(false); this.plugin.triggerEmbedUpdates(); + this.loadSceneFiles(); }); this.textIsRaw_Element = this.addAction(TEXT_DISPLAY_RAW_ICON_NAME,t("RAW"), (ev) => this.changeTextMode(TextMode.parsed)); @@ -1217,7 +1218,7 @@ export default class ExcalidrawView extends TextFileView { if (!onDropHook("file",[draggable.file],null)) { if(event[CTRL_OR_CMD] //.ctrlKey||event.metaKey) && (IMAGE_TYPES.contains(draggable.file.extension) - || this.plugin.isExcalidrawFile(draggable.file))) { + || draggable.file.extension==="md")) {//this.plugin.isExcalidrawFile(draggable.file) const f = draggable.file; const topX = currentPosition.x; const topY = currentPosition.y; diff --git a/src/constants.ts b/src/constants.ts index 208f926..78cb503 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -13,6 +13,7 @@ export const FRONTMATTER_KEY_CUSTOM_PREFIX = "excalidraw-link-prefix"; export const FRONTMATTER_KEY_CUSTOM_URL_PREFIX = "excalidraw-url-prefix"; export const FRONTMATTER_KEY_CUSTOM_LINK_BRACKETS = "excalidraw-link-brackets"; export const FRONTMATTER_KEY_DEFAULT_MODE = "excalidraw-default-mode"; +export const FRONTMATTER_KEY_FONT = "excalidraw-font"; export const VIEW_TYPE_EXCALIDRAW = "excalidraw"; export const ICON_NAME = "excalidraw-icon"; export const MAX_COLORS = 5;