@tiptap/core 3.18.0 → 3.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -719,6 +719,26 @@ interface ExtendableConfig<Options = any, Storage = any, Config extends Extensio
719
719
  type: PMType;
720
720
  parent: ParentConfig<Config>['addProseMirrorPlugins'];
721
721
  }) => Plugin[];
722
+ /**
723
+ * This function transforms pasted HTML content before it's parsed.
724
+ * Extensions can use this to modify or clean up pasted HTML.
725
+ * The transformations are chained - each extension's transform receives
726
+ * the output from the previous extension's transform.
727
+ * @see https://tiptap.dev/docs/editor/guide/custom-extensions#transform-pasted-html
728
+ * @example
729
+ * transformPastedHTML(html) {
730
+ * // Remove all style attributes
731
+ * return html.replace(/style="[^"]*"/g, '')
732
+ * }
733
+ */
734
+ transformPastedHTML?: (this: {
735
+ name: string;
736
+ options: Options;
737
+ storage: Storage;
738
+ editor: Editor;
739
+ type: PMType;
740
+ parent: ParentConfig<Config>['transformPastedHTML'];
741
+ }, html: string) => string;
722
742
  /**
723
743
  * This function adds additional extensions to the editor. This is useful for
724
744
  * building extension kits.
@@ -1496,8 +1516,18 @@ type ExtensionAttribute = {
1496
1516
  type GlobalAttributes = {
1497
1517
  /**
1498
1518
  * The node & mark types this attribute should be applied to.
1519
+ * Can be a specific array of type names, or a shorthand string:
1520
+ * - `'*'` applies to all nodes (excluding text) and all marks
1521
+ * - `'nodes'` applies to all nodes (excluding the built-in text node)
1522
+ * - `'marks'` applies to all marks
1523
+ * - `string[]` applies to specific node/mark types by name
1524
+ * @example
1525
+ * types: '*' // All nodes and marks
1526
+ * types: 'nodes' // All nodes
1527
+ * types: 'marks' // All marks
1528
+ * types: ['heading', 'paragraph'] // Specific types
1499
1529
  */
1500
- types: string[];
1530
+ types: string[] | 'nodes' | 'marks' | '*';
1501
1531
  /**
1502
1532
  * The attributes to add to the node or mark types.
1503
1533
  */
@@ -2320,6 +2350,12 @@ declare class ExtensionManager {
2320
2350
  * @returns A composed dispatch function
2321
2351
  */
2322
2352
  dispatchTransaction(baseDispatch: (tr: Transaction) => void): (tr: Transaction) => void;
2353
+ /**
2354
+ * Get the composed transformPastedHTML function from all extensions.
2355
+ * @param baseTransform The base transform function (e.g. from the editor props)
2356
+ * @returns A composed transform function that chains all extension transforms
2357
+ */
2358
+ transformPastedHTML(baseTransform?: (html: string, view?: any) => string): (html: string, view?: EditorView) => string;
2323
2359
  get markViews(): Record<string, MarkViewConstructor>;
2324
2360
  /**
2325
2361
  * Go through all extensions, create extension storages & setup marks
@@ -3528,7 +3564,7 @@ declare class Editor extends EventEmitter<EditorEvents> {
3528
3564
  */
3529
3565
  get isEditable(): boolean;
3530
3566
  /**
3531
- * Returns the editor state.
3567
+ * Returns the editor view.
3532
3568
  */
3533
3569
  get view(): EditorView;
3534
3570
  /**
package/dist/index.d.ts CHANGED
@@ -719,6 +719,26 @@ interface ExtendableConfig<Options = any, Storage = any, Config extends Extensio
719
719
  type: PMType;
720
720
  parent: ParentConfig<Config>['addProseMirrorPlugins'];
721
721
  }) => Plugin[];
722
+ /**
723
+ * This function transforms pasted HTML content before it's parsed.
724
+ * Extensions can use this to modify or clean up pasted HTML.
725
+ * The transformations are chained - each extension's transform receives
726
+ * the output from the previous extension's transform.
727
+ * @see https://tiptap.dev/docs/editor/guide/custom-extensions#transform-pasted-html
728
+ * @example
729
+ * transformPastedHTML(html) {
730
+ * // Remove all style attributes
731
+ * return html.replace(/style="[^"]*"/g, '')
732
+ * }
733
+ */
734
+ transformPastedHTML?: (this: {
735
+ name: string;
736
+ options: Options;
737
+ storage: Storage;
738
+ editor: Editor;
739
+ type: PMType;
740
+ parent: ParentConfig<Config>['transformPastedHTML'];
741
+ }, html: string) => string;
722
742
  /**
723
743
  * This function adds additional extensions to the editor. This is useful for
724
744
  * building extension kits.
@@ -1496,8 +1516,18 @@ type ExtensionAttribute = {
1496
1516
  type GlobalAttributes = {
1497
1517
  /**
1498
1518
  * The node & mark types this attribute should be applied to.
1519
+ * Can be a specific array of type names, or a shorthand string:
1520
+ * - `'*'` applies to all nodes (excluding text) and all marks
1521
+ * - `'nodes'` applies to all nodes (excluding the built-in text node)
1522
+ * - `'marks'` applies to all marks
1523
+ * - `string[]` applies to specific node/mark types by name
1524
+ * @example
1525
+ * types: '*' // All nodes and marks
1526
+ * types: 'nodes' // All nodes
1527
+ * types: 'marks' // All marks
1528
+ * types: ['heading', 'paragraph'] // Specific types
1499
1529
  */
1500
- types: string[];
1530
+ types: string[] | 'nodes' | 'marks' | '*';
1501
1531
  /**
1502
1532
  * The attributes to add to the node or mark types.
1503
1533
  */
@@ -2320,6 +2350,12 @@ declare class ExtensionManager {
2320
2350
  * @returns A composed dispatch function
2321
2351
  */
2322
2352
  dispatchTransaction(baseDispatch: (tr: Transaction) => void): (tr: Transaction) => void;
2353
+ /**
2354
+ * Get the composed transformPastedHTML function from all extensions.
2355
+ * @param baseTransform The base transform function (e.g. from the editor props)
2356
+ * @returns A composed transform function that chains all extension transforms
2357
+ */
2358
+ transformPastedHTML(baseTransform?: (html: string, view?: any) => string): (html: string, view?: EditorView) => string;
2323
2359
  get markViews(): Record<string, MarkViewConstructor>;
2324
2360
  /**
2325
2361
  * Go through all extensions, create extension storages & setup marks
@@ -3528,7 +3564,7 @@ declare class Editor extends EventEmitter<EditorEvents> {
3528
3564
  */
3529
3565
  get isEditable(): boolean;
3530
3566
  /**
3531
- * Returns the editor state.
3567
+ * Returns the editor view.
3532
3568
  */
3533
3569
  get view(): EditorView;
3534
3570
  /**
package/dist/index.js CHANGED
@@ -1348,6 +1348,9 @@ function getAttributesFromExtensions(extensions) {
1348
1348
  keepOnSplit: true,
1349
1349
  isRequired: false
1350
1350
  };
1351
+ const nodeExtensionTypes = nodeExtensions.filter((ext) => ext.name !== "text").map((ext) => ext.name);
1352
+ const markExtensionTypes = markExtensions.map((ext) => ext.name);
1353
+ const allExtensionTypes = [...nodeExtensionTypes, ...markExtensionTypes];
1351
1354
  extensions.forEach((extension) => {
1352
1355
  const context = {
1353
1356
  name: extension.name,
@@ -1365,7 +1368,19 @@ function getAttributesFromExtensions(extensions) {
1365
1368
  }
1366
1369
  const globalAttributes = addGlobalAttributes();
1367
1370
  globalAttributes.forEach((globalAttribute) => {
1368
- globalAttribute.types.forEach((type) => {
1371
+ let resolvedTypes;
1372
+ if (Array.isArray(globalAttribute.types)) {
1373
+ resolvedTypes = globalAttribute.types;
1374
+ } else if (globalAttribute.types === "*") {
1375
+ resolvedTypes = allExtensionTypes;
1376
+ } else if (globalAttribute.types === "nodes") {
1377
+ resolvedTypes = nodeExtensionTypes;
1378
+ } else if (globalAttribute.types === "marks") {
1379
+ resolvedTypes = markExtensionTypes;
1380
+ } else {
1381
+ resolvedTypes = [];
1382
+ }
1383
+ resolvedTypes.forEach((type) => {
1369
1384
  Object.entries(globalAttribute.attributes).forEach(([name, attribute]) => {
1370
1385
  extensionAttributes.push({
1371
1386
  type,
@@ -1983,6 +1998,9 @@ function isMarkActive(state, typeOrName, attributes = {}) {
1983
1998
  const from = $from.pos;
1984
1999
  const to = $to.pos;
1985
2000
  state.doc.nodesBetween(from, to, (node, pos) => {
2001
+ if (type && node.inlineContent && !node.type.allowsMarkType(type)) {
2002
+ return false;
2003
+ }
1986
2004
  if (!node.isText && !node.marks.length) {
1987
2005
  return;
1988
2006
  }
@@ -3683,6 +3701,39 @@ var ExtensionManager = class {
3683
3701
  };
3684
3702
  }, baseDispatch);
3685
3703
  }
3704
+ /**
3705
+ * Get the composed transformPastedHTML function from all extensions.
3706
+ * @param baseTransform The base transform function (e.g. from the editor props)
3707
+ * @returns A composed transform function that chains all extension transforms
3708
+ */
3709
+ transformPastedHTML(baseTransform) {
3710
+ const { editor } = this;
3711
+ const extensions = sortExtensions([...this.extensions]);
3712
+ return extensions.reduce(
3713
+ (transform, extension) => {
3714
+ const context = {
3715
+ name: extension.name,
3716
+ options: extension.options,
3717
+ storage: this.editor.extensionStorage[extension.name],
3718
+ editor,
3719
+ type: getSchemaTypeByName(extension.name, this.schema)
3720
+ };
3721
+ const extensionTransform = getExtensionField(
3722
+ extension,
3723
+ "transformPastedHTML",
3724
+ context
3725
+ );
3726
+ if (!extensionTransform) {
3727
+ return transform;
3728
+ }
3729
+ return (html, view) => {
3730
+ const transformedHtml = transform(html, view);
3731
+ return extensionTransform.call(context, transformedHtml);
3732
+ };
3733
+ },
3734
+ baseTransform || ((html) => html)
3735
+ );
3736
+ }
3686
3737
  get markViews() {
3687
3738
  const { editor } = this;
3688
3739
  const { markExtensions } = splitExtensions(this.extensions);
@@ -4705,7 +4756,7 @@ var Editor = class extends EventEmitter {
4705
4756
  return this.options.editable && this.view && this.view.editable;
4706
4757
  }
4707
4758
  /**
4708
- * Returns the editor state.
4759
+ * Returns the editor view.
4709
4760
  */
4710
4761
  get view() {
4711
4762
  if (this.editorView) {
@@ -4874,6 +4925,8 @@ var Editor = class extends EventEmitter {
4874
4925
  const { editorProps, enableExtensionDispatchTransaction } = this.options;
4875
4926
  const baseDispatch = editorProps.dispatchTransaction || this.dispatchTransaction.bind(this);
4876
4927
  const dispatch = enableExtensionDispatchTransaction ? this.extensionManager.dispatchTransaction(baseDispatch) : baseDispatch;
4928
+ const baseTransformPastedHTML = editorProps.transformPastedHTML;
4929
+ const transformPastedHTML = this.extensionManager.transformPastedHTML(baseTransformPastedHTML);
4877
4930
  this.editorView = new EditorView(element, {
4878
4931
  ...editorProps,
4879
4932
  attributes: {
@@ -4882,6 +4935,7 @@ var Editor = class extends EventEmitter {
4882
4935
  ...editorProps == null ? void 0 : editorProps.attributes
4883
4936
  },
4884
4937
  dispatchTransaction: dispatch,
4938
+ transformPastedHTML,
4885
4939
  state: this.editorState,
4886
4940
  markViews: this.extensionManager.markViews,
4887
4941
  nodeViews: this.extensionManager.nodeViews