fix: Text relayout caused by external link decorations rendered async

This commit is contained in:
Tom Moor
2022-04-03 16:48:40 -07:00
parent 41579eb4bf
commit cf71fc1108
3 changed files with 23 additions and 13 deletions

View File

@@ -728,8 +728,11 @@ const EditorStyles = styled.div<{
}
.external-link {
display: inline-block;
position: relative;
top: 2px;
width: 16px;
height: 16px;
}
.code-actions,

View File

@@ -13,12 +13,20 @@ import { EditorState, Plugin } from "prosemirror-state";
import { Decoration, DecorationSet } from "prosemirror-view";
import * as React from "react";
import ReactDOM from "react-dom";
import { isInternalUrl } from "../../utils/urls";
import { isExternalUrl } from "../../utils/urls";
import findLinkNodes from "../queries/findLinkNodes";
import { EventType, Dispatch } from "../types";
import Mark from "./Mark";
const LINK_INPUT_REGEX = /\[([^[]+)]\((\S+)\)$/;
let icon: HTMLSpanElement;
if (typeof window !== "undefined") {
const component = <OpenIcon color="currentColor" size={16} />;
icon = document.createElement("span");
icon.className = "external-link";
ReactDOM.render(component, icon);
}
function isPlainURL(
link: ProsemirrorMark,
@@ -116,20 +124,15 @@ export default class Link extends Mark {
}
get plugins() {
const component = <OpenIcon color="currentColor" size={16} />;
const icon = document.createElement("span");
icon.className = "external-link";
ReactDOM.render(component, icon);
const getLinkDecorations = (doc: Node) => {
const getLinkDecorations = (state: EditorState) => {
const decorations: Decoration[] = [];
const links = findLinkNodes(doc);
const links = findLinkNodes(state.doc);
links.forEach((nodeWithPos) => {
const linkMark = nodeWithPos.node.marks.find(
(mark) => mark.type.name === "link"
);
if (linkMark && !isInternalUrl(linkMark.attrs.href)) {
if (linkMark && isExternalUrl(linkMark.attrs.href)) {
decorations.push(
Decoration.widget(
// place the decoration at the end of the link
@@ -145,16 +148,16 @@ export default class Link extends Mark {
}
});
return DecorationSet.create(doc, decorations);
return DecorationSet.create(state.doc, decorations);
};
const plugin: Plugin = new Plugin({
state: {
init: (config, state) => {
return getLinkDecorations(state.doc);
return getLinkDecorations(state);
},
apply: (tr, oldState) => {
return tr.docChanged ? getLinkDecorations(tr.doc) : oldState;
apply: (tr, decorationSet, _oldState, newState) => {
return tr.docChanged ? getLinkDecorations(newState) : decorationSet;
},
},
props: {

View File

@@ -28,3 +28,7 @@ export function isInternalUrl(href: string) {
return false;
}
export function isExternalUrl(href: string) {
return !isInternalUrl(href);
}