@doist/typist 10.0.1 → 10.0.2
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/CHANGELOG.md +6 -0
- package/CONTRIBUTING.md +1 -1
- package/dist/components/typist-editor.d.ts +2 -2
- package/dist/components/typist-editor.d.ts.map +1 -1
- package/dist/components/typist-editor.helper.js.map +1 -1
- package/dist/components/typist-editor.js.map +1 -1
- package/dist/extensions/core/extra-editor-commands/commands/create-paragraph-end.js.map +1 -1
- package/dist/extensions/core/extra-editor-commands/commands/extend-word-range.js.map +1 -1
- package/dist/extensions/core/extra-editor-commands/commands/insert-markdown-content-at.js.map +1 -1
- package/dist/extensions/core/extra-editor-commands/commands/insert-markdown-content.js.map +1 -1
- package/dist/extensions/core/extra-editor-commands/extra-editor-commands.js.map +1 -1
- package/dist/extensions/core/view-event-handlers.js.map +1 -1
- package/dist/extensions/plain-text/paste-multiline-text.js.map +1 -1
- package/dist/extensions/plain-text/plain-text-document.js.map +1 -1
- package/dist/extensions/plain-text/plain-text-kit.js +1 -1
- package/dist/extensions/plain-text/plain-text-kit.js.map +1 -1
- package/dist/extensions/plain-text/plain-text-paragraph.js.map +1 -1
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-lists.js +2 -2
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-lists.js.map +1 -1
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-select-wrap.js.map +1 -1
- package/dist/extensions/plain-text/smart-markdown-typing/plugins/smart-url-pasting.js.map +1 -1
- package/dist/extensions/plain-text/smart-markdown-typing/smart-markdown-typing.js.map +1 -1
- package/dist/extensions/rich-text/bold-and-italics.js.map +1 -1
- package/dist/extensions/rich-text/curvenote-codemark.js.map +1 -1
- package/dist/extensions/rich-text/paste-emojis.js.map +1 -1
- package/dist/extensions/rich-text/paste-markdown.js.map +1 -1
- package/dist/extensions/rich-text/rich-text-bullet-list.js +1 -1
- package/dist/extensions/rich-text/rich-text-bullet-list.js.map +1 -1
- package/dist/extensions/rich-text/rich-text-code.js.map +1 -1
- package/dist/extensions/rich-text/rich-text-document.js.map +1 -1
- package/dist/extensions/rich-text/rich-text-heading.js.map +1 -1
- package/dist/extensions/rich-text/rich-text-image.js.map +1 -1
- package/dist/extensions/rich-text/rich-text-kit.js.map +1 -1
- package/dist/extensions/rich-text/rich-text-link.js.map +1 -1
- package/dist/extensions/rich-text/rich-text-ordered-list.js +1 -1
- package/dist/extensions/rich-text/rich-text-ordered-list.js.map +1 -1
- package/dist/extensions/rich-text/rich-text-strikethrough.js.map +1 -1
- package/dist/extensions/shared/copy-markdown-source.js.map +1 -1
- package/dist/extensions/shared/paste-html-table-as-string.js +2 -2
- package/dist/extensions/shared/paste-html-table-as-string.js.map +1 -1
- package/dist/extensions/shared/paste-singleline-text.js.map +1 -1
- package/dist/factories/create-suggestion-extension.d.ts.map +1 -1
- package/dist/factories/create-suggestion-extension.js +4 -4
- package/dist/factories/create-suggestion-extension.js.map +1 -1
- package/dist/helpers/dom.js.map +1 -1
- package/dist/helpers/schema.js.map +1 -1
- package/dist/helpers/serializer.js +10 -7
- package/dist/helpers/serializer.js.map +1 -1
- package/dist/helpers/unified.js.map +1 -1
- package/dist/hooks/use-editor.js.map +1 -1
- package/dist/serializers/html/html.js +1 -1
- package/dist/serializers/html/html.js.map +1 -1
- package/dist/serializers/html/plugins/rehype-code-block.js.map +1 -1
- package/dist/serializers/html/plugins/rehype-image.js.map +1 -1
- package/dist/serializers/html/plugins/rehype-suggestions.js +11 -9
- package/dist/serializers/html/plugins/rehype-suggestions.js.map +1 -1
- package/dist/serializers/html/plugins/rehype-task-list.js.map +1 -1
- package/dist/serializers/html/plugins/remark-autolink-literal.js.map +1 -1
- package/dist/serializers/html/plugins/remark-disable-constructs.js.map +1 -1
- package/dist/serializers/html/plugins/remark-strikethrough.js.map +1 -1
- package/dist/serializers/markdown/markdown.d.ts.map +1 -1
- package/dist/serializers/markdown/markdown.js +5 -0
- package/dist/serializers/markdown/markdown.js.map +1 -1
- package/dist/serializers/markdown/plugins/image.js +1 -1
- package/dist/serializers/markdown/plugins/image.js.map +1 -1
- package/dist/serializers/markdown/plugins/list-item.js +1 -0
- package/dist/serializers/markdown/plugins/list-item.js.map +1 -1
- package/dist/serializers/markdown/plugins/paragraph.js.map +1 -1
- package/dist/serializers/markdown/plugins/strikethrough.js.map +1 -1
- package/dist/serializers/markdown/plugins/suggestion.js.map +1 -1
- package/dist/serializers/markdown/plugins/task-item.js +1 -0
- package/dist/serializers/markdown/plugins/task-item.js.map +1 -1
- package/dist/utilities/can-insert-node-at.d.ts +1 -1
- package/dist/utilities/can-insert-node-at.js +1 -1
- package/dist/utilities/can-insert-node-at.js.map +1 -1
- package/dist/utilities/can-insert-suggestion.d.ts +1 -1
- package/dist/utilities/can-insert-suggestion.js +1 -1
- package/dist/utilities/can-insert-suggestion.js.map +1 -1
- package/package.json +25 -38
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [10.0.2](https://github.com/Doist/typist/compare/v10.0.1...v10.0.2) (2026-05-22)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* **serializers:** include trigger character in suggestion HTML output ([#1341](https://github.com/Doist/typist/issues/1341)) ([82e04a3](https://github.com/Doist/typist/commit/82e04a38667fa6a3e93e670a2a95d3030d459161))
|
|
6
|
+
|
|
1
7
|
## [10.0.1](https://github.com/Doist/typist/compare/v10.0.0...v10.0.1) (2026-04-08)
|
|
2
8
|
|
|
3
9
|
### Bug Fixes
|
package/CONTRIBUTING.md
CHANGED
|
@@ -58,7 +58,7 @@ cd typist
|
|
|
58
58
|
After cloning Typist and installing all dependencies, several commands are at your disposal:
|
|
59
59
|
|
|
60
60
|
- `npm run build`: Builds the `@doist/typist` package for publishing to [npm](https://www.npmjs.com/) and [GitHub Packages](https://github.com/orgs/Doist/packages?repo_name=typist);
|
|
61
|
-
- `npm run check`: Validates code quality with
|
|
61
|
+
- `npm run check`: Validates code quality with Oxlint, formatting with Oxfmt, and types with TypeScript;
|
|
62
62
|
- `npm run clean`: Removes temporary directories used for multiple caches;
|
|
63
63
|
- `npm run storybook:build`: Builds Storybook as a static Web application;
|
|
64
64
|
- `npm run storybook:start`: Starts Storybook Web application (available at http://localhost:6006/);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ViewEventHandlersOptions } from "../extensions/core/view-event-handlers.js";
|
|
2
2
|
import { getAllNodesAttributesByType } from "./typist-editor.helper.js";
|
|
3
|
-
import * as react from "react";
|
|
3
|
+
import * as _$react from "react";
|
|
4
4
|
import { Editor, EditorEvents, Extensions } from "@tiptap/core";
|
|
5
5
|
import { Selection } from "@tiptap/pm/state";
|
|
6
6
|
|
|
@@ -169,7 +169,7 @@ type TypistEditorProps = {
|
|
|
169
169
|
* The `TypistEditor` component represents a plain-text or a rich-text editing control, built on
|
|
170
170
|
* top of the amazing [Tiptap](https://tiptap.dev/) library.
|
|
171
171
|
*/
|
|
172
|
-
declare const TypistEditor: react.ForwardRefExoticComponent<TypistEditorProps & react.RefAttributes<TypistEditorRef>>;
|
|
172
|
+
declare const TypistEditor: _$react.ForwardRefExoticComponent<TypistEditorProps & _$react.RefAttributes<TypistEditorRef>>;
|
|
173
173
|
//#endregion
|
|
174
174
|
export { type BeforeCreateProps, type BlurProps, type CreateProps, type DestroyProps, type FocusProps, type SelectionUpdateProps, type TransacationProps, TypistEditor, type TypistEditorProps, type TypistEditorRef, type UpdateProps };
|
|
175
175
|
//# sourceMappingURL=typist-editor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typist-editor.d.ts","names":[],"sources":["../../src/components/typist-editor.tsx"],"mappings":";;;;;;;;;;AAgBiD;KAM5C,eAAA;;;;EAID,SAAA,QAAiB,MAAA;EAYF;;;EAPf,WAAA;EAAA;;;EAKA,2BAAA,GACI,QAAA,aACC,UAAA,QAAkB,2BAAA;AAAA;;;AAA2B;KAMjD,iBAAA,GAAoB,YAAA;;;;KAKpB,WAAA,GAAc,YAAA;;;;KAKd,WAAA,GAAc,YAAA,aAAyB,IAAA,CAAK,eAAA;AALlB;;;AAAA,KAU1B,oBAAA,GAAuB,YAAA;;;;KAKvB,iBAAA,GAAoB,YAAA;;;;KAKpB,UAAA,GAAa,YAAA;;AAf8C;;KAoB3D,SAAA,GAAY,YAAA;;;AAfuB;KAoBnC,YAAA,GAAe,YAAA;;;;AAfiB;KAqBhC,iBAAA;;;;EAID,SAAA;EAfU;;;EAoBV,SAAA;EAfC;;;EAoBD,OAAA;EApB4B;AAAA;;EAyB5B,gBAAA,GAAmB,SAAA;EAAA;;;EAKnB,QAAA;EAiCmB;;;;;EA1BnB,UAAA,EAAY,UAAA;EAoES;;;EA/DrB,WAAA;EAuFY;;;;;EAhFZ,cAAA,IAAkB,KAAA,EAAO,iBAAA;EAxBzB;;;;;EA+BA,QAAA,IAAY,KAAA,EAAO,WAAA;EAPnB;;;;;EAcA,QAAA,IAAY,KAAA,EAAO,WAAA;EAAnB;;;;;EAOA,iBAAA,IAAqB,KAAA,EAAO,oBAAA;EAO5B;;;;;EAAA,aAAA,IAAiB,KAAA,EAAO,iBAAA;EAcxB;;;;;EAPA,OAAA,IAAW,KAAA,EAAO,UAAA;EAqBlB;;;;;EAdA,MAAA,IAAU,KAAA,EAAO,SAAA;EA4BjB;;;;;EArBA,SAAA,IAAa,KAAA,EAAO,YAAA;EA+BR;;;AAAwB;;EAxBpC,kBAAA,GAAqB,KAAA,CAAM,cAAA;EA+Bb;;;;;EAxBd,YAAA,GAAe,KAAA,CAAM,cAAA;EAwBP;;;;;EAjBd,iBAAA,GAAoB,KAAA,CAAM,cAAA;;;;EAK1B,OAAA,GAAU,wBAAA;;;;EAKV,SAAA,GAAY,wBAAA;AAAA;;;;;cAOV,YAAA,EAAY,
|
|
1
|
+
{"version":3,"file":"typist-editor.d.ts","names":[],"sources":["../../src/components/typist-editor.tsx"],"mappings":";;;;;;;;;;AAgBiD;KAM5C,eAAA;;;;EAID,SAAA,QAAiB,MAAA;EAYF;;;EAPf,WAAA;EAAA;;;EAKA,2BAAA,GACI,QAAA,aACC,UAAA,QAAkB,2BAAA;AAAA;;;AAA2B;KAMjD,iBAAA,GAAoB,YAAA;;;;KAKpB,WAAA,GAAc,YAAA;;;;KAKd,WAAA,GAAc,YAAA,aAAyB,IAAA,CAAK,eAAA;AALlB;;;AAAA,KAU1B,oBAAA,GAAuB,YAAA;;;;KAKvB,iBAAA,GAAoB,YAAA;;;;KAKpB,UAAA,GAAa,YAAA;;AAf8C;;KAoB3D,SAAA,GAAY,YAAA;;;AAfuB;KAoBnC,YAAA,GAAe,YAAA;;;;AAfiB;KAqBhC,iBAAA;;;;EAID,SAAA;EAfU;;;EAoBV,SAAA;EAfC;;;EAoBD,OAAA;EApB4B;AAAA;;EAyB5B,gBAAA,GAAmB,SAAA;EAAA;;;EAKnB,QAAA;EAiCmB;;;;;EA1BnB,UAAA,EAAY,UAAA;EAoES;;;EA/DrB,WAAA;EAuFY;;;;;EAhFZ,cAAA,IAAkB,KAAA,EAAO,iBAAA;EAxBzB;;;;;EA+BA,QAAA,IAAY,KAAA,EAAO,WAAA;EAPnB;;;;;EAcA,QAAA,IAAY,KAAA,EAAO,WAAA;EAAnB;;;;;EAOA,iBAAA,IAAqB,KAAA,EAAO,oBAAA;EAO5B;;;;;EAAA,aAAA,IAAiB,KAAA,EAAO,iBAAA;EAcxB;;;;;EAPA,OAAA,IAAW,KAAA,EAAO,UAAA;EAqBlB;;;;;EAdA,MAAA,IAAU,KAAA,EAAO,SAAA;EA4BjB;;;;;EArBA,SAAA,IAAa,KAAA,EAAO,YAAA;EA+BR;;;AAAwB;;EAxBpC,kBAAA,GAAqB,KAAA,CAAM,cAAA;EA+Bb;;;;;EAxBd,YAAA,GAAe,KAAA,CAAM,cAAA;EAwBP;;;;;EAjBd,iBAAA,GAAoB,KAAA,CAAM,cAAA;;;;EAK1B,OAAA,GAAU,wBAAA;;;;EAKV,SAAA,GAAY,wBAAA;AAAA;;;;;cAOV,YAAA,EAAY,OAAA,CAAA,yBAAA,CAAA,iBAAA,GAAA,OAAA,CAAA,aAAA,CAAA,eAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typist-editor.helper.js","names":[],"sources":["../../src/components/typist-editor.helper.ts"],"sourcesContent":["import { Selection, TextSelection } from '@tiptap/pm/state'\nimport { clamp } from 'lodash-es'\n\nimport type { Node as ProseMirrorNode } from '@tiptap/pm/model'\n\n/**\n * Given a ProseMirror document, and a selection, resolves that selection within the bounds of the\n * document size. This works similarly to the official `autoFocus` implementation.\n */\nfunction resolveContentSelection(doc: ProseMirrorNode, selection: Selection): Selection {\n const minPos = Selection.atStart(doc).from\n const maxPos = Selection.atEnd(doc).to\n\n return TextSelection.create(\n doc,\n clamp(selection.anchor, minPos, maxPos),\n clamp(selection.head, minPos, maxPos),\n )\n}\n\n/**\n * The return type for the node attributes, an object mapping attribute names to values.\n */\ntype NodeAttributes = {\n [key: string]: unknown\n}\n\n/**\n * Given a ProseMirror document and a node type, returns the attributes of the given node type for\n * all the nodes in the document. This is based on the official implementation for the\n * `findChildren` helper function.\n */\nfunction getAllNodesAttributesByType(\n doc: ProseMirrorNode,\n nodeType: string,\n): Array<NodeAttributes> {\n const result: Array<NodeAttributes> = []\n\n doc.descendants((node) => {\n if (node.type.name === nodeType) {\n result.push(node.attrs)\n }\n })\n\n return result\n}\n\nexport { getAllNodesAttributesByType, resolveContentSelection }\n\nexport type { NodeAttributes }\n"],"mappings":";;;;;;;AASA,SAAS,wBAAwB,KAAsB,WAAiC;CACpF,MAAM,SAAS,UAAU,QAAQ,IAAI,CAAC;CACtC,MAAM,SAAS,UAAU,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"typist-editor.helper.js","names":[],"sources":["../../src/components/typist-editor.helper.ts"],"sourcesContent":["import { Selection, TextSelection } from '@tiptap/pm/state'\nimport { clamp } from 'lodash-es'\n\nimport type { Node as ProseMirrorNode } from '@tiptap/pm/model'\n\n/**\n * Given a ProseMirror document, and a selection, resolves that selection within the bounds of the\n * document size. This works similarly to the official `autoFocus` implementation.\n */\nfunction resolveContentSelection(doc: ProseMirrorNode, selection: Selection): Selection {\n const minPos = Selection.atStart(doc).from\n const maxPos = Selection.atEnd(doc).to\n\n return TextSelection.create(\n doc,\n clamp(selection.anchor, minPos, maxPos),\n clamp(selection.head, minPos, maxPos),\n )\n}\n\n/**\n * The return type for the node attributes, an object mapping attribute names to values.\n */\ntype NodeAttributes = {\n [key: string]: unknown\n}\n\n/**\n * Given a ProseMirror document and a node type, returns the attributes of the given node type for\n * all the nodes in the document. This is based on the official implementation for the\n * `findChildren` helper function.\n */\nfunction getAllNodesAttributesByType(\n doc: ProseMirrorNode,\n nodeType: string,\n): Array<NodeAttributes> {\n const result: Array<NodeAttributes> = []\n\n doc.descendants((node) => {\n if (node.type.name === nodeType) {\n result.push(node.attrs)\n }\n })\n\n return result\n}\n\nexport { getAllNodesAttributesByType, resolveContentSelection }\n\nexport type { NodeAttributes }\n"],"mappings":";;;;;;;AASA,SAAS,wBAAwB,KAAsB,WAAiC;CACpF,MAAM,SAAS,UAAU,QAAQ,IAAI,CAAC;CACtC,MAAM,SAAS,UAAU,MAAM,IAAI,CAAC;CAEpC,OAAO,cAAc,OACjB,KACA,MAAM,UAAU,QAAQ,QAAQ,OAAO,EACvC,MAAM,UAAU,MAAM,QAAQ,OAAO,CACxC;;;;;;;AAeL,SAAS,4BACL,KACA,UACqB;CACrB,MAAM,SAAgC,EAAE;CAExC,IAAI,aAAa,SAAS;EACtB,IAAI,KAAK,KAAK,SAAS,UACnB,OAAO,KAAK,KAAK,MAAM;GAE7B;CAEF,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typist-editor.js","names":[],"sources":["../../src/components/typist-editor.tsx"],"sourcesContent":["import { forwardRef, useCallback, useImperativeHandle, useMemo } from 'react'\n\nimport { getSchema } from '@tiptap/core'\nimport { Placeholder } from '@tiptap/extension-placeholder'\nimport { EditorContent } from '@tiptap/react'\n\nimport { ExtraEditorCommands } from '../extensions/core/extra-editor-commands/extra-editor-commands'\nimport { ViewEventHandlers, ViewEventHandlersOptions } from '../extensions/core/view-event-handlers'\nimport { isMultilineDocument, isPlainTextDocument } from '../helpers/schema'\nimport { useEditor } from '../hooks/use-editor'\nimport { getHTMLSerializerInstance } from '../serializers/html/html'\nimport { getMarkdownSerializerInstance } from '../serializers/markdown/markdown'\n\nimport { getAllNodesAttributesByType, resolveContentSelection } from './typist-editor.helper'\n\nimport type { Editor as CoreEditor, EditorEvents, Extensions } from '@tiptap/core'\nimport type { Selection } from '@tiptap/pm/state'\n\n/**\n * The forwarded ref that describes the helper methods that the `TypistEditor` parent component\n * will have access to.\n */\ntype TypistEditorRef = {\n /**\n * Returns the `Editor` instance associated to the `TypistEditor` component.\n */\n getEditor: () => CoreEditor\n\n /**\n * Returns the current editor document output as Markdown.\n */\n getMarkdown: () => string\n\n /**\n * Returns the attributes of a given node type for all the nodes in the editor document.\n */\n getAllNodesAttributesByType: (\n nodeType: string,\n ) => ReturnType<typeof getAllNodesAttributesByType>\n}\n\n/**\n * The properties that describe the `beforeCreate` editor event.\n */\ntype BeforeCreateProps = EditorEvents['beforeCreate']\n\n/**\n * The properties that describe the `create` editor event.\n */\ntype CreateProps = EditorEvents['create']\n\n/**\n * The properties that describe the `update` editor event.\n */\ntype UpdateProps = EditorEvents['update'] & Pick<TypistEditorRef, 'getMarkdown'>\n\n/**\n * The properties that describe the `selectionUpdate` editor event.\n */\ntype SelectionUpdateProps = EditorEvents['selectionUpdate']\n\n/**\n * The properties that describe the `transaction` editor event.\n */\ntype TransacationProps = EditorEvents['transaction']\n\n/**\n * The properties that describe the `focus` editor event.\n */\ntype FocusProps = EditorEvents['focus']\n\n/**\n * The properties that describe the `blur` editor event.\n */\ntype BlurProps = EditorEvents['blur']\n\n/**\n * The properties that describe the `destroy` editor event.\n */\ntype DestroyProps = EditorEvents['destroy']\n\n/**\n * The properties available to represent an instance of the `TypistEditor` component, including\n * the supported WAI-ARIA 1.1 attributes.\n */\ntype TypistEditorProps = {\n /**\n * Auto focus the editor to the end of the document on initialization.\n */\n autoFocus?: boolean\n\n /**\n * The CSS class for the container surrounding the editor DOM element.\n */\n className?: string\n\n /**\n * The initial Markdown content for the editor.\n */\n content?: string\n\n /**\n * The initial content selection (only applied if `autoFocus` is `true`).\n */\n contentSelection?: Selection\n\n /**\n * Determines if users can write into the editor.\n */\n editable?: boolean\n\n /**\n * The list of required extensions to initialize the editor.\n *\n * You may consider wrapping this prop with `useMemo` to prevent unnecessary re-renders.\n */\n extensions: Extensions\n\n /**\n * A short hint that gives users an idea what can be entered in the editor.\n */\n placeholder?: string\n\n /**\n * The event handler that is fired before the editor view is created.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onBeforeCreate?: (props: BeforeCreateProps) => void\n\n /**\n * The event handler that is fired when the editor view is ready.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onCreate?: (props: CreateProps) => void\n\n /**\n * The event handler that is fired when the editor content has changed.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onUpdate?: (props: UpdateProps) => void\n\n /**\n * The event handler that is fired when the editor selection has changed.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onSelectionUpdate?: (props: SelectionUpdateProps) => void\n\n /**\n * The event handler that is fired when the editor state has changed.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onTransaction?: (props: TransacationProps) => void\n\n /**\n * The event handler that is fired when the editor view gains focus.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onFocus?: (props: FocusProps) => void\n\n /**\n * The event handler that is fired when the editor view loses focus.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onBlur?: (props: BlurProps) => void\n\n /**\n * The event handler that is fired when the editor view is being destroyed.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onDestroy?: (props: DestroyProps) => void\n\n /**\n * Identifies the element (or elements) that describes the object.\n *\n * @see aria-labelledby\n */\n 'aria-describedby'?: React.AriaAttributes['aria-describedby']\n\n /**\n * Defines a string value that labels the current element.\n *\n * @see aria-labelledby.\n */\n 'aria-label'?: React.AriaAttributes['aria-label']\n\n /**\n * Identifies the element (or elements) that labels the current element.\n *\n * @see aria-describedby.\n */\n 'aria-labelledby'?: React.AriaAttributes['aria-labelledby']\n\n /**\n * The event handler that processes `click` events in the editor.\n */\n onClick?: ViewEventHandlersOptions['onClick']\n\n /**\n * The event handler that processes `keydown` events in the editor.\n */\n onKeyDown?: ViewEventHandlersOptions['onKeyDown']\n}\n\n/**\n * The `TypistEditor` component represents a plain-text or a rich-text editing control, built on\n * top of the amazing [Tiptap](https://tiptap.dev/) library.\n */\nconst TypistEditor = forwardRef<TypistEditorRef, TypistEditorProps>(function TypistEditor(\n {\n autoFocus,\n className,\n content = '',\n contentSelection,\n editable = true,\n extensions,\n placeholder,\n onBeforeCreate,\n onCreate,\n onUpdate,\n onSelectionUpdate,\n onTransaction,\n onFocus,\n onBlur,\n onDestroy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n onClick,\n onKeyDown,\n },\n ref,\n) {\n const allExtensions = useMemo(\n function initializeExtensions() {\n return [\n ...(placeholder\n ? [\n Placeholder.configure({\n placeholder,\n }),\n ]\n : []),\n ExtraEditorCommands,\n ViewEventHandlers.configure({\n onClick,\n onKeyDown,\n }),\n // Always register external extensions at the end so they get a higher priority and\n // are loaded earlier (necessary to override behaviors from built-in extensions)\n ...extensions,\n ]\n },\n [extensions, onClick, onKeyDown, placeholder],\n )\n\n const schema = useMemo(\n function generateProseMirrorSchema() {\n return getSchema(allExtensions)\n },\n [allExtensions],\n )\n\n const htmlSerializer = useMemo(\n function initializeHTMLSerializer() {\n return getHTMLSerializerInstance(schema)\n },\n [schema],\n )\n\n const markdownSerializer = useMemo(\n function initializeMarkdownSerializer() {\n return getMarkdownSerializerInstance(schema)\n },\n [schema],\n )\n\n const htmlContent = useMemo(\n function generateHTMLContent() {\n return htmlSerializer.serialize(content)\n },\n [content, htmlSerializer],\n )\n\n const ariaAttributes = useMemo(\n function initializeAriaAttributes() {\n return {\n 'aria-readonly': String(!editable),\n 'aria-multiline': String(isMultilineDocument(schema)),\n ...(ariaDescribedBy ? { 'aria-describedby': ariaDescribedBy } : {}),\n ...(ariaLabel ? { 'aria-label': ariaLabel } : {}),\n ...(ariaLabelledBy ? { 'aria-labelledby': ariaLabelledBy } : {}),\n }\n },\n [ariaDescribedBy, ariaLabel, ariaLabelledBy, editable, schema],\n )\n\n const handleCreate = useCallback(\n function handleCreate(props: CreateProps) {\n const { view } = props.editor\n\n // Apply a selection to the document if one was given and `autoFocus` is `true`\n if (autoFocus && contentSelection) {\n view.dispatch(\n view.state.tr\n .setSelection(resolveContentSelection(view.state.doc, contentSelection))\n .scrollIntoView(),\n )\n }\n\n // Invoke the user `onCreate` handle after all internal initializations\n onCreate?.(props)\n },\n [autoFocus, contentSelection, onCreate],\n )\n\n const editor = useEditor(\n {\n autofocus: autoFocus ? 'end' : false,\n content: htmlContent,\n editable,\n editorProps: {\n attributes: {\n 'data-typist-editor': 'true',\n ...(isPlainTextDocument(schema)\n ? { 'data-plain-text': 'true' }\n : { 'data-rich-text': 'true' }),\n role: 'textbox',\n ...ariaAttributes,\n },\n },\n extensions: allExtensions,\n parseOptions: {\n preserveWhitespace: isPlainTextDocument(schema),\n },\n ...(onBeforeCreate ? { onBeforeCreate } : {}),\n onCreate: handleCreate,\n ...(onUpdate\n ? {\n onUpdate(props) {\n onUpdate({\n ...props,\n getMarkdown() {\n return markdownSerializer.serialize(props.editor.getHTML())\n },\n })\n },\n }\n : {}),\n ...(onSelectionUpdate ? { onSelectionUpdate } : {}),\n ...(onTransaction ? { onTransaction } : {}),\n ...(onFocus ? { onFocus } : {}),\n ...(onBlur ? { onBlur } : {}),\n ...(onDestroy ? { onDestroy } : {}),\n },\n [\n allExtensions,\n ariaAttributes,\n autoFocus,\n editable,\n handleCreate,\n htmlContent,\n markdownSerializer,\n onBeforeCreate,\n onBlur,\n onDestroy,\n onFocus,\n onSelectionUpdate,\n onTransaction,\n onUpdate,\n schema,\n ],\n )\n\n useImperativeHandle(\n ref,\n function exposeHelperFunctionsToParent() {\n return {\n getEditor() {\n return editor\n },\n getMarkdown() {\n return markdownSerializer.serialize(editor.getHTML())\n },\n getAllNodesAttributesByType(nodeType) {\n return getAllNodesAttributesByType(editor.state.doc, nodeType)\n },\n }\n },\n [editor, markdownSerializer],\n )\n\n return <EditorContent className={className} editor={editor} />\n})\n\nexport { TypistEditor }\n\nexport type {\n BeforeCreateProps,\n BlurProps,\n CreateProps,\n DestroyProps,\n FocusProps,\n SelectionUpdateProps,\n TransacationProps,\n TypistEditorProps,\n TypistEditorRef,\n UpdateProps,\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAuNA,MAAM,eAAe,WAA+C,SAAS,aACzE,EACI,WACA,WACA,UAAU,IACV,kBACA,WAAW,MACX,YACA,aACA,gBACA,UACA,UACA,mBACA,eACA,SACA,QACA,WACA,oBAAoB,iBACpB,cAAc,WACd,mBAAmB,gBACnB,SACA,aAEJ,KACF;CACE,MAAM,gBAAgB,QAClB,SAAS,uBAAuB;AAC5B,SAAO;GACH,GAAI,cACE,CACI,YAAY,UAAU,EAClB,aACH,CAAC,CACL,GACD,EAAE;GACR;GACA,kBAAkB,UAAU;IACxB;IACA;IACH,CAAC;GAGF,GAAG;GACN;IAEL;EAAC;EAAY;EAAS;EAAW;EAAY,CAChD;CAED,MAAM,SAAS,QACX,SAAS,4BAA4B;AACjC,SAAO,UAAU,cAAc;IAEnC,CAAC,cAAc,CAClB;CAED,MAAM,iBAAiB,QACnB,SAAS,2BAA2B;AAChC,SAAO,0BAA0B,OAAO;IAE5C,CAAC,OAAO,CACX;CAED,MAAM,qBAAqB,QACvB,SAAS,+BAA+B;AACpC,SAAO,8BAA8B,OAAO;IAEhD,CAAC,OAAO,CACX;CAED,MAAM,cAAc,QAChB,SAAS,sBAAsB;AAC3B,SAAO,eAAe,UAAU,QAAQ;IAE5C,CAAC,SAAS,eAAe,CAC5B;CAED,MAAM,iBAAiB,QACnB,SAAS,2BAA2B;AAChC,SAAO;GACH,iBAAiB,OAAO,CAAC,SAAS;GAClC,kBAAkB,OAAO,oBAAoB,OAAO,CAAC;GACrD,GAAI,kBAAkB,EAAE,oBAAoB,iBAAiB,GAAG,EAAE;GAClE,GAAI,YAAY,EAAE,cAAc,WAAW,GAAG,EAAE;GAChD,GAAI,iBAAiB,EAAE,mBAAmB,gBAAgB,GAAG,EAAE;GAClE;IAEL;EAAC;EAAiB;EAAW;EAAgB;EAAU;EAAO,CACjE;CAED,MAAM,eAAe,YACjB,SAAS,aAAa,OAAoB;EACtC,MAAM,EAAE,SAAS,MAAM;AAGvB,MAAI,aAAa,iBACb,MAAK,SACD,KAAK,MAAM,GACN,aAAa,wBAAwB,KAAK,MAAM,KAAK,iBAAiB,CAAC,CACvE,gBAAgB,CACxB;AAIL,aAAW,MAAM;IAErB;EAAC;EAAW;EAAkB;EAAS,CAC1C;CAED,MAAM,SAAS,UACX;EACI,WAAW,YAAY,QAAQ;EAC/B,SAAS;EACT;EACA,aAAa,EACT,YAAY;GACR,sBAAsB;GACtB,GAAI,oBAAoB,OAAO,GACzB,EAAE,mBAAmB,QAAQ,GAC7B,EAAE,kBAAkB,QAAQ;GAClC,MAAM;GACN,GAAG;GACN,EACJ;EACD,YAAY;EACZ,cAAc,EACV,oBAAoB,oBAAoB,OAAO,EAClD;EACD,GAAI,iBAAiB,EAAE,gBAAgB,GAAG,EAAE;EAC5C,UAAU;EACV,GAAI,WACE,EACI,SAAS,OAAO;AACZ,YAAS;IACL,GAAG;IACH,cAAc;AACV,YAAO,mBAAmB,UAAU,MAAM,OAAO,SAAS,CAAC;;IAElE,CAAC;KAET,GACD,EAAE;EACR,GAAI,oBAAoB,EAAE,mBAAmB,GAAG,EAAE;EAClD,GAAI,gBAAgB,EAAE,eAAe,GAAG,EAAE;EAC1C,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;EAC9B,GAAI,SAAS,EAAE,QAAQ,GAAG,EAAE;EAC5B,GAAI,YAAY,EAAE,WAAW,GAAG,EAAE;EACrC,EACD;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACH,CACJ;AAED,qBACI,KACA,SAAS,gCAAgC;AACrC,SAAO;GACH,YAAY;AACR,WAAO;;GAEX,cAAc;AACV,WAAO,mBAAmB,UAAU,OAAO,SAAS,CAAC;;GAEzD,4BAA4B,UAAU;AAClC,WAAO,4BAA4B,OAAO,MAAM,KAAK,SAAS;;GAErE;IAEL,CAAC,QAAQ,mBAAmB,CAC/B;AAED,QAAO,oBAAC,eAAD;EAA0B;EAAmB;EAAU,CAAA;EAChE"}
|
|
1
|
+
{"version":3,"file":"typist-editor.js","names":[],"sources":["../../src/components/typist-editor.tsx"],"sourcesContent":["import { forwardRef, useCallback, useImperativeHandle, useMemo } from 'react'\n\nimport { getSchema } from '@tiptap/core'\nimport { Placeholder } from '@tiptap/extension-placeholder'\nimport { EditorContent } from '@tiptap/react'\n\nimport { ExtraEditorCommands } from '../extensions/core/extra-editor-commands/extra-editor-commands'\nimport { ViewEventHandlers, ViewEventHandlersOptions } from '../extensions/core/view-event-handlers'\nimport { isMultilineDocument, isPlainTextDocument } from '../helpers/schema'\nimport { useEditor } from '../hooks/use-editor'\nimport { getHTMLSerializerInstance } from '../serializers/html/html'\nimport { getMarkdownSerializerInstance } from '../serializers/markdown/markdown'\n\nimport { getAllNodesAttributesByType, resolveContentSelection } from './typist-editor.helper'\n\nimport type { Editor as CoreEditor, EditorEvents, Extensions } from '@tiptap/core'\nimport type { Selection } from '@tiptap/pm/state'\n\n/**\n * The forwarded ref that describes the helper methods that the `TypistEditor` parent component\n * will have access to.\n */\ntype TypistEditorRef = {\n /**\n * Returns the `Editor` instance associated to the `TypistEditor` component.\n */\n getEditor: () => CoreEditor\n\n /**\n * Returns the current editor document output as Markdown.\n */\n getMarkdown: () => string\n\n /**\n * Returns the attributes of a given node type for all the nodes in the editor document.\n */\n getAllNodesAttributesByType: (\n nodeType: string,\n ) => ReturnType<typeof getAllNodesAttributesByType>\n}\n\n/**\n * The properties that describe the `beforeCreate` editor event.\n */\ntype BeforeCreateProps = EditorEvents['beforeCreate']\n\n/**\n * The properties that describe the `create` editor event.\n */\ntype CreateProps = EditorEvents['create']\n\n/**\n * The properties that describe the `update` editor event.\n */\ntype UpdateProps = EditorEvents['update'] & Pick<TypistEditorRef, 'getMarkdown'>\n\n/**\n * The properties that describe the `selectionUpdate` editor event.\n */\ntype SelectionUpdateProps = EditorEvents['selectionUpdate']\n\n/**\n * The properties that describe the `transaction` editor event.\n */\ntype TransacationProps = EditorEvents['transaction']\n\n/**\n * The properties that describe the `focus` editor event.\n */\ntype FocusProps = EditorEvents['focus']\n\n/**\n * The properties that describe the `blur` editor event.\n */\ntype BlurProps = EditorEvents['blur']\n\n/**\n * The properties that describe the `destroy` editor event.\n */\ntype DestroyProps = EditorEvents['destroy']\n\n/**\n * The properties available to represent an instance of the `TypistEditor` component, including\n * the supported WAI-ARIA 1.1 attributes.\n */\ntype TypistEditorProps = {\n /**\n * Auto focus the editor to the end of the document on initialization.\n */\n autoFocus?: boolean\n\n /**\n * The CSS class for the container surrounding the editor DOM element.\n */\n className?: string\n\n /**\n * The initial Markdown content for the editor.\n */\n content?: string\n\n /**\n * The initial content selection (only applied if `autoFocus` is `true`).\n */\n contentSelection?: Selection\n\n /**\n * Determines if users can write into the editor.\n */\n editable?: boolean\n\n /**\n * The list of required extensions to initialize the editor.\n *\n * You may consider wrapping this prop with `useMemo` to prevent unnecessary re-renders.\n */\n extensions: Extensions\n\n /**\n * A short hint that gives users an idea what can be entered in the editor.\n */\n placeholder?: string\n\n /**\n * The event handler that is fired before the editor view is created.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onBeforeCreate?: (props: BeforeCreateProps) => void\n\n /**\n * The event handler that is fired when the editor view is ready.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onCreate?: (props: CreateProps) => void\n\n /**\n * The event handler that is fired when the editor content has changed.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onUpdate?: (props: UpdateProps) => void\n\n /**\n * The event handler that is fired when the editor selection has changed.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onSelectionUpdate?: (props: SelectionUpdateProps) => void\n\n /**\n * The event handler that is fired when the editor state has changed.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onTransaction?: (props: TransacationProps) => void\n\n /**\n * The event handler that is fired when the editor view gains focus.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onFocus?: (props: FocusProps) => void\n\n /**\n * The event handler that is fired when the editor view loses focus.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onBlur?: (props: BlurProps) => void\n\n /**\n * The event handler that is fired when the editor view is being destroyed.\n *\n * You may consider wrapping this prop with `useCallback` to prevent unnecessary re-renders.\n */\n onDestroy?: (props: DestroyProps) => void\n\n /**\n * Identifies the element (or elements) that describes the object.\n *\n * @see aria-labelledby\n */\n 'aria-describedby'?: React.AriaAttributes['aria-describedby']\n\n /**\n * Defines a string value that labels the current element.\n *\n * @see aria-labelledby.\n */\n 'aria-label'?: React.AriaAttributes['aria-label']\n\n /**\n * Identifies the element (or elements) that labels the current element.\n *\n * @see aria-describedby.\n */\n 'aria-labelledby'?: React.AriaAttributes['aria-labelledby']\n\n /**\n * The event handler that processes `click` events in the editor.\n */\n onClick?: ViewEventHandlersOptions['onClick']\n\n /**\n * The event handler that processes `keydown` events in the editor.\n */\n onKeyDown?: ViewEventHandlersOptions['onKeyDown']\n}\n\n/**\n * The `TypistEditor` component represents a plain-text or a rich-text editing control, built on\n * top of the amazing [Tiptap](https://tiptap.dev/) library.\n */\nconst TypistEditor = forwardRef<TypistEditorRef, TypistEditorProps>(function TypistEditor(\n {\n autoFocus,\n className,\n content = '',\n contentSelection,\n editable = true,\n extensions,\n placeholder,\n onBeforeCreate,\n onCreate,\n onUpdate,\n onSelectionUpdate,\n onTransaction,\n onFocus,\n onBlur,\n onDestroy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n onClick,\n onKeyDown,\n },\n ref,\n) {\n const allExtensions = useMemo(\n function initializeExtensions() {\n return [\n ...(placeholder\n ? [\n Placeholder.configure({\n placeholder,\n }),\n ]\n : []),\n ExtraEditorCommands,\n ViewEventHandlers.configure({\n onClick,\n onKeyDown,\n }),\n // Always register external extensions at the end so they get a higher priority and\n // are loaded earlier (necessary to override behaviors from built-in extensions)\n ...extensions,\n ]\n },\n [extensions, onClick, onKeyDown, placeholder],\n )\n\n const schema = useMemo(\n function generateProseMirrorSchema() {\n return getSchema(allExtensions)\n },\n [allExtensions],\n )\n\n const htmlSerializer = useMemo(\n function initializeHTMLSerializer() {\n return getHTMLSerializerInstance(schema)\n },\n [schema],\n )\n\n const markdownSerializer = useMemo(\n function initializeMarkdownSerializer() {\n return getMarkdownSerializerInstance(schema)\n },\n [schema],\n )\n\n const htmlContent = useMemo(\n function generateHTMLContent() {\n return htmlSerializer.serialize(content)\n },\n [content, htmlSerializer],\n )\n\n const ariaAttributes = useMemo(\n function initializeAriaAttributes() {\n return {\n 'aria-readonly': String(!editable),\n 'aria-multiline': String(isMultilineDocument(schema)),\n ...(ariaDescribedBy ? { 'aria-describedby': ariaDescribedBy } : {}),\n ...(ariaLabel ? { 'aria-label': ariaLabel } : {}),\n ...(ariaLabelledBy ? { 'aria-labelledby': ariaLabelledBy } : {}),\n }\n },\n [ariaDescribedBy, ariaLabel, ariaLabelledBy, editable, schema],\n )\n\n const handleCreate = useCallback(\n function handleCreate(props: CreateProps) {\n const { view } = props.editor\n\n // Apply a selection to the document if one was given and `autoFocus` is `true`\n if (autoFocus && contentSelection) {\n view.dispatch(\n view.state.tr\n .setSelection(resolveContentSelection(view.state.doc, contentSelection))\n .scrollIntoView(),\n )\n }\n\n // Invoke the user `onCreate` handle after all internal initializations\n onCreate?.(props)\n },\n [autoFocus, contentSelection, onCreate],\n )\n\n const editor = useEditor(\n {\n autofocus: autoFocus ? 'end' : false,\n content: htmlContent,\n editable,\n editorProps: {\n attributes: {\n 'data-typist-editor': 'true',\n ...(isPlainTextDocument(schema)\n ? { 'data-plain-text': 'true' }\n : { 'data-rich-text': 'true' }),\n role: 'textbox',\n ...ariaAttributes,\n },\n },\n extensions: allExtensions,\n parseOptions: {\n preserveWhitespace: isPlainTextDocument(schema),\n },\n ...(onBeforeCreate ? { onBeforeCreate } : {}),\n onCreate: handleCreate,\n ...(onUpdate\n ? {\n onUpdate(props) {\n onUpdate({\n ...props,\n getMarkdown() {\n return markdownSerializer.serialize(props.editor.getHTML())\n },\n })\n },\n }\n : {}),\n ...(onSelectionUpdate ? { onSelectionUpdate } : {}),\n ...(onTransaction ? { onTransaction } : {}),\n ...(onFocus ? { onFocus } : {}),\n ...(onBlur ? { onBlur } : {}),\n ...(onDestroy ? { onDestroy } : {}),\n },\n [\n allExtensions,\n ariaAttributes,\n autoFocus,\n editable,\n handleCreate,\n htmlContent,\n markdownSerializer,\n onBeforeCreate,\n onBlur,\n onDestroy,\n onFocus,\n onSelectionUpdate,\n onTransaction,\n onUpdate,\n schema,\n ],\n )\n\n useImperativeHandle(\n ref,\n function exposeHelperFunctionsToParent() {\n return {\n getEditor() {\n return editor\n },\n getMarkdown() {\n return markdownSerializer.serialize(editor.getHTML())\n },\n getAllNodesAttributesByType(nodeType) {\n return getAllNodesAttributesByType(editor.state.doc, nodeType)\n },\n }\n },\n [editor, markdownSerializer],\n )\n\n return <EditorContent className={className} editor={editor} />\n})\n\nexport { TypistEditor }\n\nexport type {\n BeforeCreateProps,\n BlurProps,\n CreateProps,\n DestroyProps,\n FocusProps,\n SelectionUpdateProps,\n TransacationProps,\n TypistEditorProps,\n TypistEditorRef,\n UpdateProps,\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAuNA,MAAM,eAAe,WAA+C,SAAS,aACzE,EACI,WACA,WACA,UAAU,IACV,kBACA,WAAW,MACX,YACA,aACA,gBACA,UACA,UACA,mBACA,eACA,SACA,QACA,WACA,oBAAoB,iBACpB,cAAc,WACd,mBAAmB,gBACnB,SACA,aAEJ,KACF;CACE,MAAM,gBAAgB,QAClB,SAAS,uBAAuB;EAC5B,OAAO;GACH,GAAI,cACE,CACI,YAAY,UAAU,EAClB,aACH,CAAC,CACL,GACD,EAAE;GACR;GACA,kBAAkB,UAAU;IACxB;IACA;IACH,CAAC;GAGF,GAAG;GACN;IAEL;EAAC;EAAY;EAAS;EAAW;EAAY,CAChD;CAED,MAAM,SAAS,QACX,SAAS,4BAA4B;EACjC,OAAO,UAAU,cAAc;IAEnC,CAAC,cAAc,CAClB;CAED,MAAM,iBAAiB,QACnB,SAAS,2BAA2B;EAChC,OAAO,0BAA0B,OAAO;IAE5C,CAAC,OAAO,CACX;CAED,MAAM,qBAAqB,QACvB,SAAS,+BAA+B;EACpC,OAAO,8BAA8B,OAAO;IAEhD,CAAC,OAAO,CACX;CAED,MAAM,cAAc,QAChB,SAAS,sBAAsB;EAC3B,OAAO,eAAe,UAAU,QAAQ;IAE5C,CAAC,SAAS,eAAe,CAC5B;CAED,MAAM,iBAAiB,QACnB,SAAS,2BAA2B;EAChC,OAAO;GACH,iBAAiB,OAAO,CAAC,SAAS;GAClC,kBAAkB,OAAO,oBAAoB,OAAO,CAAC;GACrD,GAAI,kBAAkB,EAAE,oBAAoB,iBAAiB,GAAG,EAAE;GAClE,GAAI,YAAY,EAAE,cAAc,WAAW,GAAG,EAAE;GAChD,GAAI,iBAAiB,EAAE,mBAAmB,gBAAgB,GAAG,EAAE;GAClE;IAEL;EAAC;EAAiB;EAAW;EAAgB;EAAU;EAAO,CACjE;CAED,MAAM,eAAe,YACjB,SAAS,aAAa,OAAoB;EACtC,MAAM,EAAE,SAAS,MAAM;EAGvB,IAAI,aAAa,kBACb,KAAK,SACD,KAAK,MAAM,GACN,aAAa,wBAAwB,KAAK,MAAM,KAAK,iBAAiB,CAAC,CACvE,gBAAgB,CACxB;EAIL,WAAW,MAAM;IAErB;EAAC;EAAW;EAAkB;EAAS,CAC1C;CAED,MAAM,SAAS,UACX;EACI,WAAW,YAAY,QAAQ;EAC/B,SAAS;EACT;EACA,aAAa,EACT,YAAY;GACR,sBAAsB;GACtB,GAAI,oBAAoB,OAAO,GACzB,EAAE,mBAAmB,QAAQ,GAC7B,EAAE,kBAAkB,QAAQ;GAClC,MAAM;GACN,GAAG;GACN,EACJ;EACD,YAAY;EACZ,cAAc,EACV,oBAAoB,oBAAoB,OAAO,EAClD;EACD,GAAI,iBAAiB,EAAE,gBAAgB,GAAG,EAAE;EAC5C,UAAU;EACV,GAAI,WACE,EACI,SAAS,OAAO;GACZ,SAAS;IACL,GAAG;IACH,cAAc;KACV,OAAO,mBAAmB,UAAU,MAAM,OAAO,SAAS,CAAC;;IAElE,CAAC;KAET,GACD,EAAE;EACR,GAAI,oBAAoB,EAAE,mBAAmB,GAAG,EAAE;EAClD,GAAI,gBAAgB,EAAE,eAAe,GAAG,EAAE;EAC1C,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;EAC9B,GAAI,SAAS,EAAE,QAAQ,GAAG,EAAE;EAC5B,GAAI,YAAY,EAAE,WAAW,GAAG,EAAE;EACrC,EACD;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACH,CACJ;CAED,oBACI,KACA,SAAS,gCAAgC;EACrC,OAAO;GACH,YAAY;IACR,OAAO;;GAEX,cAAc;IACV,OAAO,mBAAmB,UAAU,OAAO,SAAS,CAAC;;GAEzD,4BAA4B,UAAU;IAClC,OAAO,4BAA4B,OAAO,MAAM,KAAK,SAAS;;GAErE;IAEL,CAAC,QAAQ,mBAAmB,CAC/B;CAED,OAAO,oBAAC,eAAD;EAA0B;EAAmB;EAAU,CAAA;EAChE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-paragraph-end.js","names":[],"sources":["../../../../../src/extensions/core/extra-editor-commands/commands/create-paragraph-end.ts"],"sourcesContent":["import { RawCommands } from '@tiptap/core'\nimport { TextSelection } from '@tiptap/pm/state'\n\n/**\n * Augment the official `@tiptap/core` module with extra commands so that the compiler knows about\n * them. For this to work externally, a wildcard export needs to be added to the root `index.ts`.\n */\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n createParagraphEnd: {\n /**\n * Creates an empty paragraph at the end of the document.\n */\n createParagraphEnd: () => ReturnType\n }\n }\n}\n\n/**\n * Creates an empty paragraph at the end of the document.\n *\n * last node before creating the paragraph, using the build int fn\n */\nfunction createParagraphEnd(): ReturnType<RawCommands['createParagraphEnd']> {\n return ({ state, tr, chain, dispatch }) => {\n // Check if the transaction should be dispatched\n // ref: https://tiptap.dev/api/commands#dry-run-for-commands\n if (dispatch) {\n return chain()\n .command(() => {\n tr.setSelection(\n TextSelection.create(\n tr.doc,\n state.doc.content.size,\n state.doc.content.size,\n ),\n )\n\n return true\n })\n .createParagraphNear()\n .run()\n }\n\n return true\n }\n}\n\nexport { createParagraphEnd }\n"],"mappings":";;;;;;;AAuBA,SAAS,qBAAoE;
|
|
1
|
+
{"version":3,"file":"create-paragraph-end.js","names":[],"sources":["../../../../../src/extensions/core/extra-editor-commands/commands/create-paragraph-end.ts"],"sourcesContent":["import { RawCommands } from '@tiptap/core'\nimport { TextSelection } from '@tiptap/pm/state'\n\n/**\n * Augment the official `@tiptap/core` module with extra commands so that the compiler knows about\n * them. For this to work externally, a wildcard export needs to be added to the root `index.ts`.\n */\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n createParagraphEnd: {\n /**\n * Creates an empty paragraph at the end of the document.\n */\n createParagraphEnd: () => ReturnType\n }\n }\n}\n\n/**\n * Creates an empty paragraph at the end of the document.\n *\n * last node before creating the paragraph, using the build int fn\n */\nfunction createParagraphEnd(): ReturnType<RawCommands['createParagraphEnd']> {\n return ({ state, tr, chain, dispatch }) => {\n // Check if the transaction should be dispatched\n // ref: https://tiptap.dev/api/commands#dry-run-for-commands\n if (dispatch) {\n return chain()\n .command(() => {\n tr.setSelection(\n TextSelection.create(\n tr.doc,\n state.doc.content.size,\n state.doc.content.size,\n ),\n )\n\n return true\n })\n .createParagraphNear()\n .run()\n }\n\n return true\n }\n}\n\nexport { createParagraphEnd }\n"],"mappings":";;;;;;;AAuBA,SAAS,qBAAoE;CACzE,QAAQ,EAAE,OAAO,IAAI,OAAO,eAAe;EAGvC,IAAI,UACA,OAAO,OAAO,CACT,cAAc;GACX,GAAG,aACC,cAAc,OACV,GAAG,KACH,MAAM,IAAI,QAAQ,MAClB,MAAM,IAAI,QAAQ,KACrB,CACJ;GAED,OAAO;IACT,CACD,qBAAqB,CACrB,KAAK;EAGd,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extend-word-range.js","names":[],"sources":["../../../../../src/extensions/core/extra-editor-commands/commands/extend-word-range.ts"],"sourcesContent":["import { isActive, isTextSelection, RawCommands } from '@tiptap/core'\nimport { TextSelection } from '@tiptap/pm/state'\nimport { clamp } from 'lodash-es'\n\n/**\n * Augment the official `@tiptap/core` module with extra commands so that the compiler knows about\n * them. For this to work externally, a wildcard export needs to be added to the root `index.ts`.\n */\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n extendWordRange: {\n /**\n * Extends the text selection to the current word.\n */\n extendWordRange: () => ReturnType\n }\n }\n}\n\n/**\n * Extends the text selection to the current word.\n *\n * The solution for this function was inspired by the official `extendMarkRange` and\n * `setTextSelection` commands.\n */\nfunction extendWordRange(): ReturnType<RawCommands['extendWordRange']> {\n return ({ state, tr, dispatch }) => {\n const { doc, selection } = tr\n const { $head } = selection\n\n // Do nothing if cursor position is not valid for a text selection\n if (\n !isTextSelection(selection) ||\n isActive(state, 'code') ||\n isActive(state, 'codeBlock')\n ) {\n return false\n }\n\n // Check if the transaction should be dispatched\n // ref: https://tiptap.dev/api/commands#dry-run-for-commands\n if (dispatch) {\n const textBefore = $head.nodeBefore?.text?.match(/[^\\s]+$/)?.[0] || ''\n const textAfter = $head.nodeAfter?.text?.match(/^[^\\s]+/)?.[0] || ''\n\n const minPos = TextSelection.atStart(doc).from\n const maxPos = TextSelection.atEnd(doc).to\n\n tr.setSelection(\n TextSelection.create(\n doc,\n clamp(selection.head - textBefore.length, minPos, maxPos),\n clamp(selection.head + textAfter.length, minPos, maxPos),\n ),\n )\n }\n\n return true\n }\n}\n\nexport { extendWordRange }\n"],"mappings":";;;;;;;;;;AAyBA,SAAS,kBAA8D;
|
|
1
|
+
{"version":3,"file":"extend-word-range.js","names":[],"sources":["../../../../../src/extensions/core/extra-editor-commands/commands/extend-word-range.ts"],"sourcesContent":["import { isActive, isTextSelection, RawCommands } from '@tiptap/core'\nimport { TextSelection } from '@tiptap/pm/state'\nimport { clamp } from 'lodash-es'\n\n/**\n * Augment the official `@tiptap/core` module with extra commands so that the compiler knows about\n * them. For this to work externally, a wildcard export needs to be added to the root `index.ts`.\n */\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n extendWordRange: {\n /**\n * Extends the text selection to the current word.\n */\n extendWordRange: () => ReturnType\n }\n }\n}\n\n/**\n * Extends the text selection to the current word.\n *\n * The solution for this function was inspired by the official `extendMarkRange` and\n * `setTextSelection` commands.\n */\nfunction extendWordRange(): ReturnType<RawCommands['extendWordRange']> {\n return ({ state, tr, dispatch }) => {\n const { doc, selection } = tr\n const { $head } = selection\n\n // Do nothing if cursor position is not valid for a text selection\n if (\n !isTextSelection(selection) ||\n isActive(state, 'code') ||\n isActive(state, 'codeBlock')\n ) {\n return false\n }\n\n // Check if the transaction should be dispatched\n // ref: https://tiptap.dev/api/commands#dry-run-for-commands\n if (dispatch) {\n const textBefore = $head.nodeBefore?.text?.match(/[^\\s]+$/)?.[0] || ''\n const textAfter = $head.nodeAfter?.text?.match(/^[^\\s]+/)?.[0] || ''\n\n const minPos = TextSelection.atStart(doc).from\n const maxPos = TextSelection.atEnd(doc).to\n\n tr.setSelection(\n TextSelection.create(\n doc,\n clamp(selection.head - textBefore.length, minPos, maxPos),\n clamp(selection.head + textAfter.length, minPos, maxPos),\n ),\n )\n }\n\n return true\n }\n}\n\nexport { extendWordRange }\n"],"mappings":";;;;;;;;;;AAyBA,SAAS,kBAA8D;CACnE,QAAQ,EAAE,OAAO,IAAI,eAAe;EAChC,MAAM,EAAE,KAAK,cAAc;EAC3B,MAAM,EAAE,UAAU;EAGlB,IACI,CAAC,gBAAgB,UAAU,IAC3B,SAAS,OAAO,OAAO,IACvB,SAAS,OAAO,YAAY,EAE5B,OAAO;EAKX,IAAI,UAAU;GACV,MAAM,aAAa,MAAM,YAAY,MAAM,MAAM,UAAU,GAAG,MAAM;GACpE,MAAM,YAAY,MAAM,WAAW,MAAM,MAAM,UAAU,GAAG,MAAM;GAElE,MAAM,SAAS,cAAc,QAAQ,IAAI,CAAC;GAC1C,MAAM,SAAS,cAAc,MAAM,IAAI,CAAC;GAExC,GAAG,aACC,cAAc,OACV,KACA,MAAM,UAAU,OAAO,WAAW,QAAQ,QAAQ,OAAO,EACzD,MAAM,UAAU,OAAO,UAAU,QAAQ,QAAQ,OAAO,CAC3D,CACJ;;EAGL,OAAO"}
|
package/dist/extensions/core/extra-editor-commands/commands/insert-markdown-content-at.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insert-markdown-content-at.js","names":[],"sources":["../../../../../src/extensions/core/extra-editor-commands/commands/insert-markdown-content-at.ts"],"sourcesContent":["import { RawCommands, selectionToInsertionEnd } from '@tiptap/core'\nimport { DOMParser } from '@tiptap/pm/model'\n\nimport { parseHtmlToElement } from '../../../../helpers/dom'\nimport { getHTMLSerializerInstance } from '../../../../serializers/html/html'\n\nimport type { Range } from '@tiptap/core'\nimport type { ParseOptions } from '@tiptap/pm/model'\n\n/**\n * Augment the official `@tiptap/core` module with extra commands so that the compiler knows about\n * them. For this to work externally, a wildcard export needs to be added to the root `index.ts`.\n */\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n insertMarkdownContentAt: {\n /**\n * Inserts the provided Markdown content as HTML into the editor at a specific position.\n *\n * @param position The position or range the Markdown will be inserted in.\n * @param markdown The Markdown content to parse and insert as HTML.\n * @param options An optional object with the following parameters:\n * @param options.parseOptions The parse options to use when the HTML content is parsed by ProseMirror.\n * @param options.updateSelection Whether the selection should move to the newly inserted content.\n */\n insertMarkdownContentAt: (\n position: number | Range,\n markdown: string,\n options?: {\n parseOptions?: ParseOptions\n updateSelection?: boolean\n },\n ) => ReturnType\n }\n }\n}\n\n/**\n * Inserts the provided Markdown content as HTML into the editor at a specific position.\n *\n * The solution for this function was inspired by how ProseMirror pastes content from the clipboard,\n * and how Tiptap inserts content with the `insertContentAt` command.\n */\nfunction insertMarkdownContentAt(\n position: number | Range,\n markdown: string,\n options?: {\n parseOptions?: ParseOptions\n updateSelection?: boolean\n },\n): ReturnType<RawCommands['insertMarkdownContentAt']> {\n return ({ editor, tr, dispatch }) => {\n // Check if the transaction should be dispatched\n // ref: https://tiptap.dev/api/commands#dry-run-for-commands\n if (dispatch) {\n // Default values for command options must be set here\n // (they do not work if set in the function signature)\n options = {\n parseOptions: {},\n updateSelection: true,\n ...options,\n }\n\n // Get the start and end positions from the provided position\n const { from, to } =\n typeof position === 'number'\n ? { from: position, to: position }\n : { from: position.from, to: position.to }\n\n // Parse the Markdown to HTML and then then into ProseMirror nodes\n const htmlContent = getHTMLSerializerInstance(editor.schema).serialize(markdown)\n const content = DOMParser.fromSchema(editor.schema).parseSlice(\n parseHtmlToElement(htmlContent),\n options.parseOptions,\n )\n\n // Inserts the content into the editor while preserving the current selection\n tr.replaceRange(from, to, content)\n\n // Set the text cursor to the end of the inserted content\n if (options.updateSelection) {\n selectionToInsertionEnd(tr, tr.steps.length - 1, -1)\n }\n }\n\n return true\n }\n}\n\nexport { insertMarkdownContentAt }\n"],"mappings":";;;;;;;;;;;AA2CA,SAAS,wBACL,UACA,UACA,SAIkD;
|
|
1
|
+
{"version":3,"file":"insert-markdown-content-at.js","names":[],"sources":["../../../../../src/extensions/core/extra-editor-commands/commands/insert-markdown-content-at.ts"],"sourcesContent":["import { RawCommands, selectionToInsertionEnd } from '@tiptap/core'\nimport { DOMParser } from '@tiptap/pm/model'\n\nimport { parseHtmlToElement } from '../../../../helpers/dom'\nimport { getHTMLSerializerInstance } from '../../../../serializers/html/html'\n\nimport type { Range } from '@tiptap/core'\nimport type { ParseOptions } from '@tiptap/pm/model'\n\n/**\n * Augment the official `@tiptap/core` module with extra commands so that the compiler knows about\n * them. For this to work externally, a wildcard export needs to be added to the root `index.ts`.\n */\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n insertMarkdownContentAt: {\n /**\n * Inserts the provided Markdown content as HTML into the editor at a specific position.\n *\n * @param position The position or range the Markdown will be inserted in.\n * @param markdown The Markdown content to parse and insert as HTML.\n * @param options An optional object with the following parameters:\n * @param options.parseOptions The parse options to use when the HTML content is parsed by ProseMirror.\n * @param options.updateSelection Whether the selection should move to the newly inserted content.\n */\n insertMarkdownContentAt: (\n position: number | Range,\n markdown: string,\n options?: {\n parseOptions?: ParseOptions\n updateSelection?: boolean\n },\n ) => ReturnType\n }\n }\n}\n\n/**\n * Inserts the provided Markdown content as HTML into the editor at a specific position.\n *\n * The solution for this function was inspired by how ProseMirror pastes content from the clipboard,\n * and how Tiptap inserts content with the `insertContentAt` command.\n */\nfunction insertMarkdownContentAt(\n position: number | Range,\n markdown: string,\n options?: {\n parseOptions?: ParseOptions\n updateSelection?: boolean\n },\n): ReturnType<RawCommands['insertMarkdownContentAt']> {\n return ({ editor, tr, dispatch }) => {\n // Check if the transaction should be dispatched\n // ref: https://tiptap.dev/api/commands#dry-run-for-commands\n if (dispatch) {\n // Default values for command options must be set here\n // (they do not work if set in the function signature)\n options = {\n parseOptions: {},\n updateSelection: true,\n ...options,\n }\n\n // Get the start and end positions from the provided position\n const { from, to } =\n typeof position === 'number'\n ? { from: position, to: position }\n : { from: position.from, to: position.to }\n\n // Parse the Markdown to HTML and then then into ProseMirror nodes\n const htmlContent = getHTMLSerializerInstance(editor.schema).serialize(markdown)\n const content = DOMParser.fromSchema(editor.schema).parseSlice(\n parseHtmlToElement(htmlContent),\n options.parseOptions,\n )\n\n // Inserts the content into the editor while preserving the current selection\n tr.replaceRange(from, to, content)\n\n // Set the text cursor to the end of the inserted content\n if (options.updateSelection) {\n selectionToInsertionEnd(tr, tr.steps.length - 1, -1)\n }\n }\n\n return true\n }\n}\n\nexport { insertMarkdownContentAt }\n"],"mappings":";;;;;;;;;;;AA2CA,SAAS,wBACL,UACA,UACA,SAIkD;CAClD,QAAQ,EAAE,QAAQ,IAAI,eAAe;EAGjC,IAAI,UAAU;GAGV,UAAU;IACN,cAAc,EAAE;IAChB,iBAAiB;IACjB,GAAG;IACN;GAGD,MAAM,EAAE,MAAM,OACV,OAAO,aAAa,WACd;IAAE,MAAM;IAAU,IAAI;IAAU,GAChC;IAAE,MAAM,SAAS;IAAM,IAAI,SAAS;IAAI;GAGlD,MAAM,cAAc,0BAA0B,OAAO,OAAO,CAAC,UAAU,SAAS;GAChF,MAAM,UAAU,UAAU,WAAW,OAAO,OAAO,CAAC,WAChD,mBAAmB,YAAY,EAC/B,QAAQ,aACX;GAGD,GAAG,aAAa,MAAM,IAAI,QAAQ;GAGlC,IAAI,QAAQ,iBACR,wBAAwB,IAAI,GAAG,MAAM,SAAS,GAAG,GAAG;;EAI5D,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insert-markdown-content.js","names":[],"sources":["../../../../../src/extensions/core/extra-editor-commands/commands/insert-markdown-content.ts"],"sourcesContent":["import { RawCommands } from '@tiptap/core'\n\nimport type { ParseOptions } from '@tiptap/pm/model'\n\n/**\n * Augment the official `@tiptap/core` module with extra commands so that the compiler knows about\n * them. For this to work externally, a wildcard export needs to be added to the root `index.ts`.\n */\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n insertMarkdownContent: {\n /**\n * Inserts the provided Markdown as HTML into the editor at the current position.\n *\n * @param markdown The Markdown content to parse and insert as HTML.\n * @param options An optional object with the following parameters:\n * @param options.parseOptions The parse options to use when the HTML content is parsed by ProseMirror.\n * @param options.updateSelection Whether the selection should move to the newly inserted content.\n */\n insertMarkdownContent: (\n markdown: string,\n options?: {\n parseOptions?: ParseOptions\n updateSelection?: boolean\n },\n ) => ReturnType\n }\n }\n}\n\n/**\n * Inserts the provided Markdown as HTML into the editor at the current position.\n *\n * The solution for this function was inspired by how Tiptap inserts content with the\n * `insertContent` command.\n */\nfunction insertMarkdownContent(\n markdown: string,\n options?: {\n parseOptions?: ParseOptions\n updateSelection?: boolean\n },\n): ReturnType<RawCommands['insertMarkdownContent']> {\n return ({ commands, tr }) => {\n return commands.insertMarkdownContentAt(\n { from: tr.selection.from, to: tr.selection.to },\n markdown,\n options,\n )\n }\n}\n\nexport { insertMarkdownContent }\n"],"mappings":";;;;;;;AAoCA,SAAS,sBACL,UACA,SAIgD;
|
|
1
|
+
{"version":3,"file":"insert-markdown-content.js","names":[],"sources":["../../../../../src/extensions/core/extra-editor-commands/commands/insert-markdown-content.ts"],"sourcesContent":["import { RawCommands } from '@tiptap/core'\n\nimport type { ParseOptions } from '@tiptap/pm/model'\n\n/**\n * Augment the official `@tiptap/core` module with extra commands so that the compiler knows about\n * them. For this to work externally, a wildcard export needs to be added to the root `index.ts`.\n */\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n insertMarkdownContent: {\n /**\n * Inserts the provided Markdown as HTML into the editor at the current position.\n *\n * @param markdown The Markdown content to parse and insert as HTML.\n * @param options An optional object with the following parameters:\n * @param options.parseOptions The parse options to use when the HTML content is parsed by ProseMirror.\n * @param options.updateSelection Whether the selection should move to the newly inserted content.\n */\n insertMarkdownContent: (\n markdown: string,\n options?: {\n parseOptions?: ParseOptions\n updateSelection?: boolean\n },\n ) => ReturnType\n }\n }\n}\n\n/**\n * Inserts the provided Markdown as HTML into the editor at the current position.\n *\n * The solution for this function was inspired by how Tiptap inserts content with the\n * `insertContent` command.\n */\nfunction insertMarkdownContent(\n markdown: string,\n options?: {\n parseOptions?: ParseOptions\n updateSelection?: boolean\n },\n): ReturnType<RawCommands['insertMarkdownContent']> {\n return ({ commands, tr }) => {\n return commands.insertMarkdownContentAt(\n { from: tr.selection.from, to: tr.selection.to },\n markdown,\n options,\n )\n }\n}\n\nexport { insertMarkdownContent }\n"],"mappings":";;;;;;;AAoCA,SAAS,sBACL,UACA,SAIgD;CAChD,QAAQ,EAAE,UAAU,SAAS;EACzB,OAAO,SAAS,wBACZ;GAAE,MAAM,GAAG,UAAU;GAAM,IAAI,GAAG,UAAU;GAAI,EAChD,UACA,QACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extra-editor-commands.js","names":[],"sources":["../../../../src/extensions/core/extra-editor-commands/extra-editor-commands.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\n\nimport { createParagraphEnd } from './commands/create-paragraph-end'\nimport { extendWordRange } from './commands/extend-word-range'\nimport { insertMarkdownContent } from './commands/insert-markdown-content'\nimport { insertMarkdownContentAt } from './commands/insert-markdown-content-at'\n\n/**\n * The `ExtraEditorCommands` extension is a collection of editor commands that provide additional\n * helper commands not available with the built-in commands. This extension was built similarly to\n * the official `Commands` extension.\n */\nconst ExtraEditorCommands = Extension.create({\n name: 'extraEditorCommands',\n addCommands() {\n return {\n createParagraphEnd,\n extendWordRange,\n insertMarkdownContent,\n insertMarkdownContentAt,\n }\n },\n})\n\nexport { ExtraEditorCommands }\n"],"mappings":";;;;;;;;;;;AAYA,MAAM,sBAAsB,UAAU,OAAO;CACzC,MAAM;CACN,cAAc;
|
|
1
|
+
{"version":3,"file":"extra-editor-commands.js","names":[],"sources":["../../../../src/extensions/core/extra-editor-commands/extra-editor-commands.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\n\nimport { createParagraphEnd } from './commands/create-paragraph-end'\nimport { extendWordRange } from './commands/extend-word-range'\nimport { insertMarkdownContent } from './commands/insert-markdown-content'\nimport { insertMarkdownContentAt } from './commands/insert-markdown-content-at'\n\n/**\n * The `ExtraEditorCommands` extension is a collection of editor commands that provide additional\n * helper commands not available with the built-in commands. This extension was built similarly to\n * the official `Commands` extension.\n */\nconst ExtraEditorCommands = Extension.create({\n name: 'extraEditorCommands',\n addCommands() {\n return {\n createParagraphEnd,\n extendWordRange,\n insertMarkdownContent,\n insertMarkdownContentAt,\n }\n },\n})\n\nexport { ExtraEditorCommands }\n"],"mappings":";;;;;;;;;;;AAYA,MAAM,sBAAsB,UAAU,OAAO;CACzC,MAAM;CACN,cAAc;EACV,OAAO;GACH;GACA;GACA;GACA;GACH;;CAER,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-event-handlers.js","names":[],"sources":["../../../src/extensions/core/view-event-handlers.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\nimport { VIEW_EVENT_HANDLERS_PRIORITY } from '../../constants/extension-priorities'\n\nimport type { EditorView } from '@tiptap/pm/view'\n\n/**\n * The options available to customize the `ViewEventHandlers` extension.\n *\n * If more view handlers are needed, please look into the available event handlers in\n * [`prosemirror-view`](https://prosemirror.net/docs/ref/#view.Props), and add them below.\n */\ntype ViewEventHandlersOptions = {\n /**\n * Called when the editor is clicked, after `handleClickOn` handlers have been called.\n */\n onClick?: (event: MouseEvent, view: EditorView, pos: number) => boolean | void\n\n /**\n * Called when the editor receives a `keydown` event.\n */\n onKeyDown?: (event: KeyboardEvent, view: EditorView) => boolean | void\n}\n\n/**\n * The `ViewEventHandlers` extension allows handling of various ProseMirror view events.\n *\n * The various event-handling functions may all return `true` to indicate that they handled the\n * given event. The view will then take care to call `preventDefault` on the event, except with\n * `handleDOMEvents`, where the handler itself is responsible for that. Return `false` or\n * `undefined` for the default event handler to be called.\n *\n * These event handlers should be used sparingly, please consider if a reusable extension would be\n * more appropriate for your use case.\n */\nconst ViewEventHandlers = Extension.create<ViewEventHandlersOptions>({\n name: 'viewEventHandlers',\n priority: VIEW_EVENT_HANDLERS_PRIORITY,\n addProseMirrorPlugins() {\n const { options } = this\n\n return [\n new Plugin({\n key: new PluginKey('viewEventHandlers'),\n props: {\n handleClick(view, pos, event) {\n return options.onClick?.(event, view, pos) || false\n },\n handleKeyDown(view, event) {\n return options.onKeyDown?.(event, view) || false\n },\n },\n }),\n ]\n },\n})\n\nexport { ViewEventHandlers }\n\nexport type { ViewEventHandlersOptions }\n"],"mappings":";;;;;;;;;;;;;;;AAoCA,MAAM,oBAAoB,UAAU,OAAiC;CACjE,MAAM;CACN,UAAA;CACA,wBAAwB;EACpB,MAAM,EAAE,YAAY;
|
|
1
|
+
{"version":3,"file":"view-event-handlers.js","names":[],"sources":["../../../src/extensions/core/view-event-handlers.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\nimport { VIEW_EVENT_HANDLERS_PRIORITY } from '../../constants/extension-priorities'\n\nimport type { EditorView } from '@tiptap/pm/view'\n\n/**\n * The options available to customize the `ViewEventHandlers` extension.\n *\n * If more view handlers are needed, please look into the available event handlers in\n * [`prosemirror-view`](https://prosemirror.net/docs/ref/#view.Props), and add them below.\n */\ntype ViewEventHandlersOptions = {\n /**\n * Called when the editor is clicked, after `handleClickOn` handlers have been called.\n */\n onClick?: (event: MouseEvent, view: EditorView, pos: number) => boolean | void\n\n /**\n * Called when the editor receives a `keydown` event.\n */\n onKeyDown?: (event: KeyboardEvent, view: EditorView) => boolean | void\n}\n\n/**\n * The `ViewEventHandlers` extension allows handling of various ProseMirror view events.\n *\n * The various event-handling functions may all return `true` to indicate that they handled the\n * given event. The view will then take care to call `preventDefault` on the event, except with\n * `handleDOMEvents`, where the handler itself is responsible for that. Return `false` or\n * `undefined` for the default event handler to be called.\n *\n * These event handlers should be used sparingly, please consider if a reusable extension would be\n * more appropriate for your use case.\n */\nconst ViewEventHandlers = Extension.create<ViewEventHandlersOptions>({\n name: 'viewEventHandlers',\n priority: VIEW_EVENT_HANDLERS_PRIORITY,\n addProseMirrorPlugins() {\n const { options } = this\n\n return [\n new Plugin({\n key: new PluginKey('viewEventHandlers'),\n props: {\n handleClick(view, pos, event) {\n return options.onClick?.(event, view, pos) || false\n },\n handleKeyDown(view, event) {\n return options.onKeyDown?.(event, view) || false\n },\n },\n }),\n ]\n },\n})\n\nexport { ViewEventHandlers }\n\nexport type { ViewEventHandlersOptions }\n"],"mappings":";;;;;;;;;;;;;;;AAoCA,MAAM,oBAAoB,UAAU,OAAiC;CACjE,MAAM;CACN,UAAA;CACA,wBAAwB;EACpB,MAAM,EAAE,YAAY;EAEpB,OAAO,CACH,IAAI,OAAO;GACP,KAAK,IAAI,UAAU,oBAAoB;GACvC,OAAO;IACH,YAAY,MAAM,KAAK,OAAO;KAC1B,OAAO,QAAQ,UAAU,OAAO,MAAM,IAAI,IAAI;;IAElD,cAAc,MAAM,OAAO;KACvB,OAAO,QAAQ,YAAY,OAAO,KAAK,IAAI;;IAElD;GACJ,CAAC,CACL;;CAER,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paste-multiline-text.js","names":[],"sources":["../../../src/extensions/plain-text/paste-multiline-text.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"paste-multiline-text.js","names":[],"sources":["../../../src/extensions/plain-text/paste-multiline-text.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport { Fragment, Slice } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\nimport { ClipboardDataType } from '../../constants/common'\nimport { REGEX_LINE_BREAKS } from '../../constants/regular-expressions'\n\nimport type { Schema } from '@tiptap/pm/model'\nimport type { EditorView } from '@tiptap/pm/view'\n\n/**\n * Handles a text input or paste event, and replaces all found line breaks with paragraph nodes.\n *\n * @param view The current editor view to process.\n * @param text The multiline text input to parse.\n */\nfunction handleTextInputOrPaste(view: EditorView, text: string): boolean {\n const { schema } = view.state as { schema: Schema }\n const { tr } = view.state\n\n const textLines = text.split(REGEX_LINE_BREAKS)\n\n // Do not handle the event without a multiline input\n // (i.e. when the user is only typing)\n if (textLines.length === 1) {\n return false\n }\n\n // Build an array of paragraphs nodes (including empty ones)\n const paragraphNodes = textLines.map((textLine) => {\n if (textLine.length === 0) {\n return schema.nodes.paragraph.create()\n }\n\n return schema.nodes.paragraph.create(null, schema.text(textLine))\n })\n\n // Inserts the new paragraph nodes at the current cursor position\n // (takes into account if a selection needs to be replaced)\n view.dispatch(\n tr.replaceSelection(Slice.maxOpen(Fragment.fromArray(paragraphNodes))).scrollIntoView(),\n )\n\n // Suppress the default handling behaviour\n return true\n}\n\n/**\n * The `MultilineDocumentPaste` extension preserves paragraphs (including empty ones) when\n * copying-and-pasting text into the editor, or when inputting multiline text with some sort of\n * automatic text insertion shortcut. This custom extension is required for a plain-text editor\n * configured with `multiline: true`, so that multiline clipboard text is pasted correctly.\n */\nconst PasteMultilineText = Extension.create({\n name: 'pasteMultilineText',\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: new PluginKey('pasteMultilineText'),\n props: {\n handleTextInput(view: EditorView, _, __, inputText) {\n return handleTextInputOrPaste(view, inputText)\n },\n handlePaste(view: EditorView, event) {\n const clipboardText = event.clipboardData\n ?.getData(ClipboardDataType.Text)\n .trim()\n\n // Do not handle the event if the clipboard doesn't contain text\n if (!clipboardText) {\n return false\n }\n\n return handleTextInputOrPaste(view, clipboardText)\n },\n },\n }),\n ]\n },\n})\n\nexport { PasteMultilineText }\n"],"mappings":";;;;;;;;;;;;AAgBA,SAAS,uBAAuB,MAAkB,MAAuB;CACrE,MAAM,EAAE,WAAW,KAAK;CACxB,MAAM,EAAE,OAAO,KAAK;CAEpB,MAAM,YAAY,KAAK,MAAM,kBAAkB;CAI/C,IAAI,UAAU,WAAW,GACrB,OAAO;CAIX,MAAM,iBAAiB,UAAU,KAAK,aAAa;EAC/C,IAAI,SAAS,WAAW,GACpB,OAAO,OAAO,MAAM,UAAU,QAAQ;EAG1C,OAAO,OAAO,MAAM,UAAU,OAAO,MAAM,OAAO,KAAK,SAAS,CAAC;GACnE;CAIF,KAAK,SACD,GAAG,iBAAiB,MAAM,QAAQ,SAAS,UAAU,eAAe,CAAC,CAAC,CAAC,gBAAgB,CAC1F;CAGD,OAAO;;;;;;;;AASX,MAAM,qBAAqB,UAAU,OAAO;CACxC,MAAM;CACN,wBAAwB;EACpB,OAAO,CACH,IAAI,OAAO;GACP,KAAK,IAAI,UAAU,qBAAqB;GACxC,OAAO;IACH,gBAAgB,MAAkB,GAAG,IAAI,WAAW;KAChD,OAAO,uBAAuB,MAAM,UAAU;;IAElD,YAAY,MAAkB,OAAO;KACjC,MAAM,gBAAgB,MAAM,eACtB,QAAQ,kBAAkB,KAAK,CAChC,MAAM;KAGX,IAAI,CAAC,eACD,OAAO;KAGX,OAAO,uBAAuB,MAAM,cAAc;;IAEzD;GACJ,CAAC,CACL;;CAER,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plain-text-document.js","names":[],"sources":["../../../src/extensions/plain-text/plain-text-document.ts"],"sourcesContent":["import { Document } from '@tiptap/extension-document'\n\n/**\n * The options available to customize the `PlainTextDocument` extension.\n */\ntype PlainTextDocumentOptions = {\n /**\n * Indicates whether the document accepts multiple lines of input or only a single line.\n */\n multiline: boolean\n}\n\n/**\n * Custom extension that extends the built-in `Document` extension to define a schema for multiline\n * or singleline plain-text documents (as opposed to the multiple block nodes by default).\n */\nconst PlainTextDocument = Document.extend<PlainTextDocumentOptions>({\n addOptions() {\n return {\n multiline: true,\n }\n },\n content() {\n // ref: https://tiptap.dev/api/schema#content\n return `paragraph${this.options.multiline ? '+' : ''}`\n },\n})\n\nexport { PlainTextDocument }\n\nexport type { PlainTextDocumentOptions }\n"],"mappings":";;;;;;AAgBA,MAAM,oBAAoB,SAAS,OAAiC;CAChE,aAAa;
|
|
1
|
+
{"version":3,"file":"plain-text-document.js","names":[],"sources":["../../../src/extensions/plain-text/plain-text-document.ts"],"sourcesContent":["import { Document } from '@tiptap/extension-document'\n\n/**\n * The options available to customize the `PlainTextDocument` extension.\n */\ntype PlainTextDocumentOptions = {\n /**\n * Indicates whether the document accepts multiple lines of input or only a single line.\n */\n multiline: boolean\n}\n\n/**\n * Custom extension that extends the built-in `Document` extension to define a schema for multiline\n * or singleline plain-text documents (as opposed to the multiple block nodes by default).\n */\nconst PlainTextDocument = Document.extend<PlainTextDocumentOptions>({\n addOptions() {\n return {\n multiline: true,\n }\n },\n content() {\n // ref: https://tiptap.dev/api/schema#content\n return `paragraph${this.options.multiline ? '+' : ''}`\n },\n})\n\nexport { PlainTextDocument }\n\nexport type { PlainTextDocumentOptions }\n"],"mappings":";;;;;;AAgBA,MAAM,oBAAoB,SAAS,OAAiC;CAChE,aAAa;EACT,OAAO,EACH,WAAW,MACd;;CAEL,UAAU;EAEN,OAAO,YAAY,KAAK,QAAQ,YAAY,MAAM;;CAEzD,CAAC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { CopyMarkdownSource } from "../shared/copy-markdown-source.js";
|
|
2
2
|
import { PasteHTMLTableAsString } from "../shared/paste-html-table-as-string.js";
|
|
3
3
|
import { PasteSinglelineText } from "../shared/paste-singleline-text.js";
|
|
4
|
-
import { SmartMarkdownTyping } from "./smart-markdown-typing/smart-markdown-typing.js";
|
|
5
4
|
import { PasteMultilineText } from "./paste-multiline-text.js";
|
|
6
5
|
import { PlainTextDocument } from "./plain-text-document.js";
|
|
7
6
|
import { PlainTextParagraph } from "./plain-text-paragraph.js";
|
|
7
|
+
import { SmartMarkdownTyping } from "./smart-markdown-typing/smart-markdown-typing.js";
|
|
8
8
|
import { Extension } from "@tiptap/core";
|
|
9
9
|
import { History } from "@tiptap/extension-history";
|
|
10
10
|
import { Text } from "@tiptap/extension-text";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plain-text-kit.js","names":[],"sources":["../../../src/extensions/plain-text/plain-text-kit.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport { History, HistoryOptions } from '@tiptap/extension-history'\nimport { Text } from '@tiptap/extension-text'\nimport { Typography } from '@tiptap/extension-typography'\n\nimport { CopyMarkdownSource } from '../shared/copy-markdown-source'\nimport { PasteHTMLTableAsString } from '../shared/paste-html-table-as-string'\nimport { PasteSinglelineText } from '../shared/paste-singleline-text'\n\nimport {
|
|
1
|
+
{"version":3,"file":"plain-text-kit.js","names":[],"sources":["../../../src/extensions/plain-text/plain-text-kit.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport { History, HistoryOptions } from '@tiptap/extension-history'\nimport { Text } from '@tiptap/extension-text'\nimport { Typography } from '@tiptap/extension-typography'\n\nimport { CopyMarkdownSource } from '../shared/copy-markdown-source'\nimport { PasteHTMLTableAsString } from '../shared/paste-html-table-as-string'\nimport { PasteSinglelineText } from '../shared/paste-singleline-text'\n\nimport { PasteMultilineText } from './paste-multiline-text'\nimport { PlainTextDocument } from './plain-text-document'\nimport { PlainTextParagraph } from './plain-text-paragraph'\nimport { SmartMarkdownTyping } from './smart-markdown-typing/smart-markdown-typing'\n\nimport type { Extensions } from '@tiptap/core'\nimport type { PlainTextDocumentOptions } from './plain-text-document'\nimport type { PlainTextParagraphOptions } from './plain-text-paragraph'\n\n/**\n * The options available to customize the `PlainTextKit` extension.\n */\ntype PlainTextKitOptions = {\n /**\n * Set options for the `Document` extension, or `false` to disable.\n */\n document: Partial<PlainTextDocumentOptions> | false\n\n /**\n * Set options for the `History` extension, or `false` to disable.\n */\n history: Partial<HistoryOptions> | false\n\n /**\n * Set options for the `Paragraph` extension, or `false` to disable.\n */\n paragraph: Partial<PlainTextParagraphOptions> | false\n\n /**\n * Set to `false` to disable the `PasteHTMLTableAsString` extension.\n */\n pasteHTMLTableAsString: false\n\n /**\n * Set to `false` to disable the `Text` extension.\n */\n text: false\n\n /**\n * Set to `false` to disable the `Typography` extension.\n */\n typography: false\n\n /**\n * Set to `false` to disable the `SmartMarkdownTyping` extension.\n */\n smartMarkdownTyping: false\n}\n\n/**\n * The `PlainTextKit` extension is a collection of the minimal required extensions to have a basic\n * plain-text editor working. This extension is based on the official `StarterKit` extension\n * implementation, allowing almost every extension to be customized or disabled.\n */\nconst PlainTextKit = Extension.create<PlainTextKitOptions>({\n name: 'plainTextKit',\n addExtensions() {\n const extensions: Extensions = []\n\n if (this.options.document !== false) {\n extensions.push(\n PlainTextDocument.configure(this.options?.document),\n\n // Supports copying the underlying Markdown source to the clipboard\n CopyMarkdownSource,\n\n // Supports pasting plain-text into both a singleline and multiline editor\n this.options?.document?.multiline === false\n ? PasteSinglelineText\n : PasteMultilineText,\n )\n\n if (this.options?.pasteHTMLTableAsString !== false) {\n // Supports pasting tables (from spreadsheets and websites) into the editor\n extensions.push(PasteHTMLTableAsString)\n }\n }\n\n if (this.options.history !== false) {\n extensions.push(History.configure(this.options?.history))\n }\n\n if (this.options.paragraph !== false) {\n extensions.push(PlainTextParagraph.configure(this.options?.paragraph))\n }\n\n if (this.options.text !== false) {\n extensions.push(Text)\n }\n\n if (this.options.typography !== false) {\n extensions.push(Typography)\n }\n\n if (this.options.smartMarkdownTyping !== false) {\n extensions.push(SmartMarkdownTyping)\n }\n\n return extensions\n },\n})\n\nexport { PlainTextKit }\n\nexport type { PlainTextKitOptions }\n"],"mappings":";;;;;;;;;;;;;;;;;AA+DA,MAAM,eAAe,UAAU,OAA4B;CACvD,MAAM;CACN,gBAAgB;EACZ,MAAM,aAAyB,EAAE;EAEjC,IAAI,KAAK,QAAQ,aAAa,OAAO;GACjC,WAAW,KACP,kBAAkB,UAAU,KAAK,SAAS,SAAS,EAGnD,oBAGA,KAAK,SAAS,UAAU,cAAc,QAChC,sBACA,mBACT;GAED,IAAI,KAAK,SAAS,2BAA2B,OAEzC,WAAW,KAAK,uBAAuB;;EAI/C,IAAI,KAAK,QAAQ,YAAY,OACzB,WAAW,KAAK,QAAQ,UAAU,KAAK,SAAS,QAAQ,CAAC;EAG7D,IAAI,KAAK,QAAQ,cAAc,OAC3B,WAAW,KAAK,mBAAmB,UAAU,KAAK,SAAS,UAAU,CAAC;EAG1E,IAAI,KAAK,QAAQ,SAAS,OACtB,WAAW,KAAK,KAAK;EAGzB,IAAI,KAAK,QAAQ,eAAe,OAC5B,WAAW,KAAK,WAAW;EAG/B,IAAI,KAAK,QAAQ,wBAAwB,OACrC,WAAW,KAAK,oBAAoB;EAGxC,OAAO;;CAEd,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plain-text-paragraph.js","names":[],"sources":["../../../src/extensions/plain-text/plain-text-paragraph.ts"],"sourcesContent":["import { Paragraph, ParagraphOptions } from '@tiptap/extension-paragraph'\n\n/**\n * Custom extension that extends the built-in `Paragraph` extension to add an additional keyboard\n * shortcut to insert a newline (needed to behave more closely to the `<textarea>` component).\n */\nconst PlainTextParagraph = Paragraph.extend<ParagraphOptions>({\n addKeyboardShortcuts() {\n return {\n 'Shift-Enter': () => this.editor.commands.enter(),\n }\n },\n})\n\nexport { PlainTextParagraph }\n\nexport type { ParagraphOptions as PlainTextParagraphOptions }\n"],"mappings":";;;;;;AAMA,MAAM,qBAAqB,UAAU,OAAyB,EAC1D,uBAAuB;
|
|
1
|
+
{"version":3,"file":"plain-text-paragraph.js","names":[],"sources":["../../../src/extensions/plain-text/plain-text-paragraph.ts"],"sourcesContent":["import { Paragraph, ParagraphOptions } from '@tiptap/extension-paragraph'\n\n/**\n * Custom extension that extends the built-in `Paragraph` extension to add an additional keyboard\n * shortcut to insert a newline (needed to behave more closely to the `<textarea>` component).\n */\nconst PlainTextParagraph = Paragraph.extend<ParagraphOptions>({\n addKeyboardShortcuts() {\n return {\n 'Shift-Enter': () => this.editor.commands.enter(),\n }\n },\n})\n\nexport { PlainTextParagraph }\n\nexport type { ParagraphOptions as PlainTextParagraphOptions }\n"],"mappings":";;;;;;AAMA,MAAM,qBAAqB,UAAU,OAAyB,EAC1D,uBAAuB;CACnB,OAAO,EACH,qBAAqB,KAAK,OAAO,SAAS,OAAO,EACpD;GAER,CAAC"}
|
|
@@ -4,7 +4,7 @@ import { Plugin, PluginKey } from "@tiptap/pm/state";
|
|
|
4
4
|
/**
|
|
5
5
|
* A list of the allowed keys that might trigger smart typing.
|
|
6
6
|
*/
|
|
7
|
-
const ALLOWED_KEYS = ["Enter", "Tab"];
|
|
7
|
+
const ALLOWED_KEYS = new Set(["Enter", "Tab"]);
|
|
8
8
|
/**
|
|
9
9
|
* The standard and task list item regex for smart typing triggers.
|
|
10
10
|
*/
|
|
@@ -24,7 +24,7 @@ const smartLists = new Plugin({
|
|
|
24
24
|
const { schema } = view.state;
|
|
25
25
|
const { selection, tr } = view.state;
|
|
26
26
|
if (!isMultilineDocument(schema)) return false;
|
|
27
|
-
if (!ALLOWED_KEYS.
|
|
27
|
+
if (!ALLOWED_KEYS.has(event.key)) return false;
|
|
28
28
|
const match = selection.$from.nodeBefore?.text?.match(REGEX_LIST_ITEM);
|
|
29
29
|
if (!match) return false;
|
|
30
30
|
if (event.key === "Enter") if (match[0] !== match[1]) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smart-lists.js","names":[],"sources":["../../../../../src/extensions/plain-text/smart-markdown-typing/plugins/smart-lists.ts"],"sourcesContent":["import { Plugin, PluginKey } from '@tiptap/pm/state'\n\nimport { isMultilineDocument } from '../../../../helpers/schema'\n\nimport type { Schema } from '@tiptap/pm/model'\nimport type { EditorView } from '@tiptap/pm/view'\n\n/**\n * A list of the allowed keys that might trigger smart typing.\n */\nconst ALLOWED_KEYS = ['Enter', 'Tab']\n\n/**\n * The standard and task list item regex for smart typing triggers.\n */\nconst REGEX_LIST_ITEM = /^( *(?:(?:\\*|-)(?: \\[[ x]\\])?|\\d+\\.) )[^\\n]*$/i\n\n/**\n * A string with the minimum required spaces to properly indent list items.\n */\nconst INDENT_SPACES = ' '\n\n/**\n * This plugin provides a more plesant typing experience for both standard and task lists, adding\n * the list marker automatically when pressing the `Enter` key, and it also supports list items\n * indentation with the `Tab` and `Shift+Tab` keys, forward and backward, respectively.\n */\nconst smartLists = new Plugin({\n key: new PluginKey('smartLists'),\n props: {\n handleKeyDown(view: EditorView, event) {\n const { schema } = view.state as { schema: Schema }\n const { selection, tr } = view.state\n\n // Do not handle the event if not in a multiline document\n if (!isMultilineDocument(schema)) {\n return false\n }\n\n // Do not handle the event if allowed keys were not pressed\n if (!ALLOWED_KEYS.
|
|
1
|
+
{"version":3,"file":"smart-lists.js","names":[],"sources":["../../../../../src/extensions/plain-text/smart-markdown-typing/plugins/smart-lists.ts"],"sourcesContent":["import { Plugin, PluginKey } from '@tiptap/pm/state'\n\nimport { isMultilineDocument } from '../../../../helpers/schema'\n\nimport type { Schema } from '@tiptap/pm/model'\nimport type { EditorView } from '@tiptap/pm/view'\n\n/**\n * A list of the allowed keys that might trigger smart typing.\n */\nconst ALLOWED_KEYS = new Set(['Enter', 'Tab'])\n\n/**\n * The standard and task list item regex for smart typing triggers.\n */\nconst REGEX_LIST_ITEM = /^( *(?:(?:\\*|-)(?: \\[[ x]\\])?|\\d+\\.) )[^\\n]*$/i\n\n/**\n * A string with the minimum required spaces to properly indent list items.\n */\nconst INDENT_SPACES = ' '\n\n/**\n * This plugin provides a more plesant typing experience for both standard and task lists, adding\n * the list marker automatically when pressing the `Enter` key, and it also supports list items\n * indentation with the `Tab` and `Shift+Tab` keys, forward and backward, respectively.\n */\nconst smartLists = new Plugin({\n key: new PluginKey('smartLists'),\n props: {\n handleKeyDown(view: EditorView, event) {\n const { schema } = view.state as { schema: Schema }\n const { selection, tr } = view.state\n\n // Do not handle the event if not in a multiline document\n if (!isMultilineDocument(schema)) {\n return false\n }\n\n // Do not handle the event if allowed keys were not pressed\n if (!ALLOWED_KEYS.has(event.key)) {\n return false\n }\n\n const match = selection.$from.nodeBefore?.text?.match(REGEX_LIST_ITEM)\n\n // Do not handle the event if a list/task item was not found\n if (!match) {\n return false\n }\n\n // Insert a new list marker with `Enter`?\n if (event.key === 'Enter') {\n // If the whole match is different from the first group match, the list item is not\n // empty, and a new list marker is inserted; If they are equal, the list item is\n // empty, and the list marker is deleted\n if (match[0] !== match[1]) {\n // Attempt to parse the first group match as an ordered list item marker\n const orderedListItemMarkerIndex = parseInt(match[1], 10)\n\n // Increment the ordered list item marker by 1 if it's a number, otherwise\n // use the first group match as the list item marker\n const nextListItemMarker = orderedListItemMarkerIndex\n ? `${orderedListItemMarkerIndex + 1}. `\n : // Make sure the next task item marker is unchecked\n match[1].replace(/\\[x\\]/i, '[ ]')\n\n view.dispatch(\n tr\n .replaceSelectionWith(\n schema.node('paragraph', {}, schema.text(nextListItemMarker)),\n )\n .scrollIntoView(),\n )\n } else {\n view.dispatch(tr.delete(selection.from - match[1].length, selection.to))\n }\n }\n // Indent the list item with `Tab` or `Shift+Tab`?\n else if (event.key === 'Tab') {\n // If the whole match is different from the first group match, the text cursor is\n // not at the beginning of the list item (i.e., `* |<Text>`, where the pipe is), and\n // the event is not handled (for now this restriction is disabled)\n // if (match[0] !== match[1]) {\n // return false\n // }\n\n // Indent the list item forward or backward?\n if (!event.shiftKey) {\n // Indent the list item forward\n view.dispatch(\n tr\n .insertText(INDENT_SPACES, selection.from - match[0].length)\n .scrollIntoView(),\n )\n } else {\n // Indent the list item backward if the whole match starts with a whitespace,\n // otherwise do nothing as the list item is already at the start of the line\n if (match[0].startsWith(INDENT_SPACES)) {\n view.dispatch(\n tr.delete(\n selection.from - match[0].length,\n selection.to - match[0].length + INDENT_SPACES.length,\n ),\n )\n }\n }\n }\n\n // Suppress the default handling behaviour\n return true\n },\n },\n})\n\nexport { smartLists }\n"],"mappings":";;;;;;AAUA,MAAM,eAAe,IAAI,IAAI,CAAC,SAAS,MAAM,CAAC;;;;AAK9C,MAAM,kBAAkB;;;;AAKxB,MAAM,gBAAgB;;;;;;AAOtB,MAAM,aAAa,IAAI,OAAO;CAC1B,KAAK,IAAI,UAAU,aAAa;CAChC,OAAO,EACH,cAAc,MAAkB,OAAO;EACnC,MAAM,EAAE,WAAW,KAAK;EACxB,MAAM,EAAE,WAAW,OAAO,KAAK;EAG/B,IAAI,CAAC,oBAAoB,OAAO,EAC5B,OAAO;EAIX,IAAI,CAAC,aAAa,IAAI,MAAM,IAAI,EAC5B,OAAO;EAGX,MAAM,QAAQ,UAAU,MAAM,YAAY,MAAM,MAAM,gBAAgB;EAGtE,IAAI,CAAC,OACD,OAAO;EAIX,IAAI,MAAM,QAAQ,SAId,IAAI,MAAM,OAAO,MAAM,IAAI;GAEvB,MAAM,6BAA6B,SAAS,MAAM,IAAI,GAAG;GAIzD,MAAM,qBAAqB,6BACrB,GAAG,6BAA6B,EAAE,MAElC,MAAM,GAAG,QAAQ,UAAU,MAAM;GAEvC,KAAK,SACD,GACK,qBACG,OAAO,KAAK,aAAa,EAAE,EAAE,OAAO,KAAK,mBAAmB,CAAC,CAChE,CACA,gBAAgB,CACxB;SAED,KAAK,SAAS,GAAG,OAAO,UAAU,OAAO,MAAM,GAAG,QAAQ,UAAU,GAAG,CAAC;OAI3E,IAAI,MAAM,QAAQ;OASf,CAAC,MAAM,UAEP,KAAK,SACD,GACK,WAAW,eAAe,UAAU,OAAO,MAAM,GAAG,OAAO,CAC3D,gBAAgB,CACxB;QAID,IAAI,MAAM,GAAG,WAAW,cAAc,EAClC,KAAK,SACD,GAAG,OACC,UAAU,OAAO,MAAM,GAAG,QAC1B,UAAU,KAAK,MAAM,GAAG,SAAS,EACpC,CACJ;;EAMb,OAAO;IAEd;CACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smart-select-wrap.js","names":[],"sources":["../../../../../src/extensions/plain-text/smart-markdown-typing/plugins/smart-select-wrap.ts"],"sourcesContent":["import { Plugin, PluginKey, TextSelection } from '@tiptap/pm/state'\n\nimport type { EditorView } from '@tiptap/pm/view'\n\n/**\n * An object holding the acceptable wrapping symbols. The key represents the trigger character, and\n * the character to be added before the selection, while the value represents the character to be\n * added after the selection.\n */\nconst WRAPPING_SYMBOLS: Record<string, string> = {\n '*': '*',\n _: '_',\n '~': '~',\n '\"': '\"',\n \"'\": \"'\",\n '`': '`',\n '(': ')',\n '[': ']',\n '{': '}',\n '<': '>',\n}\n\n/**\n * This plugin wraps a selection with matching symbols based on the typed character, wrapping the\n * selection with the corresponding opening and closing bracket symbols when appropriate. This\n * plugin does not have support for multiple selection ranges.\n */\nconst smartSelectWrap = new Plugin({\n key: new PluginKey('smartSelectWrap'),\n props: {\n handleTextInput(view: EditorView, from, to, symbol) {\n const { selection, tr } = view.state\n\n // Do not handle the event if the selection is empty\n if (selection.empty) {\n return false\n }\n\n const wrappingSymbol = WRAPPING_SYMBOLS[symbol]\n\n // Do not handle the event if no wrapping symbol was typed\n if (wrappingSymbol === undefined) {\n return false\n }\n\n // Insert wrapping symbols around the selected text\n view.dispatch(\n tr\n .insertText(symbol, from, from)\n .insertText(wrappingSymbol, to + 1, to + 1)\n .setSelection(TextSelection.create(tr.doc, from + 1, to + 1))\n .scrollIntoView(),\n )\n\n // Suppress the default handling behaviour\n return true\n },\n },\n})\n\nexport { smartSelectWrap }\n"],"mappings":";;;;;;;AASA,MAAM,mBAA2C;CAC7C,KAAK;CACL,GAAG;CACH,KAAK;CACL,MAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACR;;;;;;AAOD,MAAM,kBAAkB,IAAI,OAAO;CAC/B,KAAK,IAAI,UAAU,kBAAkB;CACrC,OAAO,EACH,gBAAgB,MAAkB,MAAM,IAAI,QAAQ;EAChD,MAAM,EAAE,WAAW,OAAO,KAAK;
|
|
1
|
+
{"version":3,"file":"smart-select-wrap.js","names":[],"sources":["../../../../../src/extensions/plain-text/smart-markdown-typing/plugins/smart-select-wrap.ts"],"sourcesContent":["import { Plugin, PluginKey, TextSelection } from '@tiptap/pm/state'\n\nimport type { EditorView } from '@tiptap/pm/view'\n\n/**\n * An object holding the acceptable wrapping symbols. The key represents the trigger character, and\n * the character to be added before the selection, while the value represents the character to be\n * added after the selection.\n */\nconst WRAPPING_SYMBOLS: Record<string, string> = {\n '*': '*',\n _: '_',\n '~': '~',\n '\"': '\"',\n \"'\": \"'\",\n '`': '`',\n '(': ')',\n '[': ']',\n '{': '}',\n '<': '>',\n}\n\n/**\n * This plugin wraps a selection with matching symbols based on the typed character, wrapping the\n * selection with the corresponding opening and closing bracket symbols when appropriate. This\n * plugin does not have support for multiple selection ranges.\n */\nconst smartSelectWrap = new Plugin({\n key: new PluginKey('smartSelectWrap'),\n props: {\n handleTextInput(view: EditorView, from, to, symbol) {\n const { selection, tr } = view.state\n\n // Do not handle the event if the selection is empty\n if (selection.empty) {\n return false\n }\n\n const wrappingSymbol = WRAPPING_SYMBOLS[symbol]\n\n // Do not handle the event if no wrapping symbol was typed\n if (wrappingSymbol === undefined) {\n return false\n }\n\n // Insert wrapping symbols around the selected text\n view.dispatch(\n tr\n .insertText(symbol, from, from)\n .insertText(wrappingSymbol, to + 1, to + 1)\n .setSelection(TextSelection.create(tr.doc, from + 1, to + 1))\n .scrollIntoView(),\n )\n\n // Suppress the default handling behaviour\n return true\n },\n },\n})\n\nexport { smartSelectWrap }\n"],"mappings":";;;;;;;AASA,MAAM,mBAA2C;CAC7C,KAAK;CACL,GAAG;CACH,KAAK;CACL,MAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACR;;;;;;AAOD,MAAM,kBAAkB,IAAI,OAAO;CAC/B,KAAK,IAAI,UAAU,kBAAkB;CACrC,OAAO,EACH,gBAAgB,MAAkB,MAAM,IAAI,QAAQ;EAChD,MAAM,EAAE,WAAW,OAAO,KAAK;EAG/B,IAAI,UAAU,OACV,OAAO;EAGX,MAAM,iBAAiB,iBAAiB;EAGxC,IAAI,mBAAmB,KAAA,GACnB,OAAO;EAIX,KAAK,SACD,GACK,WAAW,QAAQ,MAAM,KAAK,CAC9B,WAAW,gBAAgB,KAAK,GAAG,KAAK,EAAE,CAC1C,aAAa,cAAc,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,EAAE,CAAC,CAC5D,gBAAgB,CACxB;EAGD,OAAO;IAEd;CACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smart-url-pasting.js","names":[],"sources":["../../../../../src/extensions/plain-text/smart-markdown-typing/plugins/smart-url-pasting.ts"],"sourcesContent":["import { Plugin, PluginKey, TextSelection } from '@tiptap/pm/state'\n\nimport { ClipboardDataType } from '../../../../constants/common'\nimport { REGEX_WEB_URL } from '../../../../constants/regular-expressions'\n\nimport type { EditorView } from '@tiptap/pm/view'\n\n/**\n * The perfect URL validation regular expression for exact Web URLs (matches a\n * URL from the beginning to the end without allowing for partial matches).\n */\nconst REGEX_WEB_URL_EXACT = new RegExp(`^${REGEX_WEB_URL.source}$`, REGEX_WEB_URL.flags)\n\n/**\n * This plugin replaces a selection with the pasted URL using proper link syntax; unless the\n * selection is itself a URL, which in that case the selection will just be replaced by the pasted\n * URL. This plugin does not have support for multiple selection ranges.\n */\nconst smartUrlPasting = new Plugin({\n key: new PluginKey('smartUrlPasting'),\n props: {\n handlePaste(view: EditorView, event) {\n const { selection, tr } = view.state\n\n // Do not handle the event if the selection is empty\n if (selection.empty) {\n return false\n }\n\n // Do not handle the event if the selected text is already a URL\n if (REGEX_WEB_URL_EXACT.test(selection.$head.parent.textContent)) {\n return false\n }\n\n const clipboardText = event.clipboardData?.getData(ClipboardDataType.Text).trim()\n\n // Do not handle the event if the clipboard text is not a URL\n if (!clipboardText || !REGEX_WEB_URL_EXACT.test(clipboardText)) {\n return false\n }\n\n // Apply the Markdown link syntax to the selected and clipboard text pair\n view.dispatch(\n tr\n .insertText('[', selection.from, selection.from)\n .insertText(`](${clipboardText})`, selection.to + 1, selection.to + 1)\n .setSelection(\n TextSelection.create(tr.doc, selection.from + 1, selection.to + 1),\n )\n .scrollIntoView(),\n )\n\n // Suppress the default handling behaviour\n return true\n },\n },\n})\n\nexport { smartUrlPasting }\n"],"mappings":";;;;;;;;AAWA,MAAM,sBAAsB,IAAI,OAAO,IAAI,cAAc,OAAO,IAAI,cAAc,MAAM;;;;;;AAOxF,MAAM,kBAAkB,IAAI,OAAO;CAC/B,KAAK,IAAI,UAAU,kBAAkB;CACrC,OAAO,EACH,YAAY,MAAkB,OAAO;EACjC,MAAM,EAAE,WAAW,OAAO,KAAK;
|
|
1
|
+
{"version":3,"file":"smart-url-pasting.js","names":[],"sources":["../../../../../src/extensions/plain-text/smart-markdown-typing/plugins/smart-url-pasting.ts"],"sourcesContent":["import { Plugin, PluginKey, TextSelection } from '@tiptap/pm/state'\n\nimport { ClipboardDataType } from '../../../../constants/common'\nimport { REGEX_WEB_URL } from '../../../../constants/regular-expressions'\n\nimport type { EditorView } from '@tiptap/pm/view'\n\n/**\n * The perfect URL validation regular expression for exact Web URLs (matches a\n * URL from the beginning to the end without allowing for partial matches).\n */\nconst REGEX_WEB_URL_EXACT = new RegExp(`^${REGEX_WEB_URL.source}$`, REGEX_WEB_URL.flags)\n\n/**\n * This plugin replaces a selection with the pasted URL using proper link syntax; unless the\n * selection is itself a URL, which in that case the selection will just be replaced by the pasted\n * URL. This plugin does not have support for multiple selection ranges.\n */\nconst smartUrlPasting = new Plugin({\n key: new PluginKey('smartUrlPasting'),\n props: {\n handlePaste(view: EditorView, event) {\n const { selection, tr } = view.state\n\n // Do not handle the event if the selection is empty\n if (selection.empty) {\n return false\n }\n\n // Do not handle the event if the selected text is already a URL\n if (REGEX_WEB_URL_EXACT.test(selection.$head.parent.textContent)) {\n return false\n }\n\n const clipboardText = event.clipboardData?.getData(ClipboardDataType.Text).trim()\n\n // Do not handle the event if the clipboard text is not a URL\n if (!clipboardText || !REGEX_WEB_URL_EXACT.test(clipboardText)) {\n return false\n }\n\n // Apply the Markdown link syntax to the selected and clipboard text pair\n view.dispatch(\n tr\n .insertText('[', selection.from, selection.from)\n .insertText(`](${clipboardText})`, selection.to + 1, selection.to + 1)\n .setSelection(\n TextSelection.create(tr.doc, selection.from + 1, selection.to + 1),\n )\n .scrollIntoView(),\n )\n\n // Suppress the default handling behaviour\n return true\n },\n },\n})\n\nexport { smartUrlPasting }\n"],"mappings":";;;;;;;;AAWA,MAAM,sBAAsB,IAAI,OAAO,IAAI,cAAc,OAAO,IAAI,cAAc,MAAM;;;;;;AAOxF,MAAM,kBAAkB,IAAI,OAAO;CAC/B,KAAK,IAAI,UAAU,kBAAkB;CACrC,OAAO,EACH,YAAY,MAAkB,OAAO;EACjC,MAAM,EAAE,WAAW,OAAO,KAAK;EAG/B,IAAI,UAAU,OACV,OAAO;EAIX,IAAI,oBAAoB,KAAK,UAAU,MAAM,OAAO,YAAY,EAC5D,OAAO;EAGX,MAAM,gBAAgB,MAAM,eAAe,QAAQ,kBAAkB,KAAK,CAAC,MAAM;EAGjF,IAAI,CAAC,iBAAiB,CAAC,oBAAoB,KAAK,cAAc,EAC1D,OAAO;EAIX,KAAK,SACD,GACK,WAAW,KAAK,UAAU,MAAM,UAAU,KAAK,CAC/C,WAAW,KAAK,cAAc,IAAI,UAAU,KAAK,GAAG,UAAU,KAAK,EAAE,CACrE,aACG,cAAc,OAAO,GAAG,KAAK,UAAU,OAAO,GAAG,UAAU,KAAK,EAAE,CACrE,CACA,gBAAgB,CACxB;EAGD,OAAO;IAEd;CACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smart-markdown-typing.js","names":[],"sources":["../../../../src/extensions/plain-text/smart-markdown-typing/smart-markdown-typing.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\n\nimport { SMART_MARKDOWN_TYPING_PRIORITY } from '../../../constants/extension-priorities'\n\nimport { smartLists } from './plugins/smart-lists'\nimport { smartSelectWrap } from './plugins/smart-select-wrap'\nimport { smartUrlPasting } from './plugins/smart-url-pasting'\n\n/**\n * The `SmartMarkdownTyping` extension is a collection of ProseMirror plugins that attempts to mimic\n * a smart GitHub like typing experience, and is only meant to be used with a plain-text editor.\n */\nconst SmartMarkdownTyping = Extension.create({\n name: 'smartMarkdownTyping',\n priority: SMART_MARKDOWN_TYPING_PRIORITY,\n addProseMirrorPlugins() {\n return [smartLists, smartSelectWrap, smartUrlPasting]\n },\n})\n\nexport { SmartMarkdownTyping }\n"],"mappings":";;;;;;;;;;AAYA,MAAM,sBAAsB,UAAU,OAAO;CACzC,MAAM;CACN,UAAA;CACA,wBAAwB;
|
|
1
|
+
{"version":3,"file":"smart-markdown-typing.js","names":[],"sources":["../../../../src/extensions/plain-text/smart-markdown-typing/smart-markdown-typing.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\n\nimport { SMART_MARKDOWN_TYPING_PRIORITY } from '../../../constants/extension-priorities'\n\nimport { smartLists } from './plugins/smart-lists'\nimport { smartSelectWrap } from './plugins/smart-select-wrap'\nimport { smartUrlPasting } from './plugins/smart-url-pasting'\n\n/**\n * The `SmartMarkdownTyping` extension is a collection of ProseMirror plugins that attempts to mimic\n * a smart GitHub like typing experience, and is only meant to be used with a plain-text editor.\n */\nconst SmartMarkdownTyping = Extension.create({\n name: 'smartMarkdownTyping',\n priority: SMART_MARKDOWN_TYPING_PRIORITY,\n addProseMirrorPlugins() {\n return [smartLists, smartSelectWrap, smartUrlPasting]\n },\n})\n\nexport { SmartMarkdownTyping }\n"],"mappings":";;;;;;;;;;AAYA,MAAM,sBAAsB,UAAU,OAAO;CACzC,MAAM;CACN,UAAA;CACA,wBAAwB;EACpB,OAAO;GAAC;GAAY;GAAiB;GAAgB;;CAE5D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bold-and-italics.js","names":[],"sources":["../../../src/extensions/rich-text/bold-and-italics.ts"],"sourcesContent":["import { Mark, markInputRule, markPasteRule } from '@tiptap/core'\n\n/**\n * The \"star\" (i.e. `***`) input regex for Markdown text marked with bold and italics.\n */\nconst starInputRegex = /(?:^|\\s)(\\*\\*\\*(?!\\s+\\*\\*\\*)((?:[^*]+))\\*\\*\\*(?!\\s+\\*\\*\\*))$/\n\n/**\n * The \"star\" (i.e. `***`) paste regex for Markdown text marked with bold and italics.\n */\nconst starPasteRegex = /(?:^|\\s)(\\*\\*\\*(?!\\s+\\*\\*\\*)((?:[^*]+))\\*\\*\\*(?!\\s+\\*\\*\\*))/g\n\n/**\n * The \"underscore\" (i.e. `___`) input regex for Markdown text marked with bold and italics.\n */\nconst underscoreInputRegex = /(?:^|\\s)(___(?!\\s+___)((?:[^_]+))___(?!\\s+___))$/\n\n/**\n * The \"underscore\" (i.e. `___`) paste regex for Markdown text marked with bold and italics.\n */\nconst underscorePasteRegex = /(?:^|\\s)(___(?!\\s+___)((?:[^_]+))___(?!\\s+___))/g\n\n/**\n * The `BoldAndItalics` extension adds the ability to use the `***` and `___` Markdown shortcuts\n * when typing and pasting into the editor.\n */\nconst BoldAndItalics = Mark.create({\n name: 'boldAndItalics',\n renderHTML({ HTMLAttributes }) {\n return ['strong', ['em', HTMLAttributes, 0]]\n },\n addInputRules() {\n return [\n markInputRule({\n find: starInputRegex,\n type: this.type,\n }),\n markInputRule({\n find: underscoreInputRegex,\n type: this.type,\n }),\n ]\n },\n addPasteRules() {\n return [\n markPasteRule({\n find: starPasteRegex,\n type: this.type,\n }),\n markPasteRule({\n find: underscorePasteRegex,\n type: this.type,\n }),\n ]\n },\n})\n\nexport { BoldAndItalics }\n"],"mappings":";;;;;AAKA,MAAM,iBAAiB;;;;AAKvB,MAAM,iBAAiB;;;;AAKvB,MAAM,uBAAuB;;;;AAK7B,MAAM,uBAAuB;;;;;AAM7B,MAAM,iBAAiB,KAAK,OAAO;CAC/B,MAAM;CACN,WAAW,EAAE,kBAAkB;
|
|
1
|
+
{"version":3,"file":"bold-and-italics.js","names":[],"sources":["../../../src/extensions/rich-text/bold-and-italics.ts"],"sourcesContent":["import { Mark, markInputRule, markPasteRule } from '@tiptap/core'\n\n/**\n * The \"star\" (i.e. `***`) input regex for Markdown text marked with bold and italics.\n */\nconst starInputRegex = /(?:^|\\s)(\\*\\*\\*(?!\\s+\\*\\*\\*)((?:[^*]+))\\*\\*\\*(?!\\s+\\*\\*\\*))$/\n\n/**\n * The \"star\" (i.e. `***`) paste regex for Markdown text marked with bold and italics.\n */\nconst starPasteRegex = /(?:^|\\s)(\\*\\*\\*(?!\\s+\\*\\*\\*)((?:[^*]+))\\*\\*\\*(?!\\s+\\*\\*\\*))/g\n\n/**\n * The \"underscore\" (i.e. `___`) input regex for Markdown text marked with bold and italics.\n */\nconst underscoreInputRegex = /(?:^|\\s)(___(?!\\s+___)((?:[^_]+))___(?!\\s+___))$/\n\n/**\n * The \"underscore\" (i.e. `___`) paste regex for Markdown text marked with bold and italics.\n */\nconst underscorePasteRegex = /(?:^|\\s)(___(?!\\s+___)((?:[^_]+))___(?!\\s+___))/g\n\n/**\n * The `BoldAndItalics` extension adds the ability to use the `***` and `___` Markdown shortcuts\n * when typing and pasting into the editor.\n */\nconst BoldAndItalics = Mark.create({\n name: 'boldAndItalics',\n renderHTML({ HTMLAttributes }) {\n return ['strong', ['em', HTMLAttributes, 0]]\n },\n addInputRules() {\n return [\n markInputRule({\n find: starInputRegex,\n type: this.type,\n }),\n markInputRule({\n find: underscoreInputRegex,\n type: this.type,\n }),\n ]\n },\n addPasteRules() {\n return [\n markPasteRule({\n find: starPasteRegex,\n type: this.type,\n }),\n markPasteRule({\n find: underscorePasteRegex,\n type: this.type,\n }),\n ]\n },\n})\n\nexport { BoldAndItalics }\n"],"mappings":";;;;;AAKA,MAAM,iBAAiB;;;;AAKvB,MAAM,iBAAiB;;;;AAKvB,MAAM,uBAAuB;;;;AAK7B,MAAM,uBAAuB;;;;;AAM7B,MAAM,iBAAiB,KAAK,OAAO;CAC/B,MAAM;CACN,WAAW,EAAE,kBAAkB;EAC3B,OAAO,CAAC,UAAU;GAAC;GAAM;GAAgB;GAAE,CAAC;;CAEhD,gBAAgB;EACZ,OAAO,CACH,cAAc;GACV,MAAM;GACN,MAAM,KAAK;GACd,CAAC,EACF,cAAc;GACV,MAAM;GACN,MAAM,KAAK;GACd,CAAC,CACL;;CAEL,gBAAgB;EACZ,OAAO,CACH,cAAc;GACV,MAAM;GACN,MAAM,KAAK;GACd,CAAC,EACF,cAAc;GACV,MAAM;GACN,MAAM,KAAK;GACd,CAAC,CACL;;CAER,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"curvenote-codemark.js","names":[],"sources":["../../../src/extensions/rich-text/curvenote-codemark.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport codemark from 'prosemirror-codemark'\n\n/**\n * The `CurvenoteCodemark` extension adds a plugin for ProseMirror that makes it easier to handle,\n * and navigate inline code marks. The plugin creates a fake cursor (if necessary) to show if the\n * next character to be typed will or will not be inside the inline code mark.\n *\n * @see https://github.com/curvenote/prosemirror-codemark\n */\nconst CurvenoteCodemark = Extension.create({\n name: 'curvenoteCodemark',\n addProseMirrorPlugins() {\n return codemark({\n markType: this.editor.schema.marks.code,\n })\n },\n})\n\nexport { CurvenoteCodemark }\n"],"mappings":";;;;;;;;;;AAUA,MAAM,oBAAoB,UAAU,OAAO;CACvC,MAAM;CACN,wBAAwB;
|
|
1
|
+
{"version":3,"file":"curvenote-codemark.js","names":[],"sources":["../../../src/extensions/rich-text/curvenote-codemark.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport codemark from 'prosemirror-codemark'\n\n/**\n * The `CurvenoteCodemark` extension adds a plugin for ProseMirror that makes it easier to handle,\n * and navigate inline code marks. The plugin creates a fake cursor (if necessary) to show if the\n * next character to be typed will or will not be inside the inline code mark.\n *\n * @see https://github.com/curvenote/prosemirror-codemark\n */\nconst CurvenoteCodemark = Extension.create({\n name: 'curvenoteCodemark',\n addProseMirrorPlugins() {\n return codemark({\n markType: this.editor.schema.marks.code,\n })\n },\n})\n\nexport { CurvenoteCodemark }\n"],"mappings":";;;;;;;;;;AAUA,MAAM,oBAAoB,UAAU,OAAO;CACvC,MAAM;CACN,wBAAwB;EACpB,OAAO,SAAS,EACZ,UAAU,KAAK,OAAO,OAAO,MAAM,MACtC,CAAC;;CAET,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paste-emojis.js","names":[],"sources":["../../../src/extensions/rich-text/paste-emojis.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport emojiRegex from 'emoji-regex'\n\n// Regular expression to match all emoji symbols and sequences (including textual representations)\nconst baseEmojiRegExp = emojiRegex()\n\n// Regular expression to match `<img>` tags with emoji unicode characters in the `alt` attribute\nconst imgWithEmojiRegExp = new RegExp(\n `<img[^>]+alt=\"(${baseEmojiRegExp.source})\"[^>]+/?>`,\n baseEmojiRegExp.flags,\n)\n\n/**\n * The `PasteEmojis` extension adds the ability to paste HTML image emojis as unicode characters\n * into the editor, ignoring the HTML image source. This extension works by replacing all `<img>`\n * tags with the emoji unicode character, if one is found in the `alt` attribute.\n */\nconst PasteEmojis = Extension.create({\n name: 'pasteEmojis',\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: new PluginKey('pasteEmojis'),\n props: {\n transformPastedHTML(html) {\n return html.replace(imgWithEmojiRegExp, (_, alt: string) => alt)\n },\n },\n }),\n ]\n },\n})\n\nexport { PasteEmojis }\n"],"mappings":";;;;AAKA,MAAM,kBAAkB,YAAY;AAGpC,MAAM,qBAAqB,IAAI,OAC3B,kBAAkB,gBAAgB,OAAO,aACzC,gBAAgB,MACnB;;;;;;AAOD,MAAM,cAAc,UAAU,OAAO;CACjC,MAAM;CACN,wBAAwB;
|
|
1
|
+
{"version":3,"file":"paste-emojis.js","names":[],"sources":["../../../src/extensions/rich-text/paste-emojis.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport emojiRegex from 'emoji-regex'\n\n// Regular expression to match all emoji symbols and sequences (including textual representations)\nconst baseEmojiRegExp = emojiRegex()\n\n// Regular expression to match `<img>` tags with emoji unicode characters in the `alt` attribute\nconst imgWithEmojiRegExp = new RegExp(\n `<img[^>]+alt=\"(${baseEmojiRegExp.source})\"[^>]+/?>`,\n baseEmojiRegExp.flags,\n)\n\n/**\n * The `PasteEmojis` extension adds the ability to paste HTML image emojis as unicode characters\n * into the editor, ignoring the HTML image source. This extension works by replacing all `<img>`\n * tags with the emoji unicode character, if one is found in the `alt` attribute.\n */\nconst PasteEmojis = Extension.create({\n name: 'pasteEmojis',\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: new PluginKey('pasteEmojis'),\n props: {\n transformPastedHTML(html) {\n return html.replace(imgWithEmojiRegExp, (_, alt: string) => alt)\n },\n },\n }),\n ]\n },\n})\n\nexport { PasteEmojis }\n"],"mappings":";;;;AAKA,MAAM,kBAAkB,YAAY;AAGpC,MAAM,qBAAqB,IAAI,OAC3B,kBAAkB,gBAAgB,OAAO,aACzC,gBAAgB,MACnB;;;;;;AAOD,MAAM,cAAc,UAAU,OAAO;CACjC,MAAM;CACN,wBAAwB;EACpB,OAAO,CACH,IAAI,OAAO;GACP,KAAK,IAAI,UAAU,cAAc;GACjC,OAAO,EACH,oBAAoB,MAAM;IACtB,OAAO,KAAK,QAAQ,qBAAqB,GAAG,QAAgB,IAAI;MAEvE;GACJ,CAAC,CACL;;CAER,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paste-markdown.js","names":[],"sources":["../../../src/extensions/rich-text/paste-markdown.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport { Fragment, Slice } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport * as linkify from 'linkifyjs'\n\nimport { ClipboardDataType } from '../../constants/common'\nimport { PASTE_MARKDOWN_EXTENSION_PRIORITY } from '../../constants/extension-priorities'\nimport { REGEX_PUNCTUATION } from '../../constants/regular-expressions'\n\n/**\n * A partial type for the the clipboard metadata coming from VS Code.\n *\n * @see https://github.com/microsoft/vscode/blob/1.66.2/src/vs/editor/browser/controller/textAreaInput.ts\n */\ntype VSCodeClipboardMetadata = {\n mode?: string\n}\n\n/**\n * The `PasteMarkdown` extension adds the ability to paste Markdown as HTML into the editor,\n * providing full rich-text support to the pasted content. The pasting behavior was inspired from\n * the GitLab implementation, and adapted to our requirements.\n *\n * @see https://gitlab.com/gitlab-org/gitlab/-/blob/v14.10.0-ee/app/assets/javascripts/content_editor/extensions/paste_markdown.js\n */\nconst PasteMarkdown = Extension.create({\n name: 'pasteMarkdown',\n priority: PASTE_MARKDOWN_EXTENSION_PRIORITY,\n addProseMirrorPlugins() {\n const { editor } = this\n\n return [\n new Plugin({\n key: new PluginKey('pasteMarkdown'),\n props: {\n clipboardTextParser(text) {\n // Override the default parser behavior of splitting text into lines (which\n // does not match the CommonMark spec for handling break lines), and instead\n // return a document slice with a single text node containing the whole\n // clipboard text, so that we can rely on the slice on `handlePaste` below)\n return Slice.maxOpen(Fragment.from(editor.schema.text(text)))\n },\n handlePaste(_, event, slice) {\n const isInsideCodeBlockNode =\n editor.state.selection.$from.parent.type.name === 'codeBlock'\n\n // The clipboard contains text if the slice content size is greater than\n // zero, otherwise it contains other data types (like files or images)\n const clipboardContainsText = Boolean(slice.content.size)\n\n // Do not handle the paste event if the user is pasting inside a code block\n // or if the clipboard does not contain text\n if (isInsideCodeBlockNode || !clipboardContainsText) {\n return false\n }\n\n // Get the clipboard text from the slice content instead of getting it from\n // the clipboard data because the pasted content could have already been\n // transformed by other ProseMirror plugins\n const textContent = slice.content.textBetween(0, slice.content.size, '\\n')\n\n // Do not handle the paste event if the clipboard text is only a link (in\n // this case we want the built-in handlers in Tiptap to handle the event)\n if (linkify.test(textContent)) {\n return false\n }\n\n const clipboardContainsHTML = Boolean(\n event.clipboardData?.types.some(\n (type) => type === ClipboardDataType.HTML,\n ),\n )\n\n // Unfortunately, the VS Code clipboard data type is not supported by\n // Firefox or Safari, which means that copy/paste experience from VS Code\n // into the editor with either of those browsers is subpar:\n // * The Markdown syntax is not fully converted to rich-text\n // * Code is not detected nor converted to a code-block\n const clipboardContainsVSCodeMetadata = Boolean(\n event.clipboardData?.types.some(\n (type) => type === ClipboardDataType.VSCode,\n ),\n )\n\n const clipboardContainsHTMLFromUnknownSource =\n clipboardContainsHTML && !clipboardContainsVSCodeMetadata\n\n const vsCodeClipboardMetadata: VSCodeClipboardMetadata =\n clipboardContainsVSCodeMetadata\n ? (JSON.parse(\n event.clipboardData?.getData(ClipboardDataType.VSCode) ||\n '{}',\n ) as VSCodeClipboardMetadata)\n : {}\n\n const clipboardContainsHTMLFromVSCodeOtherThanTextOrMarkdown =\n clipboardContainsVSCodeMetadata &&\n // If `mode` from the VS Code metadata is `null` it probably means that\n // the user has the VS Code `editor.copyWithSyntaxHighlighting` setting\n // set to `false`, thus returning plain-text\n vsCodeClipboardMetadata.mode !== null &&\n vsCodeClipboardMetadata.mode !== 'markdown'\n\n // Do not handle the paste event if the clipboard contains HTML from an\n // unknown source (e.g., Google Drive, Dropbox Paper, etc.) or from VS Code\n // that it's NOT plain-text or Markdown (e.g., Python, TypeScript, etc.)\n if (\n clipboardContainsHTMLFromUnknownSource ||\n clipboardContainsHTMLFromVSCodeOtherThanTextOrMarkdown\n ) {\n return false\n }\n\n // Escape all backslash characters that precede any punctuation marks, to\n // prevent the backslash itself from being interpreted as an escape sequence\n // for the subsequent character.\n const escapedTextContent = textContent.replace(\n new RegExp(`(\\\\\\\\${REGEX_PUNCTUATION.source})`, 'g'),\n '\\\\$1',\n )\n\n // Send the clipboard text through the HTML serializer to convert potential\n // Markdown into HTML, and then insert it into the editor\n editor.commands.insertMarkdownContent(escapedTextContent)\n\n // Suppress the default handling behaviour\n return true\n },\n },\n }),\n ]\n },\n})\n\nexport { PasteMarkdown }\n"],"mappings":";;;;;;;;;;;;;;;AAyBA,MAAM,gBAAgB,UAAU,OAAO;CACnC,MAAM;CACN,UAAU;CACV,wBAAwB;EACpB,MAAM,EAAE,WAAW;
|
|
1
|
+
{"version":3,"file":"paste-markdown.js","names":[],"sources":["../../../src/extensions/rich-text/paste-markdown.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport { Fragment, Slice } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport * as linkify from 'linkifyjs'\n\nimport { ClipboardDataType } from '../../constants/common'\nimport { PASTE_MARKDOWN_EXTENSION_PRIORITY } from '../../constants/extension-priorities'\nimport { REGEX_PUNCTUATION } from '../../constants/regular-expressions'\n\n/**\n * A partial type for the the clipboard metadata coming from VS Code.\n *\n * @see https://github.com/microsoft/vscode/blob/1.66.2/src/vs/editor/browser/controller/textAreaInput.ts\n */\ntype VSCodeClipboardMetadata = {\n mode?: string\n}\n\n/**\n * The `PasteMarkdown` extension adds the ability to paste Markdown as HTML into the editor,\n * providing full rich-text support to the pasted content. The pasting behavior was inspired from\n * the GitLab implementation, and adapted to our requirements.\n *\n * @see https://gitlab.com/gitlab-org/gitlab/-/blob/v14.10.0-ee/app/assets/javascripts/content_editor/extensions/paste_markdown.js\n */\nconst PasteMarkdown = Extension.create({\n name: 'pasteMarkdown',\n priority: PASTE_MARKDOWN_EXTENSION_PRIORITY,\n addProseMirrorPlugins() {\n const { editor } = this\n\n return [\n new Plugin({\n key: new PluginKey('pasteMarkdown'),\n props: {\n clipboardTextParser(text) {\n // Override the default parser behavior of splitting text into lines (which\n // does not match the CommonMark spec for handling break lines), and instead\n // return a document slice with a single text node containing the whole\n // clipboard text, so that we can rely on the slice on `handlePaste` below)\n return Slice.maxOpen(Fragment.from(editor.schema.text(text)))\n },\n handlePaste(_, event, slice) {\n const isInsideCodeBlockNode =\n editor.state.selection.$from.parent.type.name === 'codeBlock'\n\n // The clipboard contains text if the slice content size is greater than\n // zero, otherwise it contains other data types (like files or images)\n const clipboardContainsText = Boolean(slice.content.size)\n\n // Do not handle the paste event if the user is pasting inside a code block\n // or if the clipboard does not contain text\n if (isInsideCodeBlockNode || !clipboardContainsText) {\n return false\n }\n\n // Get the clipboard text from the slice content instead of getting it from\n // the clipboard data because the pasted content could have already been\n // transformed by other ProseMirror plugins\n const textContent = slice.content.textBetween(0, slice.content.size, '\\n')\n\n // Do not handle the paste event if the clipboard text is only a link (in\n // this case we want the built-in handlers in Tiptap to handle the event)\n if (linkify.test(textContent)) {\n return false\n }\n\n const clipboardContainsHTML = Boolean(\n event.clipboardData?.types.some(\n (type) => type === ClipboardDataType.HTML,\n ),\n )\n\n // Unfortunately, the VS Code clipboard data type is not supported by\n // Firefox or Safari, which means that copy/paste experience from VS Code\n // into the editor with either of those browsers is subpar:\n // * The Markdown syntax is not fully converted to rich-text\n // * Code is not detected nor converted to a code-block\n const clipboardContainsVSCodeMetadata = Boolean(\n event.clipboardData?.types.some(\n (type) => type === ClipboardDataType.VSCode,\n ),\n )\n\n const clipboardContainsHTMLFromUnknownSource =\n clipboardContainsHTML && !clipboardContainsVSCodeMetadata\n\n const vsCodeClipboardMetadata: VSCodeClipboardMetadata =\n clipboardContainsVSCodeMetadata\n ? (JSON.parse(\n event.clipboardData?.getData(ClipboardDataType.VSCode) ||\n '{}',\n ) as VSCodeClipboardMetadata)\n : {}\n\n const clipboardContainsHTMLFromVSCodeOtherThanTextOrMarkdown =\n clipboardContainsVSCodeMetadata &&\n // If `mode` from the VS Code metadata is `null` it probably means that\n // the user has the VS Code `editor.copyWithSyntaxHighlighting` setting\n // set to `false`, thus returning plain-text\n vsCodeClipboardMetadata.mode !== null &&\n vsCodeClipboardMetadata.mode !== 'markdown'\n\n // Do not handle the paste event if the clipboard contains HTML from an\n // unknown source (e.g., Google Drive, Dropbox Paper, etc.) or from VS Code\n // that it's NOT plain-text or Markdown (e.g., Python, TypeScript, etc.)\n if (\n clipboardContainsHTMLFromUnknownSource ||\n clipboardContainsHTMLFromVSCodeOtherThanTextOrMarkdown\n ) {\n return false\n }\n\n // Escape all backslash characters that precede any punctuation marks, to\n // prevent the backslash itself from being interpreted as an escape sequence\n // for the subsequent character.\n const escapedTextContent = textContent.replace(\n new RegExp(`(\\\\\\\\${REGEX_PUNCTUATION.source})`, 'g'),\n '\\\\$1',\n )\n\n // Send the clipboard text through the HTML serializer to convert potential\n // Markdown into HTML, and then insert it into the editor\n editor.commands.insertMarkdownContent(escapedTextContent)\n\n // Suppress the default handling behaviour\n return true\n },\n },\n }),\n ]\n },\n})\n\nexport { PasteMarkdown }\n"],"mappings":";;;;;;;;;;;;;;;AAyBA,MAAM,gBAAgB,UAAU,OAAO;CACnC,MAAM;CACN,UAAU;CACV,wBAAwB;EACpB,MAAM,EAAE,WAAW;EAEnB,OAAO,CACH,IAAI,OAAO;GACP,KAAK,IAAI,UAAU,gBAAgB;GACnC,OAAO;IACH,oBAAoB,MAAM;KAKtB,OAAO,MAAM,QAAQ,SAAS,KAAK,OAAO,OAAO,KAAK,KAAK,CAAC,CAAC;;IAEjE,YAAY,GAAG,OAAO,OAAO;KACzB,MAAM,wBACF,OAAO,MAAM,UAAU,MAAM,OAAO,KAAK,SAAS;KAItD,MAAM,wBAAwB,QAAQ,MAAM,QAAQ,KAAK;KAIzD,IAAI,yBAAyB,CAAC,uBAC1B,OAAO;KAMX,MAAM,cAAc,MAAM,QAAQ,YAAY,GAAG,MAAM,QAAQ,MAAM,KAAK;KAI1E,IAAI,QAAQ,KAAK,YAAY,EACzB,OAAO;KAGX,MAAM,wBAAwB,QAC1B,MAAM,eAAe,MAAM,MACtB,SAAS,SAAS,kBAAkB,KACxC,CACJ;KAOD,MAAM,kCAAkC,QACpC,MAAM,eAAe,MAAM,MACtB,SAAS,SAAS,kBAAkB,OACxC,CACJ;KAED,MAAM,yCACF,yBAAyB,CAAC;KAE9B,MAAM,0BACF,kCACO,KAAK,MACF,MAAM,eAAe,QAAQ,kBAAkB,OAAO,IAClD,KACP,GACD,EAAE;KAEZ,MAAM,yDACF,mCAIA,wBAAwB,SAAS,QACjC,wBAAwB,SAAS;KAKrC,IACI,0CACA,wDAEA,OAAO;KAMX,MAAM,qBAAqB,YAAY,QACnC,IAAI,OAAO,QAAQ,kBAAkB,OAAO,IAAI,IAAI,EACpD,OACH;KAID,OAAO,SAAS,sBAAsB,mBAAmB;KAGzD,OAAO;;IAEd;GACJ,CAAC,CACL;;CAER,CAAC"}
|
|
@@ -29,7 +29,7 @@ const RichTextBulletList = BulletList.extend({
|
|
|
29
29
|
tr.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
|
|
30
30
|
if (node.type.name === "hardBreak") hardBreakPositions.push(pos);
|
|
31
31
|
});
|
|
32
|
-
hardBreakPositions.
|
|
32
|
+
hardBreakPositions.toReversed().forEach((pos) => {
|
|
33
33
|
tr.replace(pos, pos + 1, Slice.maxOpen(Fragment.fromArray([schema.nodes.paragraph.create(), schema.nodes.paragraph.create()])));
|
|
34
34
|
});
|
|
35
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rich-text-bullet-list.js","names":[],"sources":["../../../src/extensions/rich-text/rich-text-bullet-list.ts"],"sourcesContent":["import { BulletList } from '@tiptap/extension-bullet-list'\nimport { ListItem } from '@tiptap/extension-list-item'\nimport { TextStyle } from '@tiptap/extension-text-style'\nimport { Fragment, Slice } from '@tiptap/pm/model'\n\nimport type { BulletListOptions } from '@tiptap/extension-bullet-list'\n\n/**\n * The options available to customize the `RichTextBulletList` extension.\n */\ntype RichTextBulletListOptions = {\n /**\n * Replace hard breaks in the selection with paragraphs before toggling the selection into a\n * bullet list. By default, hard breaks are not replaced.\n */\n smartToggle: boolean\n} & BulletListOptions\n\n/**\n * Custom extension that extends the built-in `BulletList` extension to add an option for smart\n * toggling, which takes into account hard breaks in the selection, and converts them into\n * paragraphs before toggling the selection into a bullet list.\n */\nconst RichTextBulletList = BulletList.extend<RichTextBulletListOptions>({\n addOptions() {\n return {\n ...this.parent?.(),\n smartToggle: false,\n }\n },\n\n addCommands() {\n const { editor, name, options } = this\n\n return {\n ...this.parent?.(),\n toggleBulletList() {\n return ({ commands, state, tr, chain }) => {\n // Replace hard breaks in the selection with paragraphs before toggling?\n if (options.smartToggle) {\n const { schema } = state\n const { selection } = tr\n const { $from, $to } = selection\n\n const hardBreakPositions: number[] = []\n\n // Find and store the positions of all hard breaks in the selection\n tr.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {\n if (node.type.name === 'hardBreak') {\n hardBreakPositions.push(pos)\n }\n })\n\n // Replace each hard break with a slice that closes and re-opens a paragraph,\n // effectively inserting a \"paragraph break\" in place of a \"hard break\"\n // (this is performed in reverse order to compensate for content shifting that\n // occurs with each replacement, ensuring accurate insertion points)\n hardBreakPositions.
|
|
1
|
+
{"version":3,"file":"rich-text-bullet-list.js","names":[],"sources":["../../../src/extensions/rich-text/rich-text-bullet-list.ts"],"sourcesContent":["import { BulletList } from '@tiptap/extension-bullet-list'\nimport { ListItem } from '@tiptap/extension-list-item'\nimport { TextStyle } from '@tiptap/extension-text-style'\nimport { Fragment, Slice } from '@tiptap/pm/model'\n\nimport type { BulletListOptions } from '@tiptap/extension-bullet-list'\n\n/**\n * The options available to customize the `RichTextBulletList` extension.\n */\ntype RichTextBulletListOptions = {\n /**\n * Replace hard breaks in the selection with paragraphs before toggling the selection into a\n * bullet list. By default, hard breaks are not replaced.\n */\n smartToggle: boolean\n} & BulletListOptions\n\n/**\n * Custom extension that extends the built-in `BulletList` extension to add an option for smart\n * toggling, which takes into account hard breaks in the selection, and converts them into\n * paragraphs before toggling the selection into a bullet list.\n */\nconst RichTextBulletList = BulletList.extend<RichTextBulletListOptions>({\n addOptions() {\n return {\n ...this.parent?.(),\n smartToggle: false,\n }\n },\n\n addCommands() {\n const { editor, name, options } = this\n\n return {\n ...this.parent?.(),\n toggleBulletList() {\n return ({ commands, state, tr, chain }) => {\n // Replace hard breaks in the selection with paragraphs before toggling?\n if (options.smartToggle) {\n const { schema } = state\n const { selection } = tr\n const { $from, $to } = selection\n\n const hardBreakPositions: number[] = []\n\n // Find and store the positions of all hard breaks in the selection\n tr.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {\n if (node.type.name === 'hardBreak') {\n hardBreakPositions.push(pos)\n }\n })\n\n // Replace each hard break with a slice that closes and re-opens a paragraph,\n // effectively inserting a \"paragraph break\" in place of a \"hard break\"\n // (this is performed in reverse order to compensate for content shifting that\n // occurs with each replacement, ensuring accurate insertion points)\n hardBreakPositions.toReversed().forEach((pos) => {\n tr.replace(\n pos,\n pos + 1,\n Slice.maxOpen(\n Fragment.fromArray([\n schema.nodes.paragraph.create(),\n schema.nodes.paragraph.create(),\n ]),\n ),\n )\n })\n }\n\n // Toggle the selection into a bullet list, optionally keeping attributes\n // (this is a verbatim copy of the built-in `toggleBulletList` command)\n\n if (options.keepAttributes) {\n return chain()\n .toggleList(name, options.itemTypeName, options.keepMarks)\n .updateAttributes(ListItem.name, editor.getAttributes(TextStyle.name))\n .run()\n }\n\n return commands.toggleList(name, options.itemTypeName, options.keepMarks)\n }\n },\n }\n },\n})\n\nexport { RichTextBulletList }\n\nexport type { RichTextBulletListOptions }\n"],"mappings":";;;;;;;;;;AAuBA,MAAM,qBAAqB,WAAW,OAAkC;CACpE,aAAa;EACT,OAAO;GACH,GAAG,KAAK,UAAU;GAClB,aAAa;GAChB;;CAGL,cAAc;EACV,MAAM,EAAE,QAAQ,MAAM,YAAY;EAElC,OAAO;GACH,GAAG,KAAK,UAAU;GAClB,mBAAmB;IACf,QAAQ,EAAE,UAAU,OAAO,IAAI,YAAY;KAEvC,IAAI,QAAQ,aAAa;MACrB,MAAM,EAAE,WAAW;MACnB,MAAM,EAAE,cAAc;MACtB,MAAM,EAAE,OAAO,QAAQ;MAEvB,MAAM,qBAA+B,EAAE;MAGvC,GAAG,IAAI,aAAa,MAAM,KAAK,IAAI,MAAM,MAAM,QAAQ;OACnD,IAAI,KAAK,KAAK,SAAS,aACnB,mBAAmB,KAAK,IAAI;QAElC;MAMF,mBAAmB,YAAY,CAAC,SAAS,QAAQ;OAC7C,GAAG,QACC,KACA,MAAM,GACN,MAAM,QACF,SAAS,UAAU,CACf,OAAO,MAAM,UAAU,QAAQ,EAC/B,OAAO,MAAM,UAAU,QAAQ,CAClC,CAAC,CACL,CACJ;QACH;;KAMN,IAAI,QAAQ,gBACR,OAAO,OAAO,CACT,WAAW,MAAM,QAAQ,cAAc,QAAQ,UAAU,CACzD,iBAAiB,SAAS,MAAM,OAAO,cAAc,UAAU,KAAK,CAAC,CACrE,KAAK;KAGd,OAAO,SAAS,WAAW,MAAM,QAAQ,cAAc,QAAQ,UAAU;;;GAGpF;;CAER,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rich-text-code.js","names":[],"sources":["../../../src/extensions/rich-text/rich-text-code.ts"],"sourcesContent":["import { markInputRule, markPasteRule } from '@tiptap/core'\nimport { Code } from '@tiptap/extension-code'\n\nimport { CODE_EXTENSION_PRIORITY } from '../../constants/extension-priorities'\n\nimport type { CodeOptions } from '@tiptap/extension-code'\n\n/**\n * The options available to customize the `RichTextCode` extension.\n */\ntype RichTextCodeOptions = CodeOptions\n\n/**\n * The original input regex for Markdown inline code (i.e. `<code>code</code>`) to prevent the issue\n * introduced in this PR: https://github.com/ueberdosis/tiptap/pull/4468#issuecomment-2575093998\n */\nconst inputRegex = /(?:^|\\s)(`(?!\\s+`)((?:[^`]+))`(?!\\s+`))$/\n\n/**\n * The original paste regex for Markdown inline code (i.e. `<code>code</code>`) to prevent the issue\n * introduced in this PR: https://github.com/ueberdosis/tiptap/pull/4468#issuecomment-2575093998\n */\nconst pasteRegex = /(?:^|\\s)(`(?!\\s+`)((?:[^`]+))`(?!\\s+`))/g\n\n/**\n * Custom extension that extends the built-in `Code` extension to allow all marks (e.g., Bold,\n * Italic, and Strikethrough) to coexist with the `Code` mark (as opposed to disallowing all any\n * other mark by default).\n *\n * @see https://tiptap.dev/api/schema#excludes\n * @see https://prosemirror.net/docs/ref/#model.MarkSpec.excludes\n */\nconst RichTextCode = Code.extend<RichTextCodeOptions>({\n priority: CODE_EXTENSION_PRIORITY,\n excludes: Code.name,\n addInputRules() {\n return [\n markInputRule({\n find: inputRegex,\n type: this.type,\n }),\n ]\n },\n addPasteRules() {\n return [\n markPasteRule({\n find: pasteRegex,\n type: this.type,\n }),\n ]\n },\n})\n\nexport { RichTextCode }\n\nexport type { RichTextCodeOptions }\n"],"mappings":";;;;;;;;AAgBA,MAAM,aAAa;;;;;AAMnB,MAAM,aAAa;;;;;;;;;AAUnB,MAAM,eAAe,KAAK,OAA4B;CAClD,UAAA;CACA,UAAU,KAAK;CACf,gBAAgB;
|
|
1
|
+
{"version":3,"file":"rich-text-code.js","names":[],"sources":["../../../src/extensions/rich-text/rich-text-code.ts"],"sourcesContent":["import { markInputRule, markPasteRule } from '@tiptap/core'\nimport { Code } from '@tiptap/extension-code'\n\nimport { CODE_EXTENSION_PRIORITY } from '../../constants/extension-priorities'\n\nimport type { CodeOptions } from '@tiptap/extension-code'\n\n/**\n * The options available to customize the `RichTextCode` extension.\n */\ntype RichTextCodeOptions = CodeOptions\n\n/**\n * The original input regex for Markdown inline code (i.e. `<code>code</code>`) to prevent the issue\n * introduced in this PR: https://github.com/ueberdosis/tiptap/pull/4468#issuecomment-2575093998\n */\nconst inputRegex = /(?:^|\\s)(`(?!\\s+`)((?:[^`]+))`(?!\\s+`))$/\n\n/**\n * The original paste regex for Markdown inline code (i.e. `<code>code</code>`) to prevent the issue\n * introduced in this PR: https://github.com/ueberdosis/tiptap/pull/4468#issuecomment-2575093998\n */\nconst pasteRegex = /(?:^|\\s)(`(?!\\s+`)((?:[^`]+))`(?!\\s+`))/g\n\n/**\n * Custom extension that extends the built-in `Code` extension to allow all marks (e.g., Bold,\n * Italic, and Strikethrough) to coexist with the `Code` mark (as opposed to disallowing all any\n * other mark by default).\n *\n * @see https://tiptap.dev/api/schema#excludes\n * @see https://prosemirror.net/docs/ref/#model.MarkSpec.excludes\n */\nconst RichTextCode = Code.extend<RichTextCodeOptions>({\n priority: CODE_EXTENSION_PRIORITY,\n excludes: Code.name,\n addInputRules() {\n return [\n markInputRule({\n find: inputRegex,\n type: this.type,\n }),\n ]\n },\n addPasteRules() {\n return [\n markPasteRule({\n find: pasteRegex,\n type: this.type,\n }),\n ]\n },\n})\n\nexport { RichTextCode }\n\nexport type { RichTextCodeOptions }\n"],"mappings":";;;;;;;;AAgBA,MAAM,aAAa;;;;;AAMnB,MAAM,aAAa;;;;;;;;;AAUnB,MAAM,eAAe,KAAK,OAA4B;CAClD,UAAA;CACA,UAAU,KAAK;CACf,gBAAgB;EACZ,OAAO,CACH,cAAc;GACV,MAAM;GACN,MAAM,KAAK;GACd,CAAC,CACL;;CAEL,gBAAgB;EACZ,OAAO,CACH,cAAc;GACV,MAAM;GACN,MAAM,KAAK;GACd,CAAC,CACL;;CAER,CAAC"}
|