diff --git a/CHANGELOG.md b/CHANGELOG.md
index 12887bb..388418e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,12 @@
+
+## v1.2.0 / 2024.12.01
+
+- ✨ 脚注内容模板支持编号${index}, 主要用于脚注编号
+- 🔥 取消脚注启用编号对脚注内容块添加命名的操作
+
+ 
+
## v1.1.9 / 2024.12.01
- 📝README 补充插件的命令介绍
- ✨ 命令面板添加取消脚注自动编号命令 #17
diff --git a/README_zh_CN.md b/README_zh_CN.md
index 02306a6..80cd0cc 100644
--- a/README_zh_CN.md
+++ b/README_zh_CN.md
@@ -8,6 +8,13 @@
## 📝更新日志
+v1.2.0 / 2024.12.01
+
+- ✨ 脚注内容模板支持编号${index}, 主要用于脚注编号
+- 🔥 取消脚注启用编号对脚注内容块添加命名的操作
+
+ 
+
v1.1.7
- ✨ 现在不勾选脚注自动编号时,添加脚注的弹窗可以使用思源富文本功能编辑脚注内容啦,但是勾选脚注自动编号,还是只能纯文本格式添加脚注内容
@@ -55,7 +62,7 @@ v1.1.6 / 2024.11.30 脚注支持脚注数字编号啦!
* **选中文本的样式**:选择无样式或自定义样式。默认:`无样式`。
* **脚注自动数字编号**:使用数字编号(如[1], [2]等)替代自定义锚文本。开启后每次新建和删除脚注会自动对所有脚注重新排序编号。
注意:目前开启此项,当脚注数量越多,排序耗时越长,介意请勿开启。
- * **脚注内容模板**:设置生成脚注内容的样式,推荐使用嵌套引述块或超级块来存放脚注内容,保证脚注内容属于同一个块,`${selection}`代表选中文本的内容,`${content}`代表脚注内容占位,`${refID}`代表选中文本所在的块的ID。另外可以使用kramdown语法设置脚注内容块的块样式。
+ * **脚注内容模板**:设置生成脚注内容的样式,推荐使用嵌套引述块或超级块来存放脚注内容,保证脚注内容属于同一个块,`${selection}`代表选中文本的内容,`${content}`代表脚注内容占位,`${refID}`代表选中文本所在的块的ID,`${index}`脚注编号默认带原块链接,`${index:text}`脚注编号纯文本。另外可以使用kramdown语法设置脚注内容块的块样式。
* **脚注内容块的别名**:设置脚注内容块的别名,提示这个块是脚注内容,设置为空则不设置别名。默认为空。
* **自定义样式**:自定义脚注块引、添加脚注时选中文字的样式、脚注内容块的样式。
* **重置设置**:重置插件设置为默认值
@@ -96,7 +103,8 @@ v1.1.6 / 2024.11.30 脚注支持脚注数字编号啦!
* `${selection}`代表选中文本的内容
* `${content}`代表脚注内容占位
-* `${refID}`代表选中文本所在的块的ID。
+* `${refID}`代表选中文本所在的块的ID
+* `${index}`脚注编号默认带原块链接,`${index:text}`脚注编号纯文本
下面列举一些用户可能用到的模板
@@ -206,48 +214,6 @@ ${content}
color: var(--b3-font-color5);
}
```
-
-### 如何模拟传统的脚注编号样式
-
-
-
-如果你想让脚注插件生成的脚注模拟传统的脚注编号样式,可以这样设置
-
-1. 开启【脚注自动数字编号】功能
-2. 插件设置中脚注内容模板设置为
-
- ```markdown
- ${content}
- ```
-3. 插件设置中的自定义样式可以设置为
-
- ```css
- /* 为脚注内容块添加相对定位,作为编号定位的参考 */
- .protyle-wysiwyg [data-node-id][custom-plugin-footnote-content] {
- position: relative;
- padding-left: 2em; /* 为编号预留空间 */
- font-size: 0.8em; /* 设置字体大小 */
- }
-
- /* 编号使用绝对定位,实现悬挂效果 */
- .protyle-wysiwyg [data-node-id][custom-plugin-footnote-content]:before {
- content: '[' attr(name) ']';
- position: absolute;
- left: 0; /* 编号靠左对齐 */
- top: 2px; /* 与内容顶部对齐 */
- }
-
- /* 脚注内容块保持块级显示,确保换行正确 */
- .protyle-wysiwyg [data-node-id][custom-plugin-footnote-content]>div:first-child {
- display: block;
- }
-
- /* 隐藏脚注内容块命名 */
- .protyle-wysiwyg [data-node-id][custom-plugin-footnote-content]>div:nth-child(2)>.protyle-attr--name {
- display: none;
- }
- ```
-
## 🙏致谢
diff --git a/public/i18n/zh_CN.json b/public/i18n/zh_CN.json
index 2c16700..99ebcc6 100644
--- a/public/i18n/zh_CN.json
+++ b/public/i18n/zh_CN.json
@@ -69,7 +69,7 @@
},
"template": {
"title": "脚注内容模版",
- "description": "模板变量:${selection}
选中文本的内容,${content}
脚注内容占位,${refID}
选中文本所在的块的ID
使用${{...}}
可以使用Sprig语法,例如插入当前时间${{now | date \"20060102 15:04:05\"}}
可以使用kramdown语法设置块样式"
+ "description": "模板变量:${selection}
选中文本的内容,${content}
脚注内容占位,${refID}
选中文本所在的块的ID,${index}
脚注编号默认带原块链接,${index:text}
脚注编号纯文本使用${{...}}
可以使用Sprig语法,例如插入当前时间${{now | date \"20060102 15:04:05\"}}
可以使用kramdown语法设置块样式"
},
"footnoteAlias": {
"title": "脚注内容块的别名",
diff --git a/src/index.ts b/src/index.ts
index ec40262..26ddb48 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -7,7 +7,7 @@ import {
import "@/index.scss";
import { IMenuItem } from "siyuan/types";
-import { appendBlock, deleteBlock, setBlockAttrs, getBlockAttrs, pushMsg, pushErrMsg, sql, renderSprig, getChildBlocks, insertBlock, renameDocByID, prependBlock, updateBlock, createDocWithMd, getDoc, getBlockKramdown } from "./api";
+import { appendBlock, deleteBlock, setBlockAttrs, getBlockAttrs, pushMsg, pushErrMsg, sql, renderSprig, getChildBlocks, insertBlock, renameDocByID, prependBlock, updateBlock, createDocWithMd, getDoc, getBlockKramdown, getBlockDOM } from "./api";
import { SettingUtils } from "./libs/setting-utils";
const STORAGE_NAME = "config";
@@ -327,11 +327,8 @@ export default class PluginFootnote extends Plugin {
footnoteBlockref: this.i18n.settings.footnoteBlockref.value,
selectFontStyle: '1',
templates: `{{{row
-> \${selection} [[↩️]](siyuan://blocks/\${refID})
-
-\${content}
-}}}
-{: style="border: 2px dashed var(--b3-border-color);"}}`,
+\${index} \${content}
+}}}`,
enableOrderedFootnotes: false, // Add new setting
footnoteAlias: '',
css: this.STYLES
@@ -399,7 +396,7 @@ export default class PluginFootnote extends Plugin {
},
editorCallback: async (protyle: any) => {
if (protyle.block?.rootID) {
- await this.reorderFootnotes(protyle.block.rootID, true);
+ await this.reorderFootnotes(protyle.block.rootID, true);
await pushMsg(this.i18n.cancelReorderFootnotes + " ...");
await pushMsg(this.i18n.cancelReorderFootnotes + " Finished");
}
@@ -544,12 +541,7 @@ export default class PluginFootnote extends Plugin {
this.settingUtils.addItem({
key: "templates",
- value: `{{{row
-> \${selection} [[↩️]](siyuan://blocks/\${refID})
-
-\${content}
-}}}
-{: style="border: 2px dashed var(--b3-border-color);"}}`,
+ value: this.getDefaultSettings().templates,
type: "textarea",
title: this.i18n.settings.template.title,
description: this.i18n.settings.template.description,
@@ -865,6 +857,8 @@ export default class PluginFootnote extends Plugin {
templates = templates.replace(/\$\{selection\}/g, cleanSelection);
templates = templates.replace(/\$\{content\}/g, zeroWhite);
templates = templates.replace(/\$\{refID\}/g, currentBlockId);
+ templates = templates.replace(/\$\{index\}/g, `[注]`); // 支持添加脚注编号
+ templates = templates.replace(/\$\{index:text\}/g, `[注]`); // 支持添加脚注编号
templates = await renderTemplates(templates);
async function renderTemplates(templates: string): Promise {
@@ -1057,6 +1051,20 @@ export default class PluginFootnote extends Plugin {
async (content) => {
// Get existing block attributes before update
const existingAttrs = await getBlockAttrs(newBlockId);
+ // 获取脚注内容块的内容
+ const originDOM = (await getBlockDOM(newBlockId)).dom;
+
+ // DOM是string,使用正则表达式检测是否span[data - type*= "custom-footnote-index"]节点,如果有则提取其[number]中的数字
+ let number = 0;
+ if (originDOM) {
+ // 使用 .*? 来匹配 data-type 中任意的前缀值
+ const match = originDOM.match(/[${number}]`) // 支持添加脚注编号
+ .replace(/\$\{index:text\}/g, `[${number}]`); // 支持添加脚注编号
const renderedTemplate = await renderTemplates(templates);
@@ -1075,7 +1085,7 @@ export default class PluginFootnote extends Plugin {
if (existingAttrs) {
await setBlockAttrs(newBlockId, {
"custom-plugin-footnote-content": existingAttrs["custom-plugin-footnote-content"],
- "name": existingAttrs["name"],
+ // "name": existingAttrs["name"],
"alias": existingAttrs["alias"]
});
}
@@ -1167,33 +1177,52 @@ export default class PluginFootnote extends Plugin {
});
// Reorder footnote blocks if needed
+ // 获取脚注块并更新编号
const footnoteBlocks = Array.from(footnoteContainerDom.querySelectorAll(`[custom-plugin-footnote-content="${docID}"]`));
- if (footnoteBlocks.length > 0 && reorderBlocks) {
- const parent = footnoteBlocks[0].parentNode;
- if (parent) {
- let referenceNode = footnoteBlocks[0].previousSibling;
- footnoteBlocks.forEach(block => block.remove());
-
- // Sort and reinsert blocks
- footnoteBlocks
- .sort((a, b) => {
- const aId = a.getAttribute('data-node-id');
- const bId = b.getAttribute('data-node-id');
- const aOrder = footnoteOrder.get(aId) || Infinity;
- const bOrder = footnoteOrder.get(bId) || Infinity;
- return aOrder - bOrder;
- })
- .forEach(block => {
- if (referenceNode) {
- referenceNode.after(block);
- referenceNode = block;
- } else {
- parent.insertBefore(block, parent.firstChild);
+ if (footnoteBlocks.length > 0) {
+ footnoteBlocks.forEach(block => {
+ // 获取脚注块的ID
+ const blockId = block.getAttribute('data-node-id');
+ if (blockId) {
+ // 获取该块对应的编号
+ const number = footnoteOrder.get(blockId);
+ if (number) {
+ // 查找并更新块内的索引编号元素
+ const indexSpan = block.querySelector('span[data-type*="custom-footnote-index"]');
+ if (indexSpan) {
+ indexSpan.textContent = `[${number}]`;
}
- });
+ }
+ }
+ });
+
+ // 如果需要重排序
+ if (reorderBlocks) {
+ const parent = footnoteBlocks[0].parentNode;
+ if (parent) {
+ let referenceNode = footnoteBlocks[0].previousSibling;
+ footnoteBlocks.forEach(block => block.remove());
+
+ // 排序并重新插入块
+ footnoteBlocks
+ .sort((a, b) => {
+ const aId = a.getAttribute('data-node-id');
+ const bId = b.getAttribute('data-node-id');
+ const aOrder = footnoteOrder.get(aId) || Infinity;
+ const bOrder = footnoteOrder.get(bId) || Infinity;
+ return aOrder - bOrder;
+ })
+ .forEach(block => {
+ if (referenceNode) {
+ referenceNode.after(block);
+ referenceNode = block;
+ } else {
+ parent.insertBefore(block, parent.firstChild);
+ }
+ });
+ }
}
}
-
// Save changes
if (protyle) {
// 应该获取protyle.wysiwyg.element.innerHTML
@@ -1204,31 +1233,31 @@ export default class PluginFootnote extends Plugin {
await updateBlock("dom", currentDom.body.innerHTML, docID);
}
if (footnoteContainerDocID !== docID) {
- console.log("不一样")
await updateBlock("dom", footnoteContainerDom.body.innerHTML, footnoteContainerDocID);
}
// Update footnote block attributes
- await Promise.all(
- Array.from(blockRefs).map(async ref => {
- const blockId = ref.getAttribute('custom-footnote');
- const number = footnoteOrder.get(blockId);
-
- // Improved block existence check
- if (blockId && number) {
- // Query the database to check if block exists
- const blockExists = await sql(
- `SELECT id FROM blocks WHERE id = '${blockId}' LIMIT 1`
- );
-
- if (blockExists && blockExists.length > 0) {
- return setBlockAttrs(blockId, { "name": number.toString() });
- }
- }
- }).filter(Boolean)
- );
+ // await Promise.all(
+ // Array.from(blockRefs).map(async ref => {
+ // const blockId = ref.getAttribute('custom-footnote');
+ // const number = footnoteOrder.get(blockId);
+
+ // // Improved block existence check
+ // if (blockId && number) {
+ // // Query the database to check if block exists
+ // const blockExists = await sql(
+ // `SELECT id FROM blocks WHERE id = '${blockId}' LIMIT 1`
+ // );
+
+ // if (blockExists && blockExists.length > 0) {
+ // return setBlockAttrs(blockId, { "name": number.toString() });
+ // }
+ // }
+ // }).filter(Boolean)
+ // );
}
+ // TODO: 脚注内容块改为用(await getBlockDOM(footnoteId)).dom获取dom,然后使用正则表达式将span[data-type*="custom-footnote-index"]的textContent替换[注]
private async cancelReorderFootnotes(docID: string, reorderBlocks: boolean) {
// Get current document DOM
const doc = await getDoc(docID);
@@ -1245,19 +1274,25 @@ export default class PluginFootnote extends Plugin {
ref.textContent = defaultAnchor;
const footnoteId = ref.getAttribute('custom-footnote');
if (footnoteId && !footnoteIds.has(footnoteId)) {
- footnoteIds.add(footnoteId);
+ footnoteIds.add(footnoteId);
}
});
// update dom
await updateBlock("dom", currentDom.body.innerHTML, docID);
- // Update footnote block attributes
+ // Update footnote blocks
await Promise.all(
Array.from(footnoteIds).map(async footnoteId => {
- return setBlockAttrs(footnoteId, { "name": "" });
+ let footnoteBlock = (await getBlockDOM(footnoteId)).dom;
+ if (footnoteBlock) {
+ footnoteBlock = footnoteBlock.replace(/(