diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index d8faf0242..622231a5e 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -62,11 +62,15 @@ defaults: shell: bash env: - HUGO_VERSION: 0.155.3 + # ---------------------------------------------------------------------------- + # Specify the deployment environment: staging or production + HUGO_ENVIRONMENT: ${{ vars.HUGO_ENVIRONMENT || 'staging' }} + HUGO_VERSION: 0.168.0 jobs: # ---------------------------------------------------------------------------- - # Validate that README.md references the correct Hugo version. + # Validate that pinned Hugo version references stay in sync + # (README.md, package.json, config/_default/module.yaml). # Only runs on push/pull_request, not scheduled runs. # validate-docs: @@ -77,26 +81,44 @@ jobs: - name: Check Hugo version consistency run: | - echo "Checking README.md for Hugo version $HUGO_VERSION" - + echo "Checking Hugo version consistency for $HUGO_VERSION" + # Check badge if ! grep -q "badge/Hugo-${HUGO_VERSION}" README.md; then echo "::error::README.md badge does not reference Hugo version $HUGO_VERSION" FAILED=1 fi - # Check download URL - if ! grep -q "hugo_extended_${HUGO_VERSION}_linux-amd64.deb" README.md; then - echo "::error::README.md download URL does not reference Hugo version $HUGO_VERSION" + # Check install instructions reference the pinned version. + # Accepts either a literal URL (hugo_extended_0.164.0_...) + # or the parameterized form (VER=0.164.0 + hugo_extended_${VER}_...). + if grep -q "hugo_extended_${HUGO_VERSION}_linux-amd64.deb" README.md; then + : + elif grep -q "VER=${HUGO_VERSION}" README.md && grep -q 'hugo_extended_${VER}_linux-amd64.deb' README.md; then + : + else + echo "::error::README.md install instructions do not reference Hugo version $HUGO_VERSION" + FAILED=1 + fi + + # Check npm wrapper stays on the pinned version (strict pin) + if ! grep -q "\"hugo-extended\": \"\\^${HUGO_VERSION}\"" package.json; then + echo "::error::package.json hugo-extended does not reference Hugo version $HUGO_VERSION (expected \"^$HUGO_VERSION\")" + FAILED=1 + fi + + # Check Hugo module minimum matches the pinned version + if ! grep -q "min: \"${HUGO_VERSION}\"" config/_default/module.yaml; then + echo "::error::config/_default/module.yaml hugoVersion.min does not reference Hugo version $HUGO_VERSION" FAILED=1 fi if [ "$FAILED" = "1" ]; then - echo "Update README.md to use Hugo version $HUGO_VERSION" + echo "Update README.md, package.json, and config/_default/module.yaml to use Hugo version $HUGO_VERSION" exit 1 fi - echo "README.md Hugo version references are consistent" + echo "Hugo version references are consistent" # ---------------------------------------------------------------------------- # Expose the Hugo version from the workflow environment as a job output. diff --git a/.gitignore b/.gitignore index e54678660..da691ffac 100644 --- a/.gitignore +++ b/.gitignore @@ -15,8 +15,12 @@ _site public/ tests/public_test/ node_modules/ +# Generated by "hugo mod npm pack" (see README "Node dependencies") +packages/hugoautogen/ _gen/ .hugo_build.lock +# Locally downloaded Hugo Debian packages (see README "Installing Hugo") +*.deb .coverage tests/__pycache__/ _vendor/ @@ -31,3 +35,5 @@ static/data/bibItems/ !/content/en/history/bibliography/_index.md !/content/en/history/bibliography/intake/ !/content/en/history/bibliography/intake/** +!/content/en/history/bibliography/zotero-resources/ +!/content/en/history/bibliography/zotero-resources/** diff --git a/README.md b/README.md index 24ef364a7..4f84ff804 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![GitHub Pages Deploy](https://github.com/Interlisp/Interlisp.github.io/actions/workflows/gh-pages.yml/badge.svg)](https://github.com/Interlisp/Interlisp.github.io/actions/workflows/gh-pages.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) -[![Hugo](https://img.shields.io/badge/Hugo-0.155.3-ff4088?logo=hugo)](https://gohugo.io/) +[![Hugo](https://img.shields.io/badge/Hugo-0.168.0-ff4088?logo=hugo)](https://gohugo.io/) [![Docsy](https://img.shields.io/badge/Theme-Docsy-blue)](https://www.docsy.dev/) The documentation repository for , the restoration @@ -54,7 +54,7 @@ cd Interlisp.github.io ./scripts/update_bibliography.sh # Start local development server -hugo server -e development +npm run hugo -- server -e development ``` Then open in your browser. @@ -65,18 +65,18 @@ Before working with this repository, ensure you have the following installed: | Tool | Version | Purpose | |------|---------|--------| -| [Hugo Extended](https://gohugo.io/installation/) | v0.145.0+ | Static site generator | +| [Hugo Extended](https://gohugo.io/installation/) | v0.168.0 (CI pins v0.168.0) | Static site generator | | [Go](https://go.dev/doc/install) | 1.24+ | Required for Hugo modules | -| [Node.js & npm](https://nodejs.org/) | Latest LTS | PostCSS and autoprefixer | +| [Node.js & npm](https://nodejs.org/) | v22+ (LTS 24) | Theme npm dependencies (Bootstrap, Font Awesome) | | [jq](https://jqlang.github.io/jq/) | Latest | Bibliography JSON processing | | curl, wget | System default | Script downloads | **Verify installations:** ```bash -hugo version # Should show "extended" and v0.145.0+ +hugo version # Should show "extended" and v0.168.0 go version # Should show 1.24+ -node --version # Should show v18+ or later +node --version # Should show v22+ or later jq --version # Any recent version ``` @@ -160,12 +160,18 @@ Local testing of updates requires running Hugo locally. Instructions for installing Hugo on various operating systems are at: [Installing Hugo](https://gohugo.io/getting-started/installing). **Interlisp uses the extended version of Hugo.** -For Ubuntu: +For Ubuntu (pinned extended edition, matches CI `HUGO_VERSION`): ```bash -wget https://github.com/gohugoio/hugo/releases/download/v0.155.3/hugo_extended_0.155.3_linux-amd64.deb - -sudo dpkg -i hugo_extended_0.155.3_linux-amd64.deb +VER=0.168.0 +DEB="hugo_extended_${VER}_linux-amd64.deb" +wget --retry-connrefused --waitretry=5 --read-timeout=30 --timeout=30 --tries=5 \ + -O "/tmp/${DEB}" "https://github.com/gohugoio/hugo/releases/download/v${VER}/${DEB}" +wget --retry-connrefused --waitretry=5 --read-timeout=30 --timeout=30 --tries=5 \ + -O "/tmp/hugo_${VER}_checksums.txt" "https://github.com/gohugoio/hugo/releases/download/v${VER}/hugo_${VER}_checksums.txt" +( cd /tmp && grep -F " ${DEB}" "hugo_${VER}_checksums.txt" | sha256sum -c - ) +sudo dpkg -i "/tmp/${DEB}" +rm -f "/tmp/${DEB}" "/tmp/hugo_${VER}_checksums.txt" ``` Verify installation: @@ -173,7 +179,7 @@ Verify installation: ```bash hugo version # Expected output: -hugo v0.155.3-8a858213b73907e823e2be2b5640a0ce4c04d295+extended linux/amd64 BuildDate=2026-02-08T16:40:42Z VendorInfo=gohugoio +hugo v0.168.0+extended linux/amd64 BuildDate=... ``` @@ -181,21 +187,29 @@ hugo v0.155.3-8a858213b73907e823e2be2b5640a0ce4c04d295+extended linux/amd64 Buil 1. Ensure bibliography data is available (see [Bibliography Data](#bibliography-data)) -2. Start the Hugo development server: +2. Install the theme's npm dependencies (Bootstrap, Font Awesome). Required — a + Docsy 0.16 module build reads them from `node_modules/`. `npm install` also + auto-generates the gitignored `packages/hugoautogen` workspace via a + `postinstall` hook, so there is no separate step: ```bash -hugo server --cleanDestinationDir --disableFastRender --renderToMemory +npm install ``` -Hugo will automatically download the Docsy theme and its dependencies as Hugo modules. Expected output: +3. Start the Hugo development server: + +```bash +npm run hugo -- server --cleanDestinationDir --disableFastRender --renderToMemory +``` + +Hugo will automatically download the Docsy theme as a Hugo module, and reads +Bootstrap and Font Awesome from `node_modules/` (installed above). Expected output: ```bash Watching for changes in /archetypes, /assets/{css,icons,js,scss}, /content/en/{history,project,software}, /layouts/{_default,_partials,_shortcodes,bibliography,redirect}, /package.json, /static/{Resources,data,docs,documentation,favicons} Watching for config changes in /config/_default, /config/development, /go.mod Start building sites … -hugo v0.155.3-8a858213b73907e823e2be2b5640a0ce4c04d295+extended linux/amd64 BuildDate=2026-02-08T16:40:42Z VendorInfo=gohugoio - -WARN WARNING: 298 sidebar entries have been truncated. To avoid this, increase `params.ui.sidebar_menu_truncate` to at least 398 (from 100) in your config file. Section: /history/bibliography +hugo v0.168.0+extended linux/amd64 BuildDate=... │ EN ──────────────────┼────── @@ -286,7 +300,7 @@ The following repository variables control the build and deployment process: | Variable | Description | Values | Default | |----------|-------------|--------|---------| | `HUGO_ENVIRONMENT` | Build environment used by the production workflow | `development`, `staging`, `production` | `production` | -| `HUGO_VERSION` | Hugo version used in CI/CD | Semantic version (e.g., `0.155.3`) | Set in workflow | +| `HUGO_VERSION` | Hugo version used in CI/CD | Semantic version (e.g., `0.168.0`) | Set in workflow | `HUGO_ENVIRONMENT` is resolved in `.github/workflows/gh-pages.yml` and passed as the `hugo-environment` input to the shared build workflow. The staging @@ -398,8 +412,7 @@ The repository follows the standard [Hugo directory structure](https://gohugo.io | Module | Version | Purpose | |--------|---------|---------| -| [google/docsy](https://github.com/google/docsy) | v0.14.3 | Technical documentation theme | -| docsy/dependencies | v0.7.2 | Docsy's required dependencies | +| [docsy/docsy](https://github.com/docsy/docsy) | v0.18.0 | Technical documentation theme (Hugo module `github.com/docsy/docsy/theme`) | Hugo modules are automatically downloaded when you run `hugo server` or `hugo build`. @@ -407,13 +420,20 @@ Hugo modules are automatically downloaded when you run `hugo server` or `hugo bu | Package | Purpose | |---------|---------| -| autoprefixer | Adds vendor prefixes to CSS for browser compatibility | | hugo-extended | Hugo binary for npm-based workflows | -| postcss / postcss-cli | CSS transformation pipeline | -| jquery | JavaScript library used by some Docsy components | -| tabpanel | Accessible tab panel widget | - -Install npm dependencies with `npm install` (optional for local development). +| sass-embedded | Dart Sass for custom SCSS compilation | + +The Docsy theme's own npm dependencies (Bootstrap and Font Awesome) are declared +in `packages/hugoautogen/package.json`, which is **auto-generated and gitignored**. +A `postinstall` hook runs `hugo mod npm pack` on every `npm install`/`npm ci`, so this +file — and the Bootstrap/Font Awesome install — is kept up to date automatically; there +is no need to run the pack step by hand or commit anything under `packages/`. When you +update Docsy, just run `npm install` and commit the updated `package.json` and +`package-lock.json`. + +Install npm dependencies with `npm install` (or `npm ci`). Since Docsy 0.16 sources Bootstrap +and Font Awesome from npm, this is **required** (not optional) for both local +development and CI builds. ### Search Configuration diff --git a/config/_default/imaging.yaml b/config/_default/imaging.yaml index 404ae9542..aa998c5f0 100644 --- a/config/_default/imaging.yaml +++ b/config/_default/imaging.yaml @@ -4,6 +4,10 @@ # # Configuration information available at: # https://gohugo.io/content-management/image-processing/#resampling-filter +# +# NOTE: The global `quality` setting was deprecated in Hugo 0.163.0 in favor +# of per-format settings. It was removed here because its previous value (75) +# matches Hugo's default. Set per-format `quality` under `imaging.` +# (e.g. `jpeg`, `webp`) if a non-default value is ever needed. resampleFilter: CatmullRom -quality: 75 anchor: smart \ No newline at end of file diff --git a/config/_default/languages.yaml b/config/_default/languages.yaml index 6d1441a07..a0d68e96a 100644 --- a/config/_default/languages.yaml +++ b/config/_default/languages.yaml @@ -5,11 +5,12 @@ # See: https://gohugo.io/content-management/multilingual/ # en: - languageName: English - languageCode: en-us + label: English + locale: en-US # Weight used for sorting. weight: 1 contentDir: content/en + direction: ltr params: description: "Dedicated to restoring and preserving the Interlisp experience" diff --git a/config/_default/module.yaml b/config/_default/module.yaml index fc98f3889..64ce0883b 100644 --- a/config/_default/module.yaml +++ b/config/_default/module.yaml @@ -1,11 +1,9 @@ proxy: "direct" # uncomment line below for temporary local development of module - # replacements = "github.com/google/docsy -> ../../docsy" + # replacements = "github.com/docsy/docsy/theme -> ../../docsy/theme" hugoVersion: extended: true - min: "0.155.2" + min: "0.168.0" imports: - - path: "github.com/google/docsy" + - path: "github.com/docsy/docsy/theme" disable: false - - path: "github.com/google/docsy/dependencies" - disable: false \ No newline at end of file diff --git a/config/_default/params.yaml b/config/_default/params.yaml index d1957ff63..d6f35c2ce 100644 --- a/config/_default/params.yaml +++ b/config/_default/params.yaml @@ -32,6 +32,12 @@ url_latest_version: https://example.com # in `markup.yaml` prism_syntax_highlighting: false +# author: site author information (used in RSS feed, etc.) +# +author: + name: Interlisp.org + email: info@interlisp.org + # copyright: site copyright information # authors: text list of authors # from_year: year in copyright statement @@ -177,3 +183,11 @@ ui: # Set to false to disable dark mode menu showLightDarkModeMenu: false + +# Docsy plugins configuration (0.18.0) +docsy: + plugins: + mermaid: + enable: false + markmap: + enable: false diff --git a/config/development/server.yaml b/config/development/server.yaml index 8540342b0..351c9ddd6 100644 --- a/config/development/server.yaml +++ b/config/development/server.yaml @@ -1,7 +1,7 @@ headers: - for: /** values: - Content-Security-Policy: script-src 'unsafe-inline' 'unsafe-eval' localhost:1313 https://code.jquery.com https://*.google.com http://*.google.com https://partner.googleadservices.com + Content-Security-Policy: script-src 'unsafe-inline' 'unsafe-eval' localhost:1313 https://*.google.com http://*.google.com https://partner.googleadservices.com Referrer-Policy: strict-origin-when-cross-origin X-Content-Type-Options: nosniff X-Frame-Options: DENY diff --git a/config/staging/hugo.yaml b/config/staging/hugo.yaml index d6576ecb3..09e8b8ee2 100644 --- a/config/staging/hugo.yaml +++ b/config/staging/hugo.yaml @@ -1,6 +1,6 @@ baseURL: https://interlisp.github.io/Interlisp.staging/ -languageCode: en-us +locale: en-us # title # Insert Staging Environment onto every page to make clear diff --git a/config/testing/hugo.yaml b/config/testing/hugo.yaml index f625566c3..a94c97bbc 100644 --- a/config/testing/hugo.yaml +++ b/config/testing/hugo.yaml @@ -11,6 +11,10 @@ # The module.mounts block must re-declare all standard project-level mounts # because adding any mount replaces Hugo's defaults for the project. # Theme (Docsy) mounts defined within that module are unaffected. +# +# Note: the mounts below do not set `lang` — that option was deprecated in Hugo +# 0.153.0. This is a single-language site, so mounts apply to the default +# (English) language without it. baseURL: "http://localhost/" @@ -30,7 +34,6 @@ module: # URLs are generated without an /en/ prefix (matching production behavior). - source: content/en target: content - lang: en - source: static target: static - source: layouts @@ -47,4 +50,3 @@ module: # Mount alongside the real bibliography content for the English language. - source: tests/fixtures/bibliography target: content/history/bibliography - lang: en diff --git a/content/en/history/bibliography/zotero-resources/_index.md b/content/en/history/bibliography/zotero-resources/_index.md new file mode 100644 index 000000000..2179a18c6 --- /dev/null +++ b/content/en/history/bibliography/zotero-resources/_index.md @@ -0,0 +1,250 @@ +--- +title: "Zotero Type Mapping Reference" +description: "How Interlisp Zotero bibliography types map to CSL JSON and Schema.org vocabulary" +type: docs +toc_hide: false +--- + +## Purpose + +This page documents how bibliography entry types are classified and mapped through the processing pipeline. It serves as a reference for: + +- **Content creators** contributing to the Interlisp Zotero group who want to understand how their entries will be categorized +- **Developers** working on the bibliography processing system who need to know current type support +- **Data consumers** using the JSON-LD output who need to understand what schema.org types represent Interlisp bibliography entries + +The mapping chain flows through three formats: + +``` +Zotero Item Type → CSL JSON Type → Schema.org @type +``` + +Each format serves a different purpose: + +- **Zotero Item Type**: Classification used within Zotero (the source system) +- **CSL JSON Type**: Standardized format for citation metadata (intermediate processing format) +- **Schema.org @type**: Structured data markup for web search engines and semantic web consumers (output format) + +A Zotero item type maps to exactly one CSL JSON type. The CSL JSON type is what the rest of the pipeline sees, and it is the value recorded as `item_type` in each bibliography entry's front matter. + +--- + +## Type Reference Table + +| Zotero Item Type | CSL Type | Schema.org @type | additionalType | genre | Notes | +|---|---|---|---|---|---| +| **Journal Article** | `article-journal` | `ScholarlyArticle` | — | — | Peer-reviewed journal articles, conference proceedings in journals | +| **Magazine Article** | `article-magazine` | `Article` | — | — | Magazine and trade publication articles | +| **Newspaper Article** | `article` | `Article` | — | — | Newspaper articles and news items | +| **Book** | `book` | `Book` | — | — | Books and monographs | +| **Book Section** | `chapter` | `Chapter` | — | — | Chapters or sections within books | +| **Conference Paper** | `paper-conference` | `ScholarlyArticle` | — | — | Papers presented at conferences (when not in proceedings) | +| **Report** | `report` | `Report` | the entry's report type | — | Technical reports, working papers, government documents | +| **Thesis** | `thesis` | `Thesis` | — | — | Master's theses, dissertations, doctoral theses | +| **Patent** | `patent` | `CreativeWork` | `"Patent"` | — | Patents and patent applications | +| **Blog Post** | `post-weblog` | `BlogPosting` | — | — | Blog posts and web log entries | +| **Webpage** | `webpage` | `WebPage` | — | — | General web pages and websites | +| **Encyclopedia Entry** | `entry-encyclopedia` | `Article` | — | — | Encyclopedia and reference work entries | +| **Film** | `motion_picture` | `VideoObject` | — | — | Films, videos, and visual media | +| **Email** | `personal_communication` | `Message` | — | — | Personal communications, emails, letters | +| **Computer Program** | `software` | `SoftwareSourceCode` | — | — | Software, source code repositories, applications, tools. The Type field names the programming language and maps to `programmingLanguage`; publisher, when present, maps to `publisher`. | +| **Document** | `document` | `CreativeWork` | `"TechnicalDocumentation"` | the entry's Type, if set | Technical manuals, guides, user documentation, software docs, specifications. Publisher, when present, maps to `publisher`. | +| **Document** with Type `Transcript` | `document` | `CreativeWork` | `"Transcript"` | `"Transcript"` | Oral history interviews, recorded interviews, media transcripts | +| **Document** with Type `Newsletter` | `document` | `CreativeWork` | `"TechnicalDocumentation"` | `"Newsletter"` | Newsletters, bulletins, and serial publications stored as documents | +| **Standard** | `standard` | `CreativeWork` | `"Standard"` | — (Type → `isPartOf`) | Technical standards, specifications, protocols, standards documents. The Type field names the standard's series (`isPartOf` → `CreativeWorkSeries`); the standard number maps to an `identifier`. | + +### Legend + +- **Zotero Item Type**: The classification used in Zotero's item type selector +- **CSL Type**: The type value in CSL JSON output from Zotero API +- **Schema.org @type**: The `@type` field in generated JSON-LD +- **additionalType**: Optional `additionalType` field in JSON-LD for additional classification +- **genre**: Optional `genre` field in JSON-LD for the entry's genre + +--- + +## Type Categories and Use Cases + +### Publishing Types (Peer-Reviewed and Published) + +These types are for published, citable research and writing: + +- **Journal Article** (`article-journal`): Peer-reviewed journal papers, conference proceedings published in journals +- **Magazine Article** (`article-magazine`): Trade magazines, popular science magazines +- **Newspaper Article** (`article`): Newspaper articles and news publications +- **Conference Paper** (`paper-conference`): Conference proceedings and papers +- **Book** (`book`): Published books and monographs +- **Book Section** (`chapter`): Chapters within books +- **Thesis** (`thesis`): Academic theses and dissertations + +### Technical and Professional Types + +- **Report** (`report`): Technical reports, working papers, government reports, internal documentation +- **Patent** (`patent`): Patents and patent applications +- **Encyclopedia Entry** (`entry-encyclopedia`): Reference works and encyclopedia entries +- **Standard** (`standard`): Technical standards, protocols, standardization documents + +### Documentary Types + +- **Document** (`document`): Broad category for technical documentation, user guides, specifications, manuals + - The Zotero **Type** field distinguishes subcategories within this item type. For an oral-history interview — a written document recording a conversation between an interviewer and an interviewee — set the Type field to `Transcript`. Its schema.org mapping is `additionalType: "Transcript"` with `genre: "Transcript"`. + - Other Type values are carried through to the Schema.org `genre` property. For example, a document with a Type of `Newsletter` maps to `genre: "Newsletter"`. +- **Standard** (`standard`): The Zotero **Type** field names the standard's series or designation (for example, `Xerox System Integration Standard`), which maps to `isPartOf` → `CreativeWorkSeries`. The entry's `@type` is `CreativeWork` with `additionalType: "Standard"`, and the standard number is emitted as a `PropertyValue` identifier. + +### Digital and Media Types + +- **Webpage** (`webpage`): Web pages, online resources, digital articles +- **Blog Post** (`post-weblog`): Blog entries and web logs +- **Film** (`motion_picture`): Videos, films, recorded presentations, documentaries +- **Computer Program** (`software`): Software repositories, source code, applications, development tools. The Zotero **Type** field names the programming language, which maps to the Schema.org `programmingLanguage` property. + +### Personal Communication + +- **Email** (`personal_communication`): Emails, letters, personal correspondence + +--- + +## For Content Creators + +### Choosing the Right Type + +When adding an entry to the Interlisp Zotero group: + +1. **Select the most specific Zotero item type** that matches your entry + - Use `Journal Article` for peer-reviewed journal papers + - Use `Conference Paper` for conference proceedings (not in a journal) + - Use `Report` for technical reports and internal documentation + - Use `Document` only when no other type fits (broad catch-all) + +2. **Fill in the Type field** for the item types that use it + - `Document`: the kind of document. Use `Transcript` for an oral-history interview. + - `Standard`: the standard's series or designation + - `Computer Program`: the programming language + +3. **Verify your schema.org mapping** by checking this reference table + +### Example: Choosing Between Report and Document + +| Aspect | Report | Document | +|--------|--------|----------| +| **Best for** | Published technical reports, working papers | User manuals, specifications, guides | +| **Publisher info available** | Usually yes | Often no | +| **Formal publication** | Yes, often | Rarely | +| **Organization issuing** | Clear (government, company, academic) | May be vague | +| **Use when** | Official documentation with publication date | In-house documentation, unpublished guides | + +--- + +## For Developers + +### Processing Pipeline + +The bibliography processing pipeline: + +1. **Fetches data** from the Zotero API (v3) for group 2914042 +2. **Extracts** the Zotero itemType and the CSL JSON type +3. **Generates markdown frontmatter** via `bibSplit.pl` (uses the CSL type) +4. **Generates JSON-LD** via the `bibliography-json-ld.html` partial (maps the CSL type to schema.org) +5. **Publishes** markdown files and embedded JSON-LD to the website + +The CSL JSON type is the entry's type of record. The Zotero **Type** field is a separate thing: it is a generic classification field whose meaning depends on the item type, and Zotero's CSL export maps it to the CSL `genre` field. It never names the entry's type. + +### Current Type Handling + +See `layouts/_partials/bibliography-json-ld.html` for the active type mappings: + +```go +{{- if eq $itemType "article-journal" -}}{{- $schemaType = "ScholarlyArticle" -}} +{{- else if eq $itemType "book" -}}{{- $schemaType = "Book" -}} +{{- else if eq $itemType "chapter" -}}{{- $schemaType = "Chapter" -}} +// ... etc +``` + +### Adding New Types + +To add a type: + +1. Add a type handler in `scripts/bibSplit.pl` (the `$type` branch chain, line ~146) so the pipeline emits it +2. Add the @type mapping in `layouts/_partials/bibliography-json-ld.html` (line ~25) +3. Add an `additionalType` assignment if the type needs further refinement (line ~124) +4. Add a test fixture under `tests/fixtures/bibliography/` and register its slug in `tests/conftest.py` +5. Add a test class in `tests/test_bibliography_jsonld.py` +6. Update this reference table and `docs/bibliography-schema.md` + +### Known Issues + +See `docs/bibliography-schema.md` for known issues and limitations in bibliography processing. + +--- + +## Schema.org Vocabulary Notes + +### CreativeWork Hierarchy + +Several types map to the generic `CreativeWork` in schema.org: + +- `patent` → `CreativeWork` (with `additionalType: "Patent"`) +- `document` → `CreativeWork` (with `additionalType: "TechnicalDocumentation"`) +- `document` with a `Transcript` type → `CreativeWork` (with `additionalType: "Transcript"`) +- `standard` → `CreativeWork` (with `additionalType: "Standard"`) + +This hierarchy allows search engines to understand that these are creative works while providing additional specificity through `additionalType`. + +### Why Not More Specific Types? + +Schema.org has no native types for: +- Generic "documents" +- Transcripts (unless linked to media) +- Technical standards (as standalone documents) +- General software (though `SoftwareSourceCode` is specific) + +Using `CreativeWork` with `additionalType` is the recommended schema.org pattern for these cases. Schema.org's `additionalType` documentation permits text values "sparingly, for cases where useful information can be added without their being an appropriate schema to reference", with the class label following the schema.org style guide. + +### The genre Property + +Schema.org's `genre` property ("Genre of the creative work") is the natural home for an entry's genre, and it is where the Zotero **Type** field is carried for `Document` entries. Both are used together for transcripts: `additionalType` states that the work is a transcript, while `genre` records the classification in schema.org's first-class slot. + +The Zotero **Type** field is generic, so its meaning depends on the item type, and so does its schema.org destination: + +| Zotero item type | Type field contains | Expressed in schema.org as | +|---|---|---| +| `Document` | the kind of document, e.g. `Transcript` | `genre`; `additionalType` is always set (`TechnicalDocumentation`, or `Transcript`) | +| `Standard` | the standard's series or designation | `isPartOf` → `CreativeWorkSeries` | +| `Computer Program` | the programming language | `programmingLanguage` | +| `Report` | the report type | `additionalType` | +| `Thesis` | the degree type | not currently mapped | +| `Webpage` | the kind of site, e.g. `Blog` | not currently mapped (`website_type` is frontmatter only) | + +--- + +## Troubleshooting + +### Entry Not Appearing with Expected Type + +1. **Check CSL JSON output**: Run `scripts/update_bibliography.sh` and examine the raw JSON for your entry's `type` field +2. **Verify mapping**: Check that the CSL type appears in the table above +3. **Check the Type field**: The CSL type is authoritative. A `type` value that looks like a genre word (for example `Transcript` or `Newsletter`) rather than a CSL type means the merge-precedence defect in `bib-fns.jq` (`semiflatten`) has regressed — the Zotero **Type** field must never overwrite the CSL type +4. **Report missing type**: If type is in CSL JSON but not in table, file an issue + +### JSON-LD Validation Errors + +1. **Use Google Structured Data Testing Tool** to validate: https://search.google.com/structured-data/testing-tool +2. **Check schema.org** for @type requirements: https://schema.org/ +3. **Review generated HTML** in browser DevTools (JSON-LD is embedded in `