Compare commits

..

6 Commits

Author SHA1 Message Date
zsviczian
7cac94bf2f 2.5.3-beta-1 2024-10-19 20:43:48 +02:00
zsviczian
43e98db174 remove font assets, replace with zip 2024-10-19 16:21:20 +02:00
zsviczian
253575bf23 font assets 2024-10-19 16:11:24 +02:00
zsviczian
7a08ced65a Merge pull request #2066 from heinrich26/master
Make the Tab Icons color change as well, if a Tab is dirty (unsaved)
2024-10-19 06:40:18 +02:00
Hendrik Horstmann
5a64e1c75e Merge branch 'zsviczian:master' into master 2024-10-16 19:28:22 +02:00
Hendrik Horstmann
a5771625df Make the Tab Icons color change as well, if a Tab is dirty (unsaved) 2024-05-22 16:17:30 +02:00
12 changed files with 126 additions and 23 deletions

BIN
assets/excalidraw-fonts.zip Normal file

Binary file not shown.

View File

@@ -1,7 +1,7 @@
{
"id": "obsidian-excalidraw-plugin",
"name": "Excalidraw",
"version": "2.5.2",
"version": "2.5.3-beta-1",
"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-57",
"@zsviczian/excalidraw": "0.17.6-2",
"chroma-js": "^2.4.2",
"clsx": "^2.0.0",
"@zsviczian/colormaster": "^1.2.2",

View File

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

View File

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

View File

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

View File

@@ -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=""
}

View File

@@ -103,6 +103,7 @@ export const {
getContainerElement,
refreshTextDimensions,
getCSSFontDefinition,
loadSceneFonts,
} = excalidrawLib;
export const FONTS_STYLE_ID = "excalidraw-custom-fonts";

View File

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

View File

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

View File

@@ -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,6 +221,7 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
embedUseExcalidrawFolder: false,
templateFilePath: "Excalidraw/Template.excalidraw",
scriptFolderPath: "Excalidraw/Scripts",
fontAssetsPath: "Excalidraw/FontAssets",
compress: true,
decompressForMDView: false,
onceOffCompressFlagReset: false,
@@ -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);
});

View File

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