feat!: Replace defaultOptions with addOptions (#2088)

* add new addOptions option

* replace defaultOptions with addOptions for all extensions

* replace defaultOptions with addOptions for all demos

* replace defaultOptions with addOptions in docs

* refactoring

* refactoring

* drop object support for addOptions

* fix optional options

* fix tests
This commit is contained in:
Philipp Kühn 2021-10-26 18:31:13 +02:00 committed by GitHub
parent 2fff9c264b
commit 9afadeb7fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 622 additions and 233 deletions

View File

@ -59,12 +59,13 @@ declare module '@tiptap/core' {
} }
} }
export const CollaborationAnnotation = Extension.create({ export const CollaborationAnnotation = Extension.create<AnnotationOptions>({
name: 'annotation', name: 'annotation',
priority: 1000, priority: 1000,
defaultOptions: <AnnotationOptions>{ addOptions() {
return {
HTMLAttributes: { HTMLAttributes: {
class: 'annotation', class: 'annotation',
}, },
@ -73,6 +74,7 @@ export const CollaborationAnnotation = Extension.create({
field: 'annotations', field: 'annotations',
map: null, map: null,
instance: '', instance: '',
}
}, },
onCreate() { onCreate() {

View File

@ -2,16 +2,17 @@ import { Extension } from '@tiptap/core'
import Suggestion from '@tiptap/suggestion' import Suggestion from '@tiptap/suggestion'
export default Extension.create({ export default Extension.create({
name: 'mention', name: 'commands',
defaultOptions: { addOptions() {
return {
suggestion: { suggestion: {
char: '/', char: '/',
startOfLine: false,
command: ({ editor, range, props }) => { command: ({ editor, range, props }) => {
props.command({ editor, range }) props.command({ editor, range })
}, },
}, },
}
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {

View File

@ -17,8 +17,10 @@ export default Node.create<DetailsSummaryOptions>({
isolating: true, isolating: true,
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
parseHTML() { parseHTML() {

View File

@ -34,8 +34,10 @@ export default Node.create<DetailsOptions>({
// defining: true, // defining: true,
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
parseHTML() { parseHTML() {

View File

@ -18,18 +18,20 @@ declare module '@tiptap/core' {
} }
} }
export default Node.create({ export default Node.create<IframeOptions>({
name: 'iframe', name: 'iframe',
group: 'block', group: 'block',
atom: true, atom: true,
defaultOptions: <IframeOptions>{ addOptions() {
return {
allowFullscreen: true, allowFullscreen: true,
HTMLAttributes: { HTMLAttributes: {
class: 'iframe-wrapper', class: 'iframe-wrapper',
}, },
}
}, },
addAttributes() { addAttributes() {

View File

@ -41,8 +41,10 @@ export const inputRegex = /!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\)/
export const Figure = Node.create<FigureOptions>({ export const Figure = Node.create<FigureOptions>({
name: 'figure', name: 'figure',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
group: 'block', group: 'block',

View File

@ -3,8 +3,10 @@ import { Node, mergeAttributes } from '@tiptap/core'
export const Figcaption = Node.create({ export const Figcaption = Node.create({
name: 'figcaption', name: 'figcaption',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
content: 'inline*', content: 'inline*',

View File

@ -4,8 +4,10 @@ import { Plugin } from 'prosemirror-state'
export const Figure = Node.create({ export const Figure = Node.create({
name: 'figure', name: 'figure',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
group: 'block', group: 'block',

View File

@ -39,11 +39,13 @@ export interface LinterOptions {
plugins: Array<typeof LinterPlugin>, plugins: Array<typeof LinterPlugin>,
} }
export const Linter = Extension.create({ export const Linter = Extension.create<LinterOptions>({
name: 'linter', name: 'linter',
defaultOptions: <LinterOptions>{ addOptions() {
return {
plugins: [], plugins: [],
}
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {

View File

@ -20,11 +20,13 @@ export interface TrailingNodeOptions {
export const TrailingNode = Extension.create<TrailingNodeOptions>({ export const TrailingNode = Extension.create<TrailingNodeOptions>({
name: 'trailingNode', name: 'trailingNode',
defaultOptions: { addOptions() {
return {
node: 'paragraph', node: 'paragraph',
notAfter: [ notAfter: [
'paragraph', 'paragraph',
], ],
}
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {

View File

@ -71,9 +71,11 @@ All settings can be configured through the extension anyway, but if you want to
import Heading from '@tiptap/extension-heading' import Heading from '@tiptap/extension-heading'
const CustomHeading = Heading.extend({ const CustomHeading = Heading.extend({
defaultOptions: { addOptions() {
...Heading.options, return {
...this.parent(),
levels: [1, 2, 3], levels: [1, 2, 3],
}
}, },
}) })
``` ```

View File

@ -26,8 +26,10 @@ export interface CustomExtensionOptions {
} }
const CustomExtension = Extension.create<CustomExtensionOptions>({ const CustomExtension = Extension.create<CustomExtensionOptions>({
defaultOptions: { addOptions() {
return {
awesomeness: 100, awesomeness: 100,
}
}, },
}) })
``` ```

View File

@ -103,7 +103,7 @@ import { Node } from '@tiptap/core'
const CustomExtension = Node.create({ const CustomExtension = Node.create({
name: 'custom_extension', name: 'custom_extension',
defaultOptions: { addOptions() {
}, },
addAttributes() { addAttributes() {

View File

@ -36,13 +36,21 @@ declare module '@tiptap/core' {
*/ */
defaultOptions?: Options, defaultOptions?: Options,
/**
* Default Options
*/
addOptions?: (this: {
name: string,
parent: Exclude<ParentConfig<ExtensionConfig<Options, Storage>>['addOptions'], undefined>,
}) => Options,
/** /**
* Default Storage * Default Storage
*/ */
addStorage?: (this: { addStorage?: (this: {
name: string, name: string,
options: Options, options: Options,
parent: ParentConfig<ExtensionConfig<Options, Storage>>['addGlobalAttributes'], parent: Exclude<ParentConfig<ExtensionConfig<Options, Storage>>['addStorage'], undefined>,
}) => Storage, }) => Storage,
/** /**
@ -278,7 +286,24 @@ export class Extension<Options = any, Storage = any> {
} }
this.name = this.config.name this.name = this.config.name
if (config.defaultOptions) {
console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`)
}
// TODO: remove `addOptions` fallback
this.options = this.config.defaultOptions this.options = this.config.defaultOptions
if (this.config.addOptions) {
this.options = callOrReturn(getExtensionField<AnyConfig['addOptions']>(
this,
'addOptions',
{
name: this.name,
},
))
}
this.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>( this.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>(
this, this,
'addStorage', 'addStorage',
@ -286,7 +311,7 @@ export class Extension<Options = any, Storage = any> {
name: this.name, name: this.name,
options: this.options, options: this.options,
}, },
)) )) || {}
} }
static create<O = any, S = any>(config: Partial<ExtensionConfig<O, S>> = {}) { static create<O = any, S = any>(config: Partial<ExtensionConfig<O, S>> = {}) {
@ -323,10 +348,25 @@ export class Extension<Options = any, Storage = any> {
? extendedConfig.name ? extendedConfig.name
: extension.parent.name : extension.parent.name
if (extendedConfig.defaultOptions) {
console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`)
}
// TODO: remove `addOptions` fallback
extension.options = extendedConfig.defaultOptions extension.options = extendedConfig.defaultOptions
? extendedConfig.defaultOptions ? extendedConfig.defaultOptions
: extension.parent.options : extension.parent.options
if (extendedConfig.addOptions) {
extension.options = callOrReturn(getExtensionField<AnyConfig['addOptions']>(
extension,
'addOptions',
{
name: extension.name,
},
))
}
extension.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>( extension.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>(
extension, extension,
'addStorage', 'addStorage',

View File

@ -42,13 +42,21 @@ declare module '@tiptap/core' {
*/ */
defaultOptions?: Options, defaultOptions?: Options,
/**
* Default Options
*/
addOptions?: (this: {
name: string,
parent: Exclude<ParentConfig<MarkConfig<Options, Storage>>['addOptions'], undefined>,
}) => Options,
/** /**
* Default Storage * Default Storage
*/ */
addStorage?: (this: { addStorage?: (this: {
name: string, name: string,
options: Options, options: Options,
parent: ParentConfig<MarkConfig<Options, Storage>>['addGlobalAttributes'], parent: Exclude<ParentConfig<MarkConfig<Options, Storage>>['addStorage'], undefined>,
}) => Storage, }) => Storage,
/** /**
@ -392,7 +400,24 @@ export class Mark<Options = any, Storage = any> {
} }
this.name = this.config.name this.name = this.config.name
if (config.defaultOptions) {
console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`)
}
// TODO: remove `addOptions` fallback
this.options = this.config.defaultOptions this.options = this.config.defaultOptions
if (this.config.addOptions) {
this.options = callOrReturn(getExtensionField<AnyConfig['addOptions']>(
this,
'addOptions',
{
name: this.name,
},
))
}
this.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>( this.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>(
this, this,
'addStorage', 'addStorage',
@ -400,7 +425,7 @@ export class Mark<Options = any, Storage = any> {
name: this.name, name: this.name,
options: this.options, options: this.options,
}, },
)) )) || {}
} }
static create<O = any, S = any>(config: Partial<MarkConfig<O, S>> = {}) { static create<O = any, S = any>(config: Partial<MarkConfig<O, S>> = {}) {
@ -437,10 +462,25 @@ export class Mark<Options = any, Storage = any> {
? extendedConfig.name ? extendedConfig.name
: extension.parent.name : extension.parent.name
if (extendedConfig.defaultOptions) {
console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`)
}
// TODO: remove `addOptions` fallback
extension.options = extendedConfig.defaultOptions extension.options = extendedConfig.defaultOptions
? extendedConfig.defaultOptions ? extendedConfig.defaultOptions
: extension.parent.options : extension.parent.options
if (extendedConfig.addOptions) {
extension.options = callOrReturn(getExtensionField<AnyConfig['addOptions']>(
extension,
'addOptions',
{
name: extension.name,
},
))
}
extension.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>( extension.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>(
extension, extension,
'addStorage', 'addStorage',

View File

@ -42,13 +42,21 @@ declare module '@tiptap/core' {
*/ */
defaultOptions?: Options, defaultOptions?: Options,
/**
* Default Options
*/
addOptions?: (this: {
name: string,
parent: Exclude<ParentConfig<NodeConfig<Options, Storage>>['addOptions'], undefined>,
}) => Options,
/** /**
* Default Storage * Default Storage
*/ */
addStorage?: (this: { addStorage?: (this: {
name: string, name: string,
options: Options, options: Options,
parent: ParentConfig<NodeConfig<Options, Storage>>['addGlobalAttributes'], parent: Exclude<ParentConfig<NodeConfig<Options, Storage>>['addStorage'], undefined>,
}) => Storage, }) => Storage,
/** /**
@ -472,7 +480,24 @@ export class Node<Options = any, Storage = any> {
} }
this.name = this.config.name this.name = this.config.name
if (config.defaultOptions) {
console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`)
}
// TODO: remove `addOptions` fallback
this.options = this.config.defaultOptions this.options = this.config.defaultOptions
if (this.config.addOptions) {
this.options = callOrReturn(getExtensionField<AnyConfig['addOptions']>(
this,
'addOptions',
{
name: this.name,
},
))
}
this.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>( this.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>(
this, this,
'addStorage', 'addStorage',
@ -480,7 +505,7 @@ export class Node<Options = any, Storage = any> {
name: this.name, name: this.name,
options: this.options, options: this.options,
}, },
)) )) || {}
} }
static create<O = any, S = any>(config: Partial<NodeConfig<O, S>> = {}) { static create<O = any, S = any>(config: Partial<NodeConfig<O, S>> = {}) {
@ -517,10 +542,25 @@ export class Node<Options = any, Storage = any> {
? extendedConfig.name ? extendedConfig.name
: extension.parent.name : extension.parent.name
if (extendedConfig.defaultOptions) {
console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`)
}
// TODO: remove `addOptions` fallback
extension.options = extendedConfig.defaultOptions extension.options = extendedConfig.defaultOptions
? extendedConfig.defaultOptions ? extendedConfig.defaultOptions
: extension.parent.options : extension.parent.options
if (extendedConfig.addOptions) {
extension.options = callOrReturn(getExtensionField<AnyConfig['addOptions']>(
extension,
'addOptions',
{
name: extension.name,
},
))
}
extension.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>( extension.storage = callOrReturn(getExtensionField<AnyConfig['addStorage']>(
extension, extension,
'addStorage', 'addStorage',

View File

@ -29,8 +29,10 @@ export const Blockquote = Node.create<BlockquoteOptions>({
name: 'blockquote', name: 'blockquote',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
content: 'block*', content: 'block*',

View File

@ -36,8 +36,10 @@ export const underscorePasteRegex = /(?:^|\s)((?:__)((?:[^__]+))(?:__))/g
export const Bold = Mark.create<BoldOptions>({ export const Bold = Mark.create<BoldOptions>({
name: 'bold', name: 'bold',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
parseHTML() { parseHTML() {

View File

@ -8,11 +8,13 @@ export type BubbleMenuOptions = Omit<BubbleMenuPluginProps, 'editor' | 'element'
export const BubbleMenu = Extension.create<BubbleMenuOptions>({ export const BubbleMenu = Extension.create<BubbleMenuOptions>({
name: 'bubbleMenu', name: 'bubbleMenu',
defaultOptions: { addOptions() {
return {
element: null, element: null,
tippyOptions: {}, tippyOptions: {},
pluginKey: 'bubbleMenu', pluginKey: 'bubbleMenu',
shouldShow: null, shouldShow: null,
}
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {

View File

@ -20,8 +20,10 @@ export const inputRegex = /^\s*([-+*])\s$/
export const BulletList = Node.create<BulletListOptions>({ export const BulletList = Node.create<BulletListOptions>({
name: 'bulletList', name: 'bulletList',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
group: 'block list', group: 'block list',

View File

@ -10,8 +10,10 @@ export interface CharacterCountOptions {
export const CharacterCount = Extension.create<CharacterCountOptions>({ export const CharacterCount = Extension.create<CharacterCountOptions>({
name: 'characterCount', name: 'characterCount',
defaultOptions: { addOptions() {
return {
limit: 0, limit: 0,
}
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {

View File

@ -7,9 +7,11 @@ export interface CodeBlockLowlightOptions extends CodeBlockOptions {
} }
export const CodeBlockLowlight = CodeBlock.extend<CodeBlockLowlightOptions>({ export const CodeBlockLowlight = CodeBlock.extend<CodeBlockLowlightOptions>({
defaultOptions: { addOptions() {
...CodeBlock.options, return {
...this.parent?.(),
lowlight, lowlight,
}
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {

View File

@ -27,9 +27,11 @@ export const tildeInputRegex = /^~~~(?<language>[a-z]*)?[\s\n]$/
export const CodeBlock = Node.create<CodeBlockOptions>({ export const CodeBlock = Node.create<CodeBlockOptions>({
name: 'codeBlock', name: 'codeBlock',
defaultOptions: { addOptions() {
return {
languageClassPrefix: 'language-', languageClassPrefix: 'language-',
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
content: 'text*', content: 'text*',

View File

@ -34,8 +34,10 @@ export const pasteRegex = /(?:^|\s)((?:`)((?:[^`]+))(?:`))/g
export const Code = Mark.create<CodeOptions>({ export const Code = Mark.create<CodeOptions>({
name: 'code', name: 'code',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
excludes: '_', excludes: '_',

View File

@ -31,7 +31,8 @@ const awarenessStatesToArray = (states: Map<number, Record<string, any>>) => {
export const CollaborationCursor = Extension.create<CollaborationCursorOptions>({ export const CollaborationCursor = Extension.create<CollaborationCursorOptions>({
name: 'collaborationCursor', name: 'collaborationCursor',
defaultOptions: { addOptions() {
return {
provider: null, provider: null,
user: { user: {
name: null, name: null,
@ -51,6 +52,7 @@ export const CollaborationCursor = Extension.create<CollaborationCursorOptions>(
return cursor return cursor
}, },
onUpdate: () => null, onUpdate: () => null,
}
}, },
addCommands() { addCommands() {

View File

@ -43,10 +43,12 @@ export const Collaboration = Extension.create<CollaborationOptions>({
priority: 1000, priority: 1000,
defaultOptions: { addOptions() {
return {
document: null, document: null,
field: 'default', field: 'default',
fragment: null, fragment: null,
}
}, },
onCreate() { onCreate() {

View File

@ -23,8 +23,10 @@ declare module '@tiptap/core' {
export const Color = Extension.create<ColorOptions>({ export const Color = Extension.create<ColorOptions>({
name: 'color', name: 'color',
defaultOptions: { addOptions() {
return {
types: ['textStyle'], types: ['textStyle'],
}
}, },
addGlobalAttributes() { addGlobalAttributes() {

View File

@ -10,10 +10,12 @@ export interface DropcursorOptions {
export const Dropcursor = Extension.create<DropcursorOptions>({ export const Dropcursor = Extension.create<DropcursorOptions>({
name: 'dropCursor', name: 'dropCursor',
defaultOptions: { addOptions() {
return {
color: 'currentColor', color: 'currentColor',
width: 1, width: 1,
class: null, class: null,
}
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {

View File

@ -8,11 +8,13 @@ export type FloatingMenuOptions = Omit<FloatingMenuPluginProps, 'editor' | 'elem
export const FloatingMenu = Extension.create<FloatingMenuOptions>({ export const FloatingMenu = Extension.create<FloatingMenuOptions>({
name: 'floatingMenu', name: 'floatingMenu',
defaultOptions: { addOptions() {
return {
element: null, element: null,
tippyOptions: {}, tippyOptions: {},
pluginKey: 'floatingMenu', pluginKey: 'floatingMenu',
shouldShow: null, shouldShow: null,
}
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {

View File

@ -10,9 +10,11 @@ export interface FocusOptions {
export const FocusClasses = Extension.create<FocusOptions>({ export const FocusClasses = Extension.create<FocusOptions>({
name: 'focus', name: 'focus',
defaultOptions: { addOptions() {
return {
className: 'has-focus', className: 'has-focus',
mode: 'all', mode: 'all',
}
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {

View File

@ -23,8 +23,10 @@ declare module '@tiptap/core' {
export const FontFamily = Extension.create<FontFamilyOptions>({ export const FontFamily = Extension.create<FontFamilyOptions>({
name: 'fontFamily', name: 'fontFamily',
defaultOptions: { addOptions() {
return {
types: ['textStyle'], types: ['textStyle'],
}
}, },
addGlobalAttributes() { addGlobalAttributes() {

View File

@ -19,9 +19,11 @@ declare module '@tiptap/core' {
export const HardBreak = Node.create<HardBreakOptions>({ export const HardBreak = Node.create<HardBreakOptions>({
name: 'hardBreak', name: 'hardBreak',
defaultOptions: { addOptions() {
return {
keepMarks: true, keepMarks: true,
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
inline: true, inline: true,

View File

@ -25,9 +25,11 @@ declare module '@tiptap/core' {
export const Heading = Node.create<HeadingOptions>({ export const Heading = Node.create<HeadingOptions>({
name: 'heading', name: 'heading',
defaultOptions: { addOptions() {
return {
levels: [1, 2, 3, 4, 5, 6], levels: [1, 2, 3, 4, 5, 6],
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
content: 'inline*', content: 'inline*',

View File

@ -35,9 +35,11 @@ export const pasteRegex = /(?:^|\s)((?:==)((?:[^~]+))(?:==))/g
export const Highlight = Mark.create<HighlightOptions>({ export const Highlight = Mark.create<HighlightOptions>({
name: 'highlight', name: 'highlight',
defaultOptions: { addOptions() {
return {
multicolor: false, multicolor: false,
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
addAttributes() { addAttributes() {

View File

@ -24,9 +24,11 @@ declare module '@tiptap/core' {
export const History = Extension.create<HistoryOptions>({ export const History = Extension.create<HistoryOptions>({
name: 'history', name: 'history',
defaultOptions: { addOptions() {
return {
depth: 100, depth: 100,
newGroupDelay: 500, newGroupDelay: 500,
}
}, },
addCommands() { addCommands() {

View File

@ -23,8 +23,10 @@ declare module '@tiptap/core' {
export const HorizontalRule = Node.create<HorizontalRuleOptions>({ export const HorizontalRule = Node.create<HorizontalRuleOptions>({
name: 'horizontalRule', name: 'horizontalRule',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
group: 'block', group: 'block',

View File

@ -25,9 +25,11 @@ export const inputRegex = /(!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\))/
export const Image = Node.create<ImageOptions>({ export const Image = Node.create<ImageOptions>({
name: 'image', name: 'image',
defaultOptions: { addOptions() {
return {
inline: false, inline: false,
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
inline() { inline() {

View File

@ -36,8 +36,10 @@ export const underscorePasteRegex = /(?:^|\s)((?:_)((?:[^_]+))(?:_))/g
export const Italic = Mark.create<ItalicOptions>({ export const Italic = Mark.create<ItalicOptions>({
name: 'italic', name: 'italic',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
parseHTML() { parseHTML() {

View File

@ -47,13 +47,15 @@ export const Link = Mark.create<LinkOptions>({
inclusive: false, inclusive: false,
defaultOptions: { addOptions() {
return {
openOnClick: true, openOnClick: true,
linkOnPaste: true, linkOnPaste: true,
HTMLAttributes: { HTMLAttributes: {
target: '_blank', target: '_blank',
rel: 'noopener noreferrer nofollow', rel: 'noopener noreferrer nofollow',
}, },
}
}, },
addAttributes() { addAttributes() {

View File

@ -7,8 +7,10 @@ export interface ListItemOptions {
export const ListItem = Node.create<ListItemOptions>({ export const ListItem = Node.create<ListItemOptions>({
name: 'listItem', name: 'listItem',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
content: 'paragraph block*', content: 'paragraph block*',

View File

@ -17,7 +17,8 @@ export const MentionPluginKey = new PluginKey('mention')
export const Mention = Node.create<MentionOptions>({ export const Mention = Node.create<MentionOptions>({
name: 'mention', name: 'mention',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
renderLabel({ options, node }) { renderLabel({ options, node }) {
return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}` return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`
@ -40,7 +41,7 @@ export const Mention = Node.create<MentionOptions>({
.focus() .focus()
.insertContentAt(range, [ .insertContentAt(range, [
{ {
type: 'mention', type: this.name,
attrs: props, attrs: props,
}, },
{ {
@ -52,12 +53,13 @@ export const Mention = Node.create<MentionOptions>({
}, },
allow: ({ editor, range }) => { allow: ({ editor, range }) => {
const $from = editor.state.doc.resolve(range.from) const $from = editor.state.doc.resolve(range.from)
const type = editor.schema.nodes.mention const type = editor.schema.nodes[this.name]
const allow = !!$from.parent.type.contentMatch.matchType(type) const allow = !!$from.parent.type.contentMatch.matchType(type)
return allow return allow
}, },
}, },
}
}, },
group: 'inline', group: 'inline',

View File

@ -20,8 +20,10 @@ export const inputRegex = /^(\d+)\.\s$/
export const OrderedList = Node.create<OrderedListOptions>({ export const OrderedList = Node.create<OrderedListOptions>({
name: 'orderedList', name: 'orderedList',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
group: 'block list', group: 'block list',

View File

@ -20,8 +20,10 @@ export const Paragraph = Node.create<ParagraphOptions>({
priority: 1000, priority: 1000,
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
group: 'block', group: 'block',

View File

@ -19,13 +19,15 @@ export interface PlaceholderOptions {
export const Placeholder = Extension.create<PlaceholderOptions>({ export const Placeholder = Extension.create<PlaceholderOptions>({
name: 'placeholder', name: 'placeholder',
defaultOptions: { addOptions() {
return {
emptyEditorClass: 'is-editor-empty', emptyEditorClass: 'is-editor-empty',
emptyNodeClass: 'is-empty', emptyNodeClass: 'is-empty',
placeholder: 'Write something …', placeholder: 'Write something …',
showOnlyWhenEditable: true, showOnlyWhenEditable: true,
showOnlyCurrent: true, showOnlyCurrent: true,
includeChildren: false, includeChildren: false,
}
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {

View File

@ -34,8 +34,10 @@ export const pasteRegex = /(?:^|\s)((?:~~)((?:[^~]+))(?:~~))/g
export const Strike = Mark.create<StrikeOptions>({ export const Strike = Mark.create<StrikeOptions>({
name: 'strike', name: 'strike',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
parseHTML() { parseHTML() {

View File

@ -26,8 +26,10 @@ declare module '@tiptap/core' {
export const Subscript = Mark.create<SubscriptExtensionOptions>({ export const Subscript = Mark.create<SubscriptExtensionOptions>({
name: 'subscript', name: 'subscript',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
parseHTML() { parseHTML() {

View File

@ -26,8 +26,10 @@ declare module '@tiptap/core' {
export const Superscript = Mark.create<SuperscriptExtensionOptions>({ export const Superscript = Mark.create<SuperscriptExtensionOptions>({
name: 'superscript', name: 'superscript',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
parseHTML() { parseHTML() {

View File

@ -7,8 +7,10 @@ export interface TableCellOptions {
export const TableCell = Node.create<TableCellOptions>({ export const TableCell = Node.create<TableCellOptions>({
name: 'tableCell', name: 'tableCell',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
content: 'block+', content: 'block+',

View File

@ -6,8 +6,10 @@ export interface TableHeaderOptions {
export const TableHeader = Node.create<TableHeaderOptions>({ export const TableHeader = Node.create<TableHeaderOptions>({
name: 'tableHeader', name: 'tableHeader',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
content: 'block+', content: 'block+',

View File

@ -7,8 +7,10 @@ export interface TableRowOptions {
export const TableRow = Node.create<TableRowOptions>({ export const TableRow = Node.create<TableRowOptions>({
name: 'tableRow', name: 'tableRow',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
content: '(tableCell | tableHeader)*', content: '(tableCell | tableHeader)*',

View File

@ -82,16 +82,18 @@ declare module '@tiptap/core' {
export const Table = Node.create<TableOptions>({ export const Table = Node.create<TableOptions>({
name: 'table', name: 'table',
defaultOptions: { // @ts-ignore
addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
resizable: false, resizable: false,
handleWidth: 5, handleWidth: 5,
cellMinWidth: 25, cellMinWidth: 25,
// TODO: fix // TODO: fix
// @ts-ignore
View: TableView, View: TableView,
lastColumnResizable: true, lastColumnResizable: true,
allowTableNodeSelection: false, allowTableNodeSelection: false,
}
}, },
content: 'tableRow+', content: 'tableRow+',

View File

@ -10,9 +10,11 @@ export const inputRegex = /^\s*(\[([ |x])\])\s$/
export const TaskItem = Node.create<TaskItemOptions>({ export const TaskItem = Node.create<TaskItemOptions>({
name: 'taskItem', name: 'taskItem',
defaultOptions: { addOptions() {
return {
nested: false, nested: false,
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
content() { content() {

View File

@ -18,8 +18,10 @@ declare module '@tiptap/core' {
export const TaskList = Node.create<TaskListOptions>({ export const TaskList = Node.create<TaskListOptions>({
name: 'taskList', name: 'taskList',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
group: 'block list', group: 'block list',

View File

@ -24,10 +24,12 @@ declare module '@tiptap/core' {
export const TextAlign = Extension.create<TextAlignOptions>({ export const TextAlign = Extension.create<TextAlignOptions>({
name: 'textAlign', name: 'textAlign',
defaultOptions: { addOptions() {
return {
types: [], types: [],
alignments: ['left', 'center', 'right', 'justify'], alignments: ['left', 'center', 'right', 'justify'],
defaultAlignment: 'left', defaultAlignment: 'left',
}
}, },
addGlobalAttributes() { addGlobalAttributes() {

View File

@ -22,8 +22,10 @@ declare module '@tiptap/core' {
export const TextStyle = Mark.create<TextStyleOptions>({ export const TextStyle = Mark.create<TextStyleOptions>({
name: 'textStyle', name: 'textStyle',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
parseHTML() { parseHTML() {

View File

@ -26,8 +26,10 @@ declare module '@tiptap/core' {
export const Underline = Mark.create<UnderlineOptions>({ export const Underline = Mark.create<UnderlineOptions>({
name: 'underline', name: 'underline',
defaultOptions: { addOptions() {
return {
HTMLAttributes: {}, HTMLAttributes: {},
}
}, },
parseHTML() { parseHTML() {

View File

@ -3,7 +3,7 @@
import { Extension } from '@tiptap/core/src/Extension' import { Extension } from '@tiptap/core/src/Extension'
describe('extension options', () => { describe('extension options', () => {
it('should set options', () => { it('should set options (deprecated)', () => {
const extension = Extension.create({ const extension = Extension.create({
defaultOptions: { defaultOptions: {
foo: 1, foo: 1,
@ -17,7 +17,23 @@ describe('extension options', () => {
}) })
}) })
it('should pass through', () => { it('should set options', () => {
const extension = Extension.create({
addOptions() {
return {
foo: 1,
bar: 1,
}
},
})
expect(extension.options).to.deep.eq({
foo: 1,
bar: 1,
})
})
it('should pass through (deprecated)', () => {
const extension = Extension const extension = Extension
.create({ .create({
defaultOptions: { defaultOptions: {
@ -34,7 +50,26 @@ describe('extension options', () => {
}) })
}) })
it('should be configurable', () => { it('should pass through', () => {
const extension = Extension
.create({
addOptions() {
return {
foo: 1,
bar: 1,
}
},
})
.extend()
.configure()
expect(extension.options).to.deep.eq({
foo: 1,
bar: 1,
})
})
it('should be configurable (deprecated)', () => {
const extension = Extension const extension = Extension
.create({ .create({
defaultOptions: { defaultOptions: {
@ -52,7 +87,27 @@ describe('extension options', () => {
}) })
}) })
it('should be extendable', () => { it('should be configurable', () => {
const extension = Extension
.create({
addOptions() {
return {
foo: 1,
bar: 1,
}
},
})
.configure({
bar: 2,
})
expect(extension.options).to.deep.eq({
foo: 1,
bar: 2,
})
})
it('should be extendable (deprecated)', () => {
const extension = Extension.create({ const extension = Extension.create({
defaultOptions: { defaultOptions: {
foo: 1, foo: 1,
@ -74,7 +129,33 @@ describe('extension options', () => {
}) })
}) })
it('should be overwritable', () => { it('should be extendable', () => {
const extension = Extension.create({
addOptions() {
return {
foo: 1,
bar: 1,
}
},
})
const newExtension = extension.extend({
addOptions() {
return {
...this.parent?.(),
baz: 1,
}
},
})
expect(newExtension.options).to.deep.eq({
foo: 1,
bar: 1,
baz: 1,
})
})
it('should be overwritable (deprecated)', () => {
const extension = Extension const extension = Extension
.create({ .create({
defaultOptions: { defaultOptions: {
@ -93,7 +174,30 @@ describe('extension options', () => {
}) })
}) })
it('should configure nested objects', () => { it('should be overwritable', () => {
const extension = Extension
.create({
addOptions() {
return {
foo: 1,
bar: 1,
}
},
})
.extend({
addOptions() {
return {
baz: 1,
}
},
})
expect(extension.options).to.deep.eq({
baz: 1,
})
})
it('should configure nested objects (deprecated)', () => {
const extension = Extension const extension = Extension
.create<{ .create<{
foo: number[], foo: number[],
@ -122,7 +226,38 @@ describe('extension options', () => {
}) })
}) })
it('should create its own instance on configure', () => { it('should configure nested objects', () => {
const extension = Extension
.create<{
foo: number[],
HTMLAttributes: Record<string, any>,
}>({
addOptions() {
return {
foo: [1, 2, 3],
HTMLAttributes: {
class: 'foo',
},
}
},
})
.configure({
foo: [1],
HTMLAttributes: {
id: 'bar',
},
})
expect(extension.options).to.deep.eq({
foo: [1],
HTMLAttributes: {
class: 'foo',
id: 'bar',
},
})
})
it('should create its own instance on configure (deprecated)', () => {
const extension = Extension const extension = Extension
.create({ .create({
defaultOptions: { defaultOptions: {
@ -150,4 +285,35 @@ describe('extension options', () => {
bar: 2, bar: 2,
}) })
}) })
it('should create its own instance on configure', () => {
const extension = Extension
.create({
addOptions() {
return {
foo: 1,
bar: 2,
}
},
})
const extension1 = extension.configure({
foo: 2,
bar: 4,
})
const extension2 = extension.configure({
foo: 3,
})
expect(extension1.options).to.deep.eq({
foo: 2,
bar: 4,
})
expect(extension2.options).to.deep.eq({
foo: 3,
bar: 2,
})
})
}) })