mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
Compare commits
8 Commits
2.5.1
...
2.5.3-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cac94bf2f | ||
|
|
43e98db174 | ||
|
|
253575bf23 | ||
|
|
7a08ced65a | ||
|
|
5a64e1c75e | ||
|
|
fc0ac92dd3 | ||
|
|
4e2d7eb637 | ||
|
|
a5771625df |
@@ -2,7 +2,7 @@
|
||||
|
||||
[简体中文](./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)
|
||||
👉👉👉 Check out and contribute to the new [Obsidian-Excalidraw Community Wiki](https://excalidraw-obsidian.online/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.
|
||||
|
||||
|
||||
BIN
assets/excalidraw-fonts.zip
Normal file
BIN
assets/excalidraw-fonts.zip
Normal file
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "2.5.1",
|
||||
"version": "2.5.3-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.5.1",
|
||||
"version": "2.5.2",
|
||||
"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-56",
|
||||
"@zsviczian/excalidraw": "0.17.6-2",
|
||||
"chroma-js": "^2.4.2",
|
||||
"clsx": "^2.0.0",
|
||||
"@zsviczian/colormaster": "^1.2.2",
|
||||
|
||||
@@ -93,6 +93,7 @@ import { EXCALIDRAW_AUTOMATE_INFO, EXCALIDRAW_SCRIPTENGINE_INFO } from "./dialog
|
||||
import { addBackOfTheNoteCard, getFrameBasedOnFrameNameOrId } from "./utils/ExcalidrawViewUtils";
|
||||
import { log } from "./utils/DebugHelper";
|
||||
import { ExcalidrawLib } from "./ExcalidrawLib";
|
||||
import { GlobalPoint } from "@zsviczian/excalidraw/types/math/types";
|
||||
|
||||
extendPlugins([
|
||||
HarmonyPlugin,
|
||||
@@ -1402,8 +1403,8 @@ export class ExcalidrawAutomate {
|
||||
): string {
|
||||
const box = getLineBox(points);
|
||||
id = id ?? nanoid();
|
||||
const startPoint = points[0];
|
||||
const endPoint = points[points.length - 1];
|
||||
const startPoint = points[0] as GlobalPoint;
|
||||
const endPoint = points[points.length - 1] as GlobalPoint;
|
||||
this.elementsDict[id] = {
|
||||
points: normalizeLinePoints(points),
|
||||
lastCommittedPoint: null,
|
||||
@@ -1693,8 +1694,8 @@ export class ExcalidrawAutomate {
|
||||
if (!connectionA) {
|
||||
const intersect = intersectElementWithLine(
|
||||
elA,
|
||||
[bCenterX, bCenterY],
|
||||
[aCenterX, aCenterY],
|
||||
[bCenterX, bCenterY] as GlobalPoint,
|
||||
[aCenterX, aCenterY] as GlobalPoint,
|
||||
GAP,
|
||||
);
|
||||
if (intersect.length === 0) {
|
||||
@@ -1707,8 +1708,8 @@ export class ExcalidrawAutomate {
|
||||
if (!connectionB) {
|
||||
const intersect = intersectElementWithLine(
|
||||
elB,
|
||||
[aCenterX, aCenterY],
|
||||
[bCenterX, bCenterY],
|
||||
[aCenterX, aCenterY] as GlobalPoint,
|
||||
[bCenterX, bCenterY] as GlobalPoint,
|
||||
GAP,
|
||||
);
|
||||
if (intersect.length === 0) {
|
||||
@@ -2421,7 +2422,12 @@ export class ExcalidrawAutomate {
|
||||
b: readonly [number, number],
|
||||
gap?: number,
|
||||
): Point[] {
|
||||
return intersectElementWithLine(element, a, b, gap);
|
||||
return intersectElementWithLine(
|
||||
element,
|
||||
a as GlobalPoint,
|
||||
b as GlobalPoint,
|
||||
gap
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2878,11 +2884,11 @@ function getFontFamily(id: number):string {
|
||||
}
|
||||
|
||||
export async function initFonts():Promise<void> {
|
||||
await excalidrawLib.registerFontsInCSS();
|
||||
/*await excalidrawLib.registerFontsInCSS();
|
||||
const fonts = excalidrawLib.getFontFamilies();
|
||||
for(let i=0;i<fonts.length;i++) {
|
||||
if(fonts[i] !== "Local Font") await (document as any).fonts.load(`16px ${fonts[i]}`);
|
||||
};
|
||||
};*/
|
||||
}
|
||||
|
||||
export function _measureText(
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
FRONTMATTER_KEYS,
|
||||
refreshTextDimensions,
|
||||
getContainerElement,
|
||||
loadSceneFonts,
|
||||
} from "./constants/constants";
|
||||
import ExcalidrawPlugin from "./main";
|
||||
import { TextMode } from "./ExcalidrawView";
|
||||
@@ -52,6 +53,8 @@ import { DEBUGGING, debug } from "./utils/DebugHelper";
|
||||
import { Mutable } from "@zsviczian/excalidraw/types/excalidraw/utility-types";
|
||||
import { updateElementIdsInScene } from "./utils/ExcalidrawSceneUtils";
|
||||
import { getNewUniqueFilepath } from "./utils/FileUtils";
|
||||
import { t } from "./lang/helpers";
|
||||
import { displayFontMessage } from "./utils/ExcalidrawViewUtils";
|
||||
|
||||
type SceneDataWithFiles = SceneData & { files: BinaryFiles };
|
||||
|
||||
@@ -745,6 +748,15 @@ export class ExcalidrawData {
|
||||
|
||||
this.deletedElements = this.scene.elements.filter((el:ExcalidrawElement)=>el.isDeleted);
|
||||
this.scene.elements = this.scene.elements.filter((el:ExcalidrawElement)=>!el.isDeleted);
|
||||
|
||||
const timer = window.setTimeout(()=>{
|
||||
const notice = new Notice(t("FONT_LOAD_SLOW"),15000);
|
||||
notice.noticeEl.oncontextmenu = () => {
|
||||
displayFontMessage(this.app);
|
||||
}
|
||||
},2000);
|
||||
await loadSceneFonts(this.scene.elements);
|
||||
clearTimeout(timer);
|
||||
|
||||
if (!this.scene.files) {
|
||||
this.scene.files = {}; //loading legacy scenes that do not yet have the files attribute.
|
||||
|
||||
14
src/ExcalidrawLib.d.ts
vendored
14
src/ExcalidrawLib.d.ts
vendored
@@ -3,8 +3,9 @@ import { ImportedDataState } from "@zsviczian/excalidraw/types/excalidraw/data/t
|
||||
import { BoundingBox } from "@zsviczian/excalidraw/types/excalidraw/element/bounds";
|
||||
import { ElementsMap, ExcalidrawBindableElement, ExcalidrawElement, ExcalidrawFrameElement, ExcalidrawFrameLikeElement, ExcalidrawTextContainer, ExcalidrawTextElement, FontFamilyValues, FontString, NonDeleted, NonDeletedExcalidrawElement, Theme } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
import { FontMetadata } from "@zsviczian/excalidraw/types/excalidraw/fonts/metadata";
|
||||
import { AppState, BinaryFiles, DataURL, GenerateDiagramToCode, Point, Zoom } from "@zsviczian/excalidraw/types/excalidraw/types";
|
||||
import { AppState, BinaryFiles, DataURL, GenerateDiagramToCode, Zoom } from "@zsviczian/excalidraw/types/excalidraw/types";
|
||||
import { Mutable } from "@zsviczian/excalidraw/types/excalidraw/utility-types";
|
||||
import { GlobalPoint } from "@zsviczian/excalidraw/types/math/types";
|
||||
|
||||
type EmbeddedLink =
|
||||
| ({
|
||||
@@ -75,16 +76,16 @@ declare namespace ExcalidrawLib {
|
||||
|
||||
function determineFocusDistance(
|
||||
element: ExcalidrawBindableElement,
|
||||
a: Point,
|
||||
b: Point,
|
||||
a: GlobalPoint,
|
||||
b: GlobalPoint,
|
||||
): number;
|
||||
|
||||
function intersectElementWithLine(
|
||||
element: ExcalidrawBindableElement,
|
||||
a: Point,
|
||||
b: Point,
|
||||
a: GlobalPoint,
|
||||
b: GlobalPoint,
|
||||
gap?: number,
|
||||
): Point[];
|
||||
): GlobalPoint[];
|
||||
|
||||
function getCommonBoundingBox(
|
||||
elements: ExcalidrawElement[] | readonly NonDeleted<ExcalidrawElement>[],
|
||||
@@ -186,5 +187,6 @@ declare namespace ExcalidrawLib {
|
||||
separator?: string,
|
||||
): string;
|
||||
function safelyParseJSON (json: string): Record<string, any> | null;
|
||||
function loadSceneFonts(elements: NonDeletedExcalidrawElement[]): Promise<void>;
|
||||
}
|
||||
|
||||
|
||||
@@ -2745,6 +2745,8 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
}
|
||||
if(!DEVICE.isMobile) {
|
||||
if(requireApiVersion("0.16.0")) {
|
||||
//@ts-ignore
|
||||
this.leaf.tabHeaderInnerIconEl.style.color="var(--color-accent)"
|
||||
//@ts-ignore
|
||||
this.leaf.tabHeaderInnerTitleEl.style.color="var(--color-accent)"
|
||||
}
|
||||
@@ -2773,6 +2775,8 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
this.actionButtons['save'].querySelector("svg").removeClass("excalidraw-dirty");
|
||||
if(!DEVICE.isMobile) {
|
||||
if(requireApiVersion("0.16.0")) {
|
||||
//@ts-ignore
|
||||
this.leaf.tabHeaderInnerIconEl.style.color=""
|
||||
//@ts-ignore
|
||||
this.leaf.tabHeaderInnerTitleEl.style.color=""
|
||||
}
|
||||
@@ -3444,7 +3448,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
toDelete.forEach((k) => delete files[k]);
|
||||
}
|
||||
|
||||
const activeTool = st.activeTool;
|
||||
const activeTool = {...st.activeTool};
|
||||
if(!["freedraw","hand"].includes(activeTool.type)) {
|
||||
activeTool.type = "selection";
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import { FILENAMEPARTS, PreviewImageType } from "./utils/UtilTypes";
|
||||
import { CustomMutationObserver, debug, DEBUGGING } from "./utils/DebugHelper";
|
||||
import { getExcalidrawFileForwardLinks } from "./utils/ExcalidrawViewUtils";
|
||||
import { linkPrompt } from "./dialogs/Prompt";
|
||||
import { isHTMLElement } from "./utils/typechecks";
|
||||
|
||||
interface imgElementAttributes {
|
||||
file?: TFile;
|
||||
@@ -405,12 +406,13 @@ const createImgElement = async (
|
||||
|
||||
let timer:number;
|
||||
const clickEvent = (ev:PointerEvent) => {
|
||||
if(!(ev.target instanceof Element)) {
|
||||
if (!isHTMLElement(ev.target)) {
|
||||
return;
|
||||
}
|
||||
const containerElement = ev.target.hasClass("excalidraw-embedded-img")
|
||||
const targetElement = ev.target as HTMLElement;
|
||||
const containerElement = targetElement.hasClass("excalidraw-embedded-img")
|
||||
? ev.target
|
||||
: getParentOfClass(ev.target, "excalidraw-embedded-img");
|
||||
: getParentOfClass(targetElement, "excalidraw-embedded-img");
|
||||
if (!containerElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ export const {
|
||||
getContainerElement,
|
||||
refreshTextDimensions,
|
||||
getCSSFontDefinition,
|
||||
loadSceneFonts,
|
||||
} = excalidrawLib;
|
||||
|
||||
export const FONTS_STYLE_ID = "excalidraw-custom-fonts";
|
||||
|
||||
@@ -17,6 +17,18 @@ 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.2": `
|
||||
## Fixed
|
||||
- Text became disconnected from sticky notes (rectangle/ellipse/diamond + text) if the sticky note contained a link (e.g., URL or wiki link), and in some cases, triggered a save error warning. [#2054](https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/2054)
|
||||
- Long-clicking to open an Excalidraw drawing from a markdown note did not work when the note was in an Obsidian pop-out window.
|
||||
- Active tool was deactivated after autosave, requiring the user to reselect the tool.
|
||||
|
||||
## Minor changes to default settings
|
||||
- I adjusted some of the default settings. This change only affects new installs of Excalidraw; existing installs and settings remain unchanged:
|
||||
- **Reuse Adjacent Pane** is now the default for opening new drawings. Excalidraw will try to open the drawing in the most recently used adjacent pane, if available.
|
||||
- **Focus on Existing Tab** is the default for reopening an already open drawing. Excalidraw will switch to the existing tab where the drawing is open, instead of creating a new one.
|
||||
- **Autosave Interval** is now set to a default value of 1 minute on Desktop and 30 seconds on mobile platforms.
|
||||
`,
|
||||
"2.5.1": `
|
||||
## New
|
||||
- Excalidraw will now save images using the filename from the file system when adding an image via the image tool (in the top toolbar).
|
||||
|
||||
@@ -187,7 +187,7 @@ export default {
|
||||
|
||||
BASIC_HEAD: "Basic",
|
||||
BASIC_DESC: `In the "Basic" settings, you can configure options such as displaying release notes after updates, receiving plugin update notifications, setting the default location for new drawings, specifying the Excalidraw folder for embedding drawings into active documents, defining an Excalidraw template file, and designating an Excalidraw Automate script folder for managing automation scripts.`,
|
||||
FOLDER_NAME: "Excalidraw folder",
|
||||
FOLDER_NAME: "Excalidraw folder (CAsE sEnsITive!)",
|
||||
FOLDER_DESC:
|
||||
"Default location for new drawings. If empty, drawings will be created in the Vault root.",
|
||||
CROP_PREFIX_NAME: "Crop file prefix",
|
||||
@@ -201,10 +201,10 @@ export default {
|
||||
ANNOTATE_PRESERVE_SIZE_NAME: "Preserve image size when annotating",
|
||||
ANNOTATE_PRESERVE_SIZE_DESC:
|
||||
"When annotating an image in markdown the replacment image link will include the width of the original image.",
|
||||
CROP_FOLDER_NAME: "Crop file folder",
|
||||
CROP_FOLDER_NAME: "Crop file folder (CaSE senSItive!)",
|
||||
CROP_FOLDER_DESC:
|
||||
"Default location for new drawings created when cropping an image. If empty, drawings will be created following the Vault attachments settings.",
|
||||
ANNOTATE_FOLDER_NAME: "Image annotation file folder",
|
||||
ANNOTATE_FOLDER_NAME: "Image annotation file folder (CaSe SeNSitIVe!)",
|
||||
ANNOTATE_FOLDER_DESC:
|
||||
"Default location for new drawings created when annotating an image. If empty, drawings will be created following the Vault attachments settings.",
|
||||
FOLDER_EMBED_NAME:
|
||||
@@ -213,7 +213,7 @@ export default {
|
||||
"Define which folder to place the newly inserted drawing into " +
|
||||
"when using the command palette action: 'Create a new drawing and embed into active document'.<br>" +
|
||||
"<b><u>Toggle ON:</u></b> Use Excalidraw folder<br><b><u>Toggle OFF:</u></b> Use the attachments folder defined in Obsidian settings.",
|
||||
TEMPLATE_NAME: "Excalidraw template file or folder",
|
||||
TEMPLATE_NAME: "Excalidraw template file or folder (caSe SenSiTive!)",
|
||||
TEMPLATE_DESC:
|
||||
"Full filepath or folderpath to the Excalidraw template.<br>" +
|
||||
"<b>Template File:</b>E.g.: If your template is in the default Excalidraw folder and its name is " +
|
||||
@@ -229,6 +229,15 @@ export default {
|
||||
"You can access your scripts from Excalidraw via the Obsidian Command Palette. Assign " +
|
||||
"hotkeys to your favorite scripts just like to any other Obsidian command. " +
|
||||
"The folder may not be the root folder of your Vault. ",
|
||||
ASSETS_FOLDER_NAME: "Local Font Assets Folder (cAsE sENsiTIvE!)",
|
||||
ASSETS_FOLDER_DESC: `Since version 2.5.3, following the implementation of CJK font support, Excalidraw downloads fonts from the internet.
|
||||
If you prefer to keep Excalidraw fully local, allowing it to work without internet access, or if your internet connection is slow
|
||||
and you want to improve performance, you can download the necessary
|
||||
<a href="https://github.com/zsviczian/obsidian-excalidraw-plugin/raw/refs/heads/master/assets/excalidraw-fonts.zip" target="_blank">font assets from GitHub</a>.
|
||||
After downloading, unzip the contents into a folder within your Vault.<br>
|
||||
You can specify the location of that folder here. For example, you may choose to place it under <code>Excalidraw/FontAssets</code>.<br><br>
|
||||
<strong>Important:</strong> Do not set this to the Vault root! Ensure that no other files are placed in this folder.<br><br>
|
||||
<strong>Note:</strong> If you're using Obsidian Sync and want to synchronize these font files across your devices, ensure that Obsidian Sync is set to synchronize "All other file types".`,
|
||||
AI_HEAD: "AI Settings - Experimental",
|
||||
AI_DESC: `In the "AI" settings, you can configure options for using OpenAI's GPT API. ` +
|
||||
`While the OpenAI API is in beta, its use is strictly limited — as such we require you use your own API key. ` +
|
||||
@@ -816,6 +825,36 @@ FILENAME_HEAD: "Filename",
|
||||
|
||||
//ExcalidrawData.ts
|
||||
LOAD_FROM_BACKUP: "Excalidraw file was corrupted. Loading from backup file.",
|
||||
FONT_LOAD_SLOW: "Loading Fonts...\n\n This is taking longer than expected. If this delay occurs regulary then you may download the fonts locally to your Vault. \n\n" +
|
||||
"(click=dismiss, right-click=Info)",
|
||||
FONT_INFO_TITLE: "Starting v2.5.3 fonts load from the Internet",
|
||||
FONT_INFO_DETAILED: `
|
||||
<p>
|
||||
To improve Obsidian's startup time and manage the large <strong>CJK font family</strong>,
|
||||
I've moved the fonts out of the plugin's <code>main.js</code>. Starting with version 2.5.3,
|
||||
fonts will be loaded from the internet. This typically shouldn't cause issues as Obsidian caches
|
||||
these files after first use.
|
||||
</p>
|
||||
<p>
|
||||
If you prefer to keep Obsidian 100% local or experience performance issues, you can download the font assets.
|
||||
</p>
|
||||
<h3>Instructions:</h3>
|
||||
<ol>
|
||||
<li>Download the fonts from <a href="https://github.com/zsviczian/obsidian-excalidraw-plugin/raw/refs/heads/master/assets/excalidraw-fonts.zip">GitHub</a>.</li>
|
||||
<li>Unzip and copy files into a Vault folder (default: <code>Excalidraw/FontAssets</code>; folder names are cAse-senSITive).</li>
|
||||
<li><mark>DO NOT</mark> set this folder to the Vault root or mix with other local fonts.</li>
|
||||
</ol>
|
||||
<h3>For Obsidian Sync Users:</h3>
|
||||
<p>
|
||||
Ensure Obsidian Sync is set to synchronize "All other file types" or download and unzip the file on all devices.
|
||||
</p>
|
||||
<h3>Note:</h3>
|
||||
<p>
|
||||
If you find this process cumbersome, please submit a feature request to Obsidian.md for supporting assets in the plugin folder.
|
||||
Currently, only a single <code>main.js</code> is supported, which leads to large files and slow startup times for complex plugins like Excalidraw.
|
||||
I apologize for the inconvenience.
|
||||
</p>
|
||||
`,
|
||||
|
||||
//ObsidianMenu.tsx
|
||||
GOTO_FULLSCREEN: "Goto fullscreen mode",
|
||||
|
||||
@@ -313,6 +313,15 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
};
|
||||
}*/
|
||||
|
||||
public async loadFontFromFile(fontName: string): Promise<ArrayBuffer> {
|
||||
const assetsFoler = "Fonts/";
|
||||
const file = this.app.vault.getAbstractFileByPath(assetsFoler + fontName);
|
||||
if(!file || !(file instanceof TFile)) {
|
||||
return;
|
||||
}
|
||||
return await this.app.vault.readBinary(file);
|
||||
}
|
||||
|
||||
async onload() {
|
||||
initCompressionWorker();
|
||||
this.loadTimestamp = Date.now();
|
||||
|
||||
@@ -49,6 +49,7 @@ export interface ExcalidrawSettings {
|
||||
embedUseExcalidrawFolder: boolean;
|
||||
templateFilePath: string;
|
||||
scriptFolderPath: string;
|
||||
fontAssetsPath: string;
|
||||
compress: boolean;
|
||||
decompressForMDView: boolean;
|
||||
onceOffCompressFlagReset: boolean; //used to reset compress to true in 2.2.0
|
||||
@@ -220,13 +221,14 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
embedUseExcalidrawFolder: false,
|
||||
templateFilePath: "Excalidraw/Template.excalidraw",
|
||||
scriptFolderPath: "Excalidraw/Scripts",
|
||||
fontAssetsPath: "Excalidraw/FontAssets",
|
||||
compress: true,
|
||||
decompressForMDView: false,
|
||||
onceOffCompressFlagReset: false,
|
||||
onceOffGPTVersionReset: false,
|
||||
autosave: true,
|
||||
autosaveIntervalDesktop: 30000,
|
||||
autosaveIntervalMobile: 20000,
|
||||
autosaveIntervalDesktop: 60000,
|
||||
autosaveIntervalMobile: 30000,
|
||||
drawingFilenamePrefix: "Drawing ",
|
||||
drawingEmbedPrefixWithFilename: true,
|
||||
drawingFilnameEmbedPostfix: " ",
|
||||
@@ -268,9 +270,9 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
done: "🗹",
|
||||
hoverPreviewWithoutCTRL: false,
|
||||
linkOpacity: 1,
|
||||
openInAdjacentPane: false,
|
||||
openInAdjacentPane: true,
|
||||
showSecondOrderLinks: true,
|
||||
focusOnFileTab: false,
|
||||
focusOnFileTab: true,
|
||||
openInMainWorkspace: true,
|
||||
showLinkBrackets: true,
|
||||
allowCtrlClick: true,
|
||||
@@ -720,6 +722,18 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(detailsEl)
|
||||
.setName(t("ASSETS_FOLDER_NAME"))
|
||||
.setDesc(fragWithHTML(t("ASSETS_FOLDER_DESC")))
|
||||
.addText((text) =>
|
||||
text
|
||||
.setPlaceholder("e.g.: Excalidraw/FontAssets")
|
||||
.setValue(this.plugin.settings.fontAssetsPath)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.fontAssetsPath = value;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
// ------------------------------------------------
|
||||
// Saving
|
||||
@@ -2484,7 +2498,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
d.addOption("Virgil", "Virgil");
|
||||
this.app.vault
|
||||
.getFiles()
|
||||
.filter((f) => ["ttf", "woff", "woff2", "otf"].contains(f.extension))
|
||||
.filter((f) => ["ttf", "woff", "woff2", "otf"].contains(f.extension) && !f.path.startsWith(this.plugin.settings.fontAssetsPath))
|
||||
.forEach((f: TFile) => {
|
||||
d.addOption(f.path, f.name);
|
||||
});
|
||||
|
||||
@@ -23,6 +23,9 @@ export function updateElementIdsInScene(
|
||||
boundEl.boundElements?.filter(x=>x.id === elementToChange.id).forEach( x => {
|
||||
(x.id as Mutable<string>) = newID;
|
||||
});
|
||||
if(boundEl.type === "text") {
|
||||
boundEl.containerId = newID;
|
||||
}
|
||||
if(boundEl.type === "arrow") {
|
||||
const arrow = boundEl as Mutable<ExcalidrawArrowElement>;
|
||||
if(arrow.startBinding?.elementId === elementToChange.id) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import { MAX_IMAGE_SIZE, IMAGE_TYPES, ANIMATED_IMAGE_TYPES, MD_EX_SECTIONS } from "src/constants/constants";
|
||||
import { App, Notice, TFile, WorkspaceLeaf } from "obsidian";
|
||||
import { App, Modal, Notice, TFile, WorkspaceLeaf } from "obsidian";
|
||||
import { ExcalidrawAutomate } from "src/ExcalidrawAutomate";
|
||||
import { REGEX_LINK, REG_LINKINDEX_HYPERLINK, getExcalidrawMarkdownHeaderSection, REGEX_TAGS } from "src/ExcalidrawData";
|
||||
import ExcalidrawView from "src/ExcalidrawView";
|
||||
@@ -402,3 +402,19 @@ export function isTextImageTransclusion (
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function displayFontMessage(app: App) {
|
||||
const modal = new Modal(app);
|
||||
|
||||
modal.onOpen = () => {
|
||||
const contentEl = modal.contentEl;
|
||||
contentEl.createEl("h2", { text: t("FONT_INFO_TITLE") });
|
||||
|
||||
const releaseNotesHTML = t("FONT_INFO_DETAILED");
|
||||
|
||||
const div = contentEl.createDiv({ cls: "release-notes" });
|
||||
div.innerHTML = releaseNotesHTML;
|
||||
}
|
||||
|
||||
modal.open();
|
||||
}
|
||||
18
src/utils/typechecks.ts
Normal file
18
src/utils/typechecks.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Checks if a given target is an HTMLElement.
|
||||
*
|
||||
* This function is necessary because `instanceof HTMLElement` can fail
|
||||
* in environments with multiple execution contexts (e.g., popout windows),
|
||||
* where `HTMLElement` comes from different global objects.
|
||||
* Instead, we use feature detection by checking for key properties
|
||||
* common to all HTML elements (nodeType and tagName).
|
||||
*
|
||||
* @param target - The target to check.
|
||||
* @returns True if the target is an HTMLElement, false otherwise.
|
||||
*/
|
||||
export function isHTMLElement (target: any): target is HTMLElement {
|
||||
return target &&
|
||||
typeof target === 'object' &&
|
||||
target.nodeType === 1 && // nodeType 1 means it's an element
|
||||
typeof target.tagName === 'string'; // tagName exists on HTML elements
|
||||
}
|
||||
Reference in New Issue
Block a user