diff --git a/.forgejo/workflows/build.yml b/.github/workflows/release.yml
similarity index 60%
rename from .forgejo/workflows/build.yml
rename to .github/workflows/release.yml
index 4bfcc57..49834e5 100644
--- a/.forgejo/workflows/build.yml
+++ b/.github/workflows/release.yml
@@ -1,9 +1,7 @@
-name: Build on Push and create Release on Tag
+name: Create Release on Tag Push
on:
push:
- branches:
- - main
tags:
- "v*"
@@ -22,7 +20,7 @@ jobs:
node-version: 20
registry-url: "https://registry.npmjs.org"
- # Install pnpm
+ # Install pnpm
- name: Install pnpm
uses: pnpm/action-setup@v4
id: pnpm-install
@@ -30,12 +28,6 @@ jobs:
version: 8
run_install: false
- # Validate Tag Matches JSON Versions
- - name: Validate Tag Matches JSON Versions
- if: github.ref_type == 'tag'
- run: |
- node scripts/validate_tag.cjs ${{ github.ref }}
-
# Get pnpm store directory
- name: Get pnpm store directory
id: pnpm-cache
@@ -60,22 +52,11 @@ jobs:
- name: Build for production
run: pnpm build
- # Move file
- - name: Move file
- run: mkdir built; mv package.zip built/package.zip
-
- # Upload artifacts
- - name: Upload artifacts
- uses: actions/upload-artifact@v3
+ - name: Release
+ uses: ncipollo/release-action@v1
with:
- path: built/package.zip
- overwrite: true
-
- # Create Forgejo Release
- - name: Create Forgejo Release
- if: github.ref_type == 'tag'
- uses: actions/forgejo-release@v1
- with:
- direction: upload
- release-dir: built
- token: ${{ secrets.FORGE_TOKEN }}
+ allowUpdates: true
+ artifactErrorsFailBuild: true
+ artifacts: "package.zip"
+ token: ${{ secrets.GITHUB_TOKEN }}
+ prerelease: false
diff --git a/package.json b/package.json
index 76504eb..f355588 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "siyuan-jsdraw-plugin",
- "version": "0.4.0",
+ "version": "0.3.0",
"type": "module",
"description": "Include a whiteboard for freehand drawing anywhere in your documents.",
"repository": "https://git.massive.box/massivebox/siyuan-jsdraw-plugin",
@@ -36,7 +36,6 @@
},
"dependencies": {
"@js-draw/material-icons": "^1.29.0",
- "js-draw": "^1.29.0",
- "ts-serializable": "^4.2.0"
+ "js-draw": "^1.29.0"
}
}
diff --git a/plugin.json b/plugin.json
index 8acdb80..3f18451 100644
--- a/plugin.json
+++ b/plugin.json
@@ -2,7 +2,7 @@
"name": "siyuan-jsdraw-plugin",
"author": "massivebox",
"url": "https://git.massive.box/massivebox/siyuan-jsdraw-plugin",
- "version": "0.4.0",
+ "version": "0.3.0",
"minAppVersion": "3.0.12",
"backends": [
"windows",
@@ -31,7 +31,7 @@
},
"funding": {
"custom": [
- "https://s.massive.box/jsdraw-plugin-donate"
+ ""
]
},
"keywords": [
diff --git a/public/i18n/en_US.json b/public/i18n/en_US.json
index fbeb088..b6d2382 100644
--- a/public/i18n/en_US.json
+++ b/public/i18n/en_US.json
@@ -1,44 +1,3 @@
{
- "insertDrawing": "Insert Drawing",
- "editDrawing": "Edit with js-draw",
- "errNoFileID": "File ID missing - couldn't open file.",
- "errSyncIDNotFound": "Couldn't find SyncID in document for drawing, make sure you're trying to edit a drawing that is included in at least a note.",
- "errCreateUnknown": "Unknown error while creating editor, please try again.",
- "errInvalidBackgroundColor": "Invalid background color! Please enter an HEX color, like #000000 (black) or #FFFFFF (white). The old background color will be used.",
- "drawing": "Drawing",
- "settings": {
- "name": "js-draw Plugin Settings",
- "suggestedColors":{
- "white": "White",
- "black": "Black",
- "transparent": "Transparent",
- "custom": "Custom",
- "darkBlue": "Dark Blue",
- "darkGray": "Dark Gray"
- },
- "grid": {
- "title": "Enable grid by default",
- "description": "Enable to automatically turn on the grid on new drawings."
- },
- "backgroundDropdown":{
- "title": "Background color",
- "description": "Default background color for new drawings."
- },
- "background": {
- "title": "Custom background",
- "description": "Hexadecimal code of the custom background color for new drawings.
This setting is only applied if \"Background Color\" is set to \"Custom\"!"
- },
- "dialogOnDesktop": {
- "title": "Open editor as dialog on desktop",
- "description": "Dialog mode provides a larger drawing area, but it's not as handy to use as tabs (default).
The editor will always open as a dialog on mobile."
- },
- "analytics": {
- "title": "Analytics",
- "description": "Enable to send anonymous usage data to the developer. Privacy Policy"
- },
- "restorePosition": {
- "title": "Remember editor position",
- "description": "When enabled, the editor will remember the zoom factor and position, and it will restore them the next time you open the drawing."
- }
- }
+ "insertDrawing": "Insert Drawing"
}
\ No newline at end of file
diff --git a/public/webapp/cursor.png b/public/webapp/cursor.png
deleted file mode 100644
index 1306cf3..0000000
Binary files a/public/webapp/cursor.png and /dev/null differ
diff --git a/scripts/validate_tag.cjs b/scripts/validate_tag.cjs
deleted file mode 100644
index c842ffc..0000000
--- a/scripts/validate_tag.cjs
+++ /dev/null
@@ -1,24 +0,0 @@
-const fs = require('fs');
-const path = require('path');
-
-const [tagName] = process.argv.slice(2); // Get tag from CLI arguments
-if (!tagName) {
- console.error('Error: No tag name provided.');
- process.exit(1);
-}
-
-const TAG_VERSION = tagName.replace('refs/tags/v', '');
-
-try {
- const packageJson = JSON.parse(fs.readFileSync(path.resolve('package.json'), 'utf8'));
- const pluginJson = JSON.parse(fs.readFileSync(path.resolve('plugin.json'), 'utf8'));
-
- if (TAG_VERSION !== packageJson.version || TAG_VERSION !== pluginJson.version) {
- console.error(`Error: Tag version (${TAG_VERSION}) does not match package.json (${packageJson.version}) or plugin.json (${pluginJson.version})`);
- process.exit(1);
- }
- console.log('Tag version matches both JSON files.');
-} catch (err) {
- console.error('Failed to read or parse JSON files:', err.message);
- process.exit(1);
-}
diff --git a/src/config.ts b/src/config.ts
index 7c4bfca..52fd764 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -1,16 +1,17 @@
import {PluginFile} from "@/file";
import {CONFIG_FILENAME, JSON_MIME, STORAGE_PATH} from "@/const";
-import {Plugin, showMessage} from "siyuan";
+import {Plugin} from "siyuan";
import {SettingUtils} from "@/libs/setting-utils";
-import {getFirstDefined} from "@/helper";
+import {validateColor} from "@/helper";
-export interface Options {
+type Options = {
+ grid: boolean
+ background: string
dialogOnDesktop: boolean
analytics: boolean
- editorOptions: EditorOptions
-}
-export interface EditorOptions {
- restorePosition: boolean;
+};
+
+export type DefaultEditorOptions = {
grid: boolean
background: string
}
@@ -28,23 +29,30 @@ export class PluginConfig {
this.file = new PluginFile(STORAGE_PATH, CONFIG_FILENAME, JSON_MIME);
}
+ getDefaultEditorOptions(): DefaultEditorOptions {
+ return {
+ grid: this.options.grid,
+ background: this.options.background,
+ };
+ }
+
async load() {
this.firstRun = false;
await this.file.loadFromSiYuanFS();
- const jsonObj = JSON.parse(this.file.getContent());
- if(jsonObj == null) {
- this.firstRun = true;
+ this.options = JSON.parse(this.file.getContent());
+ if(this.options == null) {
+ this.loadDefaultConfig();
}
- // if more than one fallback, the intermediate ones are from a legacy config file version
+ }
+
+ private loadDefaultConfig() {
this.options = {
- dialogOnDesktop: getFirstDefined(jsonObj?.dialogOnDesktop, false),
- analytics: getFirstDefined(jsonObj?.analytics, true),
- editorOptions: {
- restorePosition: getFirstDefined(jsonObj?.editorOptions?.restorePosition, jsonObj?.restorePosition, true),
- grid: getFirstDefined(jsonObj?.editorOptions?.grid, jsonObj?.grid, true),
- background: getFirstDefined(jsonObj?.editorOptions?.background, jsonObj?.background, "#00000000")
- },
+ grid: true,
+ background: "#000000",
+ dialogOnDesktop: false,
+ analytics: true,
};
+ this.firstRun = true;
}
async save() {
@@ -53,14 +61,12 @@ export class PluginConfig {
}
setConfig(config: Options) {
- this.options = config;
- }
+ if(!validateColor(config.background)) {
+ alert("Invalid background color! Please enter an HEX color, like #000000 (black) or #FFFFFF (white)");
+ config.background = this.options.background;
+ }
- static validateColor(hex: string) {
- hex = hex.replace('#', '');
- return typeof hex === 'string'
- && (hex.length === 6 || hex.length === 8)
- && !isNaN(Number('0x' + hex))
+ this.options = config;
}
}
@@ -70,100 +76,62 @@ export class PluginConfigViewer {
config: PluginConfig;
settingUtils: SettingUtils;
plugin: Plugin;
- private readonly backgroundDropdownOptions;
constructor(config: PluginConfig, plugin: Plugin) {
this.config = config;
this.plugin = plugin;
- this.backgroundDropdownOptions = {
- '#00000000': plugin.i18n.settings.suggestedColors.transparent,
- 'CUSTOM': plugin.i18n.settings.suggestedColors.custom,
- '#ffffff': plugin.i18n.settings.suggestedColors.white,
- '#1e2227': plugin.i18n.settings.suggestedColors.darkBlue,
- '#1e1e1e': plugin.i18n.settings.suggestedColors.darkGray,
- '#000000': plugin.i18n.settings.suggestedColors.black,
- }
this.populateSettingMenu();
}
- async configSaveCallback(data) {
-
- let color = data.backgroundDropdown === "CUSTOM" ? data.background : data.backgroundDropdown;
- if(!PluginConfig.validateColor(color)) {
- showMessage(this.plugin.i18n.errInvalidBackgroundColor, 0, 'error');
- data.background = this.config.options.editorOptions.background;
- this.settingUtils.set('background', data.background);
- }
-
- this.config.setConfig({
- dialogOnDesktop: data.dialogOnDesktop,
- analytics: data.analytics,
- editorOptions: {
- grid: data.grid,
- background: color,
- restorePosition: data.restorePosition,
- }
- });
- await this.config.save();
-
- }
-
populateSettingMenu() {
this.settingUtils = new SettingUtils({
plugin: this.plugin,
- name: 'optionsUI',
callback: async (data) => {
- await this.configSaveCallback(data);
+ this.config.setConfig({
+ grid: data.grid,
+ background: data.background,
+ dialogOnDesktop: data.dialogOnDesktop,
+ analytics: data.analytics,
+ });
+ await this.config.save();
}
});
this.settingUtils.addItem({
key: "grid",
- title: this.plugin.i18n.settings.grid.title,
- description: this.plugin.i18n.settings.grid.description,
- value: this.config.options.editorOptions.grid,
+ title: "Enable grid by default",
+ description: "Enable to automatically turn on the grid on new drawings.",
+ value: this.config.options.grid,
type: 'checkbox'
});
- this.settingUtils.addItem({
- key: 'backgroundDropdown',
- title: this.plugin.i18n.settings.backgroundDropdown.title,
- description: this.plugin.i18n.settings.backgroundDropdown.description,
- type: 'select',
- value: this.config.options.editorOptions.background in this.backgroundDropdownOptions ?
- this.config.options.editorOptions.background : 'CUSTOM',
- options: this.backgroundDropdownOptions,
- });
-
this.settingUtils.addItem({
key: "background",
- title: this.plugin.i18n.settings.background.title,
- description: this.plugin.i18n.settings.background.description,
- value: this.config.options.editorOptions.background,
- type: 'textinput',
- });
-
- this.settingUtils.addItem({
- key: "restorePosition",
- title: this.plugin.i18n.settings.restorePosition.title,
- description: this.plugin.i18n.settings.restorePosition.description,
- value: this.config.options.editorOptions.restorePosition,
- type: 'checkbox'
+ title: "Default background Color",
+ description: "Default background color of the drawing area for new drawings in hexadecimal.",
+ value: this.config.options.background,
+ type: 'textarea',
});
this.settingUtils.addItem({
key: "dialogOnDesktop",
- title: this.plugin.i18n.settings.dialogOnDesktop.title,
- description: this.plugin.i18n.settings.dialogOnDesktop.description,
+ title: "Open editor as dialog on desktop",
+ description: `
+ Dialog mode provides a larger drawing area, but it's not as handy to use as tabs (default).
+ The editor will always open as a dialog on mobile.
+ `,
value: this.config.options.dialogOnDesktop,
type: 'checkbox'
});
this.settingUtils.addItem({
key: "analytics",
- title: this.plugin.i18n.settings.analytics.title,
- description: this.plugin.i18n.settings.analytics.description,
+ title: "Analytics",
+ description: `
+ Enable to send anonymous usage data to the developer.
+ Privacy
+ `,
value: this.config.options.analytics,
type: 'checkbox'
});
diff --git a/src/editor.ts b/src/editor.ts
index 1331e88..8680a40 100644
--- a/src/editor.ts
+++ b/src/editor.ts
@@ -1,21 +1,12 @@
import {MaterialIconProvider} from "@js-draw/material-icons";
import {PluginAsset, PluginFile} from "@/file";
import {JSON_MIME, STORAGE_PATH, SVG_MIME, TOOLBAR_FILENAME} from "@/const";
-import Editor, {
- BackgroundComponentBackgroundType,
- BaseWidget,
- Color4,
- EditorEventType,
- Mat33,
- Vec2,
- Viewport
-} from "js-draw";
-import {Dialog, getFrontend, openTab, Plugin, showMessage} from "siyuan";
+import Editor, {BackgroundComponentBackgroundType, BaseWidget, Color4, EditorEventType} from "js-draw";
+import {Dialog, getFrontend, openTab, Plugin} from "siyuan";
import {findSyncIDInProtyle, replaceSyncID} from "@/protyle";
import DrawJSPlugin from "@/index";
-import {EditorOptions} from "@/config";
+import {DefaultEditorOptions} from "@/config";
import 'js-draw/styles';
-import {SyncIDNotFoundError, UnchangedProtyleError} from "@/errors";
export class PluginEditor {
@@ -32,9 +23,8 @@ export class PluginEditor {
getEditor(): Editor { return this.editor; }
getFileID(): string { return this.fileID; }
getSyncID(): string { return this.syncID; }
- setSyncID(syncID: string) { this.syncID = syncID; }
- private constructor(fileID: string) {
+ constructor(fileID: string, defaultEditorOptions: DefaultEditorOptions) {
this.fileID = fileID;
@@ -44,87 +34,61 @@ export class PluginEditor {
iconProvider: new MaterialIconProvider(),
});
- const styleElement = document.createElement('style');
- styleElement.innerHTML = `
- canvas.wetInkCanvas {
- cursor: url('/plugins/siyuan-jsdraw-plugin/webapp/cursor.png') 6 6, auto;
- }
- `;
- this.element.appendChild(styleElement);
+ this.genToolbar().then(() => {
+ this.editor.dispatch(this.editor.setBackgroundStyle({ autoresize: true }), false);
+ this.editor.getRootElement().style.height = '100%';
+ });
- this.editor.dispatch(this.editor.setBackgroundStyle({ autoresize: true }), false);
- this.editor.getRootElement().style.height = '100%';
+ findSyncIDInProtyle(this.fileID).then(async (syncID) => {
- }
-
- static async create(fileID: string, defaultEditorOptions: EditorOptions): Promise {
-
- const instance = new PluginEditor(fileID);
-
- await instance.genToolbar();
- let syncID = await findSyncIDInProtyle(fileID);
-
- if(syncID == null) {
- throw new SyncIDNotFoundError(fileID);
- }
- instance.setSyncID(syncID);
- await instance.restoreOrInitFile(defaultEditorOptions);
-
- return instance;
-
- }
-
- async restoreOrInitFile(defaultEditorOptions: EditorOptions) {
-
- this.drawingFile = new PluginAsset(this.fileID, this.syncID, SVG_MIME);
- await this.drawingFile.loadFromSiYuanFS();
- const drawingContent = this.drawingFile.getContent();
-
- if(drawingContent != null) {
-
- await this.editor.loadFromSVG(drawingContent);
-
- // restore position and zoom
- const svgElem = new DOMParser().parseFromString(drawingContent, SVG_MIME).documentElement;
- const editorViewStr = svgElem.getAttribute('editorView');
- if(editorViewStr != null && defaultEditorOptions.restorePosition) {
- try {
- const [viewBoxOriginX, viewBoxOriginY, zoom] = editorViewStr.split(' ').map(x => parseFloat(x));
- this.editor.dispatch(Viewport.transformBy(Mat33.scaling2D(zoom)));
- this.editor.dispatch(Viewport.transformBy(Mat33.translation(Vec2.of(
- - viewBoxOriginX,
- - viewBoxOriginY
- ))));
- }catch (e){}
+ if(syncID == null) {
+ alert(
+ "Couldn't find SyncID in protyle for this file.\n" +
+ "Make sure the drawing you're trying to edit exists in a note.\n" +
+ "Close this editor tab now, and try to open the editor again."
+ );
+ return;
}
- }else{
- // it's a new drawing
- this.editor.dispatch(this.editor.setBackgroundStyle({
- color: Color4.fromHex(defaultEditorOptions.background),
- type: defaultEditorOptions.grid ? BackgroundComponentBackgroundType.Grid : BackgroundComponentBackgroundType.SolidColor,
- autoresize: true
- }));
- }
+ this.syncID = syncID;
+ // restore drawing
+ this.drawingFile = new PluginAsset(this.fileID, syncID, SVG_MIME);
+ await this.drawingFile.loadFromSiYuanFS();
+
+ if(this.drawingFile.getContent() != null) {
+ await this.editor.loadFromSVG(this.drawingFile.getContent());
+ }else{
+ // it's a new drawing
+ this.editor.dispatch(this.editor.setBackgroundStyle({
+ color: Color4.fromHex(defaultEditorOptions.background),
+ type: defaultEditorOptions.grid ? BackgroundComponentBackgroundType.Grid : BackgroundComponentBackgroundType.SolidColor,
+ autoresize: true
+ }));
+ }
+
+ }).catch((error) => {
+ alert("Error loading drawing: " + error);
+ });
}
- async genToolbar() {
+ private async genToolbar() {
const toolbar = this.editor.addToolbar();
+ // restore toolbarFile state
+ this.toolbarFile = new PluginFile(STORAGE_PATH, TOOLBAR_FILENAME, JSON_MIME);
+ this.toolbarFile.loadFromSiYuanFS().then(() => {
+ if(this.toolbarFile.getContent() != null) {
+ toolbar.deserializeState(this.toolbarFile.getContent());
+ }
+ });
+
// save button
const saveButton = toolbar.addSaveButton(async () => {
await this.saveCallback(saveButton);
});
- // restore toolbarFile state
- this.toolbarFile = new PluginFile(STORAGE_PATH, TOOLBAR_FILENAME, JSON_MIME);
- await this.toolbarFile.loadFromSiYuanFS();
- if(this.toolbarFile.getContent() != null) {
- toolbar.deserializeState(this.toolbarFile.getContent());
- }
-
// save toolbar config on tool change (toolbar state is not saved in SVGs!)
this.editor.notifier.on(EditorEventType.ToolUpdated, () => {
this.toolbarFile.setContent(toolbar.serializeState());
@@ -139,17 +103,13 @@ export class PluginEditor {
let newSyncID: string;
const oldSyncID = this.syncID;
- const rect = this.editor.viewport.visibleRect;
- const zoom = this.editor.viewport.getScaleFactor();
- svgElem.setAttribute('editorView', `${rect.x} ${rect.y} ${zoom}`)
-
try {
this.drawingFile.setContent(svgElem.outerHTML);
await this.drawingFile.save();
newSyncID = this.drawingFile.getSyncID();
if(newSyncID != oldSyncID) { // supposed to replace protyle
const changed = await replaceSyncID(this.fileID, oldSyncID, newSyncID); // try to change protyle
- if(!changed) throw new UnchangedProtyleError();
+ if(!changed) throw new Error("Couldn't replace old images in protyle");
await this.drawingFile.removeOld(oldSyncID);
}
saveButton.setDisabled(true);
@@ -157,10 +117,7 @@ export class PluginEditor {
saveButton.setDisabled(false);
}, 500);
} catch (error) {
- showMessage("Error saving! The current drawing has been copied to your clipboard. You may need to create a new drawing and paste it there.", 0, 'error');
- if(error instanceof UnchangedProtyleError) {
- showMessage("Make sure the image you're trying to edit still exists in your documents.", 0, 'error');
- }
+ alert("Error saving! The current drawing has been copied to your clipboard. You may need to create a new drawing and paste it there.");
await navigator.clipboard.writeText(svgElem.outerHTML);
console.error(error);
console.log("Couldn't save SVG: ", svgElem.outerHTML)
@@ -176,52 +133,31 @@ export class PluginEditor {
export class EditorManager {
private editor: PluginEditor
- setEditor(editor: PluginEditor) { this.editor = editor;}
- static async create(fileID: string, p: DrawJSPlugin) {
- let instance = new EditorManager();
- try {
- let editor = await PluginEditor.create(fileID, p.config.options.editorOptions);
- instance.setEditor(editor);
- }catch (error) {
- EditorManager.handleCreationError(error, p);
- }
- return instance;
+ constructor(fileID: string, defaultEditorOptions: DefaultEditorOptions) {
+ this.editor = new PluginEditor(fileID, defaultEditorOptions);
}
static registerTab(p: DrawJSPlugin) {
p.addTab({
'type': "whiteboard",
- async init() {
+ init() {
const fileID = this.data.fileID;
if (fileID == null) {
- alert(p.i18n.errNoFileID);
+ alert("File ID missing - couldn't open file.")
return;
}
- try {
- const editor = await PluginEditor.create(fileID, p.config.options.editorOptions);
- this.element.appendChild(editor.getElement());
- }catch (error){
- EditorManager.handleCreationError(error, p);
- }
+ const editor = new PluginEditor(fileID, p.config.getDefaultEditorOptions());
+ this.element.appendChild(editor.getElement());
}
});
}
- static handleCreationError(error: any, p: DrawJSPlugin) {
- console.error(error);
- let errorTxt = p.i18n.errCreateUnknown;
- if(error instanceof SyncIDNotFoundError) {
- errorTxt = p.i18n.errSyncIDNotFound;
- }
- showMessage(errorTxt, 0, 'error');
- }
-
toTab(p: Plugin) {
openTab({
app: p.app,
custom: {
- title: p.i18n.drawing,
+ title: 'Drawing',
icon: 'iconDraw',
id: "siyuan-jsdraw-pluginwhiteboard",
data: {
@@ -240,7 +176,7 @@ export class EditorManager {
dialog.element.querySelector("#DrawingPanel").appendChild(this.editor.getElement());
}
- open(p: DrawJSPlugin) {
+ async open(p: DrawJSPlugin) {
if(getFrontend() != "mobile" && !p.config.options.dialogOnDesktop) {
this.toTab(p);
} else {
diff --git a/src/errors.ts b/src/errors.ts
deleted file mode 100644
index 914bd9c..0000000
--- a/src/errors.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-
-export class SyncIDNotFoundError extends Error {
- readonly fileID: string;
-
- constructor(fileID: string) {
- super(`SyncID not found for file ${fileID}`);
- this.fileID = fileID;
- Object.setPrototypeOf(this, new.target.prototype);
- }
-}
-
-export class UnchangedProtyleError extends Error {}
\ No newline at end of file
diff --git a/src/helper.ts b/src/helper.ts
index 7041ba5..5a08636 100644
--- a/src/helper.ts
+++ b/src/helper.ts
@@ -107,10 +107,9 @@ export function imgSrcToIDs(imgSrc: string | null): { fileID: string; syncID: st
}
-export function getFirstDefined(...a) {
- for(let i = 0; i < a.length; i++) {
- if(a[i] !== undefined) {
- return a[i];
- }
- }
+export function validateColor(hex: string) {
+ hex = hex.replace('#', '');
+ return typeof hex === 'string'
+ && hex.length === 6
+ && !isNaN(Number('0x' + hex))
}
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index 9d02d6d..599bf3a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -29,12 +29,12 @@ export default class DrawJSPlugin extends Plugin {
id: "insert-drawing",
filter: ["Insert Drawing", "Add drawing", "whiteboard", "freehand", "graphics", "jsdraw"],
html: getMenuHTML("iconDraw", this.i18n.insertDrawing),
- callback: async (protyle: Protyle) => {
+ callback: (protyle: Protyle) => {
void this.analytics.sendEvent('create');
const fileID = generateRandomString();
const syncID = generateTimeString() + '-' + generateRandomString();
protyle.insert(getMarkdownBlock(fileID, syncID), true, false);
- (await EditorManager.create(fileID, this)).open(this);
+ new EditorManager(fileID, this.config.getDefaultEditorOptions()).open(this);
}
}];
@@ -43,10 +43,10 @@ export default class DrawJSPlugin extends Plugin {
if (ids === null) return;
e.detail.menu.addItem({
icon: "iconDraw",
- label: this.i18n.editDrawing,
- click: async () => {
+ label: "Edit with js-draw",
+ click: () => {
void this.analytics.sendEvent('edit');
- (await EditorManager.create(ids.fileID, this)).open(this);
+ new EditorManager(ids.fileID, this.config.getDefaultEditorOptions()).open(this);
}
})
})