Skip to content

Commit

Permalink
2.7.3
Browse files Browse the repository at this point in the history
  • Loading branch information
zsviczian committed Dec 27, 2024
1 parent 982958a commit 5a58d17
Show file tree
Hide file tree
Showing 11 changed files with 294 additions and 183 deletions.
4 changes: 3 additions & 1 deletion ea-scripts/Deconstruct selected elements into new drawing.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Select some elements in the scene. The script will take these elements and move

```javascript
*/
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("2.0.25")) {
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("2.7.3")) {
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
return;
}
Expand Down Expand Up @@ -81,6 +81,7 @@ ea.getElements().filter(el=>el.type==="image").forEach(el=>{
const path = (img?.linkParts?.original)??(img?.file?.path);
const hyperlink = img?.hyperlink;
if(img && (path || hyperlink)) {
const colorMap = ea.getColorMapForImageElement(el);
ea.imagesDict[el.fileId] = {
mimeType: img.mimeType,
id: el.fileId,
Expand All @@ -90,6 +91,7 @@ ea.getElements().filter(el=>el.type==="image").forEach(el=>{
hyperlink,
hasSVGwithBitmap: img.isSVGwithBitmap,
latex: null,
colorMap,
};
return;
}
Expand Down
349 changes: 187 additions & 162 deletions ea-scripts/Shade Master.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion ea-scripts/directory-info.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion ea-scripts/index-new.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea
```excalidraw-script-install
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Shade%20Master.md
```
<table><tr valign='top'><td class="label">Author</td><td class="data"><a href='https://github.com/zsviczian'>@zsviczian</a></td></tr><tr valign='top'><td class="label">Source</td><td class="data"><a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Shade%20Master.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">You can modify the colors of SVG images, embedded files, and Excalidraw elements in a drawing by changing Hue, Saturation, Lightness and Transparency; and if only a single SVG or nested Excalidraw drawing is selected, then you can remap image colors.</td></tr></table>
<table><tr valign='top'><td class="label">Author</td><td class="data"><a href='https://github.com/zsviczian'>@zsviczian</a></td></tr><tr valign='top'><td class="label">Source</td><td class="data"><a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Shade%20Master.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">You can modify the colors of SVG images, embedded files, and Excalidraw elements in a drawing by changing Hue, Saturation, Lightness and Transparency; and if only a single SVG or nested Excalidraw drawing is selected, then you can remap image colors.<br><iframe width="560" height="315" src="https://www.youtube.com/embed/ISuORbVKyhQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></td></tr></table>


## Slideshow
Expand Down
2 changes: 1 addition & 1 deletion manifest-beta.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "obsidian-excalidraw-plugin",
"name": "Excalidraw",
"version": "2.7.2",
"version": "2.7.3",
"minAppVersion": "1.1.6",
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
"author": "Zsolt Viczian",
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "obsidian-excalidraw-plugin",
"name": "Excalidraw",
"version": "2.7.2",
"version": "2.7.3",
"minAppVersion": "1.1.6",
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
"author": "Zsolt Viczian",
Expand Down
23 changes: 21 additions & 2 deletions src/shared/Dialogs/Messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@ I develop this plugin as a hobby, spending my free time doing this. If you find
<div class="ex-coffee-div"><a href="https://ko-fi.com/zsolt"><img src="https://storage.ko-fi.com/cdn/kofi6.png?v=6" border="0" alt="Buy Me a Coffee at ko-fi.com" height=45></a></div>
`,
"2.7.3":`
<div class="excalidraw-videoWrapper"><div>
<iframe src="https://www.youtube.com/embed/ISuORbVKyhQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></div>
## Fixed
- Toggling image size anchoring on and off by modifying the image link did not update the image in the view until the user forced saved it or closed and opened the drawing again. This was a side-effect of the less frequent view save introduced in 2.7.1
## New
- **Shade Master Script**: A new script that allows you to modify the color lightness, hue, saturation, and transparency of selected Excalidraw elements, SVG images, and nested Excalidraw drawings. When a single image is selected, you can map colors individually. The original image remains unchanged, and a mapping table is added under ${String.fromCharCode(96)}## Embedded Files${String.fromCharCode(96)} for SVG and nested drawings. This helps maintain links between drawings while allowing different color themes.
- New Command Palette Command: "Duplicate selected image with a different image ID". Creates a copy of the selected image with a new image ID. This allows you to add multiple color mappings to the same image. In the scene the image will be treated as if a different image, but loaded from the same file in the Vault.
- New Command Palette Command: "Duplicate selected image with a different image ID". Creates a copy of the selected image with a new image ID. This allows you to add multiple color mappings to the same image. In the scene, the image will be treated as if a different image, but loaded from the same file in the Vault.
## QoL Improvements
- New setting under ${String.fromCharCode(96)}Embedding Excalidraw into your notes and Exporting${String.fromCharCode(96)} > ${String.fromCharCode(96)}Image Caching and rendering optimization${String.fromCharCode(96)}. You can now set the number of concurrent workers that render your embedded images. Increasing the number will increase the speed but temporarily reduce the responsiveness of your system in case of large drawings.
- Moved pen-related settings under ${String.fromCharCode(96)}Excalidraw appearance and behavior${String.fromCharCode(96)} to their own sub-heading called ${String.fromCharCode(96)}Pen${String.fromCharCode(96)}.
- Moved pen-related settings under ${String.fromCharCode(96)}Excalidraw appearance and behavior${String.fromCharCode(96)} to their sub-heading called ${String.fromCharCode(96)}Pen${String.fromCharCode(96)}.
- Minor error fixing and performance optimizations when loading and updating embedded images.
- Color maps in ${String.fromCharCode(96)}## Embedded Files${String.fromCharCode(96)} may now include color keys "stroke" and "fill". If set, these will change the fill and stroke attributes of the SVG root element of the relevant file.
Expand Down Expand Up @@ -57,6 +61,21 @@ getColosFromExcalidrawFile(file:TFile, img: ExcalidrawImageElement): Promise<SVG
// Extracts the fill and stroke colors from an SVG string and returns them as an SVGColorInfo.
getColorsFromSVGString(svgString: string): SVGColorInfo;
// upgraded the addImage function.
// 1. It now accepts an object as the input parameter, making your scripts more readable
// 2. AddImageOptions now includes colorMap as an optional parameter, this will only have an effect in case of SVGs and nested Excalidraws
// 3. The API function is backwards compatible, but I recommend new implementations to use the object based input
addImage(opts: AddImageOptions}): Promise<string>;
interface AddImageOptions {
topX: number;
topY: number;
imageFile: TFile | string;
scale?: boolean;
anchor?: boolean;
colorMap?: ColorMap;
}
type SVGColorInfo = Map<string, {
mappedTo: string;
fill: boolean;
Expand Down
9 changes: 7 additions & 2 deletions src/shared/Dialogs/SuggesterInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,13 @@ export const EXCALIDRAW_AUTOMATE_INFO: SuggesterInfo[] = [
},
{
field: "addImage",
code: "async addImage(topX: number, topY: number, imageFile: TFile|string, scale?: boolean, anchor?: boolean): Promise<string>;",
desc: "imageFile may be a TFile or a string that contains a hyperlink. imageFile may also be an obsidian filepath including a reference eg.: 'path/my.pdf#page=3'\nSet scale to false if you want to embed the image at 100% of its original size. Default is true which will insert a scaled image.\nanchor will only be evaluated if scale is false. anchor true will add |100% to the end of the filename, resulting in an image that will always pop back to 100% when the source file is updated or when the Excalidraw file is reopened.",
code: "async addImage(opts: {topX: number, topY: number, imageFile: TFile|string, scale?: boolean, anchor?: boolean, colorMap?: ColorMap}): Promise<string>;",
desc: "imageFile may be a TFile or a string that contains a hyperlink.\n"+
"imageFile may also be an obsidian filepath including a reference eg.: 'path/my.pdf#page=3'\n"+
"Set scale to false if you want to embed the image at 100% of its original size. Default is true which will insert a scaled image.\n"+
"anchor will only be evaluated if scale is false. anchor true will add |100% to the end of the filename, resulting in an image that will always pop back to 100% when the source file is updated or when the Excalidraw file is reopened.\n"+
"colorMap is only used for SVG images and nested Excalidraw images. See the Shade Master script and the Deconstruct Selected Elements script for examples using colorMap.\n"+
"type ColorMap = { [color: string]: string; }",
after: "",
},
{
Expand Down
48 changes: 37 additions & 11 deletions src/shared/ExcalidrawAutomate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ import { addBackOfTheNoteCard, getFrameBasedOnFrameNameOrId } from "../utils/exc
import { log } from "../utils/debugHelper";
import { ExcalidrawLib } from "../types/excalidrawLib";
import { GlobalPoint } from "@zsviczian/excalidraw/types/math/types";
import { SVGColorInfo } from "src/types/excalidrawAutomateTypes";
import { AddImageOptions, ImageInfo, SVGColorInfo } from "src/types/excalidrawAutomateTypes";
import { errorMessage, filterColorMap, getEmbeddedFileForImageElment, isColorStringTransparent, isSVGColorInfo, mergeColorMapIntoSVGColorInfo, svgColorInfoToColorMap, updateOrAddSVGColorInfo } from "src/utils/excalidrawAutomateUtils";
import { Color } from "chroma-js";

extendPlugins([
HarmonyPlugin,
Expand Down Expand Up @@ -392,7 +393,7 @@ export class ExcalidrawAutomate {

plugin: ExcalidrawPlugin;
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
imagesDict: {[key: FileId]: ImageInfo}; //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
Expand Down Expand Up @@ -774,25 +775,29 @@ export class ExcalidrawAutomate {
? `\n## Embedded Files\n`
: "\n";

const embeddedFile = (key: FileId, path: string, colorMap?:ColorMap): string => {
return `${key}: [[${path}]]${colorMap ? " " + JSON.stringify(colorMap): ""}\n\n`;
}

Object.keys(this.imagesDict).forEach((key: FileId)=> {
const item = this.imagesDict[key];
if(item.latex) {
outString += `${key}: $$${item.latex}$$\n\n`;
} else {
if(item.file) {
if(item.file instanceof TFile) {
outString += `${key}: [[${item.file.path}]]\n\n`;
outString += embeddedFile(key,item.file.path, item.colorMap);
} else {
outString += `${key}: [[${item.file}]]\n\n`;
outString += embeddedFile(key,item.file, item.colorMap);
}
} else {
const hyperlinkSplit = item.hyperlink.split("#");
const file = this.plugin.app.vault.getAbstractFileByPath(hyperlinkSplit[0]);
if(file && file instanceof TFile) {
const hasFileRef = hyperlinkSplit.length === 2
outString += hasFileRef
? `${key}: [[${file.path}#${hyperlinkSplit[1]}]]\n\n`
: `${key}: [[${file.path}]]\n\n`;
? embeddedFile(key,`${file.path}#${hyperlinkSplit[1]}`, item.colorMap)
: embeddedFile(key,file.path, item.colorMap);
} else {
outString += `${key}: ${item.hyperlink}\n\n`;
}
Expand Down Expand Up @@ -1537,12 +1542,26 @@ export class ExcalidrawAutomate {
* @returns
*/
async addImage(
topX: number,
topXOrOpts: number | AddImageOptions,
topY: number,
imageFile: TFile | string, //string may also be an Obsidian filepath with a reference such as folder/path/my.pdf#page=2
scale: boolean = true, //default is true which will scale the image to MAX_IMAGE_SIZE, false will insert image at 100% of its size
anchor: boolean = true, //only has effect if scale is false. If anchor is true the image path will include |100%, if false the image will be inserted at 100%, but if resized by the user it won't pop back to 100% the next time Excalidraw is opened.
): Promise<string> {

let colorMap: ColorMap;
let topX: number;
if(typeof topXOrOpts === "number") {
topX = topXOrOpts;
} else {
topY = topXOrOpts.topY;
topX = topXOrOpts.topX;
imageFile = topXOrOpts.imageFile;
scale = topXOrOpts.scale ?? true;
anchor = topXOrOpts.anchor ?? true;
colorMap = topXOrOpts.colorMap;
}

const id = nanoid();
const loader = new EmbeddedFilesLoader(
this.plugin,
Expand Down Expand Up @@ -1576,6 +1595,7 @@ export class ExcalidrawAutomate {
height: image.size.height,
width: image.size.width,
},
colorMap,
};
if (scale && (Math.max(image.size.width, image.size.height) > MAX_IMAGE_SIZE)) {
const scale =
Expand Down Expand Up @@ -2031,6 +2051,13 @@ export class ExcalidrawAutomate {
ef.colorMap = null;
} else {
ef.colorMap = colorMap;
//delete special mappings for default/SVG root color values
if (ef.colorMap["fill"] === "black") {
delete ef.colorMap["fill"];
}
if (ef.colorMap["stroke"] === "none") {
delete ef.colorMap["stroke"];
}
}
ef.resetImage(this.targetView.file.path, ef.linkParts.original);
fileIDWhiteList.add(el.fileId);
Expand Down Expand Up @@ -2194,21 +2221,20 @@ export class ExcalidrawAutomate {
id: el.fileId,
dataURL: sceneFile.dataURL,
created: sceneFile.created,
hasSVGwithBitmap: ef ? ef.isSVGwithBitmap : false,
...ef ? {
isHyperLink: ef.isHyperLink || imageWithRef,
isHyperLink: ef.isHyperLink || Boolean(imageWithRef),
hyperlink: imageWithRef ? `${ef.file.path}#${ef.linkParts.ref}` : ef.hyperlink,
file: imageWithRef ? null : ef.file,
hasSVGwithBitmap: ef.isSVGwithBitmap,
latex: null,
} : {},
...equation ? {
file: null,
isHyperLink: false,
hyperlink: null,
hasSVGwithBitmap: false,
latex: equation.latex,
} : {},
};
}
}
});
} else {
Expand Down
6 changes: 6 additions & 0 deletions src/shared/Scripts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,12 @@ export class ScriptEngine {
if (!view || !script || !title) {
return;
}
//addresses the situation when after paste text element IDs are not updated to 8 characters
//linked to onPaste save issue with the false parameter
if(view.getScene().elements.some(el=>!el.isDeleted && el.type === "text" && el.id.length > 8)) {
await view.save(false, true);
}

script = script.replace(/^---.*?---\n/gs, "");
const ea = getEA(view);
this.eaInstances.push(ea);
Expand Down
30 changes: 29 additions & 1 deletion src/types/excalidrawAutomateTypes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
import { DataURL } from "@zsviczian/excalidraw/types/excalidraw/types";
import { TFile } from "obsidian";
import { FileId } from "src/core";
import { ColorMap, MimeType } from "src/shared/EmbeddedFileLoader";

export type SVGColorInfo = Map<string, {
mappedTo: string;
fill: boolean;
stroke: boolean;
}>;
}>;

export type ImageInfo = {
mimeType: MimeType,
id: FileId,
dataURL: DataURL,
created: number,
isHyperLink?: boolean,
hyperlink?: string,
file?:string | TFile,
hasSVGwithBitmap: boolean,
latex?: string,
size?: {height: number, width: number},
colorMap?: ColorMap,
}

export interface AddImageOptions {
topX: number;
topY: number;
imageFile: TFile | string;
scale?: boolean;
anchor?: boolean;
colorMap?: ColorMap;
}

0 comments on commit 5a58d17

Please sign in to comment.