@portabletext/block-tools 2.0.8 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  Let's start with a complete example:
10
10
 
11
11
  ```js
12
- import {getBlockContentFeatures, htmlToBlocks} from '@portabletext/block-tools'
12
+ import {htmlToBlocks} from '@portabletext/block-tools'
13
13
  import {Schema} from '@sanity/schema'
14
14
 
15
15
  // Start with compiling a schema we can work against
@@ -58,9 +58,6 @@ const blocks = htmlToBlocks(
58
58
  // }
59
59
  // ]
60
60
  // }
61
-
62
- // Get the feature-set of a blockContentType
63
- const features = getBlockContentFeatures(blockContentType)
64
61
  ```
65
62
 
66
63
  ## Methods
@@ -197,30 +194,3 @@ Will produce
197
194
  markDefs: []
198
195
  }
199
196
  ```
200
-
201
- ### `getBlockContentFeatures(blockContentType)`
202
-
203
- Will return an object with the features enabled for the input block content type.
204
-
205
- ```js
206
- {
207
- annotations: [{title: 'Link', value: 'link'}],
208
- decorators: [
209
- {title: 'Strong', value: 'strong'},
210
- {title: 'Emphasis', value: 'em'},
211
- {title: 'Code', value: 'code'},
212
- {title: 'Underline', value: 'underline'},
213
- {title: 'Strike', value: 'strike-through'}
214
- ],
215
- styles: [
216
- {title: 'Normal', value: 'normal'},
217
- {title: 'Heading 1', value: 'h1'},
218
- {title: 'H2', value: 'h2'},
219
- {title: 'H3', value: 'h3'},
220
- {title: 'H4', value: 'h4'},
221
- {title: 'H5', value: 'h5'},
222
- {title: 'H6', value: 'h6'},
223
- {title: 'Quote', value: 'blockquote'}
224
- ]
225
- }
226
- ```
package/lib/index.cjs CHANGED
@@ -1,12 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: !0 });
3
- var flatten = require("lodash/flatten.js"), types = require("@sanity/types"), isEqual = require("lodash/isEqual.js"), uniq = require("lodash/uniq.js"), getRandomValues = require("get-random-values-esm");
3
+ var flatten = require("lodash/flatten.js"), isEqual = require("lodash/isEqual.js"), uniq = require("lodash/uniq.js"), getRandomValues = require("get-random-values-esm"), types = require("@sanity/types");
4
4
  function _interopDefaultCompat(e) {
5
5
  return e && typeof e == "object" && "default" in e ? e : { default: e };
6
6
  }
7
7
  var flatten__default = /* @__PURE__ */ _interopDefaultCompat(flatten), isEqual__default = /* @__PURE__ */ _interopDefaultCompat(isEqual), uniq__default = /* @__PURE__ */ _interopDefaultCompat(uniq), getRandomValues__default = /* @__PURE__ */ _interopDefaultCompat(getRandomValues);
8
- function findBlockType(type) {
9
- return type.type ? findBlockType(type.type) : type.name === "block";
8
+ function isArbitraryTypedObject(object) {
9
+ return isRecord(object) && typeof object._type == "string";
10
+ }
11
+ function isRecord(value) {
12
+ return !!value && (typeof value == "object" || typeof value == "function");
13
+ }
14
+ function isTextBlock(schema, block) {
15
+ return !(!isArbitraryTypedObject(block) || block._type !== schema.block.name || !Array.isArray(block.children));
16
+ }
17
+ function isSpan(schema, child) {
18
+ return !(!isArbitraryTypedObject(child) || child._type !== schema.span.name || typeof child.text != "string");
10
19
  }
11
20
  const objectToString = Object.prototype.toString;
12
21
  function resolveJsType(val) {
@@ -98,85 +107,6 @@ uniq__default.default(
98
107
  uniq__default.default(
99
108
  Object.values(HTML_DECORATOR_TAGS)
100
109
  );
101
- function blockContentFeatures(blockContentType) {
102
- if (!blockContentType)
103
- throw new Error("Parameter 'blockContentType' required");
104
- const blockType = blockContentType.of.find(findBlockType);
105
- if (!types.isBlockSchemaType(blockType))
106
- throw new Error("'block' type is not defined in this schema (required).");
107
- const ofType = blockType.fields.find(types.isBlockChildrenObjectField)?.type?.of;
108
- if (!ofType)
109
- throw new Error("No `of` declaration found for blocks `children` field");
110
- const spanType = ofType.find(
111
- (member) => member.name === "span"
112
- );
113
- if (!spanType)
114
- throw new Error(
115
- "No `span` type found in `block` schema type `children` definition"
116
- );
117
- const inlineObjectTypes = ofType.filter(
118
- (inlineType) => inlineType.name !== "span" && types.isObjectSchemaType(inlineType)
119
- ), blockObjectTypes = blockContentType.of.filter(
120
- (memberType) => memberType.name !== blockType.name && types.isObjectSchemaType(memberType)
121
- );
122
- return {
123
- styles: resolveEnabledStyles(blockType),
124
- decorators: resolveEnabledDecorators(spanType),
125
- annotations: resolveEnabledAnnotationTypes(spanType),
126
- lists: resolveEnabledListItems(blockType),
127
- types: {
128
- block: blockContentType,
129
- span: spanType,
130
- inlineObjects: inlineObjectTypes,
131
- blockObjects: blockObjectTypes
132
- }
133
- };
134
- }
135
- function resolveEnabledStyles(blockType) {
136
- const styleField = blockType.fields.find(types.isBlockStyleObjectField);
137
- if (!styleField)
138
- throw new Error(
139
- "A field with name 'style' is not defined in the block type (required)."
140
- );
141
- const textStyles = getTitledListValuesFromEnumListOptions(
142
- styleField.type.options
143
- );
144
- if (textStyles.length === 0)
145
- throw new Error(
146
- "The style fields need at least one style defined. I.e: {title: 'Normal', value: 'normal'}."
147
- );
148
- return textStyles;
149
- }
150
- function resolveEnabledAnnotationTypes(spanType) {
151
- return spanType.annotations.map((annotation) => ({
152
- title: annotation.title,
153
- type: annotation,
154
- value: annotation.name,
155
- icon: annotation.icon
156
- }));
157
- }
158
- function resolveEnabledDecorators(spanType) {
159
- return spanType.decorators;
160
- }
161
- function resolveEnabledListItems(blockType) {
162
- const listField = blockType.fields.find(types.isBlockListObjectField);
163
- if (!listField)
164
- throw new Error(
165
- "A field with name 'list' is not defined in the block type (required)."
166
- );
167
- const listItems = getTitledListValuesFromEnumListOptions(
168
- listField.type.options
169
- );
170
- if (!listItems)
171
- throw new Error("The list field need at least to be an empty array");
172
- return listItems;
173
- }
174
- function getTitledListValuesFromEnumListOptions(options) {
175
- const list = options ? options.list : void 0;
176
- return Array.isArray(list) ? list.map(
177
- (item) => types.isTitledListValue(item) ? item : { title: item, value: item }
178
- ) : [];
179
- }
180
110
  const _XPathResult = {
181
111
  BOOLEAN_TYPE: 3,
182
112
  ORDERED_NODE_ITERATOR_TYPE: 5,
@@ -348,23 +278,6 @@ var preprocessWord = (html, doc) => {
348
278
  preprocessGDocs,
349
279
  preprocessHTML
350
280
  ];
351
- function createRuleOptions(blockContentType) {
352
- const features = blockContentFeatures(blockContentType), enabledBlockStyles = features.styles.map(
353
- (item) => item.value || item.title
354
- ), enabledSpanDecorators = features.decorators.map(
355
- (item) => item.value || item.title
356
- ), enabledBlockAnnotations = features.annotations.map(
357
- (item) => item.value || item.title || ""
358
- ), enabledListTypes = features.lists.map(
359
- (item) => item.value || item.title || ""
360
- );
361
- return {
362
- enabledBlockStyles,
363
- enabledSpanDecorators,
364
- enabledBlockAnnotations,
365
- enabledListTypes
366
- };
367
- }
368
281
  function tagName(el) {
369
282
  if (el && "tagName" in el)
370
283
  return el.tagName.toLowerCase();
@@ -385,12 +298,12 @@ function defaultParseHtml() {
385
298
  );
386
299
  return (html) => new DOMParser().parseFromString(html, "text/html");
387
300
  }
388
- function flattenNestedBlocks(blocks2) {
301
+ function flattenNestedBlocks(schema, blocks2) {
389
302
  let depth = 0;
390
303
  const flattened = [], traverse = (nodes) => {
391
304
  const toRemove = [];
392
305
  nodes.forEach((node) => {
393
- depth === 0 && flattened.push(node), types.isPortableTextTextBlock(node) && (depth > 0 && (toRemove.push(node), flattened.push(node)), depth++, traverse(node.children)), node._type === "__block" && (toRemove.push(node), flattened.push(node.block));
306
+ depth === 0 && flattened.push(node), isTextBlock(schema, node) && (depth > 0 && (toRemove.push(node), flattened.push(node)), depth++, traverse(node.children)), node._type === "__block" && (toRemove.push(node), flattened.push(node.block));
394
307
  }), toRemove.forEach((node) => {
395
308
  nodes.splice(nodes.indexOf(node), 1);
396
309
  }), depth--;
@@ -408,9 +321,9 @@ function prevSpan(block, index) {
408
321
  function isWhiteSpaceChar(text) {
409
322
  return ["\xA0", " "].includes(text);
410
323
  }
411
- function trimWhitespace(blocks2) {
324
+ function trimWhitespace(schema, blocks2) {
412
325
  return blocks2.forEach((block) => {
413
- types.isPortableTextTextBlock(block) && block.children.forEach((child, index) => {
326
+ isTextBlock(schema, block) && block.children.forEach((child, index) => {
414
327
  if (!isMinimalSpan(child))
415
328
  return;
416
329
  const nextChild = nextSpan(block, index), prevChild = prevSpan(block, index);
@@ -418,14 +331,14 @@ function trimWhitespace(blocks2) {
418
331
  });
419
332
  }), blocks2;
420
333
  }
421
- function ensureRootIsBlocks(blocks2) {
334
+ function ensureRootIsBlocks(schema, blocks2) {
422
335
  return blocks2.reduce((memo, node, i, original) => {
423
336
  if (node._type === "block")
424
337
  return memo.push(node), memo;
425
338
  if (node._type === "__block")
426
339
  return memo.push(node.block), memo;
427
340
  const lastBlock = memo[memo.length - 1];
428
- if (i > 0 && !types.isPortableTextTextBlock(original[i - 1]) && types.isPortableTextTextBlock(lastBlock))
341
+ if (i > 0 && !isTextBlock(schema, original[i - 1]) && isTextBlock(schema, lastBlock))
429
342
  return lastBlock.children.push(node), memo;
430
343
  const block = {
431
344
  ...DEFAULT_BLOCK,
@@ -533,11 +446,11 @@ const blocks = {
533
446
  ...HTML_BLOCK_TAGS,
534
447
  ...HTML_HEADER_TAGS
535
448
  };
536
- function getBlockStyle(el, enabledBlockStyles) {
449
+ function getBlockStyle(schema, el) {
537
450
  const childTag = tagName(el.firstChild), block = childTag && blocks[childTag];
538
- return block && enabledBlockStyles.includes(block.style) ? block.style : BLOCK_DEFAULT_STYLE;
451
+ return block && schema.styles.some((style) => style.name === block.style) ? block.style : BLOCK_DEFAULT_STYLE;
539
452
  }
540
- function createGDocsRules(_blockContentType, options) {
453
+ function createGDocsRules(schema) {
541
454
  return [
542
455
  {
543
456
  deserialize(el) {
@@ -558,7 +471,7 @@ function createGDocsRules(_blockContentType, options) {
558
471
  ...DEFAULT_BLOCK,
559
472
  listItem: getListItemStyle$1(el),
560
473
  level: getListItemLevel$1(el),
561
- style: getBlockStyle(el, options.enabledBlockStyles),
474
+ style: getBlockStyle(schema, el),
562
475
  children: next(el.firstChild?.childNodes || [])
563
476
  };
564
477
  }
@@ -609,13 +522,13 @@ const whitespaceTextNodeRule = {
609
522
  function isWhitespaceTextNode(node) {
610
523
  return (node.nodeType === 3 && (node.textContent || "").replace(/[\r\n]/g, " ").replace(/\s\s+/g, " ") === " " && node.nextSibling && node.nextSibling.nodeType !== 3 && node.previousSibling && node.previousSibling.nodeType !== 3 || node.textContent !== " ") && tagName(node.parentNode) !== "body";
611
524
  }
612
- function resolveListItem(listNodeTagName, enabledListTypes) {
613
- if (listNodeTagName === "ul" && enabledListTypes.includes("bullet"))
525
+ function resolveListItem(schema, listNodeTagName) {
526
+ if (listNodeTagName === "ul" && schema.lists.some((list) => list.name === "bullet"))
614
527
  return "bullet";
615
- if (listNodeTagName === "ol" && enabledListTypes.includes("number"))
528
+ if (listNodeTagName === "ol" && schema.lists.some((list) => list.name === "number"))
616
529
  return "number";
617
530
  }
618
- function createHTMLRules(_blockContentType, options) {
531
+ function createHTMLRules(schema, options) {
619
532
  return [
620
533
  whitespaceTextNodeRule,
621
534
  {
@@ -623,7 +536,9 @@ function createHTMLRules(_blockContentType, options) {
623
536
  deserialize(el) {
624
537
  if (tagName(el) !== "pre")
625
538
  return;
626
- const isCodeEnabled = options.enabledBlockStyles.includes("code");
539
+ const isCodeEnabled = schema.styles.some(
540
+ (style) => style.name === "code"
541
+ );
627
542
  return {
628
543
  _type: "block",
629
544
  style: "normal",
@@ -676,11 +591,15 @@ function createHTMLRules(_blockContentType, options) {
676
591
  ...HTML_HEADER_TAGS
677
592
  }, tag = tagName(el);
678
593
  let block = tag ? blocks2[tag] : void 0;
679
- if (block)
680
- return el.parentNode && tagName(el.parentNode) === "li" ? next(el.childNodes) : (options.enabledBlockStyles.includes(block.style) || (block = DEFAULT_BLOCK), {
681
- ...block,
682
- children: next(el.childNodes)
683
- });
594
+ if (!block)
595
+ return;
596
+ if (el.parentNode && tagName(el.parentNode) === "li")
597
+ return next(el.childNodes);
598
+ const blockStyle = block.style;
599
+ return schema.styles.some((style) => style.name === blockStyle) || (block = DEFAULT_BLOCK), {
600
+ ...block,
601
+ children: next(el.childNodes)
602
+ };
684
603
  }
685
604
  },
686
605
  // Ignore span tags
@@ -723,10 +642,7 @@ function createHTMLRules(_blockContentType, options) {
723
642
  const tag = tagName(el), listItem = tag ? HTML_LIST_ITEM_TAGS[tag] : void 0, parentTag = tagName(el.parentNode) || "";
724
643
  if (!listItem || !el.parentNode || !HTML_LIST_CONTAINER_TAGS[parentTag])
725
644
  return;
726
- const enabledListItem = resolveListItem(
727
- parentTag,
728
- options.enabledListTypes
729
- );
645
+ const enabledListItem = resolveListItem(schema, parentTag);
730
646
  return enabledListItem ? (listItem.listItem = enabledListItem, {
731
647
  ...listItem,
732
648
  children: next(el.childNodes)
@@ -737,7 +653,9 @@ function createHTMLRules(_blockContentType, options) {
737
653
  {
738
654
  deserialize(el, next) {
739
655
  const decorator = HTML_DECORATOR_TAGS[tagName(el) || ""];
740
- if (!(!decorator || !options.enabledSpanDecorators.includes(decorator)))
656
+ if (!(!decorator || !schema.decorators.some(
657
+ (decoratorType) => decoratorType.name === decorator
658
+ )))
741
659
  return {
742
660
  _type: "__decorator",
743
661
  name: decorator,
@@ -751,19 +669,18 @@ function createHTMLRules(_blockContentType, options) {
751
669
  deserialize(el, next) {
752
670
  if (tagName(el) !== "a")
753
671
  return;
754
- const linkEnabled = options.enabledBlockAnnotations.includes("link"), href = isElement(el) && el.getAttribute("href");
755
- if (!href)
756
- return next(el.childNodes);
757
- let markDef;
758
- return linkEnabled ? (markDef = {
759
- _key: options.keyGenerator ? options.keyGenerator() : keyGenerator(),
760
- _type: "link",
761
- href
762
- }, {
672
+ const linkEnabled = schema.annotations.some(
673
+ (annotation) => annotation.name === "link"
674
+ ), href = isElement(el) && el.getAttribute("href");
675
+ return href ? linkEnabled ? {
763
676
  _type: "__annotation",
764
- markDef,
677
+ markDef: {
678
+ _key: options.keyGenerator ? options.keyGenerator() : keyGenerator(),
679
+ _type: "link",
680
+ href
681
+ },
765
682
  children: next(el.childNodes)
766
- }) : el.appendChild(el.ownerDocument.createTextNode(` (${href})`)) && next(el.childNodes);
683
+ } : el.appendChild(el.ownerDocument.createTextNode(` (${href})`)) && next(el.childNodes) : next(el.childNodes);
767
684
  }
768
685
  }
769
686
  ];
@@ -783,7 +700,7 @@ function isUnderline(el) {
783
700
  function isNotion(el) {
784
701
  return isElement(el) && !!el.getAttribute("data-is-notion");
785
702
  }
786
- function createNotionRules(_blockContentType) {
703
+ function createNotionRules() {
787
704
  return [
788
705
  {
789
706
  deserialize(el) {
@@ -833,16 +750,16 @@ function createWordRules() {
833
750
  }
834
751
  ];
835
752
  }
836
- function createRules(blockContentType, options) {
753
+ function createRules(schema, options) {
837
754
  return [
838
755
  ...createWordRules(),
839
756
  ...createNotionRules(),
840
- ...createGDocsRules(blockContentType, options),
841
- ...createHTMLRules(blockContentType, options)
757
+ ...createGDocsRules(schema),
758
+ ...createHTMLRules(schema, options)
842
759
  ];
843
760
  }
844
761
  class HtmlDeserializer {
845
- blockContentType;
762
+ schema;
846
763
  rules;
847
764
  parseHtml;
848
765
  _markDefs = [];
@@ -852,17 +769,13 @@ class HtmlDeserializer {
852
769
  * @param blockContentType - Schema type for array containing _at least_ a block child type
853
770
  * @param options - Options for the deserialization process
854
771
  */
855
- constructor(blockContentType, options = {}) {
856
- const { rules = [], unstable_whitespaceOnPasteMode = "preserve" } = options;
857
- if (!blockContentType)
858
- throw new Error("Parameter 'blockContentType' is required");
859
- const standardRules = createRules(blockContentType, {
860
- ...createRuleOptions(blockContentType),
772
+ constructor(schema, options = {}) {
773
+ const { rules = [], unstable_whitespaceOnPasteMode = "preserve" } = options, standardRules = createRules(schema, {
861
774
  keyGenerator: options.keyGenerator
862
775
  });
863
- this.rules = [...rules, ...standardRules];
776
+ this.schema = schema, this.rules = [...rules, ...standardRules];
864
777
  const parseHtml = options.parseHtml || defaultParseHtml();
865
- this.blockContentType = blockContentType, this.parseHtml = (html) => preprocess(html, parseHtml, { unstable_whitespaceOnPasteMode }).body;
778
+ this.parseHtml = (html) => preprocess(html, parseHtml, { unstable_whitespaceOnPasteMode }).body;
866
779
  }
867
780
  /**
868
781
  * Deserialize HTML.
@@ -873,21 +786,19 @@ class HtmlDeserializer {
873
786
  deserialize = (html) => {
874
787
  this._markDefs = [];
875
788
  const { parseHtml } = this, fragment = parseHtml(html), children = Array.from(fragment.childNodes), blocks2 = trimWhitespace(
789
+ this.schema,
876
790
  flattenNestedBlocks(
877
- ensureRootIsBlocks(this.deserializeElements(children))
791
+ this.schema,
792
+ ensureRootIsBlocks(this.schema, this.deserializeElements(children))
878
793
  )
879
794
  );
880
- this._markDefs.length > 0 && blocks2.filter(
881
- (block) => block._type === "block"
882
- ).forEach((block) => {
795
+ return this._markDefs.length > 0 && blocks2.filter((block) => isTextBlock(this.schema, block)).forEach((block) => {
883
796
  block.markDefs = block.markDefs || [], block.markDefs = block.markDefs.concat(
884
797
  this._markDefs.filter((def) => flatten__default.default(
885
798
  block.children.map((child) => child.marks || [])
886
799
  ).includes(def._key))
887
800
  );
888
- });
889
- const type = this.blockContentType.of.find(findBlockType);
890
- return type ? blocks2.map((block) => (block._type === "block" && (block._type = type.name), block)) : blocks2;
801
+ }), blocks2.map((block) => (block._type === "block" && (block._type = this.schema.block.name), block));
891
802
  };
892
803
  /**
893
804
  * Deserialize an array of DOM elements.
@@ -1001,6 +912,11 @@ class HtmlDeserializer {
1001
912
  };
1002
913
  }
1003
914
  function normalizeBlock(node, options = {}) {
915
+ const schema = {
916
+ span: {
917
+ name: "span"
918
+ }
919
+ };
1004
920
  if (node._type !== (options.blockTypeName || "block"))
1005
921
  return "_key" in node ? node : {
1006
922
  ...node,
@@ -1025,13 +941,13 @@ function normalizeBlock(node, options = {}) {
1025
941
  return block.children = block.children.reduce(
1026
942
  (acc, child) => {
1027
943
  const previousChild = acc[acc.length - 1];
1028
- return previousChild && types.isPortableTextSpan(child) && types.isPortableTextSpan(previousChild) && isEqual__default.default(previousChild.marks, child.marks) ? (lastChild && lastChild === child && child.text === "" && block.children.length > 1 || (previousChild.text += child.text), acc) : (acc.push(child), acc);
944
+ return previousChild && isSpan(schema, child) && isSpan(schema, previousChild) && isEqual__default.default(previousChild.marks, child.marks) ? (lastChild && lastChild === child && child.text === "" && block.children.length > 1 || (previousChild.text += child.text), acc) : (acc.push(child), acc);
1029
945
  },
1030
946
  []
1031
947
  ).map((child) => {
1032
948
  if (!child)
1033
949
  throw new Error("missing child");
1034
- return child._key = options.keyGenerator ? options.keyGenerator() : keyGenerator(), types.isPortableTextSpan(child) && (child.marks ? allowedDecorators && (child.marks = child.marks.filter((mark) => {
950
+ return child._key = options.keyGenerator ? options.keyGenerator() : keyGenerator(), isSpan(schema, child) && (child.marks ? allowedDecorators && (child.marks = child.marks.filter((mark) => {
1035
951
  const isAllowed = allowedDecorators.includes(mark), isUsed = block.markDefs?.some((def) => def._key === mark);
1036
952
  return isAllowed || isUsed;
1037
953
  })) : child.marks = [], usedMarkDefs.push(...child.marks)), child;
@@ -1039,13 +955,94 @@ function normalizeBlock(node, options = {}) {
1039
955
  (markDef) => usedMarkDefs.includes(markDef._key)
1040
956
  ), block;
1041
957
  }
1042
- function htmlToBlocks(html, blockContentType, options = {}) {
1043
- return new HtmlDeserializer(blockContentType, options).deserialize(html).map((block) => normalizeBlock(block, { keyGenerator: options.keyGenerator }));
958
+ function findBlockType(type) {
959
+ return type.type ? findBlockType(type.type) : type.name === "block";
1044
960
  }
1045
- function getBlockContentFeatures(blockContentType) {
1046
- return blockContentFeatures(blockContentType);
961
+ function getPortableTextSchema(blockContentType) {
962
+ if (!blockContentType)
963
+ throw new Error("Parameter 'blockContentType' required");
964
+ const blockType = blockContentType.of.find(findBlockType);
965
+ if (!types.isBlockSchemaType(blockType))
966
+ throw new Error("'block' type is not defined in this schema (required).");
967
+ const ofType = blockType.fields.find(types.isBlockChildrenObjectField)?.type?.of;
968
+ if (!ofType)
969
+ throw new Error("No `of` declaration found for blocks `children` field");
970
+ const spanType = ofType.find(
971
+ (member) => member.name === "span"
972
+ );
973
+ if (!spanType)
974
+ throw new Error(
975
+ "No `span` type found in `block` schema type `children` definition"
976
+ );
977
+ const blockName = blockContentType.of.find(findBlockType)?.name;
978
+ if (!blockName)
979
+ throw new Error("No `block` type found in schema type");
980
+ return {
981
+ styles: resolveEnabledStyles(blockType),
982
+ decorators: resolveEnabledDecorators(spanType),
983
+ annotations: resolveEnabledAnnotationTypes(spanType),
984
+ lists: resolveEnabledListItems(blockType),
985
+ block: {
986
+ name: blockName
987
+ },
988
+ span: {
989
+ name: spanType.name
990
+ }
991
+ };
992
+ }
993
+ function resolveEnabledStyles(blockType) {
994
+ const styleField = blockType.fields.find(types.isBlockStyleObjectField);
995
+ if (!styleField)
996
+ throw new Error(
997
+ "A field with name 'style' is not defined in the block type (required)."
998
+ );
999
+ const textStyles = getTitledListValuesFromEnumListOptions(
1000
+ styleField.type.options
1001
+ );
1002
+ if (textStyles.length === 0)
1003
+ throw new Error(
1004
+ "The style fields need at least one style defined. I.e: {title: 'Normal', value: 'normal'}."
1005
+ );
1006
+ return textStyles;
1007
+ }
1008
+ function resolveEnabledAnnotationTypes(spanType) {
1009
+ return spanType.annotations.map((annotation) => ({
1010
+ name: annotation.name,
1011
+ title: annotation.title
1012
+ }));
1013
+ }
1014
+ function resolveEnabledDecorators(spanType) {
1015
+ return spanType.decorators.map((decorator) => ({
1016
+ name: decorator.value,
1017
+ title: decorator.title
1018
+ }));
1019
+ }
1020
+ function resolveEnabledListItems(blockType) {
1021
+ const listField = blockType.fields.find(types.isBlockListObjectField);
1022
+ if (!listField)
1023
+ throw new Error(
1024
+ "A field with name 'list' is not defined in the block type (required)."
1025
+ );
1026
+ const listItems = getTitledListValuesFromEnumListOptions(
1027
+ listField.type.options
1028
+ );
1029
+ if (!listItems)
1030
+ throw new Error("The list field need at least to be an empty array");
1031
+ return listItems;
1032
+ }
1033
+ function getTitledListValuesFromEnumListOptions(options) {
1034
+ const list = options ? options.list : void 0;
1035
+ return Array.isArray(list) ? list.map((item) => types.isTitledListValue(item) ? {
1036
+ name: item.value ?? item.title,
1037
+ title: item.title
1038
+ } : {
1039
+ name: item
1040
+ }) : [];
1041
+ }
1042
+ function htmlToBlocks(html, blockContentType, options = {}) {
1043
+ const schema = getPortableTextSchema(blockContentType);
1044
+ return new HtmlDeserializer(schema, options).deserialize(html).map((block) => normalizeBlock(block, { keyGenerator: options.keyGenerator }));
1047
1045
  }
1048
- exports.getBlockContentFeatures = getBlockContentFeatures;
1049
1046
  exports.htmlToBlocks = htmlToBlocks;
1050
1047
  exports.normalizeBlock = normalizeBlock;
1051
1048
  exports.randomKey = randomKey;