feat: add getText() and generateText() methods (fix #1428) (#1875)

* move getTextBetween method

* add getText method

* refactoring

* refactoring

* refactoring

* move renderText to schema, add generateText method

* add GenerateText demo

* docs: update

* remove demo from html page
This commit is contained in:
Philipp Kühn
2021-09-09 23:51:05 +02:00
committed by GitHub
parent 42e8755d87
commit fe6a3e7491
15 changed files with 241 additions and 64 deletions

View File

@@ -0,0 +1,29 @@
import { Node } from 'prosemirror-model'
import getSchema from './getSchema'
import { Extensions, JSONContent, TextSerializer } from '../types'
import getTextSeralizersFromSchema from './getTextSeralizersFromSchema'
import getText from './getText'
export default function generateText(
doc: JSONContent,
extensions: Extensions,
options?: {
blockSeparator?: string,
textSerializers?: Record<string, TextSerializer>,
},
): string {
const {
blockSeparator = '\n\n',
textSerializers = {},
} = options || {}
const schema = getSchema(extensions)
const contentNode = Node.fromJSON(schema, doc)
return getText(contentNode, {
blockSeparator,
textSerializers: {
...textSerializers,
...getTextSeralizersFromSchema(schema),
},
})
}

View File

@@ -77,6 +77,12 @@ export default function getSchemaByResolvedExtensions(extensions: Extensions): S
})
}
const renderText = getExtensionField<NodeConfig['renderText']>(extension, 'renderText', context)
if (renderText) {
schema.toText = renderText
}
return [extension.name, schema]
}))

View File

@@ -0,0 +1,18 @@
import { TextSerializer } from '../types'
import { Node as ProseMirrorNode } from 'prosemirror-model'
import getTextBetween from './getTextBetween'
export default function getText(
node: ProseMirrorNode,
options?: {
blockSeparator?: string,
textSerializers?: Record<string, TextSerializer>,
},
) {
const range = {
from: 0,
to: node.content.size,
}
return getTextBetween(node, range, options)
}

View File

@@ -0,0 +1,45 @@
import { Range, TextSerializer } from '../types'
import { Node as ProseMirrorNode } from 'prosemirror-model'
export default function getTextBetween(
startNode: ProseMirrorNode,
range: Range,
options?: {
blockSeparator?: string,
textSerializers?: Record<string, TextSerializer>,
},
): string {
const { from, to } = range
const {
blockSeparator = '\n\n',
textSerializers = {},
} = options || {}
let text = ''
let separated = true
startNode.nodesBetween(from, to, (node, pos, parent, index) => {
const textSerializer = textSerializers?.[node.type.name]
if (textSerializer) {
if (node.isBlock && !separated) {
text += blockSeparator
separated = true
}
text += textSerializer({
node,
pos,
parent,
index,
})
} else if (node.isText) {
text += node?.text?.slice(Math.max(from, pos) - pos, to - pos)
separated = false
} else if (node.isBlock && !separated) {
text += blockSeparator
separated = true
}
})
return text
}

View File

@@ -0,0 +1,9 @@
import { Schema } from 'prosemirror-model'
import { TextSerializer } from '../types'
export default function getTextSeralizersFromSchema(schema: Schema): Record<string, TextSerializer> {
return Object.fromEntries(Object
.entries(schema.nodes)
.filter(([, node]) => node.spec.toText)
.map(([name, node]) => [name, node.spec.toText]))
}