5.6 KiB
link, created, tags
| link | created | tags | |
|---|---|---|---|
| https://github.com/dhanushka2001/citeorder | 2026-05-11 |
|
Simple command-line tool to correctly reorder Footnotes in Markdown files.
[!tip] Tip For those who don't wish to use the command-line, I have made a Chrome Extension which adds a toolbar inside GitHub's README.md text editor with a button to reorder footnotes.
Motivation
Markdown processors that support footnotes (e.g. GitHub’s Markdown engine, which implements the GitHub Flavored Markdown spec) automatically reorder footnotes when converting .md files to HTML. However, citeorder fixes the ordering in the .md file itself, making it neater and easier to manage lots of footnotes. Especially useful when needing to add new footnotes in the middle of a long .md file and not having to spend ages reordering every in-text and full-entry footnote manually (🥲).
In-text footnotes ("Alice here",[^1]) and full-entry footnotes ([^1]: Alice) are a many-to-one relationship. citeorder assumes the connections are correct, and relabels them according to the order in which the in-text footnotes appear.
How to use
- Download the precompiled executable from the latest release.
Installation via Homebrew (macOS/Ubuntu):
Installation via the AUR (Arch):
brew install dhanushka2001/citeorder/citeorderOr clone the repo and compile source code If you want to compile the source code yourself, clone the repo and compileyay -S citeorderciteorder.c:git clone https://github.com/dhanushka2001/citeordergcc -Wall -O2 citeorder.c -o citeorder - To run, simply enter into the terminal:
where
citeorder input.mdinput.mdis the Markdown file whose Footnotes you want reordered.citeorderwill keep the original file as is and output the changes to a new file,input-fixed.md. To allow relaxed quote handling, do:For more info and options, run:citeorder -q input.mdciteorder -h
Example
example.md:
"Alice says hi".[^1]
[^1]: Alice
"Bob is here".[^7] "I'm Charlie",[^4] "Daniel!",[^5] here.
[^4]: Charlie
[^3]: Gary
[^5]: Daniel
[^7]: Bob
Is "Ethan"[^8] here?
[^8]: Ethan
"Bob and Charlie here again"[^7][^4]
[^6]: Fred
Running:
citeorder example.md
will produce example-fixed.md:
"Alice says hi".[^1]
[^1]: Alice
"Bob is here".[^2] "I'm Charlie",[^3] "Daniel!",[^4] here.
[^2]: Bob
[^3]: Charlie
[^4]: Daniel
[^6]: Gary
Is "Ethan"[^5] here?
[^5]: Ethan
"Bob and Charlie here again"[^2][^3]
[^7]: Fred
Cases handled
- No changes needed.
- Stacked in-text footnotes, e.g.
"hello",[^3][^1][^5]→"hello",[^1][^2][^3]. - Single punctuation (or none) after end quote, e.g.
"A"[^3] "B",[^2] "C".[^6] "D"![^5]→"A"[^1] "B",[^2] "C".[^3] "D"![^4]. - Improper quote, e.g.
"hello[^1],"hello",,[^1],hello"[^1],"hello" [^1]produces an error message like:ERROR: in-text citation [^1] not properly quoted (line 5). Can ignore this error with the-q/--relaxed-quotesflag. - Full-entry footnotes with no matching in-text footnotes simply get bubbled to the end of the ordering.
- In-text footnotes with no matching full-entry footnote produce an error message like:
ERROR: in-text citation [^2] without full-entry (line 3). - Duplicate full-entry footnotes, e.g.
produces an error message like:
[^4]: Alice [^4]: BobERROR: duplicate [^4] full-entry citations (line 7 and 8). - Footnotes inside inline code (
"A"[^1]) and fenced code blocks:are ignored."A"[^1] [^1]: A [^2]: B - Footnote labels with letters/symbols are supported, and will be relabeled accordingly, e.g.
"A"[^6b]→"A"[^1]. - Spaces in the in-text or full-entry footnotes. Spaces outside the label for in-text footnotes, e.g.
"A"[^ Alice ]are accepted by Markdown processors, andciteorderwill convert that to"A"[^1]. However, for full-entry footnotes, e.g.[^ 4b ]: Alice, it is not accepted, and inciteorderit will produce an error message like:ERROR: [^ 4b ] full-entry citation contains a space (line 3). For both in-text and full-entry footnotes, spaces in the label itself, e.g."A"[^4 b],[^4 b]: Alice, are not accepted, and inciteorderyou will get an error message. - In-text or full-entry footnote missing a label, e.g.
"A"[^], will produce an error message like:ERROR: in-text citation [^] missing label (line 7). - Multiline quote:
becomes:
"T"[^4] "This quote takes up multiple lines but is still valid",[^3] "H",[^6] [^4]: T [^6]: H [^3]: Multiline quote"T"[^1] "This quote takes up multiple lines but is still valid",[^2] "H",[^3] [^1]: T [^2]: Multiline quote [^3]: H - Duplicate full-entry footnotes, e.g.
can be auto-incremented using the
"A"[^dupe], "B"[^dupe] [^dupe]: A [^dupe]: B "C"[^dupe] [^dupe]: C "D"[^1] [^1]: D-d/--relaxed-duplicatesflag (must be only ONE duplicate footnote label, and must have an equal number of full-entry and in-text duplicates):"A"[^1], "B"[^2] [^1]: A [^2]: B "C"[^3] [^3]: C "D"[^4] [^4]: D