mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
Compare commits
15 Commits
2.5.3-beta
...
2.6.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee9364b645 | ||
|
|
5bbe66900e | ||
|
|
a775a858c7 | ||
|
|
2dab801ff5 | ||
|
|
07f8a87580 | ||
|
|
91be6e2a2f | ||
|
|
5c709588dd | ||
|
|
19a46e5b11 | ||
|
|
e132d4a9fc | ||
|
|
cf2d9bea24 | ||
|
|
09cbffed1e | ||
|
|
368de8c1f4 | ||
|
|
7dcf9173c2 | ||
|
|
eac312c3a2 | ||
|
|
7a420a9d2d |
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "2.5.3-beta-1",
|
||||
"version": "2.6.0-beta-4",
|
||||
"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.6-2",
|
||||
"@zsviczian/excalidraw": "0.17.6-6",
|
||||
"chroma-js": "^2.4.2",
|
||||
"clsx": "^2.0.0",
|
||||
"@zsviczian/colormaster": "^1.2.2",
|
||||
@@ -34,7 +34,8 @@
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"roughjs": "^4.5.2",
|
||||
"woff2sfnt-sfnt2woff": "^1.0.0"
|
||||
"woff2sfnt-sfnt2woff": "^1.0.0",
|
||||
"es6-promise-pool": "2.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.9",
|
||||
|
||||
@@ -8,6 +8,7 @@ import fs from 'fs';
|
||||
import LZString from 'lz-string';
|
||||
import postprocess from '@zsviczian/rollup-plugin-postprocess';
|
||||
import cssnano from 'cssnano';
|
||||
import jsesc from 'jsesc';
|
||||
|
||||
// Load environment variables
|
||||
import dotenv from 'dotenv';
|
||||
@@ -16,7 +17,7 @@ dotenv.config();
|
||||
const DIST_FOLDER = 'dist';
|
||||
const isProd = (process.env.NODE_ENV === "production");
|
||||
const isLib = (process.env.NODE_ENV === "lib");
|
||||
console.log(`Running: ${process.env.NODE_ENV}`);
|
||||
console.log(`Running: ${process.env.NODE_ENV}; isProd: ${isProd}; isLib: ${isLib}`);
|
||||
|
||||
const excalidraw_pkg = isLib ? "" : isProd
|
||||
? fs.readFileSync("./node_modules/@zsviczian/excalidraw/dist/excalidraw.production.min.js", "utf8")
|
||||
@@ -52,11 +53,13 @@ if (!isLib) console.log(manifest.version);
|
||||
const packageString = isLib
|
||||
? ""
|
||||
: ';' + lzstring_pkg +
|
||||
'\nlet EXCALIDRAW_PACKAGES = LZString.decompressFromBase64("' + LZString.compressToBase64(react_pkg + reactdom_pkg + excalidraw_pkg) + '");\n' +
|
||||
'let {react, reactDOM, excalidrawLib} = window.eval.call(window, `(function() {' +
|
||||
'${EXCALIDRAW_PACKAGES};' +
|
||||
'return {react: React, reactDOM: ReactDOM, excalidrawLib: ExcalidrawLib};})();`);\n' +
|
||||
'let PLUGIN_VERSION="' + manifest.version + '";';
|
||||
'\nlet REACT_PACKAGES = `' +
|
||||
jsesc(react_pkg + reactdom_pkg, { quotes: 'backtick' }) +
|
||||
'`;\n' +
|
||||
'let EXCALIDRAW_PACKAGE = ""; const unpackExcalidraw = () => {EXCALIDRAW_PACKAGE = LZString.decompressFromBase64("' + LZString.compressToBase64(excalidraw_pkg) + '");};\n' +
|
||||
'let {react, reactDOM } = window.eval.call(window, `(function() {' + '${REACT_PACKAGES};' + 'return {react: React, reactDOM: ReactDOM};})();`);\n' +
|
||||
`let excalidrawLib = {};\n` +
|
||||
'let PLUGIN_VERSION="' + manifest.version + '";';
|
||||
|
||||
const BASE_CONFIG = {
|
||||
input: 'src/main.ts',
|
||||
|
||||
@@ -36,6 +36,8 @@ import {
|
||||
isMaskFile,
|
||||
getEmbeddedFilenameParts,
|
||||
cropCanvas,
|
||||
promiseTry,
|
||||
PromisePool,
|
||||
} from "./utils/Utils";
|
||||
import { ValueOf } from "./types/types";
|
||||
import { getMermaidImageElements, getMermaidText, shouldRenderMermaid } from "./utils/MermaidUtils";
|
||||
@@ -606,126 +608,169 @@ export class EmbeddedFilesLoader {
|
||||
this.isDark = excalidrawData?.scene?.appState?.theme === "dark";
|
||||
}
|
||||
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"});
|
||||
const data = await this._getObsidianImage(embeddedFile, depth);
|
||||
if (data) {
|
||||
const fileData: FileData = {
|
||||
mimeType: data.mimeType,
|
||||
id: entry.value[0],
|
||||
dataURL: data.dataURL,
|
||||
created: data.created,
|
||||
size: data.size,
|
||||
hasSVGwithBitmap: data.hasSVGwithBitmap,
|
||||
shouldScale: embeddedFile.shouldScale()
|
||||
};
|
||||
try {
|
||||
addFiles([fileData], this.isDark, false);
|
||||
}
|
||||
catch(e) {
|
||||
errorlog({ where: "EmbeddedFileLoader.loadSceneFiles", error: e });
|
||||
}
|
||||
//files.push(fileData);
|
||||
}
|
||||
} else if (embeddedFile.isSVGwithBitmap && (depth !== 0 || isThemeChange)) {
|
||||
//this will reload the image in light/dark mode when switching themes
|
||||
const fileData = {
|
||||
mimeType: embeddedFile.mimeType,
|
||||
id: entry.value[0],
|
||||
dataURL: embeddedFile.getImage(this.isDark) as DataURL,
|
||||
created: embeddedFile.mtime,
|
||||
size: embeddedFile.size,
|
||||
hasSVGwithBitmap: embeddedFile.isSVGwithBitmap,
|
||||
shouldScale: embeddedFile.shouldScale()
|
||||
};
|
||||
//files.push(fileData);
|
||||
try {
|
||||
addFiles([fileData], this.isDark, false);
|
||||
}
|
||||
catch(e) {
|
||||
errorlog({ where: "EmbeddedFileLoader.loadSceneFiles", error: e });
|
||||
}
|
||||
}
|
||||
}
|
||||
const files: FileData[][] = [];
|
||||
files.push([]);
|
||||
let batch = 0;
|
||||
|
||||
let equation;
|
||||
const equations = excalidrawData.getEquationEntries();
|
||||
while (!this.terminate && !(equation = equations.next()).done) {
|
||||
if(fileIDWhiteList && !fileIDWhiteList.has(equation.value[0])) continue;
|
||||
if (!excalidrawData.getEquation(equation.value[0]).isLoaded) {
|
||||
const latex = equation.value[1].latex;
|
||||
const data = await tex2dataURL(latex);
|
||||
if (data) {
|
||||
const fileData = {
|
||||
mimeType: data.mimeType,
|
||||
id: equation.value[0],
|
||||
dataURL: data.dataURL,
|
||||
created: data.created,
|
||||
size: data.size,
|
||||
hasSVGwithBitmap: false,
|
||||
shouldScale: true
|
||||
};
|
||||
files.push(fileData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(shouldRenderMermaid()) {
|
||||
const mermaidElements = getMermaidImageElements(excalidrawData.scene.elements);
|
||||
for(const element of mermaidElements) {
|
||||
if(this.terminate) {
|
||||
continue;
|
||||
}
|
||||
const data = getMermaidText(element);
|
||||
const result = await mermaidToExcalidraw(data, {fontSize: 20}, true);
|
||||
if(!result) {
|
||||
continue;
|
||||
}
|
||||
if(result?.files) {
|
||||
for (const key in result.files) {
|
||||
function* loadIterator():Generator<Promise<void>> {
|
||||
while (!(entry = entries.next()).done) {
|
||||
if(fileIDWhiteList && !fileIDWhiteList.has(entry.value[0])) continue;
|
||||
const embeddedFile: EmbeddedFile = entry.value[1];
|
||||
const id = entry.value[0];
|
||||
yield promiseTry(async () => {
|
||||
if(this.terminate) {
|
||||
return;
|
||||
}
|
||||
if (!embeddedFile.isLoaded(this.isDark)) {
|
||||
//debug({where:"EmbeddedFileLoader.loadSceneFiles",uid:this.uid,status:"embedded Files are not loaded"});
|
||||
const data = await this._getObsidianImage(embeddedFile, depth);
|
||||
if (data) {
|
||||
const fileData: FileData = {
|
||||
mimeType: data.mimeType,
|
||||
id: id,
|
||||
dataURL: data.dataURL,
|
||||
created: data.created,
|
||||
size: data.size,
|
||||
hasSVGwithBitmap: data.hasSVGwithBitmap,
|
||||
shouldScale: embeddedFile.shouldScale()
|
||||
};
|
||||
files[batch].push(fileData);
|
||||
/* try {
|
||||
addFiles([fileData], this.isDark, false);
|
||||
}
|
||||
catch(e) {
|
||||
errorlog({ where: "EmbeddedFileLoader.loadSceneFiles", error: e });
|
||||
}*/
|
||||
}
|
||||
} else if (embeddedFile.isSVGwithBitmap && (depth !== 0 || isThemeChange)) {
|
||||
//this will reload the image in light/dark mode when switching themes
|
||||
const fileData = {
|
||||
...result.files[key],
|
||||
id: element.fileId,
|
||||
created: Date.now(),
|
||||
hasSVGwithBitmap: false,
|
||||
shouldScale: true,
|
||||
size: await getImageSize(result.files[key].dataURL),
|
||||
mimeType: embeddedFile.mimeType,
|
||||
id: id,
|
||||
dataURL: embeddedFile.getImage(this.isDark) as DataURL,
|
||||
created: embeddedFile.mtime,
|
||||
size: embeddedFile.size,
|
||||
hasSVGwithBitmap: embeddedFile.isSVGwithBitmap,
|
||||
shouldScale: embeddedFile.shouldScale()
|
||||
};
|
||||
files.push(fileData);
|
||||
files[batch].push(fileData);
|
||||
/* try {
|
||||
addFiles([fileData], this.isDark, false);
|
||||
}
|
||||
catch(e) {
|
||||
errorlog({ where: "EmbeddedFileLoader.loadSceneFiles", error: e });
|
||||
}*/
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(result?.elements) {
|
||||
//handle case that mermaidToExcalidraw has implemented this type of diagram in the mean time
|
||||
const res = await this.getExcalidrawSVG({
|
||||
isDark: this.isDark,
|
||||
file: null,
|
||||
depth,
|
||||
inFile: null,
|
||||
hasSVGwithBitmap: false,
|
||||
elements: result.elements
|
||||
});
|
||||
if(res?.dataURL) {
|
||||
const size = await getImageSize(res.dataURL);
|
||||
const fileData:FileData = {
|
||||
mimeType: "image/svg+xml",
|
||||
id: element.fileId,
|
||||
dataURL: res.dataURL,
|
||||
created: Date.now(),
|
||||
hasSVGwithBitmap: res.hasSVGwithBitmap,
|
||||
size,
|
||||
shouldScale: true,
|
||||
};
|
||||
files.push(fileData);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let equationItem;
|
||||
const equations = excalidrawData.getEquationEntries();
|
||||
while (!(equationItem = equations.next()).done) {
|
||||
if(fileIDWhiteList && !fileIDWhiteList.has(equationItem.value[0])) continue;
|
||||
const equation = equationItem.value[1];
|
||||
const id = equationItem.value[0];
|
||||
yield promiseTry(async () => {
|
||||
if (this.terminate) {
|
||||
return;
|
||||
}
|
||||
if (!excalidrawData.getEquation(id).isLoaded) {
|
||||
const latex = equation.latex;
|
||||
const data = await tex2dataURL(latex);
|
||||
if (data) {
|
||||
const fileData = {
|
||||
mimeType: data.mimeType,
|
||||
id: id,
|
||||
dataURL: data.dataURL,
|
||||
created: data.created,
|
||||
size: data.size,
|
||||
hasSVGwithBitmap: false,
|
||||
shouldScale: true
|
||||
};
|
||||
files[batch].push(fileData);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(shouldRenderMermaid()) {
|
||||
const mermaidElements = getMermaidImageElements(excalidrawData.scene.elements);
|
||||
for(const element of mermaidElements) {
|
||||
yield promiseTry(async () => {
|
||||
if(this.terminate) {
|
||||
return;
|
||||
}
|
||||
const data = getMermaidText(element);
|
||||
const result = await mermaidToExcalidraw(data, {fontSize: 20}, true);
|
||||
if(!result) {
|
||||
return;
|
||||
}
|
||||
if(result?.files) {
|
||||
for (const key in result.files) {
|
||||
const fileData = {
|
||||
...result.files[key],
|
||||
id: element.fileId,
|
||||
created: Date.now(),
|
||||
hasSVGwithBitmap: false,
|
||||
shouldScale: true,
|
||||
size: await getImageSize(result.files[key].dataURL),
|
||||
};
|
||||
files[batch].push(fileData);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(result?.elements) {
|
||||
//handle case that mermaidToExcalidraw has implemented this type of diagram in the mean time
|
||||
if (this.terminate) {
|
||||
return;
|
||||
}
|
||||
const res = await this.getExcalidrawSVG({
|
||||
isDark: this.isDark,
|
||||
file: null,
|
||||
depth,
|
||||
inFile: null,
|
||||
hasSVGwithBitmap: false,
|
||||
elements: result.elements
|
||||
});
|
||||
if(res?.dataURL) {
|
||||
const size = await getImageSize(res.dataURL);
|
||||
const fileData:FileData = {
|
||||
mimeType: "image/svg+xml",
|
||||
id: element.fileId,
|
||||
dataURL: res.dataURL,
|
||||
created: Date.now(),
|
||||
hasSVGwithBitmap: res.hasSVGwithBitmap,
|
||||
size,
|
||||
shouldScale: true,
|
||||
};
|
||||
files[batch].push(fileData);
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const addFilesTimer = setInterval(() => {
|
||||
if(files[batch].length === 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
addFiles(files[batch], this.isDark, false);
|
||||
}
|
||||
catch(e) {
|
||||
errorlog({ where: "EmbeddedFileLoader.loadSceneFiles", error: e });
|
||||
}
|
||||
files.push([]);
|
||||
batch++;
|
||||
}, 1200);
|
||||
|
||||
const iterator = loadIterator.bind(this)();
|
||||
const concurency = 5;
|
||||
await new PromisePool(iterator, concurency).all();
|
||||
|
||||
clearInterval(addFilesTimer);
|
||||
|
||||
this.emptyPDFDocsMap();
|
||||
if (this.terminate) {
|
||||
@@ -734,7 +779,7 @@ export class EmbeddedFilesLoader {
|
||||
//debug({where:"EmbeddedFileLoader.loadSceneFiles",uid:this.uid,status:"add Files"});
|
||||
try {
|
||||
//in try block because by the time files are loaded the user may have closed the view
|
||||
addFiles(files, this.isDark, true);
|
||||
addFiles(files[batch], this.isDark, true);
|
||||
} catch (e) {
|
||||
errorlog({ where: "EmbeddedFileLoader.loadSceneFiles", error: e });
|
||||
}
|
||||
|
||||
@@ -754,7 +754,7 @@ export class ExcalidrawData {
|
||||
notice.noticeEl.oncontextmenu = () => {
|
||||
displayFontMessage(this.app);
|
||||
}
|
||||
},2000);
|
||||
},5000);
|
||||
await loadSceneFonts(this.scene.elements);
|
||||
clearTimeout(timer);
|
||||
|
||||
|
||||
1
src/ExcalidrawLib.d.ts
vendored
1
src/ExcalidrawLib.d.ts
vendored
@@ -6,6 +6,7 @@ import { FontMetadata } from "@zsviczian/excalidraw/types/excalidraw/fonts/metad
|
||||
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";
|
||||
import ExcalidrawPlugin from "./main";
|
||||
|
||||
type EmbeddedLink =
|
||||
| ({
|
||||
|
||||
@@ -1575,6 +1575,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
if(!this.plugin) {
|
||||
return;
|
||||
}
|
||||
await this.plugin.awaitInit();
|
||||
//implemented to overcome issue that activeLeafChangeEventHandler is not called when view is initialized from a saved workspace, since Obsidian 1.6.0
|
||||
let counter = 0;
|
||||
while(counter++<50 && (!Boolean(this?.plugin?.activeLeafChangeEventHandler) || !Boolean(this.canvasNodeFactory))) {
|
||||
@@ -2245,6 +2246,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
//I am using last loaded file to control when the view reloads.
|
||||
//It seems text file view gets the modified file event after sync before the modifyEventHandler in main.ts
|
||||
//reload can only be triggered via reload()
|
||||
await this.plugin.awaitInit();
|
||||
if(this.lastLoadedFile === this.file) return;
|
||||
this.isLoaded = false;
|
||||
if(!this.file) return;
|
||||
@@ -2275,6 +2277,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
if(!this?.app) {
|
||||
return;
|
||||
}
|
||||
await this.plugin.awaitInit();
|
||||
let counter = 0;
|
||||
while ((!this.file || !this.plugin.fourthFontLoaded) && counter++<50) await sleep(50);
|
||||
if(!this.file) return;
|
||||
@@ -3851,12 +3854,14 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
return;
|
||||
}
|
||||
|
||||
//dobule click
|
||||
const now = Date.now();
|
||||
if ((now - this.doubleClickTimestamp) < 600 && (now - this.doubleClickTimestamp) > 40) {
|
||||
this.identifyElementClicked();
|
||||
if(this.plugin.settings.doubleClickLinkOpenViewMode) {
|
||||
//dobule click
|
||||
const now = Date.now();
|
||||
if ((now - this.doubleClickTimestamp) < 600 && (now - this.doubleClickTimestamp) > 40) {
|
||||
this.identifyElementClicked();
|
||||
}
|
||||
this.doubleClickTimestamp = now;
|
||||
}
|
||||
this.doubleClickTimestamp = now;
|
||||
return;
|
||||
}
|
||||
if (p.button === "up") {
|
||||
@@ -5851,7 +5856,6 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
renderWebview: DEVICE.isDesktop,
|
||||
renderEmbeddable: this.renderEmbeddable.bind(this),
|
||||
renderMermaid: shouldRenderMermaid,
|
||||
obsidianHostPlugin: new WeakRef(this.plugin),
|
||||
showDeprecatedFonts: true,
|
||||
},
|
||||
this.renderCustomActionsMenu(),
|
||||
@@ -5874,6 +5878,7 @@ export default class ExcalidrawView extends TextFileView implements HoverParent{
|
||||
}
|
||||
) {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.instantiateExcalidraw, "ExcalidrawView.instantiateExcalidraw", initdata);
|
||||
await this.plugin.awaitInit();
|
||||
while(!this.semaphores.scriptsReady) {
|
||||
await sleep(50);
|
||||
}
|
||||
|
||||
@@ -353,7 +353,8 @@ const getIMG = async (
|
||||
);
|
||||
|
||||
const cacheReady = imageCache.isReady();
|
||||
|
||||
|
||||
await plugin.awaitInit();
|
||||
switch (plugin.settings.previewImageType) {
|
||||
case PreviewImageType.PNG: {
|
||||
const img = createEl("img");
|
||||
|
||||
@@ -82,7 +82,7 @@ export const obsidianToExcalidrawMap: { [key: string]: string } = {
|
||||
};
|
||||
|
||||
|
||||
export const {
|
||||
export let {
|
||||
sceneCoordsToViewportCoords,
|
||||
viewportCoordsToSceneCoords,
|
||||
determineFocusDistance,
|
||||
@@ -106,7 +106,34 @@ export const {
|
||||
loadSceneFonts,
|
||||
} = excalidrawLib;
|
||||
|
||||
export function updateExcalidrawLib() {
|
||||
({
|
||||
sceneCoordsToViewportCoords,
|
||||
viewportCoordsToSceneCoords,
|
||||
determineFocusDistance,
|
||||
intersectElementWithLine,
|
||||
getCommonBoundingBox,
|
||||
getMaximumGroups,
|
||||
measureText,
|
||||
getLineHeight,
|
||||
wrapText,
|
||||
getFontString,
|
||||
getBoundTextMaxWidth,
|
||||
exportToSvg,
|
||||
exportToBlob,
|
||||
mutateElement,
|
||||
restore,
|
||||
mermaidToExcalidraw,
|
||||
getFontFamilyString,
|
||||
getContainerElement,
|
||||
refreshTextDimensions,
|
||||
getCSSFontDefinition,
|
||||
loadSceneFonts,
|
||||
} = excalidrawLib);
|
||||
}
|
||||
|
||||
export const FONTS_STYLE_ID = "excalidraw-custom-fonts";
|
||||
export const CJK_STYLE_ID = "excalidraw-cjk-fonts";
|
||||
|
||||
export function JSON_parse(x: string): any {
|
||||
return JSON.parse(x.replaceAll("[", "["));
|
||||
|
||||
44
src/dialogs/ExcalidrawLoading.ts
Normal file
44
src/dialogs/ExcalidrawLoading.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { FileView, TextFileView, View, WorkspaceLeaf } from "obsidian";
|
||||
import ExcalidrawPlugin from "src/main";
|
||||
import { setExcalidrawView } from "src/utils/ObsidianUtils";
|
||||
|
||||
export default class ExcalidrawLoading extends FileView {
|
||||
constructor(leaf: WorkspaceLeaf, private plugin: ExcalidrawPlugin) {
|
||||
super(leaf);
|
||||
this.switchToeExcalidraw();
|
||||
this.displayLoadingText();
|
||||
}
|
||||
|
||||
public onload() {
|
||||
super.onload();
|
||||
this.displayLoadingText();
|
||||
}
|
||||
|
||||
private async switchToeExcalidraw() {
|
||||
await this.plugin.awaitInit();
|
||||
setExcalidrawView(this.leaf);
|
||||
}
|
||||
|
||||
getViewType(): string {
|
||||
return "excalidra-loading";
|
||||
}
|
||||
|
||||
getDisplayText() {
|
||||
return "Loading Excalidraw... " + (this.file?.basename ?? "");
|
||||
}
|
||||
|
||||
private displayLoadingText() {
|
||||
// Create a div element for displaying the text
|
||||
const loadingTextEl = this.contentEl.createEl("div", {
|
||||
text: this.getDisplayText()
|
||||
});
|
||||
|
||||
// Apply styling to center the text
|
||||
loadingTextEl.style.display = "flex";
|
||||
loadingTextEl.style.alignItems = "center";
|
||||
loadingTextEl.style.justifyContent = "center";
|
||||
loadingTextEl.style.height = "100%";
|
||||
loadingTextEl.style.fontSize = "1.5em"; // Adjust size as needed
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
import { TAG_AUTOEXPORT, TAG_MDREADINGMODE, TAG_PDFEXPORT } from "src/constants/constSettingsTags";
|
||||
import { labelALT, labelCTRL, labelMETA, labelSHIFT } from "src/utils/ModifierkeyHelper";
|
||||
|
||||
const CJK_FONTS = "CJK Fonts";
|
||||
// English
|
||||
export default {
|
||||
// main.ts
|
||||
@@ -97,6 +98,8 @@ export default {
|
||||
RESET_IMG_ASPECT_RATIO: "Reset selected image element aspect ratio",
|
||||
TEMPORARY_DISABLE_AUTOSAVE: "Disable autosave until next time Obsidian starts (only set this if you know what you are doing)",
|
||||
TEMPORARY_ENABLE_AUTOSAVE: "Enable autosave",
|
||||
FONTS_LOADED: "Excalidraw: CJK Fonts loaded",
|
||||
FONTS_LOAD_ERROR: "Excalidraw: Could not find CJK Fonts in the assets folder\n",
|
||||
|
||||
//ExcalidrawView.ts
|
||||
NO_SEARCH_RESULT: "Didn't find a matching element in the drawing",
|
||||
@@ -229,15 +232,6 @@ 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. ` +
|
||||
@@ -440,6 +434,7 @@ FILENAME_HEAD: "Filename",
|
||||
LONG_PRESS_DESKTOP_DESC: "Long press delay in milliseconds to open an Excalidraw Drawing embedded in a Markdown file. ",
|
||||
LONG_PRESS_MOBILE_NAME: "Long press to open mobile",
|
||||
LONG_PRESS_MOBILE_DESC: "Long press delay in milliseconds to open an Excalidraw Drawing embedded in a Markdown file. ",
|
||||
DOUBLE_CLICK_LINK_OPEN_VIEW_MODE: "Allow double-click to open links in view mode",
|
||||
|
||||
FOCUS_ON_EXISTING_TAB_NAME: "Focus on Existing Tab",
|
||||
FOCUS_ON_EXISTING_TAB_DESC: "When opening a link, Excalidraw will focus on the existing tab if the file is already open. " +
|
||||
@@ -756,6 +751,8 @@ FILENAME_HEAD: "Filename",
|
||||
"Enabling this feature simplifies the use of Excalidraw front matter properties, allowing you to leverage many powerful settings. If you prefer not to load these properties automatically, " +
|
||||
"you can disable this feature, but you will need to manually remove any unwanted properties from the suggester. " +
|
||||
"Note that turning on this setting requires restarting the plugin as properties are loaded at startup.",
|
||||
FONTS_HEAD: "Fonts",
|
||||
FONTS_DESC: "Configure local fontfaces and downloaded CJK fonts for Excalidraw.",
|
||||
CUSTOM_FONT_HEAD: "Local font",
|
||||
ENABLE_FOURTH_FONT_NAME: "Enable local font option",
|
||||
ENABLE_FOURTH_FONT_DESC:
|
||||
@@ -769,6 +766,20 @@ FILENAME_HEAD: "Filename",
|
||||
"If no file is selected, Excalidraw will default to the Virgil font. " +
|
||||
"For optimal performance, it is recommended to use a .woff2 file, as Excalidraw will encode only the necessary glyphs when exporting images to SVG. " +
|
||||
"Other font formats will embed the entire font in the exported file, potentially resulting in significantly larger file sizes.",
|
||||
OFFLINE_CJK_NAME: "Offline CJK font support",
|
||||
OFFLINE_CJK_DESC:
|
||||
`<strong>Changes you make here will only take effect after restarting Obsidian.</strong><br>
|
||||
Excalidraw.com offers handwritten CJK fonts. By default these fonts are not included in the plugin locally, but are served from the Internet.
|
||||
If you prefer to keep Excalidraw fully local, allowing it to work without Internet access 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 files from GitHub</a>.
|
||||
After downloading, unzip the contents into a folder within your Vault.<br>
|
||||
Pre-loading fonts will impact startup performance. For this reason you can select which fonts to load.`,
|
||||
CJK_ASSETS_FOLDER_NAME: "CJK Font Folder (cAsE sENsiTIvE!)",
|
||||
CJK_ASSETS_FOLDER_DESC: `You can set the location of the CJK fonts folder here. For example, you may choose to place it under <code>Excalidraw/CJK Fonts</code>.<br><br>
|
||||
<strong>Important:</strong> Do not set this folder to the Vault root! Do not put other fonts 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".`,
|
||||
LOAD_CHINESE_FONTS_NAME: "Load Chinese fonts from file at startup",
|
||||
LOAD_JAPANESE_FONTS_NAME: "Load Japanese fonts from file at startup",
|
||||
LOAD_KOREAN_FONTS_NAME: "Load Korean fonts frome file at startup",
|
||||
SCRIPT_SETTINGS_HEAD: "Settings for installed Scripts",
|
||||
SCRIPT_SETTINGS_DESC: "Some of the Excalidraw Automate Scripts include settings. Settings are organized by script. Settings will only become visible in this list after you have executed the newly downloaded script once.",
|
||||
TASKBONE_HEAD: "Taskbone Optical Character Recogntion",
|
||||
@@ -831,9 +842,8 @@ FILENAME_HEAD: "Filename",
|
||||
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.
|
||||
I've moved the CJK fonts out of the plugin's <code>main.js</code>. CJK fonts will be loaded from the internet by default.
|
||||
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.
|
||||
@@ -841,7 +851,7 @@ FILENAME_HEAD: "Filename",
|
||||
<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>Unzip and copy files into a Vault folder (default: <code>Excalidraw/${CJK_FONTS}</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>
|
||||
|
||||
@@ -1,3 +1,859 @@
|
||||
// русский
|
||||
import {
|
||||
DEVICE,
|
||||
FRONTMATTER_KEYS,
|
||||
} from "src/constants/constants";
|
||||
import { TAG_AUTOEXPORT, TAG_MDREADINGMODE, TAG_PDFEXPORT } from "src/constants/constSettingsTags";
|
||||
import { labelALT, labelCTRL, labelMETA, labelSHIFT } from "src/utils/ModifierkeyHelper";
|
||||
|
||||
export default {};
|
||||
// русский
|
||||
export default {
|
||||
// main.ts
|
||||
CONVERT_URL_TO_FILE: "Сохранить изображение из URL в локальный файл",
|
||||
UNZIP_CURRENT_FILE: "Распаковать текущий файл Excalidraw",
|
||||
ZIP_CURRENT_FILE: "Сжать текущий файл Excalidraw",
|
||||
PUBLISH_SVG_CHECK: "Obsidian Publish: Поиск устаревших экспортированных SVG и PNG-файлов",
|
||||
EMBEDDABLE_PROPERTIES: "Свойства встраиваемых элементов",
|
||||
EMBEDDABLE_RELATIVE_ZOOM: "Масштабирование выбранных встраиваемых элементов до 100% относительно текущего масштаба холста",
|
||||
OPEN_IMAGE_SOURCE: "Открыть чертеж Excalidraw",
|
||||
INSTALL_SCRIPT: "Установите скрипт",
|
||||
UPDATE_SCRIPT: "Доступно обновление - нажмите для установки",
|
||||
CHECKING_SCRIPT: "Проверка на наличие новой версии - Нажмите для переустановки",
|
||||
UNABLETOCHECK_SCRIPT: "Проверка обновления не удалась - Нажмите, чтобы переустановить",
|
||||
UPTODATE_SCRIPT: "Скрипт обновлен - Нажмите для переустановки",
|
||||
OPEN_AS_EXCALIDRAW: "Открыть как рисунок Excalidraw",
|
||||
TOGGLE_MODE: "Переключение между режимами Excalidraw и Markdown",
|
||||
CONVERT_NOTE_TO_EXCALIDRAW: "Конвертировать заметку в формате Markdown в Excalidraw Drawing",
|
||||
CONVERT_EXCALIDRAW: "Преобразование файлов *.excalidraw в файлы *.md",
|
||||
CREATE_NEW: "Создать новый чертеж",
|
||||
CONVERT_FILE_KEEP_EXT: "*.excalidraw => *.excalidraw.md",
|
||||
CONVERT_FILE_REPLACE_EXT: "*.excalidraw => *.md (совместимость с Logseq)",
|
||||
DOWNLOAD_LIBRARY: "Экспорт библиотеки трафаретов в файл *.excalidrawlib",
|
||||
OPEN_EXISTING_NEW_PANE: "Открыть существующий чертеж - В НОВОЙ ПАНЕЛИ",
|
||||
OPEN_EXISTING_ACTIVE_PANE: "Открыть существующий чертеж - В ТЕКУЩЕЙ АКТИВНОЙ ПАНЕЛИ",
|
||||
TRANSCLUDE: "Вставить чертеж",
|
||||
TRANSCLUDE_MOST_RECENT: "Вставка последнего отредактированного рисунка",
|
||||
TOGGLE_LEFTHANDED_MODE: "Переключить левосторонний режим",
|
||||
TOGGLE_SPLASHSCREEN: "Показывать заставку в новых чертежах",
|
||||
FLIP_IMAGE: "Открыть фоновым рисуноком выбранное изображения excalidraw",
|
||||
NEW_IN_NEW_PANE: "Создать новый рисунок - В СОСЕДНЕМ ОКНЕ",
|
||||
NEW_IN_NEW_TAB: "Создать новый рисунок - В НОВОЙ ТАБЛИЦЕ",
|
||||
NEW_IN_ACTIVE_PANE: "Создать новый рисунок - В ТЕКУЩЕМ АКТИВНОМ ОКНЕ",
|
||||
NEW_IN_POPOUT_WINDOW: "Создать новый рисунок - В ОТКРЫВАЮЩЕМСЯ ОКНЕ",
|
||||
NEW_IN_NEW_PANE_EMBED: "Создание нового рисунка - В СОСЕДНЕМ ОКНЕ - и вставка в активный документ",
|
||||
NEW_IN_NEW_TAB_EMBED: "Создать новый чертеж - В НОВОЙ ТАБЛИЦЕ - и вставить в активный документ",
|
||||
NEW_IN_ACTIVE_PANE_EMBED: "Создать новый рисунок - В ТЕКУЩЕМ АКТИВНОМ ОКНЕ - и вставить в активный документ",
|
||||
NEW_IN_POPOUT_WINDOW_EMBED: "Создать новый рисунок - В ОТКРЫВАЮЩЕМСЯ ОКНЕ - и вставить в активный документ",
|
||||
TOGGLE_LOCK: "Переключение текстового элемента между режимами редактирования RAW (без обработки) и PREVIEW (просмотр)",
|
||||
DELETE_FILE: "Удалить выбранное изображение или файл Markdown из Obsidian хранилища",
|
||||
COPY_ELEMENT_LINK: "Скопировать [[ссылку]] для выбранного элемента(ов)",
|
||||
COPY_DRAWING_LINK: "Скопировать ![[ссылку на вставку]] для этого рисунка",
|
||||
INSERT_LINK_TO_ELEMENT: `Копирование [[ссылка]] для выбранного элемента в буфер обмена. ${labelCTRL()}+CLICK для копирования ссылки 'group='. ${labelSHIFT()}+CLICK для копирования ссылки 'area='.`,
|
||||
INSERT_LINK_TO_ELEMENT_GROUP: "Скопируйте 'group=' ![[ссылка]] для выбранного элемента в буфер обмена.",
|
||||
INSERT_LINK_TO_ELEMENT_AREA: "Скопировать 'area=' ![[ссылка]] для выбранного элемента в буфер обмена.",
|
||||
INSERT_LINK_TO_ELEMENT_FRAME: "Скопировать 'frame=' ![[ссылка]] для выбранного элемента в буфер обмена.",
|
||||
INSERT_LINK_TO_ELEMENT_FRAME_CLIPPED: "Скопировать 'clippedframe=' ![[ссылка]] для выбранного элемента в буфер обмена.",
|
||||
INSERT_LINK_TO_ELEMENT_NORMAL: "Скопировать [[ссылка]] для выбранного элемента в буфер обмена.",
|
||||
INSERT_LINK_TO_ELEMENT_ERROR: "Выбор отдельного элемента в сцене",
|
||||
INSERT_LINK_TO_ELEMENT_READY: "Ссылка ГОТОВА и доступна в буфере обмена",
|
||||
INSERT_LINK: "Вставить ссылку на файл",
|
||||
INSERT_COMMAND: "Вставить команду Obsidian в качестве ссылки",
|
||||
INSERT_IMAGE: "Вставить изображение или рисунок Excalidraw из вашего хранилища",
|
||||
IMPORT_SVG: "Импорт SVG-файла в виде штрихов Excalidraw (поддержка SVG ограничена, TEXT в настоящее время не поддерживается)",
|
||||
IMPORT_SVG_CONTEXTMENU: "Преобразование SVG в штрихи - с ограничениями",
|
||||
INSERT_MD: "Вставка файла markdown из хранилища",
|
||||
INSERT_PDF: "Вставить PDF-файл из хранилища",
|
||||
UNIVERSAL_ADD_FILE: "Вставка ЛЮБОГО файла",
|
||||
INSERT_CARD: "Добавить сноски",
|
||||
CONVERT_CARD_TO_FILE: "Переместить сноску в файл",
|
||||
ERROR_TRY_AGAIN: "Пожалуйста, попробуйте еще раз.",
|
||||
PASTE_CODEBLOCK: "Вставить блок кода",
|
||||
INSERT_LATEX: `Вставьте формулу LaTeX (например, \\\binom{n}{k} = \\\frac{n!}{k!(n-k)!}).`,
|
||||
ENTER_LATEX: "Введите правильное выражение LaTeX",
|
||||
READ_RELEASE_NOTES: "Прочитать последние заметки о выпуске",
|
||||
RUN_OCR: "OCR полного чертежа: Захват текста из freedraw + изображения в буфер обмена и doc.props",
|
||||
RERUN_OCR: "Повторный запуск полного чертежа OCR: Захват текста из freedraw + изображения в буфер обмена и doc.props",
|
||||
RUN_OCR_ELEMENTS: "OCR выделенных элементов: Захват текста из freedraw + изображения в буфер обмена",
|
||||
TRAY_MODE: "Переключение панели свойств в трей-режим",
|
||||
SEARCH: "Поиск текста на чертеже",
|
||||
CROP_PAGE: "Обрезка и маскирование выделенной страницы",
|
||||
CROP_IMAGE: "Обрезка и маскирование изображения",
|
||||
ANNOTATE_IMAGE : "Аннотирование изображения в Excalidraw",
|
||||
INSERT_ACTIVE_PDF_PAGE_AS_IMAGE: "Вставка активной страницы PDF в качестве изображения",
|
||||
RESET_IMG_TO_100: "Установить размер выбранного элемента изображения на 100% от исходного",
|
||||
RESET_IMG_ASPECT_RATIO: "Сбросить соотношение сторон выбранного элемента изображения",
|
||||
TEMPORARY_DISABLE_AUTOSAVE: "Отключить автосохранение до следующего запуска Obsidian (устанавливайте этот параметр, только если вы знаете, что делаете)",
|
||||
TEMPORARY_ENABLE_AUTOSAVE: "Включить автосохранение",
|
||||
|
||||
//ExcalidrawView.ts
|
||||
NO_SEARCH_RESULT: "Не удалось найти подходящий элемент на чертеже",
|
||||
FORCE_SAVE_ABORTED: "Принудительное сохранение прервано, поскольку идет процесс сохранения",
|
||||
LINKLIST_SECOND_ORDER_LINK: "Ссылка второго порядка",
|
||||
MARKDOWN_EMBED_CUSTOMIZE_LINK_PROMPT_TITLE: "Настройка ссылки на встроенный файл",
|
||||
MARKDOWN_EMBED_CUSTOMIZE_LINK_PROMPT: "Не добавляйте [[квадратные скобки]] вокруг имени файла! <br>" +
|
||||
"При редактировании ссылок на изображения в формате markdown-страниц следуйте этому формату: <mark>filename#^blockref|WIDTHxMAXHEIGHT</mark><br>" +
|
||||
"Вы можете привязать изображения Excalidraw к 100% их размера, добавив <code>|100%</code> в конец ссылки.<br>" +
|
||||
"Вы можете изменить страницу PDF, изменив <code>#page=1</code> на <code>#page=2</code> и т.д.<br>" +
|
||||
"Значения обрезки прямоугольника PDF: <code>left, bottom, right, top</code>. Например: <code>#rect=0,0,500,500</code><br>",
|
||||
FRAME_CLIPPING_ENABLED: "Рендеринг кадров: Включено",
|
||||
FRAME_CLIPPING_DISABLED: "Рендеринг кадров: Отключено",
|
||||
ARROW_BINDING_INVERSE_MODE: "Инвертированный режим: Привязка стрелок по умолчанию теперь отключена. Используйте CTRL/CMD, чтобы временно включить привязку, когда это необходимо.",
|
||||
ARROW_BINDING_NORMAL_MODE: "Обычный режим: Привязка стрелок теперь включена. Используйте CTRL/CMD, чтобы временно отключить привязку при необходимости.",
|
||||
EXPORT_FILENAME_PROMPT: "Пожалуйста, укажите имя файла",
|
||||
EXPORT_FILENAME_PROMPT_PLACEHOLDER: "имя файла, оставьте пустым, чтобы отменить действие",
|
||||
WARNING_SERIOUS_ERROR: "ПРЕДУПРЕЖДЕНИЕ: Excalidraw столкнулся с неизвестной проблемой!\n\n" +
|
||||
"Есть риск, что последние изменения не будут сохранены.\n\n" +
|
||||
"На всякий случай...\n" +
|
||||
"1) Выберите рисунок с помощью CTRL/CMD+A и создайте копию с помощью CTRL/CMD+C.\n" +
|
||||
"2) Затем создайте пустой чертеж в новой панели, нажав CTRL/CMD+кнопку ленты Excalidraw,\n" +
|
||||
"3) и вставьте свою работу в новый документ с помощью CTRL/CMD+V.",
|
||||
ARIA_LABEL_TRAY_MODE: "Трей-Режим предлагает альтернативный, более просторный холст",
|
||||
MASK_FILE_NOTICE: "Это файл маски. Он используется для кадрирования изображений и маскирования частей изображения. Нажмите и удерживайте уведомление, чтобы открытьe help video.",
|
||||
INSTALL_SCRIPT_BUTTON: "Установка или обновление скриптов Excalidraw",
|
||||
OPEN_AS_MD: "Открыть как Markdown",
|
||||
EXPORT_IMAGE: `Экспорт изображения`,
|
||||
OPEN_LINK: "Открыть выделенный текст как ссылку\n(SHIFT+CLICK для открытия в новой панели)",
|
||||
EXPORT_EXCALIDRAW: "Экспорт в файл .Excalidraw",
|
||||
LINK_BUTTON_CLICK_NO_TEXT: "Выберите элемент, содержащий внутреннюю или внешнюю ссылку.\n",
|
||||
LINEAR_ELEMENT_LINK_CLICK_ERROR:
|
||||
"Ссылки на элементы со стрелками и линиями нельзя перемещать с помощью " + labelCTRL() + " + КЛИКА по элементу, поскольку при этом также активируется редактор строк.\n" +
|
||||
"Чтобы открыть ссылку, воспользуйтесь контекстным меню правой кнопки мыши или щелкните индикатор ссылки в правом верхнем углу элемента.\n",
|
||||
FILENAME_INVALID_CHARS: 'Имя файла не может содержать ни одного из следующих символов: * " \\ < > : | ? #',
|
||||
FORCE_SAVE: "Сохранить (также будут обновлены включения)",
|
||||
RAW: "Переход в режим PREVIEW (влияет только на текстовые элементы со ссылками или включениями)",
|
||||
PARSED: "Переход в режим RAW (влияет только на текстовые элементы со ссылками или включениями)",
|
||||
NOFILE: "Excalidraw (без файла)",
|
||||
COMPATIBILITY_MODE: "Файл *.excalidraw открыт в режиме совместимости. Конвертируйте в новый формат для полной функциональности плагина.",
|
||||
CONVERT_FILE: "Преобразование в новый формат",
|
||||
BACKUP_AVAILABLE: "Мы столкнулись с ошибкой при загрузке вашего рисунка. Это могло произойти, если Obsidian неожиданно закрылся во время операции сохранения. Например, если вы случайно закрыли Obsidian на своем мобильном устройстве во время сохранения.<br><br><b>ХОРОШАЯ НОВОСТЬ:</b> К счастью, доступна локальная резервная копия. Однако учтите, что если вы последний раз изменяли этот рисунок на другом устройстве (например, на планшете), а сейчас находитесь на рабочем столе, то на другом устройстве, скорее всего, имеется более свежая резервная копия.<br><br>Я рекомендую сначала попробовать открыть рисунок на другом устройстве и восстановить резервную копию из его локального хранилища.<br><br>Хотите загрузить резервную копию?",
|
||||
BACKUP_RESTORED: "Резервная копия восстановлена",
|
||||
CACHE_NOT_READY: "Приношу извинения за неудобства, но при загрузке вашего файла произошла ошибка.<br><br><mark>Немного терпения может сэкономить вам массу времени...</mark><br><br>Плагин имеет резервный кэш, но похоже, что вы только что запустили Obsidian. Инициализация резервного кэша может занять некоторое время, обычно до минуты или больше, в зависимости от производительности вашего устройства. Вы получите уведомление в правом верхнем углу, когда инициализация кэша будет завершена.<br><br>Нажмите OK, чтобы попытаться загрузить файл снова и проверить, завершилась ли инициализация кэша. Если за этим сообщением вы видите абсолютно пустой файл, я рекомендую подождать, пока кэш резервного копирования будет готов, прежде чем продолжать. Кроме того, вы можете выбрать «Отмена», чтобы вручную исправить файл.<br>",
|
||||
OBSIDIAN_TOOLS_PANEL: "Панель инструментов Obsidian",
|
||||
ERROR_SAVING_IMAGE: "При получении изображения произошла неизвестная ошибка. Возможно, по какой-то причине изображение недоступно или отклонен запрос на получение от Obsidian",
|
||||
WARNING_PASTING_ELEMENT_AS_TEXT: "ВСТАВКА ЭЛЕМЕНТОВ EXCALIDRAW В КАЧЕСТВЕ ТЕКСТОВОГО ЭЛЕМЕНТА ЗАПРЕЩЕНА",
|
||||
USE_INSERT_FILE_MODAL: "Используйте 'Вставить любой файл', чтобы вставить заметку в формате markdown",
|
||||
RECURSIVE_INSERT_ERROR: "Нельзя рекурсивно вставлять часть изображения в одно и то же изображение, так как это приведет к созданию бесконечного цикла",
|
||||
CONVERT_TO_MARKDOWN: "Преобразовать в файл...",
|
||||
SELECT_TEXTELEMENT_ONLY: "Выбрать только текстовый элемент (не контейнер)",
|
||||
REMOVE_LINK: "Удалить ссылку на текстовый элемент",
|
||||
LASER_ON: "Включить лазерный указатель",
|
||||
LASER_OFF: "Отключить лазерный указатель",
|
||||
WELCOME_RANK_NEXT: "Больше рисунков до следующего ранга!",
|
||||
WELCOME_RANK_LEGENDARY: "Вы на вершине. Продолжайте быть легендарным!",
|
||||
WELCOME_COMMAND_PALETTE: 'Введите «Excalidraw» в палитре коман',
|
||||
WELCOME_OBSIDIAN_MENU: "Изучите меню Обсидиана в правом верхнем углу",
|
||||
WELCOME_SCRIPT_LIBRARY: "Посетите библиотеку сценариев",
|
||||
WELCOME_HELP_MENU: "Найдите помощь в гамбургер-меню",
|
||||
WELCOME_YOUTUBE_ARIA: "Канал Visual PKM на YouTube",
|
||||
WELCOME_YOUTUBE_LINK: "Загляните на YouTube-канал Visual PKM.",
|
||||
WELCOME_DISCORD_ARIA: "Присоединяйтесь к серверу Discord",
|
||||
WELCOME_DISCORD_LINK: "Присоединяйтесь к серверу Discord",
|
||||
WELCOME_TWITTER_ARIA: "Следите за мной в Twitter",
|
||||
WELCOME_TWITTER_LINK: "Следите за мной в Twitter",
|
||||
WELCOME_LEARN_ARIA: "Изучение Visual PKM",
|
||||
WELCOME_LEARN_LINK: "Запишитесь на семинар по визуальному мышлению",
|
||||
WELCOME_DONATE_ARIA: "Пожертвовать на поддержку Excalidraw-Obsidian",
|
||||
WELCOME_DONATE_LINK: 'Скажите «Спасибо» и поддержите плагин.',
|
||||
SAVE_IS_TAKING_LONG: "Сохранение предыдущего файла занимает много времени. Пожалуйста, подождите...",
|
||||
SAVE_IS_TAKING_VERY_LONG: "Для повышения производительности рассмотрите возможность разделения больших рисунков на несколько файлов меньшего размера.",
|
||||
|
||||
//settings.ts
|
||||
RELEASE_NOTES_NAME: "Отображение информации о выпуске после обновления",
|
||||
RELEASE_NOTES_DESC:
|
||||
"<b><u>Переключатель ВКЛ:</u></b> Отображение информации о выпуске при каждом обновлении Excalidraw до новой версии.<br>" +
|
||||
"<b><u>Переключатель ВЫКЛ:</u></b> Тихий режим. Вы все еще можете прочитать заметки о выпуске на <a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/releases'>GitHub</a>.",
|
||||
NEWVERSION_NOTIFICATION_NAME: "Уведомление об обновлении плагина",
|
||||
NEWVERSION_NOTIFICATION_DESC:
|
||||
"<b><u>Переключатель ВКЛ:</u></b> Показывайте уведомление о появлении новой версии плагина.<br>" +
|
||||
"<b><u>Переключатель ВЫКЛ:</u></b> Тихий режим. Вам необходимо проверить обновления плагинов в разделе Community Plugins.",
|
||||
|
||||
BASIC_HEAD: "Основные",
|
||||
BASIC_DESC: `В настройках "Основные" можно настроить такие параметры, как отображение заметок о выпуске после обновлений, получение уведомлений об обновлении плагинов, установка местоположения по умолчанию для новых чертежей, указание папки Excalidraw для вставки чертежей в активные документы, определение файла шаблона Excalidraw и указание папки сценария Excalidraw Automate для управления сценариями автоматизации.`,
|
||||
FOLDER_NAME: "Папка Excalidraw",
|
||||
FOLDER_DESC: "Место по умолчанию для новых чертежей. Если пусто, чертежи будут создаваться в корне хранилища.",
|
||||
CROP_PREFIX_NAME: "Префикс файла обрезки",
|
||||
CROP_PREFIX_DESC:
|
||||
"Первая часть имени файла для новых чертежей, созданных при обрезке изображения. " +
|
||||
"Если пусто, то по умолчанию будет использоваться значение 'cropped_'.",
|
||||
ANNOTATE_PREFIX_NAME: "Префикс файла аннотации",
|
||||
ANNOTATE_PREFIX_DESC:
|
||||
"Первая часть имени файла для новых чертежей, созданных при аннотировании изображения. " +
|
||||
"Если пусто, то по умолчанию будет использоваться 'annotated_'.",
|
||||
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_FOLDER_DESC: "Место по умолчанию для новых чертежей, созданных при обрезке изображения. Если папка пуста, рисунки будут создаваться в соответствии с настройками вложений Хранилища.",
|
||||
ANNOTATE_FOLDER_NAME: "Папка с файлами аннотаций изображений",
|
||||
ANNOTATE_FOLDER_DESC: "Место по умолчанию для новых рисунков, создаваемых при аннотировании изображения. Если пусто, рисунки будут создаваться в соответствии с настройками вложений Хранилища.",
|
||||
FOLDER_EMBED_NAME: "Использовать папку Excalidraw при встраивании рисунка в активный документ",
|
||||
FOLDER_EMBED_DESC:
|
||||
"Определите, в какую папку поместить новый вставленный рисунок " +
|
||||
"при использовании действия палитры команд: 'Создать новый рисунок и вставить в активный документ'.<br>" +
|
||||
"<b><u>Переключатель ВКЛ:</u></b> Используйте папку Excalidraw<br><b><u>Переключатель ВЫКЛ:</u></b> Используйте папку вложений, определенную в настройках Obsidian.",
|
||||
TEMPLATE_NAME: "Файл или папка шаблона Excalidraw",
|
||||
TEMPLATE_DESC:
|
||||
"Полный путь к файлу или папке с шаблоном Excalidraw.<br>" +
|
||||
"<b>Файл шаблона:</b>Например: Если ваш шаблон находится в папке Excalidraw по умолчанию и его имя " +
|
||||
"Template.md, настройка должна быть: Excalidraw/Template.md (или только Excalidraw/Template - вы можете опустить .md расширение файла). " +
|
||||
"Если вы используете Excalidraw в режиме совместимости, то ваш шаблон также должен быть устаревшим файлом Excalidraw " +
|
||||
"такие как Excalidraw/Template.excalidraw. <br><b>Папка с шаблонами:</b> Вы также можете задать папку в качестве шаблона. " +
|
||||
"В этом случае вам будет предложено выбрать шаблон при создании нового чертежа.<br>" +
|
||||
"<b>Совет профи:</b> Если вы используете плагин Obsidian Templater, вы можете добавить код Templater в различные Excalidraw " +
|
||||
"шаблоны для автоматизации настройки чертежей.",
|
||||
SCRIPT_FOLDER_NAME: "Папка скриптов Excalidraw Automate (РеГИстРозависимЫЙ!)",
|
||||
SCRIPT_FOLDER_DESC:
|
||||
"Файлы, которые вы поместите в эту папку, будут рассматриваться как сценарии Excalidraw Automate. " +
|
||||
"Вы можете получить доступ к своим скриптам из Excalidraw через палитру команд Obsidian. Назначьте " +
|
||||
"горячие клавиши для ваших любимых скриптов, как и для любой другой команды Obsidian. " +
|
||||
"Эта папка может не быть корневой папкой вашего хранилища. ",
|
||||
AI_HEAD: "Настройки ИИ - Экспериментальные",
|
||||
AI_DESC: `В настройках "ИИ" вы можете настроить параметры использования GPT API OpenAI. ` +
|
||||
`Пока API OpenAI находится в бета-версии, его использование строго ограничено - поэтому мы требуем, чтобы вы использовали свой собственный ключ API. ` +
|
||||
`Вы можете создать аккаунт OpenAI, добавить небольшой кредит (минимум 5 долларов) и сгенерировать свой собственный ключ API. ` +
|
||||
`После установки API-ключа вы сможете использовать инструменты искусственного интеллекта в Excalidraw.`,
|
||||
AI_OPENAI_TOKEN_NAME: "Ключ API OpenAI",
|
||||
AI_OPENAI_TOKEN_DESC: "Вы можете получить свой ключ API OpenAI из вашего <a href='https://platform.openai.com/api-keys'>OpenAI аккаунта</a>.",
|
||||
AI_OPENAI_TOKEN_PLACEHOLDER: "Введите свой ключ API OpenAI здесь",
|
||||
AI_OPENAI_DEFAULT_MODEL_NAME: "Модель ИИ по умолчанию",
|
||||
AI_OPENAI_DEFAULT_MODEL_DESC:
|
||||
"Модель ИИ по умолчанию, используемая при генерации текста. Это поле свободного текста, поэтому вы можете ввести любое действительное имя модели OpenAI. " +
|
||||
"Узнайте больше о доступных моделях на <a href='https://platform.openai.com/docs/models'>OpenAI сайте</a>.",
|
||||
AI_OPENAI_DEFAULT_MODEL_PLACEHOLDER: "Введите здесь модель искусственного интеллекта по умолчанию, например: gpt-3.5-turbo-1106.",
|
||||
AI_OPENAI_DEFAULT_IMAGE_MODEL_NAME: "Модель ИИ для генерации изображений по умолчанию",
|
||||
AI_OPENAI_DEFAULT_IMAGE_MODEL_DESC:
|
||||
"Модель ИИ по умолчанию, используемая при генерации изображений. Редактирование и изменение изображений поддерживается OpenAI только в dall-e-2, " +
|
||||
"поэтому dall-e-2 будет автоматически использоваться в таких случаях независимо от этой настройки.<br>" +
|
||||
"Это поле свободного текста, поэтому вы можете ввести любое действительное имя модели OpenAI. " +
|
||||
"Узнайте больше о доступных моделях на <a href='https://platform.openai.com/docs/models'>OpenAI сайте</a>.",
|
||||
AI_OPENAI_DEFAULT_IMAGE_MODEL_PLACEHOLDER: "Введите здесь модель ИИ Image Generation по умолчанию, например: dall-e-3.",
|
||||
AI_OPENAI_DEFAULT_VISION_MODEL_NAME: "Модель видения ИИ по умолчанию",
|
||||
AI_OPENAI_DEFAULT_VISION_MODEL_DESC:
|
||||
"Модель зрения ИИ по умолчанию, используемая при генерации текста из изображений. Это поле свободного текста, поэтому вы можете ввести любое действительное имя модели OpenAI. " +
|
||||
"Узнайте больше о доступных моделях на <a href='https://platform.openai.com/docs/models'>OpenAI сайте</a>.",
|
||||
AI_OPENAI_DEFAULT_API_URL_NAME: "URL-адрес API OpenAI",
|
||||
AI_OPENAI_DEFAULT_API_URL_DESC:
|
||||
"URL-адрес OpenAI API по умолчанию. Это поле свободного текста, поэтому вы можете ввести любой действительный URL, совместимый с OpenAI API. " +
|
||||
"Excalidraw будет использовать этот URL при отправке API-запросов в OpenAI. Я не делаю никакой обработки ошибок в этом поле, поэтому убедитесь, что вы вводите правильный URL и изменяйте его только в том случае, если вы знаете, что делаете. ",
|
||||
AI_OPENAI_DEFAULT_IMAGE_API_URL_NAME: "URL-адрес API генерации изображений OpenAI",
|
||||
AI_OPENAI_DEFAULT_VISION_MODEL_PLACEHOLDER: "Введите здесь модель зрения ИИ по умолчанию. Например: gpt-4o",
|
||||
SAVING_HEAD: "Сохранение",
|
||||
SAVING_DESC: "В разделе 'Сохранение' раздела Настройки Excalidraw вы можете настроить способ сохранения ваших чертежей. Сюда входят опции сжатия Excalidraw JSON в Markdown, установки интервалов автосохранения для настольных и мобильных компьютеров, определения форматов имен файлов, а также выбора расширения файла .excalidraw.md или .md. ",
|
||||
COMPRESS_NAME: "Сжатие Excalidraw JSON в формате Markdown",
|
||||
COMPRESS_DESC:
|
||||
"При включении этой функции Excalidraw будет хранить JSON рисунка в формате Base64. " +
|
||||
"формат с использованием алгоритма <a href='https://pieroxy.net/blog/pages/lz-string/index.html'>LZ-String</a>. " +
|
||||
"Это уменьшит вероятность того, что Excalidraw JSON загромоздит результаты поиска в Obsidian. " +
|
||||
"Как побочный эффект, это также уменьшит размер файлов чертежей Excalidraw. " +
|
||||
"При переключении чертежа Excalidraw в режим Markdown с помощью меню опций Excalidraw файл будет " +
|
||||
"сохранен без сжатия, чтобы вы могли читать и редактировать строку JSON. Чертеж будет снова сжат " +
|
||||
"как только вы переключитесь обратно в вид Excalidraw. " +
|
||||
"Настройка имеет силу только 'на перспективу', то есть существующие чертежи не будут затронуты настройкой " +
|
||||
"пока вы не откроете и не сохраните их.<br><b><u>Переключатель ВКЛ:</u></b> Сжать чертеж JSON<br><b><u>Переключатель ВЫКЛ:</u></b> Оставьте JSON для рисования без сжатия",
|
||||
DECOMPRESS_FOR_MD_NAME: "Декомпрессия Excalidraw JSON в Markdown Режим",
|
||||
DECOMPRESS_FOR_MD_DESC:
|
||||
"При включении этой функции Excalidraw будет автоматически распаковывать JSON чертежа при переключении в режим Markdown." +
|
||||
"Это позволит вам легко читать и редактировать строку JSON. Чертеж будет снова сжат " +
|
||||
"как только вы переключитесь обратно в режим Excalidraw и сохраните чертеж (CTRL+S).<br>" +
|
||||
"Я рекомендую отключить эту функцию, так как это приведет к уменьшению размера файлов и избавит от ненужных результатов в поиске Obsidian. " +
|
||||
"Вы всегда можете воспользоваться командой 'Excalidraw: Распаковать текущий файл Excalidraw' из палитры команд. "+
|
||||
"чтобы вручную распаковывать JSON чертежа, когда вам нужно его прочитать или отредактировать.",
|
||||
AUTOSAVE_INTERVAL_DESKTOP_NAME: "Интервал для автосохранения на рабочем столе",
|
||||
AUTOSAVE_INTERVAL_DESKTOP_DESC:
|
||||
"Интервал времени между сохранениями. Автосохранение будет пропущено, если в чертеже нет изменений. " +
|
||||
"Excalidraw также сохранит файл при закрытии вкладки рабочей области или при навигации в Obsidian, но вне активной вкладки Excalidraw (например, при нажатии на ленту Obsidian, проверке обратных ссылок и т. д.). " +
|
||||
"Excalidraw не сможет сохранить вашу работу при завершении работы Obsidian напрямую, либо убив процесс Obsidian, либо нажав кнопку закрытия Obsidian вообще.",
|
||||
AUTOSAVE_INTERVAL_MOBILE_NAME: "Интервал для автосохранения на мобильном телефоне",
|
||||
AUTOSAVE_INTERVAL_MOBILE_DESC:
|
||||
"Для мобильников я рекомендую более частый интервал. " +
|
||||
"Excalidraw также сохранит файл при закрытии вкладки рабочей области или при навигации в Obsidian, но вне активной вкладки Excalidraw (например, при нажатии на ленту Obsidian, проверке обратных ссылок и т. д.). " +
|
||||
"Excalidraw не сможет сохранить вашу работу при прямом завершении работы Obsidian (т.е. смахнув ее). Также обратите внимание, что при переключении приложений на мобильном устройстве, иногда Android и iOS закрываются " +
|
||||
"Obsidian в фоновом режиме для экономии системных ресурсов. В этом случае Excalidraw не сможет сохранить последние изменения.",
|
||||
FILENAME_HEAD: "Имя файла",
|
||||
FILENAME_DESC:
|
||||
"<p>Нажмите на эту ссылку, чтобы получить <a href='https://momentjs.com/docs/#/displaying/format/'>" +
|
||||
"справочник по формату даты и времени</a>.</p>",
|
||||
FILENAME_SAMPLE: "Filename for a new drawing is: ",
|
||||
FILENAME_EMBED_SAMPLE: "Имя файла для нового встроенного чертежа: ",
|
||||
FILENAME_PREFIX_NAME: "Префикс имени файла",
|
||||
FILENAME_PREFIX_DESC: "Первая часть имени файла",
|
||||
FILENAME_PREFIX_EMBED_NAME: "Префикс имени файла при вставке нового чертежа в заметку в формате markdown",
|
||||
FILENAME_PREFIX_EMBED_DESC:
|
||||
"Должно ли имя файла нового вставленного чертежа начинаться с имени активной заметки в формате markdown " +
|
||||
"при использовании действия палитры команд: <code>Создать новый чертеж и вставить его в активный документ</code>?<br>" +
|
||||
"<b><u>Переключатель ВКЛ:</u></b> Да, имя файла нового чертежа должно начинаться с имени файла активного документа<br><b><u>Переключатель ВЫКЛ:</u></b> Нет, имя файла нового чертежа не должно включать имя файла активного документа",
|
||||
FILENAME_POSTFIX_NAME: "Пользовательский текст после имени заметки в формате markdown при вставке",
|
||||
FILENAME_POSTFIX_DESC: "Влияет на имя файла только при вставке в документ markdown. Этот текст будет вставлен после имени заметки, но перед датой.",
|
||||
FILENAME_DATE_NAME: "Дата имени файла",
|
||||
FILENAME_DATE_DESC: "Последняя часть имени файла. Оставьте пустой, если дата не нужна.",
|
||||
FILENAME_EXCALIDRAW_EXTENSION_NAME: ".excalidraw.md или .md",
|
||||
FILENAME_EXCALIDRAW_EXTENSION_DESC:
|
||||
"Эта настройка не применяется, если вы используете Excalidraw в режиме совместимости, " +
|
||||
"т.е. вы не используете файлы разметки Excalidraw.<br><b><u>Переключатель ВКЛ:</u></b> Имя файла заканчивается на .excalidraw.md<br><b><u>Переключатель ВЫКЛ:</u></b> Имя файла заканчивается на .md",
|
||||
DISPLAY_HEAD: "Внешний вид и поведение Excalidraw",
|
||||
DISPLAY_DESC: "В разделе 'Внешний вид и поведение' раздела Настройки Excalidraw вы можете настроить внешний вид и поведение Excalidraw. Сюда входят опции динамической стилизации, режима для левой руки, соответствия тем Excalidraw и Obsidian, режимов по умолчанию и многое другое.",
|
||||
DYNAMICSTYLE_NAME: "Динамическая стилизация",
|
||||
DYNAMICSTYLE_DESC: "Изменение цветов пользовательского интерфейса Excalidraw в соответствии с цветом холста",
|
||||
LEFTHANDED_MODE_NAME: "Левосторонний режим",
|
||||
LEFTHANDED_MODE_DESC:
|
||||
"В настоящее время действует только в трей режиме. Если включить этот режим, трей будет находиться с правой стороны." +
|
||||
"<br><b><u>Переключатель ВКЛ:</u></b> Левосторонний режим.<br><b><u>Переключатель ВЫКЛ:</u></b> Правосторонний режим",
|
||||
IFRAME_MATCH_THEME_NAME: "Вставки Markdown для соответствия теме Excalidraw",
|
||||
IFRAME_MATCH_THEME_DESC:
|
||||
"<b><u>Переключатель ВКЛ:</u></b> Установите значение true, если, например, вы используете Obsidian в темном режиме, но применяете excalidraw со светлым фоном. " +
|
||||
"С этой настройкой встроенный документ разметки Obsidian будет соответствовать теме Excalidraw (т.е. светлые цвета, если Excalidraw находится в светлом режиме).<br>" +
|
||||
"<b><u>Переключатель ВЫКЛ:</u></b> Установите значение false, если хотите, чтобы встроенный в Obsidian документ разметки соответствовал теме Obsidian (т.е. темные цвета, если Obsidian находится в темном режиме).",
|
||||
MATCH_THEME_NAME: "Новый чертеж в соответствии с темой Obsidian",
|
||||
MATCH_THEME_DESC:
|
||||
"Если тема темная, новый рисунок будет создан в темном режиме. Это не относится к случаям, когда вы используете шаблон для новых рисунков. " +
|
||||
"Также это не повлияет на открытие существующего чертежа. Они будут соответствовать теме шаблона/чертежа соответственно." +
|
||||
"<br><b><u>Переключатель ВКЛ:</u></b> Следуйте за Obsidian Theme<br><b><u>Переключатель ВЫКЛ:</u></b> Следовать теме, заданной в вашем шаблоне",
|
||||
MATCH_THEME_ALWAYS_NAME: "Существующие чертежи должны соответствовать теме Obsidian",
|
||||
MATCH_THEME_ALWAYS_DESC:
|
||||
"Если тема темная, чертежи будут открываться в темном режиме. Если тема светлая, они будут открываться в светлом режиме. " +
|
||||
"<br><b><u>Переключатель ВКЛ:</u></b> Соответствовать теме Obsidian<br><b><u>Переключатель ВЫКЛ:</u></b> Открывать ту же тему, что и при последнем сохранении",
|
||||
MATCH_THEME_TRIGGER_NAME: "Excalidraw будет следовать за изменениями Темы Obsidian",
|
||||
MATCH_THEME_TRIGGER_DESC:
|
||||
"Если эта опция включена, открытая панель Excalidraw будет переключаться в светлый/темный режим при смене темы Obsidian. " +
|
||||
"<br><b><u>Переключатель ВКЛ:</u></b> Следить за изменениями темы<br><b><u>Переключатель ВЫКЛ:</u></b> Чертежи не подвержены изменениям темы Obsidian",
|
||||
DEFAULT_OPEN_MODE_NAME: "Режим по умолчанию при открытии Excalidraw",
|
||||
DEFAULT_OPEN_MODE_DESC:
|
||||
"Указывает режим, в котором открывается Excalidraw: Обычный, Zen или режим просмотра. Вы также можете задать это поведение на уровне файла " +
|
||||
"добавив в документ ключ excalidraw-default-mode frontmatter со значением: normal, view или zen.",
|
||||
DEFAULT_PEN_MODE_NAME: "Режим пера",
|
||||
DEFAULT_PEN_MODE_DESC: "Должен ли режим пера автоматически включаться при открытии Excalidraw?",
|
||||
DISABLE_DOUBLE_TAP_ERASER_NAME: "Включение двойного нажатия ластика в режиме пера",
|
||||
SHOW_PEN_MODE_FREEDRAW_CROSSHAIR_NAME: "Показать (+) перекрестие в режиме пера",
|
||||
SHOW_PEN_MODE_FREEDRAW_CROSSHAIR_DESC:
|
||||
"Показывайте перекрестие в режиме пера при использовании инструмента freedraw. <b><u>Toggle Переключатель ВКЛ</u></b> Показывать <b><u>Toggle Переключатель ВЫКЛ</u></b> Скрывать<br>"+
|
||||
"Эффект зависит от устройства. Перекрестие обычно видно на планшетах для рисования, MS Surface, но не на iOS.",
|
||||
SHOW_DRAWING_OR_MD_IN_HOVER_PREVIEW_NAME: "Передача файла Excalidraw в виде изображения в предварительном просмотре при наведении...",
|
||||
SHOW_DRAWING_OR_MD_IN_HOVER_PREVIEW_DESC:
|
||||
"...даже если файл имеет ключ <b>excalidraw-open-md: true</b> frontmatter.<br>" +
|
||||
"Если этот параметр выключен и файл по умолчанию открывается в формате md, при наведении на предварительный просмотр" +
|
||||
"будет показана часть документа, содержащая разметку.",
|
||||
SHOW_DRAWING_OR_MD_IN_READING_MODE_NAME: "Рендеринг в виде изображения при чтении файла Excalidraw в режиме разметки",
|
||||
SHOW_DRAWING_OR_MD_IN_READING_MODE_DESC:
|
||||
"Когда вы находитесь в режиме чтения разметки (а именно, читаете обратную сторону рисунка), должен ли рисунок Excalidraw отображаться как изображение? " +
|
||||
"Этот параметр не влияет на отображение чертежа в режиме Excalidraw, а также при встраивании чертежа в документ с пометками или при предварительном просмотре при наведении.<br><ul>" +
|
||||
"<li>Смотрите другие связанные настройки для <a href='#«+TAG_PDFEXPORT+»'>экспорта PDF</a> в разделе 'Встраивание и экспорт' ниже.</li></ul><br>" +
|
||||
"Вы должны закрыть активный файл excalidraw/markdown и снова открыть его, чтобы это изменение вступило в силу.",
|
||||
SHOW_DRAWING_OR_MD_IN_EXPORTPDF_NAME: "При экспорте файла Excalidraw в PDF файл отображается как изображение.",
|
||||
SHOW_DRAWING_OR_MD_IN_EXPORTPDF_DESC:
|
||||
"Этот параметр управляет поведением Excalidraw при экспорте файла Excalidraw в PDF в режиме просмотра разметки с помощью функции Obsidian <b>Экспорт в PDF</b> <br>" +
|
||||
"<ul><li>Если <b>разрешить</b>, в PDF будет отображаться только чертеж Excalidraw;</li>" +
|
||||
"<li>Если <b>заблокировать</b>, то в PDF будет отображаться разметка документа.</li></ul>" +
|
||||
"См. другие связанные настройки для <a href='#«+TAG_MDREADINGMODE+»'>режима чтения разметки</a> в разделе 'Внешний вид и поведение' выше.<br>" +
|
||||
"⚠️ Обратите внимание, что необходимо закрыть активный файл excalidraw/markdown и открыть его снова, чтобы изменения вступили в силу. ⚠️",
|
||||
HOTKEY_OVERRIDE_HEAD: "Переопределение горячих клавиш",
|
||||
HOTKEY_OVERRIDE_DESC: `Некоторые горячие клавиши Excalidraw, такие как <code>${labelCTRL()}+Enter</code> для редактирования текста или <code>${labelCTRL()}+K</code> создания ссылки на элемент ` +
|
||||
"конфликтуют с настройками горячих клавиш Obsidian. Комбинации горячих клавиш, которые вы добавите ниже, отменят настройки горячих клавиш Obsidian при использовании Excalidraw, таким образом " +
|
||||
`Вы можете добавить <code>${labelCTRL()}+G</code>, если хотите по умолчанию перейти к Группе Объектов в Excalidraw вместо открытия Режима просмотра Графиков.`,
|
||||
THEME_HEAD: "Тема и стиль",
|
||||
ZOOM_HEAD: "Масштабирование",
|
||||
DEFAULT_PINCHZOOM_NAME: "Разрешить масштабирование в режиме пера",
|
||||
DEFAULT_PINCHZOOM_DESC:
|
||||
"По умолчанию зуммирование в режиме пера при использовании инструмента «Свободное рисование» отключено, чтобы предотвратить нежелательное случайное масштабирование с помощью ладони.<br>" +
|
||||
"<b><u>Переключатель ВКЛ:</u></b>Включение щипкового масштабирования в режиме пера<br><b><u>Переключатель ВЫКЛ:</u></b>Выключение щипкового масштабирования в режиме пера",
|
||||
|
||||
DEFAULT_WHEELZOOM_NAME: "Колесо мыши для масштабирования по умолчанию",
|
||||
DEFAULT_WHEELZOOM_DESC:
|
||||
`<b><u>Переключатель ВКЛ:</u></b> Колесо мыши для масштабирования; ${labelCTRL()} + Колесо мыши для прокрутки</br><b><u>Переключатель ВЫКЛ:</u></b>${labelCTRL()} + Колесико мыши для масштабирования; Колесико мыши для прокрутки`,
|
||||
|
||||
ZOOM_TO_FIT_NAME: "Изменение масштаба при изменении размера просмотра",
|
||||
ZOOM_TO_FIT_DESC: "Изменение масштаба чертежа при изменении размера панели" +
|
||||
"<br><b><u>Переключатель ВКЛ:</u></b> Увеличить масштаб<br><b><u>Переключатель ВЫКЛ:</u></b> Автоматическое масштабирование отключено",
|
||||
ZOOM_TO_FIT_ONOPEN_NAME: "Увеличение масштаба при открытии файла",
|
||||
ZOOM_TO_FIT_ONOPEN_DESC: "Изменение масштаба чертежа при его первом открытии" +
|
||||
"<br><b><u>Переключатель ВКЛ:</u></b> Увеличить масштаб<br><b><u>Переключатель ВЫКЛ:</u></b> Автоматическое масштабирование отключено",
|
||||
ZOOM_TO_FIT_MAX_LEVEL_NAME: "Увеличение до максимального уровня масштабирования",
|
||||
ZOOM_TO_FIT_MAX_LEVEL_DESC: "Установите максимальный уровень, до которого масштабирование будет увеличивать чертеж. Минимальное значение - 0,5 (50 %), максимальное - 10 (1000 %).",
|
||||
GRID_HEAD: "Сетка",
|
||||
GRID_DYNAMIC_COLOR_NAME: "Динамический цвет сетки",
|
||||
GRID_DYNAMIC_COLOR_DESC: "<b><u>Переключатель ВКЛ:</u></b>Измените цвет сетки, чтобы он соответствовал цвету холста<br><b><u>Переключатель ВЫКЛ:</u></b>Используйте цвет, указанный ниже, в качестве цвета сетки",
|
||||
GRID_COLOR_NAME: "Цвет сетки",
|
||||
GRID_OPACITY_NAME: "Прозрачность сетки",
|
||||
GRID_OPACITY_DESC: "Прозрачность сетки также будет управлять прозрачностью поля привязки при привязке стрелки к элементу.<br>" +
|
||||
"Установите прозрачность сетки. 0 - прозрачная, 100 - непрозрачная.",
|
||||
LASER_HEAD: "Лазерный указатель",
|
||||
LASER_COLOR: "Цвет лазерного указателя",
|
||||
LASER_DECAY_TIME_NAME: "Время затухания лазерного указателя",
|
||||
LASER_DECAY_TIME_DESC: "Время затухания лазерного указателя в миллисекундах. По умолчанию - 1000 (т. е. 1 секунда).",
|
||||
LASER_DECAY_LENGTH_NAME: "Длительность затухания лазерного указателя.",
|
||||
LASER_DECAY_LENGTH_DESC: "Длина затухания лазерного указателя в точках линии. По умолчанию 50.",
|
||||
LINKS_HEAD: "Ссылки, включение и задачи TODO",
|
||||
LINKS_HEAD_DESC: "В разделе 'Ссылки, включения и TODO' раздела Настройки Excalidraw вы можете настроить, как Excalidraw обрабатывает ссылки, включения и элементы TODO. Сюда входят опции для открытия ссылок, управления панелями, отображения ссылок со скобками, настройки префиксов ссылок, обработки элементов TODO и т. д. ",
|
||||
LINKS_DESC:
|
||||
`${labelCTRL()}+КЛИКНИТЕ на <code>[[Text Elements]]</code> чтобы открыть их как ссылки. ` +
|
||||
"Если выделенный текст имеет более одного <code>[[valid Obsidian links]]</code>, только первый будет открыт. " +
|
||||
"Если текст начинается как правильная веб-ссылка (то есть <code>https://</code> или <code>http://</code>), потом " +
|
||||
"плагин откроет его в браузере. " +
|
||||
"Когда файлы Obsidian изменяются, соответствующие <code>[[link]]</code> в ваших чертежах также изменится. " +
|
||||
"Если вы не хотите, чтобы текст случайно менялся в ваших чертежах, используйте <code>[[links|with aliases]]</code>.",
|
||||
DRAG_MODIFIER_NAME: "Щелкните ссылку и перетащите клавиши-модификаторы",
|
||||
DRAG_MODIFIER_DESC: "Поведение клавиши-модификатора при нажатии на ссылки и перетаскивании элементов. " +
|
||||
"Excalidraw не будет проверять вашу конфигурацию... обратите внимание, чтобы избежать конфликтов настроек. " +
|
||||
"Эти настройки отличаются для Apple и не-Apple. Если вы используете Obsidian на нескольких платформах, вам нужно будет сделать настройки отдельно. "+
|
||||
"Переключатели расположены в порядке" +
|
||||
(DEVICE.isIOS || DEVICE.isMacOS ? "SHIFT, CMD, OPT, CONTROL." : "SHIFT, CTRL, ALT, META (Клавишы Windows)."),
|
||||
LONG_PRESS_DESKTOP_NAME: "Длительное нажатие открывает рабочий стол",
|
||||
LONG_PRESS_DESKTOP_DESC: "Задержка нажатия в миллисекундах для открытия чертежа Excalidraw, встроенного в файл Markdown.",
|
||||
LONG_PRESS_MOBILE_NAME: "Длительное нажатие открывает мобильную версию",
|
||||
LONG_PRESS_MOBILE_DESC: "Задержка нажатия в миллисекундах для открытия чертежа Excalidraw, встроенного в файл Markdown.",
|
||||
|
||||
FOCUS_ON_EXISTING_TAB_NAME: "Фокус на существующей вкладке",
|
||||
FOCUS_ON_EXISTING_TAB_DESC: "При открытии ссылки Excalidraw будет фокусироваться на существующей вкладке, если файл уже открыт. " +
|
||||
"Включение этого параметра отменяет 'Повторное использование соседней панели', если файл уже открыт.",
|
||||
SECOND_ORDER_LINKS_NAME: "Показать ссылки второго порядка",
|
||||
SECOND_ORDER_LINKS_DESC: "Показывать ссылки при нажатии на ссылку в Excalidraw. Ссылки второго порядка - это обратные ссылки, указывающие на ссылку, по которой переходят. " +
|
||||
"При использовании значков изображений для соединения похожих заметок ссылки второго порядка позволяют перейти к связанным заметкам одним щелчком мыши, а не двумя. " +
|
||||
"Для понимания смотрите <a href='https://youtube.com/shorts/O_1ls9c6wBY?feature=share'>YT Short</a>.",
|
||||
ADJACENT_PANE_NAME: "Повторное использование соседней панели",
|
||||
ADJACENT_PANE_DESC:
|
||||
`Когда ${labelCTRL()}+${labelALT()} нажимает на ссылку в Excalidraw, по умолчанию плагин открывает ссылку в новой панели. ` +
|
||||
"Если включить этот параметр, Excalidraw сначала будет искать существующую панель и пытаться открыть ссылку в ней. " +
|
||||
"Excalidraw будет искать другую панель рабочего пространства, основываясь на истории фокуса/навигации, то есть на той панели, которая была активна до того, " +
|
||||
"как вы активировали Excalidraw.",
|
||||
MAINWORKSPACE_PANE_NAME: "Открыть в основном рабочем пространстве",
|
||||
MAINWORKSPACE_PANE_DESC:
|
||||
`Когда ${labelCTRL()}+${labelALT()} нажимает на ссылку в Excalidraw, по умолчанию плагин открывает ссылку в новой панели в текущем активном окне. ` +
|
||||
"Если включить этот параметр, Excalidraw откроет ссылку в существующей или новой панели в основном рабочем пространстве. ",
|
||||
LINK_BRACKETS_NAME: "Показать <code>[[brackets]]</code> вокруг ссылок",
|
||||
LINK_BRACKETS_DESC: `${
|
||||
"В режиме ПРЕДВАРИТЕЛЬНОГО ПРОСМОТРА при разборе элементов текста ставьте скобки вокруг ссылок. " +
|
||||
"Вы можете переопределить эту настройку для конкретного чертежа, добавив <code>"
|
||||
}${FRONTMATTER_KEYS["link-brackets"].name}: true/false</code> в frontmatter файла.`,
|
||||
LINK_PREFIX_NAME: "Префикс ссылки",
|
||||
LINK_PREFIX_DESC: `${
|
||||
"В режиме ПРЕДВАРИТЕЛЬНОГО ПРОСМОТРА, если элемент 'Текст' содержит ссылку, перед текстом должны стоять эти символы. " +
|
||||
"Вы можете переопределить эту настройку для конкретного чертежа, добавив <code>"
|
||||
}${FRONTMATTER_KEYS["link-prefix"].name}: "📍 "</code> в frontmatter файла.`,
|
||||
URL_PREFIX_NAME: "Префикс URL-адреса",
|
||||
URL_PREFIX_DESC: `${
|
||||
"В режиме ПРЕДВАРИТЕЛЬНОГО ПРОСМОТРА, если элемент 'Текст' содержит ссылку URL, перед текстом должны стоять эти символы. " +
|
||||
"Вы можете переопределить эту настройку для конкретного чертежа, добавив <code>"
|
||||
}${FRONTMATTER_KEYS["url-prefix"].name}: "🌐 "</code> в frontmatter файла.`,
|
||||
PARSE_TODO_NAME: "Парсинг TODO",
|
||||
PARSE_TODO_DESC: "Преобразуйте '- [ ] ' и '- [x] ' в чекбокс и поставьте галочку.",
|
||||
TODO_NAME: "Открыть иконку TODO",
|
||||
TODO_DESC: "Иконка для открытых пунктов TODO",
|
||||
DONE_NAME: "Иконка завершенного TODO",
|
||||
DONE_DESC: "Иконка для завершенных элементов TODO",
|
||||
HOVERPREVIEW_NAME: `Предварительный просмотр наведением без нажатия клавиши ${labelCTRL()}`,
|
||||
HOVERPREVIEW_DESC:
|
||||
`<b><u>Переключатель ВКЛ:</u></b> <u>В режиме просмотра</u> Exalidraw предварительный просмотр при наведении на [[вики-ссылки]] будет показан сразу, без необходимости удерживать клавишу ${labelCTRL()}. ` +
|
||||
"В Excalidraw <u>нормальный режим</u>, предварительный просмотр будет показан сразу только при наведении на синий значок ссылки в правом верхнем углу элемента.<br> " +
|
||||
`<b><u>Переключатель ВЫКЛ:</u></b> Предварительный просмотр при наведении отображается только в том случае, если при наведении на ссылку вы удерживаете клавишу ${labelCTRL()}.`,
|
||||
LINKOPACITY_NAME: "Прозрачность значка ссылки",
|
||||
LINKOPACITY_DESC: "Прозрачность значка индикатора ссылки в правом верхнем углу элемента. 1 - непрозрачный, 0 - прозрачный.",
|
||||
LINK_CTRL_CLICK_NAME: `${labelCTRL()}+КЛИК на текст с [[links]] или [](links), чтобы открыть их`,
|
||||
LINK_CTRL_CLICK_DESC:
|
||||
"Вы можете отключить эту функцию, если она мешает работе стандартных функций Excalidraw, которые вы хотите использовать. " +
|
||||
`Если эта функция отключена, для открытия ссылок можно использовать либо ${labelCTRL()} + ${labelMETA()}, либо индикатор ссылок в правом верхнем углу элемента.`,
|
||||
TRANSCLUSION_WRAP_NAME: "Поведение переноса при переполненнии включенного текста",
|
||||
TRANSCLUSION_WRAP_DESC:
|
||||
"Число задает количество символов, через которое должен быть перенесен текст. " +
|
||||
"Устанавливает поведение переноса текста. Включите этот параметр, чтобы принудительно перенести " +
|
||||
" текст (т. е. без переполнения), или выключите, чтобы мягко перенести текст (по ближайшему пробелу).",
|
||||
TRANSCLUSION_DEFAULT_WRAP_NAME: "Перенос по словам включения по умолчанию",
|
||||
TRANSCLUSION_DEFAULT_WRAP_DESC:
|
||||
"Вы можете вручную задать/переопределить длину переноса слов, используя формат `![[page#^block]]{NUMBER}`. " +
|
||||
"Обычно вам не нужно устанавливать значение по умолчанию, поскольку если вы вставите текст внутрь стикера, то Excalidraw автоматически позаботится о переносе слов. " +
|
||||
"Установите это значение на '0', если вы не хотите устанавливать значение по умолчанию. ",
|
||||
PAGE_TRANSCLUSION_CHARCOUNT_NAME: "Максимальное количество символов при включении страниц (трансклюзии)",
|
||||
PAGE_TRANSCLUSION_CHARCOUNT_DESC:
|
||||
"Максимальное количество символов, отображаемых на странице при включении всей страницы" +
|
||||
"в формате ![[markdown page]].",
|
||||
QUOTE_TRANSCLUSION_REMOVE_NAME: "Включение (Трансклюзия) цитат: удалите ведущие '> ' из каждой строки",
|
||||
QUOTE_TRANSCLUSION_REMOVE_DESC: "Удалите начальный '>' из каждой строки включения. Это улучшит читаемость цитат в текстовых включениях <br>" +
|
||||
"<b><u>Переключатель ВКЛ:</u></b> Удалить ведущие '> '<br><b><u>Переключатель ВЫКЛ:</u></b> Не удалить ведущие '> ' (обратите внимание, что он все равно будет удален из первой строки из-за функциональности API Obsidian.)",
|
||||
GET_URL_TITLE_NAME: "Используйте iframely для преобразования заголовка страницы",
|
||||
GET_URL_TITLE_DESC:
|
||||
"Используйте <code>http://iframely.server.crestify.com/iframely?url=</code> для получения заголовка страницы при переходе по ссылке в Excalidraw",
|
||||
PDF_TO_IMAGE: "PDF в изображение",
|
||||
PDF_TO_IMAGE_SCALE_NAME: "Шкала преобразования PDF в изображения",
|
||||
PDF_TO_IMAGE_SCALE_DESC: "Устанавливает разрешение изображения, которое генерируется из PDF-страницы. Более высокое разрешение приведет к увеличению размера изображений в памяти и, как следствие, к увеличению нагрузки на систему (замедлению производительности), но при этом изображение будет более четким. " +
|
||||
"Кроме того, если вы хотите скопировать страницы PDF (как изображения) на Excalidraw.com, больший размер изображения может привести к превышению лимита в 2 МБ на Excalidraw.com.",
|
||||
EMBED_TOEXCALIDRAW_HEAD: "Встраивание файлов в Excalidraw",
|
||||
EMBED_TOEXCALIDRAW_DESC: "В разделе Встраивание файлов раздела Настройки Excalidraw вы можете настроить, как различные файлы будут встраиваться в Excalidraw. Сюда входят опции для встраивания интерактивных файлов разметки (Markdown), PDF-файлов и файлов разметки (Markdown) в виде изображений.",
|
||||
MD_HEAD: "Встраивать разметку в Excalidraw в виде изображения",
|
||||
MD_EMBED_CUSTOMDATA_HEAD_NAME: "Интерактивные файлы Markdown",
|
||||
MD_EMBED_CUSTOMDATA_HEAD_DESC: `Приведенные ниже настройки будут влиять только на будущие вставки. Текущие вставки остаются неизменными. Настройки темы для встроенных фреймов находятся в разделе "Внешний вид и поведение Excalidraw".`,
|
||||
MD_EMBED_SINGLECLICK_EDIT_NAME: "Редактирование встроенной разметки (Markdown) одним щелчком мыши",
|
||||
MD_EMBED_SINGLECLICK_EDIT_DESC:
|
||||
"Однократный щелчок на встроенном файле разметки (Markdown) для его редактирования. " +
|
||||
"Если отключить эту функцию, файл с пометками сначала откроется в режиме предварительного просмотра, а затем переключится в режим редактирования, когда вы снова нажмете на него.",
|
||||
MD_TRANSCLUDE_WIDTH_NAME: "Ширина по умолчанию для включенного документа с разметкой",
|
||||
MD_TRANSCLUDE_WIDTH_DESC:
|
||||
"Ширина страницы разметки (Markdown). Это влияет на обертку слов при встраивание длинных абзацев, а также на ширину элемента изображения " +
|
||||
" Вы можете изменить ширину встроенного файла по умолчанию, " +
|
||||
"используя синтаксис <code>[[filename#heading|WIDTHxMAXHEIGHT]]</code> в режиме просмотра markdown в разделе встроенных файлов.",
|
||||
MD_TRANSCLUDE_HEIGHT_NAME: "Максимальная высота по умолчанию для документа с пометкой встраиваемый",
|
||||
MD_TRANSCLUDE_HEIGHT_DESC:
|
||||
"Встроенное изображение будет настолько высоким, насколько этого требует текст разметки (Markdown), но не выше этого значения. " +
|
||||
"Вы можете переопределить это значение, отредактировав ссылку на встроенное изображение в режиме просмотра markdown со следующим синтаксисом <code>[[filename#^blockref|WIDTHxMAXHEIGHT]]</code>.",
|
||||
MD_DEFAULT_FONT_NAME: "Шрифт по умолчанию, используемый для встроенных файлов разметки (Markdown).",
|
||||
MD_DEFAULT_FONT_DESC:
|
||||
'Установите это значение на "Virgil" или "Cascadia" или на имя файла <code>.ttf</code>, <code>.woff</code>, или <code>.woff2</code> шрифта, например. <code>MyFont.woff2</code> ' +
|
||||
"Вы можете отменить эту настройку, добавив следующий frontmatter-ключ во встроенный файл разметки (markdown): <code>excalidraw-font: font_or_filename</code>",
|
||||
MD_DEFAULT_COLOR_NAME: "Цвет шрифта по умолчанию, используемый для встроенных файлов разметки (markdown).",
|
||||
MD_DEFAULT_COLOR_DESC:
|
||||
'Установите это значение в любое допустимое имя цвета css, например, "steelblue" (<a href="https://www.w3schools.com/colors/colors_names.asp">имена цветов</a>), или допустимый шестнадцатеричный цвет, например "#e67700", ' +
|
||||
"или на любую другую допустимую строку цвета css. Вы можете отменить эту настройку, добавив следующий frontmatter-ключ во встроенный файл разметки (markdown): <code>excalidraw-font-color: steelblue</code>",
|
||||
MD_DEFAULT_BORDER_COLOR_NAME: "Цвет границы, используемый по умолчанию для встроенных файлов разметки (markdown).",
|
||||
MD_DEFAULT_BORDER_COLOR_DESC:
|
||||
'Установите это значение на любое допустимое имя цвета css, например "steelblue" (<a href="https://www.w3schools.com/colors/colors_names.asp">имена цветов</a>), или на допустимый шестнадцатеричный цвет, например "#e67700", ' +
|
||||
"или на любую другую допустимую строку цвета css. Вы можете отменить эту настройку, добавив следующий frontmatter-key во встроенный файл разметки (markdown): <code>excalidraw-border-color: gray</code>. " +
|
||||
"Оставьте пустым, если вам не нужна граница. ",
|
||||
MD_CSS_NAME: "CSS файл",
|
||||
MD_CSS_DESC:
|
||||
"Имя файла CSS для применения к вставкам markdown. Укажите имя файла с расширением (например, 'md-embed.css'). Файл css также может быть обычным файлом " +
|
||||
"markdow (e.g. 'md-embed-css.md'), просто убедитесь, что содержимое написано с использованием правильного синтаксиса css. " +
|
||||
`Если вам нужно просмотреть HTML-код, к которому вы применяете CSS, откройте Obsidian Developer Console (${DEVICE.isIOS || DEVICE.isMacOS ? "CMD+OPT+i" : "CTRL+SHIFT+i"}) и введите следующую команду: ` +
|
||||
'"ExcalidrawAutomate.mostRecentMarkdownSVG". Это отобразит последний SVG, сгенерированный Excalidraw. ' +
|
||||
"Установка font-family в css имеет свои ограничения. По умолчанию доступны только стандартные шрифты вашей операционной системы (подробнее см. в README). " +
|
||||
"Вы можете добавить еще один пользовательский шрифт, используя настройки выше. " +
|
||||
'Вы можете переопределить эту настройку css, добавив следующий frontmatter-ключ во встроенный файл разметки: "excalidraw-css: css_file_in_vault|css-snippet".',
|
||||
EMBED_HEAD: "Встраивание Excalidraw в заметки и экспорт",
|
||||
EMBED_DESC: `В настройках "Вставка и экспорт" можно настроить вставку и экспорт изображений и рисунков Excalidraw в документы. Основные настройки включают выбор типа изображения для предварительного просмотра в формате разметки (например, Native SVG или PNG), указание типа файла для вставки в документ (оригинальный Excalidraw, PNG или SVG) и управление кэшированием изображений для вставки в разметку. Вы также можете управлять размерами изображений, вставлять рисунки с помощью ссылок на вики или ссылок на разметку, а также настраивать темы изображений, цвета фона и интеграцию с Obsidian.
|
||||
Кроме того, есть настройки автоэкспорта, который автоматически генерирует файлы SVG и/или PNG, соответствующие названию ваших рисунков Excalidraw, сохраняя их синхронизацию при переименовании и удалении файлов.`,
|
||||
EMBED_CANVAS: "Поддержка Obsidian Canvas",
|
||||
EMBED_CANVAS_NAME: "Иммерсивное встраивание",
|
||||
EMBED_CANVAS_DESC:
|
||||
"Скрывайте границы и фон узлов холста при встраивании чертежа Excalidraw в холст. " +
|
||||
"Обратите внимание, что для создания полностью прозрачного фона изображения вам все равно придется настроить Excalidraw на экспорт изображений с прозрачным фоном.",
|
||||
EMBED_CACHING: "Кэширование изображений",
|
||||
EXPORT_SUBHEAD: "Настройки экспорта",
|
||||
EMBED_SIZING: "Размер изображения",
|
||||
EMBED_THEME_BACKGROUND: "Тема изображения и цвет фона",
|
||||
EMBED_IMAGE_CACHE_NAME: "Кэширование изображений для вставки в markdown",
|
||||
EMBED_IMAGE_CACHE_DESC: "Кэшируйте изображения для вставки в markdown. Это ускорит процесс встраивания, но в случае, если вы составите изображения из нескольких чертежей-субкомпонентов, " +
|
||||
"встроенное изображение в Markdown не будет обновляться, пока вы не откроете рисунок и не сохраните его, чтобы вызвать обновление кэша.",
|
||||
SCENE_IMAGE_CACHE_NAME: "Кэширование вложенных Excalidraws в Cцене",
|
||||
SCENE_IMAGE_CACHE_DESC: "Кэшируйте вложенные Excalidraws в сцене для ускорения рендеринга сцены. Это ускорит процесс рендеринга, особенно если в сцене есть глубоко вложенные Excalidraw. " +
|
||||
"Excalidraw попытается интеллектуально определить, изменились ли дочерние элементы вложенного Excalidraw, и соответствующим образом обновит кэш. " +
|
||||
"Вы можете отключить эту функцию, если у вас есть подозрения, что кэш обновляется неправильно.",
|
||||
EMBED_IMAGE_CACHE_CLEAR: "Очистка кэша",
|
||||
BACKUP_CACHE_CLEAR: "Очистка резервных копий",
|
||||
BACKUP_CACHE_CLEAR_CONFIRMATION: "Это действие удалит все резервные копии чертежей Excalidraw. Резервные копии используются в качестве меры безопасности на случай повреждения файла рисунка. Каждый раз, когда вы открываете Obsidian, плагин автоматически удаляет резервные копии файлов, которые больше не существуют в вашем хранилище. Вы уверены, что хотите удалить все резервные копии?",
|
||||
EMBED_REUSE_EXPORTED_IMAGE_NAME: "Если найдено, используйте уже экспортированное изображение для предварительного просмотра",
|
||||
EMBED_REUSE_EXPORTED_IMAGE_DESC:
|
||||
"Эта настройка работает в сочетании с настройкой <a href='#«+TAG_AUTOEXPORT+»'>Автоэкспорт SVG/PNG</a>. Если имеется экспортированное изображение, соответствующее имени файла чертежа, используйте это изображение вместо того, " +
|
||||
"чтобы генерировать изображение предварительного просмотра на лету. Однако это позволит ускорить предварительный просмотр, особенно если в чертеже много встроенных объектов, " +
|
||||
"может случиться так, что последние изменения не будут отображаться, а изображение не будет автоматически соответствовать вашей теме Obsidian, " +
|
||||
"если вы изменили тему Obsidian с момента создания экспорта. Эта настройка применяется только для вставки изображений в документы markdown. " +
|
||||
"По ряду причин этот же подход не может быть использован для ускорения загрузки чертежей с большим количеством встроенных объектов. Смотрите демонстрацию <a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/1.6.23' target='_blank'>здесь</a>.",
|
||||
/*EMBED_PREVIEW_SVG_NAME: "Отображение SVG в предварительном просмотре разметки (markdown)",
|
||||
EMBED_PREVIEW_SVG_DESC:
|
||||
"<b><u>Переключатель ВКЛ:</u></b> Вставьте рисунок как изображение <a href='https://en.wikipedia.org/wiki/Scalable_Vector_Graphics' target='_blank'>SVG</a> в предварительный просмотр разметки (markdown).<br>" +
|
||||
"<b><u>Переключатель ВЫКЛ:</u></b> Встроить рисунок как изображение <a href='' target='_blank'>PNG</a>. Обратите внимание, что некоторые из <a href='https://www.youtube.com/watch?v=yZQoJg2RCKI&t=633s' target='_blank'>функций ссылок на блоки изображений</a> не работают с встраиванием PNG.",*/
|
||||
EMBED_PREVIEW_IMAGETYPE_NAME: "Тип изображения в предварительном просмотре разметки (markdown)",
|
||||
EMBED_PREVIEW_IMAGETYPE_DESC:
|
||||
"<b><u>Родной SVG</u></b>: Высокое качество изображения. Встраиваемые веб-сайты, видео с YouTube, ссылки на Obsidian и внешние изображения, вставленные через URL-адрес, будут работать. Встроенные страницы Obsidian не будут<br>" +
|
||||
"<b><u>SVG-изображение</u></b>: Высокое качество изображений. Встроенные элементы и изображения, вставленные по URL, имеют только заполнители, ссылки не работают<br>" +
|
||||
"<b><u>PNG-изображение</u></b>: Более низкое качество изображения, но в некоторых случаях лучшая производительность при работе с большими рисунками. Встроенные элементы и изображения, вставленные по URL, имеют только заполнители, ссылки не работают. Также некоторые функции <a href='https://www.youtube.com/watch?v=yZQoJg2RCKI&t=633s' target='_blank'>ссылки на блок изображений</a> не работают с PNG-вставками.",
|
||||
PREVIEW_MATCH_OBSIDIAN_NAME: "Предварительный просмотр Excalidraw в соответствии с темой Obsidian",
|
||||
PREVIEW_MATCH_OBSIDIAN_DESC:
|
||||
"Предварительный просмотр изображений в документах должен соответствовать теме Obsidian. Если эта функция включена, то когда Obsidian находится в темном режиме, изображения Excalidraw будут отображаться в темном режиме. " +
|
||||
"Когда Obsidian находится в режиме освещения, Excalidraw также будет рендерить в режиме освещения. Вы можете отключить функцию 'Экспортировать изображение с фоном', чтобы получить более интегрированный в Obsidian вид и ощущение.",
|
||||
EMBED_WIDTH_NAME: "Ширина по умолчанию для встроенного ('включенного') изображения",
|
||||
EMBED_WIDTH_DESC:
|
||||
"Ширина по умолчанию для встроенного рисунка. Это относится к режиму редактирования и чтения, а также к предварительным просмотрам при наведении. При вставке изображения можно указать его " +
|
||||
"ширину используя <code>![[drawing.excalidraw|100]]</code> или " +
|
||||
"<code>[[drawing.excalidraw|100x100]]</code> формат.",
|
||||
EMBED_HEIGHT_NAME: "Высота по умолчанию для встроенного ('включенного') изображения",
|
||||
EMBED_HEIGHT_DESC:
|
||||
"Высота по умолчанию для встроенного рисунка. Это относится к режиму редактирования и чтения, а также к предварительным просмотрам при наведении. При вставке изображения можно указать его " +
|
||||
"высоту используя <code>![[drawing.excalidraw|100]]</code> или " +
|
||||
"<code>[[drawing.excalidraw|100x100]]</code> формат.",
|
||||
EMBED_TYPE_NAME: "Тип файла для вставки в документ",
|
||||
EMBED_TYPE_DESC:
|
||||
"Когда вы вставляете изображение в документ с помощью командной палитры, этот параметр определяет, должен ли Excalidraw вставлять оригинальный файл Excalidraw " +
|
||||
"или копию PNG или SVG. Чтобы эти типы изображений были доступны в раскрывающемся списке, их необходимо включить <a href='#"+TAG_AUTOEXPORT+"'>auto-export PNG / SVG</a> (см. ниже в разделе 'Настройки экспорта'). Для чертежей, не имеющих соответствующего PNG или " +
|
||||
"SVG, действие из палитры команд вставит неработающую ссылку. Необходимо открыть исходный чертеж и инициировать экспорт вручную. " +
|
||||
"Эта опция не будет автоматически генерировать файлы PNG/SVG, а просто будет ссылаться на уже существующие файлы.",
|
||||
EMBED_MARKDOWN_COMMENT_NAME: "Вставить ссылку на чертеж как комментари",
|
||||
EMBED_MARKDOWN_COMMENT_DESC:
|
||||
"Вставьте ссылку на исходный файл Excalidraw в виде ссылки в формате markdown под изображением, например: <code>%%[[drawing.excalidraw]]%%</code>.<br>" +
|
||||
"Вместо добавления комментария можно также выделить встроенную строку SVG или PNG и использовать действие из палитры команд: " +
|
||||
"'<code>Excalidraw: Open Excalidraw drawing</code>' чтобы открыть чертеж.",
|
||||
EMBED_WIKILINK_NAME: "Встраивание рисунка с помощью ссылки Wiki",
|
||||
EMBED_WIKILINK_DESC: "<b><u>Переключатель ВКЛ:</u></b> Excalidraw будет встраивать [[wiki link]].<br><b><u>Переключатель ВЫКЛ:</u></b> Excalidraw будет встраивать [markdown](link).",
|
||||
EXPORT_PNG_SCALE_NAME: "Масштаб экспортируемого изображения PNG",
|
||||
EXPORT_PNG_SCALE_DESC: "Масштаб экспортируемого PNG-изображения",
|
||||
EXPORT_BACKGROUND_NAME: "Экспорт изображения с фоном",
|
||||
EXPORT_BACKGROUND_DESC: "Если отключить эту функцию, экспортируемое изображение будет прозрачным.",
|
||||
EXPORT_PADDING_NAME: "Отступы изображений",
|
||||
EXPORT_PADDING_DESC:
|
||||
"Размер (в пикселях) вокруг экспортируемого изображения SVG или PNG. Для ссылок на clippedFrame значение Отступов равно 0." +
|
||||
"Если кривые линии расположены близко к краю изображения, они могут быть обрезаны при экспорте. Вы можете увеличить это значение, чтобы избежать обрезки. " +
|
||||
"Вы также можете отменить эту настройку на уровне файла, добавив ключ frontmatter <code>excalidraw-export-padding: 5<code>.",
|
||||
EXPORT_THEME_NAME: "Экспорт изображения с темой",
|
||||
EXPORT_THEME_DESC:
|
||||
"Экспортируйте изображение, соответствующее темной/светлой теме вашего рисунка. Если отключить эту функцию, " +
|
||||
"рисунки, созданные в темном режиме, будут отображаться так же, как и в светлом режиме. ",
|
||||
EXPORT_EMBED_SCENE_NAME: "Встроить сцену в экспортированное изображение",
|
||||
EXPORT_EMBED_SCENE_DESC:
|
||||
"Вставка сцены Excalidraw в экспортируемое изображение. Можно переопределить на уровне файла, добавив ключ frontmatter. <code>excalidraw-export-embed-scene: true/false<code>. " +
|
||||
"Настройка вступит в силу только при следующем (повторном) открытии чертежей.",
|
||||
EXPORT_HEAD: "Настройки автоэкспорта",
|
||||
EXPORT_SYNC_NAME: "Поддерживайте синхронизацию имен файлов .SVG и/или .PNG с файлом чертежа",
|
||||
EXPORT_SYNC_DESC:
|
||||
"Если плагин включен, он будет автоматически обновлять имена файлов .SVG и/или .PNG при переименовании чертежа в той же папке (и с тем же именем). " +
|
||||
"Плагин также автоматически удалит файлы .SVG и/или .PNG при удалении рисунка в той же папке (и с тем же именем). ",
|
||||
EXPORT_SVG_NAME: "Автоэкспорт SVG",
|
||||
EXPORT_SVG_DESC:
|
||||
"Автоматическое создание SVG-экспорта вашего чертежа, соответствующего названию файла. " +
|
||||
"Плагин сохранит файл *.SVG в той же папке, что и чертеж. " +
|
||||
"Встраивайте .svg-файл в документы вместо Excalidraw, делая вставки независимыми от платформы. " +
|
||||
"Если переключатель автоэкспорта включен, этот файл будет обновляться каждый раз, когда вы редактируете чертеж Excalidraw с соответствующим именем. " +
|
||||
"Вы можете отменить эту настройку на уровне файла, добавив ключ frontmatter <code>excalidraw-autoexport</code>.Допустимыми значениями для этого ключа являются" +
|
||||
"<code>none</code>,<code>both</code>,<code>svg</code>, и <code>png</code>.",
|
||||
EXPORT_PNG_NAME: "Автоэкспорт PNG",
|
||||
EXPORT_PNG_DESC: "То же самое, что и автоэкспорт SVG, но для *.PNG",
|
||||
EXPORT_BOTH_DARK_AND_LIGHT_NAME: "Экспорт изображения с темной и светлой тематикой",
|
||||
EXPORT_BOTH_DARK_AND_LIGHT_DESC: "Если включить эту функцию, Excalidraw будет экспортировать два файла вместо одного: filename.dark.png, filename.light.png и/или filename.dark.svg и filename.light.svg.<br>" +
|
||||
"Двойные файлы будут экспортированы как при включенном автоэкспорте SVG или PNG (или обоих), так и при нажатии кнопки экспорта на одном изображении.",
|
||||
COMPATIBILITY_HEAD: "Особенности совместимости",
|
||||
COMPATIBILITY_DESC: "Включать эти функции следует только в том случае, если у вас есть веские причины работать с файлами excalidraw.com, а не с файлами markdown. Многие функции плагина не поддерживаются в старых файлах. Типичным случаем может быть использование хранилища поверх папки проекта Visual Studio Code, а также наличие чертежей .excalidraw, к которым вы хотите получить доступ из Visual Studio Code. Другим примером может быть параллельное использование Excalidraw в Logseq и Obsidian.",
|
||||
DUMMY_TEXT_ELEMENT_LINT_SUPPORT_NAME: "Совместимость с линтерами",
|
||||
DUMMY_TEXT_ELEMENT_LINT_SUPPORT_DESC: "Excalidraw чувствителен к структуре файлов ниже <code># Excalidraw Data</code>. Автоматическая линтинговая обработка документов может создавать ошибки в Excalidraw Data. " +
|
||||
"Хотя я приложил некоторые усилия, чтобы сделать загрузку данных устойчивой к изменениям линта," +
|
||||
"это решение не является надежным.<br><mark>Лучше всего избегать линтинга или других автоматических изменений документов Excalidraw с помощью различных плагинов.</mark><br>" +
|
||||
"Используйте эту настройку, если по уважительным причинам вы решили проигнорировать мою рекомендацию и настроили линтинг файлов Excalidraw.<br> " +
|
||||
"Раздел <code>## Текстовые элементы</code> чувствителен к пустым строкам. Обычный подход к линтингу заключается в добавлении пустой строки после заголовков разделов. В случае Excalidraw это приведет к поломке/изменению первого текстового элемента в чертеже. " +
|
||||
"Чтобы решить эту проблему, можно включить эту настройку. WhenЕсли она включена, Excalidraw добавит в начало фиктивный элемент, <code>## Текстовые элементы</code> который линтер может безопасно модифицировать." ,
|
||||
PRESERVE_TEXT_AFTER_DRAWING_NAME: "Совместимость Zotero и Footnotes",
|
||||
PRESERVE_TEXT_AFTER_DRAWING_DESC: "Сохраните текст после раздела ## Чертеж в файле Markdown. Это может незначительно повлиять на производительность при сохранении очень больших рисунков.",
|
||||
DEBUGMODE_NAME: "Включить отладочные сообщения",
|
||||
DEBUGMODE_DESC: "Я рекомендую перезапустить Obsidian после включения/выключения этой настройки. Это позволяет выводить отладочные сообщения в консоль. Это полезно для устранения неполадок. " +
|
||||
"Если у вас возникли проблемы с плагином, пожалуйста, включите эту настройку, воспроизведите проблему и включите журнал консоли в проблему, которую вы поднимаете на <a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/issues'>GitHub</a>",
|
||||
SLIDING_PANES_NAME: "Поддержка плагина раздвижных областей окна (Sliding Panes plugin)",
|
||||
SLIDING_PANES_DESC:
|
||||
"Чтобы это изменение вступило в силу, необходимо перезапустить Obsidian.<br>" +
|
||||
"Если вы используете <a href='https://github.com/deathau/sliding-panes-obsidian' target='_blank'>Sliding Panes plugin</a> " +
|
||||
"Вы можете включить эту настройку, чтобы чертежи Excalidraw работали с плагином Sliding Panes.<br>" +
|
||||
"Обратите внимание, что поддержка раздвижных областей окна (Sliding Panes plugin) Excalidraw вызывает проблемы совместимости с рабочими пространствами Obsidian.<br>" +
|
||||
"Обратите внимание, что функция 'Stack Tabs' теперь доступна в Obsidian, обеспечивая встроенную поддержку большинства функций раздвижных областей окна (Sliding Panes plugin)",
|
||||
EXPORT_EXCALIDRAW_NAME: "Автоэкспорт Excalidraw",
|
||||
EXPORT_EXCALIDRAW_DESC: "Аналогично автоэкспорту SVG, но для *.Excalidraw",
|
||||
SYNC_EXCALIDRAW_NAME: "Синхронизация *.excalidraw с *.md-версией одного и того же чертежа",
|
||||
SYNC_EXCALIDRAW_DESC:
|
||||
"Если дата изменения файла *.excalidraw более поздняя, чем дата изменения файла *.md " +
|
||||
"то обновите чертеж в файле .md на основе файла .excalidraw",
|
||||
COMPATIBILITY_MODE_NAME: "Новые чертежи в виде устаревших файлов",
|
||||
COMPATIBILITY_MODE_DESC:
|
||||
"⚠️ Включайте эту функцию, только если вы знаете, что делаете. В 99,9% случаев включать эту функцию НЕ нужно. " +
|
||||
"При включении этой функции рисунки, которые вы создаете с помощью значка ленты, действий палитры команд, " +
|
||||
"и в файловом проводнике, будут все старые файлы *.excalidraw. Эта настройка также отключит напоминание" +
|
||||
"при открытии устаревшего файла для редактирования.",
|
||||
MATHJAX_NAME: "Хост библиотеки javascript MathJax (LaTeX)",
|
||||
MATHJAX_DESC: "Если вы используете уравнения LaTeX в Excalidraw, то плагину необходимо загрузить библиотеку javascript для этого. " +
|
||||
"Некоторые пользователи не могут получить доступ к определенным хост-серверам. Если у вас возникли проблемы, попробуйте сменить хост здесь. "+
|
||||
"Возможно, вам придется перезапустить Obsidian после закрытия настроек, чтобы это изменение вступило в силу.",
|
||||
LATEX_DEFAULT_NAME: "Формула LaTeX по умолчанию для новых уравнений",
|
||||
LATEX_DEFAULT_DESC: "Оставьте пустым, если вам не нужна формула по умолчанию. Здесь можно добавить форматирование по умолчанию, например <code>\\color{white}</code>.",
|
||||
NONSTANDARD_HEAD: "Поддерживаемые функции, не с Excalidraw.com",
|
||||
NONSTANDARD_DESC: `Эти настройки в разделе "Поддерживаемые функции, не относящиеся к Excalidraw.com" предоставляют возможности настройки, выходящие за рамки стандартных функций Excalidraw.com. Эти функции недоступны на сайте excalidraw.com. При экспорте чертежа в Excalidraw.com эти функции будут выглядеть иначе.
|
||||
Вы можете настроить количество пользовательских ручек, отображаемых рядом с меню Obsidian на холсте, что позволит вам выбирать из множества вариантов. Кроме того, можно включить опцию локального шрифта, которая добавляет локальный шрифт в список шрифтов на панели свойств элементов для текстовых элементов. `,
|
||||
RENDER_TWEAK_HEAD: "Улучшения рендеринга",
|
||||
MAX_IMAGE_ZOOM_IN_NAME: "Максимальное разрешение увеличения изображения",
|
||||
MAX_IMAGE_ZOOM_IN_DESC: "В целях экономии памяти и из-за того, что Apple Safari (Obsidian на iOS) имеет некоторые жестко закодированные ограничения, Excalidraw.com ограничивает максимальное разрешение изображений и крупных объектов при увеличении. Вы можете обойти это ограничение с помощью мультипликатора. " +
|
||||
"Это означает, что вы умножаете предел, установленный по умолчанию в Excalidraw. Чем больше множитель, тем лучше будет разрешение увеличения изображения, и тем больше памяти оно будет потреблять. " +
|
||||
"Я рекомендую поиграть с несколькими значениями этой настройки. Вы знаете, что натолкнулись на стену, когда при увеличении масштаба PNG-изображения оно вдруг исчезает из поля зрения. Значение по умолчанию - 1. Настройка не влияет на iOS.",
|
||||
CUSTOM_PEN_HEAD: "Пользовательские Ручки",
|
||||
CUSTOM_PEN_NAME: "Количество пользовательских ручек",
|
||||
CUSTOM_PEN_DESC: "Вы увидите эти ручки рядом с меню Obsidian на холсте. Вы можете настроить ручки на холсте, долго нажимая на кнопку ручки.",
|
||||
EXPERIMENTAL_HEAD: "Разные возможности",
|
||||
EXPERIMENTAL_DESC: `Среди прочих возможностей Excalidraw - установка формул LaTeX по умолчанию для новых уравнений, включение Предложение полей (Suggester) для автозаполнения, отображение индикаторов типов файлов Excalidraw, включение иммерсивного встраивания изображений в режиме предварительного просмотра и эксперименты с оптическим распознаванием символов Taskbone для извлечения текста из изображений и чертежей. Пользователи также могут ввести API-ключ Taskbone для расширенного использования сервиса OCR.`,
|
||||
EA_HEAD: "Автоматизация Excalidraw",
|
||||
EA_DESC:
|
||||
"Excalidraw Автоматизация - это скриптовый и автоматизированный API для Excalidraw. К сожалению, документация по API скудна. " +
|
||||
"Рекомендую прочитать <a href='https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/docs/API/ExcalidrawAutomate.d.ts'>ExcalidrawAutomate.d.ts</a> файл, " +
|
||||
"посетить <a href='https://zsviczian.github.io/obsidian-excalidraw-plugin/'>ExcalidrawAutomate How-to</a> страницу - хотя информация " +
|
||||
"здесь давно не обновлялся, - и, наконец, включите расположенный ниже Предложитель полей. Предложитель полей покажет вам доступные " +
|
||||
"функции, их параметры и краткое описание по мере ввода. Предложитель полей - это самая актуальная документация по API.",
|
||||
FIELD_SUGGESTER_NAME: "Включить Предложение полей (Suggester)",
|
||||
FIELD_SUGGESTER_DESC:
|
||||
"Предложение полей (Suggester) позаимствован у плагинов Breadcrumbs и Templater. Предложение полей (Suggester) полей будет показывать " +
|
||||
"меню автозаполнения при вводе текста с описанием функций <code>excalidraw-</code> или <code>ea.</code> в качестве подсказок для отдельных элементов в списке.",
|
||||
STARTUP_SCRIPT_NAME: "Сценарий запуска",
|
||||
STARTUP_SCRIPT_DESC:
|
||||
"Если этот параметр установлен, excalidraw будет выполнять скрипт при запуске плагина. Это полезно, если вы хотите установить какой-либо из крючков Excalidraw Automate. " +
|
||||
"Скрипт запуска - это файл в формате markdown, который должен содержать код javascript, который вы хотите выполнять при запуске Excalidraw.",
|
||||
STARTUP_SCRIPT_BUTTON_CREATE: "Создание сценария запуска",
|
||||
STARTUP_SCRIPT_BUTTON_OPEN: "Открыть сценарий запуска",
|
||||
STARTUP_SCRIPT_EXISTS: "Файл сценария запуска уже существует",
|
||||
FILETYPE_NAME: "Тип отображения (✏️) для файлов excalidraw.md в Файловом Проводнике",
|
||||
FILETYPE_DESC: "Файлы Excalidraw получат индикатор с помощью эмодзи или текста, заданного в следующей настройке.",
|
||||
FILETAG_NAME: "Установка типа индикатора для файлов excalidraw.md",
|
||||
FILETAG_DESC: "Текст или эмодзи для отображения в качестве типа индикатора.",
|
||||
INSERT_EMOJI: "Вставьте эмодзи",
|
||||
LIVEPREVIEW_NAME: "Встраивание изображений в режиме предварительного просмотра в реальном времени",
|
||||
LIVEPREVIEW_DESC:
|
||||
"Включите этот параметр для поддержки стилей вставки изображений, таких как ![[drawing|width|style]], в режиме редактирования живого предварительного просмотра. " +
|
||||
"Настройка не повлияет на открытые в данный момент документы. Чтобы изменения вступили в силу, необходимо закрыть открытые документы и" +
|
||||
"открыть их снова.",
|
||||
FADE_OUT_EXCALIDRAW_MARKUP_NAME: "Затухание разметки Excalidraw",
|
||||
FADE_OUT_EXCALIDRAW_MARKUP_DESC: "В режиме просмотра Markdown раздел после комментария %% исчезает. " +
|
||||
"Текст остается на месте, но визуальный беспорядок уменьшается. Обратите внимание, вы можете поместить %% в строку прямо над #Элементы текста, " +
|
||||
"в этом случае вся разметка рисунка исчезнет, включая #Элементы текста. Побочным эффектом будет то, что вы не сможете блокировать текст ссылок в других примечаниях, то есть после секции комментариев %%. Это редко является проблемой. " +
|
||||
"Если вы захотите отредактировать сценарий разметки Excalidraw, просто переключитесь в режим просмотра разметки и временно удалите комментарий %%.",
|
||||
EXCALIDRAW_PROPERTIES_NAME: "Загрузка свойств Excalidraw в Obsidian Suggester",
|
||||
EXCALIDRAW_PROPERTIES_DESC: "Отключите этот параметр, чтобы при запуске плагина свойства документа Excalidraw загружались в предложение свойств Obsidian. "+
|
||||
"Включение этой функции упрощает использование свойств титульного листа Excalidraw, позволяя использовать множество мощных настроек. Если вы предпочитаете не загружать эти свойства автоматически, " +
|
||||
"Вы можете отключить эту функцию, но при этом вам придется вручную удалить все ненужные свойства из предложения. " +
|
||||
"Обратите внимание, что включение этой настройки требует перезапуска плагина, так как свойства загружаются при запуске.",
|
||||
CUSTOM_FONT_HEAD: "Локальный шрифт",
|
||||
ENABLE_FOURTH_FONT_NAME: "Включите опцию локального шрифта",
|
||||
ENABLE_FOURTH_FONT_DESC:
|
||||
"Включение этой опции добавит локальный шрифт в список шрифтов на панели свойств для текстовых элементов. " +
|
||||
"Имейте в виду, что использование локального шрифта может нарушить независимость от платформы. " +
|
||||
"Файлы, использующие пользовательский шрифт, могут отображаться по-разному при открытии в другом хранилище или в более позднее время, в зависимости от настроек шрифта. " +
|
||||
"Кроме того, на сайте excalidraw.com или других версиях Excalidraw 4-й шрифт по умолчанию будет соответствовать системному шрифту.",
|
||||
FOURTH_FONT_NAME: "Локальный файл шрифта",
|
||||
FOURTH_FONT_DESC:
|
||||
"Выберите файл шрифта .otf, .ttf, .woff или .woff2 из своего хранилища, чтобы использовать его в качестве локального шрифта. " +
|
||||
"Если файл не выбран, Excalidraw по умолчанию использует шрифт Virgil. " +
|
||||
"Для оптимальной производительности рекомендуется использовать файл .woff2, так как Excalidraw закодирует только необходимые глифы при экспорте изображений в SVG. " +
|
||||
"Другие форматы шрифтов будут встраивать весь шрифт в экспортируемый файл, что может привести к значительному увеличению размера файла.",
|
||||
SCRIPT_SETTINGS_HEAD: "Настройки для установленных сценариев",
|
||||
SCRIPT_SETTINGS_DESC: "Некоторые сценарии Excalidraw Automate Scripts включают в себя настройки. Настройки упорядочены по сценариям. Настройки станут видны в этом списке только после того, как вы один раз выполните загруженный скрипт.",
|
||||
TASKBONE_HEAD: "Taskbone Оптический распознаватель символов",
|
||||
TASKBONE_DESC: "Это экспериментальная интеграция оптического распознавания символов в Excalidraw. Обратите внимание, что taskbone - это независимый внешний сервис, не предоставляемый ни Excalidraw, ни проектом плагинов Excalidraw-Obsidian. " +
|
||||
"Сервис OCR выхватывает разборчивый текст из произвольных линий и встроенных изображений на вашем холсте и помещает распознанный текст на передний план вашего рисунка, а также в буфер обмена. " +
|
||||
"Наличие текста во frontmatter позволит вам искать в Obsidian их текстовое содержание. " +
|
||||
"Обратите внимание, что процесс извлечения текста из изображения происходит не локально, а через онлайн API. Сервис taskbone хранит изображение на своих серверах только до тех пор, пока это необходимо для извлечения текста. Однако если вас это не устраивает, не используйте эту функцию.",
|
||||
TASKBONE_ENABLE_NAME: "Включить Taskbone",
|
||||
TASKBONE_ENABLE_DESC: "Включая эту услугу, вы соглашаетесь с <a href='https://www.taskbone.com/legal/terms/' target='_blank'>Условиями использования Taskbone </a> и " +
|
||||
"<a href='https://www.taskbone.com/legal/privacy/' target='_blank'>политикой конфиденциальности</a>.",
|
||||
TASKBONE_APIKEY_NAME: "Taskbone API Ключ",
|
||||
TASKBONE_APIKEY_DESC: "Taskbone предлагает бесплатную услугу с разумным количеством сканирований в месяц. Если вы хотите использовать эту функцию чаще, или вам необходимо повысить " +
|
||||
"разработчика Taskbone (как вы можете себе представить, не существует такого понятия, как «бесплатно», предоставление этого потрясающего сервиса OCR стоит разработчику Taskbone определенных денег), вы можете " +
|
||||
"приобрести платный API-ключ на сайте <a href='https://www.taskbone.com/' target='_blank'>taskbone.com</a>. Если вы уже приобрели ключ, просто перезапишите этот автоматически сгенерированный бесплатный API-ключ своим платным ключом.",
|
||||
|
||||
//HotkeyEditor
|
||||
HOTKEY_PRESS_COMBO_NANE: "Нажмите комбинацию горячих клавиш",
|
||||
HOTKEY_PRESS_COMBO_DESC: "Пожалуйста, нажмите нужную комбинацию клавиш",
|
||||
HOTKEY_BUTTON_ADD_OVERRIDE: "Добавить новое переопределение",
|
||||
HOTKEY_BUTTON_REMOVE: "Удалить",
|
||||
|
||||
//openDrawings.ts
|
||||
SELECT_FILE: "Выберите файл и нажмите Enter.",
|
||||
SELECT_COMMAND: "Выберите команду и нажмите Enter.",
|
||||
SELECT_FILE_WITH_OPTION_TO_SCALE: `Выберите файл и нажмите ENTER, или ${labelSHIFT()}+${labelMETA()}+ENTER для вставки в масштабе 100%.`,
|
||||
NO_MATCH: "Ни один файл не соответствует вашему запросу.",
|
||||
NO_MATCHING_COMMAND: "Ни одна команда не соответствует вашему запросу.",
|
||||
SELECT_FILE_TO_LINK: "Выберите файл, для которого нужно вставить ссылку.",
|
||||
SELECT_COMMAND_PLACEHOLDER: "Выберите команду, для которой нужно вставить ссылку.",
|
||||
SELECT_DRAWING: "Выберите изображение или рисунок, который необходимо вставить.",
|
||||
TYPE_FILENAME: "Введите название чертежа для выбора.",
|
||||
SELECT_FILE_OR_TYPE_NEW: "Выберите существующий чертеж или введите имя нового чертежа, затем нажмите Enter.",
|
||||
SELECT_TO_EMBED: "Выберите чертеж для вставки в активный документ.",
|
||||
SELECT_MD: "Выберите документ в формате markdown для вставки.",
|
||||
SELECT_PDF: "Выберите документ PDF для вставки.",
|
||||
PDF_PAGES_HEADER: "Страницы для загрузки?",
|
||||
PDF_PAGES_DESC: "Формат: 1, 3-5, 7, 9-11",
|
||||
|
||||
//SelectCard.ts
|
||||
TYPE_SECTION: "Введите название раздела для выбора.",
|
||||
SELECT_SECTION_OR_TYPE_NEW: "Выберите существующий раздел или введите название нового раздела, затем нажмите Enter.",
|
||||
INVALID_SECTION_NAME: "Недопустимое название раздела.",
|
||||
EMPTY_SECTION_MESSAGE: "Введите название раздела и нажмите Enter, чтобы создать новый раздел.",
|
||||
|
||||
//EmbeddedFileLoader.ts
|
||||
INFINITE_LOOP_WARNING: "ПРЕДУПРЕЖДЕНИЕ EXCALIDRAW\nОшибка при загрузке встроенных изображений из-за бесконечного цикла в файле:\n",
|
||||
|
||||
//Scripts.ts
|
||||
SCRIPT_EXECUTION_ERROR: "Ошибка выполнения сценария. Пожалуйста, найдите сообщение об ошибке в консоли разработчика.",
|
||||
|
||||
//ExcalidrawData.ts
|
||||
LOAD_FROM_BACKUP: "Файл Excalidraw был поврежден. Загрузка из резервного файла.",
|
||||
|
||||
//ObsidianMenu.tsx
|
||||
GOTO_FULLSCREEN: "Переход в полноэкранный режим",
|
||||
EXIT_FULLSCREEN: "Выход из полноэкранного режима",
|
||||
TOGGLE_FULLSCREEN: "Переключить полноэкранный режим",
|
||||
TOGGLE_DISABLEBINDING: "Переключить инвертирование поведения привязки по умолчанию",
|
||||
TOGGLE_FRAME_RENDERING: "Переключить рендеринг кадра",
|
||||
TOGGLE_FRAME_CLIPPING: "Переключить обрезку кадра",
|
||||
OPEN_LINK_CLICK: "Открыть ссылку",
|
||||
OPEN_LINK_PROPS: "Открыть ссылку на изображение или редактор формул LaTeX",
|
||||
|
||||
//IFrameActionsMenu.tsx
|
||||
NARROW_TO_HEADING: "Узкий к заголовку...",
|
||||
NARROW_TO_BLOCK: "Сузить до блока...",
|
||||
SHOW_ENTIRE_FILE: "Показать весь файл",
|
||||
ZOOM_TO_FIT: "Увеличить до нужного размера",
|
||||
RELOAD: "Перезагрузить исходную ссылку",
|
||||
OPEN_IN_BROWSER: "Открыть текущую ссылку в браузере",
|
||||
PROPERTIES: "Свойства",
|
||||
COPYCODE: "Копировать источник в буфер обмена",
|
||||
|
||||
//EmbeddableSettings.tsx
|
||||
ES_TITLE: "Настройки встраиваемых элементов",
|
||||
ES_RENAME: "Переименовать файл",
|
||||
ES_ZOOM: "Масштабирование встраиваемого контента",
|
||||
ES_YOUTUBE_START: "Время начала YouTube",
|
||||
ES_YOUTUBE_START_DESC: "ss, mm:ss, hh:mm:ss",
|
||||
ES_YOUTUBE_START_INVALID: "Время начала YouTube недействительно. Проверьте формат и повторите попытку.",
|
||||
ES_FILENAME_VISIBLE: "Видимое имя файла",
|
||||
ES_BACKGROUND_HEAD: "Цвет фона встроенной заметки",
|
||||
ES_BACKGROUND_MATCH_ELEMENT: "Соответствие фонового цвета элемента",
|
||||
ES_BACKGROUND_MATCH_CANVAS: "Соответствие цвета фона холста",
|
||||
ES_BACKGROUND_COLOR: "Цвет фона",
|
||||
ES_BORDER_HEAD: "Цвет границы встроенной заметки",
|
||||
ES_BORDER_COLOR: "Цвет границы",
|
||||
ES_BORDER_MATCH_ELEMENT: "Цвет границы элемента",
|
||||
ES_BACKGROUND_OPACITY: "Непрозрачность фона",
|
||||
ES_BORDER_OPACITY: "Непрозрачность границы",
|
||||
ES_EMBEDDABLE_SETTINGS: "Настройки встраиваемой разметки",
|
||||
ES_USE_OBSIDIAN_DEFAULTS: "Использовать настройки Obsidian по умолчанию",
|
||||
ES_ZOOM_100_RELATIVE_DESC: "Кнопка настроит масштаб элемента так, чтобы он отображал содержимое на 100% относительно текущего уровня масштабирования холста",
|
||||
ES_ZOOM_100: "Относительный 100%",
|
||||
|
||||
//Prompts.ts
|
||||
PROMPT_FILE_DOES_NOT_EXIST: "Файл не существует. Вы хотите его создать?",
|
||||
PROMPT_ERROR_NO_FILENAME: "Ошибка: Имя нового файла не может быть пустым",
|
||||
PROMPT_ERROR_DRAWING_CLOSED: "Неизвестная ошибка. Похоже, что ваш чертеж был закрыт или файл чертежа отсутствует",
|
||||
PROMPT_TITLE_NEW_FILE: "Новый файл",
|
||||
PROMPT_TITLE_CONFIRMATION: "Подтверждение",
|
||||
PROMPT_BUTTON_CREATE_EXCALIDRAW: "Создать EX",
|
||||
PROMPT_BUTTON_CREATE_EXCALIDRAW_ARIA: "Создать чертеж Excalidraw и открыть его в новой вкладке",
|
||||
PROMPT_BUTTON_CREATE_MARKDOWN: "Создать MD",
|
||||
PROMPT_BUTTON_CREATE_MARKDOWN_ARIA: "Создать документ в формате markdown и открыть его в новой вкладке",
|
||||
PROMPT_BUTTON_EMBED_MARKDOWN: "Встроить MD",
|
||||
PROMPT_BUTTON_EMBED_MARKDOWN_ARIA: "Замена выбранного элемента встроенным документом с разметкой",
|
||||
PROMPT_BUTTON_NEVERMIND: "Неважно",
|
||||
PROMPT_BUTTON_OK: "OK",
|
||||
PROMPT_BUTTON_CANCEL: "Отменить",
|
||||
PROMPT_BUTTON_INSERT_LINE: "Вставить новую строку",
|
||||
PROMPT_BUTTON_INSERT_SPACE: "Вставить пробел",
|
||||
PROMPT_BUTTON_INSERT_LINK: "Вставить ссылку на файл в формате markdown",
|
||||
PROMPT_BUTTON_UPPERCASE: "Прописные буквы",
|
||||
PROMPT_SELECT_TEMPLATE: "Выберите шаблон",
|
||||
|
||||
//ModifierKeySettings
|
||||
WEB_BROWSER_DRAG_ACTION: "Действие перетаскивания веб-браузера",
|
||||
LOCAL_FILE_DRAG_ACTION: "Действие перетаскивания локального файла ОС",
|
||||
INTERNAL_DRAG_ACTION: "Внутреннее действие перетаскивания в Obsidian",
|
||||
PANE_TARGET: "Поведение при нажатии на ссылку",
|
||||
DEFAULT_ACTION_DESC: "Если ни одна из комбинаций не применяется, для этой группы будет действовать действие по умолчанию: ",
|
||||
|
||||
//FrameSettings.ts
|
||||
FRAME_SETTINGS_TITLE: "Настройки кадров",
|
||||
FRAME_SETTINGS_ENABLE: "Включить кадры",
|
||||
FRAME_SETTIGNS_NAME: "Отображение имени кадра",
|
||||
FRAME_SETTINGS_OUTLINE: "Отображение контура кадра",
|
||||
FRAME_SETTINGS_CLIP: "Включить обрезку кадра",
|
||||
|
||||
//InsertPDFModal.ts
|
||||
IPM_PAGES_TO_IMPORT_NAME: "Страницы для импорта",
|
||||
IPM_SELECT_PAGES_TO_IMPORT: "Пожалуйста, выберите страницы для импорта",
|
||||
IPM_ADD_BORDER_BOX_NAME: "Добавить рамку",
|
||||
IPM_ADD_FRAME_NAME: "Добавить страницу в кадр",
|
||||
IPM_ADD_FRAME_DESC: "Для удобства работы я рекомендую зафиксировать страницу внутри кадра. " +
|
||||
"Однако если вы заблокировали страницу внутри кадра, то единственный способ разблокировать ее - щелкнуть правой кнопкой мыши кадр, выбрать пункт «Удалить элементы из кадра», а затем разблокировать страницу.",
|
||||
IPM_GROUP_PAGES_NAME: "Страницы группы",
|
||||
IPM_GROUP_PAGES_DESC: "Это позволит объединить все страницы в одну группу. Это рекомендуется делать, если вы блокируете страницы после импорта, потому что группу будет легче разблокировать позже, чем разблокировать каждую по отдельности.",
|
||||
IPM_SELECT_PDF: "Пожалуйста, выберите файл PDF",
|
||||
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
import { TAG_AUTOEXPORT, TAG_MDREADINGMODE, TAG_PDFEXPORT } from "src/constants/constSettingsTags";
|
||||
import { labelALT, labelCTRL, labelMETA, labelSHIFT } from "src/utils/ModifierkeyHelper";
|
||||
|
||||
const CJK_FONTS = "CJK Fonts";
|
||||
// 简体中文
|
||||
export default {
|
||||
// main.ts
|
||||
@@ -187,7 +188,7 @@ export default {
|
||||
|
||||
BASIC_HEAD: "基本",
|
||||
BASIC_DESC: `包括:更新说明,更新提示,新绘图文件、模板文件、脚本文件的存储路径等的设置。`,
|
||||
FOLDER_NAME: "Excalidraw 文件夹",
|
||||
FOLDER_NAME: "Excalidraw 文件夹(區分大小寫!)",
|
||||
FOLDER_DESC:
|
||||
"新绘图的默认存储路径。若为空,将在库的根目录中创建新绘图。",
|
||||
CROP_PREFIX_NAME: "剪贴文件的前缀",
|
||||
@@ -201,10 +202,10 @@ export default {
|
||||
ANNOTATE_PRESERVE_SIZE_NAME: "在标注时保留图像尺寸",
|
||||
ANNOTATE_PRESERVE_SIZE_DESC:
|
||||
"当在 Markdown 中标注图像时,替换后的图像链接将包含原始图像的宽度。",
|
||||
CROP_FOLDER_NAME: "剪贴文件文件夹",
|
||||
CROP_FOLDER_NAME: "剪贴文件文件夹(區分大小寫!)",
|
||||
CROP_FOLDER_DESC:
|
||||
"剪贴图像时创建新绘图的默认存储路径。如果留空,将按照 Vault 附件设置创建。",
|
||||
ANNOTATE_FOLDER_NAME: "图片标注文件文件夹",
|
||||
ANNOTATE_FOLDER_NAME: "图片标注文件文件夹(區分大小寫!)",
|
||||
ANNOTATE_FOLDER_DESC:
|
||||
"创建图片标注是的默认存储路径。如果留空,将按照 Vault 附件设置创建。",
|
||||
FOLDER_EMBED_NAME:
|
||||
@@ -213,7 +214,7 @@ export default {
|
||||
"在命令面板中执行“新建绘图”系列命令时," +
|
||||
"新建的绘图文件的存储路径。<br>" +
|
||||
"<b>开启:</b>使用上面的 Excalidraw 文件夹。 <br><b>关闭:</b>使用 Obsidian 设置的新附件默认位置。",
|
||||
TEMPLATE_NAME: "Excalidraw 模板文件",
|
||||
TEMPLATE_NAME: "Excalidraw 模板文件(區分大小寫!)",
|
||||
TEMPLATE_DESC:
|
||||
"Excalidraw 模板文件(文件夹)的存储路径。<br>" +
|
||||
"<b>模板文件:</b>比如:如果您的模板在默认的 Excalidraw 文件夹中且文件名是 " +
|
||||
@@ -747,6 +748,8 @@ FILENAME_HEAD: "文件名",
|
||||
"启用此功能简化了 Excalidraw 前置属性的使用,使您能够利用许多强大的设置。如果您不希望自动加载这些属性," +
|
||||
"您可以禁用此功能,但您将需要手动从自动提示中移除任何不需要的属性。" +
|
||||
"请注意,启用此设置需要重启插件,因为属性是在启动时加载的。",
|
||||
FONTS_HEAD: "字体",
|
||||
FONTS_DESC: "配置本地字体并下载的 CJK 字体以供 Excalidraw 使用。",
|
||||
CUSTOM_FONT_HEAD: "本地字体",
|
||||
ENABLE_FOURTH_FONT_NAME: "为文本元素启用本地字体",
|
||||
ENABLE_FOURTH_FONT_DESC:
|
||||
@@ -760,6 +763,20 @@ FILENAME_HEAD: "文件名",
|
||||
"如果没有选择文件,Excalidraw 将默认使用 Virgil 字体。"+
|
||||
"为了获得最佳性能,建议使用 .woff2 文件,因为当导出到 SVG 格式的图像时,Excalidraw 只会编码必要的字形。"+
|
||||
"其他字体格式将在导出文件中嵌入整个字体,可能会导致文件大小显著增加。<mark>译者注:</mark>您可以在<a href='https://wangchujiang.com/free-font/' target='_blank'>Free Font</a>获取免费商用中文手写字体。",
|
||||
OFFLINE_CJK_NAME: "离线 CJK 字体支持",
|
||||
OFFLINE_CJK_DESC:
|
||||
`<strong>您在这里所做的更改将在重启 Obsidian 后生效。</strong><br>
|
||||
Excalidraw.com 提供手写风格的 CJK 字体。默认情况下,这些字体并未在插件中本地包含,而是从互联网获取。
|
||||
如果您希望 Excalidraw 完全本地化,以便在没有互联网连接的情况下使用,可以从 <a href="https://github.com/zsviczian/obsidian-excalidraw-plugin/raw/refs/heads/master/assets/excalidraw-fonts.zip" target="_blank">GitHub 下载所需的字体文件</a>。
|
||||
下载后,将内容解压到您的 Vault 中的一个文件夹内。<br>
|
||||
预加载字体会影响启动性能。因此,您可以选择加载哪些字体。`,
|
||||
CJK_ASSETS_FOLDER_NAME: "CJK 字体文件夹(區分大小寫!)",
|
||||
CJK_ASSETS_FOLDER_DESC: `您可以在此设置 CJK 字体文件夹的位置。例如,您可以选择将其放置在 <code>Excalidraw/CJK Fonts</code> 下。<br><br>
|
||||
<strong>重要:</strong> 请勿将此文件夹设置为 Vault 根目录!请勿在此文件夹中放置其他字体。<br><br>
|
||||
<strong>注意:</strong> 如果您使用 Obsidian Sync 并希望在设备之间同步这些字体文件,请确保 Obsidian Sync 设置为同步“所有其他文件类型”。`,
|
||||
LOAD_CHINESE_FONTS_NAME: "启动时从文件加载中文字体",
|
||||
LOAD_JAPANESE_FONTS_NAME: "启动时从文件加载日文字体",
|
||||
LOAD_KOREAN_FONTS_NAME: "启动时从文件加载韩文字体",
|
||||
SCRIPT_SETTINGS_HEAD: "已安装脚本的设置",
|
||||
SCRIPT_SETTINGS_DESC: "有些 Excalidraw 自动化脚本包含设置项,当执行这些脚本时,它们会在该列表下添加设置项。",
|
||||
TASKBONE_HEAD: "Taskbone OCR(光学符号识别)",
|
||||
@@ -816,7 +833,35 @@ FILENAME_HEAD: "文件名",
|
||||
|
||||
//ExcalidrawData.ts
|
||||
LOAD_FROM_BACKUP: "Excalidraw 文件已损坏。尝试从备份文件中加载。",
|
||||
|
||||
FONT_LOAD_SLOW: "正在加载字体...\n\n 这比预期花费的时间更长。如果这种延迟经常发生,您可以将字体下载到您的 Vault 中。\n\n" +
|
||||
"(点击=忽略提示,右键=更多信息)",
|
||||
FONT_INFO_TITLE: "从互联网加载 v2.5.3 字体",
|
||||
FONT_INFO_DETAILED: `
|
||||
<p>
|
||||
为了提高 Obsidian 的启动时间并管理大型 <strong>CJK 字体系列</strong>,
|
||||
我已将 CJK 字体移出插件的 <code>main.js</code>。默认情况下,CJK 字体将从互联网加载。
|
||||
这通常不会造成问题,因为 Obsidian 在首次使用后会缓存这些文件。
|
||||
</p>
|
||||
<p>
|
||||
如果您希望 Obsidian 完全离线或遇到性能问题,可以下载字体资源。
|
||||
</p>
|
||||
<h3>说明:</h3>
|
||||
<ol>
|
||||
<li>从 <a href="https://github.com/zsviczian/obsidian-excalidraw-plugin/raw/refs/heads/master/assets/excalidraw-fonts.zip">GitHub</a> 下载字体。</li>
|
||||
<li>解压并将文件复制到 Vault 文件夹中(默认:<code>Excalidraw/${CJK_FONTS}</code>; 文件夹名称區分大小寫!)。</li>
|
||||
<li><mark>请勿</mark>将此文件夹设置为 Vault 根目录或与其他本地字体混合。</li>
|
||||
</ol>
|
||||
<h3>对于 Obsidian Sync 用户:</h3>
|
||||
<p>
|
||||
确保 Obsidian Sync 设置为同步“所有其他文件类型”,或者在所有设备上下载并解压文件。
|
||||
</p>
|
||||
<h3>注意:</h3>
|
||||
<p>
|
||||
如果您觉得这个过程繁琐,请向 Obsidian.md 提交功能请求,以支持插件文件夹中的资源。
|
||||
目前,仅支持(同步)单个 <code>main.js</code>,这导致大型文件和复杂插件(如 Excalidraw)启动时间较慢。
|
||||
对此带来的不便,我深表歉意。
|
||||
</p>
|
||||
`,
|
||||
//ObsidianMenu.tsx
|
||||
GOTO_FULLSCREEN: "进入全屏模式",
|
||||
EXIT_FULLSCREEN: "退出全屏模式",
|
||||
|
||||
207
src/main.ts
207
src/main.ts
@@ -45,6 +45,8 @@ import {
|
||||
DEVICE,
|
||||
sceneCoordsToViewportCoords,
|
||||
FONTS_STYLE_ID,
|
||||
CJK_STYLE_ID,
|
||||
updateExcalidrawLib,
|
||||
} from "./constants/constants";
|
||||
import ExcalidrawView, { TextMode, getTextMode } from "./ExcalidrawView";
|
||||
import {
|
||||
@@ -140,8 +142,12 @@ import { Rank, SwordColors } from "./menu/ActionIcons";
|
||||
import { RankMessage } from "./dialogs/RankMessage";
|
||||
import { initCompressionWorker, terminateCompressionWorker } from "./workers/compression-worker";
|
||||
import { WeakArray } from "./utils/WeakArray";
|
||||
import { getCJKDataURLs } from "./utils/CJKLoader";
|
||||
import ExcalidrawLoading from "./dialogs/ExcalidrawLoading";
|
||||
|
||||
declare let EXCALIDRAW_PACKAGES:string;
|
||||
declare let EXCALIDRAW_PACKAGE:string;
|
||||
declare let REACT_PACKAGES:string;
|
||||
declare const unpackExcalidraw: Function;
|
||||
declare let react:any;
|
||||
declare let reactDOM:any;
|
||||
declare let excalidrawLib: typeof ExcalidrawLib;
|
||||
@@ -193,6 +199,8 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
//private slob:string;
|
||||
private ribbonIcon:HTMLElement;
|
||||
public loadTimestamp:number;
|
||||
private isLocalCJKFontAvailabe:boolean = undefined
|
||||
public isReady = false;
|
||||
|
||||
constructor(app: App, manifest: PluginManifest) {
|
||||
super(app, manifest);
|
||||
@@ -267,7 +275,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
//@ts-ignore
|
||||
const {react:r, reactDOM:rd, excalidrawLib:e} = win.eval.call(win,
|
||||
`(function() {
|
||||
${EXCALIDRAW_PACKAGES};
|
||||
${REACT_PACKAGES + EXCALIDRAW_PACKAGE};
|
||||
return {react:React,reactDOM:ReactDOM,excalidrawLib:ExcalidrawLib};
|
||||
})()`);
|
||||
this.packageMap.set(win,{react:r, reactDOM:rd, excalidrawLib:e});
|
||||
@@ -313,9 +321,28 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
};
|
||||
}*/
|
||||
|
||||
public async loadFontFromFile(fontName: string): Promise<ArrayBuffer> {
|
||||
const assetsFoler = "Fonts/";
|
||||
const file = this.app.vault.getAbstractFileByPath(assetsFoler + fontName);
|
||||
public getCJKFontSettings() {
|
||||
const assetsFoler = this.settings.fontAssetsPath;
|
||||
if(typeof this.isLocalCJKFontAvailabe === "undefined") {
|
||||
this.isLocalCJKFontAvailabe = this.app.vault.getFiles().some(f=>f.path.startsWith(assetsFoler));
|
||||
}
|
||||
if(!this.isLocalCJKFontAvailabe) {
|
||||
return { c: false, j: false, k: false };
|
||||
}
|
||||
return {
|
||||
c: this.settings.loadChineseFonts,
|
||||
j: this.settings.loadJapaneseFonts,
|
||||
k: this.settings.loadKoreanFonts,
|
||||
}
|
||||
}
|
||||
|
||||
public async loadFontFromFile(fontName: string): Promise<ArrayBuffer|undefined> {
|
||||
const assetsFoler = this.settings.fontAssetsPath;
|
||||
|
||||
if(!this.isLocalCJKFontAvailabe) {
|
||||
return;
|
||||
}
|
||||
const file = this.app.vault.getAbstractFileByPath(normalizePath(assetsFoler + "/" + fontName));
|
||||
if(!file || !(file instanceof TFile)) {
|
||||
return;
|
||||
}
|
||||
@@ -323,11 +350,18 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
}
|
||||
|
||||
async onload() {
|
||||
initCompressionWorker();
|
||||
this.loadTimestamp = Date.now();
|
||||
addIcon(ICON_NAME, EXCALIDRAW_ICON);
|
||||
addIcon(SCRIPTENGINE_ICON_NAME, SCRIPTENGINE_ICON);
|
||||
addIcon(EXPORT_IMG_ICON_NAME, EXPORT_IMG_ICON);
|
||||
this.registerView(
|
||||
VIEW_TYPE_EXCALIDRAW,
|
||||
(leaf: WorkspaceLeaf) => {
|
||||
if(this.isReady) {
|
||||
return new ExcalidrawView(leaf, this);
|
||||
} else {
|
||||
return new ExcalidrawLoading(leaf, this);
|
||||
}
|
||||
},
|
||||
);
|
||||
//Compatibility mode with .excalidraw files
|
||||
this.registerExtensions(["excalidraw"], VIEW_TYPE_EXCALIDRAW);
|
||||
|
||||
await this.loadSettings({reEnableAutosave:true});
|
||||
const updateSettings = !this.settings.onceOffCompressFlagReset || !this.settings.onceOffGPTVersionReset;
|
||||
@@ -343,68 +377,83 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
if(updateSettings) {
|
||||
await this.saveSettings();
|
||||
}
|
||||
this.excalidrawConfig = new ExcalidrawConfig(this);
|
||||
await loadMermaid();
|
||||
this.editorHandler = new EditorHandler(this);
|
||||
this.editorHandler.setup();
|
||||
|
||||
this.addSettingTab(new ExcalidrawSettingTab(this.app, this));
|
||||
this.ea = await initExcalidrawAutomate(this);
|
||||
|
||||
this.registerView(
|
||||
VIEW_TYPE_EXCALIDRAW,
|
||||
(leaf: WorkspaceLeaf) => new ExcalidrawView(leaf, this),
|
||||
);
|
||||
|
||||
//Compatibility mode with .excalidraw files
|
||||
this.registerExtensions(["excalidraw"], VIEW_TYPE_EXCALIDRAW);
|
||||
|
||||
this.addMarkdownPostProcessor();
|
||||
this.registerInstallCodeblockProcessor();
|
||||
this.addThemeObserver();
|
||||
this.experimentalFileTypeDisplayToggle(this.settings.experimentalFileType);
|
||||
this.registerCommands();
|
||||
this.registerEventListeners();
|
||||
this.runStartupScript();
|
||||
this.initializeFonts();
|
||||
this.registerEditorSuggest(new FieldSuggester(this));
|
||||
this.setPropertyTypes();
|
||||
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
unpackExcalidraw();
|
||||
excalidrawLib = window.eval.call(window,`(function() {${EXCALIDRAW_PACKAGE};return ExcalidrawLib;})()`);
|
||||
this.packageMap.set(window,{react, reactDOM, excalidrawLib});
|
||||
updateExcalidrawLib();
|
||||
initCompressionWorker();
|
||||
this.loadTimestamp = Date.now();
|
||||
addIcon(ICON_NAME, EXCALIDRAW_ICON);
|
||||
addIcon(SCRIPTENGINE_ICON_NAME, SCRIPTENGINE_ICON);
|
||||
addIcon(EXPORT_IMG_ICON_NAME, EXPORT_IMG_ICON);
|
||||
|
||||
//inspiration taken from kanban:
|
||||
//https://github.com/mgmeyers/obsidian-kanban/blob/44118e25661bff9ebfe54f71ae33805dc88ffa53/src/main.ts#L267
|
||||
this.registerMonkeyPatches();
|
||||
this.excalidrawConfig = new ExcalidrawConfig(this);
|
||||
await loadMermaid();
|
||||
this.editorHandler = new EditorHandler(this);
|
||||
this.editorHandler.setup();
|
||||
|
||||
this.registerInstallCodeblockProcessor();
|
||||
this.addThemeObserver();
|
||||
this.experimentalFileTypeDisplayToggle(this.settings.experimentalFileType);
|
||||
this.registerCommands();
|
||||
this.registerEventListeners();
|
||||
this.runStartupScript();
|
||||
this.initializeFonts();
|
||||
this.registerEditorSuggest(new FieldSuggester(this));
|
||||
this.setPropertyTypes();
|
||||
|
||||
this.stylesManager = new StylesManager(this);
|
||||
//inspiration taken from kanban:
|
||||
//https://github.com/mgmeyers/obsidian-kanban/blob/44118e25661bff9ebfe54f71ae33805dc88ffa53/src/main.ts#L267
|
||||
this.registerMonkeyPatches();
|
||||
|
||||
// const patches = new OneOffs(this);
|
||||
if (this.settings.showReleaseNotes) {
|
||||
//I am repurposing imageElementNotice, if the value is true, this means the plugin was just newly installed to Obsidian.
|
||||
const obsidianJustInstalled = this.settings.previousRelease === "0.0.0"
|
||||
this.stylesManager = new StylesManager(this);
|
||||
|
||||
if (isVersionNewerThanOther(PLUGIN_VERSION, this.settings.previousRelease)) {
|
||||
new ReleaseNotes(
|
||||
this.app,
|
||||
this,
|
||||
obsidianJustInstalled ? null : PLUGIN_VERSION,
|
||||
).open();
|
||||
// const patches = new OneOffs(this);
|
||||
if (this.settings.showReleaseNotes) {
|
||||
//I am repurposing imageElementNotice, if the value is true, this means the plugin was just newly installed to Obsidian.
|
||||
const obsidianJustInstalled = this.settings.previousRelease === "0.0.0"
|
||||
|
||||
if (isVersionNewerThanOther(PLUGIN_VERSION, this.settings.previousRelease)) {
|
||||
new ReleaseNotes(
|
||||
this.app,
|
||||
this,
|
||||
obsidianJustInstalled ? null : PLUGIN_VERSION,
|
||||
).open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.switchToExcalidarwAfterLoad();
|
||||
this.switchToExcalidarwAfterLoad();
|
||||
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.onload,"ExcalidrawPlugin.onload > app.workspace.onLayoutReady");
|
||||
this.scriptEngine = new ScriptEngine(this);
|
||||
imageCache.initializeDB(this);
|
||||
this.taskbone = new Taskbone(this);
|
||||
this.isReady = true;
|
||||
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.onload,"ExcalidrawPlugin.onload > app.workspace.onLayoutReady");
|
||||
this.scriptEngine = new ScriptEngine(this);
|
||||
imageCache.initializeDB(this);
|
||||
});
|
||||
});
|
||||
this.taskbone = new Taskbone(this);
|
||||
}
|
||||
|
||||
public async awaitInit() {
|
||||
let counter = 0;
|
||||
while(!this.isReady && counter < 150) {
|
||||
await sleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
private setPropertyTypes() {
|
||||
if(!this.settings.loadPropertySuggestions) return;
|
||||
const app = this.app;
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.setPropertyTypes, `ExcalidrawPlugin.setPropertyTypes > app.workspace.onLayoutReady`);
|
||||
await this.awaitInit();
|
||||
Object.keys(FRONTMATTER_KEYS).forEach((key) => {
|
||||
if(FRONTMATTER_KEYS[key].depricated === true) return;
|
||||
const {name, type} = FRONTMATTER_KEYS[key];
|
||||
@@ -416,7 +465,22 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
public initializeFonts() {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.initializeFonts, `ExcalidrawPlugin.initializeFonts > app.workspace.onLayoutReady`);
|
||||
|
||||
await this.awaitInit();
|
||||
const cjkFontDataURLs = await getCJKDataURLs(this);
|
||||
if(typeof cjkFontDataURLs === "boolean" && !cjkFontDataURLs) {
|
||||
new Notice(t("FONTS_LOAD_ERROR") + this.settings.fontAssetsPath,6000);
|
||||
}
|
||||
|
||||
if(typeof cjkFontDataURLs === "object") {
|
||||
const fontDeclarations = cjkFontDataURLs.map(dataURL =>
|
||||
`@font-face { font-family: 'Xiaolai'; src: url("${dataURL}"); font-display: swap; font-weight: 400; }`
|
||||
);
|
||||
for(const ownerDocument of this.getOpenObsidianDocuments()) {
|
||||
await this.addFonts(fontDeclarations, ownerDocument, CJK_STYLE_ID);
|
||||
};
|
||||
new Notice(t("FONTS_LOADED"));
|
||||
}
|
||||
|
||||
const font = await getFontDataURL(
|
||||
this.app,
|
||||
this.settings.experimantalFourthFont,
|
||||
@@ -458,12 +522,12 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
});
|
||||
}
|
||||
|
||||
public async addFonts(declarations: string[],ownerDocument:Document = document) {
|
||||
public async addFonts(declarations: string[],ownerDocument:Document = document, styleId:string = FONTS_STYLE_ID) {
|
||||
// replace the old local font <style> element with the one we just created
|
||||
const newStylesheet = ownerDocument.createElement("style");
|
||||
newStylesheet.id = FONTS_STYLE_ID;
|
||||
newStylesheet.id = styleId;
|
||||
newStylesheet.textContent = declarations.join("");
|
||||
const oldStylesheet = ownerDocument.getElementById(FONTS_STYLE_ID);
|
||||
const oldStylesheet = ownerDocument.getElementById(styleId);
|
||||
ownerDocument.head.appendChild(newStylesheet);
|
||||
if (oldStylesheet) {
|
||||
ownerDocument.head.removeChild(oldStylesheet);
|
||||
@@ -473,11 +537,15 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
|
||||
public removeFonts() {
|
||||
this.getOpenObsidianDocuments().forEach((ownerDocument) => {
|
||||
const oldStylesheet = ownerDocument.getElementById(FONTS_STYLE_ID);
|
||||
if (oldStylesheet) {
|
||||
ownerDocument.head.removeChild(oldStylesheet);
|
||||
const oldCustomFontStylesheet = ownerDocument.getElementById(FONTS_STYLE_ID);
|
||||
if (oldCustomFontStylesheet) {
|
||||
ownerDocument.head.removeChild(oldCustomFontStylesheet);
|
||||
}
|
||||
})
|
||||
const oldCJKFontStylesheet = ownerDocument.getElementById(CJK_STYLE_ID);
|
||||
if (oldCJKFontStylesheet) {
|
||||
ownerDocument.head.removeChild(oldCJKFontStylesheet);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getOpenObsidianDocuments(): Document[] {
|
||||
@@ -493,8 +561,9 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
}
|
||||
|
||||
private switchToExcalidarwAfterLoad() {
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.switchToExcalidarwAfterLoad, `ExcalidrawPlugin.switchToExcalidarwAfterLoad > app.workspace.onLayoutReady`);
|
||||
await this.awaitInit();
|
||||
let leaf: WorkspaceLeaf;
|
||||
for (leaf of this.app.workspace.getLeavesOfType("markdown")) {
|
||||
if ( leaf.view instanceof MarkdownView && this.isExcalidrawFile(leaf.view.file)) {
|
||||
@@ -726,9 +795,9 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
initializeMarkdownPostProcessor(this);
|
||||
this.registerMarkdownPostProcessor(markdownPostProcessor);
|
||||
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.addMarkdownPostProcessor, `ExcalidrawPlugin.addMarkdownPostProcessor > app.workspace.onLayoutReady`);
|
||||
|
||||
await this.awaitInit();
|
||||
// internal-link quick preview
|
||||
this.registerEvent(this.app.workspace.on("hover-link", hoverEvent));
|
||||
|
||||
@@ -848,8 +917,9 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
? new CustomMutationObserver(fileExplorerObserverFn, "fileExplorerObserver")
|
||||
: new MutationObserver(fileExplorerObserverFn);
|
||||
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.experimentalFileTypeDisplay, `ExcalidrawPlugin.experimentalFileTypeDisplay > app.workspace.onLayoutReady`);
|
||||
await this.awaitInit();
|
||||
document.querySelectorAll(".nav-file-title").forEach(insertFiletype); //apply filetype to files already displayed
|
||||
const container = document.querySelector(".nav-files-container");
|
||||
if (container) {
|
||||
@@ -2721,6 +2791,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
}
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.runStartupScript, `ExcalidrawPlugin.runStartupScript > app.workspace.onLayoutReady, scriptPath:${this.settings?.startupScriptPath}`);
|
||||
await this.awaitInit();
|
||||
const path = this.settings.startupScriptPath.endsWith(".md")
|
||||
? this.settings.startupScriptPath
|
||||
: `${this.settings.startupScriptPath}.md`;
|
||||
@@ -2881,6 +2952,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
private registerEventListeners() {
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.registerEventListeners,`ExcalidrawPlugin.registerEventListeners > app.workspace.onLayoutReady`);
|
||||
await this.awaitInit();
|
||||
const onPasteHandler = (
|
||||
evt: ClipboardEvent,
|
||||
editor: Editor,
|
||||
@@ -3329,7 +3401,8 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
|
||||
this.settings = null;
|
||||
clearMathJaxVariables();
|
||||
EXCALIDRAW_PACKAGES = "";
|
||||
EXCALIDRAW_PACKAGE = "";
|
||||
REACT_PACKAGES = "";
|
||||
//pluginPackages = null;
|
||||
PLUGIN_VERSION = null;
|
||||
//@ts-ignore
|
||||
|
||||
105
src/settings.ts
105
src/settings.ts
@@ -50,6 +50,9 @@ export interface ExcalidrawSettings {
|
||||
templateFilePath: string;
|
||||
scriptFolderPath: string;
|
||||
fontAssetsPath: string;
|
||||
loadChineseFonts: boolean;
|
||||
loadJapaneseFonts: boolean;
|
||||
loadKoreanFonts: boolean;
|
||||
compress: boolean;
|
||||
decompressForMDView: boolean;
|
||||
onceOffCompressFlagReset: boolean; //used to reset compress to true in 2.2.0
|
||||
@@ -206,6 +209,7 @@ export interface ExcalidrawSettings {
|
||||
areaZoomLimit: number;
|
||||
longPressDesktop: number;
|
||||
longPressMobile: number;
|
||||
doubleClickLinkOpenViewMode: boolean;
|
||||
isDebugMode: boolean;
|
||||
rank: Rank;
|
||||
modifierKeyOverrides: {modifiers: Modifier[], key: string}[];
|
||||
@@ -221,7 +225,10 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
embedUseExcalidrawFolder: false,
|
||||
templateFilePath: "Excalidraw/Template.excalidraw",
|
||||
scriptFolderPath: "Excalidraw/Scripts",
|
||||
fontAssetsPath: "Excalidraw/FontAssets",
|
||||
fontAssetsPath: "Excalidraw/CJK Fonts",
|
||||
loadChineseFonts: false,
|
||||
loadJapaneseFonts: false,
|
||||
loadKoreanFonts: false,
|
||||
compress: true,
|
||||
decompressForMDView: false,
|
||||
onceOffCompressFlagReset: false,
|
||||
@@ -474,6 +481,7 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
areaZoomLimit: 1,
|
||||
longPressDesktop: 500,
|
||||
longPressMobile: 500,
|
||||
doubleClickLinkOpenViewMode: true,
|
||||
isDebugMode: false,
|
||||
rank: "Bronze",
|
||||
modifierKeyOverrides: [
|
||||
@@ -722,19 +730,6 @@ 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
|
||||
// ------------------------------------------------
|
||||
@@ -1500,6 +1495,18 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
el.innerText = ` ${this.plugin.settings.longPressMobile.toString()}`;
|
||||
});
|
||||
|
||||
new Setting(detailsEl)
|
||||
.setName(t("DOUBLE_CLICK_LINK_OPEN_VIEW_MODE"))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.doubleClickLinkOpenViewMode)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.doubleClickLinkOpenViewMode = value;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
new ModifierKeySettingsComponent(
|
||||
detailsEl,
|
||||
this.plugin.settings.modifierKeyConfig,
|
||||
@@ -2345,7 +2352,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
d.addOption("Assistant", "Assistant");
|
||||
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);
|
||||
});
|
||||
@@ -2470,8 +2477,20 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
this.applySettingsUpdate(false);
|
||||
})
|
||||
)
|
||||
|
||||
// ------------------------------------------------
|
||||
// Fonts supported features
|
||||
// ------------------------------------------------
|
||||
containerEl.createEl("hr", { cls: "excalidraw-setting-hr" });
|
||||
containerEl.createDiv({ text: t("FONTS_DESC"), cls: "setting-item-description" });
|
||||
detailsEl = this.containerEl.createEl("details");
|
||||
const fontsDetailsEl = detailsEl;
|
||||
detailsEl.createEl("summary", {
|
||||
text: t("FONTS_HEAD"),
|
||||
cls: "excalidraw-setting-h1",
|
||||
});
|
||||
|
||||
detailsEl = nonstandardDetailsEl.createEl("details");
|
||||
detailsEl = fontsDetailsEl.createEl("details");
|
||||
detailsEl.createEl("summary", {
|
||||
text: t("CUSTOM_FONT_HEAD"),
|
||||
cls: "excalidraw-setting-h3",
|
||||
@@ -2512,7 +2531,61 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
);
|
||||
});
|
||||
|
||||
detailsEl = fontsDetailsEl.createEl("details");
|
||||
detailsEl.createEl("summary", {
|
||||
text: t("OFFLINE_CJK_NAME"),
|
||||
cls: "excalidraw-setting-h3",
|
||||
});
|
||||
|
||||
const cjkdescdiv = detailsEl.createDiv({ cls: "setting-item-description" });
|
||||
cjkdescdiv.innerHTML = t("OFFLINE_CJK_DESC");
|
||||
|
||||
new Setting(detailsEl)
|
||||
.setName(t("CJK_ASSETS_FOLDER_NAME"))
|
||||
.setDesc(fragWithHTML(t("CJK_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();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(detailsEl)
|
||||
.setName(t("LOAD_CHINESE_FONTS_NAME"))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.loadChineseFonts)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.loadChineseFonts = value;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(detailsEl)
|
||||
.setName(t("LOAD_JAPANESE_FONTS_NAME"))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.loadJapaneseFonts)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.loadJapaneseFonts = value;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(detailsEl)
|
||||
.setName(t("LOAD_KOREAN_FONTS_NAME"))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.loadKoreanFonts)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.loadKoreanFonts = value;
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
|
||||
// ------------------------------------------------
|
||||
// Experimental features
|
||||
// ------------------------------------------------
|
||||
|
||||
1403
src/utils/CJKLoader.ts
Normal file
1403
src/utils/CJKLoader.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -41,6 +41,7 @@ export class StylesManager {
|
||||
this.plugin = plugin;
|
||||
plugin.app.workspace.onLayoutReady(async () => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(undefined, "StylesManager.constructor > app.workspace.onLayoutReady", this);
|
||||
await plugin.awaitInit();
|
||||
await this.harvestStyles();
|
||||
getAllWindowDocuments(plugin.app).forEach(doc => this.copyPropertiesToTheme(doc));
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import { updateElementLinksToObsidianLinks } from "src/ExcalidrawAutomate";
|
||||
import { CropImage } from "./CropImage";
|
||||
import opentype from 'opentype.js';
|
||||
import { runCompressionWorker } from "src/workers/compression-worker";
|
||||
import Pool from "es6-promise-pool";
|
||||
|
||||
declare const PLUGIN_VERSION:string;
|
||||
declare var LZString: any;
|
||||
@@ -968,4 +969,63 @@ export function cropCanvas(
|
||||
0, 0, output.width, output.height
|
||||
);
|
||||
return dstCanvas;
|
||||
}
|
||||
|
||||
// Promise.try, adapted from https://github.com/sindresorhus/p-try
|
||||
export async function promiseTry <TValue, TArgs extends unknown[]>(
|
||||
fn: (...args: TArgs) => PromiseLike<TValue> | TValue,
|
||||
...args: TArgs
|
||||
): Promise<TValue> {
|
||||
return new Promise((resolve) => {
|
||||
resolve(fn(...args));
|
||||
});
|
||||
};
|
||||
|
||||
// extending the missing types
|
||||
// relying on the [Index, T] to keep a correct order
|
||||
type TPromisePool<T, Index = number> = Pool<[Index, T][]> & {
|
||||
addEventListener: (
|
||||
type: "fulfilled",
|
||||
listener: (event: { data: { result: [Index, T] } }) => void,
|
||||
) => (event: { data: { result: [Index, T] } }) => void;
|
||||
removeEventListener: (
|
||||
type: "fulfilled",
|
||||
listener: (event: { data: { result: [Index, T] } }) => void,
|
||||
) => void;
|
||||
};
|
||||
|
||||
export class PromisePool<T> {
|
||||
private readonly pool: TPromisePool<T>;
|
||||
private readonly entries: Record<number, T> = {};
|
||||
|
||||
constructor(
|
||||
source: IterableIterator<Promise<void | readonly [number, T]>>,
|
||||
concurrency: number,
|
||||
) {
|
||||
this.pool = new Pool(
|
||||
source as unknown as () => void | PromiseLike<[number, T][]>,
|
||||
concurrency,
|
||||
) as TPromisePool<T>;
|
||||
}
|
||||
|
||||
public all() {
|
||||
const listener = (event: { data: { result: void | [number, T] } }) => {
|
||||
if (event.data.result) {
|
||||
// by default pool does not return the results, so we are gathering them manually
|
||||
// with the correct call order (represented by the index in the tuple)
|
||||
const [index, value] = event.data.result;
|
||||
this.entries[index] = value;
|
||||
}
|
||||
};
|
||||
|
||||
this.pool.addEventListener("fulfilled", listener);
|
||||
|
||||
return this.pool.start().then(() => {
|
||||
setTimeout(() => {
|
||||
this.pool.removeEventListener("fulfilled", listener);
|
||||
});
|
||||
|
||||
return Object.values(this.entries);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user