@portabletext/plugin-paste-link 3.0.27 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { c } from "react/compiler-runtime";
|
|
|
2
2
|
import { useEditor } from "@portabletext/editor";
|
|
3
3
|
import { defineBehavior, raise } from "@portabletext/editor/behaviors";
|
|
4
4
|
import * as selectors from "@portabletext/editor/selectors";
|
|
5
|
+
import { getPathSubSchema } from "@portabletext/editor/traversal";
|
|
5
6
|
import { useEffect } from "react";
|
|
6
7
|
function looksLikeUrl(text) {
|
|
7
8
|
try {
|
|
@@ -50,15 +51,15 @@ function createPasteLinkBehaviors(config) {
|
|
|
50
51
|
const {
|
|
51
52
|
snapshot,
|
|
52
53
|
event
|
|
53
|
-
} = guardParams;
|
|
54
|
-
if (
|
|
54
|
+
} = guardParams, selectionCollapsed = selectors.isSelectionCollapsed(snapshot), focusBlock = selectors.getFocusBlock(snapshot);
|
|
55
|
+
if (selectionCollapsed || !focusBlock)
|
|
55
56
|
return !1;
|
|
56
57
|
const text = event.originEvent.dataTransfer.getData("text/plain"), href = looksLikeUrl(text) ? text : void 0;
|
|
57
58
|
if (!href)
|
|
58
59
|
return !1;
|
|
59
60
|
const result = config.link({
|
|
60
61
|
context: {
|
|
61
|
-
schema: snapshot.
|
|
62
|
+
schema: getPathSubSchema(snapshot, focusBlock.path),
|
|
62
63
|
keyGenerator: snapshot.context.keyGenerator
|
|
63
64
|
},
|
|
64
65
|
value: {
|
|
@@ -100,9 +101,9 @@ function createPasteLinkBehaviors(config) {
|
|
|
100
101
|
const text = event.originEvent.dataTransfer.getData("text/plain"), href = looksLikeUrl(text) ? text : void 0;
|
|
101
102
|
if (!href)
|
|
102
103
|
return !1;
|
|
103
|
-
const result = config.link({
|
|
104
|
+
const subSchema = getPathSubSchema(snapshot, focusTextBlock.path), result = config.link({
|
|
104
105
|
context: {
|
|
105
|
-
schema:
|
|
106
|
+
schema: subSchema,
|
|
106
107
|
keyGenerator: snapshot.context.keyGenerator
|
|
107
108
|
},
|
|
108
109
|
value: {
|
|
@@ -115,7 +116,7 @@ function createPasteLinkBehaviors(config) {
|
|
|
115
116
|
_type,
|
|
116
117
|
_key,
|
|
117
118
|
...value
|
|
118
|
-
} = result, markState = selectors.getMarkState(snapshot), decoratorNames =
|
|
119
|
+
} = result, markState = selectors.getMarkState(snapshot), decoratorNames = subSchema.decorators.map((decorator) => decorator.name), activeDecorators = (markState?.marks ?? []).filter((mark) => decoratorNames.includes(mark)), markDefKey = _key ?? snapshot.context.keyGenerator(), markDef = {
|
|
119
120
|
_type,
|
|
120
121
|
_key: markDefKey,
|
|
121
122
|
...value
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/looks-like-url.ts","../src/plugin.paste-link.tsx"],"sourcesContent":["export function looksLikeUrl(text: string) {\n try {\n const url = new URL(text)\n return sensibleProtocols.includes(url.protocol)\n } catch {\n return false\n }\n}\n\nconst sensibleProtocols = ['http:', 'https:', 'mailto:', 'tel:']\n","import type {EditorContext} from '@portabletext/editor'\nimport {useEditor} from '@portabletext/editor'\nimport {\n defineBehavior,\n raise,\n type BehaviorGuard,\n type NativeBehaviorEvent,\n} from '@portabletext/editor/behaviors'\nimport * as selectors from '@portabletext/editor/selectors'\nimport {useEffect} from 'react'\nimport {looksLikeUrl} from './looks-like-url'\n\n/**\n * Guard function that controls when the paste link behavior runs.\n * Return `false` to skip the behavior and fall through to default paste handling.\n * @public\n */\nexport type PasteLinkGuard = BehaviorGuard<\n Extract<NativeBehaviorEvent, {type: 'clipboard.paste'}>,\n true\n>\n\n/**\n * Context provided to link matchers.\n * @public\n */\nexport type LinkMatcherContext = Pick<EditorContext, 'schema' | 'keyGenerator'>\n\n/**\n * Value provided to link matchers.\n * @public\n */\nexport type LinkMatcherValue = {href: string}\n\n/**\n * Object returned by link matchers.\n * @public\n */\nexport type LinkMatcherResult = {\n _type: string\n _key?: string\n [other: string]: unknown\n}\n\n/**\n * Function that converts a pasted URL into a link annotation.\n * Return `undefined` to skip handling.\n * @public\n */\nexport type LinkMatcher = (params: {\n context: LinkMatcherContext\n value: LinkMatcherValue\n}) => LinkMatcherResult | undefined\n\n/**\n * @public\n */\nexport type PasteLinkPluginProps = {\n guard?: PasteLinkGuard\n link?: LinkMatcher\n}\n\nconst defaultLinkMatcher: LinkMatcher = ({context, value}) => {\n const schemaType = context.schema.annotations.find(\n (annotation) => annotation.name === 'link',\n )\n const hrefField = schemaType?.fields.find(\n (field) => field.name === 'href' && field.type === 'string',\n )\n\n if (!schemaType || !hrefField) {\n return undefined\n }\n\n return {\n _type: schemaType.name,\n [hrefField.name]: value.href,\n }\n}\n\n/**\n * Plugin that handles pasting URLs in the editor.\n *\n * When text is selected and a URL is pasted, adds a link annotation to the selection.\n * When the caret is collapsed (no selection) and a URL is pasted, inserts the URL as text with a link annotation.\n *\n * @public\n */\nexport function PasteLinkPlugin({\n guard,\n link = defaultLinkMatcher,\n}: PasteLinkPluginProps) {\n const editor = useEditor()\n\n useEffect(() => {\n const behaviors = createPasteLinkBehaviors({guard, link})\n const unregisterBehaviors = behaviors.map((behavior) =>\n editor.registerBehavior({behavior}),\n )\n\n return () => {\n for (const unregisterBehavior of unregisterBehaviors) {\n unregisterBehavior()\n }\n }\n }, [editor, guard, link])\n\n return null\n}\n\nfunction createPasteLinkBehaviors(\n config: Required<Pick<PasteLinkPluginProps, 'link'>> &\n Pick<PasteLinkPluginProps, 'guard'>,\n) {\n /**\n * When text is selected and a URL is pasted, add a link annotation to the\n * selection. If the selection already has a link annotation, the core\n * `preventOverlappingAnnotations` behavior will remove it first.\n */\n const pasteLinkOnSelection = defineBehavior({\n on: 'clipboard.paste',\n guard: (guardParams) => {\n if (config.guard && config.guard(guardParams) === false) {\n return false\n }\n\n const {snapshot, event} = guardParams\n const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)\n\n if (selectionCollapsed) {\n return false\n }\n\n const text = event.originEvent.dataTransfer.getData('text/plain')\n const href = looksLikeUrl(text) ? text : undefined\n\n if (!href) {\n return false\n }\n\n const result = config.link({\n context: {\n schema: snapshot.context.schema,\n keyGenerator: snapshot.context.keyGenerator,\n },\n value: {href},\n })\n\n if (!result) {\n return false\n }\n\n const {_type, _key, ...value} = result\n\n return {annotation: {name: _type, _key, value}}\n },\n actions: [\n (_, {annotation}) => [\n raise({\n type: 'annotation.add',\n annotation,\n }),\n ],\n ],\n })\n\n /**\n * When the caret is collapsed (no selection) and a URL is pasted, insert the\n * URL as text with a link annotation. Existing decorators (bold, italic,\n * etc.) are preserved.\n */\n const pasteLinkAtCaret = defineBehavior({\n on: 'clipboard.paste',\n guard: (guardParams) => {\n if (config.guard && config.guard(guardParams) === false) {\n return false\n }\n\n const {snapshot, event} = guardParams\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)\n\n if (!focusTextBlock || !selectionCollapsed) {\n return false\n }\n\n const text = event.originEvent.dataTransfer.getData('text/plain')\n const href = looksLikeUrl(text) ? text : undefined\n\n if (!href) {\n return false\n }\n\n const result = config.link({\n context: {\n schema: snapshot.context.schema,\n keyGenerator: snapshot.context.keyGenerator,\n },\n value: {href},\n })\n\n if (!result) {\n return false\n }\n\n const {_type, _key, ...value} = result\n\n const markState = selectors.getMarkState(snapshot)\n const decoratorNames = snapshot.context.schema.decorators.map(\n (decorator) => decorator.name,\n )\n const activeDecorators = (markState?.marks ?? []).filter((mark) =>\n decoratorNames.includes(mark),\n )\n\n const markDefKey = _key ?? snapshot.context.keyGenerator()\n const markDef = {\n _type,\n _key: markDefKey,\n ...value,\n }\n\n return {\n focusTextBlock,\n markDef,\n markDefKey,\n href,\n activeDecorators,\n }\n },\n actions: [\n (\n {snapshot},\n {focusTextBlock, markDef, markDefKey, href, activeDecorators},\n ) => [\n raise({\n type: 'block.set',\n at: focusTextBlock.path,\n props: {\n markDefs: [...(focusTextBlock.node.markDefs ?? []), markDef],\n },\n }),\n raise({\n type: 'insert.child',\n child: {\n _type: snapshot.context.schema.span.name,\n text: href,\n marks: [...activeDecorators, markDefKey],\n },\n }),\n ],\n ],\n })\n\n return [pasteLinkOnSelection, pasteLinkAtCaret]\n}\n"],"names":["looksLikeUrl","text","url","URL","sensibleProtocols","includes","protocol","defaultLinkMatcher","context","value","schemaType","schema","annotations","find","annotation","name","hrefField","fields","field","type","_type","href","PasteLinkPlugin","t0","$","_c","guard","link","t1","undefined","editor","useEditor","t2","t3","unregisterBehaviors","createPasteLinkBehaviors","map","behavior","registerBehavior","unregisterBehavior","useEffect","config","pasteLinkOnSelection","defineBehavior","on","guardParams","snapshot","event","selectors","isSelectionCollapsed","originEvent","dataTransfer","getData","result","keyGenerator","_key","actions","_","raise","pasteLinkAtCaret","focusTextBlock","getFocusTextBlock","selectionCollapsed","markState","getMarkState","decoratorNames","decorators","decorator","activeDecorators","marks","filter","mark","markDefKey","markDef","at","path","props","markDefs","node","child","span"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/looks-like-url.ts","../src/plugin.paste-link.tsx"],"sourcesContent":["export function looksLikeUrl(text: string) {\n try {\n const url = new URL(text)\n return sensibleProtocols.includes(url.protocol)\n } catch {\n return false\n }\n}\n\nconst sensibleProtocols = ['http:', 'https:', 'mailto:', 'tel:']\n","import type {EditorContext} from '@portabletext/editor'\nimport {useEditor} from '@portabletext/editor'\nimport {\n defineBehavior,\n raise,\n type BehaviorGuard,\n type NativeBehaviorEvent,\n} from '@portabletext/editor/behaviors'\nimport * as selectors from '@portabletext/editor/selectors'\nimport {getPathSubSchema} from '@portabletext/editor/traversal'\nimport {useEffect} from 'react'\nimport {looksLikeUrl} from './looks-like-url'\n\n/**\n * Guard function that controls when the paste link behavior runs.\n * Return `false` to skip the behavior and fall through to default paste handling.\n * @public\n */\nexport type PasteLinkGuard = BehaviorGuard<\n Extract<NativeBehaviorEvent, {type: 'clipboard.paste'}>,\n true\n>\n\n/**\n * Context provided to link matchers.\n * @public\n */\nexport type LinkMatcherContext = Pick<EditorContext, 'schema' | 'keyGenerator'>\n\n/**\n * Value provided to link matchers.\n * @public\n */\nexport type LinkMatcherValue = {href: string}\n\n/**\n * Object returned by link matchers.\n * @public\n */\nexport type LinkMatcherResult = {\n _type: string\n _key?: string\n [other: string]: unknown\n}\n\n/**\n * Function that converts a pasted URL into a link annotation.\n * Return `undefined` to skip handling.\n * @public\n */\nexport type LinkMatcher = (params: {\n context: LinkMatcherContext\n value: LinkMatcherValue\n}) => LinkMatcherResult | undefined\n\n/**\n * @public\n */\nexport type PasteLinkPluginProps = {\n guard?: PasteLinkGuard\n link?: LinkMatcher\n}\n\nconst defaultLinkMatcher: LinkMatcher = ({context, value}) => {\n const schemaType = context.schema.annotations.find(\n (annotation) => annotation.name === 'link',\n )\n const hrefField = schemaType?.fields.find(\n (field) => field.name === 'href' && field.type === 'string',\n )\n\n if (!schemaType || !hrefField) {\n return undefined\n }\n\n return {\n _type: schemaType.name,\n [hrefField.name]: value.href,\n }\n}\n\n/**\n * Plugin that handles pasting URLs in the editor.\n *\n * When text is selected and a URL is pasted, adds a link annotation to the selection.\n * When the caret is collapsed (no selection) and a URL is pasted, inserts the URL as text with a link annotation.\n *\n * @public\n */\nexport function PasteLinkPlugin({\n guard,\n link = defaultLinkMatcher,\n}: PasteLinkPluginProps) {\n const editor = useEditor()\n\n useEffect(() => {\n const behaviors = createPasteLinkBehaviors({guard, link})\n const unregisterBehaviors = behaviors.map((behavior) =>\n editor.registerBehavior({behavior}),\n )\n\n return () => {\n for (const unregisterBehavior of unregisterBehaviors) {\n unregisterBehavior()\n }\n }\n }, [editor, guard, link])\n\n return null\n}\n\nfunction createPasteLinkBehaviors(\n config: Required<Pick<PasteLinkPluginProps, 'link'>> &\n Pick<PasteLinkPluginProps, 'guard'>,\n) {\n /**\n * When text is selected and a URL is pasted, add a link annotation to the\n * selection. If the selection already has a link annotation, the core\n * `preventOverlappingAnnotations` behavior will remove it first.\n */\n const pasteLinkOnSelection = defineBehavior({\n on: 'clipboard.paste',\n guard: (guardParams) => {\n if (config.guard && config.guard(guardParams) === false) {\n return false\n }\n\n const {snapshot, event} = guardParams\n const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)\n const focusBlock = selectors.getFocusBlock(snapshot)\n\n if (selectionCollapsed || !focusBlock) {\n return false\n }\n\n const text = event.originEvent.dataTransfer.getData('text/plain')\n const href = looksLikeUrl(text) ? text : undefined\n\n if (!href) {\n return false\n }\n\n const result = config.link({\n context: {\n schema: getPathSubSchema(snapshot, focusBlock.path),\n keyGenerator: snapshot.context.keyGenerator,\n },\n value: {href},\n })\n\n if (!result) {\n return false\n }\n\n const {_type, _key, ...value} = result\n\n return {annotation: {name: _type, _key, value}}\n },\n actions: [\n (_, {annotation}) => [\n raise({\n type: 'annotation.add',\n annotation,\n }),\n ],\n ],\n })\n\n /**\n * When the caret is collapsed (no selection) and a URL is pasted, insert the\n * URL as text with a link annotation. Existing decorators (bold, italic,\n * etc.) are preserved.\n */\n const pasteLinkAtCaret = defineBehavior({\n on: 'clipboard.paste',\n guard: (guardParams) => {\n if (config.guard && config.guard(guardParams) === false) {\n return false\n }\n\n const {snapshot, event} = guardParams\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)\n\n if (!focusTextBlock || !selectionCollapsed) {\n return false\n }\n\n const text = event.originEvent.dataTransfer.getData('text/plain')\n const href = looksLikeUrl(text) ? text : undefined\n\n if (!href) {\n return false\n }\n\n const subSchema = getPathSubSchema(snapshot, focusTextBlock.path)\n const result = config.link({\n context: {\n schema: subSchema,\n keyGenerator: snapshot.context.keyGenerator,\n },\n value: {href},\n })\n\n if (!result) {\n return false\n }\n\n const {_type, _key, ...value} = result\n\n const markState = selectors.getMarkState(snapshot)\n const decoratorNames = subSchema.decorators.map(\n (decorator) => decorator.name,\n )\n const activeDecorators = (markState?.marks ?? []).filter((mark) =>\n decoratorNames.includes(mark),\n )\n\n const markDefKey = _key ?? snapshot.context.keyGenerator()\n const markDef = {\n _type,\n _key: markDefKey,\n ...value,\n }\n\n return {\n focusTextBlock,\n markDef,\n markDefKey,\n href,\n activeDecorators,\n }\n },\n actions: [\n (\n {snapshot},\n {focusTextBlock, markDef, markDefKey, href, activeDecorators},\n ) => [\n raise({\n type: 'block.set',\n at: focusTextBlock.path,\n props: {\n markDefs: [...(focusTextBlock.node.markDefs ?? []), markDef],\n },\n }),\n raise({\n type: 'insert.child',\n child: {\n _type: snapshot.context.schema.span.name,\n text: href,\n marks: [...activeDecorators, markDefKey],\n },\n }),\n ],\n ],\n })\n\n return [pasteLinkOnSelection, pasteLinkAtCaret]\n}\n"],"names":["looksLikeUrl","text","url","URL","sensibleProtocols","includes","protocol","defaultLinkMatcher","context","value","schemaType","schema","annotations","find","annotation","name","hrefField","fields","field","type","_type","href","PasteLinkPlugin","t0","$","_c","guard","link","t1","undefined","editor","useEditor","t2","t3","unregisterBehaviors","createPasteLinkBehaviors","map","behavior","registerBehavior","unregisterBehavior","useEffect","config","pasteLinkOnSelection","defineBehavior","on","guardParams","snapshot","event","selectionCollapsed","selectors","isSelectionCollapsed","focusBlock","getFocusBlock","originEvent","dataTransfer","getData","result","getPathSubSchema","path","keyGenerator","_key","actions","_","raise","pasteLinkAtCaret","focusTextBlock","getFocusTextBlock","subSchema","markState","getMarkState","decoratorNames","decorators","decorator","activeDecorators","marks","filter","mark","markDefKey","markDef","at","props","markDefs","node","child","span"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/plugin-paste-link",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Allows pasting links in the Portable Text Editor",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"portabletext",
|
|
@@ -34,23 +34,23 @@
|
|
|
34
34
|
],
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@sanity/tsconfig": "^2.1.0",
|
|
37
|
-
"@types/react": "^19.2.
|
|
38
|
-
"@vitejs/plugin-react": "^5.
|
|
39
|
-
"@vitest/browser": "^4.1.
|
|
40
|
-
"@vitest/browser-playwright": "^4.1.
|
|
37
|
+
"@types/react": "^19.2.14",
|
|
38
|
+
"@vitejs/plugin-react": "^5.2.0",
|
|
39
|
+
"@vitest/browser": "^4.1.4",
|
|
40
|
+
"@vitest/browser-playwright": "^4.1.4",
|
|
41
41
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
42
42
|
"eslint": "^9.39.1",
|
|
43
|
-
"eslint-plugin-react-hooks": "^7.
|
|
44
|
-
"react": "^19.2.
|
|
43
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
44
|
+
"react": "^19.2.5",
|
|
45
45
|
"typescript": "5.9.3",
|
|
46
46
|
"typescript-eslint": "^8.48.0",
|
|
47
|
-
"vitest": "^4.1.
|
|
48
|
-
"@portabletext/editor": "^
|
|
49
|
-
"racejar": "2.0.
|
|
47
|
+
"vitest": "^4.1.4",
|
|
48
|
+
"@portabletext/editor": "^7.0.1",
|
|
49
|
+
"racejar": "2.0.6"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"react": "^19.2",
|
|
53
|
-
"@portabletext/editor": "^
|
|
53
|
+
"@portabletext/editor": "^7.0.1"
|
|
54
54
|
},
|
|
55
55
|
"engines": {
|
|
56
56
|
"node": ">=20.19 <22 || >=22.12"
|