remark-tags
remark plugin to generate tags for Markdown documents.
Install
This package is ESM
only:
Node 12+ is needed to use it and it must be import
ed instead of require
d.
npm:
npm install remark-tags
Use
Say we have the following file, example.md
:
---
title: An Example document
author: N. N.
date: 2021-10-01
keywords:
- Markdown
- Tags
nocite: |
@doe1999, @smith2004
---
See :link[A text directive]{ref=Target}, :link[Another target]
and @wadler1989 [sec. 1.3; and -@hughes1990, pp. 4].
And our module, example.js
, looks as follows:
import {readSync} from 'to-vfile'
import {reporter} from 'vfile-reporter'
import {unified} from 'unified'
import remarkParse from 'remark-parse'
import remarkFrontmatter from 'remark-frontmatter'
import remarkDirective from 'remark-directive'
import remarkCitekey from '@bernardjoseph/remark-citekey'
import remarkTags from '@bernardjoseph/remark-tags'
const processor = unified()
.use(remarkParse)
.use(remarkFrontmatter, 'yaml')
.use(remarkDirective)
.use(remarkCitekey)
.use(remarkTags, {
kinds: {
yaml: {
title: {kind: 'title'},
author: {kind: 'author'},
date: {kind: 'date'},
keywords: {kind: 'keyword'},
nocite: {kind: 'nocite', nocite: true}
},
textDirective: {
link: {kind: 'link', ref: 'ref'}
},
citekeyId: {kind: 'cite'}
}
})
const tree = processor().parse(readSync('example.md'))
processor().run(tree, (err, _, file) => {
if (err) throw err
console.error(reporter(file))
// @ts-expect-error
console.dir(file.data ? file.data.tags || [] : [], {depth: null})
})
Now, running node example
yields:
no issues found
[
{ name: 'An Example document', kind: 'title', line: 1, column: 1 },
{ name: 'N. N.', kind: 'author', line: 1, column: 1 },
{ name: '2021-10-01', kind: 'date', line: 1, column: 1 },
{ name: 'Markdown', kind: 'keyword', line: 1, column: 1 },
{ name: 'Tags', kind: 'keyword', line: 1, column: 1 },
{ name: 'doe1999', kind: 'nocite', line: 1, column: 1 },
{ name: 'smith2004', kind: 'nocite', line: 1, column: 1 },
{ name: 'Target', kind: 'link', line: 12, column: 5 },
{ name: 'Another target', kind: 'link', line: 12, column: 42 },
{ name: 'wadler1989', kind: 'cite', line: 13, column: 6 },
{ name: 'hughes1990', kind: 'cite', line: 13, column: 34 }
]
Tags are generated for YAML frontmatter entries, link
text directives and
Pandoc-style citation keys.
Text directives are described in a proposal for a syntax extension of the
Markdown language.
In the proposal, they are called inline directives.
In the example above, text directives are used as links to other documents.
API
This package exports no identifiers.
The default export is remarkTags
.
The package installs the executables remark-tags
and remark-tags-filter
.
processor().use(remarkTags[, options])
Configures processor
to generate tags for Markdown documents, depending on the
node types of the nodes of the abstract syntax trees that are generated
for Markdown documents by the remark parser.
The node types of the nodes for which tags are generated must be defined and
configured by the kinds
option of the remark-tags
plugin.
Nodes of type yaml
are generated for frontmatter entries by the remark-tags
plugin if the frontmatter of the Markdown document is parsed by the
remark-frontmatter
plugin.
Nodes of type textDirective
are generated for text directives by the
remark-directive
plugin.
In addition, the following example processor
generates tags for nodes of type
citekeyId
, which are generated for Pandoc-style citation
keys by the remark-citekey
plugin:
import {unified} from 'unified'
import remarkParse from 'remark-parse'
import remarkFrontmatter from 'remark-frontmatter'
import remarkDirective from 'remark-directive'
import remarkCitekey from '@bernardjoseph/remark-citekey'
import remarkTags from '@bernardjoseph/remark-tags'
const processor = unified()
.use(remarkParse)
.use(remarkFrontmatter, 'yaml')
.use(remarkDirective)
.use(remarkCitekey)
.use(remarkTags, {
kinds: {
yaml: {
title: {kind: 'title'},
author: {kind: 'author'},
date: {kind: 'date'},
keywords: {kind: 'keyword'},
nocite: {kind: 'nocite', nocite: true}
},
textDirective: {
link: {kind: 'link', ref: 'ref'}
},
citekeyId: {kind: 'cite'}
}
})
Running processor().run(processor().parse(file))
generates an array containing
a tag for each entry of the YAML frontmatter whose key has an entry in the
value of the yaml
entry of the kinds
option, for each text
directive whose name has an entry in the value of the textDirective
entry of
the kinds
option, and for each other node whose node type has
an entry in the kinds
option (which are the nodes of type
citekeyId
in the example processor
).
Each tag is an object with entries name
for the identifier of the tag, kind
for the kind of the tag, and line
and column
for the source line and the
source column of the tag in the parsed document.
The array of tags is assigned to file.data.tags
.
options.kinds
The node types of the nodes for which tags are generated must be defined and
configured by the kinds
option.
The value of the kinds
option is an object whose keys are
node types and whose values are objects.
The value of a kinds
option entry with key yaml
is an
object mapping YAML frontmatter keys to configuration objects.
For a frontmatter entry, tags are generated only if its key is one of the keys
of the mapping.
Each configuration object has a mandatory kind
entry and an optional nocite
entry.
Unless the value of the optional nocite
entry is true
, tags are generated if
the value of the frontmatter entry is either a single YAML block or flow
scalar or a YAML block or flow sequence of YAML block or flow scalars.
For each YAML scalar contained in value of such a frontmatter entry, a tag
whose identifier is the YAML scalar and whose kind is the value of the
kind
entry of the configuration object is generated.
If the value of the optional nocite
entry of the configuration object is
true
, tags are generated if the value of the frontmatter entry is a YAML
block scalar.
In this case, the frontmatter entry is treated as a nocite
entry in the sense
of Pandoc, containing citation keys of bibliographic references that are not
explicitly cited in the document but should occur in a bibliography for the
document.
For each Pandoc-style citation key that is contained in the
value of such a frontmatter entry, a tag whose identifier is the citation key
without the leading @
and whose kind is the value of the kind
entry of the
configuration object is generated.
The value of a kinds
option entry with key textDirective
is
an object mapping names of text directives to configuration objects.
A tag is generated for each text directive whose name is one of the keys of the
mapping.
Each configuration object has a mandatory kind
entry and an optional ref
entry.
The kind of the generated tag is the value of the kind
entry.
The value of the optional ref
entry is the name of an optional text directive
attribute.
If the text directive has an attribute with that name, the identifier of the
generated tag is the value of that attribute.
If the text directive has no such attribute, or the configuration object of the
text directive has no ref
entry, the identifier of the generated tag is the
content of the text directive (which is a Markdown formatted string).
The value of a kinds
option entry whose key is a node type
other than yaml
or textDirective
is a configuration object with a mandatory
kind
entry.
For each node of the key node type, a tag whose identifier is the content of the
node and whose kind is the value of the kind
entry of the configuration object
is generated.
The example processor
above, for instance, generates tags of kind cite
for
nodes of type citekeyId
, whose identifiers are the citation keys of
Pandoc-style citations without the leading @
.
options.strict
The strict
option is a boolean
option to restrict Pandoc-style citation
keys in nocite
entries of the YAML
frontmatter to ASCII.
Its default value is false
.
The strict
option of the remark-tags
plugin corresponds to the strict
option of the remark-citekey
plugin, which is passed
to micromark-extension-citekey
.
If the remark-citekey
plugin is imported, both strict
options should always have the same value.
Caveat
The remark-frontmatter
plugin parses frontmatters as
whole blocks.
Therefore, the line
and the column
entries of the tags that are generated
for frontmatter entries contain the starting line and column of the whole
frontmatter block instead of the starting lines and columns of the individual
entries.
remark-tags
executable
The The remark-tags
executable reads the file name of a Markdown document from the
command line and prints a JSON formatted array of tags on the console
.
It uses the following unified-args command line interface:
args({
processor: unified().use(defaultPreset).use(stringifyTags),
name: 'remark-tags',
description: 'Generate tags for Markdown documents',
version: '1.0.0',
pluginPrefix: 'remark',
extensions: ['md'],
packageField: 'remarkTagsConfig',
rcName: '.remarktagsrc',
ignoreName: '.remarktagsignore'
})
With default preset:
import remarkParse from 'remark-parse'
import remarkFrontmatter from 'remark-frontmatter'
import remarkDirective from 'remark-directive'
import remarkCitekey from '@bernardjoseph/remark-citekey'
import remarkTags from '@bernardjoseph/remark-tags'
const defaultPreset = {
plugins: [
remarkParse,
[remarkFrontmatter, 'yaml'],
remarkDirective,
remarkCitekey,
remarkTags
]
}
And compiler:
export default function stringifyTags() {
function compiler(_, file) {
const tags = file.data && file.data.tags
return JSON.stringify(tags) + os.EOL
}
Object.assign(this, {Compiler: compiler})
}
The remark-tags
executable can be configured by a configuration
file with base name remarktagsrc
.
The ignore file is .remarktagsignore
.
remark-tags-filter
executable
The The remark-tags-filter
executable reads file names of Markdown documents from
process.stdin
, one file name per line, and prints JSON formatted arrays of
tags on the console
, one array per file.
It uses the same processor as the remark-tags
executable and can be configured by a
configuration file with base name
remarktagsrc
.
An example configuration file looks as follows:
{
"plugins": {
"remark-tags": {
"strict": true,
"kinds": {
"yaml": {
"title": {"kind": "title"},
"author": {"kind": "author"},
"date": {"kind": "date"},
"keywords": {"kind": "keyword"},
"nocite": {"kind": "nocite", "nocite": true}
},
"textDirective": {
"link": {"kind": "link", "ref": "ref"}
},
"citekeyId": {"kind": "cite"}
}
},
"remark-citekey": {
"strict": true
}
}
}
Related
-
unifiedjs/unified
— interface for processing text using syntax trees -
remarkjs/remark
— markdown processor powered by plugins -
remarkjs/remark-parse
— parses Markdown to mdast syntax trees -
remarkjs/remark-frontmatter
— plugin to support frontmatter -
remarkjs/remark-directive
— plugin to support the generic directives proposal -
@bernardjoseph/remark-citekey
— plugin to support Pandoc-style citation keys
Contribute
See contributing.md
in micromark/.github
for ways to get
started.
See support.md
for ways to get help.
This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.
License
MIT © Bernd Rellermeyer