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.
| What | Why |
|---|---|
| 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.
| What | What 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
| No. | Requirement |
|---|---|
| B1 | The document reads its BibTeX data without going to the internet. |
| B2 | Every 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. |
| B3 | Accents and symbols written in LaTeX become plain characters. |
| B4 | A reference missing a field is displayed all the same, and what is missing is seen. |
| B6 | A reference whose type the program does not know is displayed all the same. |
| B9 | Each type has its own display: which fields, in which order. |
| B11 | Every author is displayed, whatever their number. Never "et al.". |
| B12 | A link to the PDF, a link to an open archive and a link to the publisher are told apart. |
| B13 | The BibTeX entry can be seen as it is written in the file. |
| B14 | The abstract can be read, when the reference has one. |
| B15 | Reading an abstract does not lose your place in the bibliography. |
| B16 | The references can be sorted by year, or by author. |
| B19 | Only the references a word appears in can be kept. |
| B20 | Sorting, 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. |
| B21 | On paper the references read, the addresses written in full. |
| B22 | Two entries sharing a key: the console says so, and the second replaces the first. |
| B23 | The bibliography is shown whole in a presentation. How this is done is the slides pagination. |
| B24 | A 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. |
| B25 | What 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. |
| B26 | In 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
| No. | Requirement |
|---|---|
| C1 | A citation is written between two words of a sentence, without breaking the paragraph. |
| C2 | A citation is not mistaken for the title of a work written in the text. |
| C7 | A citation bears a BibTeX key and names the reference having that key. |
| C8 | A citation whose key names nothing stays visible, and says it is missing. |
| C9 | An incomplete reference can still be consulted from the citation. |
| C10 | Keys naming no reference are said in the console before the author reads. |
| C11 | A reference is numbered the first time it is cited. |
| C12 | Later citations of the same reference bear that same number. |
| C13 | Numbers follow the order the citations appear in the text. |
| C14 | A single sequence of numbers for the whole document. |
| C15 | A citation shows nothing but its number. |
| C16 | A screen reader says "Reference" and the number. It does not say the brackets. |
| C19 | The number never goes alone to the next line. |
| C21 | The whole reference can be read without leaving the sentence. |
| C22 | The publication can be reached without leaving the sentence. |
| C23 | The abstract can be reached without leaving the sentence. |
| C24 | Reading can be stopped, and taken up where it was left. |
| C25 | The beginning and the end of a consultation are said, not only shown. |
| C26 | A link leads from a citation to its reference in the bibliography. |
| C27 | From a reference, a link leads to every place of the text where it is cited. |
| C28 | Consulting a reference does not scroll the page. |
| C29 | On paper the numbers and the bibliography stay. What is read on a screen only does not print. |
| C30 | Opening the page again gives the same numbers. |
| C31 | The bibliography exists before the table of contents is built. |
| C32 | Without 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
| Entity | What 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
| Actor | What it is |
|---|---|
| The author | Writes the BibTeX entries and the text that cites them. She runs nothing |
| The reader | Asks for the page, then consults, sorts, searches, follows a link, prints |
| The program | Runs in the browser of whoever opens the page |
| The console | Where what the author has to know is said |
| Flow | From | To | What |
|---|---|---|---|
| F1 | The author | The document | The BibTeX entries, in the page or in a file next to it |
| F2 | The author | The document | The text, and the citations written in its sentences |
| F3 | The reader | The program | The request for the page |
| F4 | The program | The document | The numbered citations and the bibliography |
| F5 | The program | The author | Duplicate keys, keys naming nothing, in the console |
| F6 | The reader | The program | A consultation, a sort, a search, a link, a move, a print |
| F7 | The program | The reader | What 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:
| Association | Leg 1 | Leg 2 | Comes from |
|---|---|---|---|
| has for author | REFERENCE (0,n) | AUTHOR (1,1) | A reference without an author is shown all the same |
| has for link | REFERENCE (0,n) | LINK (1,1) | A reference may have no link at all |
| carries | CITATION (1,n) | CITED_KEY (1,1) | A citation carries at least one key |
| names | CITED_KEY (0,1) | REFERENCE (0,n) | A key may name nothing, and a reference may never be cited |
MCT: the eight operations
| Operation | Triggered when | Produces |
|---|---|---|
| Op1, prepare the references | The BibTeX data are there | The references, and a console message per duplicate key |
| Op2, number the citations and tie them to the references | The references are ready and the text is there | The numbered citations, and a console message per key naming nothing |
| Op3, compose the bibliography | The references are ready | The bibliography |
| Op4, consult a reference | A consultation is asked for | The reference, or "missing reference"; the start and the end are said |
| Op5, sort or filter | A sort or a search is asked for | The bibliography sorted or filtered, and what changed is said |
| Op6, reach a publication | A link is followed | The publication |
| Op7, go from a citation to its reference, and back | The move is asked for | A request to reach a place in the document, named by the reference or by the place of the citation |
| Op8, print | Printing is asked for | The 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.
| PF | What it does | When | Where it comes out |
|---|---|---|---|
| PF1 | Prepares the references | Request for the page | Console |
| PF2 | Numbers the citations and ties them to the references | Request for the page | Page and console |
| PF3 | Composes the bibliography | Request for the page | Page |
| PF4 | Makes a reference consultable | Request in the page | Page |
| PF5 | Sorts or filters | Request in the page, which a presentation does not offer: what would ask for it is not composed there. B26 | Page |
| PF6 | Leads to the publication | Request in the page | Outside site |
| PF7 | Names the place a citation or a reference leads to | Request in the page | A request handed to the procedure that reaches a place, whatever the support |
| PF8 | Prints | Request in the page | Paper |
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
| Table | In the source | While running | On screen |
|---|---|---|---|
| REFERENCE | a BibTeX entry | an object | a row of the table |
| AUTHOR | the AUTHOR field | a list held by the object | in the cell of the reference |
| LINK | the URL and NOTE fields | a list held by the object | in the cell of the links |
| CITATION | an element written in a paragraph | that same element, in document order | the number |
| CITED_KEY | an attribute of that element | the keys read in it | nothing 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
| Module | What it does | Procedure |
|---|---|---|
| reading | Takes the BibTeX data in the page, or asks for them | before PF1 |
| preparation | Splits the entries, converts LaTeX, keeps the addresses, spots duplicate keys | PF1 |
| bibliography | Builds the table | PF3 |
| citations | Numbers the citations and ties them to the references | PF2 |
| consultation | Opens, closes, announces | PF4 |
| sorting | Sorts, filters, announces | PF5 |
| assembly | Calls the others in order, before the table of contents | the order itself |
| presentation | Says what each support shows of what the others built: a presentation shows no control, a printed page no button | the 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.
| Class | File | What it is |
|---|---|---|
Reference | bibreference.js | One BibTeX entry, cut apart. |
Author | bibauthor.js | One signatory. |
Link | biblink.js | One address, and what it leads to. |
Citation | bibcitation.js | One place of the text where references are cited. |
CitedKey | bibcitedkey.js | One key written in a citation. |
CitedReference | bibcitedref.js | What a reference owes to the text: its number and its places. |
What does the work
| Class | File | What it does |
|---|---|---|
BibtexSource | bibsource.js | Takes the data. The only one that knows where they come from. |
BibtexParser | bibparser.js | Cuts the entries apart. Never raises. |
ReferenceFormatter | bibformatter.js | Displays a reference according to its type. |
BibliographyTable | bibtable.js | Builds the table. Knows nothing of the citations. |
CitationIndex | bibcite.js | Numbers the citations and ties them to references. |
ReferenceDisclosure | bibdisclosure.js | Opens and closes one content. |
BibliographyControls | bibcontrols.js | Sorts and searches, says what changed, and checks the columns the width has room for. |
BookBibliography | bibbook.js | Calls the others in order. The entry point. |
Labels | labels.js | Writes in the language of the document. |
Errors
Three levels, and one place that catches.
| Level | What | What 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.
| No. | Who calls | Who answers | What is asked |
|---|---|---|---|
| 1 | The browser | BookBibliography | run(), which gives back a promise |
| 2 | BookBibliography | BibtexSource | The BibTeX data |
| 3 | BookBibliography | BibtexParser | The references, by key |
| 4 | BibtexParser | The console | The keys used twice |
| 5 | BookBibliography | CitationIndex | The citations, numbered and made to show it |
| 6 | CitationIndex | The console | The keys naming nothing |
| 7 | BookBibliography | CitationIndex | The number and the places of each cited reference |
| 8 | BookBibliography | BibliographyTable | The table |
| 9 | BookBibliography | ReferenceDisclosure | One per content that opens, all closed |
| 10 | BookBibliography | BibliographyControls | Sorting and searching, put on the table |
| 11 | BibliographyControls | The column selector | The columns the width has room for, checked. The reader may check the others |
| 12 | The browser | The table of contents | Built, 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
| State | What 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 isCitedKey.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 writestry.ReferenceDisclosure.open()andclose()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
| Operation | Signature | Contract |
|---|---|---|
| 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 | (): String | post: '' when there is none, never null |
| field | (name: String): String | pre: name is not empty. post: '' when the field is missing, never null |
| searchLink | (): Link | post: 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.
| Operation | Signature | Contract |
|---|---|---|
| Author.constructor | (place, firstName, particle, lastName, suffix) | pre: place is 1 or more. The four names may be empty, never null |
| Author.text | (): String | post: the whole name, no extra space, never null |
| Author.sortValue | (): String | post: family name first, then given name |
| Link.constructor | (address: String) | pre: address is not empty |
| Link./kind | (): LinkKind | post: 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): void | pre: 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 | (): void | post: [?] 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 | (): Reference | post: 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
| Operation | Signature | Contract |
|---|---|---|
| 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 | (): String | post: '' 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): String | post: no known LaTeX notation left. What is not recognised stays as it is |
| ReferenceFormatter.format | (reference: Reference): DocumentFragment | pre: 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.
| Operation | Signature | Contract |
|---|---|---|
| BibliographyTable.build | (references, cited): HTMLTableElement | pre: 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]): HTMLTableRowElement | post: 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[]): DocumentFragment | post: one numbered link per place. An empty fragment when the list is empty |
| CitationIndex.index | (root, references): void | pre: 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 | (): Boolean | post: read on the control, never stored apart |
| ReferenceDisclosure.open | (): void | pre: none. post: the content is visible, the control declares itself open, the start is said, and the focus has not moved |
| ReferenceDisclosure.close | (): void | pre: 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): void | pre: the column exists. post: the rows are sorted, the numbers have not moved, what changed is said |
| BibliographyControls.filter | (word: String): void | pre: 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): void | pre: 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
| Level | What happens | What the program does |
|---|---|---|
| 1 | Nothing can be done: no BibTeX data, no place to put the bibliography | An exception, caught by BookBibliography, said in the console. The rest of the page does not move |
| 2 | One reference is concerned: a badly written entry, a missing field, an unknown type | No exception. The reference is shown with what it has, and the lack is seen |
| 3 | The author has to know: a duplicate key, a key naming nothing | No 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 | How |
|---|---|
| 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.