mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
Compare commits
22 Commits
2.4.1
...
2.5.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b1f504b5b | ||
|
|
d8f2776b40 | ||
|
|
2fd800e0a0 | ||
|
|
712402f7b1 | ||
|
|
b5c034ed92 | ||
|
|
d2805e7a8a | ||
|
|
4011b1c89a | ||
|
|
5bc348611c | ||
|
|
dd24affdbb | ||
|
|
d8542824a1 | ||
|
|
c6bf24ed60 | ||
|
|
a910550e34 | ||
|
|
01e53471d7 | ||
|
|
5569cff20e | ||
|
|
757c12c386 | ||
|
|
4cfe6cecda | ||
|
|
a34fbad038 | ||
|
|
6138ef03e0 | ||
|
|
9eb2821c9b | ||
|
|
628bd7bdb2 | ||
|
|
a3914da4ff | ||
|
|
6a1e7f08f4 |
50
.github/ISSUE_TEMPLATE/Contribution.yml.old
vendored
Normal file
50
.github/ISSUE_TEMPLATE/Contribution.yml.old
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
name: Contribution Request
|
||||
|
||||
description: Request access to contribute to the Excalidraw plugin documentation on the wiki
|
||||
|
||||
title: '[Contribution] Request to Contribute to Wiki'
|
||||
|
||||
labels: [collaboration-request]
|
||||
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Contribution Request
|
||||
|
||||
Thank you for your interest in contributing to the Excalidraw Plugin wiki! To help me understand how you’d like to contribute, please provide the following details:
|
||||
|
||||
1. **Contribution Area**: Describe what areas of the wiki you’re interested in contributing to (e.g., fixing typos, adding new tutorials, improving existing content).
|
||||
2. **Experience**: Briefly describe your experience with Excalidraw or Obsidian and any relevant background that will help with the contribution.
|
||||
3. **Additional Information**: Any other information or questions you may have.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
- Contribution Area: Adding a tutorial on advanced Excalidraw features
|
||||
- Experience: Regular user of Excalidraw and experienced in creating tutorials
|
||||
- Additional Information: Looking forward to contributing!
|
||||
```
|
||||
|
||||
Once I review your request, I will get back to you with instructions on how to proceed. Thank you for helping improve our documentation!
|
||||
|
||||
---
|
||||
Zsolt
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Contribution Details
|
||||
description: Provide details about your contribution request.
|
||||
placeholder: |
|
||||
- Contribution Area: Adding a tutorial on advanced Excalidraw features
|
||||
- Experience: Regular user of Excalidraw and experienced in creating tutorials
|
||||
- Additional Information: Looking forward to contributing!
|
||||
|
||||
- type: checkboxes
|
||||
id: verify_guidelines
|
||||
attributes:
|
||||
label: Please read the WIKI Contributors Guidelines before submitting your request!
|
||||
options:
|
||||
- label: Yes, I have read and understood the [Contributors Guidelines](https://github.com/zsviczian/obsidian-excalidraw-plugin/wiki/Contributor-Guidelines)
|
||||
|
||||
68
.github/ISSUE_TEMPLATE/How-to.yml
vendored
Normal file
68
.github/ISSUE_TEMPLATE/How-to.yml
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
name: How to? Support request
|
||||
description: Ask for help with using the plugin or understanding its features.
|
||||
title: "SUPPORT: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
ℹ️ **Important: Please Read Before Submitting a Support Request** ℹ️
|
||||
|
||||
I am a one-person team working on this plugin as a part-time hobby. Please help me manage the workload by following these guidelines. **Support requests that don't include enough details may be closed without review**.
|
||||
|
||||
Before submitting a support request, please:
|
||||
1. **Review the [documentation](https://github.com/zsviczian/obsidian-excalidraw-plugin/wiki)** – your question may already be answered.
|
||||
2. **[Search issues](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues) (including closed ones)** to see if your question has already been addressed.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please help by providing the following details. Requests without this information may be closed without review.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
---
|
||||
|
||||
- type: checkboxes
|
||||
id: search_existing_resources
|
||||
attributes:
|
||||
label: Have you checked the documentation and searched existing issues?
|
||||
description: Please confirm that you've reviewed available resources before submitting your request.
|
||||
options:
|
||||
- label: Yes, I have reviewed the documentation and searched for related issues.
|
||||
|
||||
- type: textarea
|
||||
id: support_question
|
||||
attributes:
|
||||
label: "Your question"
|
||||
description: "Provide a clear and concise description of the question or issue you need help with."
|
||||
placeholder: "Describe your question or the problem you are trying to solve..."
|
||||
|
||||
- type: textarea
|
||||
id: steps_tried
|
||||
attributes:
|
||||
label: "Steps you've already tried"
|
||||
description: "List any steps you've taken to try to resolve or understand the issue."
|
||||
placeholder: |
|
||||
1. Tried reading the documentation.
|
||||
2. Searched the issues for similar questions.
|
||||
|
||||
- type: textarea
|
||||
id: expected_outcome
|
||||
attributes:
|
||||
label: "Expected outcome"
|
||||
description: "Describe what you expected to happen or what you are trying to achieve."
|
||||
placeholder: "Describe the result you are aiming for..."
|
||||
|
||||
- type: textarea
|
||||
id: additional_context
|
||||
attributes:
|
||||
label: "Additional context"
|
||||
description: "Add any other context or details that may help."
|
||||
placeholder: "Include any other information that may be relevant..."
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Attachments: Screenshots and files are critical!**
|
||||
A picture speaks a thousand words, and a screen recording even more. **Please attach screenshots, screen recordings, or sample files** to help illustrate your question or issue. Drag and drop them into the comment area or directly into any of the text fields above.
|
||||
69
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
69
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: Feature request
|
||||
description: Request a new feature for the Excalidraw plugin.
|
||||
title: "FR: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
🛠️ **Important: Please Read Before Submitting a Feature Request** 🛠️
|
||||
|
||||
I develop Excalidraw primarily as a hobby, and I prioritize features that I personally use regularly. Features I don't use often break without me noticing, which is why the plugin is as stable as it is—because I rely on it every day.
|
||||
|
||||
**Your task isn't just to describe the feature you want, but to sell me on the idea**. If I'm not convinced that the feature would significantly benefit my own workflow, it's unlikely I'll spend my free hobby time on it.
|
||||
|
||||
When creating your feature request:
|
||||
- **Provide real-life usage scenarios**: How will this feature help you? How do you imagine using it in practice?
|
||||
- **Sell the idea**: Convince me that I need this feature too.
|
||||
- **Include supporting materials**: Reference other solutions? Include relevant screenshots, screen recordings, and links. The more work I need to do to understand your request, the less likely it is to be implemented.
|
||||
|
||||
**Additional Guidelines:**
|
||||
- **Excalidraw Core Features**: If your request relates to core Excalidraw features, and not the Obsidian integration specifically, please raise it with the Excalidraw product team here: [Excalidraw Issues](https://github.com/excalidraw/excalidraw/issues).
|
||||
- **Cross-Platform Compatibility**: Obsidian and Excalidraw are cross-platform solutions. I cannot develop platform-specific features like Apple Pencil or Samsung S-Pen support due to technical limitations. Please only request features that make sense across all platforms (Windows, Linux, ChromeOS, macOS, Android, iOS).
|
||||
|
||||
Remember: You're not asking from a genie. You're pitching to someone who will need to spend hours (even for small changes) on testing, releasing, documenting, and supporting the feature. If you don't sell it well, it won't get done.
|
||||
|
||||
**Explore Scripting First:**
|
||||
Many feature requests can already be achieved with scripts using Excalidraw Automate. While the documentation is somewhat dated, there are nearly a hundred published scripts available. With a little determination, you can explore the possibilities. Feeding relevant scripts into GPT can often generate a working solution. Start here: [Excalidraw Automate Documentation](https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html).
|
||||
|
||||
- type: textarea
|
||||
id: problem_description
|
||||
attributes:
|
||||
label: "Is your feature request related to a problem? Please describe."
|
||||
description: "Provide a clear and concise description of the problem. Ex. I'm always frustrated when..."
|
||||
placeholder: "Describe the problem you are facing..."
|
||||
|
||||
- type: textarea
|
||||
id: solution_description
|
||||
attributes:
|
||||
label: "Describe the solution you'd like"
|
||||
description: "Provide a clear and concise description of what you want to happen."
|
||||
placeholder: "Describe the feature you are requesting..."
|
||||
|
||||
- type: textarea
|
||||
id: usage_scenario
|
||||
attributes:
|
||||
label: "Real-life usage scenarios"
|
||||
description: "Provide specific examples of how you would use this feature. Convince me that this is a feature I need in my own workflow."
|
||||
placeholder: |
|
||||
1. In this scenario, I would use the feature to...
|
||||
2. Another use case is when I...
|
||||
|
||||
- type: textarea
|
||||
id: alternatives_considered
|
||||
attributes:
|
||||
label: "Describe alternatives you've considered"
|
||||
description: "Provide a clear and concise description of any alternative solutions or features you've considered."
|
||||
placeholder: "Describe any alternative approaches you have considered..."
|
||||
|
||||
- type: textarea
|
||||
id: additional_context
|
||||
attributes:
|
||||
label: "Additional context"
|
||||
description: "Include any other context, screenshots, or references about the feature request."
|
||||
placeholder: "Include screenshots, recordings, or other supporting material..."
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Attachments: Make your case visually!**
|
||||
Supporting images, screenshots, or screen recordings are critical for helping me understand your request. Drag and drop them into the comment area or directly into any of the text fields above. Every bit of detail increases the chance of your request being understood and prioritized.
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
[简体中文](./README.zh-cn.md)
|
||||
|
||||
👉👉👉 Check out and contribute to the new [Obsidian-Excalidraw Community Wiki](https://excalidraw-obsidian.online/Hobbies/Excalidraw+Blog/WIKI/Welcome+to+the+WIKI)
|
||||
|
||||
The Obsidian-Excalidraw plugin integrates [Excalidraw](https://excalidraw.com/), a feature rich sketching tool, into Obsidian. You can store and edit Excalidraw files in your vault, you can embed drawings into your documents, and you can link to documents and other drawings to/and from Excalidraw. For a showcase of Excalidraw features, please read my blog post [here](https://www.zsolt.blog/2021/03/showcasing-excalidraw.html) and/or watch the videos below.
|
||||
|
||||
## Video Walkthrough
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import fs from'fs';
|
||||
import LZString from 'lz-string';
|
||||
|
||||
const excalidraw_pkg = isProd
|
||||
? fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.development.js", "utf8");
|
||||
const react_pkg = isProd
|
||||
? fs.readFileSync("./node_modules/react/umd/react.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/react/umd/react.development.js", "utf8");
|
||||
const reactdom_pkg = isProd
|
||||
? fs.readFileSync("./node_modules/react-dom/umd/react-dom.production.min.js", "utf8")
|
||||
: fs.readFileSync("./node_modules/react-dom/umd/react-dom.development.js", "utf8");
|
||||
const lzstring_pkg = fs.readFileSync("./node_modules/lz-string/libs/lz-string.min.js", "utf8")
|
||||
|
||||
const packageString = lzstring_pkg+'const EXCALIDRAW_PACKAGES = "' + LZString.compressToBase64(react_pkg + reactdom_pkg + excalidraw_pkg) +'";var ExcalidrawPackageLoader=(d=document)=>{const excalidraw_id = "excalidraw-script";if(!d.getElementById(excalidraw_id)){const script=d.createElement("script");script.type="text/javascript";script.id=excalidraw_id;script.text=LZString.decompressFromBase64(EXCALIDRAW_PACKAGES);d.body.appendChild(script);}};ExcalidrawPackageLoader();';
|
||||
|
||||
const mainjs = fs.readFileSync("main.js", "utf8")
|
||||
|
||||
|
||||
fs.writeFileSync(
|
||||
"main2.js",
|
||||
mainjs
|
||||
.replace('(require("react"));','')
|
||||
.replace('"use strict";','"use strict";' + packageString),
|
||||
{
|
||||
encoding: "utf8",
|
||||
flag: "w",
|
||||
mode: 0o666
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
let config = {
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
Automatically switches between the select and draw tools, based on whether a pen is being used.
|
||||
|
||||
1. Choose the select tool
|
||||
2. Hover/use the pen to draw, move it away to return to select mode
|
||||
*This is based on pen hover status, so will only work if your pen supports hover!*
|
||||
If you click draw with the mouse or press select with the pen, switching will be disabled until the opposite input method is used.
|
||||
|
||||
**Note:** This script will stay active until the *Obsidian* window is closed.
|
||||
|
||||
Compatible with my *Hardware Eraser Support* script
|
||||
|
||||
```javascript
|
||||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
let promise
|
||||
let timeout
|
||||
let disable
|
||||
|
||||
function handlePointer(e) {
|
||||
ea.setView("active");
|
||||
var activeTool = ea.getExcalidrawAPI().getAppState().activeTool;
|
||||
function setActiveTool(t) {
|
||||
ea.getExcalidrawAPI().setActiveTool(t)
|
||||
}
|
||||
|
||||
if (e.pointerType === 'pen') {
|
||||
if (disable) return
|
||||
if (!promise && activeTool.type==='selection') {
|
||||
setActiveTool({type:"freedraw"})
|
||||
}
|
||||
|
||||
if (timeout) clearTimeout(timeout)
|
||||
|
||||
function setTimeoutX(a,b) {
|
||||
timeout = setTimeout(a,b)
|
||||
return timeout
|
||||
}
|
||||
|
||||
function revert() {
|
||||
activeTool = ea.getExcalidrawAPI().getAppState().activeTool;
|
||||
disable = false
|
||||
if (activeTool.type==='freedraw') {
|
||||
setActiveTool({type:"selection"})
|
||||
} else if (activeTool.type==='selection') {
|
||||
disable = true
|
||||
}
|
||||
promise = false
|
||||
}
|
||||
|
||||
promise = new Promise(resolve => setTimeoutX(resolve, 500))
|
||||
promise.then(() => revert())
|
||||
}
|
||||
}
|
||||
function handleClick(e) {
|
||||
ea.setView("active");
|
||||
if (e.pointerType !== 'pen') {
|
||||
disable = false
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('pointermove', handlePointer, { capture: true })
|
||||
window.addEventListener('pointerdown', handleClick, { capture: true })
|
||||
|
||||
})();
|
||||
@@ -1,50 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 448 512" style="enable-background:new 0 0 448 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{stroke:#000000;stroke-width:2;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M355.8,234.1"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M32.3,139.7l28.8,24.2l63.5-71.7L95.7,67c-7.2-6.3-18.2-5.6-24.5,1.6l-40.6,46.6C24.3,122.4,25,133.3,32.3,139.7z"/>
|
||||
<path d="M61.2,165.3l-29.6-24.9c-3.7-3.3-5.9-7.8-6.3-12.7c-0.3-4.9,1.3-9.6,4.5-13.2L70.5,68c6.7-7.6,18.3-8.4,25.9-1.7L126,92.1
|
||||
L61.2,165.3z M32.9,138.9l28,23.6l62.2-70.2l-28-24.6c-6.8-5.9-17.1-5.2-23.1,1.5l-40.6,46.6c-2.9,3.3-4.3,7.5-4,11.8
|
||||
C27.6,132,29.6,136,32.9,138.9z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon points="218.7,240.1 212.3,168.6 197.2,155.4 133.7,228.1 148.9,241.3 "/>
|
||||
<path d="M148.5,242.3l-16.2-14.1l64.8-74.2l16.2,14.1l6.5,73L148.5,242.3z M135.1,228l14.1,12.3l68.4-1.2l-6.2-70.1l-14.1-12.3
|
||||
L135.1,228z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon points="192.6,151.6 129.1,224.3 66.2,168.4 129.6,96.7 "/>
|
||||
<path d="M129.2,225.7l-64.5-57.2l64.8-73.2l64.5,56.2L129.2,225.7z M67.6,168.3l61.5,54.6l62.2-71.2l-61.5-53.6L67.6,168.3z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M109.7,381.6c-23.7-22.2-40-49.3-48.9-78.2c8.2-0.9,22.4-3.6,30.1-12.3c-12.6-12.5-25.3-25-37.9-37.5c0-0.1,0-0.3,0-0.4
|
||||
l-23.6-22c-6,60.7,15.5,123.7,63.7,168.8s112.5,62.4,172.7,52.4l-24.1-22.6C194.8,432.3,146.9,416.4,109.7,381.6z"/>
|
||||
<path d="M232.6,456.1c-19.6,0-39.2-2.8-57.9-8.3c-30.9-9.1-58.6-24.9-82.3-47.1C68.7,378.6,51.1,352,40,321.8
|
||||
c-10.6-28.8-14.6-60.2-11.6-90.7l0.2-2L54,252.8v0.4c6.2,6.1,12.4,12.3,18.6,18.4c6.3,6.3,12.7,12.5,19,18.8l0.7,0.7l-0.6,0.7
|
||||
c-7.2,8.1-19.8,11.3-29.5,12.5c9.2,29.2,25.9,55.6,48.3,76.6l0,0c35.8,33.5,82.4,50.5,131.3,47.9l0.4,0l25.9,24.3l-2,0.3
|
||||
C255,455.2,243.8,456.1,232.6,456.1z M30.2,233.3c-5.6,62.5,17.5,122.9,63.6,166c46,43.1,107.8,62.1,169.8,52.5l-22.3-20.9
|
||||
c-49.2,2.5-96.2-14.7-132.3-48.5l0,0c-22.9-21.5-39.9-48.7-49.2-78.6l-0.4-1.2l1.2-0.1c9.3-1,21.6-3.8,28.8-11.3
|
||||
c-6.1-6-12.2-12.1-18.3-18.1c-6.3-6.2-12.6-12.5-18.9-18.7L52,254v-0.4L30.2,233.3z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M368.8,105.4c-56-52.4-133.5-67.2-201.3-45.5l21,19.6c56.1-13.2,117.7,1.1,163.1,43.7c33,30.9,51.7,71.2,55.9,112.7
|
||||
c-0.2-0.4-0.3-0.6-0.3-0.6s-25.1-0.1-36.5,12.7c11.8,11.6,23.5,23.3,35.3,34.9v0.1l2.4,2.3c0.4,0.4,0.9,0.9,1.3,1.3l0,0l17.7,16.6
|
||||
C444.7,234.1,424.8,157.7,368.8,105.4z"/>
|
||||
<path d="M428,305.1L409,287.3l-1.3-1.3l-2.7-2.6v-0.1c-5.8-5.7-11.5-11.4-17.3-17.1c-5.9-5.8-11.8-11.7-17.7-17.5l-0.7-0.7
|
||||
l0.6-0.7c10.5-11.8,31.7-12.9,36.4-13c-4.7-42.1-24.3-81.3-55.4-110.4c-43.5-40.9-104.2-57.1-162.2-43.5l-0.5,0.1l-22.6-21.1
|
||||
l1.6-0.5c70.5-22.6,148-5,202.3,45.7c54.3,50.7,76.9,126.9,58.9,198.8L428,305.1z M407,282.6l3.4,3.3l16.4,15.4
|
||||
c17.1-70.7-5.3-145.3-58.7-195.2l0,0c-53.3-49.9-129.3-67.4-198.7-45.8l19.4,18.1c58.5-13.6,119.6,2.9,163.5,44.1
|
||||
c31.9,29.8,51.8,70.1,56.2,113.3l0.5,5.4l-2.5-4.9c-3.8,0.1-24.3,1.1-34.5,11.7c5.7,5.6,11.3,11.2,17,16.8
|
||||
c5.9,5.8,11.7,11.6,17.6,17.4L407,282.6L407,282.6z"/>
|
||||
</g>
|
||||
<polygon points="425.2,382.2 302.7,283.9 299.4,437.6 340.9,383.8 382.3,456.5 398,447.5 359.4,379.8 "/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.3 KiB |
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
Adds support for pen inversion, a.k.a. the hardware eraser on the back of your pen.
|
||||
|
||||
Simply use the eraser on a supported pen, and it will erase. Your previous tool will be restored when the eraser leaves the screen.
|
||||
(Tested with a surface pen, but should work with all windows ink devices, and probably others)
|
||||
|
||||
**Note:** This script will stay active until the *Obsidian* window is closed.
|
||||
|
||||
Compatible with my *Auto Draw for Pen* script
|
||||
|
||||
```javascript
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
let activated
|
||||
let revert
|
||||
|
||||
function handlePointer(e) {
|
||||
const activeTool = ea.getExcalidrawAPI().getAppState().activeTool;
|
||||
const isEraser = e.pointerType === 'pen' && e.buttons & 32
|
||||
function setActiveTool(t) {
|
||||
ea.getExcalidrawAPI().setActiveTool(t)
|
||||
}
|
||||
if (!activated && isEraser) {
|
||||
//Store previous tool
|
||||
const btns = document.querySelectorAll('.App-toolbar input.ToolIcon_type_radio')
|
||||
for (const i in btns) {
|
||||
if (btns[i]?.checked) {
|
||||
revert = btns[i]
|
||||
}
|
||||
}
|
||||
revert = activeTool
|
||||
|
||||
// Activate eraser tool
|
||||
setActiveTool({type: "eraser"})
|
||||
activated = true
|
||||
|
||||
// Force Excalidraw to recognize this the same as pen tip
|
||||
// https://github.com/excalidraw/excalidraw/blob/4a9fac2d1e5c4fac334201ef53c6f5d2b5f6f9f5/src/components/App.tsx#L2945-L2951
|
||||
Object.defineProperty(e, 'button', {
|
||||
value: 0,
|
||||
writable: false
|
||||
});
|
||||
}
|
||||
// Keep on eraser!
|
||||
if (isEraser && activated) {
|
||||
setActiveTool({type: "eraser"})
|
||||
}
|
||||
if (activated && !isEraser) {
|
||||
// Revert tool on release
|
||||
// revert.click()
|
||||
setActiveTool(revert)
|
||||
activated = false
|
||||
|
||||
// Force delete "limbo" elements
|
||||
// This doesn't happen on the web app
|
||||
// It's a bug caused by switching to eraser during a stroke
|
||||
ea.setView("active");
|
||||
var del = []
|
||||
for (const i in ea.getViewElements()) {
|
||||
const element = ea.getViewElements()[i];
|
||||
if (element.opacity === 20) {
|
||||
del.push(element)
|
||||
}
|
||||
}
|
||||
ea.deleteViewElements(del)
|
||||
setActiveTool(revert)
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('pointerdown', handlePointer, { capture: true })
|
||||
window.addEventListener('pointermove', handlePointer, { capture: true })
|
||||
})();
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 448 512" style="enable-background:new 0 0 448 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{stroke:#000000;stroke-width:2;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<path class="st0" d="M355.8,234.1"/>
|
||||
<g>
|
||||
<path class="st0" d="M404.8,293.5L306.9,208l-120,137.4l97.9,85.5c13.6,11.9,34.4,10.5,46.3-3.1l76.8-88
|
||||
C419.9,326.2,418.5,305.5,404.8,293.5z M389.4,322.2l-78.2,89.6c-3.8,4.3-10.4,4.8-14.8,1l-77.8-68l92-105.3l77.8,68
|
||||
C392.8,311.2,393.2,317.8,389.4,322.2z"/>
|
||||
<polygon class="st0" points="52.4,103.7 64.4,238.9 93,263.8 213,126.4 184.4,101.4 "/>
|
||||
|
||||
<rect x="108.3" y="185.1" transform="matrix(0.6578 -0.7532 0.7532 0.6578 -108.9276 230.7956)" class="st0" width="182.4" height="100.3"/>
|
||||
<path class="st0" d="M109.7,381.6c-23.7-22.2-40-49.3-48.9-78.2c8.2-0.9,22.4-3.6,30.1-12.3c-12.6-12.5-25.3-25-37.9-37.5
|
||||
c0-0.1,0-0.3,0-0.4l-23.6-22c-6,60.7,15.5,123.7,63.7,168.8s112.5,62.4,172.7,52.4l-24.1-22.6C194.8,432.3,146.9,416.4,109.7,381.6
|
||||
z"/>
|
||||
<path class="st0" d="M368.8,105.4c-56-52.4-133.5-67.2-201.3-45.5l21,19.6c56.1-13.2,117.7,1.1,163.1,43.7
|
||||
c33,30.9,51.7,71.2,55.9,112.7c-0.2-0.4-0.3-0.6-0.3-0.6s-25.1-0.1-36.5,12.7c11.8,11.6,23.5,23.3,35.3,34.9c0,0,0,0.1,0,0.1
|
||||
l2.4,2.3c0.4,0.4,0.9,0.9,1.3,1.3c0,0,0,0,0,0l17.7,16.6C444.7,234.1,424.8,157.7,368.8,105.4z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
File diff suppressed because one or more lines are too long
@@ -115,14 +115,12 @@ 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/Auto%20Draw%20for%20Pen.svg"/></div>|[[#Auto Draw for Pen]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Boolean%20Operations.svg"/></div>|[[#Boolean Operations]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Custom%20Zoom.svg"/></div>|[[#Custom Zoom]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Copy%20Selected%20Element%20Styles%20to%20Global.svg"/></div>|[[#Copy Selected Element Styles to Global]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/ExcaliAI.svg"/></div>|[[#ExcaliAI]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Excalidraw%20Writing%20Machine.svg"/></div>|[[#Excalidraw Writing Machine]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/GPT-Draw-a-UI.svg"/></div>|[[#GPT Draw-a-UI]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Hardware%20Eraser%20Support.svg"/></div>|[[#Hardware Eraser Support]]|
|
||||
|<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/PDF%20Page%20Text%20to%20Clipboard.svg"/></div>|[[#PDF Page Text to Clipboard]]|
|
||||
|<div><img src="https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Rename%20Image.svg"/></div>|[[#Rename Image]]|
|
||||
@@ -184,12 +182,6 @@ 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/Add%20Next%20Step%20in%20Process.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script will prompt you for the title of the process step, then will create a stick note with the text. If an element is selected then the script will connect this new step with an arrow to the previous step (the selected element). If no element is selected, then the script assumes this is the first step in the process and will only output the sticky note with the text that was entered.<br><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-add-process-step.jpg'></td></tr></table>
|
||||
|
||||
## Auto Draw for Pen
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Auto%20Draw%20for%20Pen.md
|
||||
```
|
||||
<table><tr valign='top'><td class="label">Author</td><td class="data"><a href='https://github.com/threethan'>@threethan</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/Auto%20Draw%20for%20Pen.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Automatically switches from select mode to drawing mode when hovering a pen, and then back.</td></tr></table>
|
||||
|
||||
## Auto Layout
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Auto%20Layout.md
|
||||
@@ -403,13 +395,6 @@ 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/GPT-Draw-a-UI.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">This script was discontinued in favor of ExcaliAI. Draw a UI and let GPT create the code for you.<br><iframe width="400" height="225" src="https://www.youtube.com/embed/y3kHl_6Ll4w" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><img src='https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/images/scripts-draw-a-ui.jpg'></td></tr></table>
|
||||
|
||||
|
||||
## Hardware Eraser Support
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Hardware%20Eraser%20Support.md
|
||||
```
|
||||
<table><tr valign='top'><td class="label">Author</td><td class="data"><a href='https://github.com/threethan'>@threethan</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/Hardware%20Eraser%20Support.md'>File on GitHub</a></td></tr><tr valign='top'><td class="label">Description</td><td class="data">Allows you to use inversion, aka hardware eraser, on supported pens.</td></tr></table>
|
||||
|
||||
## Invert colors
|
||||
```excalidraw-script-install
|
||||
https://raw.githubusercontent.com/zsviczian/obsidian-excalidraw-plugin/master/ea-scripts/Invert%20colors.md
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "2.4.1",
|
||||
"version": "2.5.0-beta-1",
|
||||
"minAppVersion": "1.1.6",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "2.4.1",
|
||||
"version": "2.4.3",
|
||||
"minAppVersion": "1.1.6",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@zsviczian/excalidraw": "0.17.1-obsidian-47",
|
||||
"@zsviczian/excalidraw": "0.17.1-obsidian-50",
|
||||
"chroma-js": "^2.4.2",
|
||||
"clsx": "^2.0.0",
|
||||
"@zsviczian/colormaster": "^1.2.2",
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import fs from'fs';
|
||||
import LZString from 'lz-string';
|
||||
|
||||
const excalidraw_pkg = fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.production.min.js", "utf8");
|
||||
const react_pkg = fs.readFileSync("./node_modules/react/umd/react.production.min.js", "utf8");
|
||||
const reactdom_pkg = fs.readFileSync("./node_modules/react-dom/umd/react-dom.production.min.js", "utf8");
|
||||
const lzstring_pkg = fs.readFileSync("./node_modules/lz-string/libs/lz-string.min.js", "utf8");
|
||||
const mainjs = fs.readFileSync("main.js", "utf8")
|
||||
|
||||
const packageString = lzstring_pkg+'const EXCALIDRAW_PACKAGES="' + LZString.compressToBase64(react_pkg + reactdom_pkg + excalidraw_pkg) +'";var ExcalidrawPackageLoader=(d=document)=>{if(!d.getElementById("excalidraw-script")){const script=d.createElement("script");script.type="text/javascript";script.id="excalidraw-script";script.text=LZString.decompressFromBase64(EXCALIDRAW_PACKAGES);d.body.appendChild(script);}};ExcalidrawPackageLoader();';
|
||||
|
||||
fs.writeFileSync(
|
||||
"main2.js",
|
||||
mainjs
|
||||
.replace('(require("react"))','')
|
||||
.replace('"use strict";','"use strict";' + packageString),
|
||||
{
|
||||
encoding: "utf8",
|
||||
flag: "w",
|
||||
mode: 0o666
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
export default ({
|
||||
input: 'foo',
|
||||
plugins: [],
|
||||
output: [{
|
||||
file: 'foo.js',
|
||||
format: 'es'
|
||||
}]
|
||||
});
|
||||
@@ -593,6 +593,7 @@ export class EmbeddedFilesLoader {
|
||||
addFiles: (files: FileData[], isDark: boolean, final?: boolean) => void,
|
||||
depth:number,
|
||||
isThemeChange:boolean = false,
|
||||
fileIDWhiteList?: Set<FileId>,
|
||||
) {
|
||||
|
||||
if(depth > 7) {
|
||||
@@ -607,6 +608,7 @@ export class EmbeddedFilesLoader {
|
||||
let entry: IteratorResult<[FileId, EmbeddedFile]>;
|
||||
const files: FileData[] = [];
|
||||
while (!this.terminate && !(entry = entries.next()).done) {
|
||||
if(fileIDWhiteList && !fileIDWhiteList.has(entry.value[0])) continue;
|
||||
const embeddedFile: EmbeddedFile = entry.value[1];
|
||||
if (!embeddedFile.isLoaded(this.isDark)) {
|
||||
//debug({where:"EmbeddedFileLoader.loadSceneFiles",uid:this.uid,status:"embedded Files are not loaded"});
|
||||
@@ -653,6 +655,7 @@ export class EmbeddedFilesLoader {
|
||||
let equation;
|
||||
const equations = excalidrawData.getEquationEntries();
|
||||
while (!this.terminate && !(equation = equations.next()).done) {
|
||||
if(fileIDWhiteList && !fileIDWhiteList.has(entry.value[0])) continue;
|
||||
if (!excalidrawData.getEquation(equation.value[0]).isLoaded) {
|
||||
const latex = equation.value[1].latex;
|
||||
const data = await tex2dataURL(latex);
|
||||
|
||||
@@ -427,7 +427,9 @@ export class ExcalidrawAutomate {
|
||||
* @returns
|
||||
*/
|
||||
public getAPI(view?:ExcalidrawView):ExcalidrawAutomate {
|
||||
return new ExcalidrawAutomate(this.plugin, view);
|
||||
const ea = new ExcalidrawAutomate(this.plugin, view);
|
||||
this.plugin.eaInstances.push(ea);
|
||||
return ea;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -741,18 +743,18 @@ export class ExcalidrawAutomate {
|
||||
|
||||
outString += Object.keys(this.imagesDict).length > 0
|
||||
? `\n## Embedded Files\n`
|
||||
: "";
|
||||
: "\n";
|
||||
|
||||
Object.keys(this.imagesDict).forEach((key: FileId)=> {
|
||||
const item = this.imagesDict[key];
|
||||
if(item.latex) {
|
||||
outString += `${key}: $$${item.latex}$$\n`;
|
||||
outString += `${key}: $$${item.latex}$$\n\n`;
|
||||
} else {
|
||||
if(item.file) {
|
||||
if(item.file instanceof TFile) {
|
||||
outString += `${key}: [[${item.file.path}]]\n`;
|
||||
outString += `${key}: [[${item.file.path}]]\n\n`;
|
||||
} else {
|
||||
outString += `${key}: [[${item.file}]]\n`;
|
||||
outString += `${key}: [[${item.file}]]\n\n`;
|
||||
}
|
||||
} else {
|
||||
const hyperlinkSplit = item.hyperlink.split("#");
|
||||
@@ -760,15 +762,15 @@ export class ExcalidrawAutomate {
|
||||
if(file && file instanceof TFile) {
|
||||
const hasFileRef = hyperlinkSplit.length === 2
|
||||
outString += hasFileRef
|
||||
? `${key}: [[${file.path}#${hyperlinkSplit[1]}]]\n`
|
||||
: `${key}: [[${file.path}]]\n`;
|
||||
? `${key}: [[${file.path}#${hyperlinkSplit[1]}]]\n\n`
|
||||
: `${key}: [[${file.path}]]\n\n`;
|
||||
} else {
|
||||
outString += `${key}: ${item.hyperlink}\n`;
|
||||
outString += `${key}: ${item.hyperlink}\n\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return outString + "\n%%\n";
|
||||
return outString + "%%\n";
|
||||
}
|
||||
|
||||
const filename = params?.filename
|
||||
@@ -2961,27 +2963,6 @@ async function getTemplate(
|
||||
}
|
||||
|
||||
let scene = excalidrawData.scene;
|
||||
if (loadFiles) {
|
||||
//debug({where:"getTemplate",template:file.name,loader:loader.uid});
|
||||
await loader.loadSceneFiles(excalidrawData, (fileArray: FileData[]) => {
|
||||
//, isDark: boolean) => {
|
||||
if (!fileArray || fileArray.length === 0) {
|
||||
return;
|
||||
}
|
||||
for (const f of fileArray) {
|
||||
if (f.hasSVGwithBitmap) {
|
||||
hasSVGwithBitmap = true;
|
||||
}
|
||||
excalidrawData.scene.files[f.id] = {
|
||||
mimeType: f.mimeType,
|
||||
id: f.id,
|
||||
dataURL: f.dataURL,
|
||||
created: f.created,
|
||||
};
|
||||
}
|
||||
scene = scaleLoadedImage(excalidrawData.scene, fileArray).scene;
|
||||
}, depth);
|
||||
}
|
||||
|
||||
let groupElements:ExcalidrawElement[] = scene.elements;
|
||||
if(filenameParts.hasGroupref) {
|
||||
@@ -3008,8 +2989,41 @@ async function getTemplate(
|
||||
));
|
||||
}
|
||||
|
||||
const fileIDWhiteList = new Set<FileId>();
|
||||
groupElements.filter(el=>el.type==="image").forEach((el:ExcalidrawImageElement)=>fileIDWhiteList.add(el.fileId));
|
||||
|
||||
if (loadFiles) {
|
||||
//debug({where:"getTemplate",template:file.name,loader:loader.uid});
|
||||
await loader.loadSceneFiles(excalidrawData, (fileArray: FileData[]) => {
|
||||
//, isDark: boolean) => {
|
||||
if (!fileArray || fileArray.length === 0) {
|
||||
return;
|
||||
}
|
||||
for (const f of fileArray) {
|
||||
if (f.hasSVGwithBitmap) {
|
||||
hasSVGwithBitmap = true;
|
||||
}
|
||||
excalidrawData.scene.files[f.id] = {
|
||||
mimeType: f.mimeType,
|
||||
id: f.id,
|
||||
dataURL: f.dataURL,
|
||||
created: f.created,
|
||||
};
|
||||
}
|
||||
scene = scaleLoadedImage(excalidrawData.scene, fileArray).scene;
|
||||
}, depth, false, fileIDWhiteList);
|
||||
}
|
||||
|
||||
excalidrawData.destroy();
|
||||
const filehead = data.substring(0, trimLocation);
|
||||
let files:any = {};
|
||||
const sceneFilesSize = Object.values(scene.files).length;
|
||||
if (sceneFilesSize > 0) {
|
||||
if(sceneFilesSize === fileIDWhiteList.size)
|
||||
Object.values(scene.files).filter((f: any) => fileIDWhiteList.has(f.id)).forEach((f: any) => {
|
||||
files[f.id] = f;
|
||||
});
|
||||
}
|
||||
return {
|
||||
elements: convertMarkdownLinksToObsidianURLs
|
||||
? updateElementLinksToObsidianLinks({
|
||||
@@ -3018,7 +3032,7 @@ async function getTemplate(
|
||||
}) : groupElements,
|
||||
appState: scene.appState,
|
||||
frontmatter: filehead.match(/^---\n.*\n---\n/ms)?.[0] ?? filehead,
|
||||
files: scene.files,
|
||||
files,
|
||||
hasSVGwithBitmap,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1434,12 +1434,11 @@ export class ExcalidrawData {
|
||||
if (this.elementLinks.size > 0 || textElementLinks.size > 0) {
|
||||
outString += `## Element Links\n`;
|
||||
for (const key of this.elementLinks.keys()) {
|
||||
outString += `${key}: ${this.elementLinks.get(key)}\n`;
|
||||
outString += `${key}: ${this.elementLinks.get(key)}\n\n`;
|
||||
}
|
||||
for (const key of textElementLinks.keys()) {
|
||||
outString += `${key}: ${textElementLinks.get(key)}\n`;
|
||||
outString += `${key}: ${textElementLinks.get(key)}\n\n`;
|
||||
}
|
||||
outString += "\n";
|
||||
}
|
||||
|
||||
// deliberately not adding mermaids to here. It is enough to have the mermaidText in the image element's customData
|
||||
@@ -1449,7 +1448,7 @@ export class ExcalidrawData {
|
||||
: "";
|
||||
if (this.equations.size > 0) {
|
||||
for (const key of this.equations.keys()) {
|
||||
outString += `${key}: $$${this.equations.get(key).latex}$$\n`;
|
||||
outString += `${key}: $$${this.equations.get(key).latex}$$\n\n`;
|
||||
}
|
||||
}
|
||||
if (this.files.size > 0) {
|
||||
@@ -1457,18 +1456,18 @@ export class ExcalidrawData {
|
||||
const PATHREG = /(^[^#\|]*)/;
|
||||
const ef = this.files.get(key);
|
||||
if(ef.isHyperLink || ef.isLocalLink) {
|
||||
outString += `${key}: ${ef.hyperlink}\n`;
|
||||
outString += `${key}: ${ef.hyperlink}\n\n`;
|
||||
} else {
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/829
|
||||
const path = ef.file
|
||||
? ef.linkParts.original.replace(PATHREG,this.app.metadataCache.fileToLinktext(ef.file,this.file.path))
|
||||
: ef.linkParts.original;
|
||||
const colorMap = ef.colorMap ? " " + JSON.stringify(ef.colorMap) : "";
|
||||
outString += `${key}: [[${path}]]${colorMap}\n`;
|
||||
outString += `${key}: [[${path}]]${colorMap}\n\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
outString += this.equations.size > 0 || this.files.size > 0 ? "\n" : "";
|
||||
//outString += this.equations.size > 0 || this.files.size > 0 ? "\n" : "";
|
||||
|
||||
const sceneJSONstring = JSON.stringify({
|
||||
type: this.scene.type,
|
||||
|
||||
@@ -763,6 +763,8 @@ export default class ExcalidrawView extends TextFileView {
|
||||
this.clearPreventReloadTimer();
|
||||
|
||||
this.semaphores.preventReload = preventReload;
|
||||
await this.prepareGetViewData();
|
||||
|
||||
//added this to avoid Electron crash when terminating a popout window and saving the drawing, need to check back
|
||||
//can likely be removed once this is resolved: https://github.com/electron/electron/issues/40607
|
||||
if(this.semaphores?.viewunload) {
|
||||
@@ -774,10 +776,10 @@ export default class ExcalidrawView extends TextFileView {
|
||||
await plugin.app.vault.modify(file,d);
|
||||
await imageCache.addBAKToCache(file.path,d);
|
||||
},200)
|
||||
this.semaphores.saving = false;
|
||||
return;
|
||||
}
|
||||
|
||||
await this.prepareGetViewData();
|
||||
await super.save();
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
if (DEBUGGING) {
|
||||
@@ -931,6 +933,10 @@ export default class ExcalidrawView extends TextFileView {
|
||||
}
|
||||
|
||||
async openLaTeXEditor(eqId: string) {
|
||||
if(await this.excalidrawData.syncElements(this.getScene())) {
|
||||
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1994
|
||||
await this.forceSave(true);
|
||||
}
|
||||
const el = this.getViewElements().find((el:ExcalidrawElement)=>el.id === eqId && el.type==="image") as ExcalidrawImageElement;
|
||||
if(!el) {
|
||||
return;
|
||||
@@ -1544,7 +1550,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
|
||||
this.registerDomEvent(this.ownerWindow, "keydown", onKeyDown, false);
|
||||
this.registerDomEvent(this.ownerWindow, "keyup", onKeyUp, false);
|
||||
this.registerDomEvent(this.contentEl, "mouseleave", onBlurOrLeave, false);
|
||||
//this.registerDomEvent(this.contentEl, "mouseleave", onBlurOrLeave, false); //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2004
|
||||
this.registerDomEvent(this.ownerWindow, "blur", onBlurOrLeave, false);
|
||||
});
|
||||
|
||||
@@ -1783,7 +1789,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
//deliberately not calling super.onUnloadFile() to avoid autosave (saved in unload)
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.onUnloadFile,`ExcalidrawView.onUnloadFile, file:${this.file?.name}`);
|
||||
let counter = 0;
|
||||
while (this.semaphores.saving) {
|
||||
while (this.semaphores.saving && (counter++ < 200)) {
|
||||
await sleep(50); //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1988
|
||||
if(counter++ === 15) {
|
||||
new Notice(t("SAVE_IS_TAKING_LONG"));
|
||||
@@ -1792,6 +1798,10 @@ export default class ExcalidrawView extends TextFileView {
|
||||
new Notice(t("SAVE_IS_TAKING_VERY_LONG"));
|
||||
}
|
||||
}
|
||||
if(counter >= 200) {
|
||||
new Notice("Unknown error, save is taking too long");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private async forceSaveIfRequired():Promise<boolean> {
|
||||
|
||||
@@ -17,6 +17,34 @@ I develop this plugin as a hobby, spending my free time doing this. If you find
|
||||
|
||||
<div class="ex-coffee-div"><a href="https://ko-fi.com/zsolt"><img src="https://cdn.ko-fi.com/cdn/kofi3.png?v=3" height=45></a></div>
|
||||
`,
|
||||
"2.4.3": `
|
||||
Check out the [Excalidraw Plugin's Community WIKI](https://excalidraw-obsidian.online/Hobbies/Excalidraw+Blog/WIKI/Welcome+to+the+WIKI) and help with your content contribution.
|
||||
|
||||
## Fixed
|
||||
- In some situations Excalidraw hangs indefinitely when opening a different file in the same tab
|
||||
- Can't exit arrow tool on phone [#2006](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2006)
|
||||
- Save is triggered every few seconds, leading to glitches in handwriting [#2004](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2004)
|
||||
- Canvas shifts when editing text reaches right hand side of the canvas, especially at higher zoom values
|
||||
- Minor styling tweaks to adapt to Obsidian 1.7.1 new stylesheet, in particular to scale Excalidraw properly in line with Obsidian Appearance Setting Font-Size value.
|
||||
- Tweaked Compatibilty Setting description to mention Obsidian 1.7.1 Footnotes support
|
||||
`,
|
||||
"2.4.2": `
|
||||
This release addresses critical issues for all Obsidian Mobile users.
|
||||
|
||||
#### 😞 I made two mistakes...
|
||||
- I expedited the 2.4.1 release to resolve a major bug, but in doing so, I skippes some of my usual rigorous testing
|
||||
- I included a new feature in 2.4.1 fresh from Excalidraw.com because I believe it brings significant end user benefits and did not want to wait until October. However, a small part of this feature was designed for server-side execution on Excalidraw.com, not for local use on Obsidian Mobile.
|
||||
|
||||
Despite the recent two (2.4.1 and 2.4.2) emergency bug-fix releases, this doesn't deviate from the [monthly release schedule](https://youtu.be/2poSS-Z91lY). The next feature update is still planned for early October.
|
||||
|
||||
## Fixes:
|
||||
- **Excalidraw rendering issues on Obsidian Mobile:** [#1995](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1995), [#1997](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1997)
|
||||
- Nested Excalidraw drawings with text failed to render.
|
||||
- Drawings in Markdown view didn't render if they contained text and were set to SVG Image or SVG Native (they worked with PNG).
|
||||
- SVG export failed for drawings containing text.
|
||||
- **LaTeX equation duplication:** After using ALT+Drag to duplicate a LaTeX equation, editing the duplicate modified the original instead. [#1984](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1994)
|
||||
- **Unreadable Obsidian search results:** When drawings contained numerous Element Links and Embedded Files Links, search results became unreadable. This fix will apply to files saved after installing the update. [#1999](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1999)
|
||||
`,
|
||||
"2.4.1": `
|
||||
This release includes an important fix that can result in your drawing being overwritten by another drawing. Please update to this version as soon as possible.
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ export class ScriptInstallPrompt extends Modal {
|
||||
searchBar.type = "text";
|
||||
searchBar.id = "search-bar";
|
||||
searchBar.placeholder = "Search...";
|
||||
searchBar.style.width = "calc(100% - 120px)"; // space for the buttons and hit count
|
||||
//searchBar.style.width = "calc(100% - 120px)"; // space for the buttons and hit count
|
||||
|
||||
const nextButton = document.createElement("button");
|
||||
nextButton.textContent = "→";
|
||||
|
||||
@@ -654,6 +654,12 @@ export const EXCALIDRAW_AUTOMATE_INFO: SuggesterInfo[] = [
|
||||
"the function will use ea.targetView.file",
|
||||
after: "",
|
||||
},
|
||||
{
|
||||
field: "getAPI",
|
||||
code: "public getAPI(view?:ExcalidrawView):ExcalidrawAutomate",
|
||||
desc: "Returns a new instance of ExcalidrawAutomate.",
|
||||
after: "",
|
||||
},
|
||||
{
|
||||
field: "getAttachmentFilepath",
|
||||
code: "async getAttachmentFilepath(filename: string): Promise<string>",
|
||||
@@ -907,7 +913,7 @@ export const FRONTMATTER_KEYS_INFO: SuggesterInfo[] = [
|
||||
after: ": 1",
|
||||
},
|
||||
{
|
||||
field: "excalidraw-export-embed-scene",
|
||||
field: "export-embed-scene",
|
||||
code: null,
|
||||
desc: "If this key is present it will override the default excalidraw embed and export setting.",
|
||||
after: ": false",
|
||||
|
||||
@@ -653,7 +653,7 @@ FILENAME_HEAD: "Filename",
|
||||
"Use this setting if for good reasons you have decided to ignore my recommendation and configured linting of Excalidraw files.<br> " +
|
||||
"The <code>## Text Elements</code> section is sensitive to empty lines. A common linting approach is to add an empty line after section headings. In case of Excalidraw this will break/change the first text element in your drawing. " +
|
||||
"To overcome this, you can enable this setting. When enabled, Excalidraw will add a dummy element to the beginning of <code>## Text Elements</code> that the linter can safely modify." ,
|
||||
PRESERVE_TEXT_AFTER_DRAWING_NAME: "Zotero compatibility",
|
||||
PRESERVE_TEXT_AFTER_DRAWING_NAME: "Zotero and Footnotes compatibility",
|
||||
PRESERVE_TEXT_AFTER_DRAWING_DESC: "Preserve text after the ## Drawing section of the markdown file. This may have a very slight performance impact when saving very large drawings.",
|
||||
DEBUGMODE_NAME: "Enable debug messages",
|
||||
DEBUGMODE_DESC: "I recommend restarting Obsidian after enabling/disabling this setting. This enable debug messages in the console. This is useful for troubleshooting issues. " +
|
||||
|
||||
@@ -153,6 +153,24 @@ export default {
|
||||
REMOVE_LINK: "移除文字元素链接",
|
||||
LASER_ON: "启用激光笔",
|
||||
LASER_OFF: "关闭激光笔",
|
||||
WELCOME_RANK_NEXT: "张绘图之后,可以到达下一等级!",
|
||||
WELCOME_RANK_LEGENDARY: "您已是绘图大师,请续写传奇~",
|
||||
WELCOME_COMMAND_PALETTE: '在命令面板中输入 "Excalidraw"',
|
||||
WELCOME_OBSIDIAN_MENU: "探索右上角的 Obsidian 菜单",
|
||||
WELCOME_SCRIPT_LIBRARY: "访问脚本库",
|
||||
WELCOME_HELP_MENU: "在汉堡菜单(三横线)中寻找帮助",
|
||||
WELCOME_YOUTUBE_ARIA: "可视化个人知识管理的 YouTube 频道",
|
||||
WELCOME_YOUTUBE_LINK: "查看可视化个人知识管理的 YouTube 频道",
|
||||
WELCOME_DISCORD_ARIA: "加入 Discord 服务器",
|
||||
WELCOME_DISCORD_LINK: "加入 Discord 服务器",
|
||||
WELCOME_TWITTER_ARIA: "在 Twitter 上关注我",
|
||||
WELCOME_TWITTER_LINK: "在 Twitter 上关注我",
|
||||
WELCOME_LEARN_ARIA: "学习“可视化个人知识管理”(Visual PKM)",
|
||||
WELCOME_LEARN_LINK: "报名加入视觉思维工作坊",
|
||||
WELCOME_DONATE_ARIA: "捐赠以支持 Excalidraw-Obsidian",
|
||||
WELCOME_DONATE_LINK: '感谢并支持此插件。',
|
||||
SAVE_IS_TAKING_LONG: "保存您之前的文件花费的时间较长,请稍候...",
|
||||
SAVE_IS_TAKING_VERY_LONG: "为了更好的性能,请考虑将大型绘图拆分成几个较小的文件。",
|
||||
|
||||
//settings.ts
|
||||
RELEASE_NOTES_NAME: "显示更新说明",
|
||||
@@ -721,14 +739,16 @@ FILENAME_HEAD: "文件名",
|
||||
CUSTOM_FONT_HEAD: "本地字体",
|
||||
ENABLE_FOURTH_FONT_NAME: "为文本元素启用本地字体",
|
||||
ENABLE_FOURTH_FONT_DESC:
|
||||
"开启此项后,文本元素的属性面板里会多出一个本地字体按钮。<br>" +
|
||||
"使用了本地字体的绘图文件,将会失去一部分跨平台能力 —— " +
|
||||
"若将绘图文件移动到其他库中打开,显示效果可能会截然不同;" +
|
||||
"若在 excalidraw.com 或者其他版本的 Excalidraw 中打开,使用本地字体的文本会变回系统默认字体。",
|
||||
"启用此选项将在文本元素的属性面板的字体列表中添加一个本地字体。" +
|
||||
"请注意,使用这个本地字体可能会破坏平台的独立性。" +
|
||||
"使用自定义字体的文件在不同的库中打开或在以后打开时,根据字体设置,可能会以不同的方式呈现。" +
|
||||
"此外,在excalidraw.com 或其他 Excalidraw 版本中,默认的本地字体字体将使用系统字体。",
|
||||
FOURTH_FONT_NAME: "本地字体文件",
|
||||
FOURTH_FONT_DESC:
|
||||
"选择库文件夹中的一个 .ttf,.woff 或 .woff2 字体文件作为本地字体文件。若未选择文件,则使用默认的 Virgil 字体。"+
|
||||
"<mark>译者注:</mark>您可以在<a href='https://wangchujiang.com/free-font/' target='_blank'>Free Font</a>获取免费商用字体。",
|
||||
"从您的库中选择一个 .otf、.ttf、.woff 或 .woff2 字体文件作为本地字体使用。"+
|
||||
"如果没有选择文件,Excalidraw 将默认使用 Virgil 字体。"+
|
||||
"为了获得最佳性能,建议使用 .woff2 文件,因为当导出到 SVG 格式的图像时,Excalidraw 只会编码必要的字形。"+
|
||||
"其他字体格式将在导出文件中嵌入整个字体,可能会导致文件大小显著增加。<mark>译者注:</mark>您可以在<a href='https://wangchujiang.com/free-font/' target='_blank'>Free Font</a>获取免费商用中文手写字体。",
|
||||
SCRIPT_SETTINGS_HEAD: "已安装脚本的设置",
|
||||
SCRIPT_SETTINGS_DESC: "有些 Excalidraw 自动化脚本包含设置项,当执行这些脚本时,它们会在该列表下添加设置项。",
|
||||
TASKBONE_HEAD: "Taskbone OCR(光学符号识别)",
|
||||
|
||||
15
src/main.ts
15
src/main.ts
@@ -139,6 +139,7 @@ import { ExcalidrawLib } from "./ExcalidrawLib";
|
||||
import { Rank, SwordColors } from "./menu/ActionIcons";
|
||||
import { RankMessage } from "./dialogs/RankMessage";
|
||||
import { initCompressionWorker, terminateCompressionWorker } from "./workers/compression-worker";
|
||||
import { WeakArray } from "./utils/WeakArray";
|
||||
|
||||
declare let EXCALIDRAW_PACKAGES:string;
|
||||
declare let react:any;
|
||||
@@ -147,6 +148,7 @@ declare let excalidrawLib: typeof ExcalidrawLib;
|
||||
declare let PLUGIN_VERSION:string;
|
||||
|
||||
export default class ExcalidrawPlugin extends Plugin {
|
||||
public eaInstances = new WeakArray<ExcalidrawAutomate>();
|
||||
public fourthFontLoaded: boolean = false;
|
||||
public excalidrawConfig: ExcalidrawConfig;
|
||||
public taskbone: Taskbone;
|
||||
@@ -2849,14 +2851,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
// Force handlers to the front of the list
|
||||
overrideHandlers.forEach(() => scope.keys.unshift(scope.keys.pop()));
|
||||
|
||||
const handler_ctrlF = scope.register(["Mod"], "f", () => {
|
||||
const view = this.app.workspace.getActiveViewOfType(ExcalidrawView);
|
||||
if (view) {
|
||||
search(view);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
const handler_ctrlF = scope.register(["Mod"], "f", () => true);
|
||||
scope.keys.unshift(scope.keys.pop()); // Force our handler to the front of the list
|
||||
const overridSaveShortcut = (
|
||||
this.forceSaveCommand &&
|
||||
@@ -3249,6 +3244,10 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
);
|
||||
this.removeEventLisnters = [];
|
||||
|
||||
this.eaInstances.forEach((ea) => ea?.destroy());
|
||||
this.eaInstances.clear();
|
||||
this.eaInstances = null;
|
||||
|
||||
this.ea.destroy();
|
||||
this.ea = null;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import { ExportDialog } from "src/dialogs/ExportDialog";
|
||||
import { openExternalLink } from "src/utils/ExcalidrawViewUtils";
|
||||
import { UniversalInsertFileModal } from "src/dialogs/UniversalInsertFileModal";
|
||||
import { DEBUGGING, debug } from "src/utils/DebugHelper";
|
||||
import { REM_VALUE } from "src/utils/StylesManager";
|
||||
|
||||
declare const PLUGIN_VERSION:string;
|
||||
const dark = '<svg style="stroke:#ced4da;#212529;color:#ced4da;fill:#ced4da" ';
|
||||
@@ -42,7 +43,7 @@ export type PanelState = {
|
||||
scriptIconMap: ScriptIconMap | null;
|
||||
};
|
||||
|
||||
const TOOLS_PANEL_WIDTH = 228;
|
||||
const TOOLS_PANEL_WIDTH = () => REM_VALUE * 14.2;
|
||||
|
||||
export class ToolsPanel extends React.Component<PanelProps, PanelState> {
|
||||
pos1: number = 0;
|
||||
@@ -155,11 +156,11 @@ export class ToolsPanel extends React.Component<PanelProps, PanelState> {
|
||||
return {
|
||||
left:
|
||||
(this.containerRef.current.clientWidth -
|
||||
TOOLS_PANEL_WIDTH -
|
||||
(isMobileOrZen ? 0 : TOOLS_PANEL_WIDTH + 4)) /
|
||||
TOOLS_PANEL_WIDTH() -
|
||||
(isMobileOrZen ? 0 : TOOLS_PANEL_WIDTH() + 4)) /
|
||||
2 +
|
||||
this.containerRef.current.parentElement.offsetLeft +
|
||||
(isMobileOrZen ? 0 : TOOLS_PANEL_WIDTH + 4),
|
||||
(isMobileOrZen ? 0 : TOOLS_PANEL_WIDTH() + 4),
|
||||
top: 64 + this.containerRef.current.parentElement.offsetTop,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -3,6 +3,8 @@ import ExcalidrawPlugin from "src/main";
|
||||
import { getAllWindowDocuments } from "./ObsidianUtils";
|
||||
import { DEBUGGING, debug } from "./DebugHelper";
|
||||
|
||||
export let REM_VALUE = 16;
|
||||
|
||||
const STYLE_VARIABLES = [
|
||||
"--background-modifier-cover",
|
||||
"--background-primary-alt",
|
||||
@@ -77,6 +79,11 @@ export class StylesManager {
|
||||
}
|
||||
|
||||
private async harvestStyles() {
|
||||
REM_VALUE = parseInt(window.getComputedStyle(document.body).getPropertyValue('--font-text-size').trim());
|
||||
if (isNaN(REM_VALUE)) {
|
||||
REM_VALUE = 16;
|
||||
}
|
||||
|
||||
const body = document.body;
|
||||
const iframe:HTMLIFrameElement = document.createElement("iframe");
|
||||
iframe.style.display = "none";
|
||||
|
||||
15
styles.css
15
styles.css
@@ -226,7 +226,7 @@ li[data-testid] {
|
||||
}
|
||||
|
||||
.excalidraw .ToolIcon__icon img{
|
||||
height: 1em;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.excalidraw-scriptengine-install tbody>tr>td>div>img {
|
||||
@@ -394,23 +394,28 @@ div.excalidraw-draginfo {
|
||||
|
||||
.modal-content.excalidraw-scriptengine-install .search-bar-wrapper {
|
||||
position: sticky;
|
||||
top: 1em;
|
||||
margin-right: 1em;
|
||||
top: 1rem;
|
||||
margin-right: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
flex-wrap: nowrap;
|
||||
z-index: 10;
|
||||
background: var(--background-secondary);
|
||||
padding: 0.5em;
|
||||
padding: 0.5rem;
|
||||
border-bottom: 1px solid var(--background-modifier-border);
|
||||
float: right;
|
||||
max-width: 28em;
|
||||
max-width: 28rem;
|
||||
}
|
||||
|
||||
div.search-bar-wrapper input {
|
||||
margin-right: -0.5rem;
|
||||
}
|
||||
|
||||
.modal-content.excalidraw-scriptengine-install .hit-count {
|
||||
margin-left: 0.5em;
|
||||
white-space: nowrap;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.modal-content.excalidraw-scriptengine-install .active-highlight {
|
||||
|
||||
Reference in New Issue
Block a user