This page says what a host changes to move statifier_blocks from 0.31.0 to
0.44.0, one minor at a time. A host here is the code that embeds the package:
the palette it builds, the compile it calls, the documents it stores and the
publish step it runs. What each release added is in
CHANGELOG.md; this page lists only what a host has to do
about it, and says NONE where the answer is nothing.
Take the minors in order, and move the pin with each one, as the README
recommends: {:statifier_blocks, "~> 0.32.0"}, then "~> 0.33.0",
"~> 0.34.0", "~> 0.35.0", "~> 0.36.0", "~> 0.37.0", "~> 0.38.0",
"~> 0.39.0", "~> 0.40.0", "~> 0.41.0", "~> 0.42.0", "~> 0.43.0"
and "~> 0.44.0". A patch release rides its minor's pin, so each section
below covers the patches of the minor it moves to.
One value moves at every release, a patch included, and the sections below
do not repeat it: the compiler version. StatifierBlocks.Compiler.compiler_version/0
answers the package's version, and the StatifierBlocks.CompilationRecord in
what StatifierBlocks.Compiler.compile/3 answers carries it as
compiler_version, so a record compiled after the bump carries the new
version. If you pin compiler_version in a test, or compare it with a
record you stored, move the literal with each pin.
What an author changes in a document is a separate page: Migrating a document from 0.27 to 0.34. Nothing on it is required, and no stored document has to be migrated for any release below.
0.31 to 0.32
If you call StatifierBlocks.Composite.unraisable_outcomes/4 yourself, call
unraisable_outcomes/5instead, passing the config of the block you expanded as the new third argument, between the type ref and the expansion members:Composite.unraisable_outcomes(palette, ref, block.config, members, param_map)This is the release's one Breaking entry. The compiler makes this call itself, so a host that never called it directly changes nothing for it.
Recompile the documents you store before you switch. A composite that declares no outcomes used to compile green when a slot on it broke the declaration: a child in a slot its type does not declare was dropped, and a declared slot holding the wrong number of children lost its refusal. On 0.32 the compile refuses both at the Resolve stage, as
:undeclared_slotand:slot_arity_violated. A document refused there is its author's to fix; the finding's message says how.
0.32 to 0.33
Finish rolling 0.32 off before an author saves an
acceptslist. A document saved with a non-emptyacceptslist cannot be read by 0.32.0 or earlier, so a node still on 0.32, or a rollback to it, refuses that document. A stored document decodes unchanged on 0.33 and keeps itscontent_hash/1.If you match exhaustively on a
StatifierBlocks.Finding's anchor or source, add the:documentanchor and the:graphsource.Finding.from_compiler/2now adapts a Document-stage finding to the:documentanchor where it answered{:error, {:unanchorable, finding}}.If you rescue a raise from
StatifierBlocks.Compiler.compile/3for a document whoserootis not a block, or whoseslotsvalue is not a map of block lists, match the{:error, findings}it returns now instead.If you key on
:duplicate_idat the Chart stage for a block placed in a composite's pass-through slot, or in a declaring composite'son_<name>slot, under an id the expansion mints for one of its own members, key on:minted_id_collisionat the Resolve stage instead.If you store
%StatifierBlocks.CompilationRecord{}field by field, it gains anacceptsfield, the document's list as written.If you call
StatifierBlocks.Shell.drawer_view/1orShell.findings_groups/3yourself, the first takes an optionalacceptskey and the groups the second answers gain adocument?key.Put the publish gate in your publish step. Two calls judge a document before you publish it, and your step refuses on an
:errorfrom either:StatifierBlocks.Publish.findings/3takes the document as saved, the palette and the editor's context map (:datamodel,:declare,:chart_outcomes), and answers the findings of the compile's stages before Emit followed by the editor's own, in the editor's order. An:erroramong them is a document the compile would refuse before Emit or one the editor marks in error. An undeclared datamodel path is an:infoadvisory, never a refusal.StatifierBlocks.Graph.check/2takes the parent's compiled artifact and your resolver from a document id to that document's published artifact. It refuses a child that is not published, an outcome the parent routes on that the child does not declare (errorexempt), and a done-data key the parent reads that the child does not declare. Its reverse,StatifierBlocks.Graph.consumers_broken/2, judges a child's next revision against the published parents that name it.
The order they run in, with the compile between them, is How to publish a document.
0.33 to 0.34
NONE. Nothing needs migrating, the package gains no dependency, and an
editor mounted without the new publish_status assign renders exactly what it
rendered on 0.33.0. The release's additions are opt-in; the CHANGELOG says
what they are.
0.34 to 0.35
NONE. Nothing needs migrating, and the package gains no dependency.
StatifierBlocks.Plan.expressible/3 and Plan.expressible?/3 are new and
opt-in, so a host that calls neither sees no change from 0.34.0. The 0.35.1
patch, which the "~> 0.35.0" pin takes, changes the shipped stylesheet
only: a card's title no longer breaks mid-word.
0.35 to 0.36
- If you pin a card line in a test, or match the words a card shows,
read the new words for three core types, each of which now declares
sentence/1where it showed its label:core.sequencereadsRun its steps in orderwhere it readSequence;core.groupreadsRun interruptible stepswhere it readGroup; andcore.awaitreadsWait for <event>, followed by, giving up after <timeout>when a deadline is set, where it readWait for event. The same sentences name those blocks in the lines ofStatifierBlocks.Describe, new in this release.
The rest of 0.36.0 is opt-in: StatifierBlocks.Describe and the JSON
Schema the package now ships, read through StatifierBlocks.Schema, change
nothing for a host that calls neither, and the package gains no runtime
dependency. The 0.36.1 patch needs nothing from a host: Describe.outline/3
now draws the interrupt edge for an abandon handler that names
finish_as, which 0.36.0 left out.
0.36 to 0.37
- If you pin a delayed
core.send's card line, or aStatifierBlocks.Describeline built from it, read the new words: a send with a delay names that delay,In 7 days, send loan.fines_noticewhere it readSend loan.fines_notice, the short duration form put in words and any other stored spelling shown as stored. A send with no delay reads exactly as before. - If you match every edge kind
Describe.outline/3answers, add:timer, the edge from a delayedcore.sendto eachcore.on_eventandcore.awaitthat names its event, and read its delay fromStatifierBlocks.Describe.Edge's newdelayfield.render/2writes it asIn 24 hours, registration.deadline reaches ..., and a phrasing module rewords it through the new optionalPhrasing.timer/2callback. A document with no delayed send describes exactly as before.
Nothing needs migrating and the package gains no dependency. The new
explain/0 callback on StatifierBlocks.BlockType is optional, so a host
type that declares none changes nothing.
0.37 to 0.38
- Run the palette pre-flight before you deploy. A block type's declared
field types now bind: a config value its declared field type in
config_schema/1does not admit (an integer in a:stringfield, a value outside a{:select, choices}) is refused beforevalidate_config/1runs, at compile, at the edit gate and under the field in the view model, with a finding naming the field's key and its declared type. After taking 0.38 and before deploying it, runStatifierBlocks.Palette.preflight/1over your palette andStatifierBlocks.Palette.preflight/2over the documents you store, and correct each declaration or stored block they list; an empty list means you are ready. A host type whose documents disagree with its declared field types otherwise sees new:configfindings.validate_config/1still runs and its findings follow; an absent key and anullare still the type's own to judge.
StatifierBlocks.Schema.for_palette/1 is new and opt-in, and the package
gains no dependency.
0.38 to 0.39
- Finish rolling 0.38 off before a document carries a block
note. Decode now admits an optionalnotestring on a block, a key 0.38.0 and earlier refuse, so a node still on 0.38, or a rollback to it, refuses a document that carries one. A note that is not a string is refused as{:malformed_block, id, {:note, :not_a_string}}. - If you build
%StatifierBlocks.Block{}structs yourself, or match them field by field, it gains anotefield,""by default (the absent note), whichBlock.new/2takes as:note. Canonical form omits an empty note, so a document with no notes keeps itscontent_hash/1; a note changes the document's hash, not the compiled chart. - If you audit the licenses of your dependencies, the package metadata
lists
EPL-2.0besideMIT: elkjs 0.9.3 ships vendored and unmodified asassets/vendor/elk.bundled.js, with its Eclipse Public License 2.0 text beside it. Only a bundle that imports thestatifier_blocks/mapentry point loads it; the default export is unchanged.
The Map itself is opt-in: StatifierBlocks.Map, Map.Info and
StatifierBlocks.Editor.MapRegions change nothing for a host that mounts
neither region, and the package gains no Hex dependency.
0.39 to 0.40
- If you match every member of
StatifierBlocks.Edit.t()by hand, add a clause for{:update_note, id, note}, the new command that writes a block's author note; an empty note removes it.Edit.apply/2answers its inverse,{:update_note, id, previous_note}, and refuses a note that is not a string with{:malformed_block, id, {:note, :not_a_string}}, the termDocument.validate/1answers for such a note. A host that only passes commands on toEdit.apply/2orEdit.Historychanges nothing. - The editor draws a description region under its canvas:
StatifierBlocks.Editor.MapRegions.description_region/1, read from the editor's own document, palette and selection, with no map beside it. It is drawn in a read-only mount too, and noprofilekey hides it. There is nothing to pass for it. - If you mount
description_region/1yourself, it takes two new attrs, both optional:map,trueby default, andfalsefor a region with no map beside it (no hover layer, no store and no how-to-read paragraph in the idle description); andlabel, the live region'saria-label,"Description"by default. A host that passes neither gets the region it had. - If you set the
--sb-*palette on.sb-map__description, set it on.sb-map__description-frameinstead, the wrapper the region now sits in beside its hover layer, so the layer reads it too. - If you stamp the
StatifierBlocksMaphook's ids on your own element rather than mountingmap_region/1anddescription_region/1, stampdata-info-hoverwith the id of anaria-hidden,hiddenelement beside the region for the hook to fill. The hook finds its hover layer there and no longer readsdata-info-region, so without it the map has no hover. A hover no longer changes what the region announces; only a new selection does. - If you pass
phrasetomap_region/1ordescription_region/1, passnilor a function of one argument. Any other value now raises anArgumentErrornaming the attr, where it raised aFunctionClauseError;niland a one-argument function render as before.
0.40 to 0.41
- If you match the edge lines
StatifierBlocks.Describe.render/2answers, or pin them in a test, read the new words. An edge line names a container by a noun where it named it by its sentence: its title where it has one; else a short noun for its type,the stepsfor a sequence,the groupfor a group or a resumable group,the branch,the lanesfor a parallel andthe loopfor a for-each; elsetheand its palette label in lower case. A noun that opens a line with a lower-casethetakes a capital there, andthe stepsandthe lanestakestartwhere the others takestarts: the line that readRun its steps in order starts with Wait 14dnow readsThe steps start with Wait 14d, andSend loan.overdue (done) ends Run its steps in orderreadsSend loan.overdue (done) ends the steps. Wherever an edge line embeds a delayed send's sentence it is set in double quotation marks, so its own comma does not read as the line's:After "In 7 days, send loan.overdue" (done), Wait 14d. Node lines, and a step named in an edge line, keep their sentence. To keep other words, give the container a title, or reword the line throughStatifierBlocks.Describe.Phrasing, whose callback receives the new default. - If you build
StatifierBlocks.Describe.Nodestructs yourself, it gains anounfield,nilby default.outline/3fills it; a node built by hand with no noun is named by its sentence in an edge line, as before. A host that only readsoutline/3's nodes changes nothing. - If you match the idle description's how-to-read text, the
explanationofStatifierBlocks.Map.Info.idle/4, read the new paragraph: it names every mark the Map draws, the clock on a timed wait among them. - If you attach the
StatifierBlocksMaphook to your own element rather than mountingmap_region/1, give that element a child markeddata-map-canvasfor the hook to draw into. Without one the hook still draws into the element itself, which LiveView patches, and now warns once per mount in the browser console that this is not supported.map_region/1renders the child.
The Map's other changes need nothing from a host: it draws the happy
path straight through a group whose body holds a container, the hook
laying such a document out twice, and it draws the clock mark on a
timed wait (core.wait), which still takes no part in a timer edge.
0.41 to 0.42
NONE for a host that mounts neither the editor nor the Map
(map_region/1 and description_region/1) and passes no :phrase to
StatifierBlocks.Map.graph/2 or StatifierBlocks.Map.Info.elements/6:
nothing needs migrating, and the package gains no dependency. A host that
does mount them reads the bullets below.
- If you read
data-info-regionoff the elementmap_region/1renders, take the region's id from thedescriptionyou pass tomap_region/1instead. The element no longer carries the attribute, which theStatifierBlocksMaphook has not read since 0.40.0, so the hover is unchanged. A host that stamps the attribute on its own element, or never read it, changes nothing. - If you pass
phrasetomap_region/1ordescription_region/1, or:phrasetoStatifierBlocks.Map.graph/2orStatifierBlocks.Map.Info.elements/6, and pin a phrased line in a test, re-read the lines where a name your function has words for sat outside event position. Words now replace a name only in event position: afterSendor a delayed send'ssend, afterWait for, or after a rule'sWhen. A known name anywhere else stays as written, such as a path a step sets, a name after a send or wait word glued to a dotted prefix, or the event a timer edge's line names beforereaches. A name in event position reads as it did on 0.41.0. - If your page mounts the editor and reads the notes it stores, a note
a browser posts with CRLF line breaks is now stored with LF: each CRLF
becomes LF at the editor's note event, before the command, so a change
of line endings alone is no longer an undo entry. A lone CR is stored as
posted. The
{:update_note, id, note}command a host issues itself throughStatifierBlocks.Edit.apply/2still stores the note's bytes as written. - If you pass
classtodescription_region/1, it now goes on the region's hover layer as well as on the region, so what your class gives the region still shows while a hover is drawn. A rule of yours on that class now reaches the layer too; the package's stylesheet keeps a hidden layer out whatever display a single class of yours sets. - If you rescued a raise out of
description_region/1on a document whose composite declaration cannot expand, you can drop the rescue: the region now renders with no description in it and nodata-map-descriptionattribute, its id,aria-liveand label kept, and withmap={true}its hover layer and an empty store.
The release's fix for a note-free stored block needs nothing from a host:
a block built before blocks had a note, in a document kept as a stored
Erlang term, now goes through the note edit command,
StatifierBlocks.Map.Info's descriptions and the editor's note field as
a note-free block instead of raising.
The 0.42.1 patch, which the "~> 0.42.0" pin takes, changes documentation
only: NONE, beyond the compiler version every release moves (see the
top of this page).
0.42 to 0.43
NONE for a host that mounts neither the editor nor the Map
(map_region/1 and description_region/1), reads none of the Map's
answers itself (StatifierBlocks.Map.graph/2, StatifierBlocks.Map.caption/1,
StatifierBlocks.Map.start_text/0 and the descriptions
StatifierBlocks.Map.Info answers) and pins none of the findings
StatifierBlocks.Datamodel.findings/4 or StatifierBlocks.Publish.findings/3
answers: nothing needs migrating, and the package gains no dependency. A
host that mounts the Map gets its new drawing with nothing to pass for it:
the start dot first, marked Start; every end ring marked End; a legend of
the marks the drawing uses, beside it at its top right; and a drafts shelf
in a drawer under the drawing, closed on a page that cannot edit and open on
one that can. A host that does read those answers reads the bullets below.
- If you draw the graph
StatifierBlocks.Map.graph/2answers yourself, read its new shape.StatifierBlocks.Map.nodes/1is unchanged.- The start dot is the graph's first node, at its top level beside the root box rather than inside it, and its start edge is the graph's own. The edge still runs into the first step of the document's flow, or into the root's box on a document whose root body holds only a drafts shelf.
- The start node and each end node carry the word Start or End as their
one ELK
labelsentry, withlayoutOptionsplacing it outside the mark on its right. The start edge's caption reads "Starts when the system is told to", and its label is wider. - A new top-level
legendlist carries the key, one%{"mark" => mark, "line" => line, "lines" => lines}per mark the drawing uses. - A drafts shelf's node carries a new
draftsfield,%{"count" => count, "label" => label}, and thelegendgains a lastdraftsentry whose line is that row; the node stays where it was. - A group deeper in the document's tail whose rules abandon it (the last
step of an arm of the root's last step, or of the body of a group that
is) gains an
abandonedge into theabandonend node, so one abandon end can have several edges into it. - A group's rules column carries
caption"Rules: watch the steps while they run" in place of the group's sentence, and a newexplanation_linesfield, that sentence wrapped to a box's line. - A branch node's wrapped arm entry starts every line after its first with
no-break spaces as wide as the entry's number (
"1. ","10. ").
- If you draw
StatifierBlocks.Map.caption/1yourself, expect the whole first sentence of the type's explanation for a branch and the two group types, never cut to one line and ended in "...". - If you match or pin the descriptions
StatifierBlocks.Map.Infoanswers, read the new values.idle/4'sexplanation, the paragraph on how to read the map, is shorter: it opens with "A plain box is a step, drawn inside the step that holds it, with its type's name on top and what it does under it.", says what a column beside a group holds, and leaves what each mark means to the key.idle/4answers two new facts: "Finishes with", right after "What starts it", the document's ends in order (each outcome, and "abandons" for an abandon end), for example["done", "abandons"], with no such fact on a document whose map draws no end; and a last fact,{"Legend", lines}, the key's lines.StatifierBlocks.Editor.MapRegions.description_region/1shows the "Legend" fact with a map beside it and leaves it out withmap={false}, as it leaves out the paragraph.StatifierBlocks.Map.start_text/0answers "Starts when the system is told to" where it answered "Starts when told to", on every document, so the "What starts it" fact reads it too.elements/6lists the start dot before the root box and the start edge after the root's own elements and edges. The start edge'ssentencereads as two sentences, "Starts when the system is told to. First: Wait 21 days." where it read "Starts when told to, Wait 21 days". A timer edge's explanation says the delayed event arrives at the interrupt rule or the hourglass step that hears it. Each new abandon edge is described as the root-level one is.
- If you count or pin the findings
StatifierBlocks.Datamodel.findings/4answers, or thoseStatifierBlocks.Publish.findings/3answers after them, a{:list, {:path, opts}}field's rows now get the:infoundeclared-path advisory a{:path, opts}field gets: one for each undeclared row, a path repeated across rows once, anchored on the list field's key. It is:info, so a publish step that refuses on an:errorrefuses nothing new. The editor binds each row's input to a<datalist>ofpath_candidates, with nothing to pass for it.
The release's other changes need nothing from a host:
StatifierBlocks.Describe.render/2 reads a timer or interrupt edge whose
event is blank as "its event", as it already did for an edge with no event;
and the StatifierBlocksMap hook draws the first layout where it drew the
error pane when a second layout fails, draws a resume edge clear of its own
rule's box, and holds the SVG wide enough for a timer edge between two
steps of one column.
The 0.43.1 patch, which the "~> 0.43.0" pin takes, widens the predicator
requirement to admit 9.5 (~> 9.4 and >= 9.4.1), so a host moving to a
statifier that requires predicator 9.5 can resolve this package beside
it: NONE, beyond the compiler version every release moves (see the top
of this page).
0.43 to 0.44
NONE for a host that mounts neither the editor nor the Map
(map_region/1 and description_region/1), reads none of the Map's
answers itself (StatifierBlocks.Map.graph/2 and the descriptions
StatifierBlocks.Map.Info answers), reads no compiled interface, pins
or refuses on none of the findings StatifierBlocks.Publish.findings/3 or
StatifierBlocks.Graph answers, and stores no core.await with a
capture key: nothing needs migrating, no stored document has to change,
and the package gains no dependency. A host that mounts the
editor gets the capture rows on core.await with nothing to pass for them,
and may pass the new advisories assign. A host that does read those
answers reads the bullets below.
- If your publish step refuses on the
:errorfindingsStatifierBlocks.Publish.findings/3answers, it now refuses a document that declares its own datamodel roots (itsdatamodelkey holds an entry) and holds a config path no declaring surface declares: there the undeclared-path advisory is answered at:error, with the advisory's anchor,:lintsource and message. Declaring the path, or correcting it, lets the document publish. A document that declares no roots is unchanged: with only your:datamodelor:declareroots the advisory stays:infoand refuses nothing, and with nothing declared anywhere there is none. The editor andStatifierBlocks.Datamodel.findings/4still answer it at:info. - If you read the compiled
interface'sreferences, or match the findingsStatifierBlocks.Graph.check/2andconsumers_broken/2answer, read the new values.- A
core.subchartorcore.mapthat a composite's expansion placed is recorded under the composite block the stored document holds: itsblock_idis the outermost composite's id, and a newexpanded_fromkey carries the expanded member's id, which the stored document does not hold. A finding about it is anchored{:block, composite_id}on the composite, where it was anchored on the member's field. - A
core.mapwhosecollect_typenames a type the compile's:datamodeldoes not declare is now markedunresolved, and its done-data read is reported unchecked with the same:graph:warningoncollect_typea compile without:datamodelgets, its message saying the supplied datamodel does not declare the name; before, the read passed with no finding. It is a:warning, so a publish step that refuses on an:errorrefuses nothing new. Passing a:datamodelthat declares the name, or writing thecollect_typeinline, lets the keys be checked. - A reference that is
unresolvedcarries a newunresolved_reason,:no_datamodelor:not_declared. A reference recorded before the key existed, withunresolvedset and no reason, reads as:no_datamodel, the only case that setunresolvedthen.
- A
- If you build or store documents whose
core.awaitblocks carry acapturekey, it now compiles:core.awaittakes an optionalcapturemap withcore.on_event's semantics, each pair an assign on the transition the awaited event selects, and a malformed map is refused where the key used to be ignored. An await with nocapture, or an empty one, compiles to the same bytes as before. - If your page mounts the editor and stores the config it posts, the
first time its form posts an edit to an await that holds no
capture, the block's config gains an emptycapturemap, since the form now draws the capture rows for every await. It compiles to the same bytes as an absent one; a host that compares stored configs key for key sees the new key. - If you want the editor to show advisories only your host can raise,
pass the new optional
advisoriesassign toStatifierBlocks.Editor: a one-argument function the editor calls with the document on every rebuild, returning{anchor, message}or{anchor, message, opts}as aStatifierBlocks.DocumentValidatordoes. Each becomes a:lintfinding at:warningunless itsoptssay otherwise, drawn where its anchor routes it. Pass the same function toStatifierBlocks.Editor.findings_count/3as its:advisoriesoption so your count agrees with the drawer's. With the assign unset the editor draws what it drew before. - If you match or pin the descriptions
StatifierBlocks.Map.Infoanswers, or thelegendStatifierBlocks.Map.graph/2answers, read the new wording.idle/4'sexplanation, the paragraph on how to read the map, says "A caption on a branch's band, or under a group's rules column with its explanation beneath, says what that kind of step does." in place of the sentence that called it "a one-line caption".- The abandon end's explanation in
elements/6, and the key's dashed-ring line (the graph'send-abandonlegendentry, and so the "Legend" factidle/4answers), say an interrupt rule abandons "a group at the end of its flow" where they said "its last step". - The Finish edge's explanation in
elements/6reads "The arrow into a final mark: the document's last step, or a group at the end of its flow, is behind it, so when control leaves it this way, the document finishes with the outcome it names."
The release's fixes need nothing from a host: a face finding on a selected
card spans the card's width below its title row; the editor's Expand
gesture writes each member a composite mints at its block type's current
version; StatifierBlocks.Editor.ConfigForm.config_form/1 renders a class
you pass on its read-only form as well as on the editable one, so a rule
of yours on that class now reaches the read-only form too; and the
StatifierBlocksMap hook leaves the drafts drawer out and draws the path
when the drafts shelf alone fails to lay out.