@graview/core 0.1.29 → 0.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/dist/app-places.d.ts +2 -2
- package/dist/app-places.d.ts.map +1 -1
- package/dist/app-places.js +53 -3
- package/dist/app-places.js.map +1 -1
- package/dist/app.d.ts +24 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js.map +1 -1
- package/dist/arrange.d.ts +3 -1
- package/dist/arrange.d.ts.map +1 -1
- package/dist/arrange.js +3 -1
- package/dist/arrange.js.map +1 -1
- package/dist/arrangement.d.ts +18 -0
- package/dist/arrangement.d.ts.map +1 -1
- package/dist/arrangement.js +34 -0
- package/dist/arrangement.js.map +1 -1
- package/dist/arranging.d.ts.map +1 -1
- package/dist/arranging.js +17 -6
- package/dist/arranging.js.map +1 -1
- package/dist/blocks.d.ts +1 -1
- package/dist/blocks.d.ts.map +1 -1
- package/dist/catalog.d.ts +312 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +459 -0
- package/dist/catalog.js.map +1 -0
- package/dist/cli/check/brand.d.ts.map +1 -1
- package/dist/cli/check/brand.js +29 -1
- package/dist/cli/check/brand.js.map +1 -1
- package/dist/cli/check/lenses.d.ts.map +1 -1
- package/dist/cli/check/lenses.js +6 -1
- package/dist/cli/check/lenses.js.map +1 -1
- package/dist/cli/check/relations.d.ts +23 -0
- package/dist/cli/check/relations.d.ts.map +1 -1
- package/dist/cli/check/relations.js +53 -3
- package/dist/cli/check/relations.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +32 -0
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/describe.d.ts.map +1 -1
- package/dist/cli/describe.js +27 -4
- package/dist/cli/describe.js.map +1 -1
- package/dist/cli/doctor.d.ts +18 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +58 -5
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/document-schema.d.ts +2 -0
- package/dist/cli/document-schema.d.ts.map +1 -1
- package/dist/cli/document-schema.js +163 -5
- package/dist/cli/document-schema.js.map +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/types.js +6 -1
- package/dist/cli/types.js.map +1 -1
- package/dist/conformance/fixtures.d.ts.map +1 -1
- package/dist/conformance/fixtures.js +165 -0
- package/dist/conformance/fixtures.js.map +1 -1
- package/dist/coverage-words.d.ts +18 -0
- package/dist/coverage-words.d.ts.map +1 -0
- package/dist/coverage-words.js +18 -0
- package/dist/coverage-words.js.map +1 -0
- package/dist/days.d.ts +7 -1
- package/dist/days.d.ts.map +1 -1
- package/dist/days.js +10 -4
- package/dist/days.js.map +1 -1
- package/dist/document/act-findings.d.ts.map +1 -1
- package/dist/document/act-findings.js +21 -3
- package/dist/document/act-findings.js.map +1 -1
- package/dist/document/blocks.d.ts +20 -7
- package/dist/document/blocks.d.ts.map +1 -1
- package/dist/document/blocks.js +85 -15
- package/dist/document/blocks.js.map +1 -1
- package/dist/document/brand-check.d.ts +5 -0
- package/dist/document/brand-check.d.ts.map +1 -1
- package/dist/document/brand-check.js +16 -2
- package/dist/document/brand-check.js.map +1 -1
- package/dist/document/compile-checked.d.ts.map +1 -1
- package/dist/document/compile-checked.js +12 -4
- package/dist/document/compile-checked.js.map +1 -1
- package/dist/document/compile.d.ts +0 -2
- package/dist/document/compile.d.ts.map +1 -1
- package/dist/document/compile.js +19 -17
- package/dist/document/compile.js.map +1 -1
- package/dist/document/compiled.d.ts +2 -0
- package/dist/document/compiled.d.ts.map +1 -1
- package/dist/document/compiled.js +51 -12
- package/dist/document/compiled.js.map +1 -1
- package/dist/document/computed-values.d.ts +3 -0
- package/dist/document/computed-values.d.ts.map +1 -1
- package/dist/document/computed-values.js +12 -2
- package/dist/document/computed-values.js.map +1 -1
- package/dist/document/connection-findings.d.ts +6 -0
- package/dist/document/connection-findings.d.ts.map +1 -0
- package/dist/document/connection-findings.js +110 -0
- package/dist/document/connection-findings.js.map +1 -0
- package/dist/document/connection-spec.d.ts +38 -0
- package/dist/document/connection-spec.d.ts.map +1 -0
- package/dist/document/connection-spec.js +43 -0
- package/dist/document/connection-spec.js.map +1 -0
- package/dist/document/describe-coverage.d.ts +3 -0
- package/dist/document/describe-coverage.d.ts.map +1 -1
- package/dist/document/describe-coverage.js +12 -5
- package/dist/document/describe-coverage.js.map +1 -1
- package/dist/document/describe-place.d.ts.map +1 -1
- package/dist/document/describe-place.js +3 -1
- package/dist/document/describe-place.js.map +1 -1
- package/dist/document/diff.d.ts.map +1 -1
- package/dist/document/diff.js +39 -8
- package/dist/document/diff.js.map +1 -1
- package/dist/document/edit.d.ts +1 -1
- package/dist/document/edit.d.ts.map +1 -1
- package/dist/document/edit.js +251 -15
- package/dist/document/edit.js.map +1 -1
- package/dist/document/expr/evaluate.d.ts +25 -0
- package/dist/document/expr/evaluate.d.ts.map +1 -1
- package/dist/document/expr/evaluate.js +38 -0
- package/dist/document/expr/evaluate.js.map +1 -1
- package/dist/document/format-words.d.ts +1 -1
- package/dist/document/format-words.d.ts.map +1 -1
- package/dist/document/format-words.js +3 -1
- package/dist/document/format-words.js.map +1 -1
- package/dist/document/framework-path.d.ts +11 -0
- package/dist/document/framework-path.d.ts.map +1 -0
- package/dist/document/framework-path.js +122 -0
- package/dist/document/framework-path.js.map +1 -0
- package/dist/document/index.d.ts +2 -2
- package/dist/document/index.d.ts.map +1 -1
- package/dist/document/index.js +1 -1
- package/dist/document/index.js.map +1 -1
- package/dist/document/linked-findings.d.ts +5 -0
- package/dist/document/linked-findings.d.ts.map +1 -0
- package/dist/document/linked-findings.js +100 -0
- package/dist/document/linked-findings.js.map +1 -0
- package/dist/document/migrate.d.ts.map +1 -1
- package/dist/document/migrate.js +4 -1
- package/dist/document/migrate.js.map +1 -1
- package/dist/document/policy-words.d.ts +2 -0
- package/dist/document/policy-words.d.ts.map +1 -1
- package/dist/document/policy-words.js +16 -1
- package/dist/document/policy-words.js.map +1 -1
- package/dist/document/right-names.d.ts +10 -0
- package/dist/document/right-names.d.ts.map +1 -0
- package/dist/document/right-names.js +57 -0
- package/dist/document/right-names.js.map +1 -0
- package/dist/document/rules.d.ts.map +1 -1
- package/dist/document/rules.js +13 -5
- package/dist/document/rules.js.map +1 -1
- package/dist/document/schema.d.ts +86 -8
- package/dist/document/schema.d.ts.map +1 -1
- package/dist/document/schema.js +64 -7
- package/dist/document/schema.js.map +1 -1
- package/dist/document/template-parse.d.ts.map +1 -1
- package/dist/document/template-parse.js +36 -3
- package/dist/document/template-parse.js.map +1 -1
- package/dist/document/template.d.ts +13 -1
- package/dist/document/template.d.ts.map +1 -1
- package/dist/document/template.js +29 -9
- package/dist/document/template.js.map +1 -1
- package/dist/document/to-document.d.ts.map +1 -1
- package/dist/document/to-document.js +12 -0
- package/dist/document/to-document.js.map +1 -1
- package/dist/document/views.d.ts +36 -4
- package/dist/document/views.d.ts.map +1 -1
- package/dist/document/views.js +64 -21
- package/dist/document/views.js.map +1 -1
- package/dist/document.schema.json +1184 -51
- package/dist/field-sight.js +2 -2
- package/dist/field-sight.js.map +1 -1
- package/dist/forms.d.ts +1 -0
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +2 -0
- package/dist/forms.js.map +1 -1
- package/dist/graph/archived.d.ts +9 -0
- package/dist/graph/archived.d.ts.map +1 -1
- package/dist/graph/archived.js +9 -0
- package/dist/graph/archived.js.map +1 -1
- package/dist/graph/diff.d.ts +16 -0
- package/dist/graph/diff.d.ts.map +1 -1
- package/dist/graph/diff.js +18 -0
- package/dist/graph/diff.js.map +1 -1
- package/dist/graph/graph.d.ts.map +1 -1
- package/dist/graph/graph.js +5 -8
- package/dist/graph/graph.js.map +1 -1
- package/dist/grid-sort.d.ts +20 -0
- package/dist/grid-sort.d.ts.map +1 -0
- package/dist/grid-sort.js +58 -0
- package/dist/grid-sort.js.map +1 -0
- package/dist/history.d.ts +88 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +146 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +18 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/installation.d.ts +1 -1
- package/dist/kind-list.d.ts +78 -0
- package/dist/kind-list.d.ts.map +1 -0
- package/dist/kind-list.js +176 -0
- package/dist/kind-list.js.map +1 -0
- package/dist/linked.d.ts +95 -0
- package/dist/linked.d.ts.map +1 -0
- package/dist/linked.js +181 -0
- package/dist/linked.js.map +1 -0
- package/dist/mutations/arg-shape.d.ts +2 -0
- package/dist/mutations/arg-shape.d.ts.map +1 -1
- package/dist/mutations/arg-shape.js +4 -0
- package/dist/mutations/arg-shape.js.map +1 -1
- package/dist/mutations/derive-edits.d.ts.map +1 -1
- package/dist/mutations/derive-edits.js +89 -38
- package/dist/mutations/derive-edits.js.map +1 -1
- package/dist/mutations/derived-names.d.ts +3 -1
- package/dist/mutations/derived-names.d.ts.map +1 -1
- package/dist/mutations/derived-names.js +5 -3
- package/dist/mutations/derived-names.js.map +1 -1
- package/dist/mutations/edit-start.d.ts +28 -0
- package/dist/mutations/edit-start.d.ts.map +1 -0
- package/dist/mutations/edit-start.js +24 -0
- package/dist/mutations/edit-start.js.map +1 -0
- package/dist/mutations/form.d.ts +14 -0
- package/dist/mutations/form.d.ts.map +1 -1
- package/dist/mutations/form.js +5 -1
- package/dist/mutations/form.js.map +1 -1
- package/dist/mutations/kept-arguments.js +2 -2
- package/dist/mutations/kept-arguments.js.map +1 -1
- package/dist/mutations/types.d.ts +1 -1
- package/dist/mutations/types.d.ts.map +1 -1
- package/dist/navigate.d.ts +13 -0
- package/dist/navigate.d.ts.map +1 -0
- package/dist/navigate.js +13 -0
- package/dist/navigate.js.map +1 -0
- package/dist/ops/digest.d.ts +33 -0
- package/dist/ops/digest.d.ts.map +1 -0
- package/dist/ops/digest.js +47 -0
- package/dist/ops/digest.js.map +1 -0
- package/dist/ops/lineage.d.ts +13 -0
- package/dist/ops/lineage.d.ts.map +1 -1
- package/dist/ops/lineage.js +6 -4
- package/dist/ops/lineage.js.map +1 -1
- package/dist/ops/log.d.ts +6 -0
- package/dist/ops/log.d.ts.map +1 -1
- package/dist/ops/log.js +19 -12
- package/dist/ops/log.js.map +1 -1
- package/dist/ops/suggestions.d.ts +26 -0
- package/dist/ops/suggestions.d.ts.map +1 -0
- package/dist/ops/suggestions.js +21 -0
- package/dist/ops/suggestions.js.map +1 -0
- package/dist/ops/tidying.d.ts +48 -0
- package/dist/ops/tidying.d.ts.map +1 -0
- package/dist/ops/tidying.js +84 -0
- package/dist/ops/tidying.js.map +1 -0
- package/dist/ops/types.d.ts +17 -0
- package/dist/ops/types.d.ts.map +1 -1
- package/dist/ops/undo.d.ts.map +1 -1
- package/dist/ops/undo.js +10 -0
- package/dist/ops/undo.js.map +1 -1
- package/dist/past.d.ts +35 -0
- package/dist/past.d.ts.map +1 -0
- package/dist/past.js +173 -0
- package/dist/past.js.map +1 -0
- package/dist/permissions/policy.d.ts +8 -1
- package/dist/permissions/policy.d.ts.map +1 -1
- package/dist/permissions/policy.js +20 -5
- package/dist/permissions/policy.js.map +1 -1
- package/dist/places.d.ts +6 -2
- package/dist/places.d.ts.map +1 -1
- package/dist/places.js +48 -3
- package/dist/places.js.map +1 -1
- package/dist/scaffold/agents.d.ts.map +1 -1
- package/dist/scaffold/agents.js +13 -0
- package/dist/scaffold/agents.js.map +1 -1
- package/dist/scaffold/project.d.ts.map +1 -1
- package/dist/scaffold/project.js +8 -0
- package/dist/scaffold/project.js.map +1 -1
- package/dist/scaffold/ui.d.ts.map +1 -1
- package/dist/scaffold/ui.js +18 -5
- package/dist/scaffold/ui.js.map +1 -1
- package/dist/schema/app-address.d.ts +5 -0
- package/dist/schema/app-address.d.ts.map +1 -0
- package/dist/schema/app-address.js +10 -0
- package/dist/schema/app-address.js.map +1 -0
- package/dist/schema/app-link.d.ts +1 -4
- package/dist/schema/app-link.d.ts.map +1 -1
- package/dist/schema/app-link.js +5 -7
- package/dist/schema/app-link.js.map +1 -1
- package/dist/schema/define-node.d.ts +16 -0
- package/dist/schema/define-node.d.ts.map +1 -1
- package/dist/schema/define-node.js +6 -0
- package/dist/schema/define-node.js.map +1 -1
- package/dist/schema/files.d.ts +8 -0
- package/dist/schema/files.d.ts.map +1 -1
- package/dist/schema/files.js.map +1 -1
- package/dist/schema/json-schema.d.ts.map +1 -1
- package/dist/schema/json-schema.js +19 -1
- package/dist/schema/json-schema.js.map +1 -1
- package/dist/schema/linked-field.d.ts +6 -0
- package/dist/schema/linked-field.d.ts.map +1 -0
- package/dist/schema/linked-field.js +34 -0
- package/dist/schema/linked-field.js.map +1 -0
- package/dist/schema/linked-reads.d.ts +20 -0
- package/dist/schema/linked-reads.d.ts.map +1 -0
- package/dist/schema/linked-reads.js +69 -0
- package/dist/schema/linked-reads.js.map +1 -0
- package/dist/schema/linked-schema.d.ts +5 -0
- package/dist/schema/linked-schema.d.ts.map +1 -0
- package/dist/schema/linked-schema.js +9 -0
- package/dist/schema/linked-schema.js.map +1 -0
- package/dist/schema/linked.d.ts +147 -0
- package/dist/schema/linked.d.ts.map +1 -0
- package/dist/schema/linked.js +151 -0
- package/dist/schema/linked.js.map +1 -0
- package/dist/schema/reading.d.ts.map +1 -1
- package/dist/schema/reading.js +82 -27
- package/dist/schema/reading.js.map +1 -1
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +11 -4
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/types.d.ts +17 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +30 -2
- package/dist/search.js.map +1 -1
- package/dist/seat-of.d.ts +9 -0
- package/dist/seat-of.d.ts.map +1 -0
- package/dist/seat-of.js +14 -0
- package/dist/seat-of.js.map +1 -0
- package/dist/seen.d.ts +0 -12
- package/dist/seen.d.ts.map +1 -1
- package/dist/seen.js +5 -0
- package/dist/seen.js.map +1 -1
- package/dist/store.d.ts +58 -0
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +96 -11
- package/dist/store.js.map +1 -1
- package/dist/subscription-shape.d.ts +135 -0
- package/dist/subscription-shape.d.ts.map +1 -0
- package/dist/subscription-shape.js +55 -0
- package/dist/subscription-shape.js.map +1 -0
- package/dist/subscriptions.d.ts +68 -0
- package/dist/subscriptions.d.ts.map +1 -0
- package/dist/subscriptions.js +425 -0
- package/dist/subscriptions.js.map +1 -0
- package/dist/sync/connection-filter.d.ts +12 -0
- package/dist/sync/connection-filter.d.ts.map +1 -0
- package/dist/sync/connection-filter.js +34 -0
- package/dist/sync/connection-filter.js.map +1 -0
- package/dist/sync/connection.d.ts +65 -0
- package/dist/sync/connection.d.ts.map +1 -0
- package/dist/sync/connection.js +148 -0
- package/dist/sync/connection.js.map +1 -0
- package/dist/sync/engine.d.ts.map +1 -1
- package/dist/sync/engine.js +4 -0
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/google-calendar.d.ts +27 -2
- package/dist/sync/google-calendar.d.ts.map +1 -1
- package/dist/sync/google-calendar.js +55 -14
- package/dist/sync/google-calendar.js.map +1 -1
- package/dist/sync/index.d.ts +3 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +1 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/theme/derive.d.ts +16 -0
- package/dist/theme/derive.d.ts.map +1 -1
- package/dist/theme/derive.js +14 -0
- package/dist/theme/derive.js.map +1 -1
- package/dist/theme/marks.d.ts +19 -2
- package/dist/theme/marks.d.ts.map +1 -1
- package/dist/theme/marks.js +67 -2
- package/dist/theme/marks.js.map +1 -1
- package/dist/theme/types.d.ts +7 -2
- package/dist/theme/types.d.ts.map +1 -1
- package/dist/theme/types.js.map +1 -1
- package/dist/tidying.d.ts +62 -0
- package/dist/tidying.d.ts.map +1 -0
- package/dist/tidying.js +131 -0
- package/dist/tidying.js.map +1 -0
- package/dist/typed.d.ts +1 -1
- package/dist/typed.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/via.d.ts.map +1 -1
- package/dist/via.js +2 -1
- package/dist/via.js.map +1 -1
- package/dist/views/address.d.ts +13 -0
- package/dist/views/address.d.ts.map +1 -0
- package/dist/views/address.js +29 -0
- package/dist/views/address.js.map +1 -0
- package/dist/views/types.d.ts +52 -3
- package/dist/views/types.d.ts.map +1 -1
- package/dist/views/types.js +4 -3
- package/dist/views/types.js.map +1 -1
- package/dist/wall-time.d.ts +60 -0
- package/dist/wall-time.d.ts.map +1 -0
- package/dist/wall-time.js +111 -0
- package/dist/wall-time.js.map +1 -0
- package/dist/when-typed.d.ts +15 -0
- package/dist/when-typed.d.ts.map +1 -0
- package/dist/when-typed.js +158 -0
- package/dist/when-typed.js.map +1 -0
- package/dist/words.d.ts +6 -1
- package/dist/words.d.ts.map +1 -1
- package/dist/words.js +6 -1
- package/dist/words.js.map +1 -1
- package/package.json +29 -1
package/dist/document/edit.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DERIVED_ACTS, derivedActOf, derivedActsOf, givenWhenNeverArchived } from "../mutations/derived-names.js";
|
|
1
|
+
import { DERIVED_ACTS, derivedActOf, derivedActsOf, givenWhenNeverArchived, givenWhenNeverTidied } from "../mutations/derived-names.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { ExprSyntaxError, parseExpr } from "./expr/parse.js";
|
|
4
4
|
import { printExpr } from "./expr/print.js";
|
|
@@ -16,10 +16,12 @@ import { farEnd } from "./far-end.js";
|
|
|
16
16
|
import { ActSpec, EDGE_NAME, EdgeSpec, FIELD_NAME, FIELD_TYPES, FieldSpec, GrantSpec, KindSpec, NAME, RuleSpec, SightSpec, } from "./schema.js";
|
|
17
17
|
import { SHIPPED_LENSES, isShippedLens, SHIPPED_LENS_NAMES } from "../places.js";
|
|
18
18
|
import { placeSlug } from "../views/types.js";
|
|
19
|
+
import { documentListFields, kindListFindings, kindListWords, listGroup, listSort, sortTypeOfDocumentField } from "../kind-list.js";
|
|
19
20
|
import { computedOf, validateComputed } from "./computed.js";
|
|
20
21
|
import { parseTemplate, templateBraces, TemplateError } from "./template-parse.js";
|
|
21
22
|
import { validateViews, VIEW_SLOTS } from "./views.js";
|
|
22
|
-
import { brandFindings } from "./brand-check.js";
|
|
23
|
+
import { brandFindings, emojiIconSentence } from "./brand-check.js";
|
|
24
|
+
import { emojiOf } from "../theme/marks.js";
|
|
23
25
|
import { canonicalize } from "./canonical.js";
|
|
24
26
|
import { quotedAtTheEnd } from "./quote.js";
|
|
25
27
|
import { isRecord as isObject, respellDocument } from "./respell.js";
|
|
@@ -29,7 +31,7 @@ import { accentProblem } from "../theme/accent.js";
|
|
|
29
31
|
import { pageFieldFindings, pageNames, renamedOnPage, withoutOnPage } from "./page-fields.js";
|
|
30
32
|
import { capitalize, listed as listOf } from "../capital.js";
|
|
31
33
|
import { quoted } from "./quote.js";
|
|
32
|
-
import { FIRST_GRANT, FIRST_SIGHT, grantBody, grantGone, grantSentence, NO_GRANT_LEFT, NO_SIGHT_LEFT, peopleKinds, peopleSentence, archivesSentence, nounWords, pluralWords as pluralOf, sightGone, sightSentence, sightWords, whoWords } from "./policy-words.js";
|
|
34
|
+
import { FIRST_GRANT, FIRST_SIGHT, grantBody, grantGone, grantSentence, NO_GRANT_LEFT, NO_SIGHT_LEFT, peopleKinds, peopleSentence, archivesSentence, tidyingSentence, nounWords, pluralWords as pluralOf, sightGone, sightSentence, sightWords, whoWords } from "./policy-words.js";
|
|
33
35
|
/** The ops, for tool schemas and the guide. */
|
|
34
36
|
export const EDIT_OPS = [
|
|
35
37
|
"add-kind",
|
|
@@ -62,11 +64,13 @@ export const EDIT_OPS = [
|
|
|
62
64
|
"set-page-fields",
|
|
63
65
|
"add-lens",
|
|
64
66
|
"remove-lens",
|
|
67
|
+
"set-lens-hidden",
|
|
65
68
|
"set-home",
|
|
66
69
|
"arrange-pages",
|
|
67
70
|
"set-computed",
|
|
68
71
|
"set-people",
|
|
69
72
|
"set-archives",
|
|
73
|
+
"set-tidying",
|
|
70
74
|
"add-grant",
|
|
71
75
|
"remove-grant",
|
|
72
76
|
"add-sight",
|
|
@@ -77,6 +81,10 @@ const KEYWORDS = new Set(["and", "or", "not", "in", "where", "true", "false", "n
|
|
|
77
81
|
const MAX_EDITS = 50;
|
|
78
82
|
// ── shapes ─────────────────────────────────────────────────────────────────
|
|
79
83
|
const kindName = z.string().regex(NAME, 'kind names are lower-case words joined by hyphens, like "guest-list"');
|
|
84
|
+
const listKey = z.string().min(1).max(120);
|
|
85
|
+
const listDirection = z.enum(["asc", "desc"]).optional();
|
|
86
|
+
const listSortShape = z.union([listKey, z.object({ by: listKey, direction: listDirection, then: z.union([listKey, z.object({ by: listKey, direction: listDirection }).strict()]).optional() }).strict()]);
|
|
87
|
+
const listGroupShape = z.union([listKey, z.object({ by: listKey, order: z.array(z.string().min(1).max(80)).max(40).optional(), closed: z.array(z.string().min(1).max(80)).max(40).optional() }).strict()]);
|
|
80
88
|
const fieldName = z.string().regex(FIELD_NAME, 'field names are one word or camelCase, like "dueDate"');
|
|
81
89
|
const edgeName = z.string().regex(EDGE_NAME, 'relation names are one camelCase word, like "tendedBy"');
|
|
82
90
|
const actName = z.string().regex(NAME, 'act names are lower-case words joined by hyphens, like "mark-paid"');
|
|
@@ -111,7 +119,7 @@ const SHAPES = {
|
|
|
111
119
|
locale: z.union([z.string(), z.null()]).optional(),
|
|
112
120
|
// The rest of the brand (FR-124, FR-125): each as the document holds it, null to clear it.
|
|
113
121
|
logo: z.union([z.string().min(1), z.object({ src: z.string().min(1), alt: z.string().min(1).max(120).optional() }).strict(), z.null()]).optional(),
|
|
114
|
-
favicon: z.union([z.string().min(1), z.null()]).optional(),
|
|
122
|
+
favicon: z.union([z.string().min(1), z.object({ emoji: z.string() }).strict(), z.null()]).optional(),
|
|
115
123
|
typography: z.union([z.object({ display: z.union([z.string().min(1).max(200), z.null()]).optional(), body: z.union([z.string().min(1).max(200), z.null()]).optional(), mono: z.union([z.string().min(1).max(200), z.null()]).optional() }).strict(), z.null()]).optional(),
|
|
116
124
|
shape: z.union([z.object({ radius: z.union([z.number().min(0).max(32), z.null()]).optional(), density: z.union([z.number().min(0.75).max(1.5), z.null()]).optional() }).strict(), z.null()]).optional(),
|
|
117
125
|
accents: z.union([z.record(z.string(), z.union([z.number().min(0).max(360), z.null()])), z.null()]).optional(),
|
|
@@ -142,11 +150,15 @@ const SHAPES = {
|
|
|
142
150
|
on: kindName.optional(),
|
|
143
151
|
bindings: z.record(z.string(), z.unknown()).optional(),
|
|
144
152
|
options: z.record(z.string(), z.unknown()).optional(),
|
|
153
|
+
// False: the place's page leaves off the forms that begin its kind.
|
|
154
|
+
create: z.boolean().optional(),
|
|
145
155
|
at: z.number().int().min(0).optional(),
|
|
146
156
|
replace: lensTitle.optional(),
|
|
147
157
|
})
|
|
148
158
|
.strict(),
|
|
149
159
|
"remove-lens": z.object({ op: z.literal("remove-lens"), title: lensTitle, on: kindName.optional() }).strict(),
|
|
160
|
+
// A lens kept off the bar's places, the page list and the home's gallery, still reached by its address, a link or navigate.
|
|
161
|
+
"set-lens-hidden": z.object({ op: z.literal("set-lens-hidden"), title: lensTitle, on: kindName.optional(), hidden: z.boolean() }).strict(),
|
|
150
162
|
"set-home": z.object({ op: z.literal("set-home"), blocks: z.union([z.array(z.unknown()).min(1), z.null()]) }).strict(),
|
|
151
163
|
"arrange-pages": z
|
|
152
164
|
.object({
|
|
@@ -159,6 +171,10 @@ const SHAPES = {
|
|
|
159
171
|
pages: z.union([z.string().min(1).max(40), z.null()]).optional(),
|
|
160
172
|
// What a kind's list offers to filter by: `{ "request": ["status", "became.stage"] }`; null or [] gives a kind back its derived filters.
|
|
161
173
|
filters: z.record(kindName, z.union([z.array(z.string().min(1).max(120)).max(40), z.null()])).optional(),
|
|
174
|
+
// The order a kind's list opens in: `{ "feature": { "by": "score", "direction": "desc", "then": "label" } }` or a key; null gives it back its own.
|
|
175
|
+
sort: z.record(kindName, z.union([listSortShape, z.null()])).optional(),
|
|
176
|
+
// How a kind's list opens grouped: `{ "request": { "by": "status", "order": [...], "closed": ["done"] } }` or a field; null opens it ungrouped.
|
|
177
|
+
group: z.record(kindName, z.union([listGroupShape, z.null()])).optional(),
|
|
162
178
|
// The scene's word as a chat or a tool written before 0.1.17 sends it (FR-132's key, RESPELLED as `scene`).
|
|
163
179
|
overview: z.union([z.string().min(1).max(40), z.null()]).optional(),
|
|
164
180
|
})
|
|
@@ -177,6 +193,8 @@ const SHAPES = {
|
|
|
177
193
|
"set-people": z.object({ op: z.literal("set-people"), kind: kindName, people: z.boolean() }).strict(),
|
|
178
194
|
// Whether a kind's records are archived and merged, or only kept and removed (FR-173).
|
|
179
195
|
"set-archives": z.object({ op: z.literal("set-archives"), kind: kindName, archives: z.boolean() }).strict(),
|
|
196
|
+
// What the app's own actor may do on its own to a kind, or to one relation of it (`@graview/core/tidying`).
|
|
197
|
+
"set-tidying": z.object({ op: z.literal("set-tidying"), kind: kindName, relation: z.optional(z.string()), tidying: z.enum(["never", "no-links", "allowed"]) }).strict(),
|
|
180
198
|
"add-grant": z.object({ op: z.literal("add-grant") }).passthrough(),
|
|
181
199
|
"remove-grant": z.object({ op: z.literal("remove-grant") }).passthrough(),
|
|
182
200
|
"add-sight": z.object({ op: z.literal("add-sight") }).passthrough(),
|
|
@@ -500,7 +518,7 @@ class Editor {
|
|
|
500
518
|
const emptyPart = ["typography", "shape", "accents"].find((key) => isObject(e[key]) && Object.keys(e[key]).length === 0);
|
|
501
519
|
if (emptyPart)
|
|
502
520
|
return this.fail(i, emptyPart, `${emptyPart} names no part to set; name one, or give null to clear all of it`);
|
|
503
|
-
const judged = brandFindings({ ...(typeof e.logo === "string" || isObject(e.logo) ? { logo: e.logo } : {}), ...(typeof e.favicon === "string" ? { favicon: e.favicon } : {}), ...(isObject(e.typography) ? { typography: Object.fromEntries(Object.entries(e.typography).filter(([, v]) => typeof v === "string")) } : {}) }, { at, ...(this.options.fonts ? { fonts: this.options.fonts } : {}) });
|
|
521
|
+
const judged = brandFindings({ ...(typeof e.logo === "string" || isObject(e.logo) ? { logo: e.logo } : {}), ...(typeof e.favicon === "string" || isObject(e.favicon) ? { favicon: e.favicon } : {}), ...(isObject(e.typography) ? { typography: Object.fromEntries(Object.entries(e.typography).filter(([, v]) => typeof v === "string")) } : {}) }, { at, ...(this.options.fonts ? { fonts: this.options.fonts } : {}) });
|
|
504
522
|
if (judged.length > 0)
|
|
505
523
|
return void this.findings.push(...judged);
|
|
506
524
|
if (e.accent === null) {
|
|
@@ -558,6 +576,8 @@ class Editor {
|
|
|
558
576
|
const alt = (mark) => (isObject(mark) && typeof mark["alt"] === "string" ? mark["alt"] : undefined);
|
|
559
577
|
if (e[key] === null)
|
|
560
578
|
this.said.push(`The app has no ${what}.`);
|
|
579
|
+
else if (key === "favicon" && emojiOf(e[key]) !== undefined)
|
|
580
|
+
this.said.push(emojiIconSentence(emojiOf(e[key]), brand["logo"] !== undefined));
|
|
561
581
|
else if (was === undefined)
|
|
562
582
|
this.said.push(`The app gets a ${what}.`);
|
|
563
583
|
else if (canonicalize(was) === canonicalize(e[key]))
|
|
@@ -831,6 +851,8 @@ class Editor {
|
|
|
831
851
|
return this.addLens(i, e);
|
|
832
852
|
case "remove-lens":
|
|
833
853
|
return this.removeLens(i, e);
|
|
854
|
+
case "set-lens-hidden":
|
|
855
|
+
return this.setLensHidden(i, e);
|
|
834
856
|
case "set-home":
|
|
835
857
|
return this.setHome(i, e.blocks);
|
|
836
858
|
case "arrange-pages":
|
|
@@ -841,6 +863,8 @@ class Editor {
|
|
|
841
863
|
return this.setPeople(i, e);
|
|
842
864
|
case "set-archives":
|
|
843
865
|
return this.setArchives(i, e);
|
|
866
|
+
case "set-tidying":
|
|
867
|
+
return this.setTidying(i, e);
|
|
844
868
|
case "add-grant":
|
|
845
869
|
case "remove-grant":
|
|
846
870
|
case "add-sight":
|
|
@@ -971,7 +995,8 @@ class Editor {
|
|
|
971
995
|
return;
|
|
972
996
|
was = lenses[at];
|
|
973
997
|
}
|
|
974
|
-
|
|
998
|
+
// A lens drawn anew in another's place stays off the lists if that one was.
|
|
999
|
+
const lens = { name, title: e.title, ...(e.on !== undefined ? { on: e.on } : {}), ...(e.bindings !== undefined ? { bindings: e.bindings } : {}), ...(e.options !== undefined ? { options: e.options } : {}), ...(was?.["hidden"] === true ? { hidden: true } : {}), ...(e.create === false ? { create: false } : {}) };
|
|
975
1000
|
// A title is an address: one lens a title on a kind.
|
|
976
1001
|
const clash = lenses.findIndex((other, index) => index !== at && isObject(other) && typeof other["title"] === "string" && placeSlug(other["title"]) === placeSlug(e.title) && (e.on === undefined || other["on"] === undefined || other["on"] === e.on));
|
|
977
1002
|
if (clash >= 0)
|
|
@@ -993,8 +1018,9 @@ class Editor {
|
|
|
993
1018
|
return;
|
|
994
1019
|
const over = lens.on ?? kindsBound(lens)[0];
|
|
995
1020
|
const where = over ? `, over ${pluralWords(this.doc, over)}` : "";
|
|
1021
|
+
const formless = lens.create === false ? "; its page offers no form to add one" : "";
|
|
996
1022
|
if (!was) {
|
|
997
|
-
this.said.push(`A lens "${e.title}" is added${where}.`);
|
|
1023
|
+
this.said.push(`A lens "${e.title}" is added${where}${formless}.`);
|
|
998
1024
|
return;
|
|
999
1025
|
}
|
|
1000
1026
|
const retitled = was["title"] !== e.title;
|
|
@@ -1035,6 +1061,31 @@ class Editor {
|
|
|
1035
1061
|
}
|
|
1036
1062
|
return true;
|
|
1037
1063
|
}
|
|
1064
|
+
/**
|
|
1065
|
+
* A LENS KEPT OFF THE LISTS, or put back on them: still a place at its
|
|
1066
|
+
* address, reached by a link or `navigate`, but not offered by the bar,
|
|
1067
|
+
* the page list or the home's gallery. A lens a custom home links to.
|
|
1068
|
+
*/
|
|
1069
|
+
setLensHidden(i, e) {
|
|
1070
|
+
const index = this.lensIndex(i, e.title, e.on);
|
|
1071
|
+
if (index < 0)
|
|
1072
|
+
return;
|
|
1073
|
+
const lens = this.doc.lenses[index];
|
|
1074
|
+
const title = String(lens["title"]);
|
|
1075
|
+
const primary = Array.isArray(this.doc.pages?.primary) ? this.doc.pages.primary : [];
|
|
1076
|
+
if (e.hidden && primary.some((word) => namesLens(word, title))) {
|
|
1077
|
+
return this.fail(i, "hidden", `pages.primary stands "${title}" on the bar, so it cannot be kept off the lists`, 'take it out of "primary" with arrange-pages first');
|
|
1078
|
+
}
|
|
1079
|
+
const was = lens["hidden"] === true;
|
|
1080
|
+
if (e.hidden)
|
|
1081
|
+
lens["hidden"] = true;
|
|
1082
|
+
else
|
|
1083
|
+
delete lens["hidden"];
|
|
1084
|
+
if (was === e.hidden)
|
|
1085
|
+
this.said.push(e.hidden ? `The lens "${title}" was already kept off the lists.` : `The lens "${title}" was already listed.`);
|
|
1086
|
+
else
|
|
1087
|
+
this.said.push(e.hidden ? `The lens "${title}" is kept off the bar and the page list; a link or navigate still reaches it.` : `The lens "${title}" is listed on the bar and the page list again.`);
|
|
1088
|
+
}
|
|
1038
1089
|
removeLens(i, e) {
|
|
1039
1090
|
const index = this.lensIndex(i, e.title, e.on);
|
|
1040
1091
|
if (index < 0)
|
|
@@ -1046,8 +1097,20 @@ class Editor {
|
|
|
1046
1097
|
// `overview` is the scene's word as 0.1.15 and 0.1.16 took it (FR-134): read as `scene`, which wins when both are said.
|
|
1047
1098
|
const { overview, ...rest } = given;
|
|
1048
1099
|
const e = rest.scene === undefined && overview !== undefined ? { ...rest, scene: overview } : rest;
|
|
1049
|
-
if (e.order === undefined && e.hide === undefined && e.first === undefined && e.scene === undefined && e.pages === undefined && e.primary === undefined && e.filters === undefined)
|
|
1050
|
-
return this.fail(i, "", 'arrange-pages says at least one of "order", "hide", "first", "primary", "scene", "pages" or "
|
|
1100
|
+
if (e.order === undefined && e.hide === undefined && e.first === undefined && e.scene === undefined && e.pages === undefined && e.primary === undefined && e.filters === undefined && e.sort === undefined && e.group === undefined)
|
|
1101
|
+
return this.fail(i, "", 'arrange-pages says at least one of "order", "hide", "first", "primary", "scene", "pages", "filters", "sort" or "group"');
|
|
1102
|
+
// A list's order and grouping are judged as the checker judges them, each refusal its sentence.
|
|
1103
|
+
for (const part of ["sort", "group"]) {
|
|
1104
|
+
for (const [kind, spec] of Object.entries((e[part] ?? {}))) {
|
|
1105
|
+
if (!this.doc.kinds[kind])
|
|
1106
|
+
return this.fail(i, `${part}.${kind}`, `"${kind}" is not a kind this app has; it has ${Object.keys(this.doc.kinds).join(", ")}`);
|
|
1107
|
+
if (spec === null)
|
|
1108
|
+
continue;
|
|
1109
|
+
const [finding] = kindListFindings(kind, { [part]: spec }, documentListFields(this.doc.kinds[kind]), `${part}.${kind}`);
|
|
1110
|
+
if (finding)
|
|
1111
|
+
return this.fail(i, finding.path.replace(new RegExp(`^${part}\\.${kind}\\.${part}`), `${part}.${kind}`), finding.message.replace(/\.$/, ""), finding.fix.replace(/\.$/, ""));
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1051
1114
|
for (const [kind, keys] of Object.entries((e.filters ?? {}))) {
|
|
1052
1115
|
if (!this.doc.kinds[kind])
|
|
1053
1116
|
return this.fail(i, `filters.${kind}`, `"${kind}" is not a kind this app has; it has ${Object.keys(this.doc.kinds).join(", ")}`);
|
|
@@ -1135,23 +1198,133 @@ class Editor {
|
|
|
1135
1198
|
said.push(`the switch calls the ${face} "${pages[face]}"`);
|
|
1136
1199
|
}
|
|
1137
1200
|
}
|
|
1138
|
-
|
|
1201
|
+
// Each kind's list keeps what this edit does not say: its filters, its order, its grouping.
|
|
1202
|
+
const listOfKind = (kind, part, value) => {
|
|
1139
1203
|
const lists = (pages.lists ??= {});
|
|
1140
|
-
|
|
1204
|
+
const list = (lists[kind] ??= {});
|
|
1205
|
+
if (value === null)
|
|
1206
|
+
delete list[part];
|
|
1207
|
+
else
|
|
1208
|
+
list[part] = value;
|
|
1209
|
+
if (Object.keys(list).length === 0)
|
|
1141
1210
|
delete lists[kind];
|
|
1211
|
+
if (Object.keys(lists).length === 0)
|
|
1212
|
+
delete pages.lists;
|
|
1213
|
+
};
|
|
1214
|
+
for (const [kind, keys] of Object.entries((e.filters ?? {}))) {
|
|
1215
|
+
if (keys === null || keys.length === 0) {
|
|
1216
|
+
listOfKind(kind, "filters", null);
|
|
1142
1217
|
said.push(`the list of ${pluralWords(this.doc, kind)} offers its own filters again`);
|
|
1143
1218
|
}
|
|
1144
1219
|
else {
|
|
1145
|
-
|
|
1220
|
+
listOfKind(kind, "filters", [...keys]);
|
|
1146
1221
|
said.push(`the list of ${pluralWords(this.doc, kind)} filters by ${listOf(keys.map((key) => `"${key}"`))}`);
|
|
1147
1222
|
}
|
|
1148
|
-
|
|
1149
|
-
|
|
1223
|
+
}
|
|
1224
|
+
for (const part of ["sort", "group"]) {
|
|
1225
|
+
for (const [kind, spec] of Object.entries((e[part] ?? {}))) {
|
|
1226
|
+
listOfKind(kind, part, spec === null ? null : clone(spec));
|
|
1227
|
+
const plural = pluralWords(this.doc, kind);
|
|
1228
|
+
if (spec === null)
|
|
1229
|
+
said.push(part === "sort" ? `the list of ${plural} opens in its own order again` : `the list of ${plural} opens ungrouped again`);
|
|
1230
|
+
else
|
|
1231
|
+
said.push(`the list of ${plural} opens ${kindListWords({ [part]: spec }, this.listKeyType(kind))[part]}`);
|
|
1232
|
+
}
|
|
1150
1233
|
}
|
|
1151
1234
|
if (Object.keys(pages).length === 0)
|
|
1152
1235
|
delete this.doc.pages;
|
|
1153
1236
|
this.said.push(`${capitalize(listOf(said))}.`);
|
|
1154
1237
|
}
|
|
1238
|
+
/**
|
|
1239
|
+
* A KIND'S LIST FOLLOWS ITS FIELDS. Its order and grouping name a field
|
|
1240
|
+
* renamed by its new name; one gone (or a computed field no longer worked
|
|
1241
|
+
* out) lets go of the part that named it — a tiebreak, the order, the
|
|
1242
|
+
* grouping — and says so. A list left saying nothing is unsaid.
|
|
1243
|
+
*/
|
|
1244
|
+
listsFollow(kind, from, to) {
|
|
1245
|
+
const list = this.doc.pages?.lists?.[kind];
|
|
1246
|
+
if (!list)
|
|
1247
|
+
return [];
|
|
1248
|
+
const out = [];
|
|
1249
|
+
const sort = listSort(list.sort);
|
|
1250
|
+
if (sort && (sort.by === from || sort.then?.by === from)) {
|
|
1251
|
+
if (to !== undefined) {
|
|
1252
|
+
if (typeof list.sort === "string")
|
|
1253
|
+
list.sort = to;
|
|
1254
|
+
else {
|
|
1255
|
+
if (list.sort.by === from)
|
|
1256
|
+
list.sort.by = to;
|
|
1257
|
+
if (list.sort.then === from)
|
|
1258
|
+
list.sort.then = to;
|
|
1259
|
+
else if (isObject(list.sort.then) && list.sort.then["by"] === from)
|
|
1260
|
+
list.sort.then.by = to;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
else if (sort.by === from)
|
|
1264
|
+
delete list.sort;
|
|
1265
|
+
else
|
|
1266
|
+
delete list.sort.then;
|
|
1267
|
+
out.push(`the ${kind} list's order`);
|
|
1268
|
+
}
|
|
1269
|
+
if (listGroup(list.group)?.by === from) {
|
|
1270
|
+
if (to === undefined)
|
|
1271
|
+
delete list.group;
|
|
1272
|
+
else if (typeof list.group === "string")
|
|
1273
|
+
list.group = to;
|
|
1274
|
+
else
|
|
1275
|
+
list.group.by = to;
|
|
1276
|
+
out.push(`the ${kind} list's grouping`);
|
|
1277
|
+
}
|
|
1278
|
+
this.listsTidied(kind);
|
|
1279
|
+
return out;
|
|
1280
|
+
}
|
|
1281
|
+
/** A field retyped or a choice dropped: the list's order and grouping keep what still holds, and let go of what does not. */
|
|
1282
|
+
listsHold(kind, removedOptions = []) {
|
|
1283
|
+
const list = this.doc.pages?.lists?.[kind];
|
|
1284
|
+
if (!list)
|
|
1285
|
+
return [];
|
|
1286
|
+
const out = [];
|
|
1287
|
+
if (isObject(list.group) && removedOptions.length > 0) {
|
|
1288
|
+
for (const part of ["order", "closed"]) {
|
|
1289
|
+
if (!Array.isArray(list.group[part]))
|
|
1290
|
+
continue;
|
|
1291
|
+
const kept = list.group[part].filter((value) => !removedOptions.includes(value));
|
|
1292
|
+
if (kept.length === list.group[part].length)
|
|
1293
|
+
continue;
|
|
1294
|
+
if (kept.length > 0)
|
|
1295
|
+
list.group[part] = kept;
|
|
1296
|
+
else
|
|
1297
|
+
delete list.group[part];
|
|
1298
|
+
if (!out.includes(`the ${kind} list's grouping`))
|
|
1299
|
+
out.push(`the ${kind} list's grouping`);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
for (const finding of kindListFindings(kind, list, documentListFields(this.doc.kinds[kind]))) {
|
|
1303
|
+
const part = finding.path.slice(`pages.lists.${kind}.`.length).startsWith("sort") ? "sort" : "group";
|
|
1304
|
+
if (list[part] === undefined)
|
|
1305
|
+
continue;
|
|
1306
|
+
delete list[part];
|
|
1307
|
+
out.push(`the ${kind} list's ${part === "sort" ? "order" : "grouping"}`);
|
|
1308
|
+
}
|
|
1309
|
+
this.listsTidied(kind);
|
|
1310
|
+
return out;
|
|
1311
|
+
}
|
|
1312
|
+
listsTidied(kind) {
|
|
1313
|
+
const lists = this.doc.pages?.lists;
|
|
1314
|
+
if (!lists)
|
|
1315
|
+
return;
|
|
1316
|
+
if (lists[kind] && Object.keys(lists[kind]).length === 0)
|
|
1317
|
+
delete lists[kind];
|
|
1318
|
+
if (Object.keys(lists).length === 0)
|
|
1319
|
+
delete this.doc.pages.lists;
|
|
1320
|
+
if (Object.keys(this.doc.pages).length === 0)
|
|
1321
|
+
delete this.doc.pages;
|
|
1322
|
+
}
|
|
1323
|
+
/** What a key of a kind's list reads as, for the words its order is said in: a computed field is a number. */
|
|
1324
|
+
listKeyType(kind) {
|
|
1325
|
+
const spec = this.doc.kinds[kind];
|
|
1326
|
+
return (key) => (spec?.computed?.[key] !== undefined ? "number" : sortTypeOfDocumentField(spec?.fields?.[key]?.type));
|
|
1327
|
+
}
|
|
1155
1328
|
/** What a kind's list may be filtered by: its fields, its relations either way, `is`, and a choice at a relation's single far kind. */
|
|
1156
1329
|
filterKeys(kind) {
|
|
1157
1330
|
const kinds = this.doc.kinds;
|
|
@@ -1287,6 +1460,51 @@ class Editor {
|
|
|
1287
1460
|
this.toolsMoved.add(`archive-${e.kind}, unarchive-${e.kind} and merge-${e.kind} ${e.archives ? "are offered" : "are gone"}`);
|
|
1288
1461
|
this.said.push(archivesSentence(this.doc.kinds, e.kind, e.archives, already));
|
|
1289
1462
|
}
|
|
1463
|
+
/**
|
|
1464
|
+
* WHAT THE APP'S OWN ACTOR MAY DO ON ITS OWN (`@graview/core/tidying`):
|
|
1465
|
+
* a kind never tidied, or never linked automatically, or tidied again; a
|
|
1466
|
+
* relation never made or broken automatically, or tidied again. A kind
|
|
1467
|
+
* never tidied is given no leave-alone-<kind> or allow-tidying-<kind>,
|
|
1468
|
+
* which a grant may not then name.
|
|
1469
|
+
*/
|
|
1470
|
+
setTidying(i, e) {
|
|
1471
|
+
const spec = this.kind(i, e.kind);
|
|
1472
|
+
if (!spec)
|
|
1473
|
+
return;
|
|
1474
|
+
const tidying = e.tidying;
|
|
1475
|
+
if (e.relation !== undefined) {
|
|
1476
|
+
const relation = spec.edges?.[e.relation];
|
|
1477
|
+
if (!relation)
|
|
1478
|
+
return this.failAs("edit", i, "relation", `${e.kind} has no relation "${e.relation}"; it has ${Object.keys(spec.edges ?? {}).join(", ") || "none"}`);
|
|
1479
|
+
if (tidying === "no-links")
|
|
1480
|
+
return this.failAs("edit", i, "tidying", `a relation is tidied or never ("never"); "no-links" is said of a kind`, `{"op": "set-tidying", "kind": "${e.kind}", "relation": "${e.relation}", "tidying": "never"}`);
|
|
1481
|
+
const already = (relation.tidying === "never") === (tidying === "never");
|
|
1482
|
+
if (tidying === "never")
|
|
1483
|
+
relation.tidying = "never";
|
|
1484
|
+
else
|
|
1485
|
+
delete relation.tidying;
|
|
1486
|
+
this.said.push(tidyingSentence(this.doc.kinds, e.kind, e.relation, tidying, already));
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
const was = spec.tidying ?? "allowed";
|
|
1490
|
+
const already = was === tidying;
|
|
1491
|
+
if (tidying === "never" && !already) {
|
|
1492
|
+
// A grant that names leave-alone-<kind> or allow-tidying-<kind> would name an act the app no longer has.
|
|
1493
|
+
const gone = new Set(["leave-alone", "allow-tidying"].map((verb) => `${verb}-${e.kind}`).filter((act) => !this.doc.acts?.[act]));
|
|
1494
|
+
const grant = (this.doc.policy?.grants ?? []).find((g) => Array.isArray(g.mutations) && g.mutations.some((m) => gone.has(m)));
|
|
1495
|
+
if (grant) {
|
|
1496
|
+
const named = grant.mutations.filter((m) => gone.has(m));
|
|
1497
|
+
return this.failAs("grant-unknown-mutation", i, "tidying", `a grant names ${listOf(named.map((m) => `"${m}"`))}, which ${pluralOf(this.doc.kinds, e.kind)} would no longer have`, `{"op": "remove-grant", "roles": ${JSON.stringify(grant.roles)}, "mutations": ${JSON.stringify(grant.mutations)}} first, in the same change`);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
if (tidying === "allowed")
|
|
1501
|
+
delete spec.tidying;
|
|
1502
|
+
else
|
|
1503
|
+
spec.tidying = tidying;
|
|
1504
|
+
if (!already && (was === "never" || tidying === "never"))
|
|
1505
|
+
this.toolsMoved.add(`leave-alone-${e.kind} and allow-tidying-${e.kind} ${tidying === "never" ? "are gone" : "are offered"}`);
|
|
1506
|
+
this.said.push(tidyingSentence(this.doc.kinds, e.kind, undefined, tidying, already));
|
|
1507
|
+
}
|
|
1290
1508
|
/** A grant or a sight as the document holds one, or undefined having said why not. */
|
|
1291
1509
|
policyPart(i, e, sight) {
|
|
1292
1510
|
const { op: _op, ...rest } = e;
|
|
@@ -1322,7 +1540,7 @@ class Editor {
|
|
|
1322
1540
|
if (!sight && part.mutations !== "*") {
|
|
1323
1541
|
for (const [n, act] of part.mutations.entries()) {
|
|
1324
1542
|
const derived = derivedActOf(act);
|
|
1325
|
-
if (this.doc.acts?.[act] || (derived && this.doc.kinds[derived.kind] && (this.doc.kinds[derived.kind].archives !== false || givenWhenNeverArchived(derived.act))))
|
|
1543
|
+
if (this.doc.acts?.[act] || (derived && this.doc.kinds[derived.kind] && (this.doc.kinds[derived.kind].archives !== false || givenWhenNeverArchived(derived.act)) && (this.doc.kinds[derived.kind].tidying !== "never" || givenWhenNeverTidied(derived.act))))
|
|
1326
1544
|
continue;
|
|
1327
1545
|
return this.failAs("grant-act", i, `mutations.${n}`, `"${act}" is not an act this app has`, `one of ${[...Object.keys(this.doc.acts ?? {}), ...Object.keys(this.doc.kinds).flatMap(derivedActsOf)].join(", ")}`);
|
|
1328
1546
|
}
|
|
@@ -1455,6 +1673,13 @@ class Editor {
|
|
|
1455
1673
|
spec.plural = e.plural;
|
|
1456
1674
|
else if (spec.plural && (spec.plural === `${words(from)}s` || spec.plural === `${from}s`))
|
|
1457
1675
|
spec.plural = `${words(to)}s`;
|
|
1676
|
+
// Its list's filters, order and grouping follow it.
|
|
1677
|
+
const lists = this.doc.pages?.lists;
|
|
1678
|
+
if (lists?.[from] !== undefined && lists[to] === undefined) {
|
|
1679
|
+
lists[to] = lists[from];
|
|
1680
|
+
delete lists[from];
|
|
1681
|
+
touched.push(`its list`);
|
|
1682
|
+
}
|
|
1458
1683
|
// Where the app opens, when it named the kind by its plural, follows the plural (FR-80).
|
|
1459
1684
|
const pluralNow = spec.plural ?? `${words(to)}s`;
|
|
1460
1685
|
if (typeof this.doc.pages?.first === "string" && placeSlug(this.doc.pages.first) === placeSlug(pluralWas) && placeSlug(pluralWas) !== placeSlug(pluralNow)) {
|
|
@@ -1675,6 +1900,7 @@ class Editor {
|
|
|
1675
1900
|
spec.page = renamedOnPage(spec.page, field, to);
|
|
1676
1901
|
touched.push(`${kind}'s page`);
|
|
1677
1902
|
}
|
|
1903
|
+
touched.push(...this.listsFollow(kind, field, to));
|
|
1678
1904
|
for (const x of this.fills) {
|
|
1679
1905
|
if (x.kind === kind && x.field === field)
|
|
1680
1906
|
x.field = to;
|
|
@@ -1722,6 +1948,10 @@ class Editor {
|
|
|
1722
1948
|
else if (f.default !== undefined)
|
|
1723
1949
|
f.default = coerce(f.default, was, f);
|
|
1724
1950
|
const said = f.format && f.format !== "markdown" ? formatWords(f, this.doc.brand) : undefined;
|
|
1951
|
+
// A list grouped by a choice that is no longer one opens ungrouped, and says so.
|
|
1952
|
+
const held = this.listsHold(e.kind);
|
|
1953
|
+
if (held.length > 0)
|
|
1954
|
+
this.said.push(`${capitalize(listOf(held))} ${held.length === 1 ? "goes" : "go"} back to the list's own, since ${e.field} is no longer ${was === "enum" ? "a choice" : `a ${was}`}.`);
|
|
1725
1955
|
if (was === e.type && e.type === "text")
|
|
1726
1956
|
this.said.push(`${e.kind}'s ${e.field} ${e.format === "markdown" ? "is now written in Markdown, drawn as prose on the record's page" : "is drawn as written, not as Markdown"}; its values are kept.`);
|
|
1727
1957
|
else
|
|
@@ -1815,6 +2045,9 @@ class Editor {
|
|
|
1815
2045
|
delete f.default;
|
|
1816
2046
|
out.push("has no default now");
|
|
1817
2047
|
}
|
|
2048
|
+
const held = this.listsHold(e.kind, remove);
|
|
2049
|
+
if (held.length > 0)
|
|
2050
|
+
out.push(`${listOf(held)} ${held.length === 1 ? "lets" : "let"} go of ${remove.length === 1 ? "it" : "them"}`);
|
|
1818
2051
|
// An act that sets a dropped option cannot stand.
|
|
1819
2052
|
for (const [name, act] of Object.entries(this.doc.acts ?? {})) {
|
|
1820
2053
|
for (const t of setTargets(act, this.doc))
|
|
@@ -2283,6 +2516,9 @@ class Editor {
|
|
|
2283
2516
|
dropMentions(r, worked = false) {
|
|
2284
2517
|
const doc = this.doc;
|
|
2285
2518
|
const gone = [];
|
|
2519
|
+
// A kind's list ordered or grouped by it lets that go (a stored field removed, a computed one no longer worked out).
|
|
2520
|
+
if (r.t === "field")
|
|
2521
|
+
gone.push(...this.listsFollow(r.kind, r.from, undefined));
|
|
2286
2522
|
for (const [kind, spec] of Object.entries(doc.kinds)) {
|
|
2287
2523
|
for (const key of ["label", "describe"]) {
|
|
2288
2524
|
if (templateMentions(doc, spec[key], new Set([kind]), r)) {
|