refactor: 将图片预览插件从 ViewPlugin 重构为 StateField 以优化性能
continuous-integration/drone/push Build is failing
continuous-integration/drone/push Build is failing
This commit is contained in:
1 parent
aa4a4236ed
commit
bcab2fc280
1 file changed
+40
-46
@@ -1,7 +1,7 @@
|
|||||||
import { WidgetType, EditorView, ViewPlugin, Decoration, ViewUpdate } from '@codemirror/view';
|
import { WidgetType, EditorView, Decoration } from '@codemirror/view';
|
||||||
import type { DecorationSet } from '@codemirror/view';
|
import type { DecorationSet } from '@codemirror/view';
|
||||||
|
import { StateField, type Transaction, type EditorState, Range } from '@codemirror/state';
|
||||||
import { syntaxTree } from '@codemirror/language';
|
import { syntaxTree } from '@codemirror/language';
|
||||||
import { Range } from '@codemirror/state';
|
|
||||||
|
|
||||||
class ImagePreviewWidget extends WidgetType {
|
class ImagePreviewWidget extends WidgetType {
|
||||||
constructor(readonly url: string) {
|
constructor(readonly url: string) {
|
||||||
@@ -35,57 +35,51 @@ class ImagePreviewWidget extends WidgetType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getImageDecorations(view: EditorView) {
|
|
||||||
|
function getImageDecorationsForState(state: EditorState) {
|
||||||
const widgets: Range<Decoration>[] = [];
|
const widgets: Range<Decoration>[] = [];
|
||||||
const { state } = view;
|
|
||||||
|
|
||||||
for (const { from, to } of view.visibleRanges) {
|
syntaxTree(state).iterate({
|
||||||
syntaxTree(state).iterate({
|
enter: (node: {
|
||||||
from,
|
name: string;
|
||||||
to,
|
from: number;
|
||||||
enter: (node: { name: string; from: number; to: number; node: { getChild: (type: string) => any } }) => {
|
to: number;
|
||||||
if (node.name === 'Image') {
|
node: { getChild: (type: string) => any };
|
||||||
// 查找图片语法中的 URL 节点
|
}) => {
|
||||||
const urlNode = node.node.getChild('URL');
|
if (node.name === 'Image') {
|
||||||
if (urlNode) {
|
// 查找图片语法中的 URL 节点
|
||||||
let url = state.doc.sliceString(urlNode.from, urlNode.to);
|
const urlNode = node.node.getChild('URL');
|
||||||
// 处理可能的带尖括号的 URL
|
if (urlNode) {
|
||||||
if (url.startsWith('<') && url.endsWith('>')) {
|
let url = state.doc.sliceString(urlNode.from, urlNode.to);
|
||||||
url = url.slice(1, -1);
|
// 处理可能的带尖括号的 URL
|
||||||
}
|
if (url.startsWith('<') && url.endsWith('>')) {
|
||||||
|
url = url.slice(1, -1);
|
||||||
const deco = Decoration.widget({
|
|
||||||
widget: new ImagePreviewWidget(url),
|
|
||||||
block: true, // 作为块级元素显示在下方
|
|
||||||
side: 1 // 插入在节点之后
|
|
||||||
});
|
|
||||||
|
|
||||||
widgets.push(deco.range(node.to));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deco = Decoration.widget({
|
||||||
|
widget: new ImagePreviewWidget(url),
|
||||||
|
block: true, // 作为块级元素显示在下方
|
||||||
|
side: 1 // 插入在节点之后
|
||||||
|
});
|
||||||
|
|
||||||
|
widgets.push(deco.range(node.to));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return Decoration.set(widgets.sort((a, b) => a.from - b.from));
|
return Decoration.set(widgets.sort((a, b) => a.from - b.from));
|
||||||
}
|
}
|
||||||
|
|
||||||
export const imagePreviewPlugin = ViewPlugin.fromClass(
|
export const imagePreviewPlugin = StateField.define<DecorationSet>({
|
||||||
class {
|
create(state) {
|
||||||
decorations: DecorationSet;
|
return getImageDecorationsForState(state);
|
||||||
|
|
||||||
constructor(view: EditorView) {
|
|
||||||
this.decorations = getImageDecorations(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
update(update: ViewUpdate) {
|
|
||||||
// 文档改变或视口改变时重新计算
|
|
||||||
if (update.docChanged || update.viewportChanged) {
|
|
||||||
this.decorations = getImageDecorations(update.view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
update(value, tr: Transaction) {
|
||||||
decorations: (v) => v.decorations
|
if (tr.docChanged) {
|
||||||
}
|
return getImageDecorationsForState(tr.state);
|
||||||
);
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
provide: (f) => EditorView.decorations.from(f)
|
||||||
|
});
|
||||||
Reference in new issue
Block a user