diff --git a/packages/editor/src/extensions/key-map/key-map.ts b/packages/editor/src/extensions/key-map/key-map.ts index e0108a717..a90b240ed 100644 --- a/packages/editor/src/extensions/key-map/key-map.ts +++ b/packages/editor/src/extensions/key-map/key-map.ts @@ -21,6 +21,7 @@ import { Extension } from "@tiptap/core"; import { isInTable } from "@tiptap/pm/tables"; import { isListActive } from "../../utils/prosemirror"; import { CodeBlock } from "../code-block"; +import { showLinkPopup } from "../../toolbar/popups/link-popup"; export const KeyMap = Extension.create({ name: "key-map", @@ -65,6 +66,10 @@ export const KeyMap = Extension.create({ }); }); return true; + }, + "Mod-k": ({ editor }) => { + showLinkPopup(editor); + return true; } }; } diff --git a/packages/editor/src/extensions/link/link.ts b/packages/editor/src/extensions/link/link.ts index 8683159c3..42d966eb6 100644 --- a/packages/editor/src/extensions/link/link.ts +++ b/packages/editor/src/extensions/link/link.ts @@ -29,7 +29,6 @@ import { } from "@tiptap/core"; import { Plugin, TextSelection } from "@tiptap/pm/state"; import { find, registerCustomProtocol, reset } from "linkifyjs"; - import { autolink } from "./helpers/autolink"; import { clickHandler } from "./helpers/clickHandler"; import { pasteHandler } from "./helpers/pasteHandler"; diff --git a/packages/editor/src/toolbar/floating-menus/hover-popup/context.ts b/packages/editor/src/toolbar/floating-menus/hover-popup/context.ts index d785bf4f3..8734168cf 100644 --- a/packages/editor/src/toolbar/floating-menus/hover-popup/context.ts +++ b/packages/editor/src/toolbar/floating-menus/hover-popup/context.ts @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { NodeWithOffset } from "@/src/utils/prosemirror"; +import { NodeWithOffset } from "../../../utils/prosemirror"; import { createContext, useContext } from "react"; const HoverPopupContext = createContext<{ diff --git a/packages/editor/src/toolbar/popups/link-popup.tsx b/packages/editor/src/toolbar/popups/link-popup.tsx index f71cb7066..330fdcc7f 100644 --- a/packages/editor/src/toolbar/popups/link-popup.tsx +++ b/packages/editor/src/toolbar/popups/link-popup.tsx @@ -21,7 +21,12 @@ import { Input } from "@theme-ui/components"; import { Flex } from "@theme-ui/components"; import { useRefValue } from "../../hooks/use-ref-value"; import { Popup } from "../components/popup"; -import { LinkDefinition } from "../tools/link"; +import { isInternalLink, LinkDefinition } from "../tools/link"; +import { showPopup } from "../../components/popup-presenter"; +import Link, { LinkAttributes } from "../../extensions/link"; +import { ImageNode } from "../../extensions/image"; +import { findMark, selectionToOffset } from "../../utils/prosemirror"; +import { Editor, getMarkAttributes } from "@tiptap/core"; export type LinkPopupProps = { link?: LinkDefinition; @@ -84,3 +89,60 @@ export function LinkPopup(props: LinkPopupProps) { ); } + +export async function showLinkPopup(editor: Editor) { + const isActive = editor.isActive(Link.name); + const isImageActive = editor.isActive(ImageNode.name); + const selectedNode = selectionToOffset(editor.state); + const link = selectedNode?.node + ? findMark(selectedNode.node, Link.name) + : null; + const attrs = link?.attrs || getMarkAttributes(editor.state, Link.name); + const selectedText = editor.state.doc.textBetween( + editor.state.selection.from, + editor.state.selection.to + ); + if (isInternalLink(attrs.href)) { + const link = await editor.storage.createInternalLink?.( + attrs as LinkAttributes + ); + if (!link) return; + if (isActive) { + const { from, to } = editor.state.selection; + if (selectedNode) editor.commands.setTextSelection(selectedNode); + editor.commands.setLink(link); + if (selectedNode) editor.commands.setTextSelection({ from, to }); + } else { + editor.commands.setLink({ ...link, title: selectedText || link.title }); + } + return; + } + + showPopup({ + popup: (close) => ( + { + if (isActive) { + if (selectedNode) + editor.chain().focus().setTextSelection(selectedNode).run(); + editor.commands.setLink(link); + } else editor.commands.toggleLink(link); + close(); + }} + isEditing={isActive} + isImageActive={isImageActive} + /> + ), + mobile: "sheet", + desktop: "popup" + }); +} diff --git a/packages/editor/src/toolbar/tools/image.tsx b/packages/editor/src/toolbar/tools/image.tsx index ca3d2ff7c..87be3901a 100644 --- a/packages/editor/src/toolbar/tools/image.tsx +++ b/packages/editor/src/toolbar/tools/image.tsx @@ -25,7 +25,7 @@ import { MoreTools } from "../components/more-tools"; import { useToolbarLocation } from "../stores/toolbar-store"; import { ImageProperties as ImagePropertiesPopup } from "../popups/image-properties"; import { findSelectedNode } from "../../utils/prosemirror"; -import { ImageAttributes } from "@/src/extensions/image"; +import { ImageAttributes } from "../../extensions/image"; export function ImageSettings(props: ToolProps) { const { editor } = props; diff --git a/packages/editor/src/toolbar/tools/link.tsx b/packages/editor/src/toolbar/tools/link.tsx index e5cb389bf..ee57ed543 100644 --- a/packages/editor/src/toolbar/tools/link.tsx +++ b/packages/editor/src/toolbar/tools/link.tsx @@ -315,6 +315,6 @@ function LinkTool(props: LinkToolProps) { ); } -function isInternalLink(href?: string | null) { +export function isInternalLink(href?: string | null) { return typeof href === "string" ? href.startsWith("nn://") : false; } diff --git a/packages/editor/tsconfig.json b/packages/editor/tsconfig.json index c6f0fedea..b47f68260 100644 --- a/packages/editor/tsconfig.json +++ b/packages/editor/tsconfig.json @@ -4,10 +4,6 @@ "lib": ["DOM", "DOM.Iterable", "ESNext"], "jsx": "react-jsx", "outDir": "./dist/", - "baseUrl": "./", - "paths": { - "@/*": ["*"] - }, "incremental": true }, "exclude": ["src/**/*.test.ts"], diff --git a/packages/editor/tsconfig.tests.json b/packages/editor/tsconfig.tests.json deleted file mode 100644 index 45ffcc826..000000000 --- a/packages/editor/tsconfig.tests.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "../../tsconfig", - "compilerOptions": { - "module": "commonjs", - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "jsx": "react-jsx", - "outDir": "./dist/", - "baseUrl": "./", - "paths": { - "@/*": ["*"] - } - }, - "ts-node": { - "transpileOnly": true, - "swc": true, - "require": ["tsconfig-paths/register"] - }, - "include": ["src/"] -}