Vanessa 2024-12-09 12:15:41 +08:00
parent dbdf3c15a9
commit c546e0fd94
9 changed files with 45 additions and 18 deletions

View file

@ -109,6 +109,11 @@
--b3-color-transition: color .2s cubic-bezier(0, 0, .2, 1) 0ms;
--b3-background-transition: background 20ms ease-in 0s;
/* 高亮 */
--b3-highlight-color: #222;
--b3-highlight-background: #ffff00;
--b3-highlight-current-background: #ff9632;
/* 下拉菜单 */
--b3-select-background: url("data:image/svg+xml;utf8,<svg fill='rgba(95, 99, 104, .68)' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/><path d='M0 0h24v24H0z' fill='none'/></svg>") no-repeat right 2px center var(--b3-theme-background);

View file

@ -108,6 +108,11 @@
--b3-color-transition: color .2s cubic-bezier(0, 0, .2, 1) 0ms;
--b3-background-transition: background 20ms ease-in 0s;
/* 高亮 */
--b3-highlight-color: #222;
--b3-highlight-background: #ffff00;
--b3-highlight-current-background: #ff9632;
/* 下拉菜单 */
--b3-select-background: url("data:image/svg+xml;utf8,<svg fill='rgba(154, 160, 166, .68)' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/><path d='M0 0h24v24H0z' fill='none'/></svg>") no-repeat right 2px center var(--b3-theme-background);

View file

@ -694,7 +694,7 @@ const bindEvent = (app: App, element: Element, dialog?: Dialog) => {
assetElement.classList.remove("fn__none");
assetElement.innerHTML = renderAssetsPreview(dataPath);
} else if (type === "doc") {
const k = (firstPanelElement.querySelector(".b3-text-field") as HTMLInputElement).value;
const k = (firstPanelElement.querySelector(".b3-text-field") as HTMLInputElement).value;
fetchPost("/api/history/getDocHistoryContent", {
historyPath: dataPath,
highlight: !isSupportCSSHL(),
@ -713,7 +713,7 @@ const bindEvent = (app: App, element: Element, dialog?: Dialog) => {
protyle: historyEditor.protyle,
action: [Constants.CB_GET_HISTORY, Constants.CB_GET_HTML],
});
searchMarkRender(historyEditor.protyle, k.split(" "), false);
searchMarkRender(historyEditor.protyle, k.split(" "));
}
});
}

View file

@ -136,7 +136,7 @@ export class Backlink extends Model {
item.addEventListener("blur", (event: KeyboardEvent) => {
const inputElement = event.target as HTMLInputElement;
inputElement.classList.add("fn__none");
const filterIconElement = inputElement.nextElementSibling;
const filterIconElement = inputElement.nextElementSibling;
if (inputElement.value) {
filterIconElement.classList.add("block__icon--active");
filterIconElement.setAttribute("aria-label", window.siyuan.languages.filter + " " + inputElement.value);
@ -467,7 +467,7 @@ export class Backlink extends Model {
}
});
editor.protyle.notebookId = liElement.getAttribute("data-notebook-id");
searchMarkRender(editor.protyle, keyword.split(" "), false);
searchMarkRender(editor.protyle, keyword.split(" "));
this.editors.push(editor);
});
}

View file

@ -85,8 +85,8 @@ export class Protyle {
if (isSupportCSSHL()) {
const styleId = genUUID();
this.protyle.highlight.styleElement.dataset.uuid = styleId;
this.protyle.highlight.styleElement.textContent = `.protyle-wysiwyg::highlight(search-mark-${styleId}) {background-color: var(--b3-protyle-inline-mark-background);color: var(--b3-protyle-inline-mark-color);}
.protyle-wysiwyg::highlight(search-mark-hl-${styleId}) {background-color: var(--b3-theme-primary-lighter);box-shadow: 0 0 0 .5px var(--b3-theme-on-background);}`;
this.protyle.highlight.styleElement.textContent = `.protyle-wysiwyg::highlight(search-mark-${styleId}) {background-color: var(--b3-highlight-background);color: var(--b3-highlight-color);}
.protyle-wysiwyg::highlight(search-mark-hl-${styleId}) {color: var(--b3-highlight-color);background-color: var(--b3-highlight-current-background)}`;
}
this.protyle.hint = new Hint(this.protyle);

View file

@ -1,6 +1,7 @@
import {Constants} from "../../constants";
import {isInEmbedBlock} from "../util/hasClosest";
export const searchMarkRender = (protyle: IProtyle, keys: string[], isHL: boolean, cb?: () => void) => {
export const searchMarkRender = (protyle: IProtyle, keys: string[], hlId?: string | number, cb?: () => void) => {
if (!isSupportCSSHL()) {
return;
}
@ -8,6 +9,16 @@ export const searchMarkRender = (protyle: IProtyle, keys: string[], isHL: boolea
protyle.highlight.markHL.clear();
protyle.highlight.mark.clear();
protyle.highlight.ranges = [];
let isSetHL = false;
let hlBlockElement: Element;
if (typeof hlId === "string") {
Array.from(protyle.wysiwyg.element.querySelectorAll(`[data-node-id='${hlId}']`)).find(item => {
if (!isInEmbedBlock(item)) {
hlBlockElement = item
return true
}
})
}
// 准备一个数组来保存所有文本节点
@ -25,7 +36,7 @@ export const searchMarkRender = (protyle: IProtyle, keys: string[], isHL: boolea
}
const text = protyle.wysiwyg.element.textContent;
const rangeIndexes: { range: Range, startIndex: number }[] = [];
const rangeIndexes: { range: Range, startIndex: number, isCurrent: boolean }[] = [];
keys.forEach(key => {
if (!key) {
@ -50,7 +61,13 @@ export const searchMarkRender = (protyle: IProtyle, keys: string[], isHL: boolea
currentTextNode = textNodes[currentNodeIndex];
range.setEnd(currentTextNode, endIndex - (currentNodeIndex ? textNodesSize[currentNodeIndex - 1] : 0));
rangeIndexes.push({range, startIndex});
let isCurrent = false;
if (!isSetHL && hlBlockElement && hlBlockElement.contains(currentTextNode)) {
isSetHL = true;
isCurrent = true;
}
rangeIndexes.push({range, startIndex, isCurrent});
} catch (e) {
console.error("searchMarkRender error:", e);
}
@ -65,7 +82,8 @@ export const searchMarkRender = (protyle: IProtyle, keys: string[], isHL: boolea
return 0;
}
}).forEach((item, index) => {
if (index === protyle.highlight.rangeIndex && isHL) {
if ((typeof hlId === "string" && item.isCurrent) || (typeof hlId === "number" && hlId === index)) {
protyle.highlight.rangeIndex = index;
protyle.highlight.markHL.add(item.range);
} else {
protyle.highlight.mark.add(item.range);
@ -73,7 +91,7 @@ export const searchMarkRender = (protyle: IProtyle, keys: string[], isHL: boolea
protyle.highlight.ranges.push(item.range);
});
CSS.highlights.set("search-mark-" + protyle.highlight.styleElement.dataset.uuid, protyle.highlight.mark);
if (isHL) {
if (typeof hlId !== "undefined") {
CSS.highlights.set("search-mark-hl-" + protyle.highlight.styleElement.dataset.uuid, protyle.highlight.markHL);
}
if (cb) {

View file

@ -46,7 +46,7 @@ export const reloadProtyle = (protyle: IProtyle, focus: boolean, updateReadonly?
}, response => {
protyle.options.backlinkData = isMention ? response.data.backmentions : response.data.backlinks;
renderBacklink(protyle, protyle.options.backlinkData);
searchMarkRender(protyle, keyword.split(" "), false);
searchMarkRender(protyle, keyword.split(" "));
});
}
} else {
@ -58,7 +58,7 @@ export const reloadProtyle = (protyle: IProtyle, focus: boolean, updateReadonly?
updateReadonly,
cb(keys) {
if (protyle.query?.key) {
searchMarkRender(protyle, keys, true);
searchMarkRender(protyle, keys, protyle.highlight.rangeIndex);
}
}
});

View file

@ -1249,10 +1249,9 @@ export const getArticle = (options: {
const contentRect = options.edit.protyle.contentElement.getBoundingClientRect();
if (isSupportCSSHL()) {
options.edit.protyle.highlight.rangeIndex = 0;
searchMarkRender(options.edit.protyle, getResponse.data.keywords, true, () => {
if (options.edit.protyle.highlight.ranges.length > 0) {
options.edit.protyle.contentElement.scrollTop = options.edit.protyle.contentElement.scrollTop + options.edit.protyle.highlight.ranges[0].getBoundingClientRect().top - contentRect.top - contentRect.height / 2;
searchMarkRender(options.edit.protyle, getResponse.data.keywords, options.id, () => {
if (options.edit.protyle.highlight.ranges.length > 0 && options.edit.protyle.highlight.ranges[options.edit.protyle.highlight.rangeIndex]) {
options.edit.protyle.contentElement.scrollTop = options.edit.protyle.contentElement.scrollTop + options.edit.protyle.highlight.ranges[options.edit.protyle.highlight.rangeIndex].getBoundingClientRect().top - contentRect.top - contentRect.height / 2;
}
});
} else {

View file

@ -484,7 +484,7 @@ interface IProtyle {
mark: Highlight
markHL: Highlight
ranges: Range[]
rangeIndex: 0
rangeIndex: number
styleElement: HTMLStyleElement
}
getInstance: () => import("../protyle").Protyle,