Vanessa 2026-01-14 20:17:16 +08:00
parent d509172273
commit 5d6cb8eca0
5 changed files with 56 additions and 33 deletions

View file

@ -416,6 +416,7 @@ export abstract class Constants {
// "⌘", "⇧", "⌥", "⌃"
// "⌘A", "⌘X", "⌘C", "⌘V", "⌘-", "⌘=", "⌘0", "⇧⌘V", "⌘/", "⇧↑", "⇧↓", "⇧→", "⇧←", "⇧⇥", "⌃D", "⇧⌘→", "⇧⌘←",
// "⌘Home", "⌘End", "⇧↩", "↩", "PageUp", "PageDown", "⌫", "⌦", "Escape" 不可自定义
// "⌥↩" 写死,但可自定义
public static readonly SIYUAN_KEYMAP: Config.IKeymap = {
general: {
mainMenu: {default: "⌥\\", custom: "⌥\\"},

View file

@ -1,5 +1,4 @@
import {hasClosestBlock} from "../util/hasClosest";
import {updateTransaction} from "./transaction";
import {transaction} from "./transaction";
import {focusBlock} from "../util/selection";
import {Dialog} from "../../dialog";
import {Menu} from "../../plugin/Menu";
@ -7,12 +6,11 @@ import {isMobile} from "../../util/functions";
import {Constants} from "../../constants";
import {openEmojiPanel, unicode2Emoji} from "../../emoji";
export const updateCalloutType = (titleElement: HTMLElement, protyle: IProtyle) => {
const blockElement = hasClosestBlock(titleElement);
if (!blockElement) {
export const updateCalloutType = (blockElements: HTMLElement[], protyle: IProtyle) => {
if (blockElements.length === 0) {
return;
}
const blockCalloutElement = blockElement.querySelector(".callout-icon");
const blockCalloutElement = blockElements[0].querySelector(".callout-icon");
const dialog = new Dialog({
title: window.siyuan.languages.callout,
content: `<div class="b3-dialog__content">
@ -32,7 +30,7 @@ export const updateCalloutType = (titleElement: HTMLElement, protyle: IProtyle)
</div>
<span class="fn__space"></span>
<div class="b3-form__icona fn__flex-1">
<input value="${blockElement.getAttribute("data-subtype")}" type="text" class="b3-text-field fn__block b3-form__icona-input">
<input value="${blockElements[0].getAttribute("data-subtype")}" type="text" class="b3-text-field fn__block b3-form__icona-input">
<svg class="b3-form__icona-icon"><use xlink:href="#iconDown"></use></svg>
</div>
</label>
@ -56,19 +54,34 @@ export const updateCalloutType = (titleElement: HTMLElement, protyle: IProtyle)
dialog.destroy();
});
btnElements[1].addEventListener("click", () => {
const oldHTML = blockElement.outerHTML;
blockElement.setAttribute("data-subtype", textElements[0].value.trim());
let title = textElements[1].value.trim();
if (title) {
const template = document.createElement("template");
template.innerHTML = protyle.lute.Md2BlockDOM(textElements[1].value.trim());
title = template.content.firstElementChild.firstElementChild.innerHTML;
}
titleElement.innerHTML = title ||
(textElements[0].value.trim().substring(0, 1).toUpperCase() + textElements[0].value.trim().substring(1).toLowerCase());
blockCalloutElement.innerHTML = dialogCalloutIconElement.innerHTML;
updateTransaction(protyle, blockElement.getAttribute("data-node-id"), blockElement.outerHTML, oldHTML);
focusBlock(blockElement);
const doOperations: IOperation[] = [];
const undoOperations: IOperation[] = [];
blockElements.filter(item => {
const id = item.getAttribute("data-node-id");
const oldHTML = item.outerHTML;
item.setAttribute("data-subtype", textElements[0].value.trim());
let title = textElements[1].value.trim();
if (title) {
const template = document.createElement("template");
template.innerHTML = protyle.lute.Md2BlockDOM(textElements[1].value.trim());
title = template.content.firstElementChild.firstElementChild.innerHTML;
}
item.querySelector(".callout-title").innerHTML = title ||
(textElements[0].value.trim().substring(0, 1).toUpperCase() + textElements[0].value.trim().substring(1).toLowerCase());
item.querySelector(".callout-icon").innerHTML = dialogCalloutIconElement.innerHTML;
doOperations.push({
id,
data: item.outerHTML,
action: "update"
});
undoOperations.push({
id,
data: oldHTML,
action: "update"
});
});
transaction(protyle, doOperations, undoOperations);
focusBlock(blockElements[0]);
dialog.destroy();
});
const textElements: NodeListOf<HTMLInputElement> = dialog.element.querySelectorAll(".b3-text-field");
@ -88,7 +101,7 @@ export const updateCalloutType = (titleElement: HTMLElement, protyle: IProtyle)
});
textElements[0].focus();
textElements[0].select();
textElements[1].value = protyle.lute.BlockDOM2StdMd(titleElement.innerHTML);
textElements[1].value = protyle.lute.BlockDOM2StdMd(blockElements[0].querySelector(".callout-title").innerHTML);
const dialogCalloutIconElement = dialog.element.querySelector(".callout-icon");
dialogCalloutIconElement.addEventListener("click", () => {
const emojiRect = dialogCalloutIconElement.getBoundingClientRect();

View file

@ -3048,7 +3048,7 @@ export class WYSIWYG {
const calloutTitleElement = hasTopClosestByClassName(event.target, "callout-title");
if (!protyle.disabled && !event.shiftKey && !ctrlIsPressed && calloutTitleElement) {
updateCalloutType(calloutTitleElement, protyle);
updateCalloutType([hasClosestBlock(calloutTitleElement) as HTMLElement], protyle);
event.preventDefault();
event.stopPropagation();
return;

View file

@ -73,6 +73,7 @@ import {AIActions} from "../../ai/actions";
import {openLink} from "../../editor/openLink";
import {onlyProtyleCommand} from "../../boot/globalEvent/command/protyle";
import {AIChat} from "../../ai/chat";
import {updateCalloutType} from "./callout";
export const getContentByInlineHTML = (range: Range, cb: (content: string) => void) => {
let html = "";
@ -1083,17 +1084,24 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
selectElements.push(nodeElement);
}
if (selectElements.length > 0 && !isIncludesHotKey("⌥↩")) {
const otherElement = selectElements.find(item => {
return !item.classList.contains("code-block");
});
if (!otherElement) {
const languageElements: HTMLElement[] = [];
selectElements.forEach(item => {
const languageElements: HTMLElement[] = [];
const calloutElements: HTMLElement[] = [];
selectElements.forEach(item => {
if (item.classList.contains("code-block")) {
languageElements.push(item.querySelector(".protyle-action__language"));
});
} else {
const calloutElement = hasClosestByClassName(item, "callout");
if (calloutElement) {
calloutElements.push(calloutElement);
}
}
});
if (languageElements.length > 0) {
protyle.toolbar.showCodeLanguage(protyle, languageElements);
} else {
addSubList(protyle, nodeElement, range);
} else if (addSubList(protyle, nodeElement, range)) {
// 函数内部已处理
} else if (calloutElements.length > 0) {
updateCalloutType(calloutElements, protyle);
}
event.stopPropagation();
event.preventDefault();

View file

@ -52,11 +52,11 @@ export const genListItemElement = (listItemElement: Element, offset = 0, wbr = f
export const addSubList = (protyle: IProtyle, nodeElement: Element, range: Range) => {
const parentItemElement = hasClosestByClassName(nodeElement, "li");
if (!parentItemElement) {
return;
return false;
}
const lastSubItem = parentItemElement.querySelector(".list")?.lastElementChild.previousElementSibling;
if (!lastSubItem) {
return;
return false;
}
const newListElement = genListItemElement(lastSubItem, 0, true);
const id = newListElement.getAttribute("data-node-id");
@ -78,6 +78,7 @@ export const addSubList = (protyle: IProtyle, nodeElement: Element, range: Range
id,
}]);
focusByWbr(newListElement, range);
return true;
};
export const listIndent = (protyle: IProtyle, liItemElements: Element[], range: Range) => {