Extension Schema Specification

Quarto extensions can provide a _schema.yml file alongside their _extension.yml manifest. This file declares every configurable option, shortcode parameter, format key, element attribute, and CSS class the extension accepts.

A single schema serves two consumers:

Warning

Schema specification support in Quarto Wizard may evolve over time. Quarto CLI may use, modify, or discard this schema behaviour in future releases. No guarantees are provided regarding Quarto CLI native support.

File Location

Place _schema.yml (or _schema.yaml) in the same directory as _extension.yml. A _schema.json file is also supported alongside or instead of the YAML variants.

Tree
_extensions/
└── my-extension/
    ├── _extension.yml
    ├── _schema.yml
    └── my-extension.lua

When both a JSON and a YAML schema exist in the same directory, the JSON file takes precedence. JSON files use camelCase keys natively (e.g., enumCaseInsensitive, patternExact, minLength), whereas YAML files use kebab-case (e.g., enum-case-insensitive, pattern-exact, min-length).

Quarto Wizard discovers schema files automatically when scanning installed extensions.

Schema Version ($schema)

Schema files may include a $schema key at the top level to declare the schema format version. This is optional but recommended for forward-compatibility.

$schema: https://m.canouil.dev/quarto-wizard/assets/schema/v2/extension-schema.json
options:
  threshold:
    type: number

Two versions are currently supported in parallel:

  • https://m.canouil.dev/quarto-wizard/assets/schema/v2/extension-schema.json (v1, default; kebab-case canonical with camelCase aliases).
  • https://m.canouil.dev/quarto-wizard/assets/schema/v2/extension-schema.json (v2; JSON Schema canonical names exclusively).

When the $schema key is omitted, the file is validated against v1. When an unrecognised version URI is encountered, Quarto Wizard emits a warning but does not reject the schema. This allows older tooling to gracefully handle schemas written for newer versions.

v1 vs v2 vocabulary

v2 drops dual-keying so every keyword has exactly one canonical name, matching JSON Schema 2020-12 conventions wherever a JSON Schema equivalent exists.

Concept v1 canonical (YAML) v2 canonical
Minimum / maximum min / max minimum / maximum
Exclusive bounds exclusive-minimum / exclusive-maximum exclusiveMinimum / exclusiveMaximum
String length min-length / max-length minLength / maxLength
Array length min-items / max-items minItems / maxItems
Numeric step multiple-of multipleOf
Case-insensitive enum enum-case-insensitive enumCaseInsensitive
Object extra keys additional-properties additionalProperties
Object key regex property-names propertyNames
Conditional requirement dependent-required dependentRequired
Content metadata content-encoding / content-media-type contentEncoding / contentMediaType
Deprecation replacement replace-with replaceWith
Anchored pattern pattern-exact: true Removed — write ^...$ in pattern directly
Shortcode required attrs Per-attribute required: true only Per-attribute required: true OR parent-level required: [name1, ...]

Migration is mostly mechanical: rewrite kebab-case keyword names to their camelCase equivalents and replace min / max with minimum / maximum.

Top-level Structure

The schema has six optional top-level sections. An extension may define any combination of these.

# Extension-level metadata options (all extension types).
# Configured under the extension name in YAML metadata.
options:
  <option-name>: <field-descriptor>

# Per-shortcode schemas (one entry per contributed shortcode).
shortcodes:
  <shortcode-name>:
    description: <string>
    arguments:
      - name: <string>
        <field-descriptor properties>
    attributes:
      <attribute-name>: <field-descriptor>

# Per-format schemas (one entry per contributed format).
# Configured under format: <format-name>: in YAML metadata.
formats:
  <format-name>:
    <option-name>: <field-descriptor>

# Project types contributed by the extension.
# Suggested for project.type in _quarto.yml.
projects:
  - <project-type>

# Element attributes accepted by filters on Div/Span/CodeBlock elements.
# Used in: [text]{.class attr=value} or ::: {.class attr=value}
# These are Pandoc AST element attributes, not metadata options.
attributes:
  <class-or-context>:
    <attribute-name>: <field-descriptor>

# CSS classes contributed by filters, with descriptions.
# Used in: [text]{.class} or ::: {.class}
classes:
  <class-name>:
    description: <string>

options

Extension-level configuration options. Users set these values in _quarto.yml, _metadata.yml, or document front matter, scoped under the extension name inside an extensions key.

Given a _schema.yml for an extension called spotlight:

_extensions/spotlight/_schema.yml
options:
  size:
    type: number
    default: 60
    description: "Radius of the spotlight circle in pixels."
  lockPointerInsideCanvas:
    type: boolean
    default: false
    description: "Whether to lock the mouse pointer inside the canvas."

The corresponding user configuration in _quarto.yml would be:

_quarto.yml
extensions:
  spotlight:
    size: 80
    lockPointerInsideCanvas: true

The same structure works in _metadata.yml or document front matter:

presentation.qmd
---
title: "My Presentation"
extensions:
  spotlight:
    size: 80
---

shortcodes

Per-shortcode schemas, keyed by shortcode name. Each shortcode entry can specify a description, positional arguments (as an ordered array), and named attributes (as a map).

shortcodes:
  modal:
    description: "Generate a Bootstrap modal toggle or dismiss button."
    arguments:
      - name: type
        type: string
        default: "toggle"
        enum: [toggle, dismiss]
        description: "Button type: toggle to open, dismiss to close."
    attributes:
      target:
        type: string
        description: "ID of the modal to target (without the # prefix)."
      label:
        type: string
        description: "Button label text."

Shortcode arguments use the same field descriptor properties as options, plus a required name field that identifies the positional argument.

formats

Per-format options, keyed by the format name as it appears in YAML metadata (e.g., letter-pdf, invoice-pdf).

formats:
  letter-pdf:
    address:
      type: array
      required: true
      description: "Recipient address lines."
      items:
        type: string
    subject:
      type: string
      description: "Letter subject line."

projects

An array of project type strings contributed by the extension. These values are suggested for project.type in _quarto.yml.

projects:
  - my-website

attributes

Attributes accepted by filter extensions on Pandoc Div, Span, CodeBlock, and Header elements. Groups are matched against the current element using five strategies:

  • _any: matches any element regardless of class, ID, or type.
  • CSS class name (e.g. panel, highlight): matches elements that carry that class.
  • ID prefix (e.g. modal matches #modal-example): matches elements whose ID starts with that prefix followed by a hyphen.
  • Pandoc element type (Div, Span, Code, CodeBlock, Header): matches based on the structural context (fenced div :::, bracketed span ], backtick code `, or ATX heading #).

Group key matching is case-insensitive: div matches Div, codeblock matches CodeBlock, header matches Header, and so on.

Use _any for attributes accepted on any element regardless of class.

attributes:
  _any:
    colour:
      type: string
      aliases: [color, ink, fg]
      description: "Text (foreground) colour."
      completion:
        type: color
    bg-colour:
      type: string
      aliases: [bg-color, bg, paper]
      description: "Background colour."
      completion:
        type: color
  Header:
    toc-depth:
      type: number
      min: 1
      max: 6
      description: "Override table-of-contents depth for this heading."
  CodeBlock:
    filename:
      type: string
      description: "Display filename label for the code block."

classes

CSS classes contributed by the extension’s filters. Each entry maps a class name to a descriptor containing a description. Quarto Wizard uses this information to provide class name completion and hover documentation in fenced divs (:::), bracketed spans ([]), and code block attributes.

classes:
  panel:
    description: "Wraps content in a styled panel box."
  highlight:
    description: "Applies highlight styling to the element."
  callout-note:
    description: "Renders a note-style callout block."

Field Descriptor Properties

Every option, argument, or attribute is described by the same set of properties. All properties are optional.

Type and Value Constraints

Property Type Description
type string Expected value type: string, number, integer, boolean, array, object, null, or content.
required boolean Whether the field must be present. Default: false.
default any Default value applied when not provided.
const any Fixed value the field must equal.
enum array List of allowed values.
enum-case-insensitive boolean Case-insensitive enum matching. Default: false.
pattern string Regular expression the value must match (JS regex syntax).
pattern-exact boolean Deprecated. Anchor the pattern to match the entire value (wraps in ^...$). Prefer writing ^...$ directly.
min number Minimum value (inclusive, for type: number or type: integer).
max number Maximum value (inclusive, for type: number or type: integer).
minimum number Alias for min.
maximum number Alias for max.
exclusive-minimum number Exclusive minimum (value must be strictly greater).
exclusive-maximum number Exclusive maximum (value must be strictly less).
multiple-of number Value must be a positive multiple of this number (for type: number or type: integer).
min-length integer Minimum string length (for type: string).
max-length integer Maximum string length (for type: string).
min-items integer Minimum number of items (for type: array).
max-items integer Maximum number of items (for type: array).
additional-properties boolean or field descriptor Whether object values may carry keys beyond those in properties. Default: true.
property-names string Regular expression all object keys must match (for type: object).
dependent-required object Map of key → list of keys that become required when that key is present (for type: object).
format string JSON Schema format hint (e.g. uri, email, date-time). Annotation only.
content-encoding string Content encoding for a string value (e.g. base64). Annotation only.
content-media-type string Media type of a string value (e.g. application/json). Annotation only.

The integer type validates that the value is a whole number. It supports the same numeric constraints as number (min, max, exclusive-minimum, exclusive-maximum, multiple-of).

The content type is specific to shortcode arguments and accepts any Pandoc Inlines, Blocks, or string value. Quarto Wizard rejects type: content outside shortcode arguments. Validation only checks presence (for required); no further type or pattern checking applies.

The null type matches the explicit YAML value null (or ~). Combine it with another type for nullable fields, e.g. type: [string, "null"].

In JSON schema files, multi-word property names use camelCase equivalents: enumCaseInsensitive, patternExact, minLength, maxLength, minItems, maxItems, exclusiveMinimum, exclusiveMaximum, multipleOf, additionalProperties, propertyNames, dependentRequired, contentEncoding, and contentMediaType. Mixing camelCase and kebab-case forms of the same keyword on one descriptor produces a warning.

Metadata Properties

Property Type Description
description string Human-readable description shown in hover tooltips and completion detail.
title string Short human-readable label.
examples array Example values for documentation and tooling.
aliases array<string> Alternative accepted names (e.g., [color] alongside colour).
deprecated boolean, string, or object Mark the field as deprecated (see Deprecation).

Nested Type Properties

Property Type Description
items field descriptor Schema for array elements (when type: array).
properties map<string, field descriptor> Schema for object keys (when type: object).

Completion

The completion object controls IDE autocomplete behaviour. When omitted, Quarto Wizard infers completion from other properties (e.g., enum values become suggestions, type: boolean suggests true/false).

Property Type Description
type string Completion strategy (see Completion types).
extensions array<string> File extension filter for type: file (e.g., [.csv, .xlsx]).
placeholder string Hint text for type: freeform.
values array Override values for type: enum (when different from validation enum).
dynamic boolean Values come from external sources (brand colours, filesystem). Default: false.
source string Hint for dynamic value source (e.g., "brand-colors", "git-remote").

Completion Types

Type IDE Behaviour
enum Suggests values from the enum or values property.
file Opens a file picker filtered by extensions.
directory Opens a directory picker.
color Shows a colour picker.
boolean Suggests true and false.
freeform Shows a text input with placeholder as hint.
size Suggests common CSS size values.
none Disables autocompletion for this field.

Features

Alias Resolution

Alternative field names allow extensions to accept multiple spellings. The IDE suggests all names; the Lua validator resolves aliases to the primary key.

colour:
  type: string
  aliases: [color, ink, fg]
  description: "Text colour."

If a user provides color: red, validation and merging resolve it to colour = "red".

Deprecation

The deprecated property supports three forms:

  • deprecated: true marks the field as deprecated with a generic warning.
  • deprecated: "Use X instead" uses the string as the warning message.
  • Object form with replace-with enables automatic value forwarding.
old_colour:
  type: string
  deprecated:
    since: "1.2"
    message: "Use colour instead."
    replace-with: colour

colour:
  type: string

When replace-with is specified, the deprecated key’s value is forwarded to the replacement key automatically. The IDE shows a diagnostic on deprecated fields.

Boolean Coercion

YAML parsers accept true, True, yes, on (and their negatives) as boolean values. Pandoc metadata may deliver these as native booleans or as the strings "true"/"false".

For type: boolean fields, string representations are normalised to native booleans before validation.

Nested Validation

When type: array with an items descriptor, each array element is validated against the items schema. When type: object with a properties descriptor, the object value is validated recursively.

badge:
  type: array
  description: "Array of badge configuration objects."
  items:
    type: object
    properties:
      key:
        type: string
        required: true
        description: "Unique identifier for the badge."
      colour:
        type: string
        aliases: [color]
        description: "Background colour for the badge."
        completion:
          type: color

Common Patterns

Filter with options

A filter extension that reads configuration from YAML metadata.

_schema.yml
options:
  enabled:
    type: boolean
    default: true
    description: "Enable or disable the extension."
  threshold:
    type: number
    min: 0
    max: 1
    default: 0.5
    description: "Detection threshold value."

Shortcode with arguments and attributes

A shortcode extension with positional arguments and named attributes.

_schema.yml
shortcodes:
  iconify:
    description: "Renders an Iconify icon."
    arguments:
      - name: set-or-icon
        type: string
        required: true
        description: "Icon set name, or 'set:icon' combined format."
      - name: icon
        type: string
        description: "Icon name when the first argument is the set name."
    attributes:
      size:
        type: string
        description: "Icon size as a keyword or CSS value."
      flip:
        type: string
        enum: [horizontal, vertical, "horizontal,vertical"]
        description: "Flip transformation for the icon."

Format extension

A format extension with format-specific options.

_schema.yml
formats:
  letter-pdf:
    address:
      type: array
      required: true
      description: "Recipient address lines."
      items:
        type: string
    opening:
      type: string
      description: "Opening salutation."
    closing:
      type: string
      description: "Closing salutation."

Element attributes with colour picker

A filter extension that processes element attributes with IDE colour picker support.

_schema.yml
attributes:
  _any:
    colour:
      type: string
      aliases: [color, ink, fg]
      description: "Text (foreground) colour."
      completion:
        type: color
    bg-colour:
      type: string
      aliases: [bg-color, bg, paper]
      description: "Background colour."
      completion:
        type: color
    border-colour:
      type: string
      aliases: [border-color, bc]
      description: "Border colour."
      completion:
        type: color

Combined extension

An extension that defines options, shortcodes, and attributes together.

_schema.yml
options:
  size:
    type: string
    default: ""
    enum: ["", sm, lg, xl]
    enum-case-insensitive: true
    description: "Default modal dialog size."
  fade:
    type: boolean
    default: false
    description: "Apply a fade transition."

shortcodes:
  modal:
    description: "Generate a Bootstrap modal button."
    arguments:
      - name: type
        type: string
        default: "toggle"
        enum: [toggle, dismiss]
        description: "Button type."
    attributes:
      target:
        type: string
        description: "ID of the modal to target."
      label:
        type: string
        description: "Button label text."

attributes:
  modal:
    size:
      type: string
      enum: ["", sm, lg, xl]
      enum-case-insensitive: true
      description: "Modal dialog size override."
    fade:
      type: boolean
      description: "Apply a fade transition for this modal."

Reference Schema Files

The JSON Schema meta-schemas that formally describe the structure of _schema.yml and _schema.json files are published at:

These are the same schemas referenced by the $schema key at the top of schema definition files. They can be used by any JSON Schema-aware tool for validation and autocompletion.

Example instances showing every supported property are also available:

Generating a Schema with AI

The prompt below can be used with an AI assistant to generate a _schema.yml for an existing extension. Copy the prompt, attach your extension’s _extension.yml and Lua source files, and the assistant will produce a schema that matches your extension’s actual behaviour.

Prompt for generating `_schema.yml`
Generate a `_schema.yml` file for the attached Quarto extension.

Read the attached `_extension.yml` to identify the extension name and
contribution types (filters, shortcodes, formats, projects).

Then read every Lua source file to discover:

1. **Options** read from `meta` or `meta['extensions']` tables.
   Record each key, its expected type, any default value, and whether
   it is required.
2. **Shortcode arguments and attributes** parsed in shortcode handler
   functions. Record positional arguments (in order) and named
   attributes with their types, defaults, and allowed values.
3. **Format-specific options** read under a format name in metadata.
4. **Attributes** read from `el.attributes` in Div, Span, or
   CodeBlock filter functions. Group them by CSS class (use `_any` when
   the attribute applies regardless of class).
5. **Classes** contributed by the extension's filters. List each CSS
   class name the extension handles, with a short description.
   Look for patterns such as `el.classes:includes("name")`,
   `el.classes:find("name")`, or class-based conditionals.
6. **Project types** declared or contributed by the extension. If the
   extension provides a project type, list it under the `projects`
   top-level key.

For every field use the following properties where applicable:

- `type`: `string`, `number`, `integer`, `boolean`, `array`, `object`,
  `null`, or `content` (the last only for shortcode arguments that
  receive Pandoc content).
  Use `integer` when only whole numbers are valid.
  When a field accepts multiple types, express the union with an
  array on `type`: e.g. `type: [string, number]` or
  `type: [string, "null"]`.
  Do NOT use JSON Schema combinators such as `oneOf`, `anyOf`,
  `allOf`, or `not` for type unions; they are not part of this
  vocabulary and will be flagged as unknown properties.
- `required`: set to `true` only when the code raises an error or
  returns early for missing values.
- `default`: the fallback value used in the code.
- `const`: a fixed value the field must equal, when the code expects
  exactly one value.
- `enum`: list of allowed values when the code checks against a
  fixed set.
- `enum-case-insensitive`: `true` when the code lowercases or
  case-folds before comparing.
- `pattern`: regular expression the value must match (JS syntax).
- `pattern-exact`: `true` to anchor the pattern with `^...$`.
- `min` / `max`: inclusive numeric bounds
  (`minimum` and `maximum` are accepted as aliases).
- `exclusive-minimum` / `exclusive-maximum`: exclusive numeric bounds
  (value must be strictly greater / strictly less).
- `multiple-of`: value must be a positive multiple of this number.
- `min-length` / `max-length`: string length constraints.
- `min-items` / `max-items`: array item count constraints.
- `additional-properties`: `false` to forbid extra keys on a
  `type: object`, or a nested field descriptor that every extra value
  must match.
- `property-names`: regular expression every object key must match.
- `dependent-required`: map of key → list of keys that become required
  whenever that key is present.
- `format`: JSON Schema format hint (`uri`, `email`, `date-time`, etc.).
  Annotation only.
- `title`: short human-readable label.
- `examples`: list of example values for documentation and tooling.
- `aliases`: alternative key names accepted by the code.
- `deprecated`: `true`, a message string, or an object with `since`,
  `message`, and `replace-with` keys.
- `description`: one sentence in British English explaining the option.
- `completion`: controls IDE autocompletion behaviour. Sub-properties:
  `type` (`color` for CSS colour values, `file` for file paths,
  `freeform` for text input, `none` to disable), `extensions`
  (file extensions to filter when `type: file`), `placeholder`
  (hint text for `freeform`), `values` (static suggestion list),
  `dynamic` and `source` (for runtime-resolved values).
  Omit `completion` to let the IDE infer from `enum` and `type`.
- `items`: schema for elements of an `array` type. Use `items` to
  describe what each array element looks like (its type, enum, etc.).
- `properties`: schema for keys of an `object` type. Use `properties`
  to describe each expected key and its constraints.

Output only the YAML content of `_schema.yml`, nothing else.
Use kebab-case for multi-word property names (`enum-case-insensitive`,
not `enumCaseInsensitive`).
Add a one-line comment header: `# Schema for the <name> extension`.
Optionally include `$schema: https://m.canouil.dev/quarto-wizard/assets/schema/v2/extension-schema.json`
at the top level.
Reference: https://m.canouil.dev/quarto-wizard/reference/schema-specification.llms.md