1.4.4 - basic copy/paste for equations & images

This commit is contained in:
Zsolt Viczian
2021-11-01 17:41:12 +01:00
parent 41491079be
commit d33cf5ddd5
7 changed files with 99 additions and 25 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
{
"1.4.3": "0.12.16",
"1.4.4": "0.12.16",
"1.4.2": "0.11.13"
}