현재 선택된 부분에 따라 데코를 유지할건지 없앨것인지 결정

This commit is contained in:
kim365my 2024-04-05 19:54:15 +09:00
parent cb915eb4d0
commit 3370b5bd6f
2 changed files with 33 additions and 28 deletions

View File

@ -27,36 +27,42 @@ class StatefulDecorationSet {
} }
async computeAsyncDecorations(tokens: TokenSpec[]): Promise<DecorationSet | null> { async computeAsyncDecorations(tokens: TokenSpec[]): Promise<DecorationSet | null> {
// 현재 모드 판별
const isSourceMode = !this.editor.state.field(editorLivePreviewField); const isSourceMode = !this.editor.state.field(editorLivePreviewField);
if (isSourceMode) { // 현재 선택된 부분
return Decoration.none; const selectFrom = this.editor.state.selection.main.from;
} else { const selectTo = this.editor.state.selection.main.to;
const decorations: Range<Decoration>[] = [];
for (const token of tokens) { const decorations: Range<Decoration>[] = [];
let deco = this.decoCache[token.value]; for (const token of tokens) {
if (!deco) { const isSelected = (selectFrom <= token.to && selectTo >= token.from) || (selectFrom >= token.from && selectTo <= token.to);
const div = createDiv();
// 클래스 추가 if (isSelected || isSourceMode) {
div.addClass("cm-embed-block"); return Decoration.none;
div.addClass("cm-embed-link"); }
// 넣을 EL 받아오기
const linkEl = createEl("a"); let deco = this.decoCache[token.value];
linkEl.href = token.value; if (!deco) {
linkEl.addClass("markdown-rendered"); const div = createDiv();
div.appendChild(linkEl); // 클래스 추가
const params = await LinkThumbnailWidgetParams(token.value); div.addClass("cm-embed-block");
if (params != null) { div.addClass("cm-embed-link");
// 넣을 EL 받아오기
const linkEl = createEl("a");
linkEl.href = token.value;
linkEl.addClass("markdown-rendered");
div.appendChild(linkEl);
LinkThumbnailWidgetParams(token.value).then(params => {
if (params) {
linkEl.innerHTML = params; linkEl.innerHTML = params;
linkEl.addEventListener("click", (e) => e.stopPropagation()); linkEl.addEventListener("click", (e) => e.stopPropagation());
} else {
return Decoration.none;
} }
deco = this.decoCache[token.value] = Decoration.replace({widget: new EmojiWidget(div), block: true}); });
} deco = this.decoCache[token.value] = Decoration.replace({widget: new EmojiWidget(div), block: true});
decorations.push(deco.range(token.from, token.to));
} }
return Decoration.set(decorations, true); decorations.push(deco.range(token.from, token.to));
} }
return Decoration.set(decorations, true);
} }
debouncedUpdate = debounce(this.updateAsyncDecorations, 100, true); debouncedUpdate = debounce(this.updateAsyncDecorations, 100, true);
@ -81,7 +87,7 @@ function buildViewPlugin(plugin: LinkThumbnailPlugin) {
} }
update(update: ViewUpdate) { update(update: ViewUpdate) {
if (update.docChanged || update.viewportChanged) { if (update.docChanged || update.viewportChanged || update.selectionSet) {
this.buildAsyncDecorations(update.view); this.buildAsyncDecorations(update.view);
} }
} }
@ -93,9 +99,9 @@ function buildViewPlugin(plugin: LinkThumbnailPlugin) {
tree.iterate({ tree.iterate({
enter: ({node, from, to}) => { enter: ({node, from, to}) => {
const tokenProps = node.type.prop<string>(tokenClassNodeProp); const tokenProps = node.type.prop<string>(tokenClassNodeProp);
if (tokenProps && node.name === "url") { if (tokenProps && node.name === "url") {
const value = view.state.doc.sliceString(from, to); const value = view.state.doc.sliceString(from, to);
console.log(tokenProps, node, value, view.state);
if (value) { if (value) {
targetElements.push({from: from, to: to, value: value}); targetElements.push({from: from, to: to, value: value});
} }

View File

@ -14,7 +14,7 @@ export class PostProcessor {
context: MarkdownPostProcessorContext context: MarkdownPostProcessorContext
) => { ) => {
// 링크 변환 // 링크 변환
const linkEls:Element[] = element.findAll("a.external-link:not(.cm-formatting)"); const linkEls:Element[] = element.findAll("a.external-link:not(.cm-formatting, .markdown-rendered)");
for (const linkEl of linkEls) { for (const linkEl of linkEls) {
// dataview 클래스를 가진 부모 요소를 확인합니다. // dataview 클래스를 가진 부모 요소를 확인합니다.
if (linkEl.closest(".dataview") !== null) { if (linkEl.closest(".dataview") !== null) {
@ -24,7 +24,6 @@ export class PostProcessor {
const params = await LinkThumbnailWidgetParams(url); const params = await LinkThumbnailWidgetParams(url);
if (params != null) { if (params != null) {
linkEl.innerHTML = params; linkEl.innerHTML = params;
linkEl.removeClass("external-link");
linkEl.addClass("markdown-rendered"); linkEl.addClass("markdown-rendered");
linkEl.addEventListener("click", (e) => e.stopPropagation()); linkEl.addEventListener("click", (e) => e.stopPropagation());
} }