Markdown formatter and linter. Uses remark-lint plugins and a few other remark plugins.
remark <--> kramer (semordnilap, get it?)
- 🥳 A table of contents will be generated if you include a
Table of contents
header in a document, and will include heading levels 1-3. - Emphasis and strong are both indicated with
*
. - Unordered list items marked with
-
. - List items are indented one and only one space beyond the marker.
- Headings are indicated with
#
signs, e.g.## Second-level heading
. - Linked references for links or images (footnotes, essentially) are transformed into inline URLs.
- Code blocks are fenced with triple backticks.
- Some other minor stuff that should be intuitive or prevent mistakes, such as some escaping and encoding.
- 🥳 Links within the repository (to headings, other files, headings in other files) are validated.
- No duplicate top-level headings.
- No tabs.
- Reference definitions are at the end of the file, are not duplicated, and are used.
- Some other minor stuff that improves consistency.
The @mapbox/kramer
package includes a CLI that lints or formats. Formatting overwrites the input files.
Lint or format Markdown files.
Usage
kramer [options] [files...]
Files can be specified with full paths or globs.
If no files are specified, the command runs on all
Markdown files in the current working directory.
Options
-f, --format Format files instead of linting them.
Overwrites input files.
Examples
kramer
kramer docs/*.md
kramer --format "docs/**/*.md"
You can also use this package as a remark plugin, in Node code or with remark-cli.
The @mapbox/kramer
package also exports settings
and plugins
that can be used with remark's Node API.
settings
is an object of remark-stringify settings for formatting.plugins
is an array of the remark plugins that kramer uses.
The following example creates a function that reformats Markdown using kramer's rules and plugins.
const unified = require('unified');
const remarkStringify = require('remark-stringify');
const remarkParse = require('remark-parse');
const kramer = require('@mapbox/kramer');
const markdownFormatter = unified()
.use(remarkParse)
.use(remarkStringify, kramer.settings)
.use(kramer.plugins);
async function reformatMarkdown(md) {
return String(await markdownFormatter.process(md));
}
💭💡 Run Markdown linting as part of your npm test
process.
// In package.json ...
{
"scripts": {
"lint-js": "eslint .",
"lint-md": "kramer",
"lint": "npm run lint-js && npm run lint-md",
"pretest": "npm run lint"
}
}
💭💡 Use husky and linted-staged to set up a pre-commit hook that automatically lints and formats any Markdown files that are staged for a commit.
// In package.json ...
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.md": [
"kramer",
"kramer --format"
]
}
}
💭💡 Whenever you upgrade versions, reformat all your Markdown with kramer --format
.