@agentshouse/mdmodel 0.1.0-alpha.9 → 0.1.0-c5a71fe539a49

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 (379) hide show
  1. package/API.md +303 -0
  2. package/README.md +34 -189
  3. package/dist/blocks.d.ts +11 -0
  4. package/dist/blocks.d.ts.map +1 -0
  5. package/dist/blocks.js +62 -0
  6. package/dist/condition.d.ts +137 -0
  7. package/dist/condition.d.ts.map +1 -0
  8. package/dist/condition.js +394 -0
  9. package/dist/definition.d.ts +46 -27
  10. package/dist/definition.d.ts.map +1 -1
  11. package/dist/definition.js +485 -152
  12. package/dist/divide.d.ts +3 -0
  13. package/dist/divide.d.ts.map +1 -0
  14. package/dist/divide.js +310 -0
  15. package/dist/document.d.ts +12 -1
  16. package/dist/document.d.ts.map +1 -1
  17. package/dist/document.js +176 -124
  18. package/dist/fields.d.ts +4 -0
  19. package/dist/fields.d.ts.map +1 -0
  20. package/dist/fields.js +3 -0
  21. package/dist/index.d.ts +11 -3
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +8 -4
  24. package/dist/links.d.ts +1 -0
  25. package/dist/links.d.ts.map +1 -1
  26. package/dist/links.js +618 -224
  27. package/dist/paths.d.ts +5 -3
  28. package/dist/paths.d.ts.map +1 -1
  29. package/dist/paths.js +47 -37
  30. package/dist/profile.js +1 -3
  31. package/dist/project.d.ts +19 -1
  32. package/dist/project.d.ts.map +1 -1
  33. package/dist/project.js +77 -94
  34. package/dist/references.d.ts +4 -0
  35. package/dist/references.d.ts.map +1 -0
  36. package/dist/references.js +25 -0
  37. package/dist/refuse.d.ts.map +1 -1
  38. package/dist/refuse.js +2 -10
  39. package/dist/schema.d.ts +7 -5
  40. package/dist/schema.d.ts.map +1 -1
  41. package/dist/schema.js +156 -41
  42. package/dist/sections.d.ts +2 -1
  43. package/dist/sections.d.ts.map +1 -1
  44. package/dist/sections.js +44 -66
  45. package/dist/types.d.ts +40 -2
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/types.js +1 -3
  48. package/dist/validate.d.ts +3 -2
  49. package/dist/validate.d.ts.map +1 -1
  50. package/dist/validate.js +129 -142
  51. package/dist/version.d.ts +1 -1
  52. package/dist/version.d.ts.map +1 -1
  53. package/dist/version.js +1 -3
  54. package/dist/yaml.d.ts +2 -0
  55. package/dist/yaml.d.ts.map +1 -1
  56. package/dist/yaml.js +262 -192
  57. package/fixtures/README.md +91 -56
  58. package/fixtures/cases/absent-optional-field/library/companies/acme.md +4 -0
  59. package/fixtures/cases/absent-optional-field/library/deals/lead.md +6 -0
  60. package/fixtures/cases/absent-optional-field/schema.yaml +56 -0
  61. package/fixtures/cases/attachment-reference-any-file/context.json +1 -0
  62. package/fixtures/cases/attachment-reference-any-file/expected.json +1 -0
  63. package/fixtures/cases/attachment-reference-any-file/library/companies/acme.md +4 -0
  64. package/fixtures/cases/attachment-reference-any-file/library/deals/renewal.md +15 -0
  65. package/fixtures/cases/attachment-reference-any-file/library/places/depot.md +4 -0
  66. package/fixtures/cases/attachment-reference-any-file/library/products/seats.md +4 -0
  67. package/fixtures/cases/attachment-reference-any-file/library/products/support.md +4 -0
  68. package/fixtures/cases/attachment-reference-any-file/schema.yaml +32 -0
  69. package/fixtures/cases/attachment-reference-dangles/context.json +1 -0
  70. package/fixtures/cases/attachment-reference-dangles/expected.json +1 -0
  71. package/fixtures/cases/attachment-reference-dangles/library/companies/acme.md +4 -0
  72. package/fixtures/cases/attachment-reference-dangles/library/deals/renewal.md +15 -0
  73. package/fixtures/cases/attachment-reference-dangles/library/places/depot.md +4 -0
  74. package/fixtures/cases/attachment-reference-dangles/library/products/seats.md +4 -0
  75. package/fixtures/cases/attachment-reference-dangles/library/products/support.md +4 -0
  76. package/fixtures/cases/attachment-reference-dangles/schema.yaml +32 -0
  77. package/fixtures/cases/attachment-reference-outside/context.json +1 -0
  78. package/fixtures/cases/attachment-reference-outside/expected.json +6 -0
  79. package/fixtures/cases/attachment-reference-outside/library/companies/acme.md +4 -0
  80. package/fixtures/cases/attachment-reference-outside/library/deals/renewal.md +15 -0
  81. package/fixtures/cases/attachment-reference-outside/library/places/depot.md +4 -0
  82. package/fixtures/cases/attachment-reference-outside/library/products/seats.md +4 -0
  83. package/fixtures/cases/attachment-reference-outside/library/products/support.md +4 -0
  84. package/fixtures/cases/attachment-reference-outside/schema.yaml +32 -0
  85. package/fixtures/cases/binary-any-reference/expected.json +1 -2
  86. package/fixtures/cases/binary-any-reference/schema.yaml +4 -0
  87. package/fixtures/cases/binary-document-collision/expected.json +1 -2
  88. package/fixtures/cases/binary-document-collision/schema.yaml +1 -0
  89. package/fixtures/cases/binary-link-outside-collection/expected.json +1 -2
  90. package/fixtures/cases/binary-link-outside-collection/schema.yaml +1 -0
  91. package/fixtures/cases/binary-prototype-reference/expected.json +1 -2
  92. package/fixtures/cases/binary-prototype-reference/schema.yaml +4 -0
  93. package/fixtures/cases/binary-typed-reference/expected.json +1 -2
  94. package/fixtures/cases/binary-typed-reference/schema.yaml +5 -0
  95. package/fixtures/cases/boolean-field/context.json +1 -0
  96. package/fixtures/cases/boolean-field/expected.json +6 -0
  97. package/fixtures/cases/boolean-field/library/companies/acme.md +4 -0
  98. package/fixtures/cases/boolean-field/library/deals/renewal.md +31 -0
  99. package/fixtures/cases/boolean-field/schema.yaml +56 -0
  100. package/fixtures/cases/bracketed-link-definition/schema.yaml +6 -0
  101. package/fixtures/cases/closed-nested-object/context.json +1 -0
  102. package/fixtures/cases/closed-nested-object/expected.json +6 -0
  103. package/fixtures/cases/closed-nested-object/library/companies/acme.md +4 -0
  104. package/fixtures/cases/closed-nested-object/library/deals/renewal.md +32 -0
  105. package/fixtures/cases/closed-nested-object/schema.yaml +56 -0
  106. package/fixtures/cases/composed-root-reference/context.json +1 -0
  107. package/fixtures/cases/composed-root-reference/expected.json +6 -0
  108. package/fixtures/cases/composed-root-reference/library/a.md +5 -0
  109. package/fixtures/cases/composed-root-reference/schema.yaml +13 -0
  110. package/fixtures/cases/date-time-format/context.json +1 -0
  111. package/fixtures/cases/date-time-format/expected.json +6 -0
  112. package/fixtures/cases/date-time-format/library/companies/acme.md +4 -0
  113. package/fixtures/cases/date-time-format/library/deals/renewal.md +31 -0
  114. package/fixtures/cases/date-time-format/schema.yaml +56 -0
  115. package/fixtures/cases/declared-binary-links/schema.yaml +1 -0
  116. package/fixtures/cases/default-unfilled/context.json +1 -0
  117. package/fixtures/cases/default-unfilled/expected.json +6 -0
  118. package/fixtures/cases/default-unfilled/library/companies/acme.md +4 -0
  119. package/fixtures/cases/default-unfilled/library/deals/renewal.md +29 -0
  120. package/fixtures/cases/default-unfilled/schema.yaml +56 -0
  121. package/fixtures/cases/defs-pattern/context.json +1 -0
  122. package/fixtures/cases/defs-pattern/expected.json +6 -0
  123. package/fixtures/cases/defs-pattern/library/companies/acme.md +4 -0
  124. package/fixtures/cases/defs-pattern/library/deals/renewal.md +31 -0
  125. package/fixtures/cases/defs-pattern/schema.yaml +56 -0
  126. package/fixtures/cases/dependent-rule/context.json +1 -0
  127. package/fixtures/cases/dependent-rule/expected.json +6 -0
  128. package/fixtures/cases/dependent-rule/library/companies/acme.md +4 -0
  129. package/fixtures/cases/dependent-rule/library/deals/renewal.md +30 -0
  130. package/fixtures/cases/dependent-rule/schema.yaml +56 -0
  131. package/fixtures/cases/duplicate-link-definition/schema.yaml +6 -0
  132. package/fixtures/cases/email-format/context.json +1 -0
  133. package/fixtures/cases/email-format/expected.json +6 -0
  134. package/fixtures/cases/email-format/library/companies/acme.md +4 -0
  135. package/fixtures/cases/email-format/library/deals/renewal.md +31 -0
  136. package/fixtures/cases/email-format/schema.yaml +56 -0
  137. package/fixtures/cases/fenced-link-definition/schema.yaml +6 -0
  138. package/fixtures/cases/field-enum/expected.json +2 -3
  139. package/fixtures/cases/field-enum/schema.yaml +7 -0
  140. package/fixtures/cases/frontmatter-schema/context.json +1 -0
  141. package/fixtures/cases/frontmatter-schema/expected.json +5 -0
  142. package/fixtures/cases/frontmatter-schema/schema.yaml +5 -0
  143. package/fixtures/cases/integer-field/context.json +1 -0
  144. package/fixtures/cases/integer-field/expected.json +6 -0
  145. package/fixtures/cases/integer-field/library/companies/acme.md +4 -0
  146. package/fixtures/cases/integer-field/library/deals/renewal.md +31 -0
  147. package/fixtures/cases/integer-field/schema.yaml +56 -0
  148. package/fixtures/cases/interrupted-link-definition/schema.yaml +1 -0
  149. package/fixtures/cases/json-schema-constructs/context.json +1 -0
  150. package/fixtures/cases/json-schema-constructs/expected.json +1 -0
  151. package/fixtures/cases/json-schema-constructs/library/companies/acme.md +4 -0
  152. package/fixtures/cases/json-schema-constructs/library/deals/renewal.md +31 -0
  153. package/fixtures/cases/json-schema-constructs/schema.yaml +56 -0
  154. package/fixtures/cases/list-of-objects-closed/context.json +1 -0
  155. package/fixtures/cases/list-of-objects-closed/expected.json +6 -0
  156. package/fixtures/cases/list-of-objects-closed/library/companies/acme.md +4 -0
  157. package/fixtures/cases/list-of-objects-closed/library/deals/renewal.md +32 -0
  158. package/fixtures/cases/list-of-objects-closed/schema.yaml +56 -0
  159. package/fixtures/cases/list-of-objects-item/context.json +1 -0
  160. package/fixtures/cases/list-of-objects-item/expected.json +6 -0
  161. package/fixtures/cases/list-of-objects-item/library/companies/acme.md +4 -0
  162. package/fixtures/cases/list-of-objects-item/library/deals/renewal.md +31 -0
  163. package/fixtures/cases/list-of-objects-item/schema.yaml +56 -0
  164. package/fixtures/cases/list-of-objects-reference/context.json +1 -0
  165. package/fixtures/cases/list-of-objects-reference/expected.json +6 -0
  166. package/fixtures/cases/list-of-objects-reference/library/companies/acme.md +4 -0
  167. package/fixtures/cases/list-of-objects-reference/library/deals/renewal.md +14 -0
  168. package/fixtures/cases/list-of-objects-reference/library/places/depot.md +4 -0
  169. package/fixtures/cases/list-of-objects-reference/library/products/seats.md +4 -0
  170. package/fixtures/cases/list-of-objects-reference/library/products/support.md +4 -0
  171. package/fixtures/cases/list-of-objects-reference/schema.yaml +32 -0
  172. package/fixtures/cases/list-size/context.json +1 -0
  173. package/fixtures/cases/list-size/expected.json +6 -0
  174. package/fixtures/cases/list-size/library/companies/acme.md +4 -0
  175. package/fixtures/cases/list-size/library/deals/renewal.md +31 -0
  176. package/fixtures/cases/list-size/schema.yaml +56 -0
  177. package/fixtures/cases/long-fence-link-definition/schema.yaml +1 -0
  178. package/fixtures/cases/malformed-definition/expected.json +2 -4
  179. package/fixtures/cases/malformed-definition/schema.yaml +3 -0
  180. package/fixtures/cases/member-document/context.json +1 -0
  181. package/fixtures/cases/member-document/expected.json +1 -0
  182. package/fixtures/cases/member-document/library/people/ana.md +5 -0
  183. package/fixtures/cases/member-document/schema.yaml +5 -0
  184. package/fixtures/cases/missing-binary-image/expected.json +1 -2
  185. package/fixtures/cases/missing-binary-image/schema.yaml +1 -0
  186. package/fixtures/cases/missing-binary-link/expected.json +1 -2
  187. package/fixtures/cases/missing-binary-link/schema.yaml +1 -0
  188. package/fixtures/cases/missing-required-field/expected.json +2 -3
  189. package/fixtures/cases/missing-required-field/schema.yaml +7 -0
  190. package/fixtures/cases/missing-section-item-kind/expected.json +2 -4
  191. package/fixtures/cases/missing-section-item-kind/schema.yaml +6 -0
  192. package/fixtures/cases/misspelled-key/context.json +1 -0
  193. package/fixtures/cases/misspelled-key/expected.json +6 -0
  194. package/fixtures/cases/misspelled-key/library/companies/acme.md +4 -0
  195. package/fixtures/cases/misspelled-key/library/deals/renewal.md +32 -0
  196. package/fixtures/cases/misspelled-key/schema.yaml +56 -0
  197. package/fixtures/cases/nested-defs/context.json +1 -0
  198. package/fixtures/cases/nested-defs/expected.json +6 -0
  199. package/fixtures/cases/nested-defs/library/deal.md +6 -0
  200. package/fixtures/cases/nested-defs/schema.yaml +11 -0
  201. package/fixtures/cases/nested-object-reference/context.json +1 -0
  202. package/fixtures/cases/nested-object-reference/expected.json +6 -0
  203. package/fixtures/cases/nested-object-reference/library/companies/acme.md +4 -0
  204. package/fixtures/cases/nested-object-reference/library/deals/renewal.md +14 -0
  205. package/fixtures/cases/nested-object-reference/library/places/depot.md +4 -0
  206. package/fixtures/cases/nested-object-reference/library/products/seats.md +4 -0
  207. package/fixtures/cases/nested-object-reference/library/products/support.md +4 -0
  208. package/fixtures/cases/nested-object-reference/schema.yaml +32 -0
  209. package/fixtures/cases/nested-reference/context.json +1 -0
  210. package/fixtures/cases/nested-reference/expected.json +1 -0
  211. package/fixtures/cases/nested-reference/library/companies/acme.md +4 -0
  212. package/fixtures/cases/nested-reference/library/deals/renewal.md +15 -0
  213. package/fixtures/cases/nested-reference/library/places/depot.md +4 -0
  214. package/fixtures/cases/nested-reference/library/products/seats.md +4 -0
  215. package/fixtures/cases/nested-reference/library/products/support.md +4 -0
  216. package/fixtures/cases/nested-reference/schema.yaml +32 -0
  217. package/fixtures/cases/nested-required-field/context.json +1 -0
  218. package/fixtures/cases/nested-required-field/expected.json +6 -0
  219. package/fixtures/cases/nested-required-field/library/companies/acme.md +4 -0
  220. package/fixtures/cases/nested-required-field/library/deals/renewal.md +30 -0
  221. package/fixtures/cases/nested-required-field/schema.yaml +56 -0
  222. package/fixtures/cases/null-refused/context.json +1 -0
  223. package/fixtures/cases/null-refused/expected.json +6 -0
  224. package/fixtures/cases/null-refused/library/companies/acme.md +4 -0
  225. package/fixtures/cases/null-refused/library/deals/renewal.md +31 -0
  226. package/fixtures/cases/null-refused/schema.yaml +56 -0
  227. package/fixtures/cases/numeric-range/context.json +1 -0
  228. package/fixtures/cases/numeric-range/expected.json +6 -0
  229. package/fixtures/cases/numeric-range/library/companies/acme.md +4 -0
  230. package/fixtures/cases/numeric-range/library/deals/renewal.md +31 -0
  231. package/fixtures/cases/numeric-range/schema.yaml +56 -0
  232. package/fixtures/cases/one-of-variant/context.json +1 -0
  233. package/fixtures/cases/one-of-variant/expected.json +6 -0
  234. package/fixtures/cases/one-of-variant/library/companies/acme.md +4 -0
  235. package/fixtures/cases/one-of-variant/library/deals/renewal.md +31 -0
  236. package/fixtures/cases/one-of-variant/schema.yaml +56 -0
  237. package/fixtures/cases/open-map-value/context.json +1 -0
  238. package/fixtures/cases/open-map-value/expected.json +6 -0
  239. package/fixtures/cases/open-map-value/library/companies/acme.md +4 -0
  240. package/fixtures/cases/open-map-value/library/deals/renewal.md +31 -0
  241. package/fixtures/cases/open-map-value/schema.yaml +56 -0
  242. package/fixtures/cases/other-room-reference/context.json +1 -0
  243. package/fixtures/cases/other-room-reference/expected.json +6 -0
  244. package/fixtures/cases/other-room-reference/library/companies/acme.md +4 -0
  245. package/fixtures/cases/other-room-reference/library/deals/renewal.md +14 -0
  246. package/fixtures/cases/other-room-reference/library/places/depot.md +4 -0
  247. package/fixtures/cases/other-room-reference/library/products/seats.md +4 -0
  248. package/fixtures/cases/other-room-reference/library/products/support.md +4 -0
  249. package/fixtures/cases/other-room-reference/schema.yaml +32 -0
  250. package/fixtures/cases/paragraph-link-definition/schema.yaml +1 -0
  251. package/fixtures/cases/prototype-field/expected.json +2 -3
  252. package/fixtures/cases/prototype-field/schema.yaml +6 -0
  253. package/fixtures/cases/quoted-link-definition/expected.json +1 -2
  254. package/fixtures/cases/quoted-link-definition/schema.yaml +1 -0
  255. package/fixtures/cases/referenced-missing-file/expected.json +0 -1
  256. package/fixtures/cases/referenced-missing-file/schema.yaml +11 -0
  257. package/fixtures/cases/remote-ref/context.json +1 -0
  258. package/fixtures/cases/remote-ref/expected.json +5 -0
  259. package/fixtures/cases/remote-ref/schema.yaml +3 -0
  260. package/fixtures/cases/second-member-document/context.json +1 -0
  261. package/fixtures/cases/second-member-document/expected.json +5 -0
  262. package/fixtures/cases/second-member-document/schema.yaml +4 -0
  263. package/fixtures/cases/section-item-enum/context.json +1 -0
  264. package/fixtures/cases/section-item-enum/expected.json +6 -0
  265. package/fixtures/cases/section-item-enum/library/task.md +8 -0
  266. package/fixtures/cases/section-item-enum/schema.yaml +3 -0
  267. package/fixtures/cases/section-item-kind/context.json +1 -0
  268. package/fixtures/cases/section-item-kind/expected.json +6 -0
  269. package/fixtures/cases/section-item-kind/library/task.md +8 -0
  270. package/fixtures/cases/section-item-kind/schema.yaml +3 -0
  271. package/fixtures/cases/section-items/context.json +1 -0
  272. package/fixtures/cases/section-items/expected.json +1 -0
  273. package/fixtures/cases/section-items/library/other.md +3 -0
  274. package/fixtures/cases/section-items/library/page.md +42 -0
  275. package/fixtures/cases/section-items/schema.yaml +10 -0
  276. package/fixtures/cases/section-reference-path/context.json +1 -0
  277. package/fixtures/cases/section-reference-path/expected.json +6 -0
  278. package/fixtures/cases/section-reference-path/library/other.md +3 -0
  279. package/fixtures/cases/section-reference-path/library/page.md +7 -0
  280. package/fixtures/cases/section-reference-path/schema.yaml +3 -0
  281. package/fixtures/cases/section-reference-type/context.json +1 -0
  282. package/fixtures/cases/section-reference-type/expected.json +6 -0
  283. package/fixtures/cases/section-reference-type/library/note.md +1 -0
  284. package/fixtures/cases/section-reference-type/library/page.md +7 -0
  285. package/fixtures/cases/section-reference-type/schema.yaml +3 -0
  286. package/fixtures/cases/shortcut-reference-link/context.json +1 -0
  287. package/fixtures/cases/shortcut-reference-link/expected.json +5 -0
  288. package/fixtures/cases/shortcut-reference-link/library/item.md +10 -0
  289. package/fixtures/cases/shortcut-reference-link/schema.yaml +6 -0
  290. package/fixtures/cases/string-length/context.json +1 -0
  291. package/fixtures/cases/string-length/expected.json +6 -0
  292. package/fixtures/cases/string-length/library/companies/acme.md +4 -0
  293. package/fixtures/cases/string-length/library/deals/renewal.md +31 -0
  294. package/fixtures/cases/string-length/schema.yaml +56 -0
  295. package/fixtures/cases/structured-section/expected.json +1 -2
  296. package/fixtures/cases/structured-section/schema.yaml +7 -0
  297. package/fixtures/cases/submission-keys/context.json +1 -0
  298. package/fixtures/cases/submission-keys/expected.json +1 -0
  299. package/fixtures/cases/submission-keys/library/notes/visitor.md +8 -0
  300. package/fixtures/cases/submission-keys/schema.yaml +4 -0
  301. package/fixtures/cases/text-field-kind/context.json +1 -0
  302. package/fixtures/cases/text-field-kind/expected.json +6 -0
  303. package/fixtures/cases/text-field-kind/library/page.md +4 -0
  304. package/fixtures/cases/text-field-kind/schema.yaml +4 -0
  305. package/fixtures/cases/truncated-link-definition/expected.json +1 -2
  306. package/fixtures/cases/truncated-link-definition/schema.yaml +1 -0
  307. package/fixtures/cases/types-folder-content/context.json +1 -0
  308. package/fixtures/cases/types-folder-content/expected.json +1 -0
  309. package/fixtures/cases/types-folder-content/library/types/task.md +4 -0
  310. package/fixtures/cases/types-folder-content/schema.yaml +4 -0
  311. package/fixtures/cases/unclosed-frontmatter/expected.json +1 -2
  312. package/fixtures/cases/undeclared-field/expected.json +2 -3
  313. package/fixtures/cases/undeclared-field/schema.yaml +6 -0
  314. package/fixtures/cases/unevaluated-items-closed/context.json +1 -0
  315. package/fixtures/cases/unevaluated-items-closed/expected.json +6 -0
  316. package/fixtures/cases/unevaluated-items-closed/library/trip.md +6 -0
  317. package/fixtures/cases/unevaluated-items-closed/schema.yaml +10 -0
  318. package/fixtures/cases/unknown-type/context.json +1 -0
  319. package/fixtures/cases/unknown-type/expected.json +6 -0
  320. package/fixtures/cases/unknown-type/library/item.md +3 -0
  321. package/fixtures/cases/unknown-type/schema.yaml +3 -0
  322. package/fixtures/cases/unlisted-reference-type/context.json +1 -0
  323. package/fixtures/cases/unlisted-reference-type/expected.json +5 -0
  324. package/fixtures/cases/unlisted-reference-type/schema.yaml +3 -0
  325. package/fixtures/cases/unresolved-link/expected.json +1 -2
  326. package/fixtures/cases/unresolved-link/schema.yaml +6 -0
  327. package/fixtures/cases/valid-typed-document/schema.yaml +16 -0
  328. package/fixtures/cases/wide-item-fence-link/schema.yaml +1 -0
  329. package/fixtures/division.json +409 -0
  330. package/fixtures/projection.json +90 -21
  331. package/package.json +3 -12
  332. package/dist/definition.js.map +0 -1
  333. package/dist/document.js.map +0 -1
  334. package/dist/index.js.map +0 -1
  335. package/dist/links.js.map +0 -1
  336. package/dist/paths.js.map +0 -1
  337. package/dist/profile.js.map +0 -1
  338. package/dist/project.js.map +0 -1
  339. package/dist/refuse.js.map +0 -1
  340. package/dist/schema.js.map +0 -1
  341. package/dist/sections.js.map +0 -1
  342. package/dist/types.js.map +0 -1
  343. package/dist/validate.js.map +0 -1
  344. package/dist/version.js.map +0 -1
  345. package/dist/yaml.js.map +0 -1
  346. package/fixtures/cases/binary-any-reference/library/types/note.md +0 -5
  347. package/fixtures/cases/binary-document-collision/library/types/note.md +0 -3
  348. package/fixtures/cases/binary-link-outside-collection/library/types/note.md +0 -3
  349. package/fixtures/cases/binary-prototype-reference/library/types/note.md +0 -5
  350. package/fixtures/cases/binary-typed-reference/library/types/note.md +0 -5
  351. package/fixtures/cases/binary-typed-reference/library/types/person.md +0 -3
  352. package/fixtures/cases/bracketed-link-definition/library/types/task.md +0 -7
  353. package/fixtures/cases/declared-binary-links/library/types/note.md +0 -3
  354. package/fixtures/cases/duplicate-link-definition/library/types/task.md +0 -7
  355. package/fixtures/cases/fenced-link-definition/library/types/task.md +0 -7
  356. package/fixtures/cases/field-enum/library/types/task.md +0 -8
  357. package/fixtures/cases/interrupted-link-definition/library/types/note.md +0 -3
  358. package/fixtures/cases/long-fence-link-definition/library/types/note.md +0 -3
  359. package/fixtures/cases/malformed-definition/library/types/task.md +0 -5
  360. package/fixtures/cases/missing-binary-image/library/types/note.md +0 -3
  361. package/fixtures/cases/missing-binary-link/library/types/note.md +0 -3
  362. package/fixtures/cases/missing-required-field/library/types/task.md +0 -8
  363. package/fixtures/cases/missing-section-item-kind/library/types/task.md +0 -7
  364. package/fixtures/cases/paragraph-link-definition/library/types/note.md +0 -3
  365. package/fixtures/cases/prd-definition/library/types/task.md +0 -16
  366. package/fixtures/cases/prototype-field/library/types/task.md +0 -7
  367. package/fixtures/cases/quoted-link-definition/library/types/note.md +0 -3
  368. package/fixtures/cases/referenced-missing-file/library/types/person.md +0 -5
  369. package/fixtures/cases/referenced-missing-file/library/types/task.md +0 -8
  370. package/fixtures/cases/structured-section/library/types/task.md +0 -8
  371. package/fixtures/cases/truncated-link-definition/library/types/note.md +0 -3
  372. package/fixtures/cases/undeclared-field/library/types/task.md +0 -7
  373. package/fixtures/cases/unresolved-link/library/types/task.md +0 -7
  374. package/fixtures/cases/valid-typed-document/library/types/person.md +0 -5
  375. package/fixtures/cases/valid-typed-document/library/types/task.md +0 -13
  376. package/fixtures/cases/wide-item-fence-link/library/types/note.md +0 -3
  377. package/markdown-syntax-profile.md +0 -9
  378. /package/fixtures/cases/{prd-definition → absent-optional-field}/context.json +0 -0
  379. /package/fixtures/cases/{prd-definition → absent-optional-field}/expected.json +0 -0
@@ -1,171 +1,504 @@
1
- import { typeNameFromPath } from './paths.js';
2
- import { refusal } from './refuse.js';
3
- function refuse(file, rule, location) {
4
- return location === undefined ? refusal(file, rule) : refusal(file, rule, {
5
- location
6
- });
7
- }
8
- function isRecord(value) {
9
- return value !== null && typeof value === 'object' && !Array.isArray(value);
10
- }
11
- function requiredFlag(value) {
12
- if (value === undefined) return false;
13
- if (typeof value === 'boolean') return value;
1
+ import { MEMBER_FIELD, RECEIVED_FIELD, SITE_FIELD } from './fields.js';
2
+ import { equalValue, isRecord, jsValue, parseYamlMapping, YamlError } from './yaml.js';
3
+ export const JSON_TYPES = [
4
+ 'string',
5
+ 'number',
6
+ 'integer',
7
+ 'boolean',
8
+ 'object',
9
+ 'array',
10
+ 'null',
11
+ ];
12
+ export const BUILT_IN_TYPE = 'any';
13
+ export const ATTACHMENT = 'attachment';
14
+ const SCALAR_TYPES = new Set(['string', 'number', 'integer', 'boolean']);
15
+ const DEFS_REFERENCE = '#/$defs/';
16
+ const UNRESOLVED = /[\u0000-\u001f\u007f%[\]\\^{|}]|\s$/u;
17
+ export const ARRAY_INDEX = /^(?:0|[1-9][0-9]*)$/u;
18
+ const HOUSE_KEYS = {
19
+ type: { prose: false },
20
+ [SITE_FIELD]: { prose: false },
21
+ [RECEIVED_FIELD]: { prose: false },
22
+ };
23
+ function refuse(rule, location) {
24
+ return location === undefined ? { rule } : { rule, location };
25
+ }
26
+ export function escapePointer(key) {
27
+ return key.replaceAll('~', '~0').replaceAll('/', '~1');
28
+ }
29
+ function unescapePointer(segment) {
30
+ return segment.replaceAll('~1', '/').replaceAll('~0', '~');
31
+ }
32
+ export function pointerSegments(pointer) {
33
+ return pointer.split('/').slice(1).map(unescapePointer);
34
+ }
35
+ export function refTarget(reference, defs) {
36
+ if (!reference.startsWith(DEFS_REFERENCE) || UNRESOLVED.test(reference))
37
+ return undefined;
38
+ const segments = reference.slice(DEFS_REFERENCE.length).split('/');
39
+ const [name = '', ...rest] = segments.map(unescapePointer);
40
+ if (segments.some((segment) => escapePointer(unescapePointer(segment)) !== segment))
41
+ return undefined;
42
+ if (!Object.hasOwn(defs, name))
43
+ return undefined;
44
+ let node = defs[name];
45
+ for (let index = 0; index < rest.length; index += 1) {
46
+ const keyword = rest[index];
47
+ if (!isRecord(node) || !Object.hasOwn(node, keyword) || !Object.hasOwn(KEYWORDS, keyword))
48
+ return undefined;
49
+ const check = KEYWORDS[keyword];
50
+ const held = node[keyword];
51
+ if (check === SCHEMA) {
52
+ node = held;
53
+ continue;
54
+ }
55
+ const key = rest[index + 1];
56
+ index += 1;
57
+ if (check === SCHEMA_LIST && Array.isArray(held) && key !== undefined && ARRAY_INDEX.test(key))
58
+ node = held[Number(key)];
59
+ else if (check === SCHEMA_MAP &&
60
+ isRecord(held) &&
61
+ key !== undefined &&
62
+ Object.hasOwn(held, key))
63
+ node = held[key];
64
+ else
65
+ return undefined;
66
+ if (node === undefined)
67
+ return undefined;
68
+ }
69
+ return { name, node };
70
+ }
71
+ function compiles(pattern) {
72
+ if (typeof pattern !== 'string')
73
+ return false;
74
+ try {
75
+ new RegExp(pattern, 'u');
76
+ return true;
77
+ }
78
+ catch {
79
+ return false;
80
+ }
81
+ }
82
+ function finite(value) {
83
+ return typeof value === 'number' && Number.isFinite(value);
84
+ }
85
+ function count(value) {
86
+ return Number.isSafeInteger(value) && value >= 0;
87
+ }
88
+ function strings(value) {
89
+ return (Array.isArray(value) &&
90
+ value.every((item) => typeof item === 'string') &&
91
+ new Set(value).size === value.length);
92
+ }
93
+ function schemaFailure(value, at, context) {
94
+ if (typeof value === 'boolean')
95
+ return undefined;
96
+ if (!isRecord(value))
97
+ return refuse('schema', at);
98
+ for (const [key, held] of Object.entries(value)) {
99
+ const where = `${at}/${escapePointer(key)}`;
100
+ if (!Object.hasOwn(KEYWORDS, key))
101
+ return refuse('schema-keyword', where);
102
+ const check = KEYWORDS[key];
103
+ if (check === SCHEMA) {
104
+ const failure = schemaFailure(held, where, context);
105
+ if (failure !== undefined)
106
+ return failure;
107
+ continue;
108
+ }
109
+ if (check === SCHEMA_LIST) {
110
+ if (!Array.isArray(held) || held.length === 0)
111
+ return refuse(key, where);
112
+ for (const [index, item] of held.entries()) {
113
+ const failure = schemaFailure(item, `${where}/${index}`, context);
114
+ if (failure !== undefined)
115
+ return failure;
116
+ }
117
+ continue;
118
+ }
119
+ if (check === SCHEMA_MAP) {
120
+ if (!isRecord(held))
121
+ return refuse(key, where);
122
+ for (const [name, item] of Object.entries(held)) {
123
+ if (key === 'patternProperties' && !compiles(name))
124
+ return refuse(key, `${where}/${escapePointer(name)}`);
125
+ const failure = schemaFailure(item, `${where}/${escapePointer(name)}`, context);
126
+ if (failure !== undefined)
127
+ return failure;
128
+ }
129
+ continue;
130
+ }
131
+ if (!check(held, where, value, context))
132
+ return refuse(key, where);
133
+ }
14
134
  return undefined;
15
135
  }
16
- function stringList(value) {
17
- if (!Array.isArray(value) || value.length === 0) return undefined;
18
- if (!value.every((item)=>typeof item === 'string' && item !== '')) return undefined;
19
- return value;
136
+ const SCHEMA = () => true;
137
+ const SCHEMA_LIST = () => true;
138
+ const SCHEMA_MAP = () => true;
139
+ const ANY = () => true;
140
+ const TEXT = (value) => typeof value === 'string';
141
+ const FLAG = (value) => typeof value === 'boolean';
142
+ const NUMBER = finite;
143
+ const COUNT = count;
144
+ const KEYWORDS = {
145
+ $comment: TEXT,
146
+ $ref: (value, _at, _node, context) => typeof value === 'string' && refTarget(value, context.defs) !== undefined,
147
+ $defs: SCHEMA_MAP,
148
+ allOf: SCHEMA_LIST,
149
+ anyOf: SCHEMA_LIST,
150
+ oneOf: SCHEMA_LIST,
151
+ prefixItems: SCHEMA_LIST,
152
+ not: SCHEMA,
153
+ if: SCHEMA,
154
+ then: SCHEMA,
155
+ else: SCHEMA,
156
+ items: SCHEMA,
157
+ contains: SCHEMA,
158
+ additionalProperties: SCHEMA,
159
+ unevaluatedProperties: SCHEMA,
160
+ unevaluatedItems: SCHEMA,
161
+ propertyNames: SCHEMA,
162
+ contentSchema: SCHEMA,
163
+ properties: SCHEMA_MAP,
164
+ patternProperties: SCHEMA_MAP,
165
+ dependentSchemas: SCHEMA_MAP,
166
+ type: (value) => (typeof value === 'string' && JSON_TYPES.includes(value)) ||
167
+ (Array.isArray(value) &&
168
+ value.length > 0 &&
169
+ strings(value) &&
170
+ value.every((item) => JSON_TYPES.includes(item))),
171
+ enum: (value) => Array.isArray(value) && value.length > 0,
172
+ const: ANY,
173
+ multipleOf: (value) => finite(value) && value > 0,
174
+ maximum: NUMBER,
175
+ exclusiveMaximum: NUMBER,
176
+ minimum: NUMBER,
177
+ exclusiveMinimum: NUMBER,
178
+ maxLength: COUNT,
179
+ minLength: COUNT,
180
+ maxItems: COUNT,
181
+ minItems: COUNT,
182
+ maxContains: COUNT,
183
+ minContains: COUNT,
184
+ maxProperties: COUNT,
185
+ minProperties: COUNT,
186
+ pattern: compiles,
187
+ uniqueItems: FLAG,
188
+ required: strings,
189
+ dependentRequired: (value) => isRecord(value) && Object.values(value).every(strings),
190
+ format: TEXT,
191
+ contentEncoding: TEXT,
192
+ contentMediaType: TEXT,
193
+ title: TEXT,
194
+ description: TEXT,
195
+ default: ANY,
196
+ examples: (value) => Array.isArray(value),
197
+ deprecated: FLAG,
198
+ readOnly: FLAG,
199
+ writeOnly: FLAG,
200
+ reference: (value, _at, node, context) => {
201
+ if (node.type !== 'string')
202
+ return false;
203
+ const named = typeof value === 'string' ? [value] : value;
204
+ return (Array.isArray(named) &&
205
+ named.length > 0 &&
206
+ strings(named) &&
207
+ named.every((name) => name === BUILT_IN_TYPE || name === ATTACHMENT || context.types.has(name)));
208
+ },
209
+ };
210
+ function sharedType(values) {
211
+ if (values.length === 0)
212
+ return undefined;
213
+ if (values.every((value) => typeof value === 'string'))
214
+ return 'string';
215
+ if (values.every((value) => typeof value === 'number'))
216
+ return 'number';
217
+ if (values.every((value) => typeof value === 'boolean'))
218
+ return 'boolean';
219
+ return undefined;
20
220
  }
21
- const SCALAR_KINDS = new Set([
22
- 'text',
23
- 'string',
24
- 'number',
25
- 'date',
26
- 'enum',
27
- 'reference'
28
- ]);
29
- function parseScalar(file, location, spec, required) {
30
- const kind = spec.kind;
31
- if (kind === 'text') return {
32
- kind: 'text',
33
- required
34
- };
35
- if (kind === 'string') return {
36
- kind: 'string',
37
- required
38
- };
39
- if (kind === 'number') return {
40
- kind: 'number',
41
- required
42
- };
43
- if (kind === 'date') return {
44
- kind: 'date',
45
- required
46
- };
47
- if (kind === 'enum') {
48
- const values = stringList(spec.values);
49
- if (values === undefined) return refuse(file, 'definition-enum-values', location);
50
- return {
51
- kind: 'enum',
52
- required,
53
- values
54
- };
55
- }
56
- if (kind === 'reference') {
57
- if (typeof spec.to !== 'string' || spec.to === '') return refuse(file, 'definition-reference-to', location);
58
- return {
59
- kind: 'reference',
60
- required,
61
- to: spec.to
62
- };
63
- }
64
- return refuse(file, 'definition-field-kind', location);
65
- }
66
- function extraKeys(spec, allowed) {
67
- return Object.keys(spec).some((key)=>!allowed.includes(key));
68
- }
69
- function parseList(file, location, spec, required, malformed) {
70
- if (typeof spec.of !== 'string' || !SCALAR_KINDS.has(spec.of)) {
71
- return refuse(file, 'definition-list-of', location);
72
- }
73
- const allowed = spec.of === 'enum' ? [
74
- 'kind',
75
- 'required',
76
- 'of',
77
- 'values'
78
- ] : spec.of === 'reference' ? [
79
- 'kind',
80
- 'required',
81
- 'of',
82
- 'to'
83
- ] : [
84
- 'kind',
85
- 'required',
86
- 'of'
87
- ];
88
- if (extraKeys(spec, allowed)) return refuse(file, malformed, location);
89
- const inner = parseScalar(file, location, {
90
- ...spec,
91
- kind: spec.of
92
- }, false);
93
- if ('rule' in inner) return inner;
94
- return {
95
- kind: 'list',
96
- required,
97
- of: inner
221
+ function singleType(type) {
222
+ if (typeof type === 'string')
223
+ return type;
224
+ if (!Array.isArray(type))
225
+ return undefined;
226
+ const kept = type.filter((one) => one !== 'null');
227
+ return kept.length === 1 ? kept[0] : undefined;
228
+ }
229
+ function firstOf(held, read) {
230
+ for (const node of held) {
231
+ const value = read(node);
232
+ if (value !== undefined)
233
+ return value;
234
+ }
235
+ return undefined;
236
+ }
237
+ function conjoined(nodes, defs, ancestry) {
238
+ const held = [];
239
+ const reached = new Set(ancestry);
240
+ const visit = (node) => {
241
+ if (!isRecord(node) || held.includes(node))
242
+ return;
243
+ held.push(node);
244
+ if (typeof node.$ref === 'string') {
245
+ const target = refTarget(node.$ref, defs)?.node;
246
+ if (target !== undefined && !reached.has(target)) {
247
+ reached.add(target);
248
+ visit(target);
249
+ }
250
+ }
251
+ if (Array.isArray(node.allOf))
252
+ for (const one of node.allOf)
253
+ visit(one);
98
254
  };
255
+ for (const node of nodes)
256
+ visit(node);
257
+ return { held, ancestry: reached };
99
258
  }
100
- function parseField(file, location, value) {
101
- if (!isRecord(value) || typeof value.kind !== 'string') return refuse(file, 'definition-field', location);
102
- const required = requiredFlag(value.required);
103
- if (required === undefined) return refuse(file, 'definition-field', location);
104
- if (value.kind === 'list') return parseList(file, location, value, required, 'definition-field');
105
- const allowed = value.kind === 'enum' ? [
106
- 'kind',
107
- 'required',
108
- 'values'
109
- ] : value.kind === 'reference' ? [
110
- 'kind',
111
- 'required',
112
- 'to'
113
- ] : [
114
- 'kind',
115
- 'required'
116
- ];
117
- if (extraKeys(value, allowed)) return refuse(file, 'definition-field', location);
118
- return parseScalar(file, location, value, required);
119
- }
120
- function parseSection(file, location, value) {
121
- if (!isRecord(value) || value.kind !== 'text' && value.kind !== 'list') {
122
- return refuse(file, 'definition-section-kind', location);
123
- }
124
- const required = requiredFlag(value.required);
125
- if (required === undefined) return refuse(file, 'definition-section', location);
126
- if (value.kind === 'list') return parseList(file, location, value, required, 'definition-section');
127
- if (extraKeys(value, [
128
- 'kind',
129
- 'required'
130
- ])) return refuse(file, 'definition-section', location);
259
+ function variantsOf(node) {
260
+ return [
261
+ ...(Array.isArray(node.anyOf) ? node.anyOf : []),
262
+ ...(Array.isArray(node.oneOf) ? node.oneOf : []),
263
+ node.then,
264
+ node.else,
265
+ ...(isRecord(node.dependentSchemas) ? Object.values(node.dependentSchemas) : []),
266
+ ].filter(isRecord);
267
+ }
268
+ function united(left, right) {
269
+ if (left === undefined || right === undefined)
270
+ return undefined;
271
+ return [...left, ...right.filter((value) => !left.some((held) => equalValue(held, value)))];
272
+ }
273
+ function joined(left, right) {
274
+ const type = left.type === right.type ? left.type : undefined;
275
+ const format = left.format === right.format ? left.format : undefined;
276
+ const values = united(left.values, right.values);
277
+ const reference = united(left.reference, right.reference);
278
+ const items = left.items !== undefined && right.items !== undefined
279
+ ? joined(left.items, right.items)
280
+ : undefined;
131
281
  return {
132
- kind: 'text',
133
- required
282
+ ...(type === undefined ? {} : { type }),
283
+ ...(format === undefined ? {} : { format }),
284
+ ...(values === undefined ? {} : { values }),
285
+ ...(reference === undefined ? {} : { reference }),
286
+ prose: left.prose && right.prose,
287
+ ...(items === undefined ? {} : { items }),
134
288
  };
135
289
  }
136
- export function readDefinition(file, document) {
137
- if (document.type !== 'definition') return refuse(file, 'definition-type');
138
- const name = typeNameFromPath(file);
139
- if (name === '') return refuse(file, 'definition-type');
140
- for (const key of Object.keys(document.fields)){
141
- if (key !== 'type' && key !== 'fields' && key !== 'sections') {
142
- return refuse(file, 'definition-shape', key);
290
+ function propertiesOf(held, defs, ancestry) {
291
+ const declared = new Map();
292
+ for (const node of held) {
293
+ if (!isRecord(node.properties))
294
+ continue;
295
+ for (const [name, schema] of Object.entries(node.properties))
296
+ declared.set(name, [...(declared.get(name) ?? []), schema]);
297
+ }
298
+ const properties = Object.create(null);
299
+ for (const [name, schemas] of declared)
300
+ properties[name] = factsOf(schemas, defs, ancestry);
301
+ const variants = Object.create(null);
302
+ for (const branch of held.flatMap(variantsOf)) {
303
+ for (const [name, facts] of Object.entries(factsOf([branch], defs, ancestry).properties ?? {})) {
304
+ if (Object.hasOwn(properties, name))
305
+ continue;
306
+ variants[name] = Object.hasOwn(variants, name) ? joined(variants[name], facts) : facts;
143
307
  }
144
308
  }
145
- const fieldsValue = document.fields.fields;
146
- const sectionsValue = document.fields.sections;
147
- if (fieldsValue !== undefined && !isRecord(fieldsValue)) return refuse(file, 'definition-fields', 'fields');
148
- if (sectionsValue !== undefined && !isRecord(sectionsValue)) {
149
- return refuse(file, 'definition-sections', 'sections');
309
+ Object.assign(properties, variants);
310
+ return Object.keys(properties).length === 0 ? undefined : properties;
311
+ }
312
+ function factsOf(nodes, defs, ancestry) {
313
+ const { held, ancestry: reached } = conjoined(nodes, defs, ancestry);
314
+ const listed = held.flatMap((node) => Array.isArray(node.enum) ? [node.enum] : node.const !== undefined ? [[node.const]] : []);
315
+ const values = listed.length === 0
316
+ ? undefined
317
+ : listed.reduce((kept, list) => kept.filter((value) => list.some((other) => equalValue(other, value))));
318
+ const type = firstOf(held, (node) => singleType(node.type)) ??
319
+ (values === undefined ? undefined : sharedType(values));
320
+ const reference = firstOf(held, (node) => typeof node.reference === 'string'
321
+ ? [node.reference]
322
+ : Array.isArray(node.reference)
323
+ ? node.reference
324
+ : undefined);
325
+ const format = firstOf(held, (node) => typeof node.format === 'string' ? node.format : undefined);
326
+ const prose = type === 'string' &&
327
+ values === undefined &&
328
+ format === undefined &&
329
+ reference === undefined &&
330
+ held.every((node) => node.pattern === undefined);
331
+ const listedItems = held.flatMap((node) => (node.items === undefined ? [] : [node.items]));
332
+ const items = type === 'array' && listedItems.length > 0 ? factsOf(listedItems, defs, reached) : undefined;
333
+ const prefix = type === 'array'
334
+ ? firstOf(held, (node) => Array.isArray(node.prefixItems)
335
+ ? node.prefixItems.map((schema) => factsOf([schema], defs, reached))
336
+ : undefined)
337
+ : undefined;
338
+ const mapped = type === 'object' || type === undefined;
339
+ const properties = mapped ? propertiesOf(held, defs, reached) : undefined;
340
+ const patterns = mapped
341
+ ? held.flatMap((node) => Object.entries(isRecord(node.patternProperties) ? node.patternProperties : {}).map(([pattern, schema]) => ({ pattern, facts: factsOf([schema], defs, reached) })))
342
+ : [];
343
+ const opened = mapped
344
+ ? held.flatMap((node) => [node.additionalProperties, node.unevaluatedProperties].filter(isRecord))
345
+ : [];
346
+ const additional = opened.length === 0 ? undefined : factsOf(opened, defs, reached);
347
+ return {
348
+ ...(type === undefined ? {} : { type }),
349
+ ...(format === undefined ? {} : { format }),
350
+ ...(values === undefined ? {} : { values }),
351
+ ...(reference === undefined ? {} : { reference }),
352
+ prose,
353
+ ...(prefix === undefined ? {} : { prefix }),
354
+ ...(items === undefined ? {} : { items }),
355
+ ...(properties === undefined ? {} : { properties }),
356
+ ...(patterns.length === 0 ? {} : { patterns }),
357
+ ...(additional === undefined ? {} : { additional }),
358
+ };
359
+ }
360
+ export function valueFacts(node, defs) {
361
+ return factsOf([node], defs, new Set());
362
+ }
363
+ export function itemFacts(facts, index) {
364
+ return facts.prefix?.[index] ?? facts.items;
365
+ }
366
+ export function memberFacts(facts, key) {
367
+ if (facts.properties !== undefined && Object.hasOwn(facts.properties, key))
368
+ return facts.properties[key];
369
+ const pattern = facts.patterns?.find((one) => new RegExp(one.pattern, 'u').test(key));
370
+ return pattern === undefined ? facts.additional : pattern.facts;
371
+ }
372
+ function reachedDefs(value, defs, reached) {
373
+ if (Array.isArray(value)) {
374
+ for (const item of value)
375
+ reachedDefs(item, defs, reached);
376
+ return;
150
377
  }
151
- const fields = Object.create(null);
152
- for (const [fieldName, spec] of Object.entries(fieldsValue ?? {})){
153
- const parsed = parseField(file, fieldName, spec);
154
- if ('rule' in parsed) return parsed;
155
- fields[fieldName] = parsed;
378
+ if (!isRecord(value))
379
+ return;
380
+ for (const [key, held] of Object.entries(value)) {
381
+ if (key === '$ref' && typeof held === 'string') {
382
+ const name = refTarget(held, defs)?.name;
383
+ if (name === undefined || Object.hasOwn(reached, name))
384
+ continue;
385
+ reached[name] = defs[name];
386
+ reachedDefs(defs[name], defs, reached);
387
+ continue;
388
+ }
389
+ reachedDefs(held, defs, reached);
156
390
  }
391
+ }
392
+ function readSections(value, at, context) {
393
+ const failed = (rule, location) => ({ failure: refuse(rule, location) });
394
+ if (!isRecord(value))
395
+ return failed('sections', at);
157
396
  const sections = Object.create(null);
158
- for (const [sectionName, spec] of Object.entries(sectionsValue ?? {})){
159
- const parsed = parseSection(file, sectionName, spec);
160
- if ('rule' in parsed) return parsed;
161
- sections[sectionName] = parsed;
397
+ for (const [name, spec] of Object.entries(value)) {
398
+ const where = `${at}/${escapePointer(name)}`;
399
+ if (!isRecord(spec) || (spec.kind !== 'text' && spec.kind !== 'list'))
400
+ return failed('sections', where);
401
+ const allowed = spec.kind === 'list' ? ['kind', 'required', 'items'] : ['kind', 'required'];
402
+ const extra = Object.keys(spec).find((key) => !allowed.includes(key));
403
+ if (extra !== undefined)
404
+ return failed('sections', `${where}/${escapePointer(extra)}`);
405
+ if (spec.required !== undefined && typeof spec.required !== 'boolean')
406
+ return failed('sections', `${where}/required`);
407
+ const required = spec.required === true;
408
+ if (spec.kind === 'text') {
409
+ sections[name] = { kind: 'text', required };
410
+ continue;
411
+ }
412
+ if (spec.items === undefined)
413
+ return failed('sections', `${where}/items`);
414
+ const failure = schemaFailure(spec.items, `${where}/items`, context);
415
+ if (failure !== undefined)
416
+ return { failure };
417
+ const items = valueFacts(spec.items, context.defs);
418
+ if (items.type === undefined || !SCALAR_TYPES.has(items.type))
419
+ return failed('sections', `${where}/items`);
420
+ sections[name] = { kind: 'list', required, items };
421
+ }
422
+ return { sections };
423
+ }
424
+ function deepFreeze(value) {
425
+ if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {
426
+ Object.freeze(value);
427
+ for (const held of Object.values(value))
428
+ deepFreeze(held);
162
429
  }
430
+ return value;
431
+ }
432
+ function readType(name, value, context) {
433
+ const at = `/${escapePointer(name)}`;
434
+ if (!isRecord(value))
435
+ return refuse('schema', at);
436
+ const { sections: declared, member_document: mark, ...schema } = value;
437
+ if (mark !== undefined && typeof mark !== 'boolean')
438
+ return refuse('member_document', `${at}/member_document`);
439
+ const read = declared === undefined
440
+ ? { sections: Object.create(null) }
441
+ : readSections(declared, `${at}/sections`, context);
442
+ if ('failure' in read)
443
+ return read.failure;
444
+ const failure = schemaFailure(schema, at, context);
445
+ if (failure !== undefined)
446
+ return failure;
447
+ const memberDocument = mark === true;
448
+ const root = valueFacts(schema, context.defs);
449
+ const fields = Object.assign(Object.create(null), root.properties);
450
+ if (memberDocument && !Object.hasOwn(fields, MEMBER_FIELD))
451
+ fields[MEMBER_FIELD] = { type: 'string', prose: false };
452
+ const defs = Object.create(null);
453
+ reachedDefs(value, context.defs, defs);
163
454
  return {
164
455
  name,
165
- file,
456
+ memberDocument,
457
+ frontmatter: { ...root, properties: { ...HOUSE_KEYS, ...fields } },
166
458
  fields,
167
- sections
459
+ sections: read.sections,
460
+ shape: { schema: value, defs },
168
461
  };
169
462
  }
170
-
171
- //# sourceMappingURL=definition.js.map
463
+ function lineAt(text, offset) {
464
+ return text.slice(0, offset).split(/\r\n|\r|\n/).length;
465
+ }
466
+ export function readSchema(text) {
467
+ let root;
468
+ try {
469
+ root = jsValue(parseYamlMapping(text, 0, text.length));
470
+ }
471
+ catch (error) {
472
+ if (error instanceof YamlError)
473
+ return refuse('schema-yaml', `line ${lineAt(text, error.offset)}`);
474
+ throw error;
475
+ }
476
+ const defs = root.$defs ?? Object.create(null);
477
+ if (!isRecord(defs))
478
+ return refuse('$defs', '/$defs');
479
+ const names = Object.keys(root).filter((key) => key !== '$defs');
480
+ for (const name of names) {
481
+ if (name === '' || name.startsWith('$') || name === BUILT_IN_TYPE || name === ATTACHMENT)
482
+ return refuse('schema-type-name', `/${escapePointer(name)}`);
483
+ }
484
+ const context = { defs, types: new Set(names) };
485
+ for (const [name, def] of Object.entries(defs)) {
486
+ const failure = schemaFailure(def, `/$defs/${escapePointer(name)}`, context);
487
+ if (failure !== undefined)
488
+ return failure;
489
+ }
490
+ const types = Object.create(null);
491
+ let marked = false;
492
+ for (const name of names) {
493
+ const definition = readType(name, root[name], context);
494
+ if ('rule' in definition)
495
+ return definition;
496
+ if (definition.memberDocument) {
497
+ if (marked)
498
+ return refuse('member_document', `/${escapePointer(name)}/member_document`);
499
+ marked = true;
500
+ }
501
+ types[name] = deepFreeze(definition);
502
+ }
503
+ return Object.freeze({ types: Object.freeze(types) });
504
+ }
@@ -0,0 +1,3 @@
1
+ import type { Division, DivisionContext, Document } from './types.js';
2
+ export declare function divide(document: Document, file: string, context: DivisionContext): Division;
3
+ //# sourceMappingURL=divide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"divide.d.ts","sourceRoot":"","sources":["../src/divide.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAgB,MAAM,YAAY,CAAC;AA4WpF,wBAAgB,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,QAAQ,CAc3F"}