Bassie
Bassie

Reputation: 10390

How to add a custom extension when using typescript

I am trying to add a custom extension to scrumpy/tiptap, but my project is using typescript and I think this is causing me some problems.

I got the code from this issue, and tried importing and using it like this:

import HighlightMark from '../ts/tiptap-extensions/HighlightMark';

...

this.editor = new Editor({
  content: '<p>This is just a boring paragraph.</p>',
  extensions: [new HighlightMark()]
})

But I am faced with this error

Type 'HighlightMark' is not assignable to type 'ExtensionOption'. Type 'HighlightMark' is not assignable to type 'Mark'. The types returned by 'schema.toDOM(...)' are incompatible between these types. Type '(string | number | { style: string; })[]' is not assignable to type 'DOMOutputSpec'. Property '0' is missing in type '(string | number | { style: string; })[]' but required in type 'DOMOutputSpecArray'.


I tried importing it in a .d.ts (as I had to do with all the built-int tiptap extensions), but I get an error telling me that I can't import files from relative path here:

Import or export declaration in an ambient module declaration cannot reference module through relative module name.ts(2439)


I also tried just changing the file to typescript (HighlightMark.ts), but it then gives me several errors:

Property 'commands' in type 'HighlightMark' is not assignable to the same property in base type 'Mark'. Type '({ type }: { type: any; }) => (attrs: any) => Command' is not assignable to type '({ type, schema, attrs }: { type: MarkType; schema: MarkSpec; attrs: { [key: string]: string; }; }) => CommandGetter'. Type '(attrs: any) => Command' is not assignable to type 'CommandGetter'.

and

'mark' is declared but its value is never read.ts(6133) Parameter 'mark' implicitly has an 'any' type.ts(7006)

and

Parameter 'attrs' implicitly has an 'any' type.ts(7006)

Has anyone done this before? Is it actually possible?

This is the code from HighlightMark.js:

   import { Mark } from 'tiptap';
   import { toggleMark } from 'tiptap-commands'

  export default class HighlightMark extends Mark {
  get name() {
    return "mark";
  }

  get schema() {
    return {
      attrs: {
        color: {
          default: "rgba(240,87,100,0.7)"
        }
      },
      parseDOM: [
        {
          tag: "mark"
        }
      ],
      toDOM: mark => [
        "mark",
        {
          style: `background: red` // ${mark.attrs.color}
        },
        0
      ]
    };
  }

  commands({ type }) {
    return attrs => toggleMark(type, attrs);
  }
}

Upvotes: 3

Views: 3029

Answers (3)

John J. Camilleri
John J. Camilleri

Reputation: 4440

I was able to get around this by returning an object from toDOM rather than an array, like so:

toDOM: mark => {
  return {
    0: 'mark',
    1: {
      style: `background:${mark.attrs.color}`
    },
    2: '0'
  }
}

Upvotes: 1

user11809641
user11809641

Reputation: 895

I didn't run into the same problem as you, but what worked for me may be of help. To get this to work for me, I had to export the class as a module from my .js file. For you, it would look like this:

HighlightMark.js

import { Mark } from 'tiptap';
import { toggleMark } from 'tiptap-commands'

...

export { HighlightMark };

and then in your main ts file


import highlightMark from '../ts/tiptap-extensions/HighlightMark';

...

this.editor = new Editor({
  content: '<p>This is just a boring paragraph.</p>',
  extensions: [ new HighlightMark() ]
})

Upvotes: 0

Bassie
Bassie

Reputation: 10390

It seems I could resolve this by initialising tiptap like this

this.editor = new Editor({
  content: '<p>This is just a boring paragraph.</p>',
  extensions: [new HighlightMark() as any]

Which is not ideal, but seems to be working for now.

If anyone can post the real solution I will mark it as the answer

Upvotes: 1

Related Questions