import { App, ButtonComponent, DropdownComponent, normalizePath, PluginSettingTab, Setting, TextComponent, TFile, } from "obsidian"; import { GITHUB_RELEASES, VIEW_TYPE_EXCALIDRAW } from "./constants/constants"; import ExcalidrawView from "./ExcalidrawView"; import { t } from "./lang/helpers"; import type ExcalidrawPlugin from "./main"; import { PenStyle } from "./PenTypes"; import { DynamicStyle } from "./types"; import { PreviewImageType } from "./utils/UtilTypes"; import { setDynamicStyle } from "./utils/DynamicStyling"; import { getDrawingFilename, getEmbedFilename, } from "./utils/FileUtils"; import { PENS } from "./utils/Pens"; import { addIframe, fragWithHTML, setLeftHandedMode, } from "./utils/Utils"; import { imageCache } from "./utils/ImageCache"; import { ConfirmationPrompt } from "./dialogs/Prompt"; import { EmbeddableMDCustomProps } from "./dialogs/EmbeddableSettings"; import { EmbeddalbeMDFileCustomDataSettingsComponent } from "./dialogs/EmbeddableMDFileCustomDataSettingsComponent"; import { startupScript } from "./constants/starutpscript"; import { ModifierKeySet, ModifierSetType } from "./utils/ModifierkeyHelper"; import { ModifierKeySettingsComponent } from "./dialogs/ModifierKeySettings"; import { CROPPED_PREFIX } from "./utils/CarveOut"; export interface ExcalidrawSettings { folder: string; cropFolder: string; embedUseExcalidrawFolder: boolean; templateFilePath: string; scriptFolderPath: string; compress: boolean; autosave: boolean; autosaveInterval: number; autosaveIntervalDesktop: number; autosaveIntervalMobile: number; drawingFilenamePrefix: string; drawingEmbedPrefixWithFilename: boolean; drawingFilnameEmbedPostfix: string; drawingFilenameDateTime: string; useExcalidrawExtension: boolean; cropPrefix: string; displaySVGInPreview: boolean; //No longer used since 1.9.13 previewImageType: PreviewImageType; //Introduced with 1.9.13 allowImageCache: boolean; displayExportedImageIfAvailable: boolean; previewMatchObsidianTheme: boolean; width: string; dynamicStyling: DynamicStyle; isLeftHanded: boolean; iframeMatchExcalidrawTheme: boolean; matchTheme: boolean; matchThemeAlways: boolean; matchThemeTrigger: boolean; defaultMode: string; defaultPenMode: "never" | "mobile" | "always"; allowPinchZoom: boolean; allowWheelZoom: boolean; zoomToFitOnOpen: boolean; zoomToFitOnResize: boolean; zoomToFitMaxLevel: number; openInAdjacentPane: boolean; openInMainWorkspace: boolean; showLinkBrackets: boolean; linkPrefix: string; urlPrefix: string; parseTODO: boolean; todo: string; done: string; hoverPreviewWithoutCTRL: boolean; linkOpacity: number; allowCtrlClick: boolean; //if disabled only the link button in the view header will open links forceWrap: boolean; pageTransclusionCharLimit: number; wordWrappingDefault: number; removeTransclusionQuoteSigns: boolean; iframelyAllowed: boolean; pngExportScale: number; exportWithTheme: boolean; exportWithBackground: boolean; exportPaddingSVG: number; keepInSync: boolean; autoexportSVG: boolean; autoexportPNG: boolean; autoExportLightAndDark: boolean; autoexportExcalidraw: boolean; embedType: "excalidraw" | "PNG" | "SVG"; embedMarkdownCommentLinks: boolean; embedWikiLink: boolean; syncExcalidraw: boolean; compatibilityMode: boolean; experimentalFileType: boolean; experimentalFileTag: string; experimentalLivePreview: boolean; experimentalEnableFourthFont: boolean; experimantalFourthFont: string; fieldSuggester: boolean; //loadCount: number; //version 1.2 migration counter drawingOpenCount: number; library: string; library2: {}; //patchCommentBlock: boolean; //1.3.12 imageElementNotice: boolean; //1.4.0 //runWYSIWYGpatch: boolean; //1.4.9 //fixInfinitePreviewLoop: boolean; //1.4.10 mdSVGwidth: number; mdSVGmaxHeight: number; mdFont: string; mdFontColor: string; mdBorderColor: string; mdCSS: string; scriptEngineSettings: { [key:string]: { [key:string]: { value?:string, hidden?: boolean, description?: string, valueset?: string[], height?: number, } } }; defaultTrayMode: boolean; previousRelease: string; showReleaseNotes: boolean; showNewVersionNotification: boolean; //mathjaxSourceURL: string; latexBoilerplate: string; taskboneEnabled: boolean; taskboneAPIkey: string; pinnedScripts: string[]; customPens: PenStyle[]; numberOfCustomPens: number; pdfScale: number; pdfBorderBox: boolean; pdfGapSize: number; pdfGroupPages: boolean; pdfLockAfterImport: boolean; pdfNumColumns: number; pdfNumRows: number; pdfDirection: "down" | "right"; pdfImportScale: number; laserSettings: { DECAY_TIME: number, DECAY_LENGTH: number, COLOR: string, }; embeddableMarkdownDefaults: EmbeddableMDCustomProps; canvasImmersiveEmbed: boolean, startupScriptPath: string, openAIAPIToken: string, openAIDefaultTextModel: string, openAIDefaultVisionModel: string, openAIDefaultImageGenerationModel: string, openAIURL: string, openAIImageGenerationURL: string, openAIImageEditsURL: string, openAIImageVariationURL: string, modifierKeyConfig: { Mac: Record, Win: Record, }, slidingPanesSupport: boolean; areaZoomLimit: number; } declare const PLUGIN_VERSION:string; export const DEFAULT_SETTINGS: ExcalidrawSettings = { folder: "Excalidraw", cropFolder: "", embedUseExcalidrawFolder: false, templateFilePath: "Excalidraw/Template.excalidraw", scriptFolderPath: "Excalidraw/Scripts", compress: false, autosave: true, autosaveInterval: 15000, autosaveIntervalDesktop: 15000, autosaveIntervalMobile: 10000, drawingFilenamePrefix: "Drawing ", drawingEmbedPrefixWithFilename: true, drawingFilnameEmbedPostfix: " ", drawingFilenameDateTime: "YYYY-MM-DD HH.mm.ss", useExcalidrawExtension: true, cropPrefix: CROPPED_PREFIX, displaySVGInPreview: undefined, previewImageType: undefined, allowImageCache: true, displayExportedImageIfAvailable: false, previewMatchObsidianTheme: false, width: "400", dynamicStyling: "colorful", isLeftHanded: false, iframeMatchExcalidrawTheme: true, matchTheme: false, matchThemeAlways: false, matchThemeTrigger: false, defaultMode: "normal", defaultPenMode: "never", allowPinchZoom: false, allowWheelZoom: false, zoomToFitOnOpen: true, zoomToFitOnResize: true, zoomToFitMaxLevel: 2, linkPrefix: "📍", urlPrefix: "🌐", parseTODO: false, todo: "☐", done: "🗹", hoverPreviewWithoutCTRL: false, linkOpacity: 1, openInAdjacentPane: false, openInMainWorkspace: true, showLinkBrackets: true, allowCtrlClick: true, forceWrap: false, pageTransclusionCharLimit: 200, wordWrappingDefault: 0, removeTransclusionQuoteSigns: true, iframelyAllowed: true, pngExportScale: 1, exportWithTheme: true, exportWithBackground: true, exportPaddingSVG: 10, //since 1.6.17, not only SVG but also PNG keepInSync: false, autoexportSVG: false, autoexportPNG: false, autoExportLightAndDark: false, autoexportExcalidraw: false, embedType: "excalidraw", embedMarkdownCommentLinks: true, embedWikiLink: true, syncExcalidraw: false, experimentalFileType: false, experimentalFileTag: "✏️", experimentalLivePreview: true, experimentalEnableFourthFont: false, experimantalFourthFont: "Virgil", fieldSuggester: true, compatibilityMode: false, //loadCount: 0, drawingOpenCount: 0, library: `deprecated`, library2: { type: "excalidrawlib", version: 2, source: GITHUB_RELEASES+PLUGIN_VERSION, libraryItems: [], }, //patchCommentBlock: true, imageElementNotice: true, //runWYSIWYGpatch: true, //fixInfinitePreviewLoop: true, mdSVGwidth: 500, mdSVGmaxHeight: 800, mdFont: "Virgil", mdFontColor: "Black", mdBorderColor: "Black", mdCSS: "", scriptEngineSettings: {}, defaultTrayMode: true, previousRelease: "0.0.0", showReleaseNotes: true, showNewVersionNotification: true, //mathjaxSourceURL: "https://cdn.jsdelivr.net/npm/mathjax@3.2.1/es5/tex-svg.js", latexBoilerplate: "\\color{blue}", taskboneEnabled: false, taskboneAPIkey: "", pinnedScripts: [], customPens: [ {...PENS["default"]}, {...PENS["highlighter"]}, {...PENS["finetip"]}, {...PENS["fountain"]}, {...PENS["marker"]}, {...PENS["thick-thin"]}, {...PENS["thin-thick-thin"]}, {...PENS["default"]}, {...PENS["default"]}, {...PENS["default"]} ], numberOfCustomPens: 0, pdfScale: 4, pdfBorderBox: true, pdfGapSize: 20, pdfGroupPages: false, pdfLockAfterImport: true, pdfNumColumns: 1, pdfNumRows: 1, pdfDirection: "right", pdfImportScale: 0.3, laserSettings: { DECAY_LENGTH: 50, DECAY_TIME: 1000, COLOR: "#ff0000", }, embeddableMarkdownDefaults: { useObsidianDefaults: false, backgroundMatchCanvas: false, backgroundMatchElement: true, backgroundColor: "#fff", backgroundOpacity: 60, borderMatchElement: true, borderColor: "#fff", borderOpacity: 0, filenameVisible: false, }, canvasImmersiveEmbed: true, startupScriptPath: "", openAIAPIToken: "", openAIDefaultTextModel: "gpt-3.5-turbo-1106", openAIDefaultVisionModel: "gpt-4-vision-preview", openAIDefaultImageGenerationModel: "dall-e-3", openAIURL: "https://api.openai.com/v1/chat/completions", openAIImageGenerationURL: "https://api.openai.com/v1/images/generations", openAIImageEditsURL: "https://api.openai.com/v1/images/edits", openAIImageVariationURL: "https://api.openai.com/v1/images/variations", modifierKeyConfig: { Mac: { LocalFileDragAction:{ defaultAction: "image-import", rules: [ { shift: false, ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "image-import" }, { shift: true , ctrl_cmd: false, alt_opt: true , meta_ctrl: false, result: "link" }, { shift: true , ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "image-url" }, { shift: false, ctrl_cmd: false, alt_opt: true , meta_ctrl: false, result: "embeddable" }, ], }, WebBrowserDragAction: { defaultAction: "image-url", rules: [ { shift: false, ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "image-url" }, { shift: true , ctrl_cmd: false, alt_opt: true , meta_ctrl: false, result: "link" }, { shift: false, ctrl_cmd: false, alt_opt: true , meta_ctrl: false, result: "embeddable" }, { shift: true , ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "image-import" }, ], }, InternalDragAction: { defaultAction: "link", rules: [ { shift: false, ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "link" }, { shift: false, ctrl_cmd: false, alt_opt: false, meta_ctrl: true , result: "embeddable" }, { shift: true , ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "image" }, { shift: true , ctrl_cmd: false, alt_opt: false, meta_ctrl: true , result: "image-fullsize" }, ], }, LinkClickAction: { defaultAction: "new-tab", rules: [ { shift: false, ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "active-pane" }, { shift: false, ctrl_cmd: true , alt_opt: false, meta_ctrl: false, result: "new-tab" }, { shift: false, ctrl_cmd: true , alt_opt: true , meta_ctrl: false, result: "new-pane" }, { shift: true , ctrl_cmd: true , alt_opt: true , meta_ctrl: false, result: "popout-window" }, { shift: false, ctrl_cmd: true , alt_opt: false, meta_ctrl: true , result: "md-properties" }, ], }, }, Win: { LocalFileDragAction:{ defaultAction: "image-import", rules: [ { shift: false, ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "image-import" }, { shift: false, ctrl_cmd: true , alt_opt: false, meta_ctrl: false, result: "link" }, { shift: true , ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "image-url" }, { shift: true , ctrl_cmd: true , alt_opt: false, meta_ctrl: false, result: "embeddable" }, ], }, WebBrowserDragAction: { defaultAction: "image-url", rules: [ { shift: false, ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "image-url" }, { shift: false, ctrl_cmd: true , alt_opt: false, meta_ctrl: false, result: "link" }, { shift: true , ctrl_cmd: true , alt_opt: false, meta_ctrl: false, result: "embeddable" }, { shift: true , ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "image-import" }, ], }, InternalDragAction: { defaultAction: "link", rules: [ { shift: false, ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "link" }, { shift: true , ctrl_cmd: true , alt_opt: false, meta_ctrl: false, result: "embeddable" }, { shift: true , ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "image" }, { shift: false, ctrl_cmd: true , alt_opt: true , meta_ctrl: false, result: "image-fullsize" }, ], }, LinkClickAction: { defaultAction: "new-tab", rules: [ { shift: false, ctrl_cmd: false, alt_opt: false, meta_ctrl: false, result: "active-pane" }, { shift: false, ctrl_cmd: true , alt_opt: false, meta_ctrl: false, result: "new-tab" }, { shift: false, ctrl_cmd: true , alt_opt: true , meta_ctrl: false, result: "new-pane" }, { shift: true , ctrl_cmd: true , alt_opt: true , meta_ctrl: false, result: "popout-window" }, { shift: false, ctrl_cmd: true , alt_opt: false, meta_ctrl: true , result: "md-properties" }, ], }, }, }, slidingPanesSupport: false, areaZoomLimit: 1, }; export class ExcalidrawSettingTab extends PluginSettingTab { plugin: ExcalidrawPlugin; private requestEmbedUpdate: boolean = false; private requestReloadDrawings: boolean = false; private requestUpdatePinnedPens: boolean = false; private requestUpdateDynamicStyling: boolean = false; //private reloadMathJax: boolean = false; //private applyDebounceTimer: number = 0; constructor(app: App, plugin: ExcalidrawPlugin) { super(app, plugin); this.plugin = plugin; } applySettingsUpdate(requestReloadDrawings: boolean = false) { if (requestReloadDrawings) { this.requestReloadDrawings = true; } } async hide() { this.plugin.settings.scriptFolderPath = normalizePath( this.plugin.settings.scriptFolderPath, ); if ( this.plugin.settings.scriptFolderPath === "/" || this.plugin.settings.scriptFolderPath === "" ) { this.plugin.settings.scriptFolderPath = "Excalidraw/Scripts"; } this.plugin.saveSettings(); if (this.requestUpdatePinnedPens) { app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> { if (v.view instanceof ExcalidrawView) v.view.updatePinnedCustomPens() }) } if (this.requestUpdateDynamicStyling) { app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> { if (v.view instanceof ExcalidrawView) { setDynamicStyle(this.plugin.ea,v.view,v.view.previousBackgroundColor,this.plugin.settings.dynamicStyling); } }) } if (this.requestReloadDrawings) { const exs = app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW); for (const v of exs) { if (v.view instanceof ExcalidrawView) { await v.view.save(false); //debug({where:"ExcalidrawSettings.hide",file:v.view.file.name,before:"reload(true)"}) await v.view.reload(true); } } this.requestEmbedUpdate = true; } if (this.requestEmbedUpdate) { this.plugin.triggerEmbedUpdates(); } this.plugin.scriptEngine.updateScriptPath(); /* if(this.reloadMathJax) { this.plugin.loadMathJax(); }*/ } async display() { let detailsEl: HTMLElement; await this.plugin.loadSettings(); //in case sync loaded changed settings in the background this.requestEmbedUpdate = false; this.requestReloadDrawings = false; const { containerEl } = this; containerEl.addClass("excalidraw-settings"); this.containerEl.empty(); const coffeeDiv = containerEl.createDiv("coffee"); coffeeDiv.addClass("ex-coffee-div"); const coffeeLink = coffeeDiv.createEl("a", { href: "https://ko-fi.com/zsolt", }); const coffeeImg = coffeeLink.createEl("img", { attr: { src: "https://cdn.ko-fi.com/cdn/kofi3.png?v=3", }, }); coffeeImg.height = 45; // ------------------------------------------------ // Saving // ------------------------------------------------ containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv({ text: t("BASIC_DESC"), cls: "setting-item-description" }); detailsEl = this.containerEl.createEl("details"); detailsEl.createEl("summary", { text: t("BASIC_HEAD"), cls: "excalidraw-setting-h1", }); new Setting(detailsEl) .setName(t("RELEASE_NOTES_NAME")) .setDesc(fragWithHTML(t("RELEASE_NOTES_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.showReleaseNotes) .onChange(async (value) => { this.plugin.settings.showReleaseNotes = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("NEWVERSION_NOTIFICATION_NAME")) .setDesc(fragWithHTML(t("NEWVERSION_NOTIFICATION_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.showNewVersionNotification) .onChange(async (value) => { this.plugin.settings.showNewVersionNotification = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("FOLDER_NAME")) .setDesc(fragWithHTML(t("FOLDER_DESC"))) .addText((text) => text .setPlaceholder("e.g.: Excalidraw") .setValue(this.plugin.settings.folder) .onChange(async (value) => { this.plugin.settings.folder = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("FOLDER_EMBED_NAME")) .setDesc(fragWithHTML(t("FOLDER_EMBED_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.embedUseExcalidrawFolder) .onChange(async (value) => { this.plugin.settings.embedUseExcalidrawFolder = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("CROP_FOLDER_NAME")) .setDesc(fragWithHTML(t("CROP_FOLDER_DESC"))) .addText((text) => text .setPlaceholder("e.g.: Excalidraw/Cropped") .setValue(this.plugin.settings.cropFolder) .onChange(async (value) => { this.plugin.settings.cropFolder = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("TEMPLATE_NAME")) .setDesc(fragWithHTML(t("TEMPLATE_DESC"))) .addText((text) => text .setPlaceholder("e.g.: Excalidraw/Template") .setValue(this.plugin.settings.templateFilePath) .onChange(async (value) => { this.plugin.settings.templateFilePath = value; this.applySettingsUpdate(); }), ); addIframe(detailsEl, "jgUpYznHP9A",216); new Setting(detailsEl) .setName(t("SCRIPT_FOLDER_NAME")) .setDesc(fragWithHTML(t("SCRIPT_FOLDER_DESC"))) .addText((text) => text .setPlaceholder("e.g.: Excalidraw/Scripts") .setValue(this.plugin.settings.scriptFolderPath) .onChange(async (value) => { this.plugin.settings.scriptFolderPath = value; this.applySettingsUpdate(); }), ); // ------------------------------------------------ // Saving // ------------------------------------------------ containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv({ text: t("SAVING_DESC"), cls: "setting-item-description" }); detailsEl = this.containerEl.createEl("details"); const savingDetailsEl = detailsEl; detailsEl.createEl("summary", { text: t("SAVING_HEAD"), cls: "excalidraw-setting-h1", }); new Setting(detailsEl) .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(); }), ); new Setting(detailsEl) .setName(t("AUTOSAVE_INTERVAL_DESKTOP_NAME")) .setDesc(fragWithHTML(t("AUTOSAVE_INTERVAL_DESKTOP_DESC"))) .addDropdown((dropdown) => dropdown .addOption("15000", "Frequent (every 15 seconds)") .addOption("60000", "Moderate (every 60 seconds)") .addOption("300000", "Rare (every 5 minutes)") .addOption("900000", "Practically never (every 15 minutes)") .setValue(this.plugin.settings.autosaveIntervalDesktop.toString()) .onChange(async (value) => { this.plugin.settings.autosaveIntervalDesktop = parseInt(value); this.plugin.settings.autosaveInterval = app.isMobile ? this.plugin.settings.autosaveIntervalMobile : this.plugin.settings.autosaveIntervalDesktop; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("AUTOSAVE_INTERVAL_MOBILE_NAME")) .setDesc(fragWithHTML(t("AUTOSAVE_INTERVAL_MOBILE_DESC"))) .addDropdown((dropdown) => dropdown .addOption("10000", "Frequent (every 10 seconds)") .addOption("30000", "Moderate (every 30 seconds)") .addOption("60000", "Rare (every 1 minute)") .addOption("300000", "Practically never (every 5 minutes)") .setValue(this.plugin.settings.autosaveIntervalMobile.toString()) .onChange(async (value) => { this.plugin.settings.autosaveIntervalMobile = parseInt(value); this.plugin.settings.autosaveInterval = app.isMobile ? this.plugin.settings.autosaveIntervalMobile : this.plugin.settings.autosaveIntervalDesktop; this.applySettingsUpdate(); }), ); detailsEl = savingDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("FILENAME_HEAD"), cls: "excalidraw-setting-h3", }); detailsEl.createDiv("", (el) => { el.innerHTML = t("FILENAME_DESC"); }); const getFilenameSample = () => { return `${t( "FILENAME_SAMPLE", )}${getDrawingFilename( this.plugin.settings, )}
${t( "FILENAME_EMBED_SAMPLE", )}${getEmbedFilename( "{NOTE_NAME}", this.plugin.settings, )}`; }; const filenameEl = detailsEl.createEl("p", { text: "" }); filenameEl.innerHTML = getFilenameSample(); new Setting(detailsEl) .setName(t("FILENAME_PREFIX_NAME")) .setDesc(fragWithHTML(t("FILENAME_PREFIX_DESC"))) .addText((text) => text .setPlaceholder("e.g.: Drawing ") .setValue(this.plugin.settings.drawingFilenamePrefix) .onChange(async (value) => { this.plugin.settings.drawingFilenamePrefix = value.replaceAll( /[<>:"/\\|?*]/g, "_", ); text.setValue(this.plugin.settings.drawingFilenamePrefix); filenameEl.innerHTML = getFilenameSample(); this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("FILENAME_PREFIX_EMBED_NAME")) .setDesc(fragWithHTML(t("FILENAME_PREFIX_EMBED_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.drawingEmbedPrefixWithFilename) .onChange(async (value) => { this.plugin.settings.drawingEmbedPrefixWithFilename = value; filenameEl.innerHTML = getFilenameSample(); this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("FILENAME_POSTFIX_NAME")) .setDesc(fragWithHTML(t("FILENAME_POSTFIX_DESC"))) .addText((text) => text .setPlaceholder("") .setValue(this.plugin.settings.drawingFilnameEmbedPostfix) .onChange(async (value) => { this.plugin.settings.drawingFilnameEmbedPostfix = value.replaceAll( /[<>:"/\\|?*]/g, "_", ); text.setValue(this.plugin.settings.drawingFilnameEmbedPostfix); filenameEl.innerHTML = getFilenameSample(); this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("FILENAME_DATE_NAME")) .setDesc(fragWithHTML(t("FILENAME_DATE_DESC"))) .addText((text) => text .setPlaceholder("YYYY-MM-DD HH.mm.ss") .setValue(this.plugin.settings.drawingFilenameDateTime) .onChange(async (value) => { this.plugin.settings.drawingFilenameDateTime = value.replaceAll( /[<>:"/\\|?*]/g, "_", ); text.setValue(this.plugin.settings.drawingFilenameDateTime); filenameEl.innerHTML = getFilenameSample(); this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("FILENAME_EXCALIDRAW_EXTENSION_NAME")) .setDesc(fragWithHTML(t("FILENAME_EXCALIDRAW_EXTENSION_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.useExcalidrawExtension) .onChange(async (value) => { this.plugin.settings.useExcalidrawExtension = value; filenameEl.innerHTML = getFilenameSample(); this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("CROP_PREFIX_NAME")) .setDesc(fragWithHTML(t("CROP_PREFIX_DESC"))) .addText((text) => text .setPlaceholder("e.g.: Cropped_ ") .setValue(this.plugin.settings.cropPrefix) .onChange(async (value) => { this.plugin.settings.cropPrefix = value.replaceAll( /[<>:"/\\|?*]/g, "_", ); text.setValue(this.plugin.settings.cropPrefix); this.applySettingsUpdate(); }), ); //------------------------------------------------ // AI Settings //------------------------------------------------ containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv({ text: t("AI_DESC"), cls: "setting-item-description" }); detailsEl = this.containerEl.createEl("details"); const aiDetailsEl = detailsEl; detailsEl.createEl("summary", { text: t("AI_HEAD"), cls: "excalidraw-setting-h1", }); new Setting(detailsEl) .setName(t("AI_OPENAI_TOKEN_NAME")) .setDesc(fragWithHTML(t("AI_OPENAI_TOKEN_DESC"))) .addText((text) => text .setPlaceholder(t("AI_OPENAI_TOKEN_PLACEHOLDER")) .setValue(this.plugin.settings.openAIAPIToken) .onChange(async (value) => { this.plugin.settings.openAIAPIToken = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("AI_OPENAI_DEFAULT_MODEL_NAME")) .setDesc(fragWithHTML(t("AI_OPENAI_DEFAULT_MODEL_DESC"))) .addText((text) => text .setPlaceholder(t("AI_OPENAI_DEFAULT_MODEL_PLACEHOLDER")) .setValue(this.plugin.settings.openAIDefaultTextModel) .onChange(async (value) => { this.plugin.settings.openAIDefaultTextModel = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("AI_OPENAI_DEFAULT_VISION_MODEL_NAME")) .setDesc(fragWithHTML(t("AI_OPENAI_DEFAULT_VISION_MODEL_DESC"))) .addText((text) => text .setPlaceholder(t("AI_OPENAI_DEFAULT_VISION_MODEL_PLACEHOLDER")) .setValue(this.plugin.settings.openAIDefaultVisionModel) .onChange(async (value) => { this.plugin.settings.openAIDefaultVisionModel = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("AI_OPENAI_DEFAULT_IMAGE_MODEL_NAME")) .setDesc(fragWithHTML(t("AI_OPENAI_DEFAULT_IMAGE_MODEL_DESC"))) .addText((text) => text .setPlaceholder(t("AI_OPENAI_DEFAULT_IMAGE_MODEL_PLACEHOLDER")) .setValue(this.plugin.settings.openAIDefaultImageGenerationModel) .onChange(async (value) => { this.plugin.settings.openAIDefaultImageGenerationModel = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("AI_OPENAI_DEFAULT_API_URL_NAME")) .setDesc(fragWithHTML(t("AI_OPENAI_DEFAULT_API_URL_DESC"))) .addText((text) => text .setPlaceholder("e.g.: https://api.openai.com/v1/chat/completions") .setValue(this.plugin.settings.openAIURL) .onChange(async (value) => { this.plugin.settings.openAIURL = value; this.applySettingsUpdate(); }), ); // ------------------------------------------------ // Display // ------------------------------------------------ containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv({ text: t("DISPLAY_DESC"), cls: "setting-item-description" }); detailsEl = this.containerEl.createEl("details"); const displayDetailsEl = detailsEl; detailsEl.createEl("summary", { text: t("DISPLAY_HEAD"), cls: "excalidraw-setting-h1", }); new Setting(detailsEl) .setName(t("DEFAULT_PEN_MODE_NAME")) .setDesc(fragWithHTML(t("DEFAULT_PEN_MODE_DESC"))) .addDropdown((dropdown) => dropdown .addOption("never", "Never") .addOption("mobile", "On Obsidian Mobile") .addOption("always", "Always") .setValue(this.plugin.settings.defaultPenMode) .onChange(async (value: "never" | "always" | "mobile") => { this.plugin.settings.defaultPenMode = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("LEFTHANDED_MODE_NAME")) .setDesc(fragWithHTML(t("LEFTHANDED_MODE_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.isLeftHanded) .onChange(async (value) => { this.plugin.settings.isLeftHanded = value; //not clear why I need to do this. If I don't double apply the stylesheet changes //then the style won't be applied in the popout windows setLeftHandedMode(value); setTimeout(()=>setLeftHandedMode(value)); this.applySettingsUpdate(); }), ); addIframe(detailsEl, "H8Njp7ZXYag",999); detailsEl = displayDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("THEME_HEAD"), cls: "excalidraw-setting-h3", }); new Setting(detailsEl) .setName(t("DYNAMICSTYLE_NAME")) .setDesc(fragWithHTML(t("DYNAMICSTYLE_DESC"))) .addDropdown((dropdown) => dropdown .addOption("none","Dynamic Styling OFF") .addOption("colorful","Match color") .addOption("gray","Gray, match tone") .setValue(this.plugin.settings.dynamicStyling) .onChange(async (value) => { this.requestUpdateDynamicStyling = true; this.plugin.settings.dynamicStyling = value as DynamicStyle; this.applySettingsUpdate(); }), ); addIframe(detailsEl, "fypDth_-8q0"); new Setting(detailsEl) .setName(t("IFRAME_MATCH_THEME_NAME")) .setDesc(fragWithHTML(t("IFRAME_MATCH_THEME_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.iframeMatchExcalidrawTheme) .onChange(async (value) => { this.plugin.settings.iframeMatchExcalidrawTheme = value; this.applySettingsUpdate(true); }), ); addIframe(detailsEl, "ICpoyMv6KSs"); new Setting(detailsEl) .setName(t("MATCH_THEME_NAME")) .setDesc(fragWithHTML(t("MATCH_THEME_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.matchTheme) .onChange(async (value) => { this.plugin.settings.matchTheme = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("MATCH_THEME_ALWAYS_NAME")) .setDesc(fragWithHTML(t("MATCH_THEME_ALWAYS_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.matchThemeAlways) .onChange(async (value) => { this.plugin.settings.matchThemeAlways = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("MATCH_THEME_TRIGGER_NAME")) .setDesc(fragWithHTML(t("MATCH_THEME_TRIGGER_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.matchThemeTrigger) .onChange(async (value) => { this.plugin.settings.matchThemeTrigger = value; if(value) { this.plugin.addThemeObserver(); } else { this.plugin.removeThemeObserver(); } this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("DEFAULT_OPEN_MODE_NAME")) .setDesc(fragWithHTML(t("DEFAULT_OPEN_MODE_DESC"))) .addDropdown((dropdown) => dropdown .addOption("normal", "Always in normal-mode") .addOption("zen", "Always in zen-mode") .addOption("view", "Always in view-mode") .addOption("view-mobile", "Usually normal, but view-mode on Phone") .setValue(this.plugin.settings.defaultMode) .onChange(async (value) => { this.plugin.settings.defaultMode = value; this.applySettingsUpdate(); }), ); detailsEl = displayDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("ZOOM_HEAD"), cls: "excalidraw-setting-h3", }); new Setting(detailsEl) .setName(t("DEFAULT_PINCHZOOM_NAME")) .setDesc(fragWithHTML(t("DEFAULT_PINCHZOOM_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.allowPinchZoom) .onChange(async (value) => { this.plugin.settings.allowPinchZoom = value; app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> { if (v.view instanceof ExcalidrawView) v.view.updatePinchZoom() }) this.applySettingsUpdate(); }), ); addIframe(detailsEl, "rBarRfcSxNo",107); new Setting(detailsEl) .setName(t("DEFAULT_WHEELZOOM_NAME")) .setDesc(fragWithHTML(t("DEFAULT_WHEELZOOM_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.allowWheelZoom) .onChange(async (value) => { this.plugin.settings.allowWheelZoom = value; app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> { if (v.view instanceof ExcalidrawView) v.view.updateWheelZoom() }) this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("ZOOM_TO_FIT_ONOPEN_NAME")) .setDesc(fragWithHTML(t("ZOOM_TO_FIT_ONOPEN_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.zoomToFitOnOpen) .onChange(async (value) => { this.plugin.settings.zoomToFitOnOpen = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("ZOOM_TO_FIT_NAME")) .setDesc(fragWithHTML(t("ZOOM_TO_FIT_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.zoomToFitOnResize) .onChange(async (value) => { this.plugin.settings.zoomToFitOnResize = value; this.applySettingsUpdate(); }), ); let zoomText: HTMLDivElement; new Setting(detailsEl) .setName(t("ZOOM_TO_FIT_MAX_LEVEL_NAME")) .setDesc(fragWithHTML(t("ZOOM_TO_FIT_MAX_LEVEL_DESC"))) .addSlider((slider) => slider .setLimits(0.5, 10, 0.5) .setValue(this.plugin.settings.zoomToFitMaxLevel) .onChange(async (value) => { zoomText.innerText = ` ${value.toString()}`; this.plugin.settings.zoomToFitMaxLevel = value; this.applySettingsUpdate(); }), ) .settingEl.createDiv("", (el) => { zoomText = el; el.style.minWidth = "2.3em"; el.style.textAlign = "right"; el.innerText = ` ${this.plugin.settings.zoomToFitMaxLevel.toString()}`; }); detailsEl = displayDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("LASER_HEAD"), cls: "excalidraw-setting-h3", }); new Setting(detailsEl) .setName(t("LASER_COLOR")) .addColorPicker((colorPicker) => colorPicker .setValue(this.plugin.settings.laserSettings.COLOR) .onChange(async (value) => { this.plugin.settings.laserSettings.COLOR = value; this.applySettingsUpdate(); }), ); let decayTime: HTMLDivElement; new Setting(detailsEl) .setName(t("LASER_DECAY_TIME_NAME")) .setDesc(fragWithHTML(t("LASER_DECAY_TIME_DESC"))) .addSlider((slider) => slider .setLimits(500, 20000, 500) .setValue(this.plugin.settings.laserSettings.DECAY_TIME) .onChange(async (value) => { decayTime.innerText = ` ${value.toString()}`; this.plugin.settings.laserSettings.DECAY_TIME = value; this.applySettingsUpdate(); }), ) .settingEl.createDiv("", (el) => { decayTime = el; el.style.minWidth = "3em"; el.style.textAlign = "right"; el.innerText = ` ${this.plugin.settings.laserSettings.DECAY_TIME.toString()}`; }); let decayLength: HTMLDivElement; new Setting(detailsEl) .setName(t("LASER_DECAY_LENGTH_NAME")) .setDesc(fragWithHTML(t("LASER_DECAY_LENGTH_DESC"))) .addSlider((slider) => slider .setLimits(25, 2000, 25) .setValue(this.plugin.settings.laserSettings.DECAY_LENGTH) .onChange(async (value) => { decayLength.innerText = ` ${value.toString()}`; this.plugin.settings.laserSettings.DECAY_LENGTH = value; this.applySettingsUpdate(); }), ) .settingEl.createDiv("", (el) => { decayLength = el; el.style.minWidth = "3em"; el.style.textAlign = "right"; el.innerText = ` ${this.plugin.settings.laserSettings.DECAY_LENGTH.toString()}`; }); detailsEl = displayDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("DRAG_MODIFIER_NAME"), cls: "excalidraw-setting-h3", }); detailsEl.createDiv({ text: t("DRAG_MODIFIER_DESC"), cls: "setting-item-description" }); new ModifierKeySettingsComponent( detailsEl, this.plugin.settings.modifierKeyConfig, this.applySettingsUpdate, ).render(); // ------------------------------------------------ // Links and Transclusions // ------------------------------------------------ containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv({ text: t("LINKS_HEAD_DESC"), cls: "setting-item-description" }); detailsEl = this.containerEl.createEl("details"); detailsEl.createEl("summary", { text: t("LINKS_HEAD"), cls: "excalidraw-setting-h1", }); detailsEl.createEl( "span", undefined, (el) => (el.innerHTML = t("LINKS_DESC")), ); new Setting(detailsEl) .setName(t("ADJACENT_PANE_NAME")) .setDesc(fragWithHTML(t("ADJACENT_PANE_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.openInAdjacentPane) .onChange(async (value) => { this.plugin.settings.openInAdjacentPane = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("MAINWORKSPACE_PANE_NAME")) .setDesc(fragWithHTML(t("MAINWORKSPACE_PANE_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.openInMainWorkspace) .onChange(async (value) => { this.plugin.settings.openInMainWorkspace = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(fragWithHTML(t("LINK_BRACKETS_NAME"))) .setDesc(fragWithHTML(t("LINK_BRACKETS_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.showLinkBrackets) .onChange(value => { this.plugin.settings.showLinkBrackets = value; this.applySettingsUpdate(true); }), ); new Setting(detailsEl) .setName(t("LINK_PREFIX_NAME")) .setDesc(fragWithHTML(t("LINK_PREFIX_DESC"))) .addText((text) => text .setPlaceholder(t("INSERT_EMOJI")) .setValue(this.plugin.settings.linkPrefix) .onChange(value => { this.plugin.settings.linkPrefix = value; this.applySettingsUpdate(true); }), ); new Setting(detailsEl) .setName(t("URL_PREFIX_NAME")) .setDesc(fragWithHTML(t("URL_PREFIX_DESC"))) .addText((text) => text .setPlaceholder(t("INSERT_EMOJI")) .setValue(this.plugin.settings.urlPrefix) .onChange(value => { this.plugin.settings.urlPrefix = value; this.applySettingsUpdate(true); }), ); let todoPrefixSetting:TextComponent, donePrefixSetting:TextComponent; new Setting(detailsEl) .setName(t("PARSE_TODO_NAME")) .setDesc(fragWithHTML(t("PARSE_TODO_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.parseTODO) .onChange(value => { this.plugin.settings.parseTODO = value; todoPrefixSetting.setDisabled(!value); donePrefixSetting.setDisabled(!value); this.applySettingsUpdate(true); }) ); new Setting(detailsEl) .setName(t("TODO_NAME")) .setDesc(fragWithHTML(t("TODO_DESC"))) .addText((text) => { todoPrefixSetting = text; text .setPlaceholder(t("INSERT_EMOJI")) .setValue(this.plugin.settings.todo) .onChange(value => { this.plugin.settings.todo = value; this.applySettingsUpdate(true); }) } ); todoPrefixSetting.setDisabled(!this.plugin.settings.parseTODO); new Setting(detailsEl) .setName(t("DONE_NAME")) .setDesc(fragWithHTML(t("DONE_DESC"))) .setDisabled(!this.plugin.settings.parseTODO) .addText((text) => { donePrefixSetting = text; text .setPlaceholder(t("INSERT_EMOJI")) .setValue(this.plugin.settings.done) .onChange(value => { this.plugin.settings.done = value; this.applySettingsUpdate(true); }) } ); donePrefixSetting.setDisabled(!this.plugin.settings.parseTODO); let opacityText: HTMLDivElement; new Setting(detailsEl) .setName(t("LINKOPACITY_NAME")) .setDesc(fragWithHTML(t("LINKOPACITY_DESC"))) .addSlider((slider) => slider .setLimits(0, 1, 0.05) .setValue(this.plugin.settings.linkOpacity) .onChange(async (value) => { opacityText.innerText = ` ${value.toString()}`; this.plugin.settings.linkOpacity = value; this.applySettingsUpdate(true); }), ) .settingEl.createDiv("", (el) => { opacityText = el; el.style.minWidth = "2.3em"; el.style.textAlign = "right"; el.innerText = ` ${this.plugin.settings.linkOpacity.toString()}`; }); new Setting(detailsEl) .setName(t("HOVERPREVIEW_NAME")) .setDesc(fragWithHTML(t("HOVERPREVIEW_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.hoverPreviewWithoutCTRL) .onChange(async (value) => { this.plugin.settings.hoverPreviewWithoutCTRL = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("LINK_CTRL_CLICK_NAME")) .setDesc(fragWithHTML(t("LINK_CTRL_CLICK_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.allowCtrlClick) .onChange(async (value) => { this.plugin.settings.allowCtrlClick = value; this.applySettingsUpdate(); }), ); const s = new Setting(detailsEl) .setName(t("TRANSCLUSION_WRAP_NAME")) .setDesc(fragWithHTML(t("TRANSCLUSION_WRAP_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.forceWrap) .onChange(async (value) => { this.plugin.settings.forceWrap = value; this.applySettingsUpdate(true); }), ); s.descEl.innerHTML = `![[doc#^ref]]{number} ${t( "TRANSCLUSION_WRAP_DESC", )}`; new Setting(detailsEl) .setName(t("PAGE_TRANSCLUSION_CHARCOUNT_NAME")) .setDesc(fragWithHTML(t("PAGE_TRANSCLUSION_CHARCOUNT_DESC"))) .addText((text) => text .setPlaceholder("Enter a number") .setValue(this.plugin.settings.pageTransclusionCharLimit.toString()) .onChange(async (value) => { const intVal = parseInt(value); if (isNaN(intVal) && value !== "") { text.setValue( this.plugin.settings.pageTransclusionCharLimit.toString(), ); return; } this.requestEmbedUpdate = true; if (value === "") { this.plugin.settings.pageTransclusionCharLimit = 10; this.applySettingsUpdate(true); return; } this.plugin.settings.pageTransclusionCharLimit = intVal; text.setValue( this.plugin.settings.pageTransclusionCharLimit.toString(), ); this.applySettingsUpdate(true); }), ); new Setting(detailsEl) .setName(t("TRANSCLUSION_DEFAULT_WRAP_NAME")) .setDesc(fragWithHTML(t("TRANSCLUSION_DEFAULT_WRAP_DESC"))) .addText((text) => text .setPlaceholder("Enter a number") .setValue(this.plugin.settings.wordWrappingDefault.toString()) .onChange(async (value) => { const intVal = parseInt(value); if (isNaN(intVal) && value !== "") { text.setValue( this.plugin.settings.wordWrappingDefault.toString(), ); return; } this.requestEmbedUpdate = true; if (value === "") { this.plugin.settings.wordWrappingDefault = 0; this.applySettingsUpdate(true); return; } this.plugin.settings.wordWrappingDefault = intVal; text.setValue(this.plugin.settings.wordWrappingDefault.toString()); this.applySettingsUpdate(true); }), ); new Setting(detailsEl) .setName(t("QUOTE_TRANSCLUSION_REMOVE_NAME")) .setDesc(fragWithHTML(t("QUOTE_TRANSCLUSION_REMOVE_DESC"))) .addToggle(toggle => toggle .setValue(this.plugin.settings.removeTransclusionQuoteSigns) .onChange(value => { this.plugin.settings.removeTransclusionQuoteSigns = value; this.requestEmbedUpdate = true; this.applySettingsUpdate(true); }) ); new Setting(detailsEl) .setName(t("GET_URL_TITLE_NAME")) .setDesc(fragWithHTML(t("GET_URL_TITLE_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.iframelyAllowed) .onChange(async (value) => { this.plugin.settings.iframelyAllowed = value; this.applySettingsUpdate(); }), ); // ------------------------------------------------ // Embed and Export // ------------------------------------------------ containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv({ text: t("EMBED_DESC"), cls: "setting-item-description" }); detailsEl = this.containerEl.createEl("details"); const embedDetailsEl = detailsEl; detailsEl.createEl("summary", { text: t("EMBED_HEAD"), cls: "excalidraw-setting-h1", }); new Setting(detailsEl) .setName(t("EMBED_PREVIEW_IMAGETYPE_NAME")) .setDesc(fragWithHTML(t("EMBED_PREVIEW_IMAGETYPE_DESC"))) .addDropdown((dropdown) => dropdown .addOption(PreviewImageType.PNG, "PNG Image") .addOption(PreviewImageType.SVG, "Native SVG") .addOption(PreviewImageType.SVGIMG, "SVG Image") .setValue(this.plugin.settings.previewImageType) .onChange((value) => { this.plugin.settings.previewImageType = value as PreviewImageType; this.requestEmbedUpdate=true; this.applySettingsUpdate(); }) ); addIframe(detailsEl, "yZQoJg2RCKI"); addIframe(detailsEl, "opLd1SqaH_I",8); let dropdown: DropdownComponent; let embedComment: Setting; new Setting(detailsEl) .setName(t("EMBED_TYPE_NAME")) .setDesc(fragWithHTML(t("EMBED_TYPE_DESC"))) .addDropdown(async (d: DropdownComponent) => { dropdown = d; dropdown.addOption("excalidraw", "excalidraw"); if (this.plugin.settings.autoexportPNG) { dropdown.addOption("PNG", "PNG"); } else if (this.plugin.settings.embedType === "PNG") { this.plugin.settings.embedType = "excalidraw"; this.applySettingsUpdate(); } if (this.plugin.settings.autoexportSVG) { dropdown.addOption("SVG", "SVG"); } else if (this.plugin.settings.embedType === "SVG") { this.plugin.settings.embedType = "excalidraw"; this.applySettingsUpdate(); } dropdown .setValue(this.plugin.settings.embedType) .onChange(async (value) => { //@ts-ignore this.plugin.settings.embedType = value; embedComment.settingEl.style.display = value === "excalidraw" ? "none":""; this.applySettingsUpdate(); }); }); embedComment = new Setting(detailsEl) .setName(t("EMBED_MARKDOWN_COMMENT_NAME")) .setDesc(fragWithHTML(t("EMBED_MARKDOWN_COMMENT_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.embedMarkdownCommentLinks) .onChange(async (value) => { this.plugin.settings.embedMarkdownCommentLinks = value; this.applySettingsUpdate(); }), ); embedComment.settingEl.style.display = this.plugin.settings.embedType === "excalidraw" ? "none":""; new Setting(detailsEl) .setName(t("EMBED_WIKILINK_NAME")) .setDesc(fragWithHTML(t("EMBED_WIKILINK_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.embedWikiLink) .onChange(async (value) => { this.plugin.settings.embedWikiLink = value; this.applySettingsUpdate(); }), ); detailsEl = embedDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("EMBED_CANVAS"), cls: "excalidraw-setting-h3", }); new Setting(detailsEl) .setName(t("EMBED_CANVAS_NAME")) .setDesc(fragWithHTML(t("EMBED_CANVAS_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.canvasImmersiveEmbed) .onChange(async (value) => { this.plugin.settings.canvasImmersiveEmbed = value; this.applySettingsUpdate(); }), ); detailsEl = embedDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("EMBED_CACHING"), cls: "excalidraw-setting-h3", }); new Setting(detailsEl) .setName(t("EMBED_IMAGE_CACHE_NAME")) .setDesc(fragWithHTML(t("EMBED_IMAGE_CACHE_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.allowImageCache) .onChange((value) => { this.plugin.settings.allowImageCache = value; this.applySettingsUpdate(); }) ) .addButton((button) => button .setButtonText(t("EMBED_IMAGE_CACHE_CLEAR")) .onClick(() => { imageCache.clearImageCache(); }) ) .addButton((button) => button .setButtonText(t("BACKUP_CACHE_CLEAR")) .onClick(() => { const confirmationPrompt = new ConfirmationPrompt(this.plugin,t("BACKUP_CACHE_CLEAR_CONFIRMATION")); confirmationPrompt.waitForClose.then((confirmed) => { if (confirmed) { imageCache.clearBackupCache(); } }); }) ); new Setting(detailsEl) .setName(t("EMBED_REUSE_EXPORTED_IMAGE_NAME")) .setDesc(fragWithHTML(t("EMBED_REUSE_EXPORTED_IMAGE_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.displayExportedImageIfAvailable) .onChange(async (value) => { this.plugin.settings.displayExportedImageIfAvailable = value; this.applySettingsUpdate(); }), ); detailsEl = embedDetailsEl.createEl("details"); const exportDetailsEl = detailsEl; detailsEl.createEl("summary", { text: t("EXPORT_SUBHEAD"), cls: "excalidraw-setting-h3", }); addIframe(detailsEl, "wTtaXmRJ7wg",171); detailsEl = exportDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("EMBED_SIZING"), cls: "excalidraw-setting-h4", }); new Setting(detailsEl) .setName(t("EMBED_WIDTH_NAME")) .setDesc(fragWithHTML(t("EMBED_WIDTH_DESC"))) .addText((text) => text .setPlaceholder("e.g.: 400") .setValue(this.plugin.settings.width) .onChange(async (value) => { this.plugin.settings.width = value; this.applySettingsUpdate(); this.requestEmbedUpdate = true; }), ); let scaleText: HTMLDivElement; new Setting(detailsEl) .setName(t("EXPORT_PNG_SCALE_NAME")) .setDesc(fragWithHTML(t("EXPORT_PNG_SCALE_DESC"))) .addSlider((slider) => slider .setLimits(1, 5, 0.5) .setValue(this.plugin.settings.pngExportScale) .onChange(async (value) => { scaleText.innerText = ` ${value.toString()}`; this.plugin.settings.pngExportScale = value; this.applySettingsUpdate(); }), ) .settingEl.createDiv("", (el) => { scaleText = el; el.style.minWidth = "2.3em"; el.style.textAlign = "right"; el.innerText = ` ${this.plugin.settings.pngExportScale.toString()}`; }); let exportPadding: HTMLDivElement; new Setting(detailsEl) .setName(t("EXPORT_PADDING_NAME")) .setDesc(fragWithHTML(t("EXPORT_PADDING_DESC"))) .addSlider((slider) => slider .setLimits(0, 50, 5) .setValue(this.plugin.settings.exportPaddingSVG) .onChange(async (value) => { exportPadding.innerText = ` ${value.toString()}`; this.plugin.settings.exportPaddingSVG = value; this.applySettingsUpdate(); }), ) .settingEl.createDiv("", (el) => { exportPadding = el; el.style.minWidth = "2.3em"; el.style.textAlign = "right"; el.innerText = ` ${this.plugin.settings.exportPaddingSVG.toString()}`; }); detailsEl = exportDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("EMBED_THEME_BACKGROUND"), cls: "excalidraw-setting-h4", }); new Setting(detailsEl) .setName(t("EXPORT_BACKGROUND_NAME")) .setDesc(fragWithHTML(t("EXPORT_BACKGROUND_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.exportWithBackground) .onChange(async (value) => { this.plugin.settings.exportWithBackground = value; this.applySettingsUpdate(); this.requestEmbedUpdate = true; }), ); new Setting(detailsEl) .setName(t("EXPORT_THEME_NAME")) .setDesc(fragWithHTML(t("EXPORT_THEME_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.exportWithTheme) .onChange(async (value) => { this.plugin.settings.exportWithTheme = value; this.applySettingsUpdate(); this.requestEmbedUpdate = true; }), ); new Setting(detailsEl) .setName(t("PREVIEW_MATCH_OBSIDIAN_NAME")) .setDesc(fragWithHTML(t("PREVIEW_MATCH_OBSIDIAN_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.previewMatchObsidianTheme) .onChange(async (value) => { this.plugin.settings.previewMatchObsidianTheme = value; this.applySettingsUpdate(); }), ); detailsEl = exportDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("EXPORT_HEAD"), cls: "excalidraw-setting-h4", }); new Setting(detailsEl) .setName(t("EXPORT_SYNC_NAME")) .setDesc(fragWithHTML(t("EXPORT_SYNC_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.keepInSync) .onChange(async (value) => { this.plugin.settings.keepInSync = value; this.applySettingsUpdate(); }), ); const removeDropdownOption = (opt: string) => { let i = 0; for (i = 0; i < dropdown.selectEl.options.length; i++) { if ((dropdown.selectEl.item(i) as HTMLOptionElement).label === opt) { dropdown.selectEl.item(i).remove(); } } }; new Setting(detailsEl) .setName(t("EXPORT_SVG_NAME")) .setDesc(fragWithHTML(t("EXPORT_SVG_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.autoexportSVG) .onChange(async (value) => { if (value) { dropdown.addOption("SVG", "SVG"); } else { if (this.plugin.settings.embedType === "SVG") { dropdown.setValue("excalidraw"); this.plugin.settings.embedType = "excalidraw"; } removeDropdownOption("SVG"); } this.plugin.settings.autoexportSVG = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("EXPORT_PNG_NAME")) .setDesc(fragWithHTML(t("EXPORT_PNG_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.autoexportPNG) .onChange(async (value) => { if (value) { dropdown.addOption("PNG", "PNG"); } else { if (this.plugin.settings.embedType === "PNG") { dropdown.setValue("excalidraw"); this.plugin.settings.embedType = "excalidraw"; } removeDropdownOption("PNG"); } this.plugin.settings.autoexportPNG = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("EXPORT_BOTH_DARK_AND_LIGHT_NAME")) .setDesc(fragWithHTML(t("EXPORT_BOTH_DARK_AND_LIGHT_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.autoExportLightAndDark) .onChange(async (value) => { this.plugin.settings.autoExportLightAndDark = value; this.applySettingsUpdate(); }), ); // ------------------------------------------------ // Embedding settings // ------------------------------------------------ containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv({ text: t("EMBED_TOEXCALIDRAW_DESC"), cls: "setting-item-description" }); detailsEl = this.containerEl.createEl("details"); const embedFilesDetailsEl = detailsEl; detailsEl.createEl("summary", { text: t("EMBED_TOEXCALIDRAW_HEAD"), cls: "excalidraw-setting-h1", }); detailsEl = embedFilesDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("PDF_TO_IMAGE"), cls: "excalidraw-setting-h3", }); addIframe(detailsEl, "nB4cOfn0xAs"); new Setting(detailsEl) .setName(t("PDF_TO_IMAGE_SCALE_NAME")) .setDesc(fragWithHTML(t("PDF_TO_IMAGE_SCALE_DESC"))) .addDropdown((dropdown) => dropdown .addOption("0.5", "0.5") .addOption("1", "1") .addOption("2", "2") .addOption("3", "3") .addOption("4", "4") .addOption("5", "5") .addOption("6", "6") .setValue(`${this.plugin.settings.pdfScale}`) .onChange((value) => { this.plugin.settings.pdfScale = parseFloat(value); this.applySettingsUpdate(); }), ); detailsEl = embedFilesDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("MD_EMBED_CUSTOMDATA_HEAD_NAME"), cls: "excalidraw-setting-h3", }); detailsEl.createEl("span", {text: t("MD_EMBED_CUSTOMDATA_HEAD_DESC")}); new EmbeddalbeMDFileCustomDataSettingsComponent( detailsEl, this.plugin.settings.embeddableMarkdownDefaults, this.applySettingsUpdate, ).render(); detailsEl = embedFilesDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("MD_HEAD"), cls: "excalidraw-setting-h3", }); new Setting(detailsEl) .setName(t("MD_TRANSCLUDE_WIDTH_NAME")) .setDesc(fragWithHTML(t("MD_TRANSCLUDE_WIDTH_DESC"))) .addText((text) => text .setPlaceholder("Enter a number e.g. 500") .setValue(this.plugin.settings.mdSVGwidth.toString()) .onChange(async (value) => { const intVal = parseInt(value); if (isNaN(intVal) && value !== "") { text.setValue(this.plugin.settings.mdSVGwidth.toString()); return; } this.requestEmbedUpdate = true; if (value === "") { this.plugin.settings.mdSVGwidth = 500; this.applySettingsUpdate(true); return; } this.plugin.settings.mdSVGwidth = intVal; this.requestReloadDrawings = true; text.setValue(this.plugin.settings.mdSVGwidth.toString()); this.applySettingsUpdate(true); }), ); new Setting(detailsEl) .setName(t("MD_TRANSCLUDE_HEIGHT_NAME")) .setDesc(fragWithHTML(t("MD_TRANSCLUDE_HEIGHT_DESC"))) .addText((text) => text .setPlaceholder("Enter a number e.g. 800") .setValue(this.plugin.settings.mdSVGmaxHeight.toString()) .onChange(async (value) => { const intVal = parseInt(value); if (isNaN(intVal) && value !== "") { text.setValue(this.plugin.settings.mdSVGmaxHeight.toString()); return; } this.requestEmbedUpdate = true; if (value === "") { this.plugin.settings.mdSVGmaxHeight = 800; this.applySettingsUpdate(true); return; } this.plugin.settings.mdSVGmaxHeight = intVal; this.requestReloadDrawings = true; text.setValue(this.plugin.settings.mdSVGmaxHeight.toString()); this.applySettingsUpdate(true); }), ); new Setting(detailsEl) .setName(t("MD_DEFAULT_FONT_NAME")) .setDesc(fragWithHTML(t("MD_DEFAULT_FONT_DESC"))) .addDropdown(async (d: DropdownComponent) => { d.addOption("Virgil", "Virgil"); d.addOption("Cascadia", "Cascadia"); d.addOption("Assistant", "Assistant"); this.app.vault .getFiles() .filter((f) => ["ttf", "woff", "woff2"].contains(f.extension)) .forEach((f: TFile) => { d.addOption(f.path, f.name); }); d.setValue(this.plugin.settings.mdFont).onChange((value) => { this.requestReloadDrawings = true; this.plugin.settings.mdFont = value; this.applySettingsUpdate(true); }); }); new Setting(detailsEl) .setName(t("MD_DEFAULT_COLOR_NAME")) .setDesc(fragWithHTML(t("MD_DEFAULT_COLOR_DESC"))) .addText((text) => text .setPlaceholder("CSS Color-name|RGB-HEX") .setValue(this.plugin.settings.mdFontColor) .onChange((value) => { this.requestReloadDrawings = true; this.plugin.settings.mdFontColor = value; this.applySettingsUpdate(true); }), ); new Setting(detailsEl) .setName(t("MD_DEFAULT_BORDER_COLOR_NAME")) .setDesc(fragWithHTML(t("MD_DEFAULT_BORDER_COLOR_DESC"))) .addText((text) => text .setPlaceholder("CSS Color-name|RGB-HEX") .setValue(this.plugin.settings.mdBorderColor) .onChange((value) => { this.requestReloadDrawings = true; this.plugin.settings.mdBorderColor = value; this.applySettingsUpdate(true); }), ); new Setting(detailsEl) .setName(t("MD_CSS_NAME")) .setDesc(fragWithHTML(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); }), ); // ------------------------------------------------ // Non-excalidraw.com supported features // ------------------------------------------------ containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv({ text: t("NONSTANDARD_DESC"), cls: "setting-item-description" }); detailsEl = this.containerEl.createEl("details"); const nonstandardDetailsEl = detailsEl; detailsEl.createEl("summary", { text: t("NONSTANDARD_HEAD"), cls: "excalidraw-setting-h1", }); detailsEl = nonstandardDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("RENDER_TWEAK_HEAD"), cls: "excalidraw-setting-h3", }); let areaZoomText: HTMLDivElement; new Setting(detailsEl) .setName(t("MAX_IMAGE_ZOOM_IN_NAME")) .setDesc(fragWithHTML(t("MAX_IMAGE_ZOOM_IN_DESC"))) .addSlider((slider) => slider .setLimits(1, 10, 0.5) .setValue(this.plugin.settings.areaZoomLimit) .onChange(async (value) => { areaZoomText.innerText = ` ${value.toString()}`; this.plugin.settings.areaZoomLimit = value; this.applySettingsUpdate(); this.plugin.excalidrawConfig.updateValues(); }), ) .settingEl.createDiv("", (el) => { areaZoomText = el; el.style.minWidth = "2.3em"; el.style.textAlign = "right"; el.innerText = ` ${this.plugin.settings.areaZoomLimit.toString()}`; }); detailsEl = nonstandardDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("CUSTOM_PEN_HEAD"), cls: "excalidraw-setting-h3", }); addIframe(detailsEl, "OjNhjaH2KjI",69); new Setting(detailsEl) .setName(t("CUSTOM_PEN_NAME")) .setDesc(t("CUSTOM_PEN_DESC")) .addDropdown((dropdown) => dropdown .addOption("0","0") .addOption("1","1") .addOption("2","2") .addOption("3","3") .addOption("4","4") .addOption("5","5") .addOption("6","6") .addOption("7","7") .addOption("8","8") .addOption("9","9") .addOption("10","10") .setValue(this.plugin.settings.numberOfCustomPens.toString()) .onChange((value)=>{ this.plugin.settings.numberOfCustomPens = parseInt(value); this.requestUpdatePinnedPens = true; this.applySettingsUpdate(false); }) ) detailsEl = nonstandardDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("CUSTOM_FONT_HEAD"), cls: "excalidraw-setting-h3", }); addIframe(detailsEl, "eKFmrSQhFA4"); new Setting(detailsEl) .setName(t("ENABLE_FOURTH_FONT_NAME")) .setDesc(fragWithHTML(t("ENABLE_FOURTH_FONT_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.experimentalEnableFourthFont) .onChange(async (value) => { this.requestReloadDrawings = true; this.plugin.settings.experimentalEnableFourthFont = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("FOURTH_FONT_NAME")) .setDesc(fragWithHTML(t("FOURTH_FONT_DESC"))) .addDropdown(async (d: DropdownComponent) => { d.addOption("Virgil", "Virgil"); this.app.vault .getFiles() .filter((f) => ["ttf", "woff", "woff2", "otf"].contains(f.extension)) .forEach((f: TFile) => { d.addOption(f.path, f.name); }); d.setValue(this.plugin.settings.experimantalFourthFont).onChange( (value) => { this.requestReloadDrawings = true; this.plugin.settings.experimantalFourthFont = value; this.applySettingsUpdate(true); this.plugin.initializeFonts(); }, ); }); // ------------------------------------------------ // Experimental features // ------------------------------------------------ containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv( { text: t("EXPERIMENTAL_DESC"), cls: "setting-item-description" }); detailsEl = containerEl.createEl("details"); const experimentalDetailsEl = detailsEl; detailsEl.createEl("summary", { text: t("EXPERIMENTAL_HEAD"), cls: "excalidraw-setting-h1", }); addIframe(detailsEl, "r08wk-58DPk"); new Setting(detailsEl) .setName(t("LATEX_DEFAULT_NAME")) .setDesc(fragWithHTML(t("LATEX_DEFAULT_DESC"))) .addText((text) => text .setValue(this.plugin.settings.latexBoilerplate) .onChange( (value) => { this.plugin.settings.latexBoilerplate = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("FILETYPE_NAME")) .setDesc(fragWithHTML(t("FILETYPE_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.experimentalFileType) .onChange(async (value) => { this.plugin.settings.experimentalFileType = value; this.plugin.experimentalFileTypeDisplayToggle(value); this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("FILETAG_NAME")) .setDesc(fragWithHTML(t("FILETAG_DESC"))) .addText((text) => text .setPlaceholder(t("INSERT_EMOJI")) .setValue(this.plugin.settings.experimentalFileTag) .onChange(async (value) => { this.plugin.settings.experimentalFileTag = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("LIVEPREVIEW_NAME")) .setDesc(fragWithHTML(t("LIVEPREVIEW_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.experimentalLivePreview) .onChange(async (value) => { this.plugin.settings.experimentalLivePreview = value; this.applySettingsUpdate(); }), ); detailsEl = experimentalDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: t("TASKBONE_HEAD"), cls: "excalidraw-setting-h3", }); detailsEl.createDiv( { text: t("TASKBONE_DESC"), cls: "setting-item-description" }); let taskboneAPIKeyText: TextComponent; addIframe(detailsEl, "7gu4ETx7zro"); new Setting(detailsEl) .setName(t("TASKBONE_ENABLE_NAME")) .setDesc(fragWithHTML(t("TASKBONE_ENABLE_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.taskboneEnabled) .onChange(async (value) => { taskboneAPIKeyText.setDisabled(!value); this.plugin.settings.taskboneEnabled = value; if(this.plugin.settings.taskboneAPIkey === "") { const apiKey = await this.plugin.taskbone.initialize(false); if(apiKey) { taskboneAPIKeyText.setValue(apiKey); } } this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("TASKBONE_APIKEY_NAME")) .setDesc(fragWithHTML(t("TASKBONE_APIKEY_DESC"))) .addText((text) => { taskboneAPIKeyText = text; taskboneAPIKeyText .setValue(this.plugin.settings.taskboneAPIkey) .onChange(async (value) => { this.plugin.settings.taskboneAPIkey = value; this.applySettingsUpdate(); }) .setDisabled(!this.plugin.settings.taskboneEnabled); } ); // ------------------------------------------------ // ExcalidrawAutomate // ------------------------------------------------ containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv( { cls: "setting-item-description" }, (el)=>{ el.innerHTML = t("EA_DESC"); }); detailsEl = containerEl.createEl("details"); const eaDetailsEl = detailsEl; detailsEl.createEl("summary", { text: t("EA_HEAD"), cls: "excalidraw-setting-h1", }); new Setting(detailsEl) .setName(t("FIELD_SUGGESTER_NAME")) .setDesc(fragWithHTML(t("FIELD_SUGGESTER_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.fieldSuggester) .onChange(async (value) => { this.plugin.settings.fieldSuggester = value; this.applySettingsUpdate(); }), ); //STARTUP_SCRIPT_NAME //STARTUP_SCRIPT_BUTTON let startupScriptPathText: TextComponent; let startupScriptButton: ButtonComponent; const scriptExists = () => { const startupPath = normalizePath(this.plugin.settings.startupScriptPath.endsWith(".md") ? this.plugin.settings.startupScriptPath : this.plugin.settings.startupScriptPath + ".md"); return Boolean(this.app.vault.getAbstractFileByPath(startupPath)); } new Setting(detailsEl) .setName(t("STARTUP_SCRIPT_NAME")) .setDesc(fragWithHTML(t("STARTUP_SCRIPT_DESC"))) .addText((text) => { startupScriptPathText = text; text .setValue(this.plugin.settings.startupScriptPath) .onChange( (value) => { this.plugin.settings.startupScriptPath = value; startupScriptButton.setButtonText(scriptExists() ? t("STARTUP_SCRIPT_BUTTON_OPEN") : t("STARTUP_SCRIPT_BUTTON_CREATE")); this.applySettingsUpdate(); }); }) .addButton((button) => { startupScriptButton = button; startupScriptButton .setButtonText(scriptExists() ? t("STARTUP_SCRIPT_BUTTON_OPEN") : t("STARTUP_SCRIPT_BUTTON_CREATE")) .onClick(async () => { if(this.plugin.settings.startupScriptPath === "") { this.plugin.settings.startupScriptPath = normalizePath(normalizePath(this.plugin.settings.folder) + "/ExcalidrawStartup"); startupScriptPathText.setValue(this.plugin.settings.startupScriptPath); this.applySettingsUpdate(); } const startupPath = normalizePath(this.plugin.settings.startupScriptPath.endsWith(".md") ? this.plugin.settings.startupScriptPath : this.plugin.settings.startupScriptPath + ".md"); let f = this.app.vault.getAbstractFileByPath(startupPath); if(!f) { f = await this.app.vault.create(startupPath, startupScript()); } startupScriptButton.setButtonText(t("STARTUP_SCRIPT_BUTTON_OPEN")); this.app.workspace.openLinkText(f.path,"",true); this.hide(); }) }); // ------------------------------------------------ // Compatibility // ------------------------------------------------ containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv( { text: t("COMPATIBILITY_DESC"), cls: "setting-item-description" }); detailsEl = this.containerEl.createEl("details"); detailsEl.createEl("summary", { text: t("COMPATIBILITY_HEAD"), cls: "excalidraw-setting-h1", }); new Setting(detailsEl) .setName(t("SLIDING_PANES_NAME")) .setDesc(fragWithHTML(t("SLIDING_PANES_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.slidingPanesSupport) .onChange((value) => { this.plugin.settings.slidingPanesSupport = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("COMPATIBILITY_MODE_NAME")) .setDesc(fragWithHTML(t("COMPATIBILITY_MODE_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.compatibilityMode) .onChange(async (value) => { this.plugin.settings.compatibilityMode = value; filenameEl.innerHTML = getFilenameSample(); this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("EXPORT_EXCALIDRAW_NAME")) .setDesc(fragWithHTML(t("EXPORT_EXCALIDRAW_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.autoexportExcalidraw) .onChange(async (value) => { this.plugin.settings.autoexportExcalidraw = value; this.applySettingsUpdate(); }), ); new Setting(detailsEl) .setName(t("SYNC_EXCALIDRAW_NAME")) .setDesc(fragWithHTML(t("SYNC_EXCALIDRAW_DESC"))) .addToggle((toggle) => toggle .setValue(this.plugin.settings.syncExcalidraw) .onChange(async (value) => { this.plugin.settings.syncExcalidraw = value; this.applySettingsUpdate(); }), ); //------------------------------------- //Script settings //------------------------------------- const scripts = this.plugin.scriptEngine .getListofScripts() ?.map((f) => this.plugin.scriptEngine.getScriptName(f)); if ( Object.keys(this.plugin.settings.scriptEngineSettings).length > 0 && scripts ) { const textAreaHeight = (scriptName: string, variableName: string): any => { const variable = //@ts-ignore this.plugin.settings.scriptEngineSettings[scriptName][variableName]; switch (typeof variable) { case "object": return variable.height; default: return null; } }; const getValue = (scriptName: string, variableName: string): any => { const variable = //@ts-ignore this.plugin.settings.scriptEngineSettings[scriptName][variableName]; switch (typeof variable) { case "object": return variable.value; default: return variable; } }; const setValue = ( scriptName: string, variableName: string, value: any, ) => { switch ( //@ts-ignore typeof this.plugin.settings.scriptEngineSettings[scriptName][ variableName ] ) { case "object": //@ts-ignore this.plugin.settings.scriptEngineSettings[scriptName][ variableName ].value = value; break; default: //@ts-ignore this.plugin.settings.scriptEngineSettings[scriptName][ variableName ] = value; } }; const addBooleanSetting = ( scriptName: string, variableName: string, description?: string, ) => { new Setting(detailsEl) .setName(variableName) .setDesc(fragWithHTML(description ?? "")) .addToggle((toggle) => toggle .setValue(getValue(scriptName, variableName)) .onChange(async (value) => { setValue(scriptName, variableName, value); this.applySettingsUpdate(); }), ); }; const addStringSetting = ( scriptName: string, variableName: string, description?: string, valueset?: any, ) => { if ( valueset && Object.prototype.toString.call(valueset) === "[object Array]" && valueset.length > 0 ) { new Setting(detailsEl) .setName(variableName) .setDesc(fragWithHTML(description ?? "")) .addDropdown((dropdown) => { valueset.forEach((val: any) => dropdown.addOption(val.toString(), val.toString()), ); dropdown .setValue(getValue(scriptName, variableName)) .onChange(async (value) => { setValue(scriptName, variableName, value); this.applySettingsUpdate(); }); }); } else { if(textAreaHeight(scriptName, variableName)) { new Setting(detailsEl) .setName(variableName) .setDesc(fragWithHTML(description ?? "")) .addTextArea((text) => { text.inputEl.style.minHeight = textAreaHeight(scriptName, variableName); text.inputEl.style.minWidth = "400px"; text.inputEl.style.width = "100%"; text .setValue(getValue(scriptName, variableName)) .onChange(async (value) => { setValue(scriptName, variableName, value); this.applySettingsUpdate(); }); }); } else { new Setting(detailsEl) .setName(variableName) .setDesc(fragWithHTML(description ?? "")) .addText((text) => text .setValue(getValue(scriptName, variableName)) .onChange(async (value) => { setValue(scriptName, variableName, value); this.applySettingsUpdate(); }), ); } } }; const addNumberSetting = ( scriptName: string, variableName: string, description?: string, ) => { new Setting(detailsEl) .setName(variableName) .setDesc(fragWithHTML(description ?? "")) .addText((text) => text .setPlaceholder("Enter a number") .setValue(getValue(scriptName, variableName).toString()) .onChange(async (value) => { const numVal = parseFloat(value); if (isNaN(numVal) && value !== "") { text.setValue(getValue(scriptName, variableName).toString()); return; } setValue(scriptName, variableName, isNaN(numVal) ? 0 : numVal); this.applySettingsUpdate(); }), ); }; containerEl.createEl("hr", { cls: "excalidraw-setting-hr" }); containerEl.createDiv( { text: t("SCRIPT_SETTINGS_DESC"), cls: "setting-item-description" }); detailsEl = this.containerEl.createEl("details"); const scriptDetailsEl = detailsEl; detailsEl.createEl("summary", { text: t("SCRIPT_SETTINGS_HEAD"), cls: "excalidraw-setting-h1", }); addIframe(detailsEl, "H8Njp7ZXYag",52); Object.keys(this.plugin.settings.scriptEngineSettings) .filter((s) => scripts.contains(s)) .forEach((scriptName: string) => { const settings = //@ts-ignore this.plugin.settings.scriptEngineSettings[scriptName]; const values = Object.values(settings); if ( values.length === 0 || (values.length > 0 && values .map((val: any): number => (val.hidden ? 0 : 1)) .reduce((prev, cur) => prev + cur) === 0) ) { return; } detailsEl = scriptDetailsEl.createEl("details"); detailsEl.createEl("summary", { text: scriptName, cls: "excalidraw-setting-h3", }); Object.keys(settings).forEach((variableName) => { const variable = settings[variableName]; const item = variable.value ?? variable; switch (typeof item) { case "boolean": if (!variable.hidden) { addBooleanSetting( scriptName, variableName, variable.description, ); } break; case "string": if (!variable.hidden) { addStringSetting( scriptName, variableName, variable.description, variable.valueset, ); } break; case "number": if (!variable.hidden) { addNumberSetting( scriptName, variableName, variable.description, ); } break; } }); }); } } }