Compare commits

..

23 Commits
2.4.2 ... 2.5.0

Author SHA1 Message Date
zsviczian
74c0af2032 2.5.0 2024-09-13 18:45:13 +02:00
zsviczian
813c85accd 2.5.0-rc-1 2024-09-13 08:18:19 +02:00
zsviczian
c97d08c997 Merge pull request #2017 from zsviczian/fix-getExcalidrawViews
fixed getExcalidrawView
2024-09-12 12:29:49 +02:00
zsviczian
097d1bcd1b fixed getExcalidrawView 2024-09-12 10:27:04 +00:00
zsviczian
7c91186ed5 Update ExcalidrawViewUtils.ts 2024-09-12 11:41:47 +02:00
zsviczian
904bc7c994 Update ExcalidrawView.ts 2024-09-12 11:39:25 +02:00
zsviczian
9fd4ae2615 Update manifest-beta.json 2024-09-12 11:16:51 +02:00
zsviczian
18fbb0934e Merge pull request #2016 from zsviczian/style-tweaks
Obsidian 1.7.2: rework getExcalidrawViews from leaves, fix tools pane…
2024-09-12 11:10:11 +02:00
zsviczian
3ae59c85d2 Obsidian 1.7.2: rework getExcalidrawViews from leaves, fix tools panel width, fix math types 2024-09-12 09:07:43 +00:00
zsviczian
55db9b0ddb 2.5.0-beta-3 2024-09-11 22:21:50 +02:00
zsviczian
3cca2fedb0 2.5.0-beta-2 2024-09-10 18:56:38 +02:00
zsviczian
a0682b8e3c Merge pull request #2014 from dmscode/master
Update zh-cn.ts to 2.4.3
2024-09-10 07:38:37 +02:00
dmscode
da19ce1b84 Update zh-cn.ts to 2.4.3
Add a folder in ./docs for more Chinese docs, and move zh-cn README into it. Translated AutomateHowTo.md
2024-09-10 07:54:46 +08:00
zsviczian
2b1f504b5b 2.5.0-beta-1, changed to Excalidraw.com search 2024-09-09 23:03:57 +02:00
zsviczian
d8f2776b40 Improved template load performance by filtering fileIds based on selection. 2024-09-09 21:27:39 +02:00
zsviczian
2fd800e0a0 2.4.3 2024-09-09 20:20:12 +02:00
zsviczian
712402f7b1 2.4.3-rc-2 2024-09-09 20:00:39 +02:00
zsviczian
b5c034ed92 2.4.3-rc-1 2024-09-08 21:16:11 +02:00
zsviczian
d2805e7a8a Rename feature_request.md to feature_request.md.old 2024-09-07 07:20:34 +02:00
zsviczian
4011b1c89a Rename feature-request-yml to feature-request.yml 2024-09-07 07:20:10 +02:00
zsviczian
5bc348611c Create feature-request-yml 2024-09-07 07:19:42 +02:00
zsviczian
dd24affdbb Create How-to.yml 2024-09-07 06:51:15 +02:00
zsviczian
d8542824a1 removed autodraw for pen and hardware eraser support scripts 2024-09-06 22:11:10 +02:00
37 changed files with 998 additions and 397 deletions

68
.github/ISSUE_TEMPLATE/How-to.yml vendored Normal file
View 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.

View 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.

View File

@@ -1,6 +1,6 @@
# Excalidraw
[简体中文](./README.zh-cn.md)
[简体中文](./docs/zh-cn/README.md)
👉👉👉 Check out and contribute to the new [Obsidian-Excalidraw Community Wiki](https://excalidraw-obsidian.online/Hobbies/Excalidraw+Blog/WIKI/Welcome+to+the+WIKI)

484
docs/zh-cn/AutomateHowTo.md Normal file
View File

@@ -0,0 +1,484 @@
# Excalidraw 自动化使用指南
> 此说明当前更新至 `5569cff`。
[English](./AutomateHowTo.md)
Excalidraw 自动化允许您使用 [Templater](https://github.com/SilentVoid13/Templater) 插件创建 Excalidraw 绘图。
通过一些工作,使用 Excalidraw 自动化,您可以根据保管库中的文档生成简单的思维导图、填写 SVG 表单、创建自定义图表等。
您可以通过 ExcalidrawAutomate 对象访问 Excalidraw 自动化。我建议您以以下代码开始您的自动化脚本。
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
```javascript
const ea = ExcalidrawAutomate;
ea.reset();
```
第一行创建了一个实用的常量,这样您就可以避免写 100 次 `ExcalidrawAutomate`
第二行将 `ExcalidrawAutomate` 重置为默认值。这一点很重要,因为您将不知道之前执行了哪个模板,因此您也不知道 `Excalidraw` 的状态。
## 使用 Excalidraw 自动化的基本逻辑
1. 设置您想要绘制的元素的样式
2. 添加元素。每添加一个新元素,它都会在上一个元素的上方添加一层,因此在重叠对象的情况下,后添加的元素会在前一个元素之上。
3. 调用 `await ea.create();` 来实例化绘图
您可以在添加不同元素之间更改样式。我将元素样式与创建分开是基于这样的假设:您可能会设置描边颜色、描边样式、描边粗糙度等,并使用这些设置绘制大多数元素。每次添加元素时设置所有这些参数是没有意义的。
### 在深入探讨之前,这里有两个简单的示例脚本
#### 使用模板在自定义文件夹中创建具有自定义名称的新绘图
这个简单的脚本为您提供了比 Excalidraw 插件设置更大的灵活性,可以为您的绘图命名、将其放入文件夹中,并应用模板。
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
```javascript
<%*
const ea = ExcalidrawAutomate;
ea.reset();
await ea.create({
filename : tp.date.now("HH.mm"),
foldername : tp.date.now("YYYY-MM-DD"),
templatePath: "Excalidraw/Template1.excalidraw",
onNewPane : false
});
%>
```
#### 创建一个简单的绘图
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
```javascript
<%*
const ea = ExcalidrawAutomate;
ea.reset();
ea.addRect(-150,-50,450,300);
ea.addText(-100,70,"Left to right");
ea.addArrow([[-100,100],[100,100]]);
ea.style.strokeColor = "red";
ea.addText(100,-30,"top to bottom",{width:200,textAligh:"center"});
ea.addArrow([[200,0],[200,200]]);
await ea.create();
%>
```
该脚本将生成以下绘图:
![FristDemo](https://user-images.githubusercontent.com/14358394/116825643-6e5a8b00-ab90-11eb-9e3a-37c524620d0d.png)
## 属性和功能一览
这是 ExcalidrawAutomate 实现的接口:
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
```javascript
ExcalidrawAutomate: {
style: {
strokeColor: string;
backgroundColor: string;
angle: number;
fillStyle: FillStyle;
strokeWidth: number;
storkeStyle: StrokeStyle;
roughness: number;
opacity: number;
strokeSharpness: StrokeSharpness;
fontFamily: FontFamily;
fontSize: number;
textAlign: string;
verticalAlign: string;
startArrowHead: string;
endArrowHead: string;
}
canvas: {theme: string, viewBackgroundColor: string};
setFillStyle: Function;
setStrokeStyle: Function;
setStrokeSharpness: Function;
setFontFamily: Function;
setTheme: Function;
addRect: Function;
addDiamond: Function;
addEllipse: Function;
addText: Function;
addLine: Function;
addArrow: Function;
connectObjects: Function;
addToGroup: Function;
toClipboard: Function;
create: Function;
createPNG: Function;
createSVG: Function;
clear: Function;
reset: Function;
};
```
## 元素样式
正如您所注意到的,某些样式具有设置函数。这是为了帮助您浏览属性的可用值。不过,您并不需要使用设置函数,您也可以直接设置值。
### strokeColor
字符串。线条的颜色。[CSS 合法颜色值](https://www.w3schools.com/cssref/css_colors_legal.asp)
允许的值包括 [HTML 颜色名称](https://www.w3schools.com/colors/colors_names.asp)、十六进制 RGB 字符串,例如 `#FF0000` 表示红色。
### backgroundColor
字符串。对象的填充颜色。[CSS 合法颜色值](https://www.w3schools.com/cssref/css_colors_legal.asp)
允许的值包括 [HTML 颜色名称](https://www.w3schools.com/colors/colors_names.asp)、十六进制 RGB 字符串,例如 `#FF0000` 表示红色,或 `transparent`(透明)。
### angle
数字。以弧度表示的旋转。90° == `Math.PI/2`
### fillStyle, setFillStyle()
```typescript
type FillStyle = "hachure" | "cross-hatch" | "solid";
setFillStyle (val:number);
```
fillStyle 是一个字符串.
`setFillStyle()` 接受一个数字:
- 0: "hachure"(斜线填充)
- 1: "cross-hatch"(交叉斜线填充)
- 其他任何数字: "solid"(实心填充)
### strokeWidth
数字,设置描边的宽度。
### strokeStyle, setStrokeStyle()
```typescript
type StrokeStyle = "solid" | "dashed" | "dotted";
setStrokeStyle (val:number);
```
strokeStyle 是一个字符串。
`setStrokeStyle()` 接受一个数字:
- 0: "solid"(实线)
- 1: "dashed"(虚线)
- 其他任何数字: "dotted"(点线)
### roughness
数字。在 Excalidraw 中称为“粗糙度”。接受三个值:
- 0: 建筑师
- 1: 艺术家
- 2: 卡通画家
### opacity
介于 0 和 100 之间的数字。对象的透明度,包括描边和填充。
### strokeSharpness, setStrokeSharpness()
```typescript
type StrokeSharpness = "round" | "sharp";
setStrokeSharpness(val:nmuber);
```
strokeSharpness 是一个字符串。
“round” 线条是曲线“sharp” 线条在转折点处断开(硬弯折)。
`setStrokeSharpness()` 接受一个数字:
- 0: "round"(圆滑)
- 其他任何数字: "sharp"(尖锐)
### fontFamily, setFontFamily()
数字。有效值为 1、2 和 3。
`setFontFamily()` 也会接受一个数字并返回字体名称。
- 1: "Virgil, Segoe UI Emoji"
- 2: "Helvetica, Segoe UI Emoji"
- 3: "Cascadia, Segoe UI Emoji"
### fontSize
数字。默认值为 20 像素。
### textAlign
字符串。文本的水平对齐方式。有效值为 "left"(左对齐)、"center"(居中对齐)、"right"(右对齐)。
在使用 `addText()` 函数设置固定宽度时,这一点很重要。
### verticalAlign
字符串。文本的垂直对齐方式。有效值为 "top"(顶部)和 "middle"(中间)。
在使用 `addText()` 函数设置固定高度时,这一点很重要。
### startArrowHead, endArrowHead
字符串。有效值为 "arrow"(箭头)、"bar"(线条)、"dot"(点)和 "none"(无)。指定箭头的起始和结束。
在使用 `addArrow()``connectObjects()` 函数时,这一点很重要。
## canvas
设置画布的属性。
### theme, setTheme()
字符串。有效值为 "light"(明亮)和 "dark"(黑暗)。
`setTheme()` 接受一个数字:
- 0: "light"(明亮)
- 其他任何数字: "dark"(黑暗)
### viewBackgroundColor
字符串。对象的填充颜色。[CSS 合法颜色值](https://www.w3schools.com/cssref/css_colors_legal.asp)
允许的值包括 [HTML 颜色名称](https://www.w3schools.com/colors/colors_names.asp)、十六进制 RGB 字符串,例如 `#FF0000` 表示红色,或 `transparent`(透明)。
## 添加对象
这些函数将向您的绘图中添加对象。画布是无限的,接受负值和正值的 X 和 Y 坐标。X 值从左到右增加Y 值从上到下增加。
![坐标](https://user-images.githubusercontent.com/14358394/116825632-6569b980-ab90-11eb-827b-ada598e91e46.png)
### addRect(), addDiamond(), addEllipse()
```typescript
addRect(topX:number, topY:number, width:number, height:number):string
addDiamond(topX:number, topY:number, width:number, height:number):string
addEllipse(topX:number, topY:number, width:number, height:number):string
```
返回对象的 `id`。在用线连接对象时,需要使用 `id`。请参见后文。
### addText
```typescript
addText(topX:number, topY:number, text:string, formatting?:{width:number, height:number,textAlign: string, verticalAlign:string, box: boolean, boxPadding: number}):string
```
向绘图中添加文本。
格式参数是可选的:
- 如果未指定 `width`(宽度)和 `height`(高度),函数将根据 `fontFamily``fontSize` 和提供的文本计算宽度和高度。
- 如果您希望文本相对于绘图中的其他元素居中,可以提供固定的高度和宽度,同时可以指定 `textAlign``verticalAlign`,如上所述。例如:`{width:500, textAlign:"center"}`
- 如果您想在文本周围添加一个框,请设置 `{box:true}`
返回对象的 `id`。在用线连接对象时,需要使用 `id`。请参见后文。如果 `{box:true}`,则返回包围框的 `id`
### addLine()
```typescript
addLine(points: [[x:number,y:number]]):void
```
添加一条连接提供的点的线。必须至少包含两个点 `points.length >= 2`。如果提供的点超过两个,间隔点将作为断点添加。如果 `strokeSharpness` 设置为 "sharp",线条将在转折处断开;如果设置为 "round",线条将是曲线。
### addArrow()
```typescript
addArrow(points: [[x:number,y:number]],formatting?:{startArrowHead:string,endArrowHead:string,startObjectId:string,endObjectId:string}):void
```
添加一条连接提供的点的箭头。必须至少包含两个点 `points.length >= 2`。如果提供的点超过两个,间隔点将作为断点添加。如果元素 `style.strokeSharpness` 设置为 "sharp",线条将在转折处断开;如果设置为 "round",线条将是曲线。
`startArrowHead``endArrowHead` 指定要使用的箭头类型,如上所述。有效值为 "none"(无)、"arrow"(箭头)、"dot"(点)和 "bar"(线条)。例如:`{startArrowHead: "dot", endArrowHead: "arrow"}`
`startObjectId``endObjectId` 是连接对象的对象 ID。我建议使用 `connectObjects` 而不是调用 `addArrow()` 来连接对象。
### connectObjects()
```typescript
declare type ConnectionPoint = "top"|"bottom"|"left"|"right";
connectObjects(objectA: string, connectionA: ConnectionPoint, objectB: string, connectionB: ConnectionPoint, formatting?:{numberOfPoints: number,startArrowHead:string,endArrowHead:string, padding: number}):void
```
连接两个对象的箭头。
`objectA``objectB` 是字符串。这些是要连接的对象的 ID。这些 ID 是通过 `addRect()``addDiamond()``addEllipse()``addText()` 创建这些对象时返回的。
`connectionA``connectionB` 指定在对象上的连接位置。有效值为:"top"(上)、"bottom"(下)、"left"(左)和 "right"(右)。
`numberOfPoints` 设置线条的间隔断点数量。默认值为零,意味着箭头的起点和终点之间不会有断点。当在绘图中移动对象时,这些断点将影响 Excalidraw 如何重新调整线条。
`startArrowHead``endArrowHead` 的功能与 `addArrow()` 中描述的一致。
### addToGroup()
```typescript
addToGroup(objectIds:[]):void
```
`objectIds` 中列出的对象进行分组。
## Utility functions
### clear()
`clear()` 将从缓存中清除对象,但会保留元素样式设置。
### reset()
`reset()` 将首先调用 `clear()`,然后将元素样式重置为默认值。
### toClipboard()
```typescript
async toClipboard(templatePath?:string)
```
将生成的图形放入剪贴板。当您不想创建新图形,而是想将其他项目粘贴到现有图形上时,这非常有用。
### create()
```typescript
async create(params?:{filename: string, foldername:string, templatePath:string, onNewPane: boolean})
```
创建图形并打开它。
`filename` 是要创建的图形的文件名(不带扩展名)。如果为 `null`,则 Excalidraw 会生成一个文件名。
`foldername` 是文件应创建的文件夹。如果为 `null`,则将根据 Excalidraw 设置使用新图形的默认文件夹。
`templatePath` 是包含完整路径和扩展名的模板文件名。该模板文件将作为基础层添加,所有通过 ExcalidrawAutomate 添加的额外对象将出现在模板元素之上。如果为 `null`,则不使用模板,即空白图形将作为添加对象的基础。
`onNewPane` 定义新图形应创建的位置。`false` 将在当前活动的标签页中打开图形;`true` 将通过垂直分割当前标签页来打开图形。
示例:
```javascript
create({filename:"my drawing", foldername:"myfolder/subfolder/", templatePath: "Excalidraw/template.excalidraw", onNewPane: true});
```
### createSVG()
```typescript
async createSVG(templatePath?:string)
```
返回一个包含生成图形的 HTML `SVGSVGElement`
### createPNG()
```typescript
async createPNG(templatePath?:string)
```
返回一个包含生成图形的 PNG 图像的 blob。
## 示例
### 将新图形插入到当前编辑的文档中
此模板将提示您输入图形的标题。它将在您提供的标题下创建一个新图形,并在您正在编辑的文档的文件夹中。然后,它将在光标位置插入新图形,并通过分割当前标签页在新的工作区标签页中打开新图形。
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
```javascript
<%*
const defaultTitle = tp.date.now("HHmm")+' '+tp.file.title;
const title = await tp.system.prompt("Title of the drawing?", defaultTitle);
const folder = tp.file.folder(true);
const transcludePath = (folder== '/' ? '' : folder + '/') + title + '.excalidraw';
tR = String.fromCharCode(96,96,96)+'excalidraw\n[['+transcludePath+']]\n'+String.fromCharCode(96,96,96);
const ea = ExcalidrawAutomate;
ea.reset();
ea.setTheme(1); //set Theme to dark
await ea.create({
filename : title,
foldername : folder,
//templatePath: 'Excalidraw/Template.excalidraw', //uncomment if you want to use a template
onNewPane : true
});
%>
```
### 连接对象
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
```javascript
<%*
const ea = ExcalidrawAutomate;
ea.reset();
ea.addText(-130,-100,"Connecting two objects");
const a = ea.addRect(-100,-100,100,100);
const b = ea.addEllipse(200,200,100,100);
ea.connectObjects(a,"bottom",b,"left",{numberOfPoints: 2}); //see how the line breaks differently when moving objects around
ea.style.strokeColor = "red";
ea.connectObjects(a,"right",b,"top",1);
await ea.create();
%>
```
### 使用模板
这个示例与第一个类似,但旋转了 90°并使用了模板同时指定了文件名和保存图形的文件夹并在新的标签页中打开新图形。
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
```javascript
<%*
const ea = ExcalidrawAutomate;
ea.reset();
ea.style.angle = Math.PI/2;
ea.style.strokeWidth = 3.5;
ea.addRect(-150,-50,450,300);
ea.addText(-100,70,"Left to right");
ea.addArrow([[-100,100],[100,100]]);
ea.style.strokeColor = "red";
await ea.addText(100,-30,"top to bottom",{width:200,textAlign:"center"});
ea.addArrow([[200,0],[200,200]]);
await ea.create({filename:"My Drawing",foldername:"myfolder/fordemo/",templatePath:"Excalidraw/Template2.excalidraw",onNewPane:true});
%>
```
### 从文本大纲生成简单思维导图
这是一个稍微复杂一些的示例。这个示例将从一个表格化的大纲生成思维导图。
![Drawing 2021-05-05 20 52 34](https://user-images.githubusercontent.com/14358394/117194124-00a69d00-ade4-11eb-8b75-5e18a9cbc3cd.png)
输入示例:
```
- Test 1
- Test 1.1
- Test 2
- Test 2.1
- Test 2.2
- Test 2.2.1
- Test 2.2.2
- Test 2.2.3
- Test 2.2.3.1
- Test 3
- Test 3.1
```
The script:
*使用 <kbd>CTRL+Shift+V</kbd> 将代码粘贴到 Obsidian 中!*
```javascript
<%*
const IDX = Object.freeze({"depth":0, "text":1, "parent":2, "size":3, "children": 4, "objectId":5});
//check if an editor is the active view
const editor = this.app.workspace.activeLeaf?.view?.editor;
if(!editor) return;
//initialize the tree with the title of the document as the first element
let tree = [[0,this.app.workspace.activeLeaf?.view?.getDisplayText(),-1,0,[],0]];
const linecount = editor.lineCount();
//helper function, use regex to calculate indentation depth, and to get line text
function getLineProps (i) {
props = editor.getLine(i).match(/^(\t*)-\s+(.*)/);
return [props[1].length+1, props[2]];
}
//a vector that will hold last valid parent for each depth
let parents = [0];
//load outline into tree
for(i=0;i<linecount;i++) {
[depth,text] = getLineProps(i);
if(depth>parents.length) parents.push(i+1);
else parents[depth] = i+1;
tree.push([depth,text,parents[depth-1],1,[]]);
tree[parents[depth-1]][IDX.children].push(i+1);
}
//recursive function to crawl the tree and identify height aka. size of each node
function crawlTree(i) {
if(i>linecount) return 0;
size = 0;
if((i+1<=linecount && tree[i+1][IDX.depth] <= tree[i][IDX.depth])|| i == linecount) { //I am a leaf
tree[i][IDX.size] = 1;
return 1;
}
tree[i][IDX.children].forEach((node)=>{
size += crawlTree(node);
});
tree[i][IDX.size] = size;
return size;
}
crawlTree(0);
//Build the mindmap in Excalidraw
const width = 300;
const height = 100;
const ea = ExcalidrawAutomate;
ea.reset();
//stores position offset of branch/leaf in height units
offsets = [0];
for(i=0;i<=linecount;i++) {
depth = tree[i][IDX.depth];
if (depth == 1) ea.style.strokeColor = '#'+(Math.random()*0xFFFFFF<<0).toString(16);
tree[i][IDX.objectId] = ea.addText(depth*width,((tree[i][IDX.size]/2)+offsets[depth])*height,tree[i][IDX.text],{box:true});
//set child offset equal to parent offset
if((depth+1)>offsets.length) offsets.push(offsets[depth]);
else offsets[depth+1] = offsets[depth];
offsets[depth] += tree[i][IDX.size];
if(tree[i][IDX.parent]!=-1) {
ea.connectObjects(tree[tree[i][IDX.parent]][IDX.objectId],"right",tree[i][IDX.objectId],"left",{startArrowHead: 'dot'});
}
}
await ea.create({onNewPane: true});
%>
```

View File

@@ -1,6 +1,10 @@
# Excalidraw
> 此说明当前更新至 2.4.0-beta-9
> 此说明当前更新至 `5569cff`
[English](./README.md)
👉👉👉 快来查看并为新的 [Obsidian-Excalidraw 社区维基](https://excalidraw-obsidian.online/Hobbies/Excalidraw+Blog/WIKI/Welcome+to+the+WIKI)贡献你的力量吧
Obsidian-Excalidraw 插件将 [Excalidraw](https://excalidraw.com/) 这一功能丰富的草图工具集成到 Obsidian 中。您可以在您的库中存储和编辑 Excalidraw 文件,可以将图形嵌入到文档中,还可以在 Excalidraw 中链接到文档和其他图形。有关 Excalidraw 功能的展示,请查看我的博客文章 [这里](https://www.zsolt.blog/2021/03/showcasing-excalidraw.html) 或观看以下视频。

View File

@@ -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 })
})();

View File

@@ -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

View File

@@ -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 })
})();

View File

@@ -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

View File

@@ -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

View File

@@ -1,7 +1,7 @@
{
"id": "obsidian-excalidraw-plugin",
"name": "Excalidraw",
"version": "2.4.2",
"version": "2.5.0",
"minAppVersion": "1.1.6",
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
"author": "Zsolt Viczian",

View File

@@ -1,7 +1,7 @@
{
"id": "obsidian-excalidraw-plugin",
"name": "Excalidraw",
"version": "2.4.2",
"version": "2.5.0",
"minAppVersion": "1.1.6",
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
"author": "Zsolt Viczian",

View File

@@ -19,7 +19,7 @@
"license": "MIT",
"dependencies": {
"@popperjs/core": "^2.11.8",
"@zsviczian/excalidraw": "0.17.1-obsidian-48",
"@zsviczian/excalidraw": "0.17.1-obsidian-53",
"chroma-js": "^2.4.2",
"clsx": "^2.0.0",
"@zsviczian/colormaster": "^1.2.2",

View File

@@ -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);

View File

@@ -21,7 +21,6 @@ import { ExcalidrawData, getMarkdownDrawingSection, REGEX_LINK } from "src/Excal
import {
FRONTMATTER,
nanoid,
VIEW_TYPE_EXCALIDRAW,
MAX_IMAGE_SIZE,
COLOR_NAMES,
fileid,
@@ -55,14 +54,14 @@ import {
wrapTextAtCharLength,
arrayToMap,
} from "src/utils/Utils";
import { getAttachmentsFolderAndFilePath, getLeaf, getNewOrAdjacentLeaf, isObsidianThemeDark, mergeMarkdownFiles, openLeaf } from "src/utils/ObsidianUtils";
import { AppState, BinaryFileData, DataURL, ExcalidrawImperativeAPI, Point } from "@zsviczian/excalidraw/types/excalidraw/types";
import { getAttachmentsFolderAndFilePath, getExcalidrawViews, getLeaf, getNewOrAdjacentLeaf, isObsidianThemeDark, mergeMarkdownFiles, openLeaf } from "src/utils/ObsidianUtils";
import { AppState, BinaryFileData, DataURL, ExcalidrawImperativeAPI } from "@zsviczian/excalidraw/types/excalidraw/types";
import { EmbeddedFile, EmbeddedFilesLoader, FileData } from "src/EmbeddedFileLoader";
import { tex2dataURL } from "src/LaTeX";
import { GenericInputPrompt, NewFileActions } from "src/dialogs/Prompt";
import { t } from "src/lang/helpers";
import { ScriptEngine } from "src/Scripts";
import { ConnectionPoint, DeviceType } from "src/types/types";
import { ConnectionPoint, DeviceType, Point } from "src/types/types";
import CM, { ColorMaster, extendPlugins } from "@zsviczian/colormaster";
import HarmonyPlugin from "@zsviczian/colormaster/plugins/harmony";
import MixPlugin from "@zsviczian/colormaster/plugins/mix"
@@ -282,8 +281,17 @@ export class ExcalidrawAutomate {
return LZString.compressToBase64(str);
}
public decompressFromBase64(str:string): string {
return LZString.decompressFromBase64(str);
public decompressFromBase64(data:string): string {
if (!data) throw new Error("No input string provided for decompression.");
let cleanedData = '';
const length = data.length;
for (let i = 0; i < length; i++) {
const char = data[i];
if (char !== '\\n' && char !== '\\r') {
cleanedData += char;
}
}
return LZString.decompressFromBase64(cleanedData);
}
/**
@@ -1826,33 +1834,23 @@ export class ExcalidrawAutomate {
*/
setView(view?: ExcalidrawView | "first" | "active"): ExcalidrawView {
if(!view) {
const v = app.workspace.getActiveViewOfType(ExcalidrawView);
const v = this.plugin.app.workspace.getActiveViewOfType(ExcalidrawView);
if (v instanceof ExcalidrawView) {
this.targetView = v;
}
else {
const leaves =
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
if (!leaves || leaves.length == 0) {
return;
}
this.targetView = leaves[0].view as ExcalidrawView;
this.targetView = getExcalidrawViews(this.plugin.app)[0];
}
}
if (view == "active") {
const v = app.workspace.getActiveViewOfType(ExcalidrawView);
const v = this.plugin.app.workspace.getActiveViewOfType(ExcalidrawView);
if (!(v instanceof ExcalidrawView)) {
return;
}
this.targetView = v;
}
if (view == "first") {
const leaves =
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
if (!leaves || leaves.length == 0) {
return;
}
this.targetView = leaves[0].view as ExcalidrawView;
this.targetView = getExcalidrawViews(this.plugin.app)[0];
}
if (view instanceof ExcalidrawView) {
this.targetView = view;
@@ -2963,27 +2961,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) {
@@ -3010,8 +2987,49 @@ async function getTemplate(
));
}
let fileIDWhiteList:Set<FileId>;
if(groupElements.length < scene.elements.length) {
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(fileIDWhiteList && (sceneFilesSize > fileIDWhiteList.size)) {
Object.values(scene.files).filter((f: any) => fileIDWhiteList.has(f.id)).forEach((f: any) => {
files[f.id] = f;
});
} else {
files = scene.files;
}
}
return {
elements: convertMarkdownLinksToObsidianURLs
? updateElementLinksToObsidianLinks({
@@ -3020,7 +3038,7 @@ async function getTemplate(
}) : groupElements,
appState: scene.appState,
frontmatter: filehead.match(/^---\n.*\n---\n/ms)?.[0] ?? filehead,
files: scene.files,
files,
hasSVGwithBitmap,
};
}

View File

@@ -9,6 +9,8 @@ import {
MarkdownView,
request,
requireApiVersion,
HoverParent,
HoverPopover,
} from "obsidian";
//import * as React from "react";
//import * as ReactDOM from "react-dom";
@@ -251,7 +253,8 @@ type ActionButtons = "save" | "isParsed" | "isRaw" | "link" | "scriptInstall";
let windowMigratedDisableZoomOnce = false;
export default class ExcalidrawView extends TextFileView {
export default class ExcalidrawView extends TextFileView implements HoverParent{
public hoverPopover: HoverPopover;
private freedrawLastActiveTimestamp: number = 0;
public exportDialog: ExportDialog;
public excalidrawData: ExcalidrawData;
@@ -763,6 +766,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 +779,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) {
@@ -1346,7 +1351,7 @@ export default class ExcalidrawView extends TextFileView {
//if link will open in the same pane I want to save the drawing before opening the link
await this.forceSaveIfRequired();
const {leaf, promise} = openLeaf({
const { promise } = openLeaf({
plugin: this.plugin,
fnGetLeaf: () => getLeaf(this.plugin,this.leaf,keys),
file,
@@ -1548,7 +1553,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);
});
@@ -1787,7 +1792,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"));
@@ -1796,6 +1801,11 @@ 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;
}
await this.forceSaveIfRequired();
}
private async forceSaveIfRequired():Promise<boolean> {
@@ -1804,9 +1814,9 @@ export default class ExcalidrawView extends TextFileView {
let dirty = false;
//if saving was already in progress
//the function awaits the save to finish.
while (this.semaphores.saving && watchdog++ < 10) {
while (this.semaphores.saving && watchdog++ < 200) {
dirty = true;
await sleep(20);
await sleep(40);
}
if(this.excalidrawAPI) {
this.checkSceneVersion(this.excalidrawAPI.getSceneElements());
@@ -2319,14 +2329,35 @@ export default class ExcalidrawView extends TextFileView {
});
}
private getGridColor(bgColor: string, st: AppState):{Bold: string, Regular: string} {
private getGridColor(bgColor: string, st: AppState): { Bold: string, Regular: string } {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.getGridColor, "ExcalidrawView.getGridColor", bgColor, st);
const cm = this.plugin.ea.getCM(bgColor);
const isDark = cm.isDark();
const Regular = (isDark ? cm.lighterBy(7) : cm.darkerBy(7)).stringHEX({alpha: false});
const Bold = (isDark ? cm.lighterBy(14) : cm.darkerBy(14)).stringHEX({alpha: false});
return {Bold, Regular};
let Regular: string;
let Bold: string;
const opacity = this.plugin.settings.gridSettings.OPACITY/100;
if (this.plugin.settings.gridSettings.DYNAMIC_COLOR) {
// Dynamic color: concatenate opacity to the HEX string
Regular = (isDark ? cm.lighterBy(10) : cm.darkerBy(10)).alphaTo(opacity).stringRGB({ alpha: true });
Bold = (isDark ? cm.lighterBy(5) : cm.darkerBy(5)).alphaTo(opacity).stringRGB({ alpha: true });
} else {
// Custom color handling
const customCM = this.plugin.ea.getCM(this.plugin.settings.gridSettings.COLOR);
const customIsDark = customCM.isDark();
// Regular uses the custom color directly
Regular = customCM.alphaTo(opacity).stringRGB({ alpha: true });
// Bold is 7 shades lighter or darker based on the custom color's darkness
Bold = (customIsDark ? customCM.lighterBy(10) : customCM.darkerBy(10)).alphaTo(opacity).stringRGB({ alpha: true });
}
return { Bold, Regular };
}
public activeLoader: EmbeddedFilesLoader = null;
private nextLoader: EmbeddedFilesLoader = null;
@@ -3335,6 +3366,13 @@ export default class ExcalidrawView extends TextFileView {
toDelete.forEach((k) => delete files[k]);
}
const activeTool = st.activeTool;
if(!["freedraw","hand"].includes(activeTool.type)) {
activeTool.type = "selection";
}
activeTool.customType = null;
activeTool.lastActiveTool = null;
return {
type: "excalidraw",
version: 2,
@@ -3369,7 +3407,7 @@ export default class ExcalidrawView extends TextFileView {
currentStrokeOptions: st.currentStrokeOptions,
frameRendering: st.frameRendering,
objectsSnapModeEnabled: st.objectsSnapModeEnabled,
activeTool: st.activeTool,
activeTool,
},
prevTextMode: this.prevTextMode,
files,
@@ -3397,7 +3435,15 @@ export default class ExcalidrawView extends TextFileView {
}
private clearHoverPreview() {
if (this.hoverPreviewTarget) {
if (this.hoverPopover) {
this.hoverPreviewTarget = null;
//@ts-ignore
if(this.hoverPopover.embed?.editor) {
return;
}
//@ts-ignore
this.hoverPopover?.hide();
} else if (this.hoverPreviewTarget) {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.clearHoverPreview, "ExcalidrawView.clearHoverPreview", this);
const event = new MouseEvent("click", {
view: this.ownerWindow,
@@ -3583,7 +3629,7 @@ export default class ExcalidrawView extends TextFileView {
this.app.workspace.trigger("hover-link", {
event: this.lastMouseEvent,
source: VIEW_TYPE_EXCALIDRAW,
hoverParent: this.hoverPreviewTarget,
hoverParent: this,
targetEl: this.hoverPreviewTarget, //null //0.15.0 hover editor!!
linktext: this.plugin.hover.linkText,
sourcePath: this.plugin.hover.sourcePath,
@@ -3612,6 +3658,7 @@ export default class ExcalidrawView extends TextFileView {
private excalidrawDIVonKeyDown(event: KeyboardEvent) {
//(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.excalidrawDIVonKeyDown, "ExcalidrawView.excalidrawDIVonKeyDown", event);
if (this.semaphores?.viewunload) return;
if (event.target === this.excalidrawWrapperRef.current) {
return;
} //event should originate from the canvas
@@ -3738,10 +3785,18 @@ export default class ExcalidrawView extends TextFileView {
}
}
public updateGridColor(canvasColor?: string, st?: any) {
if(!canvasColor) {
st = (this.excalidrawAPI as ExcalidrawImperativeAPI).getAppState();
canvasColor = canvasColor ?? st.viewBackgroundColor === "transparent" ? "white" : st.viewBackgroundColor;
}
window.setTimeout(()=>this.updateScene({appState:{gridColor: this.getGridColor(canvasColor, st)}, storeAction: "update"}));
}
private canvasColorChangeHook(st: AppState) {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.canvasColorChangeHook, "ExcalidrawView.canvasColorChangeHook", st);
const canvasColor = st.viewBackgroundColor === "transparent" ? "white" : st.viewBackgroundColor;
window.setTimeout(()=>this.updateScene({appState:{gridColor: this.getGridColor(canvasColor, st)}, storeAction: "update"}));
this.updateGridColor(canvasColor,st);
setDynamicStyle(this.plugin.ea,this,canvasColor,this.plugin.settings.dynamicStyling);
if(this.plugin.ea.onCanvasColorChangeHook) {
try {
@@ -5037,7 +5092,8 @@ export default class ExcalidrawView extends TextFileView {
React,
t("COPY_DRAWING_LINK"),
() => {
navigator.clipboard.writeText(`![[${this.file.path}]]`);
const path = this.file.path.match(/(.*)(\.md)$/)?.[1];
navigator.clipboard.writeText(`![[${path ?? this.file.path}]]`);
},
onClose
),

View File

@@ -5,7 +5,7 @@ import {
TFile,
WorkspaceLeaf,
} from "obsidian";
import { PLUGIN_ID, VIEW_TYPE_EXCALIDRAW } from "./constants/constants";
import { PLUGIN_ID } from "./constants/constants";
import ExcalidrawView from "./ExcalidrawView";
import ExcalidrawPlugin from "./main";
import { ButtonDefinition, GenericInputPrompt, GenericSuggester } from "./dialogs/Prompt";
@@ -14,6 +14,7 @@ import { splitFolderAndFilename } from "./utils/FileUtils";
import { getEA } from "src";
import { ExcalidrawAutomate } from "./ExcalidrawAutomate";
import { WeakArray } from "./utils/WeakArray";
import { getExcalidrawViews } from "./utils/ObsidianUtils";
export type ScriptIconMap = {
[key: string]: { name: string; group: string; svgString: string };
@@ -303,10 +304,8 @@ export class ScriptEngine {
}
private updateToolPannels() {
const leaves =
this.plugin.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
leaves.forEach((leaf: WorkspaceLeaf) => {
const excalidrawView = leaf.view as ExcalidrawView;
const excalidrawViews = getExcalidrawViews(this.plugin.app);
excalidrawViews.forEach(excalidrawView => {
excalidrawView.toolsPanelRef?.current?.updateScriptIconMap(
this.scriptIconMap,
);

View File

@@ -17,6 +17,31 @@ 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.5.0": `
The new [Community Wiki](https://excalidraw-obsidian.online/Hobbies/Excalidraw+Blog/WIKI/Welcome+to+the+WIKI) is waiting for your contribution!
## Fixed
- Regression from 2.4.3: Text flickers when editing text in a container [#2015](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2015).
- Significantly improved the performance of group and frame [image fragments](https://youtu.be/sjZfdqpxqsg) when the source drawing includes many images, but the fragment does not.
- Minor styling tweaks. Note that with Obsidian 1.7.1, the font size and zoom settings in Obsidian > Appearance will affect the size of buttons and menu items in Excalidraw as well.
## New
- New Canvas Search from Excalidraw.com (CTRL/CMD+F). The "old" search is still available in the Obsidian Command Palette _"Search for text in drawing"_. The old search will also search in image-file names and frame titles, but the result set is not as sophisticated as the one built by Excalidraw.com. If you want to use the old search, you can set up a hotkey in Obsidian settings, e.g., CTRL+ALT/CMD+OPT+F. [#8438](https://github.com/excalidraw/excalidraw/pull/8438)
- Grid Color settings under **Excalidraw Appearance and Behavior**. Note that the grid color and opacity also affect the color and transparency of the binding box when using the arrow tool. [#2007](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2007)
- Refactoring the code to be compatible with the upcoming Obsidian 1.7.2.
- ${String.fromCharCode(96)}ExcalidrawAutomate.decompressFromBase64()${String.fromCharCode(96)} will now remove line breaks from the input string so you can directly supply the compressed JSON string for decompression by script.
`,
"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.

View File

@@ -1,12 +1,13 @@
import { ExcalidrawImperativeAPI } from "@zsviczian/excalidraw/types/excalidraw/types";
import { ColorComponent, Modal, Setting, SliderComponent, TextComponent, ToggleComponent } from "obsidian";
import { COLOR_NAMES, VIEW_TYPE_EXCALIDRAW } from "src/constants/constants";
import { ColorComponent, Modal, Setting, TextComponent, ToggleComponent } from "obsidian";
import { COLOR_NAMES } from "src/constants/constants";
import ExcalidrawView from "src/ExcalidrawView";
import ExcalidrawPlugin from "src/main";
import { setPen } from "src/menu/ObsidianMenu";
import { ExtendedFillStyle, PenStyle, PenType } from "src/PenTypes";
import { ExtendedFillStyle, PenType } from "src/PenTypes";
import { getExcalidrawViews } from "src/utils/ObsidianUtils";
import { PENS } from "src/utils/Pens";
import { fragWithHTML, getExportPadding, getExportTheme, getPNGScale, getWithBackground } from "src/utils/Utils";
import { fragWithHTML } from "src/utils/Utils";
import { __values } from "tslib";
const EASINGFUNCTIONS: Record<string,string> = {
@@ -65,9 +66,7 @@ export class PenSettingsModal extends Modal {
async onClose() {
if(this.dirty) {
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
if (v.view instanceof ExcalidrawView) v.view.updatePinnedCustomPens()
})
getExcalidrawViews(this.app).forEach(excalidrawView=>excalidrawView.updatePinnedCustomPens());
this.plugin.saveSettings();
const pen = this.plugin.settings.customPens[this.pen]
const api = this.view.excalidrawAPI;

View File

@@ -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 = "→";

View File

@@ -913,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",

View File

@@ -3,7 +3,7 @@ import "obsidian";
//export ExcalidrawAutomate from "./ExcalidrawAutomate";
//export {ExcalidrawAutomate} from "./ExcaildrawAutomate";
export type { ExcalidrawBindableElement, ExcalidrawElement, FileId, FillStyle, StrokeRoundness, StrokeStyle } from "@zsviczian/excalidraw/types/excalidraw/element/types";
export type { Point } from "@zsviczian/excalidraw/types/excalidraw/types";
export type { Point } from "src/types/types";
export const getEA = (view?:any): any => {
try {
return window.ExcalidrawAutomate.getAPI(view);

View File

@@ -395,6 +395,14 @@ FILENAME_HEAD: "Filename",
ZOOM_TO_FIT_MAX_LEVEL_NAME: "Zoom to fit max ZOOM level",
ZOOM_TO_FIT_MAX_LEVEL_DESC:
"Set the maximum level to which zoom to fit will enlarge the drawing. Minimum is 0.5 (50%) and maximum is 10 (1000%).",
GRID_HEAD: "Grid",
GRID_DYNAMIC_COLOR_NAME: "Dynamic grid color",
GRID_DYNAMIC_COLOR_DESC:
"<b><u>Toggle ON:</u></b>Change grid color to match the canvas color<br><b><u>Toggle OFF:</u></b>Use the color below as the grid color",
GRID_COLOR_NAME: "Grid color",
GRID_OPACITY_NAME: "Grid opacity",
GRID_OPACITY_DESC: "Grid opacity will also control the opacity of the binding box when binding an arrow to an element.<br>" +
"Set the opacity of the grid. 0 is transparent, 100 is opaque.",
LASER_HEAD: "Laser pointer",
LASER_COLOR: "Laser pointer color",
LASER_DECAY_TIME_NAME: "Laser pointer decay time",
@@ -653,7 +661,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. " +

View File

@@ -653,7 +653,7 @@ FILENAME_HEAD: "文件名",
"如果出于某些合理的原因,您决定忽略我的建议并配置了 Excalidraw 文件的自动代码格式化,那么可以使用这个设置<br> " +
"<code>## Text Elements</code> 部分对空行很敏感。一种常见的代码格式化是在章节标题后添加一个空行。但对于 Excalidraw 来说,这将破坏/改变您绘图中的第一个文本元素。" +
"为了解决这个问题,您可以启用这个设置。启用后 Excalidraw 将在 <code>## Text Elements</code> 的开头添加一个虚拟元素,供自动代码格式化工具修改。" ,
PRESERVE_TEXT_AFTER_DRAWING_NAME: "Zotero 兼容性",
PRESERVE_TEXT_AFTER_DRAWING_NAME: "Zotero 和脚注footnotes兼容性",
PRESERVE_TEXT_AFTER_DRAWING_DESC: "保留 Markdown 文件中 <code>## Drawing</code> 部分之后的文本内容。保存非常大的绘图时,这可能会造成微小的性能影响。",
DEBUGMODE_NAME: "开启 debug 信息",
DEBUGMODE_DESC: "我建议在启用/禁用此设置后重新启动 Obsidian。这将在控制台中启用调试消息。这对于排查问题很有帮助。" +

View File

@@ -101,7 +101,7 @@ import {
versionUpdateCheckTimer,
getFontMetrics,
} from "./utils/Utils";
import { editorInsertText, extractSVGPNGFileName, foldExcalidrawSection, getActivePDFPageNumberFromPDFView, getAttachmentsFolderAndFilePath, getNewOrAdjacentLeaf, getParentOfClass, isObsidianThemeDark, mergeMarkdownFiles, openLeaf, setExcalidrawView } from "./utils/ObsidianUtils";
import { editorInsertText, extractSVGPNGFileName, foldExcalidrawSection, getActivePDFPageNumberFromPDFView, getAttachmentsFolderAndFilePath, getExcalidrawViews, getNewOrAdjacentLeaf, getParentOfClass, isObsidianThemeDark, mergeMarkdownFiles, openLeaf, setExcalidrawView } from "./utils/ObsidianUtils";
import { ExcalidrawElement, ExcalidrawEmbeddableElement, ExcalidrawImageElement, ExcalidrawTextElement, FileId } from "@zsviczian/excalidraw/types/excalidraw/element/types";
import { ScriptEngine } from "./Scripts";
import {
@@ -758,9 +758,8 @@ export default class ExcalidrawPlugin extends Plugin {
setTimeout(()=>{ //run async to avoid blocking the UI
const theme = isObsidianThemeDark() ? "dark" : "light";
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
leaves.forEach((leaf: WorkspaceLeaf) => {
const excalidrawView = leaf.view as ExcalidrawView;
const excalidrawViews = getExcalidrawViews(this.app);
excalidrawViews.forEach(excalidrawView => {
if (excalidrawView.file && excalidrawView.excalidrawAPI) {
excalidrawView.setTheme(theme);
}
@@ -1495,7 +1494,6 @@ export default class ExcalidrawPlugin extends Plugin {
this.addCommand({
id: "toggle-lock",
hotkeys: [{ modifiers: ["Ctrl" || "Meta", "Shift"], key: "e" }],
name: t("TOGGLE_LOCK"),
checkCallback: (checking: boolean) => {
if (checking) {
@@ -1585,7 +1583,7 @@ export default class ExcalidrawPlugin extends Plugin {
this.addCommand({
id: "insert-link",
hotkeys: [{ modifiers: ["Ctrl" || "Meta", "Shift"], key: "k" }],
hotkeys: [{ modifiers: ["Mod", "Shift"], key: "k" }],
name: t("INSERT_LINK"),
checkCallback: (checking: boolean) => {
if (checking) {
@@ -1618,7 +1616,6 @@ export default class ExcalidrawPlugin extends Plugin {
this.addCommand({
id: "insert-link-to-element",
hotkeys: [{ modifiers: ["Ctrl" || "Meta", "Shift"], key: "k" }],
name: t("INSERT_LINK_TO_ELEMENT_NORMAL"),
checkCallback: (checking: boolean) => {
if (checking) {
@@ -2851,14 +2848,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 &&
@@ -2958,9 +2948,8 @@ export default class ExcalidrawPlugin extends Plugin {
const modifyEventHandler = async (file: TFile) => {
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(modifyEventHandler,`ExcalidrawPlugin.modifyEventHandler`, file);
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
leaves.forEach(async (leaf: WorkspaceLeaf) => {
const excalidrawView = leaf.view as ExcalidrawView;
const excalidrawViews = getExcalidrawViews(this.app);
excalidrawViews.forEach(async (excalidrawView) => {
if(excalidrawView.semaphores?.viewunload) {
return;
}
@@ -3020,10 +3009,10 @@ export default class ExcalidrawPlugin extends Plugin {
}
//close excalidraw view where this file is open
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
for (let i = 0; i < leaves.length; i++) {
if ((leaves[i].view as ExcalidrawView).file.path == file.path) {
await leaves[i].setViewState({
const excalidrawViews = getExcalidrawViews(this.app);
for (const excalidrawView of excalidrawViews) {
if (excalidrawView.file.path === file.path) {
await excalidrawView.leaf.setViewState({
type: VIEW_TYPE_EXCALIDRAW,
state: { file: null },
});
@@ -3219,8 +3208,8 @@ export default class ExcalidrawPlugin extends Plugin {
}
onunload() {
const excalidrawLeaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
excalidrawLeaves.forEach((leaf) => {
const excalidrawViews = getExcalidrawViews(this.app);
excalidrawViews.forEach(({leaf}) => {
this.setMarkdownView(leaf);
});

View File

@@ -2,7 +2,7 @@ import { AppState, ExcalidrawImperativeAPI } from "@zsviczian/excalidraw/types/e
import clsx from "clsx";
import { TFile } from "obsidian";
import * as React from "react";
import { DEVICE, VIEW_TYPE_EXCALIDRAW } from "src/constants/constants";
import { DEVICE } from "src/constants/constants";
import { PenSettingsModal } from "src/dialogs/PenSettingsModal";
import ExcalidrawView from "src/ExcalidrawView";
import { PenStyle } from "src/PenTypes";
@@ -11,8 +11,7 @@ import ExcalidrawPlugin from "../main";
import { ICONS, penIcon, stringToSVG } from "./ActionIcons";
import { UniversalInsertFileModal } from "src/dialogs/UniversalInsertFileModal";
import { t } from "src/lang/helpers";
declare const PLUGIN_VERSION:string;
import { getExcalidrawViews } from "src/utils/ObsidianUtils";
export function setPen (pen: PenStyle, api: any) {
const st = api.getAppState();
@@ -134,10 +133,8 @@ export class ObsidianMenu {
this.view.excalidrawAPI?.setToast({message:`Pin removed: ${name}`, duration: 3000, closable: true});
}
await this.plugin.saveSettings();
this.plugin.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
if (v.view instanceof ExcalidrawView) v.view.updatePinnedScripts()
})
})()
getExcalidrawViews(this.plugin.app).forEach(excalidrawView=>excalidrawView.updatePinnedScripts());
})()
},
1500
)

View File

@@ -3,7 +3,7 @@ import { Notice, TFile } from "obsidian";
import * as React from "react";
import { ActionButton } from "./ActionButton";
import { ICONS, saveIcon, stringToSVG } from "./ActionIcons";
import { DEVICE, SCRIPT_INSTALL_FOLDER, VIEW_TYPE_EXCALIDRAW } from "../constants/constants";
import { DEVICE, SCRIPT_INSTALL_FOLDER } from "../constants/constants";
import { insertLaTeXToView, search } from "../ExcalidrawAutomate";
import ExcalidrawView, { TextMode } from "../ExcalidrawView";
import { t } from "../lang/helpers";
@@ -17,10 +17,10 @@ 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";
import { getExcalidrawViews } from "src/utils/ObsidianUtils";
declare const PLUGIN_VERSION:string;
const dark = '<svg style="stroke:#ced4da;#212529;color:#ced4da;fill:#ced4da" ';
const light = '<svg style="stroke:#212529;color:#212529;fill:#212529" ';
type PanelProps = {
visible: boolean;
@@ -42,7 +42,7 @@ export type PanelState = {
scriptIconMap: ScriptIconMap | null;
};
const TOOLS_PANEL_WIDTH = 228;
const TOOLS_PANEL_WIDTH = () => REM_VALUE * 14.4;
export class ToolsPanel extends React.Component<PanelProps, PanelState> {
pos1: number = 0;
@@ -155,11 +155,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,
};
});
@@ -366,11 +366,11 @@ export class ToolsPanel extends React.Component<PanelProps, PanelState> {
async actionRunScript(key: string) {
const view = this.view;
const plugin = view.plugin;
const f = app.vault.getAbstractFileByPath(key);
const f = plugin.app.vault.getAbstractFileByPath(key);
if (f && f instanceof TFile) {
plugin.scriptEngine.executeScript(
view,
await app.vault.read(f),
await plugin.app.vault.read(f),
plugin.scriptEngine.getScriptName(f),
f
);
@@ -391,9 +391,7 @@ export class ToolsPanel extends React.Component<PanelProps, PanelState> {
api?.setToast({message:`Pinned: ${scriptName}`, duration: 3000, closable: true})
}
await plugin.saveSettings();
plugin.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
if (v.view instanceof ExcalidrawView) v.view.updatePinnedScripts()
})
getExcalidrawViews(plugin.app).forEach(excalidrawView=>excalidrawView.updatePinnedScripts());
}
private islandOnClick(event: React.MouseEvent<HTMLDivElement, MouseEvent>) {
@@ -453,7 +451,7 @@ export class ToolsPanel extends React.Component<PanelProps, PanelState> {
style={{
top: `${this.state.top}px`,
left: `${this.state.left}px`,
width: `13.75rem`,
width: `14.4rem`,
display:
this.state.visible && !this.state.excalidrawViewMode
? "block"
@@ -492,7 +490,7 @@ export class ToolsPanel extends React.Component<PanelProps, PanelState> {
maxHeight: "350px",
width: "initial",
//@ts-ignore
"--padding": 2,
"--padding": "0.125rem",
display: this.state.minimized ? "none" : "block",
}}
>

View File

@@ -10,12 +10,11 @@ import {
TextComponent,
TFile,
} from "obsidian";
import { GITHUB_RELEASES, VIEW_TYPE_EXCALIDRAW } from "./constants/constants";
import ExcalidrawView from "./ExcalidrawView";
import { GITHUB_RELEASES } from "./constants/constants";
import { t } from "./lang/helpers";
import type ExcalidrawPlugin from "./main";
import { PenStyle } from "./PenTypes";
import { DynamicStyle } from "./types/types";
import { DynamicStyle, GridSettings } from "./types/types";
import { PreviewImageType } from "./utils/UtilTypes";
import { setDynamicStyle } from "./utils/DynamicStyling";
import {
@@ -41,6 +40,7 @@ import { setDebugging } from "./utils/DebugHelper";
import { Rank } from "./menu/ActionIcons";
import { TAG_AUTOEXPORT, TAG_MDREADINGMODE, TAG_PDFEXPORT } from "src/constants/constSettingsTags";
import { HotkeyEditor } from "./dialogs/HotkeyEditor";
import { getExcalidrawViews } from "./utils/ObsidianUtils";
export interface ExcalidrawSettings {
folder: string;
@@ -179,6 +179,7 @@ export interface ExcalidrawSettings {
pdfNumRows: number;
pdfDirection: "down" | "right";
pdfImportScale: number;
gridSettings: GridSettings;
laserSettings: {
DECAY_TIME: number,
DECAY_LENGTH: number,
@@ -355,6 +356,11 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
pdfNumRows: 1,
pdfDirection: "right",
pdfImportScale: 0.3,
gridSettings: {
DYNAMIC_COLOR: true,
COLOR: "#000000",
OPACITY: 50,
},
laserSettings: {
DECAY_LENGTH: 50,
DECAY_TIME: 1000,
@@ -509,31 +515,25 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
}
this.plugin.saveSettings();
if (this.requestUpdatePinnedPens) {
this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
if (v.view instanceof ExcalidrawView) v.view.updatePinnedCustomPens()
})
getExcalidrawViews(this.app).forEach(excalidrawView =>
excalidrawView.updatePinnedCustomPens()
)
}
if (this.requestUpdateDynamicStyling) {
this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
if (v.view instanceof ExcalidrawView) {
setDynamicStyle(this.plugin.ea,v.view,v.view.previousBackgroundColor,this.plugin.settings.dynamicStyling);
}
})
getExcalidrawViews(this.app).forEach(excalidrawView =>
setDynamicStyle(this.plugin.ea,excalidrawView,excalidrawView.previousBackgroundColor,this.plugin.settings.dynamicStyling)
)
}
this.hotkeyEditor.unload();
if (this.hotkeyEditor.isDirty) {
this.plugin.registerHotkeyOverrides();
}
if (this.requestReloadDrawings) {
const exs =
this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
for (const v of exs) {
if (v.view instanceof ExcalidrawView) {
await v.view.save(false);
//debug({where:"ExcalidrawSettings.hide",file:v.view.file.name,before:"reload(true)"})
await v.view.reload(true);
}
const excalidrawViews = getExcalidrawViews(this.app);
for (const excalidrawView of excalidrawViews) {
await excalidrawView.save(false);
//debug({where:"ExcalidrawSettings.hide",file:v.view.file.name,before:"reload(true)"})
await excalidrawView.reload(true);
}
this.requestEmbedUpdate = true;
}
@@ -1241,9 +1241,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
.setValue(this.plugin.settings.allowPinchZoom)
.onChange(async (value) => {
this.plugin.settings.allowPinchZoom = value;
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
if (v.view instanceof ExcalidrawView) v.view.updatePinchZoom()
})
getExcalidrawViews(this.app).forEach(excalidrawView=>excalidrawView.updatePinchZoom())
this.applySettingsUpdate();
}),
);
@@ -1257,9 +1255,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
.setValue(this.plugin.settings.allowWheelZoom)
.onChange(async (value) => {
this.plugin.settings.allowWheelZoom = value;
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
if (v.view instanceof ExcalidrawView) v.view.updateWheelZoom()
})
getExcalidrawViews(this.app).forEach(excalidrawView=>excalidrawView.updateWheelZoom());
this.applySettingsUpdate();
}),
);
@@ -1310,7 +1306,79 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
el.innerText = ` ${this.plugin.settings.zoomToFitMaxLevel.toString()}`;
});
// ------------------------------------------------
// Grid
// ------------------------------------------------
detailsEl = displayDetailsEl.createEl("details");
detailsEl.createEl("summary", {
text: t("GRID_HEAD"),
cls: "excalidraw-setting-h3",
});
const updateGridColor = () => {
getExcalidrawViews(this.app).forEach(excalidrawView=>excalidrawView.updateGridColor());
};
// Dynamic color toggle
let gridColorSection: HTMLDivElement;
new Setting(detailsEl)
.setName(t("GRID_DYNAMIC_COLOR_NAME"))
.setDesc(fragWithHTML(t("GRID_DYNAMIC_COLOR_DESC")))
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.gridSettings.DYNAMIC_COLOR)
.onChange(async (value) => {
this.plugin.settings.gridSettings.DYNAMIC_COLOR = value;
gridColorSection.style.display = value ? "none" : "block";
this.applySettingsUpdate();
updateGridColor();
}),
);
// Create a div to contain color and opacity settings
gridColorSection = detailsEl.createDiv();
gridColorSection.style.display = this.plugin.settings.gridSettings.DYNAMIC_COLOR ? "none" : "block";
// Grid color picker
new Setting(gridColorSection)
.setName(t("GRID_COLOR_NAME"))
.addColorPicker((colorPicker) =>
colorPicker
.setValue(this.plugin.settings.gridSettings.COLOR)
.onChange(async (value) => {
this.plugin.settings.gridSettings.COLOR = value;
this.applySettingsUpdate();
updateGridColor();
}),
);
// Grid opacity slider (hex value between 00 and FF)
let opacityValue: HTMLDivElement;
new Setting(detailsEl)
.setName(t("GRID_OPACITY_NAME"))
.setDesc(fragWithHTML(t("GRID_OPACITY_DESC")))
.addSlider((slider) =>
slider
.setLimits(0, 100, 1) // 0 to 100 in decimal
.setValue(this.plugin.settings.gridSettings.OPACITY)
.onChange(async (value) => {
opacityValue.innerText = ` ${value.toString()}`;
this.plugin.settings.gridSettings.OPACITY = value;
this.applySettingsUpdate();
updateGridColor();
}),
)
.settingEl.createDiv("", (el) => {
opacityValue = el;
el.style.minWidth = "3em";
el.style.textAlign = "right";
el.innerText = ` ${this.plugin.settings.gridSettings.OPACITY}`;
});
// ------------------------------------------------
// Laser Pointer
// ------------------------------------------------
detailsEl = displayDetailsEl.createEl("details");
detailsEl.createEl("summary", {
text: t("LASER_HEAD"),

View File

@@ -13,6 +13,12 @@ export type ValueOf<T> = T[keyof T];
export type DynamicStyle = "none" | "gray" | "colorful";
export type GridSettings = {
DYNAMIC_COLOR: boolean; // Whether the grid color is dynamic
COLOR: string; // The grid color (in hex format)
OPACITY: number; // The grid opacity (hex value between "00" and "FF")
};
export type DeviceType = {
isDesktop: boolean,
isPhone: boolean,
@@ -25,6 +31,8 @@ export type DeviceType = {
isAndroid: boolean,
};
export type Point = [number, number];
declare global {
interface Window {
ExcalidrawAutomate: ExcalidrawAutomate;

View File

@@ -4,6 +4,7 @@ import { getEA } from "src";
import { ExcalidrawAutomate } from "src/ExcalidrawAutomate";
import { getCropFileNameAndFolder, getListOfTemplateFiles, splitFolderAndFilename } from "./FileUtils";
import { Notice, TFile } from "obsidian";
import { Radians } from "@zsviczian/excalidraw/types/math";
export const CROPPED_PREFIX = "cropped_";
export const ANNOTATED_PREFIX = "annotated_";
@@ -30,7 +31,7 @@ export const carveOutImage = async (sourceEA: ExcalidrawAutomate, viewImageEl: E
const scale = newImage.scale;
const angle = newImage.angle;
newImage.scale = [1,1];
newImage.angle = 0;
newImage.angle = 0 as Radians;
const ef = sourceEA.targetView.excalidrawData.getFile(viewImageEl.fileId);
let imageLink = "";

View File

@@ -82,8 +82,10 @@ export const setDynamicStyle = (
[`--color-surface-high`]: str(gray1().lighterBy(step)),
[`--color-on-primary-container`]: str(!isDark?accent().darkerBy(15):accent().lighterBy(15)),
[`--color-surface-primary-container`]: str(isDark?accent().darkerBy(step):accent().lighterBy(step)),
//[`--color-primary-darker`]: str(accent().darkerBy(step)),
//[`--color-primary-darkest`]: str(accent().darkerBy(step)),
[`--bold-color`]: str(!isDark?accent().darkerBy(15):accent().lighterBy(15)),
[`--color-primary-darker`]: str(accent().darkerBy(step)),
[`--color-primary-darkest`]: str(accent().darkerBy(2*step)),
['--button-bg-color']: str(gray1()),
[`--button-gray-1`]: str(gray1()),
[`--button-gray-2`]: str(gray2()),
[`--input-border-color`]: str(gray1()),
@@ -96,11 +98,11 @@ export const setDynamicStyle = (
[`--overlay-bg-color`]: gray2().alphaTo(0.6).stringHEX(),
[`--popup-bg-color`]: str(gray1()),
[`--color-on-surface`]: str(text),
[`--default-border-color`]: str(gray1()),
//[`--color-gray-100`]: str(text),
[`--color-gray-40`]: str(text), //frame
[`--color-gray-50`]: str(text), //frame
[`--color-surface-highlight`]: str(gray1()),
//[`--color-gray-30`]: str(gray1),
[`--color-gray-20`]: str(gray1()),
[`--sidebar-border-color`]: str(gray1()),
[`--color-primary-light`]: str(accent().lighterBy(step)),
[`--button-hover-bg`]: str(gray1()),
@@ -116,7 +118,11 @@ export const setDynamicStyle = (
[`color`]: str(text),
['--excalidraw-caret-color']: str(isLightTheme ? text : cmBG()),
[`--select-highlight-color`]: str(gray1()),
[`--color-gray-80`]: str(isDark?text.darkerBy(40):text.lighterBy(40)), //frame
[`--color-gray-90`]: str(isDark?text.darkerBy(5):text.lighterBy(5)), //search background
[`--color-gray-80`]: str(isDark?text.darkerBy(10):text.lighterBy(10)), //frame
[`--color-gray-70`]: str(isDark?text.darkerBy(10):text.lighterBy(10)), //frame
[`--default-bg-color`]: str(isDark?text.darkerBy(20):text.lighterBy(20)), //search background,
[`--color-gray-50`]: str(text), //frame
};
const styleString = Object.keys(styleObject)

View File

@@ -129,8 +129,9 @@ export function openExternalLink (link:string, app: App, element?: ExcalidrawEle
* the link to the file path. By default as a wiki link, or as a file path if returnWikiLink is false.
*/
export function parseObsidianLink(link: string, app: App, returnWikiLink: boolean = true): boolean | string {
if(!link) return false;
link = getLinkFromMarkdownLink(link);
if (!link.startsWith("obsidian://")) {
if (!link?.startsWith("obsidian://")) {
return false;
}
const url = new URL(link);
@@ -394,4 +395,4 @@ export function isTextImageTransclusion (
}
}
return false;
}
}

View File

@@ -9,8 +9,9 @@ import ExcalidrawPlugin from "../main";
import { checkAndCreateFolder, splitFolderAndFilename } from "./FileUtils";
import { linkClickModifierType, ModifierKeys } from "./ModifierkeyHelper";
import { REG_BLOCK_REF_CLEAN, REG_SECTION_REF_CLEAN, VIEW_TYPE_EXCALIDRAW } from "src/constants/constants";
import yaml, { Mark } from "js-yaml";
import yaml from "js-yaml";
import { debug, DEBUGGING } from "./DebugHelper";
import ExcalidrawView from "src/ExcalidrawView";
export const getParentOfClass = (element: Element, cssClass: string):HTMLElement | null => {
let parent = element.parentElement;
@@ -24,6 +25,11 @@ export const getParentOfClass = (element: Element, cssClass: string):HTMLElement
return parent?.classList?.contains(cssClass) ? parent : null;
};
export function getExcalidrawViews(app: App): ExcalidrawView[] {
const leaves = app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).filter(l=>l.view instanceof ExcalidrawView);
return leaves.map(l=>l.view as ExcalidrawView);
}
export const getLeaf = (
plugin: ExcalidrawPlugin,
origo: WorkspaceLeaf,

View File

@@ -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";

View File

@@ -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 {
@@ -629,4 +634,16 @@ textarea.excalidraw-wysiwyg, .excalidraw input {
.excalidraw .color-picker-content input[type="color"] {
filter: var(--theme-filter);
}
.ExcTextField__input input::placeholder {
color: var(--select-highlight-color);
}
.excalidraw textarea::placeholder {
color: var(--color-gray-50);
}
.excalidraw textarea.ttd-dialog-input {
caret-color: var(--excalidraw-caret-color);
}