Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
27b936b
feat(core/cddl): add CDDL support with parsing, highlighting, and cro…
marcoscaceres Apr 17, 2026
6b302a5
fix(core/cddl): address review feedback for index and clipboard handling
Copilot Apr 17, 2026
d5ea37a
docs(core/cddl-index): clarify optional consolidated index id param
Copilot Apr 17, 2026
9a94e1e
fix(tests): fix Copilot's heading test to account for header-wrapper
marcoscaceres Apr 17, 2026
b0b5214
fix: address Sid review findings
marcoscaceres Apr 17, 2026
f7e97d4
fix: address accessibility, security, and export review findings
marcoscaceres Apr 17, 2026
6bb1613
fix: modernize CSS units, add lang attr, update basic.built.html
marcoscaceres Apr 17, 2026
d831ea1
fix(core/cddl): avoid duplicate unresolved inline-ref warnings
Copilot Apr 17, 2026
54ccdf9
fix(cddl): address review blockers
marcoscaceres Apr 17, 2026
43314df
fix(core/cddl): register prose-defined value defs for inline refs
Copilot Apr 17, 2026
678a933
chore(core/cddl): fix TS6 lint issues after rebase
Copilot Apr 17, 2026
85a03e0
fix(core/cddl): tighten definition link resolution after TS6 lint pass
Copilot Apr 17, 2026
947c2b2
fix(cddl): address Sid's review feedback
marcoscaceres Apr 17, 2026
7b87940
Merge branch 'main' into feat/cddl-support
marcoscaceres Apr 19, 2026
2d8533f
fix(core/cddl): resolve TS6 CI lint errors in cddl and cddl-index
Copilot Apr 19, 2026
ebaeeea
refactor(core/cddl-index): initialize module bucket before push
Copilot Apr 19, 2026
e787cac
test(core/cddl): align invalid syntax expectation with processing err…
Copilot Apr 19, 2026
ed8ff9d
chore: revert unintended builds artifact updates
Copilot Apr 19, 2026
a2d9832
chore(ci): align builds outputs with main
Copilot Apr 19, 2026
865817c
Merge branch 'main' into feat/cddl-support
marcoscaceres Apr 19, 2026
523ec6a
fix(core/cddl): address Sid's review feedback
marcoscaceres Apr 20, 2026
d146fd1
fix(core/cddl): apply html tag to template strings, use renameElement
marcoscaceres Apr 21, 2026
be2e591
fix(core/cddl): add type assertion for attr in normalizeProseDfns
marcoscaceres Apr 21, 2026
e191ab9
Merge branch 'main' into feat/cddl-support
marcoscaceres Apr 21, 2026
42558ab
Merge branch 'main' into feat/cddl-support
sidvishnoi Apr 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion examples/basic.built.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
Expand Down Expand Up @@ -70,6 +70,53 @@ <h2>Start your spec!</h2>
<li>A |variable:DOMString| can be declared like this.</li>
</ol>
</section>
<section>
<h2>WebDriver BiDi Extension for Foo</h2>
<p>
This section defines the WebDriver BiDi [[WEBDRIVER-BIDI]] protocol
commands for the {{Foo}} interface.
</p>
<section>
<h3>The <code>foo.doTheFoo</code> Command</h3>
<p>
The <dfn cddl-type>FooDoTheFooCommand</dfn> invokes {{Foo/doTheFoo()}}
on the remote end. The {^FooDoTheFooParameters/bar^} parameter maps to
the {{Foo}}'s {{Foo/bar}} attribute.
</p>
<pre class="cddl">
FooDoTheFooCommand = {
method: "foo.doTheFoo",
params: FooDoTheFooParameters,
}

FooDoTheFooParameters = {
bar: tstr,
? timeout: uint,
? level: FooLevel,
}

FooLevel = "low" / "medium" / "high"
</pre>
<p>
The {^FooDoTheFooParameters/bar^} parameter is required. The
{^FooDoTheFooParameters/timeout^} parameter is optional and defaults
to 30 seconds. The {^FooLevel^} can be {^FooLevel/"low"^},
{^FooLevel/"medium"^}, or {^FooLevel/"high"^}.
</p>
</section>
<section>
<h3>The <code>foo.doTheFoo</code> Result</h3>
<p>On success, the remote end returns a {^FooDoTheFooResult^}.</p>
<pre class="cddl">
FooDoTheFooResult = {
success: bool,
? message: tstr,
? data: bstr,
}
</pre>
</section>
</section>
<section id="cddl-index"></section>
<section id="conformance">
<p>
This is required for specifications that contain normative material.
Expand Down
49 changes: 48 additions & 1 deletion examples/basic.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
Expand Down Expand Up @@ -70,6 +70,53 @@ <h2>Start your spec!</h2>
<li>A |variable:DOMString| can be declared like this.</li>
</ol>
</section>
<section>
<h2>WebDriver BiDi Extension for Foo</h2>
<p>
This section defines the WebDriver BiDi [[WEBDRIVER-BIDI]] protocol
commands for the {{Foo}} interface.
</p>
<section>
<h3>The <code>foo.doTheFoo</code> Command</h3>
<p>
The <dfn cddl-type>FooDoTheFooCommand</dfn> invokes {{Foo/doTheFoo()}}
on the remote end. The {^FooDoTheFooParameters/bar^} parameter maps to
the {{Foo}}'s {{Foo/bar}} attribute.
</p>
<pre class="cddl">
FooDoTheFooCommand = {
method: "foo.doTheFoo",
params: FooDoTheFooParameters,
}

FooDoTheFooParameters = {
bar: tstr,
? timeout: uint,
? level: FooLevel,
}

FooLevel = "low" / "medium" / "high"
</pre>
<p>
The {^FooDoTheFooParameters/bar^} parameter is required. The
{^FooDoTheFooParameters/timeout^} parameter is optional and defaults
to 30 seconds. The {^FooLevel^} can be {^FooLevel/"low"^},
{^FooLevel/"medium"^}, or {^FooLevel/"high"^}.
</p>
</section>
<section>
<h3>The <code>foo.doTheFoo</code> Result</h3>
<p>On success, the remote end returns a {^FooDoTheFooResult^}.</p>
<pre class="cddl">
FooDoTheFooResult = {
success: bool,
? message: tstr,
? data: bstr,
}
</pre>
</section>
</section>
<section id="cddl-index"></section>
<section id="conformance">
<p>
This is required for specifications that contain normative material.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@rollup/plugin-terser": "^1.0.0",
"@types/pluralize": "0.0.33",
"boxen": "^8.0.1",
"cddlparser": "^0.6.0",
"chokidar": "^5.0.0",
"clean-css": "^5.3.3",
"epipebomb": "^1.0.0",
Expand Down
21 changes: 8 additions & 13 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions profiles/w3c.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const modules = [
import("../src/core/figures.js"),
import("../src/core/tables.js"),
import("../src/core/webidl.js"),
import("../src/core/cddl.js"),
import("../src/core/biblio.js"),
import("../src/core/link-to-dfn.js"),
import("../src/core/xref.js"),
Expand All @@ -39,6 +40,7 @@ const modules = [
import("../src/core/sections.js"),
import("../src/core/fix-headers.js"),
import("../src/core/webidl-index.js"),
import("../src/core/cddl-index.js"),
import("../src/core/structure.js"),
import("../src/core/informative.js"),
import("../src/core/id-headers.js"),
Expand Down
131 changes: 131 additions & 0 deletions src/core/cddl-index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// @ts-check
/**
* Module: core/cddl-index
* Constructs a summary of CDDL in the document by
* cloning all the generated CDDL nodes and
* appending them to a pre element.
*
* Usage:
* Add a <section id="cddl-index"> to the document.
* It also supports title elements to generate a header.
* Or if a header element is an immediate child, then
* that is preferred.
*/
export const name = "core/cddl-index";
import { nonNormativeSelector, renameElement } from "./utils.js";

export function run() {
/** @type {HTMLElement | null} */
const cddlIndexSec = document.querySelector("section#cddl-index");
if (!cddlIndexSec) {
return;
}

if (
!cddlIndexSec.querySelector(":scope > :is(h2, h3, h4, h5, h6):first-child")
) {
const heading = document.createElement("h2");
if (cddlIndexSec.title) {
heading.textContent = cddlIndexSec.title;
cddlIndexSec.removeAttribute("title");
} else {
heading.textContent = "CDDL Index";
}
cddlIndexSec.prepend(heading);
}

// Filter out CDDL marked with class="exclude" and in non-normative sections
const cddlBlocks = /** @type {HTMLElement[]} */ (
Array.from(
document.querySelectorAll("pre.cddl:not(.exclude) > code")
).filter(cddl => !cddl.closest(nonNormativeSelector))
);

if (cddlBlocks.length === 0) {
const text = "This specification doesn't normatively declare any CDDL.";
cddlIndexSec.append(text);
return;
}

// Group by module if data-cddl-module is used
/** @type {Map<string, HTMLElement[]>} */
const modules = new Map();
for (const cddlCode of cddlBlocks) {
const pre = cddlCode.closest("pre");
const moduleName =
/** @type {HTMLElement} */ (pre)?.dataset.cddlModule || "";
let moduleBlocks = modules.get(moduleName);
if (!moduleBlocks) {
moduleBlocks = [];
modules.set(moduleName, moduleBlocks);
}
moduleBlocks.push(/** @type {HTMLElement} */ (cddlCode));
}

// Check if we have multiple modules
const hasModules =
modules.size > 1 || (modules.size === 1 && !modules.has(""));

if (hasModules) {
modules.forEach((blocks, moduleName) => {
const section = document.createElement("section");
const heading = document.createElement("h3");
const displayName = moduleName || "Default";
heading.textContent = `Module: ${displayName}`;
if (moduleName) {
heading.id = `cddl-index-module-${moduleName.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
}
section.append(heading);
section.append(createConsolidatedPre(blocks));
cddlIndexSec.append(section);
});
} else {
// Single consolidated pre
cddlIndexSec.append(createConsolidatedPre(cddlBlocks, "actual-cddl-index"));
}
}

/**
* Create a consolidated <pre class="cddl"> from multiple code blocks.
* @param {HTMLElement[]} cddlCodes - array of <code> elements inside <pre class="cddl">
* @param {string} [id] - optional id (used for the single consolidated index pre)
* @returns {HTMLPreElement}
*/
function createConsolidatedPre(cddlCodes, id) {
const pre = document.createElement("pre");
pre.classList.add("cddl", "def", "highlight");
if (id) {
pre.id = id;
}

const code = document.createElement("code");
cddlCodes
.map(elem => {
const fragment = document.createDocumentFragment();
elem.childNodes.forEach(child =>
fragment.appendChild(child.cloneNode(true))
Comment thread
marcoscaceres marked this conversation as resolved.
);
return fragment;
})
.forEach(fragment => {
if (code.lastChild) {
code.append("\n\n");
}
code.appendChild(fragment);
});

// Remove duplicate IDs
code.querySelectorAll("*[id]").forEach(elem => elem.removeAttribute("id"));

// Replace dfns with spans so the index doesn't create duplicate definitions
code.querySelectorAll("dfn").forEach(dfn => {
const span = renameElement(dfn, "span");
span.removeAttribute("data-export");
for (const attr of [...span.attributes]) {
if (attr.name.startsWith("data-dfn")) span.removeAttribute(attr.name);
}
});

pre.append(code);
return pre;
}
Loading
Loading