Documentation
¶
Overview ¶
Package rules holds the individual SemanticRule implementations that fire PRISM_SPEC_* error codes.
Index ¶
- type AggCompat
- type AnimationEasingKnown
- type AnimationKeyPresent
- type AnimationKeyUnique
- type ChannelForMark
- type CompositeMarkEncoding
- type ConditionSelectionRef
- type ConditionTestParses
- type ConditionValueOrBinding
- type DatasetRef
- type ExpressionParses
- type FieldExists
- type FormatStringValid
- type GeoProjection
- type ImageURLAllowed
- type LogScalePositiveDomain
- type PathDNonEmpty
- type PieDonutEncoding
- type RepeatSubstitution
- type ResolveScaleCompat
- type SankeyChannels
- type ScaleTypeCompat
- type SchemaRef
- type SelectionEncodingChannel
- type SelectionIntervalChannel
- type SelectionRef
- type TreeChannels
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AggCompat ¶
type AggCompat struct{}
AggCompat implements PRISM_SPEC_002: aggregate operations require the target field to be of a compatible measure type. Numeric aggregates (mean, sum, etc.) need quantitative or temporal fields; counting ops accept anything.
type AnimationEasingKnown ¶
type AnimationEasingKnown struct{}
AnimationEasingKnown implements PRISM_SPEC_022: when an animation block declares an easing, the name must be one of spec.AnimationEasings. An empty / omitted easing is fine (the encoder applies the default at scene-emit time).
func (AnimationEasingKnown) Check ¶
func (AnimationEasingKnown) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check fires when animation.easing is non-empty and unrecognised.
func (AnimationEasingKnown) Code ¶
func (AnimationEasingKnown) Code() string
Code returns PRISM_SPEC_022.
type AnimationKeyPresent ¶
type AnimationKeyPresent struct{}
AnimationKeyPresent implements PRISM_SPEC_023: when an animation block is declared, the spec must expose a join key. Today the only supported source is an encoding channel with key:true; future versions may accept a top-level data.key field. Composition forms (layer / concat / facet / repeat) inherit animation from the parent spec, so the rule checks the current node's encoding plus any immediate child specs that override animation.
func (AnimationKeyPresent) Check ¶
func (AnimationKeyPresent) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check fires when s.Animation is set but no descendant encoding declares key:true.
func (AnimationKeyPresent) Code ¶
func (AnimationKeyPresent) Code() string
Code returns PRISM_SPEC_023.
type AnimationKeyUnique ¶
type AnimationKeyUnique struct{}
AnimationKeyUnique implements PRISM_SPEC_024: at most one encoding channel in any given spec node may carry key:true. Composite keys are not supported in v1. The rule walks composition children (layer / concat / facet child) and emits one error per node that exceeds the cap.
func (AnimationKeyUnique) Check ¶
func (AnimationKeyUnique) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check fires for every encoding block whose channels carry key:true on more than one entry.
func (AnimationKeyUnique) Code ¶
func (AnimationKeyUnique) Code() string
Code returns PRISM_SPEC_024.
type ChannelForMark ¶
type ChannelForMark struct{}
ChannelForMark implements PRISM_SPEC_003: each encoding channel must be supported by the spec's mark type. The supported set is per-mark; for example, theta/radius are supported by arc/pie/donut but not by bar.
func (ChannelForMark) Check ¶
func (ChannelForMark) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check inspects every channel set on s.Encoding against allowedChannelsForMark(mark).
type CompositeMarkEncoding ¶
type CompositeMarkEncoding struct{}
CompositeMarkEncoding implements PRISM_SPEC_013: composite marks (histogram, heatmap, boxplot, violin) require a specific shape of encoding channels. Pie / donut are covered by PRISM_SPEC_008 (PieDonutEncoding); this rule covers the cartesian-axis composites.
Rules per mark (D059–D062):
- histogram: requires a single quantitative x channel.
- heatmap: requires both x and y to be bound.
- boxplot: requires exactly one categorical axis (x or y) and the other axis quantitative.
- violin: same as boxplot.
func (CompositeMarkEncoding) Check ¶
func (CompositeMarkEncoding) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check inspects the spec's mark + encoding against the per-mark shape requirements. Emits one PRISM_SPEC_013 per violation.
func (CompositeMarkEncoding) Code ¶
func (CompositeMarkEncoding) Code() string
Code returns PRISM_SPEC_013.
type ConditionSelectionRef ¶
type ConditionSelectionRef struct{}
ConditionSelectionRef implements PRISM_SPEC_025: every `selection` name referenced from a condition entry must resolve to a declared selection in the spec's "selection" block.
func (ConditionSelectionRef) Check ¶
func (ConditionSelectionRef) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check walks every condition-bearing channel and reports unresolved selection references.
func (ConditionSelectionRef) Code ¶
func (ConditionSelectionRef) Code() string
Code returns PRISM_SPEC_025.
type ConditionTestParses ¶
type ConditionTestParses struct{}
ConditionTestParses implements PRISM_SPEC_026: every `test` expression in a condition entry must parse via the Pulse expression parser (mirroring PRISM_SPEC_006 for transforms).
func (ConditionTestParses) Check ¶
func (ConditionTestParses) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check walks every condition-bearing channel and tries to parse each non-empty test expression. Reuses the parser shim from ExpressionParses so the syntax surface stays in sync with Pulse.
func (ConditionTestParses) Code ¶
func (ConditionTestParses) Code() string
Code returns PRISM_SPEC_026.
type ConditionValueOrBinding ¶
type ConditionValueOrBinding struct{}
ConditionValueOrBinding implements PRISM_SPEC_027: a condition entry must carry exactly one of {value, field}. Both set or neither set fails — except that a selection-form entry with neither value nor field is allowed: it implicitly inherits the channel's own field binding. test-form entries always require value or field.
func (ConditionValueOrBinding) Check ¶
func (ConditionValueOrBinding) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check walks every condition-bearing channel and flags entries with invalid value/field combinations.
func (ConditionValueOrBinding) Code ¶
func (ConditionValueOrBinding) Code() string
Code returns PRISM_SPEC_027.
type DatasetRef ¶
type DatasetRef struct{}
DatasetRef implements PRISM_SPEC_005: every named dataset reference (in data.name, transform.data, transform.join.with, transform.union) must resolve to a dataset declared in the spec's "datasets" map, in the registered SchemaLookup, or in an earlier transform's "as" output.
func (DatasetRef) Check ¶
func (DatasetRef) Check(s *spec.Spec, schemas validate.SchemaLookup) []*errors.AppError
Check walks the spec collecting dataset references and reports any that do not resolve. Recurses into child layer/concat/facet/repeat specs.
type ExpressionParses ¶
type ExpressionParses struct{}
ExpressionParses implements PRISM_SPEC_006: every Pulse expression (filter predicates, calculate expressions) must parse successfully.
TODO(pulse): switch from expr-lang/expr to Pulse's wrapper as soon as Pulse exposes a public expression parser. Pulse 0.8.4 uses expr-lang/expr v1.17.8 internally (see processing/filterer.go) but does not export the compiler/options. Until then this rule depends directly on the same expr-lang/expr version so the syntax surface matches what Pulse runs at execution time.
func (ExpressionParses) Check ¶
func (ExpressionParses) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check inspects every filter and calculate expression and tries to parse it. The selection:<name> shorthand used by SelectionRef is stripped before parsing so expressions that mix it with Pulse syntax still validate as expressions.
type FieldExists ¶
type FieldExists struct{}
FieldExists implements PRISM_SPEC_001: every encoded field must exist in the source dataset's schema (or be the output of a transform within the spec). With an EmptyLookup (no real Pulse source bound), the rule is a no-op — the resolver in P02 turns this into a hard check.
func (FieldExists) Check ¶
func (FieldExists) Check(s *spec.Spec, schemas validate.SchemaLookup) []*errors.AppError
Check inspects every encoding channel's "field" reference against the schema for the dataset bound by the leaf spec.
type FormatStringValid ¶
type FormatStringValid struct{}
FormatStringValid implements PRISM_SPEC_011: every channel.format, axis.format, and legend.format must parse as a valid d3-format specifier (subset supported in encode/format).
func (FormatStringValid) Check ¶
func (FormatStringValid) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check walks every channel inspecting Format strings + nested axis / legend format strings.
type GeoProjection ¶
type GeoProjection struct{}
GeoProjection ensures the spec's projection block is valid and that geo marks have both a projection and the right channel binding.
func (GeoProjection) Check ¶
func (GeoProjection) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
func (GeoProjection) Code ¶
func (GeoProjection) Code() string
type ImageURLAllowed ¶
type ImageURLAllowed struct{}
ImageURLAllowed implements PRISM_SPEC_016: image marks may only reference data: URLs or relative paths. Remote URLs (http, https, ftp, file, gs, s3, ...) are rejected at validate time per D068 so the encoder + renderer stay network-free (matches PROJECT.md offline-first principle).
func (ImageURLAllowed) Check ¶
func (ImageURLAllowed) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check fires when an image mark's URL string is non-empty AND is neither a data: URL nor a relative path.
type LogScalePositiveDomain ¶
type LogScalePositiveDomain struct{}
LogScalePositiveDomain implements PRISM_SPEC_010: a channel that declares scale.type=log must bind a field whose values (when available via inline data) are strictly positive. The rule walks every position + mark channel; for each that carries scale.type=log and a field name resolvable through inline data.values, it inspects the values and flags any non-positive entry.
When the dataset is external (Pulse-backed, GCS, etc.) the rule no-ops — the encoder's per-row guard surfaces the same code at render time via scale.LogScale.Apply / encode.resolveLog.
func (LogScalePositiveDomain) Check ¶
func (LogScalePositiveDomain) Check(s *spec.Spec, schemas validate.SchemaLookup) []*errors.AppError
Check inspects every channel with scale.type=log. Returns PRISM_SPEC_010 for each field whose inline values include a zero or negative.
func (LogScalePositiveDomain) Code ¶
func (LogScalePositiveDomain) Code() string
Code returns PRISM_SPEC_010.
type PathDNonEmpty ¶
type PathDNonEmpty struct{}
PathDNonEmpty implements PRISM_SPEC_017: the path mark's `d` attribute (carried as MarkDef.Path on the spec) must be a non-empty SVG path string. Empty / whitespace-only strings are rejected at validate time.
func (PathDNonEmpty) Check ¶
func (PathDNonEmpty) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check fires when the spec's mark is "path" and the d-string is empty or whitespace-only.
type PieDonutEncoding ¶
type PieDonutEncoding struct{}
PieDonutEncoding implements PRISM_SPEC_008: pie and donut marks (and the underlying arc mark when used in their composite form) must encode value via theta and category via color, never x/y. PRISM_SPEC_003 catches "channel not valid for mark" generically; this rule provides a more specific message tailored to the pie/donut workflow.
func (PieDonutEncoding) Check ¶
func (PieDonutEncoding) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check fires when:
- mark is pie or donut and the spec uses x or y, OR
- mark is pie or donut and no theta encoding is present.
type RepeatSubstitution ¶
type RepeatSubstitution struct{}
RepeatSubstitution implements PRISM_SPEC_012 at validate time. When a `repeat` block's child spec carries an encoding channel with `{"field": {"repeat": <axis>}}` substitution that references an axis the parent did NOT declare on the repeat block, the rule fires before the builder runs.
The build-time substitution walker (plan/build/composite.go) also catches this case — defense-in-depth, mirroring the layered scale rule (P08) — but firing at validate keeps the error visible through `prism validate` without driving the full plan pipeline.
func (RepeatSubstitution) Check ¶
func (RepeatSubstitution) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check walks every `repeat` block in the spec (top-level + nested inside facet / repeat / layer / concat children) and asserts that each substitution's axis is declared on its nearest-enclosing repeat block.
func (RepeatSubstitution) Code ¶
func (RepeatSubstitution) Code() string
Code returns PRISM_SPEC_012.
type ResolveScaleCompat ¶
type ResolveScaleCompat struct{}
ResolveScaleCompat implements PRISM_PLAN_005 at validate time. When a composite spec uses `resolve.scale.<channel>: "shared"` AND the layers declare incompatible types on that channel (e.g. one layer nominal + another quantitative on `y`), the rule fires before the encoder runs. The encoder also catches the same issue (defense-in- depth via encode/resolve.Unify) so dynamic-type cases — where the spec leaves `type` implicit — are still trapped.
The rule walks only the spec's top-level `layer` array; concat / hconcat / vconcat children are full charts that resolve scales independently per cell (see D050, D053), so cross-panel sharing is not in scope here.
func (ResolveScaleCompat) Check ¶
func (ResolveScaleCompat) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check inspects every shared channel in resolve.scale and asserts type agreement across the layer array. Channels where any layer omits an explicit `encoding.<ch>.type` are skipped — the encoder's table-driven inference covers that case.
func (ResolveScaleCompat) Code ¶
func (ResolveScaleCompat) Code() string
Code returns PRISM_PLAN_005.
type SankeyChannels ¶
type SankeyChannels struct{}
SankeyChannels implements PRISM_SPEC_018: sankey marks require source, target, and value channel bindings (per D064 flat-table input form). Missing channels raise a single error listing every missing name.
func (SankeyChannels) Check ¶
func (SankeyChannels) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check fires when mark is sankey and any of source / target / value is missing or has an empty Field.
type ScaleTypeCompat ¶
type ScaleTypeCompat struct{}
ScaleTypeCompat implements PRISM_SPEC_007: an explicit scale type on an encoding channel must be compatible with the field's measure type. log/pow/sqrt/linear belong on quantitative; time on temporal; band / point / ordinal on nominal/ordinal.
func (ScaleTypeCompat) Check ¶
func (ScaleTypeCompat) Check(s *spec.Spec, schemas validate.SchemaLookup) []*errors.AppError
Check inspects every channel with an inline scale.type and validates it against the channel's declared "type" (nominal/ordinal/quantitative/ temporal). If the channel has no type but the dataset is known, the rule falls back to the source field's type. No-ops when neither source is available.
type SchemaRef ¶
type SchemaRef struct{}
SchemaRef implements PRISM_SPEC_009: the spec's $schema value must reference a known Prism schema location. Accepted forms:
- The canonical URN urn:prism:schema:v1:spec.
- A relative or absolute path ending in spec.schema.json.
- A file:// URL ending in spec.schema.json.
type SelectionEncodingChannel ¶
type SelectionEncodingChannel struct{}
SelectionEncodingChannel implements PRISM_SPEC_019: every channel listed in a selection's `encodings` array must be bound in the spec's encoding block.
Both point + interval selections honour the rule. The channel name is case-sensitive (lower-case per the JSON schema enum).
func (SelectionEncodingChannel) Check ¶
func (SelectionEncodingChannel) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check walks every selection's Encodings list and confirms each entry resolves to a bound channel in s.Encoding.
func (SelectionEncodingChannel) Code ¶
func (SelectionEncodingChannel) Code() string
Code returns PRISM_SPEC_019.
type SelectionIntervalChannel ¶
type SelectionIntervalChannel struct{}
SelectionIntervalChannel implements PRISM_SPEC_020: an interval selection's `encodings` list must contain only position channels (x | y | x2 | y2 | theta). Color / size / shape intervals are not supported in v1 — those use cases route through point selections.
func (SelectionIntervalChannel) Check ¶
func (SelectionIntervalChannel) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check walks every interval selection's encodings list and reports any non-position entry.
func (SelectionIntervalChannel) Code ¶
func (SelectionIntervalChannel) Code() string
Code returns PRISM_SPEC_020.
type SelectionRef ¶
type SelectionRef struct{}
SelectionRef implements PRISM_SPEC_004: every reference to a named selection must resolve to a selection declared in the spec's "selection" block.
Selection references in v1 appear as:
- The substring "selection:<name>" inside a filter expression (the convention adopted for Pulse-expression-driven specs).
- Future: explicit references in condition encodings (deferred to v2).
func (SelectionRef) Check ¶
func (SelectionRef) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check scans filter expressions for selection references and reports any that do not match a declared selection.
type TreeChannels ¶
type TreeChannels struct{}
TreeChannels implements PRISM_SPEC_028: tree, dendrogram, and network marks require source + target channel bindings (per the flat-table input form). Missing channels raise a single error listing every missing name.
func (TreeChannels) Check ¶
func (TreeChannels) Check(s *spec.Spec, _ validate.SchemaLookup) []*errors.AppError
Check fires when mark is tree / dendrogram / network and either of source / target is missing or has an empty Field.
Source Files
¶
- agg_compat.go
- animation_easing_known.go
- animation_key_present.go
- animation_key_unique.go
- channel_for_mark.go
- composite_mark_encoding.go
- condition_selection_ref.go
- condition_test_parses.go
- condition_value_or_binding.go
- condition_walk.go
- dataset_ref.go
- expression_parses.go
- field_exists.go
- format_string_valid.go
- geo_projection.go
- image_url_allowed.go
- init.go
- log_scale_positive_domain.go
- path_d_nonempty.go
- pie_donut_encoding.go
- repeat_substitution.go
- resolve_scale_compat.go
- sankey_channels.go
- scale_type_compat.go
- schema_ref.go
- selection_encoding_channel.go
- selection_interval_channel.go
- selection_ref.go
- tree_channels.go