This commit is contained in:
parent
7bc8fba466
commit
4b5e19e754
10 changed files with 95 additions and 31 deletions
|
@ -97,6 +97,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
span[data-type~="inline-memo"] {
|
||||
background-color: var(--b3-card-info-background);
|
||||
border-bottom: 2px solid var(--b3-card-info-color);
|
||||
}
|
||||
|
||||
blockquote,
|
||||
.bq {
|
||||
padding: 4px;
|
||||
|
|
|
@ -11,9 +11,10 @@ export const initBlockPopover = () => {
|
|||
const aElement = hasClosestByAttribute(event.target, "data-type", "a", true) ||
|
||||
hasClosestByAttribute(event.target, "data-type", "tab-header") ||
|
||||
hasClosestByClassName(event.target, "emojis__item") ||
|
||||
hasClosestByClassName(event.target, "emojis__type");
|
||||
hasClosestByClassName(event.target, "emojis__type") ||
|
||||
hasClosestByAttribute(event.target, "data-type", "inline-memo");
|
||||
if (aElement) {
|
||||
let tip = aElement.getAttribute("aria-label");
|
||||
let tip = aElement.getAttribute("aria-label") || aElement.getAttribute("data-inline-memo-content");
|
||||
// 折叠块标文案替换
|
||||
if (hasClosestByAttribute(event.target, "data-type", "fold", true)) {
|
||||
tip = window.siyuan.languages.fold;
|
||||
|
|
|
@ -171,6 +171,7 @@ export abstract class Constants {
|
|||
sub: {default: "⌘J", custom: "⌘J"},
|
||||
bold: {default: "⌘B", custom: "⌘B"},
|
||||
"inline-math": {default: "⌘M", custom: "⌘M"},
|
||||
memo: {default: "⌥⌘M", custom: "⌥⌘M"},
|
||||
underline: {default: "⌘U", custom: "⌘U"},
|
||||
italic: {default: "⌘I", custom: "⌘I"},
|
||||
mark: {default: "⌘E", custom: "⌘E"},
|
||||
|
@ -397,7 +398,7 @@ export abstract class Constants {
|
|||
"lightfair", "magula", "mono-blue", "nnfx-light", "paraiso-light", "purebasic", "qtcreator-light", "routeros", "school-book",
|
||||
"stackoverflow-light", "tokyo-night-light", "vs", "xcode", "default"];
|
||||
public static readonly ZWSP: string = "\u200b";
|
||||
public static readonly INLINE_TYPE: string[] = ["block-ref", "kbd", "text", "file-annotation-ref", "a", "strong", "em", "u", "s", "mark", "sup", "sub", "tag", "code", "inline-math"];
|
||||
public static readonly INLINE_TYPE: string[] = ["block-ref", "kbd", "text", "file-annotation-ref", "a", "strong", "em", "u", "s", "mark", "sup", "sub", "tag", "code", "inline-math", "inline-memo"];
|
||||
public static readonly BLOCK_HINT_KEYS: string[] = ["((", "[[", "((", "【【"];
|
||||
public static readonly BLOCK_HINT_CLOSE_KEYS: IObject = {"((": "))", "[[": "]]", "((": "))", "【【": "】】"};
|
||||
public static readonly CODE_LANGUAGES: string[] = [
|
||||
|
|
|
@ -3,7 +3,6 @@ import * as dayjs from "dayjs";
|
|||
import {updateTransaction} from "../wysiwyg/transaction";
|
||||
import {hasClosestBlock} from "../util/hasClosest";
|
||||
import {hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock";
|
||||
import {focusByRange, focusByWbr} from "../util/selection";
|
||||
import {mathRender} from "../markdown/mathRender";
|
||||
|
||||
export class InlineMath extends ToolbarItem {
|
||||
|
@ -49,24 +48,3 @@ export class InlineMath extends ToolbarItem {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const removeLink = (linkElement: HTMLElement, range: Range) => {
|
||||
const types = linkElement.getAttribute("data-type").split(" ");
|
||||
if (types.length === 1) {
|
||||
const linkParentElement = linkElement.parentElement;
|
||||
linkElement.outerHTML = linkElement.innerHTML + "<wbr>";
|
||||
focusByWbr(linkParentElement, range);
|
||||
} else {
|
||||
types.find((itemType, index) => {
|
||||
if ("a" === itemType) {
|
||||
types.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
linkElement.setAttribute("data-type", types.join(" "));
|
||||
linkElement.removeAttribute("data-href");
|
||||
range.selectNodeContents(linkElement);
|
||||
range.collapse(false);
|
||||
focusByRange(range);
|
||||
}
|
||||
};
|
||||
|
|
52
app/src/protyle/toolbar/InlineMemo.ts
Normal file
52
app/src/protyle/toolbar/InlineMemo.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import {ToolbarItem} from "./ToolbarItem";
|
||||
import * as dayjs from "dayjs";
|
||||
import {updateTransaction} from "../wysiwyg/transaction";
|
||||
import {hasClosestBlock, hasClosestByAttribute} from "../util/hasClosest";
|
||||
import {hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock";
|
||||
|
||||
export class InlineMemo extends ToolbarItem {
|
||||
public element: HTMLElement;
|
||||
|
||||
constructor(protyle: IProtyle, menuItem: IMenuItem) {
|
||||
super(protyle, menuItem);
|
||||
this.element.addEventListener("click", async (event: MouseEvent & { changedTouches: MouseEvent[] }) => {
|
||||
protyle.toolbar.element.classList.add("fn__none");
|
||||
event.stopPropagation();
|
||||
|
||||
const range = protyle.toolbar.range;
|
||||
const nodeElement = hasClosestBlock(range.startContainer);
|
||||
if (!nodeElement) {
|
||||
return;
|
||||
}
|
||||
const memoElement = hasClosestByAttribute(range.startContainer, "data-type", "inline-memo");
|
||||
if (memoElement) {
|
||||
protyle.toolbar.showRender(protyle, memoElement);
|
||||
return;
|
||||
}
|
||||
|
||||
if (range.toString() === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!["DIV", "TD", "TH"].includes(range.startContainer.parentElement.tagName) && range.startOffset === 0 && !hasPreviousSibling(range.startContainer)) {
|
||||
range.setStartBefore(range.startContainer.parentElement);
|
||||
}
|
||||
if (!["DIV", "TD", "TH"].includes(range.endContainer.parentElement.tagName) && range.endOffset === range.endContainer.textContent.length && !hasNextSibling(range.endContainer)) {
|
||||
range.setEndAfter(range.endContainer.parentElement);
|
||||
}
|
||||
const wbrElement = document.createElement("wbr");
|
||||
range.insertNode(wbrElement);
|
||||
const html = nodeElement.outerHTML;
|
||||
|
||||
const newElement = document.createElement("span");
|
||||
newElement.innerHTML = range.toString();
|
||||
newElement.setAttribute("data-type", "inline-memo");
|
||||
range.extractContents();
|
||||
range.insertNode(newElement);
|
||||
protyle.toolbar.showRender(protyle, newElement);
|
||||
nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
|
||||
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
|
||||
wbrElement.remove();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ export class ToolbarItem {
|
|||
this.element.setAttribute("data-type", menuItem.name);
|
||||
this.element.setAttribute("aria-label", tip + hotkey);
|
||||
this.element.innerHTML = `<svg><use xlink:href="#${menuItem.icon}"></use></svg>`;
|
||||
if (["text", "a", "block-ref", "inline-math"].includes(menuItem.name)) {
|
||||
if (["text", "a", "block-ref", "inline-math", "inline-memo"].includes(menuItem.name)) {
|
||||
return;
|
||||
}
|
||||
this.element.addEventListener(getEventName(), (event) => {
|
||||
|
|
|
@ -40,6 +40,7 @@ import {electronUndo} from "../undo";
|
|||
import {previewTemplate} from "./util";
|
||||
import {showMessage} from "../../dialog/message";
|
||||
import {InlineMath} from "./InlineMath";
|
||||
import {InlineMemo} from "./InlineMemo";
|
||||
|
||||
export class Toolbar {
|
||||
public element: HTMLElement;
|
||||
|
@ -122,7 +123,7 @@ export class Toolbar {
|
|||
});
|
||||
const types = this.getCurrentType();
|
||||
types.forEach(item => {
|
||||
if (["a", "block-ref", "text", "file-annotation-ref", "inline-math", ""].includes(item)) {
|
||||
if (["a", "block-ref", "text", "file-annotation-ref", "inline-math", "inline-memo", ""].includes(item)) {
|
||||
return;
|
||||
}
|
||||
this.element.querySelector(`[data-type="${item}"]`).classList.add("protyle-toolbar__item--current");
|
||||
|
@ -191,6 +192,9 @@ export class Toolbar {
|
|||
case "inline-math":
|
||||
menuItemObj = new InlineMath(protyle, menuItem);
|
||||
break;
|
||||
case "inline-memo":
|
||||
menuItemObj = new InlineMemo(protyle, menuItem);
|
||||
break;
|
||||
case "|":
|
||||
menuItemObj = new Divider();
|
||||
break;
|
||||
|
@ -636,6 +640,8 @@ export class Toolbar {
|
|||
}
|
||||
if (type === "NodeBlockQueryEmbed") {
|
||||
title = window.siyuan.languages.blockEmbed;
|
||||
} else if (type === "inline-memo") {
|
||||
title = window.siyuan.languages.memo;
|
||||
}
|
||||
const isPin = this.subElement.querySelector('[data-type="pin"]')?.classList.contains("block__icon--active");
|
||||
const pinData: IObject = {};
|
||||
|
@ -660,7 +666,7 @@ export class Toolbar {
|
|||
<span class="fn__space"></span>
|
||||
<button data-type="after" class="block__icon b3-tooltips b3-tooltips__nw" aria-label="${window.siyuan.languages["insert-after"]}"><svg><use xlink:href="#iconAfter"></use></svg></button>
|
||||
<span class="fn__space"></span>
|
||||
<button data-type="copy" class="block__icon b3-tooltips b3-tooltips__nw${isBrowser() ? " fn__none" : ""}" aria-label="${window.siyuan.languages.copy} PNG"><svg><use xlink:href="#iconCopy"></use></svg></button>
|
||||
<button data-type="copy" class="block__icon b3-tooltips b3-tooltips__nw${(isBrowser() || type === "inline-memo") ? " fn__none" : ""}" aria-label="${window.siyuan.languages.copy} PNG"><svg><use xlink:href="#iconCopy"></use></svg></button>
|
||||
<span class="fn__space"></span>
|
||||
<button data-type="pin" class="block__icon b3-tooltips b3-tooltips__nw${isPin ? " block__icon--active" : ""}" aria-label="${window.siyuan.languages.pin}"><svg><use xlink:href="#iconPin"></use></svg></button>
|
||||
<span class="fn__space"></span>
|
||||
|
@ -680,7 +686,7 @@ export class Toolbar {
|
|||
return;
|
||||
}
|
||||
if (this.subElement.clientHeight <= window.innerHeight - nodeRect.bottom || this.subElement.clientHeight <= nodeRect.top) {
|
||||
if (type === "inline-math") {
|
||||
if (type === "inline-math" || type === "inline-memo") {
|
||||
setPosition(this.subElement, nodeRect.left, nodeRect.bottom, nodeRect.height);
|
||||
} else {
|
||||
setPosition(this.subElement, nodeRect.left + (nodeRect.width - this.subElement.clientWidth) / 2, nodeRect.bottom, nodeRect.height);
|
||||
|
@ -786,6 +792,8 @@ export class Toolbar {
|
|||
const textElement = this.subElement.querySelector(".b3-text-field") as HTMLTextAreaElement;
|
||||
if (type === "NodeHTMLBlock") {
|
||||
textElement.value = Lute.UnEscapeHTMLStr(renderElement.querySelector("protyle-html").getAttribute("data-content") || "");
|
||||
} else if (type === "inline-memo") {
|
||||
textElement.value = Lute.UnEscapeHTMLStr(renderElement.getAttribute("data-inline-memo-content") || "");
|
||||
} else {
|
||||
const switchElement = this.subElement.querySelector(".b3-switch") as HTMLInputElement;
|
||||
if (nodeElement.getAttribute("custom-heading-mode") === "1") {
|
||||
|
@ -817,6 +825,8 @@ export class Toolbar {
|
|||
const target = event.target as HTMLTextAreaElement;
|
||||
if (type === "NodeHTMLBlock") {
|
||||
renderElement.querySelector("protyle-html").setAttribute("data-content", Lute.EscapeHTMLStr(target.value));
|
||||
} else if (type === "inline-memo") {
|
||||
renderElement.setAttribute("data-inline-memo-content", Lute.EscapeHTMLStr(target.value));
|
||||
} else {
|
||||
renderElement.setAttribute("data-content", Lute.EscapeHTMLStr(target.value));
|
||||
renderElement.removeAttribute("data-render");
|
||||
|
@ -835,6 +845,8 @@ export class Toolbar {
|
|||
if (!this.subElement.querySelector('[data-type="refresh"]').classList.contains("block__icon--active")) {
|
||||
if (type === "NodeHTMLBlock") {
|
||||
renderElement.querySelector("protyle-html").setAttribute("data-content", Lute.EscapeHTMLStr(target.value));
|
||||
} else if (type === "inline-memo") {
|
||||
renderElement.setAttribute("data-inline-memo-content", Lute.EscapeHTMLStr(target.value));
|
||||
} else {
|
||||
renderElement.setAttribute("data-content", Lute.EscapeHTMLStr(target.value));
|
||||
renderElement.removeAttribute("data-render");
|
||||
|
|
|
@ -91,6 +91,7 @@ export class Options {
|
|||
"code",
|
||||
"inline-math",
|
||||
"|",
|
||||
"inline-memo",
|
||||
"text",
|
||||
] : [
|
||||
"block-ref",
|
||||
|
@ -110,6 +111,7 @@ export class Options {
|
|||
"code",
|
||||
"inline-math",
|
||||
"|",
|
||||
"inline-memo",
|
||||
"text",
|
||||
],
|
||||
typewriterMode: false,
|
||||
|
@ -222,6 +224,12 @@ export class Options {
|
|||
hotkey: window.siyuan.config.keymap.editor.insert["inline-math"].custom,
|
||||
icon: "iconMath",
|
||||
tipPosition: "n",
|
||||
}, {
|
||||
name: "inline-memo",
|
||||
lang: "memo",
|
||||
hotkey: window.siyuan.config.keymap.editor.insert.memo.custom,
|
||||
icon: "iconM",
|
||||
tipPosition: "n",
|
||||
}, {
|
||||
name: "text",
|
||||
lang: "font",
|
||||
|
|
|
@ -116,7 +116,7 @@ export class WYSIWYG {
|
|||
if (// 表格行内公式之前无法插入文字 https://github.com/siyuan-note/siyuan/issues/3908
|
||||
inlineElement.tagName==="SPAN" &&
|
||||
range.toString() === "" && range.startContainer.nodeType === 3 &&
|
||||
(currentTypes.includes("text") || currentTypes.includes("block-ref")|| currentTypes.includes("file-annotation-ref")|| currentTypes.includes("a")) &&
|
||||
(currentTypes.includes("inline-memo") || currentTypes.includes("text") || currentTypes.includes("block-ref")|| currentTypes.includes("file-annotation-ref")|| currentTypes.includes("a")) &&
|
||||
!hasNextSibling(range.startContainer) && range.startContainer.textContent.length === range.startOffset &&
|
||||
inlineElement.textContent.replace(Constants.ZWSP, "").length >= inputData.length // 为空的时候需要等于
|
||||
) {
|
||||
|
@ -1090,6 +1090,10 @@ export class WYSIWYG {
|
|||
protyle.toolbar.showFileAnnotationRef(protyle, target);
|
||||
return false;
|
||||
}
|
||||
if (types.includes("inline-memo")) {
|
||||
protyle.toolbar.showRender(protyle, target);
|
||||
return false;
|
||||
}
|
||||
if (types.includes("a")) {
|
||||
linkMenu(protyle, target);
|
||||
if (target.getAttribute("data-href")?.startsWith("siyuan://blocks")) {
|
||||
|
|
|
@ -514,6 +514,9 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
|
|||
if (types.includes("block-ref")) {
|
||||
refMenu(protyle, inlineElement);
|
||||
return;
|
||||
} else if (types.includes("inline-memo")) {
|
||||
protyle.toolbar.showRender(protyle, inlineElement);
|
||||
return;
|
||||
} else if (types.includes("file-annotation-ref")) {
|
||||
protyle.toolbar.showFileAnnotationRef(protyle, inlineElement);
|
||||
return;
|
||||
|
@ -1180,7 +1183,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
|
|||
}
|
||||
if (matchHotKey(menuItem.hotkey, event)) {
|
||||
protyle.toolbar.range = getEditorRange(protyle.wysiwyg.element);
|
||||
if (["text", "a", "block-ref", "inline-math"].includes(menuItem.name)) {
|
||||
if (["text", "a", "block-ref", "inline-math", "inline-memo"].includes(menuItem.name)) {
|
||||
protyle.toolbar.element.querySelector(`[data-type="${menuItem.name}"]`).dispatchEvent(new CustomEvent("block-ref" === menuItem.name ? getEventName() : "click"));
|
||||
} else {
|
||||
protyle.toolbar.setInlineMark(protyle, menuItem.name, "range");
|
||||
|
|
Loading…
Add table
Reference in a new issue