24c17a793f
Live preview mode is here
63 lines
1.6 KiB
TypeScript
63 lines
1.6 KiB
TypeScript
// Forked from https://codeberg.org/retronav/ixora
|
|
// Original author: Pranav Karawale
|
|
// License: Apache License 2.0.
|
|
|
|
import {
|
|
Decoration,
|
|
DecorationSet,
|
|
EditorView,
|
|
ViewPlugin,
|
|
ViewUpdate,
|
|
} from "../deps.ts";
|
|
import {
|
|
checkRangeOverlap,
|
|
invisibleDecoration,
|
|
iterateTreeInVisibleRanges,
|
|
} from "./util.ts";
|
|
|
|
function getLinkAnchor(view: EditorView) {
|
|
const widgets: any[] = [];
|
|
|
|
iterateTreeInVisibleRanges(view, {
|
|
enter: ({ type, from, to, node }) => {
|
|
if (type.name !== "URL") return;
|
|
const parent = node.parent;
|
|
const blackListedParents = ["Image"];
|
|
if (parent && !blackListedParents.includes(parent.name)) {
|
|
const marks = parent.getChildren("LinkMark");
|
|
const ranges = view.state.selection.ranges;
|
|
const cursorOverlaps = ranges.some(({ from, to }) =>
|
|
checkRangeOverlap([from, to], [parent.from, parent.to])
|
|
);
|
|
if (!cursorOverlaps) {
|
|
widgets.push(
|
|
...marks.map(({ from, to }) => invisibleDecoration.range(from, to)),
|
|
invisibleDecoration.range(from, to),
|
|
);
|
|
}
|
|
}
|
|
},
|
|
});
|
|
|
|
return Decoration.set(widgets, true);
|
|
}
|
|
|
|
export const goToLinkPlugin = ViewPlugin.fromClass(
|
|
class {
|
|
decorations: DecorationSet = Decoration.none;
|
|
constructor(view: EditorView) {
|
|
this.decorations = getLinkAnchor(view);
|
|
}
|
|
update(update: ViewUpdate) {
|
|
if (
|
|
update.docChanged ||
|
|
update.viewportChanged ||
|
|
update.selectionSet
|
|
) {
|
|
this.decorations = getLinkAnchor(update.view);
|
|
}
|
|
}
|
|
},
|
|
{ decorations: (v) => v.decorations },
|
|
);
|