mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-02-08 00:04:21 +01:00
This commit is contained in:
parent
8bf4ed7fc4
commit
31e37ff3d0
3 changed files with 93 additions and 64 deletions
|
|
@ -13,6 +13,7 @@ import {fontEvent, getFontNodeElements} from "../../protyle/toolbar/Font";
|
|||
import {hideElements} from "../../protyle/ui/hideElements";
|
||||
import {softEnter} from "../../protyle/wysiwyg/enter";
|
||||
import {isInAndroid, isInHarmony} from "../../protyle/util/compatibility";
|
||||
import {tabCodeBlock} from "../../protyle/wysiwyg/codeBlock";
|
||||
|
||||
let renderKeyboardToolbarTimeout: number;
|
||||
let showUtil = false;
|
||||
|
|
@ -346,14 +347,17 @@ const renderKeyboardToolbar = () => {
|
|||
const dynamicElements = document.querySelectorAll("#keyboardToolbar .keyboard__dynamic");
|
||||
const range = getSelection().getRangeAt(0);
|
||||
const isProtyle = hasClosestByClassName(range.startContainer, "protyle-wysiwyg", true);
|
||||
if (!isProtyle) {
|
||||
const nodeElement = hasClosestBlock(range.startContainer);
|
||||
if (!isProtyle || !nodeElement) {
|
||||
dynamicElements[0].classList.add("fn__none");
|
||||
dynamicElements[1].classList.add("fn__none");
|
||||
return;
|
||||
}
|
||||
|
||||
const selectText = range.toString();
|
||||
if (selectText || dynamicElements[0].querySelector('[data-type="goinline"]').classList.contains("protyle-toolbar__item--current")) {
|
||||
|
||||
if (!nodeElement.classList.contains("code-block") &&
|
||||
(selectText || dynamicElements[0].querySelector('[data-type="goinline"]').classList.contains("protyle-toolbar__item--current"))) {
|
||||
dynamicElements[0].classList.add("fn__none");
|
||||
dynamicElements[1].classList.remove("fn__none");
|
||||
} else {
|
||||
|
|
@ -374,16 +378,20 @@ const renderKeyboardToolbar = () => {
|
|||
} else {
|
||||
dynamicElements[0].querySelector('[data-type="redo"]').removeAttribute("disabled");
|
||||
}
|
||||
const nodeElement = hasClosestBlock(range.startContainer);
|
||||
if (nodeElement) {
|
||||
const outdentElement = dynamicElements[0].querySelector('[data-type="outdent"]');
|
||||
if (nodeElement.parentElement.classList.contains("li")) {
|
||||
outdentElement.classList.remove("fn__none");
|
||||
outdentElement.nextElementSibling.classList.remove("fn__none");
|
||||
} else {
|
||||
outdentElement.classList.add("fn__none");
|
||||
outdentElement.nextElementSibling.classList.add("fn__none");
|
||||
}
|
||||
const outdentElement = dynamicElements[0].querySelector('[data-type="outdent"]');
|
||||
const goinlineElement = dynamicElements[0].querySelector('[data-type="goinline"]');
|
||||
if (nodeElement.classList.contains("code-block")) {
|
||||
goinlineElement.classList.add("fn__none");
|
||||
} else {
|
||||
goinlineElement.classList.remove("fn__none");
|
||||
}
|
||||
if (nodeElement.parentElement.classList.contains("li") ||
|
||||
nodeElement.classList.contains("code-block")) {
|
||||
outdentElement.classList.remove("fn__none");
|
||||
outdentElement.nextElementSibling.classList.remove("fn__none");
|
||||
} else {
|
||||
outdentElement.classList.add("fn__none");
|
||||
outdentElement.nextElementSibling.classList.add("fn__none");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -689,11 +697,23 @@ export const initKeyboardToolbar = () => {
|
|||
activeBlur();
|
||||
return;
|
||||
} else if (type === "outdent") {
|
||||
listOutdent(protyle, [nodeElement.parentElement], range);
|
||||
if (nodeElement.classList.contains("code-block")) {
|
||||
if (range.toString() !== "") {
|
||||
tabCodeBlock(protyle, nodeElement, range, true);
|
||||
}
|
||||
} else {
|
||||
listOutdent(protyle, [nodeElement.parentElement], range);
|
||||
}
|
||||
focusByRange(range);
|
||||
return;
|
||||
} else if (type === "indent") {
|
||||
listIndent(protyle, [nodeElement.parentElement], range);
|
||||
if (nodeElement.classList.contains("code-block")) {
|
||||
if (range.toString() !== "") {
|
||||
tabCodeBlock(protyle, nodeElement, range);
|
||||
}
|
||||
} else {
|
||||
listIndent(protyle, [nodeElement.parentElement], range);
|
||||
}
|
||||
focusByRange(range);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
56
app/src/protyle/wysiwyg/codeBlock.ts
Normal file
56
app/src/protyle/wysiwyg/codeBlock.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import {hasNextSibling} from "./getBlock";
|
||||
import {setLastNodeRange} from "../util/selection";
|
||||
import {updateTransaction} from "./transaction";
|
||||
|
||||
export const tabCodeBlock = (protyle: IProtyle, nodeElement: HTMLElement,
|
||||
range: Range, outdent = false) => {
|
||||
// https://github.com/siyuan-note/siyuan/issues/12650
|
||||
if (!hasNextSibling(range.endContainer) && range.endContainer.textContent.endsWith("\n") && range.endOffset > 0) {
|
||||
range.setEnd(range.endContainer, range.endOffset - 1);
|
||||
}
|
||||
const wbrElement = document.createElement("wbr");
|
||||
range.insertNode(wbrElement);
|
||||
range.setStartAfter(wbrElement);
|
||||
const oldHTML = nodeElement.outerHTML;
|
||||
let text = "";
|
||||
const tabSpace = window.siyuan.config.editor.codeTabSpaces === 0 ? "\t" : "".padStart(window.siyuan.config.editor.codeTabSpaces, " ");
|
||||
if (!outdent) {
|
||||
range.extractContents().textContent.split("\n").forEach((item: string) => {
|
||||
text += tabSpace + item + "\n";
|
||||
});
|
||||
} else {
|
||||
range.extractContents().textContent.split("\n").forEach((item: string) => {
|
||||
if (item.startsWith(tabSpace)) {
|
||||
text += item.replace(tabSpace, "") + "\n";
|
||||
} else {
|
||||
text += item + "\n";
|
||||
}
|
||||
});
|
||||
}
|
||||
let language = nodeElement.querySelector(".protyle-action__language").textContent;
|
||||
// 语言优先级处理 https://github.com/siyuan-note/siyuan/issues/14767
|
||||
if (range.commonAncestorContainer.nodeType === 1) {
|
||||
const snippetClassName = (range.commonAncestorContainer as HTMLElement).className;
|
||||
if (snippetClassName.startsWith("language-")) {
|
||||
language = snippetClassName.replace("language-", "");
|
||||
// https://github.com/siyuan-note/siyuan/issues/14767
|
||||
if (wbrElement.parentElement !== range.commonAncestorContainer) {
|
||||
wbrElement.parentElement.after(wbrElement);
|
||||
wbrElement.previousElementSibling.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!window.hljs.getLanguage(language)) {
|
||||
language = "plaintext";
|
||||
}
|
||||
wbrElement.insertAdjacentHTML("afterend", window.hljs.highlight(text.substr(0, text.length - 1), {
|
||||
language,
|
||||
ignoreIllegals: true
|
||||
}).value + "<br>");
|
||||
range.setStart(wbrElement.nextSibling, 0);
|
||||
const brElement = wbrElement.parentElement.querySelector("br");
|
||||
setLastNodeRange(brElement.previousSibling as Element, range, false);
|
||||
brElement.remove();
|
||||
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, oldHTML);
|
||||
wbrElement.remove();
|
||||
};
|
||||
|
|
@ -75,6 +75,7 @@ import {openLink} from "../../editor/openLink";
|
|||
import {onlyProtyleCommand} from "../../boot/globalEvent/command/protyle";
|
||||
import {AIChat} from "../../ai/chat";
|
||||
import {updateCalloutType} from "./callout";
|
||||
import {tabCodeBlock} from "./codeBlock";
|
||||
|
||||
export const getContentByInlineHTML = (range: Range, cb: (content: string) => void) => {
|
||||
let html = "";
|
||||
|
|
@ -1870,56 +1871,8 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
|
|||
// tab 需等待 list 和 table 处理完成
|
||||
if (event.key === "Tab" && isNotCtrl(event) && !event.altKey) {
|
||||
event.preventDefault();
|
||||
const tabSpace = window.siyuan.config.editor.codeTabSpaces === 0 ? "\t" : "".padStart(window.siyuan.config.editor.codeTabSpaces, " ");
|
||||
if (nodeType === "NodeCodeBlock" && selectText !== "") {
|
||||
// https://github.com/siyuan-note/siyuan/issues/12650
|
||||
if (!hasNextSibling(range.endContainer) && range.endContainer.textContent.endsWith("\n") && range.endOffset > 0) {
|
||||
range.setEnd(range.endContainer, range.endOffset - 1);
|
||||
}
|
||||
const wbrElement = document.createElement("wbr");
|
||||
range.insertNode(wbrElement);
|
||||
range.setStartAfter(wbrElement);
|
||||
const oldHTML = nodeElement.outerHTML;
|
||||
let text = "";
|
||||
if (!event.shiftKey) {
|
||||
range.extractContents().textContent.split("\n").forEach((item: string) => {
|
||||
text += tabSpace + item + "\n";
|
||||
});
|
||||
} else {
|
||||
range.extractContents().textContent.split("\n").forEach((item: string) => {
|
||||
if (item.startsWith(tabSpace)) {
|
||||
text += item.replace(tabSpace, "") + "\n";
|
||||
} else {
|
||||
text += item + "\n";
|
||||
}
|
||||
});
|
||||
}
|
||||
let language = nodeElement.querySelector(".protyle-action__language").textContent;
|
||||
// 语言优先级处理 https://github.com/siyuan-note/siyuan/issues/14767
|
||||
if (range.commonAncestorContainer.nodeType === 1) {
|
||||
const snippetClassName = (range.commonAncestorContainer as HTMLElement).className;
|
||||
if (snippetClassName.startsWith("language-")) {
|
||||
language = snippetClassName.replace("language-", "");
|
||||
// https://github.com/siyuan-note/siyuan/issues/14767
|
||||
if (wbrElement.parentElement !== range.commonAncestorContainer) {
|
||||
wbrElement.parentElement.after(wbrElement);
|
||||
wbrElement.previousElementSibling.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!window.hljs.getLanguage(language)) {
|
||||
language = "plaintext";
|
||||
}
|
||||
wbrElement.insertAdjacentHTML("afterend", window.hljs.highlight(text.substr(0, text.length - 1), {
|
||||
language,
|
||||
ignoreIllegals: true
|
||||
}).value + "<br>");
|
||||
range.setStart(wbrElement.nextSibling, 0);
|
||||
const brElement = wbrElement.parentElement.querySelector("br");
|
||||
setLastNodeRange(brElement.previousSibling as Element, range, false);
|
||||
brElement.remove();
|
||||
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, oldHTML);
|
||||
wbrElement.remove();
|
||||
tabCodeBlock(protyle, nodeElement, range, event.shiftKey);
|
||||
return;
|
||||
}
|
||||
if (!event.shiftKey) {
|
||||
|
|
@ -1946,7 +1899,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
|
|||
range.insertNode(wbrElement);
|
||||
const oldHTML = nodeElement.outerHTML;
|
||||
range.extractContents();
|
||||
range.insertNode(document.createTextNode(tabSpace));
|
||||
range.insertNode(document.createTextNode(window.siyuan.config.editor.codeTabSpaces === 0 ? "\t" : "".padStart(window.siyuan.config.editor.codeTabSpaces, " ")));
|
||||
range.collapse(false);
|
||||
focusByRange(range);
|
||||
wbrElement.remove();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue