Skip to main content
Version: Current

AGENTS.md - docs/

The published site is Docusaurus 3.7 (MDX v3): https://nussknacker.io/documentation. The docs/ folder is uploaded to the repo that serves it (see CONTRIBUTING/README.md), so nothing in this repo builds the docs - a file that cannot compile is found only after the upload, when the site build fails. Compile what you touched yourself before handing the change over.

.md files are parsed as CommonMark, where { is ordinary text. .mdx files are JSX, where every unescaped { opens a JavaScript expression. The rules below are about .mdx only.

Curly braces in .mdx​

SpEL ({#input.amount}), JSON ({"a": 1}) and SQL quantifiers ({2,}) are all over these docs and all contain braces. MDX reads them in three ways, and only the first is loud:

Written in prose or a table cellWhat happens
{#input.amount}, {"a": 1}, {2,}build fails: Could not parse expression with acorn
{n}, {foo} - anything shaped like one identifiercompiles, then ReferenceError: n is not defined when the page renders
{}compiles to nothing - the braces vanish from the page, no error at all

Do not reflexively wrap braces in backticks to silence this. Backticks add monospace and a code meaning; when the braces are not code, or their neighbours are unstyled, that is the wrong fix. Choose by what the braces actually are:

  • Fenced code block - multi-line JSON, SpEL or HOCON configuration. Braces are inert inside a fence, so nothing needs escaping. This is the right home for anything longer than a phrase.
  • Inline code - `{#input.amount}`, `A{2,}` - the braces are code the reader could type: an expression, a JSON fragment, a quantifier. Use it when a code span is also how it should look.
  • Backslash escape, \{ and \} - the braces belong to running prose, or to a UI label quoted verbatim, and monospace would be wrong or inconsistent. Renders a bare {. Reach for this when the neighbouring items carry no code styling: in the quantifier table in components/matchRecognize.mdx, (\{2,\}) sits beside (+), (?) and (*), so backticking only the brace rows would look arbitrary.
  • {"{"} - only inside JSX children, where markdown escapes do not apply. selfManaged/configuration/Overview.mdx needs it and explains why in a comment; nothing else should.

Each escape widens a table cell by two characters - re-pad the column so the source pipes stay aligned.

Compiling a changed .mdx locally​

Set the checker up once, outside the repo:

mkdir -p /tmp/mdxcheck && cd /tmp/mdxcheck && npm install @mdx-js/mdx@3 remark-frontmatter remark-gfm
cat > check.mjs <<'EOF'
import {compile} from '@mdx-js/mdx'
import remarkFrontmatter from 'remark-frontmatter'
import remarkGfm from 'remark-gfm'
import {readFileSync} from 'node:fs'
let bad = 0
for (const f of process.argv.slice(2)) {
// Docusaurus preprocesses HTML comments away; plain MDX v3 rejects them, so do the same here
const src = readFileSync(f, 'utf8').replace(/<!--[\s\S]*?-->/g, '')
try { await compile(src, {remarkPlugins: [remarkFrontmatter, remarkGfm]}) }
catch (e) { bad++; console.log(`FAIL ${f}:${e.line ?? '?'} ${e.reason ?? e.message.split('\n')[0]}`) }
}
console.log(bad ? `${bad} file(s) fail` : 'all files compile')
EOF

Then, from the repo root:

node /tmp/mdxcheck/check.mjs $(git diff --name-only HEAD -- 'docs/**/*.mdx')   # changed files
node /tmp/mdxcheck/check.mjs $(find docs -name '*.mdx') # all 108, ~2s

A clean run only proves the files parse. It cannot see the second row of the table above, so also read back any {...} you left unescaped and confirm it is a real reference to something imported in the file, not prose that happens to look like an identifier.

Note on HTML comments: 58 .mdx files here use <!-- ... -->, which MDX v3 rejects on its own and Docusaurus strips in a compatibility step before compiling. That is why the checker above removes them too. Do not add new ones - write {/* ... */} - and do not "fix" the existing ones as a side errand.