@ifc-lite/ids-authoring 0.0.0-stage → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +373 -0
- package/README.md +469 -2
- package/dist/bsdd/cache.d.ts +37 -0
- package/dist/bsdd/cache.d.ts.map +1 -0
- package/dist/bsdd/cache.js +116 -0
- package/dist/bsdd/cache.js.map +1 -0
- package/dist/bsdd/contract.d.ts +31 -0
- package/dist/bsdd/contract.d.ts.map +1 -0
- package/dist/bsdd/contract.js +185 -0
- package/dist/bsdd/contract.js.map +1 -0
- package/dist/bsdd/dictionary.d.ts +42 -0
- package/dist/bsdd/dictionary.d.ts.map +1 -0
- package/dist/bsdd/dictionary.js +115 -0
- package/dist/bsdd/dictionary.js.map +1 -0
- package/dist/bsdd/generator.d.ts +82 -0
- package/dist/bsdd/generator.d.ts.map +1 -0
- package/dist/bsdd/generator.js +155 -0
- package/dist/bsdd/generator.js.map +1 -0
- package/dist/bsdd/http-source.d.ts +15 -0
- package/dist/bsdd/http-source.d.ts.map +1 -0
- package/dist/bsdd/http-source.js +196 -0
- package/dist/bsdd/http-source.js.map +1 -0
- package/dist/bsdd/idb-store.d.ts +16 -0
- package/dist/bsdd/idb-store.d.ts.map +1 -0
- package/dist/bsdd/idb-store.js +58 -0
- package/dist/bsdd/idb-store.js.map +1 -0
- package/dist/bsdd/insert.d.ts +55 -0
- package/dist/bsdd/insert.d.ts.map +1 -0
- package/dist/bsdd/insert.js +105 -0
- package/dist/bsdd/insert.js.map +1 -0
- package/dist/bsdd/mapping.d.ts +62 -0
- package/dist/bsdd/mapping.d.ts.map +1 -0
- package/dist/bsdd/mapping.js +163 -0
- package/dist/bsdd/mapping.js.map +1 -0
- package/dist/bsdd/picker.d.ts +91 -0
- package/dist/bsdd/picker.d.ts.map +1 -0
- package/dist/bsdd/picker.js +151 -0
- package/dist/bsdd/picker.js.map +1 -0
- package/dist/bsdd/types.d.ts +162 -0
- package/dist/bsdd/types.d.ts.map +1 -0
- package/dist/bsdd/types.js +26 -0
- package/dist/bsdd/types.js.map +1 -0
- package/dist/bsdd/uri-health.d.ts +65 -0
- package/dist/bsdd/uri-health.d.ts.map +1 -0
- package/dist/bsdd/uri-health.js +110 -0
- package/dist/bsdd/uri-health.js.map +1 -0
- package/dist/canonical-json.d.ts +7 -0
- package/dist/canonical-json.d.ts.map +1 -0
- package/dist/canonical-json.js +20 -0
- package/dist/canonical-json.js.map +1 -0
- package/dist/comments/view.d.ts +37 -0
- package/dist/comments/view.d.ts.map +1 -0
- package/dist/comments/view.js +61 -0
- package/dist/comments/view.js.map +1 -0
- package/dist/compound/expand.d.ts +5 -0
- package/dist/compound/expand.d.ts.map +1 -0
- package/dist/compound/expand.js +135 -0
- package/dist/compound/expand.js.map +1 -0
- package/dist/compound/from-bsdd.d.ts +9 -0
- package/dist/compound/from-bsdd.d.ts.map +1 -0
- package/dist/compound/from-bsdd.js +166 -0
- package/dist/compound/from-bsdd.js.map +1 -0
- package/dist/diff/align.d.ts +42 -0
- package/dist/diff/align.d.ts.map +1 -0
- package/dist/diff/align.js +78 -0
- package/dist/diff/align.js.map +1 -0
- package/dist/diff/changelog-text.d.ts +39 -0
- package/dist/diff/changelog-text.d.ts.map +1 -0
- package/dist/diff/changelog-text.js +120 -0
- package/dist/diff/changelog-text.js.map +1 -0
- package/dist/diff/changelog.d.ts +28 -0
- package/dist/diff/changelog.d.ts.map +1 -0
- package/dist/diff/changelog.js +173 -0
- package/dist/diff/changelog.js.map +1 -0
- package/dist/diff/compare.d.ts +25 -0
- package/dist/diff/compare.d.ts.map +1 -0
- package/dist/diff/compare.js +150 -0
- package/dist/diff/compare.js.map +1 -0
- package/dist/diff/diff.d.ts +13 -0
- package/dist/diff/diff.d.ts.map +1 -0
- package/dist/diff/diff.js +140 -0
- package/dist/diff/diff.js.map +1 -0
- package/dist/diff/index.d.ts +5 -0
- package/dist/diff/index.d.ts.map +1 -0
- package/dist/diff/index.js +7 -0
- package/dist/diff/index.js.map +1 -0
- package/dist/diff/patch.d.ts +10 -0
- package/dist/diff/patch.d.ts.map +1 -0
- package/dist/diff/patch.js +177 -0
- package/dist/diff/patch.js.map +1 -0
- package/dist/diff/types.d.ts +201 -0
- package/dist/diff/types.d.ts.map +1 -0
- package/dist/diff/types.js +5 -0
- package/dist/diff/types.js.map +1 -0
- package/dist/document/fields.d.ts +33 -0
- package/dist/document/fields.d.ts.map +1 -0
- package/dist/document/fields.js +117 -0
- package/dist/document/fields.js.map +1 -0
- package/dist/document/from-ids.d.ts +32 -0
- package/dist/document/from-ids.d.ts.map +1 -0
- package/dist/document/from-ids.js +47 -0
- package/dist/document/from-ids.js.map +1 -0
- package/dist/document/node-index.d.ts +32 -0
- package/dist/document/node-index.d.ts.map +1 -0
- package/dist/document/node-index.js +127 -0
- package/dist/document/node-index.js.map +1 -0
- package/dist/document/types.d.ts +170 -0
- package/dist/document/types.d.ts.map +1 -0
- package/dist/document/types.js +19 -0
- package/dist/document/types.js.map +1 -0
- package/dist/gate/bsdd.d.ts +12 -0
- package/dist/gate/bsdd.d.ts.map +1 -0
- package/dist/gate/bsdd.js +17 -0
- package/dist/gate/bsdd.js.map +1 -0
- package/dist/gate/check.d.ts +6 -0
- package/dist/gate/check.d.ts.map +1 -0
- package/dist/gate/check.js +125 -0
- package/dist/gate/check.js.map +1 -0
- package/dist/gate/context.d.ts +51 -0
- package/dist/gate/context.d.ts.map +1 -0
- package/dist/gate/context.js +74 -0
- package/dist/gate/context.js.map +1 -0
- package/dist/gate/grounding-pset.d.ts +5 -0
- package/dist/gate/grounding-pset.d.ts.map +1 -0
- package/dist/gate/grounding-pset.js +179 -0
- package/dist/gate/grounding-pset.js.map +1 -0
- package/dist/gate/grounding.d.ts +48 -0
- package/dist/gate/grounding.d.ts.map +1 -0
- package/dist/gate/grounding.js +146 -0
- package/dist/gate/grounding.js.map +1 -0
- package/dist/gate/rank.d.ts +28 -0
- package/dist/gate/rank.d.ts.map +1 -0
- package/dist/gate/rank.js +68 -0
- package/dist/gate/rank.js.map +1 -0
- package/dist/gate/structural.d.ts +43 -0
- package/dist/gate/structural.d.ts.map +1 -0
- package/dist/gate/structural.js +175 -0
- package/dist/gate/structural.js.map +1 -0
- package/dist/gate/types.d.ts +45 -0
- package/dist/gate/types.d.ts.map +1 -0
- package/dist/gate/types.js +5 -0
- package/dist/gate/types.js.map +1 -0
- package/dist/gate/values.d.ts +19 -0
- package/dist/gate/values.d.ts.map +1 -0
- package/dist/gate/values.js +124 -0
- package/dist/gate/values.js.map +1 -0
- package/dist/headless/apply-gated.d.ts +32 -0
- package/dist/headless/apply-gated.d.ts.map +1 -0
- package/dist/headless/apply-gated.js +26 -0
- package/dist/headless/apply-gated.js.map +1 -0
- package/dist/headless/diff.d.ts +41 -0
- package/dist/headless/diff.d.ts.map +1 -0
- package/dist/headless/diff.js +116 -0
- package/dist/headless/diff.js.map +1 -0
- package/dist/headless/node-path.d.ts +10 -0
- package/dist/headless/node-path.d.ts.map +1 -0
- package/dist/headless/node-path.js +24 -0
- package/dist/headless/node-path.js.map +1 -0
- package/dist/headless/read.d.ts +26 -0
- package/dist/headless/read.d.ts.map +1 -0
- package/dist/headless/read.js +78 -0
- package/dist/headless/read.js.map +1 -0
- package/dist/headless/schema-lookup.d.ts +52 -0
- package/dist/headless/schema-lookup.d.ts.map +1 -0
- package/dist/headless/schema-lookup.js +77 -0
- package/dist/headless/schema-lookup.js.map +1 -0
- package/dist/headless/write.d.ts +46 -0
- package/dist/headless/write.d.ts.map +1 -0
- package/dist/headless/write.js +103 -0
- package/dist/headless/write.js.map +1 -0
- package/dist/history/history.d.ts +90 -0
- package/dist/history/history.d.ts.map +1 -0
- package/dist/history/history.js +86 -0
- package/dist/history/history.js.map +1 -0
- package/dist/history/persistence.d.ts +33 -0
- package/dist/history/persistence.d.ts.map +1 -0
- package/dist/history/persistence.js +71 -0
- package/dist/history/persistence.js.map +1 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +75 -0
- package/dist/index.js.map +1 -0
- package/dist/lint/context.d.ts +15 -0
- package/dist/lint/context.d.ts.map +1 -0
- package/dist/lint/context.js +24 -0
- package/dist/lint/context.js.map +1 -0
- package/dist/lint/docs.d.ts +18 -0
- package/dist/lint/docs.d.ts.map +1 -0
- package/dist/lint/docs.js +117 -0
- package/dist/lint/docs.js.map +1 -0
- package/dist/lint/engine.d.ts +21 -0
- package/dist/lint/engine.d.ts.map +1 -0
- package/dist/lint/engine.js +123 -0
- package/dist/lint/engine.js.map +1 -0
- package/dist/lint/fix.d.ts +27 -0
- package/dist/lint/fix.d.ts.map +1 -0
- package/dist/lint/fix.js +22 -0
- package/dist/lint/fix.js.map +1 -0
- package/dist/lint/precision.d.ts +51 -0
- package/dist/lint/precision.d.ts.map +1 -0
- package/dist/lint/precision.js +64 -0
- package/dist/lint/precision.js.map +1 -0
- package/dist/lint/rules/bsdd.d.ts +5 -0
- package/dist/lint/rules/bsdd.d.ts.map +1 -0
- package/dist/lint/rules/bsdd.js +123 -0
- package/dist/lint/rules/bsdd.js.map +1 -0
- package/dist/lint/rules/card.d.ts +10 -0
- package/dist/lint/rules/card.d.ts.map +1 -0
- package/dist/lint/rules/card.js +140 -0
- package/dist/lint/rules/card.js.map +1 -0
- package/dist/lint/rules/doc-ver-part.d.ts +7 -0
- package/dist/lint/rules/doc-ver-part.d.ts.map +1 -0
- package/dist/lint/rules/doc-ver-part.js +155 -0
- package/dist/lint/rules/doc-ver-part.js.map +1 -0
- package/dist/lint/rules/entity.d.ts +12 -0
- package/dist/lint/rules/entity.d.ts.map +1 -0
- package/dist/lint/rules/entity.js +215 -0
- package/dist/lint/rules/entity.js.map +1 -0
- package/dist/lint/rules/index.d.ts +4 -0
- package/dist/lint/rules/index.d.ts.map +1 -0
- package/dist/lint/rules/index.js +63 -0
- package/dist/lint/rules/index.js.map +1 -0
- package/dist/lint/rules/pdt-att.d.ts +7 -0
- package/dist/lint/rules/pdt-att.d.ts.map +1 -0
- package/dist/lint/rules/pdt-att.js +209 -0
- package/dist/lint/rules/pdt-att.js.map +1 -0
- package/dist/lint/rules/pset.d.ts +12 -0
- package/dist/lint/rules/pset.d.ts.map +1 -0
- package/dist/lint/rules/pset.js +263 -0
- package/dist/lint/rules/pset.js.map +1 -0
- package/dist/lint/rules/regex.d.ts +6 -0
- package/dist/lint/rules/regex.d.ts.map +1 -0
- package/dist/lint/rules/regex.js +184 -0
- package/dist/lint/rules/regex.js.map +1 -0
- package/dist/lint/rules/spec-doc.d.ts +5 -0
- package/dist/lint/rules/spec-doc.d.ts.map +1 -0
- package/dist/lint/rules/spec-doc.js +132 -0
- package/dist/lint/rules/spec-doc.js.map +1 -0
- package/dist/lint/rules/spec.d.ts +24 -0
- package/dist/lint/rules/spec.d.ts.map +1 -0
- package/dist/lint/rules/spec.js +162 -0
- package/dist/lint/rules/spec.js.map +1 -0
- package/dist/lint/rules/units.d.ts +4 -0
- package/dist/lint/rules/units.d.ts.map +1 -0
- package/dist/lint/rules/units.js +101 -0
- package/dist/lint/rules/units.js.map +1 -0
- package/dist/lint/rules/util.d.ts +37 -0
- package/dist/lint/rules/util.d.ts.map +1 -0
- package/dist/lint/rules/util.js +117 -0
- package/dist/lint/rules/util.js.map +1 -0
- package/dist/lint/rules/value-sites.d.ts +28 -0
- package/dist/lint/rules/value-sites.d.ts.map +1 -0
- package/dist/lint/rules/value-sites.js +81 -0
- package/dist/lint/rules/value-sites.js.map +1 -0
- package/dist/lint/rules/values.d.ts +22 -0
- package/dist/lint/rules/values.d.ts.map +1 -0
- package/dist/lint/rules/values.js +237 -0
- package/dist/lint/rules/values.js.map +1 -0
- package/dist/lint/rules/xsd-regex.d.ts +34 -0
- package/dist/lint/rules/xsd-regex.d.ts.map +1 -0
- package/dist/lint/rules/xsd-regex.js +149 -0
- package/dist/lint/rules/xsd-regex.js.map +1 -0
- package/dist/lint/solver/sample.d.ts +3 -0
- package/dist/lint/solver/sample.d.ts.map +1 -0
- package/dist/lint/solver/sample.js +134 -0
- package/dist/lint/solver/sample.js.map +1 -0
- package/dist/lint/solver/solver.d.ts +39 -0
- package/dist/lint/solver/solver.d.ts.map +1 -0
- package/dist/lint/solver/solver.js +126 -0
- package/dist/lint/solver/solver.js.map +1 -0
- package/dist/lint/suppress.d.ts +12 -0
- package/dist/lint/suppress.d.ts.map +1 -0
- package/dist/lint/suppress.js +56 -0
- package/dist/lint/suppress.js.map +1 -0
- package/dist/lint/types.d.ts +162 -0
- package/dist/lint/types.d.ts.map +1 -0
- package/dist/lint/types.js +5 -0
- package/dist/lint/types.js.map +1 -0
- package/dist/lint/walk.d.ts +20 -0
- package/dist/lint/walk.d.ts.map +1 -0
- package/dist/lint/walk.js +47 -0
- package/dist/lint/walk.js.map +1 -0
- package/dist/match/cascade.d.ts +53 -0
- package/dist/match/cascade.d.ts.map +1 -0
- package/dist/match/cascade.js +135 -0
- package/dist/match/cascade.js.map +1 -0
- package/dist/match/reidentify.d.ts +46 -0
- package/dist/match/reidentify.d.ts.map +1 -0
- package/dist/match/reidentify.js +67 -0
- package/dist/match/reidentify.js.map +1 -0
- package/dist/merge/comments.d.ts +13 -0
- package/dist/merge/comments.d.ts.map +1 -0
- package/dist/merge/comments.js +61 -0
- package/dist/merge/comments.js.map +1 -0
- package/dist/merge/index.d.ts +4 -0
- package/dist/merge/index.d.ts.map +1 -0
- package/dist/merge/index.js +6 -0
- package/dist/merge/index.js.map +1 -0
- package/dist/merge/keys.d.ts +22 -0
- package/dist/merge/keys.d.ts.map +1 -0
- package/dist/merge/keys.js +54 -0
- package/dist/merge/keys.js.map +1 -0
- package/dist/merge/merge.d.ts +8 -0
- package/dist/merge/merge.d.ts.map +1 -0
- package/dist/merge/merge.js +206 -0
- package/dist/merge/merge.js.map +1 -0
- package/dist/merge/order.d.ts +11 -0
- package/dist/merge/order.d.ts.map +1 -0
- package/dist/merge/order.js +117 -0
- package/dist/merge/order.js.map +1 -0
- package/dist/merge/sidecar.d.ts +12 -0
- package/dist/merge/sidecar.d.ts.map +1 -0
- package/dist/merge/sidecar.js +64 -0
- package/dist/merge/sidecar.js.map +1 -0
- package/dist/merge/types.d.ts +50 -0
- package/dist/merge/types.d.ts.map +1 -0
- package/dist/merge/types.js +5 -0
- package/dist/merge/types.js.map +1 -0
- package/dist/merge/view.d.ts +28 -0
- package/dist/merge/view.d.ts.map +1 -0
- package/dist/merge/view.js +35 -0
- package/dist/merge/view.js.map +1 -0
- package/dist/ops/draft.d.ts +33 -0
- package/dist/ops/draft.d.ts.map +1 -0
- package/dist/ops/draft.js +253 -0
- package/dist/ops/draft.js.map +1 -0
- package/dist/ops/json-schema-lite.d.ts +41 -0
- package/dist/ops/json-schema-lite.d.ts.map +1 -0
- package/dist/ops/json-schema-lite.js +119 -0
- package/dist/ops/json-schema-lite.js.map +1 -0
- package/dist/ops/schema-values.d.ts +5 -0
- package/dist/ops/schema-values.d.ts.map +1 -0
- package/dist/ops/schema-values.js +233 -0
- package/dist/ops/schema-values.js.map +1 -0
- package/dist/ops/schema.d.ts +27 -0
- package/dist/ops/schema.d.ts.map +1 -0
- package/dist/ops/schema.js +258 -0
- package/dist/ops/schema.js.map +1 -0
- package/dist/ops/sidecar-ops.d.ts +85 -0
- package/dist/ops/sidecar-ops.d.ts.map +1 -0
- package/dist/ops/sidecar-ops.js +5 -0
- package/dist/ops/sidecar-ops.js.map +1 -0
- package/dist/ops/types.d.ts +400 -0
- package/dist/ops/types.d.ts.map +1 -0
- package/dist/ops/types.js +5 -0
- package/dist/ops/types.js.map +1 -0
- package/dist/ops/units.d.ts +4 -0
- package/dist/ops/units.d.ts.map +1 -0
- package/dist/ops/units.js +75 -0
- package/dist/ops/units.js.map +1 -0
- package/dist/reducer/apply.d.ts +33 -0
- package/dist/reducer/apply.d.ts.map +1 -0
- package/dist/reducer/apply.js +123 -0
- package/dist/reducer/apply.js.map +1 -0
- package/dist/reducer/comment-ops.d.ts +18 -0
- package/dist/reducer/comment-ops.d.ts.map +1 -0
- package/dist/reducer/comment-ops.js +104 -0
- package/dist/reducer/comment-ops.js.map +1 -0
- package/dist/reducer/edit.d.ts +38 -0
- package/dist/reducer/edit.d.ts.map +1 -0
- package/dist/reducer/edit.js +126 -0
- package/dist/reducer/edit.js.map +1 -0
- package/dist/reducer/facet-ops.d.ts +20 -0
- package/dist/reducer/facet-ops.d.ts.map +1 -0
- package/dist/reducer/facet-ops.js +184 -0
- package/dist/reducer/facet-ops.js.map +1 -0
- package/dist/reducer/meta-ops.d.ts +20 -0
- package/dist/reducer/meta-ops.d.ts.map +1 -0
- package/dist/reducer/meta-ops.js +52 -0
- package/dist/reducer/meta-ops.js.map +1 -0
- package/dist/reducer/spec-ops.d.ts +29 -0
- package/dist/reducer/spec-ops.d.ts.map +1 -0
- package/dist/reducer/spec-ops.js +181 -0
- package/dist/reducer/spec-ops.js.map +1 -0
- package/dist/reducer/test-ops.d.ts +15 -0
- package/dist/reducer/test-ops.d.ts.map +1 -0
- package/dist/reducer/test-ops.js +90 -0
- package/dist/reducer/test-ops.js.map +1 -0
- package/dist/reducer/value-ops.d.ts +26 -0
- package/dist/reducer/value-ops.d.ts.map +1 -0
- package/dist/reducer/value-ops.js +173 -0
- package/dist/reducer/value-ops.js.map +1 -0
- package/dist/render/describe.d.ts +20 -0
- package/dist/render/describe.d.ts.map +1 -0
- package/dist/render/describe.js +47 -0
- package/dist/render/describe.js.map +1 -0
- package/dist/revision/index.d.ts +4 -0
- package/dist/revision/index.d.ts.map +1 -0
- package/dist/revision/index.js +7 -0
- package/dist/revision/index.js.map +1 -0
- package/dist/revision/revision.d.ts +79 -0
- package/dist/revision/revision.d.ts.map +1 -0
- package/dist/revision/revision.js +120 -0
- package/dist/revision/revision.js.map +1 -0
- package/dist/revision/sha256.d.ts +3 -0
- package/dist/revision/sha256.d.ts.map +1 -0
- package/dist/revision/sha256.js +69 -0
- package/dist/revision/sha256.js.map +1 -0
- package/dist/revision/verify.d.ts +21 -0
- package/dist/revision/verify.d.ts.map +1 -0
- package/dist/revision/verify.js +51 -0
- package/dist/revision/verify.js.map +1 -0
- package/dist/revision/view.d.ts +36 -0
- package/dist/revision/view.d.ts.map +1 -0
- package/dist/revision/view.js +32 -0
- package/dist/revision/view.js.map +1 -0
- package/dist/sidecar/idsz.d.ts +14 -0
- package/dist/sidecar/idsz.d.ts.map +1 -0
- package/dist/sidecar/idsz.js +58 -0
- package/dist/sidecar/idsz.js.map +1 -0
- package/dist/sidecar/sidecar-schema.d.ts +4 -0
- package/dist/sidecar/sidecar-schema.d.ts.map +1 -0
- package/dist/sidecar/sidecar-schema.js +69 -0
- package/dist/sidecar/sidecar-schema.js.map +1 -0
- package/dist/sidecar/sidecar.d.ts +102 -0
- package/dist/sidecar/sidecar.d.ts.map +1 -0
- package/dist/sidecar/sidecar.js +160 -0
- package/dist/sidecar/sidecar.js.map +1 -0
- package/dist/testing/index.d.ts +6 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +8 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/junit.d.ts +10 -0
- package/dist/testing/junit.d.ts.map +1 -0
- package/dist/testing/junit.js +51 -0
- package/dist/testing/junit.js.map +1 -0
- package/dist/testing/outcome.d.ts +10 -0
- package/dist/testing/outcome.d.ts.map +1 -0
- package/dist/testing/outcome.js +22 -0
- package/dist/testing/outcome.js.map +1 -0
- package/dist/testing/runner.d.ts +72 -0
- package/dist/testing/runner.d.ts.map +1 -0
- package/dist/testing/runner.js +60 -0
- package/dist/testing/runner.js.map +1 -0
- package/dist/testing/types.d.ts +60 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing/types.js +5 -0
- package/dist/testing/types.js.map +1 -0
- package/dist/testing/view.d.ts +31 -0
- package/dist/testing/view.d.ts.map +1 -0
- package/dist/testing/view.js +30 -0
- package/dist/testing/view.js.map +1 -0
- package/dist/uuid.d.ts +39 -0
- package/dist/uuid.d.ts.map +1 -0
- package/dist/uuid.js +84 -0
- package/dist/uuid.js.map +1 -0
- package/package.json +56 -3
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal semantic diff of two IDS documents, for `ifc-lite ids diff`
|
|
3
|
+
* and the MCP `ids_diff` tool.
|
|
4
|
+
*
|
|
5
|
+
* Matching is the re-identification cascade (`reidentify`): specifications
|
|
6
|
+
* by identifier, then name + applicability signature, then similarity;
|
|
7
|
+
* facets within a matched specification the same way. Matched nodes keep
|
|
8
|
+
* one node id, so "changed" is "same node id, different content", and a
|
|
9
|
+
* renamed specification is a change, not a remove plus an add.
|
|
10
|
+
*
|
|
11
|
+
* This is the shell the CLI and MCP surfaces need now. The full engine of
|
|
12
|
+
* IDS-104 (field-level paths inside constraints, a plain-language
|
|
13
|
+
* changelog, three-way merge) supersedes it; when it lands, this module is
|
|
14
|
+
* deleted and the surfaces call that engine instead.
|
|
15
|
+
*/
|
|
16
|
+
import type { IDSDocument } from '@ifc-lite/ids';
|
|
17
|
+
import { type ReidentifyReport } from '../match/reidentify.js';
|
|
18
|
+
export type IdsDiffChange = 'added' | 'removed' | 'changed';
|
|
19
|
+
export interface IdsDiffEntry {
|
|
20
|
+
change: IdsDiffChange;
|
|
21
|
+
node: 'info' | 'spec' | 'facet';
|
|
22
|
+
/** The specification's name (the new one when it was renamed). */
|
|
23
|
+
spec?: string;
|
|
24
|
+
/** XML path of the node: in the new document, or in the old one for `removed`. */
|
|
25
|
+
path: string;
|
|
26
|
+
/** For `changed`: the field that differs (`name`, `cardinality`, `facet`, `optionality`, …). */
|
|
27
|
+
field?: string;
|
|
28
|
+
before?: string;
|
|
29
|
+
after?: string;
|
|
30
|
+
/** One plain-language line. */
|
|
31
|
+
text: string;
|
|
32
|
+
}
|
|
33
|
+
export interface IdsDiff {
|
|
34
|
+
identical: boolean;
|
|
35
|
+
entries: IdsDiffEntry[];
|
|
36
|
+
/** How specifications and facets were paired. */
|
|
37
|
+
matching: ReidentifyReport;
|
|
38
|
+
}
|
|
39
|
+
/** Compare `before` with `after`. Pure; never throws on parsed input. */
|
|
40
|
+
export declare function diffIds(before: IDSDocument, after: IDSDocument): IdsDiff;
|
|
41
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/headless/diff.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,WAAW,EAA+E,MAAM,eAAe,CAAC;AAE9H,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAK3E,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAChC,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,iDAAiD;IACjD,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAkFD,yEAAyE;AACzE,wBAAgB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAsCxE"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { reidentify } from '../match/reidentify.js';
|
|
5
|
+
import { describeFacet } from '../render/describe.js';
|
|
6
|
+
import { studioDocumentFromIds } from './read.js';
|
|
7
|
+
import { lostPaths } from './write.js';
|
|
8
|
+
const INFO_FIELDS = ['title', 'copyright', 'version', 'description', 'author', 'date', 'purpose', 'milestone'];
|
|
9
|
+
function same(a, b) {
|
|
10
|
+
return lostPaths(a, b).length === 0 && lostPaths(b, a).length === 0;
|
|
11
|
+
}
|
|
12
|
+
function cardinality(spec) {
|
|
13
|
+
if (spec.maxOccurs === 0)
|
|
14
|
+
return 'prohibited';
|
|
15
|
+
return (spec.minOccurs ?? 0) > 0 ? 'required' : 'optional';
|
|
16
|
+
}
|
|
17
|
+
function specFields(spec) {
|
|
18
|
+
return {
|
|
19
|
+
name: spec.name,
|
|
20
|
+
identifier: spec.identifier,
|
|
21
|
+
description: spec.description,
|
|
22
|
+
instructions: spec.instructions,
|
|
23
|
+
ifcVersion: spec.ifcVersions.join(' '),
|
|
24
|
+
cardinality: cardinality(spec),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function slots(doc, specIndex, section) {
|
|
28
|
+
const spec = doc.ids.specifications[specIndex];
|
|
29
|
+
const nodes = doc.nodes.specs[specIndex];
|
|
30
|
+
const out = new Map();
|
|
31
|
+
if (section === 'applicability') {
|
|
32
|
+
spec.applicability.facets.forEach((facet, index) => out.set(nodes.applicability[index].id, { facet, index }));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
spec.requirements.forEach((requirement, index) => out.set(nodes.requirements[index].id, { facet: requirement.facet, requirement, index }));
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
function describe(slot, section) {
|
|
40
|
+
return describeFacet(slot.facet, section, (slot.requirement?.optionality ?? 'required'));
|
|
41
|
+
}
|
|
42
|
+
function diffFacets(a, ai, b, bi, out) {
|
|
43
|
+
const spec = b.ids.specifications[bi].name;
|
|
44
|
+
for (const section of ['applicability', 'requirements']) {
|
|
45
|
+
const before = slots(a, ai, section);
|
|
46
|
+
const after = slots(b, bi, section);
|
|
47
|
+
const label = section === 'applicability' ? 'applicability' : 'requirement';
|
|
48
|
+
for (const [id, slot] of after) {
|
|
49
|
+
const path = `specifications[${bi}].${section}[${slot.index}]`;
|
|
50
|
+
const old = before.get(id);
|
|
51
|
+
if (!old) {
|
|
52
|
+
out.push({ change: 'added', node: 'facet', spec, path, text: `${spec}: ${label} added: ${describe(slot, section)}` });
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (!same(old.facet, slot.facet)) {
|
|
56
|
+
const was = describe(old, section);
|
|
57
|
+
const now = describe(slot, section);
|
|
58
|
+
out.push({ change: 'changed', node: 'facet', spec, path, field: 'facet', before: was, after: now, text: `${spec}: ${label} changed: ${was} → ${now}` });
|
|
59
|
+
}
|
|
60
|
+
else if (old.requirement && slot.requirement && old.requirement.optionality !== slot.requirement.optionality) {
|
|
61
|
+
const [was, now] = [old.requirement.optionality, slot.requirement.optionality];
|
|
62
|
+
const what = describeFacet(slot.facet, section);
|
|
63
|
+
out.push({ change: 'changed', node: 'facet', spec, path, field: 'optionality', before: was, after: now, text: `${spec}: ${label} changed from ${was} to ${now}: ${what}` });
|
|
64
|
+
}
|
|
65
|
+
if (old.requirement?.instructions !== slot.requirement?.instructions) {
|
|
66
|
+
out.push({ change: 'changed', node: 'facet', spec, path, field: 'instructions', before: old.requirement?.instructions, after: slot.requirement?.instructions, text: `${spec}: instructions of a requirement changed` });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
for (const [id, slot] of before) {
|
|
70
|
+
if (after.has(id))
|
|
71
|
+
continue;
|
|
72
|
+
const path = `specifications[${ai}].${section}[${slot.index}]`;
|
|
73
|
+
out.push({ change: 'removed', node: 'facet', spec, path, text: `${spec}: ${label} removed: ${describe(slot, section)}` });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** Compare `before` with `after`. Pure; never throws on parsed input. */
|
|
78
|
+
export function diffIds(before, after) {
|
|
79
|
+
const a = studioDocumentFromIds(before);
|
|
80
|
+
const { doc: b, report } = reidentify(a, after);
|
|
81
|
+
const entries = [];
|
|
82
|
+
for (const field of INFO_FIELDS) {
|
|
83
|
+
const [was, now] = [before.info[field], after.info[field]];
|
|
84
|
+
if (was !== now)
|
|
85
|
+
entries.push({ change: 'changed', node: 'info', path: `info.${field}`, field, before: was, after: now, text: `Document ${field} changed from "${was ?? ''}" to "${now ?? ''}"` });
|
|
86
|
+
}
|
|
87
|
+
const indexOfA = new Map(a.nodes.specs.map((s, i) => [s.id, i]));
|
|
88
|
+
b.nodes.specs.forEach((nodes, bi) => {
|
|
89
|
+
const spec = b.ids.specifications[bi];
|
|
90
|
+
const ai = indexOfA.get(nodes.id);
|
|
91
|
+
if (ai === undefined) {
|
|
92
|
+
entries.push({ change: 'added', node: 'spec', spec: spec.name, path: `specifications[${bi}]`, text: `Specification "${spec.name}" added` });
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const was = specFields(a.ids.specifications[ai]);
|
|
96
|
+
const now = specFields(spec);
|
|
97
|
+
for (const field of Object.keys(now)) {
|
|
98
|
+
if (was[field] === now[field])
|
|
99
|
+
continue;
|
|
100
|
+
entries.push({
|
|
101
|
+
change: 'changed', node: 'spec', spec: spec.name, path: `specifications[${bi}]`, field, before: was[field], after: now[field],
|
|
102
|
+
text: field === 'name' ? `Specification "${was.name}" renamed to "${now.name}"` : `${spec.name}: ${field} changed from "${was[field] ?? ''}" to "${now[field] ?? ''}"`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
diffFacets(a, ai, b, bi, entries);
|
|
106
|
+
});
|
|
107
|
+
const removed = new Set(report.specs.removed);
|
|
108
|
+
a.nodes.specs.forEach((nodes, ai) => {
|
|
109
|
+
if (!removed.has(nodes.id))
|
|
110
|
+
return;
|
|
111
|
+
const name = a.ids.specifications[ai].name;
|
|
112
|
+
entries.push({ change: 'removed', node: 'spec', spec: name, path: `specifications[${ai}]`, text: `Specification "${name}" removed` });
|
|
113
|
+
});
|
|
114
|
+
return { identical: entries.length === 0, entries, matching: report };
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/headless/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { StudioDocument } from '../document/types.js';
|
|
2
|
+
import type { Uuid } from '../uuid.js';
|
|
3
|
+
/**
|
|
4
|
+
* A path a person can find in the XML, for node `id`:
|
|
5
|
+
* `specifications[2].requirements[1].baseName`. Headless output prints
|
|
6
|
+
* this next to (or instead of) the node UUID, which means nothing outside
|
|
7
|
+
* the Studio. `undefined` for an id the document does not hold.
|
|
8
|
+
*/
|
|
9
|
+
export declare function nodePath(doc: StudioDocument, id: Uuid): string | undefined;
|
|
10
|
+
//# sourceMappingURL=node-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-path.d.ts","sourceRoot":"","sources":["../../src/headless/node-path.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAS1E"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { locateNode } from '../document/node-index.js';
|
|
5
|
+
/**
|
|
6
|
+
* A path a person can find in the XML, for node `id`:
|
|
7
|
+
* `specifications[2].requirements[1].baseName`. Headless output prints
|
|
8
|
+
* this next to (or instead of) the node UUID, which means nothing outside
|
|
9
|
+
* the Studio. `undefined` for an id the document does not hold.
|
|
10
|
+
*/
|
|
11
|
+
export function nodePath(doc, id) {
|
|
12
|
+
const loc = locateNode(doc, id);
|
|
13
|
+
if (!loc)
|
|
14
|
+
return undefined;
|
|
15
|
+
if (loc.kind === 'document')
|
|
16
|
+
return 'info';
|
|
17
|
+
const spec = `specifications[${loc.specIndex}]`;
|
|
18
|
+
if (loc.kind === 'spec')
|
|
19
|
+
return spec;
|
|
20
|
+
const facet = loc.section === 'applicability' ? `${spec}.applicability[${loc.facetIndex}]` : `${spec}.requirements[${loc.facetIndex}]`;
|
|
21
|
+
// Field names carry the facet type (`property.baseName`); the path already has it.
|
|
22
|
+
return loc.kind === 'constraint' ? `${facet}.${loc.field.slice(loc.field.indexOf('.') + 1)}` : facet;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=node-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-path.js","sourceRoot":"","sources":["../../src/headless/node-path.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAIvD;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAmB,EAAE,EAAQ;IACpD,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAChC,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC;IAC3C,MAAM,IAAI,GAAG,kBAAkB,GAAG,CAAC,SAAS,GAAG,CAAC;IAChD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,KAAK,eAAe,CAAC,CAAC,CAAC,GAAG,IAAI,kBAAkB,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,iBAAiB,GAAG,CAAC,UAAU,GAAG,CAAC;IACvI,mFAAmF;IACnF,OAAO,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AACvG,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading IDS for headless callers (CLI, MCP, SDK, Flow).
|
|
3
|
+
*
|
|
4
|
+
* Headless callers are stateless: the same XML read twice must give the
|
|
5
|
+
* same node ids, or an agent that reads a document, then refers to a node
|
|
6
|
+
* id in its next tool call, addresses nothing. Node ids are therefore
|
|
7
|
+
* derived from the content fingerprint instead of minted from the clock.
|
|
8
|
+
*/
|
|
9
|
+
import { type IDSDocument } from '@ifc-lite/ids';
|
|
10
|
+
import type { StudioDocument } from '../document/types.js';
|
|
11
|
+
/** Wrap a parsed IDS with node ids that depend only on its content. */
|
|
12
|
+
export declare function studioDocumentFromIds(ids: IDSDocument): StudioDocument;
|
|
13
|
+
/**
|
|
14
|
+
* Parse IDS XML into a `StudioDocument` with deterministic node ids.
|
|
15
|
+
* Throws the parser's `IDSParseError` on malformed input.
|
|
16
|
+
*/
|
|
17
|
+
export declare function readStudioDocument(xml: string): StudioDocument;
|
|
18
|
+
/**
|
|
19
|
+
* Accept a `StudioDocument` that crossed a process boundary (an MCP tool
|
|
20
|
+
* argument, a Flow port, a file). Throws an `Error` naming the first
|
|
21
|
+
* problem. This checks the shape and the node index only: content written
|
|
22
|
+
* into the JSON by hand never passed the grounding gate, which is why
|
|
23
|
+
* `writeStudioDocument` audits what it serialises.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseStudioDocument(value: unknown): StudioDocument;
|
|
26
|
+
//# sourceMappingURL=read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/headless/read.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAG3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D,uEAAuE;AACvE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,WAAW,GAAG,cAAc,CAItE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAE9D;AAMD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAgClE"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* Reading IDS for headless callers (CLI, MCP, SDK, Flow).
|
|
6
|
+
*
|
|
7
|
+
* Headless callers are stateless: the same XML read twice must give the
|
|
8
|
+
* same node ids, or an agent that reads a document, then refers to a node
|
|
9
|
+
* id in its next tool call, addresses nothing. Node ids are therefore
|
|
10
|
+
* derived from the content fingerprint instead of minted from the clock.
|
|
11
|
+
*/
|
|
12
|
+
import { parseIDS } from '@ifc-lite/ids';
|
|
13
|
+
import { fromIdsDocument } from '../document/from-ids.js';
|
|
14
|
+
import { verifyNodeIndex } from '../document/node-index.js';
|
|
15
|
+
import { fingerprintIds } from '../sidecar/sidecar.js';
|
|
16
|
+
import { deriveId, isUuid } from '../uuid.js';
|
|
17
|
+
/** Wrap a parsed IDS with node ids that depend only on its content. */
|
|
18
|
+
export function studioDocumentFromIds(ids) {
|
|
19
|
+
const seed = fingerprintIds(ids);
|
|
20
|
+
let n = 0;
|
|
21
|
+
return fromIdsDocument(ids, { newId: () => deriveId(seed, `node:${n++}`) });
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse IDS XML into a `StudioDocument` with deterministic node ids.
|
|
25
|
+
* Throws the parser's `IDSParseError` on malformed input.
|
|
26
|
+
*/
|
|
27
|
+
export function readStudioDocument(xml) {
|
|
28
|
+
return studioDocumentFromIds(parseIDS(xml));
|
|
29
|
+
}
|
|
30
|
+
function isRecord(v) {
|
|
31
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Accept a `StudioDocument` that crossed a process boundary (an MCP tool
|
|
35
|
+
* argument, a Flow port, a file). Throws an `Error` naming the first
|
|
36
|
+
* problem. This checks the shape and the node index only: content written
|
|
37
|
+
* into the JSON by hand never passed the grounding gate, which is why
|
|
38
|
+
* `writeStudioDocument` audits what it serialises.
|
|
39
|
+
*/
|
|
40
|
+
export function parseStudioDocument(value) {
|
|
41
|
+
if (!isRecord(value))
|
|
42
|
+
throw new Error('a Studio document must be a JSON object');
|
|
43
|
+
if (value.schemaVersion !== 1)
|
|
44
|
+
throw new Error(`unsupported Studio document schemaVersion ${String(value.schemaVersion)}`);
|
|
45
|
+
if (!isUuid(value.docId))
|
|
46
|
+
throw new Error('docId must be a UUID');
|
|
47
|
+
const ids = value.ids;
|
|
48
|
+
if (!isRecord(ids) || !isRecord(ids.info) || !Array.isArray(ids.specifications)) {
|
|
49
|
+
throw new Error('ids must hold info and specifications');
|
|
50
|
+
}
|
|
51
|
+
const nodes = value.nodes;
|
|
52
|
+
if (!isRecord(nodes) || !isUuid(nodes.document) || !Array.isArray(nodes.specs)) {
|
|
53
|
+
throw new Error('nodes must hold the document id and one entry per specification');
|
|
54
|
+
}
|
|
55
|
+
if (!isRecord(value.meta))
|
|
56
|
+
throw new Error('meta must be an object');
|
|
57
|
+
for (const [i, spec] of ids.specifications.entries()) {
|
|
58
|
+
if (!isRecord(spec) || !isRecord(spec.applicability) || !Array.isArray(spec.applicability.facets) || !Array.isArray(spec.requirements)) {
|
|
59
|
+
throw new Error(`specification ${i} must hold applicability.facets and requirements`);
|
|
60
|
+
}
|
|
61
|
+
const facets = [...spec.applicability.facets, ...spec.requirements.map((r) => (isRecord(r) ? r.facet : r))];
|
|
62
|
+
if (!facets.every((f) => isRecord(f) && typeof f.type === 'string')) {
|
|
63
|
+
throw new Error(`specification ${i} holds a facet without a type`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
for (const [i, sn] of nodes.specs.entries()) {
|
|
67
|
+
if (!isRecord(sn) || !Array.isArray(sn.applicability) || !Array.isArray(sn.requirements)) {
|
|
68
|
+
throw new Error(`nodes.specs[${i}] must hold applicability and requirements`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// The checks above establish every field `verifyNodeIndex` reads.
|
|
72
|
+
const doc = value;
|
|
73
|
+
const problems = verifyNodeIndex(doc);
|
|
74
|
+
if (problems.length > 0)
|
|
75
|
+
throw new Error(`inconsistent node index: ${problems[0]}`);
|
|
76
|
+
return doc;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/headless/read.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grounding lookups over the gate's schema tables, for agents that author
|
|
3
|
+
* IDS (MCP `ids_schema_search` / `ids_schema_entity` / `ids_schema_pset`).
|
|
4
|
+
* An agent that looks a name up here and then uses it passes the gate,
|
|
5
|
+
* because both read the same tables.
|
|
6
|
+
*/
|
|
7
|
+
import type { IFCVersion } from '@ifc-lite/ids';
|
|
8
|
+
import { type GateContext } from '../gate/context.js';
|
|
9
|
+
export type SchemaKind = 'entity' | 'pset' | 'property' | 'dataType';
|
|
10
|
+
export interface SchemaHit {
|
|
11
|
+
kind: SchemaKind;
|
|
12
|
+
value: string;
|
|
13
|
+
/** 0..1, higher is better. */
|
|
14
|
+
score: number;
|
|
15
|
+
reason?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SchemaSearchOptions {
|
|
18
|
+
/** Restrict to one kind (default: all). */
|
|
19
|
+
kind?: SchemaKind;
|
|
20
|
+
/** Schema version (default IFC4). */
|
|
21
|
+
version?: IFCVersion;
|
|
22
|
+
limit?: number;
|
|
23
|
+
}
|
|
24
|
+
/** Rank schema names close to `query`, best first. */
|
|
25
|
+
export declare function searchSchema(ctx: GateContext, query: string, options?: SchemaSearchOptions): SchemaHit[];
|
|
26
|
+
export interface EntityDescription {
|
|
27
|
+
name: string;
|
|
28
|
+
version: IFCVersion;
|
|
29
|
+
abstract: boolean;
|
|
30
|
+
/** Supertypes, nearest first. */
|
|
31
|
+
ancestors: string[];
|
|
32
|
+
predefinedTypes: string[];
|
|
33
|
+
attributes: string[];
|
|
34
|
+
/** Standard property and quantity sets applicable to the entity or a supertype. */
|
|
35
|
+
propertySets: string[];
|
|
36
|
+
}
|
|
37
|
+
/** The entity as the gate sees it, or `undefined` when the name is not an entity of `version`. */
|
|
38
|
+
export declare function describeEntity(ctx: GateContext, name: string, version?: IFCVersion): EntityDescription | undefined;
|
|
39
|
+
export interface PsetDescription {
|
|
40
|
+
name: string;
|
|
41
|
+
version: IFCVersion;
|
|
42
|
+
applicableEntities: string[];
|
|
43
|
+
properties: {
|
|
44
|
+
name: string;
|
|
45
|
+
kind: string;
|
|
46
|
+
dataType?: string;
|
|
47
|
+
enumeration?: string[];
|
|
48
|
+
}[];
|
|
49
|
+
}
|
|
50
|
+
/** The standard property or quantity set, or `undefined` when `version` has none of that name. */
|
|
51
|
+
export declare function describePset(ctx: GateContext, name: string, version?: IFCVersion): PsetDescription | undefined;
|
|
52
|
+
//# sourceMappingURL=schema-lookup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-lookup.d.ts","sourceRoot":"","sources":["../../src/headless/schema-lookup.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAoB,KAAK,WAAW,EAAsB,MAAM,oBAAoB,CAAC;AAG5F,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,CAAC;AAErE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,2CAA2C;IAC3C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,qCAAqC;IACrC,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAoBD,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,SAAS,EAAE,CAc5G;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,iCAAiC;IACjC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,mFAAmF;IACnF,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,kGAAkG;AAClG,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,UAAmB,GAAG,iBAAiB,GAAG,SAAS,CAmB1H;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,UAAU,CAAC;IACpB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;CACzF;AAED,kGAAkG;AAClG,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,UAAmB,GAAG,eAAe,GAAG,SAAS,CActH"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { inheritanceChain } from '../gate/context.js';
|
|
5
|
+
import { rankCandidates } from '../gate/rank.js';
|
|
6
|
+
const MAX_SETS_IN_REASON = 3;
|
|
7
|
+
function pools(t) {
|
|
8
|
+
return {
|
|
9
|
+
entity: t.entityNames,
|
|
10
|
+
pset: t.psetNames,
|
|
11
|
+
property: [...t.psetsByProperty.keys()],
|
|
12
|
+
dataType: [...t.dataTypes.values()].map((d) => d.name),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function propertyReason(t, name) {
|
|
16
|
+
const sets = t.psetsByProperty.get(name);
|
|
17
|
+
if (!sets?.length)
|
|
18
|
+
return undefined;
|
|
19
|
+
const more = sets.length > MAX_SETS_IN_REASON ? ` and ${sets.length - MAX_SETS_IN_REASON} more` : '';
|
|
20
|
+
return `in ${sets.slice(0, MAX_SETS_IN_REASON).join(', ')}${more}`;
|
|
21
|
+
}
|
|
22
|
+
/** Rank schema names close to `query`, best first. */
|
|
23
|
+
export function searchSchema(ctx, query, options = {}) {
|
|
24
|
+
const t = ctx.tables[options.version ?? 'IFC4'];
|
|
25
|
+
const limit = options.limit ?? 10;
|
|
26
|
+
const all = pools(t);
|
|
27
|
+
const kinds = options.kind ? [options.kind] : ['entity', 'pset', 'property', 'dataType'];
|
|
28
|
+
const hits = [];
|
|
29
|
+
for (const kind of kinds) {
|
|
30
|
+
for (const c of rankCandidates(query, all[kind], { limit })) {
|
|
31
|
+
const reason = kind === 'property' ? propertyReason(t, c.value) : undefined;
|
|
32
|
+
hits.push(reason ? { kind, value: c.value, score: c.score, reason } : { kind, value: c.value, score: c.score });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
hits.sort((a, b) => b.score - a.score || a.value.localeCompare(b.value));
|
|
36
|
+
return hits.slice(0, limit);
|
|
37
|
+
}
|
|
38
|
+
/** The entity as the gate sees it, or `undefined` when the name is not an entity of `version`. */
|
|
39
|
+
export function describeEntity(ctx, name, version = 'IFC4') {
|
|
40
|
+
const t = ctx.tables[version];
|
|
41
|
+
const chain = inheritanceChain(t, name);
|
|
42
|
+
if (chain.length === 0)
|
|
43
|
+
return undefined;
|
|
44
|
+
const [self, ...ancestors] = chain;
|
|
45
|
+
const names = new Set(chain.map((e) => e.name.toUpperCase()));
|
|
46
|
+
const propertySets = [...t.psets.values()]
|
|
47
|
+
.filter((p) => p.applicableEntities.some((a) => names.has(a.toUpperCase())))
|
|
48
|
+
.map((p) => p.name)
|
|
49
|
+
.sort();
|
|
50
|
+
return {
|
|
51
|
+
name: self.name,
|
|
52
|
+
version,
|
|
53
|
+
abstract: self.abstract,
|
|
54
|
+
ancestors: ancestors.map((e) => e.name),
|
|
55
|
+
predefinedTypes: [...self.predefinedTypes],
|
|
56
|
+
attributes: [...self.attributes],
|
|
57
|
+
propertySets,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** The standard property or quantity set, or `undefined` when `version` has none of that name. */
|
|
61
|
+
export function describePset(ctx, name, version = 'IFC4') {
|
|
62
|
+
const pset = ctx.tables[version].psets.get(name);
|
|
63
|
+
if (!pset)
|
|
64
|
+
return undefined;
|
|
65
|
+
return {
|
|
66
|
+
name: pset.name,
|
|
67
|
+
version,
|
|
68
|
+
applicableEntities: [...pset.applicableEntities],
|
|
69
|
+
properties: pset.properties.map((p) => ({
|
|
70
|
+
name: p.name,
|
|
71
|
+
kind: p.kind,
|
|
72
|
+
...(p.dataType ? { dataType: p.dataType } : {}),
|
|
73
|
+
...(p.enumeration ? { enumeration: [...p.enumeration] } : {}),
|
|
74
|
+
})),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=schema-lookup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-lookup.js","sourceRoot":"","sources":["../../src/headless/schema-lookup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Writing and formatting IDS for headless callers, with a losslessness guard.
|
|
3
|
+
*
|
|
4
|
+
* The XML writer is injected (`IdsWriter`). The CLI, MCP and SDK pass the
|
|
5
|
+
* full IDS 1.0 writer, `writeIdsXml` from `@ifc-lite/ids` (ADR-005, P-01).
|
|
6
|
+
* Whatever the writer, a
|
|
7
|
+
* headless write never returns XML that reads back with less content than
|
|
8
|
+
* it was given: the output is parsed again and every value the input
|
|
9
|
+
* defines must survive. Anything that does not is reported as `lost`, so
|
|
10
|
+
* `ids fmt --write` cannot silently delete an author or a restriction.
|
|
11
|
+
*/
|
|
12
|
+
import { type IDSDocument } from '@ifc-lite/ids';
|
|
13
|
+
import type { StudioDocument } from '../document/types.js';
|
|
14
|
+
/** Serialise an IDS document as IDS 1.0 XML. May throw to refuse. */
|
|
15
|
+
export type IdsWriter = (ids: IDSDocument) => string;
|
|
16
|
+
export interface WriteFailure {
|
|
17
|
+
ok: false;
|
|
18
|
+
reason: 'parse' | 'refused' | 'lossy';
|
|
19
|
+
message: string;
|
|
20
|
+
/** For `lossy`: paths whose value did not survive the round trip. */
|
|
21
|
+
lost?: string[];
|
|
22
|
+
}
|
|
23
|
+
export type WriteOutcome = {
|
|
24
|
+
ok: true;
|
|
25
|
+
xml: string;
|
|
26
|
+
} | WriteFailure;
|
|
27
|
+
export type FormatOutcome = {
|
|
28
|
+
ok: true;
|
|
29
|
+
xml: string;
|
|
30
|
+
changed: boolean;
|
|
31
|
+
} | WriteFailure;
|
|
32
|
+
/**
|
|
33
|
+
* Paths where `source` defines a value that `written` does not reproduce.
|
|
34
|
+
* Values only `written` has (defaults a parser fills in) are not losses.
|
|
35
|
+
*/
|
|
36
|
+
export declare function lostPaths(source: unknown, written: unknown, path?: string, out?: string[]): string[];
|
|
37
|
+
/** Write `ids` and prove the XML reads back with the same content. */
|
|
38
|
+
export declare function writeIdsChecked(ids: IDSDocument, write: IdsWriter): WriteOutcome;
|
|
39
|
+
/** Serialise a Studio document (its `ids` content; the sidecar travels separately). */
|
|
40
|
+
export declare function writeStudioDocument(doc: StudioDocument, write: IdsWriter): WriteOutcome;
|
|
41
|
+
/**
|
|
42
|
+
* Canonical formatting: parse, write, verify. `changed` compares the
|
|
43
|
+
* canonical XML with the input byte for byte (after CRLF → LF).
|
|
44
|
+
*/
|
|
45
|
+
export declare function formatIds(xml: string, write: IdsWriter): FormatOutcome;
|
|
46
|
+
//# sourceMappingURL=write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/headless/write.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,qEAAqE;AACrE,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,MAAM,CAAC;AAErD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,YAAY,CAAC;AAOvF;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,SAAK,EAAE,GAAG,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CAwBpG;AAMD,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,GAAG,YAAY,CAuBhF;AAED,uFAAuF;AACvF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,GAAG,YAAY,CAEvF;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,aAAa,CAUtE"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* Writing and formatting IDS for headless callers, with a losslessness guard.
|
|
6
|
+
*
|
|
7
|
+
* The XML writer is injected (`IdsWriter`). The CLI, MCP and SDK pass the
|
|
8
|
+
* full IDS 1.0 writer, `writeIdsXml` from `@ifc-lite/ids` (ADR-005, P-01).
|
|
9
|
+
* Whatever the writer, a
|
|
10
|
+
* headless write never returns XML that reads back with less content than
|
|
11
|
+
* it was given: the output is parsed again and every value the input
|
|
12
|
+
* defines must survive. Anything that does not is reported as `lost`, so
|
|
13
|
+
* `ids fmt --write` cannot silently delete an author or a restriction.
|
|
14
|
+
*/
|
|
15
|
+
import { parseIDS } from '@ifc-lite/ids';
|
|
16
|
+
/** Fields that record source spelling or node identity, not content. */
|
|
17
|
+
function ignored(key) {
|
|
18
|
+
return key === 'id' || key.endsWith('Raw') || key.startsWith('raw');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Paths where `source` defines a value that `written` does not reproduce.
|
|
22
|
+
* Values only `written` has (defaults a parser fills in) are not losses.
|
|
23
|
+
*/
|
|
24
|
+
export function lostPaths(source, written, path = '', out = []) {
|
|
25
|
+
if (source === undefined || source === null)
|
|
26
|
+
return out;
|
|
27
|
+
if (Array.isArray(source)) {
|
|
28
|
+
if (!Array.isArray(written)) {
|
|
29
|
+
out.push(path || '(root)');
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
source.forEach((item, i) => lostPaths(item, written[i], `${path}[${i}]`, out));
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
if (typeof source === 'object') {
|
|
36
|
+
if (typeof written !== 'object' || written === null || Array.isArray(written)) {
|
|
37
|
+
out.push(path || '(root)');
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
const w = written;
|
|
41
|
+
for (const [key, value] of Object.entries(source)) {
|
|
42
|
+
if (ignored(key))
|
|
43
|
+
continue;
|
|
44
|
+
lostPaths(value, w[key], path ? `${path}.${key}` : key, out);
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
if (source !== written)
|
|
49
|
+
out.push(path || '(root)');
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
function message(err) {
|
|
53
|
+
return err instanceof Error ? err.message : String(err);
|
|
54
|
+
}
|
|
55
|
+
/** Write `ids` and prove the XML reads back with the same content. */
|
|
56
|
+
export function writeIdsChecked(ids, write) {
|
|
57
|
+
let xml;
|
|
58
|
+
try {
|
|
59
|
+
xml = write(ids);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
return { ok: false, reason: 'refused', message: message(err) };
|
|
63
|
+
}
|
|
64
|
+
let reread;
|
|
65
|
+
try {
|
|
66
|
+
reread = parseIDS(xml);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
return { ok: false, reason: 'refused', message: `the writer produced XML that does not parse: ${message(err)}` };
|
|
70
|
+
}
|
|
71
|
+
const lost = lostPaths(ids, reread);
|
|
72
|
+
if (lost.length > 0) {
|
|
73
|
+
return {
|
|
74
|
+
ok: false,
|
|
75
|
+
reason: 'lossy',
|
|
76
|
+
message: `the IDS writer cannot represent ${lost.length} value(s) without loss`,
|
|
77
|
+
lost,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return { ok: true, xml };
|
|
81
|
+
}
|
|
82
|
+
/** Serialise a Studio document (its `ids` content; the sidecar travels separately). */
|
|
83
|
+
export function writeStudioDocument(doc, write) {
|
|
84
|
+
return writeIdsChecked(doc.ids, write);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Canonical formatting: parse, write, verify. `changed` compares the
|
|
88
|
+
* canonical XML with the input byte for byte (after CRLF → LF).
|
|
89
|
+
*/
|
|
90
|
+
export function formatIds(xml, write) {
|
|
91
|
+
let ids;
|
|
92
|
+
try {
|
|
93
|
+
ids = parseIDS(xml);
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
return { ok: false, reason: 'parse', message: message(err) };
|
|
97
|
+
}
|
|
98
|
+
const out = writeIdsChecked(ids, write);
|
|
99
|
+
if (!out.ok)
|
|
100
|
+
return out;
|
|
101
|
+
return { ok: true, xml: out.xml, changed: xml.replace(/\r\n/g, '\n') !== out.xml };
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=write.js.map
|