diff --git a/app/src/assets/scss/_typography.scss b/app/src/assets/scss/_typography.scss
index 6a635cdad..663f31b1b 100644
--- a/app/src/assets/scss/_typography.scss
+++ b/app/src/assets/scss/_typography.scss
@@ -52,7 +52,8 @@
color: var(--b3-protyle-inline-s-color);
}
- strong {
+ strong,
+ span[data-type~="strong"] {
color: var(--b3-protyle-inline-strong-color);
}
diff --git a/app/src/assets/scss/_wysiwyg.scss b/app/src/assets/scss/_wysiwyg.scss
index b3af986f9..cffdf4190 100644
--- a/app/src/assets/scss/_wysiwyg.scss
+++ b/app/src/assets/scss/_wysiwyg.scss
@@ -169,6 +169,10 @@
}
}
+ span[data-type~="strong"] {
+ font-weight: bold;
+ }
+
span[data-type="tag"] {
border-bottom: 1px solid var(--b3-protyle-inline-tag-color);
color: var(--b3-protyle-inline-tag-color);
diff --git a/app/src/constants.ts b/app/src/constants.ts
index 603b6bd4e..c15fe5a37 100644
--- a/app/src/constants.ts
+++ b/app/src/constants.ts
@@ -397,7 +397,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[] = ["link", "bold", "italic", "underline", "strike", "mark", "sup", "sub", "tag", "inline-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"];
public static readonly BLOCK_HINT_KEYS: string[] = ["((", "[[", "((", "【【"];
public static readonly BLOCK_HINT_CLOSE_KEYS: IObject = {"((": "))", "[[": "]]", "((": "))", "【【": "】】"};
public static readonly CODE_LANGUAGES: string[] = [
diff --git a/app/src/protyle/hint/extend.ts b/app/src/protyle/hint/extend.ts
index 976d7d5ac..98ee428be 100644
--- a/app/src/protyle/hint/extend.ts
+++ b/app/src/protyle/hint/extend.ts
@@ -110,23 +110,23 @@ export const hintSlash = (key: string, protyle: IProtyle) => {
html: `
${window.siyuan.languages.emoji}
`,
}, {
filter: ["链接", "lianjie", "lj", "link"],
- value: "link",
+ value: "a",
html: `${window.siyuan.languages.link}
`,
}, {
- filter: ["粗体", "cuti", "ct", "bold"],
- value: "bold",
+ filter: ["粗体", "cuti", "ct", "bold", "strong"],
+ value: "strong",
html: `${window.siyuan.languages.bold}
`,
}, {
- filter: ["斜体", "xieti", "xt", "italic"],
- value: "italic",
+ filter: ["斜体", "xieti", "xt", "italic", "em"],
+ value: "em",
html: `${window.siyuan.languages.italic}
`,
}, {
filter: ["下划线", "xiahuaxian", "xhx", "underline"],
- value: "underline",
+ value: "u",
html: `${window.siyuan.languages.underline}
`,
}, {
filter: ["删除线", "shanchuxian", "scx", "strike"],
- value: "strike",
+ value: "s",
html: `${window.siyuan.languages.strike}
`,
}, {
filter: ["标记", "biaoji", "bj", "mark"],
@@ -146,7 +146,7 @@ export const hintSlash = (key: string, protyle: IProtyle) => {
html: `${window.siyuan.languages.tag}
`,
}, {
filter: ["行内代码", "hangneidaima", "hndm", "inline code"],
- value: "inline-code",
+ value: "code",
html: `${window.siyuan.languages["inline-code"]}
`,
}, {
filter: ["行内数学公式", "hangneishuxuegongshi", "hnsxgs", "inline math"],
diff --git a/app/src/protyle/toolbar/Font.ts b/app/src/protyle/toolbar/Font.ts
index 19f420008..bb02c0a50 100644
--- a/app/src/protyle/toolbar/Font.ts
+++ b/app/src/protyle/toolbar/Font.ts
@@ -120,7 +120,7 @@ export const fontEvent = (protyle: IProtyle, type?: string, color?: string) => {
color = fontStyles[1];
}
}
- protyle.toolbar.setInlineMark(protyle, "bold", "add", true);
+ protyle.toolbar.setInlineMark(protyle, "text", "add", true);
const range = protyle.toolbar.range;
const fontElement = hasClosestByMatchTag(range.startContainer, "STRONG");
if (!fontElement) {
diff --git a/app/src/protyle/toolbar/ToolbarItem.ts b/app/src/protyle/toolbar/ToolbarItem.ts
index 30859636c..de9bc3a68 100644
--- a/app/src/protyle/toolbar/ToolbarItem.ts
+++ b/app/src/protyle/toolbar/ToolbarItem.ts
@@ -7,7 +7,7 @@ export class ToolbarItem {
constructor(protyle: IProtyle, menuItem: IMenuItem) {
this.element = document.createElement("button");
const hotkey = menuItem.hotkey ? ` ${updateHotkeyTip(menuItem.hotkey)}` : "";
- const tip = menuItem.tip || window.siyuan.languages[menuItem.name];
+ const tip = menuItem.tip || window.siyuan.languages[menuItem.lang];
this.element.classList.add("protyle-toolbar__item", "b3-tooltips", `b3-tooltips__${menuItem.tipPosition}`);
this.element.setAttribute("data-type", menuItem.name);
this.element.setAttribute("aria-label", tip + hotkey);
diff --git a/app/src/protyle/toolbar/index.ts b/app/src/protyle/toolbar/index.ts
index f25baa908..24985b89c 100644
--- a/app/src/protyle/toolbar/index.ts
+++ b/app/src/protyle/toolbar/index.ts
@@ -134,31 +134,31 @@ export class Toolbar {
}
public getCurrentType(range = this.range) {
- const types: string[] = [];
+ let types: string[] = [];
let startElement = range.startContainer as HTMLElement;
if (startElement.nodeType === 3) {
startElement = startElement.parentElement;
- if (startElement.getAttribute("data-type") === "virtual-block-ref" && !["DIV", "TD", "TH"].includes(startElement.parentElement.tagName)) {
- startElement = startElement.parentElement;
- }
} else if (startElement.childElementCount > 0 && startElement.childNodes[range.startOffset]?.nodeType !== 3) {
startElement = startElement.childNodes[range.startOffset] as HTMLElement;
}
if (!startElement || startElement.nodeType === 3) {
return [];
}
+ if (!["DIV", "TD", "TH"].includes(startElement.tagName)) {
+ types = startElement.getAttribute("data-type").split(" ");
+ }
let endElement = range.endContainer as HTMLElement;
if (endElement.nodeType === 3) {
endElement = endElement.parentElement;
- if (endElement.getAttribute("data-type") === "virtual-block-ref" && !["DIV", "TD", "TH"].includes(endElement.parentElement.tagName)) {
- endElement = endElement.parentElement;
- }
} else if (endElement.childElementCount > 0 && endElement.childNodes[range.endOffset]?.nodeType !== 3) {
endElement = endElement.childNodes[range.endOffset] as HTMLElement;
}
if (!endElement || endElement.nodeType === 3) {
return [];
}
+ if (!["DIV", "TD", "TH"].includes(endElement.tagName)) {
+ types = types.concat(endElement.getAttribute("data-type").split(" "));
+ }
if (range.startOffset === range.startContainer.textContent.length) {
const nextSibling = hasNextSibling(range.startContainer as Element);
if (nextSibling && nextSibling.nodeType !== 3 && (nextSibling as Element).getAttribute("data-type") === "inline-math") {
@@ -170,77 +170,41 @@ export class Toolbar {
types.push("inline-math");
}
}
- if (startElement.tagName === "STRONG" || endElement.tagName === "STRONG") {
- types.push("bold");
- }
- if (startElement.tagName === "EM" || endElement.tagName === "EM") {
- types.push("italic");
- }
- if (startElement.tagName === "U" || endElement.tagName === "U") {
- types.push("underline");
- }
- if (startElement.tagName === "S" || endElement.tagName === "S") {
- types.push("strike");
- }
- if (startElement.tagName === "MARK" || endElement.tagName === "MARK") {
- types.push("mark");
- }
- if (startElement.tagName === "SUP" || endElement.tagName === "SUP") {
- types.push("sup");
- }
- if (startElement.tagName === "SUB" || endElement.tagName === "SUB") {
- types.push("sub");
- }
- if (startElement.tagName === "KBD" || endElement.tagName === "KBD") {
- types.push("kbd");
- }
- if (startElement.tagName === "SPAN" || endElement.tagName === "SPAN") {
- const startType = startElement.getAttribute("data-type");
- const endType = endElement.getAttribute("data-type");
- if (startType === "tag" || endType === "tag") {
- types.push("tag");
- } else if (startType === "a" || endType === "a") {
- types.push("link");
- } else if (startType === "block-ref" || endType === "block-ref") {
- types.push("blockRef");
- } else if (startType === "file-annotation-ref" || endType === "file-annotation-ref") {
- types.push("fileAnnotationRef");
- } else if (startType === "inline-math") {
- types.push("inline-math");
+ range.cloneContents().childNodes.forEach((item:HTMLElement) => {
+ if (item.nodeType !== 3) {
+ types = types.concat(item.getAttribute("data--type").split(" "));
}
- }
- if (startElement.tagName === "CODE" || endElement.tagName === "CODE") {
- types.push("inline-code");
- }
+ });
+ types = [...new Set(types)];
return types;
}
private genItem(protyle: IProtyle, menuItem: IMenuItem) {
let menuItemObj;
switch (menuItem.name) {
- case "bold":
- case "italic":
- case "strike":
- case "inline-code":
+ case "strong":
+ case "em":
+ case "s":
+ case "code":
case "mark":
case "tag":
- case "underline":
+ case "u":
case "sup":
case "sub":
case "kbd":
case "inline-math":
menuItemObj = new ToolbarItem(protyle, menuItem);
break;
- case "blockRef":
+ case "block-ref":
menuItemObj = new BlockRef(protyle, menuItem);
break;
case "|":
menuItemObj = new Divider();
break;
- case "font":
+ case "text":
menuItemObj = new Font(protyle, menuItem);
break;
- case "link":
+ case "a":
menuItemObj = new Link(protyle, menuItem);
break;
}
@@ -267,7 +231,54 @@ export class Toolbar {
});
}
- public async setInlineMark(protyle: IProtyle, type: string, action: "remove" | "add" | "range" | "toolbar", focusAdd = false) {
+ public setInlineMark(protyle: IProtyle, type: string, action: "remove" | "add" | "range" | "toolbar", focusAdd = false) {
+ const nodeElement = hasClosestBlock(this.range.startContainer);
+ if (!nodeElement) {
+ return;
+ }
+ const wbrElement = document.createElement("wbr");
+ const html = nodeElement.outerHTML;
+
+ if (this.range.startOffset === 0 && !hasPreviousSibling(this.range.startContainer)) {
+ this.range.setStartBefore(this.range.startContainer.parentElement)
+ }
+ if (this.range.endOffset === this.range.endContainer.textContent.length && !hasNextSibling(this.range.endContainer)) {
+ this.range.setEndAfter(this.range.endContainer.parentElement)
+ }
+ const actionBtn = action === "toolbar" ? this.element.querySelector(`[data-type="${type}"]`) : undefined;
+ const contents = this.range.extractContents();
+ this.range.insertNode(wbrElement);
+ const newNodes: Node[] = [];
+ contents.childNodes.forEach((item: HTMLElement) => {
+ if (item.nodeType === 3) {
+ if (item.textContent !== "") {
+ const inlineElement = document.createElement("span");
+ inlineElement.setAttribute("data-type", type);
+ inlineElement.appendChild(item);
+ newNodes.push(inlineElement);
+ }
+ } else {
+ const types = (item.getAttribute("data-type") || "").split(" ");
+ types.push(type);
+ item.setAttribute("data-type", types.join(" "));
+ newNodes.push(item);
+ }
+ });
+ newNodes.forEach((item, index) => {
+ this.range.insertNode(item);
+ if (index === 0) {
+ this.range.setStart(item.firstChild, 0);
+ }
+ if (index === newNodes.length - 1) {
+ this.range.setEnd(item.lastChild, item.lastChild.textContent.length);
+ }
+ });
+ nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
+ updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
+ wbrElement.remove();
+ }
+
+ public async setInlineMark1(protyle: IProtyle, type: string, action: "remove" | "add" | "range" | "toolbar", focusAdd = false) {
const nodeElement = hasClosestBlock(this.range.startContainer);
if (!nodeElement) {
return;
@@ -281,7 +292,7 @@ export class Toolbar {
return;
}
// 对已有字体样式的文字再次添加字体样式
- if (focusAdd && action === "add" && types.includes("bold") && this.range.startContainer.nodeType === 3 &&
+ if (focusAdd && action === "add" && types.includes("text") && this.range.startContainer.nodeType === 3 &&
this.range.startContainer.parentNode.isSameNode(this.range.endContainer.parentNode)) {
return;
}
diff --git a/app/src/protyle/util/Options.ts b/app/src/protyle/util/Options.ts
index c97208f8c..bdf7438de 100644
--- a/app/src/protyle/util/Options.ts
+++ b/app/src/protyle/util/Options.ts
@@ -78,28 +78,28 @@ export class Options {
mode: "both",
},
toolbar: isMobile() ? [
- "blockRef",
- "link",
+ "block-ref",
+ "a",
"|",
- "bold",
- "italic",
- "underline",
- "strike",
+ "strong",
+ "em",
+ "u",
+ "s",
"mark",
"|",
"tag",
- "inline-code",
+ "code",
"inline-math",
"|",
- "font",
+ "text",
] : [
- "blockRef",
- "link",
+ "block-ref",
+ "a",
"|",
- "bold",
- "italic",
- "underline",
- "strike",
+ "strong",
+ "em",
+ "u",
+ "s",
"mark",
"|",
"sup",
@@ -107,10 +107,10 @@ export class Options {
"kbd",
"|",
"tag",
- "inline-code",
+ "code",
"inline-math",
"|",
- "font",
+ "text",
],
typewriterMode: false,
upload: {
@@ -145,79 +145,92 @@ export class Options {
private mergeToolbar(toolbar: Array) {
const toolbarItem: IMenuItem [] = [{
- name: "blockRef",
+ name: "block-ref",
hotkey: window.siyuan.config.keymap.editor.insert.blockRef.custom,
+ lang: "blockRef",
icon: "iconGraph",
tipPosition: "ne",
}, {
- name: "link",
+ name: "a",
hotkey: window.siyuan.config.keymap.editor.insert.link.custom,
+ lang: "link",
icon: "iconLink",
tipPosition: "n",
}, {
- name: "bold",
+ name: "strong",
+ lang: "bold",
hotkey: window.siyuan.config.keymap.editor.insert.bold.custom,
icon: "iconBold",
tipPosition: "n",
}, {
- name: "italic",
+ name: "em",
+ lang: "italic",
hotkey: window.siyuan.config.keymap.editor.insert.italic.custom,
icon: "iconItalic",
tipPosition: "n",
}, {
- name: "underline",
+ name: "u",
+ lang: "underline",
hotkey: window.siyuan.config.keymap.editor.insert.underline.custom,
icon: "iconUnderline",
tipPosition: "n",
}, {
- name: "strike",
+ name: "s",
+ lang: "strike",
hotkey: window.siyuan.config.keymap.editor.insert.strike.custom,
icon: "iconStrike",
tipPosition: "n",
}, {
name: "mark",
+ lang: "mark",
hotkey: window.siyuan.config.keymap.editor.insert.mark.custom,
icon: "iconMark",
tipPosition: "n",
}, {
name: "sup",
+ lang: "sup",
hotkey: window.siyuan.config.keymap.editor.insert.sup.custom,
icon: "iconSup",
tipPosition: "n",
}, {
name: "sub",
+ lang: "sub",
hotkey: window.siyuan.config.keymap.editor.insert.sub.custom,
icon: "iconSub",
tipPosition: "n",
}, {
name: "kbd",
+ lang: "kbd",
hotkey: window.siyuan.config.keymap.editor.insert.kbd.custom,
icon: "iconKeymap",
tipPosition: "n",
}, {
name: "tag",
+ lang: "tag",
hotkey: window.siyuan.config.keymap.editor.insert.tag.custom,
icon: "iconTags",
tipPosition: "n",
}, {
- name: "inline-code",
+ name: "code",
+ lang: "inline-code",
hotkey: window.siyuan.config.keymap.editor.insert["inline-code"].custom,
icon: "iconInlineCode",
tipPosition: "n",
}, {
name: "inline-math",
+ lang: "inline-math",
hotkey: window.siyuan.config.keymap.editor.insert["inline-math"].custom,
icon: "iconMath",
tipPosition: "n",
}, {
- name: "font",
+ name: "text",
+ lang: "font",
hotkey: window.siyuan.config.keymap.editor.insert.font.custom,
icon: "iconFont",
tipPosition: "n",
}, {
name: "|",
- }
- ];
+ }];
const toolbarResult: IMenuItem[] = [];
toolbar.forEach((menuItem: IMenuItem) => {
let currentMenuItem = menuItem;
diff --git a/app/src/types/protyle.d.ts b/app/src/types/protyle.d.ts
index 7f6c8b551..8d7e17bf7 100644
--- a/app/src/types/protyle.d.ts
+++ b/app/src/types/protyle.d.ts
@@ -268,6 +268,7 @@ interface IUpload {
interface IMenuItem {
/** 唯一标示 */
name: string;
+ lang?: string;
/** svg 图标 */
icon?: string;
/** 提示 */