En bref
Un recueil d’essais de plusieurs auteurs. Chaque essai montre son auteur sous le titre et se termine par sa propre liste de références, comme dans les ouvrages collectifs.
Ce que vous allez composer
The Working Page, un petit recueil d’essais sur l’histoire de l’imprimerie, dirigé par deux chercheurs et écrit par trois. Chaque essai arrive de son contributeur sous forme de fichier Markdown avec son propre bloc BibTeX, et le livre le garde ainsi : un volume de 155 × 235 mm en Libre Caslon, une page de titre rouge, et des chapitres qui s’ouvrent sur un numéro, un titre et le nom du contributeur. Chaque chapitre se termine sur sa propre liste « References » en Chicago auteur-date, qui ne contient que les ouvrages cités par l’essai. Printing Press as an Agent of Change d’Eisenstein est cité par deux contributeurs et figure donc dans leurs deux listes ; New Introduction to Bibliography de Gaskell fait de même dans les chapitres 1 et 3.
Cette recette répond à
- Comment donner à chaque chapitre d’un ouvrage collectif son propre auteur et sa propre bibliographie ?
- Comment citer des ouvrages et construire la bibliographie en APA, en IEEE ou dans un autre style de citation ?
La réponse courte
// Citations are [@key] in the text; each contributor's BibTeX goes in a :::references block
// in their own chapter. Register the engine once, before the first build.
registerCitationEngine(createCiteprocEngine({ styles: STYLES, locales: LOCALES }));
const citations = {
style: 'chicago-author-date', // the humanities' author-date: (Eisenstein 1979)
bibliography: {
// 'chapter': a :::bibliography lists the works its own document cites, so a work two
// contributors cite appears in both lists. 'book' (the default) would print one list,
// after the last chapter. The scope is per document, not per H1: each essay must be a
// document of its own in buildBundle (see the chapters region).
scope: 'chapter',
title: '', // no bold title paragraph: each chapter has its own ## References heading
fontSize: em(0.9), lineHeight: pt(12.4), hangingIndent: mm(5), entrySpacing: pt(2.6),
},
};
// Numbering and disambiguation still see the whole book: two Smiths of 2001 in different
// chapters would print 2001a and 2001b, as one bibliography would.
Ingrédients
- Fonctionnalités
- Bibliographie tirée des référencesCitations dans un style bibliographiqueLivres construits chapitre par chapitreAttributs de titreOuvertures composéesTable des matièresTitres courants et foliosTitres courants selon le rôle de la pageStyles de titreChapitres non numérotésCouvertures, pages de titre et colophonsAncrer les éléments de maquetteEncadrés flottantsMarges en miroirPalette de couleurs sémantiqueExport PDF
- Utilise aussi
- EncadrésTitres numérotésCouleur du papierPolices intégrées au PDFTitres courants par section
- Typographie
- Libre Caslon Text, Libre Caslon Display, IBM Plex Sans Condensed (SIL OFL 1.1)
- Ressources
- Aucune : chaque image est dessinée en code
Préparation
#1 · Un document par contributeur
// A chapter's :::bibliography lists what that document cites; one Markdown file holding all
// three essays would make every list repeat the works of the chapters before it.
const chapters = [front, lowe, okafor, ferrer].map((markdown) => ({ markdown }));
const book = () => buildBundle({ chapters, config: config(), resources: [] });
La portée de la réponse courte est celle d’un document. buildBundle met en page les quatre documents comme un seul livre : numéros de page, numéros de chapitre et table des matières se suivent sans interruption, tandis que chaque :::bibliography rassemble les citations de son propre fichier. Les références restent là où le contributeur les a écrites : une clé définie dans un chapitre vaut pour tout le livre, une seule entrée partagée aurait donc suffi, mais des chapitres autonomes peuvent être échangés ou réordonnés sans casser la liste d’un autre essai.
#2 · La signature est un attribut du titre
// # The Compositor's Day {author="Margaret Lowe" short="The Compositor's Day"}
const byline = text('byline', '{attr.author}', { fontFamily: TEXT, italic: true,
fontSize: pt(12), color: col('ink'), align: 'left' }, below('title', 4));
const versoAuthor = head('verso-author', '{attr.author}', 'even',
at('page', 'top-left', MARGIN.outer + 8, 13)); // in the running head
const tocAuthor = { enabled: true, attr: 'author', fontFamily: TEXT, fontSize: pt(9.5),
color: col('muted') }; // a line under each title in the contents (italic by default)
Le titre de chaque essai porte author="…" et un titre short="…" pour le titre courant. L’ouverture imprime l’auteur sous le titre, le titre courant du verso nomme l’auteur de l’essai auquel appartient la page, et la table des matières imprime le nom sur une ligne sous chaque entrée. Rien dans les pages liminaires du livre ne liste les contributeurs deux fois.
#3 · L’ouverture
// Nine lines of reserve and a line of margin under them (the level's marginBottom): ten
// lines, 48 mm, under a one-line title. A two-line title reaches past the reserve, and the
// margin then carries the text a line lower, clear of the rule.
const opener = { enabled: true, minHeight: pt(LEAD * 9), slot: { elements: [
text('kicker', t({ en: 'Chapter {number}', es: 'Capítulo {number}' }), { ...label,
fontSize: pt(8.5), letterSpacing: pt(1.7), color: col('accent') },
at('container', 'top-left', 0, 4)),
text('title', '{titleText}', { fontFamily: DISPLAY, fontSize: pt(28), lineHeight: 1.08,
color: col('ink'), align: 'left', overflow: 'wrap' }, below('kicker', 3, { width: 'fill' })),
byline,
{ kind: 'rule', id: 'rule', direction: 'horizontal', thickness: pt(1.2), color: col('accent'),
placement: { ...below('byline', 6), size: { width: mm(16) } } },
] } };
Surtitre, titre et signature s’empilent depuis le haut de la zone de texte, chacun ancré sous le précédent : un titre de deux lignes, comme celui du chapitre 3, fait descendre avec lui la signature et le filet. La réserve fait descendre le texte de 48 mm, dix lignes, sous un titre d’une ligne ; un titre de deux lignes prend une ligne de plus, si bien que le filet reste à l’écart du texte et que le chapitre 3 commence une ligne plus bas que les deux autres.
#4 · Des titres courants pour un livre à plusieurs auteurs
function head(id, content, parity, placement, look = {}) { // hoisted: the byline uses it
return { ...text(id, content, { ...label, fontWeight: 500, fontSize: pt(7.5),
letterSpacing: pt(1.1), color: col('muted'), ...look }, placement), parity, pages: 'body' };
}
const folio = { fontWeight: 600, color: col('ink') };
const header = { elements: [
head('verso-folio', '{pageNumber}', 'even', at('page', 'top-left', MARGIN.outer, 13), folio),
versoAuthor,
head('recto-title', '{attr.short}', 'odd', at('page', 'top-right', -(MARGIN.outer + 8), 13),
{ align: 'right' }),
head('recto-folio', '{pageNumber}', 'odd', at('page', 'top-right', -MARGIN.outer, 13),
{ ...folio, align: 'right' }),
] };
const footer = { elements: [{ ...head('drop-folio', '{pageNumber}', 'all',
at('container', 'top', 0, 9), { ...folio, align: 'center' }), pages: 'opener' }] };
Un ouvrage collectif nomme le contributeur au verso et le chapitre au recto, là où une monographie imprimerait le titre du livre et le chapitre. Les titres courants sont filtrés sur pages: 'body' : les pages d’ouverture ne portent donc qu’un folio en pied.
#5 · Les pages liminaires
const bare = { numbered: false, toc: false, header: { elements: [] }, footer: { elements: [] } };
const cover = { enabled: true, slot: { elements: [
{ kind: 'box', id: 'field', style: { backgroundColor: col('accent') },
placement: { ...at('bleed', 'top-left'), size: { width: 'fill', height: mm(150) } } },
text('title', '{titleText}', { fontFamily: DISPLAY, fontSize: pt(58), lineHeight: 1,
color: col('paper'), align: 'left', overflow: 'wrap' },
{ ...at('page', 'top-left', MARGIN.inner, 64), size: { width: mm(118) } }),
text('subtitle', '{subtitle}', { fontFamily: TEXT, italic: true, fontSize: pt(15),
color: col('paper'), align: 'left' }, below('title', 5)),
text('editors', '{attr.editors}', { ...label, fontSize: pt(9), letterSpacing: pt(1.8),
color: col('accent') }, at('page', 'top-left', MARGIN.inner, 162)),
text('contributors', '{attr.contributors}', { fontFamily: TEXT, italic: true, fontSize: pt(12),
color: col('ink'), align: 'left' }, below('editors', 3)),
text('imprint', '{attr.imprint}', { ...label, fontWeight: 500, fontSize: pt(7.5),
letterSpacing: pt(1.5), color: col('muted') }, at('page', 'bottom-left', MARGIN.inner, -16)),
] } };
const contentsOpener = { enabled: true, minHeight: mm(40), slot: { elements: [
text('kicker', '{title}', { ...label, fontSize: pt(8.5), letterSpacing: pt(1.7),
color: col('accent') }, at('container', 'top-left', 0, 4)),
text('title', '{titleText}', { fontFamily: DISPLAY, fontSize: pt(28), color: col('ink'),
align: 'left' }, below('kicker', 3)),
] } };
const contents = {
levels: [{ level: 1, fontFamily: TEXT, fontSize: pt(12.5), lineHeight: pt(LEAD),
numberFontFamily: LABEL, numberFontSize: pt(10), numberFontWeight: 600,
numberColor: col('accent'), numberWidth: mm(6), numberGap: mm(3), marginBottom: pt(LEAD) }],
pageNumber: { fontFamily: LABEL, fontSize: pt(9), fontWeight: 600, color: col('ink'),
width: mm(7) },
leader: { char: '. ', gap: mm(2) },
subtitle: tocAuthor,
};
La page de titre et la table des matières sont deux titres non numérotés du premier document, sans titres courants ni entrée dans la table des matières. Leurs maquettes lisent {title} et {subtitle} dans le frontmatter, et les directeurs et contributeurs dans les attributs du titre lui-même.
La recette complète
// ═══ Postext Cookbook · Nº 098 · An edited volume with a bibliography per chapter ═════ // https://postext.dev/en/cookbook/edited-volume-chapter-bibliographies // Code: MIT · Text: original (CC BY 4.0) · Pictures: none // Fonts: Libre Caslon Text & Display, IBM Plex Sans Condensed (OFL 1.1) · Needs postext ≥ 1.28.0 // Three essays by three contributors, each a Markdown document of its own with its own // BibTeX block, laid out by buildBundle as one volume: every chapter closes on its own list. import { buildBundle, prepareFonts, withLoadedFonts, renderPageToCanvas, registerCitationEngine, } from 'https://esm.sh/postext'; import { renderToPdf, decompressWoff2 } from 'https://esm.sh/postext-pdf'; import { createCiteprocEngine, STYLES, LOCALES } from 'https://esm.sh/postext-citeproc'; const LANG = 'en'; // @lang: the language of the sample document ('en' | 'es') const RECIPE = 'edited-volume-chapter-bibliographies'; // ─── 1 · Design ───────────────────────────────────────────────────────────── // #region palette: printer's red on a warm paper, the rest in ink const palette = { ink: '#211c19', // text: a warm near-black accent: '#8e2b1f', // printer's red: the cover field, kickers, the references heading rule: '#cdbfb2', // hairlines muted: '#6b5f57', // running heads, the contents' contributors, the colophon paper: '#fcfaf6', // the page, and the type on the red field }; const col = (id) => ({ hex: palette[id], model: 'hex', paletteId: id }); const colorPalette = Object.entries({ ...palette, 'main-color': palette.accent }) .map(([id, hex]) => ({ id, name: id, value: { hex, model: 'hex' } })); // #endregion const TEXT = 'Libre Caslon Text', DISPLAY = 'Libre Caslon Display'; const LABEL = 'IBM Plex Sans Condensed'; const MARGIN = { top: 23, bottom: 22, inner: 20, outer: 18 }; // mm, mirrored const LEAD = 13.8; // body leading in pt: the baseline grid const label = { fontFamily: LABEL, fontWeight: 600, textTransform: 'uppercase', align: 'left' }; const at = (to, edge, x = 0, y = 0) => ({ anchor: { to, edge }, offset: { x: mm(x), y: mm(y) } }); const below = (id, y, size) => ({ ...at(`#${id}`, 'below', 0, y), ...(size && { size }) }); const text = (id, content, look, placement) => ({ kind: 'text', id, content, ...look, placement }); // #region answer: one list per chapter: scope 'chapter' over a book of separate documents // Citations are [@key] in the text; each contributor's BibTeX goes in a :::references block // in their own chapter. Register the engine once, before the first build. registerCitationEngine(createCiteprocEngine({ styles: STYLES, locales: LOCALES })); const citations = { style: 'chicago-author-date', // the humanities' author-date: (Eisenstein 1979) bibliography: { // 'chapter': a :::bibliography lists the works its own document cites, so a work two // contributors cite appears in both lists. 'book' (the default) would print one list, // after the last chapter. The scope is per document, not per H1: each essay must be a // document of its own in buildBundle (see the chapters region). scope: 'chapter', title: '', // no bold title paragraph: each chapter has its own ## References heading fontSize: em(0.9), lineHeight: pt(12.4), hangingIndent: mm(5), entrySpacing: pt(2.6), }, }; // Numbering and disambiguation still see the whole book: two Smiths of 2001 in different // chapters would print 2001a and 2001b, as one bibliography would. // #endregion // #region byline: the contributor, from the heading, in three places // # The Compositor's Day {author="Margaret Lowe" short="The Compositor's Day"} const byline = text('byline', '{attr.author}', { fontFamily: TEXT, italic: true, fontSize: pt(12), color: col('ink'), align: 'left' }, below('title', 4)); const versoAuthor = head('verso-author', '{attr.author}', 'even', at('page', 'top-left', MARGIN.outer + 8, 13)); // in the running head const tocAuthor = { enabled: true, attr: 'author', fontFamily: TEXT, fontSize: pt(9.5), color: col('muted') }; // a line under each title in the contents (italic by default) // #endregion // #region opener: kicker, title and byline over a short red rule, sunk ten lines // Nine lines of reserve and a line of margin under them (the level's marginBottom): ten // lines, 48 mm, under a one-line title. A two-line title reaches past the reserve, and the // margin then carries the text a line lower, clear of the rule. const opener = { enabled: true, minHeight: pt(LEAD * 9), slot: { elements: [ text('kicker', t({ en: 'Chapter {number}', es: 'Capítulo {number}' }), { ...label, fontSize: pt(8.5), letterSpacing: pt(1.7), color: col('accent') }, at('container', 'top-left', 0, 4)), text('title', '{titleText}', { fontFamily: DISPLAY, fontSize: pt(28), lineHeight: 1.08, color: col('ink'), align: 'left', overflow: 'wrap' }, below('kicker', 3, { width: 'fill' })), byline, { kind: 'rule', id: 'rule', direction: 'horizontal', thickness: pt(1.2), color: col('accent'), placement: { ...below('byline', 6), size: { width: mm(16) } } }, ] } }; // #endregion // #region running-heads: contributor on the verso, short title on the recto, folios outside function head(id, content, parity, placement, look = {}) { // hoisted: the byline uses it return { ...text(id, content, { ...label, fontWeight: 500, fontSize: pt(7.5), letterSpacing: pt(1.1), color: col('muted'), ...look }, placement), parity, pages: 'body' }; } const folio = { fontWeight: 600, color: col('ink') }; const header = { elements: [ head('verso-folio', '{pageNumber}', 'even', at('page', 'top-left', MARGIN.outer, 13), folio), versoAuthor, head('recto-title', '{attr.short}', 'odd', at('page', 'top-right', -(MARGIN.outer + 8), 13), { align: 'right' }), head('recto-folio', '{pageNumber}', 'odd', at('page', 'top-right', -MARGIN.outer, 13), { ...folio, align: 'right' }), ] }; const footer = { elements: [{ ...head('drop-folio', '{pageNumber}', 'all', at('container', 'top', 0, 9), { ...folio, align: 'center' }), pages: 'opener' }] }; // #endregion // #region front: the title page on a red field, and the contents const bare = { numbered: false, toc: false, header: { elements: [] }, footer: { elements: [] } }; const cover = { enabled: true, slot: { elements: [ { kind: 'box', id: 'field', style: { backgroundColor: col('accent') }, placement: { ...at('bleed', 'top-left'), size: { width: 'fill', height: mm(150) } } }, text('title', '{titleText}', { fontFamily: DISPLAY, fontSize: pt(58), lineHeight: 1, color: col('paper'), align: 'left', overflow: 'wrap' }, { ...at('page', 'top-left', MARGIN.inner, 64), size: { width: mm(118) } }), text('subtitle', '{subtitle}', { fontFamily: TEXT, italic: true, fontSize: pt(15), color: col('paper'), align: 'left' }, below('title', 5)), text('editors', '{attr.editors}', { ...label, fontSize: pt(9), letterSpacing: pt(1.8), color: col('accent') }, at('page', 'top-left', MARGIN.inner, 162)), text('contributors', '{attr.contributors}', { fontFamily: TEXT, italic: true, fontSize: pt(12), color: col('ink'), align: 'left' }, below('editors', 3)), text('imprint', '{attr.imprint}', { ...label, fontWeight: 500, fontSize: pt(7.5), letterSpacing: pt(1.5), color: col('muted') }, at('page', 'bottom-left', MARGIN.inner, -16)), ] } }; const contentsOpener = { enabled: true, minHeight: mm(40), slot: { elements: [ text('kicker', '{title}', { ...label, fontSize: pt(8.5), letterSpacing: pt(1.7), color: col('accent') }, at('container', 'top-left', 0, 4)), text('title', '{titleText}', { fontFamily: DISPLAY, fontSize: pt(28), color: col('ink'), align: 'left' }, below('kicker', 3)), ] } }; const contents = { levels: [{ level: 1, fontFamily: TEXT, fontSize: pt(12.5), lineHeight: pt(LEAD), numberFontFamily: LABEL, numberFontSize: pt(10), numberFontWeight: 600, numberColor: col('accent'), numberWidth: mm(6), numberGap: mm(3), marginBottom: pt(LEAD) }], pageNumber: { fontFamily: LABEL, fontSize: pt(9), fontWeight: 600, color: col('ink'), width: mm(7) }, leader: { char: '. ', gap: mm(2) }, subtitle: tocAuthor, }; // #endregion const config = () => ({ locale: t({ en: 'en-us', es: 'es' }), colorPalette, citations, page: { sizePreset: 'custom', width: mm(155), height: mm(235), dpi: 150, backgroundColor: col('paper'), margins: { top: mm(MARGIN.top), bottom: mm(MARGIN.bottom), left: mm(MARGIN.inner), right: mm(MARGIN.outer), mirror: true } }, layout: { layoutType: 'single' }, bodyText: { fontFamily: TEXT, fontSize: pt(9.6), lineHeight: pt(LEAD), color: col('ink'), boldColor: col('ink'), italicColor: col('ink'), referenceColor: col('ink'), textAlign: 'justify', firstLineIndent: mm(4.5), indentAfterHeading: false, hyphenation: { enabled: true }, optimalLineBreaking: true, maxWordSpacing: 1.7, avoidWidows: true, avoidOrphans: true, avoidRunts: true }, // 'remainder': a subhead that opens a page keeps the half line above it and stands as // close to its text as the subheads set in mid-page. headings: { fontFamily: DISPLAY, fontWeight: 400, color: col('ink'), columnHeadSpace: 'remainder', levels: [ // 'any': an essay opens on the next page, recto or verso, as in most edited volumes. { level: 1, numberingTemplate: '{1}', marginBottom: pt(LEAD), breakBefore: { enabled: true, parity: 'any' }, advancedDesign: opener }, { level: 2, fontFamily: TEXT, italic: true, fontSize: pt(11), lineHeight: pt(LEAD * 1.5), numberingTemplate: '', marginTop: pt(LEAD * 0.5), marginBottom: pt(0) }, ] }, headingStyles: [ { id: 'cover', ...bare, span: 'page', advancedDesign: cover, marginBottom: pt(0) }, { id: 'contents', ...bare, advancedDesign: contentsOpener, marginBottom: pt(0) }, // The references heading: the label face in red, out of the contents. { id: 'references', toc: false, fontFamily: LABEL, fontWeight: 600, italic: false, fontSize: pt(8.5), letterSpacing: pt(1.7), textTransform: 'uppercase', color: col('accent'), lineHeight: pt(LEAD * 2), marginTop: pt(LEAD), marginBottom: pt(0) }, ], toc: contents, calloutStyles: [{ id: 'colophon', placement: 'bottom', backgroundEnabled: false, stripe: { enabled: true, side: 'top', width: pt(0.5), color: col('rule') }, padding: { top: mm(2.5), right: pt(0), bottom: pt(0), left: pt(0) }, marginBottom: pt(0), body: { fontFamily: LABEL, fontSize: pt(7.5), lineHeight: pt(10.5), color: col('muted'), textAlign: 'left', firstLineIndent: pt(0) } }], header, footer, }); // ─── 2 · Content ──────────────────────────────────────────────────────────── const front = String.raw`---Exemple Markdown · 13 lignes · content.en.md
title: "The Working Page" subtitle: "Essays on Printing, Type and Reading" --- # The Working Page {style="cover" editors="Edited by Helen Ashby and Tomás Ribera" contributors="Margaret Lowe · Daniel Okafor · Lucía Ferrer" imprint="Quire Editions · Edinburgh · 2026"} # Contents {style="contents"} :::toc :::callout{type="colophon"} Set in Libre Caslon Text, Libre Caslon Display and IBM Plex Sans Condensed (SIL OFL). Text: original, CC BY 4.0. The volume, its editors and its contributors are fictional; the works they cite are real. :::`; // title page and contents (content.<lang>.md) const lowe = String.raw`# The Compositor’s Day {author="Margaret Lowe" short="The Compositor’s Day"}Exemple Markdown · 44 lignes · content.lowe.en.md
Every page printed by hand passed through a compositor before it reached the press. He stood at a pair of cases, the capitals in the upper one and the small letters in the lower, read a few words of his copy and picked the sorts one at a time into the composing stick in his left hand. When the stick was full he slid the lines onto a galley; when there were lines enough for a page he tied them up with cord and set the page aside until the whole forme could be imposed and locked into its chase. Joseph Moxon described the routine in his *Mechanick Exercises* of 1683–84, the first full manual of printing in English, and most of what bibliographers later wrote about the compositor starts from his account [@gaskell1972]. The work was paid by the piece. A compositor was credited with the number of ens he set, and his speed, his spelling and his care decided what the reader received. That is why the compositor matters to anyone who edits an early printed text: between the author’s manuscript and the printed sheet stood a man with his own habits, working against the clock, who could misread a word, run short of a letter or change the spelling to make a line fit. ## Reading the evidence of the type The type itself keeps a record of this work. A sort with a nicked serif or a broken stem prints the same flaw wherever it is used, and once the page has been printed the compositor distributes the type back into the case, so the damaged letter turns up again a few pages later. Charlton Hinman followed hundreds of such letters through the Shakespeare First Folio of 1623 and worked out the order in which its pages were set, which compositor set them and how the work moved between the cases [@hinman1963]. His method rested on patience and a Hinman collator, but its premise was simple: type is a finite stock, and its movements can be traced. Spelling gave a second kind of evidence. One compositor preferred *doe* and *goe*, another *do* and *go*; one set a colon where his partner set a comma. Where the copy did not dictate a form, the compositor’s preference showed through, and a page set by one man reads differently from a page set by another. Bibliographers assembled such preferences into profiles and used them to assign pages and to weigh the authority of a reading [@gaskell1972]. ## Printers of the mind The weakness of these methods lay in what they assumed about the printing house. Analyses of type recurrence often supposed that a shop worked through one book at a time, a compositor setting the pages in order and a press printing each forme as soon as it was ready. D. F. McKenzie tested that picture against the records of Cambridge University Press for the years 1696 to 1712, which survive in unusual detail, and found that it did not hold [@mckenzie1969]. Several books were in production at once. Compositors moved from one job to another as copy arrived; pressmen printed sheets of different books in the same week; work stopped and restarted as paper, money or the author’s revisions allowed. McKenzie’s conclusion was that bibliographers had built their arguments on “printers of the mind”, an orderly workshop that existed in their reasoning and not in the archive. A pattern found in the type could be explained by more than one sequence of work, and a single sequence could not be inferred from it without outside evidence. His essay did not end the study of compositors, but it changed its tone: inferences now came with the conditions under which they held. ## What the compositor made The compositor also produced something larger than any single page. Because the same setting of type printed every copy of a sheet, an edition of several hundred copies carried the same text, page for page, to readers who would never meet. Elizabeth Eisenstein made this repetition the centre of her account of early modern Europe: the identical copy, she argued, allowed scholars in different cities to compare the same tables, maps and texts, to correct them in later editions and to build on one another’s work [@eisenstein1979]. The second essay in this volume returns to her argument and to the objections it met. Yet the copies of an edition were never quite identical. Errors were often caught while a sheet was on the press, and the forme was unlocked and corrected without the sheets already printed being thrown away, so that corrected and uncorrected states were bound up together in the same edition [@gaskell1972]. Hinman found such press variants throughout the Folio [@hinman1963]. The compositor’s day, in other words, made both the stability that Eisenstein described and the small instabilities that bibliographers spend their careers collating. ## References {style="references"} :::bibliography :::references{format=bibtex} @book{gaskell1972, author = {Gaskell, Philip}, title = {A New Introduction to Bibliography}, publisher = {Clarendon Press}, address = {Oxford}, year = 1972} @book{hinman1963, author = {Hinman, Charlton}, title = {The Printing and Proof-Reading of the First Folio of Shakespeare}, publisher = {Clarendon Press}, address = {Oxford}, year = 1963} @article{mckenzie1969, author = {McKenzie, D. F.}, title = {Printers of the Mind: Some Notes on Bibliographical Theories and Printing-House Practices}, journal = {Studies in Bibliography}, volume = 22, pages = {1--75}, year = 1969} @book{eisenstein1979, author = {Eisenstein, Elizabeth L.}, title = {The Printing Press as an Agent of Change: Communications and Cultural Transformations in Early-Modern Europe}, publisher = {Cambridge University Press}, address = {Cambridge}, year = 1979} :::`; // content.lowe.<lang>.md: chapter 1, and so on const okafor = String.raw`# What Fixity Meant {author="Daniel Okafor" short="What Fixity Meant"}Exemple Markdown · 48 lignes · content.okafor.en.md
Few books in the history of the book have been argued with as long as Elizabeth Eisenstein’s. *The Printing Press as an Agent of Change* appeared in two volumes in 1979 and proposed that the shift from script to print was itself a cause of the Renaissance revival of learning, of the Reformation and of the new science of the seventeenth century [@eisenstein1979]. Her case rested on a few features that print had and manuscript did not: dissemination in hundreds of copies at once, standardisation of text and image, and above all what she called typographical fixity, the capacity of an edition to preserve a text unchanged and to let it be corrected and improved in the next. The thesis was large, and its reception divided along a familiar line. Historians of ideas found in it an explanation of why scholarship became cumulative after 1500. Historians of printing pointed to the variety of what presses actually produced, from error-filled almanacs to pirated editions, and asked whether fixity was a property of print or a result that some printers achieved some of the time. ## Credit and piracy Adrian Johns gave the second answer its fullest form [@johns1998]. Studying the London book trade of the seventeenth century, he found that readers had good reason to distrust what they bought. Editions were reprinted without permission, attributed to authors who had not written them, or issued with the wrong date and imprint. The Stationers’ Company kept a register of titles to settle disputes among its members, but the register protected the trade’s own arrangements rather than the author’s text. A reader who wanted to know whether a printed book was what it claimed to be had to rely on the reputation of the printer and the bookseller, on the people who vouched for the edition, and on the conventions of the shop where it was sold. Fixity, in Johns’s account, was therefore something made. It took the work of authors who watched over their proofs, of booksellers who guarded their names, and of institutions such as the Royal Society, which licensed and supervised the books it sponsored. His most cited example is the Astronomer Royal, John Flamsteed, who saw his observations printed in 1712 in an edition he had not approved and spent years trying to recover and suppress it. Where Eisenstein saw a feature of the technology, Johns saw a set of practices that had to be learned, and that could fail. ## Circuits and models The debate between the two positions is easier to follow with a map of what a book passes through. Robert Darnton drew one in 1982: a communications circuit that runs from the author to the publisher, the printers, the shippers, the booksellers and the readers, and back to the author, with each stage shaped by economic, political and intellectual conditions [@darnton1982]. The model placed the history of books among the people who handled them, and many studies of the 1980s worked through it stage by stage. Thomas Adams and Nicolas Barker objected that Darnton’s circuit described the trade and lost sight of the object. They proposed a model built around the book itself and the events in its life: publication, manufacture, distribution, reception and survival [@adams1993]. The difference matters to the argument about fixity. In Darnton’s circuit, fixity belongs to the relations between printers, sellers and readers; in Adams and Barker’s model, it is also a question of which copies survived, where, and in what state. ## The form of the text D. F. McKenzie widened the question further in his Panizzi lectures, published in 1986 [@mckenzie1986]. Bibliography, he argued, should study texts as recorded forms and the processes of their transmission, including their production and their reception, and it should treat the form of a text as part of its meaning. His example was William Congreve, whose plays changed character when they were reset for the collected *Works* of 1710: the new layout divided the scenes differently, marked entrances in a new way and invited a different kind of reading. From McKenzie’s position the quarrel over fixity looks less like a quarrel. An edition can fix the words of a text and still change how it reads; a reprint can keep the meaning and lose the form that carried it. Eisenstein described what the press made possible, and Johns described what it took to make that possibility hold [@eisenstein1979; @johns1998]. Both are histories of the same pages, written from different ends of the circuit. ## References {style="references"} :::bibliography :::references{format=bibtex} @book{eisenstein1979, author = {Eisenstein, Elizabeth L.}, title = {The Printing Press as an Agent of Change: Communications and Cultural Transformations in Early-Modern Europe}, publisher = {Cambridge University Press}, address = {Cambridge}, year = 1979} @book{johns1998, author = {Johns, Adrian}, title = {The Nature of the Book: Print and Knowledge in the Making}, publisher = {University of Chicago Press}, address = {Chicago}, year = 1998} @article{darnton1982, author = {Darnton, Robert}, title = {What Is the History of Books?}, journal = {Daedalus}, volume = 111, number = 3, pages = {65--83}, year = 1982} @incollection{adams1993, author = {Adams, Thomas R. and Barker, Nicolas}, title = {A New Model for the Study of the Book}, booktitle = {A Potencie of Life: Books in Society}, editor = {Barker, Nicolas}, publisher = {British Library}, address = {London}, pages = {5--43}, year = 1993} @book{mckenzie1986, author = {McKenzie, D. F.}, title = {Bibliography and the Sociology of Texts}, series = {The Panizzi Lectures}, publisher = {British Library}, address = {London}, year = 1986} :::`; const ferrer = String.raw`# Punches, Matrices and the Name Garamond {author="Lucía Ferrer" short="Punches and Matrices"}Exemple Markdown · 45 lignes · content.ferrer.en.md
Before a compositor could set a page, someone had to make the letters he picked from the case. Printing spread quickly: Lucien Febvre and Henri-Jean Martin estimated that fifteen to twenty million copies of books had been printed in Europe before 1500 [@febvre1976]. Every one of those copies was printed from type cast in a mould, and every typeface began as a set of steel punches cut by hand at the size the reader would see. The sequence of work is well documented, though the hand skills it required have mostly been lost [@carter1969]. The punchcutter shaped the end of a steel bar into the reversed form of a letter, filing and engraving it and checking it against smoke proofs. The enclosed spaces of the letter, the counters of *a*, *e* or *o*, were usually struck into the punch with a counterpunch, which let him repeat the same counter in several letters of the fount. Fred Smeijers, who has cut punches himself, argues that the counterpunch explains much of the consistency of sixteenth-century faces: the shapes were related because they were made with the same tools [@smeijers1996]. ## From punch to sort The hardened punch was driven into a bar of copper to make a matrix. The matrix had to be justified, filed so that the letter sat at the right depth and position, and then fitted into a hand mould, an adjustable box of steel and wood into which the caster poured an alloy of lead, tin and antimony. Each pour gave one sort, and the finished type, rubbed and dressed, was sold to printers by weight [@gaskell1972]. Punches were the founder’s capital. They could be used for decades, lent, inherited or sold, and a set of strikes from them allowed another foundry to cast the same face. This is why the faces of a few French punchcutters of the mid-sixteenth century spread across Europe within a generation. ## Whose letters It also made attribution difficult. A face appears in a printer’s book long after it was cut, under the printer’s name and not the cutter’s. Harry Carter’s survey of early typography set out the evidence available to sort these questions: specimen sheets, inventories, contracts and the books themselves [@carter1969]. Hendrik Vervliet spent decades applying it to the French Renaissance, comparing faces letter by letter across hundreds of books, and his catalogues redistributed many types long credited to Claude Garamont among his contemporaries, Robert Granjon and Pierre Haultin among them [@vervliet2008]. The name Garamond had a modern history of its own. When foundries in the early twentieth century revived “Garamond” for machine composition, several of them took as their model types that had been cut not by Garamont but by Jean Jannon, a printer at Sedan, some sixty years after Garamont’s death. Beatrice Warde pointed this out in 1926. The revivals kept the name, and many digital faces still carry it. ## What the reader sees None of this is visible on the page as a reader meets it. The reader judges a book by how easily it reads. The bibliographer sees, in the same page, the trace of a punchcutter’s files, the wear of a matrix and the habits of the caster who justified it. Early printers bought their type by size names, pica, english, long primer, and judged it as the reader did, by the page it made [@gaskell1972]. The history of type begins in steel, but it was always written for that page. ## References {style="references"} :::bibliography :::references{format=bibtex} @book{febvre1976, author = {Febvre, Lucien and Martin, Henri-Jean}, title = {The Coming of the Book: The Impact of Printing, 1450--1800}, translator = {Gerard, David}, publisher = {NLB}, address = {London}, year = 1976} @book{carter1969, author = {Carter, Harry}, title = {A View of Early Typography up to about 1600}, publisher = {Clarendon Press}, address = {Oxford}, year = 1969} @book{smeijers1996, author = {Smeijers, Fred}, title = {Counterpunch: Making Type in the Sixteenth Century, Designing Typefaces Now}, publisher = {Hyphen Press}, address = {London}, year = 1996} @book{gaskell1972, author = {Gaskell, Philip}, title = {A New Introduction to Bibliography}, publisher = {Clarendon Press}, address = {Oxford}, year = 1972} @book{vervliet2008, author = {Vervliet, Hendrik D. L.}, title = {The Palaeotypography of the French Renaissance: Selected Papers on Sixteenth-Century Typefaces}, publisher = {Brill}, address = {Leiden}, year = 2008} :::`; // #region chapters: one document per contributor, each with its own references // A chapter's :::bibliography lists what that document cites; one Markdown file holding all // three essays would make every list repeat the works of the chapters before it. const chapters = [front, lowe, okafor, ferrer].map((markdown) => ({ markdown })); const book = () => buildBundle({ chapters, config: config(), resources: [] }); // #endregion // ─── 3 · Fonts ────────────────────────────────────────────────────────────── const FONTS = { // text, display and label faces 'Libre Caslon Text': ['400', '400i', '700'], 'Libre Caslon Display': ['400'], 'IBM Plex Sans Condensed': ['400', '500', '600'], }; // ─── 4 · Build & show ─────────────────────────────────────────────────────── const all = chapters.map((chapter) => chapter.markdown).join('\n'); await prepareFonts(all, config(), kitFonts(FONTS)); const docs = await withLoadedFonts(book, { ...kitFonts(FONTS), text: all }); // one VDTDocument per Markdown document showPages(docs, { title: t({ en: 'The Working Page', es: 'La página en obra' }) }); offerPdf(() => renderToPdf(docs, { fontProvider: fontsourceProvider }), `${RECIPE}.pdf`);Kit · core, fonts, viewer, pdf : identique dans toutes les recettes · 269 lignes
// ─── Kit ── helpers shared by every Cookbook recipe · postext.dev/cookbook ───── // ─── Kit · core v1 ── the same in every recipe · postext.dev/cookbook function mm(value) { return { value, unit: 'mm' }; } function pt(value) { return { value, unit: 'pt' }; } function em(value) { return { value, unit: 'em' }; } /** The sample language's string: t({ en: 'Figure', es: 'Figura' }). */ function t(strings) { return strings[LANG] ?? Object.values(strings)[0]; } /** A file in this recipe's assets folder, served from the Postext repo by jsDelivr. */ function asset(file) { return `https://cdn.jsdelivr.net/gh/drnachio/postext@main/cookbook/${RECIPE}/assets/${file}`; } // ─── Kit · fonts v3 ── the same in every recipe · postext.dev/cookbook // Postext loads the faces a config asks for before layout (prepareFonts, // buildDocumentWithFonts) and asks the kit for the files: Fontsource's, the // files the PDF embeds too. /** The options of buildDocumentWithFonts / prepareFonts / withLoadedFonts: * the Fontsource resolver, and the faces of FONTS loaded with the ones the * config names. FONTS = { 'Family Name': ['400', '400i', '700'] }. */ function kitFonts(FONTS = {}) { const faces = Object.entries(FONTS).flatMap(([family, specs]) => specs.map((spec) => ({ family, weight: parseInt(spec, 10), style: spec.endsWith('i') ? 'italic' : 'normal' }))); return { resolve: fontsourceResolver, faces }; } /** A face's Fontsource files, in a fixed order: latin, then latin-ext and greek * when `text` needs them and the family ships them (kitSubsetsFor), each with * its unicode-range. Null for a weight or slant Fontsource does not ship. */ async function fontsourceResolver(family, weight, style, { text = '' } = {}) { const id = fontsourceId(family); const meta = await fontsourceMeta(family); if (meta && !(meta.weights.includes(weight) && meta.styles.includes(style))) return null; kitStatus('Loading fonts…'); const at = await fontsourceAt(id); return ['latin', ...kitSubsetsFor(text, meta)].map((subset) => ({ source: `${at}files/${id}-${subset}-${weight}-${style}.woff2`, unicodeRange: kitRanges()[subset], })); } /** The unicode-range of each Fontsource file the kit loads (a function: the * kit is inlined after the pen's code, which runs before a const would be set). */ function kitRanges() { return { latin: 'U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,' + 'U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD', 'latin-ext': 'U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,' + 'U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF', greek: 'U+0370-03FF', }; } /** For the cjk, arabic and comics blocks, which add their own files: the * faces of `faces` = { 'Family Name': ['400', '400i', '700'] }. `text` is the sample: * č ł † α χ also load latin-ext and greek files (kitSubsetsFor). With * `optional`, a face Fontsource does not ship is skipped instead of failing. * The files are added once all have loaded, in the order asked (latin, then * latin-ext, then greek), whatever order they arrive in: the last one added * wins a character two files hold. Resolves to the number of faces added. */ async function loadFonts(faces, text = '', { optional = false } = {}) { kitStatus('Loading fonts…'); const ranges = kitRanges(); const jobs = []; for (const [family, specs] of Object.entries(faces)) { const id = fontsourceId(family); const todo = [...new Set(specs)].map((spec) => [parseInt(spec, 10), spec.endsWith('i') ? 'italic' : 'normal']) .filter(([weight, style]) => !hasFace(family, weight, style)); // before any await const at = fontsourceAt(id); const meta = optional || /[^\0-ÿ]/u.test(text) ? await fontsourceMeta(family) : null; const subsets = ['latin', ...kitSubsetsFor(text, meta)]; for (const [weight, style] of todo) { if (optional && !(meta?.weights.includes(weight) && meta.styles.includes(style))) continue; for (const subset of subsets) { const url = `${await at}files/${id}-${subset}-${weight}-${style}.woff2`; const face = new FontFace(family, `url(${url}) format('woff2')`, { weight: String(weight), style, unicodeRange: ranges[subset] }); jobs.push(face.load().catch(() => { if (subset === 'latin' && !optional) throw new Error(`Fontsource has no ${family} ${weight} ${style}`); })); } } } const ready = await Promise.all(jobs).catch((error) => { kitFail(error); throw error; }); return ready.filter((face) => face && document.fonts.add(face)).length; } /** A loaded FontFace covers this family, weight and style (fonts.check() would * also say yes for families nobody declared). */ function hasFace(family, weight, style) { for (const face of document.fonts) { if (face.status !== 'loaded' || face.style !== style) continue; if (face.family.replace(/^["']|["']$/g, '') !== family) continue; const [low, high = low] = face.weight.split(' ').map(Number); if (weight >= low && weight <= high) return true; } return false; } /** The files beyond latin `text` needs that `meta`'s family ships. */ function kitSubsetsFor(text, meta) { return [[/[Ā-˿ᴀ-ᶿḀ-ỿ†ℓⱠ-Ɀ꜠-ꟿ]/u, 'latin-ext'], [/[Ͱ-Ͽ]/u, 'greek']] .filter(([re, x]) => re.test(text) && meta?.subsets?.includes(x)).map(([, x]) => x); } /** Fontsource's id for a family: 'Source Serif 4' → 'source-serif-4'. */ function fontsourceId(family) { return family.toLowerCase().replace(/\s+/g, '-'); } /** A package's folder at the one version @5 names now (#766). */ function fontsourceAt(id, u = `https://cdn.jsdelivr.net/npm/@fontsource/${id}@`) { return (fontsourceAt.c ??= {})[id] ??= fetch(u + '5/package.json').then((r) => r.json()) .then((p) => p.version || 5, () => 5).then((v) => `${u}${v}/`); } /** The family's Fontsource metadata (weights, styles, subsets), or null. */ function fontsourceMeta(family) { fontsourceMeta.cache ??= new Map(); const id = fontsourceId(family); if (!fontsourceMeta.cache.has(id)) { fontsourceMeta.cache.set(id, fetch(`https://api.fontsource.org/v1/fonts/${id}`) .then((res) => (res.ok ? res.json() : null), () => null)); } return fontsourceMeta.cache.get(id); } // ─── Kit · viewer v2 ── the same in every recipe · postext.dev/cookbook /** The pages as spreads on a dark desk, page 1 alone, then verso | recto, * each painted when it scrolls near. Other options go to renderPageToCanvas. */ function showPages(docs, { title, width = 460, ...render } = {}) { const root = viewer(title); const pages = [docs].flat().flatMap((doc) => doc.pages.map((page) => ({ doc, page, n: (doc.pageIndexOffset ?? 0) + page.index }))); const spreads = []; let verso = null; for (const p of pages) { if (p.n % 2 === 1) { if (verso) spreads.push([verso, null]); verso = p; } else { spreads.push([verso, p]); verso = null; } } if (verso) spreads.push([verso, null]); const density = Math.min(window.devicePixelRatio || 1, 2); showPages.painter?.disconnect(); const painter = new IntersectionObserver((entries) => { for (const { isIntersecting, target } of entries) { if (!isIntersecting) continue; painter.unobserve(target); const { doc, page } = target.postext; renderPageToCanvas(page, doc, target, { ...render, scale: (width * density) / page.width }); } }, { rootMargin: '800px' }); showPages.painter = painter; root.replaceChildren(...spreads.map((pair) => { const spread = document.createElement('div'); spread.className = 'pt-spread'; for (const p of pair) { const figure = document.createElement('figure'); if (p) { const label = p.page.pageLabel || String(p.n + 1); const canvas = document.createElement('canvas'); canvas.postext = p; canvas.style.aspectRatio = `${p.page.width} / ${p.page.height}`; canvas.setAttribute('role', 'img'); canvas.setAttribute('aria-label', `Page ${label}`); const folio = document.createElement('figcaption'); folio.textContent = label; figure.append(canvas, folio); painter.observe(canvas); } else figure.className = 'pt-blank'; spread.append(figure); } return spread; })); kitStatus(`${pages.length} ${pages.length === 1 ? 'page' : 'pages'}`); document.documentElement.dataset.postext = 'ready'; return pages.length; } /** The desk, the bar and the error reporting, created once. */ function viewer(title) { if (!document.getElementById('pt-kit')) { document.head.insertAdjacentHTML('beforeend', `<style id="pt-kit"> :root { color-scheme: dark; } body { margin: 0; background: #0e1014; color: #b9bcc4; font: 13px/1.45 system-ui, sans-serif; } #pt-bar { position: sticky; top: 0; z-index: 1; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; padding: 10px 16px; background: rgb(14 16 20 / .92); backdrop-filter: blur(6px); border-bottom: 1px solid #23262d; } #pt-bar strong { color: #f4f1ea; font-weight: 600; } #pt-actions { display: flex; gap: 12px; margin-left: auto; } #pt-actions a, #pt-actions button { color: #d8a21a; font: inherit; background: none; border: 0; padding: 0; cursor: pointer; } #pages { display: grid; justify-items: center; gap: 48px; padding: 32px 16px 72px; } .pt-spread { display: flex; } .pt-spread figure { margin: 0; width: min(460px, 44vw); } .pt-spread canvas { display: block; width: 100%; background: #fff; box-shadow: 0 1px 2px rgb(0 0 0 / .5), 0 22px 44px -16px rgb(0 0 0 / .8); } .pt-spread figure:first-child canvas { box-shadow: inset -14px 0 14px -14px rgb(0 0 0 / .18), 0 1px 2px rgb(0 0 0 / .5), 0 22px 44px -16px rgb(0 0 0 / .8); } .pt-spread figcaption { margin-top: 10px; text-align: center; font: 600 10px/1 system-ui, sans-serif; letter-spacing: .18em; text-transform: uppercase; color: #6c7079; } .pt-blank { visibility: hidden; } @media (max-width: 760px) { .pt-spread { flex-direction: column; gap: 32px; } .pt-spread figure { width: min(460px, 92vw); } .pt-blank { display: none; } } </style>`); document.body.insertAdjacentHTML('afterbegin', '<header id="pt-bar"><strong id="pt-title"></strong><span id="pt-status" role="status"></span><span id="pt-actions"></span></header>'); document.getElementById('pt-title').textContent = document.title || 'Postext'; addEventListener('error', (event) => kitFail(event.error ?? event.message)); addEventListener('unhandledrejection', (event) => kitFail(event.reason)); } if (title) document.getElementById('pt-title').textContent = title; return document.getElementById('pages') ?? document.body.appendChild(Object.assign(document.createElement('main'), { id: 'pages' })); } function kitStatus(text) { viewer(); document.getElementById('pt-status').textContent = text; } function kitFail(error) { document.documentElement.dataset.postext = 'error'; kitStatus(`Error: ${error?.message ?? error}`); } // ─── Kit · pdf v3 ── the same in every recipe that exports a PDF /** The Fontsource files the screen used, as TrueType, with their range and * place: the nearest weight the family ships, upright with no italic; * latin, then what its letters need (kitSubsetsFor). */ async function fontsourceProvider(family, weight, style, request) { const id = fontsourceId(family); const meta = await fontsourceMeta(family); const weights = meta?.weights?.length ? meta.weights : [400, 700]; const w = weights.reduce((a, b) => (Math.abs(b - weight) < Math.abs(a - weight) ? b : a)); const s = style === 'italic' && meta && !meta.styles.includes('italic') ? 'normal' : style; const text = String.fromCodePoint(...(request?.codePoints ?? [])); const files = await Promise.all(['latin', ...kitSubsetsFor(text, meta)].map(async (subset, order) => { const res = await fetch(`${await fontsourceAt(id)}files/${id}-${subset}-${w}-${s}.woff2`); if (!res.ok) throw new Error(`Fontsource has no ${family} ${w} ${s} ${subset}`); return Object.assign(await decompressWoff2(new Uint8Array(await res.arrayBuffer())), { unicodeRange: kitRanges()[subset], order }); })); return files.length === 1 ? files[0] : files; } /** A "Build the PDF" button; then "Open the PDF" (a new tab: CodePen's frame * shows no PDFs) and a download link. */ function offerPdf(makePdf, filename) { viewer(); const button = Object.assign(document.createElement('button'), { type: 'button', textContent: 'Build the PDF' }); button.dataset.postextPdf = filename; button.addEventListener('click', async () => { button.disabled = true; button.textContent = 'Building the PDF…'; try { const bytes = await makePdf(); const url = URL.createObjectURL(new Blob([bytes], { type: 'application/pdf' })); const size = `${Math.max(1, Math.round(bytes.length / 1024))} KB`; button.replaceWith( Object.assign(document.createElement('a'), { href: url, target: '_blank', rel: 'noopener', textContent: 'Open the PDF ↗' }), Object.assign(document.createElement('a'), { href: url, download: filename, textContent: `Download ${filename} · ${size}` })); } catch (error) { button.disabled = false; button.textContent = 'Build the PDF'; kitFail(error); } }); document.getElementById('pt-actions').append(button); } // ─── /Kit ───────────────────────────────────────────────────────────────────────
Le script.js composé s’exécute tel quel : collez-le dans le script de module de n’importe quelle page, ou ouvrez la recette sur CodePen. Dossier de la recette sur GitHub ↗ (s’ouvre dans un nouvel onglet)
Variantes
#Une seule liste pour tout le volume
Certains éditeurs rassemblent tous les ouvrages dans une seule bibliographie en fin de livre. Changez la portée et supprimez les trois titres ## References ; la liste suit alors le dernier chapitre.
- scope: 'chapter',
- title: '', // no bold title paragraph: each chapter has its own ## References heading
+ scope: 'book',
+ title: 'Bibliography',#Citer en APA
Un volume de sciences sociales change le style et rien d’autre.
- style: 'chicago-author-date', // the humanities' author-date: (Eisenstein 1979)
+ style: 'apa',Erreurs fréquentes
Erreur fréquente
Une clé définie deux fois garde sa première entrée, sans bruit
Les références valent pour tout le livre : une clé écrite dans deux chapitres garde la première définition, et la seconde est ignorée sans avertissement. Dans un livre à plusieurs auteurs, préfixez les clés de chaque contributeur. Bibliographie tirée des références →
Erreur fréquente
Valeurs d’attribut : pas de { ni de } ; une valeur avec " entre apostrophes simples
Une valeur d’attribut s’arrête à l’accolade fermante : elle ne peut donc contenir ni { ni }. Une valeur qui contient un guillemet double se met entre apostrophes simples ; un signe dollar ne pose pas de problème. Attributs de titre →
Erreur fréquente
Un style de titre hérite du saut de page de son niveau
Une entrée headingStyles reprend de son niveau de titre chaque champ qu’elle omet, breakBefore compris. Une page de table des matières ou un colophon mis en forme sur un H1 après un :::pagebreak hérite de la parité 'odd' et atterrit derrière une page blanche. Donnez à un tel style breakBefore: { enabled: false }. Styles de titre →
scope: 'chapter'liste ce que cite le document avant le:::bibliography, pas ce que cite sa section H1. Avec tous les essais dans un seul fichier Markdown, la deuxième liste reprend les ouvrages du premier essai et la troisième ceux des deux premiers.- La première définition d’une clé l’emporte dans tout le livre. Si deux contributeurs utilisent tous deux
smith2001pour des ouvrages différents, l’essai suivant cite sans avertissement le livre du premier contributeur : donnez un préfixe aux clés de chaque contributeur, ou vérifiez les listes par rapport aux manuscrits. - La désambiguïsation est calculée pour tout le livre. Deux ouvrages différents de Smith parus en 2001 dans des chapitres différents peuvent s’imprimer 2001a et 2001b, même quand la liste d’un chapitre n’en contient qu’un.
- Un intertitre qui ouvre une page perd par défaut tout son espace au-dessus, et le calage sur la grille place alors dessous la fraction de ligne dont il a besoin : Whose letters, en haut de la page 10, serait plus éloigné de son texte que What the reader sees, plus bas sur la page.
headings.columnHeadSpace: 'remainder'garde cette fraction de ligne au-dessus de l’intertitre (titres). Ce réglage convient à un livre sur une colonne, où aucune colonne voisine ne montre que l’intertitre commence un peu plus bas.
Crédits
- Recette
- Ignacio Ferro
- Texte
- Texte original, CC BY 4.0
- Polices
- Libre Caslon Text (SIL OFL 1.1) · Libre Caslon Display (SIL OFL 1.1) · IBM Plex Sans Condensed (SIL OFL 1.1)
Modifier ce texte ↗ (s’ouvre dans un nouvel onglet)Dossier de la recette sur GitHub ↗ (s’ouvre dans un nouvel onglet)


