Whakerexa > Extras > Book > Bibliography > Design

What this is

In short

A document writes its BibTeX entries and its text. When its page opens, the browser reads the entries, numbers the citations of the text in the order they appear, and builds the bibliography. Nobody runs anything, and nothing is fetched from the internet.

This page is the design of that work: what it does, what it deliberately does not do, the decisions that explain the code where it surprises, and the classes that carry it. Read the section below before reporting a behaviour as a bug: several of them are choices.

Two independent domains

The bibliography lists what the BibTeX data holds. It does not depend on the citations: a page without a single citation gets its table all the same, which is what publications.html shows. The citations, on their side, are numbered even when the page says nowhere to put the bibliography.

What the text owes to a reference, its number and the places it is cited at, is handed to the table from the outside. The table never asks the citations anything.

What it does not do

Left out on purpose

These were written as requirements, then set aside. They are not missing: they were decided against.

Requirements that were dropped
WhatWhy
Show the type of a reference in a column The formatted reference already says what it is.
Sort the types by importance No order of types is true for two readers.
Count the publications by year and by type, and draw them A bibliography is read, not measured.
Put a publication in the bibliography without citing it The BibTeX data decide what is listed; the text decides what is numbered.
Say whether a reference is open access or not What an address leads to already says it.
Mark a citation already consulted The numbers going up already tell a new reference from a known one.
Report a citation written inside a title Dropped after the model was written.

Not in the first version

These are established requirements that the code does not write yet. A document that needs them will not get them by trying harder.

Requirements postponed
WhatWhat happens today
One citation bearing several references The whole attribute is read as one key. data-bibtex="a, b" names no reference, so the citation says it is missing and the console reports the key. Write one span per reference.
A citation aiming at a page or a chapter Nothing reads it. CitedKey carries the field, and nothing fills it.
Going from a citation to its reference, and back, in a presentation. C26 and C27 Not shown to an audience. Following such a renvoi lays the slides over one another and leaves them half drawn, and the cause has not been found: the support reached is the right one, the reading stands at it, and nothing inside it is touched. Both links are written as they are on a page, and hidden by bibbook.css where a slide carries them. They hold on a page and on paper.

Choices that look like limits

  • Every author is written, whatever their number. Never "et al.": a bibliography that hides names hides people who did the work.
  • Nothing is ever completed from the internet. An entry missing a field is shown with the field missing, and the missing field is made visible.
  • An entry whose type nobody planned for is displayed by a fallback template rather than left out.
  • A reference that no citation names has no number, and sorts after every reference that has one.

Requirements

The bibliography

What the bibliography has to do
No.Requirement
B1The document reads its BibTeX data without going to the internet.
B2Every entry is cut apart: its type, its key, each of its fields. The authors are a list in the order they sign, each name split into given name, particle, family name and suffix.
B3Accents and symbols written in LaTeX become plain characters.
B4A reference missing a field is displayed all the same, and what is missing is seen.
B6A reference whose type the program does not know is displayed all the same.
B9Each type has its own display: which fields, in which order.
B11Every author is displayed, whatever their number. Never "et al.".
B12A link to the PDF, a link to an open archive and a link to the publisher are told apart.
B13The BibTeX entry can be seen as it is written in the file.
B14The abstract can be read, when the reference has one.
B15Reading an abstract does not lose your place in the bibliography.
B16The references can be sorted by year, or by author.
B19Only the references a word appears in can be kept.
B20Sorting, searching, and how the bibliography is built are said to whoever does not see the table: a status message, WCAG 4.1.3. Nothing of it is drawn.
B21On paper the references read, the addresses written in full.
B22Two entries sharing a key: the console says so, and the second replaces the first.
B23The bibliography is shown whole in a presentation. How this is done is the slides pagination.
B24A reference is read whole on a narrow screen: what numbers it and what dates it never take the width its text needs. The columns follow the width of the screen, at every moment and not only when the page opens.
B25What a reference opens, its abstract and its BibTeX source, is read whatever the columns show. Hiding a column takes away a column, never the content of a row that has none: B13 and B14 hold at every width.
B26In a presentation, what acts upon the bibliography is not shown: neither the search field nor the column selector. An audience reads what is on the screen and acts on nothing; what is read on its own stays, the sorting of a column being written as well as done.

The citations

What a citation has to do
No.Requirement
C1A citation is written between two words of a sentence, without breaking the paragraph.
C2A citation is not mistaken for the title of a work written in the text.
C7A citation bears a BibTeX key and names the reference having that key.
C8A citation whose key names nothing stays visible, and says it is missing.
C9An incomplete reference can still be consulted from the citation.
C10Keys naming no reference are said in the console before the author reads.
C11A reference is numbered the first time it is cited.
C12Later citations of the same reference bear that same number.
C13Numbers follow the order the citations appear in the text.
C14A single sequence of numbers for the whole document.
C15A citation shows nothing but its number.
C16A screen reader says "Reference" and the number. It does not say the brackets.
C19The number never goes alone to the next line.
C21The whole reference can be read without leaving the sentence.
C22The publication can be reached without leaving the sentence.
C23The abstract can be reached without leaving the sentence.
C24Reading can be stopped, and taken up where it was left.
C25The beginning and the end of a consultation are said, not only shown.
C26A link leads from a citation to its reference in the bibliography.
C27From a reference, a link leads to every place of the text where it is cited.
C28Consulting a reference does not scroll the page.
C29On paper the numbers and the bibliography stay. What is read on a screen only does not print.
C30Opening the page again gives the same numbers.
C31The bibliography exists before the table of contents is built.
C32Without JavaScript, the sentence stays readable.

Decisions

The numbers

They follow the order the citations appear in the text, in a single sequence for the whole document. The bibliography is built in that order, so it is already the order it prints in.

Why: the column of numbers then gives what no other column gives, the place where a reference is first cited. Reading from one end to the other, the numbers go up, which tells a reader whether a reference is a new one without opening anything. An alphabetical order would give a sequence with no apparent logic.

Where the columns give way

On a narrow screen the number and the year are not shown, and the reference takes the whole width. Nothing else changes: the table stays a table, its columns stay columns, and the reader turns the two of them back on from the column selector the bibliography builds with its search field.

When: whenever the screen crosses that width, and not only when the page opens. A device is turned over and a window is resized without anything being loaded again, and the columns follow. Between two crossings, what the reader checked is left alone: the width decides the default, never the choice.

Why not stack the entry: laying a row out as blocks takes the roles of a table away from it, and a screen reader stops saying which cell it is reading and under which header. Hiding a column costs none of that, and the selector is the component the sortable table is built with.

Why at all: the number and the year are two characters and four characters, but a column asks for a share of the width all the same. Measured on a reference of 413 characters, they take 186 pixels out of 800, leaving 581 to the text, which reads in six lines. On a screen of 400 pixels they take 225 and leave 185, which is a dozen characters a line and a reference thirty lines tall.

Where: at the step of the phone held sideways, and not at the mobile border of the framework. A tablet held upright has the width for the three columns, and hiding them there would waste it.

Counted in what: in font sizes, 38.75 of them, and never in pixels. That is 620 pixels for a text of 16 and 698 for a text of 18, so the columns give way sooner in contrast mode, where the text is written larger. A media query could not do this, its condition being read before any variable is resolved; this threshold is held in JavaScript, which has no such limit.

What this is not: a feature withheld from a small screen. Everything the bibliography does on a wide screen, it does on a phone. Only the columns checked at the opening differ.

The citation in the source

A citation is a span bearing a data-bibtex attribute. Three consequences.

A span is allowed between two words of a sentence, which details is not: a browser closes the paragraph when it meets it, so it cannot stand inside a sentence. The attribute is what tells a citation from a cite element bearing the title of a work. And what is written inside the span is what a reader gets when JavaScript does not run, replaced by the number as soon as it does.

What opens, and what closes

Several contents may stay open at the same time, and none closes on its own: closing what nobody asked to close makes what is being read disappear.

The focus does not move when a content opens, so the page does not scroll; it comes back to the control when it closes, which matters when the closing came from inside the content. Whether a content is open is read on its control, which already declares it for a screen reader: keeping it a second time would make two truths possible.

The addresses

They come from the BibTeX fields, and they are optional. BibTeX has a single URL field; when a second address is needed, NOTE holds it. This is a habit of the house, not a standard, so what an address leads to is never read in the name of its field: it is read in the address itself.

Nothing is ever completed by going to the internet. Data that are well kept do not need it.

The language

Everything the program writes follows the language of the document. The language is read on the element, and is never written in the code. A text that cannot follow it says which language it is in, as WCAG 3.1.2 asks.

What is said to whoever wrote the document

In the console, and nowhere else: a key used twice, a key naming no reference. A reference that is never cited is not worth a message. The reader is told nothing: a bibliography that could not be built is not their doing.

The model

What the data are made of

Entities
EntityWhat it carries
Reference Known by its BibTeX key: its type, its fields, its abstract, and the entry as it was written.
Author Only exists as part of a reference: its place among the signatories, its given name, particle, family name and suffix.
Link Only exists as part of a reference: an address.
Citation Known by itself: its place in the order the citations appear.
CitedKey Only exists as part of a citation: its place in it, the key as written, and the page aimed at when there is one.

Two things are computed and never stored: the number of a reference, which is given at its first citation and does not exist for a reference nobody cites, and what an address leads to, which is read in the address.

How this was designed

The way, and why it is written here

Design first, then the tests, then the code. The design is a Merise analysis, from the communication between the actors down to where the code goes, and the UML diagrams that lead to it. It is written here, in full, so that whoever picks the work up has everything on one page.

The working notes are in notes/bibliography/. This chapter says the same thing, and is the one that is kept up to date. The two domains, the bibliography and the citations, are not a starting point: they came out of the operations below.

MCC: who exchanges what

ActorWhat it is
The authorWrites the BibTeX entries and the text that cites them. She runs nothing
The readerAsks for the page, then consults, sorts, searches, follows a link, prints
The programRuns in the browser of whoever opens the page
The consoleWhere what the author has to know is said
FlowFromToWhat
F1The authorThe documentThe BibTeX entries, in the page or in a file next to it
F2The authorThe documentThe text, and the citations written in its sentences
F3The readerThe programThe request for the page
F4The programThe documentThe numbered citations and the bibliography
F5The programThe authorDuplicate keys, keys naming nothing, in the console
F6The readerThe programA consultation, a sort, a search, a link, a move, a print
F7The programThe readerWhat was asked, said as well as shown

Nothing is ever asked of the internet: a document reads its own data.

MCD: the associations

The entities are in the chapter above. What ties them:

AssociationLeg 1Leg 2Comes from
has for authorREFERENCE (0,n)AUTHOR (1,1)A reference without an author is shown all the same
has for linkREFERENCE (0,n)LINK (1,1)A reference may have no link at all
carriesCITATION (1,n)CITED_KEY (1,1)A citation carries at least one key
namesCITED_KEY (0,1)REFERENCE (0,n)A key may name nothing, and a reference may never be cited

MCT: the eight operations

OperationTriggered whenProduces
Op1, prepare the referencesThe BibTeX data are thereThe references, and a console message per duplicate key
Op2, number the citations and tie them to the referencesThe references are ready and the text is thereThe numbered citations, and a console message per key naming nothing
Op3, compose the bibliographyThe references are readyThe bibliography
Op4, consult a referenceA consultation is asked forThe reference, or "missing reference"; the start and the end are said
Op5, sort or filterA sort or a search is asked forThe bibliography sorted or filtered, and what changed is said
Op6, reach a publicationA link is followedThe publication
Op7, go from a citation to its reference, and backThe move is asked forA request to reach a place in the document, named by the reference or by the place of the citation
Op8, printPrinting is asked forThe printable document

Op3 does not need Op2: that is where the two domains come from, and publications.html is the proof, a bibliography with no citation at all.

Op8 is not "print" in the strict sense: it removes what only makes sense on a screen, and the browser lays the document on the pages. Laying a composed document on surfaces of fixed height is an operation of its own, and the slides need it too, which is what the slides pagination is about.

Op7 shows nothing by itself. It knows which place is wanted, never what it takes to show it, that depending on the support the document is read on. It therefore produces a request, and the treatment that answers it, reaching a place in the document, is modelled where the supports are, in the slides pagination. C26 and C27 are held by the two together: this dossier names the place, that one shows it. The place named never travels in the address of the page, which holds where the reader stands and nothing else.

Op5 is the only operation a support can take away. What triggers it, a search or a choice of columns, is asked for by whoever reads and acts; an audience does neither. So Op3 composes the bibliography without what triggers Op5 when it composes it in a presentation, and Op5 is then never triggered. What is read on its own stays, the order of a sorted column being written in its header and not only drawn. B26.

Three requirements are not operations: the work gives the same result every time, the bibliography exists before the table of contents is built, and the sentence stays readable when no operation has run.

MOT: where, when, and by whom

In the browser of whoever opens the page. Two moments, and both are requests from the reader: the request for the page, once, and a request inside the page, once per request.

PFWhat it doesWhenWhere it comes out
PF1Prepares the referencesRequest for the pageConsole
PF2Numbers the citations and ties them to the referencesRequest for the pagePage and console
PF3Composes the bibliographyRequest for the pagePage
PF4Makes a reference consultableRequest in the pagePage
PF5Sorts or filtersRequest in the page, which a presentation does not offer: what would ask for it is not composed there. B26Page
PF6Leads to the publicationRequest in the pageOutside site
PF7Names the place a citation or a reference leads toRequest in the pageA request handed to the procedure that reaches a place, whatever the support
PF8PrintsRequest in the pagePaper

PF1 before PF2 and PF3. PF3 before the table of contents is built. PF2 is not needed by PF3. Nothing is kept from one opening to the next: everything starts again, and gives the same result.

MLD: the tables

  • REFERENCE (key, type, BibTeX fields, abstract, bibtex_text)
  • AUTHOR (key, place, given_name, particle, family_name, suffix)
  • LINK (key, address)
  • CITATION (citation_id, place_in_the_text)
  • CITED_KEY (citation_id, place_in_the_citation, written_key, key, page_aimed_at)

An author and a link exist only as part of a reference, so they carry its key. The key of a cited key may be empty: what is written may name no reference. Two rules the keys do not hold: a citation carries at least one key, and two citations never share a place in the text.

Not in the tables: the number of a reference, and what an address leads to. Both are computed.

MPD: where each table exists

TableIn the sourceWhile runningOn screen
REFERENCEa BibTeX entryan objecta row of the table
AUTHORthe AUTHOR fielda list held by the objectin the cell of the reference
LINKthe URL and NOTE fieldsa list held by the objectin the cell of the links
CITATIONan element written in a paragraphthat same element, in document orderthe number
CITED_KEYan attribute of that elementthe keys read in itnothing of its own

What the author writes is <span data-bibtex="bigi2022lrec">Bigi, 2022</span>: a span is allowed inside a sentence, the attribute carries the key and tells a citation from a <cite> holding a title, and what is written inside stays readable when no operation has run.

Everything the program writes follows the language of the document, read on the element and never written in the code, which is the WCAG 3.1.2 criterion.

MOpT: where the code goes

ModuleWhat it doesProcedure
readingTakes the BibTeX data in the page, or asks for thembefore PF1
preparationSplits the entries, converts LaTeX, keeps the addresses, spots duplicate keysPF1
bibliographyBuilds the tablePF3
citationsNumbers the citations and ties them to the referencesPF2
consultationOpens, closes, announcesPF4
sortingSorts, filters, announcesPF5
assemblyCalls the others in order, before the table of contentsthe order itself
presentationSays what each support shows of what the others built: a presentation shows no control, a printed page no buttonthe emission rules of PF3, PF5 and PF8

The presentation module holds no treatment: it takes nothing in and gives nothing back, it only says what of a built bibliography each support shows. That is why the same bibliography, built once, is read on a page, on a slide and on paper. PF6 and PF7 need no module at all: they are links.

Written where each is: the modules that treat under wexa_statics/js/extras/book/, the presentation module in wexa_statics/css/extras/bibbook.css.

UML, and where it is written

The class diagram is the chapter below, the sequence when the page opens and the states of a consultation are the two chapters after it. The classes that carry the data come from the MLD, those that do the work from the MOpT, one per module. The presentation module has none: it holds no treatment, so there is nothing for a class to do.

The classes

What carries the data

Their fields are private and set at construction. Nothing modifies them afterwards, and what they give back is either a string or a copy.

Data classes, under js/extras/book/
ClassFileWhat it is
Referencebibreference.jsOne BibTeX entry, cut apart.
Authorbibauthor.jsOne signatory.
Linkbiblink.jsOne address, and what it leads to.
Citationbibcitation.jsOne place of the text where references are cited.
CitedKeybibcitedkey.jsOne key written in a citation.
CitedReferencebibcitedref.jsWhat a reference owes to the text: its number and its places.

What does the work

Working classes
ClassFileWhat it does
BibtexSourcebibsource.jsTakes the data. The only one that knows where they come from.
BibtexParserbibparser.jsCuts the entries apart. Never raises.
ReferenceFormatterbibformatter.jsDisplays a reference according to its type.
BibliographyTablebibtable.jsBuilds the table. Knows nothing of the citations.
CitationIndexbibcite.jsNumbers the citations and ties them to references.
ReferenceDisclosurebibdisclosure.jsOpens and closes one content.
BibliographyControlsbibcontrols.jsSorts and searches, says what changed, and checks the columns the width has room for.
BookBibliographybibbook.jsCalls the others in order. The entry point.
Labelslabels.jsWrites in the language of the document.

Errors

Three levels, and one place that catches.

What happens when something is wrong
LevelWhatWhat the program does
1 Nothing can be done: no BibTeX data, nowhere to put the bibliography. An error, caught by BookBibliography, said in the console. The rest of the page does not move.
2 One reference is concerned: an unreadable entry, a missing field, an unknown type. Nothing is raised. It is displayed with what it has, and what is missing is seen.
3 The author has to know: a key used twice, a key naming nothing. Nothing is raised. A message in the console, and the work goes on.

run() never raises, and is the only place in the program that writes try. An error that is not a BibliographyError is a mistake in the program, and has to be seen.

When the page opens

In order

This is the only moment where the order matters. Everything else happens on a request from the reader.

What calls what
No.Who callsWho answersWhat is asked
1The browserBookBibliographyrun(), which gives back a promise
2BookBibliographyBibtexSourceThe BibTeX data
3BookBibliographyBibtexParserThe references, by key
4BibtexParserThe consoleThe keys used twice
5BookBibliographyCitationIndexThe citations, numbered and made to show it
6CitationIndexThe consoleThe keys naming nothing
7BookBibliographyCitationIndexThe number and the places of each cited reference
8BookBibliographyBibliographyTableThe table
9BookBibliographyReferenceDisclosureOne per content that opens, all closed
10BookBibliographyBibliographyControlsSorting and searching, put on the table
11BibliographyControlsThe column selectorThe columns the width has room for, checked. The reader may check the others
12The browserThe table of contentsBuilt, and it sees the heading of the bibliography

The citations are numbered before the place of the bibliography is looked for: they are in the text, and the text is there. A document with nowhere to put its bibliography still reads.

read() may ask a server for a file, so run() gives back a promise, and whatever builds the table of contents waits for it. That is what holds C31.

Nothing is kept

Everything starts again at every opening, and gives the same result: the order of the text does not change, so the numbers do not either.

Consulting a reference

Two states

What is true in each state
StateWhat is true
Closed The control declares itself closed. The content is neither seen, nor reached by the keyboard, nor read by a screen reader.
Open The control declares itself open. The content is seen, TAB goes through it, a screen reader reads it.

Activating the control opens it or closes it: clicking, Enter or Space, which a button answers to without anything being written for them. A control placed inside the content closes it too.

What changes nothing

  • Opening another content: several stay open at the same time.
  • Sorting: it moves rows, it opens and closes nothing.
  • Searching: a content left open comes back open with its reference.
  • Printing: what opens on a screen does not print, and the state stays.

What the classes promise

Rules that hold everywhere

These are worth more than any list of signatures: they say what a caller never has to check.

  • A field, a list or a map that is absent gives back an empty string, an empty array or an empty map, never null. The one exception is CitedKey.reference, because a key naming nothing is a case C8 asks to treat apart.
  • The fields of a data class are private and set at construction. What they give back is a copy, so nothing outside can change what the BibTeX data say.
  • BibtexParser.parse() never raises: an unreadable entry is left aside and said in the console, and the others are parsed all the same.
  • CitationIndex.index() never raises, and starts again from nothing at every call.
  • BookBibliography.run() never raises, and is the only place that writes try.
  • ReferenceDisclosure.open() and close() have no precondition: calling either twice does nothing wrong.

Where a number comes from

The number of a reference is nowhere in the data. It is given at the first citation, taken up by the later ones, and does not exist for a reference nobody cites. It travels from CitationIndex to BibliographyTable in one object, CitedReference, together with the places the reference is cited at, and it travels through BookBibliography: the table never speaks to the citations.

The contracts, class by class

How to read them

+ public, - private, / derived and never stored, {readOnly} does not change after construction, {ordered} the order matters, [0..1] may be absent. 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. The types are the ones written in the JSDoc.

The data classes

Reference
OperationSignatureContract
constructor(key, type, fields, authors, links, source)pre: key and type are not empty. post: the object does not change any more
get authors(): Author[]post: in the order they sign
get links(): Link[]post: may be empty
get abstract(): Stringpost: '' when there is none, never null
field(name: String): Stringpre: name is not empty. post: '' when the field is missing, never null
searchLink(): Linkpost: always a link, built from the title and the first author

field() always giving a string is what lets ReferenceFormatter write no existence test at all.

Author, Link, Citation, CitedKey, CitedReference
OperationSignatureContract
Author.constructor(place, firstName, particle, lastName, suffix)pre: place is 1 or more. The four names may be empty, never null
Author.text(): Stringpost: the whole name, no extra space, never null
Author.sortValue(): Stringpost: family name first, then given name
Link.constructor(address: String)pre: address is not empty
Link./kind(): LinkKindpost: one of pdf, repository, publisher, search, other, read in the address
Citation.constructor(element, place, citedKeys)pre: citedKeys holds at least one
Citation.showNumber(number: Number): voidpre: number is 1 or more. post: the number in brackets, the accessible name "Reference" and the number, and a non-breaking space before it
Citation.showMissing(): voidpost: [?] and the accessible name "missing reference". No number is given
CitedKey.constructor(place, writtenKey, reference, targetPage)pre: writtenKey is not empty. reference is null when no reference bears that key
CitedKey.get reference(): Referencepost: may give null, the one exception to the no-null rule
CitedReference(number, places)What CitationIndex gives and BibliographyTable receives, so that the two never talk to each other

other exists in LinkKind so that an address nothing recognises is shown all the same, as a plain link. A reference is looked up before a CitedKey is built, never set afterwards.

The working classes

BibtexSource, BibtexParser, ReferenceFormatter
OperationSignatureContract
BibtexSource.constructor(element, address)pre: at least one of the two is given
BibtexSource.read(): Promise<String>post: a text that is not empty, or raises MissingBibtexData
BibtexSource.readFromPage(): Stringpost: '' when the element is not there
BibtexSource.readFromAddress(): Promise<String>post: '' when the request fails. Never goes to the internet, only to the given address
BibtexParser.parse(text: String): Map<String, Reference>pre: text is not empty. post: a map, possibly empty. Never raises
BibtexParser.parseEntry(text: String): Reference [0..1]post: null when the entry cannot be read, and it is said in the console
BibtexParser.parseAuthors(text: String): Author[]post: in the order they sign. Empty when the field is missing
BibtexParser.decodeLatex(text: String): Stringpost: no known LaTeX notation left. What is not recognised stays as it is
ReferenceFormatter.format(reference: Reference): DocumentFragmentpre: reference is not null. post: never empty, even for an unknown type
ReferenceFormatter.templateFor(type: String): String[]post: the fallback template when the type is unknown

BibtexSource is the only class that knows where the data come from. templates says, for each type, which fields and in which order: changing a display is changing that map, and nothing else.

BibliographyTable, CitationIndex, ReferenceDisclosure, BibliographyControls, BookBibliography, SortaTable
OperationSignatureContract
BibliographyTable.build(references, cited): HTMLTableElementpre: neither map is null, cited may be empty. post: one row per reference, each bearing an identifier; the number column exists only when cited is not empty; a caption and column heads declared as such
BibliographyTable.buildRow(reference, cited [0..1]): HTMLTableRowElementpost: the number, the year, the formatted reference, what can be opened. The reference cell carries the value it is sorted on
BibliographyTable.backLinks(places: HTMLElement[]): DocumentFragmentpost: one numbered link per place. An empty fragment when the list is empty
CitationIndex.index(root, references): voidpre: root is not null. post: every citation shows its number or its absence; the numbers run from 1 to n without a gap, in document order; two citations of the same key bear the same number. Never raises
CitationIndex.citedReferences(): Map<String, CitedReference>pre: index() has been called. post: empty when no citation was found
ReferenceDisclosure.constructor(control, content)pre: both exist, and content follows control in document order
ReferenceDisclosure./isOpen(): Booleanpost: read on the control, never stored apart
ReferenceDisclosure.open(): voidpre: none. post: the content is visible, the control declares itself open, the start is said, and the focus has not moved
ReferenceDisclosure.close(): voidpre: none. post: the content is hidden, the control declares itself closed, the end is said, and the focus is on the control
BibliographyControls.sortBy(column: Number): voidpre: the column exists. post: the rows are sorted, the numbers have not moved, what changed is said
BibliographyControls.filter(word: String): voidpre: none. post: the rows the word does not appear in are hidden; an empty word gives them all back; what changed is said
BookBibliography.run(): Promise<void>post: never raises. Every exception is caught and said in the console. The page stays readable whatever happens
SortaTable.columnVisibility(columnIndex: Number, show: Boolean): voidpre: none. post: only the cells belonging to that column are hidden or shown. A cell spanning several columns belongs to none of them and is never touched, so what a row opens stays readable. B25

How an error travels

LevelWhat happensWhat the program does
1Nothing can be done: no BibTeX data, no place to put the bibliographyAn exception, caught by BookBibliography, said in the console. The rest of the page does not move
2One reference is concerned: a badly written entry, a missing field, an unknown typeNo exception. The reference is shown with what it has, and the lack is seen
3The author has to know: a duplicate key, a key naming nothingNo exception. A message in the console, and the work goes on

Three exception classes: BibliographyError, the mother, raised by nobody; MissingBibtexData, raised by BibtexSource.read(); MissingBibliographyPlace, raised by BookBibliography.run(). No other exception is raised by the program.

One handler, on run(). It catches BibliographyError, so both of them in one gesture, writes the message in the console, and ends without undoing what was already built. Anything that is not a BibliographyError is a programming mistake, and has to be seen.

An error in JavaScript must never do worse than the absence of JavaScript: without it the sentence stays readable, and that stays true when the program stops.

How BibTeX is read

Four algorithms, and where they come from

They come from bib-list.js, written in 2008. Its code is not reused; these four readings are, because they are right and they handle what a naive one gets wrong.

What the parser does
WhatHow
Cutting the entries Braces are counted, never matched by a regular expression. A brace preceded by a backslash does not count. An entry starts at an "@" met outside any brace and ends when the count is back to zero. An "@" starting a line while an entry is still open means a closing brace is missing: the entry is closed by force, and reading starts again there.
Cutting one entry It is read backwards. The last equal sign is looked for, the value taken from there, then the last comma before it, which gives the name of the field. What is left at the beginning carries the type and the key. Reading backwards is what makes a value holding commas and equal signs cost nothing, and an abstract always holds some.
Telling a real equal sign Braces are counted backwards from the end up to the equal sign: when the count is not zero, that sign sits inside a value. A value delimited by double quotes is checked apart, since its braces are balanced even when the sign belongs to an equation.
Cutting the names Names are separated by " and ". Each follows one of the three forms BibTeX allows: "First von Last", "von Last, First", "von Last, Jr, First"; the number of commas says which. The particle is recognised by the case of the word, read on the first letter met outside braces, with a third caseless case for digits and punctuation, which belongs to the family name.

What was not taken

bib-list.js converts LaTeX notations through a closed list of thirteen replacements, whose own comment admits it is incomplete, and produces HTML entities where plain characters are wanted. It also erases every brace, which loses the case a {SPPAS} protects.

Here, accents are converted by rule, an accent and a letter, and the braces that protect a case are removed without touching what they protect. A notation nobody knows is left as it was written rather than thrown away.