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

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 (404) hide show
  1. package/API.md +368 -0
  2. package/README.md +36 -194
  3. package/dist/blocks.d.ts +11 -0
  4. package/dist/blocks.d.ts.map +1 -0
  5. package/dist/blocks.js +69 -0
  6. package/dist/condition.d.ts +162 -0
  7. package/dist/condition.d.ts.map +1 -0
  8. package/dist/condition.js +616 -0
  9. package/dist/definition.d.ts +70 -27
  10. package/dist/definition.d.ts.map +1 -1
  11. package/dist/definition.js +728 -146
  12. package/dist/divide.d.ts +3 -0
  13. package/dist/divide.d.ts.map +1 -0
  14. package/dist/divide.js +320 -0
  15. package/dist/document.d.ts +12 -2
  16. package/dist/document.d.ts.map +1 -1
  17. package/dist/document.js +400 -177
  18. package/dist/fields.d.ts +6 -0
  19. package/dist/fields.d.ts.map +1 -0
  20. package/dist/fields.js +10 -0
  21. package/dist/index.d.ts +16 -3
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +10 -4
  24. package/dist/links.d.ts +4 -0
  25. package/dist/links.d.ts.map +1 -1
  26. package/dist/links.js +633 -225
  27. package/dist/paths.d.ts +15 -4
  28. package/dist/paths.d.ts.map +1 -1
  29. package/dist/paths.js +149 -36
  30. package/dist/profile.js +1 -3
  31. package/dist/project.d.ts +20 -1
  32. package/dist/project.d.ts.map +1 -1
  33. package/dist/project.js +101 -95
  34. package/dist/references.d.ts +4 -0
  35. package/dist/references.d.ts.map +1 -0
  36. package/dist/references.js +30 -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 +95 -3
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/types.js +1 -3
  48. package/dist/validate.d.ts +10 -2
  49. package/dist/validate.d.ts.map +1 -1
  50. package/dist/validate.js +283 -159
  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 +9 -3
  55. package/dist/yaml.d.ts.map +1 -1
  56. package/dist/yaml.js +300 -201
  57. package/fixtures/README.md +91 -56
  58. package/fixtures/cases/absent-link-dangles/library/item.md +8 -0
  59. package/fixtures/cases/absent-link-dangles/schema.yaml +6 -0
  60. package/fixtures/cases/absent-optional-field/context.json +1 -0
  61. package/fixtures/cases/absent-optional-field/expected.json +1 -0
  62. package/fixtures/cases/absent-optional-field/library/companies/acme.md +4 -0
  63. package/fixtures/cases/absent-optional-field/library/deals/lead.md +6 -0
  64. package/fixtures/cases/absent-optional-field/schema.yaml +56 -0
  65. package/fixtures/cases/absolute-link/context.json +1 -0
  66. package/fixtures/cases/absolute-link/expected.json +5 -0
  67. package/fixtures/cases/absolute-link/library/item.md +8 -0
  68. package/fixtures/cases/absolute-link/schema.yaml +6 -0
  69. package/fixtures/cases/attachment-reference-any-file/context.json +1 -0
  70. package/fixtures/cases/attachment-reference-any-file/expected.json +1 -0
  71. package/fixtures/cases/attachment-reference-any-file/library/companies/acme.md +4 -0
  72. package/fixtures/cases/attachment-reference-any-file/library/deals/renewal.md +15 -0
  73. package/fixtures/cases/attachment-reference-any-file/library/places/depot.md +4 -0
  74. package/fixtures/cases/attachment-reference-any-file/library/products/seats.md +4 -0
  75. package/fixtures/cases/attachment-reference-any-file/library/products/support.md +4 -0
  76. package/fixtures/cases/attachment-reference-any-file/schema.yaml +32 -0
  77. package/fixtures/cases/attachment-reference-dangles/context.json +1 -0
  78. package/fixtures/cases/attachment-reference-dangles/expected.json +1 -0
  79. package/fixtures/cases/attachment-reference-dangles/library/companies/acme.md +4 -0
  80. package/fixtures/cases/attachment-reference-dangles/library/deals/renewal.md +15 -0
  81. package/fixtures/cases/attachment-reference-dangles/library/places/depot.md +4 -0
  82. package/fixtures/cases/attachment-reference-dangles/library/products/seats.md +4 -0
  83. package/fixtures/cases/attachment-reference-dangles/library/products/support.md +4 -0
  84. package/fixtures/cases/attachment-reference-dangles/schema.yaml +32 -0
  85. package/fixtures/cases/attachment-reference-outside/context.json +1 -0
  86. package/fixtures/cases/attachment-reference-outside/expected.json +6 -0
  87. package/fixtures/cases/attachment-reference-outside/library/companies/acme.md +4 -0
  88. package/fixtures/cases/attachment-reference-outside/library/deals/renewal.md +15 -0
  89. package/fixtures/cases/attachment-reference-outside/library/places/depot.md +4 -0
  90. package/fixtures/cases/attachment-reference-outside/library/products/seats.md +4 -0
  91. package/fixtures/cases/attachment-reference-outside/library/products/support.md +4 -0
  92. package/fixtures/cases/attachment-reference-outside/schema.yaml +32 -0
  93. package/fixtures/cases/binary-any-reference/expected.json +1 -2
  94. package/fixtures/cases/binary-any-reference/schema.yaml +4 -0
  95. package/fixtures/cases/binary-document-collision/expected.json +1 -2
  96. package/fixtures/cases/binary-document-collision/schema.yaml +1 -0
  97. package/fixtures/cases/binary-image-dangles/expected.json +1 -0
  98. package/fixtures/cases/binary-image-dangles/schema.yaml +1 -0
  99. package/fixtures/cases/binary-link-dangles/expected.json +1 -0
  100. package/fixtures/cases/binary-link-dangles/schema.yaml +1 -0
  101. package/fixtures/cases/binary-link-outside-collection/expected.json +1 -2
  102. package/fixtures/cases/binary-link-outside-collection/schema.yaml +1 -0
  103. package/fixtures/cases/binary-prototype-reference/expected.json +1 -2
  104. package/fixtures/cases/binary-prototype-reference/schema.yaml +4 -0
  105. package/fixtures/cases/binary-typed-reference/expected.json +1 -2
  106. package/fixtures/cases/binary-typed-reference/schema.yaml +5 -0
  107. package/fixtures/cases/boolean-field/context.json +1 -0
  108. package/fixtures/cases/boolean-field/expected.json +6 -0
  109. package/fixtures/cases/boolean-field/library/companies/acme.md +4 -0
  110. package/fixtures/cases/boolean-field/library/deals/renewal.md +31 -0
  111. package/fixtures/cases/boolean-field/schema.yaml +56 -0
  112. package/fixtures/cases/bracketed-link-definition/schema.yaml +6 -0
  113. package/fixtures/cases/closed-nested-object/context.json +1 -0
  114. package/fixtures/cases/closed-nested-object/expected.json +6 -0
  115. package/fixtures/cases/closed-nested-object/library/companies/acme.md +4 -0
  116. package/fixtures/cases/closed-nested-object/library/deals/renewal.md +32 -0
  117. package/fixtures/cases/closed-nested-object/schema.yaml +56 -0
  118. package/fixtures/cases/composed-root-reference/context.json +1 -0
  119. package/fixtures/cases/composed-root-reference/expected.json +6 -0
  120. package/fixtures/cases/composed-root-reference/library/a.md +5 -0
  121. package/fixtures/cases/composed-root-reference/schema.yaml +13 -0
  122. package/fixtures/cases/cross-room-link/context.json +1 -0
  123. package/fixtures/cases/cross-room-link/expected.json +1 -0
  124. package/fixtures/cases/cross-room-link/library/clients/acme.md +6 -0
  125. package/fixtures/cases/cross-room-link/schema.yaml +3 -0
  126. package/fixtures/cases/cross-room-reference/context.json +1 -0
  127. package/fixtures/cases/cross-room-reference/expected.json +1 -0
  128. package/fixtures/cases/cross-room-reference/library/clients/acme.md +9 -0
  129. package/fixtures/cases/cross-room-reference/schema.yaml +9 -0
  130. package/fixtures/cases/date-time-format/context.json +1 -0
  131. package/fixtures/cases/date-time-format/expected.json +6 -0
  132. package/fixtures/cases/date-time-format/library/companies/acme.md +4 -0
  133. package/fixtures/cases/date-time-format/library/deals/renewal.md +31 -0
  134. package/fixtures/cases/date-time-format/schema.yaml +56 -0
  135. package/fixtures/cases/declared-binary-links/schema.yaml +1 -0
  136. package/fixtures/cases/default-unfilled/context.json +1 -0
  137. package/fixtures/cases/default-unfilled/expected.json +6 -0
  138. package/fixtures/cases/default-unfilled/library/companies/acme.md +4 -0
  139. package/fixtures/cases/default-unfilled/library/deals/renewal.md +29 -0
  140. package/fixtures/cases/default-unfilled/schema.yaml +56 -0
  141. package/fixtures/cases/defs-pattern/context.json +1 -0
  142. package/fixtures/cases/defs-pattern/expected.json +6 -0
  143. package/fixtures/cases/defs-pattern/library/companies/acme.md +4 -0
  144. package/fixtures/cases/defs-pattern/library/deals/renewal.md +31 -0
  145. package/fixtures/cases/defs-pattern/schema.yaml +56 -0
  146. package/fixtures/cases/dependent-rule/context.json +1 -0
  147. package/fixtures/cases/dependent-rule/expected.json +6 -0
  148. package/fixtures/cases/dependent-rule/library/companies/acme.md +4 -0
  149. package/fixtures/cases/dependent-rule/library/deals/renewal.md +30 -0
  150. package/fixtures/cases/dependent-rule/schema.yaml +56 -0
  151. package/fixtures/cases/duplicate-link-definition/schema.yaml +6 -0
  152. package/fixtures/cases/email-format/context.json +1 -0
  153. package/fixtures/cases/email-format/expected.json +6 -0
  154. package/fixtures/cases/email-format/library/companies/acme.md +4 -0
  155. package/fixtures/cases/email-format/library/deals/renewal.md +31 -0
  156. package/fixtures/cases/email-format/schema.yaml +56 -0
  157. package/fixtures/cases/fenced-link-definition/schema.yaml +6 -0
  158. package/fixtures/cases/field-enum/expected.json +2 -3
  159. package/fixtures/cases/field-enum/schema.yaml +7 -0
  160. package/fixtures/cases/frontmatter-schema/context.json +1 -0
  161. package/fixtures/cases/frontmatter-schema/expected.json +5 -0
  162. package/fixtures/cases/frontmatter-schema/schema.yaml +5 -0
  163. package/fixtures/cases/integer-field/context.json +1 -0
  164. package/fixtures/cases/integer-field/expected.json +6 -0
  165. package/fixtures/cases/integer-field/library/companies/acme.md +4 -0
  166. package/fixtures/cases/integer-field/library/deals/renewal.md +31 -0
  167. package/fixtures/cases/integer-field/schema.yaml +56 -0
  168. package/fixtures/cases/interrupted-link-definition/schema.yaml +1 -0
  169. package/fixtures/cases/json-schema-constructs/context.json +1 -0
  170. package/fixtures/cases/json-schema-constructs/expected.json +1 -0
  171. package/fixtures/cases/json-schema-constructs/library/companies/acme.md +4 -0
  172. package/fixtures/cases/json-schema-constructs/library/deals/renewal.md +31 -0
  173. package/fixtures/cases/json-schema-constructs/schema.yaml +56 -0
  174. package/fixtures/cases/list-of-objects-closed/context.json +1 -0
  175. package/fixtures/cases/list-of-objects-closed/expected.json +6 -0
  176. package/fixtures/cases/list-of-objects-closed/library/companies/acme.md +4 -0
  177. package/fixtures/cases/list-of-objects-closed/library/deals/renewal.md +32 -0
  178. package/fixtures/cases/list-of-objects-closed/schema.yaml +56 -0
  179. package/fixtures/cases/list-of-objects-item/context.json +1 -0
  180. package/fixtures/cases/list-of-objects-item/expected.json +6 -0
  181. package/fixtures/cases/list-of-objects-item/library/companies/acme.md +4 -0
  182. package/fixtures/cases/list-of-objects-item/library/deals/renewal.md +31 -0
  183. package/fixtures/cases/list-of-objects-item/schema.yaml +56 -0
  184. package/fixtures/cases/list-of-objects-reference/context.json +1 -0
  185. package/fixtures/cases/list-of-objects-reference/expected.json +6 -0
  186. package/fixtures/cases/list-of-objects-reference/library/companies/acme.md +4 -0
  187. package/fixtures/cases/list-of-objects-reference/library/deals/renewal.md +14 -0
  188. package/fixtures/cases/list-of-objects-reference/library/places/depot.md +4 -0
  189. package/fixtures/cases/list-of-objects-reference/library/products/seats.md +4 -0
  190. package/fixtures/cases/list-of-objects-reference/library/products/support.md +4 -0
  191. package/fixtures/cases/list-of-objects-reference/schema.yaml +32 -0
  192. package/fixtures/cases/list-size/context.json +1 -0
  193. package/fixtures/cases/list-size/expected.json +6 -0
  194. package/fixtures/cases/list-size/library/companies/acme.md +4 -0
  195. package/fixtures/cases/list-size/library/deals/renewal.md +31 -0
  196. package/fixtures/cases/list-size/schema.yaml +56 -0
  197. package/fixtures/cases/long-fence-link-definition/schema.yaml +1 -0
  198. package/fixtures/cases/malformed-definition/expected.json +2 -4
  199. package/fixtures/cases/malformed-definition/schema.yaml +3 -0
  200. package/fixtures/cases/member-document/context.json +1 -0
  201. package/fixtures/cases/member-document/expected.json +1 -0
  202. package/fixtures/cases/member-document/library/people/ana.md +5 -0
  203. package/fixtures/cases/member-document/schema.yaml +5 -0
  204. package/fixtures/cases/missing-required-field/expected.json +2 -3
  205. package/fixtures/cases/missing-required-field/schema.yaml +7 -0
  206. package/fixtures/cases/missing-section-item-kind/expected.json +2 -4
  207. package/fixtures/cases/missing-section-item-kind/schema.yaml +6 -0
  208. package/fixtures/cases/misspelled-key/context.json +1 -0
  209. package/fixtures/cases/misspelled-key/expected.json +6 -0
  210. package/fixtures/cases/misspelled-key/library/companies/acme.md +4 -0
  211. package/fixtures/cases/misspelled-key/library/deals/renewal.md +32 -0
  212. package/fixtures/cases/misspelled-key/schema.yaml +56 -0
  213. package/fixtures/cases/nested-defs/context.json +1 -0
  214. package/fixtures/cases/nested-defs/expected.json +6 -0
  215. package/fixtures/cases/nested-defs/library/deal.md +6 -0
  216. package/fixtures/cases/nested-defs/schema.yaml +11 -0
  217. package/fixtures/cases/nested-object-reference/context.json +1 -0
  218. package/fixtures/cases/nested-object-reference/expected.json +6 -0
  219. package/fixtures/cases/nested-object-reference/library/companies/acme.md +4 -0
  220. package/fixtures/cases/nested-object-reference/library/deals/renewal.md +14 -0
  221. package/fixtures/cases/nested-object-reference/library/places/depot.md +4 -0
  222. package/fixtures/cases/nested-object-reference/library/products/seats.md +4 -0
  223. package/fixtures/cases/nested-object-reference/library/products/support.md +4 -0
  224. package/fixtures/cases/nested-object-reference/schema.yaml +32 -0
  225. package/fixtures/cases/nested-reference/context.json +1 -0
  226. package/fixtures/cases/nested-reference/expected.json +1 -0
  227. package/fixtures/cases/nested-reference/library/companies/acme.md +4 -0
  228. package/fixtures/cases/nested-reference/library/deals/renewal.md +15 -0
  229. package/fixtures/cases/nested-reference/library/places/depot.md +4 -0
  230. package/fixtures/cases/nested-reference/library/products/seats.md +4 -0
  231. package/fixtures/cases/nested-reference/library/products/support.md +4 -0
  232. package/fixtures/cases/nested-reference/schema.yaml +32 -0
  233. package/fixtures/cases/nested-required-field/context.json +1 -0
  234. package/fixtures/cases/nested-required-field/expected.json +6 -0
  235. package/fixtures/cases/nested-required-field/library/companies/acme.md +4 -0
  236. package/fixtures/cases/nested-required-field/library/deals/renewal.md +30 -0
  237. package/fixtures/cases/nested-required-field/schema.yaml +56 -0
  238. package/fixtures/cases/null-refused/context.json +1 -0
  239. package/fixtures/cases/null-refused/expected.json +6 -0
  240. package/fixtures/cases/null-refused/library/companies/acme.md +4 -0
  241. package/fixtures/cases/null-refused/library/deals/renewal.md +31 -0
  242. package/fixtures/cases/null-refused/schema.yaml +56 -0
  243. package/fixtures/cases/numeric-range/context.json +1 -0
  244. package/fixtures/cases/numeric-range/expected.json +6 -0
  245. package/fixtures/cases/numeric-range/library/companies/acme.md +4 -0
  246. package/fixtures/cases/numeric-range/library/deals/renewal.md +31 -0
  247. package/fixtures/cases/numeric-range/schema.yaml +56 -0
  248. package/fixtures/cases/one-of-variant/context.json +1 -0
  249. package/fixtures/cases/one-of-variant/expected.json +6 -0
  250. package/fixtures/cases/one-of-variant/library/companies/acme.md +4 -0
  251. package/fixtures/cases/one-of-variant/library/deals/renewal.md +31 -0
  252. package/fixtures/cases/one-of-variant/schema.yaml +56 -0
  253. package/fixtures/cases/open-map-value/context.json +1 -0
  254. package/fixtures/cases/open-map-value/expected.json +6 -0
  255. package/fixtures/cases/open-map-value/library/companies/acme.md +4 -0
  256. package/fixtures/cases/open-map-value/library/deals/renewal.md +31 -0
  257. package/fixtures/cases/open-map-value/schema.yaml +56 -0
  258. package/fixtures/cases/other-room-reference/context.json +1 -0
  259. package/fixtures/cases/other-room-reference/expected.json +6 -0
  260. package/fixtures/cases/other-room-reference/library/companies/acme.md +4 -0
  261. package/fixtures/cases/other-room-reference/library/deals/renewal.md +14 -0
  262. package/fixtures/cases/other-room-reference/library/places/depot.md +4 -0
  263. package/fixtures/cases/other-room-reference/library/products/seats.md +4 -0
  264. package/fixtures/cases/other-room-reference/library/products/support.md +4 -0
  265. package/fixtures/cases/other-room-reference/schema.yaml +32 -0
  266. package/fixtures/cases/paragraph-link-definition/schema.yaml +1 -0
  267. package/fixtures/cases/prototype-field/expected.json +2 -3
  268. package/fixtures/cases/prototype-field/schema.yaml +6 -0
  269. package/fixtures/cases/quoted-link-definition/expected.json +1 -2
  270. package/fixtures/cases/quoted-link-definition/library/notes/draft.md +1 -1
  271. package/fixtures/cases/quoted-link-definition/schema.yaml +1 -0
  272. package/fixtures/cases/referenced-missing-file/expected.json +0 -1
  273. package/fixtures/cases/referenced-missing-file/schema.yaml +11 -0
  274. package/fixtures/cases/remote-ref/context.json +1 -0
  275. package/fixtures/cases/remote-ref/expected.json +5 -0
  276. package/fixtures/cases/remote-ref/schema.yaml +3 -0
  277. package/fixtures/cases/second-member-document/context.json +1 -0
  278. package/fixtures/cases/second-member-document/expected.json +5 -0
  279. package/fixtures/cases/second-member-document/schema.yaml +4 -0
  280. package/fixtures/cases/section-item-enum/context.json +1 -0
  281. package/fixtures/cases/section-item-enum/expected.json +6 -0
  282. package/fixtures/cases/section-item-enum/library/task.md +8 -0
  283. package/fixtures/cases/section-item-enum/schema.yaml +3 -0
  284. package/fixtures/cases/section-item-kind/context.json +1 -0
  285. package/fixtures/cases/section-item-kind/expected.json +6 -0
  286. package/fixtures/cases/section-item-kind/library/task.md +8 -0
  287. package/fixtures/cases/section-item-kind/schema.yaml +3 -0
  288. package/fixtures/cases/section-items/context.json +1 -0
  289. package/fixtures/cases/section-items/expected.json +1 -0
  290. package/fixtures/cases/section-items/library/other.md +3 -0
  291. package/fixtures/cases/section-items/library/page.md +42 -0
  292. package/fixtures/cases/section-items/schema.yaml +10 -0
  293. package/fixtures/cases/section-reference-path/context.json +1 -0
  294. package/fixtures/cases/section-reference-path/expected.json +6 -0
  295. package/fixtures/cases/section-reference-path/library/other.md +3 -0
  296. package/fixtures/cases/section-reference-path/library/page.md +7 -0
  297. package/fixtures/cases/section-reference-path/schema.yaml +3 -0
  298. package/fixtures/cases/section-reference-type/context.json +1 -0
  299. package/fixtures/cases/section-reference-type/expected.json +6 -0
  300. package/fixtures/cases/section-reference-type/library/note.md +1 -0
  301. package/fixtures/cases/section-reference-type/library/page.md +7 -0
  302. package/fixtures/cases/section-reference-type/schema.yaml +3 -0
  303. package/fixtures/cases/shortcut-reference-link/context.json +1 -0
  304. package/fixtures/cases/shortcut-reference-link/expected.json +5 -0
  305. package/fixtures/cases/shortcut-reference-link/library/item.md +10 -0
  306. package/fixtures/cases/shortcut-reference-link/schema.yaml +6 -0
  307. package/fixtures/cases/string-length/context.json +1 -0
  308. package/fixtures/cases/string-length/expected.json +6 -0
  309. package/fixtures/cases/string-length/library/companies/acme.md +4 -0
  310. package/fixtures/cases/string-length/library/deals/renewal.md +31 -0
  311. package/fixtures/cases/string-length/schema.yaml +56 -0
  312. package/fixtures/cases/structured-section/expected.json +1 -2
  313. package/fixtures/cases/structured-section/schema.yaml +7 -0
  314. package/fixtures/cases/submission-keys/context.json +1 -0
  315. package/fixtures/cases/submission-keys/expected.json +1 -0
  316. package/fixtures/cases/submission-keys/library/notes/visitor.md +8 -0
  317. package/fixtures/cases/submission-keys/schema.yaml +4 -0
  318. package/fixtures/cases/text-field-kind/context.json +1 -0
  319. package/fixtures/cases/text-field-kind/expected.json +6 -0
  320. package/fixtures/cases/text-field-kind/library/page.md +4 -0
  321. package/fixtures/cases/text-field-kind/schema.yaml +4 -0
  322. package/fixtures/cases/truncated-link-definition/expected.json +1 -2
  323. package/fixtures/cases/truncated-link-definition/library/notes/draft.md +1 -1
  324. package/fixtures/cases/truncated-link-definition/schema.yaml +1 -0
  325. package/fixtures/cases/types-folder-content/context.json +1 -0
  326. package/fixtures/cases/types-folder-content/expected.json +1 -0
  327. package/fixtures/cases/types-folder-content/library/types/task.md +4 -0
  328. package/fixtures/cases/types-folder-content/schema.yaml +4 -0
  329. package/fixtures/cases/unclosed-frontmatter/expected.json +1 -2
  330. package/fixtures/cases/undeclared-field/expected.json +2 -3
  331. package/fixtures/cases/undeclared-field/schema.yaml +6 -0
  332. package/fixtures/cases/unevaluated-items-closed/context.json +1 -0
  333. package/fixtures/cases/unevaluated-items-closed/expected.json +6 -0
  334. package/fixtures/cases/unevaluated-items-closed/library/trip.md +6 -0
  335. package/fixtures/cases/unevaluated-items-closed/schema.yaml +10 -0
  336. package/fixtures/cases/unknown-type/context.json +1 -0
  337. package/fixtures/cases/unknown-type/expected.json +6 -0
  338. package/fixtures/cases/unknown-type/library/item.md +3 -0
  339. package/fixtures/cases/unknown-type/schema.yaml +3 -0
  340. package/fixtures/cases/unlisted-reference-type/context.json +1 -0
  341. package/fixtures/cases/unlisted-reference-type/expected.json +5 -0
  342. package/fixtures/cases/unlisted-reference-type/schema.yaml +3 -0
  343. package/fixtures/cases/unresolved-link/expected.json +1 -2
  344. package/fixtures/cases/unresolved-link/library/item.md +1 -1
  345. package/fixtures/cases/unresolved-link/schema.yaml +6 -0
  346. package/fixtures/cases/valid-typed-document/schema.yaml +16 -0
  347. package/fixtures/cases/wide-item-fence-link/schema.yaml +1 -0
  348. package/fixtures/division.json +409 -0
  349. package/fixtures/projection.json +90 -21
  350. package/package.json +6 -13
  351. package/dist/definition.js.map +0 -1
  352. package/dist/document.js.map +0 -1
  353. package/dist/index.js.map +0 -1
  354. package/dist/links.js.map +0 -1
  355. package/dist/paths.js.map +0 -1
  356. package/dist/profile.js.map +0 -1
  357. package/dist/project.js.map +0 -1
  358. package/dist/refuse.js.map +0 -1
  359. package/dist/schema.js.map +0 -1
  360. package/dist/sections.js.map +0 -1
  361. package/dist/types.js.map +0 -1
  362. package/dist/validate.js.map +0 -1
  363. package/dist/version.js.map +0 -1
  364. package/dist/yaml.js.map +0 -1
  365. package/fixtures/cases/binary-any-reference/library/types/note.md +0 -5
  366. package/fixtures/cases/binary-document-collision/library/types/note.md +0 -3
  367. package/fixtures/cases/binary-link-outside-collection/library/types/note.md +0 -3
  368. package/fixtures/cases/binary-prototype-reference/library/types/note.md +0 -5
  369. package/fixtures/cases/binary-typed-reference/library/types/note.md +0 -5
  370. package/fixtures/cases/binary-typed-reference/library/types/person.md +0 -3
  371. package/fixtures/cases/bracketed-link-definition/library/types/task.md +0 -7
  372. package/fixtures/cases/declared-binary-links/library/types/note.md +0 -3
  373. package/fixtures/cases/duplicate-link-definition/library/types/task.md +0 -7
  374. package/fixtures/cases/fenced-link-definition/library/types/task.md +0 -7
  375. package/fixtures/cases/field-enum/library/types/task.md +0 -8
  376. package/fixtures/cases/interrupted-link-definition/library/types/note.md +0 -3
  377. package/fixtures/cases/long-fence-link-definition/library/types/note.md +0 -3
  378. package/fixtures/cases/malformed-definition/library/types/task.md +0 -5
  379. package/fixtures/cases/missing-binary-image/expected.json +0 -6
  380. package/fixtures/cases/missing-binary-image/library/types/note.md +0 -3
  381. package/fixtures/cases/missing-binary-link/expected.json +0 -6
  382. package/fixtures/cases/missing-binary-link/library/types/note.md +0 -3
  383. package/fixtures/cases/missing-required-field/library/types/task.md +0 -8
  384. package/fixtures/cases/missing-section-item-kind/library/types/task.md +0 -7
  385. package/fixtures/cases/paragraph-link-definition/library/types/note.md +0 -3
  386. package/fixtures/cases/prd-definition/library/types/task.md +0 -16
  387. package/fixtures/cases/prototype-field/library/types/task.md +0 -7
  388. package/fixtures/cases/quoted-link-definition/library/types/note.md +0 -3
  389. package/fixtures/cases/referenced-missing-file/library/types/person.md +0 -5
  390. package/fixtures/cases/referenced-missing-file/library/types/task.md +0 -8
  391. package/fixtures/cases/structured-section/library/types/task.md +0 -8
  392. package/fixtures/cases/truncated-link-definition/library/types/note.md +0 -3
  393. package/fixtures/cases/undeclared-field/library/types/task.md +0 -7
  394. package/fixtures/cases/unresolved-link/library/types/task.md +0 -7
  395. package/fixtures/cases/valid-typed-document/library/types/person.md +0 -5
  396. package/fixtures/cases/valid-typed-document/library/types/task.md +0 -13
  397. package/fixtures/cases/wide-item-fence-link/library/types/note.md +0 -3
  398. package/markdown-syntax-profile.md +0 -9
  399. /package/fixtures/cases/{prd-definition → absent-link-dangles}/context.json +0 -0
  400. /package/fixtures/cases/{prd-definition → absent-link-dangles}/expected.json +0 -0
  401. /package/fixtures/cases/{missing-binary-image → binary-image-dangles}/context.json +0 -0
  402. /package/fixtures/cases/{missing-binary-image → binary-image-dangles}/library/notes/draft.md +0 -0
  403. /package/fixtures/cases/{missing-binary-link → binary-link-dangles}/context.json +0 -0
  404. /package/fixtures/cases/{missing-binary-link → binary-link-dangles}/library/notes/draft.md +0 -0
package/dist/document.js CHANGED
@@ -1,13 +1,22 @@
1
- import { hrefOccurrences } from './links.js';
2
- import { classifyHref, hrefSuffix } from './paths.js';
1
+ import { ARRAY_INDEX, pointerSegments } from './definition.js';
2
+ import { destinations, hrefOccurrences, linkInventory, } from './links.js';
3
+ import { destinationPath, relative, retarget, roomPath, roomTarget, SHELL_ROOMS, shellTarget, target, } from './paths.js';
4
+ import { references } from './references.js';
3
5
  import { headingSpans, sectionsRecord } from './sections.js';
4
6
  import { refusal } from './refuse.js';
5
- import { bodyStartAfterYaml, bodyStartOf, equalValue, extractFrontmatter, jsValue, lineEnding, mapEntry, parseYamlMapping, serializeJs, serializeKey, YamlError } from './yaml.js';
7
+ import { bodyStartAfterYaml, bodyStartOf, equalValue, extractFrontmatter, frontmatterValue, jsValue, lineEnding, mapEntry, parseYamlMapping, serializeJs, serializeKey, YamlError, } from './yaml.js';
6
8
  const internals = new WeakMap();
9
+ const inventories = new WeakMap();
10
+ export function inventoryOf(document) {
11
+ const held = inventories.get(document);
12
+ if (held !== undefined)
13
+ return held;
14
+ const inventory = linkInventory(document.content.slice(bodyStartOf(document.content)));
15
+ inventories.set(document, inventory);
16
+ return inventory;
17
+ }
7
18
  function refuse(file, rule, location) {
8
- return location === undefined ? refusal(file, rule) : refusal(file, rule, {
9
- location
10
- });
19
+ return location === undefined ? refusal(file, rule) : refusal(file, rule, { location });
11
20
  }
12
21
  function freezeDocument(content, type, fields, preamble, sections, internal) {
13
22
  const document = Object.freeze({
@@ -15,151 +24,75 @@ function freezeDocument(content, type, fields, preamble, sections, internal) {
15
24
  type,
16
25
  fields: Object.freeze(fields),
17
26
  preamble,
18
- sections: Object.freeze(sections)
27
+ sections: Object.freeze(sections),
19
28
  });
20
29
  internals.set(document, internal);
21
30
  return document;
22
31
  }
23
32
  function declaredType(fields) {
24
33
  const value = fields.type;
25
- if (value === undefined || value === null) return undefined;
26
- if (typeof value !== 'string' || value === '') return undefined;
34
+ if (value === undefined || value === null)
35
+ return undefined;
36
+ if (typeof value !== 'string' || value === '')
37
+ return undefined;
27
38
  return value;
28
39
  }
29
- export function parse(content, file = '') {
40
+ function opened(content, file) {
30
41
  const fence = extractFrontmatter(content);
31
- if (fence.kind === 'none') {
32
- const spans = headingSpans(content, 0);
33
- return {
34
- ok: true,
35
- document: freezeDocument(content, undefined, {}, content.slice(0, spans[0]?.headingStart), sectionsRecord(spans, content), {
36
- root: null,
37
- yamlEnd: 0,
38
- bodyStart: 0
39
- })
40
- };
41
- }
42
- if (fence.kind === 'unclosed') return {
43
- ok: false,
44
- refusal: refuse(file, 'frontmatter-fence')
45
- };
42
+ if (fence.kind === 'none')
43
+ return { ok: true, root: null, fields: {}, yamlEnd: 0 };
44
+ if (fence.kind === 'unclosed')
45
+ return { ok: false, refusal: refuse(file, 'frontmatter-fence') };
46
46
  try {
47
47
  const root = parseYamlMapping(content, fence.yamlStart, fence.yamlEnd);
48
48
  const fields = jsValue(root);
49
49
  if (fields === null || typeof fields !== 'object' || Array.isArray(fields)) {
50
- return {
51
- ok: false,
52
- refusal: refuse(file, 'frontmatter-fence')
53
- };
50
+ return { ok: false, refusal: refuse(file, 'frontmatter-fence') };
54
51
  }
55
- const bodyStart = bodyStartAfterYaml(content, fence.yamlEnd);
56
- const spans = headingSpans(content, bodyStart);
57
- const record = fields;
58
- return {
59
- ok: true,
60
- document: freezeDocument(content, declaredType(record), record, content.slice(bodyStart, spans[0]?.headingStart), sectionsRecord(spans, content), {
61
- root,
62
- yamlEnd: fence.yamlEnd,
63
- bodyStart
64
- })
65
- };
66
- } catch (error) {
67
- if (error instanceof YamlError) return {
68
- ok: false,
69
- refusal: refuse(file, 'frontmatter-fence')
70
- };
52
+ return { ok: true, root, fields: fields, yamlEnd: fence.yamlEnd };
53
+ }
54
+ catch (error) {
55
+ if (error instanceof YamlError)
56
+ return { ok: false, refusal: refuse(file, 'frontmatter-fence') };
71
57
  throw error;
72
58
  }
73
59
  }
74
- function splice(content, start, end, insert) {
75
- return content.slice(0, start) + insert + content.slice(end);
76
- }
77
- function applyField(document, name, value, prior) {
78
- const internal = internals.get(document);
79
- if (internal === undefined || internal.root === null) {
80
- return {
81
- outcome: 'refuse',
82
- refusal: refuse('', 'frontmatter-fence', name)
83
- };
84
- }
85
- if (!equalValue(document.fields[name], prior)) {
86
- return {
87
- outcome: 'stale',
88
- document
89
- };
90
- }
91
- let nextContent;
92
- const existing = mapEntry(internal.root, name);
93
- if (existing !== undefined) {
94
- nextContent = splice(document.content, existing.value.start, existing.value.end, serializeJs(value));
95
- } else {
96
- const nl = lineEnding(document.content);
97
- const line = `${serializeKey(name)}: ${serializeJs(value)}${nl}`;
98
- const before = document.content.slice(0, internal.yamlEnd);
99
- const prefix = before.endsWith('\n') || before.endsWith('\r\n') ? '' : nl;
100
- nextContent = splice(document.content, internal.yamlEnd, internal.yamlEnd, `${prefix}${line}`);
101
- }
102
- const parsed = parse(nextContent);
103
- if (!parsed.ok) return {
104
- outcome: 'refuse',
105
- refusal: parsed.refusal
106
- };
107
- return {
108
- outcome: 'applied',
109
- document: parsed.document
110
- };
111
- }
112
- function applySection(document, name, value, prior) {
113
- const internal = internals.get(document);
114
- if (internal === undefined) return {
115
- outcome: 'refuse',
116
- refusal: refuse('', 'required-section', name)
117
- };
118
- const spans = headingSpans(document.content, internal.bodyStart);
119
- const span = spans.find((item)=>item.name === name);
120
- if (span === undefined) return {
121
- outcome: 'refuse',
122
- refusal: refuse('', 'required-section', name)
123
- };
124
- const current = document.content.slice(span.bodyStart, span.bodyEnd);
125
- if (current !== prior) return {
126
- outcome: 'stale',
127
- document
128
- };
129
- const parsed = parse(splice(document.content, span.bodyStart, span.bodyEnd, value));
130
- if (!parsed.ok) return {
131
- outcome: 'refuse',
132
- refusal: parsed.refusal
133
- };
60
+ export function parseFrontmatter(content, file = '') {
61
+ const read = opened(content, file);
62
+ if (!read.ok)
63
+ return read;
134
64
  return {
135
- outcome: 'applied',
136
- document: parsed.document
65
+ ok: true,
66
+ frontmatter: Object.freeze({
67
+ content,
68
+ type: declaredType(read.fields),
69
+ fields: Object.freeze(read.fields),
70
+ }),
137
71
  };
138
72
  }
139
- function applyPreamble(document, value, prior) {
140
- if (document.preamble !== prior) return {
141
- outcome: 'stale',
142
- document
143
- };
144
- const start = bodyStartOf(document.content);
145
- const parsed = parse(splice(document.content, start, start + document.preamble.length, value));
146
- if (!parsed.ok) return {
147
- outcome: 'refuse',
148
- refusal: parsed.refusal
149
- };
73
+ export function parse(content, file = '') {
74
+ const read = opened(content, file);
75
+ if (!read.ok)
76
+ return read;
77
+ const bodyStart = read.root === null ? 0 : bodyStartAfterYaml(content, read.yamlEnd);
78
+ const spans = headingSpans(content, bodyStart);
150
79
  return {
151
- outcome: 'applied',
152
- document: parsed.document
80
+ ok: true,
81
+ document: freezeDocument(content, declaredType(read.fields), read.fields, content.slice(bodyStart, spans[0]?.headingStart), sectionsRecord(spans, content), { root: read.root, yamlEnd: read.yamlEnd, bodyStart }),
153
82
  };
154
83
  }
155
84
  function fitsBare(to) {
156
- if (to === '' || to.startsWith('<')) return false;
85
+ if (to === '' || to.startsWith('<'))
86
+ return false;
157
87
  let depth = 0;
158
- for (const character of to){
159
- if (/[\s\u0000-\u001f\u007f]/.test(character)) return false;
160
- if (character === '(') depth += 1;
88
+ for (const character of to) {
89
+ if (/[\s\u0000-\u001f\u007f]/.test(character))
90
+ return false;
91
+ if (character === '(')
92
+ depth += 1;
161
93
  else if (character === ')') {
162
- if (depth === 0) return false;
94
+ if (depth === 0)
95
+ return false;
163
96
  depth -= 1;
164
97
  }
165
98
  }
@@ -169,74 +102,364 @@ function fitsBrackets(to) {
169
102
  return to !== '' && !/[<>\n\r]/.test(to);
170
103
  }
171
104
  function destinationText(to, bracketed) {
172
- if (fitsBare(to)) return bracketed && fitsBrackets(to) ? `<${to}>` : to;
173
- if (fitsBrackets(to)) return `<${to}>`;
105
+ if (fitsBare(to))
106
+ return bracketed && fitsBrackets(to) ? `<${to}>` : to;
107
+ if (fitsBrackets(to))
108
+ return `<${to}>`;
174
109
  return null;
175
110
  }
176
- function applyLink(document, href, to) {
177
- const content = document.content;
178
- const bodyStart = bodyStartOf(content);
179
- const matches = hrefOccurrences(content.slice(bodyStart)).filter((occurrence)=>occurrence.href === href);
180
- if (matches.length === 0) return {
181
- outcome: 'stale',
182
- document
111
+ function shellRelinked(body, file, handle) {
112
+ const occurrences = hrefOccurrences(body);
113
+ const written = new Map();
114
+ for (const href of new Set(occurrences.map((occurrence) => occurrence.href))) {
115
+ const path = shellTarget(href, handle);
116
+ if (path === null)
117
+ continue;
118
+ const to = retarget(href, relative(file, path));
119
+ if (destinationText(to, false) === null)
120
+ return refuse('', 'unwritable-link', to);
121
+ written.set(href, to);
122
+ }
123
+ let rewritten = '';
124
+ let cursor = 0;
125
+ for (const match of occurrences) {
126
+ const to = written.get(match.href);
127
+ if (to === undefined)
128
+ continue;
129
+ rewritten += body.slice(cursor, match.start) + destinationText(to, match.bracketed);
130
+ cursor = match.end;
131
+ }
132
+ return rewritten + body.slice(cursor);
133
+ }
134
+ function nodeAt(root, pointer, entryOf = mapEntry) {
135
+ let node = root;
136
+ for (const key of pointerSegments(pointer)) {
137
+ if (node?.kind === 'map')
138
+ node = entryOf(node, key)?.value;
139
+ else if (node?.kind === 'seq' && ARRAY_INDEX.test(key))
140
+ node = node.items[Number(key)];
141
+ else
142
+ return undefined;
143
+ }
144
+ return node;
145
+ }
146
+ function scalarText(source, value) {
147
+ if (source === "'")
148
+ return `'${value.replaceAll("'", "''")}'`;
149
+ if (source === '"')
150
+ return JSON.stringify(value);
151
+ return serializeJs(value);
152
+ }
153
+ export function relativize(document, file, handle, definition, kept = new Set()) {
154
+ const relativized = (href) => {
155
+ const path = shellTarget(href, handle);
156
+ return path === null || kept.has(`${SHELL_ROOMS}${handle}/${path}`) ? null : path;
183
157
  };
184
- const written = to + hrefSuffix(href);
158
+ const changes = [];
159
+ for (const { pointer, value } of definition === undefined
160
+ ? []
161
+ : references(document, definition)) {
162
+ const path = relativized(value);
163
+ if (path !== null)
164
+ changes.push({
165
+ kind: 'reference',
166
+ pointer,
167
+ value: retarget(value, relative(file, path)),
168
+ prior: value,
169
+ });
170
+ }
171
+ for (const href of new Set(destinations(inventoryOf(document)).map(({ href }) => href))) {
172
+ const path = relativized(href);
173
+ if (path !== null)
174
+ changes.push({ kind: 'link', href, to: relative(file, path) });
175
+ }
176
+ return apply(document, changes);
177
+ }
178
+ export function relativizeBody(body, file, handle) {
179
+ const relinkedBody = shellRelinked(body, file, handle);
180
+ if (typeof relinkedBody !== 'string')
181
+ return { outcome: 'refuse', refusal: relinkedBody };
182
+ const elsewhere = hrefOccurrences(relinkedBody).find(({ href }) => destinationPath(href)?.startsWith(SHELL_ROOMS) === true && roomTarget(href) === null);
183
+ if (elsewhere !== undefined)
184
+ return { outcome: 'refuse', refusal: refuse(file, 'unresolved-link', elsewhere.href) };
185
+ return { outcome: 'applied', body: relinkedBody };
186
+ }
187
+ export function relinkBody(body, file, moves) {
185
188
  let rewritten = '';
186
189
  let cursor = 0;
187
- for (const match of matches){
190
+ for (const match of hrefOccurrences(body)) {
191
+ const from = target(file, match.href) ?? roomPath(match.href);
192
+ const to = from === null ? undefined : moves.get(from);
193
+ if (to === undefined)
194
+ continue;
195
+ const written = retarget(match.href, from.startsWith(SHELL_ROOMS) || to.startsWith(SHELL_ROOMS) ? to : relative(file, to));
188
196
  const text = destinationText(written, match.bracketed);
189
- if (text === null) return {
190
- outcome: 'refuse',
191
- refusal: refuse('', 'unwritable-link', written)
192
- };
193
- rewritten += content.slice(cursor, bodyStart + match.start);
194
- rewritten += text;
195
- cursor = bodyStart + match.end;
196
- }
197
- const parsed = parse(rewritten + content.slice(cursor));
198
- if (!parsed.ok) return {
199
- outcome: 'refuse',
200
- refusal: parsed.refusal
201
- };
202
- return {
203
- outcome: 'applied',
204
- document: parsed.document
205
- };
197
+ if (text === null)
198
+ return { outcome: 'refuse', refusal: refuse(file, 'unwritable-link', written) };
199
+ rewritten += body.slice(cursor, match.start) + text;
200
+ cursor = match.end;
201
+ }
202
+ return { outcome: 'applied', body: rewritten + body.slice(cursor) };
206
203
  }
207
- export function links(document, file) {
204
+ function linksIn(occurrences, file) {
208
205
  const found = [];
209
206
  const seen = new Set();
210
- for (const occurrence of hrefOccurrences(document.content.slice(bodyStartOf(document.content)))){
211
- if (seen.has(occurrence.href)) continue;
212
- const resolved = classifyHref(file, occurrence.href);
213
- if (resolved.kind !== 'path') continue;
207
+ for (const occurrence of occurrences) {
208
+ if (seen.has(occurrence.href))
209
+ continue;
210
+ const resolved = target(file, occurrence.href);
211
+ if (resolved === null)
212
+ continue;
214
213
  seen.add(occurrence.href);
215
- found.push({
216
- href: occurrence.href,
217
- target: resolved.path
218
- });
214
+ found.push({ href: occurrence.href, target: resolved });
219
215
  }
220
216
  return found;
221
217
  }
222
- export function apply(document, change) {
223
- if (change.kind === 'link') return applyLink(document, change.href, change.to);
224
- if (change.kind === 'preamble') return applyPreamble(document, change.value, change.prior);
225
- try {
226
- if (change.kind === 'field') return applyField(document, change.name, change.value, change.prior);
227
- return applySection(document, change.name, change.value, change.prior);
228
- } catch (error) {
229
- if (error instanceof YamlError) {
230
- return {
231
- outcome: 'refuse',
232
- refusal: refuse('', 'frontmatter-fence', change.name)
233
- };
218
+ export function links(document, file) {
219
+ return linksIn(destinations(inventoryOf(document)), file);
220
+ }
221
+ export function bodyLinks(body, file) {
222
+ return linksIn(hrefOccurrences(body), file);
223
+ }
224
+ function internalOf(document) {
225
+ const held = internals.get(document);
226
+ if (held !== undefined)
227
+ return held;
228
+ const read = opened(document.content, '');
229
+ if (!read.ok)
230
+ return read.refusal;
231
+ return {
232
+ root: read.root,
233
+ yamlEnd: read.yamlEnd,
234
+ bodyStart: read.root === null ? 0 : bodyStartAfterYaml(document.content, read.yamlEnd),
235
+ };
236
+ }
237
+ function partOf(change) {
238
+ if (change.kind === 'field' || change.kind === 'section')
239
+ return `${change.kind} ${change.name}`;
240
+ if (change.kind === 'link')
241
+ return `link ${change.href}`;
242
+ if (change.kind === 'reference')
243
+ return `reference ${change.pointer}`;
244
+ return 'preamble';
245
+ }
246
+ function planner(document, internal) {
247
+ const content = document.content;
248
+ const keyed = new Map();
249
+ let spans;
250
+ let occurrences;
251
+ let ending;
252
+ let added = 0;
253
+ const entryOf = (map, key) => {
254
+ let index = keyed.get(map);
255
+ if (index === undefined) {
256
+ index = new Map();
257
+ for (const entry of map.entries)
258
+ if (!index.has(entry.key))
259
+ index.set(entry.key, entry);
260
+ keyed.set(map, index);
234
261
  }
235
- throw error;
262
+ return index.get(key);
263
+ };
264
+ const field = (name, value, prior, at) => {
265
+ const root = internal.root;
266
+ if (root === null)
267
+ return refuse('', 'frontmatter-fence', name);
268
+ if (!equalValue(document.fields[name], prior))
269
+ return 'stale';
270
+ if (!frontmatterValue(value))
271
+ return refuse('', 'frontmatter-fence', name);
272
+ const existing = entryOf(root, name);
273
+ if (existing !== undefined) {
274
+ const held = existing.value;
275
+ const inline = held.start > existing.after && !/[\r\n]/.test(content.slice(existing.after, held.start));
276
+ return inline
277
+ ? [{ start: held.start, end: held.end, text: serializeJs(value), at }]
278
+ : [{ start: existing.after, end: held.end, text: ` ${serializeJs(value)}`, at }];
279
+ }
280
+ const entry = `${serializeKey(name)}: ${serializeJs(value)}`;
281
+ added += 1;
282
+ if (content[root.start] === '{') {
283
+ const separator = root.entries.length === 0 && added === 1 ? '' : ', ';
284
+ return [{ start: root.end - 1, end: root.end - 1, text: `${separator}${entry}`, at }];
285
+ }
286
+ const lineStart = content.lastIndexOf('\n', root.start - 1) + 1;
287
+ ending ??= lineEnding(content);
288
+ const line = `${content.slice(lineStart, root.start)}${entry}${ending}`;
289
+ return [{ start: internal.yamlEnd, end: internal.yamlEnd, text: line, at, entry: true }];
290
+ };
291
+ const section = (name, value, prior, at) => {
292
+ if (spans === undefined) {
293
+ spans = new Map();
294
+ for (const span of headingSpans(content, internal.bodyStart))
295
+ if (!spans.has(span.name))
296
+ spans.set(span.name, span);
297
+ }
298
+ const span = spans.get(name);
299
+ if (span === undefined)
300
+ return refuse('', 'required-section', name);
301
+ if (content.slice(span.bodyStart, span.bodyEnd) !== prior)
302
+ return 'stale';
303
+ return [{ start: span.bodyStart, end: span.bodyEnd, text: value, at }];
304
+ };
305
+ const link = (href, to, at) => {
306
+ if (occurrences === undefined) {
307
+ occurrences = new Map();
308
+ for (const occurrence of destinations(inventoryOf(document))) {
309
+ const same = occurrences.get(occurrence.href);
310
+ if (same === undefined)
311
+ occurrences.set(occurrence.href, [occurrence]);
312
+ else
313
+ same.push(occurrence);
314
+ }
315
+ }
316
+ const found = occurrences.get(href);
317
+ if (found === undefined)
318
+ return 'stale';
319
+ const written = retarget(href, to);
320
+ if (destinationText(written, false) === null)
321
+ return refuse('', 'unwritable-link', written);
322
+ return found.map((occurrence) => ({
323
+ start: internal.bodyStart + occurrence.start,
324
+ end: internal.bodyStart + occurrence.end,
325
+ text: destinationText(written, occurrence.bracketed),
326
+ at,
327
+ }));
328
+ };
329
+ const reference = (pointer, value, prior, at) => {
330
+ const node = internal.root === null ? undefined : nodeAt(internal.root, pointer, entryOf);
331
+ if (node?.kind !== 'scalar' || node.value !== prior)
332
+ return 'stale';
333
+ return [
334
+ { start: node.start, end: node.end, text: scalarText(content[node.start], value), at },
335
+ ];
336
+ };
337
+ return (change, at) => {
338
+ if (change.kind === 'field')
339
+ return field(change.name, change.value, change.prior, at);
340
+ if (change.kind === 'section')
341
+ return section(change.name, change.value, change.prior, at);
342
+ if (change.kind === 'link')
343
+ return link(change.href, change.to, at);
344
+ if (change.kind === 'reference')
345
+ return reference(change.pointer, change.value, change.prior, at);
346
+ if (document.preamble !== change.prior)
347
+ return 'stale';
348
+ const start = internal.bodyStart;
349
+ return [{ start, end: start + document.preamble.length, text: change.value, at }];
350
+ };
351
+ }
352
+ function overlapping(edits, stale) {
353
+ let reach = -1;
354
+ let owner = -1;
355
+ for (const edit of edits) {
356
+ if (edit.start < reach)
357
+ stale.add(Math.max(edit.at, owner));
358
+ if (edit.end > reach) {
359
+ reach = edit.end;
360
+ owner = edit.at;
361
+ }
362
+ }
363
+ }
364
+ function firstHeadings(content, bodyStart) {
365
+ const first = new Map();
366
+ for (const span of headingSpans(content, bodyStart)) {
367
+ if (!first.has(span.name))
368
+ first.set(span.name, span.headingStart);
369
+ }
370
+ return first;
371
+ }
372
+ function hidden(before, bodyStart, after, shifts) {
373
+ const placed = firstHeadings(after, bodyStartOf(after));
374
+ let shift = 0;
375
+ let index = 0;
376
+ for (const [name, at] of firstHeadings(before, bodyStart)) {
377
+ while (index < shifts.length && shifts[index][0] <= at) {
378
+ shift += shifts[index][1];
379
+ index += 1;
380
+ }
381
+ if (placed.get(name) !== at + shift)
382
+ return name;
383
+ }
384
+ return undefined;
385
+ }
386
+ function spliced(source, edits) {
387
+ const shifts = [];
388
+ const pieces = [];
389
+ let cursor = 0;
390
+ let entered = false;
391
+ let ended = false;
392
+ for (const edit of edits) {
393
+ const kept = source.slice(cursor, edit.start);
394
+ pieces.push(kept);
395
+ if (kept !== '')
396
+ ended = kept.endsWith('\n');
397
+ let text = edit.text;
398
+ if (edit.entry === true && !entered) {
399
+ entered = true;
400
+ if (!ended)
401
+ text = `${lineEnding(source)}${text}`;
402
+ }
403
+ pieces.push(text);
404
+ if (text !== '')
405
+ ended = text.endsWith('\n');
406
+ shifts.push([edit.start, text.length - (edit.end - edit.start)]);
407
+ cursor = edit.end;
236
408
  }
409
+ pieces.push(source.slice(cursor));
410
+ return { content: pieces.join(''), shifts };
411
+ }
412
+ export function apply(document, changes) {
413
+ const internal = internalOf(document);
414
+ if (!('bodyStart' in internal))
415
+ return { outcome: 'refuse', refusal: internal };
416
+ const plan = planner(document, internal);
417
+ const edits = [];
418
+ const stale = new Set();
419
+ const named = new Set();
420
+ for (const [at, change] of changes.entries()) {
421
+ const planned = plan(change, at);
422
+ if (planned === 'stale') {
423
+ stale.add(at);
424
+ continue;
425
+ }
426
+ if (!Array.isArray(planned))
427
+ return { outcome: 'refuse', refusal: planned };
428
+ const part = partOf(change);
429
+ if (named.has(part)) {
430
+ stale.add(at);
431
+ continue;
432
+ }
433
+ named.add(part);
434
+ for (const edit of planned)
435
+ edits.push(edit);
436
+ }
437
+ edits.sort((left, right) => left.start - right.start || left.end - right.end || left.at - right.at);
438
+ overlapping(edits, stale);
439
+ if (stale.size > 0)
440
+ return { outcome: 'stale', document, stale: [...stale].sort((left, right) => left - right) };
441
+ const source = document.content;
442
+ const { content } = spliced(source, edits);
443
+ if (content === source)
444
+ return { outcome: 'applied', document };
445
+ const replaced = edits.filter((edit) => {
446
+ const kind = changes[edit.at].kind;
447
+ return kind === 'section' || kind === 'preamble';
448
+ });
449
+ if (replaced.length > 0) {
450
+ const checked = spliced(source, replaced);
451
+ const name = hidden(source, internal.bodyStart, checked.content, checked.shifts);
452
+ if (name !== undefined)
453
+ return { outcome: 'refuse', refusal: refuse('', 'overlapping-section', name) };
454
+ }
455
+ const parsed = parse(content);
456
+ if (!parsed.ok)
457
+ return { outcome: 'refuse', refusal: parsed.refusal };
458
+ return { outcome: 'applied', document: parsed.document };
237
459
  }
238
460
  export function serialize(document) {
239
461
  return document.content;
240
462
  }
241
-
242
- //# sourceMappingURL=document.js.map
463
+ export function frontmatter(document) {
464
+ return internals.get(document)?.root ?? null;
465
+ }
@@ -0,0 +1,6 @@
1
+ export declare const TYPE_FIELD = "type";
2
+ export declare const MEMBER_FIELD = "member";
3
+ export declare const SITE_FIELD = "site";
4
+ export declare const RECEIVED_FIELD = "received";
5
+ export declare const HOUSE_FIELDS: readonly string[];
6
+ //# sourceMappingURL=fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../src/fields.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,SAAS,CAAC;AAEjC,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC,eAAO,MAAM,UAAU,SAAS,CAAC;AAEjC,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EAKzC,CAAC"}
package/dist/fields.js ADDED
@@ -0,0 +1,10 @@
1
+ export const TYPE_FIELD = 'type';
2
+ export const MEMBER_FIELD = 'member';
3
+ export const SITE_FIELD = 'site';
4
+ export const RECEIVED_FIELD = 'received';
5
+ export const HOUSE_FIELDS = [
6
+ TYPE_FIELD,
7
+ SITE_FIELD,
8
+ RECEIVED_FIELD,
9
+ MEMBER_FIELD,
10
+ ];