Files
mikkeli 230a3badc3 fix(ses): preserve h1 elements — do not strip first heading
Songs always carries a # Song title line so stripping makes sense there,
but SES body structure is freeform and may use h1 deliberately.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 00:00:08 +09:00

4.3 KiB

SCHEMA — SES light novel source files

Source-file contract for the SES pipeline. Files in mikkeli/ses-light-novel must follow this contract to be picked up by the auto-publisher.

The schema lives entirely in the YAML frontmatter block at the top of each .md file. The body below the frontmatter is plain markdown, rendered to MediaWiki wikitext by Pandoc.

File layout

---
title: Wakkanai
type: story
wiki:
  publish: true
---

## Section 1
### The coast or the shore

... body markdown ...

The renderer parses the frontmatter, validates required fields, then hands the body to Pandoc. The first-line # Heading is preserved — use it if you want an h1 on the rendered page.

Fields

Required

title (string)

The MediaWiki page name, without the SES: prefix — the pipeline prepends it automatically. MediaWiki capitalises the first letter; lowercase input is fine.

Example: title: Wakkanai → wiki page SES:Wakkanai at URL /wiki/SES:Wakkanai.

wiki.publish (boolean)

Publishing gate. true means the pipeline writes this file to the wiki. false means the file is ignored.

wiki must be a YAML mapping, not a list:

# correct
wiki:
  publish: true

# wrong — will be silently skipped
wiki:
  - publish: true

Optional

type (string)

The page type. Drives [[Category:SES:<type>]] injection. If omitted, the pipeline falls back to the file's immediate parent directory name (stories, people, places, etc.).

Example: type: story[[Category:SES:story]].

If neither type nor a meaningful directory name is available (file sits at the repo root), the fallback is uncategorized.

categories (list of strings)

Additional wiki categories to inject beyond the automatic SES and SES:<type> ones. Each entry becomes [[Category:<value>]].

categories:
  - Featured

Body

Plain markdown. The body is passed through Pandoc as-is — the first-line # Heading is not stripped, so you can use h1 elements freely. Do not embed raw wikitext ({{Template}}, raw [[Wikilinks]], etc.) unless you intend the literal output.

Renderer behaviour

For each .md with wiki.publish: true:

  1. Parse and validate frontmatter.
  2. Pipe the body through pandoc -f markdown -t mediawiki.
  3. Prepend the auto-generated banner: {{Auto-generated|source=<source URL>|commit=<sha>}}.
  4. Append category tags: [[Category:SES]], [[Category:SES:<type>]], and any entries from categories.
  5. Read the current wiki page content via the MediaWiki API; if identical to the generated output, skip the write (idempotency).
  6. If the page exists and does not start with {{Auto-generated, skip with a warning (manual page protection).
  7. Otherwise, write the page with an edit summary referencing the source commit.

Implemented scope

  • Frontmatter parsing and validation
  • SES: title prefix
  • Pandoc-based markdown → wikitext body rendering (h1 elements preserved)
  • Banner template injection
  • Category:SES + Category:SES:<type> injection (type from frontmatter, fallback to parent directory)
  • Additional categories via categories list
  • Idempotent writes (no-op skip when content matches)
  • Manual-page protection (skip pages without auto-gen banner)
  • Files without wiki.publish: true silently skipped

Not in scope (intentional)

  • Sibling/cross-page link resolution — write wikilinks directly in the body
  • Separate upload of companion files (no LRC equivalent)

Examples

A story chapter

---
title: Wakkanai
type: story
wiki:
  publish: true
---

Wiki page: SES:Wakkanai. Categories: SES, SES:story.

A world entry (type from directory)

---
title: Emms White
wiki:
  publish: true
---

File at world/people/emms_white.md. Type falls back to people. Wiki page: SES:Emms White. Categories: SES, SES:people.

A draft (not published)

---
title: Helsinki
type: place
wiki:
  publish: false
---

Validation errors the renderer must produce

Files without wiki.publish: true are silently skipped. The pipeline fails fast only on opted-in files with invalid data:

  • Missing or empty title on a file with wiki.publish: true
  • wiki.publish present but not a boolean
  • categories (if present) is not a list
  • Two publishable source files resolve to the same wiki title