From 5dcbdebbb790ec2f664d9ecdb77a07894ab36936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 21 Oct 2020 23:55:14 +0200 Subject: [PATCH] add global attributes --- packages/core/src/Extension.ts | 8 ++++ packages/core/src/Mark.ts | 7 ++++ packages/core/src/Node.ts | 1 + packages/core/src/types.ts | 9 ++++- .../src/utils/getAttributesFromExtensions.ts | 40 +++++++++++++++---- .../core/src/utils/getRenderedAttributes.ts | 2 +- packages/extension-paragraph/index.ts | 21 +++++++++- 7 files changed, 77 insertions(+), 11 deletions(-) diff --git a/packages/core/src/Extension.ts b/packages/core/src/Extension.ts index 9289e812..9ed640ba 100644 --- a/packages/core/src/Extension.ts +++ b/packages/core/src/Extension.ts @@ -113,9 +113,16 @@ // } // } +import { GlobalAttributes } from './types' + export interface ExtensionSpec { name: string, defaultOptions?: Options, + createGlobalAttributes?: ( + this: { + options: Options, + }, + ) => GlobalAttributes, createCommands?(this: { options: Options, // editor: Editor, @@ -133,6 +140,7 @@ const defaultExtension: Extension = { type: 'extension', name: 'extension', options: {}, + createGlobalAttributes: () => [], createCommands: () => ({}), } diff --git a/packages/core/src/Mark.ts b/packages/core/src/Mark.ts index 09ea5345..64a47914 100644 --- a/packages/core/src/Mark.ts +++ b/packages/core/src/Mark.ts @@ -49,6 +49,7 @@ import { DOMOutputSpec, MarkSpec, Mark } from 'prosemirror-model' import { ExtensionSpec } from './Extension' +import { Attributes } from './types' export interface MarkExtensionSpec extends ExtensionSpec { inclusive?: MarkSpec['inclusive'], @@ -71,6 +72,11 @@ export interface MarkExtensionSpec extends Extensio }, } ) => DOMOutputSpec, + createAttributes?: ( + this: { + options: Options, + }, + ) => Attributes, } export type MarkExtension = Required & { @@ -88,6 +94,7 @@ const defaultMark: MarkExtension = { excludes: null, group: null, spanning: null, + createGlobalAttributes: () => [], createCommands: () => ({}), parseHTML: () => null, renderHTML: () => null, diff --git a/packages/core/src/Node.ts b/packages/core/src/Node.ts index 4458edbd..df8cd74c 100644 --- a/packages/core/src/Node.ts +++ b/packages/core/src/Node.ts @@ -130,6 +130,7 @@ const defaultNode: NodeExtension = { code: null, defining: null, isolating: null, + createGlobalAttributes: () => [], createCommands: () => ({}), parseHTML: () => null, renderHTML: () => null, diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index f2edacc4..43887d50 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -14,11 +14,16 @@ export type Attribute = { } export type Attributes = { - [key: string]: Attribute + [key: string]: Attribute, } export type ExtensionAttribute = { type: string, name: string, - attribute: Attribute + attribute: Attribute, } + +export type GlobalAttributes = { + types: string[], + attributes: Attributes, +}[] diff --git a/packages/core/src/utils/getAttributesFromExtensions.ts b/packages/core/src/utils/getAttributesFromExtensions.ts index 6eae27be..4cd83410 100644 --- a/packages/core/src/utils/getAttributesFromExtensions.ts +++ b/packages/core/src/utils/getAttributesFromExtensions.ts @@ -1,13 +1,16 @@ -import { - Extensions, Attributes, Attribute, ExtensionAttribute, -} from '../types' import splitExtensions from './splitExtensions' +import { + Extensions, + GlobalAttributes, + Attributes, + Attribute, + ExtensionAttribute, +} from '../types' export default function getAttributesFromExtensions(extensions: Extensions) { const allAttributes: ExtensionAttribute[] = [] - - const { nodeExtensions } = splitExtensions(extensions) - + const { nodeExtensions, markExtensions } = splitExtensions(extensions) + const nodeAndMarkExtensions = [...nodeExtensions, ...markExtensions] const defaultAttribute: Required = { default: null, rendered: true, @@ -15,7 +18,30 @@ export default function getAttributesFromExtensions(extensions: Extensions) { parseHTML: () => null, } - nodeExtensions.forEach(extension => { + extensions.forEach(extension => { + const context = { + options: extension.options, + } + + const globalAttributes = extension.createGlobalAttributes.bind(context)() as GlobalAttributes + + globalAttributes.forEach(globalAttribute => { + globalAttribute.types.forEach(type => { + Object.entries(globalAttribute.attributes).forEach(([name, attribute]) => { + allAttributes.push({ + type, + name, + attribute: { + ...defaultAttribute, + ...attribute, + }, + }) + }) + }) + }) + }) + + nodeAndMarkExtensions.forEach(extension => { const context = { options: extension.options, } diff --git a/packages/core/src/utils/getRenderedAttributes.ts b/packages/core/src/utils/getRenderedAttributes.ts index e7ffd6ee..bfb9a709 100644 --- a/packages/core/src/utils/getRenderedAttributes.ts +++ b/packages/core/src/utils/getRenderedAttributes.ts @@ -9,7 +9,7 @@ export default function getRenderedAttributes(node: Node, attributes: ExtensionA return item.attribute.renderHTML(node.attrs) }) .reduce((accumulator, value) => { - // TODO: add support for "class" merge + // TODO: add support for "class" and "style" merge return { ...accumulator, ...value, diff --git a/packages/extension-paragraph/index.ts b/packages/extension-paragraph/index.ts index efa65eba..cb9ecf71 100644 --- a/packages/extension-paragraph/index.ts +++ b/packages/extension-paragraph/index.ts @@ -65,12 +65,31 @@ export default createNode({ content: 'inline*', + createGlobalAttributes() { + return [ + { + types: ['paragraph'], + attributes: { + align: { + default: 'right', + renderHTML: attributes => ({ + style: `text-align: ${attributes.align}`, + }), + }, + }, + }, + ] + }, + createAttributes() { return { id: { default: '123', rendered: true, - renderHTML: attributes => ({ class: `foo-${attributes.id}`, id: 'foo' }), + renderHTML: attributes => ({ + class: `foo-${attributes.id}`, + id: 'foo', + }), }, } },