block-directive

77 cases. Source: tests/block-directive.json.

#1 canonical

Source

:::card[Pricing tiers]{tone=info}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": "Pricing tiers",
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {
      "tone": "info"
    }
  }
}

#2 name only

Source

:::steps

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "steps",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#3 name and attributes

Source

:::grid{cols=3 gap=md}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "grid",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {
      "cols": "3",
      "gap": "md"
    }
  }
}

#4 name and argument

Source

:::card[Title]

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": "Title",
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#5 every vocabulary name

Source

:::figure

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "figure",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#6 columns

Source

:::columns{ratio="2:1"}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "columns",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {
      "ratio": "2:1"
    }
  }
}

#7 tabs

Source

:::tabs{active=2}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "tabs",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {
      "active": "2"
    }
  }
}

#8 metrics

Source

:::metrics{direction=inverse}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "metrics",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {
      "direction": "inverse"
    }
  }
}

#9 longer fence for nesting

Source

::::card

Parse result

{
  "type": "directive-open",
  "fence": 4,
  "name": "card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#10 much longer fence

Source

:::::::columns

Parse result

{
  "type": "directive-open",
  "fence": 7,
  "name": "columns",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#11 empty argument

Source

:::card[]

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": "",
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#12 empty attribute specifier

Source

:::card{}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#13 argument with nested brackets is kept raw

Source

:::card[See [the docs](https://x.y)]

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": "See [the docs](https://x.y)",
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#14 argument with escaped bracket is kept raw

Source

:::card[a \] b]

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": "a \\] b",
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#15 argument may contain braces

Source

:::card[a {b} c]{#x}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": "a {b} c",
  "attributes": {
    "type": "attributes",
    "id": "x",
    "classes": [],
    "attrs": {}
  }
}

#16 id and classes on a directive

Source

:::figure[Lifecycle]{#fig-lifecycle .wide width=60%}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "figure",
  "argument": "Lifecycle",
  "attributes": {
    "type": "attributes",
    "id": "fig-lifecycle",
    "classes": [
      "wide"
    ],
    "attrs": {
      "width": "60%"
    }
  }
}

#17 trailing whitespace is allowed

Source

:::card  	

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#18 one space of indentation

Source

 :::card

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#19 three spaces of indentation

Source

   :::card

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

#20 closing fence

Source

:::

Parse result

{
  "type": "directive-close",
  "fence": 3
}

#21 longer closing fence

Source

:::::

Parse result

{
  "type": "directive-close",
  "fence": 5
}

#22 closing fence with trailing whitespace

Source

:::  

Parse result

{
  "type": "directive-close",
  "fence": 3
}

#23 indented closing fence

Source

  :::

Parse result

{
  "type": "directive-close",
  "fence": 3
}

#24 four spaces of indentation is not a fence

Source

    :::card

Parse result

null

#25 tab indentation is not a fence

Source

	:::card

Parse result

null

#26 single colon is text

Source

: not a fence

Parse result

null

#27 colons mid-line are text

Source

use std::vector here

Parse result

null

#28 empty line is text

Source

(empty)

Parse result

null

#29 anonymous div

invalid

Source

::: {.foo}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": null,
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_MISSING_NAME DIRECTIVE_TRAILING_CONTENT

#30 attributes with no name

invalid

Source

:::{.foo}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": null,
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [
      "foo"
    ],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_MISSING_NAME

#31 argument with no name

invalid

Source

:::[Title]

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": null,
  "argument": "Title",
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_MISSING_NAME

#32 name starting with a digit

invalid

Source

:::9card

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": null,
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_BAD_NAME

#33 name starting with a hyphen

invalid

Source

:::-card

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": null,
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_BAD_NAME

#34 unknown name

invalid

Source

:::panel

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "panel",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_UNKNOWN_NAME

#35 callout is not a directive

invalid

Source

:::callout

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "callout",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_UNKNOWN_NAME

#36 deferred construct is unknown in v0

invalid

Source

:::timeline

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "timeline",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_UNKNOWN_NAME

#37 separator name used as a block

invalid

Source

:::col

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "col",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_UNKNOWN_NAME

#38 names are case-sensitive

invalid

Source

:::Card

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "Card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_UNKNOWN_NAME

#39 space before the argument

invalid

Source

:::card [Title]

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_TRAILING_CONTENT

#40 space before the attributes

invalid

Source

:::card {tone=info}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_TRAILING_CONTENT

#41 space between argument and attributes

invalid

Source

:::card[T] {tone=info}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": "T",
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_TRAILING_CONTENT

#42 attributes before argument

invalid

Source

:::card{#x}[T]

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": "x",
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_TRAILING_CONTENT

#43 free text after the name

invalid

Source

:::card and more

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_TRAILING_CONTENT

#44 text after a closing fence is an unnamed opening fence

invalid

Source

::: done

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": null,
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_MISSING_NAME DIRECTIVE_TRAILING_CONTENT

#45 unterminated argument

invalid

Source

:::card[Title

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": "Title",
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_UNTERMINATED_ARGUMENT

#46 unbalanced nested bracket keeps the rest of the line

invalid

Source

:::card[a [b]

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": "a [b]",
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_UNTERMINATED_ARGUMENT

#47 escaped closing bracket leaves the argument open

invalid

Source

:::card[a\]

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": "a\\]",
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_UNTERMINATED_ARGUMENT

#48 bad attribute specifier propagates ATTR codes

invalid

Source

:::card{#}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: ATTR_BAD_IDENTIFIER

#49 unterminated attribute specifier

invalid

Source

:::card{tone=info

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "card",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {
      "tone": "info"
    }
  }
}

Diagnostics: ATTR_UNTERMINATED

#50 unknown name and bad attributes are both reported

invalid

Source

:::panel{=x}

Parse result

{
  "type": "directive-open",
  "fence": 3,
  "name": "panel",
  "argument": null,
  "attributes": {
    "type": "attributes",
    "id": null,
    "classes": [],
    "attrs": {}
  }
}

Diagnostics: DIRECTIVE_UNKNOWN_NAME ATTR_UNEXPECTED_CHAR

#51 document: canonical block

Source

:::card[Pricing tiers]{tone=info}
Content here.
:::

Rendered

Pricing tiers

Content here.

Downgrade

# Pricing tiers

Content here.

#52 document: argument is inline content

Source

:::card[Pricing *tiers* `now`]
:::

Rendered

Pricing tiers now

Downgrade

# Pricing *tiers* `now`

#53 document: empty content

Source

:::card
:::

Rendered

Downgrade

(empty)

#54 document: several blocks and blank lines inside

Source

:::card
One.

Two.

- a
- b
:::

Rendered

One.

Two.

  • a
  • b

Downgrade

One.

Two.

- a
- b

#55 document: nesting with a longer outer fence

Source

::::card[Outer]
Main.

:::card[Inner]
Side.
:::
::::

Rendered

Outer

Main.

Inner

Side.

Downgrade

# Outer

Main.

## Inner

Side.

#56 document: same-length fences close the outer, then the inner is unclosed and the last fence is stray

Source

:::card
:::card
inner
:::
:::

Rendered

inner

:::

Downgrade

inner

:::

Diagnostics: DIRECTIVE_UNCLOSED DIRECTIVE_STRAY_FENCE

#57 document: closing fence may be longer than the opening

Source

:::card
x
:::::

Rendered

x

Downgrade

x

#58 document: closing fence may be indented up to three spaces

Source

:::card
x
   :::

Rendered

x

Downgrade

x

#59 document: unclosed at end of document is a warning

Source

:::card
Text

Rendered

Text

Downgrade

Text

Diagnostics: DIRECTIVE_UNCLOSED

#60 document: opening fence and nothing else

Source

:::card

Rendered

Downgrade

(empty)

Diagnostics: DIRECTIVE_UNCLOSED

#61 document: unclosed inside a blockquote ends with the blockquote

Source

> :::card
> hi

after

Rendered

hi

after

Downgrade

> hi

after

Diagnostics: DIRECTIVE_UNCLOSED

#62 document: directive inside a blockquote

Source

> :::card
> hi
> :::

Rendered

hi

Downgrade

> hi

#63 document: directive inside a list item

Source

- item
  :::card
  inner
  :::

Rendered

  • item

    inner

Downgrade

- item

  inner

#64 document: directive interrupts a paragraph

Source

text
:::steps
1. a
:::
more

Rendered

text

  1. a

more

Downgrade

text

1. a

more

#65 document: stray closing fence is paragraph text

Source

Para

:::

Rendered

Para

:::

Downgrade

Para

:::

Diagnostics: DIRECTIVE_STRAY_FENCE

#66 document: stray fence as a lazy paragraph line

Source

Para
:::

Rendered

Para :::

Downgrade

Para
:::

Diagnostics: DIRECTIVE_STRAY_FENCE

#67 document: colons inside a code fence are code

Source

```
:::card
:::
```

Rendered

:::card
:::

Downgrade

```
:::card
:::
```

#68 document: code block containing a fence line needs a longer outer fence

Source

::::card
```
:::
```
::::

Rendered

:::

Downgrade

```
:::
```

#69 document: table content

Source

:::metrics
| a | b |
|---|---|
| 1 | 2 |
:::

Rendered

1
2

Downgrade

| a | b |
| - | - |
| 1 | 2 |

#70 document: four-space indented fence is indented code

Source

    :::card

Rendered

:::card

Downgrade

```
:::card
```

#71 document: plain CommonMark passes through

Source

# H

Para with `code` and ::: mid.

Rendered

H

Para with code and ::: mid.

Downgrade

# H

Para with `code` and ::: mid.

#72 document: CRLF line endings

Source

:::card
x
:::

Rendered

x

Downgrade

x

#73 document: malformed opening fence still forms a block

invalid

Source

::: {.foo}
x
:::

Rendered

x

Downgrade

x

Diagnostics: DIRECTIVE_MISSING_NAME DIRECTIVE_TRAILING_CONTENT

#74 document: unknown name still forms a block

invalid

Source

:::panel
x
:::

Rendered

x

Downgrade

x

Diagnostics: DIRECTIVE_UNKNOWN_NAME

#75 document: attribute errors carry through

invalid

Source

:::card{#}
:::

Rendered

Downgrade

(empty)

Diagnostics: ATTR_BAD_IDENTIFIER

#76 document: unterminated argument yields a null argument

invalid

Source

:::card[oops
x
:::

Rendered

x

Downgrade

x

Diagnostics: DIRECTIVE_UNTERMINATED_ARGUMENT

#77 document: closing fence with trailing text is a malformed opening fence

invalid

Source

:::card
x
::: done

Rendered

x

Downgrade

x

Diagnostics: DIRECTIVE_MISSING_NAME DIRECTIVE_TRAILING_CONTENT DIRECTIVE_UNCLOSED DIRECTIVE_UNCLOSED