mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-06-13 05:11:04 +08:00
feat(core): add rewriteUnknownContent
utility for cleaning JSON (#5915)
Some checks are pending
build / lint (20) (push) Waiting to run
build / test (20, map[name:Demos/Examples spec:./demos/src/Examples/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/Experiments spec:./demos/src/Experiments/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/Extensions spec:./demos/src/Extensions/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/GuideContent spec:./demos/src/GuideContent/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/GuideGettingStarted spec:./demos/src/GuideGettingStarted/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/Marks spec:./demos/src/Marks/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/Nodes spec:./demos/src/Nodes/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Integration spec:./tests/cypress/integration/**/*.spec.{js,ts}]) (push) Waiting to run
build / build (20) (push) Blocked by required conditions
Publish / Release (20) (push) Waiting to run
Some checks are pending
build / lint (20) (push) Waiting to run
build / test (20, map[name:Demos/Examples spec:./demos/src/Examples/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/Experiments spec:./demos/src/Experiments/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/Extensions spec:./demos/src/Extensions/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/GuideContent spec:./demos/src/GuideContent/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/GuideGettingStarted spec:./demos/src/GuideGettingStarted/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/Marks spec:./demos/src/Marks/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Demos/Nodes spec:./demos/src/Nodes/**/*.spec.{js,ts}]) (push) Waiting to run
build / test (20, map[name:Integration spec:./tests/cypress/integration/**/*.spec.{js,ts}]) (push) Waiting to run
build / build (20) (push) Blocked by required conditions
Publish / Release (20) (push) Waiting to run
This commit is contained in:
parent
d1b7dd238d
commit
8c619c6f96
5
.changeset/violet-foxes-fetch.md
Normal file
5
.changeset/violet-foxes-fetch.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tiptap/core": patch
|
||||
---
|
||||
|
||||
Add `rewriteUnknownContent` helper, which can strip your editor JSON of content which is invalid within the current editor's schema
|
@ -46,5 +46,6 @@ export * from './isNodeSelection.js'
|
||||
export * from './isTextSelection.js'
|
||||
export * from './posToDOMRect.js'
|
||||
export * from './resolveFocusPosition.js'
|
||||
export * from './rewriteUnknownContent.js'
|
||||
export * from './selectionToInsertionEnd.js'
|
||||
export * from './splitExtensions.js'
|
||||
|
148
packages/core/src/helpers/rewriteUnknownContent.ts
Normal file
148
packages/core/src/helpers/rewriteUnknownContent.ts
Normal file
@ -0,0 +1,148 @@
|
||||
import type { Schema } from '@tiptap/pm/model'
|
||||
|
||||
import type { JSONContent } from '../types.js'
|
||||
|
||||
type RewriteUnknownContentOptions = {
|
||||
/**
|
||||
* If true, unknown nodes will be treated as paragraphs
|
||||
* @default true
|
||||
*/
|
||||
fallbackToParagraph?: boolean;
|
||||
};
|
||||
|
||||
type RewrittenContent = {
|
||||
/**
|
||||
* The original JSON content that was rewritten
|
||||
*/
|
||||
original: JSONContent;
|
||||
/**
|
||||
* The name of the node or mark that was unsupported
|
||||
*/
|
||||
unsupported: string;
|
||||
}[];
|
||||
|
||||
/**
|
||||
* The actual implementation of the rewriteUnknownContent function
|
||||
*/
|
||||
function rewriteUnknownContentInner({
|
||||
json,
|
||||
validMarks,
|
||||
validNodes,
|
||||
options,
|
||||
rewrittenContent = [],
|
||||
}: {
|
||||
json: JSONContent;
|
||||
validMarks: Set<string>;
|
||||
validNodes: Set<string>;
|
||||
options?: RewriteUnknownContentOptions;
|
||||
rewrittenContent?: RewrittenContent;
|
||||
}): {
|
||||
/**
|
||||
* The cleaned JSON content
|
||||
*/
|
||||
json: JSONContent | null;
|
||||
/**
|
||||
* The array of nodes and marks that were rewritten
|
||||
*/
|
||||
rewrittenContent: RewrittenContent;
|
||||
} {
|
||||
if (json.marks && Array.isArray(json.marks)) {
|
||||
json.marks = json.marks.filter(mark => {
|
||||
const name = typeof mark === 'string' ? mark : mark.type
|
||||
|
||||
if (validMarks.has(name)) {
|
||||
return true
|
||||
}
|
||||
|
||||
rewrittenContent.push({
|
||||
original: JSON.parse(JSON.stringify(mark)),
|
||||
unsupported: name,
|
||||
})
|
||||
// Just ignore any unknown marks
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
if (json.content && Array.isArray(json.content)) {
|
||||
json.content = json.content
|
||||
.map(
|
||||
value => rewriteUnknownContentInner({
|
||||
json: value,
|
||||
validMarks,
|
||||
validNodes,
|
||||
options,
|
||||
rewrittenContent,
|
||||
}).json,
|
||||
)
|
||||
.filter(a => a !== null && a !== undefined)
|
||||
}
|
||||
|
||||
if (json.type && !validNodes.has(json.type)) {
|
||||
rewrittenContent.push({
|
||||
original: JSON.parse(JSON.stringify(json)),
|
||||
unsupported: json.type,
|
||||
})
|
||||
|
||||
if (json.content && Array.isArray(json.content) && (options?.fallbackToParagraph !== false)) {
|
||||
// Just treat it like a paragraph and hope for the best
|
||||
json.type = 'paragraph'
|
||||
|
||||
return {
|
||||
json,
|
||||
rewrittenContent,
|
||||
}
|
||||
}
|
||||
|
||||
// or just omit it entirely
|
||||
return {
|
||||
json: null,
|
||||
rewrittenContent,
|
||||
}
|
||||
}
|
||||
|
||||
return { json, rewrittenContent }
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite unknown nodes and marks within JSON content
|
||||
* Allowing for user within the editor
|
||||
*/
|
||||
export function rewriteUnknownContent(
|
||||
/**
|
||||
* The JSON content to clean of unknown nodes and marks
|
||||
*/
|
||||
json: JSONContent,
|
||||
/**
|
||||
* The schema to use for validation
|
||||
*/
|
||||
schema: Schema,
|
||||
/**
|
||||
* Options for the cleaning process
|
||||
*/
|
||||
options?: RewriteUnknownContentOptions,
|
||||
): {
|
||||
/**
|
||||
* The cleaned JSON content
|
||||
*/
|
||||
json: JSONContent | null;
|
||||
/**
|
||||
* The array of nodes and marks that were rewritten
|
||||
*/
|
||||
rewrittenContent: {
|
||||
/**
|
||||
* The original JSON content that was rewritten
|
||||
*/
|
||||
original: JSONContent;
|
||||
/**
|
||||
* The name of the node or mark that was unsupported
|
||||
*/
|
||||
unsupported: string;
|
||||
}[];
|
||||
} {
|
||||
return rewriteUnknownContentInner({
|
||||
json,
|
||||
validNodes: new Set(Object.keys(schema.nodes)),
|
||||
validMarks: new Set(Object.keys(schema.marks)),
|
||||
options,
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user