mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
2.0.19
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { ExcalidrawFrameElement, ExcalidrawImageElement } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
import { ExcalidrawEmbeddableElement, ExcalidrawFrameElement, ExcalidrawImageElement } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
import { Mutable } from "@zsviczian/excalidraw/types/excalidraw/utility-types";
|
||||
import { getEA } from "src";
|
||||
import { ExcalidrawAutomate } from "src/ExcalidrawAutomate";
|
||||
import { splitFolderAndFilename } from "./FileUtils";
|
||||
import { getCropFileNameAndFolder, splitFolderAndFilename } from "./FileUtils";
|
||||
import { Notice, TFile } from "obsidian";
|
||||
import ExcalidrawView from "src/ExcalidrawView";
|
||||
import { ExcalidrawImperativeAPI } from "@zsviczian/excalidraw/types/excalidraw/types";
|
||||
@@ -34,20 +34,20 @@ export const carveOutImage = async (sourceEA: ExcalidrawAutomate, viewImageEl: E
|
||||
let imageLink = "";
|
||||
let fname = "";
|
||||
if(ef.file) {
|
||||
fname = CROPPED_PREFIX + ef.file.basename;
|
||||
imageLink = `[[${ef.file.path}]]`;
|
||||
fname = ef.file.basename;
|
||||
const ref = ef.linkParts?.ref ? `#${ef.linkParts.ref}` : ``;
|
||||
imageLink = `[[${ef.file.path}${ref}]]`;
|
||||
} else {
|
||||
const imagename = ef.hyperlink?.match(/^.*\/([^?]*)\??.*$/)?.[1];
|
||||
imageLink = ef.hyperlink;
|
||||
fname = viewImageEl
|
||||
? CROPPED_PREFIX + imagename.substring(0,imagename.lastIndexOf("."))
|
||||
: CROPPED_PREFIX + "_image";
|
||||
? imagename.substring(0,imagename.lastIndexOf("."))
|
||||
: "_image";
|
||||
}
|
||||
|
||||
const attachmentPath = await sourceEA.getAttachmentFilepath(fname + ".md");
|
||||
const {folderpath: foldername, filename} = splitFolderAndFilename(attachmentPath);
|
||||
const {folderpath, filename} = await getCropFileNameAndFolder(sourceEA.plugin,sourceEA.targetView.file.path,fname);
|
||||
|
||||
const file = await createImageCropperFile(targetEA, newImage.id, imageLink, foldername, filename);
|
||||
const file = await createImageCropperFile(targetEA, newImage.id, imageLink, folderpath, filename);
|
||||
if(!file) return;
|
||||
|
||||
//console.log(await app.vault.read(file));
|
||||
@@ -65,13 +65,57 @@ export const carveOutImage = async (sourceEA: ExcalidrawAutomate, viewImageEl: E
|
||||
sourceEA.addElementsToView(false, true, true);
|
||||
}
|
||||
|
||||
export const carveOutPDF = async (sourceEA: ExcalidrawAutomate, embeddableEl: ExcalidrawEmbeddableElement, pdfPathWithPage: string, pdfFile: TFile) => {
|
||||
if(!embeddableEl || !pdfPathWithPage || !sourceEA?.targetView) return;
|
||||
|
||||
const targetEA = getEA(sourceEA.targetView) as ExcalidrawAutomate;
|
||||
|
||||
const {height, width} = embeddableEl;
|
||||
|
||||
if(!height || !width || height === 0 || width === 0) return;
|
||||
|
||||
const imageId = await targetEA.addImage(0,0, pdfPathWithPage);
|
||||
const newImage = targetEA.getElement(imageId) as Mutable<ExcalidrawImageElement>;
|
||||
newImage.x = 0;
|
||||
newImage.y = 0;
|
||||
newImage.width = width;
|
||||
newImage.height = height;
|
||||
const angle = embeddableEl.angle;
|
||||
|
||||
const fname = pdfFile.basename;
|
||||
const imageLink = `[[${pdfPathWithPage}]]`;
|
||||
|
||||
const {folderpath, filename} = await getCropFileNameAndFolder(sourceEA.plugin,sourceEA.targetView.file.path,fname);
|
||||
|
||||
const file = await createImageCropperFile(targetEA, newImage.id, imageLink, folderpath, filename);
|
||||
if(!file) return;
|
||||
|
||||
//console.log(await app.vault.read(file));
|
||||
sourceEA.clear();
|
||||
const replacingImageID = await sourceEA.addImage(embeddableEl.x + embeddableEl.width + 10, embeddableEl.y, file, true);
|
||||
const replacingImage = sourceEA.getElement(replacingImageID) as Mutable<ExcalidrawImageElement>;
|
||||
const imageAspectRatio = replacingImage.width / replacingImage.height;
|
||||
if(imageAspectRatio > 1) {
|
||||
replacingImage.width = embeddableEl.width;
|
||||
replacingImage.height = replacingImage.width / imageAspectRatio;
|
||||
} else {
|
||||
replacingImage.height = embeddableEl.height;
|
||||
replacingImage.width = replacingImage.height * imageAspectRatio;
|
||||
}
|
||||
replacingImage.angle = angle;
|
||||
sourceEA.addElementsToView(false, true, true);
|
||||
}
|
||||
|
||||
|
||||
export const createImageCropperFile = async (targetEA: ExcalidrawAutomate, imageID: string, imageLink:string, foldername: string, filename: string): Promise<TFile> => {
|
||||
const workspace = targetEA.plugin.app.workspace;
|
||||
const vault = targetEA.plugin.app.vault;
|
||||
const newImage = targetEA.getElement(imageID) as Mutable<ExcalidrawImageElement>;
|
||||
const { width, height } = newImage;
|
||||
const isPDF = imageLink.match(/\[\[([^#]*)#.*]]/)?.[1]?.endsWith(".pdf");
|
||||
|
||||
newImage.opacity = 100;
|
||||
newImage.locked = true;
|
||||
newImage.link = imageLink;
|
||||
|
||||
const frameID = targetEA.addFrame(0,0,width,height,"Adjust frame to crop image. Add elements for mask: White shows, Black hides.");
|
||||
const frame = targetEA.getElement(frameID) as Mutable<ExcalidrawFrameElement>;
|
||||
@@ -87,7 +131,7 @@ export const createImageCropperFile = async (targetEA: ExcalidrawAutomate, image
|
||||
targetEA.style.roughness = 0;
|
||||
targetEA.style.roundness = null;
|
||||
targetEA.canvas.theme = "light";
|
||||
targetEA.canvas.viewBackgroundColor = "#3d3d3d";
|
||||
targetEA.canvas.viewBackgroundColor = isPDF ? "#5d5d5d" : "#3d3d3d";
|
||||
|
||||
const templateFile = app.vault.getAbstractFileByPath(targetEA.plugin.settings.templateFilePath);
|
||||
if(templateFile && templateFile instanceof TFile) {
|
||||
@@ -107,6 +151,7 @@ export const createImageCropperFile = async (targetEA: ExcalidrawAutomate, image
|
||||
"excalidraw-export-dark": false,
|
||||
"excalidraw-export-padding": 0,
|
||||
"excalidraw-export-transparent": true,
|
||||
...isPDF ? {"cssclasses": "excalidraw-cropped-pdfpage"} : {},
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ export const setDynamicStyle = (
|
||||
[`--color-gray-50`]: str(text), //frame
|
||||
[`--color-surface-highlight`]: str(gray1()),
|
||||
//[`--color-gray-30`]: str(gray1),
|
||||
[`--color-gray-80`]: str(isDark?text.lighterBy(15):text.darkerBy(15)), //frame
|
||||
[`--color-gray-80`]: str(isDark?text.darkerBy(40):text.lighterBy(40)), //frame
|
||||
[`--sidebar-border-color`]: str(gray1()),
|
||||
[`--color-primary-light`]: str(accent().lighterBy(step)),
|
||||
[`--button-hover-bg`]: str(gray1()),
|
||||
@@ -130,7 +130,7 @@ export const setDynamicStyle = (
|
||||
const frameColor = {
|
||||
stroke: str(isDark?gray2().lighterBy(15):gray2().darkerBy(15)),
|
||||
fill: str((isDark?gray2().lighterBy(30):gray2().darkerBy(30)).alphaTo(0.2)),
|
||||
nameColor: str(isDark?gray2().lighterBy(40):gray2().darkerBy(40)),
|
||||
nameColor: str(isDark?gray2().lighterBy(50):gray2().darkerBy(50)),
|
||||
}
|
||||
const scene = api.getSceneElements();
|
||||
scene.filter(el=>el.type==="frame").forEach((e:ExcalidrawFrameElement)=>{
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
|
||||
import { MAX_IMAGE_SIZE, IMAGE_TYPES, ANIMATED_IMAGE_TYPES } from "src/constants/constants";
|
||||
import { TFile } from "obsidian";
|
||||
import { App, TFile } from "obsidian";
|
||||
import { ExcalidrawAutomate } from "src/ExcalidrawAutomate";
|
||||
import { REGEX_LINK, REG_LINKINDEX_HYPERLINK } from "src/ExcalidrawData";
|
||||
import ExcalidrawView from "src/ExcalidrawView";
|
||||
import { ExcalidrawElement } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
import { getLinkParts } from "./Utils";
|
||||
|
||||
export const insertImageToView = async (
|
||||
ea: ExcalidrawAutomate,
|
||||
@@ -61,4 +64,56 @@ export const getLinkTextFromLink = (text: string): string => {
|
||||
if (linktext.match(REG_LINKINDEX_HYPERLINK)) return;
|
||||
|
||||
return linktext;
|
||||
}
|
||||
|
||||
export const openTagSearch = (link:string, app: App, view?: ExcalidrawView) => {
|
||||
const tags = link
|
||||
.matchAll(/#([\p{Letter}\p{Emoji_Presentation}\p{Number}\/_-]+)/gu)
|
||||
.next();
|
||||
if (!tags.value || tags.value.length < 2) {
|
||||
return;
|
||||
}
|
||||
const search = app.workspace.getLeavesOfType("search");
|
||||
if (search.length == 0) {
|
||||
return;
|
||||
}
|
||||
//@ts-ignore
|
||||
search[0].view.setQuery(`tag:${tags.value[1]}`);
|
||||
app.workspace.revealLeaf(search[0]);
|
||||
|
||||
if (view && view.isFullscreen()) {
|
||||
view.exitFullscreen();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
export const openExternalLink = (link:string, app: App, element?: ExcalidrawElement):boolean => {
|
||||
if (link.match(/^cmd:\/\/.*/)) {
|
||||
const cmd = link.replace("cmd://", "");
|
||||
//@ts-ignore
|
||||
app.commands.executeCommandById(cmd);
|
||||
return true;
|
||||
}
|
||||
if (link.match(REG_LINKINDEX_HYPERLINK)) {
|
||||
window.open(link, "_blank");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export const getExcalidrawFileForwardLinks = (app: App, excalidrawFile: TFile):string => {
|
||||
let secondOrderLinks = "";
|
||||
const forwardLinks = app.metadataCache.getLinks()[excalidrawFile.path];
|
||||
if(forwardLinks && forwardLinks.length > 0) {
|
||||
const linkset = new Set<string>();
|
||||
forwardLinks.forEach(link => {
|
||||
const linkparts = getLinkParts(link.link);
|
||||
const f = app.metadataCache.getFirstLinkpathDest(linkparts.path, excalidrawFile.path);
|
||||
if(f && f.path !== excalidrawFile.path) {
|
||||
linkset.add(`[[${f.path}${linkparts.ref?"#"+linkparts.ref:""}|Second Order Link: ${f.basename}]]`);
|
||||
}
|
||||
});
|
||||
secondOrderLinks = [...linkset].join(" ");
|
||||
}
|
||||
return secondOrderLinks;
|
||||
}
|
||||
@@ -5,6 +5,9 @@ import { IMAGE_MIME_TYPES, MimeType } from "src/EmbeddedFileLoader";
|
||||
import { ExcalidrawSettings } from "src/settings";
|
||||
import { errorlog, getDataURL } from "./Utils";
|
||||
import ExcalidrawPlugin from "src/main";
|
||||
import ExcalidrawView from "src/ExcalidrawView";
|
||||
import { CROPPED_PREFIX } from "./CarveOut";
|
||||
import { getAttachmentsFolderAndFilePath } from "./ObsidianUtils";
|
||||
|
||||
/**
|
||||
* Splits a full path including a folderpath and a filename into separate folderpath and filename components
|
||||
@@ -370,4 +373,17 @@ export const getLink = (
|
||||
return plugin.settings.embedWikiLink
|
||||
? `${embed ? "!" : ""}[[${path}${alias ? `|${alias}` : ""}]]`
|
||||
: `${embed ? "!" : ""}[${alias ?? ""}](${encodeURI(path)})`
|
||||
}
|
||||
|
||||
export const getCropFileNameAndFolder = async (plugin: ExcalidrawPlugin, hostPath: string, baseNewFileName: string):Promise<{folderpath: string, filename: string}> => {
|
||||
let prefix = plugin.settings.cropPrefix;
|
||||
if(!prefix || prefix.trim() === "") prefix = CROPPED_PREFIX;
|
||||
const filename = prefix + baseNewFileName + ".md";
|
||||
if(!plugin.settings.cropFolder || plugin.settings.cropFolder.trim() === "") {
|
||||
const folderpath = (await getAttachmentsFolderAndFilePath(plugin.app, hostPath, filename)).folder;
|
||||
return {folderpath, filename};
|
||||
}
|
||||
const folderpath = normalizePath(plugin.settings.cropFolder);
|
||||
await checkAndCreateFolder(folderpath);
|
||||
return {folderpath, filename};
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
App,
|
||||
normalizePath, parseFrontMatterEntry, TFile, Workspace, WorkspaceLeaf, WorkspaceSplit
|
||||
normalizePath, parseFrontMatterEntry, TFile, View, Workspace, WorkspaceLeaf, WorkspaceSplit
|
||||
} from "obsidian";
|
||||
import ExcalidrawPlugin from "../main";
|
||||
import { checkAndCreateFolder, splitFolderAndFilename } from "./FileUtils";
|
||||
@@ -254,4 +254,7 @@ export const getFileCSSClasses = (
|
||||
return [];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
export const getActivePDFPageNumberFromPDFView = (view: View): number => view?.viewer?.child?.pdfViewer?.page;
|
||||
@@ -13,15 +13,10 @@ import {
|
||||
VIRGIL_FONT,
|
||||
} from "src/constants/constFonts";
|
||||
import {
|
||||
FRONTMATTER_KEY_EXPORT_DARK,
|
||||
FRONTMATTER_KEY_EXPORT_TRANSPARENT,
|
||||
FRONTMATTER_KEY_EXPORT_SVGPADDING,
|
||||
FRONTMATTER_KEY_EXPORT_PNGSCALE,
|
||||
FRONTMATTER_KEY_EXPORT_PADDING,
|
||||
exportToSvg,
|
||||
exportToBlob,
|
||||
IMAGE_TYPES,
|
||||
FRONTMATTER_KEY_MASK
|
||||
FRONTMATTER_KEYS,
|
||||
} from "../constants/constants";
|
||||
import ExcalidrawPlugin from "../main";
|
||||
import { ExcalidrawElement } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
@@ -548,9 +543,9 @@ export const isMaskFile = (
|
||||
const fileCache = plugin.app.metadataCache.getFileCache(file);
|
||||
if (
|
||||
fileCache?.frontmatter &&
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_MASK] != null
|
||||
fileCache.frontmatter[FRONTMATTER_KEYS["mask"].name] != null
|
||||
) {
|
||||
return Boolean(fileCache.frontmatter[FRONTMATTER_KEY_MASK]);
|
||||
return Boolean(fileCache.frontmatter[FRONTMATTER_KEYS["mask"].name]);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -564,7 +559,7 @@ export const hasExportTheme = (
|
||||
const fileCache = plugin.app.metadataCache.getFileCache(file);
|
||||
if (
|
||||
fileCache?.frontmatter &&
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_DARK] != null
|
||||
fileCache.frontmatter[FRONTMATTER_KEYS["export-dark"].name] != null
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@@ -581,9 +576,9 @@ export const getExportTheme = (
|
||||
const fileCache = plugin.app.metadataCache.getFileCache(file);
|
||||
if (
|
||||
fileCache?.frontmatter &&
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_DARK] != null
|
||||
fileCache.frontmatter[FRONTMATTER_KEYS["export-dark"].name] != null
|
||||
) {
|
||||
return fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_DARK]
|
||||
return fileCache.frontmatter[FRONTMATTER_KEYS["export-dark"].name]
|
||||
? "dark"
|
||||
: "light";
|
||||
}
|
||||
@@ -599,7 +594,7 @@ export const hasExportBackground = (
|
||||
const fileCache = plugin.app.metadataCache.getFileCache(file);
|
||||
if (
|
||||
fileCache?.frontmatter &&
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_TRANSPARENT] != null
|
||||
fileCache.frontmatter[FRONTMATTER_KEYS["export-transparent"].name] != null
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@@ -615,9 +610,9 @@ export const getWithBackground = (
|
||||
const fileCache = plugin.app.metadataCache.getFileCache(file);
|
||||
if (
|
||||
fileCache?.frontmatter &&
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_TRANSPARENT] != null
|
||||
fileCache.frontmatter[FRONTMATTER_KEYS["export-transparent"].name] != null
|
||||
) {
|
||||
return !fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_TRANSPARENT];
|
||||
return !fileCache.frontmatter[FRONTMATTER_KEYS["export-transparent"].name];
|
||||
}
|
||||
}
|
||||
return plugin.settings.exportWithBackground;
|
||||
@@ -631,9 +626,9 @@ export const getExportPadding = (
|
||||
const fileCache = plugin.app.metadataCache.getFileCache(file);
|
||||
if(!fileCache?.frontmatter) return plugin.settings.exportPaddingSVG;
|
||||
|
||||
if (fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_PADDING] != null) {
|
||||
if (fileCache.frontmatter[FRONTMATTER_KEYS["export-padding"].name] != null) {
|
||||
const val = parseInt(
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_PADDING],
|
||||
fileCache.frontmatter[FRONTMATTER_KEYS["export-padding"].name],
|
||||
);
|
||||
if (!isNaN(val)) {
|
||||
return val;
|
||||
@@ -641,9 +636,9 @@ export const getExportPadding = (
|
||||
}
|
||||
|
||||
//depricated. Retained for backward compatibility
|
||||
if (fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_SVGPADDING] != null) {
|
||||
if (fileCache.frontmatter[FRONTMATTER_KEYS["export-svgpadding"].name] != null) {
|
||||
const val = parseInt(
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_SVGPADDING],
|
||||
fileCache.frontmatter[FRONTMATTER_KEYS["export-svgpadding"].name],
|
||||
);
|
||||
if (!isNaN(val)) {
|
||||
return val;
|
||||
@@ -659,10 +654,10 @@ export const getPNGScale = (plugin: ExcalidrawPlugin, file: TFile): number => {
|
||||
const fileCache = plugin.app.metadataCache.getFileCache(file);
|
||||
if (
|
||||
fileCache?.frontmatter &&
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_PNGSCALE] != null
|
||||
fileCache.frontmatter[FRONTMATTER_KEYS["export-pngscale"].name] != null
|
||||
) {
|
||||
const val = parseFloat(
|
||||
fileCache.frontmatter[FRONTMATTER_KEY_EXPORT_PNGSCALE],
|
||||
fileCache.frontmatter[FRONTMATTER_KEYS["export-pngscale"].name],
|
||||
);
|
||||
if (!isNaN(val) && val > 0) {
|
||||
return val;
|
||||
|
||||
Reference in New Issue
Block a user