Skip to content

Commit e5c89d9

Browse files
authored
Add support for non-prose elements (#82)
1 parent 031f3e8 commit e5c89d9

File tree

7 files changed

+264
-5
lines changed

7 files changed

+264
-5
lines changed

css/smpte.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,12 @@ figure {
247247
margin-top: 1rem;
248248
}
249249

250+
/* elements */
251+
252+
#sec-elements ol {
253+
list-style-type: none;
254+
}
255+
250256
/* links */
251257

252258
.ext-ref {

doc/elements/sample.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a sample element.

doc/main.html

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ <h2>Directory layout</h2>
9999
<ul>
100100
<li><code>doc/main.html</code>: main element of the document (see <a href="#sec-main-element"></a>).</li>
101101
<li><code>doc/media/</code>: directory containing media referenced by the main element (see <a href="#sec-figure-element"></a>).</li>
102+
<li><code>doc/elements/</code>: directory containing non-prose elements of the document (see <a
103+
href="#sec-elements-section"></a>).</li>
102104
<li><code>doc/snippets/</code>: directory containing snippets embedded in the main element (see <a href="#sec-snippets-element"></a>).</li>
103105
<li><code>tooling/</code>: directory consisting of the tools necessary to render SMPTE documents (see <a href="#sec-tooling"></a>).</li>
104106
<li><code>.smpte-build.json</code>: JSON file used to configure the HTML rendering process (see <a href="#sec-building"></a>).</li>
@@ -278,6 +280,10 @@ <h4>Overall structure</h4>
278280
<td><a>Annex section</a></td>
279281
<td>0 or more</td>
280282
</tr>
283+
<tr>
284+
<td><a>Additional elements section</a></td>
285+
<td>0 or 1</td>
286+
</tr>
281287
<tr>
282288
<td><a>Bibliography</a></td>
283289
<td>0 or 1</td>
@@ -531,6 +537,42 @@ <h4>Annex section(s)</h4>
531537

532538
</section>
533539

540+
<section id="sec-elements-section">
541+
<h4>Additional elements section</h4>
542+
543+
<p>The <dfn>additional elements section</dfn> collects the non-prose elements of the document.</p>
544+
545+
<p>The <code>id</code> attribute shall be present on the <code>section</code> element and equal to
546+
<code>sec-elements</code>.</p>
547+
548+
<p>The heading of the section shall not be present.</p>
549+
550+
<p>If present, the section shall:</p>
551+
<ul>
552+
<li>come immediately before the <a>Bibliography</a> section; and</li>
553+
<li>contain a single ordered list <code>ol</code> where each element <code>li</code> contains exactly one <code>a</code>
554+
that links to an element of the document.</li>
555+
</ul>
556+
557+
<p>Each <code>a</code> element shall have:</p>
558+
<ul>
559+
<li>an <code>id</code> attribute whose value is prefixed with <code>element-</code>;</li>
560+
<li>a <code>title</code> attribute that provides a short description of the element;</li>
561+
<li>a <code>href</code> attribute that links to the element itself, typically in the <code>doc/elements</code>
562+
directory.</li>
563+
</ul>
564+
565+
<div class="example">
566+
<pre>&lt;section id=&quot;sec-elements&quot;&gt;
567+
&lt;ol&gt;
568+
&lt;li&gt;
569+
&lt;a id=&quot;element-a&quot; title=&quot;Description of the elemnent&quot; href=&quot;./elements/form.docx&quot;&gt;&lt;/a&gt;
570+
&lt;/li&gt;
571+
&lt;/ol&gt;
572+
&lt;/section&gt;</pre>
573+
</div>
574+
</section>
575+
534576
<section id="sec-bibliography-section">
535577
<h4>Bibliography section</h4>
536578

@@ -593,6 +635,17 @@ <h4>Citing normative references</h4>
593635

594636
</section>
595637

638+
<section id="sec-elements-linking">
639+
<h4>Citing non-prose elements</h4>
640+
641+
<p>When citing an non-prose element of the document, an <code>a</code> element with its <code>href</code> attribute
642+
referencing a <code>a</code> element from the <a>additional elements section</a> shall be used.</p>
643+
644+
<div class="example">
645+
<code>&lt;a href=&quot;#element-a&quot;&gt;&lt;/a&gt;</code> is rendered as <a href="#element-a"></a>.
646+
</div>
647+
648+
</section>
596649

597650
<section id="sec-bibliographic-linking">
598651
<h4>Citing bibliographic references</h4>
@@ -1031,6 +1084,12 @@ <h3>Amazon AWS integration</h3>
10311084
</section>
10321085
</section>
10331086

1087+
<section id="sec-elements">
1088+
<ol>
1089+
<li><a id="element-a" title="Sample text element" href="./elements/sample.txt"></a></li>
1090+
</ol>
1091+
</section>
1092+
10341093
<section id="sec-bibliography">
10351094
<ul>
10361095
<li><cite id="bib-iso-directives-part2">ISO/IEC Directives, Part 2</cite>, Principles and rules for the structure and drafting

js/validate.mjs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ function _validateClause(e, lvl, logger) {
265265
}
266266

267267
function validateClause(e, logger) {
268-
if (e.classList.contains("annex") || e.id === "sec-bibliography")
268+
if (e.classList.contains("annex") || e.id === "sec-bibliography" || e.id === "sec-elements")
269269
return false;
270270

271271
_validateClause(e, 2, logger);
@@ -282,6 +282,27 @@ function validateAnnex(e, logger) {
282282
return true;
283283
}
284284

285+
function validateElementsAnnex(e, logger) {
286+
if (e.id !== "sec-elements")
287+
return false;
288+
289+
if (e.firstElementChild.tagName === "OL" && e.childElementCount === 1) {
290+
for (const li of e.firstElementChild.children) {
291+
if (li.tagName === "LI") {
292+
if (li.firstElementChild.tagName !== "A" || !li.firstElementChild.id || li.childElementCount !== 1 || !li.firstElementChild.title || !li.firstElementChild.href) {
293+
logger.error(`Each <li> element of the Elements Annex must contain a single <a> element with a title, id and href attributes.`);
294+
}
295+
} else {
296+
logger.error(`The <ol> element of the Elements Annex must contain only <li> elements`);
297+
}
298+
}
299+
} else {
300+
logger.error(`The Elements Annex section must contain a single <ol> element.`);
301+
}
302+
303+
return true;
304+
}
305+
285306
function validateBibliography(e, logger) {
286307
if (e.id !== "sec-bibliography")
287308
return false;
@@ -302,6 +323,7 @@ function validateBody(body, logger) {
302323
[validateDefs, 0, 1],
303324
[validateClause, 0, Infinity],
304325
[validateAnnex, 0, Infinity],
326+
[validateElementsAnnex, 0, 1],
305327
[validateBibliography, 0, 1],
306328
];
307329

@@ -319,18 +341,24 @@ function validateBody(body, logger) {
319341
while (index < sectionDefs.length) {
320342
sectionDef = sectionDefs.at(index);
321343

322-
if ((sectionDef.at(0))(child, logger))
344+
if ((sectionDef.at(0))(child, logger)) {
345+
matchCount++;
323346
break;
347+
}
348+
349+
index++;
324350

325351
if (matchCount < sectionDef.at(1))
326352
logger.error(`Too few instances of ${sectionDef.at(0).name}`);
327353

328-
matchCount = 0
354+
matchCount = 0;
329355

330-
index++;
331356
}
332357

333-
matchCount++;
358+
if (index >= sectionDefs.length) {
359+
logger.error(`Expected ${sectionDef.at(0).name} but found ${child.tagName} with id ${child.id}`);
360+
break
361+
}
334362

335363
if (matchCount > sectionDef.at(2))
336364
logger.error(`Too few instances of ${sectionDef.at(0).name}`);

smpte.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,55 @@ function insertBibliography(docMetadata) {
422422
h2.innerText = "Bibliography";
423423
}
424424

425+
const SMPTE_ELEMENTS_ID = "sec-elements";
426+
427+
function insertElementsAnnex(docMetadata) {
428+
const sec = document.getElementById(SMPTE_ELEMENTS_ID);
429+
430+
if (sec === null)
431+
return;
432+
433+
if (sec.children.length !== 1 || sec.firstElementChild.tagName !== "OL") {
434+
logEvent(`Elements section must contain a single <ol> element.`);
435+
return;
436+
}
437+
438+
sec.classList.add("annex");
439+
440+
const intro = document.createElement("p");
441+
intro.innerText = "This annex lists non-prose elements of this document."
442+
sec.insertBefore(intro, sec.firstChild);
443+
444+
const h2 = document.createElement("h2");
445+
h2.innerText = "Additional elements";
446+
sec.insertBefore(h2, sec.firstChild);
447+
448+
let counter = "a".charCodeAt();
449+
450+
for(const e of sec.querySelectorAll("li > a")) {
451+
452+
const headingNum = document.createElement("span");
453+
headingNum.className = "heading-number";
454+
headingNum.innerText = String.fromCharCode(counter++);
455+
456+
const headingLabel = document.createElement("span");
457+
headingLabel.className = "heading-label";
458+
headingLabel.appendChild(headingNum);
459+
headingLabel.appendChild(document.createTextNode("."));
460+
461+
e.parentElement.insertBefore(headingLabel, e);
462+
463+
e.innerText = "(link)";
464+
465+
if (e.title) {
466+
e.parentElement.insertBefore(document.createTextNode(" " + e.title + " "), e);
467+
} else {
468+
logEvent("All links listed in the Elements Annex must have a title attribute.")
469+
}
470+
471+
}
472+
}
473+
425474
const SMPTE_CONFORMANCE_ID = "sec-conformance";
426475

427476
function insertConformance(docMetadata) {
@@ -727,6 +776,47 @@ function numberNotes() {
727776
}
728777
}
729778

779+
function numberElements() {
780+
let counter = 1;
781+
782+
for (let e of document.querySelectorAll("#sec-elements li")) {
783+
784+
let numPrefix = "";
785+
786+
if (section.classList.contains("annex")) {
787+
counter = 1;
788+
numPrefix = section.querySelector(".heading-number").innerText + ".";
789+
}
790+
791+
for (let figure of section.querySelectorAll("figure")) {
792+
793+
const figcaption = figure.querySelector("figcaption");
794+
795+
if (figcaption === null) {
796+
logEvent(`Figure is missing a caption`);
797+
continue;
798+
}
799+
800+
const headingLabel = document.createElement("span");
801+
headingLabel.className = "heading-label";
802+
803+
const headingNumberElement = document.createElement("span");
804+
headingNumberElement.className = "heading-number";
805+
headingNumberElement.innerText = numPrefix + counter;
806+
807+
headingLabel.appendChild(document.createTextNode("Figure "));
808+
headingLabel.appendChild(headingNumberElement);
809+
headingLabel.appendChild(document.createTextNode(" –⁠ "));
810+
811+
812+
figcaption.insertBefore(headingLabel, figcaption.firstChild);
813+
814+
counter++;
815+
}
816+
817+
}
818+
}
819+
730820
function numberExamples() {
731821

732822
for (let section of document.querySelectorAll("section")) {
@@ -888,6 +978,11 @@ function resolveLinks(docMetadata) {
888978
anchor.innerText = targetNumber;
889979
}
890980

981+
} else if (target.parentElement.parentElement.parentElement.id === "sec-elements") {
982+
/* element */
983+
984+
anchor.innerText = "Element " + target.parentElement.querySelector(".heading-number").innerText;
985+
891986
} else {
892987
logEvent(`Anchor points to ambiguous #${target_id}`)
893988
anchor.innerText = "????";
@@ -929,6 +1024,7 @@ function render() {
9291024
insertNormativeReferences(docMetadata);
9301025
insertTermsAndDefinitions(docMetadata);
9311026

1027+
insertElementsAnnex(docMetadata);
9321028
insertBibliography(docMetadata);
9331029
numberSections(document.body, "");
9341030
numberTables();
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!doctype html>
2+
<html>
3+
<head itemscope="itemscope" itemtype="http://smpte.org/standards/documents">
4+
<meta charset="utf-8" />
5+
<meta http-equiv="x-ua-compatible" content="ie=edge" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<script src="../../../../smpte.js"></script>
8+
<meta itemprop="test" content="invalid" />
9+
<meta itemprop="pubType" content="AG" />
10+
<meta itemprop="pubNumber" content="99" />
11+
<meta itemprop="pubState" content="draft" />
12+
<meta itemprop="pubDateTime" content="20XX-XX-XX" />
13+
<title>Title of the document</title>
14+
</head>
15+
<body>
16+
<section id="sec-scope">
17+
<p>This is the scope of the document.</p>
18+
</section>
19+
<section>
20+
<h2>Hello</h2>
21+
22+
<p>Reference to <a href="#element-a"></a></p>
23+
</section>
24+
<section id="sec-elements">
25+
<ol>
26+
<li><a id="element-a" title="I am an element" href="https://smpte.org"></a></li>
27+
</ol>
28+
</section>
29+
<section class="annex" id="sec-last-annex">
30+
<h2>Last Annex</h2>
31+
</section>
32+
<section id="sec-bibliography">
33+
<ul>
34+
<li><cite id="bib-draft-bhutton-json-schema-00">IETF draft-bhutton-json-schema-00</cite>, Wright, A., H. Andrews; B. Hutton, G. Dennis, "JSON Schema: A Media Type for Describing JSON Documents", Work in Progress, December 8, 2020.
35+
<a>https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00</a></li>
36+
</ul>
37+
</section>
38+
</body>
39+
</html>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!doctype html>
2+
<html>
3+
<head itemscope="itemscope" itemtype="http://smpte.org/standards/documents">
4+
<meta charset="utf-8" />
5+
<meta http-equiv="x-ua-compatible" content="ie=edge" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<script src="../../../../smpte.js"></script>
8+
<meta itemprop="test" content="valid" />
9+
<meta itemprop="pubType" content="AG" />
10+
<meta itemprop="pubNumber" content="99" />
11+
<meta itemprop="pubState" content="draft" />
12+
<meta itemprop="pubDateTime" content="20XX-XX-XX" />
13+
<title>Title of the document</title>
14+
</head>
15+
<body>
16+
<section id="sec-scope">
17+
<p>This is the scope of the document.</p>
18+
</section>
19+
<section>
20+
<h2>Hello</h2>
21+
22+
<p>Reference to <a href="#element-a"></a></p>
23+
</section>
24+
<section id="sec-elements">
25+
<ol>
26+
<li><a id="element-a" title="I am an element" href="https://smpte.org"></a></li>
27+
</ol>
28+
</section>
29+
</body>
30+
</html>

0 commit comments

Comments
 (0)