自定义 Excalidraw 脚本 - 快速插入时间戳笔记
脚本借助了 QuickAdd 的 API,需要配合 QuickAdd 插件来使用
脚本设置
快速添加时间戳笔记
按时间戳形式命名,利用 quickaddApi.date.now(“YYYY-MM-DD”) 等命名建立的,请根据需求来设置
配置好路径后,可以设置笔记名
输入框中添加笔记别名为 20231110153740_别名.md
,不输入则为:20231110153740.md
不同模式下的嵌入形式
Card(图标类型卡片)、Frame(嵌入式 Frame)、Link(笔记 WiKi 链接)、Image(SVG 文档图片),Box 则是画板内部的边框文字
Card 模式下会嵌入图标 (需要配置路径下的图标)
设置 Card 模式下图标
快速删除本地笔记
选择或框选笔记后,再次运行脚本就可以删除本地笔记和画板元素了,可批量操作。
JS 脚本
const quickaddApi = this.app.plugins.plugins.quickadd.api;
// const ea = ExcalidrawAutomate;
const path = require("path");
const fs = require("fs");
// 设置quickerInsetNote模板设置
let settings = ea.getScriptSettings();
//set default values on first run
if (!settings["QuickerInsertZKCardPath"]) {
settings = {
"QuickerInsertZKCardPath": {
value: "D-每日生活记录/QuickNotes",
description: "TimeStampNote的存放路径(相对路径)<br>eg:D-每日生活记录/QuickNotes<br>空值:默认为当前笔记路径"
},
"QuickerInsertZKCardTemplate": {
value: "YYYY/YYYYMM/YYYYMMDD/YYYYMMDDHHMMSS",
description: "TimeStampNote默认名称,若为存储路径用/隔开<br>eg:YYYYMM/YYYYMMDDHHMMSS"
},
"QuickerInsertZKCardYaml": {
value: "---\ncssclasses:\n - Excalidraw-Markdown\n---\n\n",
height: "250px",
description: "设定笔记模板"
},
"QuickerInsertZKCardImagePath": {
value: "Y-图形文件存储/Excalidraw图形/Icons",
description: "配置图标的文件夹",
},
"Default Insert Type": {
value: "Box",
valueset: ["Card", "Frame", "Link", "Image", "Box", "无"],
description: "Card(图标类型卡片)、Frame(嵌入式Frame)、Link(笔记链接)、Image(SVG图片)<br>无:ESC或回车退出,其他类型则直接创建",
}
};
ea.setScriptSettings(settings);
}
// 存储路径
const folderPath = settings["QuickerInsertZKCardPath"].value ? settings["QuickerInsertZKCardPath"].value : path.dirname(app.workspace.getActiveFile().path);
console.log(folderPath);
// 调用函数生成时间戳
const timestamp = quickaddApi.date.now(settings["QuickerInsertZKCardTemplate"].value);
console.log(timestamp);
// 创建文件夹路径下的Markdown文件,fname为文件名
const Yaml = settings["QuickerInsertZKCardYaml"].value;
// 设置默认值
let fileAlistName = "";
let InsertType = settings["Default Insert Type"].value;
listFiles = fileListByPath(settings["QuickerInsertZKCardImagePath"].value);
listFiles.sort((a, b) => a.localeCompare(b));
let listFileNames = [];
for (i of listFiles) {
listFileNames.push(path.basename(i));
}
console.log(listFileNames);
let insertImageName = listFileNames[0];
console.log(insertImageName);
ea.setView("active");
const trashFiles = ea.getViewSelectedElements().filter(el => el.link);
// 获取库所有文件列表
const files = app.vault.getFiles();
if (Object.keys(trashFiles).length) {
for (let trashFile of trashFiles) {
filePaths = getFilePath(files, trashFile);
let isConfirm = await quickaddApi.yesNoPrompt("是否删除本地文件", `${filePaths}`);
if (isConfirm) {
// 删除元素
ea.deleteViewElements(ea.getViewSelectedElements().filter(el => el.id == trashFile.id));
// ea.clear();
await ea.addElementsToView(false, true);
await ea.getExcalidrawAPI().history.clear(); //避免撤消/重做扰乱
// 删除文件
if ((app.vault.adapter).exists(filePaths)) {
(app.vault.adapter).trashLocal(filePaths);
}
}
}
await ea.addElementsToView(false, true);
return; // 提前结束函数的执行
} else {
const customControls = (container) => {
new ea.obsidian.Setting(container)
.setName(`插入笔记图标`)
.addDropdown(dropdown => {
listFileNames.forEach(fileName => dropdown.addOption(fileName, fileName));
dropdown
.setValue(insertImageName)
.onChange(value => {
insertImageName = value;
});
});
};
fileAlistName = await utils.inputPrompt(
"时间戳笔记别名",
"输入文件名别名,默认为📝",
"",
[
{
caption: "Card",
action: () => {
InsertType = "Card";
return;
}
},
{
caption: "Link",
action: () => {
InsertType = "Link";
return;
}
},
{
caption: "Frame",
action: () => { InsertType = "Frame"; return; }
},
{
caption: "Image",
action: () => { InsertType = "Image"; return; }
},
{
caption: "Box",
action: () => { InsertType = "Box"; return; }
}
],
1,
false,
customControls
);
// 时间戳笔记路径
const filePath = fileAlistName ? `${folderPath}/${timestamp}_${fileAlistName}.md` : `${folderPath}/${timestamp}.md`;
console.log(filePath);
const fileName = path.basename(filePath).replace(/\.md/, "");
console.log([filePath, fileName]);
// 获取Obsidian文件对象
const rootFolder = app.vault.getRoot();
console.log(rootFolder);
// 设置默认输入文本
// let inputText = "";
// 添加Markdown文件为图片到当前文件
if (InsertType == "Card") {
let { insertType, inputText } = await openEditPrompt();
if (!insertType) return;
await app.fileManager.createNewFile(rootFolder, filePath, "md", inputText ? `${Yaml}\n${inputText}` : `${Yaml}`);
let id = await ea.addImage(0, 0, insertImageName);
let el = ea.getElement(id);
el.link = `[[${fileName}]]`;
} else if (InsertType == "Link") {
let { insertType, inputText } = await openEditPrompt();
if (!insertType) return;
await app.fileManager.createNewFile(rootFolder, filePath, "md", inputText ? `${Yaml}\n${inputText}` : `${Yaml}`);
let id = await ea.addText(0, 0, fileAlistName ? `[[${fileName}|${fileAlistName}]]` : `[[${fileName}|📝]]`);
let el = ea.getElement(id);
el.link = `[[${fileName}]]`;
el.fontSize = 80;
} else if (InsertType == "Frame") {
let { insertType, inputText } = await openEditPrompt();
if (!insertType) return;
// 设定固定Yaml
let file = await app.fileManager.createNewFile(rootFolder, filePath, "md", inputText ? `${Yaml}\n${inputText}` : `${Yaml}`);
// 设置Frame样式
ea.style.strokeColor = "#FFFFFF";
ea.style.strokeStyle = "solid";
ea.style.fillStyle = "solid";
ea.style.backgroundColor = "#ced4da";
ea.style.roughness = 0;
// ea.style.roundness = { type: 3 };
ea.style.strokeWidth = 2;
let id = await ea.addIFrame(0, 0, 400, 200, 0, file);
let el = ea.getElement(id);
el.link = `[[${fileName}]]`;
} else if (InsertType == "Image") {
let { insertType, inputText } = await openEditPrompt();
if (!insertType) return;
// 插入图片建议不用Yaml
let file = await app.fileManager.createNewFile(rootFolder, filePath, "md", inputText ? `${Yaml}\n${inputText}` : "");
let id = await ea.addImage(0, 0, file);
let el = ea.getElement(id);
el.link = `[[${fileName}]]`;
} else if (InsertType == "Box") {
let { insertType, inputText } = await openEditPrompt();
if (!insertType) return;
ea.style.backgroundColor = "transparent";
ea.style.strokeColor = "#1e1e1e";
ea.style.fillStyle = 'solid';
ea.style.roughness = 0;
// ea.style.roundness = { type: 3 }; // 圆角
ea.style.strokeWidth = 2;
ea.style.fontFamily = 4;
ea.style.fontSize = 20;
let id = await ea.addText(0, 0, inputText,
{
width: 500,
box: true,
wrapAt: 90,
textAlign: "left",
textVerticalAlign: "middle",
box: "box"
});
let el = ea.getElement(id);
} else {
return;
};
await ea.addElementsToView(true, true);
ea.moveViewElementToZIndex(el.id, 99);
}
function fileListByPath(filePath) {
// const path = require("path");
let files = app.vault.getFiles().filter(f => path.dirname(f.path) == filePath);
let fileNames = files.map((f) => f.path);
return fileNames;
}
// 打开文本编辑器
async function openEditPrompt(Text = "") {
// 打开编辑窗口
let insertType = true;
let inputText = "";
inputText = await utils.inputPrompt(
"输入笔记内容",
"输入笔记内容,ESC退出输入,Ctrl + Enter",
Text,
[
{
caption: "取消编辑",
action: () => {
insertType = false;
return;
}
},
{
caption: "完成编辑",
action: () => {
insertType = true;
return;
}
}
],
10,
true
);
return { insertType, inputText };
}
// 由文件列表和el元素获取文件路径(相对路径)
function getFilePath(files, el) {
let files2 = files.filter(f => path.basename(f.path).replace(".md", "").endsWith(el.link.replace(/\[\[/, "").replace(/\|.*]]/, "").replace(/\]\]/, "").replace(".md", "")));
let filePath = files2.map((f) => f.path)[0];
console.log(filePath);
return filePath;
}
简化版:直接 Frame 模式
const quickaddApi = this.app.plugins.plugins.quickadd.api;
// const ea = ExcalidrawAutomate;
const path = require("path");
const fs = require("fs");
// 设置 quickerInsetNote 模板设置
let settings = ea.getScriptSettings();
//set default values on first run
if (!settings["QuickerInsertZKCardPath"]) {
settings = {
"QuickerInsertZKCardPath": {
value: "D-每日生活记录/QuickNotes",
description: "TimeStampNote 的存放路径(相对路径)<br>eg:D-每日生活记录/QuickNotes<br>空值:默认为当前笔记路径"
},
"QuickerInsertZKCardTemplate": {
value: "[QuickNote]-YYYYMMDDHHmmss",
description: "TimeStampNote 默认名称,若为存储路径用/隔开<br>eg:YYYYMM/YYYYMMDDHHMMSS"
},
"QuickerInsertZKCardYaml": {
value: "---\ncssclasses:\n - Excalidraw-Markdown\n---\n\n",
height: "250px",
description: "设定笔记模板"
},
};
ea.setScriptSettings(settings);
}
// 存储路径
const folderPath = settings["QuickerInsertZKCardPath"].value ? settings["QuickerInsertZKCardPath"].value : path.dirname(app.workspace.getActiveFile().path);
console.log(folderPath);
// 调用函数生成时间戳
const timestamp = quickaddApi.date.now(settings["QuickerInsertZKCardTemplate"].value);
console.log(timestamp);
// 创建文件夹路径下的 Markdown 文件,fname 为文件名
const Yaml = settings["QuickerInsertZKCardYaml"].value;
ea.setView("active");
const trashFiles = ea.getViewSelectedElements().filter(el => el.link);
// 获取库所有文件列表
const files = app.vault.getFiles();
if (Object.keys(trashFiles).length) {
for (let trashFile of trashFiles) {
const filePaths = getFilePath(files, trashFile);
let isConfirm = await quickaddApi.yesNoPrompt("是否删除本地文件", `${filePaths}`);
if (isConfirm) {
// 删除元素
ea.deleteViewElements(ea.getViewSelectedElements().filter(el => el.id == trashFile.id));
// ea.clear();
await ea.addElementsToView(false, true);
await ea.getExcalidrawAPI().history.clear(); //避免撤消/重做扰乱
// 删除文件
if ((app.vault.adapter).exists(filePaths)) {
(app.vault.adapter).trashLocal(filePaths);
}
}
}
await ea.addElementsToView(false, true);
return; // 提前结束函数的执行
}
// 时间戳笔记路径
const filePath = `${folderPath}/${timestamp}.md`;
console.log(filePath);
const fileName = path.basename(filePath).replace(/\.md/, "");
console.log([filePath, fileName]);
// 获取 Obsidian 文件对象
const rootFolder = app.vault.getRoot();
console.log(rootFolder);
let { insertType, inputText } = await openEditPrompt();
if (!insertType) return;
// 设定固定 Yaml
let file = await app.fileManager.createNewFile(rootFolder, filePath, "md", inputText ? `${Yaml}\n${inputText}` : `${Yaml}`);
// 设置 Frame 样式
ea.style.strokeColor = "#FFFFFF";
ea.style.strokeStyle = "solid";
ea.style.fillStyle = "solid";
ea.style.backgroundColor = "#ced4da";
ea.style.roughness = 0;
ea.style.roundness = { type: 3 };
ea.style.strokeWidth = 2;
let id = await ea.addIFrame(0, 0, 600, 300, 0, file);
let el = ea.getElement(id);
el.link = `[[${fileName}]]`;
await ea.addElementsToView(true, true);
ea.moveViewElementToZIndex(el.id, 99);
return;
// 打开文本编辑器
async function openEditPrompt(Text = "") {
// 打开编辑窗口
let insertType = false;
let inputText = "";
inputText = await utils.inputPrompt(
"输入笔记内容",
"输入笔记内容,ESC 退出输入,Ctrl + Enter",
Text,
[
{
caption: "取消编辑",
action: () => {
insertType = false;
return;
}
},
{
caption: "完成编辑",
action: () => {
insertType = true;
return;
}
}
],
10,
false
);
return { insertType, inputText };
}
// 由文件列表和 el 元素获取文件路径(相对路径)
function getFilePath(files, el) {
let files2 = files.filter(f => path.basename(f.path).replace(".md", "").endsWith(el.link.replace(/\[\[/, "").replace(/\|.\*]]/, "").replace(/\]\]/, "").replace(".md", "")));
let filePath = files2.map((f) => f.path)[0];
console.log(filePath);
return filePath;
}
讨论
若阁下有独到的见解或新颖的想法,诚邀您在文章下方留言,与大家共同探讨。
反馈交流
其他渠道
版权声明
版权声明:所有 PKMer 文章如果需要转载,请附上原文出处链接。