mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-03-06 04:40:15 +01:00
Merge branch 'dev' into markmap
This commit is contained in:
commit
95f2c7eec0
113 changed files with 895 additions and 518 deletions
|
|
@ -11,7 +11,7 @@ import {getThemeMode, setInlineStyle} from "../../util/assets";
|
|||
import {fetchPost, fetchSyncPost} from "../../util/fetch";
|
||||
import {Dialog} from "../../dialog";
|
||||
import {replaceLocalPath} from "../../editor/rename";
|
||||
import {getScreenWidth, isInAndroid, isInHarmony, setStorageVal} from "../util/compatibility";
|
||||
import {getScreenWidth, isInAndroid, isInHarmony, isInIOS, setStorageVal} from "../util/compatibility";
|
||||
import {getFrontend} from "../../util/functions";
|
||||
|
||||
const getPluginStyle = async () => {
|
||||
|
|
@ -117,13 +117,23 @@ export const saveExport = (option: IExportOptions) => {
|
|||
const getSnippetCSS = () => {
|
||||
let snippetCSS = "";
|
||||
document.querySelectorAll("style").forEach((item) => {
|
||||
if (item.id.startsWith("snippet")) {
|
||||
if (item.id.startsWith("snippetCSS")) {
|
||||
snippetCSS += item.outerHTML;
|
||||
}
|
||||
});
|
||||
return snippetCSS;
|
||||
};
|
||||
|
||||
const getSnippetJS = () => {
|
||||
let snippetScript = "";
|
||||
document.querySelectorAll("script").forEach((item) => {
|
||||
if (item.id.startsWith("snippetJS")) {
|
||||
snippetScript += item.outerHTML;
|
||||
}
|
||||
});
|
||||
return snippetScript;
|
||||
};
|
||||
|
||||
/// #if !BROWSER
|
||||
const renderPDF = async (id: string) => {
|
||||
const localData = window.siyuan.storage[Constants.LOCAL_EXPORTPDF];
|
||||
|
|
@ -624,7 +634,9 @@ ${getIconScript(servePath)}
|
|||
}
|
||||
})
|
||||
});
|
||||
</script></body></html>`;
|
||||
</script>
|
||||
${getSnippetJS()}
|
||||
</body></html>`;
|
||||
fetchPost("/api/export/exportTempContent", {content: html}, (response) => {
|
||||
ipcRenderer.send(Constants.SIYUAN_EXPORT_NEWWINDOW, response.data.url);
|
||||
});
|
||||
|
|
@ -705,13 +717,14 @@ export const onExport = async (data: IWebSocketData, filePath: string, servePath
|
|||
themeStyle = `<link rel="stylesheet" type="text/css" id="themeStyle" href="${servePath}appearance/themes/${themeName}/theme.css?${Constants.SIYUAN_VERSION}"/>`;
|
||||
}
|
||||
const screenWidth = getScreenWidth();
|
||||
const mobileHtml = isInAndroid() || isInHarmony() ? {
|
||||
const isInMobile = isInAndroid() || isInHarmony() || isInIOS();
|
||||
const mobileHtml = isInMobile ? {
|
||||
js: `document.body.style.minWidth = "${screenWidth}px";`,
|
||||
css: `@page { size: A4; margin: 10mm 0 10mm 0; }
|
||||
.protyle-wysiwyg {padding: 0; margin: 0;}`
|
||||
} : {js: "", css: ""};
|
||||
const html = `<!DOCTYPE html>
|
||||
<html lang="${window.siyuan.config.appearance.lang}" data-theme-mode="${getThemeMode()}" data-light-theme="${window.siyuan.config.appearance.themeLight}" data-dark-theme="${window.siyuan.config.appearance.themeDark}">
|
||||
<html lang="${window.siyuan.config.appearance.lang}" data-theme-mode="${isInMobile ? "light" : getThemeMode()}" data-light-theme="${window.siyuan.config.appearance.themeLight}" data-dark-theme="${window.siyuan.config.appearance.themeDark}">
|
||||
<head>
|
||||
<base href="${servePath}">
|
||||
<meta charset="utf-8">
|
||||
|
|
@ -775,7 +788,8 @@ ${getIconScript(servePath)}
|
|||
event.stopPropagation();
|
||||
})
|
||||
});
|
||||
</script></body></html>`;
|
||||
</script>
|
||||
${getSnippetJS()}</body></html>`;
|
||||
// 移动端导出 pdf、浏览器导出 HTML
|
||||
if (typeof filePath === "undefined") {
|
||||
return html;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ import {openFileById} from "../../editor/util";
|
|||
import * as path from "path";
|
||||
/// #endif
|
||||
import {checkFold} from "../../util/noRelyPCFunction";
|
||||
import {clearSelect} from "../util/clearSelect";
|
||||
import {clearSelect} from "../util/clear";
|
||||
|
||||
export class Gutter {
|
||||
public element: HTMLElement;
|
||||
|
|
@ -2102,6 +2102,8 @@ export class Gutter {
|
|||
this.genClick(nodeElements, protyle, (e: HTMLElement) => {
|
||||
if (e.classList.contains("av")) {
|
||||
e.style.justifyContent = "";
|
||||
} else if (["NodeIFrame", "NodeWidget"].includes(e.getAttribute("data-type"))) {
|
||||
e.style.margin = "";
|
||||
} else {
|
||||
e.style.textAlign = "left";
|
||||
}
|
||||
|
|
@ -2116,6 +2118,8 @@ export class Gutter {
|
|||
this.genClick(nodeElements, protyle, (e: HTMLElement) => {
|
||||
if (e.classList.contains("av")) {
|
||||
e.style.justifyContent = "center";
|
||||
} else if (["NodeIFrame", "NodeWidget"].includes(e.getAttribute("data-type"))) {
|
||||
e.style.margin = "0 auto";
|
||||
} else {
|
||||
e.style.textAlign = "center";
|
||||
}
|
||||
|
|
@ -2130,6 +2134,8 @@ export class Gutter {
|
|||
this.genClick(nodeElements, protyle, (e: HTMLElement) => {
|
||||
if (e.classList.contains("av")) {
|
||||
e.style.justifyContent = "flex-end";
|
||||
} else if (["NodeIFrame", "NodeWidget"].includes(e.getAttribute("data-type"))) {
|
||||
e.style.margin = "0 0 0 auto";
|
||||
} else {
|
||||
e.style.textAlign = "right";
|
||||
}
|
||||
|
|
@ -2180,6 +2186,8 @@ export class Gutter {
|
|||
this.genClick(nodeElements, protyle, (e: HTMLElement) => {
|
||||
if (e.classList.contains("av")) {
|
||||
e.style.justifyContent = "";
|
||||
} else if (["NodeIFrame", "NodeWidget"].includes(e.getAttribute("data-type"))) {
|
||||
e.style.margin = "";
|
||||
} else {
|
||||
e.style.textAlign = "";
|
||||
e.style.direction = "";
|
||||
|
|
|
|||
|
|
@ -209,8 +209,24 @@ ${unicode2Emoji(emoji.unicode)}</button>`;
|
|||
if (this.element.classList.contains("fn__none")) {
|
||||
this.element.innerHTML = '<div class="fn__loading" style="height: 128px;position: initial"><img width="64px" src="/stage/loading-pure.svg"></div>';
|
||||
this.element.classList.remove("fn__none");
|
||||
const textareaPosition = getSelectionPosition(protyle.wysiwyg.element);
|
||||
setPosition(this.element, textareaPosition.left, textareaPosition.top + 26, 30);
|
||||
if (this.source === "av") {
|
||||
const cellElement = hasClosestByClassName(protyle.toolbar.range.startContainer, "av__cell");
|
||||
if (cellElement) {
|
||||
/// #if !MOBILE
|
||||
const cellRect = cellElement.getBoundingClientRect();
|
||||
setPosition(this.element, cellRect.left, cellRect.bottom, cellRect.height);
|
||||
/// #else
|
||||
setPosition(this.element, 0, 0);
|
||||
/// #endif
|
||||
}
|
||||
} else {
|
||||
/// #if !MOBILE
|
||||
const textareaPosition = getSelectionPosition(protyle.wysiwyg.element);
|
||||
setPosition(this.element, textareaPosition.left, textareaPosition.top + 26, 30);
|
||||
/// #else
|
||||
setPosition(this.element, 0, 0);
|
||||
/// #endif
|
||||
}
|
||||
} else {
|
||||
this.element.insertAdjacentHTML("beforeend", '<div class="fn__loading"><img width="64px" src="/stage/loading-pure.svg"></div>');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -347,6 +347,7 @@ export class Protyle {
|
|||
data: getResponse,
|
||||
protyle: this.protyle,
|
||||
action: mergedOptions.action,
|
||||
scrollPosition: mergedOptions.scrollPosition,
|
||||
afterCB: () => {
|
||||
this.afterOnGet(mergedOptions);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,9 +36,10 @@ import {fetchPost, fetchSyncPost} from "../../../util/fetch";
|
|||
import {scrollCenter} from "../../../util/highlightById";
|
||||
import {escapeHtml} from "../../../util/escape";
|
||||
import {editGalleryItem, openGalleryItemMenu} from "./gallery/util";
|
||||
import {clearSelect} from "../../util/clearSelect";
|
||||
import {clearSelect} from "../../util/clear";
|
||||
import {removeCompressURL} from "../../../util/image";
|
||||
|
||||
let foldTimeout: number;
|
||||
export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLElement }) => {
|
||||
if (isOnlyMeta(event)) {
|
||||
return false;
|
||||
|
|
@ -228,9 +229,17 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
|
|||
event.stopPropagation();
|
||||
return true;
|
||||
} else if (type === "av-group-fold") {
|
||||
if (target.getAttribute("data-folding") !== "true") {
|
||||
target.setAttribute("data-folding", "true");
|
||||
const isOpen = target.firstElementChild.classList.contains("av__group-arrow--open");
|
||||
target.setAttribute("data-processed", "true");
|
||||
const isOpen = target.firstElementChild.classList.contains("av__group-arrow--open");
|
||||
if (isOpen) {
|
||||
target.firstElementChild.classList.remove("av__group-arrow--open");
|
||||
target.parentElement.nextElementSibling.classList.add("fn__none");
|
||||
} else {
|
||||
target.firstElementChild.classList.add("av__group-arrow--open");
|
||||
target.parentElement.nextElementSibling.classList.remove("fn__none");
|
||||
}
|
||||
clearTimeout(foldTimeout);
|
||||
foldTimeout = window.setTimeout(() => {
|
||||
transaction(protyle, [{
|
||||
action: "foldAttrViewGroup",
|
||||
avID: blockElement.dataset.avId,
|
||||
|
|
@ -244,14 +253,7 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
|
|||
id: target.dataset.id,
|
||||
data: !isOpen
|
||||
}]);
|
||||
if (isOpen) {
|
||||
target.firstElementChild.classList.remove("av__group-arrow--open");
|
||||
target.parentElement.nextElementSibling.classList.add("fn__none");
|
||||
} else {
|
||||
target.firstElementChild.classList.add("av__group-arrow--open");
|
||||
target.parentElement.nextElementSibling.classList.remove("fn__none");
|
||||
}
|
||||
}
|
||||
}, Constants.TIMEOUT_COUNT);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import {genCellValue, getTypeByCellElement, renderCell, renderCellAttr} from "..
|
|||
import {fetchPost} from "../../../../util/fetch";
|
||||
import {setPage} from "../row";
|
||||
import {Constants} from "../../../../constants";
|
||||
import {clearSelect} from "../../../util/clearSelect";
|
||||
import {clearSelect} from "../../../util/clear";
|
||||
|
||||
export const insertGalleryItemAnimation = (options: {
|
||||
blockElement: HTMLElement;
|
||||
|
|
|
|||
|
|
@ -104,8 +104,8 @@ ${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value, rowIndex,
|
|||
});
|
||||
galleryHTML += `</div>
|
||||
<div class="av__gallery-actions">
|
||||
<span class="protyle-icon protyle-icon--first b3-tooltips b3-tooltips__n" aria-label="${window.siyuan.languages.displayEmptyFields}" data-type="av-gallery-edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
|
||||
<span class="protyle-icon protyle-icon--last b3-tooltips b3-tooltips__n" aria-label="${window.siyuan.languages.more}" data-type="av-gallery-more"><svg><use xlink:href="#iconMore"></use></svg></span>
|
||||
<span class="protyle-icon protyle-icon--first ariaLabel" data-position="4north" aria-label="${window.siyuan.languages.displayEmptyFields}" data-type="av-gallery-edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
|
||||
<span class="protyle-icon protyle-icon--last ariaLabel" data-position="4north" aria-label="${window.siyuan.languages.more}" data-type="av-gallery-more"><svg><use xlink:href="#iconMore"></use></svg></span>
|
||||
</div>
|
||||
</div>`;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ const getKanbanTitleHTML = (group: IAVView, counter: number) => {
|
|||
// av__group-name 为第三方需求,本应用内没有使用,但不能移除 https://github.com/siyuan-note/siyuan/issues/15736
|
||||
return `<div class="av__group-title">
|
||||
<span class="av__group-name fn__ellipsis" style="white-space: nowrap;">${nameHTML}</span>
|
||||
${counter === 0 ? '<span class="fn__space"></span>' : `<span aria-label="${window.siyuan.languages.entryNum}" data-position="north" class="av__group-counter ariaLabel">${counter}</span>`}
|
||||
${(!counter || counter === 0) ? '<span class="fn__space"></span>' : `<span aria-label="${window.siyuan.languages.entryNum}" data-position="north" class="av__group-counter ariaLabel">${counter}</span>`}
|
||||
<span class="fn__flex-1"></span>
|
||||
<span class="av__group-icon av__group-icon--hover ariaLabel" data-type="av-add-top" data-position="north" aria-label="${window.siyuan.languages.newRow}"><svg><use xlink:href="#iconAdd"></use></svg></span>
|
||||
</div>`;
|
||||
|
|
@ -100,8 +100,8 @@ ${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value, rowIndex,
|
|||
});
|
||||
galleryHTML += `</div>
|
||||
<div class="av__gallery-actions">
|
||||
<span class="protyle-icon protyle-icon--first b3-tooltips b3-tooltips__n" aria-label="${window.siyuan.languages.displayEmptyFields}" data-type="av-gallery-edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
|
||||
<span class="protyle-icon protyle-icon--last b3-tooltips b3-tooltips__n" aria-label="${window.siyuan.languages.more}" data-type="av-gallery-more"><svg><use xlink:href="#iconMore"></use></svg></span>
|
||||
<span class="protyle-icon protyle-icon--first ariaLabel" data-position="4north" aria-label="${window.siyuan.languages.displayEmptyFields}" data-type="av-gallery-edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
|
||||
<span class="protyle-icon protyle-icon--last ariaLabel" data-position="4north" aria-label="${window.siyuan.languages.more}" data-type="av-gallery-more"><svg><use xlink:href="#iconMore"></use></svg></span>
|
||||
</div>
|
||||
</div>`;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {avContextmenu} from "./action";
|
|||
import {hasClosestByClassName} from "../../util/hasClosest";
|
||||
import {Constants} from "../../../constants";
|
||||
import {upDownHint} from "../../../util/upDownHint";
|
||||
import {clearSelect} from "../../util/clearSelect";
|
||||
import {clearSelect} from "../../util/clear";
|
||||
|
||||
export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyle: IProtyle) => {
|
||||
if (!nodeElement.classList.contains("av") || !window.siyuan.menus.menu.element.classList.contains("fn__none")) {
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ export const bindLayoutEvent = (options: {
|
|||
return;
|
||||
}
|
||||
const toggleBgElement = options.menuElement.querySelector('.b3-switch[data-type="toggle-kanban-bg"]') as HTMLInputElement;
|
||||
toggleBgElement.addEventListener("change", () => {
|
||||
toggleBgElement?.addEventListener("change", () => {
|
||||
const checked = toggleBgElement.checked;
|
||||
transaction(options.protyle, [{
|
||||
action: "setAttrViewFillColBackgroundColor",
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import {renderGallery} from "./gallery/render";
|
|||
import {getFieldsByData, getViewIcon} from "./view";
|
||||
import {openMenuPanel} from "./openMenuPanel";
|
||||
import {getPageSize} from "./groups";
|
||||
import {clearSelect} from "../../util/clearSelect";
|
||||
import {clearSelect} from "../../util/clear";
|
||||
import {showMessage} from "../../../dialog/message";
|
||||
import {renderKanban} from "./kanban/render";
|
||||
|
||||
|
|
@ -251,7 +251,7 @@ export const getGroupTitleHTML = (group: IAVView, counter: number) => {
|
|||
</div>
|
||||
<span class="fn__space"></span>
|
||||
<span class="av__group-name">${nameHTML}</span>
|
||||
${counter === 0 ? '<span class="fn__space"></span>' : `<span aria-label="${window.siyuan.languages.entryNum}" data-position="north" class="av__group-counter ariaLabel">${counter}</span>`}
|
||||
${(!counter || counter === 0) ? '<span class="fn__space"></span>' : `<span aria-label="${window.siyuan.languages.entryNum}" data-position="north" class="av__group-counter ariaLabel">${counter}</span>`}
|
||||
<span class="av__group-icon av__group-icon--hover ariaLabel" data-type="av-add-top" data-position="north" aria-label="${window.siyuan.languages.newRow}"><svg><use xlink:href="#iconAdd"></use></svg></span>
|
||||
</div>`;
|
||||
};
|
||||
|
|
@ -784,6 +784,10 @@ export const refreshAV = (protyle: IProtyle, operation: IOperation) => {
|
|||
getAVElements(protyle, operation.avID).forEach((item) => {
|
||||
const foldElement = item.querySelector(`[data-type="av-group-fold"][data-id="${operation.id}"]`);
|
||||
if (foldElement) {
|
||||
if (foldElement.getAttribute("data-processed") === "true") {
|
||||
foldElement.removeAttribute("data-processed");
|
||||
return;
|
||||
}
|
||||
if (operation.data) {
|
||||
foldElement.firstElementChild.classList.remove("av__group-arrow--open");
|
||||
foldElement.parentElement.nextElementSibling.classList.add("fn__none");
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {fetchPost} from "../../../util/fetch";
|
|||
import * as dayjs from "dayjs";
|
||||
import {Constants} from "../../../constants";
|
||||
import {insertGalleryItemAnimation} from "./gallery/item";
|
||||
import {clearSelect} from "../../util/clearSelect";
|
||||
import {clearSelect} from "../../util/clear";
|
||||
import {isCustomAttr} from "./blockAttr";
|
||||
|
||||
export const getFieldIdByCellElement = (cellElement: Element, viewType: TAVView): string => {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const genIconHTML = (element?: false | HTMLElement, actions = ["edit", "m
|
|||
}
|
||||
}
|
||||
const mapActionToHTML = (action: string, isFirst: boolean, isLast: boolean) => {
|
||||
const classList = ["b3-tooltips__nw", "b3-tooltips", "protyle-icon"];
|
||||
const classList = ["ariaLabel", "protyle-icon"];
|
||||
if (isFirst) classList.push("protyle-icon--first");
|
||||
if (isLast) classList.push("protyle-icon--last");
|
||||
let aria = "";
|
||||
|
|
@ -45,7 +45,7 @@ export const genIconHTML = (element?: false | HTMLElement, actions = ["edit", "m
|
|||
}
|
||||
// Only the edit button honors read-only enable
|
||||
const hidden = (action === "edit" && !enable) ? " fn__none" : "";
|
||||
return `<span aria-label="${aria}" class="${classList.join(" ")} ${className}${hidden}"><svg><use xlink:href="#${icon}"></use></svg></span>`;
|
||||
return `<span aria-label="${aria}" data-position="4north" class="${classList.join(" ")} ${className}${hidden}"><svg><use xlink:href="#${icon}"></use></svg></span>`;
|
||||
};
|
||||
const res: string[] = [];
|
||||
for (let i = 0; i < actions.length; i++) {
|
||||
|
|
@ -65,9 +65,9 @@ export const genRenderFrame = (renderElement: Element) => {
|
|||
const type = renderElement.getAttribute("data-type");
|
||||
if (type === "NodeBlockQueryEmbed") {
|
||||
renderElement.insertAdjacentHTML("afterbegin", `<div class="protyle-icons${isInEmbedBlock(renderElement) ? " fn__none" : ""}">
|
||||
<span aria-label="${window.siyuan.languages.refresh}" class="b3-tooltips__nw b3-tooltips protyle-icon protyle-action__reload protyle-icon--first"><svg class="fn__rotate"><use xlink:href="#iconRefresh"></use></svg></span>
|
||||
<span aria-label="${window.siyuan.languages.update} SQL" class="b3-tooltips__nw b3-tooltips protyle-icon protyle-action__edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
|
||||
<span aria-label="${window.siyuan.languages.more}" class="b3-tooltips__nw b3-tooltips protyle-icon protyle-action__menu protyle-icon--last"><svg><use xlink:href="#iconMore"></use></svg></span>
|
||||
<span aria-label="${window.siyuan.languages.refresh}" data-position="4north" class="ariaLabel protyle-icon protyle-action__reload protyle-icon--first"><svg class="fn__rotate"><use xlink:href="#iconRefresh"></use></svg></span>
|
||||
<span aria-label="${window.siyuan.languages.update} SQL" data-position="4north" class="ariaLabel protyle-icon protyle-action__edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
|
||||
<span aria-label="${window.siyuan.languages.more}" data-position="4north" class="ariaLabel protyle-icon protyle-action__menu protyle-icon--last"><svg><use xlink:href="#iconMore"></use></svg></span>
|
||||
</div><div class="protyle-cursor">${Constants.ZWSP}</div>`);
|
||||
} else if (type === "NodeMathBlock" || renderElement.getAttribute("data-subtype") === "math") {
|
||||
renderElement.firstElementChild.innerHTML = `<span></span><span class="protyle-cursor">${Constants.ZWSP}</span>`;
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ export const toolbarKeyToMenu = (toolbar: Array<string | IMenuItem>) => {
|
|||
};
|
||||
|
||||
export const copyTextByType = async (ids: string[],
|
||||
type: "ref" | "blockEmbed" | "protocol" | "protocolMd" | "hPath" | "id") => {
|
||||
type: "ref" | "blockEmbed" | "protocol" | "protocolMd" | "hPath" | "id" | "webURL") => {
|
||||
let text = "";
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
const id = ids[i];
|
||||
|
|
@ -236,6 +236,8 @@ export const copyTextByType = async (ids: string[],
|
|||
} else if (type === "hPath") {
|
||||
const response = await fetchSyncPost("/api/filetree/getHPathByID", {id});
|
||||
text += response.data;
|
||||
} else if (type === "webURL") {
|
||||
text += `${window.location.origin}?id=${id}`;
|
||||
} else if (type === "id") {
|
||||
text += id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,19 @@
|
|||
import {updateHeader} from "../render/av/row";
|
||||
import {Constants} from "../../constants";
|
||||
|
||||
export const clearBlockElement = (element: Element) => {
|
||||
element.classList.remove("protyle-wysiwyg--select", "protyle-wysiwyg--hl");
|
||||
element.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
|
||||
element.removeAttribute("refcount");
|
||||
element.querySelector(".protyle-attr--av")?.remove();
|
||||
element.querySelector(".protyle-attr--refcount")?.remove();
|
||||
element.removeAttribute("custom-avs");
|
||||
element.getAttributeNames().forEach(attr => {
|
||||
if (attr.startsWith("custom-sy-av-s-text-")) {
|
||||
element.removeAttribute(attr);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const clearSelect = (types: ("av" | "img" | "cell" | "row" | "galleryItem")[], element: Element) => {
|
||||
if (types.includes("cell")) {
|
||||
|
|
@ -34,7 +34,7 @@ import {webUtils} from "electron";
|
|||
import {addDragFill, getTypeByCellElement} from "../render/av/cell";
|
||||
import {processClonePHElement} from "../render/util";
|
||||
import {insertGalleryItemAnimation} from "../render/av/gallery/item";
|
||||
import {clearSelect} from "./clearSelect";
|
||||
import {clearSelect} from "./clear";
|
||||
import {dragoverTab} from "../render/av/view";
|
||||
|
||||
// position: afterbegin 为拖拽成超级块; "afterend", "beforebegin" 一般拖拽
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ export const onGet = (options: {
|
|||
protyle: IProtyle,
|
||||
action?: TProtyleAction[],
|
||||
scrollAttr?: IScrollAttr
|
||||
updateReadonly?: boolean
|
||||
updateReadonly?: boolean,
|
||||
scrollPosition?: ScrollLogicalPosition,
|
||||
afterCB?: () => void
|
||||
}) => {
|
||||
if (!options.action) {
|
||||
|
|
@ -96,6 +97,7 @@ export const onGet = (options: {
|
|||
updateReadonly: options.updateReadonly,
|
||||
isSyncing: options.data.data.isSyncing,
|
||||
afterCB: options.afterCB,
|
||||
scrollPosition: options.scrollPosition
|
||||
}, options.protyle);
|
||||
removeLoading(options.protyle);
|
||||
return;
|
||||
|
|
@ -122,6 +124,7 @@ export const onGet = (options: {
|
|||
updateReadonly: options.updateReadonly,
|
||||
isSyncing: options.data.data.isSyncing,
|
||||
afterCB: options.afterCB,
|
||||
scrollPosition: options.scrollPosition
|
||||
}, options.protyle);
|
||||
removeLoading(options.protyle);
|
||||
});
|
||||
|
|
@ -133,7 +136,8 @@ const setHTML = (options: {
|
|||
isSyncing: boolean,
|
||||
expand: boolean,
|
||||
updateReadonly?: boolean,
|
||||
scrollAttr?: IScrollAttr
|
||||
scrollAttr?: IScrollAttr,
|
||||
scrollPosition?: ScrollLogicalPosition,
|
||||
afterCB?: () => void
|
||||
}, protyle: IProtyle) => {
|
||||
if (protyle.contentElement.classList.contains("fn__none") && protyle.wysiwyg.element.innerHTML !== "") {
|
||||
|
|
@ -256,7 +260,7 @@ const setHTML = (options: {
|
|||
}
|
||||
}
|
||||
|
||||
focusElementById(protyle, options.action, options.scrollAttr);
|
||||
focusElementById(protyle, options.action, options.scrollAttr, options.scrollPosition);
|
||||
|
||||
if (options.action.includes(Constants.CB_GET_SETID)) {
|
||||
// 点击大纲后,如果需要动态加载,在定位后,需要重置 block.id https://github.com/siyuan-note/siyuan/issues/4487
|
||||
|
|
@ -448,7 +452,7 @@ export const enableProtyle = (protyle: IProtyle) => {
|
|||
hideTooltip();
|
||||
};
|
||||
|
||||
const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScrollAttr) => {
|
||||
const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScrollAttr, scrollPosition?: ScrollLogicalPosition) => {
|
||||
let focusElement: Element;
|
||||
if (scrollAttr && scrollAttr.focusId) {
|
||||
focusElement = protyle.wysiwyg.element.querySelector(`[data-node-id="${scrollAttr.focusId}"]`);
|
||||
|
|
@ -460,6 +464,9 @@ const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScr
|
|||
}
|
||||
});
|
||||
}
|
||||
if (!focusElement && protyle.block.id === protyle.block.rootID) {
|
||||
focusElement = protyle.title.editElement;
|
||||
}
|
||||
if (protyle.block.mode === 4) {
|
||||
preventScroll(protyle);
|
||||
focusElement = protyle.wysiwyg.element.lastElementChild;
|
||||
|
|
@ -491,7 +498,7 @@ const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScr
|
|||
protyle.observerLoad?.disconnect();
|
||||
if (action.includes(Constants.CB_GET_FOCUS) || action.includes(Constants.CB_GET_SCROLL) || action.includes(Constants.CB_GET_HL) || action.includes(Constants.CB_GET_FOCUSFIRST)) {
|
||||
if (!hasScrollTop) {
|
||||
scrollCenter(protyle, focusElement);
|
||||
scrollCenter(protyle, focusElement, scrollPosition);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
|
|
@ -503,7 +510,7 @@ const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScr
|
|||
}
|
||||
if (action.includes(Constants.CB_GET_FOCUS) || action.includes(Constants.CB_GET_HL) || action.includes(Constants.CB_GET_FOCUSFIRST)) {
|
||||
if (!hasScrollTop) {
|
||||
scrollCenter(protyle, focusElement);
|
||||
scrollCenter(protyle, focusElement, scrollPosition);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {hideElements} from "../ui/hideElements";
|
|||
import {avRender} from "../render/av/render";
|
||||
import {cellScrollIntoView, getCellText} from "../render/av/cell";
|
||||
import {getContenteditableElement} from "../wysiwyg/getBlock";
|
||||
import {clearBlockElement} from "./clear";
|
||||
|
||||
export const getTextStar = (blockElement: HTMLElement) => {
|
||||
const dataType = blockElement.dataset.type;
|
||||
|
|
@ -407,10 +408,7 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
|
|||
tempElement.querySelectorAll("[data-node-id]").forEach((e) => {
|
||||
const newId = Lute.NewNodeID();
|
||||
e.setAttribute("data-node-id", newId);
|
||||
e.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
|
||||
e.classList.remove("protyle-wysiwyg--select", "protyle-wysiwyg--hl");
|
||||
e.setAttribute("updated", newId.split("-")[0]);
|
||||
e.removeAttribute("refcount");
|
||||
clearBlockElement(e);
|
||||
isBlock = true;
|
||||
});
|
||||
if (nodeElement.classList.contains("table")) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {processClonePHElement} from "../render/util";
|
|||
import {copyTextByType} from "../toolbar/util";
|
||||
import {hasClosestByTag, hasTopClosestByClassName} from "../util/hasClosest";
|
||||
import {removeEmbed} from "./removeEmbed";
|
||||
import {clearBlockElement} from "../util/clear";
|
||||
|
||||
export const commonHotkey = (protyle: IProtyle, event: KeyboardEvent, nodeElement?: HTMLElement) => {
|
||||
if (matchHotKey(window.siyuan.config.keymap.editor.general.netImg2LocalAsset.custom, event)) {
|
||||
|
|
@ -313,19 +314,14 @@ export const duplicateBlock = async (nodeElements: Element[], protyle: IProtyle)
|
|||
focusElement = tempElement;
|
||||
}
|
||||
tempElement.setAttribute("data-node-id", newId);
|
||||
tempElement.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
|
||||
tempElement.classList.remove("protyle-wysiwyg--hl");
|
||||
tempElement.setAttribute("updated", newId.split("-")[0]);
|
||||
tempElement.removeAttribute("refcount");
|
||||
tempElement.lastElementChild.querySelector(".protyle-attr--refcount")?.remove();
|
||||
clearBlockElement(tempElement);
|
||||
tempElement.classList.add("protyle-wysiwyg--select");
|
||||
tempElement.querySelectorAll("[data-node-id]").forEach(childItem => {
|
||||
const subNewId = Lute.NewNodeID();
|
||||
childItem.setAttribute("data-node-id", subNewId);
|
||||
childItem.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
|
||||
childItem.classList.remove("protyle-wysiwyg--hl");
|
||||
childItem.setAttribute("updated", subNewId.split("-")[0]);
|
||||
childItem.removeAttribute("refcount");
|
||||
childItem.lastElementChild.querySelector(".protyle-attr--refcount")?.remove();
|
||||
clearBlockElement(childItem);
|
||||
});
|
||||
if (typeof starIndex === "number") {
|
||||
const orderIndex = starIndex + index + 1;
|
||||
|
|
@ -354,13 +350,11 @@ export const duplicateBlock = async (nodeElements: Element[], protyle: IProtyle)
|
|||
}
|
||||
childItem.querySelectorAll("[data-node-id]").forEach(subItem => {
|
||||
subItem.setAttribute("data-node-id", Lute.NewNodeID());
|
||||
subItem.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
|
||||
subItem.removeAttribute("refcount");
|
||||
clearBlockElement(subItem);
|
||||
});
|
||||
const newChildId = Lute.NewNodeID();
|
||||
childItem.setAttribute("data-node-id", newChildId);
|
||||
childItem.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
|
||||
childItem.removeAttribute("refcount");
|
||||
clearBlockElement(childItem);
|
||||
doOperations.push({
|
||||
context: {
|
||||
ignoreProcess: "true"
|
||||
|
|
|
|||
|
|
@ -101,6 +101,16 @@ import { hideTooltip } from "../../dialog/tooltip";
|
|||
import { openGalleryItemMenu } from "../render/av/gallery/util";
|
||||
import { clearSelect } from "../util/clearSelect";
|
||||
import { chartRender } from "../render/chartRender";
|
||||
import {openEmojiPanel, unicode2Emoji} from "../../emoji";
|
||||
import {openLink} from "../../editor/openLink";
|
||||
import {mathRender} from "../render/mathRender";
|
||||
import {editAssetItem} from "../render/av/asset";
|
||||
import {img3115} from "../../boot/compatibleVersion";
|
||||
import {globalClickHideMenu} from "../../boot/globalEvent/click";
|
||||
import {hideTooltip} from "../../dialog/tooltip";
|
||||
import {openGalleryItemMenu} from "../render/av/gallery/util";
|
||||
import {clearSelect} from "../util/clear";
|
||||
import {chartRender} from "../render/chartRender";
|
||||
|
||||
export class WYSIWYG {
|
||||
public lastHTMLs: { [key: string]: string } = {};
|
||||
|
|
@ -152,7 +162,7 @@ export class WYSIWYG {
|
|||
}
|
||||
}
|
||||
ialKeys.forEach((key: string) => {
|
||||
if (!["title-img", "title", "updated", "icon", "id", "type", "class", "spellcheck", "contenteditable", "data-doc-type", "style", "data-realwidth", "data-readonly"].includes(key)) {
|
||||
if (!["title-img", "title", "updated", "icon", "id", "type", "class", "spellcheck", "contenteditable", "data-doc-type", "style", "data-realwidth", "data-readonly", "av-names"].includes(key)) {
|
||||
this.element.setAttribute(key, ial[key]);
|
||||
}
|
||||
});
|
||||
|
|
@ -655,8 +665,13 @@ export class WYSIWYG {
|
|||
}
|
||||
if (isOnlyMeta(event) && !event.shiftKey && !event.altKey) {
|
||||
let ctrlElement = nodeElement;
|
||||
if (!hasSelectClassElement && galleryItemElement) {
|
||||
galleryItemElement.classList.toggle("av__gallery-item--select");
|
||||
const rowElement = hasClosestByClassName(target, "av__row");
|
||||
if (!hasSelectClassElement && (galleryItemElement || (rowElement && !rowElement.classList.contains("av__row--header")))) {
|
||||
if (galleryItemElement) {
|
||||
galleryItemElement.classList.toggle("av__gallery-item--select");
|
||||
} else if (rowElement) {
|
||||
selectRow(rowElement.querySelector(".av__firstcol"), "toggle");
|
||||
}
|
||||
} else if (ctrlElement) {
|
||||
const embedBlockElement = isInEmbedBlock(ctrlElement);
|
||||
if (embedBlockElement) {
|
||||
|
|
@ -917,15 +932,20 @@ export class WYSIWYG {
|
|||
};
|
||||
return false;
|
||||
}
|
||||
// 图片、iframe、video 缩放
|
||||
// 图片、iframe、video、挂件缩放
|
||||
if (!protyle.disabled && target.classList.contains("protyle-action__drag")) {
|
||||
if (!nodeElement) {
|
||||
return;
|
||||
}
|
||||
let isCenter = true;
|
||||
if (["NodeIFrame", "NodeWidget", "NodeVideo"].includes(nodeElement.getAttribute("data-type"))) {
|
||||
if ("NodeVideo" === nodeElement.dataset.type) {
|
||||
nodeElement.classList.add("iframe--drag");
|
||||
if (nodeElement.style.textAlign === "left" || nodeElement.style.textAlign === "right") {
|
||||
if (["left", "right", ""].includes(nodeElement.style.textAlign)) {
|
||||
isCenter = false;
|
||||
}
|
||||
} else if (["NodeIFrame", "NodeWidget"].includes(nodeElement.dataset.type)) {
|
||||
nodeElement.classList.add("iframe--drag");
|
||||
if (!nodeElement.style.margin) {
|
||||
isCenter = false;
|
||||
}
|
||||
} else if (target.parentElement.parentElement.getAttribute("data-type") === "img") {
|
||||
|
|
@ -943,6 +963,11 @@ export class WYSIWYG {
|
|||
if (dragElement.tagName === "IMG") {
|
||||
img3115(imgElement);
|
||||
}
|
||||
// 3.4.1 以前历史数据兼容
|
||||
if (dragElement.tagName === "IFRAME") {
|
||||
dragElement.style.height = "";
|
||||
dragElement.style.width = "";
|
||||
}
|
||||
documentSelf.onmousemove = (moveEvent: MouseEvent) => {
|
||||
if (dragElement.tagName === "IMG") {
|
||||
dragElement.style.height = "";
|
||||
|
|
@ -951,13 +976,19 @@ export class WYSIWYG {
|
|||
const multiple = ((dragElement.tagName === "IMG" && !imgElement.style.minWidth && nodeElement.style.textAlign !== "center") || !isCenter) ? 1 : 2;
|
||||
if (dragElement.tagName === "IMG") {
|
||||
dragElement.parentElement.style.width = Math.max(17, dragWidth + (moveEvent.clientX - x) * multiple) + "px";
|
||||
} else if (dragElement.tagName === "IFRAME") {
|
||||
nodeElement.style.width = Math.max(17, dragWidth + (moveEvent.clientX - x) * multiple) + "px";
|
||||
} else {
|
||||
dragElement.style.width = Math.max(17, dragWidth + (moveEvent.clientX - x) * multiple) + "px";
|
||||
}
|
||||
}
|
||||
if (dragElement.tagName !== "IMG") {
|
||||
if (moveEvent.clientY > y - dragHeight + 8 && moveEvent.clientY < mostBottom) {
|
||||
dragElement.style.height = (dragHeight + (moveEvent.clientY - y)) + "px";
|
||||
if (dragElement.tagName === "IFRAME") {
|
||||
nodeElement.style.height = (dragHeight + (moveEvent.clientY - y)) + "px";
|
||||
} else {
|
||||
dragElement.style.height = (dragHeight + (moveEvent.clientY - y)) + "px";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -763,6 +763,16 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (selectText === "" && event.key === "ArrowLeft" && position.start === 1 &&
|
||||
range.startContainer.textContent === Constants.ZWSP) {
|
||||
range.setStart(range.startContainer, 0);
|
||||
range.collapse(true);
|
||||
}
|
||||
if (selectText === "" && event.key === "ArrowRight" && position.start === 0 &&
|
||||
range.startContainer.textContent === Constants.ZWSP) {
|
||||
range.setStart(range.startContainer, 1);
|
||||
range.collapse(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ export const breakList = (protyle: IProtyle, blockElement: Element, range: Range
|
|||
action: "delete"
|
||||
});
|
||||
|
||||
Array.from(listItemElement.children).reverse().forEach((item) => {
|
||||
Array.from(listItemElement.children).reverse().forEach((item, index) => {
|
||||
if (!item.classList.contains("protyle-action") && !item.classList.contains("protyle-attr")) {
|
||||
doOperations.push({
|
||||
id: item.getAttribute("data-node-id"),
|
||||
|
|
@ -286,7 +286,8 @@ export const breakList = (protyle: IProtyle, blockElement: Element, range: Range
|
|||
undoOperations.push({
|
||||
id: item.getAttribute("data-node-id"),
|
||||
action: "move",
|
||||
parentID: listItemId
|
||||
parentID: listItemId,
|
||||
data: index === listItemElement.childElementCount - 2 ? "focus" : null
|
||||
});
|
||||
listItemElement.parentElement.after(item);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -611,13 +611,14 @@ export const onTransaction = (protyle: IProtyle, operation: IOperation, isUndo:
|
|||
data.new.style += ";animation:addCard 450ms linear";
|
||||
}
|
||||
Object.keys(data.new).forEach(key => {
|
||||
if ("id" === key) {
|
||||
if ("id" === key || "av-names" === key) {
|
||||
// 设置属性以后不应该给块元素添加 id 属性 No longer add the `id` attribute to block elements after setting the attribute https://github.com/siyuan-note/siyuan/issues/15327
|
||||
// av-names 属性仅用于生成角标,不添加到元素
|
||||
return;
|
||||
}
|
||||
|
||||
item.setAttribute(key, data.new[key]);
|
||||
if (key === Constants.CUSTOM_RIFF_DECKS && data.new[Constants.CUSTOM_RIFF_DECKS] !== data.old[Constants.CUSTOM_RIFF_DECKS]) {
|
||||
if (key === Constants.CUSTOM_RIFF_DECKS && key !== data.old[Constants.CUSTOM_RIFF_DECKS]) {
|
||||
item.style.animation = "addCard 450ms linear";
|
||||
setTimeout(() => {
|
||||
if (item.parentElement) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue