This document explains how the documentation examples pipeline works under the hood.
Sections:
- Pipeline overview (“How it works”)
- Collector internals
- Manifest schema (selected)
- Test runner internals
- Special behaviors and notes
- Validation and references
- Collection phase (scripts/collect-docs-examples.js)
- Scans docs/ (excluding presentations, build artifacts, etc.)
- Finds include blocks:
{% include components/sampletabs_tpl.md ... %} - Resolves parameters:
formId,htmlSource,cssSource,jsHead,jsHidden,jsSource,tests,expectedConsoleErrors,expectedPageErrors, and additional flags (showEditor, showEditorSource, addLoadSaveButtons) - Resolves
{% capture %}blocks and performs recursive interpolation of{{ variables }}(including Jekyll filters like replace) - Applies transformations:
█→ four spaces (indentation)$$→-${formId}(ensures unique IDs per example)- Removes
!importantfrom CSS
- Skips examples with
jsSource="-" - Writes a JSON manifest to
test/.cache/docs_examples.json
- Execution phase (test/co_located_tests.tests.js)
- Loads the manifest
- For each example:
- Generates a minimal HTML page with the example’s HTML/CSS and SmarkForm library
- Injects JS (jsHead + jsHidden + jsSource) inside an IIFE
- Performs smoke checks:
- Page loads and form container is visible
- Console and page error counts match expectations
- Enforces tests presence (must be
tests=falseor valid code) - If custom tests are provided:
- Writes the code to a temporary .mjs file
- Dynamically imports it and invokes the default export with
{ page, expect, id, ...helpers }
Key steps:
- Capture extraction:
{% capture var %}...{% endcapture %}stored in-memory and referenced by include parameters. - Variable interpolation: recursively resolves
{{ variable }}, supportsreplacefilter. Special case:{{""}}becomes an empty string (Jekyll newline prevention). - Parameter resolution:
formIdused verbatim (not resolved from captures)tests=falserespected as a literal string- Other parameters may reference captures
- Docs-only parameters (filtered out, not passed to tests):
demoValue: seeds thedemosubform's default value in Jekyll viadata-smarkinjection. Irrelevant to the test form, which always starts empty. The collector explicitly skips it via theDOCS_ONLY_PARAMSset incollect-docs-examples.js.
- Transformations:
█→ spaces$$→-${formId}(done consistently across HTML/CSS/JS and tests)- CSS
!importantstripped
- Skips examples with
jsSource="-" - Default jsHead when missing:
const myForm = new SmarkForm(document.getElementById("myForm-${formId}"));
- Error expectations:
expectedConsoleErrorsandexpectedPageErrorsparsed as integers (default 0).
- Additional flags recorded:
showEditor,showEditorSource,addLoadSaveButtons(boolean by string comparison).
Each example entry resembles:
{
"id": "<docs_path>_<formId>",
"file": "<relative docs md file>",
"formId": "my_example",
"htmlSource": "...",
"cssSource": "...",
"jsHead": "...",
"jsHidden": "...",
"jsSource": "...",
"tests": "false | <ESM code string>",
"expectedConsoleErrors": 0,
"expectedPageErrors": 0,
"notes": "",
"showEditor": false,
"showEditorSource": false,
"addLoadSaveButtons": false
}Location: test/.cache/docs_examples.json (gitignored).
- Builds a temporary HTML page per example under
test/tmp/and serves it via the local test server (...helpers). - Injects
dist/SmarkForm.umd.jsand the example’s JS (jsHead + jsHidden + jsSource). - Records:
- Console messages (collects .type() and .text())
- Console errors (type === 'error')
- Page errors (page.on('pageerror'))
- Assertions:
- Form container
#myForm-${formId}is visible - Error counts match
expectedConsoleErrorsandexpectedPageErrors(default 0)
- Form container
- Tests enforcement:
- Missing/empty
testscauses a descriptive failure tests=falsedisables custom test execution but smoke checks still run
- Missing/empty
- Custom tests:
- Written to a temporary
.mjsmodule - Imported dynamically (
file://...) - Must export a default async function
- Receives
{ page, expect, id, root, ...helpers } root→#myForm-${id}locator
- Written to a temporary
- Skipping examples:
- Use
jsSource="-"to exclude a docs example from the manifest and runner (for purely illustrative cases).
- Use
- Explicitly disabling custom tests:
tests=falsesatisfies the enforcement and only skips custom test execution; smoke checks still apply.
- Error demonstrations:
- Use
expectedConsoleErrorsandexpectedPageErrorsto avoid red failures on intentional errors.
- Use
- showEditor handling:
- The collector records
showEditor,showEditorSource, andaddLoadSaveButtons. These flags don’t impact the runner assertions but are preserved for completeness and potential future use.
- The collector records
Validation tests at test/co_located_tests_validation.tests.js verify:
- The manifest loads
testsis present for all examples and none are emptyexpectedConsoleErrorsandexpectedPageErrorsexist and are valid- Known examples in docs/_test_examples.md have the expected configuration
- Transformations (no
█, no stray$$)
References:
- Examples: test/doc/_test_examples.md
- Collector: scripts/collect-docs-examples.js
- Runner: test/co_located_tests.tests.js