{"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"markdoc-tags","__idx":0},"children":["Markdoc tags"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Redocly projects write Markdown with ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://markdoc.dev"},"children":["Markdoc"]}," tags such as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{% admonition type=\"info\" %}"]},"."," ","Recheck parses those tags when you turn Markdoc parsing on, and the ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/cli/v2/recheck/presets#recheckmarkdoc"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["recheck/markdoc"]}," preset"]}," validates them."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Markdoc parsing is off by default, because Liquid and Jinja templates use the same ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{% %}"]}," delimiters for unrelated syntax."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"turn-on-markdoc-parsing","__idx":1},"children":["Turn on Markdoc parsing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["markdoc: true"]}," in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["recheck"]}," block and add the preset:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"extends:\n  - recheck/markdown\n  - recheck/markdoc\nrecheck:\n  markdoc: true\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["markdoc: true"]}," is the short form of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["markdoc: { schema: realm }"]},", which validates tags against the built-in schema of the Realm theme."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The preset's four rules only report when parsing is on."," ","With the preset but without ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["markdoc"]},", the command prints a warning that the rules can never report."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To write ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["about"]}," Markdoc syntax, wrap the literal tag in a code span, such as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["`{% partial /%}`"]},"."," ","A code span never parses as a tag."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"choose-or-extend-the-schema","__idx":2},"children":["Choose or extend the schema"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The object form picks the schema and adds your own tags:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"recheck:\n  markdoc:\n    schema: realm\n    extend:\n      tagsFile: ./markdoc-tags.yaml\n      tags:\n        raw-partial:\n          selfClosing: true\n          attributes:\n            file:\n              type: string\n              required: true\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Key"},"children":["Key"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["schema"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Required."]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["realm"]}," validates tags against the built-in Realm schema. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]}," parses and pairs tags without a schema check."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["extend.tags"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Your own tags, merged over the schema."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["extend.tagsFile"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A YAML file of tags, relative to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly.yaml"]},". Inline ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tags"]}," win over it. Set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tags"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tagsFile"]},", or both."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["With ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["schema: false"]},", tag pairing and the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["markdoc.tag"]}," scope still work, and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["markdoc-syntax"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["markdoc-pairing"]}," still report."," ","Only ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["markdoc-unknown-tag"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["markdoc-attributes"]}," go quiet, because there is no schema to check against."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Tags merge in the order built-in schema, then ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tagsFile"]},", then inline ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tags"]},"."," ","A tag defined twice is replaced whole, not merged attribute by attribute."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tagsFile"]}," that does not exist, is not valid YAML, or holds an invalid tag entry is a configuration error."," ","The run fails rather than silently skipping the Markdoc checks."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"tag-schema-shape","__idx":3},"children":["Tag schema shape"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Each tag has these keys:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"tag-name:\n  selfClosing: true\n  attributes:\n    level:\n      type: string\n      required: true\n      default: info\n      enum: [info, warning, danger]\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Key"},"children":["Key"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Type"},"children":["Type"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["selfClosing"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["boolean"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The tag is written as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{% tag /%}"]}," and has no close tag."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["attributes.<name>.type"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["string"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Required."]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["string"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["number"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["boolean"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["attributes.<name>.required"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["boolean"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The attribute must be present."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["attributes.<name>.default"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["any"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The default value."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["attributes.<name>.enum"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["[string]"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The allowed values."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["attributes.<name>.dynamic"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["boolean"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The value is computed, so only its presence is checked."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"generate-a-tags-file-from-a-theme","__idx":4},"children":["Generate a tags file from a theme"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A project that defines tags in a theme module, such as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme/markdoc/schema.ts"]},", can generate the tags file instead of writing it by hand:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"redocly recheck --generate-markdoc-schema --from=@theme/markdoc/schema.js --output=markdoc-tags.yaml\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Option"},"children":["Option"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["--from"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A module that exports ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tags"]},", as a named export or on the default export. Repeat it to merge several modules. Paths are relative to the working directory."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["--output"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Where to write the YAML file."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["--check"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Compare the file in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["--output"]}," with a fresh generation and fail if it differs, without writing. Use it in CI."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The command extracts the parts of each tag it can check statically: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["selfClosing"]},", and each attribute's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["type"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["required"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["default"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["enum"]},"."," ","An attribute with a custom class or a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["validate"]}," function is written as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["dynamic: true"]},"."," ","Two modules that define the same tag with different shapes fail the command, so the merge never picks one by flag order."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The command imports each module with Node.js, so the module must be JavaScript."," ","Compile a TypeScript module first, or run the CLI under a loader such as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tsx"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The generated file opens with a header that names its source modules and the command to regenerate it."," ","Commit the file and point ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["extend.tagsFile"]}," at it."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"how-markdoc-parsing-changes-other-rules","__idx":5},"children":["How Markdoc parsing changes other rules"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Turning ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["markdoc"]}," on changes how every rule sees a tag, not only the Markdoc rules:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Prose scopes leave the tag out."]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paragraph"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["heading"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["list-item"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blockquote"]},", and table cell scopes blank out the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{% ... %}"]}," span before a rule runs, with the same width, so a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["swap"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pattern"]}," match cannot fire on tag syntax, and a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["length"]}," count does not include it."," ","A heading or cell whose whole text is a tag produces no segment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["--fix"]}," never rewrites a tag."]}," ","A fix that would change the bytes of a tag is withheld and reported as a skipped fix."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Indented code blocks and setext headings are off."]}," ","Markdoc's own parser does not recognize them, and Realm renders them as prose, so Recheck matches that while the flag is on."," ","A ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{% table %}"]}," line followed by ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["---"]}," is a table row, not a heading."," ","Expect ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["heading-style"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blanks-around-headings"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["capitalization"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["code-block-style"]}," findings to move the first time you turn the flag on."]}]}]},"frontmatter":{"seo":{"title":"Lint Markdoc tags with Recheck","description":"Turn on Markdoc-aware parsing in Recheck, validate tags against a schema, and generate a tag schema from a theme."}},"tagList":[],"title":"Lint Markdoc tags with Recheck","lastModified":"2026-10-05T09:58:30.000Z"}