Whakerexa > Icons > Design

Definition of the needs

The problem, and what is aimed at

An application draws what it wants, and puts it where it wants. What it does not choose are the icons the framework draws in its own components — the arrow of a nav, the two of the accessibility controls, the boxes of a selector, the fourteen of a presentation. Those come from one set, in one place, and an application that wants others has to rewrite the components that hold them.

What the framework offers besides is one set, under one path, asked for by name. An application that needs two sets has no way to say that the same button is not drawn the same in both: several sets are several drawings of each icon its pages use, and there is one place to put them. One that owns a drawing of its own has no way to add it beside the others. And one whose icons are images rather than line drawings has no way in at all.

The question is therefore: how does a document show the icons that belong to it, without redrawing what it does not care about, and without losing what a local document, a dark mode or a screen reader ask of an icon.

What is aimed at: let an application bring its own icons, whole sets or a handful; let a document be read with the set that suits whoever reads it; keep what the framework holds today, an icon that follows the color of what surrounds it, on a document opened from a disk, without a server and without the internet; and ask an application for the drawings, and for nothing else.

What an application writes to get all that is on icons.html.

Expression of the needs

An application has icons that belong to it, and wants to show them. It does not want to redraw the ones the framework provides and that suit it. It therefore gives the icons it owns, and the framework gives the others.

What it gives is not one set: one of them is complete and the others are not. An application that shows an incomplete one wants the missing names answered by its own complete set, and not by drawings that are not its own. It says which of its sets answers for the others; what came with the tool answers last, and only what neither of them carries.

One application may need several sets: the same button is not always drawn the same way, and what tells one set from the next is its own business. It gives as many as it wants, each under a name, and the reader chooses the one the document is shown with. Changing that choice does not load the page again, and the choice holds from one page to the next.

The reader sees the icons wherever the document is opened, served or taken from a disk. He sees them whatever the mode and the theme he reads in, and at the size he reads the text at: a contrast mode writes the text larger, and an icon that stayed where it was would be small beside it, and harder to aim at when a button holds nothing else. And whoever does not see them is told what they stand for.

Nothing moves when a drawing arrives, and nothing moves when the set changes. The room is therefore declared by the place and not by the drawing, in both its dimensions, since an icon is not always square: a set of flags is not a set of arrows. A drawing of other proportions is held inside that room rather than stretched to it.

An icon may be asked for under a name that no set carries. The page holds and shows the rest, and the console names it, so that whoever wrote the page can correct it.

What is not shown is not sent, and what is going to be shown says the room it takes before it arrives. Both are asked by the RGESN, the French reference for the eco-design of digital services, as WCAG asks that an icon be told to whoever does not see it. Neither is an improvement here: they are conditions.

Elicitation of the needs

Six things are handled, and they are all that is handled.

I1. A name is what an icon is asked for by. It says what the icon stands for, never where it is drawn: the same name is answered by a different drawing from one set to the next.

I2. A drawing is what answers a name. Its form follows from the file it stands in: a line drawing, which takes the color of what surrounds it, or an image, which carries its own.

I3. A ground is what covers a surface: a texture laid on a plain background. It is named as an icon is, and answered the same way, but it designates nothing, and it is asked for by a surface and not by a place.

I4. A set is what holds drawings and grounds under names. It carries part of the names, or all of them, and says which ones it carries. One is the reference set, and answers what the others leave unanswered.

I5. The set in force is the one a document is read with. There is one at a time, and the reader chooses it.

I6. A name it does not carry goes down a chain of two: the fallback set, which the application names among its own, and then the reference set, which belongs to the framework. Either may be absent, and the chain is the same for every name.

Organisation of the needs

I10 Icons of an application

  • I11 The author can declare a set of icons that belongs to the application.
  • I12 The icons an application brings are shown in place of the ones that came with the tool.
  • I13 The author is free to draw only some of the icons, the others being no less shown.
  • I14 A name the shown set does not carry is answered all the same, by another set.
  • I16 The author says which of the sets answers what the others leave unanswered. What that one does not carry either is answered last, by what came with the tool.
  • I15 The author adds an icon by bringing its drawing, and writes nothing else.
  • I17 The author can be told the names a set answers, so that a page lays out the drawings it can ask for without listing them by hand.
  • I18 The author says where his set stands, wherever that is: beside the page, at the root of the site, or on another host. A set he brings has no reason to stand where the tool stands.

I20 Several sets

  • I21 The author can declare several sets, each under a name.
  • I22 The reader can choose the set the document is shown with.
  • I23 One set is in force at a time, for the whole document.
  • I24 The set in force is the same from one page of the document to the next.
  • I25 The set in force changes without the page being loaded again.
  • I26 A drawing is loaded only when it comes into what the reader sees. RGESN
  • I27 A change of set loads again only the drawings the document is showing.

I30 What an icon is made of

  • I31 The author can bring line drawings and images, of whatever the file they stand in, in one set. Grounds are I70.
  • I32 A line drawing is shown in the color of what surrounds it.
  • I33 An icon that carries its colors is shown as it is drawn.
  • I34 The element that holds an icon declares the room it takes, in both its dimensions, before the drawing arrives. RGESN
  • I37 An image carries the two dimensions the place declared, so that nothing waits for the file to know them. RGESN
  • I38 A drawing whose proportions are not those of the place is held inside it, and never stretched.
  • I35 Nothing moves around the icon when the drawing arrives.
  • I36 An icon is drawn at the size of the text around it, and grows with it.

I70 Grounds

  • I71 The author can bring grounds, each under a name, in the sets that carry the icons.
  • I72 A surface is covered with the ground of the set in force.
  • I73 A surface whose name the shown set does not carry is covered all the same, by the ground of another set.
  • I74 What a ground stands for is never told: it stands for nothing.
  • I75 Nothing moves around a surface when its ground arrives.
  • I76 A surface is covered only while the reader sees it.

I40 Where the document is read

  • I41 The reader can see the icons on a document opened from a disk, with no server.
  • I42 Nothing is asked of the internet.
  • I43 The reader sees the icons in every mode and every theme.

I50 What an icon says

  • I51 The reader who does not see the icon is told what it stands for.
  • I52 The icon itself is not read out.

I60 What is missing

  • I61 Nothing is shown for a name no set carries.
  • I62 That name is said in the console, for whoever wrote the page.
  • I63 Everything else is shown, and the page holds.

Left for later: showing two sets at the same time, so that they can be compared, and adding a set once the page is open.

What was set aside

These were considered and decided against. They are not missing.

Set aside, and why
WhatWhy
Asking for a representation by its path rather than by a name A path names one drawing. A name is what several sets answer, and without it there is no set to choose from
Trying a representation to see whether a set carries it Where nothing serves the document the try is never answered, and where something does it costs a request for every name a set does not carry. A set says what it carries instead
Asking a set to carry every name Nobody would bring a set for three drawings, and the chain already answers the rest
Loading the page again to change the set It makes the reader pay for the document, its stylesheets and its scripts, to change what is drawn in a few places
Loading a whole set when the set in force changes What is not in view is answered when it comes into view, and most of a set is never seen on one page
Holding, for a later change of set, the demands that are out of view They are answered when they come into view, under the set that is in force then
A requirement on the contrast between a representation and its background It is the theme that carries the pair of colors. A line drawing takes the color of what surrounds it, which ties it to the theme and says it once
Two mechanisms, one for the icons and one for the grounds Two declarations, two fallbacks and two registers, for one need
A set that answers a name by drawing it rather than by carrying a drawing Nothing asks for it

Merise

MCC — who exchanges what

The organisation is the document, and what runs it. Two external actors exchange with it, and it is cut into two internal ones.

The external actors, and the flows of the context
ActorWhat it is
AuthorDraws the icons, declares the sets, writes the pages that ask for them
ReaderAsks for a page, chooses the set it is shown with, reads what is shown
FlowFromToWhat
1AuthorThe documentThe sets, each under a name, and what each one carries
2AuthorThe documentThe drawings
3ReaderThe documentThe request for a page
4ReaderThe documentThe set the document is to be shown with
5The documentReaderThe icons shown, and what each one stands for
6The documentAuthorThe names no set carries
The internal actors, and the flows between them
ActorWhat it holds
SetsThe sets that were declared, what each one carries, and where its drawings are
PlacesThe places of the document that ask for an icon, and what is shown at each
FlowFromToWhat
7PlacesSetsA name, when a place comes into view
8SetsPlacesThe drawing that answers it, or nothing
9ReaderSetsThe set to put in force (flow 4, once inside)
10SetsPlacesThe set has changed: what is shown is to be asked for again

Flows 1 to 4 come from outside and become the external events of the MCT. Flows 5 and 6 leave it and are its results. Nothing else crosses: nothing is asked of a server, nothing is stored, nothing is sent back. I42

MCD — what the data are made of

Five entity classes, the identifier of each one written with a #.

ClassPropertiesWhat it is
SET# name, where_the_drawings_areA set of icons. One is the reference set, one may be the fallback set, the others are declared and nothing else
CONTENT# content_name, kind, file, /formWhat answers a name. Its kind is a drawing, shown at a place, or a ground, laid on a surface. Its file is what the set declared under that name, and its form follows from it. It exists only inside a set, and is identified relatively to it
PLACE# place_id, name_asked, roomSomewhere in the document where an icon is asked for. It says the name it asks for and the room it takes
SURFACE# surface_id, name_askedSomewhere in the document that is covered. It says the name it asks for, and takes the room it already has
READING# documentThe document being read. There is one, and it is shown with one set
RelationVerbLeg 1Leg 2
R1carriesSET (1,n)CONTENT (1,1)
R2answersCONTENT (0,n)PLACE (0,1)
R3is shown withREADING (1,1)SET (0,n)
R5falls back toSET (0,1)SET (0,n)
R4coversCONTENT (0,n)SURFACE (0,1)

R1 is an aggregation: a content is named inside the set that carries it, and two sets name a content the same way without naming the same content. The set is the aggregating class, the content the aggregated one.

R2 leaves a place with no content, which is the case I61 asks to treat: a name no set carries answers nothing, and the room stays empty. R4 says the same of a surface, which keeps the plain background it had.

Two things are computed, never held: which content answers a place or a surface, which follows from R3 and R1 and changes when the reading is shown with another set I25; and whether a place or a surface is in view, which is what triggers the question I26 I76.

The constraints

On roles. SET takes part in R1 and R3, CONTENT in R1, R2 and R4. A content answers a place or covers a surface, never both, which is an exclusion on roles between R2 and R4: its kind says which of the two it is. Nothing else — no totality, no subset, no equality.

On relations. A content that answers a place is carried by a set, which would be a subset constraint from R2 to R1; the cardinality (1,1) of R1 already says it, and the arrow would add nothing. The same holds of R4. No exclusion, no equality between relations.

What the formalism does not carry is said here. C3 is the one that decides: it restricts R2 by R3, and no arrow between two relations says that.

No.ConstraintComes from
C1A set carries a name once. Two drawings under one name in one set is a set declared twiceR1
C2The reference set carries every name asked for by what the organisation draws itselfI14
C3A place is answered by the first set of the chain that carries the name: the set in force, then the one it falls back to, then the reference setR1, R2, R3, R5, I14 I16
C10The chain of the fallback has no cycle and is read once: a set that falls back to itself, or to one that falls back to it, answers as if it fell back to nothingR5
C4A place that no set answers is not asked again under the same set in force: what a set carries it has already saidI6 I61
C5The form of a content follows from its file, and from nothing else: a set carries line drawings and images side by side, since an author takes the files he hasCONTENT.file, I31
C8A content answers places, or covers surfaces, and never both: its kind says whichR2, R4, CONTENT.kind
C9A surface is never told to whoever does not see it, a ground standing for nothingI74
C6A place declares its room, in both dimensions, before it is answered. The room does not depend on which set answers it, nor on the proportions of the drawing that doesI34 I35 I38
C7A place is asked for only while it is in view, and only once under a given set in forceI26 I27
C11Where a set stands is written by the page and read as the page writes it: from the page, from the root of the site, from another host, and from where the tool stands only when nothing else is saidI18
C12The names a set answers are the names of the chain of C3, said once and in the order of that chain: what the set in force carries, then what answers for it, then the reference setI17, C3

That is why which drawing answers a place is computed and never held: it follows from R3, then from R1, and it changes when the reading is shown with another set.

MCT — the events and the operations

What has to be done, and on what. Not when, not how, not where.

The events
No.EventKindComes from
E1Sets are declaredexternalFlows 1 and 2
E2A page is asked forexternalFlow 3
E3A set is chosenexternalFlow 4
E4A place or a surface comes into viewinternalOP2, then the reading
E5The set in force has changedinternalOP2
OP1 — Establish the sets
WhatSays
SynchronisationE1 AND E2
ActionsHold each set under its name, with what it carries — drawings and grounds — and where they are. Hold which one answers for the others, and the reference set last: those two are the chain a name goes down
ResultThe sets are known. Always
ResultA message: a set declared twice. When two sets bear one name

Nothing is read here: a set says what it carries, and OP1 believes it. That is what lets OP3 answer without asking. I6

OP2 — Put a set in force
WhatSays
Synchronisation(the sets are known AND E2) OR E3
ActionsTake the set the reader names; the one the page names when he names none; the reference set when neither names one
ResultOne set in force. Always
ResultE5, the set has changed. When the set taken is not the one that was in force
ResultE4, for each place and each surface in view. When the reading begins

A set that was never declared is a set nobody named: the set in force does not change for it. I23

OP3 — Answer a demand
WhatSays
SynchronisationE4 AND a set is in force
ActionsGo down the chain — the set in force, the one that answers for the others, the reference set — and stop at the first that carries the name; read what answers, and put it where it was asked for
ResultThe drawing, at the place. When a set carries the name and the content is a drawing
ResultThe ground, on the surface. When a set carries the name and the content is a ground
ResultThe room, left empty, or the plain background kept. When no set carries the name
ResultA message: the name no set carries. When no set carries the name

OP3 is ininterruptible for one demand: a set put in force while a content is being read is taken into account after, by E5, and not during. Nothing moves around what was asked for, the room of a place having been declared before and a surface keeping the one it has. I34 I75

What the content is decides what OP3 produces, and nothing else does: a drawing is shown at a place, a ground is laid on a surface, and neither is ever the other. C8

OP4 — Ask again what is shown
WhatSays
SynchronisationE5
ActionsTake back what was answered at the places and the surfaces that are in view
ResultE4, for each of them. Always

OP4 answers nothing of its own: it gives OP3 its event back, and for what is in view only. What is not seen is answered when it is seen. I27

One process, four operations. E1 and E2 open it, E3 comes as often as the reader asks, E4 as often as the reading moves, and E5 only when OP2 changes what was in force.

MOT — when, where, and by whom

The operations of the MCT, cut into functional procedures, each triggered by one event.

PFFromTriggered byDurationPlaceIn chargeResources
PF0—The application is builtOnce, before anything is read The machine of the authorAuthor The drawings and the grounds, and what gathers them into the document
PF1OP1E1 AND E2Once per page, before anything is shown Where the document is readThe organisation What the document declares of its sets, and which of them answers for the others
PF2OP2The page opensOnce per page, after PF1 Where the document is readThe organisation The address, and what the page names as its default
PF3OP2E3, the reader asksAs often as he asks Where the document is readReader The sets known by PF1
PF4OP3E4, a place or a surface comes into viewOnce per demand and per set in force Where the document is readThe organisation The set in force, and the content — read where it stands when the document is served, taken from what PF0 gathered when it is not
PF5OP4E5, the set has changedOnce per change, on what is in view only Where the document is readThe organisation The places and the surfaces PF4 has answered

PF0 is what the MCT does not show: a document read where nothing serves it cannot go and get anything, so what it will need has to be gathered into it beforehand. That happens elsewhere, at another time, and under the responsibility of the author — which is why a set meant for such a document is gathered as the reference set is. I41

Everything else happens where the document is read. Nothing is done elsewhere, and nothing is kept from one opening to the next: PF1 and PF2 run again at every opening, and give the same result.

PF2 and PF3 are one operation cut in two, because two events trigger it and two are in charge: the system at the opening, the reader afterwards. What they produce is the same, one set in force. I24

PF4 comes as often as the reading moves, and never before PF2: a demand answered without a set in force would be answered twice. Its resources differ according to whether the document is served or not, and it is the only procedure where that difference is seen.

MLD — the tables

Each entity class becomes a table, its identifier becomes the key.

TableColumnsComes from
SETname, where_the_contents_areThe entity class SET
CONTENTset_name, content_name, kind, fileThe entity class CONTENT, and R1. The form is not a column: it is read in the file
PLACEplace_id, name_asked, roomThe entity class PLACE
SURFACEsurface_id, name_askedThe entity class SURFACE
READINGdocument, set_in_forceThe entity class READING, and R3

R1 is an aggregation: the aggregated class takes the key of the aggregating one, so CONTENT holds the name of its set, and the two together tell one content from another. Two sets carry a content under one name without carrying the same content.

R3 has a low cardinality on the side of READING, which is (1,1): the table READING takes the key of SET, under the name of what it says — set_in_force.

R2 and R4 are translated by nothing. Which content answers a place, and which one covers a surface, are computed from the set in force and from what the sets carry: a column would hold an answer that changes as soon as the reading is shown with another set, and would have to be emptied at every change. C3

Not in the tables either: whether a place or a surface is in view. It is read where the document is read, and it changes as the reading moves.

MPD — where each table stands

Here the tool is named, and not before: Whakerexa answers what the needs ask for, and it is the one that is extended. There is no database — the tables are borne by the document, by what runs it, and by what is built before it is read.

TableIn the sourceWhile runningOn screen
SET What a page declares on wexa.loader.js: a name, a path, and the files it carries, each under the name it answers to. Another attribute names the set that answers for the others An object held by the manager of the sets Nothing of its own
CONTENT A file in the folder of its set on http; a string written into wexa.bundle.js by build_bundle_js.py on file:// The markup or the address, once read, in the cache of the manager The icon, or the ground
PLACE An element that names its icon and declares its room, in calc(var(--font-size) * n) for each of its two dimensions That same element The room, then the drawing
SURFACE An element that names its ground That same element The plain background, then the ground over it
READING Nothing The name of the set in force, held beside the sets What the document is shown with, and the name written in the address, as the theme is

Two things the tables do not hold are read from the browser: whether a place is in view, which IntersectionObserver answers, and the size of the text around an icon, which the font size of the element answers.

The reference set is wexa_statics/icons/mono-svg/. What a set says it carries is what makes the chain work with no request: on file:// a request would never be answered, and on http it would cost one for every name a set does not carry, at every step of the chain. I6

MOpT — where the code goes

ModuleWhat it doesProcedure
setsHolds the sets, what each one carries, where its contents are, and which form they takePF1
choiceHolds the set in force, changes it, and says it in the addressPF2, PF3
readingReads a content, from a file or from what was gathered into the document. The only one that knows where a content comes fromPF4
placingPuts a content where it was asked for, and the only one that knows a line drawing from an image and a drawing from a groundPF4
watchingSays when a place or a surface comes into view, and when it leavesthe trigger of PF4
registerHolds what has been answered, so that a change of set asks again for that and nothing elsePF5
gatheringWrites the contents of a set into the document, for a document read where nothing serves itPF0

Under wexa_statics/js/, one file per class, as the framework already writes them. The module that gathers is a script of scripts/, run before a release, beside the one that builds the bundle.

SVGIconsManager answered for reading and for placing at once, and for one set only. It is what the modules above took apart, and it is gone.

The decisions of the tool

What the levels above do not decide, and what the code will show. They belong here: they are choices about the tool, and they could not be made before it was named.

D1. One package holds what customises the look. The manager of the themes and the one of the sets hold the same kind of state — a name in force, read in the address and written back — and they answer the same need on two matters. They are written together rather than apart.

D1b. The manager is held under Wexa.iconsets. Wexa.icons is the name of the older manager, which the components of the framework still call: taking it would leave them without icons. The two names live side by side until D2 is done, and D2 is a broken promise for whoever calls Wexa.icons.get().

D2. What reads and what places are taken apart. SVGIconsManager did both, for one set. Reading changes when a document is served or not; placing changes when a content is a line, an image or a ground. They do not change for the same reasons, so they are not one class. The older one is removed, and Wexa.icons is the new manager: what it holds of the old are get() and inject(), which the components of the framework call.

D3. A place declares its room counted on the font size, in calc(var(--font-size) * n) as the framework counts every size, and in both dimensions. One declaration holds three needs: the room kept before the image arrives I34, the size that follows the text I36, and the two dimensions an image is given so that nothing waits for the file to know them I37. A drawing of other proportions is held inside that room I38: the place is what does not change from one set to the next, so it is the place that decides the shape.

D4. A set is declared on the loader, beside the themes, and not in a call written in every page. A page says what it brings where it already says what it loads, and names there the set that answers for the others.

D7. A set is declared in one line: its name, its place, its files. The name is what stands before the first colon and the files what stands after the last one, so that the place between the two keeps the colon of an address that carries a host. The files are written and not asked for: it is what lets a name fall back with no request at all, on a document read from a disk as on one that is served I41 I42.

D8. The names a set answers are computed, never held. They follow the chain of C3 and change with the set in force, exactly as the drawing that answers a place does. A page that lays them out asks for them when it lays them out I17.

D9. The demand is carried by the element that means something — a button, a link, a heading — and never by an element written for the icon alone. What the icon stands for is said by that element and not by the drawing I51: an element written for the drawing alone would carry something that names nothing, and a reader who does not see it would be told nothing. It is also what keeps the drawing out of the reading I52, the element that holds it being what is announced.

D6. The chain has two links and no more. A set that answers for the others, then the reference set. Letting each set name the one it falls back to would make a chain of any length, which nobody asked for, and which would have to be walked at every name and guarded against cycles.

D5. What a set carries is gathered into the document at build time, by a tool the author runs. It is the only way a document read with nothing serving it can answer a name. Only the line drawings are gathered — an image is answered by its address, which a document finds beside itself.

D5b. What is gathered is written on the namespace of the framework, as Wexa.gatheredIcons, and not under a name of its own. The style guide of the project asks that a global be avoided; the framework already holds one, Wexa, and a second would be one too many. The file that carries the drawings is loaded before Whakerexa is there, so it makes that object if it has to and wexa.js adds to what it finds. What an older build left under a name of its own is read as well: the decision changes where the list is written, not what a document already carrying one can do.

It is a script and not a file of settings. A browser refuses fetch() on a file:// address, and that address is the one case this file exists for I41 I42: a .json could not be read there, while a script is run. Served, nothing of this is needed — a drawing is asked for when a place demands it — so a file of settings would fail where it would be useful, and add a request where it would not.

It is a list and not a call on a class: a file loaded by a page cannot know when the framework will be there, and a list waits without asking anything. Its name says a list and not a constant — the page fills it, the loader empties it. And a list is all it is, so an author whose tools are his own writes it as he likes: nothing of the framework runs to produce it, and nothing of it is asked at the moment it is read.

UML

The classes that carry the data

They come from the MLD, one class per table, and they are set at construction. What they give back is a string or a copy.

ClassFromWhat it is
IconSetSETA set: its name, where its contents stand, the form they take, and the names it carries
IconContentCONTENTWhat answers a name: its kind, a drawing or a ground, and its source
IconDemandPLACE, SURFACEAn element that asks for a name. Its kind says whether it is a place or a surface

PLACE and SURFACE become one class: they differ by what answers them, which C8 says is the kind of the content, and by nothing they hold themselves. READING becomes no class at all — the set in force is a name, held by the one that changes it.

The classes that do the work

One per module of the MOpT, and each one is the only one that knows what it knows.

ClassModuleWhat it does
IconSetssetsHolds the declared sets and the reference one. Says which set answers a name, and never reads anything
IconChoicechoiceHolds the set in force, changes it, reads it in the address and writes it there
IconReaderreadingReads a content. The only one that knows a file from what was gathered into the document
IconPlacerplacingPuts a content where it was asked for. The only one that knows a line drawing from an image, and a drawing from a ground
IconWatcherwatchingSays when a demand comes into view. The only one that reads the rendering
IconRegisterregisterHolds the demands that were answered, and gives back those in view
IconManager—Calls the others in order, and is the only one that catches an error

What each one promises: IconSets reads nothing and asks nothing, which is what makes it testable without a document; IconReader is the only one that goes and gets a content; IconPlacer is the only one that changes the document shown; IconManager is the only one that writes a try.

The states of a demand

StateWhat is true
WrittenThe element names what it asks for and, for a place, declares its room. Nothing is shown
WatchedThe demand is known, and waits to come into view
AnsweredA content is where it was asked for, and the demand is held for a later change of set
UnansweredNo set carried the name. The room stays empty, and the console has said it

A change of the set in force takes an answered demand back to watched, and only those in view. An unanswered one is not tried again under the same set: what a set carries it has already said. C4

The sequence when the page opens

  1. The page declares its sets; IconSets holds them, the one that answers for the others, then the reference set: that is the chain.
  2. IconChoice reads the address, then what the page names, then falls back on the first set of the chain.
  3. IconWatcher is given the demands of the document.
  4. A demand comes into view: IconSets says which set answers its name.
  5. IconReader reads the content; IconPlacer puts it where it was asked for.
  6. IconRegister holds the demand.
  7. The reader chooses another set: IconChoice says so, IconRegister gives back what is in view, and step 4 begins again for those.

Step 1 before step 2, and step 2 before step 4: a demand answered before a set is in force would be answered twice, and would move what is around it.

The error policy

LevelWhat happensWhat is done
1Nothing can be done: not one set, not even the reference oneAn exception, caught by IconManager, said in the console
2One demand is concerned: no set carries the name, or the content cannot be readNo exception. The room stays empty, and the rest of the page holds
3The author has to know: a name nobody carries, a set declared twiceNo exception. A message in the console, and the work goes on

Exceptions are raised at the lowest level and caught at the highest. An error must never do worse than the absence of the program: without it a page shows no icon and reads all the same.

The contracts, class by class

How to read them

+ public, - private, / derived and never held, {readOnly} does not change after construction, {ordered} the order matters. pre is what has to be true on the way in, and what the operation does not check; post is what the caller can count on.

Two rules hold everywhere: a name that answers nothing gives back an empty string, an empty array or an empty map, never null; and the fields of a data class are set at construction and give back a copy.

The data classes

IconSet
OperationSignatureContract
constructor(name, base, files)pre: name and base are not empty; files names a file under each name it answers to, and may be empty. post: the object does not change any more
get name(): Stringpost: the name the set was declared under
carries(name: String): Booleanpre: none. post: true when the set declared that name. Reads nothing and asks nothing. I6
addressOf(name: String): Stringpre: the set carries the name. post: where the content stands, from the base of the set and the file declared under that name
/formOf(name: String): IconFormpre: the set carries the name. post: line when the file is an SVG, image otherwise. Read in the file, never held. C5

carries() answers from what was declared, never from what exists: that is the whole of decision 2.

IconContent
OperationSignatureContract
constructor(name, kind, form, source)pre: name is not empty; kind is a drawing or a ground; source is what was read. post: the object does not change any more
get kind(): IconKindpost: drawing or ground. It says what answers a place and what covers a surface. C8
get form(): IconFormpost: line or image, read in the file it stands in
get source(): Stringpost: the markup of a line drawing, or the address of an image. Never empty
IconDemand
OperationSignatureContract
constructor(element, name, kind)pre: element is not null; name is not empty; kind is a place or a surface. post: the object does not change any more
get name(): Stringpost: the name the element asks for
get kind(): DemandKindpost: place or surface. A place holds a room, a surface holds what it already has
get element(): HTMLElementpost: the element itself, never a copy: it is what is written into

The working classes

OperationSignatureContract
IconSets.declare(set: IconSet): voidpre: set is not null. post: the set answers under its name; a name declared twice keeps the first and is said in the console. C1
IconSets.reference(set: IconSet): voidpre: set is not null. post: it is the set a name falls back to, and it is looked at last. C2
IconSets.fallback(name: String): voidpre: none. post: the set of that name is the one the others fall back to. A name that was never declared leaves the chain as it was
IconSets.setFor(name: String, inForce: String): IconSetpre: none. post: the first set of the chain that carries the name — the one in force, the one it falls back to, the reference one — or null when none carries it. Reads nothing. C3, C10
IconChoice.inForce(): Stringpost: the name of the set the document is shown with. Never empty: the reference set when nothing else was named
IconChoice.put(name: String): Booleanpre: none. post: true when the set in force changed, and the address says it; false when the name was already in force or was never declared. I23 I24
IconReader.read(set: IconSet, name: String): Promise<IconContent>pre: the set carries the name. post: the content, read where the document is read from; raises UnreadableContent when it cannot be read. The only one that goes and gets anything
IconPlacer.place(demand: IconDemand, content: IconContent): voidpre: the kind of the content answers the kind of the demand. post: the content is where it was asked for, held inside the room the place declared and never stretched to it; an image carries that room in its two dimensions; nothing around it has moved; a line drawing takes the color of what surrounds it, an image keeps its own. I32 I33 I35 I37 I38 I75
IconPlacer.clear(demand: IconDemand): voidpre: none. post: the demand shows nothing, and keeps its room. Calling it twice does nothing wrong
IconWatcher.watch(demands: IconDemand[], onView): voidpre: none. post: onView is called once per demand when it comes into view, and again after clear(). Reads the rendering, and decides nothing. I26 I76
IconRegister.hold(demand: IconDemand): voidpre: none. post: the demand is given back by inView()
IconRegister.inView(): IconDemand[]post: those of the held demands that are in view, in no order. May be empty. I27
IconManager.constructor(sets, named, watcher)pre: sets is not null. post: one set in force. A watcher is made when none is given: a test gives one, being unable to wait for a rendering
IconManager.run(root): Promise<void>post: every demand in view is answered or left empty; never raises; kept when everything is done
IconManager.show(name: String): Promise<void>pre: none. post: the document is shown with that set; the demands in view are answered again and no others; never raises. I25 I27

IconSets.setFor() is the whole of the fallback, and it reads nothing: it is the one operation that decides, and the one that is tested without a document.

Three exception classes: IconError, the mother, raised by nobody; NoSetAtAll, raised when not one set was declared; UnreadableContent, raised by IconReader.read(). IconManager is the only one that writes a try.

What is tested, and where

Without a document

IconSets decides the whole chain and reads nothing, so every rule of it is checked without opening anything: a name the set in force carries comes from that set; a name it does not carry comes from the set that answers for the others; a name neither carries comes from the reference set; a name none of the three carries comes back as nothing; a set that answers for itself answers as if it answered for nothing; a set declared twice keeps the first and says so. C1, C2, C3, C10

IconSet.carries() answers from what was declared and never from what exists, which is checked by declaring names no file stands behind: the answer is the same. That is the test that holds decision 2, and it would pass on a machine with no icon at all.

IconChoice reads and writes one name: a set that was never declared does not become the set in force; putting the one already in force changes nothing and says so; the name is found again in the address. I23 I24

IconRegister gives back what it holds, and only what is in view. I27

With a document

IconPlacer is checked on written markup: a line drawing takes the color of what surrounds it and an image keeps its own I32 I33; a ground covers a surface and no place [C8]; what surrounds a demand has the same size before and after, and the same again with a drawing of other proportions I35 I38 I75; an image carries the two dimensions the place declared I37; and clear() leaves the room where it was.

IconWatcher is checked on a document taller than one screen: a demand out of view is not announced, and is announced when the reading reaches it. I26 I76

IconManager is checked on what must not break the page: not one set declared, a name nobody carries, a content that cannot be read. It never raises, the page holds, and the console has said the name. I61 I62 I63

Where

In wexa_statics/js/tests/, one file per class, run by tests.html, as the framework already tests. The tests of the first section are the ones written first: they are the whole of the decisions, and they need nothing to run.