flashcard-md-spec
v1.1.0
Published
A specification for writing flashcards in Markdown, with a conformance fixture corpus.
Maintainers
Readme
flashcard-md-spec
A specification for writing flashcards in Markdown, and the conformance fixture corpus that keeps implementations of it honest.
A deck is an ordinary Markdown file. Cards are ## headings.
---
tags:
- french
- verbs
---
# French verbs
## se rendre compte
- to realize, to become aware
- reflexive, takes `de` before a nounSPEC.md— the normative document.fixtures/— the corpus, indexed byfixtures/manifest.json.examples/learn-flashcard-md.md— a self-teaching deck: its cards teach the format it is written in. Non-normative; import it into a flashcard app, or read the source next toSPEC.md.
Why this exists
Five programs grew their own dialect of "flashcards in Markdown" independently, and the dialects drifted. Two of them disagreed about where a card ends — the one difference that silently destroys a user's review scheduling — and nobody had noticed, because nothing compared them.
Prose alone would drift again. So the deliverable is the corpus: each implementation runs the same cases in its own test suite, and a disagreement becomes a failing test in whichever repository is wrong.
Using it
pnpm add -D flashcard-md-specThe package contains no parser — deliberately. It ships SPEC.md,
fixtures/, the example deck, and nothing that runs.
Read fixtures/README.md for the case format. In short,
a consumer parses input.md, maps its model to the fixture shape through a
test-only adapter, and compares; a producer runs the corpus in the opposite
direction, reproducing each canonical input.md byte-for-byte and rejecting
everything under invalid/.
Implementations
| Project | Class |
| --- | --- |
| pdfanki | producer |
| @ankimd/core | consumer, producer |
| leitner | consumer |
A producer must emit canonical form only. A consumer must parse anything
valid and must never refuse a whole file over one bad card. See SPEC.md §3.
Versioning
SPEC.md carries major.minor; this package adds the patch digit, so a fixture
typo does not read as a specification revision.
Any change that can move a card boundary is a major version, without exception. Consumers key persistent review state on card identity, so a shifted boundary silently destroys scheduling history. There is no small boundary change.
Development
pnpm install
pnpm run check # the manifest and the fixture tree agree, and the cases are well formed
pnpm test # the check script catches the mistakes it is supposed to catch
pnpm run lint
pnpm run formatpnpm run check is the gate that matters. It verifies that every case on disk is
indexed and vice versa, that every text field in an expected.json is a verbatim
slice of its input.md, that effective tags really are the union of file and
card tags, and that the manifest's specVersion matches what SPEC.md declares.
Never reformat anything under fixtures/. The expected.json files hold
literal slices of the input.md beside them, so normalizing whitespace or list
markers would silently gut the case. The formatter is configured to skip that
directory; pnpm run check will catch it if that ever stops working.
License
MIT
