Skip to content

About

Pre-alpha, dependency-free web component for variant-aware code examples: switch OS/shell/language, substitute variables, then copy tailored snippets into documentation.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

78 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

ProgBlocks

A dependency-free web component for variant-aware, personalisable code examples in technical documentation — pre-alpha.

What this is

ProgBlocks is a single custom element, <prog-block>, that renders variant-switchable, variable-substituted code examples for documentation: pick an OS/shell/language tab, fill in {{ variables }}, copy the result. Conceived for BerryWiki and decoupled by design so it can be injected into ddraig-ssg output, nextgen-languages previewers, or plain Markdown sites. What follows is what actually exists, not the pitch — for the itemised, evidence-backed version see AUDIT.adoc (verified vs. asserted vs. explicitly-not-claimed) and DEBT.adoc (known defects, with status).

Status

Pre-alpha. Nothing has been released. Every version field in the repository says 0.3.0 (aligned 2026-10-05). It is a pre-release number, not a release: there is no tag and no published package.

The core works and is tested. As of 2026-10-05 the component builds its shadow tree once and patches it in place; every piece of author or reader text reaches the page through textContent, never innerHTML. That one change closed the injection surface, made variables typeable, and made the tablist accessible. bun test runs 49 tests, 0 failing, and just a11y (axe-core in a real Chromium) reports no WCAG 2.2 AA violations on the demo. Nothing has been checked with a screen reader yet.

Scope was cut to the charter. ProgBlocks renders code examples; it is not an editor, IDE or language server. The contenteditable editor, the placeholder linter, split view, smart paste and the JSON/CSV/Nickel export (whose encodings were not real) have been removed; export is now a plain-text Download of the personalised example.

Try it

Open index.html in a browser, or embed it anywhere:

<script type="module" src="/path/to/progblocks/src/prog-block.js"></script>

<prog-block group="os" line-numbers>
  <template data-variant="macOS">brew install {{ package = ripgrep }}</template>
  <template data-variant="Linux">sudo apt-get install {{ package = ripgrep }}</template>
</prog-block>

Write example code inside <template> the way you would inside <pre>: escape < as &lt; and & as &amp;. Unescaped tags are dropped, never rendered. The stylesheet is resolved against the module's own URL, so the page can live at any depth.

Authoring reference

You write You get
<template data-variant="Name">…</template> (two or more) A tab per variant, WAI-ARIA tabs keyboard model (arrows, Home, End)
Plain text, no templates A single example; the language attribute is shown as its label
{{ name }} A labelled input; the value is substituted everywhere it appears, in every variant
{{ name = default }} The same, pre-filled with default until the reader types
group="os" Every block in the page with that group switches variant together
variant="Linux" The initially selected variant
persist (with group) The reader's tab choice is remembered in localStorage (key progblocks:variant:<group>) and restored on the next page load, ahead of variant. Only the variant name is stored; if storage is blocked, the group still syncs within the page
label="Operating system" Accessible name of the tablist (default "Example variants")
line-numbers A line-number gutter, hidden from assistive technology and from copy
language="bash" class="language-bash" on the <code>, for an external highlighter
filename="install.sh" The Download button's file name (default example.txt). Control and bidi characters, path separators, leading dots and Windows device names are removed or neutralised, and it is capped at 120 characters
glyph-mode A compact inline rendering with no header or inputs

Script API: block.variant (get/set), block.text (the personalised example), block.getVariable(name), block.setVariable(name, value), block.refresh() (re-reads authored content; only needed after editing a <template>'s .content directly, which no observer can see). Other light-DOM edits are picked up automatically. Events (bubbling, composed): progblocks:variant-change { variant }, progblocks:variable-change { name, value }. Styling: --pb-* custom properties, and ::part(header | tab | copy-button | download-button | variables | code | variable).

Features

Feature Status Notes
Custom element registers Works Guarded by tests/registration.test.js
Safe rendering of untrusted content Works No innerHTML in src/; tested for markup in variants, tab labels and typed values, mutation-checked once by hand on 2026-10-05 (not automated)
Variant tabs Works Tabs pattern with roving tabindex, aria-controls/aria-labelledby, wrap-around arrows, Home/End
Cross-block variant sync Works group attribute; page-local by default. With persist the reader's choice is remembered across page loads in localStorage, and other open tabs follow
Variable substitution Works Inline defaults; one input per variable across all variants; values survive variant switches; typing keeps focus
Copy to clipboard Works Copies the personalised text; result announced via a role=status live region
Download Works Saves the personalised text as plain text; filename attribute, default example.txt
Line numbers Works line-numbers attribute
Accessibility Audited, not screen-reader tested AA target. Labelled inputs, focus rings, forced-colours support, no colour-only state. axe-core: 0 violations (just a11y)
Syntax highlighting Absent Out of scope for now; the language-* class lets a host highlighter hook in
Reacting to light-DOM changes after connect Works A MutationObserver rebuilds the block (one rebuild per microtask), keeping the selected variant and the reader's values; focus inside the block is lost when it rebuilds. Edits to a <template>'s .content need block.refresh()
Grammar-backed variable parser Not planned Template variables are a regular expression in tokenize(). A2ML is retired (2026-10-05); the unimported src/a2ml-parser.js stub and the placeholder assets/tree-sitter-a2ml.wasm were deleted
K9 / Nickel validation triad Removed The unused src/k9-validator.js stub (which always reported "valid") and the self-describing contracts.ncl were deleted on 2026-10-06 (RELEASE-CRITERIA T2)

Documentation

Document What it answers
ARCHITECTURE.md The module map, the render model and why it's a problem, the shadow-DOM styling limitation, and how variants/variables/render fit together
AGENTS.md What this repo is, the canonical read order, and the hard do-nots
EXPLAINME.adoc Every substantive claim this project makes, mapped to the file/line that implements it and the test that evidences it — or "no automated evidence" where there is none
AUDIT.adoc What is verified, what is merely asserted, and what is explicitly not claimed
DEBT.adoc Known debt by kind, with evidence and status (OPEN / FLAG-ONLY / ACCEPTED)
CHANGELOG.md Project history — currently all [Unreleased]
SECURITY.md Threat model and how to report an issue
CONTRIBUTING.md How to work on this repo
GOVERNANCE.md How decisions get made
CODE_OF_CONDUCT.md Expected conduct and how to report a problem
.machine_readable/descriptiles/progblocks_chora.deed The repo deed: the machine-readable record of the repo and the entry point for agents ((manifest …) clause); current state is its (maturity …) clause
docs/wiki/Home.adoc The in-repo wiki landing page — canonical; the GitHub wiki is generated from docs/wiki/ by tools/publish-wiki.mjs

Development

just test    # bun test — the same command CI runs (`bun run test`)
just a11y    # axe-core audit of index.html in Chromium — set CHROMIUM_PATH (CI runs it too)

tests/component.test.js covers rendering safety, variants, variables, copy, embedding, the persist option and authored content that changes after render; tests/registration.test.js guards module loading; tests/ci-config.test.js and tests/dependabot-config.test.js guard the CI configuration.

Licence

MPL-2.0. Historic conflicting licence claims — AGPL in a stray settings.yml, CC-BY-SA in the launcher descriptor (then progblocks.launcher.a2ml, now progblocks.launcher_praxis.deed) — were resolved to MPL-2.0 in PR #15. SPDX headers estate-wide are MPL-2.0.

Origin

Conceived for BerryWiki; decoupled by design so it can be injected into ddraig-ssg output, nextgen-languages previewers, or plain Markdown sites. Part of the Hyperpolymath / Metadatastician ecosystem.

About

Pre-alpha, dependency-free web component for variant-aware code examples: switch OS/shell/language, substitute variables, then copy tailored snippets into documentation.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages