mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
Compare commits
42 Commits
panel-grou
...
1.7.26
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0940a8628a | ||
|
|
46ee9e9524 | ||
|
|
c044278a4a | ||
|
|
aa9118cdae | ||
|
|
d19b32d0c4 | ||
|
|
dd7f0750fd | ||
|
|
e1330cd8bb | ||
|
|
04367bd3cd | ||
|
|
7d139462bf | ||
|
|
d8e429d815 | ||
|
|
4685a6f014 | ||
|
|
03b389a2b5 | ||
|
|
024f7979a7 | ||
|
|
f9e9ac0728 | ||
|
|
c6eb5859b5 | ||
|
|
377268f30c | ||
|
|
b23afc9621 | ||
|
|
d92c95c3fd | ||
|
|
98b39ab2b0 | ||
|
|
431d5e1104 | ||
|
|
adaf6ee0ae | ||
|
|
3d7d6df2ec | ||
|
|
71d00e0c8d | ||
|
|
ed316fc2c4 | ||
|
|
83f12a8fc5 | ||
|
|
2b7253168e | ||
|
|
70a869fa05 | ||
|
|
e66c31618b | ||
|
|
91298190dc | ||
|
|
11b4091d34 | ||
|
|
78287ab5f3 | ||
|
|
f632c709a5 | ||
|
|
2499629f17 | ||
|
|
16f2240c5b | ||
|
|
f670e3db9d | ||
|
|
b5710033bc | ||
|
|
2117844fc2 | ||
|
|
650956054f | ||
|
|
5d24e4f063 | ||
|
|
994ed375b2 | ||
|
|
3acbe2c1bd | ||
|
|
8594fbc490 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -15,4 +15,5 @@ data.json
|
||||
lib
|
||||
|
||||
#VSCode
|
||||
.vscode
|
||||
.vscode
|
||||
yarn.lock
|
||||
|
||||
@@ -17,7 +17,10 @@ Please upgrade to Obsidian v0.12.19 or higher to get the latest release.
|
||||
|[](https://youtu.be/eKFmrSQhFA4)|[](https://youtu.be/qbPIAZguJeo)|[](https://youtu.be/2Y8OhkGiTHg)|
|
||||
|[](https://youtu.be/2v9TZmQNO8c)|[](https://youtu.be/xHPGWR3m0c8)|[](https://youtu.be/gMIKXyhS-dM)|
|
||||
|[](https://youtu.be/Etskjw7a5zo)|[](https://youtu.be/4N6efq1DtH0)|[](https://youtu.be/U2LkBRBk4LY)|
|
||||
| [](https://youtu.be/qiKuqMcNWgU)|[](https://youtu.be/yZQoJg2RCKI)| |
|
||||
| [](https://youtu.be/qiKuqMcNWgU)|[](https://youtu.be/yZQoJg2RCKI)|[](https://youtu.be/6PLGHBH9VZ4) |
|
||||
|[](https://youtu.be/epYNx2FSf2w) | [](https://youtu.be/Amhlv6r9WvM) | [](https://youtu.be/r9oB1SlK1GU) |
|
||||
|[](https://youtu.be/7gJDwNgQ6NU) | | |
|
||||
|
||||
|
||||
|
||||
# Key features
|
||||
@@ -50,8 +53,8 @@ Please upgrade to Obsidian v0.12.19 or higher to get the latest release.
|
||||
- Insert LaTeX formulas using the Command Palette action "Insert LaTeX formula". You can edit formulas either in Markdown view, or by <kbd>CTRL/CMD + Click</kbd> on the formula.
|
||||
- Drag & Drop support
|
||||
- You can drag files from the Obsidian file explorer and they will become links to those files in Excalidraw.
|
||||
- Dragging image files (PNG, SVG, JPG, Excalidraw) from Obsidian's file explorer while pressing the <kbd>CTRL/CMD</kbd> button will embed the image into your drawing.
|
||||
- You can drag and drop images from outside Obsidian onto Excalidraw. These images will be embedded into your drawing and saved to Obsidian.
|
||||
- Dragging image files (PNG, SVG, JPG, ICO, GIF, WEBP, Excalidraw) from Obsidian's file explorer while pressing the <kbd>CTRL</kbd> (<kbd>SHIFT</kbd> on Mac) button will embed the image into your drawing.
|
||||
- If in addition to <kbd>CTRL</kbd> or <kbd>SHIFT</kbd> you also hold down <kbd>ALT<kbd>, the image will be inserted at 100% of its size. ⚠ Note: this is a very niche feature with a very particular behavior that I built primarily for myself (even more so than other features in Excalidraw Obsidian - also built primarily for myself 😉)... This will reset your embedded image to 100% size every time you open the Excalidraw drawing, or in case you have embedded an Excalidraw drawing on your canvas inserted using this function, every time you update the embedded drawing, it will be scaled back to 100% size. This means that even if you resize the image on the drawing, it will reset to 100% the next time you open the file or you modify the original embedded object. This feature is useful when you decompose a drawing into separate Excalidraw files, but when combined onto a single canvas you want the individual pieces to maintain their actual sizes. I use this feature to construct Book-on-a-Page summaries from atomic drawings.
|
||||
- You can drag and drop text from Markdown views onto Excalidraw.
|
||||
- You can drag and drop web addresses from your browser and they will become links.
|
||||
- Image support
|
||||
|
||||
@@ -362,7 +362,7 @@ export declare class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
* 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.
|
||||
* In case you want to prevent the excalidraw onLinkHover action you must return true, it will stop the native excalidraw onLinkHover management flow.
|
||||
*/
|
||||
onLinkHoverHook: (element: NonDeletedExcalidrawElement, linkText: string, view: ExcalidrawView, ea: ExcalidrawAutomate) => boolean;
|
||||
/**
|
||||
|
||||
@@ -16,274 +16,37 @@ The color conversion method was copied from [color-convert](https://github.com/Q
|
||||
```javascript
|
||||
*/
|
||||
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.7.19")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
let settings = ea.getScriptSettings();
|
||||
//set default values on first run
|
||||
if(!settings["Step size"]) {
|
||||
settings = {
|
||||
"Step size" : {
|
||||
value: 2,
|
||||
description: "Step size in percentage for making the color darker"
|
||||
}
|
||||
};
|
||||
ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
const step = settings["Step size"].value;
|
||||
|
||||
const elements = ea
|
||||
.getViewSelectedElements()
|
||||
.filter((el) =>
|
||||
["rectangle", "ellipse", "diamond", "image", "line"].includes(el.type)
|
||||
["rectangle", "ellipse", "diamond", "image", "line", "freedraw"].includes(el.type)
|
||||
);
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
for (const el of ea.getElements()) {
|
||||
const color = colorNameToHex(el.backgroundColor);
|
||||
const rgbColor = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
|
||||
if (rgbColor) {
|
||||
const r = parseInt(rgbColor[1], 16);
|
||||
const g = parseInt(rgbColor[2], 16);
|
||||
const b = parseInt(rgbColor[3], 16);
|
||||
const originalRgb = [r, g, b];
|
||||
const hsl = rgbToHsl(originalRgb);
|
||||
const step = 2;
|
||||
const newLightness = hsl[2] - step;
|
||||
if (newLightness > 0) {
|
||||
hsl[2] = newLightness;
|
||||
}
|
||||
const newRgb = hslToRgb(hsl);
|
||||
el.backgroundColor = "#" + rgbToHexString(newRgb);
|
||||
const color = ea.colorNameToHex(el.backgroundColor);
|
||||
const cm = ea.getCM(color);
|
||||
if (cm) {
|
||||
const darker = cm.darkerBy(step);
|
||||
if(Math.floor(darker.lightness)>0) el.backgroundColor = darker.stringHSL();
|
||||
}
|
||||
}
|
||||
await ea.addElementsToView(false, false);
|
||||
|
||||
function rgbToHexString(args) {
|
||||
const integer =
|
||||
((Math.round(args[0]) & 0xff) << 16) +
|
||||
((Math.round(args[1]) & 0xff) << 8) +
|
||||
(Math.round(args[2]) & 0xff);
|
||||
|
||||
const string = integer.toString(16).toUpperCase();
|
||||
return "000000".substring(string.length) + string;
|
||||
}
|
||||
|
||||
function hslToRgb(hsl) {
|
||||
const h = hsl[0] / 360;
|
||||
const s = hsl[1] / 100;
|
||||
const l = hsl[2] / 100;
|
||||
let t2;
|
||||
let t3;
|
||||
let val;
|
||||
|
||||
if (s === 0) {
|
||||
val = l * 255;
|
||||
return [val, val, val];
|
||||
}
|
||||
|
||||
if (l < 0.5) {
|
||||
t2 = l * (1 + s);
|
||||
} else {
|
||||
t2 = l + s - l * s;
|
||||
}
|
||||
|
||||
const t1 = 2 * l - t2;
|
||||
|
||||
const rgb = [0, 0, 0];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
t3 = h + (1 / 3) * -(i - 1);
|
||||
if (t3 < 0) {
|
||||
t3++;
|
||||
}
|
||||
|
||||
if (t3 > 1) {
|
||||
t3--;
|
||||
}
|
||||
|
||||
if (6 * t3 < 1) {
|
||||
val = t1 + (t2 - t1) * 6 * t3;
|
||||
} else if (2 * t3 < 1) {
|
||||
val = t2;
|
||||
} else if (3 * t3 < 2) {
|
||||
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
|
||||
} else {
|
||||
val = t1;
|
||||
}
|
||||
|
||||
rgb[i] = val * 255;
|
||||
}
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
function rgbToHsl(rgb) {
|
||||
const r = rgb[0] / 255;
|
||||
const g = rgb[1] / 255;
|
||||
const b = rgb[2] / 255;
|
||||
const min = Math.min(r, g, b);
|
||||
const max = Math.max(r, g, b);
|
||||
const delta = max - min;
|
||||
let h;
|
||||
let s;
|
||||
|
||||
if (max === min) {
|
||||
h = 0;
|
||||
} else if (r === max) {
|
||||
h = (g - b) / delta;
|
||||
} else if (g === max) {
|
||||
h = 2 + (b - r) / delta;
|
||||
} else if (b === max) {
|
||||
h = 4 + (r - g) / delta;
|
||||
}
|
||||
|
||||
h = Math.min(h * 60, 360);
|
||||
|
||||
if (h < 0) {
|
||||
h += 360;
|
||||
}
|
||||
|
||||
const l = (min + max) / 2;
|
||||
|
||||
if (max === min) {
|
||||
s = 0;
|
||||
} else if (l <= 0.5) {
|
||||
s = delta / (max + min);
|
||||
} else {
|
||||
s = delta / (2 - max - min);
|
||||
}
|
||||
|
||||
return [h, s * 100, l * 100];
|
||||
}
|
||||
|
||||
function colorNameToHex(color) {
|
||||
const colors = {
|
||||
aliceblue: "#f0f8ff",
|
||||
antiquewhite: "#faebd7",
|
||||
aqua: "#00ffff",
|
||||
aquamarine: "#7fffd4",
|
||||
azure: "#f0ffff",
|
||||
beige: "#f5f5dc",
|
||||
bisque: "#ffe4c4",
|
||||
black: "#000000",
|
||||
blanchedalmond: "#ffebcd",
|
||||
blue: "#0000ff",
|
||||
blueviolet: "#8a2be2",
|
||||
brown: "#a52a2a",
|
||||
burlywood: "#deb887",
|
||||
cadetblue: "#5f9ea0",
|
||||
chartreuse: "#7fff00",
|
||||
chocolate: "#d2691e",
|
||||
coral: "#ff7f50",
|
||||
cornflowerblue: "#6495ed",
|
||||
cornsilk: "#fff8dc",
|
||||
crimson: "#dc143c",
|
||||
cyan: "#00ffff",
|
||||
darkblue: "#00008b",
|
||||
darkcyan: "#008b8b",
|
||||
darkgoldenrod: "#b8860b",
|
||||
darkgray: "#a9a9a9",
|
||||
darkgreen: "#006400",
|
||||
darkkhaki: "#bdb76b",
|
||||
darkmagenta: "#8b008b",
|
||||
darkolivegreen: "#556b2f",
|
||||
darkorange: "#ff8c00",
|
||||
darkorchid: "#9932cc",
|
||||
darkred: "#8b0000",
|
||||
darksalmon: "#e9967a",
|
||||
darkseagreen: "#8fbc8f",
|
||||
darkslateblue: "#483d8b",
|
||||
darkslategray: "#2f4f4f",
|
||||
darkturquoise: "#00ced1",
|
||||
darkviolet: "#9400d3",
|
||||
deeppink: "#ff1493",
|
||||
deepskyblue: "#00bfff",
|
||||
dimgray: "#696969",
|
||||
dodgerblue: "#1e90ff",
|
||||
firebrick: "#b22222",
|
||||
floralwhite: "#fffaf0",
|
||||
forestgreen: "#228b22",
|
||||
fuchsia: "#ff00ff",
|
||||
gainsboro: "#dcdcdc",
|
||||
ghostwhite: "#f8f8ff",
|
||||
gold: "#ffd700",
|
||||
goldenrod: "#daa520",
|
||||
gray: "#808080",
|
||||
green: "#008000",
|
||||
greenyellow: "#adff2f",
|
||||
honeydew: "#f0fff0",
|
||||
hotpink: "#ff69b4",
|
||||
"indianred ": "#cd5c5c",
|
||||
indigo: "#4b0082",
|
||||
ivory: "#fffff0",
|
||||
khaki: "#f0e68c",
|
||||
lavender: "#e6e6fa",
|
||||
lavenderblush: "#fff0f5",
|
||||
lawngreen: "#7cfc00",
|
||||
lemonchiffon: "#fffacd",
|
||||
lightblue: "#add8e6",
|
||||
lightcoral: "#f08080",
|
||||
lightcyan: "#e0ffff",
|
||||
lightgoldenrodyellow: "#fafad2",
|
||||
lightgrey: "#d3d3d3",
|
||||
lightgreen: "#90ee90",
|
||||
lightpink: "#ffb6c1",
|
||||
lightsalmon: "#ffa07a",
|
||||
lightseagreen: "#20b2aa",
|
||||
lightskyblue: "#87cefa",
|
||||
lightslategray: "#778899",
|
||||
lightsteelblue: "#b0c4de",
|
||||
lightyellow: "#ffffe0",
|
||||
lime: "#00ff00",
|
||||
limegreen: "#32cd32",
|
||||
linen: "#faf0e6",
|
||||
magenta: "#ff00ff",
|
||||
maroon: "#800000",
|
||||
mediumaquamarine: "#66cdaa",
|
||||
mediumblue: "#0000cd",
|
||||
mediumorchid: "#ba55d3",
|
||||
mediumpurple: "#9370d8",
|
||||
mediumseagreen: "#3cb371",
|
||||
mediumslateblue: "#7b68ee",
|
||||
mediumspringgreen: "#00fa9a",
|
||||
mediumturquoise: "#48d1cc",
|
||||
mediumvioletred: "#c71585",
|
||||
midnightblue: "#191970",
|
||||
mintcream: "#f5fffa",
|
||||
mistyrose: "#ffe4e1",
|
||||
moccasin: "#ffe4b5",
|
||||
navajowhite: "#ffdead",
|
||||
navy: "#000080",
|
||||
oldlace: "#fdf5e6",
|
||||
olive: "#808000",
|
||||
olivedrab: "#6b8e23",
|
||||
orange: "#ffa500",
|
||||
orangered: "#ff4500",
|
||||
orchid: "#da70d6",
|
||||
palegoldenrod: "#eee8aa",
|
||||
palegreen: "#98fb98",
|
||||
paleturquoise: "#afeeee",
|
||||
palevioletred: "#d87093",
|
||||
papayawhip: "#ffefd5",
|
||||
peachpuff: "#ffdab9",
|
||||
peru: "#cd853f",
|
||||
pink: "#ffc0cb",
|
||||
plum: "#dda0dd",
|
||||
powderblue: "#b0e0e6",
|
||||
purple: "#800080",
|
||||
rebeccapurple: "#663399",
|
||||
red: "#ff0000",
|
||||
rosybrown: "#bc8f8f",
|
||||
royalblue: "#4169e1",
|
||||
saddlebrown: "#8b4513",
|
||||
salmon: "#fa8072",
|
||||
sandybrown: "#f4a460",
|
||||
seagreen: "#2e8b57",
|
||||
seashell: "#fff5ee",
|
||||
sienna: "#a0522d",
|
||||
silver: "#c0c0c0",
|
||||
skyblue: "#87ceeb",
|
||||
slateblue: "#6a5acd",
|
||||
slategray: "#708090",
|
||||
snow: "#fffafa",
|
||||
springgreen: "#00ff7f",
|
||||
steelblue: "#4682b4",
|
||||
tan: "#d2b48c",
|
||||
teal: "#008080",
|
||||
thistle: "#d8bfd8",
|
||||
tomato: "#ff6347",
|
||||
turquoise: "#40e0d0",
|
||||
violet: "#ee82ee",
|
||||
wheat: "#f5deb3",
|
||||
white: "#ffffff",
|
||||
whitesmoke: "#f5f5f5",
|
||||
yellow: "#ffff00",
|
||||
yellowgreen: "#9acd32",
|
||||
};
|
||||
if (typeof colors[color.toLowerCase()] != "undefined")
|
||||
return colors[color.toLowerCase()];
|
||||
return color;
|
||||
}
|
||||
|
||||
@@ -16,274 +16,37 @@ The color conversion method was copied from [color-convert](https://github.com/Q
|
||||
```javascript
|
||||
*/
|
||||
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.7.19")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
let settings = ea.getScriptSettings();
|
||||
//set default values on first run
|
||||
if(!settings["Step size"]) {
|
||||
settings = {
|
||||
"Step size" : {
|
||||
value: 2,
|
||||
description: "Step size in percentage for making the color lighter"
|
||||
}
|
||||
};
|
||||
ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
const step = settings["Step size"].value;
|
||||
|
||||
const elements = ea
|
||||
.getViewSelectedElements()
|
||||
.filter((el) =>
|
||||
["rectangle", "ellipse", "diamond", "image", "line"].includes(el.type)
|
||||
["rectangle", "ellipse", "diamond", "image", "line", "freedraw"].includes(el.type)
|
||||
);
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
for (const el of ea.getElements()) {
|
||||
const color = colorNameToHex(el.backgroundColor);
|
||||
const rgbColor = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
|
||||
if (rgbColor) {
|
||||
const r = parseInt(rgbColor[1], 16);
|
||||
const g = parseInt(rgbColor[2], 16);
|
||||
const b = parseInt(rgbColor[3], 16);
|
||||
const originalRgb = [r, g, b];
|
||||
const hsl = rgbToHsl(originalRgb);
|
||||
const step = 2;
|
||||
const newLightness = hsl[2] + step;
|
||||
if (newLightness < 100) {
|
||||
hsl[2] = newLightness;
|
||||
}
|
||||
const newRgb = hslToRgb(hsl);
|
||||
el.backgroundColor = "#" + rgbToHexString(newRgb);
|
||||
const color = ea.colorNameToHex(el.backgroundColor);
|
||||
const cm = ea.getCM(color);
|
||||
if (cm) {
|
||||
const lighter = cm.lighterBy(step);
|
||||
if(Math.ceil(lighter.lightness)<100) el.backgroundColor = lighter.stringHSL();
|
||||
}
|
||||
}
|
||||
await ea.addElementsToView(false, false);
|
||||
|
||||
function rgbToHexString(args) {
|
||||
const integer =
|
||||
((Math.round(args[0]) & 0xff) << 16) +
|
||||
((Math.round(args[1]) & 0xff) << 8) +
|
||||
(Math.round(args[2]) & 0xff);
|
||||
|
||||
const string = integer.toString(16).toUpperCase();
|
||||
return "000000".substring(string.length) + string;
|
||||
}
|
||||
|
||||
function hslToRgb(hsl) {
|
||||
const h = hsl[0] / 360;
|
||||
const s = hsl[1] / 100;
|
||||
const l = hsl[2] / 100;
|
||||
let t2;
|
||||
let t3;
|
||||
let val;
|
||||
|
||||
if (s === 0) {
|
||||
val = l * 255;
|
||||
return [val, val, val];
|
||||
}
|
||||
|
||||
if (l < 0.5) {
|
||||
t2 = l * (1 + s);
|
||||
} else {
|
||||
t2 = l + s - l * s;
|
||||
}
|
||||
|
||||
const t1 = 2 * l - t2;
|
||||
|
||||
const rgb = [0, 0, 0];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
t3 = h + (1 / 3) * -(i - 1);
|
||||
if (t3 < 0) {
|
||||
t3++;
|
||||
}
|
||||
|
||||
if (t3 > 1) {
|
||||
t3--;
|
||||
}
|
||||
|
||||
if (6 * t3 < 1) {
|
||||
val = t1 + (t2 - t1) * 6 * t3;
|
||||
} else if (2 * t3 < 1) {
|
||||
val = t2;
|
||||
} else if (3 * t3 < 2) {
|
||||
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
|
||||
} else {
|
||||
val = t1;
|
||||
}
|
||||
|
||||
rgb[i] = val * 255;
|
||||
}
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
function rgbToHsl(rgb) {
|
||||
const r = rgb[0] / 255;
|
||||
const g = rgb[1] / 255;
|
||||
const b = rgb[2] / 255;
|
||||
const min = Math.min(r, g, b);
|
||||
const max = Math.max(r, g, b);
|
||||
const delta = max - min;
|
||||
let h;
|
||||
let s;
|
||||
|
||||
if (max === min) {
|
||||
h = 0;
|
||||
} else if (r === max) {
|
||||
h = (g - b) / delta;
|
||||
} else if (g === max) {
|
||||
h = 2 + (b - r) / delta;
|
||||
} else if (b === max) {
|
||||
h = 4 + (r - g) / delta;
|
||||
}
|
||||
|
||||
h = Math.min(h * 60, 360);
|
||||
|
||||
if (h < 0) {
|
||||
h += 360;
|
||||
}
|
||||
|
||||
const l = (min + max) / 2;
|
||||
|
||||
if (max === min) {
|
||||
s = 0;
|
||||
} else if (l <= 0.5) {
|
||||
s = delta / (max + min);
|
||||
} else {
|
||||
s = delta / (2 - max - min);
|
||||
}
|
||||
|
||||
return [h, s * 100, l * 100];
|
||||
}
|
||||
|
||||
function colorNameToHex(color) {
|
||||
const colors = {
|
||||
aliceblue: "#f0f8ff",
|
||||
antiquewhite: "#faebd7",
|
||||
aqua: "#00ffff",
|
||||
aquamarine: "#7fffd4",
|
||||
azure: "#f0ffff",
|
||||
beige: "#f5f5dc",
|
||||
bisque: "#ffe4c4",
|
||||
black: "#000000",
|
||||
blanchedalmond: "#ffebcd",
|
||||
blue: "#0000ff",
|
||||
blueviolet: "#8a2be2",
|
||||
brown: "#a52a2a",
|
||||
burlywood: "#deb887",
|
||||
cadetblue: "#5f9ea0",
|
||||
chartreuse: "#7fff00",
|
||||
chocolate: "#d2691e",
|
||||
coral: "#ff7f50",
|
||||
cornflowerblue: "#6495ed",
|
||||
cornsilk: "#fff8dc",
|
||||
crimson: "#dc143c",
|
||||
cyan: "#00ffff",
|
||||
darkblue: "#00008b",
|
||||
darkcyan: "#008b8b",
|
||||
darkgoldenrod: "#b8860b",
|
||||
darkgray: "#a9a9a9",
|
||||
darkgreen: "#006400",
|
||||
darkkhaki: "#bdb76b",
|
||||
darkmagenta: "#8b008b",
|
||||
darkolivegreen: "#556b2f",
|
||||
darkorange: "#ff8c00",
|
||||
darkorchid: "#9932cc",
|
||||
darkred: "#8b0000",
|
||||
darksalmon: "#e9967a",
|
||||
darkseagreen: "#8fbc8f",
|
||||
darkslateblue: "#483d8b",
|
||||
darkslategray: "#2f4f4f",
|
||||
darkturquoise: "#00ced1",
|
||||
darkviolet: "#9400d3",
|
||||
deeppink: "#ff1493",
|
||||
deepskyblue: "#00bfff",
|
||||
dimgray: "#696969",
|
||||
dodgerblue: "#1e90ff",
|
||||
firebrick: "#b22222",
|
||||
floralwhite: "#fffaf0",
|
||||
forestgreen: "#228b22",
|
||||
fuchsia: "#ff00ff",
|
||||
gainsboro: "#dcdcdc",
|
||||
ghostwhite: "#f8f8ff",
|
||||
gold: "#ffd700",
|
||||
goldenrod: "#daa520",
|
||||
gray: "#808080",
|
||||
green: "#008000",
|
||||
greenyellow: "#adff2f",
|
||||
honeydew: "#f0fff0",
|
||||
hotpink: "#ff69b4",
|
||||
"indianred ": "#cd5c5c",
|
||||
indigo: "#4b0082",
|
||||
ivory: "#fffff0",
|
||||
khaki: "#f0e68c",
|
||||
lavender: "#e6e6fa",
|
||||
lavenderblush: "#fff0f5",
|
||||
lawngreen: "#7cfc00",
|
||||
lemonchiffon: "#fffacd",
|
||||
lightblue: "#add8e6",
|
||||
lightcoral: "#f08080",
|
||||
lightcyan: "#e0ffff",
|
||||
lightgoldenrodyellow: "#fafad2",
|
||||
lightgrey: "#d3d3d3",
|
||||
lightgreen: "#90ee90",
|
||||
lightpink: "#ffb6c1",
|
||||
lightsalmon: "#ffa07a",
|
||||
lightseagreen: "#20b2aa",
|
||||
lightskyblue: "#87cefa",
|
||||
lightslategray: "#778899",
|
||||
lightsteelblue: "#b0c4de",
|
||||
lightyellow: "#ffffe0",
|
||||
lime: "#00ff00",
|
||||
limegreen: "#32cd32",
|
||||
linen: "#faf0e6",
|
||||
magenta: "#ff00ff",
|
||||
maroon: "#800000",
|
||||
mediumaquamarine: "#66cdaa",
|
||||
mediumblue: "#0000cd",
|
||||
mediumorchid: "#ba55d3",
|
||||
mediumpurple: "#9370d8",
|
||||
mediumseagreen: "#3cb371",
|
||||
mediumslateblue: "#7b68ee",
|
||||
mediumspringgreen: "#00fa9a",
|
||||
mediumturquoise: "#48d1cc",
|
||||
mediumvioletred: "#c71585",
|
||||
midnightblue: "#191970",
|
||||
mintcream: "#f5fffa",
|
||||
mistyrose: "#ffe4e1",
|
||||
moccasin: "#ffe4b5",
|
||||
navajowhite: "#ffdead",
|
||||
navy: "#000080",
|
||||
oldlace: "#fdf5e6",
|
||||
olive: "#808000",
|
||||
olivedrab: "#6b8e23",
|
||||
orange: "#ffa500",
|
||||
orangered: "#ff4500",
|
||||
orchid: "#da70d6",
|
||||
palegoldenrod: "#eee8aa",
|
||||
palegreen: "#98fb98",
|
||||
paleturquoise: "#afeeee",
|
||||
palevioletred: "#d87093",
|
||||
papayawhip: "#ffefd5",
|
||||
peachpuff: "#ffdab9",
|
||||
peru: "#cd853f",
|
||||
pink: "#ffc0cb",
|
||||
plum: "#dda0dd",
|
||||
powderblue: "#b0e0e6",
|
||||
purple: "#800080",
|
||||
rebeccapurple: "#663399",
|
||||
red: "#ff0000",
|
||||
rosybrown: "#bc8f8f",
|
||||
royalblue: "#4169e1",
|
||||
saddlebrown: "#8b4513",
|
||||
salmon: "#fa8072",
|
||||
sandybrown: "#f4a460",
|
||||
seagreen: "#2e8b57",
|
||||
seashell: "#fff5ee",
|
||||
sienna: "#a0522d",
|
||||
silver: "#c0c0c0",
|
||||
skyblue: "#87ceeb",
|
||||
slateblue: "#6a5acd",
|
||||
slategray: "#708090",
|
||||
snow: "#fffafa",
|
||||
springgreen: "#00ff7f",
|
||||
steelblue: "#4682b4",
|
||||
tan: "#d2b48c",
|
||||
teal: "#008080",
|
||||
thistle: "#d8bfd8",
|
||||
tomato: "#ff6347",
|
||||
turquoise: "#40e0d0",
|
||||
violet: "#ee82ee",
|
||||
wheat: "#f5deb3",
|
||||
white: "#ffffff",
|
||||
whitesmoke: "#f5f5f5",
|
||||
yellow: "#ffff00",
|
||||
yellowgreen: "#9acd32",
|
||||
};
|
||||
if (typeof colors[color.toLowerCase()] != "undefined")
|
||||
return colors[color.toLowerCase()];
|
||||
return color;
|
||||
}
|
||||
|
||||
188
ea-scripts/Palette loader.md
Normal file
188
ea-scripts/Palette loader.md
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
Design your palette at http://paletton.com/
|
||||
Once you are happy with your colors, click Tables/Export in the bottom right of the screen:
|
||||

|
||||
Then click "Color swatches/as Sketch Palette"
|
||||

|
||||
Copy the contents of the page to a markdown file in your vault. Place the file in the Excalidraw/Palettes folder (you can change this folder in settings).
|
||||

|
||||

|
||||
|
||||
```javascript
|
||||
*/
|
||||
//--------------------------
|
||||
// Load settings
|
||||
//--------------------------
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.7.19")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
const api = ea.getExcalidrawAPI();
|
||||
let settings = ea.getScriptSettings();
|
||||
//set default values on first run
|
||||
if(!settings["Palette folder"]) {
|
||||
settings = {
|
||||
"Palette folder" : {
|
||||
value: "Excalidraw/Palettes",
|
||||
description: "The path to the folder where you store the Excalidraw Palettes"
|
||||
},
|
||||
"Light-gray" : {
|
||||
value: "#505050",
|
||||
description: "Base light-gray used for mixing with the accent color to generate the palette light-gray"
|
||||
},
|
||||
"Dark-gray" : {
|
||||
value: "#e0e0e0",
|
||||
description: "Base dark-gray used for mixing with the accent color to generate the palette dark-gray"
|
||||
}
|
||||
};
|
||||
ea.setScriptSettings(settings);
|
||||
}
|
||||
|
||||
const lightGray = settings["Light-gray"].value;
|
||||
const darkGray = settings["Dark-gray"].value;
|
||||
|
||||
let paletteFolder = settings["Palette folder"].value.toLowerCase();
|
||||
if(paletteFolder === "" || paletteFolder === "/") {
|
||||
new Notice("The palette folder cannot be the root folder of your vault");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!paletteFolder.endsWith("/")) paletteFolder += "/";
|
||||
|
||||
|
||||
//--------------------------
|
||||
// Select palette
|
||||
//--------------------------
|
||||
const palettes = app.vault.getFiles()
|
||||
.filter(f=>f.extension === "md" && f.path.toLowerCase() === paletteFolder + f.name.toLowerCase())
|
||||
.sort((a,b)=>a.basename.toLowerCase()<b.basename.toLowerCase()?-1:1);
|
||||
const file = await utils.suggester(["Excalidraw Default"].concat(palettes.map(f=>f.name)),["Default"].concat(palettes), "Choose a palette, press ESC to abort");
|
||||
if(!file) return;
|
||||
|
||||
if(file === "Default") {
|
||||
api.updateScene({
|
||||
appState: {
|
||||
colorPalette: {}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
//--------------------------
|
||||
// Load palette
|
||||
//--------------------------
|
||||
const sketchPalette = await app.vault.read(file);
|
||||
|
||||
const parseJSON = (data) => {
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const loadPaletteFromPlainText = (data) => {
|
||||
const colors = [];
|
||||
data.replaceAll("\r","").split("\n").forEach(c=>{
|
||||
c = c.trim();
|
||||
if(c==="") return;
|
||||
if(c.match(/[^hslrga-fA-F\(\d\.\,\%\s)#]/)) return;
|
||||
const cm = ea.getCM(c);
|
||||
if(cm) colors.push(cm.stringHEX({alpha: false}));
|
||||
})
|
||||
return colors;
|
||||
}
|
||||
|
||||
const paletteJSON = parseJSON(sketchPalette);
|
||||
|
||||
const colors = paletteJSON
|
||||
? paletteJSON.colors.map(c=>ea.getCM({r:c.red*255,g:c.green*255,b:c.blue*255,a:c.alpha}).stringHEX({alpha: false}))
|
||||
: loadPaletteFromPlainText(sketchPalette);
|
||||
const baseColor = ea.getCM(colors[0]);
|
||||
|
||||
// Add black, white, transparent, gary
|
||||
const palette = [[
|
||||
"transparent",
|
||||
"black",
|
||||
baseColor.mix({color: lightGray, ratio:0.95}).stringHEX({alpha: false}),
|
||||
baseColor.mix({color: darkGray, ratio:0.95}).stringHEX({alpha: false}),
|
||||
"white"
|
||||
]];
|
||||
|
||||
// Create Excalidraw palette
|
||||
for(i=0;i<Math.floor(colors.length/5);i++) {
|
||||
palette.push([
|
||||
colors[i*5+1],
|
||||
colors[i*5+2],
|
||||
colors[i*5],
|
||||
colors[i*5+3],
|
||||
colors[i*5+4]
|
||||
]);
|
||||
}
|
||||
|
||||
const paletteSize = palette.flat().length;
|
||||
const newPalette = {
|
||||
canvasBackground: palette.flat(),
|
||||
elementStroke: palette.flat(),
|
||||
elementBackground: palette.flat()
|
||||
};
|
||||
|
||||
|
||||
//--------------------------
|
||||
// Check if palette has the same size as the current. Is re-paint possible?
|
||||
//--------------------------
|
||||
const oldPalette = api.getAppState().colorPalette;
|
||||
|
||||
//You can only switch and repaint equal size palettes
|
||||
let canRepaint = Object.keys(oldPalette).length === 3 &&
|
||||
oldPalette.canvasBackground.length === paletteSize &&
|
||||
oldPalette.elementBackground.length === paletteSize &&
|
||||
oldPalette.elementStroke.length === paletteSize;
|
||||
|
||||
//Check that the palette for canvas background, element stroke and element background are the same
|
||||
for(i=0;canRepaint && i<paletteSize;i++) {
|
||||
if(
|
||||
oldPalette.canvasBackground[i] !== oldPalette.elementBackground[i] ||
|
||||
oldPalette.canvasBackground[i] !== oldPalette.elementStroke[i]
|
||||
) {
|
||||
canRepaint = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const shouldRepaint = canRepaint && await utils.suggester(["Try repainting the drawing with the new palette","Just load the new palette"], [true, false],"ESC will load the palette without repainting");
|
||||
|
||||
|
||||
//--------------------------
|
||||
// Apply palette
|
||||
//--------------------------
|
||||
if(shouldRepaint) {
|
||||
const map = new Map();
|
||||
for(i=0;i<paletteSize;i++) {
|
||||
map.set(oldPalette.canvasBackground[i],newPalette.canvasBackground[i])
|
||||
}
|
||||
|
||||
ea.copyViewElementsToEAforEditing(ea.getViewElements());
|
||||
ea.getElements().forEach(el=>{
|
||||
el.strokeColor = map.get(el.strokeColor)??el.strokeColor;
|
||||
el.backgroundColor = map.get(el.backgroundColor)??el.backgroundColor;
|
||||
})
|
||||
|
||||
const canvasColor = api.getAppState().viewBackgroundColor;
|
||||
|
||||
await api.updateScene({
|
||||
appState: {
|
||||
colorPalette: newPalette,
|
||||
viewBackgroundColor: map.get(canvasColor)??canvasColor
|
||||
}
|
||||
});
|
||||
|
||||
ea.addElementsToView();
|
||||
} else {
|
||||
api.updateScene({
|
||||
appState: {
|
||||
colorPalette: newPalette
|
||||
}
|
||||
});
|
||||
}
|
||||
1
ea-scripts/Palette loader.svg
Normal file
1
ea-scripts/Palette loader.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M512 255.1C512 256.9 511.1 257.8 511.1 258.7C511.6 295.2 478.4 319.1 441.9 319.1H344C317.5 319.1 296 341.5 296 368C296 371.4 296.4 374.7 297 377.9C299.2 388.1 303.5 397.1 307.9 407.8C313.9 421.6 320 435.3 320 449.8C320 481.7 298.4 510.5 266.6 511.8C263.1 511.9 259.5 512 256 512C114.6 512 0 397.4 0 256C0 114.6 114.6 0 256 0C397.4 0 512 114.6 512 256V255.1zM96 255.1C78.33 255.1 64 270.3 64 287.1C64 305.7 78.33 319.1 96 319.1C113.7 319.1 128 305.7 128 287.1C128 270.3 113.7 255.1 96 255.1zM128 191.1C145.7 191.1 160 177.7 160 159.1C160 142.3 145.7 127.1 128 127.1C110.3 127.1 96 142.3 96 159.1C96 177.7 110.3 191.1 128 191.1zM256 63.1C238.3 63.1 224 78.33 224 95.1C224 113.7 238.3 127.1 256 127.1C273.7 127.1 288 113.7 288 95.1C288 78.33 273.7 63.1 256 63.1zM384 191.1C401.7 191.1 416 177.7 416 159.1C416 142.3 401.7 127.1 384 127.1C366.3 127.1 352 142.3 352 159.1C352 177.7 366.3 191.1 384 191.1z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
29
ea-scripts/Rename Image.md
Normal file
29
ea-scripts/Rename Image.md
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
|
||||

|
||||
|
||||
Select an image on the canvas and run the script. You will be prompted to provide a new filename / filepath. This cuts down the time to name images you paste from the web or drag and drop from your file system.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
await ea.addElementsToView(); //to ensure all images are saved into the file
|
||||
|
||||
const img = ea.getViewSelectedElements().filter(el=>el.type === "image");
|
||||
if(img.length === 0) {
|
||||
new Notice("No image is selected");
|
||||
return;
|
||||
}
|
||||
|
||||
for(i of img) {
|
||||
const currentPath = ea.plugin.filesMaster.get(i.fileId).path;
|
||||
const file = app.vault.getAbstractFileByPath(currentPath);
|
||||
if(!file) {
|
||||
new Notice("Can't find file: " + currentPath);
|
||||
continue;
|
||||
}
|
||||
const pathNoExtension = file.path.substring(0,file.path.length-file.extension.length-1);
|
||||
const newPath = await utils.inputPrompt("Please provide the filename","file path",pathNoExtension);
|
||||
if(newPath && newPath !== pathNoExtension) {
|
||||
await app.fileManager.renameFile(file,`${newPath}.${file.extension}`);
|
||||
}
|
||||
}
|
||||
1
ea-scripts/Rename Image.svg
Normal file
1
ea-scripts/Rename Image.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" stroke="#000" viewBox="0 0 122.88 102.06"><path stroke-linecap="round" stroke-width="4" d="M8.18,23.12h67.09v5.39H8.18c-0.77,0-1.47,0.31-1.98,0.82c-0.5,0.51-0.82,1.21-0.82,1.98v39.46c0,0.77,0.31,1.47,0.82,1.98 c0.51,0.5,1.21,0.82,1.98,0.82h67.09v5.39H8.18c-2.24,0-4.29-0.92-5.77-2.4L2.4,76.53C0.92,75.05,0,73.01,0,70.76V31.3 c0-2.24,0.92-4.29,2.4-5.77l0.01-0.01C3.89,24.04,5.94,23.12,8.18,23.12L8.18,23.12z M71.77,53.85c-1.52,0-2.75-1.23-2.75-2.75 c0-1.52,1.23-2.75,2.75-2.75h12.78V18.04c-0.39-3.8-1.56-6.62-3.34-8.6c-1.93-2.16-4.67-3.43-7.99-3.98 c-1.49-0.24-2.51-1.65-2.26-3.15c0.24-1.49,1.65-2.51,3.15-2.26c4.54,0.75,8.37,2.57,11.19,5.74c0.72,0.8,1.37,1.69,1.94,2.66 c0.72-1.25,1.58-2.35,2.56-3.32c2.94-2.92,6.88-4.51,11.59-5.1c1.51-0.18,2.88,0.89,3.06,2.4c0.18,1.51-0.89,2.88-2.4,3.06 c-3.52,0.44-6.38,1.54-8.39,3.53c-1.99,1.97-3.25,4.91-3.61,9.04v5.07h24.65c2.24,0,4.29,0.92,5.77,2.4l0.01,0.01 c1.48,1.48,2.4,3.53,2.4,5.77v39.46c0,2.24-0.92,4.29-2.4,5.77l-0.01,0.01c-1.48,1.48-3.53,2.4-5.77,2.4H90.05v5.07 c0.36,4.13,1.62,7.08,3.61,9.04c2,1.98,4.86,3.09,8.39,3.53c1.51,0.18,2.58,1.56,2.4,3.06c-0.18,1.51-1.55,2.58-3.06,2.4 c-4.7-0.59-8.65-2.18-11.59-5.1c-0.98-0.97-1.84-2.07-2.56-3.32c-0.57,0.97-1.22,1.85-1.94,2.66c-2.83,3.16-6.66,4.99-11.19,5.74 c-1.49,0.24-2.9-0.77-3.15-2.26c-0.24-1.49,0.77-2.9,2.26-3.15c3.32-0.55,6.06-1.81,7.99-3.98c1.78-1.99,2.94-4.81,3.34-8.6 l0-30.17H71.77L71.77,53.85L71.77,53.85z M90.05,28.5v19.84h12.98c1.52,0,2.75,1.23,2.75,2.75c0,1.52-1.23,2.75-2.75,2.75H90.05 v19.71h24.65c0.77,0,1.47-0.31,1.98-0.82c0.5-0.51,0.82-1.21,0.82-1.98V31.3c0-0.77-0.31-1.47-0.82-1.98 c-0.51-0.5-1.21-0.82-1.98-0.82H90.05L90.05,28.5z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -14,6 +14,11 @@ https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.h
|
||||
```javascript
|
||||
*/
|
||||
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.7.19")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
|
||||
let repeatNum = parseInt(await utils.inputPrompt("repeat times?","number","5"));
|
||||
if(!repeatNum) {
|
||||
new Notice("Please enter a number.");
|
||||
@@ -43,38 +48,25 @@ const heightDistance = selectedElements[1].height - selectedElements[0].height;
|
||||
const angleDistance = selectedElements[1].angle - selectedElements[0].angle;
|
||||
|
||||
const bgColor1 = ea.colorNameToHex(selectedElements[0].backgroundColor);
|
||||
const rgbBgColor1 = parseColorString(bgColor1);
|
||||
const cmBgColor1 = ea.getCM(bgColor1);
|
||||
const bgColor2 = ea.colorNameToHex(selectedElements[1].backgroundColor);
|
||||
const rgbBgColor2 = parseColorString(bgColor2);
|
||||
let bgHDistance = 0;
|
||||
let bgSDistance = 0;
|
||||
let bgLDistance = 0;
|
||||
|
||||
if(rgbBgColor1 && rgbBgColor2) {
|
||||
const bgHsl1 = ea.rgbToHsl([rgbBgColor1.value[0], rgbBgColor1.value[1], rgbBgColor1.value[2]]);
|
||||
const bgHsl2 = ea.rgbToHsl([rgbBgColor2.value[0], rgbBgColor2.value[1], rgbBgColor2.value[2]]);
|
||||
|
||||
bgHDistance = bgHsl2[0] - bgHsl1[0];
|
||||
bgSDistance = bgHsl2[1] - bgHsl1[1];
|
||||
bgLDistance = bgHsl2[2] - bgHsl1[2];
|
||||
}
|
||||
let cmBgColor2 = ea.getCM(bgColor2);
|
||||
const isBgTransparent = cmBgColor1.alpha === 0 || cmBgColor2.alpha === 0;
|
||||
const bgHDistance = cmBgColor2.hue - cmBgColor1.hue;
|
||||
const bgSDistance = cmBgColor2.saturation - cmBgColor1.saturation;
|
||||
const bgLDistance = cmBgColor2.lightness - cmBgColor1.lightness;
|
||||
const bgADistance = cmBgColor2.alpha - cmBgColor1.alpha;
|
||||
|
||||
const strokeColor1 = ea.colorNameToHex(selectedElements[0].strokeColor);
|
||||
const rgbStrokeColor1 = parseColorString(strokeColor1);
|
||||
const cmStrokeColor1 = ea.getCM(strokeColor1);
|
||||
const strokeColor2 = ea.colorNameToHex(selectedElements[1].strokeColor);
|
||||
const rgbStrokeColor2 = parseColorString(strokeColor2);
|
||||
let strokeHDistance = 0;
|
||||
let strokeSDistance = 0;
|
||||
let strokeLDistance = 0;
|
||||
let cmStrokeColor2 = ea.getCM(strokeColor2);
|
||||
const isStrokeTransparent = cmStrokeColor1.alpha === 0 || cmStrokeColor2.alpha ===0;
|
||||
const strokeHDistance = cmStrokeColor2.hue - cmStrokeColor1.hue;
|
||||
const strokeSDistance = cmStrokeColor2.saturation - cmStrokeColor1.saturation;
|
||||
const strokeLDistance = cmStrokeColor2.lightness - cmStrokeColor1.lightness;
|
||||
const strokeADistance = cmStrokeColor2.alpha - cmStrokeColor1.alpha;
|
||||
|
||||
if(rgbStrokeColor1 && rgbStrokeColor2) {
|
||||
const strokeHsl1 = ea.rgbToHsl([rgbStrokeColor1.value[0], rgbStrokeColor1.value[1], rgbStrokeColor1.value[2]]);
|
||||
const strokeHsl2 = ea.rgbToHsl([rgbStrokeColor2.value[0], rgbStrokeColor2.value[1], rgbStrokeColor2.value[2]]);
|
||||
|
||||
strokeHDistance = strokeHsl2[0] - strokeHsl1[0];
|
||||
strokeSDistance = strokeHsl2[1] - strokeHsl1[1];
|
||||
strokeLDistance = strokeHsl2[2] - strokeHsl1[2];
|
||||
}
|
||||
|
||||
ea.copyViewElementsToEAforEditing(selectedElements);
|
||||
for(let i=0; i<repeatNum; i++) {
|
||||
@@ -106,262 +98,19 @@ for(let i=0; i<repeatNum; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
if(rgbBgColor1 && rgbBgColor2) {
|
||||
const bgHsl2 = ea.rgbToHsl([rgbBgColor2.value[0], rgbBgColor2.value[1], rgbBgColor2.value[2]]);
|
||||
const newBgH = bgHsl2[0] + bgHDistance * (i + 1);
|
||||
const newBgS = bgHsl2[1] + bgSDistance * (i + 1);
|
||||
const newBgL = bgHsl2[2] + bgLDistance * (i + 1);
|
||||
|
||||
if(newBgH >= 0 && newBgH <= 360 && newBgS >= 0 && newBgS <= 100 && newBgL >= 0 && newBgL <= 100) {
|
||||
const newBgRgb = ea.hslToRgb([newBgH, newBgS, newBgL]);
|
||||
newEl.backgroundColor = rgbColorToString(newBgRgb, rgbBgColor1.model);
|
||||
}
|
||||
if(!isBgTransparent) {
|
||||
cmBgColor2 = cmBgColor2.hueBy(bgHDistance).saturateBy(bgSDistance).lighterBy(bgLDistance).alphaBy(bgADistance);
|
||||
newEl.backgroundColor = cmBgColor2.stringHEX();
|
||||
} else {
|
||||
newEl.backgroundColor = "transparent";
|
||||
}
|
||||
|
||||
if(rgbStrokeColor1 && rgbStrokeColor2) {
|
||||
const strokeHsl2 = ea.rgbToHsl([rgbStrokeColor2.value[0], rgbStrokeColor2.value[1], rgbStrokeColor2.value[2]]);
|
||||
const newStrokeH = strokeHsl2[0] + strokeHDistance * (i + 1);
|
||||
const newStrokeS = strokeHsl2[1] + strokeSDistance * (i + 1);
|
||||
const newStrokeL = strokeHsl2[2] + strokeLDistance * (i + 1);
|
||||
|
||||
if(newStrokeH >= 0 && newStrokeH <= 360 && newStrokeS >= 0 && newStrokeS <= 100 && newStrokeL >= 0 && newStrokeL <= 100) {
|
||||
const newStrokeRgb = ea.hslToRgb([newStrokeH, newStrokeS, newStrokeL]);
|
||||
newEl.strokeColor = rgbColorToString(newStrokeRgb, rgbStrokeColor1.model);
|
||||
}
|
||||
if(!isStrokeTransparent) {
|
||||
cmStrokeColor2 = cmStrokeColor2.hueBy(strokeHDistance).saturateBy(strokeSDistance).lighterBy(strokeLDistance).alphaBy(strokeADistance);
|
||||
newEl.strokeColor = cmStrokeColor2.stringHEX();
|
||||
} else {
|
||||
newEl.strokeColor = "transparent";
|
||||
}
|
||||
}
|
||||
|
||||
await ea.addElementsToView(false, false, true);
|
||||
|
||||
function parseColorString(string) {
|
||||
var prefix = string.substring(0, 3).toLowerCase();
|
||||
var val;
|
||||
var model;
|
||||
switch (prefix) {
|
||||
case 'hsl':
|
||||
val = ea.hslToRgb(parseHslColorString(string));
|
||||
model = 'hsl';
|
||||
break;
|
||||
case 'hwb':
|
||||
val = hwbToRgb(parseHwbColorString(string));
|
||||
model = 'hwb';
|
||||
break;
|
||||
default:
|
||||
val = parseRgbColorString(string);
|
||||
model = 'rgb';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!val) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {model: model, value: val};
|
||||
};
|
||||
|
||||
function parseRgbColorString(string) {
|
||||
if (!string) {
|
||||
return null;
|
||||
}
|
||||
var colorNames={};
|
||||
|
||||
var abbr = /^#([a-f0-9]{3,4})$/i;
|
||||
var hex = /^#([a-f0-9]{6})([a-f0-9]{2})?$/i;
|
||||
var rgba = /^rgba?\(\s*([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/;
|
||||
var per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/;
|
||||
var keyword = /^(\w+)$/;
|
||||
|
||||
var rgb = [0, 0, 0, 1];
|
||||
var match;
|
||||
var i;
|
||||
var hexAlpha;
|
||||
|
||||
if (match = string.match(hex)) {
|
||||
hexAlpha = match[2];
|
||||
match = match[1];
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
var i2 = i * 2;
|
||||
rgb[i] = parseInt(match.slice(i2, i2 + 2), 16);
|
||||
}
|
||||
|
||||
if (hexAlpha) {
|
||||
rgb[3] = parseInt(hexAlpha, 16) / 255;
|
||||
}
|
||||
} else if (match = string.match(abbr)) {
|
||||
match = match[1];
|
||||
hexAlpha = match[3];
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
rgb[i] = parseInt(match[i] + match[i], 16);
|
||||
}
|
||||
|
||||
if (hexAlpha) {
|
||||
rgb[3] = parseInt(hexAlpha + hexAlpha, 16) / 255;
|
||||
}
|
||||
} else if (match = string.match(rgba)) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
rgb[i] = parseInt(match[i + 1], 0);
|
||||
}
|
||||
|
||||
if (match[4]) {
|
||||
if (match[5]) {
|
||||
rgb[3] = parseFloat(match[4]) * 0.01;
|
||||
} else {
|
||||
rgb[3] = parseFloat(match[4]);
|
||||
}
|
||||
}
|
||||
} else if (match = string.match(per)) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55);
|
||||
}
|
||||
|
||||
if (match[4]) {
|
||||
if (match[5]) {
|
||||
rgb[3] = parseFloat(match[4]) * 0.01;
|
||||
} else {
|
||||
rgb[3] = parseFloat(match[4]);
|
||||
}
|
||||
}
|
||||
} else if (match = string.match(keyword)) {
|
||||
if (match[1] === 'transparent') {
|
||||
return [0, 0, 0, 0];
|
||||
}
|
||||
|
||||
if (!hasOwnProperty.call(colorNames, match[1])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
rgb = colorNames[match[1]];
|
||||
rgb[3] = 1;
|
||||
|
||||
return rgb;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
rgb[i] = clamp(rgb[i], 0, 255);
|
||||
}
|
||||
rgb[3] = clamp(rgb[3], 0, 1);
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
function parseHslColorString(string) {
|
||||
if (!string) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var hsl = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,?\s*([+-]?[\d\.]+)%\s*,?\s*([+-]?[\d\.]+)%\s*(?:[,|\/]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/;
|
||||
var match = string.match(hsl);
|
||||
|
||||
if (match) {
|
||||
var alpha = parseFloat(match[4]);
|
||||
var h = ((parseFloat(match[1]) % 360) + 360) % 360;
|
||||
var s = clamp(parseFloat(match[2]), 0, 100);
|
||||
var l = clamp(parseFloat(match[3]), 0, 100);
|
||||
var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1);
|
||||
|
||||
return [h, s, l, a];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function parseHwbColorString(string) {
|
||||
if (!string) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var hwb = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/;
|
||||
var match = string.match(hwb);
|
||||
|
||||
if (match) {
|
||||
var alpha = parseFloat(match[4]);
|
||||
var h = ((parseFloat(match[1]) % 360) + 360) % 360;
|
||||
var w = clamp(parseFloat(match[2]), 0, 100);
|
||||
var b = clamp(parseFloat(match[3]), 0, 100);
|
||||
var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1);
|
||||
return [h, w, b, a];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function rgbColorToString(color, model) {
|
||||
switch (model) {
|
||||
case 'hsl':
|
||||
return rgbColorToHslString(color);
|
||||
case 'hwb':
|
||||
return rgbColorToHwbString(color);
|
||||
default:
|
||||
return ea.rgbToHexString(color);
|
||||
}
|
||||
}
|
||||
|
||||
function rgbColorToHslString(rgb) {
|
||||
var hsl = ea.rgbToHsl(rgb);
|
||||
return 'hsl(' + hsl[0] + ', ' + hsl[1] + '%, ' + hsl[2] + '%)'
|
||||
};
|
||||
|
||||
function rgbColorToHwbString(rgb) {
|
||||
var hwb = rgbToHwb(rgb);
|
||||
|
||||
return 'hwb(' + hwb[0] + ', ' + hwb[1] + '%, ' + hwb[2] + '%)';
|
||||
};
|
||||
|
||||
function rgbToHwb(rgb) {
|
||||
const r = rgb[0];
|
||||
const g = rgb[1];
|
||||
let b = rgb[2];
|
||||
const h = convert.rgb.hsl(rgb)[0];
|
||||
const w = 1 / 255 * Math.min(r, Math.min(g, b));
|
||||
|
||||
b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
|
||||
|
||||
return [h, w * 100, b * 100];
|
||||
};
|
||||
|
||||
function hwbToRgb(hwb) {
|
||||
const h = hwb[0] / 360;
|
||||
let wh = hwb[1] / 100;
|
||||
let bl = hwb[2] / 100;
|
||||
const ratio = wh + bl;
|
||||
let f;
|
||||
|
||||
// Wh + bl cant be > 1
|
||||
if (ratio > 1) {
|
||||
wh /= ratio;
|
||||
bl /= ratio;
|
||||
}
|
||||
|
||||
const i = Math.floor(6 * h);
|
||||
const v = 1 - bl;
|
||||
f = 6 * h - i;
|
||||
|
||||
if ((i & 0x01) !== 0) {
|
||||
f = 1 - f;
|
||||
}
|
||||
|
||||
const n = wh + f * (v - wh);
|
||||
let r;
|
||||
let g;
|
||||
let b;
|
||||
switch (i) {
|
||||
default:
|
||||
case 6:
|
||||
case 0: r = v; g = n; b = wh; break;
|
||||
case 1: r = n; g = v; b = wh; break;
|
||||
case 2: r = wh; g = v; b = n; break;
|
||||
case 3: r = wh; g = n; b = v; break;
|
||||
case 4: r = n; g = wh; b = v; break;
|
||||
case 5: r = v; g = wh; b = n; break;
|
||||
}
|
||||
|
||||
return [r * 255, g * 255, b * 255];
|
||||
}
|
||||
|
||||
function clamp(num, min, max) {
|
||||
return Math.min(Math.max(min, num), max);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||

|
||||
|
||||
Use this script to set the background color of unclosed (i.e. open) line objects by creating a clone of the object. The script will set the stroke color of the clone to transparent and will add a straight line to close the object. Use settings to define the default background color, the fill style, and the strokeWidth of the clone. By default the clone will be grouped with the original object, you can disable this also in settings.
|
||||
Use this script to set the background color of unclosed (i.e. open) line and freedraw objects by creating a clone of the object. The script will set the stroke color of the clone to transparent and will add a straight line to close the object. Use settings to define the default background color, the fill style, and the strokeWidth of the clone. By default the clone will be grouped with the original object, you can disable this also in settings.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
@@ -41,9 +41,9 @@ const backgroundColor = settings["Background Color"].value;
|
||||
const fillStyle = settings["Fill Style"].value;
|
||||
const shouldGroup = settings["Group 'shadow' with original"].value;
|
||||
|
||||
const elements = ea.getViewSelectedElements().filter(el=>el.type==="line");
|
||||
const elements = ea.getViewSelectedElements().filter(el=>el.type==="line" || el.type==="freedraw");
|
||||
if(elements.length === 0) {
|
||||
new Notice("No line object is selected");
|
||||
new Notice("No line or freedraw object is selected");
|
||||
}
|
||||
|
||||
ea.copyViewElementsToEAforEditing(elements);
|
||||
|
||||
49
ea-scripts/Text Arch.md
Normal file
49
ea-scripts/Text Arch.md
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||

|
||||
|
||||
Fit a text to the arch of a circle. The script will prompt you for the radius of the circle and then split your text to individual letters and place each letter to the arch defined by the radius. Setting a lower radius value will increase the arching of the text. Note that the arched-text will no longer be editable as a text element and it will no longer function as a markdown link. Emojis are currently not supported.
|
||||
|
||||
```javascript
|
||||
*/
|
||||
el = ea.getViewSelectedElement();
|
||||
if(!el || el.type!=="text") {
|
||||
new Notice("Please select a text element");
|
||||
return;
|
||||
}
|
||||
|
||||
ea.style.fontSize = el.fontSize;
|
||||
ea.style.fontFamily = el.fontFamily;
|
||||
ea.style.strokeColor = el.strokeColor;
|
||||
ea.style.opacity = el.opacity;
|
||||
|
||||
const r = parseInt (await utils.inputPrompt("The radius of the arch you'd like to fit the text to","number","150"));
|
||||
const archAbove = await utils.suggester(["Arch above","Arch below"],[true,false]);
|
||||
|
||||
if(isNaN(r)) {
|
||||
new Notice("The radius is not a number");
|
||||
return;
|
||||
}
|
||||
|
||||
circlePoint = (angle) => archAbove
|
||||
? [
|
||||
r * Math.sin(angle),
|
||||
-r * Math.cos(angle)
|
||||
]
|
||||
: [
|
||||
-r * Math.sin(angle),
|
||||
r * Math.cos(angle)
|
||||
];
|
||||
|
||||
let rot = (archAbove ? -0.5 : 0.5) * ea.measureText(el.text).width/r;
|
||||
|
||||
let objectIDs = [];
|
||||
for(i=0;i<el.text.length;i++) {
|
||||
const character = el.text.substring(i,i+1);
|
||||
const width = ea.measureText(character).width;
|
||||
ea.style.angle = rot;
|
||||
const [x,y] = circlePoint(rot);
|
||||
rot += (archAbove ? 1 : -1) *width / r;
|
||||
objectIDs.push(ea.addText(x,y,character));
|
||||
}
|
||||
ea.addToGroup(objectIDs);
|
||||
ea.addElementsToView(true);
|
||||
1
ea-scripts/Text Arch.svg
Normal file
1
ea-scripts/Text Arch.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" stroke="#000" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><g fill="none"><circle cx="12" cy="12" r="10"></circle><path d="M17 12h.01"></path><path d="M12 12h.01"></path><path d="M7 12h.01"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 309 B |
File diff suppressed because one or more lines are too long
@@ -58,6 +58,8 @@ I would love to include your contribution in the script library. If you have a s
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Normalize%20Selected%20Arrows.svg"/></div>|[[#Normalize Selected Arrows]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/OCR%20-%20Optical%20Character%20Recognition.svg"/></div>|[[#OCR - Optical Character Recognition]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Organic%20Line.svg"/></div>|[[#Organic Line]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Palette%20loader.svg"/></div>|[[#Palette Loader]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Rename%20Image.svg"/></div>|[[#Rename Image]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Repeat%20Elements.svg"/></div>|[[#Repeat Elements]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Reverse%20arrows.svg"/></div>|[[#Reverse arrows]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Scribble%20Helper.svg"/></div>|[[#Scribble Helper]]|
|
||||
@@ -70,6 +72,7 @@ I would love to include your contribution in the script library. If you have a s
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Stroke%20Width%20of%20Selected%20Elements.svg"/></div>|[[#Set Stroke Width of Selected Elements]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Set%20Text%20Alignment.svg"/></div>|[[#Set Text Alignment]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Split%20text%20by%20lines.svg"/></div>|[[#Split text by lines]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Text%20Arch.svg"/></div>|[[#Text Arch]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.svg"/></div>|[[#Transfer TextElements to Excalidraw markdown metadata]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Zoom%20to%20Fit%20Selected%20Elements.svg"/></div>|[[#Zoom to Fit Selected Elements]]|
|
||||
|
||||
@@ -259,6 +262,18 @@ https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea
|
||||
```
|
||||
<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/Organic%20Line.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Converts selected freedraw lines such that pencil pressure will decrease from maximum to minimum from the beginning of the line to its end. The resulting line is placed at the back of the layers, under all other items. Helpful when drawing organic mindmaps.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-organic-line.jpg'></td></tr></table>
|
||||
|
||||
## Palette Loader
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Palette%20loader.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/Palette%20loader.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Design your palette at <a href="http://paletton.com/" target="_blank">paletton.com</a> Once you are happy with your colors, click Tables/Export in the bottom right of the screen. Then click "Color swatches/as Sketch Palette", and copy the contents of the page to a markdown file in the palette folder of your vault (default is Excalidraw/Palette)<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-sketch-palette-loader-1.jpg'></td></tr></table>
|
||||
|
||||
## Rename Image
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Rename%20Image.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/Rename%20Image.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Select an image on the canvas and run the script. You will be prompted to provide a new filename / filepath. This cuts down the time to name images you paste from the web or drag and drop from your file system.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/rename-image.png'></td></tr></table>
|
||||
|
||||
## Repeat Elements
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Repeat%20Elements.md
|
||||
@@ -287,7 +302,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/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.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/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Use this script to set the background color of unclosed (i.e. open) line objects by creating a clone of the object. The script will set the stroke color of the clone to transparent and will add a straight line to close the object. Use settings to define the default background color, the fill style, and the strokeWidth of the clone. By default the clone will be grouped with the original object, you can disable this also in settings.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-set-background-color-of-unclosed-line.jpg'></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/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Use this script to set the background color of unclosed (i.e. open) line and freedraw objects by creating a clone of the object. The script will set the stroke color of the clone to transparent and will add a straight line to close the object. Use settings to define the default background color, the fill style, and the strokeWidth of the clone. By default the clone will be grouped with the original object, you can disable this also in settings.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-set-background-color-of-unclosed-line.jpg'></td></tr></table>
|
||||
|
||||
## Set Dimensions
|
||||
```excalidraw-script-install
|
||||
@@ -331,6 +346,12 @@ https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea
|
||||
```
|
||||
<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/Split%20text%20by%20lines.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Split lines of text into separate text elements for easier reorganization<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-split-lines.jpg'></td></tr></table>
|
||||
|
||||
## Text Arch
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Text%20Arch.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/Text%20Arch.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Fit a text to the arch of a circle. The script will prompt you for the radius of the circle and then split your text to individual letters and place each letter to the arch defined by the radius. Setting a lower radius value will increase the arching of the text. Note that the arched-text will no longer be editable as a text element and it will no longer function as a markdown link. Emojis are currently not supported.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/text-arch.jpg'></td></tr></table>
|
||||
|
||||
## Transfer TextElements to Excalidraw markdown metadata
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Transfer%20TextElements%20to%20Excalidraw%20markdown%20metadata.md
|
||||
|
||||
BIN
images/rename-image.png
Normal file
BIN
images/rename-image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
images/text-arch.jpg
Normal file
BIN
images/text-arch.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "1.7.18",
|
||||
"version": "1.7.26",
|
||||
"minAppVersion": "0.15.6",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "obsidian-excalidraw-plugin",
|
||||
"version": "1.7.11",
|
||||
"version": "1.7.26",
|
||||
"description": "This is an Obsidian.md plugin that lets you view and edit Excalidraw drawings",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
@@ -18,7 +18,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/lz-string": "^1.3.34",
|
||||
"@zsviczian/excalidraw": "0.12.0-obsidian-8",
|
||||
"@zsviczian/excalidraw": "0.13.0-obsidian",
|
||||
"clsx": "^1.1.1",
|
||||
"lz-string": "^1.4.4",
|
||||
"monkey-around": "^2.3.0",
|
||||
@@ -49,7 +49,7 @@
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"html2canvas": "^1.4.0",
|
||||
"nanoid": "^4.0.0",
|
||||
"obsidian": "^0.15.4",
|
||||
"obsidian": "^0.16.3",
|
||||
"prettier": "^2.5.1",
|
||||
"rollup": "^2.70.1",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ import {
|
||||
ExcalidrawBindableElement,
|
||||
FileId,
|
||||
NonDeletedExcalidrawElement,
|
||||
ExcalidrawImageElement,
|
||||
} from "@zsviczian/excalidraw/types/element/types";
|
||||
import { normalizePath, TFile, WorkspaceLeaf } from "obsidian";
|
||||
import ExcalidrawView, { ExportSettings, TextMode } from "./ExcalidrawView";
|
||||
@@ -25,6 +26,7 @@ import {
|
||||
embedFontsInSVG,
|
||||
errorlog,
|
||||
getEmbeddedFilenameParts,
|
||||
getImageSize,
|
||||
getPNG,
|
||||
getSVG,
|
||||
isVersionNewerThanOther,
|
||||
@@ -891,6 +893,7 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
topX: number,
|
||||
topY: number,
|
||||
imageFile: TFile,
|
||||
scale: boolean = true, //true will scale the image to MAX_IMAGE_SIZE, false will insert image at 100% of its size
|
||||
): Promise<string> {
|
||||
const id = nanoid();
|
||||
const loader = new EmbeddedFilesLoader(
|
||||
@@ -907,11 +910,11 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
id: fileId,
|
||||
dataURL: image.dataURL,
|
||||
created: image.created,
|
||||
file: imageFile.path,
|
||||
file: imageFile.path + (scale ? "":"|100%"),
|
||||
hasSVGwithBitmap: image.hasSVGwithBitmap,
|
||||
latex: null,
|
||||
};
|
||||
if (Math.max(image.size.width, image.size.height) > MAX_IMAGE_SIZE) {
|
||||
if (scale && (Math.max(image.size.width, image.size.height) > MAX_IMAGE_SIZE)) {
|
||||
const scale =
|
||||
MAX_IMAGE_SIZE / Math.max(image.size.width, image.size.height);
|
||||
image.size.width = scale * image.size.width;
|
||||
@@ -1214,7 +1217,7 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
getViewElements(): ExcalidrawElement[] {
|
||||
//@ts-ignore
|
||||
if (!this.targetView || !this.targetView?._loaded) {
|
||||
errorMessage("targetView not set", "getViewSelectedElements()");
|
||||
errorMessage("targetView not set", "getViewElements()");
|
||||
return [];
|
||||
}
|
||||
const current = this.targetView?.excalidrawRef?.current;
|
||||
@@ -1232,7 +1235,7 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
deleteViewElements(elToDelete: ExcalidrawElement[]): boolean {
|
||||
//@ts-ignore
|
||||
if (!this.targetView || !this.targetView?._loaded) {
|
||||
errorMessage("targetView not set", "getViewSelectedElements()");
|
||||
errorMessage("targetView not set", "deleteViewElements()");
|
||||
return false;
|
||||
}
|
||||
const current = this.targetView?.excalidrawRef?.current;
|
||||
@@ -1280,7 +1283,7 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
getViewFileForImageElement(el: ExcalidrawElement): TFile | null {
|
||||
//@ts-ignore
|
||||
if (!this.targetView || !this.targetView?._loaded) {
|
||||
errorMessage("targetView not set", "getViewSelectedElements()");
|
||||
errorMessage("targetView not set", "getViewFileForImageElement()");
|
||||
return null;
|
||||
}
|
||||
if (!el || el.type !== "image") {
|
||||
@@ -1488,6 +1491,15 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
pointerPosition: { x: number; y: number }; //the pointer position on canvas at the time of drop
|
||||
}) => boolean = null;
|
||||
|
||||
/**
|
||||
* If set, this callback is triggered whenever the active canvas color changes
|
||||
*/
|
||||
onCanvasColorChangeHook: (
|
||||
ea: ExcalidrawAutomate,
|
||||
view: ExcalidrawView, //the excalidraw view
|
||||
color: string,
|
||||
) => void = null;
|
||||
|
||||
/**
|
||||
* utility function to generate EmbeddedFilesLoader object
|
||||
* @param isDark
|
||||
@@ -1678,6 +1690,30 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
return { width: size.w ?? 0, height: size.h ?? 0 };
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the size of the image element at 100% (i.e. the original size)
|
||||
* @param imageElement an image element from the active scene on targetView
|
||||
*/
|
||||
async getOriginalImageSize(imageElement: ExcalidrawImageElement): Promise<{width: number; height: number}> {
|
||||
//@ts-ignore
|
||||
if (!this.targetView || !this.targetView?._loaded) {
|
||||
errorMessage("targetView not set", "getOriginalImageSize()");
|
||||
return null;
|
||||
}
|
||||
if(!imageElement || imageElement.type !== "image") {
|
||||
errorMessage("Please provide a single image element as input", "getOriginalImageSize()");
|
||||
return null;
|
||||
}
|
||||
const ef = this.targetView.excalidrawData.getFile(imageElement.fileId);
|
||||
if(!ef) {
|
||||
errorMessage("Please provide a single image element as input", "getOriginalImageSize()");
|
||||
return null;
|
||||
}
|
||||
const isDark = this.getExcalidrawAPI().getAppState().theme === "dark";
|
||||
const dataURL = ef.getImage(isDark);
|
||||
return await getImageSize(dataURL);
|
||||
}
|
||||
|
||||
/**
|
||||
* verifyMinimumPluginVersion returns true if plugin version is >= than required
|
||||
* recommended use:
|
||||
@@ -1831,6 +1867,10 @@ export class ExcalidrawAutomate implements ExcalidrawAutomateInterface {
|
||||
log("Creates a CM object. Visit https://github.com/lbragile/ColorMaster for documentation.");
|
||||
return;
|
||||
}
|
||||
if(typeof color === "string") {
|
||||
color = this.colorNameToHex(color);
|
||||
}
|
||||
|
||||
return CM(color);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -488,7 +488,7 @@ export class ExcalidrawData {
|
||||
let res = data.matchAll(/\s\^(.{8})[\n]+/g);
|
||||
let parts;
|
||||
while (!(parts = res.next()).done) {
|
||||
const text = data.substring(position, parts.value.index);
|
||||
let text = data.substring(position, parts.value.index);
|
||||
const id: string = parts.value[1];
|
||||
const textEl = this.scene.elements.filter((el: any) => el.id === id)[0];
|
||||
if (textEl) {
|
||||
@@ -502,6 +502,13 @@ export class ExcalidrawData {
|
||||
this.elementLinks.set(id, text);
|
||||
} else {
|
||||
const wrapAt = estimateMaxLineLen(textEl.text, textEl.originalText);
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/566
|
||||
const elementLinkRes = text.matchAll(/^%%\*\*\*>>>text element-link:(\[\[[^<*\]]*]])<<<\*\*\*%%/gm);
|
||||
const elementLink = elementLinkRes.next();
|
||||
if(!elementLink.done) {
|
||||
text = text.replace(/^%%\*\*\*>>>text element-link:\[\[[^<*\]]*]]<<<\*\*\*%%/gm,"");
|
||||
textEl.link = elementLink.value[1];
|
||||
}
|
||||
const parseRes = await this.parse(text);
|
||||
this.textElements.set(id, {
|
||||
raw: text,
|
||||
@@ -847,6 +854,7 @@ export class ExcalidrawData {
|
||||
* @returns
|
||||
*/
|
||||
private async parse(text: string): Promise<{ parsed: string; link: string }> {
|
||||
text = this.parseCheckbox(text);
|
||||
let outString = "";
|
||||
let link = null;
|
||||
let position = 0;
|
||||
@@ -869,8 +877,14 @@ export class ExcalidrawData {
|
||||
}
|
||||
if (REGEX_LINK.isTransclusion(parts)) {
|
||||
//transclusion //parts.value[1] || parts.value[4]
|
||||
const contents = (await this.getTransclusion(REGEX_LINK.getLink(parts)))
|
||||
.contents;
|
||||
let contents = this
|
||||
.parseCheckbox((await this.getTransclusion(REGEX_LINK.getLink(parts))).contents)
|
||||
.replaceAll(/%%[^%]*%%/gm,""); //remove comments, consequence of https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/566
|
||||
if(this.plugin.settings.removeTransclusionQuoteSigns) {
|
||||
//remove leading > signs from transcluded quotations; the first > sign is not explicitlyl removed becuse
|
||||
//Obsidian app.metadataCache.blockCache returns the block position already discarding the first '> '
|
||||
contents = contents.replaceAll(/\n\s*>\s?/gm,"\n");
|
||||
}
|
||||
outString +=
|
||||
text.substring(position, parts.value.index) +
|
||||
wrapText(
|
||||
@@ -907,6 +921,16 @@ export class ExcalidrawData {
|
||||
return { parsed: outString, link };
|
||||
}
|
||||
|
||||
private parseCheckbox(text:string):string {
|
||||
return this.plugin.settings.parseTODO
|
||||
? text
|
||||
.replaceAll(/^- \[\s] /g,`${this.plugin.settings.todo} `)
|
||||
.replaceAll(/\n- \[\s] /g,`\n${this.plugin.settings.todo} `)
|
||||
.replaceAll(/^- \[[^\s]] /g,`${this.plugin.settings.done} `)
|
||||
.replaceAll(/\n- \[[^\s]] /g,`\n${this.plugin.settings.done} `)
|
||||
: text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a quick parse of the raw text. Returns the parsed string if raw text does not include a transclusion.
|
||||
* Return null if raw text includes a transclusion.
|
||||
@@ -928,7 +952,7 @@ export class ExcalidrawData {
|
||||
if (hasTransclusion(text)) {
|
||||
return [null, null];
|
||||
}
|
||||
|
||||
text = this.parseCheckbox(text);
|
||||
let outString = "";
|
||||
let link = null;
|
||||
let position = 0;
|
||||
@@ -980,7 +1004,15 @@ export class ExcalidrawData {
|
||||
generateMD(deletedElements: ExcalidrawElement[] = []): string {
|
||||
let outString = "# Text Elements\n";
|
||||
for (const key of this.textElements.keys()) {
|
||||
outString += `${this.textElements.get(key).raw} ^${key}\n\n`;
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/566
|
||||
const element = this.scene.elements.filter((el:any)=>el.id===key);
|
||||
let elementString = this.textElements.get(key).raw;
|
||||
if(element && element.length===1 && element[0].link && element[0].rawText === element[0].originalText) {
|
||||
if(element[0].link.match(/^\[\[[^\]]*]]$/g)) { //apply this only to markdown links
|
||||
elementString = `%%***>>>text element-link:${element[0].link}<<<***%%` + elementString;
|
||||
}
|
||||
}
|
||||
outString += `${elementString} ^${key}\n\n`;
|
||||
}
|
||||
|
||||
for (const key of this.elementLinks.keys()) {
|
||||
@@ -998,7 +1030,13 @@ export class ExcalidrawData {
|
||||
}
|
||||
if (this.files.size > 0) {
|
||||
for (const key of this.files.keys()) {
|
||||
outString += `${key}: [[${this.files.get(key).linkParts.original}]]\n`;
|
||||
const PATHREG = /(^[^#\|]*)/;
|
||||
const ef = this.files.get(key);
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/829
|
||||
const path = ef.file
|
||||
? ef.linkParts.original.replace(PATHREG,app.metadataCache.fileToLinktext(ef.file,this.file.path))
|
||||
: ef.linkParts.original;
|
||||
outString += `${key}: [[${path}]]\n`;
|
||||
}
|
||||
}
|
||||
outString += this.equations.size > 0 || this.files.size > 0 ? "\n" : "";
|
||||
@@ -1049,7 +1087,7 @@ export class ExcalidrawData {
|
||||
});
|
||||
|
||||
//check if there are any images that need to be processed in the new scene
|
||||
if (!scene.files || scene.files == {}) {
|
||||
if (!scene.files || Object.keys(scene.files).length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1065,7 +1103,7 @@ export class ExcalidrawData {
|
||||
const equation = this.getEquation(fileId);
|
||||
//const equation = this.equations.get(fileId as FileId);
|
||||
//images should have a single reference, but equations and markdown embeds should have as many as instances of the file in the scene
|
||||
if(file && (file.file.extension !== "md" || this.plugin.isExcalidrawFile(file.file))) {
|
||||
if(file && file.file && (file.file.extension !== "md" || this.plugin.isExcalidrawFile(file.file))) {
|
||||
return;
|
||||
}
|
||||
const newId = fileid();
|
||||
@@ -1541,15 +1579,15 @@ export const getTransclusion = async (
|
||||
if (!para) {
|
||||
return { contents: linkParts.original.trim(), lineNum: 0 };
|
||||
}
|
||||
if (["blockquote", "listItem"].includes(para.type)) {
|
||||
if (["blockquote"].includes(para.type)) {
|
||||
para = para.children[0];
|
||||
} //blockquotes are special, they have one child, which has the paragraph
|
||||
const startPos = para.position.start.offset;
|
||||
const lineNum = para.position.start.line;
|
||||
const endPos =
|
||||
para.children[para.children.length - 1]?.position.start.offset - 1; //alternative: filter((c:any)=>c.type=="blockid")[0]
|
||||
const endPos = para.position.end.offset; //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/853
|
||||
//para.children[para.children.length - 1]?.position.start.offset - 1; //!not clear what the side effect of the #853 change is
|
||||
return {
|
||||
contents: contents.substring(startPos, endPos).trim(),
|
||||
contents: contents.substring(startPos, endPos).replaceAll(/ \^\S*$|^\^\S*$/gm,"").trim(), //remove the block reference from the end of the line, or from the beginning of a new line
|
||||
lineNum,
|
||||
};
|
||||
}
|
||||
@@ -1600,7 +1638,7 @@ export const getTransclusion = async (
|
||||
return {
|
||||
leadingHashes: "#".repeat(depth) + " ",
|
||||
contents: contents.substring(startPos).trim(),
|
||||
lineNum
|
||||
lineNum
|
||||
};
|
||||
}
|
||||
return { contents: linkParts.original.trim(), lineNum: 0 };
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,7 @@ export const updateEquation = async (
|
||||
created: data.created,
|
||||
size: data.size,
|
||||
hasSVGwithBitmap: false,
|
||||
shouldScale: true,
|
||||
});
|
||||
addFiles(files, view);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,7 @@ export const REG_LINKINDEX_INVALIDCHARS = /[<>:"\\|?*#]/g;
|
||||
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 IMAGE_TYPES = ["jpeg", "jpg", "png", "gif", "svg", "webp", "bmp", "ico"];
|
||||
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";
|
||||
|
||||
@@ -17,12 +17,23 @@ export class InsertImageDialog extends FuzzySuggestModal<TFile> {
|
||||
this.limit = 20;
|
||||
this.setInstructions([
|
||||
{
|
||||
command: t("SELECT_FILE"),
|
||||
command: t("SELECT_FILE_WITH_OPTION_TO_SCALE"),
|
||||
purpose: "",
|
||||
},
|
||||
]);
|
||||
this.setPlaceholder(t("SELECT_DRAWING"));
|
||||
this.emptyStateText = t("NO_MATCH");
|
||||
this.inputEl.onkeyup = (e) => {
|
||||
//@ts-ignore
|
||||
if (e.key === "Enter" && e.altKey && this.chooser.values) {
|
||||
this.onChooseItem(
|
||||
//@ts-ignore
|
||||
this.chooser.values[this.chooser.selectedItem].item,
|
||||
new KeyboardEvent("keypress",{altKey: true})
|
||||
);
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getItems(): TFile[] {
|
||||
@@ -39,13 +50,13 @@ export class InsertImageDialog extends FuzzySuggestModal<TFile> {
|
||||
return item.path;
|
||||
}
|
||||
|
||||
onChooseItem(item: TFile): void {
|
||||
onChooseItem(item: TFile, event: KeyboardEvent): void {
|
||||
const ea = this.plugin.ea;
|
||||
ea.reset();
|
||||
ea.setView(this.view);
|
||||
ea.canvas.theme = this.view.excalidrawAPI.getAppState().theme;
|
||||
(async () => {
|
||||
await ea.addImage(0, 0, item);
|
||||
await ea.addImage(0, 0, item, !event.altKey);
|
||||
ea.addElementsToView(true, false, true);
|
||||
})();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,111 @@ 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.26":`## Fixed
|
||||
- Transcluded block with a parent bullet does not embed sub-bullet [#853](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/853)
|
||||
- Transcluded text will now exclude ^block-references at end of lines
|
||||
- Phantom duplicates of the drawing appear when "zoom to fit" results in a zoom value below 10% and there are many objects on the canvas [#850](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/850)
|
||||
- CTRL+Wheel will increase/decrease zoom in steps of 5% matching the behavior of the "+" & "-" zoom buttons.
|
||||
- Latest updates from Excalidarw.com
|
||||
- Freedraw flip not scaling correctly [#5752](https://github.com/excalidraw/excalidraw/pull/5752)
|
||||
- Multiple elements resizing regressions [#5586](https://github.com/excalidraw/excalidraw/pull/5586)
|
||||
|
||||
## New - power user features
|
||||
- Force the embedded image to always scale to 100%. Note: this is a very niche feature with a very particular behavior that I built primarily for myself (even more so than other features in Excalidraw Obsidian - also built primarily for myself 😉)... This will reset your embedded image to 100% size every time you open the Excalidraw drawing, or in case you have embedded an Excalidraw drawing on your canvas inserted using this function, every time you update the embedded drawing, it will be scaled back to 100% size. This means that even if you resize the image on the drawing, it will reset to 100% the next time you open the file or you modify the original embedded object. This feature is useful when you decompose a drawing into separate Excalidraw files, but when combined onto a single canvas you want the individual pieces to maintain their actual sizes. I use this feature to construct Book-on-a-Page summaries from atomic drawings.
|
||||
- I added an action to the command palette to temporarily disable/enable Excalidraw autosave. When autosave is disabled, Excalidraw will still save your drawing when changing to another Obsidian window, but it will not save every 10 seconds. On a mobile device (but also on a desktop) this can lead to data loss if you terminate Obsidian abruptly (i.e. swipe the application away, or close Obsidian without first closing the drawing). Use this feature if you find Excalidraw laggy.`,
|
||||
"1.7.25":`## Fixed
|
||||
- Tool buttons did not "stick" the first time you clicked them.
|
||||
- Tray (in tray mode) was higher when the help button was visible. The tray in tablet mode was too large and the help button was missing.
|
||||
- ExcalidrawAutomate ${String.fromCharCode(96)}getCM(color:TInput): ColorMaster;${String.fromCharCode(96)} function will now properly convert valid [css color names](https://www.w3schools.com/colors/colors_names.asp) to ColorMaster objects.
|
||||
- The downloaded script icons in the Excalidraw-Obsidian menu were not always correct
|
||||
- The obsidian mobile navigation bar at the bottom overlapped with Excalidraw
|
||||
|
||||
## New
|
||||
- Created ExcalidrawAutomate hook for styling script when the canvas color changes. See sample [onCanvasColorChangeHook](https://gist.github.com/zsviczian/c7223c5b4af30d5c88a0cae05300305c) implementation following the link.
|
||||
|
||||
<div class="excalidraw-videoWrapper"><div>
|
||||
<iframe src="https://www.youtube.com/embed/LtR04fNTKTM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
${String.fromCharCode(96, 96, 96)}typescript
|
||||
/**
|
||||
* If set, this callback is triggered whenever the active canvas color changes
|
||||
*/
|
||||
onCanvasColorChangeHook: (
|
||||
ea: ExcalidrawAutomate,
|
||||
view: ExcalidrawView, //the Excalidraw view
|
||||
color: string,
|
||||
) => void = null;
|
||||
${String.fromCharCode(96, 96, 96)}
|
||||
`,
|
||||
"1.7.24":`
|
||||
# New and improved
|
||||
- **Updated Chinese translation**. Thanks, @tswwe!
|
||||
- **Improved update for TextElement links**: Until now, when you attached a link to a file to a TextElement using the "Create Link" command, this link did not get updated when the file was renamed or moved. Only links created as markdown links in the TextElement text were updated. Now both approaches work. Keep in mind however, that if you have a link in the TextElemenet text, it will override the link attached to the text element using the create link command. [#566](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/566)
|
||||
- **Transclusion filters markdown comments**: Text transclusion in a TextElement using the ${String.fromCharCode(96)}![[file]]${String.fromCharCode(96)} or ${String.fromCharCode(96)}![[file#section]]${String.fromCharCode(96)} format did not filter out markdown comments in the file placed ${String.fromCharCode(96)}%% inside a comment block %%${String.fromCharCode(96)}. Now they do.
|
||||
- **Remove leading '>' from trancluded quotes**: Added a new option in settings under **Links and Transclusion** to remove the leading ${String.fromCharCode(96)}> ${String.fromCharCode(96)} characters from quotes you transclude as a text element in your drawing.
|
||||

|
||||
- **Added support for ${String.fromCharCode(96)}webp${String.fromCharCode(96)}, ${String.fromCharCode(96)}bmp${String.fromCharCode(96)}, and ${String.fromCharCode(96)}ico${String.fromCharCode(96)} images**. This extends the already supported formats (${String.fromCharCode(96)}jpg${String.fromCharCode(96)}, ${String.fromCharCode(96)}gif${String.fromCharCode(96)}, ${String.fromCharCode(96)}png${String.fromCharCode(96)}, ${String.fromCharCode(96)}svg${String.fromCharCode(96)}).
|
||||
- **Added command palette action to reset images to original size**. Select a single image or embedded Excalidraw drawing on your canvas and choose ${String.fromCharCode(96)}Set selected image element size to 100% of original${String.fromCharCode(96)} from the command palette. This function is especially helpful when you combine atomic drawings on a single canvas, keeping each atomic piece in its original excalidraw file (i.e. the way I create [book on a page summaries](https://www.youtube.com/playlist?list=PL6mqgtMZ4NP1-mbCYc3T7mr-unmsIXpEG))
|
||||
- The ${String.fromCharCode(96)}async getOriginalImageSize(imageElement: ExcalidrawImageElement): Promise<{width: number; height: number}>${String.fromCharCode(96)} function is also avaiable via ExcalidrawAutomate. You may use this function to resize images to custom scales (e.g. 50% size, or to fit a certain bounding rectangle).
|
||||
|
||||
# Fixed
|
||||
- **Upgraded perfect freehand package to resolve unwanted dots on end of lines** [#5727](https://github.com/excalidraw/excalidraw/pull/5727)
|
||||
- **Pinch zoom in View mode opens images** resulting in a very annoying behavior [#837](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/837)
|
||||
- **Embedded files** such as transcluded markdown documents and images **did not honor the Obsidian "New Link Format" setting** (shortest path, relative path, absolute path). [#829](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/829)
|
||||
- **Fixed error with dataview queries involving Excalidraw files**: In case you created a task on an Excalidraw canvas (${String.fromCharCode(96)}docA.md${String.fromCharCode(96)}) by typing ${String.fromCharCode(96)}- [ ] Task [[owner]] #tag${String.fromCharCode(96)}, and then you created a Dataview tasklist in another document (${String.fromCharCode(96)}docB.md${String.fromCharCode(96)}) such that the query criteria matched the task in ${String.fromCharCode(96)}docA.md${String.fromCharCode(96)}, then the task from ${String.fromCharCode(96)}docA.md${String.fromCharCode(96)} only appeared as an empty line when viewing ${String.fromCharCode(96)}docB.md${String.fromCharCode(96)}. If you now embedded ${String.fromCharCode(96)}docB.md${String.fromCharCode(96)} into a third markdown document (${String.fromCharCode(96)}docC.md${String.fromCharCode(96)}), then instead of the contents of ${String.fromCharCode(96)}docB.md${String.fromCharCode(96)} Obsidian rendered ${String.fromCharCode(96)}docA.md${String.fromCharCode(96)}. [#835](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/835)
|
||||
`,
|
||||
"1.7.22":`
|
||||
# Fixed
|
||||
- Text size in sticky notes increased when opening the drawing and when editing a sticky note [#824](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/824)
|
||||
- ToDo rendering did not work properly when there were parsed links in the text
|
||||
- Horizontal text alignment in sticky notes did not honor text alignment setting when resizing text. The text was always aligned center even when text alignment was left or right. [#5720](https://github.com/excalidraw/excalidraw/issues/5720)
|
||||
`,
|
||||
"1.7.21":`
|
||||
# New from Excalidraw.com
|
||||
- Image-mirroring in export preview and in exported SVG [#5700](https://github.com/excalidraw/excalidraw/pull/5700), [#811](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/811), [#617](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/617)
|
||||
|
||||
# New
|
||||
- Ctrl+s will force-save your drawing and update all your transclusions
|
||||
- Added setting to parse ${String.fromCharCode(96)}- [ ] ${String.fromCharCode(96)} and ${String.fromCharCode(96)}- [x] ${String.fromCharCode(96)} todo items. Parsing is disabled by default. This feature can be found under "Links and Transclusions" in Plugin Settings. [#819](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/819)
|
||||
|
||||

|
||||
|
||||
<iframe src="https://user-images.githubusercontent.com/14358394/192151120-3c61c822-0352-4ba7-9900-b38078fb373c.mp4" title="Demo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
- Added new scripts to the script library
|
||||
- [Rename Image](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Rename%20Image.md)
|
||||
- [Text Arch](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Text%20Arch.md)
|
||||
|
||||
<iframe src="https://user-images.githubusercontent.com/14358394/192151105-78c0115b-4e30-4296-b647-e3c05851a48f.mp4" title="Demo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
# Fixed
|
||||
- Fixed toast message to display script name on press and hold on mobile and iPad.
|
||||
- Fixed save error when the embedded image file is not found (i.e. it was moved, renamed, or deleted)
|
||||
|
||||
`,
|
||||
"1.7.20":`
|
||||
# New from Excalidraw.com
|
||||
- support segment midpoints in line editor [#5641](https://github.com/excalidraw/excalidraw/pull/5641)
|
||||
<div class="excalidraw-videoWrapper"><div>
|
||||
<iframe src="https://user-images.githubusercontent.com/11256141/187417807-3efeb673-6c96-4744-be0e-70119b0c6839.mp4" title="Demo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div></div>
|
||||
|
||||
# Fixed
|
||||
- When editing a line or arrow and selecting a tool on the toolbar, the tool jumps back to the selection tool and you need to click again to select the tool [#5703](https://github.com/excalidraw/excalidraw/issues/5703)
|
||||
- Minor improvement of autosave, hopefully decreasing occasional lagging
|
||||
`,
|
||||
"1.7.19":`
|
||||
# QoL improvements
|
||||
- Reintroduced the help button. I also added the help button to the Tray (in Tray Mode) and moved help to the canvas action panel (in non-TrayMode) because in Obsidian 0.16.0 the status bar hides the help icon.
|
||||
- Resetting the canvas with the "Reset Canvas" button will now preserve your custom color palette.
|
||||
- I updated the [Set background color of unlclosed line object](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Set%20background%20color%20of%20unclosed%20line%20object%20by%20adding%20a%20shadow%20clone.md) script. The script will now add background color to open freedraw objects as well. You no longer need to convert freedraw objects to lines before setting the background color. Check the Script Engine library to download the update.
|
||||
|
||||
# New in Excalidraw Automate
|
||||
- I added the [ColorMaster](https://github.com/lbragile/ColorMaster#readme) library to ExcalidrawAutomate. You can get a CM object by calling ${String.fromCharCode(96)}ExcalidrawAutomate.getCM(<your color comes here>)${String.fromCharCode(96)}. Color master introduces many new ways to manipulate colors from script. I will publish scripts that make use of this new functionality including supporting videos on my YouTube channel in the coming days.
|
||||
`,
|
||||
"1.7.18":`
|
||||
## Critical fix
|
||||
- duplicating text elements, adding text elements from the library, and pasting excalidraw text elements results in a corrupted file!!`,
|
||||
|
||||
@@ -52,7 +52,7 @@ export default {
|
||||
INSERT_LINK_TO_ELEMENT_ERROR: "Select a single element in the scene",
|
||||
INSERT_LINK_TO_ELEMENT_READY: "Link is READY and available on the clipboard",
|
||||
INSERT_LINK: "Insert link to file",
|
||||
INSERT_IMAGE: "Insert image from vault",
|
||||
INSERT_IMAGE: "Insert image or Excalidraw drawing from your vault",
|
||||
INSERT_MD: "Insert markdown file from vault",
|
||||
INSERT_LATEX:
|
||||
"Insert LaTeX formula (e.g. \\binom{n}{k} = \\frac{n!}{k!(n-k)!})",
|
||||
@@ -60,6 +60,9 @@ export default {
|
||||
READ_RELEASE_NOTES: "Read latest release notes",
|
||||
TRAY_MODE: "Toggle property-panel tray-mode",
|
||||
SEARCH: "Search for text in drawing",
|
||||
RESET_IMG_TO_100: "Set selected image element size to 100% of original",
|
||||
TEMPORARY_DISABLE_AUTOSAVE: "Disable autosave until next time Obsidian starts (only set this if you know what you are doing)",
|
||||
TEMPORARY_ENABLE_AUTOSAVE: "Enable autosave",
|
||||
|
||||
//ExcalidrawView.ts
|
||||
INSTALL_SCRIPT_BUTTON: "Install or update Excalidraw Scripts",
|
||||
@@ -77,7 +80,7 @@ export default {
|
||||
FILE_DOES_NOT_EXIST:
|
||||
"File does not exist. Hold down ALT (or ALT+SHIFT) and CLICK link button to create a new file.",
|
||||
FORCE_SAVE:
|
||||
"Force-save to update transclusions in adjacent panes.\n(Check autosave settings in plugin settings.)",
|
||||
"Save (will also update transclusions)",
|
||||
RAW: "Change to PREVIEW mode (only effects text-elements with links or transclusions)",
|
||||
PARSED:
|
||||
"Change to RAW mode (only effects text-elements with links or transclusions)",
|
||||
@@ -112,7 +115,7 @@ export default {
|
||||
"Template.md, the setting would be: Excalidraw/Template.md (or just Excalidraw/Template - you may omit the .md file extension). " +
|
||||
"If you are using Excalidraw in compatibility mode, then your template must be a legacy Excalidraw file as well " +
|
||||
"such as Excalidraw/Template.excalidraw.",
|
||||
SCRIPT_FOLDER_NAME: "Excalidraw Automate script folder",
|
||||
SCRIPT_FOLDER_NAME: "Excalidraw Automate script folder (CASE SeNSitiVE!)",
|
||||
SCRIPT_FOLDER_DESC:
|
||||
"The files you place in this folder will be treated as Excalidraw Automate scripts. " +
|
||||
"You can access your scripts from Excalidraw via the Obsidian Command Palette. Assign " +
|
||||
@@ -226,6 +229,12 @@ export default {
|
||||
"In PREVIEW mode, if the Text Element contains a URL link, precede the text with these characters. " +
|
||||
"You can override this setting for a specific drawing by adding <code>"
|
||||
}${FRONTMATTER_KEY_CUSTOM_URL_PREFIX}: "🌐 "</code> to the file's frontmatter.`,
|
||||
PARSE_TODO_NAME: "Parse todo",
|
||||
PARSE_TODO_DESC: "Convert '- [ ] ' and '- [x] ' to checkpox and tick in the box.",
|
||||
TODO_NAME: "Open TODO icon",
|
||||
TODO_DESC: "Icon to use for open TODO items",
|
||||
DONE_NAME: "Completed TODO icon",
|
||||
DONE_DESC: "Icon to use for completed TODO items",
|
||||
HOVERPREVIEW_NAME: "Hover preview without CTRL/CMD key",
|
||||
HOVERPREVIEW_DESC:
|
||||
"<b>Toggle On</b>: In Exalidraw <u>view mode</u> the hover preview for [[wiki links]] will be shown immediately, without the need to hold the CTRL/CMD key. " +
|
||||
@@ -253,6 +262,9 @@ export default {
|
||||
PAGE_TRANSCLUSION_CHARCOUNT_DESC:
|
||||
"The maximum number of characters to display from the page when transcluding an entire page with the " +
|
||||
"![[markdown page]] format.",
|
||||
QUOTE_TRANSCLUSION_REMOVE_NAME: "Quote translusion: remove leading '> ' from each line",
|
||||
QUOTE_TRANSCLUSION_REMOVE_DESC: "Remove the leading '> ' from each line of the transclusion. This will improve readibility of quotes in text only transclusions<br>" +
|
||||
"<b>Toggle ON:</b> Remove leading '> '<br><b>Toggle OFF:</b> Do not remove leading '> ' (note it will still be removed from the first row due to Obsidian API functionality)",
|
||||
GET_URL_TITLE_NAME: "Use iframely to resolve page title",
|
||||
GET_URL_TITLE_DESC:
|
||||
"Use the <code>http://iframely.server.crestify.com/iframely?url=</code> to get title of page when dropping a link into Excalidraw",
|
||||
@@ -408,9 +420,10 @@ export default {
|
||||
|
||||
//openDrawings.ts
|
||||
SELECT_FILE: "Select a file then press enter.",
|
||||
SELECT_FILE_WITH_OPTION_TO_SCALE: "Select a file then press ENTER, or ALT+ENTER to insert at 100% scale.",
|
||||
NO_MATCH: "No file matches your query.",
|
||||
SELECT_FILE_TO_LINK: "Select the file you want to insert the link for.",
|
||||
SELECT_DRAWING: "Select the drawing you want to insert",
|
||||
SELECT_DRAWING: "Select the image or drawing you want to insert",
|
||||
TYPE_FILENAME: "Type name of drawing to select.",
|
||||
SELECT_FILE_OR_TYPE_NEW:
|
||||
"Select existing drawing or type name of a new drawing then press Enter.",
|
||||
|
||||
@@ -9,10 +9,13 @@ export default {
|
||||
// main.ts
|
||||
INSTALL_SCRIPT: "安装此脚本",
|
||||
UPDATE_SCRIPT: "发现可用更新 - 点击安装",
|
||||
CHECKING_SCRIPT: "检查脚本更新 - 点击重新安装",
|
||||
UNABLETOCHECK_SCRIPT: "检查更新失败 - 点击重新安装",
|
||||
UPTODATE_SCRIPT: "已安装最新脚本 - 点击重新安装",
|
||||
OPEN_AS_EXCALIDRAW: "打开为 Excalidraw 绘图(Excalidraw 模式)",
|
||||
CHECKING_SCRIPT:
|
||||
"检查脚本更新 - 点击重新安装",
|
||||
UNABLETOCHECK_SCRIPT:
|
||||
"检查更新失败 - 点击重新安装",
|
||||
UPTODATE_SCRIPT:
|
||||
"已安装最新脚本 - 点击重新安装",
|
||||
OPEN_AS_EXCALIDRAW: "打开为 Excalidraw 绘图",
|
||||
TOGGLE_MODE: "在 Excalidraw 和 Markdown 模式之间切换",
|
||||
CONVERT_NOTE_TO_EXCALIDRAW: "转换空白笔记为 Excalidraw 绘图",
|
||||
CONVERT_EXCALIDRAW: "转换 *.excalidraw 为 *.md 文件",
|
||||
@@ -20,33 +23,47 @@ export default {
|
||||
CONVERT_FILE_KEEP_EXT: "*.excalidraw => *.excalidraw.md",
|
||||
CONVERT_FILE_REPLACE_EXT: "*.excalidraw => *.md (兼容 Logseq)",
|
||||
DOWNLOAD_LIBRARY: "导出 stencil 库为 *.excalidrawlib 文件",
|
||||
OPEN_EXISTING_NEW_PANE: "打开已有的绘图(在新面板)",
|
||||
OPEN_EXISTING_ACTIVE_PANE: "打开已有的绘图(在当前面板)",
|
||||
TRANSCLUDE: "插入(嵌入)绘图到当前文档",
|
||||
TRANSCLUDE_MOST_RECENT: "插入(嵌入)最近编辑的绘图到当前文档",
|
||||
NEW_IN_NEW_PANE: "新建绘图(在新面板)",
|
||||
NEW_IN_ACTIVE_PANE: "新建绘图(在当前面板)",
|
||||
NEW_IN_NEW_PANE_EMBED: "新建绘图(在新面板),并插入(嵌入)到当前文档",
|
||||
NEW_IN_ACTIVE_PANE_EMBED: "新建绘图(在当前面板),并插入(嵌入)到当前文档",
|
||||
OPEN_EXISTING_NEW_PANE: "打开已有的绘图 - 于新面板",
|
||||
OPEN_EXISTING_ACTIVE_PANE:
|
||||
"打开已有的绘图 - 于当前面板",
|
||||
TRANSCLUDE: "嵌入绘图(形如 ![[drawing]])到当前文档",
|
||||
TRANSCLUDE_MOST_RECENT: "嵌入最近编辑过的绘图(形如 ![[drawing]])到当前文档",
|
||||
TOGGLE_LEFTHANDED_MODE: "切换为左手模式",
|
||||
NEW_IN_NEW_PANE: "新建绘图 - 于新面板",
|
||||
NEW_IN_ACTIVE_PANE: "新建绘图 - 于当前面板",
|
||||
NEW_IN_POPOUT_WINDOW: "新建绘图 - 于新窗口",
|
||||
NEW_IN_NEW_PANE_EMBED:
|
||||
"新建绘图 - 于新面板 - 并将其嵌入(形如 ![[drawing]])到当前文档",
|
||||
NEW_IN_ACTIVE_PANE_EMBED:
|
||||
"新建绘图 - 于当前面板 - 并将其嵌入(形如 ![[drawing]])到当前文档",
|
||||
NEW_IN_POPOUT_WINDOW_EMBED: "新建绘图 - 于新窗口 - 并将其嵌入(形如 ![[drawing]])到当前文档",
|
||||
EXPORT_SVG: "导出 SVG 文件到当前目录",
|
||||
EXPORT_PNG: "导出 PNG 文件到当前目录",
|
||||
TOGGLE_LOCK: "切换文本元素的原文/预览模式",
|
||||
DELETE_FILE: "删除所选的图像或以图像形式嵌入的 Markdown 文档(包括其源文件)",
|
||||
INSERT_LINK_TO_ELEMENT: "复制所选元素(以链接形式)",
|
||||
TOGGLE_LOCK: "切换文本元素为原文模式(RAW)/预览模式(PREVIEW)",
|
||||
DELETE_FILE: "从库中删除所选图像(或 MD-Embed)的源文件",
|
||||
INSERT_LINK_TO_ELEMENT:
|
||||
"复制所选元素的内部链接。按住 CTRL/CMD 可复制元素所在分组的内部链接。按住 SHIFT 可复制元素周围区域的内部链接。",
|
||||
INSERT_LINK_TO_ELEMENT_GROUP:
|
||||
"复制所选元素所在分组的内部链接(形如 [[file#^group=elementID]])",
|
||||
INSERT_LINK_TO_ELEMENT_AREA:
|
||||
"复制所选元素周围区域的内部链接(形如 [[file#^area=elementID]])",
|
||||
INSERT_LINK_TO_ELEMENT_NORMAL:
|
||||
"复制所选元素的引用链接(形如 [[file#^elementID]])",
|
||||
INSERT_LINK_TO_ELEMENT_ERROR: "未选择画布里的单个元素",
|
||||
INSERT_LINK_TO_ELEMENT_READY: "链接已生成并复制到剪贴板",
|
||||
INSERT_LINK: "插入(链接)文件到当前绘图",
|
||||
INSERT_IMAGE: "插入(以图像形式嵌入)图像到当前绘图",
|
||||
INSERT_MD: "插入(以图像形式嵌入) Markdown 文档到当前绘图",
|
||||
INSERT_LATEX: "插入 LaTeX 公式",
|
||||
INSERT_LINK: "插入文件的内部链接(形如 [[drawing]])到当前绘图",
|
||||
INSERT_IMAGE: "插入图像(以图像形式嵌入)到当前绘图",
|
||||
INSERT_MD: "插入 Markdown 文档(以图像形式嵌入)到当前绘图",
|
||||
INSERT_LATEX:
|
||||
"插入 LaTeX 公式到当前绘图",
|
||||
ENTER_LATEX: "输入 LaTeX 表达式",
|
||||
READ_RELEASE_NOTES: "阅读本插件的最新发行版本说明",
|
||||
TRAY_MODE: "切换绘图工具属性页的面板(Panel)/托盘(Tray)模式",
|
||||
TRAY_MODE: "切换绘图工具属性页为面板模式(Panel)/托盘模式(Tray)",
|
||||
SEARCH: "搜索文本",
|
||||
|
||||
//ExcalidrawView.ts
|
||||
INSTALL_SCRIPT_BUTTON: "安装或更新 Excalidraw 自动化脚本",
|
||||
OPEN_AS_MD: "打开为 Markdown 文件(Markdown 模式)",
|
||||
OPEN_AS_MD: "打开为 Markdown 文件",
|
||||
SAVE_AS_PNG: "导出 PNG 到当前目录(按住 CTRL/CMD 设定导出路径)",
|
||||
SAVE_AS_SVG: "导出 SVG 到当前目录(按住 CTRL/CMD 设定导出路径)",
|
||||
OPEN_LINK: "打开所选元素里的链接 \n(按住 SHIFT 在新面板打开)",
|
||||
@@ -55,13 +72,12 @@ export default {
|
||||
"请选择一个含有链接的图形或文本元素。\n" +
|
||||
"按住 SHIFT 并点击此按钮可在新面板中打开链接。\n" +
|
||||
"您也可以直接在画布中按住 CTRL/CMD 并点击图形或文本元素来打开链接。",
|
||||
TEXT_ELEMENT_EMPTY:
|
||||
"未选中图形或文本元素,或者元素不包含有效的链接([[链接|别名]] 或 [别名](链接))",
|
||||
FILENAME_INVALID_CHARS: '文件名不能含有以下符号: * " \\ < > : | ? #',
|
||||
FILENAME_INVALID_CHARS:
|
||||
'文件名不能含有以下符号: * " \\ < > : | ? #',
|
||||
FILE_DOES_NOT_EXIST:
|
||||
"文件不存在。按住 ALT(或 ALT + SHIFT)并点击链接来创建新文件。",
|
||||
FORCE_SAVE:
|
||||
"立刻保存该绘图,并更新其他嵌入了该绘图的面板。\n(详见插件设置中的定期保存选项)",
|
||||
"立刻保存该绘图(并更新嵌入了该绘图的面板)。\n详见插件设置中的定期保存选项",
|
||||
RAW: "文本元素正以原文(RAW)模式显示链接。\n点击切换到预览(PREVIEW)模式",
|
||||
PARSED:
|
||||
"文本元素正以预览(PREVIEW)模式显示链接。\n点击切换到原文(RAW)模式",
|
||||
@@ -75,13 +91,20 @@ export default {
|
||||
RELEASE_NOTES_DESC:
|
||||
"<b>开启:</b>每次更新本插件后,显示最新发行版本的说明。<br>" +
|
||||
"<b>关闭:</b>您仍可以在 <a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/releases'>GitHub</a> 上阅读更新说明。",
|
||||
NEWVERSION_NOTIFICATION_NAME: "通知插件更新",
|
||||
NEWVERSION_NOTIFICATION_DESC:
|
||||
"<b>开启:</b>当本插件存在可用更新时,显示通知。<br>" +
|
||||
"<b>关闭:</b>您需要手动检查本插件的更新(设置 - 第三方插件 - 检查更新)。",
|
||||
|
||||
FOLDER_NAME: "Excalidraw 文件夹",
|
||||
FOLDER_DESC: "新绘图的默认存储路径。若为空,将在库的根目录中创建新绘图。",
|
||||
FOLDER_EMBED_NAME: "将 Excalidraw 文件夹用于“新建绘图”命令创建的绘图",
|
||||
FOLDER_DESC:
|
||||
"新绘图的默认存储路径。若为空,将在库的根目录中创建新绘图。",
|
||||
FOLDER_EMBED_NAME:
|
||||
"将 Excalidraw 文件夹用于“新建绘图”命令创建的绘图",
|
||||
FOLDER_EMBED_DESC:
|
||||
"在命令面板中执行“新建绘图,并插入(嵌入)到当前文档”之类命令时," +
|
||||
"在命令面板中执行“新建绘图”系列命令时," +
|
||||
"新绘图的存储路径。<br>" +
|
||||
"<b>开启:</b>使用 Excalidraw 文件夹。 <b>关闭:</b>使用 Obsidian 设置的新附件默认位置。",
|
||||
"<b>开启:</b>使用 Excalidraw 文件夹。 <br><b>关闭:</b>使用 Obsidian 设置的新附件默认位置。",
|
||||
TEMPLATE_NAME: "Excalidraw 模板文件",
|
||||
TEMPLATE_DESC:
|
||||
"Excalidraw 模板文件的完整路径。<br>" +
|
||||
@@ -113,89 +136,107 @@ export default {
|
||||
"但是在手机或平板上通过滑动手势退出 Obsidian 时,可能无法顺利触发自动保存。因此我添加了定期保存功能作为弥补。",
|
||||
AUTOSAVE_INTERVAL_NAME: "定期保存的时间间隔",
|
||||
AUTOSAVE_INTERVAL_DESC:
|
||||
"每隔多长时间执行一次保存。如果当前绘图没有发生改变,将不会进行定期保存。",
|
||||
"每隔多长时间执行一次保存。如果当前绘图没有发生改变,将不会触发保存。",
|
||||
FILENAME_HEAD: "文件名",
|
||||
FILENAME_DESC:
|
||||
"<p>点击阅读" +
|
||||
"<a href='https://momentjs.com/docs/#/displaying/format/'>日期和时间格式参考</a>。</p>",
|
||||
FILENAME_SAMPLE: "当前设置下,新绘图的文件名形如:",
|
||||
FILENAME_EMBED_SAMPLE: "“新建绘图”命令创建的绘图的文件名形如:",
|
||||
FILENAME_PREFIX_NAME: "文件名前缀",
|
||||
FILENAME_PREFIX_DESC: "文件名的第一部分",
|
||||
FILENAME_PREFIX_EMBED_NAME: "“新建绘图”命令创建的绘图的文件名前缀",
|
||||
FILENAME_SAMPLE: "“新建绘图”系列命令创建的文件名形如:",
|
||||
FILENAME_EMBED_SAMPLE: "“新建绘图并嵌入到当前文档”系列命令创建的文件名形如:",
|
||||
FILENAME_PREFIX_NAME: "“新建绘图”系列命令创建的文件名前缀",
|
||||
FILENAME_PREFIX_DESC: "执行“新建绘图”系列命令时,创建的绘图文件名的第一部分",
|
||||
FILENAME_PREFIX_EMBED_NAME:
|
||||
"“新建绘图并嵌入到当前文档”系列命令创建的文件名前缀",
|
||||
FILENAME_PREFIX_EMBED_DESC:
|
||||
"若开启此项," +
|
||||
"则在命令面板中执行“新建绘图,并插入(嵌入)到当前文档”之类命令时," +
|
||||
"创建的绘图文件名将以当前文档名作为开头。",
|
||||
FILENAME_POSTFIX_NAME: "“新建绘图”命令创建的绘图的文件名后缀",
|
||||
"执行“新建绘图并嵌入到当前文档”系列命令时," +
|
||||
"创建的绘图文件名是否以当前文档名作为前缀?<br>" +
|
||||
"<b>开启:</b>是<br><b>关闭:</b>否",
|
||||
FILENAME_POSTFIX_NAME:
|
||||
"“新建绘图并嵌入到当前文档”系列命令创建的文件名的中间部分",
|
||||
FILENAME_POSTFIX_DESC:
|
||||
"介于文件名前缀和文件名日期之间的文本。仅对“新建绘图”命令创建的绘图生效。",
|
||||
FILENAME_DATE_NAME: "文件名日期",
|
||||
FILENAME_DATE_DESC: "文件名的最后一部分",
|
||||
"介于文件名前缀和日期时间之间的文本。仅对“新建绘图并嵌入到当前文档”系列命令创建的绘图生效。",
|
||||
FILENAME_DATE_NAME: "文件名里的日期时间",
|
||||
FILENAME_DATE_DESC:
|
||||
"文件名的最后一部分。允许留空。",
|
||||
FILENAME_EXCALIDRAW_EXTENSION_NAME: "文件扩展名(.excalidraw.md 或 .md)",
|
||||
FILENAME_EXCALIDRAW_EXTENSION_DESC:
|
||||
"该选项在兼容模式(即非 Excalidraw 专用 Markdown 文件)下不会生效。<br>" +
|
||||
"<b>开启:</b>使用 .excalidraw.md 作为扩展名;<b>关闭:</b>使用 .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.",*/
|
||||
"<b>开启:</b>使用 .excalidraw.md 作为扩展名。<br><b>关闭:</b>使用 .md 作为扩展名。",
|
||||
DISPLAY_HEAD: "显示",
|
||||
LEFTHANDED_MODE_NAME: "左手模式",
|
||||
LEFTHANDED_MODE_DESC:
|
||||
"目前只影响托盘模式下,绘图工具属性页的位置。若开启此项,则托盘处于右侧。",
|
||||
"目前只在托盘模式下生效。若开启此项,则托盘(绘图工具属性页)将位于右侧。" +
|
||||
"<br><b>开启:</b>左手模式。<br><b>关闭:</b>右手模式。",
|
||||
MATCH_THEME_NAME: "使新建的绘图匹配 Obsidian 主题",
|
||||
MATCH_THEME_DESC:
|
||||
"如果 Obsidian 使用黑暗主题,新建的绘图文件也将使用黑暗主题。<br>" +
|
||||
"但是若设置了模板,新建的绘图文件将跟随模板主题;另外,此功能不会作用于已有的绘图。",
|
||||
"但是若设置了模板,新建的绘图文件将跟随模板主题;另外,此功能不会作用于已有的绘图。" +
|
||||
"<br><b>开启:</b>跟随 Obsidian 主题风格。<br><b>关闭:</b>跟随模板主题风格。",
|
||||
MATCH_THEME_ALWAYS_NAME: "使已有的绘图匹配 Obsidian 主题",
|
||||
MATCH_THEME_ALWAYS_DESC:
|
||||
"如果 Obsidian 使用黑暗主题,则绘图文件也将以黑暗主题打开;反之亦然。",
|
||||
"如果 Obsidian 使用黑暗主题,则绘图文件也将以黑暗主题打开;反之亦然。" +
|
||||
"<br><b>开启:</b>匹配 Obsidian 主题风格。<br><b>关闭:</b>采用上次保存时的主题风格。",
|
||||
MATCH_THEME_TRIGGER_NAME: "Excalidraw 主题跟随 Obsidian 主题变化",
|
||||
MATCH_THEME_TRIGGER_DESC:
|
||||
"开启此项,则切换 Obsidian 的黑暗/明亮主题时,当前活动的 Excalidraw 面板的主题会随之改变。",
|
||||
"开启此项,则切换 Obsidian 的黑暗/明亮主题时,已打开的 Excalidraw 面板的主题会随之改变。" +
|
||||
"<br><b>开启:</b>跟随主题变化。<br><b>关闭:</b>不跟随主题变化。",
|
||||
DEFAULT_OPEN_MODE_NAME: "Excalidraw 的默认运行模式",
|
||||
DEFAULT_OPEN_MODE_DESC:
|
||||
"设置 Excalidraw 的运行模式:普通模式,禅模式,或者阅读模式。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 Frontmatter 中添加形如 <code>excalidraw-default-mode: normal/zen/view</code> 的键值对。",
|
||||
"设置 Excalidraw 的运行模式:普通模式(Normal)/禅模式(Zen)/阅读模式(View)。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>excalidraw-default-mode: normal/zen/view</code> 的键值对。",
|
||||
DEFAULT_PEN_MODE_NAME: "触控笔模式(Pen mode)",
|
||||
DEFAULT_PEN_MODE_DESC:
|
||||
"打开绘图时,是否自动开启触控笔模式?",
|
||||
ZOOM_TO_FIT_NAME: "自动缩放以适应面板调整",
|
||||
ZOOM_TO_FIT_DESC: "调整面板大小时,自适应地缩放画布",
|
||||
ZOOM_TO_FIT_DESC: "调整面板大小时,自适应地缩放画布" +
|
||||
"<br><b>开启:</b>自动缩放。<br><b>关闭:</b>禁用自动缩放。",
|
||||
ZOOM_TO_FIT_MAX_LEVEL_NAME: "自动缩放的最高级别",
|
||||
ZOOM_TO_FIT_MAX_LEVEL_DESC:
|
||||
"自动缩放画布时,允许放大的最高级别。该值不能低于 0.5(50%)且不能超过 10(1000%)。",
|
||||
LINKS_HEAD: "链接(Links) & 嵌入到绘图中的文档(Transclusion)",
|
||||
LINKS_HEAD: "链接(Links) & 以文本形式嵌入到绘图中的文档(Transclusion)",
|
||||
LINKS_DESC:
|
||||
"按住 CTRL/CMD 并点击包含 <code>[[链接]]</code> 的文本元素可以打开其中的链接。" +
|
||||
"如果所选文本元素包含多个 <code>[[有效的 Obsidian 链接]]</code> ,只会打开第一个链接;" +
|
||||
"按住 CTRL/CMD 并点击包含 <code>[[链接]]</code> 的文本元素可以打开其中的链接。<br>" +
|
||||
"如果所选文本元素包含多个 <code>[[有效的内部链接]]</code> ,只会打开第一个链接;" +
|
||||
"如果所选文本元素包含有效的 URL 链接 (如 <code>https://</code> 或 <code>http://</code>)," +
|
||||
"插件会在浏览器中打开 URL 链接。<br>" +
|
||||
"链接的源文件被重命名时,绘图中相应的 <code>[[链接]]</code> 也会同步更新。" +
|
||||
"若您不愿绘图中的链接文本因此而变化,可用 <code>[[链接|别名]]</code> 来使用别名。",
|
||||
"插件会在浏览器中打开链接。<br>" +
|
||||
"链接的源文件被重命名时,绘图中相应的 <code>[[内部链接]]</code> 也会同步更新。" +
|
||||
"若您不愿绘图中的链接外观因此而变化,可使用 <code>[[内部链接|别名]]</code>。",
|
||||
ADJACENT_PANE_NAME: "在相邻面板中打开",
|
||||
ADJACENT_PANE_DESC:
|
||||
"按住 CTRL/CMD + SHIFT 并点击链接时,插件默认会在新面板中打开该链接。<br>" +
|
||||
"按住 CTRL/CMD + SHIFT 并点击绘图里的内部链接时,插件默认会在新面板中打开该链接。<br>" +
|
||||
"若开启此项,Excalidraw 会先尝试寻找已有的相邻面板(按照右侧、左侧、上方、下方的顺序)," +
|
||||
"并在其中打开链接。如果找不到," +
|
||||
"再在新面板中打开链接。",
|
||||
"并在其中打开该链接。如果找不到," +
|
||||
"再在新面板中打开。",
|
||||
MAINWORKSPACE_PANE_NAME: "在主工作区中打开",
|
||||
MAINWORKSPACE_PANE_DESC:
|
||||
"按住 CTRL/CMD + SHIFT 并点击绘图里的内部链接时,插件默认会在当前窗口的新面板中打开该链接。<br>" +
|
||||
"若开启此项,Excalidraw 会在主工作区的面板中打开该链接。",
|
||||
LINK_BRACKETS_NAME: "在链接的两侧显示 [[中括号]]",
|
||||
LINK_BRACKETS_DESC: `${
|
||||
"文本元素处于预览模式时,在链接的两侧显示中括号。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 Frontmatter 中添加形如 <code>"
|
||||
"文本元素处于预览模式时,在内部链接的两侧显示中括号。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>"
|
||||
}${FRONTMATTER_KEY_CUSTOM_LINK_BRACKETS}: true/false</code> 的键值对。`,
|
||||
LINK_PREFIX_NAME: "链接的前缀",
|
||||
LINK_PREFIX_NAME: "内部链接的前缀",
|
||||
LINK_PREFIX_DESC: `${
|
||||
"文本元素处于预览模式时,如果其中包含链接,则添加此前缀。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 Frontmatter 中添加形如 <code>"
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>"
|
||||
}${FRONTMATTER_KEY_CUSTOM_PREFIX}: "📍 "</code> 的键值对。`,
|
||||
URL_PREFIX_NAME: "URL 的前缀",
|
||||
URL_PREFIX_NAME: "外部链接的前缀",
|
||||
URL_PREFIX_DESC: `${
|
||||
"预览模式下,如果文本元素包含 URL 链接,则添加此前缀。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 Frontmatter 中添加形如 <code>"
|
||||
"文本元素处于预览模式时,如果其中包含外部链接,则添加此前缀。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>"
|
||||
}${FRONTMATTER_KEY_CUSTOM_URL_PREFIX}: "🌐 "</code> 的键值对。`,
|
||||
HOVERPREVIEW_NAME: "鼠标悬停预览链接",
|
||||
PARSE_TODO_NAME: "解析任务列表(Todo)",
|
||||
PARSE_TODO_DESC: "将文本元素中的 <code>- [ ]</code> 和 <code>- [x]</code> 前缀显示为方框。",
|
||||
TODO_NAME: "未完成的 Todo 项目",
|
||||
TODO_DESC: "未完成的 Todo 项目的符号",
|
||||
DONE_NAME: "已完成的 Todo 项目",
|
||||
DONE_DESC: "已完成的 Todo 项目的符号",
|
||||
HOVERPREVIEW_NAME: "鼠标悬停预览内部链接",
|
||||
HOVERPREVIEW_DESC:
|
||||
"<b>开启:</b>鼠标悬停在 <code>[[链接]]</code> 上即可预览。<br><b>关闭:</b>鼠标悬停在 <code>[[链接]]</code> 上,并且按住 CTRL/CMD 时进行预览。",
|
||||
"<b>开启:</b>在 Excalidraw <u>阅读模式(View)</u>下,鼠标悬停在 <code>[[内部链接]]</code> 上即可预览;" +
|
||||
"而在<u>普通模式(Normal)</u>下, 鼠标悬停在内部链接右上角的蓝色标识上即可预览。<br> " +
|
||||
"<b>关闭:</b>鼠标悬停在 <code>[[内部链接]]</code> 上,并且按住 CTRL/CMD 时进行预览。",
|
||||
LINKOPACITY_NAME: "链接标识的透明度",
|
||||
LINKOPACITY_DESC:
|
||||
"含有链接的元素,其右上角的链接标识的透明度。介于 0(全透明)到 1(不透明)之间。",
|
||||
@@ -204,48 +245,52 @@ export default {
|
||||
LINK_CTRL_CLICK_DESC:
|
||||
"如果此功能影响到您使用某些原版 Excalidraw 功能,可将其关闭。" +
|
||||
"关闭后,您只能通过绘图面板标题栏中的链接按钮来打开链接。",
|
||||
TRANSCLUSION_WRAP_NAME: "嵌入文档(Translusion)的折行方式",
|
||||
TRANSCLUSION_WRAP_NAME: "Transclusion 的折行方式",
|
||||
TRANSCLUSION_WRAP_DESC:
|
||||
"中的 number 表示嵌入的文本溢出时,在第几个字符处进行折行。<br>" +
|
||||
"此开关控制具体的折行方式。若开启,则严格在 number 处折行,禁止溢出;" +
|
||||
"若关闭,则允许在 number 位置后最近的空格处折行。",
|
||||
TRANSCLUSION_DEFAULT_WRAP_NAME: "嵌入文档(Translusion)的默认折行位置",
|
||||
TRANSCLUSION_DEFAULT_WRAP_NAME: "Transclusion 的默认折行位置",
|
||||
TRANSCLUSION_DEFAULT_WRAP_DESC:
|
||||
"除了通过 <code>![[doc#^block]]{number}</code> 中的 number 来控制折行位置,您也可以在此设置 number 的默认值。<br>" +
|
||||
"一般设为 0 即可,表示不设置固定的默认值,这样当您需要嵌入文档到便签中时," +
|
||||
"Excalidraw 能更好地帮您自动处理。",
|
||||
PAGE_TRANSCLUSION_CHARCOUNT_NAME: "嵌入文档(Translusion)的最大显示字符数",
|
||||
PAGE_TRANSCLUSION_CHARCOUNT_NAME: "Transclusion 的最大显示字符数",
|
||||
PAGE_TRANSCLUSION_CHARCOUNT_DESC:
|
||||
"以 <code>![[Markdown 文档]]</code> 的形式将文档嵌入到绘图中时," +
|
||||
"以 <code>![[内部链接]]</code> 或 <code></code> 的形式将文档以文本形式嵌入到绘图中时," +
|
||||
"该文档在绘图中可显示的最大字符数量。",
|
||||
GET_URL_TITLE_NAME: "使用 iframly 获取页面标题",
|
||||
GET_URL_TITLE_DESC:
|
||||
"拖放链接到 Excalidraw 时,使用 <code>http://iframely.server.crestify.com/iframely?url=</code> 来获取页面的标题。",
|
||||
MD_HEAD: "以图像形式嵌入到绘图中的 Markdown 文档(MD-Embed)",
|
||||
MD_HEAD_DESC:
|
||||
"您可以将 Markdown 文档以图像(而非链接)的形式嵌入到绘图中," +
|
||||
"方法是按住 CTRL/CMD 并从文件管理器中把文档拖入绘图,或者使用命令面板里的相关命令。",
|
||||
"您还可以将 Markdown 文档以图像形式(而非文本形式)嵌入到绘图中。" +
|
||||
"方法是按住 CTRL/CMD 并从文件管理器中把文档拖入绘图,或者执行“以图像形式嵌入”系列命令。",
|
||||
MD_TRANSCLUDE_WIDTH_NAME: "MD-Embed 的默认宽度",
|
||||
MD_TRANSCLUDE_WIDTH_DESC:
|
||||
"MD-Embed 图像的宽度。该选项会影响到折行,以及图像元素的宽度。<br>" +
|
||||
"MD-Embed 的宽度。该选项会影响到折行,以及图像元素的宽度。<br>" +
|
||||
"您可为绘图中的某个 MD-Embed 单独设置此项,方法是将绘图切换至 Markdown 模式," +
|
||||
"并修改相应的 <code>[[Embed文件名#标题|宽度x最大高度]]</code>。",
|
||||
MD_TRANSCLUDE_HEIGHT_NAME: "MD-Embed 的默认最大高度",
|
||||
MD_TRANSCLUDE_HEIGHT_NAME:
|
||||
"MD-Embed 的默认最大高度",
|
||||
MD_TRANSCLUDE_HEIGHT_DESC:
|
||||
"MD-Embed 图像的高度取决于文档内容的多少,但最大不会超过该值。<br>" +
|
||||
"MD-Embed 的高度取决于 Markdown 文档内容的多少,但最大不会超过该值。<br>" +
|
||||
"您可为绘图中的某个 MD-Embed 单独设置此项,方法是将绘图切换至 Markdown 模式,并修改相应的 <code>[[Embed文件名#^块引ID|宽度x最大高度]]</code>。",
|
||||
MD_DEFAULT_FONT_NAME: "MD-Embed 的默认字体",
|
||||
MD_DEFAULT_FONT_NAME:
|
||||
"MD-Embed 的默认字体",
|
||||
MD_DEFAULT_FONT_DESC:
|
||||
"可以设为 <code>Virgil</code>,<code>Casadia</code> 或其他有效的 .ttf/.woff/.woff2 字体文件(如 <code>我的字体.woff2</code>)。<br>" +
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 Frontmatter 中添加形如 <code>excalidraw-font: 字体名或文件名</code> 的键值对。",
|
||||
MD_DEFAULT_COLOR_NAME: "MD-Embed 的默认文本颜色",
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 frontmatter 中添加形如 <code>excalidraw-font: 字体名或文件名</code> 的键值对。",
|
||||
MD_DEFAULT_COLOR_NAME:
|
||||
"MD-Embed 的默认文本颜色",
|
||||
MD_DEFAULT_COLOR_DESC:
|
||||
"可以填写 HTML 颜色名,如 steelblue(参考 <a href='https://www.w3schools.com/colors/colors_names.asp'>HTML Color Names</a>),或者有效的 16 进制颜色值,例如 #e67700,或者任何其他有效的 CSS 颜色。<br>" +
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 Frontmatter 中添加形如 <code>excalidraw-font-color: steelblue</code> 的键值对。",
|
||||
MD_DEFAULT_BORDER_COLOR_NAME: "MD-Embed 的默认边框颜色",
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 frontmatter 中添加形如 <code>excalidraw-font-color: steelblue</code> 的键值对。",
|
||||
MD_DEFAULT_BORDER_COLOR_NAME:
|
||||
"MD-Embed 的默认边框颜色",
|
||||
MD_DEFAULT_BORDER_COLOR_DESC:
|
||||
"可以填写 HTML 颜色名,如 steelblue(参考 <a href='https://www.w3schools.com/colors/colors_names.asp'>HTML Color Names</a>),或者有效的 16 进制颜色值,例如 #e67700,或者任何其他有效的 CSS 颜色。<br>" +
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 Frontmatter 中添加形如 <code>excalidraw-border-color: gray</code> 的键值对。<br>" +
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 frontmatter 中添加形如 <code>excalidraw-border-color: gray</code> 的键值对。<br>" +
|
||||
"如果您不想要边框,请留空。",
|
||||
MD_CSS_NAME: "MD-Embed 的默认 CSS 样式表",
|
||||
MD_CSS_DESC:
|
||||
@@ -255,58 +300,76 @@ export default {
|
||||
"<code>ExcalidrawAutomate.mostRecentMarkdownSVG</code> —— 这将显示 Excalidraw 最近生成的 SVG。<br>" +
|
||||
"此外,在 CSS 中不能任意地设置字体,您一般只能使用系统默认的标准字体(详见 README)," +
|
||||
"但可以通过上面的设置来额外添加一个自定义字体。<br>" +
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 Frontmatter 中添加形如 <code>excalidraw-css: 库中的CSS文件或CSS片段</code> 的键值对。",
|
||||
"您可为某个 MD-Embed 单独设置此项,方法是在其源文件的 frontmatter 中添加形如 <code>excalidraw-css: 库中的CSS文件或CSS片段</code> 的键值对。",
|
||||
EMBED_HEAD: "嵌入到文档中的绘图(Embed) & 导出",
|
||||
EMBED_PREVIEW_SVG_NAME: "在 Markdown 阅读视图下显示 SVG 格式的预览图",
|
||||
EMBED_REUSE_EXPORTED_IMAGE_NAME:
|
||||
"将之前已导出的图像作为 Embed 的预览图(如果存在的话)",
|
||||
EMBED_REUSE_EXPORTED_IMAGE_DESC:
|
||||
"该选项与“自动导出 SVG/PNG 副本”选项配合使用。如果存在文件名相匹配的 SVG/PNG 副本,则将其作为 Embed 的预览图,而不再重新生成预览图。<br>" +
|
||||
"该选项能够提高性能,尤其是当 Embed 中含有大量图像或 MD-Embed 时。" +
|
||||
"但是,该选项也可能导致预览图无法立即响应你最新的修改,或者你对 Obsidian 主题风格的改变。<br>" +
|
||||
"该选项仅作用于嵌入到文档中的绘图。" +
|
||||
"由于种种原因,该技术无法用于加快绘图文件的打开速度。详见<a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/1.6.23' target='_blank'>此说明</a>。",
|
||||
EMBED_PREVIEW_SVG_NAME: "生成 SVG 格式的 Embed 预览图",
|
||||
EMBED_PREVIEW_SVG_DESC:
|
||||
"Obsidian 的 Markdown 阅读视图默认会将嵌入的绘图显示为 SVG 格式的预览图。若关闭此项,则显示为 PNG 格式。",
|
||||
PREVIEW_MATCH_OBSIDIAN_NAME: "预览图匹配 Obsidian 主题",
|
||||
"<b>开启:</b>在 Markdown 预览模式下,为 Embed 生成 <a href='https://en.wikipedia.org/wiki/Scalable_Vector_Graphics' target='_blank'>SVG</a> 格式的预览图。<br>" +
|
||||
"<b>关闭:</b>为 Embed 生成 <a href='' target='_blank'>PNG</a> 格式的预览图。注意:PNG 格式预览图不支持某些 <a href='https://www.youtube.com/watch?v=yZQoJg2RCKI&t=633s' target='_blank'>绘图元素的块引用特性</a>。",
|
||||
PREVIEW_MATCH_OBSIDIAN_NAME: "Embed 预览图匹配 Obsidian 主题",
|
||||
PREVIEW_MATCH_OBSIDIAN_DESC:
|
||||
"开启此项,则当 Obsidian 处于黑暗模式时,预览图也会以黑暗模式渲染;" +
|
||||
"当 Obsidian 处于明亮模式时,的预览图也会以明亮模式渲染。<br>您可能还需要关闭“导出的图像包含背景”开关,来获得与 Obsidian 更加协调的观感。",
|
||||
EMBED_WIDTH_NAME: "预览图的默认宽度",
|
||||
"开启此项,则当 Obsidian 处于黑暗模式时,Embed 的预览图也会以黑暗模式渲染;当 Obsidian 处于明亮模式时,预览图也会以明亮模式渲染。<br>" +
|
||||
"您可能还需要关闭“导出的图像包含背景”开关,来获得与 Obsidian 更加协调的观感。",
|
||||
EMBED_WIDTH_NAME: "Embed 预览图的默认宽度",
|
||||
EMBED_WIDTH_DESC:
|
||||
"该选项同时作用于 Obsidian 实时预览模式下的编辑视图和阅读视图,以及鼠标悬停时的预览图。<br>" +
|
||||
"您可为嵌入到文档中的某个绘图单独设置此项," +
|
||||
"该选项同时作用于 Obsidian 实时预览模式下的编辑视图和阅读视图,以及鼠标悬停时浮现的预览图。<br>" +
|
||||
"您可为某个要嵌入到文档中的绘图(Embed)单独设置此项," +
|
||||
"方法是修改相应的链接格式为形如 <code>![[drawing.excalidraw|100]]</code> 或 <code>[[drawing.excalidraw|100x100]]</code> 的格式。",
|
||||
EMBED_TYPE_NAME: "“嵌入绘图到当前文档”命令的源文件类型",
|
||||
EMBED_TYPE_NAME: "“嵌入绘图到当前文档”系列命令的源文件类型",
|
||||
EMBED_TYPE_DESC:
|
||||
"在命令面板中执行“嵌入绘图到当前文档”之类命令时,要嵌入绘图文件,还是嵌入其 PNG 或 SVG 副本。<br>" +
|
||||
"如果您想在该下拉框中选择 PNG 或 SVG 副本,需要先开启下方的“自动导出 PNG 格式副本”或“自动导出 SVG 格式副本”开关。" +
|
||||
"若您选择了嵌入 PNG 或 SVG 副本,当绘图缺少对应的 PNG 或 SVG 副本时,该命令将会插入一条损坏的链接,您需要打开绘图文件并手动导出副本才能修复 —— " +
|
||||
"该选项不会帮您自动生成 PNG/SVG 副本,而只会引用已经存在的 PNG/SVG 副本。",
|
||||
EMBED_WIKILINK_NAME: "“嵌入绘图到当前文档”命令产生的链接类型",
|
||||
"在命令面板中执行“嵌入绘图到当前文档”系列命令时,要嵌入绘图文件本身,还是嵌入其 PNG 或 SVG 副本。<br>" +
|
||||
"如果您想选择 PNG 或 SVG 副本,需要先开启下方的“自动导出 PNG 副本”或“自动导出 SVG 副本”开关。<br>" +
|
||||
"如果您选择了 PNG 或 SVG 副本,当副本不存在时,该命令将会插入一条损坏的链接,您需要打开绘图文件并手动导出副本才能修复 —— " +
|
||||
"也就是说,该选项不会自动帮您生成 PNG/SVG 副本,而只会引用已有的 PNG/SVG 副本。",
|
||||
EMBED_WIKILINK_NAME: "“嵌入绘图到当前文档”命令产生的内部链接类型",
|
||||
EMBED_WIKILINK_DESC:
|
||||
"<b>开启:</b>将产生 <code>![[Wiki 链接]]</code>。<b>关闭:</b>将产生 <code></code>。",
|
||||
EXPORT_PNG_SCALE_NAME: "导出 PNG 图像的比例",
|
||||
EXPORT_PNG_SCALE_NAME: "导出的 PNG 图像的比例",
|
||||
EXPORT_PNG_SCALE_DESC: "导出的 PNG 图像的大小比例",
|
||||
EXPORT_BACKGROUND_NAME: "导出的图像包含背景",
|
||||
EXPORT_BACKGROUND_DESC: "如果关闭,将导出透明背景的图像。",
|
||||
EXPORT_SVG_PADDING_NAME: "导出 SVG 图像的边距",
|
||||
EXPORT_SVG_PADDING_DESC:
|
||||
"导出的 PNG 图像的空白边距(像素)。增加该值,可以避免在导出 SVG 图像时,过于靠近画布边缘的图形被裁掉。",
|
||||
EXPORT_BACKGROUND_DESC:
|
||||
"如果关闭,将导出透明背景的图像。",
|
||||
EXPORT_PADDING_NAME: "导出的图像的空白边距",
|
||||
EXPORT_PADDING_DESC:
|
||||
"导出的 SVG/PNG 图像四周的空白边距(单位:像素)。<br>" +
|
||||
"增加该值,可以避免在导出图像时,靠近图像边缘的图形被裁掉。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>excalidraw-export-padding: 5<code> 的键值对。",
|
||||
EXPORT_THEME_NAME: "导出的图像包含主题",
|
||||
EXPORT_THEME_DESC:
|
||||
"导出与绘图的黑暗/明亮主题匹配的图像。" +
|
||||
"如果关闭,在黑暗主题下导出的图像将和明亮主题一样。",
|
||||
EXPORT_HEAD: "导出设置",
|
||||
EXPORT_SYNC_NAME: "保持 .SVG 和 .PNG 文件名与绘图文件同步",
|
||||
EXPORT_SYNC_NAME:
|
||||
"保持 SVG/PNG 文件名与绘图文件同步",
|
||||
EXPORT_SYNC_DESC:
|
||||
"打开后,当绘图文件被重命名时,插件将同步更新同文件夹下的同名 .SVG 和 .PNG 文件。" +
|
||||
"当绘图文件被删除时,插件将自动删除同文件夹下的同名 .SVG 和 .PNG 文件。",
|
||||
EXPORT_SVG_NAME: "自动导出 SVG 格式副本",
|
||||
EXPORT_SVG_NAME: "自动导出 SVG 副本",
|
||||
EXPORT_SVG_DESC:
|
||||
"自动导出和绘图文件同名的 SVG 格式副本。" +
|
||||
"自动导出和绘图文件同名的 SVG 副本。" +
|
||||
"插件会将副本保存到绘图文件所在的文件夹中。" +
|
||||
"在文档中嵌入这个 SVG 文件,相比直接嵌入绘图文件,具有更强的跨平台能力。<br>" +
|
||||
"此开关开启时,每次您编辑 Excalidraw 绘图,其 SVG 文件副本都会同步更新。",
|
||||
EXPORT_PNG_NAME: "自动导出 PNG 格式副本",
|
||||
EXPORT_PNG_DESC: "和“自动导出 SVG 格式副本”类似,但是导出格式为 *.PNG。",
|
||||
"此开关开启时,每次您编辑 Excalidraw 绘图,其 SVG 文件副本都会同步更新。<br>" +
|
||||
"您可为某个绘图单独设置此项,方法是在其 frontmatter 中添加形如 <code>excalidraw-autoexport: none/both/svg/png</code>" +
|
||||
"的键值对",
|
||||
EXPORT_PNG_NAME: "自动导出 PNG 副本",
|
||||
EXPORT_PNG_DESC: "和“自动导出 SVG 副本”类似,但是导出格式为 *.PNG。",
|
||||
EXPORT_BOTH_DARK_AND_LIGHT_NAME: "同时导出黑暗和明亮风格的图像",
|
||||
EXPORT_BOTH_DARK_AND_LIGHT_DESC: "若开启,Excalidraw 将导出两个文件:filename.dark.png(或 filename.dark.svg)和 filename.light.png(或 filename.light.svg)。<br>"+
|
||||
"该选项可作用于“自动导出 SVG 副本”、“自动导出 PNG 副本”,以及其他的手动的导出命令。",
|
||||
COMPATIBILITY_HEAD: "兼容性设置",
|
||||
EXPORT_EXCALIDRAW_NAME: "自动导出 Excalidraw 格式副本",
|
||||
EXPORT_EXCALIDRAW_DESC:
|
||||
"和“自动导出 SVG 格式副本”类似,但是导出格式为 *.excalidraw。",
|
||||
SYNC_EXCALIDRAW_NAME: "保持同一绘图的新旧格式文件内容一致",
|
||||
EXPORT_EXCALIDRAW_NAME: "自动导出 Excalidraw 旧格式副本",
|
||||
EXPORT_EXCALIDRAW_DESC: "和“自动导出 SVG 副本”类似,但是导出格式为 *.excalidraw。",
|
||||
SYNC_EXCALIDRAW_NAME:
|
||||
"新旧格式绘图文件的内容保持同步",
|
||||
SYNC_EXCALIDRAW_DESC:
|
||||
"如果旧格式(*.excalidraw)绘图文件的修改日期比新格式(*.md)更新," +
|
||||
"则根据旧格式文件的内容来更新新格式文件。",
|
||||
@@ -315,15 +378,20 @@ export default {
|
||||
"开启此功能后,您通过功能区按钮、命令面板、" +
|
||||
"文件浏览器等创建的绘图都将是旧格式(*.excalidraw)。" +
|
||||
"此外,您打开旧格式绘图文件时将不再收到提醒消息。",
|
||||
MATHJAX_NAME: "MathJax (LaTeX) 的 javascript 库服务器",
|
||||
MATHJAX_DESC: "如果您在绘图中使用 LaTeX,插件需要从服务器获取并加载一个 javascript 库。" +
|
||||
"如果您的网络无法访问某些库服务器,可以尝试通过此选项更换库服务器。"+
|
||||
"更改此选项后,您可能需要重启 Obsidian 来使其生效。",
|
||||
EXPERIMENTAL_HEAD: "实验性功能",
|
||||
EXPERIMENTAL_DESC:
|
||||
"以下部分设置不会立即生效,需要刷新文件资源管理器或者重启 Obsidian 才会生效。",
|
||||
FIELD_SUGGESTER_NAME: "开启 Field Suggester",
|
||||
FIELD_SUGGESTER_NAME: "开启字段建议",
|
||||
FIELD_SUGGESTER_DESC:
|
||||
"开启后,当您在编辑器中输入 <code>excalidraw-</code> 或者 <code>ea.</code> 时,会弹出一个带有函数说明的自动补全提示菜单。<br>" +
|
||||
"该功能借鉴了 Breadcrumbs 和 Templater 插件。",
|
||||
FILETYPE_NAME: "在文件浏览器中为 excalidraw.md 文件添加类型标识符(如 ✏️)",
|
||||
FILETYPE_DESC: "可通过下一项设置来自定义类型标识符。",
|
||||
FILETYPE_DESC:
|
||||
"可通过下一项设置来自定义类型标识符。",
|
||||
FILETAG_NAME: "excalidraw.md 文件的类型标识符",
|
||||
FILETAG_DESC: "要显示为类型标识符的 emoji 或文本。",
|
||||
INSERT_EMOJI: "插入 emoji",
|
||||
@@ -350,7 +418,8 @@ export default {
|
||||
SELECT_FILE_TO_LINK: "选择要插入(链接)到当前绘图中的文件。",
|
||||
SELECT_DRAWING: "选择要插入(以图像形式嵌入)到当前绘图中的图像。",
|
||||
TYPE_FILENAME: "键入要选择的绘图名称。",
|
||||
SELECT_FILE_OR_TYPE_NEW: "选择已有绘图,或者新绘图的类型,然后按回车。",
|
||||
SELECT_FILE_OR_TYPE_NEW:
|
||||
"选择已有绘图,或者新绘图的类型,然后按回车。",
|
||||
SELECT_TO_EMBED: "选择要插入(嵌入)到当前文档中的绘图。",
|
||||
SELECT_MD: "选择要插入(以图像形式嵌入)到当前绘图中的 Markdown 文档。",
|
||||
|
||||
@@ -359,7 +428,8 @@ export default {
|
||||
"EXCALIDRAW 警告\n停止加载嵌入的图像,因为此文件中存在死循环:\n",
|
||||
|
||||
//Scripts.ts
|
||||
SCRIPT_EXECUTION_ERROR: "脚本运行错误。请在开发者控制台中查看错误信息。",
|
||||
SCRIPT_EXECUTION_ERROR:
|
||||
"脚本运行错误。请在开发者控制台中查看错误信息。",
|
||||
|
||||
//ExcalidrawData.ts
|
||||
LOAD_FROM_BACKUP: "Excalidraw 文件已损坏。尝试从备份文件中加载。",
|
||||
|
||||
4379
src/main.ts
4379
src/main.ts
File diff suppressed because it is too large
Load Diff
@@ -42,7 +42,7 @@ export class ActionButton extends React.Component<ButtonProps, ButtonState> {
|
||||
onPointerDown={() => {
|
||||
this.toastMessageTimeout = window.setTimeout(
|
||||
() =>
|
||||
this.props.view.excalidrawAPI?.setToastMessage(this.props.title),
|
||||
this.props.view.excalidrawAPI?.setToast({message:this.props.title}),
|
||||
300,
|
||||
);
|
||||
}}
|
||||
|
||||
@@ -287,3 +287,15 @@ export const ICONS = {
|
||||
</svg>
|
||||
),
|
||||
};
|
||||
|
||||
export const stringToSVG = (svg: string) => {
|
||||
svg = svg
|
||||
.replace(/stroke\s*=\s*['"][^"']*['"]/g,"")
|
||||
.replace(/width\s*=\s*['"][^"']*['"]/g,"")
|
||||
.replace(/height\s*=\s*['"][^"']*['"]/g,"")
|
||||
.replace("<svg ",`<svg style="stroke:var(--icon-fill-color);color:var(--icon-fill-color);fill:var(--icon-fill-color)" `)
|
||||
|
||||
return (
|
||||
<div dangerouslySetInnerHTML={{__html: svg}}></div>
|
||||
)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@ import {
|
||||
normalizePath,
|
||||
PluginSettingTab,
|
||||
Setting,
|
||||
TextComponent,
|
||||
TFile,
|
||||
} from "obsidian";
|
||||
import { VIEW_TYPE_EXCALIDRAW } from "./Constants";
|
||||
@@ -15,6 +16,7 @@ import {
|
||||
getEmbedFilename,
|
||||
} from "./utils/FileUtils";
|
||||
import {
|
||||
fragWithHTML,
|
||||
setLeftHandedMode,
|
||||
} from "./utils/Utils";
|
||||
|
||||
@@ -48,12 +50,16 @@ export interface ExcalidrawSettings {
|
||||
showLinkBrackets: boolean;
|
||||
linkPrefix: string;
|
||||
urlPrefix: string;
|
||||
parseTODO: boolean;
|
||||
todo: string;
|
||||
done: string;
|
||||
hoverPreviewWithoutCTRL: boolean;
|
||||
linkOpacity: number;
|
||||
allowCtrlClick: boolean; //if disabled only the link button in the view header will open links
|
||||
forceWrap: boolean;
|
||||
pageTransclusionCharLimit: number;
|
||||
wordWrappingDefault: number;
|
||||
removeTransclusionQuoteSigns: boolean;
|
||||
iframelyAllowed: boolean;
|
||||
pngExportScale: number;
|
||||
exportWithTheme: boolean;
|
||||
@@ -133,6 +139,9 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
zoomToFitMaxLevel: 2,
|
||||
linkPrefix: "📍",
|
||||
urlPrefix: "🌐",
|
||||
parseTODO: false,
|
||||
todo: "☐",
|
||||
done: "🗹",
|
||||
hoverPreviewWithoutCTRL: false,
|
||||
linkOpacity: 1,
|
||||
openInAdjacentPane: false,
|
||||
@@ -142,6 +151,7 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
forceWrap: false,
|
||||
pageTransclusionCharLimit: 200,
|
||||
wordWrappingDefault: 0,
|
||||
removeTransclusionQuoteSigns: true,
|
||||
iframelyAllowed: true,
|
||||
pngExportScale: 1,
|
||||
exportWithTheme: true,
|
||||
@@ -189,9 +199,6 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
mathjaxSourceURL: "https://cdn.jsdelivr.net/npm/mathjax@3.2.1/es5/tex-svg.js"
|
||||
};
|
||||
|
||||
const fragWithHTML = (html: string) =>
|
||||
createFragment((frag) => (frag.createDiv().innerHTML = html));
|
||||
|
||||
export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
plugin: ExcalidrawPlugin;
|
||||
private requestEmbedUpdate: boolean = false;
|
||||
@@ -605,7 +612,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showLinkBrackets)
|
||||
.onChange(async (value) => {
|
||||
.onChange(value => {
|
||||
this.plugin.settings.showLinkBrackets = value;
|
||||
this.applySettingsUpdate(true);
|
||||
}),
|
||||
@@ -618,7 +625,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
text
|
||||
.setPlaceholder(t("INSERT_EMOJI"))
|
||||
.setValue(this.plugin.settings.linkPrefix)
|
||||
.onChange((value) => {
|
||||
.onChange(value => {
|
||||
this.plugin.settings.linkPrefix = value;
|
||||
this.applySettingsUpdate(true);
|
||||
}),
|
||||
@@ -631,12 +638,61 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
text
|
||||
.setPlaceholder(t("INSERT_EMOJI"))
|
||||
.setValue(this.plugin.settings.urlPrefix)
|
||||
.onChange(async (value) => {
|
||||
.onChange(value => {
|
||||
this.plugin.settings.urlPrefix = value;
|
||||
this.applySettingsUpdate(true);
|
||||
}),
|
||||
);
|
||||
|
||||
let todoPrefixSetting:TextComponent, donePrefixSetting:TextComponent;
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("PARSE_TODO_NAME"))
|
||||
.setDesc(fragWithHTML(t("PARSE_TODO_DESC")))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.parseTODO)
|
||||
.onChange(value => {
|
||||
this.plugin.settings.parseTODO = value;
|
||||
todoPrefixSetting.setDisabled(!value);
|
||||
donePrefixSetting.setDisabled(!value);
|
||||
this.applySettingsUpdate(true);
|
||||
})
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("TODO_NAME"))
|
||||
.setDesc(fragWithHTML(t("TODO_DESC")))
|
||||
.addText((text) => {
|
||||
todoPrefixSetting = text;
|
||||
text
|
||||
.setPlaceholder(t("INSERT_EMOJI"))
|
||||
.setValue(this.plugin.settings.todo)
|
||||
.onChange(value => {
|
||||
this.plugin.settings.todo = value;
|
||||
this.applySettingsUpdate(true);
|
||||
})
|
||||
}
|
||||
);
|
||||
todoPrefixSetting.setDisabled(!this.plugin.settings.parseTODO);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("DONE_NAME"))
|
||||
.setDesc(fragWithHTML(t("DONE_DESC")))
|
||||
.setDisabled(!this.plugin.settings.parseTODO)
|
||||
.addText((text) => {
|
||||
donePrefixSetting = text;
|
||||
text
|
||||
.setPlaceholder(t("INSERT_EMOJI"))
|
||||
.setValue(this.plugin.settings.done)
|
||||
.onChange(value => {
|
||||
this.plugin.settings.done = value;
|
||||
this.applySettingsUpdate(true);
|
||||
})
|
||||
}
|
||||
);
|
||||
donePrefixSetting.setDisabled(!this.plugin.settings.parseTODO);
|
||||
|
||||
let opacityText: HTMLDivElement;
|
||||
new Setting(containerEl)
|
||||
.setName(t("LINKOPACITY_NAME"))
|
||||
@@ -753,6 +809,19 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("QUOTE_TRANSCLUSION_REMOVE_NAME"))
|
||||
.setDesc(fragWithHTML(t("QUOTE_TRANSCLUSION_REMOVE_DESC")))
|
||||
.addToggle(toggle =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.removeTransclusionQuoteSigns)
|
||||
.onChange(value => {
|
||||
this.plugin.settings.removeTransclusionQuoteSigns = value;
|
||||
this.requestEmbedUpdate = true;
|
||||
this.applySettingsUpdate(true);
|
||||
})
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t("GET_URL_TITLE_NAME"))
|
||||
.setDesc(fragWithHTML(t("GET_URL_TITLE_DESC")))
|
||||
|
||||
3
src/types.d.ts
vendored
3
src/types.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
import { ExcalidrawBindableElement, ExcalidrawElement, FileId, FillStyle, NonDeletedExcalidrawElement, StrokeSharpness, StrokeStyle } from "@zsviczian/excalidraw/types/element/types";
|
||||
import { ExcalidrawBindableElement, ExcalidrawElement, ExcalidrawImageElement, FileId, FillStyle, NonDeletedExcalidrawElement, StrokeSharpness, StrokeStyle } from "@zsviczian/excalidraw/types/element/types";
|
||||
import { Point } from "@zsviczian/excalidraw/types/types";
|
||||
import { TFile, WorkspaceLeaf } from "obsidian";
|
||||
import { EmbeddedFilesLoader } from "./EmbeddedFileLoader";
|
||||
@@ -223,6 +223,7 @@ export interface ExcalidrawAutomateInterface {
|
||||
//verifyMinimumPluginVersion returns true if plugin version is >= than required
|
||||
//recommended use:
|
||||
//if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.5.20")) {new Notice("message");return;}
|
||||
getOriginalImageSize(imageElement: ExcalidrawImageElement): Promise<{width: number; height: number}>;
|
||||
verifyMinimumPluginVersion(requiredVersion: string): boolean;
|
||||
isExcalidrawView(view: any): boolean;
|
||||
selectElementsInView(elements: ExcalidrawElement[]): void; //sets selection in view
|
||||
|
||||
1290
src/utils/Utils.ts
1290
src/utils/Utils.ts
File diff suppressed because it is too large
Load Diff
@@ -223,4 +223,8 @@ textarea.excalidraw-wysiwyg {
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.is-tablet .excalidraw button {
|
||||
padding: initial;
|
||||
}
|
||||
26
yarn.lock
26
yarn.lock
@@ -2216,10 +2216,10 @@
|
||||
dependencies:
|
||||
"@zerollup/ts-helpers" "^1.7.18"
|
||||
|
||||
"@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"
|
||||
"@zsviczian/excalidraw@0.13.0-obsidian":
|
||||
"integrity" "sha512-c4SnBEGKtenLB/1gSjXe3BVA+yZfo8b1p2E7sVcaPG8MTz6cpQsCB2+cv7Zta5ihIxuGfK3ZSepVhMbN7RFY2w=="
|
||||
"resolved" "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.13.0-obsidian.tgz"
|
||||
"version" "0.13.0-obsidian"
|
||||
|
||||
"abab@^2.0.3", "abab@^2.0.5":
|
||||
"integrity" "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q=="
|
||||
@@ -6206,10 +6206,10 @@
|
||||
dependencies:
|
||||
"minimist" "^1.2.5"
|
||||
|
||||
"moment@2.29.3":
|
||||
"integrity" "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw=="
|
||||
"resolved" "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz"
|
||||
"version" "2.29.3"
|
||||
"moment@2.29.4":
|
||||
"integrity" "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
|
||||
"resolved" "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz"
|
||||
"version" "2.29.4"
|
||||
|
||||
"monkey-around@^2.3.0":
|
||||
"integrity" "sha512-QWcCUWjqE/MCk9cXlSKZ1Qc486LD439xw/Ak8Nt6l2PuL9+yrc9TJakt7OHDuOqPRYY4nTWBAEFKn32PE/SfXA=="
|
||||
@@ -6420,13 +6420,13 @@
|
||||
"define-properties" "^1.1.3"
|
||||
"es-abstract" "^1.19.1"
|
||||
|
||||
"obsidian@^0.15.4":
|
||||
"integrity" "sha512-FE11CxxpVD6t/DBvjLvlT7q7YYW91ubTqPKIIp286LdnyLipS8Xi3Tif8i8ALPv87Vg9obKM43aWcPsYLxLllQ=="
|
||||
"resolved" "https://registry.npmjs.org/obsidian/-/obsidian-0.15.4.tgz"
|
||||
"version" "0.15.4"
|
||||
"obsidian@^0.16.3":
|
||||
"integrity" "sha512-hal9qk1A0GMhHSeLr2/+o3OpLmImiP+Y+sx2ewP13ds76KXsziG96n+IPFT0mSkup1zSwhEu+DeRhmbcyCCXWw=="
|
||||
"resolved" "https://registry.npmjs.org/obsidian/-/obsidian-0.16.3.tgz"
|
||||
"version" "0.16.3"
|
||||
dependencies:
|
||||
"@types/codemirror" "0.0.108"
|
||||
"moment" "2.29.3"
|
||||
"moment" "2.29.4"
|
||||
|
||||
"obuf@^1.0.0", "obuf@^1.1.2":
|
||||
"integrity" "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="
|
||||
|
||||
Reference in New Issue
Block a user