mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
1.2.4
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "1.2.3",
|
||||
"version": "1.2.4",
|
||||
"minAppVersion": "0.11.13",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from "obsidian";
|
||||
import * as React from "react";
|
||||
import * as ReactDOM from "react-dom";
|
||||
import Excalidraw, {exportToSvg, getSceneVersion} from "@excalidraw/excalidraw";
|
||||
import Excalidraw, {exportToSvg, getSceneVersion, loadLibraryFromBlob} from "@excalidraw/excalidraw";
|
||||
import { ExcalidrawElement } from "@excalidraw/excalidraw/types/element/types";
|
||||
import {
|
||||
AppState,
|
||||
@@ -33,6 +33,7 @@ import ExcalidrawPlugin from './main';
|
||||
import {ExcalidrawAutomate} from './ExcalidrawAutomate';
|
||||
import { t } from "./lang/helpers";
|
||||
import { ExcalidrawData, REG_LINK_BACKETS } from "./ExcalidrawData";
|
||||
import { download } from "./Utils";
|
||||
|
||||
declare let window: ExcalidrawAutomate;
|
||||
|
||||
@@ -216,16 +217,6 @@ export default class ExcalidrawView extends TextFileView {
|
||||
}
|
||||
}
|
||||
|
||||
download(encoding:string,data:any,filename:string) {
|
||||
let element = document.createElement('a');
|
||||
element.setAttribute('href', (encoding ? encoding + ',' : '') + data);
|
||||
element.setAttribute('download', filename);
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
|
||||
onload() {
|
||||
//console.log("ExcalidrawView.onload()");
|
||||
this.addAction(DISK_ICON_NAME,t("FORCE_SAVE"),async (ev)=> {
|
||||
@@ -307,8 +298,8 @@ export default class ExcalidrawView extends TextFileView {
|
||||
this.app.workspace.onLayoutReady(async ()=>{
|
||||
//console.log("ExcalidrawView.setViewData()");
|
||||
this.compatibilityMode = this.file.extension == "excalidraw";
|
||||
this.plugin.settings.drawingOpenCount++;
|
||||
this.plugin.saveSettings();
|
||||
await this.plugin.loadSettings();
|
||||
this.plugin.opencount++;
|
||||
if(this.compatibilityMode) {
|
||||
this.unlockedElement.hide();
|
||||
this.lockedElement.hide();
|
||||
@@ -390,7 +381,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
.setIcon(ICON_NAME)
|
||||
.onClick( async (ev) => {
|
||||
if(!this.getScene || !this.file) return;
|
||||
this.download('data:text/plain;charset=utf-8',encodeURIComponent(JSON.stringify(this.getScene())), this.file.basename+'.excalidraw');
|
||||
download('data:text/plain;charset=utf-8',encodeURIComponent(JSON.stringify(this.getScene())), this.file.basename+'.excalidraw');
|
||||
});
|
||||
});
|
||||
} else {
|
||||
@@ -423,7 +414,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
const self = this;
|
||||
reader.onloadend = function() {
|
||||
let base64data = reader.result;
|
||||
self.download(null,base64data,self.file.basename+'.png');
|
||||
download(null,base64data,self.file.basename+'.png');
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -444,7 +435,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
let svg = await ExcalidrawView.getSVG(this.getScene(),exportSettings);
|
||||
if(!svg) return null;
|
||||
svg = ExcalidrawView.embedFontsInSVG(svg);
|
||||
this.download("data:image/svg+xml;base64",btoa(unescape(encodeURIComponent(svg.outerHTML))),this.file.basename+'.svg');
|
||||
download("data:image/svg+xml;base64",btoa(unescape(encodeURIComponent(svg.outerHTML))),this.file.basename+'.svg');
|
||||
return;
|
||||
}
|
||||
this.saveSVG()
|
||||
@@ -455,7 +446,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
}
|
||||
|
||||
async getLibrary() {
|
||||
const data = JSON_parse(this.plugin.settings.library);
|
||||
const data = JSON_parse(this.plugin.getStencilLibrary());
|
||||
return data?.library ? data.library : [];
|
||||
}
|
||||
|
||||
@@ -640,7 +631,25 @@ export default class ExcalidrawView extends TextFileView {
|
||||
}
|
||||
}*/
|
||||
|
||||
let timestamp = (new Date()).getTime();
|
||||
let timestamp = 0;
|
||||
|
||||
const dblclickEvent = (e: Event):boolean => {
|
||||
if((e.target instanceof HTMLCanvasElement) && this.getSelectedText(true)) { //text element is selected
|
||||
const now = (new Date()).getTime();
|
||||
if(now-timestamp < 600) { //double click
|
||||
if(this.isTextLocked) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
new Notice(t("UNLOCK_TO_EDIT"));
|
||||
}
|
||||
timestamp = 0;
|
||||
this.lock(false);
|
||||
return true;
|
||||
}
|
||||
timestamp = now;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return React.createElement(
|
||||
React.Fragment,
|
||||
@@ -651,19 +660,13 @@ export default class ExcalidrawView extends TextFileView {
|
||||
className: "excalidraw-wrapper",
|
||||
ref: excalidrawWrapperRef,
|
||||
key: "abc",
|
||||
onTouchEnd: (e: TouchEvent) => {
|
||||
if (dblclickEvent(e)) return;
|
||||
},
|
||||
onClick: (e:MouseEvent):any => {
|
||||
if(this.isTextLocked && (e.target instanceof HTMLCanvasElement) && this.getSelectedText(true)) { //text element is selected
|
||||
const now = (new Date()).getTime();
|
||||
if(now-timestamp < 600) { //double click
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.lock(false);
|
||||
new Notice(t("UNLOCK_TO_EDIT"));
|
||||
timestamp = now;
|
||||
return;
|
||||
}
|
||||
timestamp = now;
|
||||
}
|
||||
//@ts-ignore
|
||||
if(this.app.isMobile) return;
|
||||
if(this.isTextLocked && dblclickEvent(e)) return;
|
||||
if(!(e.ctrlKey||e.metaKey)) return;
|
||||
if(!(this.plugin.settings.allowCtrlClick)) return;
|
||||
if(!this.getSelectedId()) return;
|
||||
@@ -735,7 +738,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
},
|
||||
onLibraryChange: (items:LibraryItems) => {
|
||||
(async () => {
|
||||
this.plugin.settings.library = EXCALIDRAW_LIB_HEADER+JSON.stringify(items)+'}';
|
||||
this.plugin.setStencilLibrary(EXCALIDRAW_LIB_HEADER+JSON.stringify(items)+'}');
|
||||
await this.plugin.saveSettings();
|
||||
})();
|
||||
}
|
||||
|
||||
30
src/Utils.ts
Normal file
30
src/Utils.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { normalizePath, TFolder } from "obsidian";
|
||||
|
||||
/**
|
||||
* Splits a full path including a folderpath and a filename into separate folderpath and filename components
|
||||
* @param filepath
|
||||
*/
|
||||
export function splitFolderAndFilename(filepath: string):{folderpath: string, filename: string} {
|
||||
let folderpath: string, filename:string;
|
||||
const lastIndex = filepath.lastIndexOf("/");
|
||||
return {
|
||||
folderpath: normalizePath(filepath.substr(0,lastIndex)),
|
||||
filename: lastIndex==-1 ? filepath : filepath.substr(lastIndex+1),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Download data as file from Obsidian, to store on local device
|
||||
* @param encoding
|
||||
* @param data
|
||||
* @param filename
|
||||
*/
|
||||
export function download(encoding:string,data:any,filename:string) {
|
||||
let element = document.createElement('a');
|
||||
element.setAttribute('href', (encoding ? encoding + ',' : '') + data);
|
||||
element.setAttribute('download', filename);
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
@@ -10,6 +10,7 @@ export default {
|
||||
CREATE_NEW : "New Excalidraw drawing",
|
||||
CONVERT_FILE_KEEP_EXT: "*.excalidraw => *.excalidraw.md",
|
||||
CONVERT_FILE_REPLACE_EXT: "*.excalidraw => *.md (Logseq compatibility)",
|
||||
DOWNLOAD_LIBRARY: "Export stencil library as an *.excalidrawlib file",
|
||||
OPEN_EXISTING_NEW_PANE: "Open an existing drawing - IN A NEW PANE",
|
||||
OPEN_EXISTING_ACTIVE_PANE: "Open an existing drawing - IN THE CURRENT ACTIVE PANE",
|
||||
TRANSCLUDE: "Transclude (embed) a drawing",
|
||||
@@ -108,6 +109,17 @@ export default {
|
||||
"While the auto-export switch is on, this file will get updated every time you edit the excalidraw drawing with the matching name.",
|
||||
EXPORT_PNG_NAME: "Auto-export PNG",
|
||||
EXPORT_PNG_DESC: "Same as the auto-export SVG, but for *.PNG",
|
||||
/* STENCIL_HEAD: "Stencil Library",
|
||||
STENCIL_INVAULT_NAME: "Store as FILE",
|
||||
STENCIL_INVAULT_DESC: "By enabling this feature, the stencil library will be stored in a file specified in the next setting. " +
|
||||
"Obsidan Sync now synchronizes all filetypes. By storing your stencil library in a file you can synchronize your library between devices. " +
|
||||
"When enabling this setting, if the file you specified is empty, your existing stencils in settings will be copied to the file. " +
|
||||
"When disabling this setting, your current stencil library will not overwirte stencils in your settings. " +
|
||||
"You need to close all Excalidraw views and reopen them, for this change to take effect. " +
|
||||
"The default filename is Excalidraw/stencils.excalidrawlib " ,
|
||||
STENCIL_PATH_NAME: "Filepath",
|
||||
STENCIL_PATH_DESC: "This can only be edited when \"Store as FILE\" is turned off. " +
|
||||
"The filepath of the stencil library. Enter the filename without the extension. ",*/
|
||||
COMPATIBILITY_HEAD: "Compatibility features",
|
||||
EXPORT_EXCALIDRAW_NAME: "Auto-export Excalidraw",
|
||||
EXPORT_EXCALIDRAW_DESC: "Same as the auto-export SVG, but for *.Excalidraw",
|
||||
|
||||
76
src/main.ts
76
src/main.ts
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
TFile,
|
||||
TFolder,
|
||||
Plugin,
|
||||
WorkspaceLeaf,
|
||||
addIcon,
|
||||
@@ -16,6 +15,7 @@ import {
|
||||
MarkdownRenderer,
|
||||
ViewState,
|
||||
Notice,
|
||||
TFolder,
|
||||
} from "obsidian";
|
||||
|
||||
import {
|
||||
@@ -58,17 +58,20 @@ import { Prompt } from "./Prompt";
|
||||
import { around } from "monkey-around";
|
||||
import { t } from "./lang/helpers";
|
||||
import { MigrationPrompt } from "./MigrationPrompt";
|
||||
import { download, splitFolderAndFilename } from "./Utils";
|
||||
|
||||
export default class ExcalidrawPlugin extends Plugin {
|
||||
public excalidrawFileModes: { [file: string]: string } = {};
|
||||
private _loaded: boolean = false;
|
||||
public settings: ExcalidrawSettings;
|
||||
//public stencilLibrary: any = null;
|
||||
private openDialog: OpenFileDialog;
|
||||
private activeExcalidrawView: ExcalidrawView = null;
|
||||
public lastActiveExcalidrawFilePath: string = null;
|
||||
private hover: {linkText: string, sourcePath: string} = {linkText: null, sourcePath: null};
|
||||
private observer: MutationObserver;
|
||||
private fileExplorerObserver: MutationObserver;
|
||||
public opencount:number = 0;
|
||||
|
||||
constructor(app: App, manifest: PluginManifest) {
|
||||
super(app, manifest);
|
||||
@@ -102,7 +105,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
//inspiration taken from kanban:
|
||||
//https://github.com/mgmeyers/obsidian-kanban/blob/44118e25661bff9ebfe54f71ae33805dc88ffa53/src/main.ts#L267
|
||||
this.registerMonkeyPatches();
|
||||
if(this.settings.loadCount<3) this.migrationNotice();
|
||||
if(this.settings.loadCount<1) this.migrationNotice();
|
||||
|
||||
}
|
||||
|
||||
@@ -110,7 +113,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
const self = this;
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
self.settings.loadCount++;
|
||||
self.saveSettings();
|
||||
//self.saveSettings();
|
||||
const files = this.app.vault.getFiles().filter((f)=>f.extension=="excalidraw");
|
||||
if(files.length>0) {
|
||||
const prompt = new MigrationPrompt(self.app, self);
|
||||
@@ -239,7 +242,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
//@ts-ignore
|
||||
this.app.workspace.on('hover-link',hoverEvent)
|
||||
);
|
||||
|
||||
|
||||
//monitoring for div.popover.hover-popover.file-embed.is-loaded to be added to the DOM tree
|
||||
this.observer = new MutationObserver((m)=>{
|
||||
if(m.length == 0) return;
|
||||
@@ -411,6 +414,14 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
this.app.workspace.on("file-menu", fileMenuHandlerConvertReplaceExtension)
|
||||
);
|
||||
|
||||
this.addCommand({
|
||||
id: "excalidraw-download-lib",
|
||||
name: t("DOWNLOAD_LIBRARY"),
|
||||
callback: () => {
|
||||
download('data:text/plain;charset=utf-8',encodeURIComponent(this.settings.library), 'my-obsidian-library.excalidrawlib');
|
||||
},
|
||||
});
|
||||
|
||||
this.addCommand({
|
||||
id: "excalidraw-open",
|
||||
name: t("OPEN_EXISTING_NEW_PANE"),
|
||||
@@ -847,6 +858,9 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
for (let i=0;i<leaves.length;i++) {
|
||||
(leaves[i].view as ExcalidrawView).save();
|
||||
}
|
||||
this.settings.drawingOpenCount += this.opencount;
|
||||
this.settings.loadCount++;
|
||||
this.saveSettings();
|
||||
}
|
||||
self.registerEvent(
|
||||
self.app.workspace.on("quit",quitEventHandler)
|
||||
@@ -881,7 +895,9 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
excalidrawLeaves.forEach((leaf) => {
|
||||
this.setMarkdownView(leaf);
|
||||
});
|
||||
|
||||
this.settings.drawingOpenCount += this.opencount;
|
||||
this.settings.loadCount++;
|
||||
this.saveSettings();
|
||||
}
|
||||
|
||||
public embedDrawing(data:string) {
|
||||
@@ -894,12 +910,45 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
|
||||
}
|
||||
|
||||
private async loadSettings() {
|
||||
public async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
/* if(this.settings.libraryInVault) {
|
||||
const filepath = this.settings.libraryLocation+".excalidrawlib";
|
||||
const file = this.app.vault.getAbstractFileByPath(filepath);
|
||||
if(file && file instanceof TFile) {
|
||||
this.stencilLibrary = await this.app.vault.read(file);
|
||||
} else {
|
||||
this.stencilLibrary = this.settings.library;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
/* if(this.settings.libraryInVault) {
|
||||
const filepath = this.settings.libraryLocation+".excalidrawlib";
|
||||
const f = splitFolderAndFilename(filepath);
|
||||
await this.checkAndCreateFolder(f.folderpath);
|
||||
const file = this.app.vault.getAbstractFileByPath(filepath);
|
||||
if(file && file instanceof TFile) {
|
||||
await this.app.vault.modify(file,this.stencilLibrary ? this.stencilLibrary : this.settings.library)
|
||||
} else {
|
||||
await this.app.vault.create(filepath,JSON.stringify(this.stencilLibrary ? this.stencilLibrary : this.settings.library));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public getStencilLibrary():string {
|
||||
//if(this.settings.libraryInVault) return this.stencilLibrary;
|
||||
return this.settings.library;
|
||||
}
|
||||
|
||||
public setStencilLibrary(library:string) {
|
||||
/* if(this.settings.libraryInVault) {
|
||||
this.stencilLibrary = library;
|
||||
} else {*/
|
||||
this.settings.library = library;
|
||||
//}
|
||||
}
|
||||
|
||||
public triggerEmbedUpdates(filepath?:string){
|
||||
@@ -961,10 +1010,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
|
||||
public async createDrawing(filename: string, onNewPane: boolean, foldername?: string, initData?:string) {
|
||||
const folderpath = normalizePath(foldername ? foldername: this.settings.folder);
|
||||
const folder = this.app.vault.getAbstractFileByPath(folderpath);
|
||||
if (!(folder && folder instanceof TFolder)) {
|
||||
await this.app.vault.createFolder(folderpath);
|
||||
}
|
||||
await this.checkAndCreateFolder(folderpath); //create folder if it does not exist
|
||||
|
||||
const fname = this.getNewUniqueFilepath(filename,folderpath);
|
||||
|
||||
@@ -1018,4 +1064,14 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
const fileCache = this.app.metadataCache.getFileCache(f);
|
||||
return !!fileCache?.frontmatter && !!fileCache.frontmatter[FRONTMATTER_KEY];
|
||||
}
|
||||
|
||||
/**
|
||||
* Open or create a folderpath if it does not exist
|
||||
* @param folderpath
|
||||
*/
|
||||
public async checkAndCreateFolder(folderpath:string) {
|
||||
let folder = this.app.vault.getAbstractFileByPath(folderpath);
|
||||
if(folder && folder instanceof TFolder) return;
|
||||
await this.app.vault.createFolder(folderpath);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
import {
|
||||
App,
|
||||
PluginSettingTab,
|
||||
Setting
|
||||
Setting,
|
||||
TFile
|
||||
} from 'obsidian';
|
||||
import { VIEW_TYPE_EXCALIDRAW } from './constants';
|
||||
import ExcalidrawView from './ExcalidrawView';
|
||||
import { t } from './lang/helpers';
|
||||
import type ExcalidrawPlugin from "./main";
|
||||
import { splitFolderAndFilename } from './Utils';
|
||||
|
||||
export interface ExcalidrawSettings {
|
||||
folder: string,
|
||||
@@ -25,12 +27,14 @@ export interface ExcalidrawSettings {
|
||||
autoexportPNG: boolean,
|
||||
autoexportExcalidraw: boolean,
|
||||
syncExcalidraw: boolean,
|
||||
library: string,
|
||||
compatibilityMode: boolean,
|
||||
experimentalFileType: boolean,
|
||||
experimentalFileTag: string,
|
||||
loadCount: number, //version 1.2 migration counter
|
||||
drawingOpenCount: number,
|
||||
// libraryInVault: boolean, //if true, library is stored in the vault in a file
|
||||
// libraryLocation: string, //full path to the library file
|
||||
library: string,
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
@@ -50,12 +54,14 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
autoexportPNG: false,
|
||||
autoexportExcalidraw: false,
|
||||
syncExcalidraw: false,
|
||||
library: `{"type":"excalidrawlib","version":1,"library":[]}`,
|
||||
experimentalFileType: false,
|
||||
experimentalFileTag: "✏️",
|
||||
compatibilityMode: false,
|
||||
loadCount: 0,
|
||||
drawingOpenCount: 0,
|
||||
// libraryInVault: false,
|
||||
// libraryLocation: "Excalidraw/library",
|
||||
library: `{"type":"excalidrawlib","version":1,"library":[]}`,
|
||||
}
|
||||
|
||||
export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
@@ -271,6 +277,48 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
this.plugin.settings.autoexportPNG = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
|
||||
/*
|
||||
this.containerEl.createEl('h1', {text: t("STENCIL_HEAD")});
|
||||
|
||||
const changeLibrary = async () => {
|
||||
if(!this.plugin.settings.libraryInVault) return;
|
||||
const filepath = this.plugin.settings.libraryLocation+".excalidrawlib";
|
||||
const f = splitFolderAndFilename(filepath);
|
||||
await this.plugin.checkAndCreateFolder(f.folderpath);
|
||||
const file = this.app.vault.getAbstractFileByPath(filepath);
|
||||
if(file && file instanceof TFile) {
|
||||
this.plugin.stencilLibrary = await this.app.vault.read(file);
|
||||
} else {
|
||||
this.plugin.stencilLibrary = this.plugin.settings.library;
|
||||
}
|
||||
}
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("STENCIL_INVAULT_NAME"))
|
||||
.setDesc(t("STENCIL_INVAULT_DESC"))
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.libraryInVault)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.libraryInVault = value;
|
||||
if(value) stencilLib.setDisabled(true);
|
||||
|
||||
await changeLibrary();
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
|
||||
const stencilLib = new Setting(containerEl)
|
||||
.setName(t("STENCIL_PATH_NAME"))
|
||||
.setDesc(t("STENCIL_PATH_DESC"))
|
||||
.addText(text => text
|
||||
.setPlaceholder('Excalidraw/library')
|
||||
.setValue(this.plugin.settings.libraryLocation)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.libraryInVault = false;
|
||||
this.plugin.stencilLibrary = null;
|
||||
this.plugin.settings.libraryLocation = value;
|
||||
await this.plugin.saveSettings();
|
||||
})); */
|
||||
|
||||
this.containerEl.createEl('h1', {text: t("COMPATIBILITY_HEAD")});
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ button.ToolIcon_type_button[title="Export"] {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: "Virgil";
|
||||
src: url("https://excalidraw.com/Virgil.woff2");
|
||||
@@ -71,4 +71,4 @@ button.ToolIcon_type_button[title="Export"] {
|
||||
@font-face {
|
||||
font-family: "Cascadia";
|
||||
src: url("https://excalidraw.com/Cascadia.woff2");
|
||||
}
|
||||
}*/
|
||||
|
||||
Reference in New Issue
Block a user