Compare commits

..

13 Commits

Author SHA1 Message Date
Zsolt Viczian
1c707db3a7 1.0.6 2021-04-28 21:38:22 +02:00
zsviczian
a56fda222d Update .gitignore 2021-04-28 16:08:21 +02:00
zsviczian
9fcbe5b7d7 Delete data.json 2021-04-28 16:05:25 +02:00
zsviczian
3c6dbcc8bb Delete data-ZsoltServer.json 2021-04-28 16:05:09 +02:00
zsviczian
25e2f3d8bb Update README.md 2021-04-28 15:58:45 +02:00
zsviczian
1c35e86118 Update README.md 2021-04-28 15:57:34 +02:00
zsviczian
61b716d8f6 Update manifest.json 2021-04-28 15:46:27 +02:00
zsviczian
2a0404fe18 Update versions.json 2021-04-28 15:46:04 +02:00
Zsolt Viczian
4f4a80b317 revert readme commit 2021-04-28 15:43:59 +02:00
Zsolt Viczian
0259dc579f Revert "left align images in readme.md"
This reverts commit fe84c607a6.
2021-04-28 15:43:30 +02:00
zsviczian
fe84c607a6 left align images in readme.md 2021-04-28 15:36:33 +02:00
zsviczian
b8178ac07c Update README.md 2021-04-28 13:52:35 +02:00
Zsolt Viczian
a65c6afed2 correct manifest and versions 2021-04-28 06:25:20 +02:00
10 changed files with 145 additions and 114 deletions

3
.gitignore vendored
View File

@@ -10,4 +10,5 @@ package-lock.json
main.js
*.js.map
stats.html
hot-reload.bat
hot-reload.bat
data.json

View File

@@ -29,7 +29,8 @@ The Obsidian-Excalidraw plugin integrates [Excalidraw](https://excalidraw.com/),
[![Part 6: Intro to Obsidian-Excalidraw: Embedding drawings](https://user-images.githubusercontent.com/14358394/115983954-bbdd6380-a5a4-11eb-9243-f0151451afcd.jpg)](https://youtu.be/JQeJ-Hh-xAI)
### Known issues
- On iPad: As you draw left to right it opens left sidebar. Draw right to left, opens right sidebar. Draw down, opens commands palette. So seems open is emulating the gestures, even when drawing towards the center. I understand that the issue will be resolved in the next release of Obsidian mobile.
- On mobile (iOS and Android): As you draw left to right it opens left sidebar. Draw right to left, opens right sidebar. Draw down, opens commands palette. So seems open is emulating the gestures, even when drawing towards the center. I understand that the issue will be resolved in the next release of Obsidian mobile.
- I have seen two cases when adding a stencil library did not work. In both cases the end solution was a reinstall of Obsidian. The root cause is not clear, but may be due to the incremental updates of Obsidian from an early version.
### Excalidraw in Obsidian
https://user-images.githubusercontent.com/14358394/115386872-3fc8d180-a1da-11eb-9366-16d0e064932a.mp4
@@ -42,6 +43,7 @@ By clicking [here](https://github.com/zsviczian/obsidian-excalidraw-plugin/issue
### Support
If you want to support me and my work, you can donate me a little something.
[<img src="https://user-images.githubusercontent.com/14358394/115450238-f39e8100-a21b-11eb-89d0-fa4b82cdbce8.png" width="200">](https://ko-fi.com/zsolt)
[<img style="float:left" src="https://user-images.githubusercontent.com/14358394/115450238-f39e8100-a21b-11eb-89d0-fa4b82cdbce8.png" width="200">](https://ko-fi.com/zsolt)
[https://ko-fi/zsolt](https://ko-fi.com/zsolt)

View File

@@ -1 +0,0 @@
{"openFile":"Blog/attachements/security through obscurity.excalidraw","settings":{"folder":"excalidraw","templateFilePath":"excalidraw/Template.excalidraw"}}

View File

@@ -1 +0,0 @@
{"folder":"excalidraw","templateFilePath":"excalidraw/Template.excalidra","width":"400","openFile":"excalidraw/new file.excalidraw","settings":{"folder":"excalidraw","templateFilePath":""}}

View File

@@ -7,4 +7,4 @@
"author": "Zsolt Viczian",
"authorUrl": "https://zsolt.blog",
"isDesktopOnly": false
}
}

View File

@@ -3,11 +3,11 @@ import {
WorkspaceLeaf,
normalizePath,
TFile,
Menu,
} from "obsidian";
import * as React from "react";
import * as ReactDOM from "react-dom";
import Excalidraw, {exportToSvg} from "@excalidraw/excalidraw";
//import Excalidraw, {exportToSvg} from "aakansha-excalidraw";
import { ExcalidrawElement } from "@excalidraw/excalidraw/types/element/types";
import {
AppState,
@@ -19,7 +19,10 @@ import {
ICON_NAME,
EXCALIDRAW_LIB_HEADER,
VIRGIL_FONT,
CASCADIA_FONT
CASCADIA_FONT,
DISK_ICON_NAME,
PNG_ICON_NAME,
SVG_ICON_NAME
} from './constants';
import ExcalidrawPlugin from './main';
@@ -95,6 +98,15 @@ export default class ExcalidrawView extends TextFileView {
else return this.data;
}
async onload() {
this.addAction(DISK_ICON_NAME,"Save drawing",async (ev)=> {
await this.save();
this.plugin.triggerEmbedUpdates();
});
this.addAction(PNG_ICON_NAME,"Export as PNG",async (ev)=>this.savePNG());
this.addAction(SVG_ICON_NAME,"Export as SVG",async (ev)=>this.saveSVG());
}
async onunload() {
if(this.excalidrawRef) await this.save();
}
@@ -239,9 +251,11 @@ export default class ExcalidrawView extends TextFileView {
this.contentEl.querySelector("canvas")?.dispatchEvent(e);
}
},
onLibraryChange: async (items:LibraryItems) => {
this.plugin.settings.library = EXCALIDRAW_LIB_HEADER+JSON.stringify(items)+'}';
await this.plugin.saveSettings();
onLibraryChange: (items:LibraryItems) => {
(async () => {
this.plugin.settings.library = EXCALIDRAW_LIB_HEADER+JSON.stringify(items)+'}';
await this.plugin.saveSettings();
})();
}
})
)

File diff suppressed because one or more lines are too long

View File

@@ -8,6 +8,7 @@ import {
PluginManifest,
MarkdownView,
normalizePath,
MarkdownPostProcessorContext,
} from 'obsidian';
import {
BLANK_DRAWING,
@@ -16,6 +17,13 @@ import {
ICON_NAME,
EXCALIDRAW_FILE_EXTENSION,
CODEBLOCK_EXCALIDRAW,
DISK_ICON,
DISK_ICON_NAME,
PNG_ICON,
PNG_ICON_NAME,
SVG_ICON,
SVG_ICON_NAME,
RERENDER_EVENT
} from './constants';
import ExcalidrawView, {ExportSettings} from './ExcalidrawView';
import {
@@ -39,6 +47,9 @@ export default class ExcalidrawPlugin extends Plugin {
async onload() {
addIcon(ICON_NAME, EXCALIDRAW_ICON);
addIcon(DISK_ICON_NAME,DISK_ICON);
addIcon(PNG_ICON_NAME,PNG_ICON);
addIcon(SVG_ICON_NAME,SVG_ICON);
this.registerView(
VIEW_TYPE_EXCALIDRAW,
@@ -48,87 +59,34 @@ export default class ExcalidrawPlugin extends Plugin {
this.registerExtensions([EXCALIDRAW_FILE_EXTENSION],VIEW_TYPE_EXCALIDRAW);
this.registerMarkdownCodeBlockProcessor(CODEBLOCK_EXCALIDRAW, async (source,el,ctx) => {
const parseError = (message: string) => {
el.createDiv("excalidraw-error",(el)=> {
el.createEl("p","Please provide a link to an excalidraw file: [[file."+EXCALIDRAW_FILE_EXTENSION+"]]");
el.createEl("p",message);
el.createEl("p",source);
})
}
const fname = source.match(/\[{2}([^|]*).*\]{2}/m)[1];
const filenameWH = source.match(/\[{2}(.*)\|(\d*)x(\d*)\]{2}/m);
const filenameW = source.match(/\[{2}(.*)\|(\d*)\]{2}/m);
let style = "excalidraw-svg"
style += source.contains("|left") ? "-left" : "";
style += source.contains("|right") ? "-right" : "";
style += source.contains("|center") ? "-center" : "";
let fwidth:string = this.settings.width;
let fheight:string = null;
if (filenameWH) {
fwidth = filenameWH[2];
fheight = filenameWH[3];
} else if (filenameW) {
fwidth = filenameW[2];
}
if(fname == '') {
parseError("No link to file found in codeblock.");
return;
}
const file = this.app.vault.getAbstractFileByPath(fname);
if(!(file && file instanceof TFile)) {
parseError("File does not exist. " + fname);
return;
}
if(file.extension != EXCALIDRAW_FILE_EXTENSION) {
parseError("Not an excalidraw file. Must have extension " + EXCALIDRAW_FILE_EXTENSION);
return;
}
const content = await this.app.vault.read(file);
const exportSettings: ExportSettings = {
withBackground: this.settings.exportWithBackground,
withTheme: this.settings.exportWithTheme
}
const svg = ExcalidrawView.getSVG(content,exportSettings);
if(!svg) {
parseError("Parse error. Not a valid Excalidraw file.");
return;
}
el.createDiv("excalidraw-svg",(el)=> {
svg.removeAttribute('width');
svg.removeAttribute('height');
svg.style.setProperty('width',fwidth);
if(fheight) svg.style.setProperty('height',fheight);
svg.addClass(style);
el.appendChild(svg);
el.addEventListener(RERENDER_EVENT,async (e) => {
e.stopPropagation();
el.empty();
this.codeblockProcessor(source,el,ctx,this);
});
});
this.codeblockProcessor(source,el,ctx,this);
});
await this.loadSettings();
this.addSettingTab(new ExcalidrawSettingTab(this.app, this));
this.openDialog = new OpenFileDialog(this.app, this);
this.addRibbonIcon(ICON_NAME, 'Excalidraw', async () => {
this.createDrawing(this.getNextDefaultFilename(), this.settings.ribbonInNewPane);
this.addRibbonIcon(ICON_NAME, 'Create a new drawing in Excalidraw', async (e) => {
this.createDrawing(this.getNextDefaultFilename(), e.ctrlKey);
});
this.addCommand({
id: "excalidraw-open",
name: "Open an existing drawing or create new one on a new pane",
name: "Open an existing drawing - IN A NEW PANE",
callback: () => {
this.openDialog.start(openDialogAction.openFile, true);
},
});
this.addCommand({
id: "excalidraw-open-on-current",
name: "Open an existing drawing or create new one on the currently active pane",
name: "Open an existing drawing - IN THE CURRENT ACTIVE PANE",
callback: () => {
this.openDialog.start(openDialogAction.openFile, false);
},
@@ -136,7 +94,7 @@ export default class ExcalidrawPlugin extends Plugin {
this.addCommand({
id: "excalidraw-insert-transclusion",
name: "Transclude an ."+EXCALIDRAW_FILE_EXTENSION+" file into a markdown document",
name: "Transclude (embed) an ."+EXCALIDRAW_FILE_EXTENSION+" drawing",
checkCallback: (checking: boolean) => {
if (checking) {
return this.app.workspace.activeLeaf.view.getViewType() == "markdown";
@@ -147,10 +105,9 @@ export default class ExcalidrawPlugin extends Plugin {
},
});
this.addCommand({
id: "excalidraw-autocreate",
name: "Create a new drawing and open on a new pane",
name: "Create a new drawing - IN A NEW PANE",
callback: () => {
this.createDrawing(this.getNextDefaultFilename(), true);
},
@@ -158,7 +115,7 @@ export default class ExcalidrawPlugin extends Plugin {
this.addCommand({
id: "excalidraw-autocreate-on-current",
name: "Create a new drawing and open on the currently active pane",
name: "Create a new drawing - IN THE CURRENT ACTIVE PANE",
callback: () => {
this.createDrawing(this.getNextDefaultFilename(), false);
},
@@ -166,7 +123,7 @@ export default class ExcalidrawPlugin extends Plugin {
this.addCommand({
id: 'export-svg',
name: 'Export the current drawing as an SVG image next to the current .excalidraw file',
name: 'Export SVG. Save it next to the current file',
checkCallback: (checking: boolean) => {
if (checking) {
return this.app.workspace.activeLeaf.view.getViewType() == VIEW_TYPE_EXCALIDRAW;
@@ -183,7 +140,7 @@ export default class ExcalidrawPlugin extends Plugin {
this.addCommand({
id: 'export-png',
name: 'Export the current drawing as a PNG image next to the current .excalidraw file',
name: 'Export PNG. Save it next to the current file',
checkCallback: (checking: boolean) => {
if (checking) {
return this.app.workspace.activeLeaf.view.getViewType() == VIEW_TYPE_EXCALIDRAW;
@@ -220,7 +177,62 @@ export default class ExcalidrawPlugin extends Plugin {
}
});
}
private async codeblockProcessor(source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext, plugin: ExcalidrawPlugin) {
const parseError = (message: string) => {
el.createDiv("excalidraw-error",(el)=> {
el.createEl("p","Please provide a link to an excalidraw file: [[file."+EXCALIDRAW_FILE_EXTENSION+"]]");
el.createEl("p",message);
el.createEl("p",source);
})
}
const parts = source.match(/\[{2}([^|]*)\|?(\d*)x?(\d*)\|?(.*)\]{2}/m);
if(!parts) {
parseError("No link to file found in codeblock.");
return;
}
const fname = parts[1];
const fwidth = parts[2]? parts[2] : plugin.settings.width;
const fheight = parts[3];
const style = "excalidraw-svg" + (parts[4] ? "-" + parts[4] : "");
if(!fname) {
parseError("No link to file found in codeblock.");
return;
}
const file = plugin.app.vault.getAbstractFileByPath(fname);
if(!(file && file instanceof TFile)) {
parseError("File does not exist. " + fname);
return;
}
if(file.extension != EXCALIDRAW_FILE_EXTENSION) {
parseError("Not an excalidraw file. Must have extension " + EXCALIDRAW_FILE_EXTENSION);
return;
}
const content = await plugin.app.vault.read(file);
const exportSettings: ExportSettings = {
withBackground: plugin.settings.exportWithBackground,
withTheme: plugin.settings.exportWithTheme
}
const svg = ExcalidrawView.getSVG(content,exportSettings);
if(!svg) {
parseError("Parse error. Not a valid Excalidraw file.");
return;
}
el.createDiv("excalidraw-svg",(el)=> {
svg.removeAttribute('width');
svg.removeAttribute('height');
svg.style.setProperty('width',fwidth);
if(fheight) svg.style.setProperty('height',fheight);
svg.addClass(style);
el.appendChild(svg);
});
}
public insertCodeblock(data:string) {
const activeView = this.app.workspace.getActiveViewOfType(MarkdownView);
if(activeView) {
@@ -243,6 +255,14 @@ export default class ExcalidrawPlugin extends Plugin {
await this.saveData(this.settings);
}
public triggerEmbedUpdates(){
const e = document.createEvent("Event")
e.initEvent(RERENDER_EVENT,true,false);
document
.querySelectorAll("svg[class^='excalidraw-svg']")
.forEach((el) => el.dispatchEvent(e));
}
public async openDrawing(drawingFile: TFile, onNewPane: boolean) {
const leafs = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
let leaf:WorkspaceLeaf = null;

View File

@@ -10,7 +10,6 @@ export interface ExcalidrawSettings {
folder: string,
templateFilePath: string,
width: string,
ribbonInNewPane: boolean,
exportWithTheme: boolean,
exportWithBackground: boolean,
autoexportSVG: boolean,
@@ -23,7 +22,6 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
folder: 'Excalidraw',
templateFilePath: 'Excalidraw/Template.excalidraw',
width: '400',
ribbonInNewPane: false,
exportWithTheme: true,
exportWithBackground: true,
autoexportSVG: false,
@@ -58,8 +56,8 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
new Setting(containerEl)
.setName('Excalidraw template file')
.setDesc('Full path to file containing the file you want to use as the template for new Excalidraw drawings. '+
'Note that Excalidraw files will have an extension of ".excalidraw" ' +
'Assuming your template is in the default excalidraw folder, the setting would be: excalidraw/Template.excalidraw')
'Note that Excalidraw files will have the extension ".excalidraw". ' +
'Assuming your template is in the default Excalidraw folder, the setting would be: Excalidraw/Template.excalidraw')
.addText(text => text
.setPlaceholder('Excalidraw/Template.excalidraw')
.setValue(this.plugin.settings.templateFilePath)
@@ -69,7 +67,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
}));
new Setting(containerEl)
.setName('Default width of embedded image')
.setName('Default width of embedded (transcluded) image')
.setDesc('The default width of an embedded drawing. You can specify a different ' +
'width when embedding an image using the [[drawing.excalidraw|100]] or ' +
'[[drawing.excalidraw|100x100]] format.')
@@ -79,47 +77,40 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
.onChange(async (value) => {
this.plugin.settings.width = value;
await this.plugin.saveSettings();
this.plugin.triggerEmbedUpdates();
}));
new Setting(containerEl)
.setName('Ribbon button opens drawing in new pane by splitting active pane')
.setDesc('If set, when pressing the ribbon button an empty drawing will open in a new pane by splitting the active pane.')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.ribbonInNewPane)
.onChange(async (value) => {
this.plugin.settings.ribbonInNewPane = value;
await this.plugin.saveSettings();
}));
this.containerEl.createEl('h1', {text: 'Embedded image settings'});
new Setting(containerEl)
.setName('Export image with background')
.setDesc('If turned of the exported image will be transparent.')
.setDesc('If turned off, the exported image will be transparent.')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.exportWithBackground)
.onChange(async (value) => {
this.plugin.settings.exportWithBackground = value;
await this.plugin.saveSettings();
this.plugin.triggerEmbedUpdates();
}));
new Setting(containerEl)
.setName('Export image with theme')
.setDesc('Export the image matching the dark/light theme setting used for your drawing in Excalidraw')
.setDesc('Export the image matching the dark/light theme setting used for your drawing in Excalidraw. If turned off, ' +
'drawings created in drak mode will appear as they would in light mode.')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.exportWithTheme)
.onChange(async (value) => {
this.plugin.settings.exportWithTheme = value;
await this.plugin.saveSettings();
this.plugin.triggerEmbedUpdates();
}));
new Setting(containerEl)
.setName('Auto export SVG')
.setDesc('Automatically create an SVG export of your drawing matching the title of your .excalidraw file, saved in the same folder. '+
'You can use this file ("my drawing.svg") to embed into documents in a platform independent way. ' +
'The file will get updated every time you edit the excalidraw drawing.')
.setName('Auto-export SVG')
.setDesc('Automatically create an SVG export of your drawing matching the title of your "my drawing.excalidraw" file. ' +
'The plugin will save the .SVG file in the same folder as the drawing. '+
'You can use this file ("my drawing.svg") to embed your drawing into documents in a platform independent way. ' +
'While the auto export switch is on, this file will get updated every time you edit the excalidraw drawing with the matching name.')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.autoexportSVG)
.onChange(async (value) => {
@@ -128,10 +119,8 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
}));
new Setting(containerEl)
.setName('Auto export PNG')
.setDesc('Automatically create a PNG export of your drawing matching the title of your .excalidraw file, saved in the same folder. '+
'You can use this file ("my drawing.png") to embed into documents in a platform independent way. ' +
'The file will get updated every time you edit the excalidraw drawing.')
.setName('Auto-export PNG')
.setDesc('Same as the auto-export SVG, but for PNG.')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.autoexportPNG)
.onChange(async (value) => {
@@ -141,9 +130,9 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
new Setting(containerEl)
.setName('Keep .svg and/or .png filename in sync with the .excalidraw filename')
.setDesc('Automaticaly update the .svg and/or .png filename when .excalidraw file in the same folder is renamed. ' +
'Automatically delete the .svg and/or .png file when the .excalidraw file in the same folder is deleted. ')
.setName('Keep the .SVG and/or .PNG filenames in sync with the .excalidraw file')
.setDesc('When turned on, the plugin will automaticaly update the filename of the .SVG and/or .PNG files when the .excalidraw file in the same folder (and same name) is renamed. ' +
'The plugin will also automatically delete the .SVG and/or .PNG files when the .excalidraw file in the same folder (and same name) is deleted. ')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.keepInSync)
.onChange(async (value) => {

View File

@@ -1,4 +1,4 @@
{
"1.0.6": "0.11.13",
"1.0.5": "0.11.13"
}
}