From e98b1755eefc84614fbe900be25fdb13eae830d1 Mon Sep 17 00:00:00 2001 From: Zsolt Viczian Date: Sat, 19 Feb 2022 18:16:00 +0100 Subject: [PATCH] 1.6.13 --- docs/API/attributes_functions_overview.md | 6 + manifest.json | 2 +- package.json | 6 +- src/ExcalidrawAutomate.ts | 109 ++++++++++++++++- src/ExcalidrawData.ts | 42 ++++++- src/ExcalidrawView.ts | 68 +++++++++-- src/SuggestorInfo.ts | 30 +++++ src/Utils.ts | 9 ++ src/constants.ts | 142 ++++++++++++++++++++++ src/lang/locale/en.ts | 12 +- src/main.ts | 4 +- src/settings.ts | 14 +++ styles.css | 4 + versions.json | 2 +- yarn.lock | 10 ++ 15 files changed, 436 insertions(+), 24 deletions(-) diff --git a/docs/API/attributes_functions_overview.md b/docs/API/attributes_functions_overview.md index e5f0703..433d5e6 100644 --- a/docs/API/attributes_functions_overview.md +++ b/docs/API/attributes_functions_overview.md @@ -195,6 +195,12 @@ export interface ExcalidrawAutomate { selectElementsInView(elements: ExcalidrawElement[]): void; //sets selection in view generateElementId(): string; //returns an 8 character long random id cloneElement(element: ExcalidrawElement): ExcalidrawElement; //Returns a clone of the element with a new id + moveViewElementToZIndex(elementId:number, newZIndex:number): void; //Moves the element to a specific position in the z-index + hexStringToRgb(color: string):number[]; + rgbToHexString(color: number[]):string; + hslToRgb(color: number[]):number[]; + rgbToHsl(color:number[]):number[]; + colorNameToHex(color:string):string; } ``` diff --git a/manifest.json b/manifest.json index eb00bbd..f052933 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "obsidian-excalidraw-plugin", "name": "Excalidraw", - "version": "1.6.12", + "version": "1.6.13", "minAppVersion": "0.12.16", "description": "An Obsidian plugin to edit and view Excalidraw drawings", "author": "Zsolt Viczian", diff --git a/package.json b/package.json index d6f3950..725266f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-excalidraw-plugin", - "version": "1.6.9", + "version": "1.6.13", "description": "This is an Obsidian.md plugin that lets you view and edit Excalidraw drawings", "main": "main.js", "scripts": { @@ -17,7 +17,9 @@ "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "^5.0.0", - "roughjs": "^4.5.2" + "roughjs": "^4.5.2", + "lz-string": "^1.4.4", + "@types/lz-string": "^1.3.34" }, "devDependencies": { "@babel/core": "^7.16.12", diff --git a/src/ExcalidrawAutomate.ts b/src/ExcalidrawAutomate.ts index 1518879..fa40118 100644 --- a/src/ExcalidrawAutomate.ts +++ b/src/ExcalidrawAutomate.ts @@ -15,6 +15,7 @@ import { VIEW_TYPE_EXCALIDRAW, MAX_IMAGE_SIZE, PLUGIN_ID, + COLOR_NAMES, } from "./constants"; import { //debug, @@ -36,7 +37,6 @@ import { getMaximumGroups, intersectElementWithLine, } from "@zsviczian/excalidraw"; -import { stringify } from "querystring"; declare type ConnectionPoint = "top" | "bottom" | "left" | "right" | null; const GAP = 4; @@ -234,6 +234,11 @@ export interface ExcalidrawAutomate { generateElementId(): string; //returns an 8 character long random id cloneElement(element: ExcalidrawElement): ExcalidrawElement; //Returns a clone of the element with a new id moveViewElementToZIndex(elementId:number, newZIndex:number): void; //Moves the element to a specific position in the z-index + hexStringToRgb(color: string):number[]; + rgbToHexString(color: number[]):string; + hslToRgb(color: number[]):number[]; + rgbToHsl(color:number[]):number[]; + colorNameToHex(color:string):string; } declare let window: any; @@ -1348,6 +1353,108 @@ export async function initExcalidrawAutomate( elements: elements, commitToHistory: true, }); + }, + hexStringToRgb(color: string):number[] { + const res = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color); + return [parseInt(res[1], 16), parseInt(res[2], 16), parseInt(res[3], 16)]; + }, + rgbToHexString(color: number[]):string { + const colorInt = + ((Math.round(color[0]) & 0xff) << 16) + + ((Math.round(color[1]) & 0xff) << 8) + + (Math.round(color[2]) & 0xff); + const colorStr = colorInt.toString(16).toLowerCase(); + return "#"+"000000".substring(colorStr.length) + colorStr; + }, + hslToRgb(color: number[]):number[] { + const h = color[0] / 360; + const s = color[1] / 100; + const l = color[2] / 100; + let t2; + let t3; + let val; + + if (s === 0) { + val = l * 255; + return [val, val, val]; + } + + if (l < 0.5) { + t2 = l * (1 + s); + } else { + t2 = l + s - l * s; + } + + const t1 = 2 * l - t2; + + const rgb = [0, 0, 0]; + for (let i = 0; i < 3; i++) { + t3 = h + (1 / 3) * -(i - 1); + if (t3 < 0) { + t3++; + } + + if (t3 > 1) { + t3--; + } + + if (6 * t3 < 1) { + val = t1 + (t2 - t1) * 6 * t3; + } else if (2 * t3 < 1) { + val = t2; + } else if (3 * t3 < 2) { + val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + } else { + val = t1; + } + + rgb[i] = val * 255; + } + return rgb; + }, + rgbToHsl(color:number[]):number[] { + const r = color[0] / 255; + const g = color[1] / 255; + const b = color[2] / 255; + const min = Math.min(r, g, b); + const max = Math.max(r, g, b); + const delta = max - min; + let h; + let s; + + if (max === min) { + h = 0; + } else if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else if (b === max) { + h = 4 + (r - g) / delta; + } + + h = Math.min(h * 60, 360); + + if (h < 0) { + h += 360; + } + + const l = (min + max) / 2; + + if (max === min) { + s = 0; + } else if (l <= 0.5) { + s = delta / (max + min); + } else { + s = delta / (2 - max - min); + } + + return [h, s * 100, l * 100]; + }, + colorNameToHex(color:string):string { + if (COLOR_NAMES.has(color.toLowerCase().trim())) { + return COLOR_NAMES.get(color.toLowerCase().trim()); + } + return color.trim(); } }; await initFonts(); diff --git a/src/ExcalidrawData.ts b/src/ExcalidrawData.ts index a19e9ba..b596d1a 100644 --- a/src/ExcalidrawData.ts +++ b/src/ExcalidrawData.ts @@ -20,6 +20,8 @@ import ExcalidrawPlugin from "./main"; import { JSON_parse } from "./constants"; import { TextMode } from "./ExcalidrawView"; import { + compress, + decompress, getAttachmentsFolderAndFilePath, //getBakPath, getBinaryFileFromDataURL, @@ -86,8 +88,31 @@ export const REG_LINKINDEX_HYPERLINK = /^\w+:\/\//; //added \n at and of DRAWING_REG: https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/357 const DRAWING_REG = /\n# Drawing\n[^`]*(```json\n)([\s\S]*?)```\n/gm; //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/182 const DRAWING_REG_FALLBACK = /\n# Drawing\n(```json\n)?(.*)(```)?(%%)?/gm; +const DRAWING_COMPRESSED_REG = /\n# Drawing\n[^`]*(```compressed\-json\n)([\s\S]*?)```\n/gm; //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/182 +const DRAWING_COMPRESSED_REG_FALLBACK = /\n# Drawing\n(```compressed\-json\n)?(.*)(```)?(%%)?/gm; export function getJSON(data: string): { scene: string; pos: number } { - let res = data.matchAll(DRAWING_REG); + let res; + if(data.match(/```compressed\-json\n/gm)) { + res = data.matchAll(DRAWING_COMPRESSED_REG); + + //In case the user adds a text element with the contents "# Drawing\n" + let parts; + parts = res.next(); + if (parts.done) { + //did not find a match + res = data.matchAll(DRAWING_COMPRESSED_REG_FALLBACK); + parts = res.next(); + } + if (parts.value && parts.value.length > 1) { + const result = decompress(parts.value[2]); + return { + scene: result.substring(0, result.lastIndexOf("}") + 1), + pos: parts.value.index, + }; //this is a workaround in case sync merges two files together and one version is still an old version without the ```codeblock + } + return { scene: data, pos: parts.value ? parts.value.index : 0 }; + } + res = data.matchAll(DRAWING_REG); //In case the user adds a text element with the contents "# Drawing\n" let parts; @@ -107,8 +132,10 @@ export function getJSON(data: string): { scene: string; pos: number } { return { scene: data, pos: parts.value ? parts.value.index : 0 }; } -export function getMarkdownDrawingSection(jsonString: string) { - return `%%\n# Drawing\n\x60\x60\x60json\n${jsonString}\n\x60\x60\x60\n%%`; +export function getMarkdownDrawingSection(jsonString: string, compressed: boolean) { + return compressed + ? `%%\n# Drawing\n\x60\x60\x60compressed-json\n${compress(jsonString)}\n\x60\x60\x60\n%%` + : `%%\n# Drawing\n\x60\x60\x60json\n${jsonString}\n\x60\x60\x60\n%%`; } /** @@ -372,12 +399,14 @@ export class ExcalidrawData { if (!file) { return false; } + this.loaded = false; this.compatibilityMode = true; this.file = file; this.textElements = new Map< string, { raw: string; parsed: string; wrapAt: number } >(); + this.elementLinks = new Map(); this.setShowLinkBrackets(); this.setLinkPrefix(); this.setUrlPrefix(); @@ -394,6 +423,7 @@ export class ExcalidrawData { this.findNewTextElementsInScene(); this.findNewElementLinksInScene(); await this.setTextMode(TextMode.raw, true); //legacy files are always displayed in raw mode. + this.loaded = true; return true; } @@ -762,6 +792,7 @@ export class ExcalidrawData { * Generate markdown file representation of excalidraw drawing * @returns markdown string */ + disableCompression: boolean = false; generateMD(): string { let outString = "# Text Elements\n"; for (const key of this.textElements.keys()) { @@ -789,7 +820,10 @@ export class ExcalidrawData { outString += this.equations.size > 0 || this.files.size > 0 ? "\n" : ""; const sceneJSONstring = JSON.stringify(this.scene, null, "\t"); - return outString + getMarkdownDrawingSection(sceneJSONstring); + return outString + getMarkdownDrawingSection( + sceneJSONstring, + this.disableCompression ? false: this.plugin.settings.compress + ); } /** diff --git a/src/ExcalidrawView.ts b/src/ExcalidrawView.ts index 8979148..a41e52b 100644 --- a/src/ExcalidrawView.ts +++ b/src/ExcalidrawView.ts @@ -6,6 +6,7 @@ import { WorkspaceItem, Notice, Menu, + MarkdownView, } from "obsidian"; import * as React from "react"; import * as ReactDOM from "react-dom"; @@ -258,7 +259,7 @@ export default class ExcalidrawView extends TextFileView { //- by monkeypatches on detach(next) //This semaphore helps avoid collision of saves private preventSave:boolean = false; //this.saving is taken by Obsidian. When I set this, nothing got saved at all. - async save(preventReload: boolean = true) { + async save(preventReload: boolean = true, forcesave: boolean = false) { if(this.preventSave) { return; } @@ -278,7 +279,7 @@ export default class ExcalidrawView extends TextFileView { } this.preventReload = preventReload; - const allowSave = (this.dirty !== null && this.dirty) || this.autosaving; //dirty == false when view.file == null; + const allowSave = (this.dirty !== null && this.dirty) || this.autosaving || forcesave; //dirty == false when view.file == null; this.dirty = null; const scene = this.getScene(); @@ -365,8 +366,12 @@ export default class ExcalidrawView extends TextFileView { header = header.replace(REG_IMG, "$1"); } //end of remove - - return header + this.excalidrawData.generateMD(); + if(!this.excalidrawData.disableCompression) { + this.excalidrawData.disableCompression = this.isEditedAsMarkdownInOtherView(); + } + const reuslt = header + this.excalidrawData.generateMD(); + this.excalidrawData.disableCompression = false; + return reuslt; } if (this.compatibilityMode) { return JSON.stringify(scene, null, "\t"); @@ -610,7 +615,7 @@ export default class ExcalidrawView extends TextFileView { }); this.diskIcon = this.addAction(DISK_ICON_NAME, t("FORCE_SAVE"), async () => { - await this.save(false); + await this.save(false, true); this.plugin.triggerEmbedUpdates(); this.loadSceneFiles(); }); @@ -659,6 +664,7 @@ export default class ExcalidrawView extends TextFileView { ); } this.setupAutosaveTimer(); + this.contentEl.addClass("excalidraw-view"); } public setTheme(theme: string) { @@ -695,7 +701,9 @@ export default class ExcalidrawView extends TextFileView { public setupAutosaveTimer() { const timer = async () => { - if (this.dirty && + if ( + this.isLoaded && + this.dirty && this.dirty == this.file?.path && this.plugin.settings.autosave ) { @@ -747,7 +755,8 @@ export default class ExcalidrawView extends TextFileView { if (!this.file) { return; } - if (file) { + const loadOnModifyTrigger = (file && file === this.file); + if (loadOnModifyTrigger) { this.data = await this.app.vault.cachedRead(file); } if (fullreload) { @@ -757,7 +766,7 @@ export default class ExcalidrawView extends TextFileView { } this.excalidrawData.scene.appState.theme = this.excalidrawAPI.getAppState().theme; - await this.loadDrawing(false); + await this.loadDrawing(loadOnModifyTrigger); this.dirty = null; } @@ -783,8 +792,6 @@ export default class ExcalidrawView extends TextFileView { } data = this.data = data.replaceAll("\r\n", "\n").replaceAll("\r", "\n"); this.app.workspace.onLayoutReady(async () => { - this.dirty = null; - this.diskIcon.querySelector("svg").removeClass("excalidraw-dirty"); this.compatibilityMode = this.file.extension === "excalidraw"; await this.plugin.loadSettings(); if (this.compatibilityMode) { @@ -794,7 +801,9 @@ export default class ExcalidrawView extends TextFileView { if (!this.plugin.settings.compatibilityMode) { new Notice(t("COMPATIBILITY_MODE"), 4000); } + this.excalidrawData.disableCompression = true; } else { + this.excalidrawData.disableCompression = false; const textMode = getTextMode(data); this.changeTextMode(textMode, false); try { @@ -864,6 +873,7 @@ export default class ExcalidrawView extends TextFileView { }, 500); } + initialContainerSizeUpdate = false; /** * * @param justloaded - a flag to trigger zoom to fit after the drawing has been loaded @@ -871,6 +881,9 @@ export default class ExcalidrawView extends TextFileView { private async loadDrawing(justloaded: boolean) { const excalidrawData = this.excalidrawData.scene; this.justLoaded = justloaded; + this.initialContainerSizeUpdate =justloaded; + this.dirty = null; + this.diskIcon.querySelector("svg").removeClass("excalidraw-dirty"); const om = this.excalidrawData.getOpenMode(); this.preventReload = false; if (this.excalidrawRef) { @@ -922,6 +935,24 @@ export default class ExcalidrawView extends TextFileView { }); //files are loaded on excalidrawRef readyPromise } + const isCompressed = this.data.match(/```compressed\-json\n/gm) !== null; + + if( + !this.compatibilityMode && + (this.plugin.settings.compress !== isCompressed) && + !this.isEditedAsMarkdownInOtherView() + ) { + this.dirty = this.file?.path; + this.diskIcon.querySelector("svg").addClass("excalidraw-dirty"); + } + } + + isEditedAsMarkdownInOtherView():boolean { + //if the user is editing the same file in markdown mode, do not compress it + const leaves = this.app.workspace.getLeavesOfType("markdown"); + return leaves + .filter(leaf => (leaf.view as MarkdownView).file === this.file) + .length > 0; } //Compatibility mode with .excalidraw files @@ -961,6 +992,10 @@ export default class ExcalidrawView extends TextFileView { .setTitle(t("OPEN_AS_MD")) .setIcon("document") .onClick(async () => { + if(this.plugin.settings.compress === true) { + this.excalidrawData.disableCompression = true; + await this.save(true,true); + } this.setMarkdownView(); }); }) @@ -1814,7 +1849,10 @@ export default class ExcalidrawView extends TextFileView { st.editingLinearElement === null ) { const sceneVersion = getSceneVersion(et); - if (sceneVersion !== this.previousSceneVersion) { + if ( + sceneVersion > 0 && + sceneVersion !== this.previousSceneVersion + ) { this.previousSceneVersion = sceneVersion; this.dirty = this.file?.path; this.diskIcon.querySelector("svg").addClass("excalidraw-dirty"); @@ -2185,7 +2223,13 @@ export default class ExcalidrawView extends TextFileView { .filter((el: ExcalidrawElement) => el.boundElements?.map((e) => e.type).includes("text"), ); - api.updateContainerSize(containers); + if(containers.length > 0) { + if(this.initialContainerSizeUpdate) { //updateContainerSize will bump scene version which will trigger a false autosave + this.justLoaded = true; //after load, which will lead to a ping-pong between two syncronizing devices + } + api.updateContainerSize(containers); + } + this.initialContainerSizeUpdate = false; }; if (delay) { setTimeout(() => update(), 50); diff --git a/src/SuggestorInfo.ts b/src/SuggestorInfo.ts index b0eb389..f4d229a 100644 --- a/src/SuggestorInfo.ts +++ b/src/SuggestorInfo.ts @@ -446,6 +446,36 @@ export const EXCALIDRAW_AUTOMATE_INFO:SuggestorInfo[] = [ desc: "Moves the element to a specific position in the z-index", after: "", }, + { + field: "hexStringToRgb", + code: "hexStringToRgb(color: string):number[];", + desc: "Converts a HEX color to an RGB number array. #FF0000 to [255,0,0]", + after: "", + }, + { + field: "rgbToHexString", + code: "rgbToHexString(color: number[]):string;", + desc: "Converts an RGB number array to a HEX string. [255,0,0] to #FF0000", + after: "", + }, + { + field: "hslToRgb", + code: "hslToRgb(color: number[]):number[];", + desc: "Converts an HSL number array to an RGB number array. [0,100,50] to [255,0,0]", + after: "", + }, + { + field: "rgbToHsl", + code: "rgbToHsl(color:number[]):number[];", + desc: "Converts an RGB number array to an HSL number array. [255,0,0] to [0,100,50]", + after: "", + }, + { + field: "colorNameToHex", + code: "colorNameToHex(color:string):string;", + desc: "Converts a CSS color name to its HEX color equivalent. 'White' to #FFFFFF", + after: "", + }, ]; export const EXCALIDRAW_SCRIPTENGINE_INFO:SuggestorInfo[] = [ diff --git a/src/Utils.ts b/src/Utils.ts index 315c009..686b203 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -21,6 +21,7 @@ import { import ExcalidrawPlugin from "./main"; import { ExcalidrawElement } from "@zsviczian/excalidraw/types/element/types"; import { ExportSettings } from "./ExcalidrawView"; +import { compressToBase64, decompressFromBase64 } from "lz-string"; declare module "obsidian" { interface Workspace { @@ -550,6 +551,14 @@ export const getLinkParts = (fname: string): LinkParts => { }; }; +export const compress = (data:string):string => { + return compressToBase64(data).replace(/(.{1024})/g, "$1\n"); +}; + +export const decompress = (data:string):string => { + return decompressFromBase64(data.replaceAll("\n","").replaceAll("\r","")); +}; + export const errorlog = (data: {}) => { console.error({ plugin: "Excalidraw", ...data }); }; diff --git a/src/constants.ts b/src/constants.ts index 19b3fcb..751ba7e 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -55,6 +55,148 @@ export const TEXT_DISPLAY_RAW_ICON_NAME = "presentation"; export const FULLSCREEN_ICON_NAME = "fullscreen"; export const EXIT_FULLSCREEN_ICON_NAME = "exit-fullscreen"; export const SCRIPTENGINE_ICON_NAME = "ScriptEngine"; +export const COLOR_NAMES = new Map(); +COLOR_NAMES.set("aliceblue","#f0f8ff"); +COLOR_NAMES.set("antiquewhite","#faebd7"); +COLOR_NAMES.set("aqua","#00ffff"); +COLOR_NAMES.set("aquamarine","#7fffd4"); +COLOR_NAMES.set("azure","#f0ffff"); +COLOR_NAMES.set("beige","#f5f5dc"); +COLOR_NAMES.set("bisque","#ffe4c4"); +COLOR_NAMES.set("black","#000000"); +COLOR_NAMES.set("blanchedalmond","#ffebcd"); +COLOR_NAMES.set("blue","#0000ff"); +COLOR_NAMES.set("blueviolet","#8a2be2"); +COLOR_NAMES.set("brown","#a52a2a"); +COLOR_NAMES.set("burlywood","#deb887"); +COLOR_NAMES.set("cadetblue","#5f9ea0"); +COLOR_NAMES.set("chartreuse","#7fff00"); +COLOR_NAMES.set("chocolate","#d2691e"); +COLOR_NAMES.set("coral","#ff7f50"); +COLOR_NAMES.set("cornflowerblue","#6495ed"); +COLOR_NAMES.set("cornsilk","#fff8dc"); +COLOR_NAMES.set("crimson","#dc143c"); +COLOR_NAMES.set("cyan","#00ffff"); +COLOR_NAMES.set("darkblue","#00008b"); +COLOR_NAMES.set("darkcyan","#008b8b"); +COLOR_NAMES.set("darkgoldenrod","#b8860b"); +COLOR_NAMES.set("darkgray","#a9a9a9"); +COLOR_NAMES.set("darkgreen","#006400"); +COLOR_NAMES.set("darkkhaki","#bdb76b"); +COLOR_NAMES.set("darkmagenta","#8b008b"); +COLOR_NAMES.set("darkolivegreen","#556b2f"); +COLOR_NAMES.set("darkorange","#ff8c00"); +COLOR_NAMES.set("darkorchid","#9932cc"); +COLOR_NAMES.set("darkred","#8b0000"); +COLOR_NAMES.set("darksalmon","#e9967a"); +COLOR_NAMES.set("darkseagreen","#8fbc8f"); +COLOR_NAMES.set("darkslateblue","#483d8b"); +COLOR_NAMES.set("darkslategray","#2f4f4f"); +COLOR_NAMES.set("darkturquoise","#00ced1"); +COLOR_NAMES.set("darkviolet","#9400d3"); +COLOR_NAMES.set("deeppink","#ff1493"); +COLOR_NAMES.set("deepskyblue","#00bfff"); +COLOR_NAMES.set("dimgray","#696969"); +COLOR_NAMES.set("dodgerblue","#1e90ff"); +COLOR_NAMES.set("firebrick","#b22222"); +COLOR_NAMES.set("floralwhite","#fffaf0"); +COLOR_NAMES.set("forestgreen","#228b22"); +COLOR_NAMES.set("fuchsia","#ff00ff"); +COLOR_NAMES.set("gainsboro","#dcdcdc"); +COLOR_NAMES.set("ghostwhite","#f8f8ff"); +COLOR_NAMES.set("gold","#ffd700"); +COLOR_NAMES.set("goldenrod","#daa520"); +COLOR_NAMES.set("gray","#808080"); +COLOR_NAMES.set("green","#008000"); +COLOR_NAMES.set("greenyellow","#adff2f"); +COLOR_NAMES.set("honeydew","#f0fff0"); +COLOR_NAMES.set("hotpink","#ff69b4"); +COLOR_NAMES.set("indianred","#cd5c5c"); +COLOR_NAMES.set("indigo","#4b0082"); +COLOR_NAMES.set("ivory","#fffff0"); +COLOR_NAMES.set("khaki","#f0e68c"); +COLOR_NAMES.set("lavender","#e6e6fa"); +COLOR_NAMES.set("lavenderblush","#fff0f5"); +COLOR_NAMES.set("lawngreen","#7cfc00"); +COLOR_NAMES.set("lemonchiffon","#fffacd"); +COLOR_NAMES.set("lightblue","#add8e6"); +COLOR_NAMES.set("lightcoral","#f08080"); +COLOR_NAMES.set("lightcyan","#e0ffff"); +COLOR_NAMES.set("lightgoldenrodyellow","#fafad2"); +COLOR_NAMES.set("lightgrey","#d3d3d3"); +COLOR_NAMES.set("lightgreen","#90ee90"); +COLOR_NAMES.set("lightpink","#ffb6c1"); +COLOR_NAMES.set("lightsalmon","#ffa07a"); +COLOR_NAMES.set("lightseagreen","#20b2aa"); +COLOR_NAMES.set("lightskyblue","#87cefa"); +COLOR_NAMES.set("lightslategray","#778899"); +COLOR_NAMES.set("lightsteelblue","#b0c4de"); +COLOR_NAMES.set("lightyellow","#ffffe0"); +COLOR_NAMES.set("lime","#00ff00"); +COLOR_NAMES.set("limegreen","#32cd32"); +COLOR_NAMES.set("linen","#faf0e6"); +COLOR_NAMES.set("magenta","#ff00ff"); +COLOR_NAMES.set("maroon","#800000"); +COLOR_NAMES.set("mediumaquamarine","#66cdaa"); +COLOR_NAMES.set("mediumblue","#0000cd"); +COLOR_NAMES.set("mediumorchid","#ba55d3"); +COLOR_NAMES.set("mediumpurple","#9370d8"); +COLOR_NAMES.set("mediumseagreen","#3cb371"); +COLOR_NAMES.set("mediumslateblue","#7b68ee"); +COLOR_NAMES.set("mediumspringgreen","#00fa9a"); +COLOR_NAMES.set("mediumturquoise","#48d1cc"); +COLOR_NAMES.set("mediumvioletred","#c71585"); +COLOR_NAMES.set("midnightblue","#191970"); +COLOR_NAMES.set("mintcream","#f5fffa"); +COLOR_NAMES.set("mistyrose","#ffe4e1"); +COLOR_NAMES.set("moccasin","#ffe4b5"); +COLOR_NAMES.set("navajowhite","#ffdead"); +COLOR_NAMES.set("navy","#000080"); +COLOR_NAMES.set("oldlace","#fdf5e6"); +COLOR_NAMES.set("olive","#808000"); +COLOR_NAMES.set("olivedrab","#6b8e23"); +COLOR_NAMES.set("orange","#ffa500"); +COLOR_NAMES.set("orangered","#ff4500"); +COLOR_NAMES.set("orchid","#da70d6"); +COLOR_NAMES.set("palegoldenrod","#eee8aa"); +COLOR_NAMES.set("palegreen","#98fb98"); +COLOR_NAMES.set("paleturquoise","#afeeee"); +COLOR_NAMES.set("palevioletred","#d87093"); +COLOR_NAMES.set("papayawhip","#ffefd5"); +COLOR_NAMES.set("peachpuff","#ffdab9"); +COLOR_NAMES.set("peru","#cd853f"); +COLOR_NAMES.set("pink","#ffc0cb"); +COLOR_NAMES.set("plum","#dda0dd"); +COLOR_NAMES.set("powderblue","#b0e0e6"); +COLOR_NAMES.set("purple","#800080"); +COLOR_NAMES.set("rebeccapurple","#663399"); +COLOR_NAMES.set("red","#ff0000"); +COLOR_NAMES.set("rosybrown","#bc8f8f"); +COLOR_NAMES.set("royalblue","#4169e1"); +COLOR_NAMES.set("saddlebrown","#8b4513"); +COLOR_NAMES.set("salmon","#fa8072"); +COLOR_NAMES.set("sandybrown","#f4a460"); +COLOR_NAMES.set("seagreen","#2e8b57"); +COLOR_NAMES.set("seashell","#fff5ee"); +COLOR_NAMES.set("sienna","#a0522d"); +COLOR_NAMES.set("silver","#c0c0c0"); +COLOR_NAMES.set("skyblue","#87ceeb"); +COLOR_NAMES.set("slateblue","#6a5acd"); +COLOR_NAMES.set("slategray","#708090"); +COLOR_NAMES.set("snow","#fffafa"); +COLOR_NAMES.set("springgreen","#00ff7f"); +COLOR_NAMES.set("steelblue","#4682b4"); +COLOR_NAMES.set("tan","#d2b48c"); +COLOR_NAMES.set("teal","#008080"); +COLOR_NAMES.set("thistle","#d8bfd8"); +COLOR_NAMES.set("tomato","#ff6347"); +COLOR_NAMES.set("turquoise","#40e0d0"); +COLOR_NAMES.set("violet","#ee82ee"); +COLOR_NAMES.set("wheat","#f5deb3"); +COLOR_NAMES.set("white","#ffffff"); +COLOR_NAMES.set("whitesmoke","#f5f5f5"); +COLOR_NAMES.set("yellow","#ffff00"); +COLOR_NAMES.set("yellowgreen","#9acd32"); export const SCRIPTENGINE_ICON = ``; export const DISK_ICON_NAME = "disk"; export const DISK_ICON = ``; diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts index 3b7f203..ce2bad0 100644 --- a/src/lang/locale/en.ts +++ b/src/lang/locale/en.ts @@ -64,7 +64,7 @@ export default { FILE_DOES_NOT_EXIST: "File does not exist. Hold down ALT (or ALT+SHIFT) and CLICK link button to create a new file.", FORCE_SAVE: - "Force-save to update transclusions in adjacent panes.\n(Please note, that autosave is always on)", + "Force-save to update transclusions in adjacent panes.\n(Check autosave settings in plugin settings.)", RAW: "Change to PREVIEW mode (only effects text-elements with links or transclusions)", PARSED: "Change to RAW mode (only effects text-elements with links or transclusions)", @@ -96,6 +96,16 @@ export default { "You can access your scripts from Excalidraw via the Obsidian Command Palette. Assign " + "hotkeys to your favorite scripts just like to any other Obsidian command. " + "The folder may not be the root folder of your Vault. ", + COMPRESS_NAME: "Compress Excalidraw JSON in Markdown", + COMPRESS_DESC: "By enabling this feature Excalidraw will store the drawing JSON in a Base64 compressed " + + "format using the LZ-String algorithm. " + + "This will reduce the chance of Excalidraw JSON cluttering your search results in Obsidian. " + + "As a side effect, this will also reduce the filesize of Excalidraw drawings. " + + "When you switch an Excalidraw drawing to Markdown view, using the options menu in Excalidraw, the file will " + + "be saved without compression, so that you can read and edit the JSON string. The drawing will be compressed again " + + "once you switch back to Excalidraw view. " + + "The setting only has effect 'point forward', meaning, existing drawings will not be effected by the setting " + + "until you open them and save them. ", AUTOSAVE_NAME: "Enable Autosave", AUTOSAVE_DESC: "Automatically save the active drawing, in case there are changes, every 15, 30 seconds, or 1, 2, 3, 4, or 5 minute. Save normally happens when you close Excalidraw or Obsidian, or move " + diff --git a/src/main.ts b/src/main.ts index 7e9b36d..c1035a8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1539,7 +1539,7 @@ export default class ExcalidrawPlugin extends Plugin { this.settings.matchTheme && isObsidianThemeDark() ? DARK_BLANK_DRAWING : BLANK_DRAWING; - return `${FRONTMATTER}\n${getMarkdownDrawingSection(blank)}`; + return `${FRONTMATTER}\n${getMarkdownDrawingSection(blank,this.settings.compress)}`; } /** @@ -1570,7 +1570,7 @@ export default class ExcalidrawPlugin extends Plugin { } return ( outString + - getMarkdownDrawingSection(JSON.stringify(JSON_parse(data), null, "\t")) + getMarkdownDrawingSection(JSON.stringify(JSON_parse(data), null, "\t"),this.settings.compress) ); } diff --git a/src/settings.ts b/src/settings.ts index fc749e5..aad1a6c 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -16,6 +16,7 @@ export interface ExcalidrawSettings { embedUseExcalidrawFolder: boolean; templateFilePath: string; scriptFolderPath: string; + compress: boolean; autosave: boolean; autosaveInterval: number; drawingFilenamePrefix: string; @@ -79,6 +80,7 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = { embedUseExcalidrawFolder: false, templateFilePath: "Excalidraw/Template.excalidraw", scriptFolderPath: "Excalidraw/Scripts", + compress: false, autosave: true, autosaveInterval: 15000, drawingFilenamePrefix: "Drawing ", @@ -261,6 +263,18 @@ export class ExcalidrawSettingTab extends PluginSettingTab { }), ); + new Setting(containerEl) + .setName(t("COMPRESS_NAME")) + .setDesc(fragWithHTML(t("COMPRESS_DESC"))) + .addToggle((toggle) => + toggle + .setValue(this.plugin.settings.compress) + .onChange(async (value) => { + this.plugin.settings.compress = value; + this.applySettingsUpdate(); + }), + ); + this.containerEl.createEl("h1", { text: t("FILENAME_HEAD") }); containerEl.createDiv("", (el) => { el.innerHTML = t("FILENAME_DESC"); diff --git a/styles.css b/styles.css index 370c9ba..0ce8d76 100644 --- a/styles.css +++ b/styles.css @@ -148,4 +148,8 @@ li[data-testid] { .excalidraw-dirty { color: red; +} + +.workspace-leaf-content .excalidraw-view { + padding: 0px 1px; /*1px so on ipad swipe in from left and right still works*/ } \ No newline at end of file diff --git a/versions.json b/versions.json index a8f1d10..4bf956e 100644 --- a/versions.json +++ b/versions.json @@ -1,4 +1,4 @@ { - "1.6.12": "0.12.16", + "1.6.13": "0.12.16", "1.4.2": "0.11.13" } diff --git a/yarn.lock b/yarn.lock index 760cab5..8976582 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1748,6 +1748,11 @@ "resolved" "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" "version" "0.0.29" +"@types/lz-string@^1.3.34": + "integrity" "sha512-j6G1e8DULJx3ONf6NdR5JiR2ZY3K3PaaqiEuKYkLQO0Czfi1AzrtjfnfCROyWGeDd5IVMKCwsgSmMip9OWijow==" + "resolved" "https://registry.npmjs.org/@types/lz-string/-/lz-string-1.3.34.tgz" + "version" "1.3.34" + "@types/mime@^1": "integrity" "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" "resolved" "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz" @@ -5866,6 +5871,11 @@ dependencies: "yallist" "^4.0.0" +"lz-string@^1.4.4": + "integrity" "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=" + "resolved" "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz" + "version" "1.4.4" + "magic-string@^0.25.0", "magic-string@^0.25.7": "integrity" "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==" "resolved" "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz"