feat: support readings and lecture rendering

This commit is contained in:
2026-08-08 16:24:50 -04:00
parent 468af3a815
commit f475c630e0
10 changed files with 1535 additions and 11 deletions
+67
View File
@@ -26,8 +26,75 @@ That gives you:
`build/` and `reports/` are in the generated `.gitignore`.
The other four are the repository's content and belong in review.
If the directory already has a `.gitignore`, `init` keeps it and inserts only the patterns it was missing at the top, so running this inside an existing repository costs you nothing.
Add `--with-examples` if you want a filled-in bank to read rather than an empty directory to stare at.
## Declare your texts once
Every work the course cites goes in `references`, keyed by the citation key you would use in a `.bib` file.
```yaml
references:
kuriyan2013molecules:
label: KKW
kind: book
role: required
title: 'The molecules of life: Physical and chemical principles'
authors: ['Kuriyan, John', 'Konforti, Boyana', 'Wemmer, David']
year: 2013
publisher: W. W. Norton & Company
base_url: https://library.scient.ing/kuriyan2013molecules/
note: On reserve at the Bevier Engineering Library.
```
`label` is the short form a reading list shows, and it has to name one work, because reports print it instead of the key.
`base_url` is what a reading's `path` is joined to, so the key appears once in the file rather than once per reading.
## Point readings at objectives
A reading names a location inside a reference and lists the objectives it serves.
```yaml
lectures:
L1.1:
title: Enthalpy
readings:
- ref: kuriyan2013molecules
locator: '§1.3'
path: '1/A/#3'
objectives: [lo-water-attenuation, lo-coulomb-estimate]
summary: >-
Ionic interactions: favorable in vacuum, attenuated ~80-fold by water.
focus: >-
The two magnitudes and the factor of 80.
skip: >-
Skip the unit-conversion derivation.
```
The three prose fields answer three different questions, and each has a different reader.
`summary` says what the section contains, `focus` says what to take from it, and `skip` says what to ignore.
A student report quotes `focus` at somebody who missed the objective; a lecture page prints all three.
The mapping lives on the reading rather than on the objective because objectives outlive editions.
When a textbook renumbers its sections, one block of `readings` changes and `learning_objectives` does not.
Going the other way is a scan: `coursebank lecture coverage` lists the readings behind each objective and flags the ones with none.
Set `order` on each objective if you want a lecture page to number them in teaching order.
The registry is a map, so declaration order is lost on load, and sorting by id would put `lo-enthalpy` ahead of `lo-first-law`.
A reading written as a plain string, which is what this field held before, still loads and is written back out unchanged.
## Generate the reading list
```console
$ coursebank lecture readings L1.1 --out lectures/l1_1-readings.qmd
wrote lectures/l1_1-readings.qmd
```
Objective numbers in the generated page (`_(LO 4, 7)_`) are positional, so they are computed at render time rather than written down.
Insert an objective and everything after it renumbers on the next build.
## Point your editor at the schemas
The schemas are the difference between authoring items and looking up field names.