New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@portabletext/editor

Package Overview
Dependencies
Maintainers
9
Versions
133
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@portabletext/editor - npm Package Compare versions

Comparing version 1.33.5 to 1.33.6

src/internal-utils/parse-blocks.test.ts

22

lib/_chunks-es/behavior.core.js

@@ -450,3 +450,3 @@ import { isSelectionCollapsed, getCaretWordSelection, isSelectionExpanded, getFocusBlockObject, getNextBlock, getPreviousBlock, getFocusTextBlock, isAtTheEndOfBlock, getFocusSpan, isAtTheStartOfBlock, getFocusListBlock, getSelectedBlocks, createGuards } from "./selector.is-at-the-start-of-block.js";

}) => [raise({
type: "text block.unset",
type: "block.unset",
props: ["listItem", "level"],

@@ -476,4 +476,6 @@ at: focusTextBlock.path

}) => [raise({
type: "text block.set",
level,
type: "block.set",
props: {
level
},
at: focusTextBlock.path

@@ -498,3 +500,3 @@ })]]

}) => [raise({
type: "text block.unset",
type: "block.unset",
props: ["listItem", "level"],

@@ -524,4 +526,6 @@ at: focusListBlock.path

}) => selectedListBlocks.map((selectedListBlock) => raise({
type: "text block.set",
level: Math.min(MAX_LIST_LEVEL, Math.max(1, selectedListBlock.node.level + 1)),
type: "block.set",
props: {
level: Math.min(MAX_LIST_LEVEL, Math.max(1, selectedListBlock.node.level + 1))
},
at: selectedListBlock.path

@@ -550,4 +554,6 @@ }))]

}) => selectedListBlocks.map((selectedListBlock) => raise({
type: "text block.set",
level: Math.min(MAX_LIST_LEVEL, Math.max(1, selectedListBlock.node.level - 1)),
type: "block.set",
props: {
level: Math.min(MAX_LIST_LEVEL, Math.max(1, selectedListBlock.node.level - 1))
},
at: selectedListBlock.path

@@ -554,0 +560,0 @@ }))]

@@ -52,8 +52,10 @@ import { isPortableTextTextBlock } from "@sanity/types";

}) => [{
type: "text block.unset",
type: "block.unset",
props: ["listItem", "level"],
at: focusTextBlock.path
}, {
type: "text block.set",
style,
type: "block.set",
props: {
style
},
at: focusTextBlock.path

@@ -217,8 +219,10 @@ }, {

}) => [{
type: "text block.unset",
type: "block.unset",
props: ["listItem", "level"],
at: focusTextBlock.path
}, {
type: "text block.set",
style,
type: "block.set",
props: {
style
},
at: focusTextBlock.path

@@ -260,4 +264,6 @@ }, {

}) => [{
type: "text block.set",
style: defaultStyle,
type: "block.set",
props: {
style: defaultStyle
},
at: focusTextBlock.path

@@ -321,6 +327,8 @@ }]]

}) => [{
type: "text block.set",
listItem,
level: 1,
style,
type: "block.set",
props: {
listItem,
level: 1,
style
},
at: focusTextBlock.path

@@ -327,0 +335,0 @@ }, {

@@ -1,2 +0,1 @@

import { isPortableTextTextBlock, isPortableTextSpan } from "@sanity/types";
import { blockOffsetToSpanSelectionPoint } from "./util.slice-blocks.js";

@@ -14,52 +13,70 @@ function isTypedObject(object) {

}) {
if (!isTypedObject(block) || block._type !== context.schema.block.name && !context.schema.blockObjects.some((blockObject) => blockObject.name === block._type))
return;
if (block._type !== context.schema.block.name) {
const _key = options.refreshKeys ? context.keyGenerator() : typeof block._key == "string" ? block._key : context.keyGenerator();
return parseTextBlock({
block,
context,
options
}) ?? parseBlockObject({
blockObject: block,
context,
options
});
}
function parseBlockObject({
blockObject,
context,
options
}) {
if (isTypedObject(blockObject) && !(blockObject._type === context.schema.block.name || blockObject._type === "block" || !context.schema.blockObjects.some(({
name
}) => name === blockObject._type)))
return {
...block,
_key
...blockObject,
_key: options.refreshKeys ? context.keyGenerator() : typeof blockObject._key == "string" ? blockObject._key : context.keyGenerator()
};
}
if (!isPortableTextTextBlock(block))
return {
_type: context.schema.block.name,
_key: options.refreshKeys ? context.keyGenerator() : typeof block._key == "string" ? block._key : context.keyGenerator(),
children: [{
_key: context.keyGenerator(),
_type: context.schema.span.name,
text: "",
marks: []
}],
markDefs: [],
style: context.schema.styles[0].value
};
const markDefKeyMap = /* @__PURE__ */ new Map(), markDefs = (block.markDefs ?? []).flatMap((markDef) => {
}
function isTextBlock(schema, block) {
return parseTextBlock({
block,
context: {
schema,
keyGenerator: () => ""
},
options: {
refreshKeys: !1
}
}) !== void 0;
}
function parseTextBlock({
block,
context,
options
}) {
if (!isTypedObject(block) || block._type !== context.schema.block.name)
return;
const _key = options.refreshKeys ? context.keyGenerator() : typeof block._key == "string" ? block._key : context.keyGenerator(), unparsedMarkDefs = Array.isArray(block.markDefs) ? block.markDefs : [], markDefKeyMap = /* @__PURE__ */ new Map(), markDefs = unparsedMarkDefs.flatMap((markDef) => {
if (!isTypedObject(markDef))
return [];
if (typeof markDef._key != "string")
return [];
if (context.schema.annotations.some((annotation) => annotation.name === markDef._type)) {
const _key = options.refreshKeys ? context.keyGenerator() : markDef._key;
return markDefKeyMap.set(markDef._key, _key), [{
const _key2 = options.refreshKeys ? context.keyGenerator() : markDef._key;
return markDefKeyMap.set(markDef._key, _key2), [{
...markDef,
_key
_key: _key2
}];
}
return [];
}), children = block.children.flatMap((child) => {
if (!isTypedObject(child))
return [];
if (child._type !== context.schema.span.name && !context.schema.inlineObjects.some((inlineObject) => inlineObject.name === child._type))
return [];
if (!isPortableTextSpan(child))
return [{
...child,
_key: options.refreshKeys ? context.keyGenerator() : child._key
}];
const marks = (child.marks ?? []).flatMap((mark) => markDefKeyMap.has(mark) ? [markDefKeyMap.get(mark)] : context.schema.decorators.some((decorator) => decorator.value === mark) ? [mark] : []);
return [{
...child,
_key: options.refreshKeys ? context.keyGenerator() : child._key,
marks
}];
}), parsedBlock = {
}), children = (Array.isArray(block.children) ? block.children : []).map((child) => parseSpan({
span: child,
context,
markDefKeyMap,
options
}) ?? parseInlineObject({
inlineObject: child,
context,
options
})).filter((child) => child !== void 0), parsedBlock = {
// Spread the entire block to allow custom properties on it
...block,
_key: options.refreshKeys ? context.keyGenerator() : block._key,
_key,
children: children.length > 0 ? children : [{

@@ -73,8 +90,46 @@ _key: context.keyGenerator(),

};
if (!context.schema.styles.find((style) => style.value === block.style)) {
const defaultStyle = context.schema.styles[0].value;
if (typeof parsedBlock.style != "string" || !context.schema.styles.find((style) => style.value === block.style)) {
const defaultStyle = context.schema.styles.at(0)?.value;
defaultStyle !== void 0 ? parsedBlock.style = defaultStyle : delete parsedBlock.style;
}
return context.schema.lists.find((list) => list.value === block.listItem) || (delete parsedBlock.listItem, delete parsedBlock.level), parsedBlock;
return (typeof parsedBlock.listItem != "string" || !context.schema.lists.find((list) => list.value === block.listItem)) && delete parsedBlock.listItem, typeof parsedBlock.level != "number" && delete parsedBlock.level, parsedBlock;
}
function parseSpan({
span,
context,
markDefKeyMap,
options
}) {
if (!isTypedObject(span) || span._type !== context.schema.span.name || span._type !== "span")
return;
const marks = (Array.isArray(span.marks) ? span.marks : []).flatMap((mark) => {
if (typeof mark != "string")
return [];
const markDefKey = markDefKeyMap.get(mark);
return markDefKey !== void 0 ? [markDefKey] : context.schema.decorators.some((decorator) => decorator.value === mark) ? [mark] : [];
});
return {
// Spread the entire span to allow custom properties on it
...span,
_type: "span",
_key: options.refreshKeys ? context.keyGenerator() : typeof span._key == "string" ? span._key : context.keyGenerator(),
text: typeof span.text == "string" ? span.text : "",
marks
};
}
function parseInlineObject({
inlineObject,
context,
options
}) {
if (isTypedObject(inlineObject) && !(inlineObject._type === context.schema.span.name || inlineObject._type === "span" || // Respect the schema definition and don't parse inline objects that are not defined
!context.schema.inlineObjects.some(({
name
}) => name === inlineObject._type)))
return {
// Spread the entire inline object to allow custom properties on it
...inlineObject,
_key: options.refreshKeys ? context.keyGenerator() : typeof inlineObject._key == "string" ? inlineObject._key : context.keyGenerator()
};
}
function blockOffsetsToSelection({

@@ -102,4 +157,5 @@ value,

blockOffsetsToSelection,
isTextBlock,
parseBlock
};
//# sourceMappingURL=util.block-offsets-to-selection.js.map

@@ -201,4 +201,2 @@ import type {

| 'style.toggle'
| 'text block.set'
| 'text block.unset'
| 'key.down'

@@ -258,4 +256,2 @@ | 'key.up'

| 'style.toggle'
| 'text block.set'
| 'text block.unset'
| 'key.down'

@@ -320,4 +316,2 @@ | 'key.up'

| 'style.toggle'
| 'text block.set'
| 'text block.unset'
| 'key.down'

@@ -377,4 +371,2 @@ | 'key.up'

| 'style.toggle'
| 'text block.set'
| 'text block.unset'
| 'key.down'

@@ -439,4 +431,2 @@ | 'key.up'

| 'style.toggle'
| 'text block.set'
| 'text block.unset'
| 'key.down'

@@ -496,4 +486,2 @@ | 'key.up'

| 'style.toggle'
| 'text block.set'
| 'text block.unset'
| 'key.down'

@@ -558,4 +546,2 @@ | 'key.up'

| 'style.toggle'
| 'text block.set'
| 'text block.unset'
| 'key.down'

@@ -615,4 +601,2 @@ | 'key.up'

| 'style.toggle'
| 'text block.set'
| 'text block.unset'
| 'key.down'

@@ -719,4 +703,2 @@ | 'key.up'

| 'style.toggle'
| 'text block.set'
| 'text block.unset'
| 'key.down'

@@ -776,4 +758,2 @@ | 'key.up'

| 'style.toggle'
| 'text block.set'
| 'text block.unset'
| 'key.down'

@@ -1036,3 +1016,3 @@ | 'key.up'

at: [KeyedSegment]
[props: string]: unknown
props: Record<string, unknown>
}

@@ -1200,14 +1180,2 @@ | {

}
| {
type: 'text block.set'
at: [KeyedSegment]
level?: number
listItem?: string
style?: string
}
| {
type: 'text block.unset'
at: [KeyedSegment]
props: Array<'level' | 'listItem' | 'style'>
}
| (PickFromUnion<

@@ -1214,0 +1182,0 @@ ConverterEvent,

{
"name": "@portabletext/editor",
"version": "1.33.5",
"version": "1.33.6",
"description": "Portable Text Editor made in React",

@@ -82,3 +82,3 @@ "keywords": [

"xstate": "^5.19.2",
"@portabletext/block-tools": "1.1.7",
"@portabletext/block-tools": "1.1.8",
"@portabletext/patches": "1.1.3"

@@ -90,4 +90,4 @@ },

"@sanity/pkg-utils": "^7.0.4",
"@sanity/schema": "^3.75.0",
"@sanity/types": "^3.75.0",
"@sanity/schema": "^3.75.1",
"@sanity/types": "^3.75.1",
"@testing-library/jest-dom": "^6.6.3",

@@ -120,4 +120,4 @@ "@testing-library/react": "^16.2.0",

"peerDependencies": {
"@sanity/schema": "^3.75.0",
"@sanity/types": "^3.75.0",
"@sanity/schema": "^3.75.1",
"@sanity/types": "^3.75.1",
"react": "^16.9 || ^17 || ^18 || ^19",

@@ -124,0 +124,0 @@ "rxjs": "^7.8.1"

@@ -1,3 +0,6 @@

import {Transforms} from 'slate'
import {Editor, Transforms, type Element as SlateElement} from 'slate'
import {parseBlock} from '../internal-utils/parse-blocks'
import {toSlateRange} from '../internal-utils/ranges'
import {fromSlateValue, toSlateValue} from '../internal-utils/values'
import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps'
import type {BehaviorActionImplementation} from './behavior.actions'

@@ -7,3 +10,3 @@

'block.set'
> = ({action}) => {
> = ({context, action}) => {
const location = toSlateRange(

@@ -18,8 +21,48 @@ {

if (!location) {
return
throw new Error(
`Unable to convert ${JSON.stringify(action.at)} into a Slate Range`,
)
}
const {at, editor, type, ...payload} = action
const blockEntry = Editor.node(action.editor, location, {depth: 1})
const block = blockEntry?.[0]
Transforms.setNodes(action.editor, payload, {at: location})
if (!block) {
throw new Error(`Unable to find block at ${JSON.stringify(action.at)}`)
}
const parsedBlock = fromSlateValue(
[block],
context.schema.block.name,
KEY_TO_VALUE_ELEMENT.get(action.editor),
).at(0)
if (!parsedBlock) {
throw new Error(`Unable to parse block at ${JSON.stringify(action.at)}`)
}
const {_type, ...filteredProps} = action.props
const updatedBlock = parseBlock({
context,
block: {
...parsedBlock,
...filteredProps,
},
options: {refreshKeys: false},
})
if (!updatedBlock) {
throw new Error(`Unable to update block at ${JSON.stringify(action.at)}`)
}
const slateBlock = toSlateValue([updatedBlock], {
schemaTypes: context.schema,
})?.at(0) as SlateElement | undefined
if (!slateBlock) {
throw new Error(`Unable to convert block to Slate value`)
}
Transforms.setNodes(action.editor, slateBlock, {at: location})
}

@@ -1,3 +0,7 @@

import {Transforms} from 'slate'
import {omit} from 'lodash'
import {Editor, Transforms} from 'slate'
import {isTextBlock, parseBlock} from '../internal-utils/parse-blocks'
import {toSlateRange} from '../internal-utils/ranges'
import {fromSlateValue} from '../internal-utils/values'
import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps'
import type {BehaviorActionImplementation} from './behavior.actions'

@@ -7,3 +11,3 @@

'block.unset'
> = ({action}) => {
> = ({context, action}) => {
const location = toSlateRange(

@@ -18,6 +22,76 @@ {

if (!location) {
throw new Error(
`Unable to convert ${JSON.stringify(action.at)} into a Slate Range`,
)
}
const blockEntry = Editor.node(action.editor, location, {depth: 1})
const block = blockEntry?.[0]
if (!block) {
throw new Error(`Unable to find block at ${JSON.stringify(action.at)}`)
}
const parsedBlock = fromSlateValue(
[block],
context.schema.block.name,
KEY_TO_VALUE_ELEMENT.get(action.editor),
).at(0)
if (!parsedBlock) {
throw new Error(`Unable to parse block at ${JSON.stringify(action.at)}`)
}
if (isTextBlock(context.schema, parsedBlock)) {
const propsToRemove = action.props.filter((prop) => prop !== '_type')
const updatedTextBlock = parseBlock({
context,
block: omit(parsedBlock, propsToRemove),
options: {refreshKeys: false},
})
if (!updatedTextBlock) {
throw new Error(`Unable to update block at ${JSON.stringify(action.at)}`)
}
const propsToSet: Record<string, unknown> = {}
for (const prop of propsToRemove) {
if (!(prop in updatedTextBlock)) {
propsToSet[prop] = undefined
} else {
propsToSet[prop] = (updatedTextBlock as Record<string, unknown>)[prop]
}
}
Transforms.setNodes(action.editor, propsToSet, {at: location})
return
}
Transforms.unsetNodes(action.editor, action.props, {at: location})
const updatedBlockObject = parseBlock({
context,
block: omit(
parsedBlock,
action.props.filter((prop) => prop !== '_type'),
),
options: {refreshKeys: false},
})
if (!updatedBlockObject) {
throw new Error(`Unable to update block at ${JSON.stringify(action.at)}`)
}
const {_type, _key, ...props} = updatedBlockObject
Transforms.setNodes(
action.editor,
{
_type,
_key,
value: props,
},
{at: location},
)
}

@@ -51,4 +51,2 @@ import {deleteForward, insertText, Path, Transforms} from 'slate'

} from './behavior.action.style'
import {textBlockSetActionImplementation} from './behavior.action.text-block.set'
import {textBlockUnsetActionImplementation} from './behavior.action.text-block.unset'

@@ -270,4 +268,2 @@ export type BehaviorActionImplementationContext = Pick<

'style.remove': removeStyleActionImplementation,
'text block.set': textBlockSetActionImplementation,
'text block.unset': textBlockUnsetActionImplementation,
}

@@ -605,3 +601,3 @@

}
case 'style.toggle': {
default: {
behaviorActionImplementations['style.toggle']({

@@ -613,16 +609,3 @@ context,

}
case 'text block.set': {
behaviorActionImplementations['text block.set']({
context,
action,
})
break
}
default: {
behaviorActionImplementations['text block.unset']({
context,
action,
})
}
}
}

@@ -33,3 +33,3 @@ import {createGuards} from '../behavior-actions/behavior.guards'

raise({
type: 'text block.unset',
type: 'block.unset',
props: ['listItem', 'level'],

@@ -70,4 +70,4 @@ at: focusTextBlock.path,

raise({
type: 'text block.set',
level,
type: 'block.set',
props: {level},
at: focusTextBlock.path,

@@ -98,3 +98,3 @@ }),

raise({
type: 'text block.unset',
type: 'block.unset',
props: ['listItem', 'level'],

@@ -139,7 +139,9 @@ at: focusListBlock.path,

raise({
type: 'text block.set',
level: Math.min(
MAX_LIST_LEVEL,
Math.max(1, selectedListBlock.node.level + 1),
),
type: 'block.set',
props: {
level: Math.min(
MAX_LIST_LEVEL,
Math.max(1, selectedListBlock.node.level + 1),
),
},
at: selectedListBlock.path,

@@ -183,7 +185,9 @@ }),

raise({
type: 'text block.set',
level: Math.min(
MAX_LIST_LEVEL,
Math.max(1, selectedListBlock.node.level - 1),
),
type: 'block.set',
props: {
level: Math.min(
MAX_LIST_LEVEL,
Math.max(1, selectedListBlock.node.level - 1),
),
},
at: selectedListBlock.path,

@@ -190,0 +194,0 @@ }),

@@ -130,3 +130,3 @@ import {isPortableTextTextBlock} from '@sanity/types'

{
type: 'text block.unset',
type: 'block.unset',
props: ['listItem', 'level'],

@@ -136,4 +136,4 @@ at: focusTextBlock.path,

{
type: 'text block.set',
style,
type: 'block.set',
props: {style},
at: focusTextBlock.path,

@@ -331,3 +331,3 @@ },

{
type: 'text block.unset',
type: 'block.unset',
props: ['listItem', 'level'],

@@ -337,4 +337,4 @@ at: focusTextBlock.path,

{
type: 'text block.set',
style,
type: 'block.set',
props: {style},
at: focusTextBlock.path,

@@ -386,4 +386,4 @@ },

{
type: 'text block.set',
style: defaultStyle,
type: 'block.set',
props: {style: defaultStyle},
at: focusTextBlock.path,

@@ -472,6 +472,8 @@ },

{
type: 'text block.set',
listItem,
level: 1,
style,
type: 'block.set',
props: {
listItem,
level: 1,
style,
},
at: focusTextBlock.path,

@@ -478,0 +480,0 @@ },

@@ -41,3 +41,3 @@ import type {

at: [KeyedSegment]
[props: string]: unknown
props: Record<string, unknown>
}

@@ -199,14 +199,2 @@ | {

}
| {
type: 'text block.set'
at: [KeyedSegment]
level?: number
listItem?: string
style?: string
}
| {
type: 'text block.unset'
at: [KeyedSegment]
props: Array<'level' | 'listItem' | 'style'>
}
| (PickFromUnion<

@@ -213,0 +201,0 @@ ConverterEvent,

@@ -415,2 +415,3 @@ import {assert, describe, expect, test} from 'vitest'

markDefs: [],
level: 1,
style: 'normal',

@@ -572,3 +573,3 @@ },

text: 'foo',
marks: ['k0'],
marks: ['k1'],
},

@@ -583,3 +584,3 @@ {

{
_key: 'k0',
_key: 'k1',
_type: 'link',

@@ -586,0 +587,0 @@ href: 'https://example.com',

@@ -1,6 +0,8 @@

import {
isPortableTextSpan,
isPortableTextTextBlock,
type PortableTextBlock,
import type {
PortableTextBlock,
PortableTextObject,
PortableTextSpan,
PortableTextTextBlock,
} from '@sanity/types'
import type {EditorSchema} from '../editor/define-schema'
import type {EditorContext} from '../editor/editor-snapshot'

@@ -20,3 +22,18 @@ import {isTypedObject} from './asserters'

}): PortableTextBlock | undefined {
if (!isTypedObject(block)) {
return (
parseTextBlock({block, context, options}) ??
parseBlockObject({blockObject: block, context, options})
)
}
function parseBlockObject({
blockObject,
context,
options,
}: {
blockObject: unknown
context: Pick<EditorContext, 'keyGenerator' | 'schema'>
options: {refreshKeys: boolean}
}): PortableTextObject | undefined {
if (!isTypedObject(blockObject)) {
return undefined

@@ -26,6 +43,5 @@ }

if (
block._type !== context.schema.block.name &&
!context.schema.blockObjects.some(
(blockObject) => blockObject.name === block._type,
)
blockObject._type === context.schema.block.name ||
blockObject._type === 'block' ||
!context.schema.blockObjects.some(({name}) => name === blockObject._type)
) {

@@ -35,37 +51,61 @@ return undefined

if (block._type !== context.schema.block.name) {
const _key = options.refreshKeys
return {
...blockObject,
_key: options.refreshKeys
? context.keyGenerator()
: typeof block._key === 'string'
? block._key
: context.keyGenerator()
return {
...block,
_key,
}
: typeof blockObject._key === 'string'
? blockObject._key
: context.keyGenerator(),
}
}
if (!isPortableTextTextBlock(block)) {
return {
_type: context.schema.block.name,
_key: options.refreshKeys
? context.keyGenerator()
: typeof block._key === 'string'
? block._key
: context.keyGenerator(),
children: [
{
_key: context.keyGenerator(),
_type: context.schema.span.name,
text: '',
marks: [],
},
],
markDefs: [],
style: context.schema.styles[0].value,
}
export function isTextBlock(
schema: EditorSchema,
block: unknown,
): block is PortableTextTextBlock {
return (
parseTextBlock({
block,
context: {schema, keyGenerator: () => ''},
options: {refreshKeys: false},
}) !== undefined
)
}
function parseTextBlock({
block,
context,
options,
}: {
block: unknown
context: Pick<EditorContext, 'keyGenerator' | 'schema'>
options: {refreshKeys: boolean}
}): PortableTextTextBlock | undefined {
if (!isTypedObject(block)) {
return undefined
}
if (block._type !== context.schema.block.name) {
return undefined
}
const _key = options.refreshKeys
? context.keyGenerator()
: typeof block._key === 'string'
? block._key
: context.keyGenerator()
const unparsedMarkDefs: Array<unknown> = Array.isArray(block.markDefs)
? block.markDefs
: []
const markDefKeyMap = new Map<string, string>()
const markDefs = (block.markDefs ?? []).flatMap((markDef) => {
const markDefs = unparsedMarkDefs.flatMap((markDef) => {
if (!isTypedObject(markDef)) {
return []
}
if (typeof markDef._key !== 'string') {
return []
}
if (

@@ -90,51 +130,18 @@ context.schema.annotations.some(

const children = block.children.flatMap((child) => {
if (!isTypedObject(child)) {
return []
}
const unparsedChildren: Array<unknown> = Array.isArray(block.children)
? block.children
: []
if (
child._type !== context.schema.span.name &&
!context.schema.inlineObjects.some(
(inlineObject) => inlineObject.name === child._type,
)
) {
return []
}
const children = unparsedChildren
.map(
(child) =>
parseSpan({span: child, context, markDefKeyMap, options}) ??
parseInlineObject({inlineObject: child, context, options}),
)
.filter((child) => child !== undefined)
if (!isPortableTextSpan(child)) {
return [
{
...child,
_key: options.refreshKeys ? context.keyGenerator() : child._key,
},
]
}
const marks = (child.marks ?? []).flatMap((mark) => {
if (markDefKeyMap.has(mark)) {
return [markDefKeyMap.get(mark)]
}
if (
context.schema.decorators.some((decorator) => decorator.value === mark)
) {
return [mark]
}
return []
})
return [
{
...child,
_key: options.refreshKeys ? context.keyGenerator() : child._key,
marks,
},
]
})
const parsedBlock = {
const parsedBlock: PortableTextTextBlock = {
// Spread the entire block to allow custom properties on it
...block,
_key: options.refreshKeys ? context.keyGenerator() : block._key,
_key,
children:

@@ -154,4 +161,10 @@ children.length > 0

if (!context.schema.styles.find((style) => style.value === block.style)) {
const defaultStyle = context.schema.styles[0].value
/**
* Reset text block .style if it's somehow set to an invalid type
*/
if (
typeof parsedBlock.style !== 'string' ||
!context.schema.styles.find((style) => style.value === block.style)
) {
const defaultStyle = context.schema.styles.at(0)?.value

@@ -165,4 +178,16 @@ if (defaultStyle !== undefined) {

if (!context.schema.lists.find((list) => list.value === block.listItem)) {
/**
* Reset text block .listItem if it's somehow set to an invalid type
*/
if (
typeof parsedBlock.listItem !== 'string' ||
!context.schema.lists.find((list) => list.value === block.listItem)
) {
delete parsedBlock.listItem
}
/**
* Reset text block .level if it's somehow set to an invalid type
*/
if (typeof parsedBlock.level !== 'number') {
delete parsedBlock.level

@@ -173,1 +198,91 @@ }

}
export function parseSpan({
span,
context,
markDefKeyMap,
options,
}: {
span: unknown
context: Pick<EditorContext, 'keyGenerator' | 'schema'>
markDefKeyMap: Map<string, string>
options: {refreshKeys: boolean}
}): PortableTextSpan | undefined {
if (!isTypedObject(span)) {
return undefined
}
// In reality, the span schema name is always 'span', but we only the check here anyway
if (span._type !== context.schema.span.name || span._type !== 'span') {
return undefined
}
const unparsedMarks: Array<unknown> = Array.isArray(span.marks)
? span.marks
: []
const marks = unparsedMarks.flatMap((mark) => {
if (typeof mark !== 'string') {
return []
}
const markDefKey = markDefKeyMap.get(mark)
if (markDefKey !== undefined) {
return [markDefKey]
}
if (
context.schema.decorators.some((decorator) => decorator.value === mark)
) {
return [mark]
}
return []
})
return {
// Spread the entire span to allow custom properties on it
...span,
_type: 'span',
_key: options.refreshKeys
? context.keyGenerator()
: typeof span._key === 'string'
? span._key
: context.keyGenerator(),
text: typeof span.text === 'string' ? span.text : '',
marks,
}
}
function parseInlineObject({
inlineObject,
context,
options,
}: {
inlineObject: unknown
context: Pick<EditorContext, 'keyGenerator' | 'schema'>
options: {refreshKeys: boolean}
}): PortableTextObject | undefined {
if (!isTypedObject(inlineObject)) {
return undefined
}
if (
inlineObject._type === context.schema.span.name ||
inlineObject._type === 'span' ||
// Respect the schema definition and don't parse inline objects that are not defined
!context.schema.inlineObjects.some(({name}) => name === inlineObject._type)
) {
return undefined
}
return {
// Spread the entire inline object to allow custom properties on it
...inlineObject,
_key: options.refreshKeys
? context.keyGenerator()
: typeof inlineObject._key === 'string'
? inlineObject._key
: context.keyGenerator(),
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc