Skip to content

Commit

Permalink
feat(link-editor): change link editor from a popover to a plugin pane (
Browse files Browse the repository at this point in the history
…#142)

fixes #19
  • Loading branch information
b-kelly committed Jun 28, 2022
1 parent 768b575 commit 3e4c847
Show file tree
Hide file tree
Showing 11 changed files with 1,104 additions and 490 deletions.
64 changes: 43 additions & 21 deletions src/rich-text/commands/index.ts
Expand Up @@ -18,9 +18,9 @@ import {
imageUploaderEnabled,
showImageUploader,
} from "../../shared/prosemirror-plugins/image-upload";
import { getCurrentTextNode, getShortcut } from "../../shared/utils";
import type { CommonViewOptions } from "../../shared/view";
import { getShortcut } from "../../shared/utils";
import { LINK_TOOLTIP_KEY } from "../plugins/link-editor";
import { showLinkEditor } from "../plugins/link-editor";
import { insertParagraphIfAtDocEnd } from "./helpers";
import {
insertTableColumnAfterCommand,
Expand Down Expand Up @@ -198,30 +198,52 @@ export function insertLinkCommand(
dispatch: (tr: Transaction) => void,
view: EditorView
): boolean {
if (state.selection.empty) return false;
// never actually toggle the mark, as that is done in the link editor
// we do want to *pretend* to, as toggleMark checks for validity
const valid = toggleMark(state.schema.marks.link, { href: null })(
state,
null
);

let linkUrl = null;
if (dispatch && valid) {
let selectedText: string;
let linkUrl: string;

if (dispatch) {
const selectedText =
state.selection.content().content.firstChild?.textContent ?? null;
const linkMatch = /^http(s)?:\/\/\S+$/.exec(selectedText);
linkUrl = linkMatch?.length > 0 ? linkMatch[0] : "";

// wrap the dispatch function so that we can add additional transactions after toggleMark
const oldDispatch = dispatch;
dispatch = (tr) => {
oldDispatch(tr);
view.dispatch(
LINK_TOOLTIP_KEY.setEditMode(true, state, view.state.tr)
const $anchor = state.selection.$anchor;
// if selection is empty, but inside link mark, use the link url/text from it
if (state.selection.empty && $anchor.textOffset) {
const currentTextNode = getCurrentTextNode(state);
const mark = currentTextNode.marks.find(
(m) => m.type === state.schema.marks.link
);
};
if (mark) {
selectedText = currentTextNode.text;
linkUrl = mark.attrs.href as string;

// expand the selection so we're editing the entire link
const pos = $anchor.pos;
dispatch(
state.tr.setSelection(
TextSelection.create(
state.doc,
pos - $anchor.textOffset,
pos - $anchor.textOffset + selectedText.length
)
)
);
}
} else {
selectedText =
state.selection.content().content.firstChild?.textContent ??
null;
const linkMatch = /^http(s)?:\/\/\S+$/.exec(selectedText);
linkUrl = linkMatch?.length > 0 ? linkMatch[0] : "";
}

showLinkEditor(view, linkUrl, selectedText);
}

return toggleMark(state.schema.marks.link, { href: linkUrl })(
state,
dispatch
);
return valid;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/rich-text/editor.ts
Expand Up @@ -33,7 +33,7 @@ import { TagLink } from "./node-views/tag-link";
import { codePasteHandler } from "./plugins/code-paste-handler";
import { linkPasteHandler } from "./plugins/link-paste-handler";
import { linkPreviewPlugin, LinkPreviewProvider } from "./plugins/link-preview";
import { linkTooltipPlugin } from "./plugins/link-editor";
import { linkEditorPlugin } from "./plugins/link-editor";
import { placeholderPlugin } from "../shared/prosemirror-plugins/placeholder";
import { plainTextPasteHandler } from "./plugins/plain-text-paste-handler";
import { spoilerToggle } from "./plugins/spoiler-toggle";
Expand Down Expand Up @@ -125,7 +125,7 @@ export class RichTextEditor extends BaseView {
interfaceManagerPlugin(
this.options.pluginParentContainer
),
linkTooltipPlugin(this.options.parserFeatures),
linkEditorPlugin(this.options.parserFeatures),
placeholderPlugin(this.options.placeholderText),
richTextImageUpload(
this.options.imageUpload,
Expand Down

0 comments on commit 3e4c847

Please sign in to comment.