mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
Compare commits
15 Commits
1.7.15
...
colormaste
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0bb5a00fb | ||
|
|
1aac4ffdf3 | ||
|
|
64fd43abb8 | ||
|
|
31ae51a421 | ||
|
|
0d879b7a7e | ||
|
|
d8166bbf8c | ||
|
|
82bde38a4b | ||
|
|
36b679434f | ||
|
|
6fa90662b3 | ||
|
|
7f45dad610 | ||
|
|
0e1ee0dde2 | ||
|
|
6c7b63cbdf | ||
|
|
bca7010394 | ||
|
|
3565a5bf94 | ||
|
|
f85fc124d9 |
@@ -21,11 +21,12 @@ Please upgrade to Obsidian v0.12.19 or higher to get the latest release.
|
||||
|
||||
|
||||
# Key features
|
||||
- The plugin aims to integrate Excalidraw seamlessly into Obsidian including Command Palette actions, File Explorer features, Option Menu commands, and the Ribbon Button.
|
||||
- The plugin integrates Excalidraw seamlessly into Obsidian including Command Palette actions, File Explorer features, Option Menu commands, and the Ribbon Button.
|
||||
- <kbd>CTRL/CMD+Click</kbd> on the ribbon button, or in the file explorer to create / open drawings in a new pane.
|
||||
- Settings will allow you to customize Excalidraw to your needs:
|
||||
- Default folder for new drawings and define custom filename pattern for new drawings.
|
||||
- Template for new drawings. The template will restore stroke properties. This means you can set up defaults in your template for stroke color, stroke width, opacity, font family, font size, fill style, stroke style, etc. This also applies to ExcalidrawAutomate.
|
||||
- Via the template you can customize the color palette used by Excalidraw. Switch to Markdown view. Scroll down to the bottom of the file and find `"AppState": {`. Find `"customColorPalette": {` at the end of the AppState section. You may specify the 3 palettes used in Excalidraw by adding any or all of the following 3 variables: `"canvasBackground":[], "elementBackground":[], "elementStroke": []`. Add a comma separated list of valid HTML colors (e.g. `#FF0000` for red) in the array for each of the variables. See my videos above for further help.
|
||||
- If portability is important to you: Auto-export SVG and/or PNG files including keep-in-sync feature so you can embed SVG/PNG into your documents instead of embedding excalidraw files. You can override export settings for an individual file by adding the `excalidraw-autoexport` frontmatter key. Valid values for this key are `none`, `both`, `png` and `svg`.
|
||||
- Specify the default width of embedded drawings.
|
||||
- Compatibility features to auto-export and keep in sync markdown excalidraw files and legacy .excalidraw files.
|
||||
@@ -76,7 +77,7 @@ Please upgrade to Obsidian v0.12.19 or higher to get the latest release.
|
||||
- Frontmatter tags to customize image export at a file level [519](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/519). If these keys are present they will override the default excalidraw embed and export settings.
|
||||
- `excalidraw-export-transparent: true`: true == Transparent / false == with background.
|
||||
- `excalidraw-export-dark`: true == Dark mode / false == light mode.
|
||||
- `excalidraw-export-svgpadding`: This only affects export to SVG. Specify the export padding for the image
|
||||
- `excalidraw-export-padding`: Specify the export padding for the image
|
||||
- `excalidraw-export-pngscale`: This only affects export to PNG. Specify the export scale for the image. The typical range is between 0.5 and 5, but you can experiment with other values as well.
|
||||
- Embed complete markdown files into your drawings
|
||||
- Drag from the desired file from the Obsidian file explorer and hold down <kbd>CTRL/CMD</kbd> while dropping the file onto the canvas.
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
Here's the interface implemented by ExcalidrawAutomate:
|
||||
|
||||
```typescript
|
||||
export interface ExcalidrawAutomate {
|
||||
export declare class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
plugin: ExcalidrawPlugin;
|
||||
elementsDict: {}; //contains the ExcalidrawElements currently edited in Automate indexed by el.id
|
||||
imagesDict: {}; //the images files including DataURL, indexed by fileId
|
||||
targetView: ExcalidrawView = null; //the view currently edited
|
||||
elementsDict: {[key:string]:any}; //contains the ExcalidrawElements currently edited in Automate indexed by el.id
|
||||
imagesDict: {[key: FileId]: any}; //the images files including DataURL, indexed by fileId
|
||||
mostRecentMarkdownSVG:SVGSVGElement = null; //Markdown renderer will drop a copy of the most recent SVG here for debugging purposes
|
||||
style: {
|
||||
strokeColor: string; //https://www.w3schools.com/colors/default.asp
|
||||
backgroundColor: string;
|
||||
@@ -29,178 +31,521 @@ export interface ExcalidrawAutomate {
|
||||
viewBackgroundColor: string;
|
||||
gridSize: number;
|
||||
};
|
||||
setFillStyle(val: number): void; //0:"hachure", 1:"cross-hatch" 2:"solid"
|
||||
setStrokeStyle(val: number): void; //0:"solid", 1:"dashed", 2:"dotted"
|
||||
setStrokeSharpness(val: number): void; //0:"round", 1:"sharp"
|
||||
setFontFamily(val: number): void; //1: Virgil, 2:Helvetica, 3:Cascadia
|
||||
setTheme(val: number): void; //0:"light", 1:"dark"
|
||||
addToGroup(objectIds: []): string;
|
||||
toClipboard(templatePath?: string): void;
|
||||
getElements(): ExcalidrawElement[]; //get all elements from ExcalidrawAutomate elementsDict
|
||||
getElement(id: string): ExcalidrawElement; //get single element from ExcalidrawAutomate elementsDict
|
||||
create(params?: {
|
||||
//create a drawing and save it to filename
|
||||
filename?: string; //if null: default filename as defined in Excalidraw settings
|
||||
foldername?: string; //if null: default folder as defined in Excalidraw settings
|
||||
templatePath?: string;
|
||||
onNewPane?: boolean;
|
||||
frontmatterKeys?: {
|
||||
"excalidraw-plugin"?: "raw" | "parsed";
|
||||
"excalidraw-link-prefix"?: string;
|
||||
"excalidraw-link-brackets"?: boolean;
|
||||
"excalidraw-url-prefix"?: string;
|
||||
constructor(plugin: ExcalidrawPlugin, view?: ExcalidrawView);
|
||||
/**
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
getAPI(view?: ExcalidrawView): ExcalidrawAutomate;
|
||||
/**
|
||||
* @param val //0:"hachure", 1:"cross-hatch" 2:"solid"
|
||||
* @returns
|
||||
*/
|
||||
setFillStyle(val: number): "hachure" | "cross-hatch" | "solid";
|
||||
/**
|
||||
* @param val //0:"solid", 1:"dashed", 2:"dotted"
|
||||
* @returns
|
||||
*/
|
||||
setStrokeStyle(val: number): "solid" | "dashed" | "dotted";
|
||||
/**
|
||||
* @param val //0:"round", 1:"sharp"
|
||||
* @returns
|
||||
*/
|
||||
setStrokeSharpness(val: number): "round" | "sharp";
|
||||
/**
|
||||
* @param val //1: Virgil, 2:Helvetica, 3:Cascadia
|
||||
* @returns
|
||||
*/
|
||||
setFontFamily(val: number): "Virgil, Segoe UI Emoji" | "Helvetica, Segoe UI Emoji" | "Cascadia, Segoe UI Emoji" | "LocalFont";
|
||||
/**
|
||||
* @param val //0:"light", 1:"dark"
|
||||
* @returns
|
||||
*/
|
||||
setTheme(val: number): "light" | "dark";
|
||||
/**
|
||||
* @param objectIds
|
||||
* @returns
|
||||
*/
|
||||
addToGroup(objectIds: string[]): string;
|
||||
/**
|
||||
* @param templatePath
|
||||
*/
|
||||
toClipboard(templatePath?: string): Promise<void>;
|
||||
/**
|
||||
* get all elements from ExcalidrawAutomate elementsDict
|
||||
* @returns elements from elemenetsDict
|
||||
*/
|
||||
getElements(): ExcalidrawElement[];
|
||||
/**
|
||||
* get single element from ExcalidrawAutomate elementsDict
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
getElement(id: string): ExcalidrawElement;
|
||||
/**
|
||||
* create a drawing and save it to filename
|
||||
* @param params
|
||||
* filename: if null, default filename as defined in Excalidraw settings
|
||||
* foldername: if null, default folder as defined in Excalidraw settings
|
||||
* @returns
|
||||
*/
|
||||
create(params?: {
|
||||
filename?: string;
|
||||
foldername?: string;
|
||||
templatePath?: string;
|
||||
onNewPane?: boolean;
|
||||
frontmatterKeys?: {
|
||||
"excalidraw-plugin"?: "raw" | "parsed";
|
||||
"excalidraw-link-prefix"?: string;
|
||||
"excalidraw-link-brackets"?: boolean;
|
||||
"excalidraw-url-prefix"?: string;
|
||||
"excalidraw-export-transparent"?: boolean;
|
||||
"excalidraw-export-dark"?: boolean;
|
||||
"excalidraw-export-svgpadding"?: number;
|
||||
"excalidraw-export-pngscale"?: number;
|
||||
"excalidraw-default-mode"?: "view" | "zen";
|
||||
};
|
||||
}): Promise<string>;
|
||||
/**
|
||||
*
|
||||
* @param templatePath
|
||||
* @param embedFont
|
||||
* @param exportSettings use ExcalidrawAutomate.getExportSettings(boolean,boolean)
|
||||
* @param loader use ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
|
||||
* @param theme
|
||||
* @returns
|
||||
*/
|
||||
createSVG(templatePath?: string, embedFont?: boolean, exportSettings?: ExportSettings, loader?: EmbeddedFilesLoader, theme?: string, padding?: number): Promise<SVGSVGElement>;
|
||||
/**
|
||||
*
|
||||
* @param templatePath
|
||||
* @param scale
|
||||
* @param exportSettings use ExcalidrawAutomate.getExportSettings(boolean,boolean)
|
||||
* @param loader use ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
|
||||
* @param theme
|
||||
* @returns
|
||||
*/
|
||||
createPNG(templatePath?: string, scale?: number, exportSettings?: ExportSettings, loader?: EmbeddedFilesLoader, theme?: string, padding?: number): Promise<any>;
|
||||
/**
|
||||
*
|
||||
* @param text
|
||||
* @param lineLen
|
||||
* @returns
|
||||
*/
|
||||
wrapText(text: string, lineLen: number): string;
|
||||
private boxedElement;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns
|
||||
*/
|
||||
addRect(topX: number, topY: number, width: number, height: number): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns
|
||||
*/
|
||||
addDiamond(topX: number, topY: number, width: number, height: number): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns
|
||||
*/
|
||||
addEllipse(topX: number, topY: number, width: number, height: number): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns
|
||||
*/
|
||||
addBlob(topX: number, topY: number, width: number, height: number): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param text
|
||||
* @param formatting
|
||||
* box: if !null, text will be boxed
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
addText(topX: number, topY: number, text: string, formatting?: {
|
||||
wrapAt?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
textAlign?: string;
|
||||
box?: boolean | "box" | "blob" | "ellipse" | "diamond";
|
||||
boxPadding?: number;
|
||||
}, id?: string): string;
|
||||
/**
|
||||
*
|
||||
* @param points
|
||||
* @returns
|
||||
*/
|
||||
addLine(points: [[x: number, y: number]]): string;
|
||||
/**
|
||||
*
|
||||
* @param points
|
||||
* @param formatting
|
||||
* @returns
|
||||
*/
|
||||
addArrow(points: [x: number, y: number][], formatting?: {
|
||||
startArrowHead?: string;
|
||||
endArrowHead?: string;
|
||||
startObjectId?: string;
|
||||
endObjectId?: string;
|
||||
}): string;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param imageFile
|
||||
* @returns
|
||||
*/
|
||||
addImage(topX: number, topY: number, imageFile: TFile): Promise<string>;
|
||||
/**
|
||||
*
|
||||
* @param topX
|
||||
* @param topY
|
||||
* @param tex
|
||||
* @returns
|
||||
*/
|
||||
addLaTex(topX: number, topY: number, tex: string): Promise<string>;
|
||||
/**
|
||||
*
|
||||
* @param objectA
|
||||
* @param connectionA type ConnectionPoint = "top" | "bottom" | "left" | "right" | null
|
||||
* @param objectB
|
||||
* @param connectionB when passed null, Excalidraw will automatically decide
|
||||
* @param formatting
|
||||
* numberOfPoints: points on the line. Default is 0 ie. line will only have a start and end point
|
||||
* startArrowHead: "triangle"|"dot"|"arrow"|"bar"|null
|
||||
* endArrowHead: "triangle"|"dot"|"arrow"|"bar"|null
|
||||
* padding:
|
||||
* @returns
|
||||
*/
|
||||
connectObjects(objectA: string, connectionA: ConnectionPoint | null, objectB: string, connectionB: ConnectionPoint | null, formatting?: {
|
||||
numberOfPoints?: number;
|
||||
startArrowHead?: "triangle" | "dot" | "arrow" | "bar" | null;
|
||||
endArrowHead?: "triangle" | "dot" | "arrow" | "bar" | null;
|
||||
padding?: number;
|
||||
}): string;
|
||||
/**
|
||||
* Adds a text label to a line or arrow. Currently only works with a straight (2 point - start & end - line)
|
||||
* @param lineId id of the line or arrow object in elementsDict
|
||||
* @param label the label text
|
||||
* @returns undefined (if unsuccessful) or the id of the new text element
|
||||
*/
|
||||
addLabelToLine(lineId: string, label: string): string;
|
||||
/**
|
||||
* clear elementsDict and imagesDict only
|
||||
*/
|
||||
clear(): void;
|
||||
/**
|
||||
* clear() + reset all style values to default
|
||||
*/
|
||||
reset(): void;
|
||||
/**
|
||||
* returns true if MD file is an Excalidraw file
|
||||
* @param f
|
||||
* @returns
|
||||
*/
|
||||
isExcalidrawFile(f: TFile): boolean;
|
||||
/**
|
||||
*
|
||||
* @param view
|
||||
* @returns
|
||||
*/
|
||||
setView(view: ExcalidrawView | "first" | "active"): ExcalidrawView;
|
||||
/**
|
||||
*
|
||||
* @returns https://github.com/excalidraw/excalidraw/tree/master/src/packages/excalidraw#ref
|
||||
*/
|
||||
getExcalidrawAPI(): any;
|
||||
/**
|
||||
* get elements in View
|
||||
* @returns
|
||||
*/
|
||||
getViewElements(): ExcalidrawElement[];
|
||||
/**
|
||||
*
|
||||
* @param elToDelete
|
||||
* @returns
|
||||
*/
|
||||
deleteViewElements(elToDelete: ExcalidrawElement[]): boolean;
|
||||
/**
|
||||
* get the selected element in the view, if more are selected, get the first
|
||||
* @returns
|
||||
*/
|
||||
getViewSelectedElement(): any;
|
||||
/**
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
getViewSelectedElements(): any[];
|
||||
/**
|
||||
*
|
||||
* @param el
|
||||
* @returns TFile file handle for the image element
|
||||
*/
|
||||
getViewFileForImageElement(el: ExcalidrawElement): TFile | null;
|
||||
/**
|
||||
* copies elements from view to elementsDict for editing
|
||||
* @param elements
|
||||
*/
|
||||
copyViewElementsToEAforEditing(elements: ExcalidrawElement[]): void;
|
||||
/**
|
||||
*
|
||||
* @param forceViewMode
|
||||
* @returns
|
||||
*/
|
||||
viewToggleFullScreen(forceViewMode?: boolean): void;
|
||||
/**
|
||||
* connect an object to the selected element in the view
|
||||
* @param objectA ID of the element
|
||||
* @param connectionA
|
||||
* @param connectionB
|
||||
* @param formatting
|
||||
* @returns
|
||||
*/
|
||||
connectObjectWithViewSelectedElement(objectA: string, connectionA: ConnectionPoint | null, connectionB: ConnectionPoint | null, formatting?: {
|
||||
numberOfPoints?: number;
|
||||
startArrowHead?: "triangle" | "dot" | "arrow" | "bar" | null;
|
||||
endArrowHead?: "triangle" | "dot" | "arrow" | "bar" | null;
|
||||
padding?: number;
|
||||
}): boolean;
|
||||
/**
|
||||
* Adds elements from elementsDict to the current view
|
||||
* @param repositionToCursor default is false
|
||||
* @param save default is true
|
||||
* @param newElementsOnTop controls whether elements created with ExcalidrawAutomate
|
||||
* are added at the bottom of the stack or the top of the stack of elements already in the view
|
||||
* Note that elements copied to the view with copyViewElementsToEAforEditing retain their
|
||||
* position in the stack of elements in the view even if modified using EA
|
||||
* default is false, i.e. the new elements get to the bottom of the stack
|
||||
* @returns
|
||||
*/
|
||||
addElementsToView(repositionToCursor?: boolean, save?: boolean, newElementsOnTop?: boolean): Promise<boolean>;
|
||||
/**
|
||||
* Register instance of EA to use for hooks with TargetView
|
||||
* By default ExcalidrawViews will check window.ExcalidrawAutomate for event hooks.
|
||||
* Using this event you can set a different instance of Excalidraw Automate for hooks
|
||||
* @returns true if successful
|
||||
*/
|
||||
registerThisAsViewEA(): boolean;
|
||||
/**
|
||||
* Sets the targetView EA to window.ExcalidrawAutomate
|
||||
* @returns true if successful
|
||||
*/
|
||||
deregisterThisAsViewEA(): boolean;
|
||||
/**
|
||||
* If set, this callback is triggered when the user closes an Excalidraw view.
|
||||
*/
|
||||
onViewUnloadHook: (view: ExcalidrawView) => void;
|
||||
/**
|
||||
* If set, this callback is triggered, when the user changes the view mode.
|
||||
* You can use this callback in case you want to do something additional when the user switches to view mode and back.
|
||||
*/
|
||||
onViewModeChangeHook: (isViewModeEnabled: boolean, view: ExcalidrawView, ea: ExcalidrawAutomate) => void;
|
||||
/**
|
||||
* If set, this callback is triggered, when the user hovers a link in the scene.
|
||||
* You can use this callback in case you want to do something additional when the onLinkHover event occurs.
|
||||
* This callback must return a boolean value.
|
||||
* In case you want to prevent the excalidraw onLinkHover action you must return false, it will stop the native excalidraw onLinkHover management flow.
|
||||
*/
|
||||
onLinkHoverHook: (element: NonDeletedExcalidrawElement, linkText: string, view: ExcalidrawView, ea: ExcalidrawAutomate) => boolean;
|
||||
/**
|
||||
* If set, this callback is triggered, when the user clicks a link in the scene.
|
||||
* You can use this callback in case you want to do something additional when the onLinkClick event occurs.
|
||||
* This callback must return a boolean value.
|
||||
* In case you want to prevent the excalidraw onLinkClick action you must return false, it will stop the native excalidraw onLinkClick management flow.
|
||||
*/
|
||||
onLinkClickHook: (element: ExcalidrawElement, linkText: string, event: MouseEvent, view: ExcalidrawView, ea: ExcalidrawAutomate) => boolean;
|
||||
/**
|
||||
* If set, this callback is triggered, when Excalidraw receives an onDrop event.
|
||||
* You can use this callback in case you want to do something additional when the onDrop event occurs.
|
||||
* This callback must return a boolean value.
|
||||
* In case you want to prevent the excalidraw onDrop action you must return false, it will stop the native excalidraw onDrop management flow.
|
||||
*/
|
||||
onDropHook: (data: {
|
||||
ea: ExcalidrawAutomate;
|
||||
event: React.DragEvent<HTMLDivElement>;
|
||||
draggable: any;
|
||||
type: "file" | "text" | "unknown";
|
||||
payload: {
|
||||
files: TFile[];
|
||||
text: string;
|
||||
};
|
||||
excalidrawFile: TFile;
|
||||
view: ExcalidrawView;
|
||||
pointerPosition: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
}) => boolean;
|
||||
/**
|
||||
* utility function to generate EmbeddedFilesLoader object
|
||||
* @param isDark
|
||||
* @returns
|
||||
*/
|
||||
getEmbeddedFilesLoader(isDark?: boolean): EmbeddedFilesLoader;
|
||||
/**
|
||||
* utility function to generate ExportSettings object
|
||||
* @param withBackground
|
||||
* @param withTheme
|
||||
* @returns
|
||||
*/
|
||||
getExportSettings(withBackground: boolean, withTheme: boolean): ExportSettings;
|
||||
/**
|
||||
* get bounding box of elements
|
||||
* bounding box is the box encapsulating all of the elements completely
|
||||
* @param elements
|
||||
* @returns
|
||||
*/
|
||||
getBoundingBox(elements: ExcalidrawElement[]): {
|
||||
topX: number;
|
||||
topY: number;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
}): Promise<string>;
|
||||
createSVG(
|
||||
templatePath?: string,
|
||||
embedFont?: boolean,
|
||||
exportSettings?: ExportSettings, //use ExcalidrawAutomate.getExportSettings(boolean,boolean)
|
||||
loader?: EmbeddedFilesLoader, //use ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
|
||||
theme?: string,
|
||||
): Promise<SVGSVGElement>;
|
||||
createPNG(
|
||||
templatePath?: string,
|
||||
scale?: number,
|
||||
exportSettings?: ExportSettings, //use ExcalidrawAutomate.getExportSettings(boolean,boolean)
|
||||
loader?: EmbeddedFilesLoader, //use ExcalidrawAutomate.getEmbeddedFilesLoader(boolean?)
|
||||
theme?: string,
|
||||
): Promise<any>;
|
||||
wrapText(text: string, lineLen: number): string;
|
||||
addRect(topX: number, topY: number, width: number, height: number): string;
|
||||
addDiamond(topX: number, topY: number, width: number, height: number): string;
|
||||
addEllipse(topX: number, topY: number, width: number, height: number): string;
|
||||
addBlob(topX: number, topY: number, width: number, height: number): string;
|
||||
addText(
|
||||
topX: number,
|
||||
topY: number,
|
||||
text: string,
|
||||
formatting?: {
|
||||
wrapAt?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
textAlign?: string;
|
||||
box?: boolean | "box" | "blob" | "ellipse" | "diamond"; //if !null, text will be boxed
|
||||
boxPadding?: number;
|
||||
},
|
||||
id?: string,
|
||||
): string;
|
||||
addLine(points: [[x: number, y: number]]): string;
|
||||
addArrow(
|
||||
points: [[x: number, y: number]],
|
||||
formatting?: {
|
||||
startArrowHead?: string;
|
||||
endArrowHead?: string;
|
||||
startObjectId?: string;
|
||||
endObjectId?: string;
|
||||
},
|
||||
): string;
|
||||
addImage(topX: number, topY: number, imageFile: TFile): Promise<string>;
|
||||
addLaTex(topX: number, topY: number, tex: string): Promise<string>;
|
||||
connectObjects(
|
||||
objectA: string,
|
||||
connectionA: ConnectionPoint, //type ConnectionPoint = "top" | "bottom" | "left" | "right" | null
|
||||
objectB: string,
|
||||
connectionB: ConnectionPoint, //when passed null, Excalidraw will automatically decide
|
||||
formatting?: {
|
||||
numberOfPoints?: number; //points on the line. Default is 0 ie. line will only have a start and end point
|
||||
startArrowHead?: string; //"triangle"|"dot"|"arrow"|"bar"|null
|
||||
endArrowHead?: string; //"triangle"|"dot"|"arrow"|"bar"|null
|
||||
padding?: number;
|
||||
},
|
||||
): void;
|
||||
clear(): void; //clear elementsDict and imagesDict only
|
||||
reset(): void; //clear() + reset all style values to default
|
||||
isExcalidrawFile(f: TFile): boolean; //returns true if MD file is an Excalidraw file
|
||||
//view manipulation
|
||||
targetView: ExcalidrawView; //the view currently edited
|
||||
setView(view: ExcalidrawView | "first" | "active"): ExcalidrawView;
|
||||
getExcalidrawAPI(): any; //https://github.com/excalidraw/excalidraw/tree/master/src/packages/excalidraw#ref
|
||||
getViewElements(): ExcalidrawElement[]; //get elements in View
|
||||
deleteViewElements(el: ExcalidrawElement[]): boolean;
|
||||
getViewSelectedElement(): ExcalidrawElement; //get the selected element in the view, if more are selected, get the first
|
||||
getViewSelectedElements(): ExcalidrawElement[];
|
||||
getViewFileForImageElement(el: ExcalidrawElement): TFile | null; //Returns the TFile file handle for the image element
|
||||
copyViewElementsToEAforEditing(elements: ExcalidrawElement[]): void; //copies elements from view to elementsDict for editing
|
||||
viewToggleFullScreen(forceViewMode?: boolean): void;
|
||||
connectObjectWithViewSelectedElement( //connect an object to the selected element in the view
|
||||
objectA: string, //see connectObjects
|
||||
connectionA: ConnectionPoint,
|
||||
connectionB: ConnectionPoint,
|
||||
formatting?: {
|
||||
numberOfPoints?: number;
|
||||
startArrowHead?: string;
|
||||
endArrowHead?: string;
|
||||
padding?: number;
|
||||
},
|
||||
): boolean;
|
||||
addElementsToView( //Adds elements from elementsDict to the current view
|
||||
repositionToCursor?: boolean, //default is false
|
||||
save?: boolean, //default is true
|
||||
//newElementsOnTop controls whether elements created with ExcalidrawAutomate
|
||||
//are added at the bottom of the stack or the top of the stack of elements already in the view
|
||||
//Note that elements copied to the view with copyViewElementsToEAforEditing retain their
|
||||
//position in the stack of elements in the view even if modified using EA
|
||||
newElementsOnTop?: boolean, //default is false, i.e. the new elements get to the bottom of the stack
|
||||
): Promise<boolean>;
|
||||
onDropHook(data: {
|
||||
//if set Excalidraw will call this function onDrop events
|
||||
ea: ExcalidrawAutomate;
|
||||
event: React.DragEvent<HTMLDivElement>;
|
||||
draggable: any; //Obsidian draggable object
|
||||
type: "file" | "text" | "unknown";
|
||||
payload: {
|
||||
files: TFile[]; //TFile[] array of dropped files
|
||||
text: string; //string
|
||||
/**
|
||||
* elements grouped by the highest level groups
|
||||
* @param elements
|
||||
* @returns
|
||||
*/
|
||||
getMaximumGroups(elements: ExcalidrawElement[]): ExcalidrawElement[][];
|
||||
/**
|
||||
* gets the largest element from a group. useful when a text element is grouped with a box, and you want to connect an arrow to the box
|
||||
* @param elements
|
||||
* @returns
|
||||
*/
|
||||
getLargestElement(elements: ExcalidrawElement[]): ExcalidrawElement;
|
||||
/**
|
||||
* Gets the groupId for the group that contains all the elements, or null if such a group does not exist
|
||||
* @param elements
|
||||
* @returns null or the groupId
|
||||
*/
|
||||
getCommonGroupForElements(elements: ExcalidrawElement[]): string;
|
||||
/**
|
||||
* Gets all the elements from elements[] that share one or more groupIds with element.
|
||||
* @param element
|
||||
* @param elements - typically all the non-deleted elements in the scene
|
||||
* @returns
|
||||
*/
|
||||
getElementsInTheSameGroupWithElement(element: ExcalidrawElement, elements: ExcalidrawElement[]): ExcalidrawElement[];
|
||||
/**
|
||||
* @param element
|
||||
* @param a
|
||||
* @param b
|
||||
* @param gap
|
||||
* @returns 2 or 0 intersection points between line going through `a` and `b`
|
||||
* and the `element`, in ascending order of distance from `a`.
|
||||
*/
|
||||
intersectElementWithLine(element: ExcalidrawBindableElement, a: readonly [number, number], b: readonly [number, number], gap?: number): Point[];
|
||||
/**
|
||||
* See OCR plugin for example on how to use scriptSettings
|
||||
* Set by the ScriptEngine
|
||||
*/
|
||||
activeScript: string;
|
||||
/**
|
||||
*
|
||||
* @returns script settings. Saves settings in plugin settings, under the activeScript key
|
||||
*/
|
||||
getScriptSettings(): {};
|
||||
/**
|
||||
* sets script settings.
|
||||
* @param settings
|
||||
* @returns
|
||||
*/
|
||||
setScriptSettings(settings: any): Promise<void>;
|
||||
/**
|
||||
* Open a file in a new workspaceleaf or reuse an existing adjacent leaf depending on Excalidraw Plugin Settings
|
||||
* @param file
|
||||
* @returns
|
||||
*/
|
||||
openFileInNewOrAdjacentLeaf(file: TFile): WorkspaceLeaf;
|
||||
/**
|
||||
* measure text size based on current style settings
|
||||
* @param text
|
||||
* @returns
|
||||
*/
|
||||
measureText(text: string): {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
excalidrawFile: TFile; //the file receiving the drop event
|
||||
view: ExcalidrawView; //the excalidraw view receiving the drop
|
||||
pointerPosition: { x: number; y: number }; //the pointer position on canvas at the time of drop
|
||||
}): boolean; //a return of true will stop the default onDrop processing in Excalidraw
|
||||
mostRecentMarkdownSVG: SVGSVGElement; //Markdown renderer will drop a copy of the most recent SVG here for debugging purposes
|
||||
getEmbeddedFilesLoader(isDark?: boolean): EmbeddedFilesLoader; //utility function to generate EmbeddedFilesLoader object
|
||||
getExportSettings( //utility function to generate ExportSettings object
|
||||
withBackground: boolean,
|
||||
withTheme: boolean,
|
||||
): ExportSettings;
|
||||
getBoundingBox(elements: ExcalidrawElement[]): {
|
||||
//get bounding box of elements
|
||||
topX: number; //bounding box is the box encapsulating all of the elements completely
|
||||
topY: number;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
//elements grouped by the highest level groups
|
||||
getMaximumGroups(elements: ExcalidrawElement[]): ExcalidrawElement[][];
|
||||
//gets the largest element from a group. useful when a text element is grouped with a box, and you want to connect an arrow to the box
|
||||
getLargestElement(elements: ExcalidrawElement[]): ExcalidrawElement;
|
||||
// Returns 2 or 0 intersection points between line going through `a` and `b`
|
||||
// and the `element`, in ascending order of distance from `a`.
|
||||
intersectElementWithLine(
|
||||
element: ExcalidrawBindableElement,
|
||||
a: readonly [number, number],
|
||||
b: readonly [number, number],
|
||||
gap?: number, //if given, element is inflated by this value
|
||||
): Point[];
|
||||
|
||||
//See OCR plugin for example on how to use scriptSettings
|
||||
activeScript: string; //Set automatically by the ScriptEngine
|
||||
getScriptSettings(): {}; //Returns script settings. Saves settings in plugin settings, under the activeScript key
|
||||
setScriptSettings(settings: any): Promise<void>; //sets script settings.
|
||||
openFileInNewOrAdjacentLeaf(file: TFile): WorkspaceLeaf; //Open a file in a new workspaceleaf or reuse an existing adjacent leaf depending on Excalidraw Plugin Settings
|
||||
measureText(text: string): { width: number; height: number }; //measure text size based on current style settings
|
||||
//verifyMinimumPluginVersion returns true if plugin version is >= than required
|
||||
//recommended use:
|
||||
//if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.5.20")) {new Notice("message");return;}
|
||||
verifyMinimumPluginVersion(requiredVersion: string): boolean;
|
||||
selectElementsInView(elements: ExcalidrawElement[]): void; //sets selection in view
|
||||
generateElementId(): string; //returns an 8 character long random id
|
||||
cloneElement(element: ExcalidrawElement): ExcalidrawElement; //Returns a clone of the element with a new id
|
||||
moveViewElementToZIndex(elementId:number, newZIndex:number): void; //Moves the element to a specific position in the z-index
|
||||
hexStringToRgb(color: string):number[];
|
||||
rgbToHexString(color: number[]):string;
|
||||
hslToRgb(color: number[]):number[];
|
||||
rgbToHsl(color:number[]):number[];
|
||||
colorNameToHex(color:string):string;
|
||||
}
|
||||
```
|
||||
/**
|
||||
* verifyMinimumPluginVersion returns true if plugin version is >= than required
|
||||
* recommended use:
|
||||
* if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.5.20")) {new Notice("message");return;}
|
||||
* @param requiredVersion
|
||||
* @returns
|
||||
*/
|
||||
verifyMinimumPluginVersion(requiredVersion: string): boolean;
|
||||
/**
|
||||
* Check if view is instance of ExcalidrawView
|
||||
* @param view
|
||||
* @returns
|
||||
*/
|
||||
isExcalidrawView(view: any): boolean;
|
||||
/**
|
||||
* sets selection in view
|
||||
* @param elements
|
||||
* @returns
|
||||
*/
|
||||
selectElementsInView(elements: ExcalidrawElement[]): void;
|
||||
/**
|
||||
* @returns an 8 character long random id
|
||||
*/
|
||||
generateElementId(): string;
|
||||
/**
|
||||
* @param element
|
||||
* @returns a clone of the element with a new id
|
||||
*/
|
||||
cloneElement(element: ExcalidrawElement): ExcalidrawElement;
|
||||
/**
|
||||
* Moves the element to a specific position in the z-index
|
||||
*/
|
||||
moveViewElementToZIndex(elementId: number, newZIndex: number): void;
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
hexStringToRgb(color: string): number[];
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
rgbToHexString(color: number[]): string;
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
hslToRgb(color: number[]): number[];
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
rgbToHsl(color: number[]): number[];
|
||||
/**
|
||||
*
|
||||
* @param color
|
||||
* @returns
|
||||
*/
|
||||
colorNameToHex(color: string): string;
|
||||
}```
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ settings = ea.getScriptSettings();
|
||||
if(!settings["Border color"]) {
|
||||
settings = {
|
||||
"Border color" : {
|
||||
value: "#000000",
|
||||
value: "transparent",
|
||||
description: "Any legal HTML color (#000000, rgb, color-name, etc.). Set to 'transparent' for transparent color."
|
||||
},
|
||||
"Background color" : {
|
||||
|
||||
@@ -3,13 +3,28 @@ Click to watch the intro video:
|
||||
|
||||
[](https://youtu.be/hePJcObHIso)
|
||||
|
||||
> **Warning**
|
||||
> There is an easier way to install/manage scripts than what is shown in this video
|
||||
|
||||
See the [Excalidraw Script Engine](https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html) documentation for more details.
|
||||
|
||||
## How to install scripts into your Obsidian Vault
|
||||
To install one of the built-in scripts:
|
||||
- Open up an excalidraw drawing in Obsidian
|
||||
- In the pane dropdown menu select "Install or update Excalidraw Scripts"
|
||||
- Click on one of the available scripts
|
||||
- Click on "Install this script" (note if the script is already installed you will instead see an option to update it)
|
||||
- Restart Obsidian so the script will be picked up
|
||||
|
||||
Note: By default this will install the script into your vault in the `Excalidraw/Scripts/Downloaded` folder
|
||||
|
||||
<details><summary>Manual installation of scripts</summary>
|
||||
|
||||
Open the script you are interested in and save it to your Obsidian Vault including the first line `/*`, or open it in "Raw" and copy the entire contents to Obsidian.
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
## List of available scripts
|
||||
|Title|Description|Icon|Contributor|
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "1.7.15",
|
||||
"version": "1.7.18",
|
||||
"minAppVersion": "0.15.6",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -18,14 +18,15 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/lz-string": "^1.3.34",
|
||||
"@zsviczian/excalidraw": "0.12.0-obsidian-5",
|
||||
"@zsviczian/excalidraw": "0.12.0-obsidian-8",
|
||||
"clsx": "^1.1.1",
|
||||
"lz-string": "^1.4.4",
|
||||
"monkey-around": "^2.3.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "^5.0.1",
|
||||
"roughjs": "^4.5.2"
|
||||
"roughjs": "^4.5.2",
|
||||
"colormaster": "1.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.16.12",
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
getFontDataURL,
|
||||
getImageSize,
|
||||
getLinkParts,
|
||||
getSVGPadding,
|
||||
getExportPadding,
|
||||
getWithBackground,
|
||||
hasExportBackground,
|
||||
hasExportTheme,
|
||||
@@ -252,7 +252,7 @@ export class EmbeddedFilesLoader {
|
||||
[],
|
||||
this.plugin,
|
||||
depth+1,
|
||||
getSVGPadding(this.plugin, file),
|
||||
getExportPadding(this.plugin, file),
|
||||
);
|
||||
//https://stackoverflow.com/questions/51154171/remove-css-filter-on-child-elements
|
||||
const imageList = svg.querySelectorAll(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -588,6 +588,7 @@ export class ExcalidrawData {
|
||||
}
|
||||
|
||||
public async setTextMode(textMode: TextMode, forceupdate: boolean = false) {
|
||||
if(!this.scene) return;
|
||||
this.textMode = textMode;
|
||||
await this.updateSceneTextElements(forceupdate);
|
||||
}
|
||||
@@ -739,7 +740,13 @@ export class ExcalidrawData {
|
||||
this.textElements.set(id, { raw, parsed: null, wrapAt });
|
||||
this.parseasync(id, raw, wrapAt);
|
||||
}
|
||||
} else if (!this.textElements.has(te.id)) {
|
||||
const raw = te.rawText && te.rawText !== "" ? te.rawText : te.text; //this is for compatibility with drawings created before the rawText change on ExcalidrawTextElement
|
||||
const wrapAt = estimateMaxLineLen(te.text, te.originalText);
|
||||
this.textElements.set(id, { raw, parsed: null, wrapAt });
|
||||
this.parseasync(id, raw, wrapAt);
|
||||
}
|
||||
|
||||
}
|
||||
if (dirty) {
|
||||
//reload scene json in case it has changed
|
||||
@@ -781,11 +788,14 @@ export class ExcalidrawData {
|
||||
this.textElements.delete(key); //if no longer in the scene, delete the text element
|
||||
} else {
|
||||
const text = await this.getText(key, false);
|
||||
const raw = this.scene.prevTextMode === TextMode.parsed
|
||||
? el[0].rawText
|
||||
: (el[0].originalText ?? el[0].text);
|
||||
if (text !== (el[0].originalText ?? el[0].text)) {
|
||||
const wrapAt = estimateMaxLineLen(el[0].text, el[0].originalText);
|
||||
this.textElements.set(key, {
|
||||
raw: el[0].originalText ?? el[0].text,
|
||||
parsed: (await this.parse(el[0].originalText ?? el[0].text)).parsed,
|
||||
raw,
|
||||
parsed: (await this.parse(raw)).parsed,
|
||||
wrapAt,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ import {
|
||||
LOCAL_PROTOCOL,
|
||||
} from "./Constants";
|
||||
import ExcalidrawPlugin from "./main";
|
||||
import { repositionElementsToCursor, ExcalidrawAutomate, getTextElementsMatchingQuery } from "./ExcalidrawAutomate";
|
||||
import { repositionElementsToCursor, ExcalidrawAutomate, getTextElementsMatchingQuery, cloneElement } from "./ExcalidrawAutomate";
|
||||
import { t } from "./lang/helpers";
|
||||
import {
|
||||
ExcalidrawData,
|
||||
@@ -68,7 +68,7 @@ import {
|
||||
getPNG,
|
||||
getPNGScale,
|
||||
getSVG,
|
||||
getSVGPadding,
|
||||
getExportPadding,
|
||||
getWithBackground,
|
||||
hasExportTheme,
|
||||
isVersionNewerThanOther,
|
||||
@@ -92,14 +92,10 @@ import { ObsidianMenu } from "./menu/ObsidianMenu";
|
||||
import { ToolsPanel } from "./menu/ToolsPanel";
|
||||
import { ScriptEngine } from "./Scripts";
|
||||
import { getTextElementAtPointer, getImageElementAtPointer, getElementWithLinkAtPointer } from "./utils/GetElementAtPointer";
|
||||
import { execArgv } from "process";
|
||||
import { findLastIndex } from "@zsviczian/excalidraw/types/utils";
|
||||
import { fileOpen } from "@zsviczian/excalidraw/types/data/filesystem";
|
||||
|
||||
|
||||
export enum TextMode {
|
||||
parsed,
|
||||
raw,
|
||||
parsed = "parsed",
|
||||
raw = "raw",
|
||||
}
|
||||
|
||||
interface WorkspaceItemExt extends WorkspaceItem {
|
||||
@@ -256,6 +252,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
public textMode: TextMode = TextMode.raw;
|
||||
private textIsParsed_Element: HTMLElement;
|
||||
private textIsRaw_Element: HTMLElement;
|
||||
private linkAction_Element: HTMLElement;
|
||||
public compatibilityMode: boolean = false;
|
||||
private obsidianMenu: ObsidianMenu;
|
||||
|
||||
@@ -344,7 +341,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
);
|
||||
}
|
||||
|
||||
public async svg(scene: any): Promise<SVGSVGElement> {
|
||||
public async svg(scene: any, theme?:string): Promise<SVGSVGElement> {
|
||||
const exportSettings: ExportSettings = {
|
||||
withBackground: getWithBackground(this.plugin, this.file),
|
||||
withTheme: true,
|
||||
@@ -355,12 +352,12 @@ export default class ExcalidrawView extends TextFileView {
|
||||
...{
|
||||
appState: {
|
||||
...scene.appState,
|
||||
theme: getExportTheme(this.plugin, this.file, scene.appState.theme),
|
||||
theme: theme ?? getExportTheme(this.plugin, this.file, scene.appState.theme),
|
||||
},
|
||||
},
|
||||
},
|
||||
exportSettings,
|
||||
getSVGPadding(this.plugin, this.file),
|
||||
getExportPadding(this.plugin, this.file),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -371,25 +368,35 @@ export default class ExcalidrawView extends TextFileView {
|
||||
}
|
||||
scene = this.getScene();
|
||||
}
|
||||
const filepath = getIMGFilename(this.file.path, "svg"); //.substring(0,this.file.path.lastIndexOf(this.compatibilityMode ? '.excalidraw':'.md')) + '.svg';
|
||||
const file = app.vault.getAbstractFileByPath(normalizePath(filepath));
|
||||
|
||||
const svg = await this.svg(scene);
|
||||
if (!svg) {
|
||||
return;
|
||||
const exportImage = async (filepath:string, theme?:string) => {
|
||||
const file = app.vault.getAbstractFileByPath(normalizePath(filepath));
|
||||
|
||||
const svg = await this.svg(scene,theme);
|
||||
if (!svg) {
|
||||
return;
|
||||
}
|
||||
const serializer = new XMLSerializer();
|
||||
const svgString = serializer.serializeToString(
|
||||
embedFontsInSVG(svg, this.plugin),
|
||||
);
|
||||
if (file && file instanceof TFile) {
|
||||
await app.vault.modify(file, svgString);
|
||||
} else {
|
||||
await app.vault.create(filepath, svgString);
|
||||
}
|
||||
}
|
||||
const serializer = new XMLSerializer();
|
||||
const svgString = serializer.serializeToString(
|
||||
embedFontsInSVG(svg, this.plugin),
|
||||
);
|
||||
if (file && file instanceof TFile) {
|
||||
await app.vault.modify(file, svgString);
|
||||
|
||||
if(this.plugin.settings.autoExportLightAndDark) {
|
||||
await exportImage(getIMGFilename(this.file.path, "dark.svg"),"dark");
|
||||
await exportImage(getIMGFilename(this.file.path, "light.svg"),"light");
|
||||
} else {
|
||||
await app.vault.create(filepath, svgString);
|
||||
await exportImage(getIMGFilename(this.file.path, "svg"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async png(scene: any): Promise<Blob> {
|
||||
public async png(scene: any, theme?:string): Promise<Blob> {
|
||||
const exportSettings: ExportSettings = {
|
||||
withBackground: getWithBackground(this.plugin, this.file),
|
||||
withTheme: true,
|
||||
@@ -400,11 +407,12 @@ export default class ExcalidrawView extends TextFileView {
|
||||
...{
|
||||
appState: {
|
||||
...scene.appState,
|
||||
theme: getExportTheme(this.plugin, this.file, scene.appState.theme),
|
||||
theme: theme ?? getExportTheme(this.plugin, this.file, scene.appState.theme),
|
||||
},
|
||||
},
|
||||
},
|
||||
exportSettings,
|
||||
getExportPadding(this.plugin, this.file),
|
||||
getPNGScale(this.plugin, this.file),
|
||||
);
|
||||
}
|
||||
@@ -417,17 +425,25 @@ export default class ExcalidrawView extends TextFileView {
|
||||
scene = this.getScene();
|
||||
}
|
||||
|
||||
const filepath = getIMGFilename(this.file.path, "png"); //this.file.path.substring(0,this.file.path.lastIndexOf(this.compatibilityMode ? '.excalidraw':'.md')) + '.png';
|
||||
const file = app.vault.getAbstractFileByPath(normalizePath(filepath));
|
||||
const exportImage = async (filepath:string, theme?:string) => {
|
||||
const file = app.vault.getAbstractFileByPath(normalizePath(filepath));
|
||||
|
||||
const png = await this.png(scene);
|
||||
if (!png) {
|
||||
return;
|
||||
const png = await this.png(scene,theme);
|
||||
if (!png) {
|
||||
return;
|
||||
}
|
||||
if (file && file instanceof TFile) {
|
||||
await app.vault.modifyBinary(file, await png.arrayBuffer());
|
||||
} else {
|
||||
await app.vault.createBinary(filepath, await png.arrayBuffer());
|
||||
}
|
||||
}
|
||||
if (file && file instanceof TFile) {
|
||||
await app.vault.modifyBinary(file, await png.arrayBuffer());
|
||||
|
||||
if(this.plugin.settings.autoExportLightAndDark) {
|
||||
await exportImage(getIMGFilename(this.file.path, "dark.png"),"dark");
|
||||
await exportImage(getIMGFilename(this.file.path, "light.png"),"light");
|
||||
} else {
|
||||
await app.vault.createBinary(filepath, await png.arrayBuffer());
|
||||
await exportImage(getIMGFilename(this.file.path, "png"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1010,7 +1026,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
() => this.changeTextMode(TextMode.raw),
|
||||
);
|
||||
|
||||
this.addAction("link", t("OPEN_LINK"), (ev) =>
|
||||
this.linkAction_Element = this.addAction("link", t("OPEN_LINK"), (ev) =>
|
||||
this.handleLinkClick(this, ev),
|
||||
);
|
||||
|
||||
@@ -1148,7 +1164,12 @@ export default class ExcalidrawView extends TextFileView {
|
||||
});
|
||||
}
|
||||
|
||||
private prevTextMode: TextMode;
|
||||
private blockTextModeChange: boolean = false;
|
||||
public async changeTextMode(textMode: TextMode, reload: boolean = true) {
|
||||
if(this.compatibilityMode) return;
|
||||
if(this.blockTextModeChange) return;
|
||||
this.blockTextModeChange = true;
|
||||
this.textMode = textMode;
|
||||
if (textMode === TextMode.parsed) {
|
||||
this.textIsRaw_Element.hide();
|
||||
@@ -1160,15 +1181,17 @@ export default class ExcalidrawView extends TextFileView {
|
||||
if (this.toolsPanelRef && this.toolsPanelRef.current) {
|
||||
this.toolsPanelRef.current.setPreviewMode(textMode === TextMode.parsed);
|
||||
}
|
||||
if (reload) {
|
||||
await this.save(false, true);
|
||||
this.updateContainerSize();
|
||||
const api = this.excalidrawAPI;
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const api = this.excalidrawAPI;
|
||||
if (api && reload) {
|
||||
await this.save();
|
||||
this.preventAutozoom();
|
||||
await this.excalidrawData.loadData(this.data, this.file, this.textMode);
|
||||
this.excalidrawData.scene.appState.theme = api.getAppState().theme;
|
||||
await this.loadDrawing(false);
|
||||
api.history.clear(); //to avoid undo replacing links with parsed text
|
||||
}
|
||||
this.prevTextMode = this.textMode;
|
||||
this.blockTextModeChange = false;
|
||||
}
|
||||
|
||||
public setupAutosaveTimer() {
|
||||
@@ -1400,7 +1423,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
|
||||
private isLoaded: boolean = false;
|
||||
async setViewData(data: string, clear: boolean = false) {
|
||||
checkExcalidrawVersion(app);
|
||||
if(this.plugin.settings.showNewVersionNotification) checkExcalidrawVersion(app);
|
||||
this.isLoaded = false;
|
||||
if (clear) {
|
||||
this.clear();
|
||||
@@ -1413,12 +1436,15 @@ export default class ExcalidrawView extends TextFileView {
|
||||
if (this.compatibilityMode) {
|
||||
this.textIsRaw_Element.hide();
|
||||
this.textIsParsed_Element.hide();
|
||||
this.linkAction_Element.hide();
|
||||
this.textMode = TextMode.raw;
|
||||
await this.excalidrawData.loadLegacyData(data, this.file);
|
||||
if (!this.plugin.settings.compatibilityMode) {
|
||||
new Notice(t("COMPATIBILITY_MODE"), 4000);
|
||||
}
|
||||
this.excalidrawData.disableCompression = true;
|
||||
} else {
|
||||
this.linkAction_Element.show();
|
||||
this.excalidrawData.disableCompression = false;
|
||||
const textMode = getTextMode(data);
|
||||
this.changeTextMode(textMode, false);
|
||||
@@ -2400,11 +2426,13 @@ export default class ExcalidrawView extends TextFileView {
|
||||
gridSize: st.gridSize,
|
||||
colorPalette: st.colorPalette,
|
||||
},
|
||||
prevTextMode: this.prevTextMode,
|
||||
files,
|
||||
};
|
||||
};
|
||||
|
||||
this.refresh = () => {
|
||||
if(this.contentEl.clientWidth === 0 || this.contentEl.clientHeight === 0) return;
|
||||
const api = this.excalidrawAPI;
|
||||
if (!excalidrawRef?.current || !api) {
|
||||
return;
|
||||
@@ -3000,6 +3028,9 @@ export default class ExcalidrawView extends TextFileView {
|
||||
clearTimeout(this.isEditingTextResetTimer);
|
||||
this.isEditingTextResetTimer = null;
|
||||
this.semaphores.isEditingText = true; //to prevent autoresize on mobile when keyboard pops up
|
||||
if(this.compatibilityMode) {
|
||||
return textElement.originalText ?? textElement.text;
|
||||
}
|
||||
const raw = this.excalidrawData.getRawText(textElement.id);
|
||||
if (!raw) {
|
||||
return textElement.rawText;
|
||||
@@ -3016,6 +3047,23 @@ export default class ExcalidrawView extends TextFileView {
|
||||
if (!api) {
|
||||
return [null, null, null];
|
||||
}
|
||||
const FORBIDDEN_TEXT = `{"type":"excalidraw/clipboard","elements":[{"`;
|
||||
const WARNING = "PASTING EXCALIDRAW ELEMENTS AS A TEXT ELEMENT IS NOT ALLOWED";
|
||||
if(text.startsWith(FORBIDDEN_TEXT)) {
|
||||
setTimeout(async ()=>{
|
||||
const elements = this.excalidrawAPI.getSceneElements();
|
||||
const el = elements.filter((el:ExcalidrawElement)=>el.id === textElement.id);
|
||||
if(el.length === 1) {
|
||||
const clone = cloneElement(el[0]);
|
||||
clone.rawText = WARNING;
|
||||
elements[elements.indexOf(el[0])] = clone;
|
||||
this.excalidrawData.setTextElement(clone.id,WARNING,WARNING,()=>{});
|
||||
await this.updateScene({elements});
|
||||
api.history.clear();
|
||||
}
|
||||
});
|
||||
return [WARNING,WARNING,null];
|
||||
}
|
||||
this.semaphores.isEditingText = true;
|
||||
this.isEditingTextResetTimer = setTimeout(() => {
|
||||
this.semaphores.isEditingText = false;
|
||||
@@ -3045,14 +3093,26 @@ export default class ExcalidrawView extends TextFileView {
|
||||
textElement.id,
|
||||
text,
|
||||
originalText,
|
||||
async () => {
|
||||
await this.save(false);
|
||||
//save preventReload==false, it will reload and update container sizes
|
||||
async (wrappedParsedText:string, parsedText:string) => {
|
||||
//this callback function will only be invoked if quick parse fails, i.e. there is a transclusion in the raw text
|
||||
//thus I only check if TextMode.parsed, text is always != with parseResult
|
||||
if (this.textMode === TextMode.parsed) {
|
||||
api.history.clear();
|
||||
if(this.textMode === TextMode.raw) return;
|
||||
|
||||
const elements = this.excalidrawAPI.getSceneElements();
|
||||
const el = elements.filter((el:ExcalidrawElement)=>el.id === textElement.id);
|
||||
if(el.length === 1) {
|
||||
const clone = cloneElement(el[0]);
|
||||
this.excalidrawData.updateTextElement(
|
||||
clone,
|
||||
wrappedParsedText,
|
||||
parsedText,
|
||||
true
|
||||
);
|
||||
elements[elements.indexOf(el[0])] = clone;
|
||||
await this.updateScene({elements});
|
||||
if(clone.containerId) this.updateContainerSize(clone.containerId);
|
||||
}
|
||||
|
||||
api.history.clear();
|
||||
},
|
||||
);
|
||||
if (parseResultWrapped) {
|
||||
@@ -3272,6 +3332,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
}
|
||||
|
||||
private updateContainerSize(containerId?: string, delay: boolean = false) {
|
||||
//console.log("updateContainerSize", containerId);
|
||||
const api = this.excalidrawAPI;
|
||||
if (!api) {
|
||||
return;
|
||||
@@ -3309,7 +3370,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
return;
|
||||
}
|
||||
const maxZoom = this.plugin.settings.zoomToFitMaxLevel;
|
||||
const elements = api.getSceneElements();
|
||||
const elements = api.getSceneElements().filter((el:ExcalidrawElement)=>el.width<10000 && el.height<10000);
|
||||
if (delay) {
|
||||
//time for the DOM to render, I am sure there is a more elegant solution
|
||||
setTimeout(
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
getEmbeddedFilenameParts,
|
||||
getExportTheme,
|
||||
getQuickImagePreview,
|
||||
getSVGPadding,
|
||||
getExportPadding,
|
||||
getWithBackground,
|
||||
hasExportTheme,
|
||||
svgToBase64,
|
||||
@@ -165,7 +165,7 @@ const getIMG = async (
|
||||
[],
|
||||
plugin,
|
||||
0,
|
||||
getSVGPadding(plugin, file),
|
||||
getExportPadding(plugin, file),
|
||||
)
|
||||
).outerHTML;
|
||||
let svg: SVGSVGElement = null;
|
||||
|
||||
@@ -21,12 +21,14 @@ export const REG_BLOCK_REF_CLEAN =
|
||||
/[!"#$%&()*+,.:;<=>?@^`{|}~\/\[\]\\]/g; //https://discord.com/channels/686053708261228577/989603365606531104/1000128926619816048
|
||||
// /\+|\/|~|=|%|\(|\)|{|}|,|&|\.|\$|!|\?|;|\[|]|\^|#|\*|<|>|&|@|\||\\|"|:|\s/g;
|
||||
export const IMAGE_TYPES = ["jpeg", "jpg", "png", "gif", "svg"];
|
||||
export const EXPORT_TYPES = ["svg", "dark.svg", "light.svg", "png", "dark.png", "light.png"];
|
||||
export const MAX_IMAGE_SIZE = 500;
|
||||
export const FRONTMATTER_KEY = "excalidraw-plugin";
|
||||
export const FRONTMATTER_KEY_EXPORT_TRANSPARENT =
|
||||
"excalidraw-export-transparent";
|
||||
export const FRONTMATTER_KEY_EXPORT_DARK = "excalidraw-export-dark";
|
||||
export const FRONTMATTER_KEY_EXPORT_SVGPADDING = "excalidraw-export-svgpadding";
|
||||
export const FRONTMATTER_KEY_EXPORT_SVGPADDING = "excalidraw-export-svgpadding"; //depricated
|
||||
export const FRONTMATTER_KEY_EXPORT_PADDING = "excalidraw-export-padding";
|
||||
export const FRONTMATTER_KEY_EXPORT_PNGSCALE = "excalidraw-export-pngscale";
|
||||
export const FRONTMATTER_KEY_CUSTOM_PREFIX = "excalidraw-link-prefix";
|
||||
export const FRONTMATTER_KEY_CUSTOM_URL_PREFIX = "excalidraw-url-prefix";
|
||||
|
||||
@@ -17,8 +17,40 @@ I develop this plugin as a hobby, spending most of my free time doing this. If y
|
||||
|
||||
<div class="ex-coffee-div"><a href="https://ko-fi.com/zsolt"><img src="https://cdn.ko-fi.com/cdn/kofi3.png?v=3" height=45></a></div>
|
||||
`,
|
||||
"1.7.18":`
|
||||
## Critical fix
|
||||
- duplicating text elements, adding text elements from the library, and pasting excalidraw text elements results in a corrupted file!!`,
|
||||
"1.7.17":`
|
||||
## Fixed
|
||||
- Block transclusions sometimes got lost when switching between RAW mode and PREVIEW mode. [#769](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/769)
|
||||
|
||||
## New
|
||||
- Added feature to disable "new Excalidraw version" notification [#770](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/770)
|
||||
- Added option to export both light- and dark-themed images at the same time. If this is enabled Excalidraw will create two files "filename.dark.png" and "filename.light.png" (or .svg depending on your other settings). See practical use case here: [Aadam's Notes](https://notes.aadam.dev/SBYNtPHqsTW9Ck1Kuoxsu/)
|
||||
- Added custom export padding for PNG images. Use the frontmatter key ${String.fromCharCode(96)}excalidraw-export-padding${String.fromCharCode(96)} to set the padding at a file level, or set padding for all your files in plugin settings. The new feature replaces the old "SVG Padding" option and applies to both SVG and PNG exports.
|
||||
|
||||
## ExcalidrawAutomate
|
||||
- Added ${String.fromCharCode(96)}padding${String.fromCharCode(96)} to the createPNG function call.
|
||||
${String.fromCharCode(96, 96, 96)}typescript
|
||||
async createPNG(
|
||||
templatePath?: string,
|
||||
scale: number = 1,
|
||||
exportSettings?: ExportSettings,
|
||||
loader?: EmbeddedFilesLoader,
|
||||
theme?: string,
|
||||
padding?: number,
|
||||
)
|
||||
${String.fromCharCode(96, 96, 96)}
|
||||
`,
|
||||
"1.7.16":`
|
||||
## Fixed
|
||||
- Excalidraw canvas is empty after saving the drawing and re-opening it at a later time. If you accidentally paste Excalidraw elements from the clipboard as the contents of a text element, in certain situations this can corrupt the Excalidraw file and as a result, Excalidraw will load an empty-looking drawing the next time. Changing to markdown view, these files can be repaired, however, to avoid accidental data loss, I have prevented pasting of excalidraw clipboard contents as text elements. [#768](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/768)
|
||||
|
||||
## New
|
||||
- Add zoom % display in tray-mode [737](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/737)
|
||||
`,
|
||||
"1.7.15":`
|
||||
# Fixed
|
||||
## Fixed
|
||||
- Canvas turns white when adding point for curved line [#760](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/760), [#738](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/738), [#5602](https://github.com/excalidraw/excalidraw/issues/5602)
|
||||
`,
|
||||
"1.7.14": `
|
||||
@@ -41,7 +73,7 @@ I develop this plugin as a hobby, spending most of my free time doing this. If y
|
||||
- Create a new folder not working when clicking on a link in Erxcalidraw that points to a file that is in a folder that does not yet exist. [741](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/741)
|
||||
- Downgraded to React 17 due to various stability issues, including [#738](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/738) and [#747](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/747)
|
||||
|
||||
# New in Excalidraw Automate
|
||||
## New in Excalidraw Automate
|
||||
- I added two new Excalidraw Automate functions
|
||||
${String.fromCharCode(96, 96, 96)}typescript
|
||||
/**
|
||||
@@ -69,46 +101,46 @@ ${String.fromCharCode(96, 96, 96)}`,
|
||||
- ${String.fromCharCode(96)}Open in Adjacent Pane${String.fromCharCode(96)} and ${String.fromCharCode(96)}Open in Main Workspace${String.fromCharCode(96)} Excalidraw plugin settings is fixed
|
||||
`,
|
||||
"1.7.12": `
|
||||
# New from Excalidraw.com:
|
||||
## New from Excalidraw.com:
|
||||
- Showing a mid-point for lines and arrows. By touching the mid-point you can easily add an additional point to a two-point line. This is especially helpful when working on a tablet with touch input. ([#5534](https://github.com/excalidraw/excalidraw/pull/5534))
|
||||
- Lock angle when editing a line or an arrow with SHIFT pressed. Pressing SHIFT will restrict the edited point to snap to certain discrete angles. ([#5527](https://github.com/excalidraw/excalidraw/pull/5527))
|
||||
|
||||
# Fixed:
|
||||
## Fixed:
|
||||
- Clicking Obsidian search-results pointing to an element on the canvas works again ([#734](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/734))
|
||||
- The feature to allow resizing and rotation of lines and arrows consisting of 3 or more points by showing the bounding box when selected is back ([#5554](https://github.com/excalidraw/excalidraw/pull/5554))
|
||||
|
||||
# New
|
||||
## New
|
||||
- You can now use the following frontmatter key to allow/prevent automatic export of PNG/SVG images at a file level. This frontmatter will override export settings for the given file. ([#732](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/732)
|
||||
${String.fromCharCode(96)}excalidraw-autoexport: none|both|svg|png${String.fromCharCode(96)}
|
||||
`,
|
||||
"1.7.11": `
|
||||
# Fixed
|
||||
## Fixed
|
||||
- Markdown files embed into the Excalidraw canvas crashed when the embedded markdown file included a nested Markdown embed with a block reference (i.e. the markdown document you are dropping into Excalidraw included a quote you referenced from another file using a ${String.fromCharCode(96)}[[other-file#^blockref]]${String.fromCharCode(96)} block or section reference.
|
||||
- Horizontal flipping of arrows and lines broke in 1.7.10. ([#726](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/726))
|
||||
`,
|
||||
"1.7.10": `
|
||||
# New from Excalidraw.com
|
||||
## New from Excalidraw.com
|
||||
- Improved handling of arrows and lines. ([#5501](https://github.com/excalidraw/excalidraw/pull/5501))
|
||||
|
||||
# Fixed
|
||||
## Fixed
|
||||
- When opening a document in view-mode or zen-mode the panel buttons no longer flash up for a moment before switching to the desired mode. ([#479](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/479))
|
||||
- The "blinding white screen" no longer flashes up while loading the scene if the scene is dark ([#241](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/241))
|
||||
|
||||
# Under the hood
|
||||
## Under the hood
|
||||
- Finalized migration to React 18 (no longer showing an error about React 17 compatibility mode in console log)
|
||||
`,
|
||||
"1.7.9": `
|
||||
# New features and fixes from Excalidraw.com:
|
||||
## New features and fixes from Excalidraw.com:
|
||||
- The right-click context menu is now scrollable on smaller screens ([#4030](https://github.com/excalidraw/excalidraw/pull/4030), [#5520](https://github.com/excalidraw/excalidraw/pull/5520))
|
||||
- Holding down the shift key while rotating an object will rotate it at discrete angles. Rotation is continuous without the SHIFT key. ([#5500](https://github.com/excalidraw/excalidraw/pull/5500))
|
||||
- Improved cursor alignment when resizing an element proportionally (maintain aspect ratio) by holding SHIFT during resizing. ([#5513](https://github.com/excalidraw/excalidraw/pull/5515))
|
||||
- Improved freedraw performance during editing (now has proper canvas caching), and no more blurry freedraw shapes when exporting on a higher scale. ([#5481](https://github.com/excalidraw/excalidraw/pull/5481))
|
||||
- Sidebar stencil library now correctly scrolls vertically ([#5459](https://github.com/excalidraw/excalidraw/pull/5459))
|
||||
|
||||
# New in Obsidian:
|
||||
## New in Obsidian:
|
||||
- Fullscreen mode on iPad. When there are multiple work panes open, clicking the fullscreen action in the Excalidraw Obsidian menu will hide the other work panes and make Excalidraw fullscreen.
|
||||
|
||||
# Fixes in Obsidian:
|
||||
## Fixes in Obsidian:
|
||||
- Drag&Drop an image from a web browser into Excalidraw ([#697](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/697))
|
||||
- On Obsidian Mobile 1.3.0, when the drawing included an embedded image, switching from markdown-view to Excalidraw-view caused the drawing to disappear (it had to be recovered from backup or synchronization history). ([#715](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/715))
|
||||
- When working on a mobile device (tablet and phone) and using two work panes (one for drawing and the other for editing a markdown document) if you switched focus from the drawing to the markdown document auto-zoom changed the zoom level of the drawing. ([#723](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/723)), ([#705](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/705))
|
||||
|
||||
@@ -587,9 +587,9 @@ export const FRONTMATTER_KEYS_INFO: SuggesterInfo[] = [
|
||||
after: ": true",
|
||||
},
|
||||
{
|
||||
field: "export-svgpadding",
|
||||
field: "export-padding",
|
||||
code: null,
|
||||
desc: "If this key is present it will override the default excalidraw embed and export setting. This only affects export to SVG. Specify the export padding for the image.",
|
||||
desc: "If this key is present it will override the default excalidraw embed and export setting. This only affects both SVG and PNG export. Specify the export padding for the image.",
|
||||
after: ": 5",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -36,7 +36,7 @@ export default {
|
||||
"Create a new drawing - IN A NEW PANE - and embed into active document",
|
||||
NEW_IN_ACTIVE_PANE_EMBED:
|
||||
"Create a new drawing - IN THE CURRENT ACTIVE PANE - and embed into active document",
|
||||
NEW_IN_POPOUT_WINDOW_EMBED: "Create a new drawing - IN A POPOUT WINDOW - and embedd into active document",
|
||||
NEW_IN_POPOUT_WINDOW_EMBED: "Create a new drawing - IN A POPOUT WINDOW - and embed into active document",
|
||||
EXPORT_SVG: "Save as SVG next to the current file",
|
||||
EXPORT_PNG: "Save as PNG next to the current file",
|
||||
TOGGLE_LOCK: "Toggle Text Element edit RAW/PREVIEW",
|
||||
@@ -91,6 +91,11 @@ export default {
|
||||
RELEASE_NOTES_DESC:
|
||||
"<b>Toggle ON:</b> Display release notes each time you update Excalidraw to a newer version.<br>" +
|
||||
"<b>Toggle OFF:</b> Silent mode. You can still read release notes on <a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/releases'>GitHub</a>.",
|
||||
NEWVERSION_NOTIFICATION_NAME: "Plugin update notification",
|
||||
NEWVERSION_NOTIFICATION_DESC:
|
||||
"<b>Toggle ON:</b> Show a notification when a new version of the plugin is avaiable.<br>" +
|
||||
"<b>Toggle OFF:</b> Silent mode. You need to check for plugin updates in Community Plugins.",
|
||||
|
||||
FOLDER_NAME: "Excalidraw folder",
|
||||
FOLDER_DESC:
|
||||
"Default location for new drawings. If empty, drawings will be created in the Vault root.",
|
||||
@@ -98,8 +103,8 @@ export default {
|
||||
"Use Excalidraw folder when embedding a drawing into the active document",
|
||||
FOLDER_EMBED_DESC:
|
||||
"Define which folder to place the newly inserted drawing into " +
|
||||
"when using the command palette action: 'Create a new drawing and embed into active document'. " +
|
||||
"ON: Use Excalidraw folder; OFF: use attachments folder defined in Obsidian settings",
|
||||
"when using the command palette action: 'Create a new drawing and embed into active document'.<br>" +
|
||||
"<b>Toggle ON:</b> Use Excalidraw folder<br><b>Toggle OFF:</b> use the attachments folder defined in Obsidian settings.",
|
||||
TEMPLATE_NAME: "Excalidraw template file",
|
||||
TEMPLATE_DESC:
|
||||
"Full filepath to the Excalidraw template. " +
|
||||
@@ -123,7 +128,7 @@ export default {
|
||||
"be saved without compression, so that you can read and edit the JSON string. The drawing will be compressed again " +
|
||||
"once you switch back to Excalidraw view. " +
|
||||
"The setting only has effect 'point forward', meaning, existing drawings will not be effected by the setting " +
|
||||
"until you open them and save them. ",
|
||||
"until you open them and save them.<br><b>Toggle ON:</b> Compress drawing JSON<br><b>Toggle OFF:</b> Leave drawing JSON uncompressed",
|
||||
AUTOSAVE_NAME: "Enable Autosave",
|
||||
AUTOSAVE_DESC:
|
||||
"Automatically save the active drawing, in case there are changes, every 15, 30 seconds, or 1, 2, 3, 4, or 5 minute. Save normally happens when you close Excalidraw or Obsidian, or move " +
|
||||
@@ -144,8 +149,8 @@ export default {
|
||||
"Filename prefix when embedding a new drawing into a markdown note",
|
||||
FILENAME_PREFIX_EMBED_DESC:
|
||||
"Should the filename of the newly inserted drawing start with the name of the active markdown note " +
|
||||
"when using the command palette action: <code>Create a new drawing and embed into active document</code>? " +
|
||||
"ON: Yes, OFF: Not",
|
||||
"when using the command palette action: <code>Create a new drawing and embed into active document</code>?<br>" +
|
||||
"<b>Toggle ON:</b> Yes, the filename of a new drawing should start with filename of the active document<br><b>Toggle OFF:</b> No, filename of a new drawing should not include the filename of the active document",
|
||||
FILENAME_POSTFIX_NAME:
|
||||
"Custom text after markdown Note's name when embedding",
|
||||
FILENAME_POSTFIX_DESC:
|
||||
@@ -156,26 +161,25 @@ export default {
|
||||
FILENAME_EXCALIDRAW_EXTENSION_NAME: ".excalidraw.md or .md",
|
||||
FILENAME_EXCALIDRAW_EXTENSION_DESC:
|
||||
"This setting does not apply if you use Excalidraw in compatibility mode, " +
|
||||
"i.e. you are not using Excalidraw markdown files. Toggle ON = filename ends with .excalidraw.md, Toggle OFF = filename ends with .md",
|
||||
/*SVG_IN_MD_NAME: "SVG Snapshot to markdown file",
|
||||
SVG_IN_MD_DESC: "If the switch is 'on' Excalidraw will include an SVG snapshot in the markdown file. "+
|
||||
"When SVG snapshots are saved to the Excalidraw.md file, drawings that include large png, jpg, gif images may take extreme long time to open in markdown view. " +
|
||||
"On the other hand, SVG snapshots provide some level of platform independence and longevity to your drawings. Even if Excalidraw will no longer exist, the snapshot " +
|
||||
"can be opened with an app that reads SVGs. In addition hover previews will be less resource intensive if SVG snapshots are enabled.",*/
|
||||
"i.e. you are not using Excalidraw markdown files.<br><b>Toggle ON:</b> filename ends with .excalidraw.md<br><b>Toggle OFF:</b> filename ends with .md",
|
||||
DISPLAY_HEAD: "Display",
|
||||
LEFTHANDED_MODE_NAME: "Left-handed mode",
|
||||
LEFTHANDED_MODE_DESC:
|
||||
"Currently only has effect in tray-mode. If turned on, the tray will be on the right side.",
|
||||
"Currently only has effect in tray-mode. If turned on, the tray will be on the right side." +
|
||||
"<br><b>Toggle ON:</b> Left-handed mode.<br><b>Toggle OFF:</b> Right-handed moded",
|
||||
MATCH_THEME_NAME: "New drawing to match Obsidian theme",
|
||||
MATCH_THEME_DESC:
|
||||
"If theme is dark, new drawing will be created in dark mode. This does not apply when you use a template for new drawings. " +
|
||||
"Also this will not effect when you open an existing drawing. Those will follow the theme of the template/drawing respectively.",
|
||||
"Also this will not effect when you open an existing drawing. Those will follow the theme of the template/drawing respectively." +
|
||||
"<br><b>Toggle ON:</b> Follow Obsidian Theme<br><b>Toggle OFF:</b>Follow theme defined in your template",
|
||||
MATCH_THEME_ALWAYS_NAME: "Existing drawings to match Obsidian theme",
|
||||
MATCH_THEME_ALWAYS_DESC:
|
||||
"If theme is dark, drawings will be opened in dark mode. If your theme is light, they will be opened in light mode. ",
|
||||
"If theme is dark, drawings will be opened in dark mode. If your theme is light, they will be opened in light mode. " +
|
||||
"<br><b>Toggle ON:</b> Match Obsidian theme<br><b>Toggle OFF:</b> Open with the same theme as last saved",
|
||||
MATCH_THEME_TRIGGER_NAME: "Excalidraw to follow when Obsidian Theme changes",
|
||||
MATCH_THEME_TRIGGER_DESC:
|
||||
"If this option is enabled open Excalidraw pane will switch to light/dark mode when Obsidian theme changes. ",
|
||||
"If this option is enabled open Excalidraw pane will switch to light/dark mode when Obsidian theme changes. " +
|
||||
"<br><b>Toggle ON:</b> Follow theme changes<br><b>Toggle OFF:</b> Drawings are not effected by Obsidian theme changes",
|
||||
DEFAULT_OPEN_MODE_NAME: "Default mode when opening Excalidraw",
|
||||
DEFAULT_OPEN_MODE_DESC:
|
||||
"Specifies the mode how Excalidraw opens: Normal, Zen, or View mode. You may also set this behavior on a file level by " +
|
||||
@@ -184,7 +188,8 @@ export default {
|
||||
DEFAULT_PEN_MODE_DESC:
|
||||
"Should pen mode be automatically enabled when opening Excalidraw?",
|
||||
ZOOM_TO_FIT_NAME: "Zoom to fit on view resize",
|
||||
ZOOM_TO_FIT_DESC: "Zoom to fit drawing when the pane is resized",
|
||||
ZOOM_TO_FIT_DESC: "Zoom to fit drawing when the pane is resized" +
|
||||
"<br><b>Toggle ON:</b> Zoom to fit<br><b>Toggle OFF:</b> Auto zoom disabled",
|
||||
ZOOM_TO_FIT_MAX_LEVEL_NAME: "Zoom to fit max ZOOM level",
|
||||
ZOOM_TO_FIT_MAX_LEVEL_DESC:
|
||||
"Set the maximum level to which zoom to fit will enlarge the drawing. Minimum is 0.5 (50%) and maximum is 10 (1000%).",
|
||||
@@ -301,7 +306,8 @@ export default {
|
||||
"For a number of reasons, the same approach cannot be used to expedite the loading of drawings with many embedded objects. See demonstration <a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/1.6.23' target='_blank'>here</a>.",
|
||||
EMBED_PREVIEW_SVG_NAME: "Display SVG in markdown preview",
|
||||
EMBED_PREVIEW_SVG_DESC:
|
||||
"The default is to display drawings as SVG images in the markdown preview. Turning this feature off, the markdown preview will display the drawing as an embedded PNG image.",
|
||||
"<b>Toggle ON</b>: Embed drawing as an <a href='https://en.wikipedia.org/wiki/Scalable_Vector_Graphics' target='_blank'>SVG</a> image into the markdown preview.<br>" +
|
||||
"<b>Toggle OFF</b>: Embedd drawing as a <a href='' target='_blank'>PNG</a> image. Note, that some of the <a href='https://www.youtube.com/watch?v=yZQoJg2RCKI&t=633s' target='_blank'>image block referencing features</a> do not work with PNG embeds.",
|
||||
PREVIEW_MATCH_OBSIDIAN_NAME: "Excalidraw preview to match Obsidian theme",
|
||||
PREVIEW_MATCH_OBSIDIAN_DESC:
|
||||
"Image preview in documents should match the Obsidian theme. If enabled, when Obsidian is in dark mode, Excalidraw images will render in dark mode. " +
|
||||
@@ -325,9 +331,11 @@ export default {
|
||||
EXPORT_BACKGROUND_NAME: "Export image with background",
|
||||
EXPORT_BACKGROUND_DESC:
|
||||
"If turned off, the exported image will be transparent.",
|
||||
EXPORT_SVG_PADDING_NAME: "SVG Padding",
|
||||
EXPORT_SVG_PADDING_DESC:
|
||||
"The padding (in pixels) around the exported SVG image. If you have curved lines close to the edge of the image they might get cropped during SVG export. You can increase this value to avoid cropping.",
|
||||
EXPORT_PADDING_NAME: "Image Padding",
|
||||
EXPORT_PADDING_DESC:
|
||||
"The padding (in pixels) around the exported SVG or PNG image. " +
|
||||
"If you have curved lines close to the edge of the image they might get cropped during image export. You can increase this value to avoid cropping. " +
|
||||
"You can also override this setting at a file level by adding the <code>excalidraw-export-padding: 5<code> frontmatter key.",
|
||||
EXPORT_THEME_NAME: "Export image with theme",
|
||||
EXPORT_THEME_DESC:
|
||||
"Export the image matching the dark/light theme of your drawing. If turned off, " +
|
||||
@@ -348,6 +356,9 @@ export default {
|
||||
"<code>none</code>,<code>both</code>,<code>svg</code>, and <code>png</code>",
|
||||
EXPORT_PNG_NAME: "Auto-export PNG",
|
||||
EXPORT_PNG_DESC: "Same as the auto-export SVG, but for *.PNG",
|
||||
EXPORT_BOTH_DARK_AND_LIGHT_NAME: "Export both dark- and light-themed image",
|
||||
EXPORT_BOTH_DARK_AND_LIGHT_DESC: "When enabled, Excalidraw will export two files instead of one: filename.dark.png, filename.light.png and/or filename.dark.svg and filename.light.svg<br>"+
|
||||
"Double files will be exported both if auto-export SVG or PNG (or both) are enabled, as well as when clicking export on a single image.",
|
||||
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
@@ -41,6 +41,7 @@ import {
|
||||
SCRIPT_INSTALL_FOLDER,
|
||||
VIRGIL_FONT,
|
||||
VIRGIL_DATAURL,
|
||||
EXPORT_TYPES,
|
||||
} from "./Constants";
|
||||
import ExcalidrawView, { TextMode, getTextMode } from "./ExcalidrawView";
|
||||
import {
|
||||
@@ -73,7 +74,6 @@ import {
|
||||
getDrawingFilename,
|
||||
getEmbedFilename,
|
||||
getIMGFilename,
|
||||
getIMGPathFromExcalidrawFile,
|
||||
getNewUniqueFilepath,
|
||||
} from "./utils/FileUtils";
|
||||
import {
|
||||
@@ -84,6 +84,7 @@ import {
|
||||
sleep,
|
||||
debug,
|
||||
isVersionNewerThanOther,
|
||||
getExportTheme,
|
||||
} from "./utils/Utils";
|
||||
import { getAttachmentsFolderAndFilePath, getNewOrAdjacentLeaf, getParentOfClass, isObsidianThemeDark } from "./utils/ObsidianUtils";
|
||||
//import { OneOffs } from "./OneOffs";
|
||||
@@ -965,7 +966,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
return false;
|
||||
}
|
||||
const view = this.app.workspace.getActiveViewOfType(ExcalidrawView);
|
||||
if (view) {
|
||||
if (view && !view.compatibilityMode) {
|
||||
view.changeTextMode(
|
||||
view.textMode === TextMode.parsed ? TextMode.raw : TextMode.parsed,
|
||||
);
|
||||
@@ -1309,7 +1310,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
FRONTMATTER + (await this.exportSceneToMD(data)),
|
||||
);
|
||||
if (this.settings.keepInSync) {
|
||||
[".svg", ".png"].forEach((ext: string) => {
|
||||
EXPORT_TYPES.forEach((ext: string) => {
|
||||
const oldIMGpath =
|
||||
file.path.substring(0, file.path.lastIndexOf(".excalidraw")) + ext;
|
||||
const imgFile = this.app.vault.getAbstractFileByPath(
|
||||
@@ -1462,13 +1463,13 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
if (!self.settings.keepInSync) {
|
||||
return;
|
||||
}
|
||||
[".svg", ".png", ".excalidraw"].forEach(async (ext: string) => {
|
||||
const oldIMGpath = getIMGPathFromExcalidrawFile(oldPath, ext);
|
||||
[EXPORT_TYPES, "excalidraw"].flat().forEach(async (ext: string) => {
|
||||
const oldIMGpath = getIMGFilename(oldPath, ext);
|
||||
const imgFile = app.vault.getAbstractFileByPath(
|
||||
normalizePath(oldIMGpath),
|
||||
);
|
||||
if (imgFile && imgFile instanceof TFile) {
|
||||
const newIMGpath = getIMGPathFromExcalidrawFile(file.path, ext);
|
||||
const newIMGpath = getIMGFilename(file.path, ext);
|
||||
await app.fileManager.renameFile(imgFile, newIMGpath);
|
||||
}
|
||||
});
|
||||
@@ -1537,8 +1538,8 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
//delete PNG and SVG files as well
|
||||
if (self.settings.keepInSync) {
|
||||
setTimeout(() => {
|
||||
[".svg", ".png", ".excalidraw"].forEach(async (ext: string) => {
|
||||
const imgPath = getIMGPathFromExcalidrawFile(file.path, ext);
|
||||
[EXPORT_TYPES, "excalidraw"].flat().forEach(async (ext: string) => {
|
||||
const imgPath = getIMGFilename(file.path, ext);
|
||||
const imgFile = app.vault.getAbstractFileByPath(
|
||||
normalizePath(imgPath),
|
||||
);
|
||||
@@ -1801,42 +1802,67 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
public async embedDrawing(file: TFile) {
|
||||
const activeView = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (activeView && activeView.file) {
|
||||
const data = this.app.metadataCache.fileToLinktext(
|
||||
const excalidrawRelativePath = this.app.metadataCache.fileToLinktext(
|
||||
file,
|
||||
activeView.file.path,
|
||||
this.settings.embedType === "excalidraw",
|
||||
);
|
||||
const editor = activeView.editor;
|
||||
|
||||
//embed Excalidraw
|
||||
if (this.settings.embedType === "excalidraw") {
|
||||
editor.replaceSelection(
|
||||
this.settings.embedWikiLink
|
||||
? `![[${data}]]`
|
||||
: `})`,
|
||||
? `![[${excalidrawRelativePath}]]`
|
||||
: `})`,
|
||||
);
|
||||
editor.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
const filename = getIMGPathFromExcalidrawFile(
|
||||
data,
|
||||
`.${this.settings.embedType.toLowerCase()}`,
|
||||
);
|
||||
const filepath = getIMGPathFromExcalidrawFile(
|
||||
file.path,
|
||||
`.${this.settings.embedType.toLowerCase()}`,
|
||||
);
|
||||
//embed image
|
||||
let theme = this.settings.autoExportLightAndDark
|
||||
? getExportTheme (
|
||||
this,
|
||||
file,
|
||||
this.settings.exportWithTheme
|
||||
? isObsidianThemeDark() ? "dark":"light"
|
||||
: "light"
|
||||
)
|
||||
: "";
|
||||
|
||||
const imgFile = this.app.vault.getAbstractFileByPath(filepath);
|
||||
theme = theme===""?"":theme+".";
|
||||
|
||||
const imageRelativePath = getIMGFilename(
|
||||
excalidrawRelativePath,
|
||||
theme+this.settings.embedType.toLowerCase(),
|
||||
);
|
||||
const imageFullpath = getIMGFilename(
|
||||
file.path,
|
||||
theme+this.settings.embedType.toLowerCase(),
|
||||
);
|
||||
|
||||
//will hold incorrect value if theme==="", however in that case it won't be used
|
||||
const otherTheme = theme === "dark." ? "light.":"dark.";
|
||||
const otherImageRelativePath = getIMGFilename(
|
||||
excalidrawRelativePath,
|
||||
otherTheme+this.settings.embedType.toLowerCase(),
|
||||
);
|
||||
|
||||
|
||||
const imgFile = this.app.vault.getAbstractFileByPath(imageFullpath);
|
||||
if (!imgFile) {
|
||||
await this.app.vault.create(filepath, "");
|
||||
await this.app.vault.create(imageFullpath, "");
|
||||
await sleep(200);
|
||||
}
|
||||
|
||||
editor.replaceSelection(
|
||||
this.settings.embedWikiLink
|
||||
? `![[${filename}]]\n%%[[${data}|🖋 Edit in Excalidraw]]%%`
|
||||
: `})\n%%[🖋 Edit in Excalidraw](${encodeURI(
|
||||
data,
|
||||
)})%%`,
|
||||
? `![[${imageRelativePath}]]\n%%[[${excalidrawRelativePath}|🖋 Edit in Excalidraw]]${
|
||||
otherImageRelativePath ? ", and the [["+otherImageRelativePath+"|"+otherTheme.split(".")[0]+" exported image]]":""}%%`
|
||||
: `})\n%%[🖋 Edit in Excalidraw](${encodeURI(
|
||||
excalidrawRelativePath,
|
||||
)})${otherImageRelativePath?", and the ["+otherTheme.split(".")[0]+" exported image]("+encodeURI(otherImageRelativePath)+")":""}%%`,
|
||||
);
|
||||
editor.focus();
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ export interface ExcalidrawSettings {
|
||||
keepInSync: boolean;
|
||||
autoexportSVG: boolean;
|
||||
autoexportPNG: boolean;
|
||||
autoExportLightAndDark: boolean;
|
||||
autoexportExcalidraw: boolean;
|
||||
embedType: "excalidraw" | "PNG" | "SVG";
|
||||
embedWikiLink: boolean;
|
||||
@@ -101,6 +102,7 @@ export interface ExcalidrawSettings {
|
||||
defaultTrayMode: boolean;
|
||||
previousRelease: string;
|
||||
showReleaseNotes: boolean;
|
||||
showNewVersionNotification: boolean;
|
||||
mathjaxSourceURL: string;
|
||||
}
|
||||
|
||||
@@ -144,10 +146,11 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
pngExportScale: 1,
|
||||
exportWithTheme: true,
|
||||
exportWithBackground: true,
|
||||
exportPaddingSVG: 10,
|
||||
exportPaddingSVG: 10, //since 1.6.17, not only SVG but also PNG
|
||||
keepInSync: false,
|
||||
autoexportSVG: false,
|
||||
autoexportPNG: false,
|
||||
autoExportLightAndDark: false,
|
||||
autoexportExcalidraw: false,
|
||||
embedType: "excalidraw",
|
||||
embedWikiLink: true,
|
||||
@@ -182,6 +185,7 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
defaultTrayMode: false,
|
||||
previousRelease: "1.6.13",
|
||||
showReleaseNotes: true,
|
||||
showNewVersionNotification: true,
|
||||
mathjaxSourceURL: "https://cdn.jsdelivr.net/npm/mathjax@3.2.1/es5/tex-svg.js"
|
||||
};
|
||||
|
||||
@@ -269,6 +273,18 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.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(containerEl)
|
||||
.setName(t("FOLDER_NAME"))
|
||||
.setDesc(fragWithHTML(t("FOLDER_DESC")))
|
||||
@@ -996,8 +1012,8 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
let exportPadding: HTMLDivElement;
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("EXPORT_SVG_PADDING_NAME"))
|
||||
.setDesc(fragWithHTML(t("EXPORT_SVG_PADDING_DESC")))
|
||||
.setName(t("EXPORT_PADDING_NAME"))
|
||||
.setDesc(fragWithHTML(t("EXPORT_PADDING_DESC")))
|
||||
.addSlider((slider) =>
|
||||
slider
|
||||
.setLimits(0, 50, 5)
|
||||
@@ -1093,6 +1109,18 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.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();
|
||||
}),
|
||||
);
|
||||
|
||||
this.containerEl.createEl("h1", { text: t("COMPATIBILITY_HEAD") });
|
||||
|
||||
new Setting(containerEl)
|
||||
|
||||
@@ -42,7 +42,7 @@ export function splitFolderAndFilename(filepath: string): {
|
||||
* @param newExtension - extension of IMG file in ".extension" format
|
||||
* @returns
|
||||
*/
|
||||
export function getIMGPathFromExcalidrawFile(
|
||||
/*export function getIMGPathFromExcalidrawFile(
|
||||
excalidrawPath: string,
|
||||
newExtension: string,
|
||||
): string {
|
||||
@@ -52,6 +52,16 @@ export function getIMGPathFromExcalidrawFile(
|
||||
excalidrawPath.substring(0, excalidrawPath.lastIndexOf(replaceExtension)) +
|
||||
newExtension
|
||||
);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Generates the image filename based on the excalidraw filename
|
||||
* @param path - path to the excalidraw file
|
||||
* @param extension - extension without the preceeding "."
|
||||
* @returns
|
||||
*/
|
||||
export function getIMGFilename(path: string, extension: string): string {
|
||||
return `${path.substring(0, path.lastIndexOf("."))}.${extension}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,6 +145,3 @@ export async function checkAndCreateFolder(folderpath: string) {
|
||||
await vault.createFolder(folderpath);
|
||||
}
|
||||
|
||||
export function getIMGFilename(path: string, extension: string): string {
|
||||
return `${path.substring(0, path.lastIndexOf("."))}.${extension}`;
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
FRONTMATTER_KEY_EXPORT_TRANSPARENT,
|
||||
FRONTMATTER_KEY_EXPORT_SVGPADDING,
|
||||
FRONTMATTER_KEY_EXPORT_PNGSCALE,
|
||||
FRONTMATTER_KEY_EXPORT_PADDING,
|
||||
} from "../Constants";
|
||||
import ExcalidrawPlugin from "../main";
|
||||
import { ExcalidrawElement } from "@zsviczian/excalidraw/types/element/types";
|
||||
@@ -287,6 +288,7 @@ export const getSVG = async (
|
||||
export const getPNG = async (
|
||||
scene: any,
|
||||
exportSettings: ExportSettings,
|
||||
padding: number,
|
||||
scale: number = 1,
|
||||
) => {
|
||||
try {
|
||||
@@ -300,6 +302,7 @@ export const getPNG = async (
|
||||
...scene.appState,
|
||||
},
|
||||
files: scene.files,
|
||||
exportPadding: padding,
|
||||
mimeType: "image/png",
|
||||
getDimensions: (width: number, height: number) => ({
|
||||
width: width * scale,
|
||||
@@ -516,16 +519,25 @@ export const getWithBackground = (
|
||||
return plugin.settings.exportWithBackground;
|
||||
};
|
||||
|
||||
export const getSVGPadding = (
|
||||
export const getExportPadding = (
|
||||
plugin: ExcalidrawPlugin,
|
||||
file: TFile,
|
||||
): number => {
|
||||
if (file) {
|
||||
const fileCache = plugin.app.metadataCache.getFileCache(file);
|
||||
if (
|
||||
fileCache?.frontmatter &&
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_SVGPADDING] != null
|
||||
) {
|
||||
if(!fileCache?.frontmatter) return plugin.settings.exportPaddingSVG;
|
||||
|
||||
if (fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_PADDING] != null) {
|
||||
const val = parseInt(
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_PADDING],
|
||||
);
|
||||
if (!isNaN(val)) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
//depricated. Retained for backward compatibility
|
||||
if (fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_SVGPADDING] != null) {
|
||||
const val = parseInt(
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_SVGPADDING],
|
||||
);
|
||||
@@ -533,6 +545,7 @@ export const getSVGPadding = (
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return plugin.settings.exportPaddingSVG;
|
||||
};
|
||||
|
||||
13
yarn.lock
13
yarn.lock
@@ -2216,10 +2216,10 @@
|
||||
dependencies:
|
||||
"@zerollup/ts-helpers" "^1.7.18"
|
||||
|
||||
"@zsviczian/excalidraw@0.12.0-obsidian-5":
|
||||
"integrity" "sha512-AZQzqlxNbwk+BoKn3R10Xo/V+JoYwJ1mJ9+khUTSsavS7s41xRmA+6k+tKAPa+ce4PSEzZnXg8ZrxTUuNQBxxA=="
|
||||
"resolved" "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.12.0-obsidian-5.tgz"
|
||||
"version" "0.12.0-obsidian-5"
|
||||
"@zsviczian/excalidraw@0.12.0-obsidian-8":
|
||||
"integrity" "sha512-pftFJjZD0oFzwG/qc63f63fXP7ZPhQJZlr1A1+woWLhf426D3Z50H2K3EhrteIl1i8uy5kIDZ68K/rNZg+zbOg=="
|
||||
"resolved" "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.12.0-obsidian-8.tgz"
|
||||
"version" "0.12.0-obsidian-8"
|
||||
|
||||
"abab@^2.0.3", "abab@^2.0.5":
|
||||
"integrity" "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q=="
|
||||
@@ -3063,6 +3063,11 @@
|
||||
"resolved" "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz"
|
||||
"version" "2.0.16"
|
||||
|
||||
"colormaster@1.2.1":
|
||||
"integrity" "sha512-+G9g1fOW+TC4+y5IWYI4f7mb+l+oEto/N3qJTFrJNaayFpidZUWhZJGxoSJjhNMIiTttcU1kf4XSyfxHyHkQYw=="
|
||||
"resolved" "https://registry.npmjs.org/colormaster/-/colormaster-1.2.1.tgz"
|
||||
"version" "1.2.1"
|
||||
|
||||
"combined-stream@^1.0.8":
|
||||
"integrity" "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="
|
||||
"resolved" "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
|
||||
|
||||
Reference in New Issue
Block a user