Compare commits

..

20 Commits

Author SHA1 Message Date
Zsolt Viczian
cc7227d164 1.4.18 2021-12-04 16:38:21 +01:00
zsviczian
c75e7fb76c Merge pull request #293 from qifei9/patch-1
Update zh-cn.ts
2021-12-04 13:15:21 +01:00
Zsolt Viczian
6d3eb20ff1 check if exists before adding to embeddedFiles 2021-12-04 13:14:39 +01:00
qifei9
a603e4eeac Update zh-cn.ts
Fix the translation of `COMPATIBILITY_MODE_DESC` of zh-cn
2021-12-04 19:44:59 +08:00
zsviczian
ac260925dd Update ExcalidrawView.ts 2021-12-03 12:51:15 +01:00
Zsolt Viczian
1a2e7ac23f 1.4.17 2021-12-01 22:05:09 +01:00
Zsolt Viczian
1eb9b88f4b updated readme 2021-11-30 20:12:05 +01:00
Zsolt Viczian
a7814f383a 1.4.16 2021-11-30 19:57:50 +01:00
zsviczian
54e6d47df0 Update README.md 2021-11-30 14:59:19 +01:00
zsviczian
55ea1cf121 Update README.md 2021-11-30 14:57:02 +01:00
zsviczian
a2982f3406 Update EmbeddedFileLoader.ts 2021-11-30 14:52:21 +01:00
zsviczian
633ff1fea8 #286
https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/286#issuecomment-982179639
2021-11-30 08:46:05 +01:00
Zsolt Viczian
3312df0743 Merge branch 'master' of https://github.com/zsviczian/obsidian-excalidraw-plugin 2021-11-29 22:03:30 +01:00
Zsolt Viczian
0722bb8133 1.4.15 2021-11-29 22:02:59 +01:00
zsviczian
c9be4d95d7 Update README.md 2021-11-29 14:46:47 +01:00
Zsolt Viczian
023ddcec39 en.ts edited 2021-11-28 21:09:54 +01:00
zsviczian
9255643646 Update README.md 2021-11-28 21:09:04 +01:00
Zsolt Viczian
36ead43102 1.4.14 2021-11-28 20:54:51 +01:00
zsviczian
f61d000326 Update README.md 2021-11-28 07:52:44 +01:00
zsviczian
9bb254dc48 Update README.md 2021-11-28 07:42:21 +01:00
13 changed files with 252 additions and 72 deletions

View File

@@ -11,6 +11,8 @@ Please upgrade to Obsidian v0.12.19 or higher to get the latest release.
|[![3 Groups](https://user-images.githubusercontent.com/14358394/125160323-96f89580-e17c-11eb-9bce-8eb1067a51bb.jpg)](https://youtu.be/QOL1KF7-kdc)|[![4 Stencil](https://user-images.githubusercontent.com/14358394/125160332-9f50d080-e17c-11eb-98e9-fec60fe147d9.jpg)](https://youtu.be/aSgcbfspvfo)|[![5 embedding](https://user-images.githubusercontent.com/14358394/125160341-a546b180-e17c-11eb-9de8-d87fdc844c9c.jpg)](https://youtu.be/MaJ5jJwBRWs)|
|[![6 Links](https://user-images.githubusercontent.com/14358394/125160346-aa0b6580-e17c-11eb-930b-4024807040d1.jpg)](https://youtu.be/MXzeCOEExNo)|[![7 Markdown](https://user-images.githubusercontent.com/14358394/125160354-b2fc3700-e17c-11eb-81af-9e71e461f6dd.jpg)](https://youtu.be/R0IAg0s-wQE)|[![8 Templates](https://user-images.githubusercontent.com/14358394/125160360-b8f21800-e17c-11eb-8bd8-79d4e3f6e92d.jpg)](https://youtu.be/ibdS7ykwpW4)|
|[![9 Excalidraw Automate](https://user-images.githubusercontent.com/14358394/125160367-bdb6cc00-e17c-11eb-92f1-6f59faea85fd.jpg)](https://youtu.be/VRZVujfVab0)|[![10 Miscellaneous](https://user-images.githubusercontent.com/14358394/125160374-c3141680-e17c-11eb-8cc2-dfaffd903d15.jpg)](https://youtu.be/D1iBYo1_jjc)|[![Image Elements](https://user-images.githubusercontent.com/14358394/138607067-ccb62f92-48a4-4880-ac6e-68c1bf86ac2c.png)](https://www.youtube.com/watch?v=_c_0zpBJ4Xc&)|
|[![LaTex Demo](https://user-images.githubusercontent.com/14358394/143732412-1c65227e-4381-406d-847a-b001ab3506ca.jpg)](https://youtu.be/r08wk-58DPk)|[![markdown embeds](https://user-images.githubusercontent.com/14358394/143732440-90bfa029-8615-462e-ada3-c903d71a82c9.jpg)](https://youtu.be/tsecSfnTMow)|[![markdownAdvanced](https://user-images.githubusercontent.com/14358394/143783906-15cee494-c6d5-4495-a2ca-74634e4e7355.jpg)](https://youtu.be/K6qZkTz8GHs)|
# Key features
- The plugin aims to integrate Excalidraw seamlessly into Obsidian including Command Palette actions, File Explorer features, Option Menu commands, and the Ribbon Button.
@@ -58,6 +60,17 @@ Please upgrade to Obsidian v0.12.19 or higher to get the latest release.
- `excalidraw-link-prefix: "📍"` preview prefix for internal links
- `excalidraw-url-prefix: "🌐"` preview prefix for external links
- `excalidraw-link-brackets: true|false` whether or not to display brackets around links in preview
- Embed complete markdown files into your drawings
- Drag from the desired file from the Obsidian file explorer and hold down CTRL/CMD while dropping the file onto the canvas.
- Use the command palette action: `Insert markdown file from vault`
- Use custom woff, woff2 or TTF font to display the document, you can set the default font to use under Excalidraw Settings.
- You can set a custom css for rendering the snapshot image of your markdown document. Only operating system standard fonts are supported as the font-family ([Win10](https://docs.microsoft.com/en-us/typography/fonts/windows_10_font_list), [Mac & iOS](https://developer.apple.com/fonts/system-fonts/)), plus you can set one additional custom font using the setting explained above. (for a demonstration watch this [video](https://youtu.be/K6qZkTz8GHs) and check out this [sample css](https://github.com/zsviczian/obsidian-excalidraw-plugin/discussions/281)).
- To help with styling you can observe the SVG snapshot of the markdown document created by Excalidraw. Open Obsidian Developer Console (CTRL+Shift+i) and execute the following command: `ExcalidrawAutomate.mostRecentMarkdownSVG`
- You can control appearance of the embedded markdown file on a file by file bases by adding the following front matter keys to your markdown document:
- `excalidraw-font: Virgil|Cascadia|font_file_name.extension`
- `excalidraw-font-color: css-color-name|#HEXcolor|any-other-html-standard-format`, you can find css color names [here](https://www.w3schools.com/colors/colors_names.asp).
- `excalidraw-css: "css-filename|css snippet"`
- Switch to markdown view or use CTRL/CMD+ALT/OPT click on the image to edit properties of the embed: `[[filename#^blockref|WIDTHxMAXHEIGHT]]`
- Includes full [QuickAdd](https://github.com/chhoumann/quickadd), [Templater](https://silentvoid13.github.io/Templater/) and [Dataview](https://blacksmithgu.github.io/obsidian-dataview/docs/api/intro/) support through ExcalidrawAutomate. Check out the [detailed help + examples](https://zsviczian.github.io/obsidian-excalidraw-plugin/). I also have a [YouTube ExcalidrawAutomate Playlist](https://www.youtube.com/playlist?list=PL6mqgtMZ4NP1IR4nXxSlMA4PA5E-qpyHZ) with lots of examples.
- REQUIRES AN OBSIDIAN SYNC SUBSCRIPTION: Full drawing file history and synchronization between devices
- Multilanguage support: if you'd like to help out by translating the plugin, please get in contact with me.

View File

@@ -52,8 +52,20 @@ export interface ExcalidrawAutomate {
}
}
):Promise<string>;
createSVG (templatePath?:string, embedFont?:boolean):Promise<SVGSVGElement>;
createPNG (templatePath?:string):Promise<any>;
createSVG (
templatePath?:string,
embedFont?:boolean,
exportSettings?:ExportSettings, //see ExcalidrawAutomate.getExportSettings(boolean,boolean)
loader?:EmbeddedFilesLoader, //see ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
theme?:string
):Promise<SVGSVGElement>;
createPNG (
templatePath?:string,
scale?:number,
exportSettings?:ExportSettings, //see ExcalidrawAutomate.getExportSettings(boolean,boolean)
loader?:EmbeddedFilesLoader, //see ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
theme?:string
):Promise<any>;
wrapText (text:string, lineLen:number):string;
addRect (topX:number, topY:number, width:number, height:number):string;
addDiamond (topX:number, topY:number, width:number, height:number):string;
@@ -84,7 +96,7 @@ export interface ExcalidrawAutomate {
}
):string ;
addImage(topX:number, topY:number, imageFile: TFile):Promise<string>;
addLaTex(topX:number, topY:number, tex: string, color?:string):Promise<string>;
addLaTex(topX:number, topY:number, tex: string):Promise<string>;
connectObjects (
objectA: string,
connectionA: ConnectionPoint,
@@ -134,6 +146,10 @@ export interface ExcalidrawAutomate {
view: ExcalidrawView, //the excalidraw view receiving the drop
pointerPosition: {x:number, y:number} //the pointer position on canvas at the time of drop
}):boolean;
mostRecentMarkdownSVG:SVGSVGElement; //Markdown renderer will drop a copy of the most recent SVG here for debugging purposes
//utility functions to generate EmbeddedFilesLoaderand ExportSettings objects
getEmbeddedFilesLoader(isDark?:boolean):EmbeddedFilesLoader;
getExportSettings(withBackground:boolean,withTheme:boolean):ExportSettings;
}
```

View File

@@ -1,7 +1,7 @@
{
"id": "obsidian-excalidraw-plugin",
"name": "Excalidraw",
"version": "1.4.13",
"version": "1.4.18",
"minAppVersion": "0.12.16",
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
"author": "Zsolt Viczian",

View File

@@ -1,16 +1,14 @@
import { FileId } from "@zsviczian/excalidraw/types/element/types";
import { BinaryFileData, DataURL } from "@zsviczian/excalidraw/types/types";
import { link } from "fs";
import { App, MarkdownRenderer, Notice, TFile } from "obsidian";
import { CASCADIA_FONT, fileid, FRONTMATTER_KEY_CSS, FRONTMATTER_KEY_FONT, FRONTMATTER_KEY_FONTCOLOR, IMAGE_TYPES, nanoid, VIRGIL_FONT } from "./constants";
import { CASCADIA_FONT, fileid, FRONTMATTER_KEY_FONT, FRONTMATTER_KEY_FONTCOLOR, FRONTMATTER_KEY_MD_STYLE, IMAGE_TYPES, nanoid, VIRGIL_FONT } from "./constants";
import { createSVG } from "./ExcalidrawAutomate";
import { ExcalidrawData, getTransclusion } from "./ExcalidrawData";
import ExcalidrawView, { ExportSettings } from "./ExcalidrawView";
import { ExportSettings } from "./ExcalidrawView";
import { t } from "./lang/helpers";
import de from "./lang/locale/de";
import { tex2dataURL } from "./LaTeX";
import ExcalidrawPlugin from "./main";
import {debug, errorlog, getImageSize, getLinkParts, LinkParts, svgToBase64 } from "./Utils";
import {errorlog, getImageSize, getLinkParts, LinkParts, svgToBase64 } from "./Utils";
export declare type MimeType = "image/svg+xml" | "image/png" | "image/jpeg" | "image/gif" | "application/octet-stream";
export type FileData = BinaryFileData & {
@@ -50,9 +48,13 @@ export class EmbeddedFile {
if(!this.linkParts.width) this.linkParts.width = this.plugin.settings.mdSVGwidth;
if(!this.linkParts.height) this.linkParts.height = this.plugin.settings.mdSVGmaxHeight;
this.file = this.plugin.app.metadataCache.getFirstLinkpathDest(this.linkParts.path,hostPath);
if(!this.file) {
new Notice("Excalidraw Warning: could not find image file: "+imgPath,5000);
}
}
private fileChanged():boolean {
if(!this.file) return false;
return this.mtime !=this.file.stat.mtime;
}
@@ -282,24 +284,25 @@ const getSVGData = async (app: App, file: TFile): Promise<DataURL> => {
}
const convertMarkdownToSVG = async (plugin: ExcalidrawPlugin, file: TFile, linkParts: LinkParts): Promise<DataURL> => {
//const text = await plugin.app.vault.cachedRead(file);
//1.
//get the markdown text
const [text,line] = await getTransclusion(linkParts,plugin.app,file);
const fileCache = plugin.app.metadataCache.getFileCache(file);
//2.
//get styles
let fontName:string;
const fileCache = plugin.app.metadataCache.getFileCache(file);
let fontDef:string;
let font = plugin.settings.mdFont;
let fontName = plugin.settings.mdFont;
if (fileCache?.frontmatter && fileCache.frontmatter[FRONTMATTER_KEY_FONT]!=null) {
font = fileCache.frontmatter[FRONTMATTER_KEY_FONT];
fontName = fileCache.frontmatter[FRONTMATTER_KEY_FONT];
}
switch(font){
case "Virgil":
case "": fontName = "Virgil";fontDef = VIRGIL_FONT; break;
case "Cascadia": fontName = "Cascadia";fontDef = CASCADIA_FONT; break;
switch(fontName){
case "Virgil": fontDef = VIRGIL_FONT; break;
case "Cascadia": fontDef = CASCADIA_FONT; break;
case "": fontDef = ""; break;
default:
const f = plugin.app.metadataCache.getFirstLinkpathDest(font,file.path);
const f = plugin.app.metadataCache.getFirstLinkpathDest(fontName,file.path);
if(f) {
const ab = await plugin.app.vault.readBinary(f);
const mimeType=f.extension.startsWith("woff")?"application/font-woff":"font/truetype";
@@ -308,48 +311,120 @@ const convertMarkdownToSVG = async (plugin: ExcalidrawPlugin, file: TFile, linkP
const split = fontDef.split(";base64,",2);
fontDef = split[0]+";charset=utf-8;base64,"+split[1];
} else {
fontName = "Virgil";fontDef = VIRGIL_FONT;
fontDef = "";
}
}
const fontColor = fileCache?.frontmatter ? fileCache.frontmatter[FRONTMATTER_KEY_FONTCOLOR] : plugin.settings.mdFontColor;
//construct SVG
const div = createDiv();
div.setAttribute("xmlns","http://www.w3.org/1999/xhtml");
div.style.fontFamily = fontName;
if(fontColor) div.style.color = fontColor;
div.style.fontSize = "initial";
await MarkdownRenderer.renderMarkdown(text,div,file.path,plugin);
div.querySelectorAll(":scope > *[class^='frontmatter']").forEach((el)=>div.removeChild(el));
//brute force to swap <a> to <u> because links anyway don't work when the foreignObject is
//encapsulated in an img element. <a> does not render with an underline, <u> will.
const xml = (new XMLSerializer().serializeToString(div)).replaceAll("<a ","<u ").replaceAll("</a>","</u>");
let svgStyle = ' width="'+linkParts.width+'px" height="100%"';
const fontColor = fileCache?.frontmatter ? fileCache.frontmatter[FRONTMATTER_KEY_FONTCOLOR]??plugin.settings.mdFontColor:plugin.settings.mdFontColor;
let style = fileCache?.frontmatter ? (fileCache.frontmatter[FRONTMATTER_KEY_MD_STYLE]??"") : "";
let frontmatterCSSisAfile = false;
if(style && style!="") {
const f = plugin.app.metadataCache.getFirstLinkpathDest(style,file.path);
if(f) {
style = await plugin.app.vault.read(f);
frontmatterCSSisAfile = true;
}
}
if(!frontmatterCSSisAfile && plugin.settings.mdCSS && plugin.settings.mdCSS!="") {
const f = plugin.app.metadataCache.getFirstLinkpathDest(plugin.settings.mdCSS,file.path);
if(f) {
style += "\n"+await plugin.app.vault.read(f);
}
}
//3.
//SVG helper functions
//the SVG will first have ~infinite height. After sizing this will be reduced
let svgStyle = ' width="'+linkParts.width+'px" height="100000"';
let foreignObjectStyle = ' width="'+linkParts.width+'px" height="100%"';
const svg = () => '<svg xmlns="http://www.w3.org/2000/svg"'+svgStyle+'>'
const svg = (xml:string,xmlFooter:string,style?:string) =>
'<svg xmlns="http://www.w3.org/2000/svg"'+svgStyle+'>'
+ (style?'<style>'+style+'</style>':'')
+ '<foreignObject x="0" y="0"'+foreignObjectStyle+'>'
+ xml
+ '</foreignObject><defs><style>'
+ fontDef
+ '</style></defs></svg>';
+ xml
+ xmlFooter //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/286#issuecomment-982179639
+ '</foreignObject>'
+ (fontDef!==""
? ('<defs><style>' + fontDef + '</style></defs>')
: "")
+ '</svg>';
//4.
//create document div - this will be the contents of the foreign object
const mdDIV = createDiv();
mdDIV.setAttribute("xmlns","http://www.w3.org/1999/xhtml");
mdDIV.setAttribute("class","excalidraw-md-host");
// mdDIV.setAttribute("style",style);
if(fontName !== "") mdDIV.style.fontFamily = fontName;
mdDIV.style.overflow = "auto";
mdDIV.style.display = "block";
if(fontColor && fontColor!="") mdDIV.style.color = fontColor;
await MarkdownRenderer.renderMarkdown(text,mdDIV,file.path,plugin);
mdDIV.querySelectorAll(":scope > *[class^='frontmatter']").forEach((el)=>mdDIV.removeChild(el));
//5.1
//get SVG size.
//First I need to create a fully self contained copy of the document to convert
//blank styles into inline styles using computedStyle
const iframeHost = document.body.createDiv();
iframeHost.style.display = "none";
const iframe = iframeHost.createEl("iframe");
const iframeDoc = iframe.contentWindow.document;
if(style) {
const styleEl = iframeDoc.createElement("style");
styleEl.type = "text/css";
styleEl.innerHTML = style;
iframeDoc.head.appendChild(styleEl);
}
const stylingDIV = iframeDoc.importNode(mdDIV,true)
iframeDoc.body.appendChild(stylingDIV);
const footerDIV = createDiv();
footerDIV.setAttribute("class","excalidraw-md-footer");
iframeDoc.body.appendChild(footerDIV);
iframeDoc.body.querySelectorAll("*").forEach((el:HTMLElement)=>{
const elementStyle = el.style;
const computedStyle = window.getComputedStyle(el);
let style = "";
for (const prop in elementStyle) {
if (elementStyle.hasOwnProperty(prop)) {
style += prop + ": " + computedStyle[prop] + ";";
}
}
el.setAttribute("style",style);
});
const xmlINiframe = (new XMLSerializer().serializeToString(stylingDIV))
const xmlFooter = (new XMLSerializer().serializeToString(footerDIV))
document.body.removeChild(iframeHost);
//5.2
//get SVG size
const parser = new DOMParser();
const doc = parser.parseFromString(svg(),"image/svg+xml");
const doc = parser.parseFromString(svg(xmlINiframe,xmlFooter),"image/svg+xml");
const svgEl = doc.firstElementChild;
const host = createDiv();
host.appendChild(svgEl);
document.body.appendChild(host);
const height = svgEl.firstElementChild.firstElementChild.scrollHeight;
const footerHeight = svgEl.querySelector(".excalidraw-md-footer").scrollHeight;
const height = svgEl.querySelector(".excalidraw-md-host").scrollHeight + footerHeight;
const svgHeight = height <= linkParts.height ? height : linkParts.height;
document.body.removeChild(host);
//finalize SVG
svgStyle = ' width="'+linkParts.width+'px" height="'+svgHeight+'px"';
foreignObjectStyle = ' width="'+linkParts.width+'px" height="'+svgHeight+'px"';
return svgToBase64(svg()) as DataURL;
mdDIV.style.height = (svgHeight-footerHeight)+"px";
mdDIV.style.overflow = "hidden";
const xml = (new XMLSerializer().serializeToString(mdDIV))
const finalSVG = svg(xml,'<div class="excalidraw-md-footer"></div>',style);
plugin.ea.mostRecentMarkdownSVG = parser.parseFromString(finalSVG,"image/svg+xml").firstElementChild as SVGSVGElement;
return svgToBase64(finalSVG) as DataURL;
}
const getDataURL = async (file: ArrayBuffer,mimeType: string): Promise<DataURL> => {

View File

@@ -7,7 +7,6 @@ import {
FileId,
} from "@zsviczian/excalidraw/types/element/types";
import {
MarkdownRenderer,
normalizePath,
TFile
} from "obsidian"
@@ -19,7 +18,7 @@ import {
VIEW_TYPE_EXCALIDRAW,
MAX_IMAGE_SIZE,
} from "./constants";
import { debug, embedFontsInSVG, errorlog, getPNG, getSVG, scaleLoadedImage, wrapText } from "./Utils";
import { debug, embedFontsInSVG, errorlog, getPNG, getSVG, isObsidianThemeDark, scaleLoadedImage, wrapText } from "./Utils";
import { AppState, DataURL } from "@zsviczian/excalidraw/types/types";
import { EmbeddedFilesLoader, FileData, MimeType } from "./EmbeddedFileLoader";
import { tex2dataURL } from "./LaTeX";
@@ -78,15 +77,15 @@ export interface ExcalidrawAutomate {
createSVG (
templatePath?:string,
embedFont?:boolean,
exportSettings?:ExportSettings,
loader?:EmbeddedFilesLoader,
exportSettings?:ExportSettings, //see ExcalidrawAutomate.getExportSettings(boolean,boolean)
loader?:EmbeddedFilesLoader, //see ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
theme?:string
):Promise<SVGSVGElement>;
createPNG (
templatePath?:string,
scale?:number,
exportSettings?:ExportSettings,
loader?:EmbeddedFilesLoader,
exportSettings?:ExportSettings, //see ExcalidrawAutomate.getExportSettings(boolean,boolean)
loader?:EmbeddedFilesLoader, //see ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
theme?:string
):Promise<any>;
wrapText (text:string, lineLen:number):string;
@@ -169,7 +168,10 @@ export interface ExcalidrawAutomate {
view: ExcalidrawView, //the excalidraw view receiving the drop
pointerPosition: {x:number, y:number} //the pointer position on canvas at the time of drop
}):boolean;
renderMarkdown(text:string,el:HTMLElement):Promise<void>;
mostRecentMarkdownSVG:SVGSVGElement; //Markdown renderer will drop a copy of the most recent SVG here for debugging purposes
//utility functions to generate EmbeddedFilesLoaderand ExportSettings objects
getEmbeddedFilesLoader(isDark?:boolean):EmbeddedFilesLoader;
getExportSettings(withBackground:boolean,withTheme:boolean):ExportSettings;
}
declare let window: any;
@@ -359,9 +361,26 @@ export async function initExcalidrawAutomate(plugin: ExcalidrawPlugin):Promise<E
templatePath?:string,
embedFont:boolean = false,
exportSettings?:ExportSettings,
loader:EmbeddedFilesLoader = new EmbeddedFilesLoader(this.plugin),
loader?:EmbeddedFilesLoader,
theme?:string,
):Promise<SVGSVGElement> {
if(!theme) {
theme = this.plugin.settings.previewMatchObsidianTheme
? (isObsidianThemeDark() ? "dark" : "light")
: (!this.plugin.settings.exportWithTheme
? "light"
: undefined);
}
if(theme && !exportSettings) {
exportSettings = {
withBackground: this.plugin.settings.exportBackground,
withTheme: true
}
}
if(!loader) {
const loader = new EmbeddedFilesLoader(this.plugin,theme?(theme==="dark"):undefined);
}
return await createSVG(
templatePath,
embedFont,
@@ -378,9 +397,26 @@ export async function initExcalidrawAutomate(plugin: ExcalidrawPlugin):Promise<E
templatePath?:string,
scale:number=1,
exportSettings?:ExportSettings,
loader:EmbeddedFilesLoader = new EmbeddedFilesLoader(this.plugin),
loader?:EmbeddedFilesLoader,
theme?:string
) {
if(!theme) {
theme = this.plugin.settings.previewMatchObsidianTheme
? (isObsidianThemeDark() ? "dark" : "light")
: (!this.plugin.settings.exportWithTheme
? "light"
: undefined);
}
if(theme && !exportSettings) {
exportSettings = {
withBackground: this.plugin.settings.exportBackground,
withTheme: true
}
}
if(!loader) {
const loader = new EmbeddedFilesLoader(this.plugin,theme?(theme==="dark"):undefined);
}
return await createPNG(
templatePath,
scale,
@@ -750,9 +786,13 @@ export async function initExcalidrawAutomate(plugin: ExcalidrawPlugin):Promise<E
return await this.targetView.addElements(elements,repositionToCursor,save,this.imagesDict);
},
onDropHook:null,
async renderMarkdown(text:string,el:HTMLElement):Promise<void> {
await MarkdownRenderer.renderMarkdown(text,el,'',this.plugin);
}
mostRecentMarkdownSVG:null,
getEmbeddedFilesLoader(isDark?:boolean):EmbeddedFilesLoader {
return new EmbeddedFilesLoader(this.plugin,isDark);
},
getExportSettings(withBackground:boolean,withTheme:boolean):ExportSettings{
return {withBackground,withTheme};
},
};
await initFonts();
return window.ExcalidrawAutomate;
@@ -928,14 +968,15 @@ export async function createPNG(
templatePath:string = undefined,
scale:number=1,
exportSettings:ExportSettings,
loader:EmbeddedFilesLoader = new EmbeddedFilesLoader(this.plugin),
loader:EmbeddedFilesLoader,
forceTheme:string = undefined,
canvasTheme: string = undefined,
canvasBackgroundColor: string = undefined,
automateElements: ExcalidrawElement[] = [],
plugin: ExcalidrawPlugin,
) {
const template = templatePath ? (await getTemplate(this.plugin,templatePath,true,loader)) : null;
if(!loader) loader = new EmbeddedFilesLoader(plugin);
const template = templatePath ? (await getTemplate(plugin,templatePath,true,loader)) : null;
let elements = template?.elements ?? [];
elements = elements.concat(automateElements);
return await getPNG(
@@ -962,13 +1003,14 @@ export async function createSVG(
templatePath:string = undefined,
embedFont:boolean = false,
exportSettings:ExportSettings,
loader:EmbeddedFilesLoader = new EmbeddedFilesLoader(this.plugin),
loader:EmbeddedFilesLoader,
forceTheme:string = undefined,
canvasTheme: string = undefined,
canvasBackgroundColor: string = undefined,
automateElements: ExcalidrawElement[] = [],
plugin: ExcalidrawPlugin,
):Promise<SVGSVGElement> {
if(!loader) loader = new EmbeddedFilesLoader(plugin);
const template = templatePath ? (await getTemplate(plugin,templatePath,true,loader)) : null;
let elements = template?.elements ?? [];
elements = elements.concat(automateElements);

View File

@@ -1,4 +1,4 @@
import { App, TFile } from "obsidian";
import { App, Notice, TFile } from "obsidian";
import {
nanoid,
FRONTMATTER_KEY_CUSTOM_PREFIX,
@@ -641,7 +641,10 @@ export class ExcalidrawData {
*/
public setFile(fileId:FileId, data:EmbeddedFile) {
//always store absolute path because in case of paste, relative path may not resolve ok
if(!data) return;
this.files.set(fileId,data);
if(!data.file) return;
this.plugin.filesMaster.set(
fileId,
{

View File

@@ -58,6 +58,8 @@ const REG_LINKINDEX_INVALIDCHARS = /[<>:"\\|?*]/g;
export const addFiles = async (files:FileData[], view: ExcalidrawView,isDark?:boolean) => {
if(!files || files.length === 0 || !view) return;
files = files.filter((f)=>(f.size.height>0) && (f.size.width>0)); //height will be zero when file does not exisig in case of broken embedded file links
if(files.length === 0) return;
const [dirty, scene] = scaleLoadedImage(view.getScene(),files);
if(isDark===undefined) isDark = scene.appState.theme;
if(dirty) {
@@ -71,6 +73,7 @@ export const addFiles = async (files:FileData[], view: ExcalidrawView,isDark?:bo
for(const f of files) {
if(view.excalidrawData.hasFile(f.id)) {
const embeddedFile = view.excalidrawData.getFile(f.id);
embeddedFile.setImage(
f.dataURL,
f.mimeType,
@@ -861,7 +864,8 @@ export default class ExcalidrawView extends TextFileView {
}
};
const el: ExcalidrawElement[] = this.excalidrawAPI.getSceneElements();
const newIds = newElements.map((e)=>e.id);
const el: ExcalidrawElement[] = this.excalidrawAPI.getSceneElements().filter((e:ExcalidrawElement)=>!newIds.includes(e.id));
let st: AppState = this.excalidrawAPI.getAppState();
if(repositionToCursor) newElements = repositionElementsToCursor(newElements,currentPosition,true);
@@ -891,7 +895,7 @@ export default class ExcalidrawView extends TextFileView {
);
this.excalidrawData.setFile(images[k].id,embeddedFile);
}
if(images[k].tex) {
if(images[k].latex) {
this.excalidrawData.setEquation(
images[k].id,
{
@@ -1398,4 +1402,4 @@ export default class ExcalidrawView extends TextFileView {
export function getTextMode(data:string):TextMode {
const parsed = data.search("excalidraw-plugin: parsed\n")>-1 || data.search("excalidraw-plugin: locked\n")>-1; //locked for backward compatibility
return parsed ? TextMode.parsed : TextMode.raw;
}
}

View File

@@ -15,7 +15,7 @@ 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 FRONTMATTER_KEY_FONTCOLOR = "excalidraw-font-color";
export const FRONTMATTER_KEY_CSS = "excalidraw-css-file";
export const FRONTMATTER_KEY_MD_STYLE = "excalidraw-css";
export const VIEW_TYPE_EXCALIDRAW = "excalidraw";
export const ICON_NAME = "excalidraw-icon";
export const MAX_COLORS = 5;

View File

@@ -143,6 +143,14 @@ export default {
MD_DEFAULT_COLOR_NAME: "The default font color to use for embedded markdown files.",
MD_DEFAULT_COLOR_DESC: 'Set this to allowed css color names e.g. "steelblue" (https://www.w3schools.com/colors/colors_names.asp), or a valid hexadecimal color e.g. "#e67700". ' +
'You can override this setting by adding the following frontmatter-key to the embedded markdown file: "excalidraw-font-color: color_name_or_rgbhex"',
MD_CSS_NAME: "CSS file",
MD_CSS_DESC: "The filename of the CSS to apply to markdown embeds. Provide the filename with extension (e.g. 'md-embed.css'). The css file may also be a plain " +
"markdown file (e.g. 'md-embed-css.md'), just make sure the content is written using valid css syntax. " +
"If you need to look at the HTML code you are applying the CSS to, then open Obsidian Developer Console (CTRL+SHIFT+i) and type in the follwoing command: " +
'"ExcalidrawAutomate.mostRecentMarkdownSVG". This will display the most recent SVG generated by Excalidraw. ' +
"Setting the font-family in the css is has limitations. By default only your operating system's standard fonts are available (see README for details). "+
"You can add one custom font beyond that using the setting above. " +
'You can override this css setting by adding the following frontmatter-key to the embedded markdown file: "excalidraw-css: css_file_in_valut|css-snippet".',
EMBED_HEAD: "Embed & Export",
EMBED_PREVIEW_SVG_NAME: "Display SVG in markdown preview",
EMBED_PREVIEW_SVG_DESC: "The default is to display drawings as SVG images in the markdown preview. Turning this feature off, the markdown preview will display the drawing as an embedded PNG image.",

View File

@@ -118,9 +118,9 @@ export default {
SYNC_EXCALIDRAW_DESC: "如果 *.excalidraw 文件的修改比 *.md 文件的修改更新" +
",会根据 .excalidraw 文件更新 .md 文件中的绘图",
COMPATIBILITY_MODE_NAME: "以旧格式创建新绘图",
COMPATIBILITY_MODE_DESC: "通过启用此功能图形,您可以使用功能区图标、命令面板操作、 "+
"并且文件浏览器将仍旧保留 *.excalidraw 文件。 此设置还将" +
"关闭你打开旧格式绘图时的提醒消息",
COMPATIBILITY_MODE_DESC: "启用此功能后,你使用功能区图标、命令面板"+
"文件浏览器创建的绘图都将是旧格式 *.excalidraw 文件。 此设置还将" +
"关闭你打开并编辑旧格式绘图文件时的提醒消息",
EXPERIMENTAL_HEAD: "实验性特性",
EXPERIMENTAL_DESC: "这些设置不会立即生效,只有在刷新文件资源管理器或重新启动 Obsidian 时才会生效。",
FILETYPE_NAME: "在文件浏览器中给所有的 Excalidraw 文件加上 ✏️ 标识符",

View File

@@ -155,8 +155,8 @@ export default class ExcalidrawPlugin extends Plugin {
const self = this;
this.loadMathJax();
process.env.REACT_APP_LIBRARY_URL = "https://libraries.excalidraw.com/";
process.env.REACT_APP_LIBRARY_BACKEND = "https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries";
// process.env.REACT_APP_LIBRARY_URL = "https://libraries.excalidraw.com/";
// process.env.REACT_APP_LIBRARY_BACKEND = "https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries";
}
private loadMathJax() {
@@ -460,6 +460,8 @@ export default class ExcalidrawPlugin extends Plugin {
if(!this.settings.matchThemeTrigger) return;
//@ts-ignore
if(m[0]?.oldValue === m[0]?.target?.getAttribute("class")) return;
//@ts-ignore
if(m[0]?.oldValue?.includes("theme-dark") === m[0]?.target?.classList?.contains("theme-dark")) return;
const theme = isObsidianThemeDark() ? "dark":"light";
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
leaves.forEach((leaf:WorkspaceLeaf)=> {
@@ -487,8 +489,11 @@ export default class ExcalidrawPlugin extends Plugin {
private experimentalFileTypeDisplay() {
const insertFiletype = (el: HTMLElement) => {
if(el.childElementCount != 1) return;
//@ts-ignore
if(this.isExcalidrawFile(this.app.vault.getAbstractFileByPath(el.attributes["data-path"].value))) {
const filename = el.getAttribute("data-path");
if(!filename) return;
const f = this.app.vault.getAbstractFileByPath(filename);
if(!f || !(f instanceof TFile)) return;
if(this.isExcalidrawFile(f)) {
el.insertBefore(createDiv({cls:"nav-file-tag",text:this.settings.experimentalFileTag}),el.firstChild);
}
};

View File

@@ -56,6 +56,7 @@ export interface ExcalidrawSettings {
mdSVGmaxHeight: number,
mdFont: string,
mdFontColor: string,
mdCSS: string,
}
export const DEFAULT_SETTINGS: ExcalidrawSettings = {
@@ -109,6 +110,7 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
mdSVGmaxHeight: 800,
mdFont: "Virgil",
mdFontColor: "Black",
mdCSS: ""
}
export class ExcalidrawSettingTab extends PluginSettingTab {
@@ -127,7 +129,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
const plugin = this.plugin;
this.applyDebounceTimer = window.setTimeout(() => {
plugin.saveSettings();
}, 200);
}, 100);
if(requestReloadDrawings) this.requestReloadDrawings = true;
}
@@ -478,6 +480,18 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
this.applySettingsUpdate(true);
}));
new Setting(containerEl)
.setName(t("MD_CSS_NAME"))
.setDesc(t("MD_CSS_DESC"))
.addText(text => text
.setPlaceholder("filename of css file in vault")
.setValue(this.plugin.settings.mdCSS)
.onChange((value) => {
this.requestReloadDrawings=true;
this.plugin.settings.mdCSS = value;
this.applySettingsUpdate(true);
}));
this.containerEl.createEl('h1', {text: t("EMBED_HEAD")});

View File

@@ -1,4 +1,4 @@
{
"1.4.13": "0.12.16",
"1.4.18": "0.12.16",
"1.4.2": "0.11.13"
}