mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-09-22 00:20:47 +02:00
Compare commits
20 commits
master
...
v3.3.3-dev
Author | SHA1 | Date | |
---|---|---|---|
![]() |
eca318c4ff | ||
![]() |
9f76274747 | ||
![]() |
582f60f574 | ||
![]() |
a2329077e7 | ||
![]() |
a63686cb05 | ||
![]() |
d6e7d0163a | ||
![]() |
6cc6ef66f9 | ||
![]() |
72c84f5f3d | ||
![]() |
043511c2b8 | ||
![]() |
e37ab0db78 | ||
![]() |
fd83286438 | ||
![]() |
24285aae56 | ||
![]() |
8cbefc8788 | ||
![]() |
deb9b933af | ||
![]() |
8476ddd18c | ||
![]() |
ee4ddf89c1 | ||
![]() |
d5e7b27a11 | ||
![]() |
9c37468386 | ||
![]() |
de19d69f99 | ||
![]() |
9a15b466f3 |
30 changed files with 958 additions and 652 deletions
|
@ -1,5 +1,9 @@
|
|||
document.body.insertAdjacentHTML('afterbegin', `<svg id="iconsAnt" style="position: absolute; width: 0; height: 0; overflow: hidden;" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<symbol id="iconInclude" viewBox="0 0 32 32">
|
||||
<path d="M22.091 2.435v7.747h7.582v13.65h-2.637v-11.013h-4.945v9.156h-9.436v5.11h11.036v2.637h-13.674v-7.747h-7.582v-13.65h2.637v11.013h4.945v-9.156h9.436l0-5.11h-11.036v-2.637h13.674zM19.454 12.82h-6.799v6.518l6.799 0v-6.518z"></path>
|
||||
<path d="M1 1h5.604v5.604h-5.604zM25.396 1h5.604v5.604h-5.604zM25.396 25.396h5.604v5.604h-5.604zM1 25.396h5.604v5.604h-5.604z"></path>
|
||||
</symbol>
|
||||
<symbol id="iconGroups" viewBox="0 0 32 32">
|
||||
<path d="M3.074 1c-0.646 0-1.17 0.524-1.17 1.17s0.524 1.17 1.17 1.17h25.851c0.646 0 1.17-0.524 1.17-1.17s-0.524-1.17-1.17-1.17v0zM3.074 17.526c-0.646 0-1.17 0.524-1.17 1.17s0.524 1.17 1.17 1.17h25.851c0.646 0 1.17-0.524 1.17-1.17s-0.524-1.17-1.17-1.17v0zM1.904 8.517c0-1.175 0.953-2.128 2.128-2.128v0h3.83c1.175 0 2.128 0.953 2.128 2.128v0 3.83c0 1.175-0.953 2.128-2.128 2.128v0h-3.83c-1.175 0-2.128-0.953-2.128-2.128v0zM4.245 8.73v3.404h3.404v-3.404zM14.085 6.389c-1.175 0-2.128 0.953-2.128 2.128v0 3.83c0 1.175 0.953 2.128 2.128 2.128v0h3.83c1.175 0 2.128-0.953 2.128-2.128v0-3.83c0-1.175-0.953-2.128-2.128-2.128v0zM14.298 12.134v-3.404h3.404v3.404zM22.011 8.517c0-1.175 0.953-2.128 2.128-2.128v0h3.83c1.175 0 2.128 0.953 2.128 2.128v0 3.83c0 1.175-0.953 2.128-2.128 2.128v0h-3.83c-1.175 0-2.128-0.953-2.128-2.128v0zM24.351 8.73v3.404h3.404v-3.404zM4.032 22.915c-1.175 0-2.128 0.953-2.128 2.128v0 3.83c0 1.175 0.953 2.128 2.128 2.128v0h3.83c1.175 0 2.128-0.953 2.128-2.128v0-3.83c0-1.175-0.953-2.128-2.128-2.128v0zM4.245 28.66v-3.404h3.404v3.404zM11.957 25.043c0-1.175 0.953-2.128 2.128-2.128v0h3.83c1.175 0 2.128 0.953 2.128 2.128v0 3.83c0 1.175-0.953 2.128-2.128 2.128v0h-3.83c-1.175 0-2.128-0.953-2.128-2.128v0zM14.298 25.255v3.404h3.404v-3.404zM24.138 22.915c-1.175 0-2.128 0.953-2.128 2.128v0 3.83c0 1.175 0.953 2.128 2.128 2.128v0h3.83c1.175 0 2.128-0.953 2.128-2.128v0-3.83c0-1.175-0.953-2.128-2.128-2.128v0zM24.351 28.66v-3.404h3.404v3.404z"></path>
|
||||
</symbol>
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
"name": "ant",
|
||||
"author": "Vanessa",
|
||||
"url": "https://github.com/Vanessa219",
|
||||
"version": "1.34.0"
|
||||
"version": "1.35.0"
|
||||
}
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
<body>
|
||||
<h2>SiYuan</h2>
|
||||
<div class="fn__clear">
|
||||
<div>
|
||||
<svg>
|
||||
<use xlink:href="#iconInclude"></use>
|
||||
</svg>
|
||||
iconGroups
|
||||
</div>
|
||||
<div>
|
||||
<svg>
|
||||
<use xlink:href="#iconGroups"></use>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
document.body.insertAdjacentHTML('afterbegin', `<svg id="iconsMaterial" style="position: absolute; width: 0; height: 0; overflow: hidden;" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<symbol id="iconInclude" viewBox="0 0 32 32">
|
||||
<path d="M22.091 2.435v7.747h7.582v13.65h-2.637v-11.013h-4.945v9.156h-9.436v5.11h11.036v2.637h-13.674v-7.747h-7.582v-13.65h2.637v11.013h4.945v-9.156h9.436l0-5.11h-11.036v-2.637h13.674zM19.454 12.82h-6.799v6.518l6.799 0v-6.518z"></path>
|
||||
<path d="M1 1h5.604v5.604h-5.604zM25.396 1h5.604v5.604h-5.604zM25.396 25.396h5.604v5.604h-5.604zM1 25.396h5.604v5.604h-5.604z"></path>
|
||||
</symbol>
|
||||
<symbol id="iconGroups" viewBox="0 0 32 32">
|
||||
<path d="M3.074 1c-0.646 0-1.17 0.524-1.17 1.17s0.524 1.17 1.17 1.17h25.851c0.646 0 1.17-0.524 1.17-1.17s-0.524-1.17-1.17-1.17v0zM3.074 17.526c-0.646 0-1.17 0.524-1.17 1.17s0.524 1.17 1.17 1.17h25.851c0.646 0 1.17-0.524 1.17-1.17s-0.524-1.17-1.17-1.17v0zM1.904 8.517c0-1.175 0.953-2.128 2.128-2.128v0h3.83c1.175 0 2.128 0.953 2.128 2.128v0 3.83c0 1.175-0.953 2.128-2.128 2.128v0h-3.83c-1.175 0-2.128-0.953-2.128-2.128v0zM4.245 8.73v3.404h3.404v-3.404zM14.085 6.389c-1.175 0-2.128 0.953-2.128 2.128v0 3.83c0 1.175 0.953 2.128 2.128 2.128v0h3.83c1.175 0 2.128-0.953 2.128-2.128v0-3.83c0-1.175-0.953-2.128-2.128-2.128v0zM14.298 12.134v-3.404h3.404v3.404zM22.011 8.517c0-1.175 0.953-2.128 2.128-2.128v0h3.83c1.175 0 2.128 0.953 2.128 2.128v0 3.83c0 1.175-0.953 2.128-2.128 2.128v0h-3.83c-1.175 0-2.128-0.953-2.128-2.128v0zM24.351 8.73v3.404h3.404v-3.404zM4.032 22.915c-1.175 0-2.128 0.953-2.128 2.128v0 3.83c0 1.175 0.953 2.128 2.128 2.128v0h3.83c1.175 0 2.128-0.953 2.128-2.128v0-3.83c0-1.175-0.953-2.128-2.128-2.128v0zM4.245 28.66v-3.404h3.404v3.404zM11.957 25.043c0-1.175 0.953-2.128 2.128-2.128v0h3.83c1.175 0 2.128 0.953 2.128 2.128v0 3.83c0 1.175-0.953 2.128-2.128 2.128v0h-3.83c-1.175 0-2.128-0.953-2.128-2.128v0zM14.298 25.255v3.404h3.404v-3.404zM24.138 22.915c-1.175 0-2.128 0.953-2.128 2.128v0 3.83c0 1.175 0.953 2.128 2.128 2.128v0h3.83c1.175 0 2.128-0.953 2.128-2.128v0-3.83c0-1.175-0.953-2.128-2.128-2.128v0zM24.351 28.66v-3.404h3.404v3.404z"></path>
|
||||
</symbol>
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
"name": "material",
|
||||
"author": "Vanessa",
|
||||
"url": "https://github.com/Vanessa219",
|
||||
"version": "1.34.0"
|
||||
"version": "1.35.0"
|
||||
}
|
||||
|
|
|
@ -14,12 +14,7 @@ import {fetchPost, fetchSyncPost} from "../../util/fetch";
|
|||
import {openEmojiPanel, unicode2Emoji} from "../../emoji";
|
||||
import {mountHelp, newNotebook} from "../../util/mount";
|
||||
import {confirmDialog} from "../../dialog/confirmDialog";
|
||||
import {
|
||||
isNotCtrl,
|
||||
isOnlyMeta,
|
||||
setStorageVal,
|
||||
updateHotkeyAfterTip
|
||||
} from "../../protyle/util/compatibility";
|
||||
import {isNotCtrl, isOnlyMeta, setStorageVal, updateHotkeyAfterTip} from "../../protyle/util/compatibility";
|
||||
import {openFileById} from "../../editor/util";
|
||||
import {
|
||||
hasClosestByAttribute,
|
||||
|
@ -178,18 +173,6 @@ export class Files extends Model {
|
|||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
break;
|
||||
} else if (type === "remove") {
|
||||
confirmDialog(window.siyuan.languages.deleteOpConfirm,
|
||||
`${window.siyuan.languages.confirmDelete} <b>${escapeHtml(target.parentElement.querySelector(".b3-list-item__text").textContent)}</b>?`, () => {
|
||||
fetchPost("/api/notebook/removeNotebook", {
|
||||
notebook: target.getAttribute("data-url"),
|
||||
callback: Constants.CB_MOUNT_REMOVE
|
||||
});
|
||||
}, undefined, true);
|
||||
window.siyuan.menus.menu.remove();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
break;
|
||||
} else if (type === "open") {
|
||||
fetchPost("/api/notebook/openNotebook", {
|
||||
notebook: target.getAttribute("data-url")
|
||||
|
@ -813,14 +796,14 @@ export class Files extends Model {
|
|||
private genNotebook(item: INotebook) {
|
||||
const emojiHTML = `<span class="b3-list-item__icon b3-tooltips b3-tooltips__e" aria-label="${window.siyuan.languages.changeIcon}">${unicode2Emoji(item.icon || window.siyuan.storage[Constants.LOCAL_IMAGES].note)}</span>`;
|
||||
if (item.closed) {
|
||||
return `<li data-type="open" data-url="${item.id}" class="b3-list-item b3-list-item--hide-action">
|
||||
return `<li data-url="${item.id}" class="b3-list-item b3-list-item--hide-action">
|
||||
<span class="b3-list-item__toggle fn__hidden">
|
||||
<svg class="b3-list-item__arrow"><use xlink:href="#iconRight"></use></svg>
|
||||
</span>
|
||||
${emojiHTML}
|
||||
<span class="b3-list-item__text">${escapeHtml(item.name)}</span>
|
||||
<span data-type="remove" data-url="${item.id}" class="b3-list-item__action b3-tooltips b3-tooltips__w${(window.siyuan.config.readonly) ? " fn__none" : ""}" aria-label="${window.siyuan.languages.delete}">
|
||||
<svg><use xlink:href="#iconTrashcan"></use></svg>
|
||||
<span class="b3-list-item__text" style="cursor: default;">${escapeHtml(item.name)}</span>
|
||||
<span data-type="open" data-url="${item.id}" class="b3-list-item__action b3-tooltips b3-tooltips__w${(window.siyuan.config.readonly) ? " fn__none" : ""}" aria-label="${window.siyuan.languages.openBy}">
|
||||
<svg><use xlink:href="#iconOpen"></use></svg>
|
||||
</span>
|
||||
</li>`;
|
||||
} else {
|
||||
|
@ -1016,6 +999,12 @@ data-type="navigation-root" data-path="/">
|
|||
} else {
|
||||
sourceElement.remove();
|
||||
}
|
||||
} else {
|
||||
const parentElement = this.element.querySelector(`ul[data-url="${response.data.fromNotebook}"] li[data-path="${pathPosix().dirname(response.data.fromPath)}.sy"]`) as HTMLElement;
|
||||
if (parentElement && parentElement.getAttribute("data-count") === "1") {
|
||||
parentElement.querySelector(".b3-list-item__toggle").classList.add("fn__hidden");
|
||||
parentElement.querySelector(".b3-list-item__arrow").classList.remove("b3-list-item__arrow--open");
|
||||
}
|
||||
}
|
||||
const newElement = this.element.querySelector(`[data-url="${response.data.toNotebook}"] li[data-path="${response.data.toPath}"]`) as HTMLElement;
|
||||
// 更新移动到的新文件夹
|
||||
|
|
|
@ -750,7 +750,7 @@ export const newModelByInitData = (app: App, tab: Tab, json: any) => {
|
|||
rootId: json.rootId,
|
||||
blockId: json.blockId,
|
||||
mode: json.mode,
|
||||
action: typeof json.action === "string" ? [json.action] : json.action,
|
||||
action: typeof json.action === "string" ? [json.action, Constants.CB_GET_FOCUS] : json.action.concat(Constants.CB_GET_FOCUS),
|
||||
});
|
||||
}
|
||||
return model;
|
||||
|
|
|
@ -176,17 +176,6 @@ export class MobileFiles extends Model {
|
|||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
break;
|
||||
} else if (type === "remove") {
|
||||
confirmDialog(window.siyuan.languages.deleteOpConfirm,
|
||||
`${window.siyuan.languages.confirmDelete} <b>${escapeHtml(target.parentElement.querySelector(".b3-list-item__text").textContent)}</b>?`, () => {
|
||||
fetchPost("/api/notebook/removeNotebook", {
|
||||
notebook: target.getAttribute("data-url"),
|
||||
callback: Constants.CB_MOUNT_REMOVE
|
||||
});
|
||||
}, undefined, true);
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
break;
|
||||
} else if (type === "open") {
|
||||
fetchPost("/api/notebook/openNotebook", {
|
||||
notebook: target.getAttribute("data-url")
|
||||
|
@ -309,14 +298,14 @@ export class MobileFiles extends Model {
|
|||
private genNotebook(item: INotebook) {
|
||||
const emojiHTML = `<span class="b3-list-item__icon b3-tooltips b3-tooltips__e" aria-label="${window.siyuan.languages.changeIcon}">${unicode2Emoji(item.icon || window.siyuan.storage[Constants.LOCAL_IMAGES].note)}</span>`;
|
||||
if (item.closed) {
|
||||
return `<li data-type="open" data-url="${item.id}" class="b3-list-item">
|
||||
return `<li data-url="${item.id}" class="b3-list-item">
|
||||
<span class="b3-list-item__toggle fn__hidden">
|
||||
<svg class="b3-list-item__arrow"><use xlink:href="#iconRight"></use></svg>
|
||||
</span>
|
||||
${emojiHTML}
|
||||
<span class="b3-list-item__text">${escapeHtml(item.name)}</span>
|
||||
<span data-type="remove" data-url="${item.id}" class="b3-list-item__action${(window.siyuan.config.readonly) ? " fn__none" : ""}">
|
||||
<svg><use xlink:href="#iconTrashcan"></use></svg>
|
||||
<span data-type="open" data-url="${item.id}" class="b3-list-item__action${(window.siyuan.config.readonly) ? " fn__none" : ""}">
|
||||
<svg><use xlink:href="#iconOpen"></use></svg>
|
||||
</span>
|
||||
</li>`;
|
||||
} else {
|
||||
|
@ -402,6 +391,12 @@ export class MobileFiles extends Model {
|
|||
} else {
|
||||
sourceElement.remove();
|
||||
}
|
||||
} else {
|
||||
const parentElement = this.element.querySelector(`ul[data-url="${data.fromNotebook}"] li[data-path="${pathPosix().dirname(data.fromPath)}.sy"]`) as HTMLElement;
|
||||
if (parentElement && parentElement.getAttribute("data-count") === "1") {
|
||||
parentElement.querySelector(".b3-list-item__toggle").classList.add("fn__hidden");
|
||||
parentElement.querySelector(".b3-list-item__arrow").classList.remove("b3-list-item__arrow--open");
|
||||
}
|
||||
}
|
||||
const newElement = this.element.querySelector(`[data-url="${data.toNotebook}"] li[data-path="${data.toPath}"]`) as HTMLElement;
|
||||
// 重新展开移动到的新文件夹
|
||||
|
|
|
@ -752,7 +752,7 @@ export const popSearch = (app: App, searchConfig?: any) => {
|
|||
<div class="toolbar">
|
||||
<span class="fn__flex-1"></span>
|
||||
<svg data-type="toggle-replace" class="toolbar__icon${config.hasReplace ? " toolbar__icon--active" : ""}"><use xlink:href="#iconReplace"></use></svg>
|
||||
<svg ${enableIncludeChild ? "" : "disabled"} data-type="include" class="toolbar__icon${includeChild ? " toolbar__icon--active" : ""}"><use xlink:href="#iconCopy"></use></svg>
|
||||
<svg ${enableIncludeChild ? "" : "disabled"} data-type="include" class="toolbar__icon${includeChild ? " toolbar__icon--active" : ""}"><use xlink:href="#iconInclude"></use></svg>
|
||||
<svg data-type="path" class="toolbar__icon"><use xlink:href="#iconFolder"></use></svg>
|
||||
<svg ${document.querySelector("#empty").classList.contains("fn__none") ? "" : "disabled"} data-type="currentPath" class="toolbar__icon"><use xlink:href="#iconFocus"></use></svg>
|
||||
<svg data-type="expand" class="toolbar__icon${config.group === 0 ? " fn__none" : ""}"><use xlink:href="#iconExpand"></use></svg>
|
||||
|
|
|
@ -58,7 +58,7 @@ export class Breadcrumb {
|
|||
<span class="protyle-breadcrumb__space"></span>
|
||||
<button class="protyle-breadcrumb__icon fn__none ariaLabel" aria-label="${updateHotkeyTip(window.siyuan.config.keymap.editor.general.exitFocus.custom)}" data-type="exit-focus">${window.siyuan.languages.exitFocus}</button>
|
||||
${padHTML}
|
||||
<button class="block__icon fn__flex-center ariaLabel${window.siyuan.config.readonly ? " fn__none" : ""}" aria-label="${window.siyuan.languages.lockEdit}" data-type="readonly"><svg><use xlink:href="#iconUnlock"></use></svg></button>
|
||||
<button class="block__icon fn__flex-center ariaLabel${window.siyuan.config.readonly ? " fn__none" : ""}" aria-label="${window.siyuan.languages.lockEdit}" data-type="readonly" data-subtype="unlock"><svg><use xlink:href="#iconUnlock"></use></svg></button>
|
||||
<button class="block__icon fn__flex-center ariaLabel" data-type="doc" aria-label="${isMac() ? window.siyuan.languages.gutterTip2 : window.siyuan.languages.gutterTip2.replace("⇧", "Shift+")}"><svg><use xlink:href="#iconFile"></use></svg></button>
|
||||
<button class="block__icon fn__flex-center ariaLabel" data-type="more" aria-label="${window.siyuan.languages.more}"><svg><use xlink:href="#iconMore"></use></svg></button>
|
||||
<button class="block__icon fn__flex-center fn__none ariaLabel" data-type="context" aria-label="${window.siyuan.languages.context}"><svg><use xlink:href="#iconAlignCenter"></use></svg></button>`;
|
||||
|
|
|
@ -1802,15 +1802,6 @@ export class Gutter {
|
|||
transferBlockRef(id);
|
||||
}
|
||||
}
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
id: "jumpToParentNext",
|
||||
label: window.siyuan.languages.jumpToParentNext,
|
||||
accelerator: window.siyuan.config.keymap.editor.general.jumpToParentNext.custom,
|
||||
click() {
|
||||
hideElements(["select"], protyle);
|
||||
jumpToParent(protyle, nodeElement, "next");
|
||||
}
|
||||
}).element);
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
id: "jumpToParentPrev",
|
||||
label: window.siyuan.languages.jumpToParentPrev,
|
||||
|
@ -1820,6 +1811,15 @@ export class Gutter {
|
|||
jumpToParent(protyle, nodeElement, "previous");
|
||||
}
|
||||
}).element);
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
id: "jumpToParentNext",
|
||||
label: window.siyuan.languages.jumpToParentNext,
|
||||
accelerator: window.siyuan.config.keymap.editor.general.jumpToParentNext.custom,
|
||||
click() {
|
||||
hideElements(["select"], protyle);
|
||||
jumpToParent(protyle, nodeElement, "next");
|
||||
}
|
||||
}).element);
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
id: "jumpToParent",
|
||||
label: window.siyuan.languages.jumpToParent,
|
||||
|
|
|
@ -761,6 +761,7 @@ export const refreshAV = (protyle: IProtyle, operation: IOperation) => {
|
|||
const attrElement = document.querySelector(`.b3-dialog--open[data-key="${Constants.DIALOG_ATTR}"] .custom-attr > [data-av-id="${avID}"]`) as HTMLElement;
|
||||
if (attrElement) {
|
||||
// 更新属性面板
|
||||
attrElement.removeAttribute("data-rendering");
|
||||
renderAVAttribute(attrElement.parentElement, attrElement.dataset.nodeId, protyle);
|
||||
} else {
|
||||
if (operation.action === "insertAttrViewBlock" && operation.context?.ignoreTip !== "true") {
|
||||
|
|
|
@ -14,7 +14,7 @@ export const mermaidRender = (element: Element, cdn = Constants.PROTYLE_CDN) =>
|
|||
if (mermaidElements.length === 0) {
|
||||
return;
|
||||
}
|
||||
addScript(`${cdn}/js/mermaid/mermaid.min.js?v=11.6.0`, "protyleMermaidScript").then(() => {
|
||||
addScript(`${cdn}/js/mermaid/mermaid.min.js?v=11.11.0`, "protyleMermaidScript").then(() => {
|
||||
const config: any = {
|
||||
securityLevel: "loose", // 升级后无 https://github.com/siyuan-note/siyuan/issues/3587,可使用该选项
|
||||
altFontFamily: "sans-serif",
|
||||
|
|
|
@ -368,8 +368,10 @@ export const disabledProtyle = (protyle: IProtyle) => {
|
|||
item.setAttribute("draggable", "false");
|
||||
});
|
||||
if (protyle.breadcrumb) {
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="readonly"] use').setAttribute("xlink:href", "#iconLock");
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="readonly"]').setAttribute("aria-label", window.siyuan.config.editor.readOnly ? window.siyuan.languages.tempUnlock : window.siyuan.languages.unlockEdit);
|
||||
const readonlyButton = protyle.breadcrumb.element.parentElement.querySelector('[data-type="readonly"]');
|
||||
readonlyButton.querySelector("use").setAttribute("xlink:href", "#iconLock");
|
||||
readonlyButton.setAttribute("aria-label", window.siyuan.config.editor.readOnly ? window.siyuan.languages.tempUnlock : window.siyuan.languages.unlockEdit);
|
||||
readonlyButton.setAttribute("data-subtype", "lock");
|
||||
const undoElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="undo"]');
|
||||
if (undoElement && !undoElement.classList.contains("fn__none")) {
|
||||
undoElement.classList.add("fn__none");
|
||||
|
@ -426,8 +428,10 @@ export const enableProtyle = (protyle: IProtyle) => {
|
|||
}
|
||||
});
|
||||
if (protyle.breadcrumb) {
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="readonly"] use').setAttribute("xlink:href", "#iconUnlock");
|
||||
protyle.breadcrumb.element.parentElement.querySelector('[data-type="readonly"]').setAttribute("aria-label", window.siyuan.config.editor.readOnly ? window.siyuan.languages.cancelTempUnlock : window.siyuan.languages.lockEdit);
|
||||
const readonlyButton = protyle.breadcrumb.element.parentElement.querySelector('[data-type="readonly"]');
|
||||
readonlyButton.querySelector("use").setAttribute("xlink:href", "#iconUnlock");
|
||||
readonlyButton.setAttribute("aria-label", window.siyuan.config.editor.readOnly ? window.siyuan.languages.cancelTempUnlock : window.siyuan.languages.lockEdit);
|
||||
readonlyButton.setAttribute("data-subtype", "unlock");
|
||||
const undoElement = protyle.breadcrumb.element.parentElement.querySelector('[data-type="undo"]');
|
||||
if (undoElement && undoElement.classList.contains("fn__none")) {
|
||||
undoElement.classList.remove("fn__none");
|
||||
|
|
|
@ -1741,7 +1741,7 @@ export class WYSIWYG {
|
|||
}
|
||||
const range = getSelection().getRangeAt(0);
|
||||
if (this.element === range.startContainer || this.element.contains(range.startContainer)) {
|
||||
protyle.toolbar.range = range;
|
||||
protyle.toolbar.range = range.cloneRange();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
|
|||
</span>
|
||||
<span class="fn__space"></span>
|
||||
<span data-position="9south" id="searchInclude" ${enableIncludeChild ? "" : "disabled"} aria-label="${window.siyuan.languages.includeChildDoc}" class="block__icon block__icon--show ariaLabel">
|
||||
<svg${includeChild ? ' class="ft__primary"' : ""}><use xlink:href="#iconCopy"></use></svg>
|
||||
<svg${includeChild ? ' class="ft__primary"' : ""}><use xlink:href="#iconInclude"></use></svg>
|
||||
</span>
|
||||
<span class="fn__space"></span>
|
||||
<span id="searchPath" aria-label="${window.siyuan.languages.specifyPath}" class="block__icon block__icon--show ariaLabel" data-position="9south">
|
||||
|
@ -494,6 +494,11 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
|
|||
event.preventDefault();
|
||||
break;
|
||||
} else if (target.id === "searchInclude") {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
if (target.hasAttribute("disabled")) {
|
||||
return;
|
||||
}
|
||||
const svgElement = target.firstElementChild;
|
||||
svgElement.classList.toggle("ft__primary");
|
||||
if (!svgElement.classList.contains("ft__primary")) {
|
||||
|
@ -511,8 +516,6 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
|
|||
}
|
||||
config.page = 1;
|
||||
inputEvent(element, config, edit, true);
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
break;
|
||||
} else if (target.id === "searchReplace") {
|
||||
// ctrl+P 不需要保存
|
||||
|
|
1197
app/stage/protyle/js/mermaid/mermaid.min.js
vendored
1197
app/stage/protyle/js/mermaid/mermaid.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -221,6 +221,10 @@ type View struct {
|
|||
GroupSort int `json:"groupSort"` // 分组排序值,用于手动排序
|
||||
}
|
||||
|
||||
func (view *View) IsGroupView() bool {
|
||||
return nil != view.Group && "" != view.Group.Field
|
||||
}
|
||||
|
||||
// GetGroupValue 获取分组视图的分组值。
|
||||
func (view *View) GetGroupValue() string {
|
||||
if nil == view.GroupVal {
|
||||
|
@ -270,7 +274,7 @@ func (view *View) RemoveGroupByID(groupID string) {
|
|||
|
||||
// GetGroupKey 获取分组视图的分组字段。
|
||||
func (view *View) GetGroupKey(attrView *AttributeView) (ret *Key) {
|
||||
if nil == view.Group || "" == view.Group.Field {
|
||||
if !view.IsGroupView() {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -295,6 +299,7 @@ type LayoutType string
|
|||
const (
|
||||
LayoutTypeTable LayoutType = "table" // 属性视图类型 - 表格
|
||||
LayoutTypeGallery LayoutType = "gallery" // 属性视图类型 - 卡片
|
||||
LayoutTypeKanban LayoutType = "kanban" // 属性视图类型 - 看板
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -530,6 +535,15 @@ func SaveAttributeView(av *AttributeView) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
// 清理渲染回填值
|
||||
for _, kv := range av.KeyValues {
|
||||
for i := len(kv.Values) - 1; i >= 0; i-- {
|
||||
if kv.Values[i].IsRenderAutoFill {
|
||||
kv.Values = append(kv.Values[:i], kv.Values[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var data []byte
|
||||
if util.UseSingleLineSave {
|
||||
data, err = gulu.JSON.MarshalJSON(av)
|
||||
|
|
149
kernel/av/layout_kanban.go
Normal file
149
kernel/av/layout_kanban.go
Normal file
|
@ -0,0 +1,149 @@
|
|||
// SiYuan - Refactor your thinking
|
||||
// Copyright (c) 2020-present, b3log.org
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package av
|
||||
|
||||
import (
|
||||
"github.com/88250/lute/ast"
|
||||
)
|
||||
|
||||
// LayoutKanban 描述了看板视图的结构。
|
||||
type LayoutKanban struct {
|
||||
*BaseLayout
|
||||
|
||||
GroupFields []*ViewKanbanField `json:"field"` // 字段
|
||||
}
|
||||
|
||||
func NewLayoutKanban() *LayoutKanban {
|
||||
return &LayoutKanban{
|
||||
BaseLayout: &BaseLayout{
|
||||
Spec: 0,
|
||||
ID: ast.NewNodeID(),
|
||||
ShowIcon: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ViewKanbanField 描述了看板字段的结构。
|
||||
type ViewKanbanField struct {
|
||||
*BaseField
|
||||
}
|
||||
|
||||
// Kanban 描述了看板视图实例的结构。
|
||||
type Kanban struct {
|
||||
*BaseInstance
|
||||
|
||||
Fields []*KanbanField `json:"fields"` // 卡片字段
|
||||
Cards []*KanbanCard `json:"cards"` // 卡片
|
||||
CardCount int `json:"rowCount"` // 总卡片数
|
||||
}
|
||||
|
||||
// KanbanCard 描述了看板实例卡片的结构。
|
||||
type KanbanCard struct {
|
||||
ID string `json:"id"` // 卡片 ID
|
||||
Values []*KanbanFieldValue `json:"values"` // 卡片字段值
|
||||
}
|
||||
|
||||
// KanbanField 描述了看板实例字段的结构。
|
||||
type KanbanField struct {
|
||||
*BaseInstanceField
|
||||
}
|
||||
|
||||
// KanbanFieldValue 描述了卡片字段实例值的结构。
|
||||
type KanbanFieldValue struct {
|
||||
*BaseValue
|
||||
}
|
||||
|
||||
func (card *KanbanCard) GetID() string {
|
||||
return card.ID
|
||||
}
|
||||
|
||||
func (card *KanbanCard) GetBlockValue() (ret *Value) {
|
||||
for _, v := range card.Values {
|
||||
if KeyTypeBlock == v.ValueType {
|
||||
ret = v.Value
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (card *KanbanCard) GetValues() (ret []*Value) {
|
||||
ret = []*Value{}
|
||||
for _, v := range card.Values {
|
||||
ret = append(ret, v.Value)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (card *KanbanCard) GetValue(keyID string) (ret *Value) {
|
||||
for _, value := range card.Values {
|
||||
if nil != value.Value && keyID == value.Value.KeyID {
|
||||
ret = value.Value
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (kanban *Kanban) GetItems() (ret []Item) {
|
||||
ret = []Item{}
|
||||
for _, card := range kanban.Cards {
|
||||
ret = append(ret, card)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (kanban *Kanban) SetItems(items []Item) {
|
||||
kanban.Cards = []*KanbanCard{}
|
||||
for _, item := range items {
|
||||
kanban.Cards = append(kanban.Cards, item.(*KanbanCard))
|
||||
}
|
||||
}
|
||||
|
||||
func (kanban *Kanban) CountItems() int {
|
||||
return len(kanban.Cards)
|
||||
}
|
||||
|
||||
func (kanban *Kanban) GetFields() (ret []Field) {
|
||||
ret = []Field{}
|
||||
for _, field := range kanban.Fields {
|
||||
ret = append(ret, field)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (kanban *Kanban) GetField(id string) (ret Field, fieldIndex int) {
|
||||
for i, field := range kanban.Fields {
|
||||
if field.ID == id {
|
||||
return field, i
|
||||
}
|
||||
}
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
func (kanban *Kanban) GetValue(itemID, keyID string) (ret *Value) {
|
||||
for _, card := range kanban.Cards {
|
||||
if card.ID == itemID {
|
||||
return card.GetValue(keyID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (kanban *Kanban) GetType() LayoutType {
|
||||
return LayoutTypeKanban
|
||||
}
|
|
@ -57,6 +57,8 @@ type Value struct {
|
|||
Checkbox *ValueCheckbox `json:"checkbox,omitempty"`
|
||||
Relation *ValueRelation `json:"relation,omitempty"`
|
||||
Rollup *ValueRollup `json:"rollup,omitempty"`
|
||||
|
||||
IsRenderAutoFill bool `json:"-"` // 标识是否是渲染阶段自动填充的值,保存数据的时候要删掉
|
||||
}
|
||||
|
||||
func (value *Value) SetUpdatedAt(mills int64) {
|
||||
|
|
|
@ -206,6 +206,12 @@ func DocIAL(absPath string) (ret map[string]string) {
|
|||
return
|
||||
}
|
||||
|
||||
func TreeSize(tree *parse.Tree) (size uint64) {
|
||||
luteEngine := util.NewLute() // 不关注用户的自定义解析渲染选项
|
||||
renderer := render.NewJSONRenderer(tree, luteEngine.RenderOptions)
|
||||
return uint64(len(renderer.Render()))
|
||||
}
|
||||
|
||||
func WriteTree(tree *parse.Tree) (size uint64, err error) {
|
||||
data, filePath, err := prepareWriteTree(tree)
|
||||
if err != nil {
|
||||
|
|
|
@ -101,7 +101,7 @@ func GetAttrViewAddingBlockDefaultValues(avID, viewID, groupID, previousBlockID,
|
|||
return
|
||||
}
|
||||
|
||||
if 1 > len(view.Filters) && nil == view.Group {
|
||||
if 1 > len(view.Filters) && !view.IsGroupView() {
|
||||
// 没有过滤条件也没有分组条件时忽略
|
||||
return
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ func GetAttrViewAddingBlockDefaultValues(avID, viewID, groupID, previousBlockID,
|
|||
func getAttrViewAddingBlockDefaultValues(attrView *av.AttributeView, view, groupView *av.View, previousItemID, addingItemID string) (ret map[string]*av.Value) {
|
||||
ret = map[string]*av.Value{}
|
||||
|
||||
if 1 > len(view.Filters) && nil == view.Group {
|
||||
if 1 > len(view.Filters) && !view.IsGroupView() {
|
||||
// 没有过滤条件也没有分组条件时忽略
|
||||
return
|
||||
}
|
||||
|
@ -533,7 +533,7 @@ func foldAttrViewGroup(avID, blockID, groupID string, folded bool) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
if nil == view.Group {
|
||||
if !view.IsGroupView() {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1032,7 +1032,7 @@ func AppendAttributeViewDetachedBlocksWithValues(avID string, blocksValues [][]*
|
|||
v.IsDetached = true
|
||||
v.CreatedAt = now
|
||||
v.UpdatedAt = now
|
||||
|
||||
v.IsRenderAutoFill = false
|
||||
keyValues.Values = append(keyValues.Values, v)
|
||||
|
||||
if av.KeyTypeSelect == v.Type || av.KeyTypeMSelect == v.Type {
|
||||
|
@ -1725,7 +1725,7 @@ func GetBlockAttributeViewKeys(nodeID string) (ret []*BlockAttributeViewKeys) {
|
|||
}
|
||||
|
||||
func genAttrViewGroups(view *av.View, attrView *av.AttributeView) {
|
||||
if nil == view.Group {
|
||||
if !view.IsGroupView() {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1969,7 +1969,7 @@ type GroupState struct {
|
|||
|
||||
func getAttrViewGroupStates(view *av.View) (groupStates map[string]*GroupState) {
|
||||
groupStates = map[string]*GroupState{}
|
||||
if nil == view.Group {
|
||||
if !view.IsGroupView() {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -2329,6 +2329,7 @@ func updateAttributeViewColRelation(operation *Operation) (err error) {
|
|||
destVal.Relation = &av.ValueRelation{}
|
||||
}
|
||||
destVal.UpdatedAt = now
|
||||
destVal.IsRenderAutoFill = false
|
||||
}
|
||||
destVal.Relation.BlockIDs = append(destVal.Relation.BlockIDs, srcVal.BlockID)
|
||||
destVal.Relation.BlockIDs = gulu.Str.RemoveDuplicatedElem(destVal.Relation.BlockIDs)
|
||||
|
@ -3145,12 +3146,19 @@ func addAttributeViewBlock(now int64, avID, dbBlockID, viewID, groupID, previous
|
|||
// The database date field supports filling the current time by default https://github.com/siyuan-note/siyuan/issues/10823
|
||||
for _, keyValues := range attrView.KeyValues {
|
||||
if av.KeyTypeDate == keyValues.Key.Type && nil != keyValues.Key.Date && keyValues.Key.Date.AutoFillNow {
|
||||
if nil == keyValues.GetValue(addingItemID) { // 避免覆盖已有值(可能前面已经通过过滤或者分组条件填充了值)
|
||||
val := keyValues.GetValue(addingItemID)
|
||||
if nil == val { // 避免覆盖已有值(可能前面已经通过过滤或者分组条件填充了值)
|
||||
dateVal := &av.Value{
|
||||
ID: ast.NewNodeID(), KeyID: keyValues.Key.ID, BlockID: addingItemID, Type: av.KeyTypeDate, IsDetached: isDetached, CreatedAt: now, UpdatedAt: now + 1000,
|
||||
Date: &av.ValueDate{Content: now, IsNotEmpty: true},
|
||||
}
|
||||
keyValues.Values = append(keyValues.Values, dateVal)
|
||||
} else {
|
||||
if val.IsRenderAutoFill {
|
||||
val.CreatedAt, val.UpdatedAt = now, now+1000
|
||||
val.Date.Content, val.Date.IsNotEmpty = now, true
|
||||
val.IsRenderAutoFill = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3230,11 +3238,13 @@ func fillDefaultValue(attrView *av.AttributeView, view, groupView *av.View, prev
|
|||
|
||||
existingVal := keyValues.GetValue(addingItemID)
|
||||
if nil == existingVal {
|
||||
newValue.IsRenderAutoFill = false
|
||||
keyValues.Values = append(keyValues.Values, newValue)
|
||||
} else {
|
||||
newValueRaw := newValue.GetValByType(keyValues.Key.Type)
|
||||
if av.KeyTypeBlock != existingVal.Type || (av.KeyTypeBlock == existingVal.Type && existingVal.IsDetached) {
|
||||
// 非主键的值直接覆盖,主键的值只覆盖非绑定块
|
||||
existingVal.IsRenderAutoFill = false
|
||||
existingVal.SetValByType(keyValues.Key.Type, newValueRaw)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,14 +97,14 @@ func renderAttributeViewGroups(viewable av.Viewable, attrView *av.AttributeView,
|
|||
if isGroupByDate(view) {
|
||||
createdDate := time.UnixMilli(view.GroupCreated).Format("2006-01-02")
|
||||
if time.Now().Format("2006-01-02") != createdDate {
|
||||
regenAttrViewGroups(attrView)
|
||||
genAttrViewGroups(view, attrView) // 仅重新生成一个视图的分组以提升性能
|
||||
av.SaveAttributeView(attrView)
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是按模板分组则需要重新生成分组
|
||||
if isGroupByTemplate(attrView, view) {
|
||||
regenAttrViewGroups(attrView)
|
||||
genAttrViewGroups(view, attrView) // 仅重新生成一个视图的分组以提升性能
|
||||
av.SaveAttributeView(attrView)
|
||||
}
|
||||
|
||||
|
@ -177,7 +177,7 @@ func renderAttributeViewGroups(viewable av.Viewable, attrView *av.AttributeView,
|
|||
}
|
||||
|
||||
func hideEmptyGroupViews(view *av.View, viewable av.Viewable) {
|
||||
if nil == view.Group {
|
||||
if !view.IsGroupView() {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -343,14 +343,14 @@ func sortGroupsBySelectOption(view *av.View, groupKey *av.Key) {
|
|||
}
|
||||
|
||||
func isGroupByDate(view *av.View) bool {
|
||||
if nil == view.Group {
|
||||
if !view.IsGroupView() {
|
||||
return false
|
||||
}
|
||||
return av.GroupMethodDateDay == view.Group.Method || av.GroupMethodDateWeek == view.Group.Method || av.GroupMethodDateMonth == view.Group.Method || av.GroupMethodDateYear == view.Group.Method || av.GroupMethodDateRelative == view.Group.Method
|
||||
}
|
||||
|
||||
func isGroupByTemplate(attrView *av.AttributeView, view *av.View) bool {
|
||||
if nil == view.Group {
|
||||
if !view.IsGroupView() {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -234,6 +234,22 @@ func GetBlockSiblingID(id string) (parent, previous, next string) {
|
|||
next = flb.ID
|
||||
}
|
||||
}
|
||||
|
||||
if "" == previous && "" == next && nil != current {
|
||||
parent = current.ID
|
||||
if nil != current.Previous {
|
||||
previous = current.Previous.ID
|
||||
if flb := treenode.FirstChildBlock(current.Previous); nil != flb {
|
||||
previous = flb.ID
|
||||
}
|
||||
}
|
||||
if nil != current.Next {
|
||||
next = current.Next.ID
|
||||
if flb := treenode.FirstChildBlock(current.Next); nil != flb {
|
||||
next = flb.ID
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -473,6 +473,8 @@ func moveTree(tree *parse.Tree) {
|
|||
|
||||
box := Conf.Box(tree.Box)
|
||||
box.renameSubTrees(tree)
|
||||
|
||||
refreshDocInfo(tree)
|
||||
}
|
||||
|
||||
func (box *Box) renameSubTrees(tree *parse.Tree) {
|
||||
|
|
|
@ -2271,11 +2271,11 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool,
|
|||
|
||||
switch blockRefMode {
|
||||
case 2: // 锚文本块链
|
||||
blockRefLink := &ast.Node{Type: ast.NodeTextMark, TextMarkType: "a", TextMarkTextContent: linkText, TextMarkAHref: "siyuan://blocks/" + defID}
|
||||
blockRefLink := &ast.Node{Type: ast.NodeTextMark, TextMarkTextContent: linkText, TextMarkAHref: "siyuan://blocks/" + defID}
|
||||
blockRefLink.KramdownIAL = n.KramdownIAL
|
||||
if n.IsTextMarkType("inline-memo") {
|
||||
if "block-ref" != n.TextMarkType { // 除了块引还有其他元素 https://github.com/siyuan-note/siyuan/issues/15698
|
||||
blockRefLink.TextMarkType = strings.TrimSpace(strings.ReplaceAll(n.TextMarkType, "block-ref", "a"))
|
||||
blockRefLink.TextMarkInlineMemoContent = n.TextMarkInlineMemoContent
|
||||
blockRefLink.TextMarkType = "a inline-memo"
|
||||
}
|
||||
n.InsertBefore(blockRefLink)
|
||||
unlinks = append(unlinks, n)
|
||||
|
@ -2291,11 +2291,11 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool,
|
|||
}
|
||||
} else {
|
||||
blockRefLink = &ast.Node{Type: ast.NodeText, Tokens: []byte(linkText)}
|
||||
if n.IsTextMarkType("inline-memo") {
|
||||
if "block-ref" != n.TextMarkType {
|
||||
blockRefLink.Type = ast.NodeTextMark
|
||||
blockRefLink.TextMarkInlineMemoContent = n.TextMarkInlineMemoContent
|
||||
blockRefLink.TextMarkType = "inline-memo"
|
||||
blockRefLink.TextMarkType = strings.TrimSpace(strings.ReplaceAll(n.TextMarkType, "block-ref", ""))
|
||||
blockRefLink.TextMarkTextContent = linkText
|
||||
blockRefLink.TextMarkInlineMemoContent = n.TextMarkInlineMemoContent
|
||||
}
|
||||
}
|
||||
n.InsertBefore(blockRefLink)
|
||||
|
@ -2315,13 +2315,13 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool,
|
|||
}
|
||||
|
||||
text := &ast.Node{Type: ast.NodeText, Tokens: []byte(linkText)}
|
||||
n.InsertBefore(text)
|
||||
if n.IsTextMarkType("inline-memo") {
|
||||
if "block-ref" != n.TextMarkType {
|
||||
text.Type = ast.NodeTextMark
|
||||
text.TextMarkType = "inline-memo"
|
||||
text.TextMarkType = strings.TrimSpace(strings.ReplaceAll(n.TextMarkType, "block-ref", ""))
|
||||
text.TextMarkTextContent = linkText
|
||||
text.TextMarkInlineMemoContent = n.TextMarkInlineMemoContent
|
||||
}
|
||||
n.InsertBefore(text)
|
||||
n.InsertBefore(&ast.Node{Type: ast.NodeFootnotesRef, Tokens: []byte("^" + refFoot.refNum), FootnotesRefId: refFoot.refNum, FootnotesRefLabel: []byte("^" + refFoot.refNum)})
|
||||
unlinks = append(unlinks, n)
|
||||
}
|
||||
|
|
|
@ -933,7 +933,7 @@ func writeTreeUpsertQueue(tree *parse.Tree) (err error) {
|
|||
return
|
||||
}
|
||||
sql.UpsertTreeQueue(tree)
|
||||
refreshDocInfo(tree, size)
|
||||
refreshDocInfoWithSize(tree, size)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -959,7 +959,7 @@ func renameWriteJSONQueue(tree *parse.Tree) (err error) {
|
|||
}
|
||||
sql.RenameTreeQueue(tree)
|
||||
treenode.UpsertBlockTree(tree)
|
||||
refreshDocInfo(tree, size)
|
||||
refreshDocInfoWithSize(tree, size)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1371,6 +1371,8 @@ func moveDoc(fromBox *Box, fromPath string, toBox *Box, toPath string, luteEngin
|
|||
return
|
||||
}
|
||||
|
||||
fromParentTree := loadParentTree(tree)
|
||||
|
||||
moveToRoot := "/" == toPath
|
||||
toBlockID := tree.ID
|
||||
fromFolder := path.Join(path.Dir(fromPath), tree.ID)
|
||||
|
@ -1489,6 +1491,8 @@ func moveDoc(fromBox *Box, fromPath string, toBox *Box, toPath string, luteEngin
|
|||
}
|
||||
evt.Callback = callback
|
||||
util.PushEvent(evt)
|
||||
|
||||
refreshDocInfo(fromParentTree)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ package model
|
|||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -38,25 +37,22 @@ import (
|
|||
"github.com/siyuan-note/siyuan/kernel/util"
|
||||
)
|
||||
|
||||
func refreshDocInfo(tree *parse.Tree, size uint64) {
|
||||
func refreshDocInfo(tree *parse.Tree) {
|
||||
refreshDocInfoWithSize(tree, filesys.TreeSize(tree))
|
||||
}
|
||||
|
||||
func refreshDocInfoWithSize(tree *parse.Tree, size uint64) {
|
||||
refreshDocInfo0(tree, size)
|
||||
refreshParentDocInfo(tree)
|
||||
}
|
||||
|
||||
func refreshParentDocInfo(tree *parse.Tree) {
|
||||
parentTree := loadParentTree(tree)
|
||||
if nil == parentTree {
|
||||
return
|
||||
}
|
||||
|
||||
luteEngine := lute.New()
|
||||
boxDir := filepath.Join(util.DataDir, tree.Box)
|
||||
parentDir := path.Dir(tree.Path)
|
||||
if parentDir == boxDir || parentDir == "/" {
|
||||
return
|
||||
}
|
||||
|
||||
parentPath := parentDir + ".sy"
|
||||
parentTree, err := filesys.LoadTree(tree.Box, parentPath, luteEngine)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
renderer := render.NewJSONRenderer(parentTree, luteEngine.RenderOptions)
|
||||
data := renderer.Render()
|
||||
refreshDocInfo0(parentTree, uint64(len(data)))
|
||||
|
|
|
@ -305,3 +305,16 @@ func indexTreeInFilesystem(rootID string) {
|
|||
sql.IndexTreeQueue(tree)
|
||||
logging.LogInfof("reindexed tree by filesystem [rootID=%s]", rootID)
|
||||
}
|
||||
|
||||
func loadParentTree(tree *parse.Tree) (ret *parse.Tree) {
|
||||
boxDir := filepath.Join(util.DataDir, tree.Box)
|
||||
parentDir := path.Dir(tree.Path)
|
||||
if parentDir == boxDir || parentDir == "/" {
|
||||
return
|
||||
}
|
||||
|
||||
luteEngine := lute.New()
|
||||
parentPath := parentDir + ".sy"
|
||||
ret, _ = filesys.LoadTree(tree.Box, parentPath, luteEngine)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -624,6 +624,7 @@ func fillAttributeViewKeyValues(attrView *av.AttributeView, collection av.Collec
|
|||
}
|
||||
}
|
||||
if !exist {
|
||||
val.IsRenderAutoFill = true
|
||||
keyValues.Values = append(keyValues.Values, val)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue