Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Selectors

Selectors in mq allow you to select specific markdown nodes from a document. You can also access attributes of selected nodes using dot notation.

Basic Selector Usage

Selectors use the . prefix to select markdown nodes. For example:

.h       # Selects all heading nodes
.code    # Selects all code blocks
.link    # Selects all link nodes

Selector Calls (Filtered Matching)

Selectors can accept arguments to filter nodes by specific properties, using a function-call syntax:

.h(1)           # Selects only h1 headings
.h(2, 3)        # Selects h2 and h3 headings
.h(1..3)        # Selects h1, h2, and h3 headings (range)
.code("rust")   # Selects only Rust code blocks

Heading Depth Filtering

Pass one or more numeric arguments to match headings at specific depths:

# Select only top-level headings
.h(1)

# Select h2 and h3 headings
.h(2, 3)

# Select h1 through h3 using a range
.h(1..3)

Code Language Filtering

Pass a string argument to match code blocks with a specific language:

# Select only Rust code blocks
.code("rust")

# Select Python or JavaScript code blocks
.code("python") | to_array | concat(.code("javascript"))

Combining with Other Operations

Selector calls can be combined with pipes and functions just like plain selectors:

# Extract content of all h2 headings
.h(2) | .value

# Count Rust code blocks
.code("rust") | len()

# Replace language of all TypeScript blocks
.code("typescript").lang |= "ts"

Attribute Access

Once you’ve selected a node, you can access its attributes using dot notation. The available attributes depend on the node type.

Common Attributes

value

Most nodes support value to get the text content:

.code.value    # Gets the code content

Heading Attributes

Heading nodes support the following attributes:

AttributeTypeDescriptionExample
depth, levelIntegerThe heading level (1-6).h.level
valueStringThe value of the heading.h.value

Example:

# Input: # Hello World

.h.level # Returns: 1
.h.value # Returns: "Hello World"

Code Block Attributes

Code block nodes support the following attributes:

AttributeTypeDescriptionExample
lang, languageStringThe language of the code block.code.lang
valueStringThe code content.code.value
metaStringMetadata associated with the code block.code.meta
fenceBooleanWhether the code block is fenced.code.fence

Example:

# Input: ```rust
# fn main() {}
# ```

.code.lang      # Returns: "rust"
.code.value     # Returns: "fn main() {}"

Link nodes support the following attributes:

AttributeTypeDescriptionExample
urlStringThe URL of the link.link.url
titleStringThe title of the link.link.title
valueStringThe link value.link.value

Example:

# Input: [Example](https://example.com "Example Site")

.link.url       # Returns: "https://example.com"
.link.title     # Returns: "Example Site"
.link.value     # Returns: "Example"

Image Attributes

Image nodes support the following attributes:

AttributeTypeDescriptionExample
urlStringThe URL of the image.image.url
altStringThe alt text of the image.image.alt
titleStringThe title of the image.image.title

Example:

# Input: ![Alt text](image.png "Image Title")

.image.url      # Returns: "image.png"
.image.alt      # Returns: "Alt text"
.image.title    # Returns: "Image Title"

List Attributes

List nodes support the following attributes:

AttributeTypeDescriptionExample
indexIntegerThe index of the list item.list.index
levelIntegerThe nesting level of the list item.list.level
orderedBooleanWhether the list is ordered.list.ordered
checkedBooleanThe checked state (for task lists).list.checked
valueStringThe text content of the list item.list.value

Table Cell Attributes

Table cell nodes support the following attributes:

AttributeTypeDescriptionExample
rowIntegerThe row number of the cell.[0][0].row
columnIntegerThe column number of the cell.[0][0].column
last_cell_in_rowBooleanWhether this is the last cell in the row.[0][0].last_cell_in_row
last_cell_of_in_tableBooleanWhether this is the last cell in the table.[0][0].last_cell_of_in_table
valueStringThe text content of the cell.[0][0].value

Reference Nodes Attributes

Reference nodes (link references, image references, footnotes) support:

Node TypeAttributesDescription
.link_refident, labelIdentifier and label of link reference
.image_refident, label, altIdentifier, label, and alt text
.footnote_refident, labelIdentifier and label of footnote
.footnoteident, textIdentifier and content of footnote
.definitionident, url, title, labelLink/image definition attributes

MDX Attributes

MDX nodes support the following attributes:

AttributeTypeDescriptionExample
nameStringThe name of the MDX element.mdx_jsx_flow_element.name
valueStringThe content of the MDX node.mdx_flow_expression.value

Text Nodes Attributes

Text, HTML, YAML, TOML, Math nodes support:

AttributeTypeDescriptionExample
valueStringThe text content.text.value

Property Selector (Dict Key Access)

Property selectors access values from dict (object) values using quoted dot notation (."key"). They work on both single dicts and arrays of dicts.

Use ."key" to access a dict key by name:

# Input dict: {"name": "Alice", "age": 30}

."name"   # Returns: "Alice"
."age"    # Returns: 30

Keys with spaces, special characters, or names that match reserved selector names are also supported:

# Input dict: {"h1": "title", "my key": "value"}

."h1"       # Returns: "title"
."my key"   # Returns: "value"
."url"      # Returns: the "url" key value

Escape sequences inside quoted keys: \" for a literal " and \\ for a literal \.

Arrays of Dicts

When applied to an array of dicts, the property selector maps over each element:

# Input: [{"name": "Alice"}, {"name": "Bob"}, {"name": "Charlie"}]

."name"   # Returns: ["Alice", "Bob", "Charlie"]

Non-dict elements in the array return none.

Missing Keys

Accessing a key that doesn’t exist returns none:

# Input dict: {"name": "Alice"}

."age"    # Returns: none

Combining Selectors with Functions

You can combine selectors with functions like select(), map(), and filter() for powerful transformations:

Using select()

The select() function filters elements based on a condition:

# Select only code blocks (exclude non-code nodes)
select(.code)

# Select nodes that are not code blocks
select(!.code)

Using map()

Transform each selected node:

# Get all heading levels
.h | map(fn(h): h.level;)

# Get all code block languages
.code | map(fn(c): c.lang;)

Using filter()

Filter nodes based on attribute values:

# Get only level 2 headings
.h | filter(fn(h): h.level == 2;)

# Get only rust code blocks
.code | filter(fn(c): c.lang == "rust";)

The selector call syntax provides a more concise alternative for common cases:

.h(2)           # equivalent to: .h | filter(fn(h): h.level == 2;)
.code("rust")   # equivalent to: .code | filter(fn(c): c.lang == "rust";)

Extract Code Languages

.code.lang
.link.url

Filter High-Level Headings

# Using attribute comparison
select(.h.level <= 2)

# Using selector call for exact levels
.h(1, 2)

Setting Attributes

You can modify node attributes using the update operator (|=):

# Change code block language
.code.lang |= "rust"

# Update link URL
.link.url |= "https://new-url.com"

# Update heading level
.h.depth |= 2

The set_attr() function is an alternative that takes the attribute name as a string:

.code | set_attr("lang", "rust")
.link | set_attr("url", "https://new-url.com")
.h | set_attr("level", 2)

See Also