What a fragment is about, and the ids it refers to (spec/14 §19.2, §19.8).
A fragment's kind is derived, never stored: walk down while the fragment sets exactly
one key, and the kind is the last node kind reached. A library body says its kind with a
singular wrapper — %{style: %{…}} — and a hand-written fragment says it by the schema's
own keys; both read the same way here. A fragment about more than one thing at its
shallowest branching point is :design.
An id is {kind, n} (§19.2). refs/1 finds every id a fragment carries, which is
how a bundle takes the closure of an entry, and relocate/2 rewrites them through a
table, which is how an import renumbers (§19.7). Both are deep walks that stop at a
struct, as every walk over a design does (D-92).
Examples
iex> Visualize.Chart.Fragment.kind(%{style: %{stroke_width: 5}})
:style
iex> Visualize.Chart.Fragment.kind(%{styles: %{series: %{stroke_width: 5}}})
:style
iex> Visualize.Chart.Fragment.kind(%{frames: %{main: %{axes: [%{scale: :x, side: :bottom}]}}})
:axis
iex> Visualize.Chart.Fragment.kind(%{frames: %{main: %{margin: %{top: 1}}}})
:margin
iex> Visualize.Chart.Fragment.kind(%{theme: :dark})
:theme
iex> Visualize.Chart.Fragment.kind(%{composite: %{uses: []}})
:composite
iex> Visualize.Chart.Fragment.kind(%{version: 2, theme: :dark, frames: %{main: %{}}})
nil
iex> Visualize.Chart.Fragment.refs(%{style: [{:style, 11}, %{fill: {:style, 3}}]})
[{:style, 3}, {:style, 11}]
Summary
Functions
The name of a design's frame; :main when it has none or several.
The path of a design's frame, and its name (spec/14 §2.1, #383): a design holds its
frames by name, so the builder addresses frames.<name> where it used to address
frame. A design with one frame gives that one, whatever it is called; an empty or
many-framed fragment gives :main, the name a migrated design takes (§9).
The fragment to_json/1 wrote (#465): tagged terms back as %Visualize.Chart.Use{},
ids, variables and atoms. An id whose kind is not one a fragment can have is left as it
was read, so no atom is made from a document's kind. {:error, {:json, message}} for text
that is not JSON. from_json(to_json(f)) is f.
The kind of a fragment (§19.8): the last node kind reached walking down while exactly one
key is set. nil when the fragment is many things — it branches at the top, or its one
key is a design scalar such as version — which is no kind of fragment: the thing that
is many kinds is a composite, whose sites are each one.
Every kind a fragment can be, and so every kind an id can carry: the schema's node kinds
but the design, and :composite (§19.6, §19.8). A design is the deployed tier, not a
kind of fragment.
Every id a fragment refers to, once each, sorted (§19.7). Sorted rather than in the order met, because the order a map is walked in is the runtime's and not a promise.
A fragment with every id rewritten through a table, and the ids the table did not carry, sorted (§19.7). An id that is not in the table is left as it is — it resolves as a mask (§19.2) — and is returned so an import can report it.
The kind a singular wrapper key names — :style for style: — or nil for any other
key, composite included (spec/14 §19.2).
A fragment of any kind as the JSON of §11 and §19.7 (#465): use sites as $use, ids as
$id, variables as $var. It is not validated as a design — a fragment may be partial —
so a host that keeps its library in a database can write whatever Store.put/2 hands it.
{:error, {:missing_dependency, :jason}} without Jason, as Visualize.Chart.to_json/1.
A singular-wrapper body as {kind, body} — %{style: %{…}} is {:style, %{…}} — or nil
for anything else, a composite included (spec/14 §19.2).
Types
@type id() :: {atom(), pos_integer()}
An id: the kind of thing, and a number its store never repeats (§19.2).
Functions
The name of a design's frame; :main when it has none or several.
The path of a design's frame, and its name (spec/14 §2.1, #383): a design holds its
frames by name, so the builder addresses frames.<name> where it used to address
frame. A design with one frame gives that one, whatever it is called; an empty or
many-framed fragment gives :main, the name a migrated design takes (§9).
iex> Visualize.Chart.Fragment.frame_path(%{frames: %{history: %{kind: :cartesian}}})
[:frames, :history]
iex> Visualize.Chart.Fragment.frame_path(%{})
[:frames, :main]
@spec from_json(String.t()) :: {:ok, map()} | {:error, {:json, String.t()} | {:missing_dependency, :jason}}
The fragment to_json/1 wrote (#465): tagged terms back as %Visualize.Chart.Use{},
ids, variables and atoms. An id whose kind is not one a fragment can have is left as it
was read, so no atom is made from a document's kind. {:error, {:json, message}} for text
that is not JSON. from_json(to_json(f)) is f.
The kind of a fragment (§19.8): the last node kind reached walking down while exactly one
key is set. nil when the fragment is many things — it branches at the top, or its one
key is a design scalar such as version — which is no kind of fragment: the thing that
is many kinds is a composite, whose sites are each one.
@spec kinds() :: [atom(), ...]
Every kind a fragment can be, and so every kind an id can carry: the schema's node kinds
but the design, and :composite (§19.6, §19.8). A design is the deployed tier, not a
kind of fragment.
Every id a fragment refers to, once each, sorted (§19.7). Sorted rather than in the order met, because the order a map is walked in is the runtime's and not a promise.
An id is a {kind, n} tuple whose kind is one of kinds/0 and whose n is a positive
integer. A tuple of any other shape — an anchor {:axis, :y}, a {:field, :t} — is a
value and is left alone.
A fragment with every id rewritten through a table, and the ids the table did not carry, sorted (§19.7). An id that is not in the table is left as it is — it resolves as a mask (§19.2) — and is returned so an import can report it.
iex> table = %{{:style, 11} => {:style, 1}}
iex> Visualize.Chart.Fragment.relocate(%{style: [{:style, 11}, {:style, 9}]}, table)
{%{style: [{:style, 1}, {:style, 9}]}, [{:style, 9}]}
The kind a singular wrapper key names — :style for style: — or nil for any other
key, composite included (spec/14 §19.2).
iex> Visualize.Chart.Fragment.singular(:scale)
:scale
iex> Visualize.Chart.Fragment.singular(:styles)
nil
A fragment of any kind as the JSON of §11 and §19.7 (#465): use sites as $use, ids as
$id, variables as $var. It is not validated as a design — a fragment may be partial —
so a host that keeps its library in a database can write whatever Store.put/2 hands it.
{:error, {:missing_dependency, :jason}} without Jason, as Visualize.Chart.to_json/1.
iex> {:ok, json} = Visualize.Chart.Fragment.to_json(%{style: %{stroke_width: 5}})
iex> Visualize.Chart.Fragment.from_json(json)
{:ok, %{style: %{stroke_width: 5}}}
A singular-wrapper body as {kind, body} — %{style: %{…}} is {:style, %{…}} — or nil
for anything else, a composite included (spec/14 §19.2).
iex> Visualize.Chart.Fragment.wrapped(%{style: %{stroke_width: 5}})
{:style, %{stroke_width: 5}}
iex> Visualize.Chart.Fragment.wrapped(%{styles: %{series: %{}}})
nil