mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
1.4.4 - basic copy/paste for equations & images
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "1.4.3",
|
||||
"version": "1.4.4",
|
||||
"minAppVersion": "0.12.16",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -868,7 +868,7 @@ async function getTemplate(plugin: ExcalidrawPlugin, fileWithPath:string, loadFi
|
||||
if(trimLocation == -1) trimLocation = data.search("# Drawing\n");
|
||||
|
||||
if(loadFiles) {
|
||||
await loadSceneFiles(plugin,excalidrawData.files, excalidrawData.equations, null, (fileArray:any, view:any)=>{
|
||||
await loadSceneFiles(plugin,excalidrawData, null, (fileArray:any, view:any)=>{
|
||||
for(const f of fileArray) {
|
||||
excalidrawData.scene.files[f.id] = f;
|
||||
}
|
||||
|
||||
@@ -113,8 +113,8 @@ export class ExcalidrawData {
|
||||
private textMode: TextMode = TextMode.raw;
|
||||
private plugin: ExcalidrawPlugin;
|
||||
public loaded: boolean = false;
|
||||
public files:Map<FileId,string> = null; //fileId, path
|
||||
public equations:Map<FileId,string> = null; //fileId, path
|
||||
private files:Map<FileId,string> = null; //fileId, path
|
||||
private equations:Map<FileId,string> = null; //fileId, path
|
||||
private compatibilityMode:boolean = false;
|
||||
|
||||
constructor(plugin: ExcalidrawPlugin) {
|
||||
@@ -215,14 +215,14 @@ export class ExcalidrawData {
|
||||
const REG_FILEID_FILEPATH = /([\w\d]*):\s*\[\[([^\]]*)]]\n/gm;
|
||||
res = data.matchAll(REG_FILEID_FILEPATH);
|
||||
while(!(parts = res.next()).done) {
|
||||
this.files.set(parts.value[1] as FileId,parts.value[2]);
|
||||
this.setFile(parts.value[1] as FileId,parts.value[2]);
|
||||
}
|
||||
|
||||
//Load Equations
|
||||
const REG_FILEID_EQUATION = /([\w\d]*):\s*\$\$(.*)(\$\$\s*\n)/gm;
|
||||
res = data.matchAll(REG_FILEID_EQUATION);
|
||||
while(!(parts = res.next()).done) {
|
||||
this.equations.set(parts.value[1] as FileId,parts.value[2]);
|
||||
this.setEquation(parts.value[1] as FileId,parts.value[2]);
|
||||
}
|
||||
|
||||
//Check to see if there are text elements in the JSON that were missed from the # Text Elements section
|
||||
@@ -556,7 +556,7 @@ export class ExcalidrawData {
|
||||
if(!scene.files || scene.files == {}) return false;
|
||||
|
||||
for(const key of Object.keys(scene.files)) {
|
||||
if(!(this.files.has(key as FileId) || this.equations.has(key as FileId))) {
|
||||
if(!(this.hasFile(key as FileId) || this.hasEquation(key as FileId))) {
|
||||
dirty = true;
|
||||
let fname = "Pasted Image "+window.moment().format("YYYYMMDDHHmmss_SSS");
|
||||
switch(scene.files[key].mimeType) {
|
||||
@@ -568,7 +568,7 @@ export class ExcalidrawData {
|
||||
}
|
||||
const [folder,filepath] = await getAttachmentsFolderAndFilePath(this.app,this.file.path,fname);
|
||||
await this.app.vault.createBinary(filepath,getBinaryFileFromDataURL(scene.files[key].dataURL));
|
||||
this.files.set(key as FileId,filepath);
|
||||
this.setFile(key as FileId,filepath);
|
||||
}
|
||||
}
|
||||
return dirty;
|
||||
@@ -663,4 +663,74 @@ export class ExcalidrawData {
|
||||
return showLinkBrackets != this.showLinkBrackets;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// Files and equations copy/paste support
|
||||
// This is not a complete solution, it assumes the source document is opened first
|
||||
// at that time the fileId is stored in the master files/equations map
|
||||
// when pasted the map is checked if the file already exists
|
||||
// This will not work if pasting from one vault to another, but for the most common usecase
|
||||
// of copying an image or equation from one drawing to another within the same vault
|
||||
// this is going to do the job
|
||||
*/
|
||||
public setFile(fileId:FileId, path:string) {
|
||||
//always store absolute path because in case of paste, relative path may not resolve ok
|
||||
const file = this.app.metadataCache.getFirstLinkpathDest(path,this.file.path);
|
||||
const p = file?.path ?? path;
|
||||
this.files.set(fileId,p);
|
||||
this.plugin.filesMaster.set(fileId,p);
|
||||
}
|
||||
|
||||
public getFile(fileId:FileId) {
|
||||
return this.files.get(fileId);
|
||||
}
|
||||
|
||||
public getFileEntries() {
|
||||
return this.files.entries();
|
||||
}
|
||||
|
||||
public deleteFile(fileId:FileId) {
|
||||
this.files.delete(fileId);
|
||||
//deliberately not deleting from plugin.filesMaster
|
||||
//could be present in other drawings as well
|
||||
}
|
||||
|
||||
//Image copy/paste support
|
||||
public hasFile(fileId:FileId):boolean {
|
||||
if(this.files.has(fileId)) return true;
|
||||
if(this.plugin.filesMaster.has(fileId)) {
|
||||
this.files.set(fileId,this.plugin.filesMaster.get(fileId));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public setEquation(fileId:FileId, equation:string) {
|
||||
this.equations.set(fileId,equation);
|
||||
this.plugin.equationsMaster.set(fileId,equation);
|
||||
}
|
||||
|
||||
public getEquation(fileId: FileId) {
|
||||
return this.equations.get(fileId);
|
||||
}
|
||||
|
||||
public getEquationEntries() {
|
||||
return this.equations.entries();
|
||||
}
|
||||
|
||||
public deleteEquation(fileId:FileId) {
|
||||
this.equations.delete(fileId);
|
||||
//deliberately not deleting from plugin.equationsMaster
|
||||
//could be present in other drawings as well
|
||||
}
|
||||
|
||||
//Image copy/paste support
|
||||
public hasEquation(fileId:FileId):boolean {
|
||||
if(this.equations.has(fileId)) return true;
|
||||
if(this.plugin.equationsMaster.has(fileId)) {
|
||||
this.equations.set(fileId,this.plugin.equationsMaster.get(fileId));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -269,20 +269,20 @@ export default class ExcalidrawView extends TextFileView {
|
||||
} else {
|
||||
const selectedImage = this.getSelectedImageElement();
|
||||
if(selectedImage?.id) {
|
||||
if(this.excalidrawData.equations.has(selectedImage.fileId)) {
|
||||
const equation = this.excalidrawData.equations.get(selectedImage.fileId);
|
||||
if(this.excalidrawData.hasEquation(selectedImage.fileId)) {
|
||||
const equation = this.excalidrawData.getEquation(selectedImage.fileId);
|
||||
const prompt = new Prompt(this.app, t("ENTER_LATEX"),equation,'');
|
||||
prompt.openAndGetValue( async (formula:string)=> {
|
||||
if(!formula) return;
|
||||
this.excalidrawData.equations.set(selectedImage.fileId,formula);
|
||||
this.excalidrawData.setEquation(selectedImage.fileId,formula);
|
||||
await this.save(true);
|
||||
await updateEquation(formula,selectedImage.fileId,this,addFiles);
|
||||
});
|
||||
return;
|
||||
}
|
||||
await this.save(true); //in case pasted images haven't been saved yet
|
||||
if(this.excalidrawData.files.has(selectedImage.fileId)) {
|
||||
linkText = this.excalidrawData.files.get(selectedImage.fileId);
|
||||
if(this.excalidrawData.hasFile(selectedImage.fileId)) {
|
||||
linkText = this.excalidrawData.getFile(selectedImage.fileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -471,8 +471,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
}
|
||||
loadSceneFiles(
|
||||
this.plugin,
|
||||
this.excalidrawData.files,
|
||||
this.excalidrawData.equations,
|
||||
this.excalidrawData,
|
||||
this,
|
||||
(files:any, view:ExcalidrawView) => addFiles(files,view),
|
||||
this.file?.path
|
||||
@@ -659,8 +658,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
this.excalidrawAPI = api;
|
||||
loadSceneFiles(
|
||||
this.plugin,
|
||||
this.excalidrawData.files,
|
||||
this.excalidrawData.equations,
|
||||
this.excalidrawData,
|
||||
this,
|
||||
(files:any, view:ExcalidrawView)=>addFiles(files,view),
|
||||
this.file?.path
|
||||
@@ -785,10 +783,10 @@ export default class ExcalidrawView extends TextFileView {
|
||||
created: images[k].created
|
||||
});
|
||||
if(images[k].file) {
|
||||
this.excalidrawData.files.set(images[k].id,images[k].file);
|
||||
this.excalidrawData.setFile(images[k].id,images[k].file);
|
||||
}
|
||||
if(images[k].tex) {
|
||||
this.excalidrawData.equations.set(images[k].id,images[k].tex);
|
||||
this.excalidrawData.setEquation(images[k].id,images[k].tex);
|
||||
}
|
||||
});
|
||||
this.excalidrawAPI.addFiles(files);
|
||||
|
||||
10
src/Utils.ts
10
src/Utils.ts
@@ -9,6 +9,7 @@ import ExcalidrawView, { ExportSettings } from "./ExcalidrawView";
|
||||
import { ExcalidrawSettings } from "./settings";
|
||||
import { html_beautify } from "js-beautify";
|
||||
import html2canvas from "html2canvas";
|
||||
import { ExcalidrawData } from "./ExcalidrawData";
|
||||
|
||||
declare module "obsidian" {
|
||||
interface Workspace {
|
||||
@@ -371,18 +372,17 @@ export const embedFontsInSVG = (svg:SVGSVGElement):SVGSVGElement => {
|
||||
|
||||
export const loadSceneFiles = async (
|
||||
plugin:ExcalidrawPlugin,
|
||||
filesMap: Map<FileId, string>,
|
||||
equationsMap: Map<FileId, string>,
|
||||
excalidrawData: ExcalidrawData,
|
||||
view: ExcalidrawView,
|
||||
addFiles:Function,
|
||||
sourcePath:string
|
||||
) => {
|
||||
const app = plugin.app;
|
||||
let entries = filesMap.entries();
|
||||
let entries = excalidrawData.getFileEntries();
|
||||
let entry;
|
||||
let files:BinaryFileData[] = [];
|
||||
while(!(entry = entries.next()).done) {
|
||||
const file = app.metadataCache.getFirstLinkpathDest(entry.value[1],sourcePath)
|
||||
const file = app.metadataCache.getFirstLinkpathDest(entry.value[1],sourcePath);
|
||||
if(file && file instanceof TFile) {
|
||||
const data = await getObsidianImage(plugin,file);
|
||||
files.push({
|
||||
@@ -396,7 +396,7 @@ export const loadSceneFiles = async (
|
||||
}
|
||||
}
|
||||
|
||||
entries = equationsMap.entries();
|
||||
entries = excalidrawData.getEquationEntries();
|
||||
while(!(entry = entries.next()).done) {
|
||||
const tex = entry.value[1];
|
||||
const data = await tex2dataURL(tex);
|
||||
|
||||
@@ -62,6 +62,7 @@ import { around } from "monkey-around";
|
||||
import { t } from "./lang/helpers";
|
||||
import { checkAndCreateFolder, download, embedFontsInSVG, generateSVGString, getAttachmentsFolderAndFilePath, getIMGPathFromExcalidrawFile, getNewUniqueFilepath, getPNG, getSVG, isObsidianThemeDark, splitFolderAndFilename, svgToBase64 } from "./Utils";
|
||||
import { OneOffs } from "./OneOffs";
|
||||
import { FileId } from "@zsviczian/excalidraw/types/element/types";
|
||||
|
||||
declare module "obsidian" {
|
||||
interface App {
|
||||
@@ -86,9 +87,14 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
private fileExplorerObserver: MutationObserver;
|
||||
public opencount:number = 0;
|
||||
public ea:ExcalidrawAutomate;
|
||||
//A master list of fileIds to facilitate copy / paste
|
||||
public filesMaster:Map<FileId,string> = null; //fileId, path
|
||||
public equationsMaster:Map<FileId,string> = null; //fileId, formula
|
||||
|
||||
constructor(app: App, manifest: PluginManifest) {
|
||||
super(app, manifest);
|
||||
this.filesMaster = new Map<FileId,string>();
|
||||
this.equationsMaster = new Map<FileId,string>();
|
||||
}
|
||||
|
||||
async onload() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"1.4.3": "0.12.16",
|
||||
"1.4.4": "0.12.16",
|
||||
"1.4.2": "0.11.13"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user