Tramaj.Node
- Package
- purescript-tramaj-purs
- Repository
- lucasdicioccio/purescript-tramaj-purs
The evaluated document representation — Tramaj's output domain and its
portable interchange boundary. nodeToJson/nodeFromJson implement
the normative representation specified in specs/node-json.md; that
document, not this module, is the contract other implementations and
hosts are held to.
Deliberately independent of both the expression AST (Tramaj.Ast) and
of any particular render target — folding a Node into Halogen HTML
is Tramaj.Halogen's job, in its own package, and another host may
fold the same tree into YAML, HCL or a UI model instead.
Kept in lockstep with ../tramaj-hs/src/Tramaj/Node.hs.
#Node Source
data NodeThree constructors, with enough expressivity inside them to carry
scalars losslessly — see specs/decisions.md #5.
NText holds a Json, not a String: .p($ctx.count) with
count = 3 keeps the number 3 rather than stringifying it.
Rendering a scalar to characters is a host decision, so the
interchange format declines to make it.
NElement holds a value slot alongside its children, for targets
that attach a body value to a tagged node (a YAML/HCL scalar leaf, a
config value); it is null unless a template sets one. Its
attributes are an ordered array rather than a map: an element may
carry any number of attributes and any number of actions, and
source order is preserved.
NFragment is a real node here — an ordered sibling sequence with no
wrapper element. A host may flatten fragments when folding;
evaluation does not.
Constructors
NText Json AnnotationsNElement String (Array NodeAttribute) Json (Array Node) AnnotationsNFragment (Array Node) Annotations
Instances
#NodeAttribute Source
data NodeAttributeBoth attribute-position constructs, sharing one array. An action's
event and key are plain String because both are static in the source
AST (see Tramaj.Ast); only the payload is computed.
Constructors
Instances
#Annotations Source
type Annotations = Map String JsonArbitrary host/tooling metadata hung off any node. The core language
assigns no meaning to any key; unknown annotations must not affect
semantics, and every node-to-node transformation must carry them
through unchanged. This is where a future type/domain/constraint pass
puts what it derives, without the Node constructors having to
change.
#nodeToJson Source
nodeToJson :: Node -> JsonEncodes to the normative representation. Every field is always
emitted, including an empty annotations and a null element
value — see specs/node-json.md, "Decoding": on the wire a missing
field is a bug, not a default.
#nodeFromJson Source
nodeFromJson :: Json -> Either String NodeDecodes the normative representation, strictly: a missing or ill-typed
field is an error rather than a silently-defaulted value, so
nodeFromJson <<< nodeToJson round-trips and a malformed document is
reported where it is read rather than where it later misbehaves. The
Left carries a human-readable description of what was wrong.
#mapActions Source
mapActions :: forall f. Applicative f => (String -> String -> Json -> f NodeAttribute) -> Node -> f NodeRewrites every action reachable in a tree, leaving everything else —
tags, ordinary attributes, element value slots, child order, and every
annotation map — untouched. Polymorphic in the applicative so a caller
that only fails (Either) and one that also accumulates something
alongside its result (v3-symbols constraint emission) can share this
one traversal.
Jsonhas noShowinstance, so every payload isstringifyd explicitly rather than riding along on a derived one.