@gmb/bitmark-parser-generator 1.34.0 → 2.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.
Files changed (317) hide show
  1. package/dist/browser/bitmark-parser-generator.min.js +1 -1
  2. package/dist/browser/bundle-report.html +2 -2
  3. package/dist/cjs/BitmarkParserGenerator.js +8 -3
  4. package/dist/cjs/BitmarkParserGenerator.js.map +1 -1
  5. package/dist/cjs/ast/Ast.js +1 -0
  6. package/dist/cjs/ast/Ast.js.map +1 -1
  7. package/dist/cjs/ast/BaseBuilder.js +91 -54
  8. package/dist/cjs/ast/BaseBuilder.js.map +1 -1
  9. package/dist/cjs/ast/Builder.js +780 -377
  10. package/dist/cjs/ast/Builder.js.map +1 -1
  11. package/dist/cjs/ast/ResourceBuilder.js +516 -252
  12. package/dist/cjs/ast/ResourceBuilder.js.map +1 -1
  13. package/dist/cjs/ast/rules/NodeValidator.js +61 -22
  14. package/dist/cjs/ast/rules/NodeValidator.js.map +1 -1
  15. package/dist/cjs/ast/writer/StreamWriter.js +13 -0
  16. package/dist/cjs/ast/writer/StreamWriter.js.map +1 -1
  17. package/dist/cjs/ast/writer/StringWriter.js +13 -0
  18. package/dist/cjs/ast/writer/StringWriter.js.map +1 -1
  19. package/dist/cjs/breakscaping/Breakscape.js +122 -95
  20. package/dist/cjs/breakscaping/Breakscape.js.map +1 -1
  21. package/dist/cjs/config/raw/bits.js +24 -5
  22. package/dist/cjs/config/raw/bits.js.map +1 -1
  23. package/dist/cjs/config/raw/properties.js +7 -2
  24. package/dist/cjs/config/raw/properties.js.map +1 -1
  25. package/dist/cjs/generated/build-info.js +1 -1
  26. package/dist/cjs/generated/build-info.js.map +1 -1
  27. package/dist/cjs/generated/parser/bitmark/bitmark-peggy-parser.js +312 -262
  28. package/dist/cjs/generated/parser/bitmark/bitmark-peggy-parser.js.map +1 -1
  29. package/dist/cjs/generator/AstWalkerGenerator.js +4 -1
  30. package/dist/cjs/generator/AstWalkerGenerator.js.map +1 -1
  31. package/dist/cjs/generator/bitmark/BitmarkGenerator.js +977 -336
  32. package/dist/cjs/generator/bitmark/BitmarkGenerator.js.map +1 -1
  33. package/dist/cjs/generator/json/JsonGenerator.js +361 -1964
  34. package/dist/cjs/generator/json/JsonGenerator.js.map +1 -1
  35. package/dist/cjs/generator/text/TextGenerator.js +26 -8
  36. package/dist/cjs/generator/text/TextGenerator.js.map +1 -1
  37. package/dist/cjs/index.js.map +1 -1
  38. package/dist/cjs/model/ast/NodeType.js +64 -42
  39. package/dist/cjs/model/ast/NodeType.js.map +1 -1
  40. package/dist/cjs/model/config/enum/PropertyConfigKey.js +1 -0
  41. package/dist/cjs/model/config/enum/PropertyConfigKey.js.map +1 -1
  42. package/dist/cjs/model/enum/BitType.js +2 -2
  43. package/dist/cjs/model/enum/BitType.js.map +1 -1
  44. package/dist/cjs/model/enum/PropertyFormat.js +3 -1
  45. package/dist/cjs/model/enum/PropertyFormat.js.map +1 -1
  46. package/dist/cjs/model/enum/TextFormat.js +1 -0
  47. package/dist/cjs/model/enum/TextFormat.js.map +1 -1
  48. package/dist/cjs/parser/bitmark/peg/BitmarkPegParserHelper.js +22 -4
  49. package/dist/cjs/parser/bitmark/peg/BitmarkPegParserHelper.js.map +1 -1
  50. package/dist/cjs/parser/bitmark/peg/BitmarkPegParserProcessor.js +93 -88
  51. package/dist/cjs/parser/bitmark/peg/BitmarkPegParserProcessor.js.map +1 -1
  52. package/dist/cjs/parser/bitmark/peg/BitmarkPegParserTypes.js +3 -1
  53. package/dist/cjs/parser/bitmark/peg/BitmarkPegParserTypes.js.map +1 -1
  54. package/dist/cjs/parser/bitmark/peg/BitmarkPegParserValidator.js +10 -32
  55. package/dist/cjs/parser/bitmark/peg/BitmarkPegParserValidator.js.map +1 -1
  56. package/dist/cjs/parser/bitmark/peg/contentProcessors/BodyContentProcessor.js +255 -0
  57. package/dist/cjs/parser/bitmark/peg/contentProcessors/BodyContentProcessor.js.map +1 -0
  58. package/dist/cjs/parser/bitmark/peg/contentProcessors/BookChainContentProcessor.js +2 -1
  59. package/dist/cjs/parser/bitmark/peg/contentProcessors/BookChainContentProcessor.js.map +1 -1
  60. package/dist/cjs/parser/bitmark/peg/contentProcessors/CardContentProcessor.js +175 -129
  61. package/dist/cjs/parser/bitmark/peg/contentProcessors/CardContentProcessor.js.map +1 -1
  62. package/dist/cjs/parser/bitmark/peg/contentProcessors/ClozeTagContentProcessor.js +8 -2
  63. package/dist/cjs/parser/bitmark/peg/contentProcessors/ClozeTagContentProcessor.js.map +1 -1
  64. package/dist/cjs/parser/bitmark/peg/contentProcessors/ContentProcessorUtils.js +61 -0
  65. package/dist/cjs/parser/bitmark/peg/contentProcessors/ContentProcessorUtils.js.map +1 -0
  66. package/dist/cjs/parser/bitmark/peg/contentProcessors/DefaultTagContentProcessor.js +11 -5
  67. package/dist/cjs/parser/bitmark/peg/contentProcessors/DefaultTagContentProcessor.js.map +1 -1
  68. package/dist/cjs/parser/bitmark/peg/contentProcessors/ExampleTagContentProcessor.js +21 -17
  69. package/dist/cjs/parser/bitmark/peg/contentProcessors/ExampleTagContentProcessor.js.map +1 -1
  70. package/dist/cjs/parser/bitmark/peg/contentProcessors/FooterContentProcessor.js +50 -0
  71. package/dist/cjs/parser/bitmark/peg/contentProcessors/FooterContentProcessor.js.map +1 -0
  72. package/dist/cjs/parser/bitmark/peg/contentProcessors/GapChainContentProcessor.js +2 -15
  73. package/dist/cjs/parser/bitmark/peg/contentProcessors/GapChainContentProcessor.js.map +1 -1
  74. package/dist/cjs/parser/bitmark/peg/contentProcessors/ImageSourceChainContentProcessor.js +2 -4
  75. package/dist/cjs/parser/bitmark/peg/contentProcessors/ImageSourceChainContentProcessor.js.map +1 -1
  76. package/dist/cjs/parser/bitmark/peg/contentProcessors/ItemLeadTagContentProcessor.js +4 -1
  77. package/dist/cjs/parser/bitmark/peg/contentProcessors/ItemLeadTagContentProcessor.js.map +1 -1
  78. package/dist/cjs/parser/bitmark/peg/contentProcessors/MarkChainContentProcessor.js +2 -4
  79. package/dist/cjs/parser/bitmark/peg/contentProcessors/MarkChainContentProcessor.js.map +1 -1
  80. package/dist/cjs/parser/bitmark/peg/contentProcessors/MarkConfigChainContentProcessor.js +5 -5
  81. package/dist/cjs/parser/bitmark/peg/contentProcessors/MarkConfigChainContentProcessor.js.map +1 -1
  82. package/dist/cjs/parser/bitmark/peg/contentProcessors/PersonChainContentProcessor.js +5 -6
  83. package/dist/cjs/parser/bitmark/peg/contentProcessors/PersonChainContentProcessor.js.map +1 -1
  84. package/dist/cjs/parser/bitmark/peg/contentProcessors/PropertyContentProcessor.js +23 -7
  85. package/dist/cjs/parser/bitmark/peg/contentProcessors/PropertyContentProcessor.js.map +1 -1
  86. package/dist/cjs/parser/bitmark/peg/contentProcessors/RatingLevelChainContentProcessor.js +5 -5
  87. package/dist/cjs/parser/bitmark/peg/contentProcessors/RatingLevelChainContentProcessor.js.map +1 -1
  88. package/dist/cjs/parser/bitmark/peg/contentProcessors/ReferenceTagContentProcessor.js +3 -2
  89. package/dist/cjs/parser/bitmark/peg/contentProcessors/ReferenceTagContentProcessor.js.map +1 -1
  90. package/dist/cjs/parser/bitmark/peg/contentProcessors/ResourceContentProcessor.js +19 -8
  91. package/dist/cjs/parser/bitmark/peg/contentProcessors/ResourceContentProcessor.js.map +1 -1
  92. package/dist/cjs/parser/bitmark/peg/contentProcessors/ServingsChainContentProcessor.js +4 -6
  93. package/dist/cjs/parser/bitmark/peg/contentProcessors/ServingsChainContentProcessor.js.map +1 -1
  94. package/dist/cjs/parser/bitmark/peg/contentProcessors/TechnicalTermChainContentProcessor.js +4 -5
  95. package/dist/cjs/parser/bitmark/peg/contentProcessors/TechnicalTermChainContentProcessor.js.map +1 -1
  96. package/dist/cjs/parser/bitmark/peg/contentProcessors/TitleTagContentProcessor.js +14 -5
  97. package/dist/cjs/parser/bitmark/peg/contentProcessors/TitleTagContentProcessor.js.map +1 -1
  98. package/dist/cjs/parser/bitmark/peg/contentProcessors/TrueFalseChainContentProcessor.js +37 -21
  99. package/dist/cjs/parser/bitmark/peg/contentProcessors/TrueFalseChainContentProcessor.js.map +1 -1
  100. package/dist/cjs/parser/bitmark/peg/contentProcessors/TrueFalseTagContentProcessor.js +3 -2
  101. package/dist/cjs/parser/bitmark/peg/contentProcessors/TrueFalseTagContentProcessor.js.map +1 -1
  102. package/dist/cjs/parser/json/JsonParser.js +73 -759
  103. package/dist/cjs/parser/json/JsonParser.js.map +1 -1
  104. package/dist/cjs/parser/text/TextParser.js +75 -1
  105. package/dist/cjs/parser/text/TextParser.js.map +1 -1
  106. package/dist/cjs/utils/BitUtils.js +15 -13
  107. package/dist/cjs/utils/BitUtils.js.map +1 -1
  108. package/dist/cjs/utils/StringUtils.js +40 -0
  109. package/dist/cjs/utils/StringUtils.js.map +1 -1
  110. package/dist/esm/BitmarkParserGenerator.js +8 -3
  111. package/dist/esm/BitmarkParserGenerator.js.map +1 -1
  112. package/dist/esm/ast/Ast.js +1 -0
  113. package/dist/esm/ast/Ast.js.map +1 -1
  114. package/dist/esm/ast/BaseBuilder.js +91 -54
  115. package/dist/esm/ast/BaseBuilder.js.map +1 -1
  116. package/dist/esm/ast/Builder.js +780 -377
  117. package/dist/esm/ast/Builder.js.map +1 -1
  118. package/dist/esm/ast/ResourceBuilder.js +516 -252
  119. package/dist/esm/ast/ResourceBuilder.js.map +1 -1
  120. package/dist/esm/ast/rules/NodeValidator.js +61 -22
  121. package/dist/esm/ast/rules/NodeValidator.js.map +1 -1
  122. package/dist/esm/ast/writer/StreamWriter.js +13 -0
  123. package/dist/esm/ast/writer/StreamWriter.js.map +1 -1
  124. package/dist/esm/ast/writer/StringWriter.js +13 -0
  125. package/dist/esm/ast/writer/StringWriter.js.map +1 -1
  126. package/dist/esm/breakscaping/Breakscape.js +122 -95
  127. package/dist/esm/breakscaping/Breakscape.js.map +1 -1
  128. package/dist/esm/config/raw/bits.js +24 -5
  129. package/dist/esm/config/raw/bits.js.map +1 -1
  130. package/dist/esm/config/raw/properties.js +7 -2
  131. package/dist/esm/config/raw/properties.js.map +1 -1
  132. package/dist/esm/generated/build-info.js +1 -1
  133. package/dist/esm/generated/build-info.js.map +1 -1
  134. package/dist/esm/generated/parser/bitmark/bitmark-peggy-parser.js +312 -262
  135. package/dist/esm/generated/parser/bitmark/bitmark-peggy-parser.js.map +1 -1
  136. package/dist/esm/generator/AstWalkerGenerator.js +4 -1
  137. package/dist/esm/generator/AstWalkerGenerator.js.map +1 -1
  138. package/dist/esm/generator/bitmark/BitmarkGenerator.js +977 -336
  139. package/dist/esm/generator/bitmark/BitmarkGenerator.js.map +1 -1
  140. package/dist/esm/generator/json/JsonGenerator.js +361 -1964
  141. package/dist/esm/generator/json/JsonGenerator.js.map +1 -1
  142. package/dist/esm/generator/text/TextGenerator.js +26 -8
  143. package/dist/esm/generator/text/TextGenerator.js.map +1 -1
  144. package/dist/esm/index.js.map +1 -1
  145. package/dist/esm/model/ast/NodeType.js +64 -42
  146. package/dist/esm/model/ast/NodeType.js.map +1 -1
  147. package/dist/esm/model/config/enum/PropertyConfigKey.js +1 -0
  148. package/dist/esm/model/config/enum/PropertyConfigKey.js.map +1 -1
  149. package/dist/esm/model/enum/BitType.js +2 -2
  150. package/dist/esm/model/enum/BitType.js.map +1 -1
  151. package/dist/esm/model/enum/PropertyFormat.js +3 -1
  152. package/dist/esm/model/enum/PropertyFormat.js.map +1 -1
  153. package/dist/esm/model/enum/TextFormat.js +1 -0
  154. package/dist/esm/model/enum/TextFormat.js.map +1 -1
  155. package/dist/esm/parser/bitmark/peg/BitmarkPegParserHelper.js +22 -4
  156. package/dist/esm/parser/bitmark/peg/BitmarkPegParserHelper.js.map +1 -1
  157. package/dist/esm/parser/bitmark/peg/BitmarkPegParserProcessor.js +93 -88
  158. package/dist/esm/parser/bitmark/peg/BitmarkPegParserProcessor.js.map +1 -1
  159. package/dist/esm/parser/bitmark/peg/BitmarkPegParserTypes.js +3 -1
  160. package/dist/esm/parser/bitmark/peg/BitmarkPegParserTypes.js.map +1 -1
  161. package/dist/esm/parser/bitmark/peg/BitmarkPegParserValidator.js +10 -32
  162. package/dist/esm/parser/bitmark/peg/BitmarkPegParserValidator.js.map +1 -1
  163. package/dist/esm/parser/bitmark/peg/contentProcessors/BodyContentProcessor.js +252 -0
  164. package/dist/esm/parser/bitmark/peg/contentProcessors/BodyContentProcessor.js.map +1 -0
  165. package/dist/esm/parser/bitmark/peg/contentProcessors/BookChainContentProcessor.js +2 -1
  166. package/dist/esm/parser/bitmark/peg/contentProcessors/BookChainContentProcessor.js.map +1 -1
  167. package/dist/esm/parser/bitmark/peg/contentProcessors/CardContentProcessor.js +175 -129
  168. package/dist/esm/parser/bitmark/peg/contentProcessors/CardContentProcessor.js.map +1 -1
  169. package/dist/esm/parser/bitmark/peg/contentProcessors/ClozeTagContentProcessor.js +8 -2
  170. package/dist/esm/parser/bitmark/peg/contentProcessors/ClozeTagContentProcessor.js.map +1 -1
  171. package/dist/esm/parser/bitmark/peg/contentProcessors/ContentProcessorUtils.js +58 -0
  172. package/dist/esm/parser/bitmark/peg/contentProcessors/ContentProcessorUtils.js.map +1 -0
  173. package/dist/esm/parser/bitmark/peg/contentProcessors/DefaultTagContentProcessor.js +11 -5
  174. package/dist/esm/parser/bitmark/peg/contentProcessors/DefaultTagContentProcessor.js.map +1 -1
  175. package/dist/esm/parser/bitmark/peg/contentProcessors/ExampleTagContentProcessor.js +21 -17
  176. package/dist/esm/parser/bitmark/peg/contentProcessors/ExampleTagContentProcessor.js.map +1 -1
  177. package/dist/esm/parser/bitmark/peg/contentProcessors/FooterContentProcessor.js +47 -0
  178. package/dist/esm/parser/bitmark/peg/contentProcessors/FooterContentProcessor.js.map +1 -0
  179. package/dist/esm/parser/bitmark/peg/contentProcessors/GapChainContentProcessor.js +2 -15
  180. package/dist/esm/parser/bitmark/peg/contentProcessors/GapChainContentProcessor.js.map +1 -1
  181. package/dist/esm/parser/bitmark/peg/contentProcessors/ImageSourceChainContentProcessor.js +2 -4
  182. package/dist/esm/parser/bitmark/peg/contentProcessors/ImageSourceChainContentProcessor.js.map +1 -1
  183. package/dist/esm/parser/bitmark/peg/contentProcessors/ItemLeadTagContentProcessor.js +4 -1
  184. package/dist/esm/parser/bitmark/peg/contentProcessors/ItemLeadTagContentProcessor.js.map +1 -1
  185. package/dist/esm/parser/bitmark/peg/contentProcessors/MarkChainContentProcessor.js +2 -4
  186. package/dist/esm/parser/bitmark/peg/contentProcessors/MarkChainContentProcessor.js.map +1 -1
  187. package/dist/esm/parser/bitmark/peg/contentProcessors/MarkConfigChainContentProcessor.js +5 -5
  188. package/dist/esm/parser/bitmark/peg/contentProcessors/MarkConfigChainContentProcessor.js.map +1 -1
  189. package/dist/esm/parser/bitmark/peg/contentProcessors/PersonChainContentProcessor.js +5 -6
  190. package/dist/esm/parser/bitmark/peg/contentProcessors/PersonChainContentProcessor.js.map +1 -1
  191. package/dist/esm/parser/bitmark/peg/contentProcessors/PropertyContentProcessor.js +23 -7
  192. package/dist/esm/parser/bitmark/peg/contentProcessors/PropertyContentProcessor.js.map +1 -1
  193. package/dist/esm/parser/bitmark/peg/contentProcessors/RatingLevelChainContentProcessor.js +5 -5
  194. package/dist/esm/parser/bitmark/peg/contentProcessors/RatingLevelChainContentProcessor.js.map +1 -1
  195. package/dist/esm/parser/bitmark/peg/contentProcessors/ReferenceTagContentProcessor.js +3 -2
  196. package/dist/esm/parser/bitmark/peg/contentProcessors/ReferenceTagContentProcessor.js.map +1 -1
  197. package/dist/esm/parser/bitmark/peg/contentProcessors/ResourceContentProcessor.js +19 -8
  198. package/dist/esm/parser/bitmark/peg/contentProcessors/ResourceContentProcessor.js.map +1 -1
  199. package/dist/esm/parser/bitmark/peg/contentProcessors/ServingsChainContentProcessor.js +4 -6
  200. package/dist/esm/parser/bitmark/peg/contentProcessors/ServingsChainContentProcessor.js.map +1 -1
  201. package/dist/esm/parser/bitmark/peg/contentProcessors/TechnicalTermChainContentProcessor.js +4 -5
  202. package/dist/esm/parser/bitmark/peg/contentProcessors/TechnicalTermChainContentProcessor.js.map +1 -1
  203. package/dist/esm/parser/bitmark/peg/contentProcessors/TitleTagContentProcessor.js +14 -5
  204. package/dist/esm/parser/bitmark/peg/contentProcessors/TitleTagContentProcessor.js.map +1 -1
  205. package/dist/esm/parser/bitmark/peg/contentProcessors/TrueFalseChainContentProcessor.js +37 -21
  206. package/dist/esm/parser/bitmark/peg/contentProcessors/TrueFalseChainContentProcessor.js.map +1 -1
  207. package/dist/esm/parser/bitmark/peg/contentProcessors/TrueFalseTagContentProcessor.js +3 -2
  208. package/dist/esm/parser/bitmark/peg/contentProcessors/TrueFalseTagContentProcessor.js.map +1 -1
  209. package/dist/esm/parser/json/JsonParser.js +73 -759
  210. package/dist/esm/parser/json/JsonParser.js.map +1 -1
  211. package/dist/esm/parser/text/TextParser.js +75 -1
  212. package/dist/esm/parser/text/TextParser.js.map +1 -1
  213. package/dist/esm/utils/BitUtils.js +15 -13
  214. package/dist/esm/utils/BitUtils.js.map +1 -1
  215. package/dist/esm/utils/StringUtils.js +40 -0
  216. package/dist/esm/utils/StringUtils.js.map +1 -1
  217. package/dist/types/BitmarkParserGenerator.d.ts +8 -0
  218. package/dist/types/BitmarkParserGenerator.d.ts.map +1 -1
  219. package/dist/types/ast/Ast.d.ts.map +1 -1
  220. package/dist/types/ast/BaseBuilder.d.ts +31 -21
  221. package/dist/types/ast/BaseBuilder.d.ts.map +1 -1
  222. package/dist/types/ast/Builder.d.ts +283 -435
  223. package/dist/types/ast/Builder.d.ts.map +1 -1
  224. package/dist/types/ast/ResourceBuilder.d.ts +177 -164
  225. package/dist/types/ast/ResourceBuilder.d.ts.map +1 -1
  226. package/dist/types/ast/rules/NodeValidator.d.ts +3 -2
  227. package/dist/types/ast/rules/NodeValidator.d.ts.map +1 -1
  228. package/dist/types/ast/writer/StreamWriter.d.ts +2 -0
  229. package/dist/types/ast/writer/StreamWriter.d.ts.map +1 -1
  230. package/dist/types/ast/writer/StringWriter.d.ts +2 -0
  231. package/dist/types/ast/writer/StringWriter.d.ts.map +1 -1
  232. package/dist/types/ast/writer/Writer.d.ts +6 -0
  233. package/dist/types/ast/writer/Writer.d.ts.map +1 -1
  234. package/dist/types/breakscaping/Breakscape.d.ts +6 -1
  235. package/dist/types/breakscaping/Breakscape.d.ts.map +1 -1
  236. package/dist/types/config/raw/bits.d.ts.map +1 -1
  237. package/dist/types/config/raw/properties.d.ts.map +1 -1
  238. package/dist/types/generated/parser/bitmark/bitmark-peggy-parser.d.ts.map +1 -1
  239. package/dist/types/generator/AstWalkerGenerator.d.ts.map +1 -1
  240. package/dist/types/generator/bitmark/BitmarkGenerator.d.ts +91 -55
  241. package/dist/types/generator/bitmark/BitmarkGenerator.d.ts.map +1 -1
  242. package/dist/types/generator/json/JsonGenerator.d.ts +96 -108
  243. package/dist/types/generator/json/JsonGenerator.d.ts.map +1 -1
  244. package/dist/types/generator/text/TextGenerator.d.ts +14 -2
  245. package/dist/types/generator/text/TextGenerator.d.ts.map +1 -1
  246. package/dist/types/index.d.ts +2 -2
  247. package/dist/types/index.d.ts.map +1 -1
  248. package/dist/types/model/ast/NodeType.d.ts +122 -84
  249. package/dist/types/model/ast/NodeType.d.ts.map +1 -1
  250. package/dist/types/model/ast/Nodes.d.ts +66 -436
  251. package/dist/types/model/ast/Nodes.d.ts.map +1 -1
  252. package/dist/types/model/ast/TextNodes.d.ts +1 -1
  253. package/dist/types/model/ast/TextNodes.d.ts.map +1 -1
  254. package/dist/types/model/config/enum/ConfigKey.d.ts +2 -0
  255. package/dist/types/model/config/enum/ConfigKey.d.ts.map +1 -1
  256. package/dist/types/model/config/enum/PropertyConfigKey.d.ts +3 -0
  257. package/dist/types/model/config/enum/PropertyConfigKey.d.ts.map +1 -1
  258. package/dist/types/model/enum/BitType.d.ts +4 -4
  259. package/dist/types/model/enum/PropertyFormat.d.ts +4 -2
  260. package/dist/types/model/enum/PropertyFormat.d.ts.map +1 -1
  261. package/dist/types/model/enum/PropertyTag.d.ts +2 -0
  262. package/dist/types/model/enum/PropertyTag.d.ts.map +1 -1
  263. package/dist/types/model/enum/TextFormat.d.ts +2 -0
  264. package/dist/types/model/enum/TextFormat.d.ts.map +1 -1
  265. package/dist/types/model/json/BitJson.d.ts +32 -20
  266. package/dist/types/model/json/BitJson.d.ts.map +1 -1
  267. package/dist/types/model/json/BodyBitJson.d.ts +16 -12
  268. package/dist/types/model/json/BodyBitJson.d.ts.map +1 -1
  269. package/dist/types/model/json/ResourceJson.d.ts +2 -22
  270. package/dist/types/model/json/ResourceJson.d.ts.map +1 -1
  271. package/dist/types/parser/bitmark/peg/BitmarkPegParserHelper.d.ts +4 -2
  272. package/dist/types/parser/bitmark/peg/BitmarkPegParserHelper.d.ts.map +1 -1
  273. package/dist/types/parser/bitmark/peg/BitmarkPegParserProcessor.d.ts +3 -9
  274. package/dist/types/parser/bitmark/peg/BitmarkPegParserProcessor.d.ts.map +1 -1
  275. package/dist/types/parser/bitmark/peg/BitmarkPegParserTypes.d.ts +90 -74
  276. package/dist/types/parser/bitmark/peg/BitmarkPegParserTypes.d.ts.map +1 -1
  277. package/dist/types/parser/bitmark/peg/BitmarkPegParserValidator.d.ts +2 -2
  278. package/dist/types/parser/bitmark/peg/BitmarkPegParserValidator.d.ts.map +1 -1
  279. package/dist/types/parser/bitmark/peg/contentProcessors/BodyContentProcessor.d.ts +37 -0
  280. package/dist/types/parser/bitmark/peg/contentProcessors/BodyContentProcessor.d.ts.map +1 -0
  281. package/dist/types/parser/bitmark/peg/contentProcessors/BookChainContentProcessor.d.ts.map +1 -1
  282. package/dist/types/parser/bitmark/peg/contentProcessors/CardContentProcessor.d.ts +2 -2
  283. package/dist/types/parser/bitmark/peg/contentProcessors/CardContentProcessor.d.ts.map +1 -1
  284. package/dist/types/parser/bitmark/peg/contentProcessors/ClozeTagContentProcessor.d.ts.map +1 -1
  285. package/dist/types/parser/bitmark/peg/contentProcessors/ContentProcessorUtils.d.ts +15 -0
  286. package/dist/types/parser/bitmark/peg/contentProcessors/ContentProcessorUtils.d.ts.map +1 -0
  287. package/dist/types/parser/bitmark/peg/contentProcessors/DefaultTagContentProcessor.d.ts.map +1 -1
  288. package/dist/types/parser/bitmark/peg/contentProcessors/ExampleTagContentProcessor.d.ts.map +1 -1
  289. package/dist/types/parser/bitmark/peg/contentProcessors/FooterContentProcessor.d.ts +16 -0
  290. package/dist/types/parser/bitmark/peg/contentProcessors/FooterContentProcessor.d.ts.map +1 -0
  291. package/dist/types/parser/bitmark/peg/contentProcessors/GapChainContentProcessor.d.ts.map +1 -1
  292. package/dist/types/parser/bitmark/peg/contentProcessors/ImageSourceChainContentProcessor.d.ts.map +1 -1
  293. package/dist/types/parser/bitmark/peg/contentProcessors/ItemLeadTagContentProcessor.d.ts.map +1 -1
  294. package/dist/types/parser/bitmark/peg/contentProcessors/MarkChainContentProcessor.d.ts.map +1 -1
  295. package/dist/types/parser/bitmark/peg/contentProcessors/MarkConfigChainContentProcessor.d.ts.map +1 -1
  296. package/dist/types/parser/bitmark/peg/contentProcessors/PersonChainContentProcessor.d.ts.map +1 -1
  297. package/dist/types/parser/bitmark/peg/contentProcessors/PropertyContentProcessor.d.ts.map +1 -1
  298. package/dist/types/parser/bitmark/peg/contentProcessors/RatingLevelChainContentProcessor.d.ts.map +1 -1
  299. package/dist/types/parser/bitmark/peg/contentProcessors/ReferenceTagContentProcessor.d.ts.map +1 -1
  300. package/dist/types/parser/bitmark/peg/contentProcessors/ResourceContentProcessor.d.ts +2 -2
  301. package/dist/types/parser/bitmark/peg/contentProcessors/ResourceContentProcessor.d.ts.map +1 -1
  302. package/dist/types/parser/bitmark/peg/contentProcessors/ServingsChainContentProcessor.d.ts.map +1 -1
  303. package/dist/types/parser/bitmark/peg/contentProcessors/TechnicalTermChainContentProcessor.d.ts.map +1 -1
  304. package/dist/types/parser/bitmark/peg/contentProcessors/TitleTagContentProcessor.d.ts +5 -2
  305. package/dist/types/parser/bitmark/peg/contentProcessors/TitleTagContentProcessor.d.ts.map +1 -1
  306. package/dist/types/parser/bitmark/peg/contentProcessors/TrueFalseChainContentProcessor.d.ts +1 -1
  307. package/dist/types/parser/bitmark/peg/contentProcessors/TrueFalseChainContentProcessor.d.ts.map +1 -1
  308. package/dist/types/parser/bitmark/peg/contentProcessors/TrueFalseTagContentProcessor.d.ts.map +1 -1
  309. package/dist/types/parser/json/JsonParser.d.ts +9 -72
  310. package/dist/types/parser/json/JsonParser.d.ts.map +1 -1
  311. package/dist/types/parser/text/TextParser.d.ts +16 -1
  312. package/dist/types/parser/text/TextParser.d.ts.map +1 -1
  313. package/dist/types/utils/BitUtils.d.ts +8 -8
  314. package/dist/types/utils/BitUtils.d.ts.map +1 -1
  315. package/dist/types/utils/StringUtils.d.ts +24 -0
  316. package/dist/types/utils/StringUtils.d.ts.map +1 -1
  317. package/package.json +1 -1
@@ -10,22 +10,29 @@ const ResourceTag_1 = require("../model/enum/ResourceTag");
10
10
  const TextFormat_1 = require("../model/enum/TextFormat");
11
11
  const ArrayUtils_1 = require("../utils/ArrayUtils");
12
12
  const BitUtils_1 = require("../utils/BitUtils");
13
+ const BooleanUtils_1 = require("../utils/BooleanUtils");
13
14
  const NumberUtils_1 = require("../utils/NumberUtils");
14
15
  const ObjectUtils_1 = require("../utils/ObjectUtils");
16
+ const StringUtils_1 = require("../utils/StringUtils");
15
17
  const Env_1 = require("../utils/env/Env");
16
18
  const BaseBuilder_1 = require("./BaseBuilder");
19
+ const ResourceBuilder_1 = require("./ResourceBuilder");
17
20
  const NodeValidator_1 = require("./rules/NodeValidator");
18
21
  /**
19
22
  * Builder to build bitmark AST node programmatically
20
23
  */
21
24
  class Builder extends BaseBuilder_1.BaseBuilder {
25
+ constructor() {
26
+ super(...arguments);
27
+ this.resourceBuilder = new ResourceBuilder_1.ResourceBuilder();
28
+ }
22
29
  /**
23
30
  * Build bitmark node
24
31
  *
25
32
  * @param data - data for the node
26
33
  * @returns
27
34
  */
28
- bitmark(data) {
35
+ buildBitmark(data) {
29
36
  const { bits, errors } = data;
30
37
  const node = {
31
38
  bits,
@@ -41,49 +48,44 @@ class Builder extends BaseBuilder_1.BaseBuilder {
41
48
  * @param data - data for the node
42
49
  * @returns
43
50
  */
44
- bit(data) {
45
- var _a;
46
- const { bitType, bitLevel, textFormat, resourceType, isCommented, id, internalComment, externalId, spaceId, padletId, jupyterId, jupyterExecutionCount, isPublic, aiGenerated, machineTranslated, analyticsTag, feedbackEngine, feedbackType, disableFeedback, releaseVersion, releaseKind, releaseDate, ageRange, lang, language, publisher, publisherName, theme, computerLanguage, target, slug, tag, reductionTag, bubbleTag, levelCEFRp, levelCEFR, levelILR, levelACTFL, icon, iconTag, colorTag, flashcardSet, subtype, bookAlias, coverImage, coverColor, publications, author, subject, date, dateEnd, location, kind, hasMarkAsDone, processHandIn, action, showInIndex, blockId, pageNo, x, y, width, height, index, classification, availableClassifications, allowedBit, tableFixedHeader, tableSearch, tableSort, tablePagination, tablePaginationLimit, tableHeight, tableWhitespaceNoWrap, tableAutoWidth, tableResizableColumns, quizCountItems, quizStrikethroughSolutions, codeLineNumbers, codeMinimap, stripePricingTableId, stripePublishableKey, thumbImage, scormSource, posterImage, focusX, focusY, pointerLeft, pointerTop, listItemIndent, backgroundWallpaper, hasBookNavigation, duration, referenceProperty, deeplink, externalLink, externalLinkText, videoCallLink, vendorUrl, search, bot, list, textReference, isTracked, isInfoOnly, imageFirst, activityType, labelTrue, labelFalse, content2Buy, mailingList, buttonCaption, callToActionUrl, caption, book, quotedPerson, partialAnswer, reasonableNumOfChars, sampleSolution, additionalSolutions, resolved, resolvedDate, resolvedBy, maxCreatedBits, maxDisplayLevel, page, productId, product, productList, productVideo, productVideoList, productFolder, technicalTerm, servings, ratingLevelStart, ratingLevelEnd, ratingLevelSelected, title, subtitle, level, toc, progress, anchor, reference, referenceEnd, isCaseSensitive, item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample, example, imageSource, person, markConfig, extraProperties, imagePlaceholder, resources: _resources, body, footer, markup, parser, } = data;
47
- const bitConfig = Config_1.Config.getBitConfig(bitType);
48
- // Convert resources into an array
49
- const resources = ArrayUtils_1.ArrayUtils.asArray(_resources);
51
+ buildBit(data) {
52
+ var _a, _b, _c, _d, _e, _f, _g, _h;
53
+ const bitConfig = Config_1.Config.getBitConfig(data.bitType);
54
+ const textFormat = (_a = TextFormat_1.TextFormat.fromValue(data.textFormat)) !== null && _a !== void 0 ? _a : bitConfig.textFormatDefault;
55
+ // Validate and convert resources, and ensure it is an array
56
+ // const resources = ArrayUtils.asArray(resourcesIn);
50
57
  // Set the card node data
51
- const cardNode = this.cardNode(data);
58
+ const cardNode = this.buildCardNode(data.bitType, textFormat, data);
52
59
  // Add reasonableNumOfChars to the bit only for essay bits (in other cases it will be pushed down the tree)
53
- const reasonableNumOfCharsProperty = Config_1.Config.isOfBitType(bitType, BitType_1.BitType.essay)
54
- ? this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.reasonableNumOfChars, reasonableNumOfChars)
60
+ const reasonableNumOfCharsProperty = Config_1.Config.isOfBitType(data.bitType, BitType_1.BitType.essay)
61
+ ? this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.reasonableNumOfChars, data.reasonableNumOfChars)
55
62
  : undefined;
63
+ const convertedExample = Object.assign({}, this.toExample(data.__isDefaultExample, data.example));
56
64
  // NOTE: Node order is important and is defined here
57
- const node = Object.assign(Object.assign({ bitType,
58
- bitLevel, textFormat: (_a = TextFormat_1.TextFormat.fromValue(textFormat)) !== null && _a !== void 0 ? _a : bitConfig.textFormatDefault, resourceType: ResourceTag_1.ResourceTag.fromValue(resourceType), isCommented, id: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.id, id), internalComment: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.internalComment, internalComment), externalId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.externalId, externalId), spaceId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.spaceId, spaceId), padletId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.padletId, padletId), jupyterId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.jupyterId, jupyterId), jupyterExecutionCount: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.jupyterExecutionCount, jupyterExecutionCount), isPublic: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.isPublic, isPublic), aiGenerated: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.aiGenerated, aiGenerated), machineTranslated: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.machineTranslated, machineTranslated), analyticsTag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.analyticsTag, analyticsTag), feedbackEngine: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.feedbackEngine, feedbackEngine), feedbackType: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.feedbackType, feedbackType), disableFeedback: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.disableFeedback, disableFeedback), releaseVersion: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.releaseVersion, releaseVersion), releaseKind: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.releaseKind, releaseKind), releaseDate: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.releaseDate, releaseDate), book, ageRange: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.ageRange, ageRange), lang: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.lang, lang), language: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.language, language), publisher: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.publisher, publisher), publisherName: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.publisherName, publisherName), theme: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.theme, theme), computerLanguage: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.computerLanguage, computerLanguage), target: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.target, target), slug: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.slug, slug), tag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tag, tag), reductionTag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.reductionTag, reductionTag), bubbleTag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.bubbleTag, bubbleTag), levelCEFRp: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.levelCEFRp, levelCEFRp), levelCEFR: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.levelCEFR, levelCEFR), levelILR: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.levelILR, levelILR), levelACTFL: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.levelACTFL, levelACTFL), icon: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.icon, icon), iconTag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.iconTag, iconTag), colorTag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.colorTag, colorTag), flashcardSet: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.flashcardSet, flashcardSet), subtype: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.subtype, subtype), bookAlias: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.bookAlias, bookAlias), coverImage: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.coverImage, coverImage), coverColor: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.coverColor, coverColor), publications: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.publications, publications), author: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.author, author), subject: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.subject, subject), date: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.date, date), dateEnd: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.dateEnd, dateEnd), location: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.location, location), kind: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.kind, kind), hasMarkAsDone: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.hasMarkAsDone, hasMarkAsDone), processHandIn: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.processHandIn, processHandIn), action: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.action, action), showInIndex: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.showInIndex, showInIndex), blockId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.blockId, blockId), pageNo: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.pageNo, pageNo), x: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.x, x), y: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.y, y), width: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.width, width), height: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.height, height), index: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.index, index), classification: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.classification, classification), availableClassifications: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.availableClassifications, availableClassifications), allowedBit: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.allowedBit, allowedBit), tableFixedHeader: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableFixedHeader, tableFixedHeader), tableSearch: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableSearch, tableSearch), tableSort: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableSort, tableSort), tablePagination: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tablePagination, tablePagination), tablePaginationLimit: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tablePaginationLimit, tablePaginationLimit), tableHeight: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableHeight, tableHeight), tableWhitespaceNoWrap: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableWhitespaceNoWrap, tableWhitespaceNoWrap), tableAutoWidth: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableAutoWidth, tableAutoWidth), tableResizableColumns: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableResizableColumns, tableResizableColumns), quizCountItems: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.quizCountItems, quizCountItems), quizStrikethroughSolutions: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.quizStrikethroughSolutions, quizStrikethroughSolutions), codeLineNumbers: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.codeLineNumbers, codeLineNumbers), codeMinimap: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.codeMinimap, codeMinimap), stripePricingTableId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.stripePricingTableId, stripePricingTableId), stripePublishableKey: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.stripePublishableKey, stripePublishableKey), thumbImage: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.thumbImage, thumbImage), scormSource: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.scormSource, scormSource), posterImage: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.posterImage, posterImage), focusX: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.focusX, focusX), focusY: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.focusY, focusY), pointerLeft: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.pointerLeft, pointerLeft), pointerTop: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.pointerTop, pointerTop), listItemIndent: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.listItemIndent, listItemIndent), backgroundWallpaper: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.backgroundWallpaper, backgroundWallpaper), hasBookNavigation: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.hasBookNavigation, hasBookNavigation), deeplink: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.deeplink, deeplink), externalLink: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.externalLink, externalLink), externalLinkText: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.externalLinkText, externalLinkText), videoCallLink: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.videoCallLink, videoCallLink), vendorUrl: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.vendorUrl, vendorUrl), search: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.search, search), bot: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.bot, bot), duration: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.duration, duration), referenceProperty: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.property_reference, referenceProperty), list: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.list, list), textReference: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.textReference, textReference), isTracked: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.isTracked, isTracked), isInfoOnly: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.isInfoOnly, isInfoOnly), imageFirst: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.imageFirst, imageFirst), activityType: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.activityType, activityType), labelTrue: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.labelTrue, labelTrue), labelFalse: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.labelFalse, labelFalse), content2Buy: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.content2Buy, content2Buy), mailingList: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.mailingList, mailingList), buttonCaption: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.buttonCaption, buttonCaption), callToActionUrl: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.callToActionUrl, callToActionUrl), caption, quotedPerson: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.quotedPerson, quotedPerson), partialAnswer: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.partialAnswer, partialAnswer), reasonableNumOfChars: reasonableNumOfCharsProperty, sampleSolution: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.property_sampleSolution, sampleSolution), additionalSolutions: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.additionalSolutions, additionalSolutions), resolved: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.resolved, resolved), resolvedDate: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.resolvedDate, resolvedDate), resolvedBy: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.resolvedBy, resolvedBy), maxCreatedBits: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.maxCreatedBits, maxCreatedBits), maxDisplayLevel: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.maxDisplayLevel, maxDisplayLevel), page: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.page, page), productId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.productId, productId), product: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.product, product), productList: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.productList, productList), productVideo: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.productVideo, productVideo), productVideoList: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.productVideoList, productVideoList), productFolder: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.productFolder, productFolder), technicalTerm,
59
- servings,
60
- ratingLevelStart,
61
- ratingLevelEnd, ratingLevelSelected: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.ratingLevelSelected, ratingLevelSelected), title,
62
- subtitle, level: NumberUtils_1.NumberUtils.asNumber(level), toc: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.toc, toc), progress: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.progress, progress), anchor,
63
- reference,
64
- referenceEnd,
65
- markConfig, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
66
- instruction }, this.toExample(isDefaultExample, example)), { imageSource,
67
- person,
68
- imagePlaceholder,
69
- resources,
70
- body,
71
- cardNode,
72
- footer,
73
- markup,
74
- parser,
65
+ const node = Object.assign(Object.assign({ bitType: data.bitType, bitLevel: data.bitLevel, textFormat, resourceType: ResourceTag_1.ResourceTag.fromValue(data.resourceType), isCommented: data.isCommented,
66
+ // Properties
67
+ id: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.id, data.id), internalComment: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.internalComment, data.internalComment), externalId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.externalId, data.externalId), spaceId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.spaceId, data.spaceId), padletId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.padletId, data.padletId), jupyterId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.jupyterId, data.jupyterId), jupyterExecutionCount: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.jupyterExecutionCount, data.jupyterExecutionCount), isPublic: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.isPublic, data.isPublic), aiGenerated: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.aiGenerated, data.aiGenerated), machineTranslated: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.machineTranslated, data.machineTranslated), analyticsTag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.analyticsTag, data.analyticsTag), feedbackEngine: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.feedbackEngine, data.feedbackEngine), feedbackType: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.feedbackType, data.feedbackType), disableFeedback: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.disableFeedback, data.disableFeedback), releaseVersion: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.releaseVersion, data.releaseVersion), releaseKind: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.releaseKind, data.releaseKind), releaseDate: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.releaseDate, data.releaseDate), book: data.book, ageRange: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.ageRange, data.ageRange), lang: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.lang, data.lang), language: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.language, data.language), publisher: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.publisher, data.publisher), publisherName: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.publisherName, data.publisherName), theme: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.theme, data.theme), computerLanguage: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.computerLanguage, data.computerLanguage), target: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.target, data.target), slug: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.slug, data.slug), tag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tag, data.tag), reductionTag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.reductionTag, data.reductionTag), bubbleTag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.bubbleTag, data.bubbleTag), levelCEFRp: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.levelCEFRp, data.levelCEFRp), levelCEFR: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.levelCEFR, data.levelCEFR), levelILR: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.levelILR, data.levelILR), levelACTFL: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.levelACTFL, data.levelACTFL), icon: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.icon, data.icon), iconTag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.iconTag, data.iconTag), colorTag: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.colorTag, data.colorTag), flashcardSet: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.flashcardSet, data.flashcardSet), subtype: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.subtype, data.subtype), bookAlias: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.bookAlias, data.bookAlias), coverImage: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.coverImage, data.coverImage), coverColor: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.coverColor, data.coverColor), publications: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.publications, data.publications), author: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.author, data.author), subject: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.subject, data.subject), date: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.date, data.date), dateEnd: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.dateEnd, data.dateEnd), location: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.location, data.location), kind: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.kind, data.kind), hasMarkAsDone: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.hasMarkAsDone, data.hasMarkAsDone), processHandIn: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.processHandIn, data.processHandIn), action: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.action, data.action), showInIndex: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.showInIndex, data.showInIndex), blockId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.blockId, data.blockId), pageNo: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.pageNo, data.pageNo), x: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.x, data.x), y: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.y, data.y), width: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.width, data.width), height: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.height, data.height), index: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.index, data.index), classification: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.classification, data.classification), availableClassifications: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.availableClassifications, data.availableClassifications), allowedBit: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.allowedBit, data.allowedBit), tableFixedHeader: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableFixedHeader, data.tableFixedHeader), tableSearch: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableSearch, data.tableSearch), tableSort: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableSort, data.tableSort), tablePagination: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tablePagination, data.tablePagination), tablePaginationLimit: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tablePaginationLimit, data.tablePaginationLimit), tableHeight: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableHeight, data.tableHeight), tableWhitespaceNoWrap: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableWhitespaceNoWrap, data.tableWhitespaceNoWrap), tableAutoWidth: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableAutoWidth, data.tableAutoWidth), tableResizableColumns: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableResizableColumns, data.tableResizableColumns), tableColumnMinWidth: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.tableColumnMinWidth, data.tableColumnMinWidth), quizCountItems: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.quizCountItems, data.quizCountItems), quizStrikethroughSolutions: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.quizStrikethroughSolutions, data.quizStrikethroughSolutions), codeLineNumbers: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.codeLineNumbers, data.codeLineNumbers), codeMinimap: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.codeMinimap, data.codeMinimap), stripePricingTableId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.stripePricingTableId, data.stripePricingTableId), stripePublishableKey: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.stripePublishableKey, data.stripePublishableKey), thumbImage: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.thumbImage, data.thumbImage), scormSource: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.scormSource, data.scormSource), posterImage: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.posterImage, data.posterImage), focusX: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.focusX, data.focusX), focusY: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.focusY, data.focusY), pointerLeft: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.pointerLeft, data.pointerLeft), pointerTop: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.pointerTop, data.pointerTop), listItemIndent: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.listItemIndent, data.listItemIndent), backgroundWallpaper: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.backgroundWallpaper, data.backgroundWallpaper), hasBookNavigation: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.hasBookNavigation, data.hasBookNavigation), duration: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.duration, data.duration), deeplink: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.deeplink, data.deeplink), externalLink: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.externalLink, data.externalLink), externalLinkText: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.externalLinkText, data.externalLinkText), videoCallLink: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.videoCallLink, data.videoCallLink), vendorUrl: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.vendorUrl, data.vendorUrl), search: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.search, data.search), list: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.list, data.list), textReference: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.textReference, data.textReference), isTracked: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.isTracked, data.isTracked), isInfoOnly: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.isInfoOnly, data.isInfoOnly), imageFirst: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.imageFirst, data.imageFirst), activityType: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.activityType, data.activityType), labelTrue: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.labelTrue, data.labelTrue), labelFalse: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.labelFalse, data.labelFalse), content2Buy: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.content2Buy, data.content2Buy), mailingList: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.mailingList, data.mailingList), buttonCaption: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.buttonCaption, data.buttonCaption), callToActionUrl: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.callToActionUrl, data.callToActionUrl), caption: this.handleJsonText(data.caption), quotedPerson: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.quotedPerson, data.quotedPerson), reasonableNumOfChars: reasonableNumOfCharsProperty, resolved: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.resolved, data.resolved), resolvedDate: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.resolvedDate, data.resolvedDate), resolvedBy: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.resolvedBy, data.resolvedBy), maxCreatedBits: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.maxCreatedBits, data.maxCreatedBits), maxDisplayLevel: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.maxDisplayLevel, data.maxDisplayLevel), page: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.page, data.page), productId: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.productId, data.productId), product: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.product, data.product), productList: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.productList, data.productList), productVideo: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.productVideo, data.productVideo), productVideoList: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.productVideoList, data.productVideoList), productFolder: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.productFolder, data.productFolder), technicalTerm: this.buildTechnicalTerm(data.technicalTerm), servings: this.buildServings(data.servings), ratingLevelStart: this.buildRatingLevelStartEnd(data.ratingLevelStart), ratingLevelEnd: this.buildRatingLevelStartEnd(data.ratingLevelEnd), ratingLevelSelected: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.ratingLevelSelected, data.ratingLevelSelected), markConfig: this.buildMarkConfigs(data.markConfig), imageSource: this.buildImageSource(data.imageSource), person: this.buildPerson(data.bitType, data.person), bot: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.bot, data.bot), referenceProperty: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.property_reference, data.referenceProperty),
68
+ // Book data
69
+ title: this.handleJsonText(data.title), subtitle: this.handleJsonText(data.subtitle), level: NumberUtils_1.NumberUtils.asNumber(data.level), toc: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.toc, data.toc), progress: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.progress, data.progress), anchor: data.anchor, reference: data.reference, referenceEnd: data.referenceEnd,
70
+ // Item, Lead, Hint, Instruction
71
+ item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), pageNumber: this.handleJsonText(data.pageNumber), marginNumber: this.handleJsonText(data.marginNumber), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction), partialAnswer: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.partialAnswer, data.partialAnswer), sampleSolution: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.property_sampleSolution, data.sampleSolution), additionalSolutions: this.toAstProperty(PropertyConfigKey_1.PropertyConfigKey.additionalSolutions, data.additionalSolutions) }, this.toExample(data.__isDefaultExample, data.example)), {
72
+ // Person
73
+ // Body
74
+ body: this.buildBody(textFormat, data.body), imagePlaceholder: ArrayUtils_1.ArrayUtils.asSingle(this.resourceBuilder.resourceFromResourceDataJson(data.bitType, ResourceTag_1.ResourceTag.image, (_b = data.imagePlaceholder) === null || _b === void 0 ? void 0 : _b.image)), resources: ArrayUtils_1.ArrayUtils.asArray(this.resourceBuilder.resourceFromResourceJson(data.bitType, data.resources)), cardNode, footer: this.buildFooter(data.footer), markup: data.markup, parser: data.parser,
75
75
  // Must always be last in the AST so key clashes are avoided correctly with other properties
76
- extraProperties: this.parseExtraProperties(extraProperties) });
76
+ extraProperties: this.parseExtraProperties(data.extraProperties),
77
+ // Private properties
78
+ __isDefaultExample: (_c = data.__isDefaultExample) !== null && _c !== void 0 ? _c : false });
77
79
  // Push reasonableNumOfChars down the tree for the interview bit
78
- if (Config_1.Config.isOfBitType(bitType, BitType_1.BitType.interview)) {
79
- this.pushDownTree(undefined, undefined, cardNode, 'questions', PropertyConfigKey_1.PropertyConfigKey.reasonableNumOfChars, reasonableNumOfChars);
80
+ if (Config_1.Config.isOfBitType(data.bitType, BitType_1.BitType.interview)) {
81
+ this.pushDownTree(undefined, undefined, cardNode, 'questions', PropertyConfigKey_1.PropertyConfigKey.reasonableNumOfChars, data.reasonableNumOfChars);
80
82
  }
81
83
  // Push isCaseSensitive down the tree for the cloze, match and match-matrix bits
82
- this.pushDownTree(body, [BodyBitType_1.BodyBitType.gap], undefined, undefined, PropertyConfigKey_1.PropertyConfigKey.isCaseSensitive, isCaseSensitive);
83
- this.pushDownTree(undefined, undefined, cardNode, 'pairs', PropertyConfigKey_1.PropertyConfigKey.isCaseSensitive, isCaseSensitive);
84
- this.pushDownTree(undefined, undefined, cardNode, ['matrix', 'cells'], PropertyConfigKey_1.PropertyConfigKey.isCaseSensitive, isCaseSensitive);
85
- // If isDefaultExample is set at the bit level, push the default example down the tree to the relevant nodes
86
- this.pushExampleDownTree(body, cardNode, isDefaultExample, example);
84
+ this.pushDownTree([data.body, ...((_e = (_d = cardNode === null || cardNode === void 0 ? void 0 : cardNode.cardBits) === null || _d === void 0 ? void 0 : _d.map((cardBit) => cardBit.body)) !== null && _e !== void 0 ? _e : [])], [BodyBitType_1.BodyBitType.gap], undefined, 'isCaseSensitive', PropertyConfigKey_1.PropertyConfigKey.isCaseSensitive, (_f = data.isCaseSensitive) !== null && _f !== void 0 ? _f : true);
85
+ this.pushDownTree(undefined, undefined, cardNode, 'pairs', PropertyConfigKey_1.PropertyConfigKey.isCaseSensitive, (_g = data.isCaseSensitive) !== null && _g !== void 0 ? _g : true);
86
+ this.pushDownTree(undefined, undefined, cardNode, ['matrix', 'cells'], PropertyConfigKey_1.PropertyConfigKey.isCaseSensitive, (_h = data.isCaseSensitive) !== null && _h !== void 0 ? _h : true);
87
+ // If __isDefaultExample is set at the bit level, push the default example down the tree to the relevant nodes
88
+ this.pushExampleDownTree(data.body, cardNode, data.__isDefaultExample, convertedExample.example);
87
89
  // Set default values
88
90
  this.setDefaultBitValues(node);
89
91
  // Set the 'isExample' flags
@@ -93,45 +95,88 @@ class Builder extends BaseBuilder_1.BaseBuilder {
93
95
  // Remove Unset Optionals
94
96
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
95
97
  ignoreAllFalse: true,
96
- ignoreEmptyString: ['example'],
98
+ ignoreUndefined: ['example'],
99
+ ignoreEmptyArrays: ['item', 'lead', 'pageNumber', 'marginNumber', 'hint', 'instruction'],
97
100
  });
98
101
  // Validate and correct invalid bits as much as possible
99
102
  return NodeValidator_1.NodeValidator.validateBit(node);
100
103
  }
104
+ /**
105
+ * Build choice[] node
106
+ *
107
+ * @param data - data for the node
108
+ * @returns
109
+ */
110
+ buildChoices(data) {
111
+ if (!Array.isArray(data))
112
+ return undefined;
113
+ const nodes = data.map((d) => this.buildChoice(d)).filter((d) => d != null);
114
+ return nodes.length > 0 ? nodes : undefined;
115
+ }
101
116
  /**
102
117
  * Build choice node
103
118
  *
104
119
  * @param data - data for the node
105
120
  * @returns
106
121
  */
107
- choice(data) {
108
- const { text, isCorrect, item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample, example } = data;
122
+ buildChoice(data) {
123
+ var _a;
124
+ if (!data)
125
+ return undefined;
109
126
  // NOTE: Node order is important and is defined here
110
- const node = Object.assign({ text, isCorrect: !!isCorrect, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
111
- instruction }, this.toExampleBoolean(isDefaultExample, example));
127
+ const node = Object.assign({ choice: (_a = data.choice) !== null && _a !== void 0 ? _a : '', isCorrect: !!data.isCorrect, item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(data.__isDefaultExample, data.example, !!data.isCorrect));
112
128
  // Remove Unset Optionals
113
129
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
114
130
  ignoreAllFalse: true,
131
+ ignoreEmptyArrays: ['item', 'hint', 'instruction'],
132
+ ignoreUndefined: ['example'],
115
133
  });
116
134
  return node;
117
135
  }
136
+ /**
137
+ * Build response[] node
138
+ *
139
+ * @param data - data for the node
140
+ * @returns
141
+ */
142
+ buildResponses(data) {
143
+ if (!Array.isArray(data))
144
+ return undefined;
145
+ const nodes = data.map((d) => this.buildResponse(d)).filter((d) => d != null);
146
+ return nodes.length > 0 ? nodes : undefined;
147
+ }
118
148
  /**
119
149
  * Build response node
120
150
  *
121
151
  * @param data - data for the node
122
152
  * @returns
123
153
  */
124
- response(data) {
125
- const { text, isCorrect, item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample, example } = data;
154
+ buildResponse(data) {
155
+ var _a;
156
+ if (!data)
157
+ return undefined;
126
158
  // NOTE: Node order is important and is defined here
127
- const node = Object.assign({ text, isCorrect: !!isCorrect, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
128
- instruction }, this.toExampleBoolean(isDefaultExample, example));
159
+ const node = Object.assign({ response: (_a = data.response) !== null && _a !== void 0 ? _a : '', isCorrect: !!data.isCorrect, item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(data.__isDefaultExample, data.example, !!data.isCorrect));
129
160
  // Remove Unset Optionals
130
161
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
131
162
  ignoreAllFalse: true,
163
+ ignoreEmptyArrays: ['item', 'hint', 'instruction'],
164
+ ignoreUndefined: ['example'],
132
165
  });
133
166
  return node;
134
167
  }
168
+ /**
169
+ * Build bot response[] node
170
+ *
171
+ * @param data - data for the node
172
+ * @returns
173
+ */
174
+ buildBotResponses(data) {
175
+ if (!Array.isArray(data))
176
+ return undefined;
177
+ const nodes = data.map((d) => this.botResponse(d)).filter((d) => d != null);
178
+ return nodes.length > 0 ? nodes : undefined;
179
+ }
135
180
  /**
136
181
  * Build bot response node
137
182
  *
@@ -139,44 +184,79 @@ class Builder extends BaseBuilder_1.BaseBuilder {
139
184
  * @returns
140
185
  */
141
186
  botResponse(data) {
142
- const { response, reaction, feedback, item, lead, pageNumber, marginNumber, hint } = data;
187
+ var _a, _b, _c;
188
+ if (!data)
189
+ return undefined;
143
190
  // NOTE: Node order is important and is defined here
144
191
  const node = {
145
- response,
146
- reaction,
147
- feedback,
148
- itemLead: this.itemLead(item, lead, pageNumber, marginNumber),
149
- hint,
192
+ response: (_a = data.response) !== null && _a !== void 0 ? _a : '',
193
+ reaction: (_b = data.reaction) !== null && _b !== void 0 ? _b : '',
194
+ feedback: (_c = data.feedback) !== null && _c !== void 0 ? _c : '',
195
+ item: this.handleJsonText(data.item),
196
+ lead: this.handleJsonText(data.lead),
197
+ hint: this.handleJsonText(data.hint),
150
198
  };
151
199
  // Remove Unset Optionals
152
200
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
153
201
  ignoreEmptyString: ['response', 'reaction', 'feedback'],
202
+ ignoreAllFalse: true,
203
+ ignoreEmptyArrays: ['item'],
204
+ ignoreUndefined: ['example'],
154
205
  });
155
206
  return node;
156
207
  }
208
+ /**
209
+ * Build quiz[] node
210
+ *
211
+ * @param data - data for the node
212
+ * @returns
213
+ */
214
+ buildQuizzes(data) {
215
+ if (!Array.isArray(data))
216
+ return undefined;
217
+ const nodes = data.map((d) => this.buildQuiz(d)).filter((d) => d != null);
218
+ return nodes.length > 0 ? nodes : undefined;
219
+ }
157
220
  /**
158
221
  * Build quiz node
159
222
  *
160
223
  * @param data - data for the node
161
224
  * @returns
162
225
  */
163
- quiz(data) {
164
- const { choices, responses, item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample, example } = data;
165
- // Push isDefaultExample down the tree
166
- this.pushExampleDownTreeBoolean(isDefaultExample, example, true, choices);
167
- this.pushExampleDownTreeBoolean(isDefaultExample, example, false, responses);
226
+ buildQuiz(data) {
227
+ if (!data)
228
+ return undefined;
229
+ const convertedExample = Object.assign({}, this.toExample(data.__isDefaultExample, data.__defaultExample));
230
+ let choices;
231
+ let responses;
232
+ if (data.choices) {
233
+ choices = this.buildChoices(data.choices);
234
+ // Push __isDefaultExample down the tree
235
+ this.pushExampleDownTreeBoolean(data.__isDefaultExample, convertedExample.example, true, choices);
236
+ }
237
+ else if (data.responses) {
238
+ responses = this.buildResponses(data.responses);
239
+ // Push __isDefaultExample down the tree
240
+ this.pushExampleDownTreeBoolean(data.__isDefaultExample, convertedExample.example, false, responses);
241
+ }
242
+ else {
243
+ // No choices or responses, not a valid quiz
244
+ return undefined;
245
+ }
168
246
  // NOTE: Node order is important and is defined here
169
247
  const node = {
170
- itemLead: this.itemLead(item, lead, pageNumber, marginNumber),
171
- hint,
172
- instruction,
173
- isExample: isDefaultExample || example != null,
174
- choices,
175
- responses,
248
+ item: this.handleJsonText(data.item),
249
+ lead: this.handleJsonText(data.lead),
250
+ hint: this.handleJsonText(data.hint),
251
+ instruction: this.handleJsonText(data.instruction),
252
+ isExample: !!data.__defaultExample,
253
+ choices: choices,
254
+ responses: responses,
176
255
  };
177
256
  // Remove Unset Optionals
178
257
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
179
258
  ignoreAllFalse: true,
259
+ ignoreEmptyArrays: ['item', 'hint', 'instruction'],
180
260
  });
181
261
  return node;
182
262
  }
@@ -186,69 +266,126 @@ class Builder extends BaseBuilder_1.BaseBuilder {
186
266
  * @param data - data for the node
187
267
  * @returns
188
268
  */
189
- heading(data) {
190
- var _a;
191
- const { forKeys, forValues } = data;
192
- if (forKeys == null)
269
+ buildHeading(data) {
270
+ var _a, _b, _c;
271
+ if (!data)
272
+ return undefined;
273
+ if (data.forKeys == null)
193
274
  return undefined;
194
275
  // NOTE: Node order is important and is defined here
195
276
  const node = {
196
- forKeys: forKeys || Breakscape_1.Breakscape.EMPTY_STRING,
197
- forValues: (_a = ArrayUtils_1.ArrayUtils.asArray(forValues)) !== null && _a !== void 0 ? _a : [],
277
+ forKeys: (_a = data.forKeys) !== null && _a !== void 0 ? _a : '',
278
+ forValues: (_c = (_b = data.forValues) !== null && _b !== void 0 ? _b : data.__forValuesDefault) !== null && _c !== void 0 ? _c : '',
198
279
  };
199
280
  // Remove Unset Optionals
200
- // ObjectUtils.removeUnwantedProperties(node);
281
+ ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
282
+ ignoreAllFalse: true,
283
+ ignoreEmptyString: ['forKeys', 'forValues'],
284
+ ignoreEmptyArrays: ['forValues'],
285
+ });
201
286
  return node;
202
287
  }
288
+ /**
289
+ * Build pair[] node
290
+ *
291
+ * @param data - data for the node
292
+ * @returns
293
+ */
294
+ buildPairs(bitType, data) {
295
+ if (!Array.isArray(data))
296
+ return undefined;
297
+ const nodes = data.map((d) => this.buildPair(bitType, d)).filter((d) => d != null);
298
+ return nodes.length > 0 ? nodes : undefined;
299
+ }
203
300
  /**
204
301
  * Build pair node
205
302
  *
206
303
  * @param data - data for the node
207
304
  * @returns
208
305
  */
209
- pair(data) {
210
- const { key, keyAudio, keyImage, values, item, lead, pageNumber, marginNumber, hint, instruction, isCaseSensitive, isDefaultExample, example, } = data;
306
+ buildPair(bitType, data) {
307
+ var _a, _b, _c, _d;
308
+ if (!data)
309
+ return undefined;
310
+ // Set default example
311
+ const defaultExample = Array.isArray(data.__valuesAst) && data.__valuesAst.length > 0 ? data.__valuesAst[0] : null;
312
+ // Process the keyAudio and keyImage resources
313
+ const keyAudio = (_a = ArrayUtils_1.ArrayUtils.asSingle(this.resourceBuilder.resourceFromResourceDataJson(bitType, ResourceTag_1.ResourceTag.audio, data.keyAudio))) === null || _a === void 0 ? void 0 : _a.audio;
314
+ const keyImage = (_b = ArrayUtils_1.ArrayUtils.asSingle(this.resourceBuilder.resourceFromResourceDataJson(bitType, ResourceTag_1.ResourceTag.image, data.keyImage))) === null || _b === void 0 ? void 0 : _b.image;
211
315
  // NOTE: Node order is important and is defined here
212
- const node = Object.assign(Object.assign({ key,
213
- keyAudio,
214
- keyImage, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
215
- instruction }, this.toExample(isDefaultExample, example)), { isCaseSensitive,
216
- values });
316
+ const node = Object.assign(Object.assign({ key: (_c = data.key) !== null && _c !== void 0 ? _c : '', keyAudio,
317
+ keyImage, item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction), isCaseSensitive: data.isCaseSensitive }, this.toExample(data.__isDefaultExample, data.example, defaultExample)), { values: (_d = data.values) !== null && _d !== void 0 ? _d : [], __valuesAst: data.__valuesAst });
217
318
  // Remove Unset Optionals
218
319
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
219
320
  ignoreAllFalse: true,
321
+ ignoreEmptyArrays: ['item', 'hint', 'instruction', 'values'],
322
+ ignoreUndefined: ['example', 'isCaseSensitive'],
220
323
  });
324
+ // if (node.key) {
325
+ // delete node.keyAudio;
326
+ // delete node.keyImage;
327
+ // }
328
+ // if (node.keyAudio != null) {
329
+ // delete node.key;
330
+ // delete node.keyImage;
331
+ // }
332
+ // if (node.keyImage != null) {
333
+ // delete node.key;
334
+ // delete node.keyAudio;
335
+ // }
221
336
  return node;
222
337
  }
338
+ /**
339
+ * Build matrix[] node
340
+ *
341
+ * @param data - data for the node
342
+ * @returns
343
+ */
344
+ buildMatricies(data) {
345
+ if (!Array.isArray(data))
346
+ return undefined;
347
+ const nodes = data.map((d) => this.buildMatrix(d)).filter((d) => d != null);
348
+ return nodes.length > 0 ? nodes : undefined;
349
+ }
223
350
  /**
224
351
  * Build matrix node
225
352
  *
226
353
  * @param data - data for the node
227
354
  * @returns
228
355
  */
229
- matrix(data) {
230
- const { key, cells, item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample } = data;
356
+ buildMatrix(data) {
357
+ var _a, _b, _c;
358
+ if (!data)
359
+ return undefined;
360
+ // const convertedExample = {
361
+ // ...this.toExample(__isDefaultExample, example),
362
+ // };
363
+ // // Push __isDefaultExample down the tree
364
+ // this.pushExampleDownTreeBoolean(__isDefaultExample, convertedExample.example, true, choices);
365
+ // this.pushExampleDownTreeBoolean(__isDefaultExample, convertedExample.example, false, responses);
231
366
  let isExample = false;
232
367
  // Set isExample for matrix based on isExample for cells
233
- for (const c of cells !== null && cells !== void 0 ? cells : []) {
234
- if (isDefaultExample && !c.isExample) {
235
- c.isDefaultExample = true;
368
+ for (const c of (_a = data.cells) !== null && _a !== void 0 ? _a : []) {
369
+ if (data.__isDefaultExample && !c.isExample) {
236
370
  c.isExample = true;
237
371
  }
238
372
  isExample = c.isExample ? true : isExample;
239
373
  }
240
374
  // NOTE: Node order is important and is defined here
241
375
  const node = {
242
- key,
243
- itemLead: this.itemLead(item, lead, pageNumber, marginNumber),
244
- hint,
245
- instruction,
376
+ key: (_b = data.key) !== null && _b !== void 0 ? _b : '',
377
+ item: this.handleJsonText(data.item),
378
+ lead: this.handleJsonText(data.lead),
379
+ hint: this.handleJsonText(data.hint),
380
+ instruction: this.handleJsonText(data.instruction),
246
381
  isExample,
247
- cells,
382
+ cells: ((_c = data.cells) !== null && _c !== void 0 ? _c : []).map((c) => this.buildMatrixCell(c)).filter((c) => c != null),
248
383
  };
249
384
  // Remove Unset Optionals
250
385
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
251
386
  ignoreAllFalse: true,
387
+ ignoreEmptyArrays: ['hint', 'item', 'cells'],
388
+ ignoreUndefined: ['isCaseSensitive'],
252
389
  });
253
390
  return node;
254
391
  }
@@ -258,15 +395,19 @@ class Builder extends BaseBuilder_1.BaseBuilder {
258
395
  * @param data - data for the node
259
396
  * @returns
260
397
  */
261
- matrixCell(data) {
262
- const { values, item, lead, pageNumber, marginNumber, hint, instruction, isCaseSensitive, isDefaultExample, example, } = data;
398
+ buildMatrixCell(data) {
399
+ var _a;
400
+ if (!data)
401
+ return undefined;
402
+ // Set default example
403
+ const defaultExample = Array.isArray(data.__valuesAst) && data.__valuesAst.length > 0 ? data.__valuesAst[0] : null;
263
404
  // NOTE: Node order is important and is defined here
264
- const node = Object.assign({ values, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
265
- instruction,
266
- isCaseSensitive }, this.toExample(isDefaultExample, example));
405
+ const node = Object.assign(Object.assign({ values: (_a = data.values) !== null && _a !== void 0 ? _a : [], item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction), isCaseSensitive: data.isCaseSensitive }, this.toExample(data.__isDefaultExample, data.example, defaultExample)), { __valuesAst: data.__valuesAst });
267
406
  // Remove Unset Optionals
268
407
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
269
408
  ignoreAllFalse: true,
409
+ ignoreEmptyArrays: ['instruction', 'item', 'values'],
410
+ ignoreUndefined: ['example', 'isCaseSensitive'],
270
411
  });
271
412
  return node;
272
413
  }
@@ -276,12 +417,14 @@ class Builder extends BaseBuilder_1.BaseBuilder {
276
417
  * @param data - data for the node
277
418
  * @returns
278
419
  */
279
- table(data) {
280
- const { columns, rows } = data;
420
+ buildTable(dataIn) {
421
+ var _a, _b;
422
+ if (!dataIn)
423
+ return undefined;
281
424
  // NOTE: Node order is important and is defined here
282
425
  const node = {
283
- columns,
284
- rows,
426
+ columns: (_a = dataIn.columns) !== null && _a !== void 0 ? _a : [],
427
+ data: ((_b = dataIn.data) !== null && _b !== void 0 ? _b : []).map((row) => row !== null && row !== void 0 ? row : []),
285
428
  };
286
429
  // Remove Unset Optionals
287
430
  // ObjectUtils.removeUnwantedProperties(node, {
@@ -289,81 +432,235 @@ class Builder extends BaseBuilder_1.BaseBuilder {
289
432
  // });
290
433
  return node;
291
434
  }
435
+ /**
436
+ * Build question[] node
437
+ *
438
+ * @param data - data for the node
439
+ * @returns
440
+ */
441
+ buildQuestions(data) {
442
+ if (!Array.isArray(data))
443
+ return undefined;
444
+ const nodes = data.map((d) => this.buildQuestion(d)).filter((d) => d != null);
445
+ return nodes.length > 0 ? nodes : undefined;
446
+ }
292
447
  /**
293
448
  * Build question node
294
449
  *
295
450
  * @param data - data for the node
296
451
  * @returns
297
452
  */
298
- question(data) {
299
- const { question, partialAnswer, item, lead, pageNumber, marginNumber, hint, instruction, reasonableNumOfChars, sampleSolution, additionalSolutions, isDefaultExample, example, } = data;
453
+ buildQuestion(data) {
454
+ var _a, _b, _c, _d, _e;
455
+ if (!data)
456
+ return undefined;
457
+ // Set default example
458
+ const defaultExample = data.__sampleSolutionAst;
300
459
  // NOTE: Node order is important and is defined here
301
- const node = Object.assign(Object.assign({ itemLead: this.itemLead(item, lead, pageNumber, marginNumber), question,
302
- partialAnswer,
303
- hint,
304
- instruction }, this.toExample(isDefaultExample, example)), { reasonableNumOfChars,
305
- sampleSolution,
306
- additionalSolutions });
460
+ const node = Object.assign(Object.assign({ question: (_a = data.question) !== null && _a !== void 0 ? _a : '', partialAnswer: (_b = data.partialAnswer) !== null && _b !== void 0 ? _b : '', sampleSolution: (_c = data.sampleSolution) !== null && _c !== void 0 ? _c : '', additionalSolutions: ((_d = data.additionalSolutions) !== null && _d !== void 0 ? _d : undefined), reasonableNumOfChars: ((_e = data.reasonableNumOfChars) !== null && _e !== void 0 ? _e : undefined), item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(data.__isDefaultExample, data.example, defaultExample)), { __sampleSolutionAst: data.__sampleSolutionAst });
307
461
  // Remove Unset Optionals
308
462
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
309
- ignoreEmptyString: ['question'],
310
463
  ignoreAllFalse: true,
464
+ ignoreEmptyArrays: ['item', 'hint', 'instruction'],
465
+ ignoreUndefined: ['example'],
466
+ ignoreEmptyString: ['question', 'partialAnswer', 'sampleSolution'],
311
467
  });
312
468
  return node;
313
469
  }
470
+ /**
471
+ * Build ingredient[] node
472
+ *
473
+ * @param data - data for the node
474
+ * @returns
475
+ */
476
+ buildIngredients(data) {
477
+ if (!Array.isArray(data))
478
+ return undefined;
479
+ const nodes = data.map((d) => this.buildIngredient(d)).filter((d) => d != null);
480
+ return nodes.length > 0 ? nodes : undefined;
481
+ }
314
482
  /**
315
483
  * Build ingredient node
316
484
  *
317
485
  * @param data - data for the node
318
486
  * @returns
319
487
  */
320
- ingredient(data) {
321
- const { title, checked, item, quantity, unit, unitAbbr, decimalPlaces, disableCalculation } = data;
488
+ buildIngredient(data) {
489
+ var _a, _b, _c, _d, _e, _f, _g, _h;
490
+ if (!data)
491
+ return undefined;
322
492
  // NOTE: Node order is important and is defined here
323
493
  const node = {
324
- title,
325
- checked: checked !== null && checked !== void 0 ? checked : false,
326
- item,
327
- quantity,
328
- unit,
329
- unitAbbr,
330
- decimalPlaces,
331
- disableCalculation,
494
+ title: (_a = data.title) !== null && _a !== void 0 ? _a : '',
495
+ checked: (_b = data.checked) !== null && _b !== void 0 ? _b : false,
496
+ item: (_c = data.item) !== null && _c !== void 0 ? _c : '',
497
+ quantity: (_d = data.quantity) !== null && _d !== void 0 ? _d : 0,
498
+ unit: (_e = data.unit) !== null && _e !== void 0 ? _e : '',
499
+ unitAbbr: (_f = data.unitAbbr) !== null && _f !== void 0 ? _f : '',
500
+ decimalPlaces: (_g = data.decimalPlaces) !== null && _g !== void 0 ? _g : 1,
501
+ disableCalculation: (_h = data.disableCalculation) !== null && _h !== void 0 ? _h : false,
332
502
  };
333
503
  // Remove Unset Optionals
334
504
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
335
505
  ignoreAllFalse: true,
506
+ // ignoreAllEmptyArrays: true,
507
+ // ignoreUndefined: ['example'],
508
+ ignoreEmptyString: ['item', 'unit'],
336
509
  });
337
510
  return node;
338
511
  }
339
512
  /**
340
513
  * Build body node
514
+ * - Handles JSON, Bitmark text, and plain text
515
+ * - body: set to either string, TextAst, or JSON
516
+ * - bodyBits: set to array of BodyBitJson (will be validated and merged into body if it is a string)
517
+ * - placeholders: set to placeholders from v2 JSON when body is a v2 JSON string
518
+ * - bodyString: set to the original string if body is a string (only used for card body)
341
519
  *
342
520
  * @param data - data for the node
343
521
  * @returns
344
522
  */
345
- body(data) {
346
- const { bodyParts, bodyJson } = data;
347
- const node = {
348
- bodyParts,
349
- bodyJson,
523
+ buildBody(textFormat, data) {
524
+ if (!data)
525
+ return undefined;
526
+ let body;
527
+ const bodyBits = [];
528
+ const placeholders = data.placeholders;
529
+ const bodyString = data.bodyString;
530
+ // Handle JSON type body
531
+ const handleJsonBody = () => {
532
+ // Attempt to parse a string body as JSON to support the legacy format
533
+ if (typeof data.body === 'string') {
534
+ try {
535
+ body = JSON.parse(data.body);
536
+ }
537
+ catch (e) {
538
+ // Could not parse JSON - set body to null
539
+ body = null;
540
+ }
541
+ }
542
+ else {
543
+ body = data.body;
544
+ }
350
545
  };
351
- return node;
352
- }
353
- /**
354
- * Build bodyPartText node
355
- *
356
- * @param data - data for the node
357
- * @returns
358
- */
359
- bodyText(data) {
360
- const { text } = data;
361
- // NOTE: Node order is important and is defined here
546
+ // Handle Bitmark text type body (both AST v3 and plain text v2)
547
+ const handleBitmarkTextBody = () => {
548
+ var _a;
549
+ let rawBody = data.body;
550
+ let bodyStr;
551
+ const placeholderNodes = {};
552
+ // TODO - process body bits through the correct builders.
553
+ if (StringUtils_1.StringUtils.isString(data.body)) {
554
+ // Body is a string (legacy bitmark v2, or not bitmark--/++)
555
+ bodyStr = ((_a = data.body) !== null && _a !== void 0 ? _a : '').trim();
556
+ rawBody = [];
557
+ }
558
+ else if (Array.isArray(data.body)) {
559
+ // Body is an array (prosemirror like JSON)
560
+ // Already in the correct format
561
+ }
562
+ else {
563
+ // body is invalid
564
+ rawBody = [];
565
+ }
566
+ if (placeholders) {
567
+ for (const [key, val] of Object.entries(placeholders)) {
568
+ // const bit = this.bodyBitToAst(val);
569
+ // placeholderNodes[key] = bit as BodyBit;
570
+ placeholderNodes[key] = val;
571
+ }
572
+ }
573
+ if (bodyStr) {
574
+ // Breakscape
575
+ bodyStr = Breakscape_1.Breakscape.breakscape(bodyStr, {
576
+ textFormat: TextFormat_1.TextFormat.bitmarkMinusMinus, // Treat as bitmark-- for v2 text
577
+ });
578
+ // Convert placeholders {1} to [!1], etc.
579
+ let index = 0;
580
+ const newPlaceholderNodes = [];
581
+ for (const [key, val] of Object.entries(placeholderNodes)) {
582
+ if (bodyStr) {
583
+ const newKey = `[!${index}]`;
584
+ bodyStr = bodyStr.replace(`${key}`, newKey);
585
+ newPlaceholderNodes.push(val);
586
+ index++;
587
+ }
588
+ }
589
+ // Convert the body string to AST
590
+ rawBody = this.textParser.toAst(bodyStr, {
591
+ textFormat: TextFormat_1.TextFormat.bitmarkMinusMinus, // Treat as bitmark-- for v2 text
592
+ });
593
+ const replaceBitsRecursive = (bodyText) => {
594
+ for (let i = 0, len = bodyText.length; i < len; i++) {
595
+ const bodyPart = bodyText[i];
596
+ if (bodyPart.type === 'bit') {
597
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
598
+ const index = bodyPart.index;
599
+ if (newPlaceholderNodes[index] != null) {
600
+ bodyText[i] = newPlaceholderNodes[index];
601
+ }
602
+ }
603
+ else {
604
+ if (bodyPart.content)
605
+ replaceBitsRecursive(bodyPart.content);
606
+ }
607
+ }
608
+ };
609
+ // Replace the placeholders with the AST
610
+ replaceBitsRecursive(rawBody);
611
+ }
612
+ // Process the body bits to ensure they are valid
613
+ this.textParser.walkBodyBits(rawBody, (parent, index, bodyBit) => {
614
+ // Ensure the body bit is valid
615
+ let parsedBit;
616
+ switch (bodyBit.type) {
617
+ case BodyBitType_1.BodyBitType.gap:
618
+ parsedBit = this.buildGap(bodyBit);
619
+ break;
620
+ case BodyBitType_1.BodyBitType.mark:
621
+ parsedBit = this.buildMark(bodyBit);
622
+ break;
623
+ case BodyBitType_1.BodyBitType.select:
624
+ parsedBit = this.buildSelect(bodyBit);
625
+ break;
626
+ case BodyBitType_1.BodyBitType.highlight:
627
+ parsedBit = this.buildHighlight(bodyBit);
628
+ break;
629
+ default:
630
+ // TODO?? Ensure other parts are valid
631
+ }
632
+ if (parsedBit != undefined) {
633
+ parent[index] = parsedBit;
634
+ bodyBits.push(parsedBit);
635
+ }
636
+ });
637
+ // Set the body
638
+ body = rawBody;
639
+ // Mark the body as text
640
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
641
+ body.__tag = 'text';
642
+ };
643
+ const handlePlainTextBody = () => {
644
+ body = data.body;
645
+ };
646
+ const isBitmarkText = textFormat === TextFormat_1.TextFormat.bitmarkMinusMinus || textFormat === TextFormat_1.TextFormat.bitmarkPlusPlus;
647
+ if (textFormat === TextFormat_1.TextFormat.json) {
648
+ // JSON
649
+ handleJsonBody();
650
+ }
651
+ else if (isBitmarkText) {
652
+ // Bitmark text (either ast or string)
653
+ handleBitmarkTextBody();
654
+ }
655
+ else {
656
+ // Text but not bitmark (plain text)
657
+ handlePlainTextBody();
658
+ }
362
659
  const node = {
363
- type: BodyBitType_1.BodyBitType.text,
364
- data: {
365
- bodyText: text,
366
- },
660
+ body,
661
+ bodyBits,
662
+ bodyString,
663
+ // Placeholders are only ever parsed into AST, never stored directly
367
664
  };
368
665
  return node;
369
666
  }
@@ -373,11 +670,11 @@ class Builder extends BaseBuilder_1.BaseBuilder {
373
670
  * @param data - data for the node
374
671
  * @returns
375
672
  */
376
- footerText(data) {
377
- const { text } = data;
378
- // NOTE: Node order is important and is defined here
673
+ buildFooter(data) {
674
+ if (!data)
675
+ return undefined;
379
676
  const node = {
380
- footerText: text,
677
+ footer: this.handleJsonText(data.footer),
381
678
  };
382
679
  return node;
383
680
  }
@@ -387,38 +684,54 @@ class Builder extends BaseBuilder_1.BaseBuilder {
387
684
  * @param data - data for the node
388
685
  * @returns
389
686
  */
390
- gap(data) {
391
- const { solutions, item, lead, pageNumber, marginNumber, hint, instruction, isCaseSensitive, isDefaultExample, example, } = data;
392
- // const defaultExample = Array.isArray(solutions) && solutions.length === 1 ? solutions[0] : null;
687
+ buildGap(data) {
688
+ var _a;
689
+ if (!data)
690
+ return undefined;
691
+ // Set default example
692
+ const defaultExample = Array.isArray(data.__solutionsAst) && data.__solutionsAst.length > 0 ? data.__solutionsAst[0] : null;
393
693
  // NOTE: Node order is important and is defined here
394
- const node = {
395
- type: BodyBitType_1.BodyBitType.gap,
396
- data: Object.assign({ solutions, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
397
- instruction,
398
- isCaseSensitive }, this.toExample(isDefaultExample, example)),
399
- };
694
+ const node = Object.assign(Object.assign({ type: BodyBitType_1.BodyBitType.gap, solutions: (_a = data.solutions) !== null && _a !== void 0 ? _a : [], item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction), isCaseSensitive: data.isCaseSensitive }, this.toExample(data.__isDefaultExample, data.example, defaultExample)), { __solutionsAst: data.__solutionsAst });
400
695
  // Remove Unset Optionals
401
696
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
402
697
  ignoreAllFalse: true,
698
+ ignoreAllEmptyArrays: true,
699
+ ignoreUndefined: ['example', 'isCaseSensitive'],
403
700
  });
404
701
  return node;
405
702
  }
703
+ /**
704
+ * Build mark configs node
705
+ *
706
+ * @param data - data for the node
707
+ * @returns
708
+ */
709
+ buildMarkConfigs(data) {
710
+ if (!Array.isArray(data))
711
+ return undefined;
712
+ const nodes = data.map((d) => this.buildMarkConfig(d)).filter((d) => d != null);
713
+ return nodes.length > 0 ? nodes : undefined;
714
+ }
406
715
  /**
407
716
  * Build mark config node
408
717
  *
409
718
  * @param data - data for the node
410
719
  * @returns
411
720
  */
412
- markConfig(data) {
413
- const { mark, color, emphasis } = data;
721
+ buildMarkConfig(data) {
722
+ var _a, _b, _c;
723
+ if (!data)
724
+ return undefined;
414
725
  // NOTE: Node order is important and is defined here
415
726
  const node = {
416
- mark,
417
- color,
418
- emphasis,
727
+ mark: (_a = data.mark) !== null && _a !== void 0 ? _a : 'unknown',
728
+ color: (_b = data.color) !== null && _b !== void 0 ? _b : '',
729
+ emphasis: (_c = data.emphasis) !== null && _c !== void 0 ? _c : '',
419
730
  };
420
731
  // Remove Unset Optionals
421
- ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node);
732
+ ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
733
+ ignoreAllEmptyString: true,
734
+ });
422
735
  return node;
423
736
  }
424
737
  /**
@@ -427,17 +740,19 @@ class Builder extends BaseBuilder_1.BaseBuilder {
427
740
  * @param data - data for the node
428
741
  * @returns
429
742
  */
430
- mark(data) {
431
- const { solution, mark, item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample, example } = data;
743
+ buildMark(data) {
744
+ var _a, _b;
745
+ if (!data)
746
+ return undefined;
432
747
  // NOTE: Node order is important and is defined here
433
- const node = {
434
- type: BodyBitType_1.BodyBitType.mark,
435
- data: Object.assign({ solution,
436
- mark, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
437
- instruction }, this.toExample(isDefaultExample, example)),
438
- };
748
+ const node = Object.assign({ type: BodyBitType_1.BodyBitType.mark, solution: (_a = data.solution) !== null && _a !== void 0 ? _a : '', mark: (_b = data.mark) !== null && _b !== void 0 ? _b : '', item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(data.__isDefaultExample, data.example, true));
439
749
  // Remove Unset Optionals
440
- ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node);
750
+ ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
751
+ ignoreAllFalse: true,
752
+ ignoreAllEmptyArrays: true,
753
+ ignoreUndefined: ['example'],
754
+ ignoreEmptyString: ['solution', 'mark'],
755
+ });
441
756
  return node;
442
757
  }
443
758
  /**
@@ -446,40 +761,49 @@ class Builder extends BaseBuilder_1.BaseBuilder {
446
761
  * @param data - data for the node
447
762
  * @returns
448
763
  */
449
- select(data) {
450
- const { options, prefix, postfix, item, lead, pageNumber, marginNumber, hint, instruction } = data;
764
+ buildSelect(data) {
765
+ var _a, _b, _c;
766
+ if (!data)
767
+ return undefined;
451
768
  // NOTE: Node order is important and is defined here
452
- const node = {
453
- type: BodyBitType_1.BodyBitType.select,
454
- data: {
455
- prefix,
456
- options,
457
- postfix,
458
- itemLead: this.itemLead(item, lead, pageNumber, marginNumber),
459
- hint,
460
- instruction,
461
- },
462
- };
769
+ const node = Object.assign(Object.assign({ type: BodyBitType_1.BodyBitType.select, options: (_a = this.buildSelectOptions(data.options)) !== null && _a !== void 0 ? _a : [], prefix: (_b = data.prefix) !== null && _b !== void 0 ? _b : '', postfix: (_c = data.postfix) !== null && _c !== void 0 ? _c : '', item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(false, undefined, undefined)), { __hintString: data.__hintString, __instructionString: data.__instructionString });
463
770
  // Remove Unset Optionals
464
771
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
465
772
  ignoreAllFalse: true,
773
+ ignoreAllEmptyArrays: true,
774
+ ignoreEmptyString: ['prefix', 'postfix'],
466
775
  });
467
776
  return node;
468
777
  }
778
+ /**
779
+ * Build selectOption[] node
780
+ *
781
+ * @param data - data for the node
782
+ * @returns
783
+ */
784
+ buildSelectOptions(data) {
785
+ if (!Array.isArray(data))
786
+ return undefined;
787
+ const nodes = data.map((d) => this.buildSelectOption(d)).filter((d) => d != null);
788
+ return nodes.length > 0 ? nodes : undefined;
789
+ }
469
790
  /**
470
791
  * Build selectOption node
471
792
  *
472
793
  * @param data - data for the node
473
794
  * @returns
474
795
  */
475
- selectOption(data) {
476
- const { text, isCorrect, item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample, example } = data;
796
+ buildSelectOption(data) {
797
+ var _a;
798
+ if (!data)
799
+ return undefined;
477
800
  // NOTE: Node order is important and is defined here
478
- const node = Object.assign({ text, isCorrect: !!isCorrect, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
479
- instruction }, this.toExample(isDefaultExample, example));
801
+ const node = Object.assign({ text: (_a = data.text) !== null && _a !== void 0 ? _a : '', isCorrect: !!data.isCorrect, item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(data.__isDefaultExample, data.example, !!data.isCorrect));
480
802
  // Remove Unset Optionals
481
803
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
482
804
  ignoreAllFalse: true,
805
+ ignoreAllEmptyArrays: true,
806
+ ignoreUndefined: ['example'],
483
807
  });
484
808
  return node;
485
809
  }
@@ -489,95 +813,143 @@ class Builder extends BaseBuilder_1.BaseBuilder {
489
813
  * @param data - data for the node
490
814
  * @returns
491
815
  */
492
- highlight(data) {
493
- const { texts, prefix, postfix, item, lead, pageNumber, marginNumber, hint, instruction } = data;
816
+ buildHighlight(data) {
817
+ var _a, _b, _c;
818
+ if (!data)
819
+ return undefined;
494
820
  // NOTE: Node order is important and is defined here
495
- const node = {
496
- type: BodyBitType_1.BodyBitType.highlight,
497
- data: {
498
- prefix,
499
- texts,
500
- postfix,
501
- itemLead: this.itemLead(item, lead, pageNumber, marginNumber),
502
- hint,
503
- instruction,
504
- },
505
- };
821
+ const node = Object.assign({ type: BodyBitType_1.BodyBitType.highlight, texts: (_a = this.buildHighlightTexts(data.texts)) !== null && _a !== void 0 ? _a : [], prefix: (_b = data.prefix) !== null && _b !== void 0 ? _b : '', postfix: (_c = data.postfix) !== null && _c !== void 0 ? _c : '', item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(false, undefined, undefined));
506
822
  // Remove Unset Optionals
507
823
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
508
824
  ignoreAllFalse: true,
825
+ ignoreAllEmptyArrays: true,
826
+ ignoreEmptyString: ['prefix', 'postfix'],
509
827
  });
510
828
  return node;
511
829
  }
830
+ /**
831
+ * Build highlightText[] node
832
+ *
833
+ * @param data - data for the node
834
+ * @returns
835
+ */
836
+ buildHighlightTexts(data) {
837
+ if (!Array.isArray(data))
838
+ return undefined;
839
+ const nodes = data.map((d) => this.buildHighlightText(d)).filter((d) => d != null);
840
+ return nodes.length > 0 ? nodes : undefined;
841
+ }
512
842
  /**
513
843
  * Build highlightText node
514
844
  *
515
845
  * @param data - data for the node
516
846
  * @returns
517
847
  */
518
- highlightText(data) {
519
- const { text, isCorrect, isHighlighted, item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample, example, } = data;
848
+ buildHighlightText(data) {
849
+ var _a;
850
+ if (!data)
851
+ return undefined;
520
852
  // NOTE: Node order is important and is defined here
521
- const node = Object.assign({ text, isCorrect: !!isCorrect, isHighlighted: !!isHighlighted, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
522
- instruction }, this.toExample(isDefaultExample, example));
853
+ const node = Object.assign({ text: (_a = data.text) !== null && _a !== void 0 ? _a : '', isCorrect: !!data.isCorrect, isHighlighted: !!data.isHighlighted, item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(data.__isDefaultExample, data.example, !!data.isCorrect));
523
854
  // Remove Unset Optionals
524
855
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
525
856
  ignoreAllFalse: true,
857
+ ignoreAllEmptyArrays: true,
858
+ ignoreUndefined: ['example'],
526
859
  });
527
860
  return node;
528
861
  }
862
+ /**
863
+ * Build flashcards node
864
+ *
865
+ * @param data - data for the node
866
+ * @returns
867
+ */
868
+ buildFlashcards(data) {
869
+ if (!Array.isArray(data))
870
+ return undefined;
871
+ const nodes = data.map((d) => this.buildFlashcard(d)).filter((d) => d != null);
872
+ return nodes.length > 0 ? nodes : undefined;
873
+ }
529
874
  /**
530
875
  * Build flashcard node
531
876
  *
532
877
  * @param data - data for the node
533
878
  * @returns
534
879
  */
535
- flashcard(data) {
536
- const { question, answer, alternativeAnswers, item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample, example, } = data;
880
+ buildFlashcard(data) {
881
+ if (!data)
882
+ return undefined;
537
883
  // NOTE: Node order is important and is defined here
538
- const node = Object.assign({ question,
539
- answer,
540
- alternativeAnswers, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
541
- instruction }, this.toExampleBoolean(isDefaultExample, example));
884
+ const node = Object.assign({ question: this.handleJsonText(data.question), answer: this.handleJsonText(data.answer), alternativeAnswers: this.handleJsonText(data.alternativeAnswers), item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(data.__isDefaultExample, data.example, true));
542
885
  // Remove Unset Optionals
543
886
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
544
887
  ignoreAllFalse: true,
888
+ ignoreEmptyArrays: ['question', 'answer', 'alternativeAnswers', 'item', 'hint', 'instruction'],
889
+ ignoreUndefined: ['example'],
545
890
  });
546
891
  return node;
547
892
  }
893
+ /**
894
+ * Build definitionListItem[] node
895
+ *
896
+ * @param data - data for the node
897
+ * @returns
898
+ */
899
+ buildDefinitionList(data) {
900
+ if (!Array.isArray(data))
901
+ return undefined;
902
+ const nodes = data.map((d) => this.buildDefinitionListItem(d)).filter((d) => d != null);
903
+ return nodes.length > 0 ? nodes : undefined;
904
+ }
548
905
  /**
549
906
  * Build definitionListItem node
550
907
  *
551
908
  * @param data - data for the node
552
909
  * @returns
553
910
  */
554
- definitionListItem(data) {
555
- const { term, description, alternativeDefinitions, item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample, example, } = data;
911
+ buildDefinitionListItem(data) {
912
+ if (!data)
913
+ return undefined;
556
914
  // NOTE: Node order is important and is defined here
557
- const node = Object.assign({ term,
558
- description,
559
- alternativeDefinitions, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
560
- instruction }, this.toExampleBoolean(isDefaultExample, example));
915
+ const node = Object.assign({ term: this.handleJsonText(data.term, TextFormat_1.TextFormat.bitmarkMinusMinus), definition: this.handleJsonText(data.definition), alternativeDefinitions: this.handleJsonText(data.alternativeDefinitions), item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(data.__isDefaultExample, data.example, true));
561
916
  // Remove Unset Optionals
562
917
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
563
918
  ignoreAllFalse: true,
919
+ ignoreEmptyArrays: ['question', 'answer', 'alternativeDefinitions', 'item', 'hint', 'instruction'],
920
+ ignoreUndefined: ['example'],
564
921
  });
565
922
  return node;
566
923
  }
924
+ /**
925
+ * Build statement[] node
926
+ *
927
+ * @param data - data for the node
928
+ * @returns
929
+ */
930
+ buildStatements(data) {
931
+ if (!Array.isArray(data))
932
+ return undefined;
933
+ const nodes = data.map((d) => this.buildStatement(d)).filter((d) => d != null);
934
+ return nodes.length > 0 ? nodes : undefined;
935
+ }
567
936
  /**
568
937
  * Build statement node
569
938
  *
570
939
  * @param data - data for the node
571
940
  * @returns
572
941
  */
573
- statement(data) {
574
- const { text, isCorrect, item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample, example } = data;
942
+ buildStatement(data) {
943
+ var _a;
944
+ if (!data)
945
+ return undefined;
575
946
  // NOTE: Node order is important and is defined here
576
- const node = Object.assign({ text, isCorrect: !!isCorrect, itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
577
- instruction }, this.toExampleBoolean(isDefaultExample, example));
947
+ const node = Object.assign({ statement: (_a = data.statement) !== null && _a !== void 0 ? _a : '', isCorrect: !!data.isCorrect, item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(data.__isDefaultExample, data.example, !!data.isCorrect));
578
948
  // Remove Unset Optionals
579
949
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
580
950
  ignoreAllFalse: true,
951
+ // ignoreAllEmptyArrays: true,
952
+ ignoreUndefined: ['example'],
581
953
  });
582
954
  return node;
583
955
  }
@@ -587,19 +959,23 @@ class Builder extends BaseBuilder_1.BaseBuilder {
587
959
  * @param data - data for the node
588
960
  * @returns
589
961
  */
590
- imageSource(data) {
962
+ buildImageSource(data) {
963
+ if (!data)
964
+ return undefined;
591
965
  const { url, mockupId, size, format, trim } = data;
592
966
  // NOTE: Node order is important and is defined here
593
967
  const node = {
594
- url,
595
- mockupId,
596
- size,
597
- format,
598
- trim,
968
+ url: url !== null && url !== void 0 ? url : '',
969
+ mockupId: mockupId !== null && mockupId !== void 0 ? mockupId : '',
970
+ size: (size !== null && size !== void 0 ? size : null),
971
+ format: (format !== null && format !== void 0 ? format : null),
972
+ trim: (BooleanUtils_1.BooleanUtils.isBoolean(trim) ? trim : null),
599
973
  };
600
974
  // Remove Unset Optionals
601
975
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
602
976
  ignoreFalse: ['trim'],
977
+ ignoreEmptyString: ['url', 'mockupId'],
978
+ ignoreAllUndefined: true,
603
979
  });
604
980
  return node;
605
981
  }
@@ -609,16 +985,23 @@ class Builder extends BaseBuilder_1.BaseBuilder {
609
985
  * @param data - data for the node
610
986
  * @returns
611
987
  */
612
- person(data) {
988
+ buildPerson(bitType, data) {
989
+ var _a;
990
+ if (!data)
991
+ return undefined;
613
992
  const { name, title, avatarImage } = data;
993
+ // { name: string; title?: string; avatarImage?: ImageResourceJson }
614
994
  // NOTE: Node order is important and is defined here
615
995
  const node = {
616
- name,
617
- title,
618
- avatarImage,
996
+ name: name !== null && name !== void 0 ? name : '',
997
+ title: (title !== null && title !== void 0 ? title : undefined),
998
+ avatarImage: (_a = ArrayUtils_1.ArrayUtils.asSingle(this.resourceBuilder.resourceFromResourceDataJson(bitType, ResourceTag_1.ResourceTag.image, avatarImage))) === null || _a === void 0 ? void 0 : _a.image,
619
999
  };
620
1000
  // Remove Unset Optionals
621
- ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node);
1001
+ ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
1002
+ ignoreEmptyString: ['name'],
1003
+ ignoreAllUndefined: true,
1004
+ });
622
1005
  return node;
623
1006
  }
624
1007
  /**
@@ -627,15 +1010,20 @@ class Builder extends BaseBuilder_1.BaseBuilder {
627
1010
  * @param data - data for the node
628
1011
  * @returns
629
1012
  */
630
- technicalTerm(data) {
1013
+ buildTechnicalTerm(data) {
1014
+ if (!data)
1015
+ return undefined;
631
1016
  const { technicalTerm, lang } = data;
632
1017
  // NOTE: Node order is important and is defined here
633
1018
  const node = {
634
- technicalTerm,
635
- lang,
1019
+ technicalTerm: technicalTerm !== null && technicalTerm !== void 0 ? technicalTerm : '',
1020
+ lang: lang !== null && lang !== void 0 ? lang : '',
636
1021
  };
637
1022
  // Remove Unset Optionals
638
- ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node);
1023
+ ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
1024
+ ignoreEmptyString: ['technicalTerm'],
1025
+ // ignoreAllUndefined: true,
1026
+ });
639
1027
  return node;
640
1028
  }
641
1029
  /**
@@ -644,19 +1032,24 @@ class Builder extends BaseBuilder_1.BaseBuilder {
644
1032
  * @param data - data for the node
645
1033
  * @returns
646
1034
  */
647
- servings(data) {
1035
+ buildServings(data) {
1036
+ if (!data)
1037
+ return undefined;
648
1038
  const { servings, unit, unitAbbr, decimalPlaces, disableCalculation, hint } = data;
649
1039
  // NOTE: Node order is important and is defined here
650
1040
  const node = {
651
- servings,
652
- unit,
653
- unitAbbr,
654
- decimalPlaces,
655
- disableCalculation,
656
- hint,
1041
+ servings: servings !== null && servings !== void 0 ? servings : 0,
1042
+ unit: unit !== null && unit !== void 0 ? unit : '',
1043
+ unitAbbr: unitAbbr !== null && unitAbbr !== void 0 ? unitAbbr : '',
1044
+ decimalPlaces: decimalPlaces !== null && decimalPlaces !== void 0 ? decimalPlaces : 1,
1045
+ disableCalculation: disableCalculation !== null && disableCalculation !== void 0 ? disableCalculation : false,
1046
+ hint: hint !== null && hint !== void 0 ? hint : '',
657
1047
  };
658
1048
  // Remove Unset Optionals
659
- ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node);
1049
+ ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
1050
+ ignoreEmptyString: ['servings', 'unit'],
1051
+ // ignoreAllUndefined: true,
1052
+ });
660
1053
  return node;
661
1054
  }
662
1055
  /**
@@ -665,15 +1058,20 @@ class Builder extends BaseBuilder_1.BaseBuilder {
665
1058
  * @param data - data for the node
666
1059
  * @returns
667
1060
  */
668
- ratingLevelStartEnd(data) {
1061
+ buildRatingLevelStartEnd(data) {
1062
+ if (!data)
1063
+ return undefined;
669
1064
  const { level, label } = data;
670
1065
  // NOTE: Node order is important and is defined here
671
1066
  const node = {
672
- level,
673
- label,
1067
+ level: level !== null && level !== void 0 ? level : 0,
1068
+ label: this.handleJsonText(label),
674
1069
  };
675
1070
  // Remove Unset Optionals
676
- ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node);
1071
+ ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
1072
+ // ignoreEmptyArrays: ['servings', 'unit'],
1073
+ // ignoreAllUndefined: true,
1074
+ });
677
1075
  return node;
678
1076
  }
679
1077
  /**
@@ -682,15 +1080,22 @@ class Builder extends BaseBuilder_1.BaseBuilder {
682
1080
  * @param data - data for the node
683
1081
  * @returns
684
1082
  */
685
- captionDefinition(data) {
686
- const { term, description } = data;
1083
+ buildCaptionDefinition(data) {
1084
+ var _a, _b;
1085
+ if (!data)
1086
+ return undefined;
687
1087
  // NOTE: Node order is important and is defined here
688
1088
  const node = {
689
- term,
690
- description,
1089
+ // term: this.convertJsonTextToAstText(data.term),
1090
+ // description: this.convertJsonTextToAstText(data.description),
1091
+ term: (_a = data.term) !== null && _a !== void 0 ? _a : '',
1092
+ definition: (_b = data.definition) !== null && _b !== void 0 ? _b : '',
691
1093
  };
692
1094
  // Remove Unset Optionals
693
- ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node);
1095
+ ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
1096
+ ignoreEmptyString: ['term', 'description'],
1097
+ // ignoreAllUndefined: true,
1098
+ });
694
1099
  return node;
695
1100
  }
696
1101
  /**
@@ -699,32 +1104,39 @@ class Builder extends BaseBuilder_1.BaseBuilder {
699
1104
  * @param data - data for the node
700
1105
  * @returns
701
1106
  */
702
- captionDefinitionList(data) {
703
- const { columns, definitions } = data;
1107
+ buildCaptionDefinitionList(data) {
1108
+ var _a, _b;
1109
+ if (!data)
1110
+ return undefined;
704
1111
  // NOTE: Node order is important and is defined here
705
1112
  const node = {
706
- columns,
707
- definitions,
1113
+ columns: (_a = data.columns) !== null && _a !== void 0 ? _a : [],
1114
+ definitions: ((_b = data.definitions) !== null && _b !== void 0 ? _b : [])
1115
+ .map((d) => {
1116
+ return this.buildCaptionDefinition({
1117
+ term: d.term,
1118
+ definition: d.definition,
1119
+ });
1120
+ })
1121
+ .filter((d) => d != null),
708
1122
  };
709
1123
  // Remove Unset Optionals
710
- ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node);
1124
+ ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
1125
+ ignoreAllEmptyArrays: true,
1126
+ });
711
1127
  return node;
712
1128
  }
713
- //
714
- // Private
715
- //
716
- itemLead(item, lead, pageNumber, marginNumber) {
717
- let node;
718
- // NOTE: Node order is important and is defined here
719
- if (item || lead || pageNumber || marginNumber) {
720
- node = {
721
- item,
722
- lead,
723
- pageNumber,
724
- marginNumber,
725
- };
726
- }
727
- return node;
1129
+ /**
1130
+ * Build card bit[] node
1131
+ *
1132
+ * @param data - data for the node
1133
+ * @returns
1134
+ */
1135
+ buildCardBits(textFormat, data) {
1136
+ if (!Array.isArray(data))
1137
+ return undefined;
1138
+ const nodes = data.map((d) => this.buildCardBit(textFormat, d)).filter((d) => d != null);
1139
+ return nodes.length > 0 ? nodes : undefined;
728
1140
  }
729
1141
  /**
730
1142
  * Build card bit node
@@ -732,116 +1144,101 @@ class Builder extends BaseBuilder_1.BaseBuilder {
732
1144
  * @param data - data for the node
733
1145
  * @returns
734
1146
  */
735
- cardBit(data) {
736
- const { item, lead, pageNumber, marginNumber, hint, instruction, isDefaultExample, example, extraProperties, body, } = data;
1147
+ buildCardBit(textFormat, data) {
1148
+ var _a;
1149
+ if (!data)
1150
+ return undefined;
737
1151
  // NOTE: Node order is important and is defined here
738
- const node = Object.assign(Object.assign({ itemLead: this.itemLead(item, lead, pageNumber, marginNumber), hint,
739
- instruction }, this.toExample(isDefaultExample, example)), { body,
1152
+ const node = Object.assign(Object.assign({ item: this.handleJsonText(data.item), lead: this.handleJsonText(data.lead), hint: this.handleJsonText(data.hint), instruction: this.handleJsonText(data.instruction) }, this.toExample(data.__isDefaultExample, data.example)), { __isDefaultExample: (_a = data.__isDefaultExample) !== null && _a !== void 0 ? _a : false, body: this.buildBody(textFormat, data.body),
740
1153
  // Must always be last in the AST so key clashes are avoided correctly with other properties
741
- extraProperties: this.parseExtraProperties(extraProperties) });
1154
+ extraProperties: this.parseExtraProperties(data.extraProperties) });
742
1155
  // Remove Unset Optionals
743
1156
  ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node, {
744
1157
  ignoreAllFalse: true,
745
- ignoreEmptyString: ['example'],
1158
+ // ignoreEmptyArrays: ['example'],
1159
+ ignoreUndefined: ['example'],
746
1160
  });
747
1161
  // Validate and correct invalid bits as much as possible
748
1162
  return NodeValidator_1.NodeValidator.validateCardBit(node);
749
1163
  }
750
- cardNode(data) {
751
- let node;
752
- const { questions, elements, flashcards, definitions, statement, statements, choices, responses, quizzes, heading, pairs, matrix, table, botResponses, ingredients, captionDefinitionList, cardBits, } = data;
753
- if (questions ||
754
- elements ||
755
- flashcards ||
756
- definitions ||
757
- statement ||
758
- statements ||
759
- choices ||
760
- responses ||
761
- quizzes ||
762
- heading ||
763
- pairs ||
764
- matrix ||
765
- table ||
766
- botResponses ||
767
- ingredients ||
768
- captionDefinitionList ||
769
- cardBits) {
770
- node = {
771
- questions,
772
- elements,
773
- flashcards,
774
- definitions,
775
- statement,
776
- statements,
777
- choices,
778
- responses,
779
- quizzes,
780
- heading,
781
- pairs,
782
- matrix,
783
- table,
784
- botResponses,
785
- ingredients,
786
- captionDefinitionList,
787
- cardBits,
788
- };
789
- // Remove Unset Optionals
790
- ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node);
791
- }
792
- return node;
1164
+ //
1165
+ // Private
1166
+ //
1167
+ buildCardNode(bitType, textFormat, data) {
1168
+ const node = {
1169
+ questions: this.buildQuestions(data.questions),
1170
+ elements: data.elements,
1171
+ flashcards: this.buildFlashcards(data.flashcards),
1172
+ definitions: this.buildDefinitionList(data.definitions),
1173
+ statement: this.buildStatement(data.statement),
1174
+ statements: this.buildStatements(data.statements),
1175
+ choices: this.buildChoices(data.choices),
1176
+ responses: this.buildResponses(data.responses),
1177
+ quizzes: this.buildQuizzes(data.quizzes),
1178
+ heading: this.buildHeading(data.heading),
1179
+ pairs: this.buildPairs(bitType, data.pairs),
1180
+ matrix: this.buildMatricies(data.matrix),
1181
+ table: this.buildTable(data.table),
1182
+ botResponses: this.buildBotResponses(data.botResponses),
1183
+ ingredients: this.buildIngredients(data.ingredients),
1184
+ captionDefinitionList: this.buildCaptionDefinitionList(data.captionDefinitionList),
1185
+ cardBits: this.buildCardBits(textFormat, data.cardBits),
1186
+ };
1187
+ // Remove Unset Optionals
1188
+ ObjectUtils_1.ObjectUtils.removeUnwantedProperties(node);
1189
+ return Object.keys(node).length > 0 ? node : undefined;
793
1190
  }
794
1191
  /**
795
1192
  * Set examples down the tree
796
1193
  *
797
1194
  * @param body
798
1195
  * @param cardNode
799
- * @param isDefaultExample
1196
+ * @param __isDefaultExample
800
1197
  * @param example
801
1198
  * @returns true if any of the answers has an example, otherwise undefined
802
1199
  */
803
- pushExampleDownTree(body, cardNode, isDefaultExample, example) {
804
- if (isDefaultExample || example) {
1200
+ pushExampleDownTree(body, cardNode, __isDefaultExample, example) {
1201
+ if (__isDefaultExample || example != null) {
805
1202
  if (cardNode) {
806
- this.pushExampleDownTreeString(isDefaultExample, example, cardNode.pairs);
807
- this.pushExampleDownTreeBoolean(isDefaultExample, example, false, cardNode.flashcards);
808
- this.pushExampleDownTreeBoolean(isDefaultExample, example, false, cardNode.definitions);
809
- this.pushExampleDownTreeBoolean(isDefaultExample, example, true, cardNode.choices);
810
- this.pushExampleDownTreeBoolean(isDefaultExample, example, false, cardNode.responses, cardNode.statements, cardNode.statement);
1203
+ this.pushExampleDownTreeString(__isDefaultExample, example, cardNode.pairs);
1204
+ this.pushExampleDownTreeBoolean(__isDefaultExample, example, false, cardNode.flashcards);
1205
+ this.pushExampleDownTreeBoolean(__isDefaultExample, example, false, cardNode.definitions);
1206
+ this.pushExampleDownTreeBoolean(__isDefaultExample, example, true, cardNode.choices);
1207
+ this.pushExampleDownTreeBoolean(__isDefaultExample, example, false, cardNode.responses, cardNode.statements, cardNode.statement);
811
1208
  if (cardNode.quizzes) {
812
1209
  for (const quiz of cardNode.quizzes) {
813
- this.pushExampleDownTreeBoolean(isDefaultExample, example, true, quiz.choices);
814
- this.pushExampleDownTreeBoolean(isDefaultExample, example, false, quiz.responses);
1210
+ this.pushExampleDownTreeBoolean(__isDefaultExample, example, true, quiz.choices);
1211
+ this.pushExampleDownTreeBoolean(__isDefaultExample, example, false, quiz.responses);
815
1212
  }
816
1213
  }
817
1214
  if (cardNode.matrix) {
818
1215
  for (const m of cardNode.matrix) {
819
- this.pushExampleDownTreeString(isDefaultExample, example, m.cells);
1216
+ this.pushExampleDownTreeString(__isDefaultExample, example, m.cells);
820
1217
  }
821
1218
  }
822
1219
  }
823
1220
  if (body) {
824
- this.pushExampleDownTreeBodyBits(isDefaultExample, example, body);
1221
+ this.pushExampleDownTreeBodyBits(__isDefaultExample, example, body);
825
1222
  }
826
1223
  }
827
1224
  }
828
1225
  /**
829
1226
  * Set examples for boolean nodes
830
1227
  *
831
- * @param isDefaultExample
1228
+ * @param __isDefaultExample
832
1229
  * @param example
833
1230
  * @param onlyCorrect
834
1231
  * @param nodes
835
1232
  * @returns true if any of the answers has an example, otherwise undefined
836
1233
  */
837
- pushExampleDownTreeBoolean(isDefaultExample, example, onlyCorrect, ...nodes) {
838
- if (!isDefaultExample && !example)
1234
+ pushExampleDownTreeBoolean(__isDefaultExample, example, onlyCorrect, ...nodes) {
1235
+ if (!__isDefaultExample && example == null)
839
1236
  return;
840
1237
  if (Array.isArray(nodes)) {
841
1238
  for (const ds of nodes) {
842
1239
  if (ds) {
843
1240
  const exampleNodes = Array.isArray(ds) ? ds : [ds];
844
- BitUtils_1.BitUtils.fillBooleanExample(exampleNodes, isDefaultExample, example, onlyCorrect);
1241
+ BitUtils_1.BitUtils.fillBooleanExample(exampleNodes, __isDefaultExample, example, onlyCorrect);
845
1242
  }
846
1243
  }
847
1244
  }
@@ -849,49 +1246,48 @@ class Builder extends BaseBuilder_1.BaseBuilder {
849
1246
  /**
850
1247
  * Set examples for string nodes
851
1248
  *
852
- * @param isDefaultExample
1249
+ * @param __isDefaultExample
853
1250
  * @param example
854
1251
  * @param nodes
855
1252
  * @returns true if any of the answers has an example, otherwise undefined
856
1253
  */
857
- pushExampleDownTreeString(isDefaultExample, example, ...nodes) {
858
- if (!isDefaultExample && !example)
1254
+ pushExampleDownTreeString(__isDefaultExample, example, ...nodes) {
1255
+ if (!__isDefaultExample && !example)
859
1256
  return;
860
1257
  if (Array.isArray(nodes)) {
861
1258
  for (const ds of nodes) {
862
1259
  if (ds) {
863
1260
  const exampleNodes = Array.isArray(ds) ? ds : [ds];
864
- BitUtils_1.BitUtils.fillStringExample(exampleNodes, isDefaultExample, example, false);
1261
+ BitUtils_1.BitUtils.fillStringExample(exampleNodes, __isDefaultExample, example, false);
865
1262
  }
866
1263
  }
867
1264
  }
868
1265
  }
869
- pushExampleDownTreeBodyBits(isDefaultExample, example, body) {
870
- if (!isDefaultExample && !example)
871
- return;
872
- if (!body || !body.bodyParts || body.bodyParts.length === 0)
1266
+ pushExampleDownTreeBodyBits(__isDefaultExample, example, body) {
1267
+ if (!__isDefaultExample && !example)
873
1268
  return;
874
- for (const part of body.bodyParts) {
1269
+ const bodyBitsJson = this.textParser.extractBodyBits(body === null || body === void 0 ? void 0 : body.body);
1270
+ for (const part of bodyBitsJson) {
875
1271
  if (part) {
876
1272
  switch (part.type) {
877
1273
  case BodyBitType_1.BodyBitType.gap: {
878
1274
  const gap = part;
879
- BitUtils_1.BitUtils.fillStringExample([gap.data], isDefaultExample, example, false);
1275
+ BitUtils_1.BitUtils.fillStringExample([gap], __isDefaultExample, example, false);
880
1276
  break;
881
1277
  }
882
1278
  case BodyBitType_1.BodyBitType.mark: {
883
1279
  const mark = part;
884
- BitUtils_1.BitUtils.fillBooleanExample([mark.data], isDefaultExample, example, false);
1280
+ BitUtils_1.BitUtils.fillBooleanExample([mark], __isDefaultExample, example, false);
885
1281
  break;
886
1282
  }
887
1283
  case BodyBitType_1.BodyBitType.select: {
888
1284
  const select = part;
889
- BitUtils_1.BitUtils.fillBooleanExample(select.data.options, isDefaultExample, example, true);
1285
+ BitUtils_1.BitUtils.fillBooleanExample(select.options, __isDefaultExample, example, true);
890
1286
  break;
891
1287
  }
892
1288
  case BodyBitType_1.BodyBitType.highlight: {
893
1289
  const highlight = part;
894
- BitUtils_1.BitUtils.fillBooleanExample(highlight.data.texts, isDefaultExample, example, true);
1290
+ BitUtils_1.BitUtils.fillBooleanExample(highlight.texts, __isDefaultExample, example, true);
895
1291
  break;
896
1292
  }
897
1293
  }
@@ -903,7 +1299,7 @@ class Builder extends BaseBuilder_1.BaseBuilder {
903
1299
  *
904
1300
  * This function is not type safe and should be used with care
905
1301
  *
906
- * @param body set if the value should be passed down the body to the body bits
1302
+ * @param body/body[] set if the value should be passed down the body to the body bits / card body bits
907
1303
  * @param bodyBitTypes body bit types to push the value down to
908
1304
  * @param cardNode set if the value should be passed down the card node
909
1305
  * @param path path for the value
@@ -925,14 +1321,22 @@ class Builder extends BaseBuilder_1.BaseBuilder {
925
1321
  }
926
1322
  }
927
1323
  // Add value to body bit types if required
928
- if (bodyBitTypes && body && body.bodyParts && body.bodyParts.length > 0) {
929
- for (const part of body.bodyParts) {
930
- if (part) {
931
- if (bodyBitTypes.indexOf(part.type) !== -1) {
932
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
933
- const data = part.data;
934
- if (data[path] == null) {
935
- data[path] = value;
1324
+ if (body) {
1325
+ const bodyArray = (Array.isArray(body) ? body : [body]);
1326
+ for (const b of bodyArray) {
1327
+ if (b && b.body && bodyBitTypes) {
1328
+ const bodyBitsJson = this.textParser.extractBodyBits(b.body);
1329
+ if (bodyBitTypes && bodyBitsJson && bodyBitsJson.length > 0) {
1330
+ for (const part of bodyBitsJson) {
1331
+ if (part) {
1332
+ if (bodyBitTypes.indexOf(part.type) !== -1) {
1333
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1334
+ const data = part;
1335
+ if (data[path] == null) {
1336
+ data[path] = value;
1337
+ }
1338
+ }
1339
+ }
936
1340
  }
937
1341
  }
938
1342
  }
@@ -960,12 +1364,12 @@ class Builder extends BaseBuilder_1.BaseBuilder {
960
1364
  * @param bit
961
1365
  */
962
1366
  setIsExampleFlags(bit) {
1367
+ // bit.isExample = false;
963
1368
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
964
- bit.isExample = false;
965
1369
  const checkIsExample = (example) => {
966
1370
  if (!example)
967
1371
  return false;
968
- if (example.isDefaultExample || example.example != undefined) {
1372
+ if ( /*example.__isDefaultExample ||*/example.isExample || example.example != undefined) {
969
1373
  example.isExample = true;
970
1374
  bit.isExample = true;
971
1375
  }
@@ -981,32 +1385,31 @@ class Builder extends BaseBuilder_1.BaseBuilder {
981
1385
  };
982
1386
  const { body, cardNode } = bit;
983
1387
  // Body bit level
984
- if (body && body.bodyParts) {
985
- for (const bodyPart of body.bodyParts) {
986
- switch (bodyPart.type) {
987
- case BodyBitType_1.BodyBitType.gap:
988
- case BodyBitType_1.BodyBitType.mark: {
989
- checkIsExample(bodyPart.data);
990
- break;
991
- }
992
- case BodyBitType_1.BodyBitType.select: {
993
- const select = bodyPart;
994
- let hasExample = false;
995
- for (const option of select.data.options) {
996
- hasExample = checkIsExample(option) ? true : hasExample;
997
- }
998
- select.data.isExample = hasExample;
999
- break;
1388
+ const bodyBitsJson = this.textParser.extractBodyBits(body === null || body === void 0 ? void 0 : body.body);
1389
+ for (const bodyPart of bodyBitsJson) {
1390
+ switch (bodyPart.type) {
1391
+ case BodyBitType_1.BodyBitType.gap:
1392
+ case BodyBitType_1.BodyBitType.mark: {
1393
+ checkIsExample(bodyPart);
1394
+ break;
1395
+ }
1396
+ case BodyBitType_1.BodyBitType.select: {
1397
+ const select = bodyPart;
1398
+ let hasExample = false;
1399
+ for (const option of select.options) {
1400
+ hasExample = checkIsExample(option) ? true : hasExample;
1000
1401
  }
1001
- case BodyBitType_1.BodyBitType.highlight: {
1002
- const highlight = bodyPart;
1003
- let hasExample = false;
1004
- for (const text of highlight.data.texts) {
1005
- hasExample = checkIsExample(text) ? true : hasExample;
1006
- }
1007
- highlight.data.isExample = hasExample;
1008
- break;
1402
+ select.isExample = hasExample;
1403
+ break;
1404
+ }
1405
+ case BodyBitType_1.BodyBitType.highlight: {
1406
+ const highlight = bodyPart;
1407
+ let hasExample = false;
1408
+ for (const text of highlight.texts) {
1409
+ hasExample = checkIsExample(text) ? true : hasExample;
1009
1410
  }
1411
+ highlight.isExample = hasExample;
1412
+ break;
1010
1413
  }
1011
1414
  }
1012
1415
  }