Detect tests with selectors
A regex definition matches your file’s raw text. That includes code samples, so a pattern for **bold** also matches bold syntax inside a fenced example. A selector matches what the file means instead: a link, a bold phrase, a code block, or a comment. Doc Detective parses the file, and the selector picks the nodes you name.
Selectors work in custom fileTypes for Markdown, MDX, HTML, DITA, and AsciiDoc files. Regex definitions keep working, and one file type can use both.
Write your first selector
This config adds a definition to the Markdown file type. It turns every bash code block into a runShell step:
The key, codeBlock, is the kind of node to select. Its value narrows the selection, and "bash" is short for { "language": ["bash"] }. $1 is the code block’s content.
To check what gets detected without running anything, pass --dry-run:
Choose a definition form
A markup definition needs regex, one selector kind, or both:
A node’s main text is its content, else its text, else its alt.
In HTML and DITA, a text node holds prose as written, so a pattern sees entities such as " and & rather than the characters they stand for. Bold, italic, and link text is decoded, as it renders.
A kind with regex limits an existing pattern to the right place. This definition finds version numbers in prose, but not in code blocks, inline code, or links:
Kinds
{} selects every node of a kind. codeBlock also takes a string that names one language, and element takes a string that names one tag. A kind a format doesn’t produce matches nothing.
HTML inside Markdown, and lowercase JSX tags in MDX such as <a> and <img>, produce the same kinds as HTML. Text between inline HTML tags stays Markdown prose.
A code block’s language comes from the fence in Markdown, a language-x class in HTML, a language-x output class in DITA, and a [source,x] line in AsciiDoc. In AsciiDoc, the options after the language, such as testIgnore in [source,bash,testIgnore], are its meta.
Code holds no nodes. That covers Markdown’s indented code blocks and inline code, and HTML’s <pre>, <code>, <script>, and <style>. It also covers DITA’s <codeblock>, <codeph>, <pre>, <screen>, and <msgblock>, and AsciiDoc’s listings, literal blocks, ++++ blocks, and indented paragraphs.
In Markdown, URLs in angle brackets such as <https://example.com>, and reference-style links such as [text][ref], aren’t links. Their text stays part of the surrounding prose.
Options
All options are optional. Patterns are regular expressions, run without flags.
Each format sets attributes its own way, and each can set class. In Markdown, an attribute list right after a link or image holds them, as in {.screenshot}, and a class such as .screenshot sets class. In MDX, they’re a component’s props, and className on a lowercase tag sets class. A prop set with an expression, such as count={1 + 1}, reads as its source text, 1 + 1, because detection doesn’t run code. In HTML and DITA, they’re the tag’s attributes. DITA’s outputclass also sets class, and an <image>’s href is its src. In AsciiDoc, they come from an image’s attribute list, as in image::shot.png[Results, role=screenshot]. A role sets class, from role= or a [.screenshot] line above the image.
Use node fields in actions
captures lists the fields to use as $1, $2, and so on, in order. This definition opens a link when the sentence says “Go to” before it:
A field a node doesn’t have is an empty string. A regex group that didn’t take part leaves out the action field that uses it, as in regex definitions.
Read inline statements from nodes
inlineStatements.in lists the nodes that hold inline test statements. Doc Detective reads a node as a statement when its text starts with test, test start, test end, test ignore start, test ignore end, or step. A comment inside a code block isn’t a node, so a statement in a code sample stays text.
An entry can also select nodes like a markup definition, with two more keys:
valuenames the field that holds the statement, such asattributes.content.regexfinds the statement in the text. The first group becomes the statement, else the whole match.
This entry reads statements from comments that start with dd:, and skips drafts:
in works beside the regex statement keys, such as testStart and step. A statement that both find counts once.
Which files get parsed
The file’s extension picks the parser:
For any other extension, Doc Detective uses the format in extends, so a file type that extends markdown parses its .txt files as Markdown. The HTML and DITA parsers accept broken markup, so they never stop detection.
Doc Detective warns, and keeps detecting, in two cases:
- An
.mdxfile isn’t valid MDX. It parses as Markdown instead, so content inside JSX components isn’t detected. Run your site’s build to find the error. - No parser handles the file. Selectors match nothing, and regex definitions still run. Set
extendsto a built-in format, or use regex definitions.
Dry runs don’t print warnings, so run without --dry-run to see them.
Next steps
- Custom input formats covers regex definitions and file type settings.
- The config reference lists every
fileTypeskey.