mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-02-24 04:00:59 +01:00
editor: add ctrl+k to create link shortcut (#3501)
* editor: added link pop-up keyboard short-cut * editor: Ctrl+K to create link --------- Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { NodeWithOffset } from "@/src/utils/prosemirror";
|
||||
import { NodeWithOffset } from "../../../utils/prosemirror";
|
||||
import { createContext, useContext } from "react";
|
||||
|
||||
const HoverPopupContext = createContext<{
|
||||
|
||||
@@ -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) {
|
||||
</Popup>
|
||||
);
|
||||
}
|
||||
|
||||
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) => (
|
||||
<LinkPopup
|
||||
link={
|
||||
selectedNode && selectedNode.node
|
||||
? {
|
||||
title: isActive ? selectedNode.node.textContent : selectedText,
|
||||
href: link?.attrs.href || ""
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
onClose={close}
|
||||
onDone={(link) => {
|
||||
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"
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -4,10 +4,6 @@
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"jsx": "react-jsx",
|
||||
"outDir": "./dist/",
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["*"]
|
||||
},
|
||||
"incremental": true
|
||||
},
|
||||
"exclude": ["src/**/*.test.ts"],
|
||||
|
||||
@@ -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/"]
|
||||
}
|
||||
Reference in New Issue
Block a user