Skip to content

Commit 0f0f3ee

Browse files
authored
Merge pull request #3992 from ralfhandl/no-local-biblio
Build script: no local biblio, use only Specref ids
2 parents 08f92ad + aa17cea commit 0f0f3ee

File tree

7 files changed

+224
-102
lines changed

7 files changed

+224
-102
lines changed

scripts/md2html/md2html.js

+73-102
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ complete control over formatting and syntax highlighting */
55
'use strict';
66

77
/**
8-
@author Mike Ralphson <[email protected]>
9-
**/
8+
* @author Mike Ralphson <[email protected]>
9+
**/
1010

1111
const fs = require('fs');
1212
const path = require('path');
@@ -34,7 +34,7 @@ const md = require('markdown-it')({
3434
linkify: true,
3535
typographer: true,
3636
highlight: function (str, lang) {
37-
if (lang && hljs.getLanguage(lang)) { // && !argv.respec) {
37+
if (lang && hljs.getLanguage(lang)) {
3838
try {
3939
return '<pre class="nohighlight"><code>' +
4040
hljs.highlight(str, { language: lang }).value +
@@ -86,56 +86,9 @@ function preface(title,options) {
8686
],
8787
},
8888
],
89-
localBiblio: {
90-
"OpenAPI-Learn": {
91-
title: "OpenAPI - Getting started, and the specification explained",
92-
href: "https://learn.openapis.org/",
93-
publisher: "OpenAPI Initiative"
94-
},
95-
"OpenAPI-Registry": {
96-
title: "OpenAPI Initiative Registry",
97-
href: "https://spec.openapis.org/registry/index.html",
98-
publisher: "OpenAPI Initiative"
99-
},
100-
//TODO: remove localBiblio once Specref PRs https://github.com/tobie/specref/pulls/ralfhandl are merged
101-
"JSON-Schema-Validation-04": {
102-
authors: [ "Kris Zyp", "Francis Galiegue", "Gary Court" ],
103-
href: "https://datatracker.ietf.org/doc/html/draft-fge-json-schema-validation-00",
104-
publisher: "Internet Engineering Task Force (IETF)",
105-
status: "Internet-Draft",
106-
title: "JSON Schema: interactive and non interactive validation. Draft 4",
107-
date: "1 February 2013"
108-
},
109-
"JSON-Schema-05": {
110-
authors: [ "Austin Wright" ],
111-
href: "https://datatracker.ietf.org/doc/html/draft-wright-json-schema-00",
112-
publisher: "Internet Engineering Task Force (IETF)",
113-
status: "Internet-Draft",
114-
title: "JSON Schema: A Media Type for Describing JSON Documents. Draft 5",
115-
date: "13 October 2016"
116-
},
117-
"JSON-Schema-Validation-05": {
118-
authors: [ "Austin Wright", "G. Luff" ],
119-
href: "https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00",
120-
publisher: "Internet Engineering Task Force (IETF)",
121-
status: "Internet-Draft",
122-
title: "JSON Schema Validation: A Vocabulary for Structural Validation of JSON. Draft 5",
123-
date: "13 October 2016"
124-
},
125-
"JSON-Schema-Validation-2020-12": {
126-
authors: [ "Austin Wright", "Henry Andrews", "Ben Hutton" ],
127-
href: "https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00",
128-
publisher: "Internet Engineering Task Force (IETF)",
129-
status: "Internet-Draft",
130-
title: "JSON Schema Validation: A Vocabulary for Structural Validation of JSON. Draft 2020-12",
131-
date: "8 December 2020"
132-
},
133-
"SPDX": {
134-
href: "https://spdx.org/licenses/",
135-
title: "SPDX License List",
136-
publisher: "Linux Foundation"
137-
}
138-
}
89+
// localBiblio: {
90+
// // add local bibliography entries here, add them to https://www.specref.org/, and remove them here once published
91+
// }
13992
};
14093

14194
let preface = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>${md.utils.escapeHtml(title)}</title>`;
@@ -154,9 +107,10 @@ function preface(title,options) {
154107
preface += '</head><body>';
155108
preface += '<style>';
156109
preface += '#respec-ui { visibility: hidden; }';
157-
preface += 'h1,h2,h3 { color: #629b34; }';
158-
preface += '.dt-published { color: #629b34; } .dt-published::before { content: "Published "; }';
159-
preface += 'a[href] { color: #45512c; }'; // third OAI colour is #8ad000
110+
preface += '#title { color: #578000; } #subtitle { color: #578000; }';
111+
preface += '.dt-published { color: #578000; } .dt-published::before { content: "Published "; }';
112+
preface += 'h1,h2,h3,h4,h5,h6 { color: #578000; font-weight: normal; font-style: normal; }';
113+
preface += 'a[href] { color: #45512c; }';
160114
preface += 'body:not(.toc-inline) #toc h2 { color: #45512c; }';
161115
preface += 'table { display: block; width: 100%; overflow: auto; }';
162116
preface += 'table th { font-weight: 600; }';
@@ -166,7 +120,7 @@ function preface(title,options) {
166120
preface += 'pre { background-color: #f6f8fa !important; }';
167121
preface += 'code { color: #c83500 } th code { color: inherit }';
168122
preface += 'a.bibref { text-decoration: underline;}';
169-
preface += fs.readFileSync(path.resolve(__dirname,'gist.css'),'utf8').split('\n').join(' ');
123+
preface += fs.readFileSync(path.resolve(__dirname,'gist.css'),'utf8').split(/\r?\n/).join(' ');
170124
preface += '</style>';
171125
preface += `<h1 id="title">${title.split('|')[0]}</h1>`;
172126
preface += `<p class="copyright">Copyright © ${options.publishDate.getFullYear()} the Linux Foundation</p>`;
@@ -247,68 +201,31 @@ let indents = [0];
247201
for (let l in lines) {
248202
let line = lines[l];
249203

204+
// remove TOC from older spec versions, respec will generate a new one
250205
if (line.startsWith('## Table of Contents')) inTOC = true;
251206
if (line.startsWith('<!-- /TOC')) inTOC = false;
252207
if (inTOC) line = '';
253208

209+
// special formatting for Definitions section
254210
if (line.startsWith('## Definitions')) {
255211
inDefs = true;
256212
bsFix = false;
257213
}
258214
else if (line.startsWith('## ')) inDefs = false;
259215

216+
// recognize code blocks
260217
if (line.startsWith('```')) {
261218
inCodeBlock = !inCodeBlock;
262219
line += '\n'; // fixes formatting of first line of syntax-highlighted blocks
263220
}
264221

265-
if (!inCodeBlock && line.startsWith('#')) {
266-
let indent = 0;
267-
while (line[indent] === '#') indent++;
268-
let originalIndent = indent;
269-
270-
let prevIndent = indents[indents.length-1]; // peek
271-
let delta = indent-prevIndent;
272-
273-
if (!argv.respec) {
274-
if (delta===0) indent = lastIndent
275-
else if (delta<0) indent = lastIndent-1
276-
else if (delta>0) indent = lastIndent+1;
277-
}
278-
279-
if (indent < 0) {
280-
indent = 1;
281-
}
282-
if (argv.respec && (indent > 1)) {
283-
indent--;
284-
}
285-
let newIndent = indent;
286-
if (!argv.respec && (indent <= 2) && bsFix) {
287-
newIndent++;
288-
}
289-
290-
let title = line.split('# ')[1];
291-
if (inDefs) title = '<dfn>'+title+'</dfn>';
292-
line = ('#'.repeat(newIndent)+' '+title);
293-
294-
if (delta>0) indents.push(originalIndent);
295-
if (delta<0) {
296-
let d = Math.abs(delta);
297-
while (d>0) {
298-
indents.pop();
299-
d--;
300-
}
301-
}
302-
lastIndent = indent;
303-
}
304-
305222
if (line.indexOf('<a name="')>=0) {
306223
if (line.indexOf('<a name="parameterAllowEmptyValue"/>')>=0)
307224
// fix syntax error in 2.0.md
308225
line = line.replace('<a name="parameterAllowEmptyValue"/>','<span id="parameterAllowEmptyValue"></span>');
309226
else {
310-
line = line.replace('<a name=','<span id=');
311-
line = line.replace('</a>','</span>');
227+
// replace deprecated <a name="..."></a> with <span id="..."></span>
228+
line = line.replace(/<a name="([^"]+)"><\/a>/g,'<span id="$1"></span>');
312229
}
313230
}
314231

@@ -352,6 +269,7 @@ for (let l in lines) {
352269
line = line.replace('consult http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4)','consult [[HTML401]] [Section 17.13.4](http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4)');
353270
line = line.replace('[IANA Status Code Registry](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml)','[[IANA-HTTP-STATUS-CODES|IANA Status Code Registry]]');
354271
line = line.replace('[IANA Authentication Scheme registry](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml)','[[IANA-HTTP-AUTHSCHEMES]]');
272+
line = line.replace('[JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03)','[[JSON-Reference|JSON Reference]]');
355273
line = line.replace('[JSON Schema Specification Draft 4](https://json-schema.org/)','[[JSON-Schema-04|JSON Schema Specification Draft 4]]');
356274
line = line.replace('[JSON Schema Core](https://tools.ietf.org/html/draft-zyp-json-schema-04)','[[JSON-Schema-04|JSON Schema Core]]');
357275
line = line.replace('[JSON Schema Validation](https://tools.ietf.org/html/draft-fge-json-schema-validation-00)','[[JSON-Schema-Validation-04|JSON Schema Validation]]');
@@ -361,13 +279,15 @@ for (let l in lines) {
361279
line = line.replace('[JSON Schema Specification Draft 2020-12](https://tools.ietf.org/html/draft-bhutton-json-schema-00)','[[JSON-Schema-2020-12|JSON Schema Specification Draft 2020-12]]');
362280
line = line.replace('[JSON Schema Core](https://tools.ietf.org/html/draft-bhutton-json-schema-00)','[[JSON-Schema-2020-12|JSON Schema Core]]');
363281
line = line.replace('[JSON Schema Validation](https://tools.ietf.org/html/draft-bhutton-json-schema-validation-00)','[[JSON-Schema-Validation-2020-12|JSON Schema Validation]]');
364-
line = line.replace('[SPDX](https://spdx.org/licenses/)','[[SPDX]]');
282+
line = line.replace('[SPDX](https://spdx.org/licenses/) license','[[SPDX-Licenses]]');
365283
line = line.replace('[XML namespaces](https://www.w3.org/TR/xml-names11/)','[[xml-names11|XML namespaces]]');
366284
line = line.replace('JSON standards. YAML,','[[RFC7159|JSON]] standards. [[YAML|YAML]],'); // 2.0.md only
367285
line = line.replace('JSON or YAML format.','[[RFC7159|JSON]] or [[YAML|YAML]] format.');
368286
line = line.replace(/YAML version \[1\.2\]\(https:\/\/(www\.)?yaml\.org\/spec\/1\.2\/spec\.html\)/,'[[YAML|YAML version 1.2]]');
369287
}
370288

289+
// fix relative links (to examples)
290+
//TODO: adjust when moving examples to a different repo
371291
if (!inCodeBlock && line.indexOf('](../') >= 0) {
372292
const regExp = /\((\.\.[^)]+)\)/g;
373293
line = line.replace(regExp,function(match,group1){
@@ -376,6 +296,50 @@ for (let l in lines) {
376296
});
377297
}
378298

299+
// fix indentation of headings
300+
// - make sure that each heading is at most one level deeper than the previous heading
301+
// - reduce heading level by one if we're in respec mode except for h1
302+
if (!inCodeBlock && line.startsWith('#')) {
303+
let indent = 0;
304+
while (line[indent] === '#') indent++;
305+
let originalIndent = indent;
306+
307+
let prevIndent = indents[indents.length-1]; // peek
308+
let delta = indent-prevIndent;
309+
310+
if (!argv.respec) {
311+
if (delta===0) indent = lastIndent
312+
else if (delta<0) indent = lastIndent-1
313+
else if (delta>0) indent = lastIndent+1;
314+
}
315+
316+
if (indent < 0) {
317+
indent = 1;
318+
}
319+
if (argv.respec && (indent > 1)) {
320+
indent--;
321+
}
322+
let newIndent = indent;
323+
if (!argv.respec && (indent <= 2) && bsFix) {
324+
newIndent++;
325+
}
326+
327+
let title = line.split('# ')[1];
328+
if (inDefs) title = '<dfn>'+title+'</dfn>';
329+
line = ('#'.repeat(newIndent)+' '+title);
330+
331+
if (delta>0) indents.push(originalIndent);
332+
if (delta<0) {
333+
let d = Math.abs(delta);
334+
while (d>0) {
335+
indents.pop();
336+
d--;
337+
}
338+
}
339+
lastIndent = indent;
340+
}
341+
342+
// wrap section text in <section>...</section> tags for respec
379343
if (!inCodeBlock && argv.respec && line.startsWith('#')) {
380344
let heading = 0;
381345
while (line[heading] === '#') heading++;
@@ -384,16 +348,23 @@ for (let l in lines) {
384348
if (delta>0) delta = 1;
385349
let prefix = '';
386350
let newSection = '<section>';
387-
if (line.includes('## Version ')) {
351+
const m = line.match(/# Version ([0-9.]+)$/);
352+
if (m) {
388353
// our conformance section is headlined with 'Version x.y.z'
354+
// and respec needs a conformance section in a "formal" specification
389355
newSection = '<section class="override" id="conformance">';
356+
// adjust the heading to be at level 2 because respec insists on h2 here
357+
// Note: older specs had this at h4, newer specs at h2, and all heading levels have been reduced by 1 in the preceding block
358+
line = '#' + m[0];
359+
delta = 1;
360+
heading = 2;
390361
}
391362
if (line.includes('Appendix')) {
392363
newSection = '<section class="appendix">';
393364
}
394365

395366
// heading level delta is either 0 or is +1/-1, or we're in respec mode
396-
/* respec insists on <section>...</section> breaks around headings */
367+
// respec insists on <section>...</section> breaks around headings
397368

398369
if (delta === 0) {
399370
prefix = '</section>'+newSection;

tests/md2html/fixtures/.gitattributes

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.html text eol=lf

tests/md2html/fixtures/basic-new.html

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>OpenAPI Specification v30.0.1 | Introduction, Definitions, &amp; More</title><meta name="description" content="The OpenAPI Specification (OAS) defines a standard, programming language-agnostic interface description for HTTP APIs."><link rel="canonical" href="https://spec.openapis.org/oas/latest.html" /><script src="../js/respec-w3c.js" class="remove"></script><script class="remove">var respecConfig = {"specStatus":"base","latestVersion":"https://spec.openapis.org/oas/latest.html","editors":[],"formerEditors":[],"publishDate":"3001-04-01T00:00:00.000Z","subtitle":"Version 30.0.1","edDraftURI":"https://github.com/OAI/OpenAPI-Specification/","shortName":"OAS","historyURI":null,"lint":false,"logos":[{"src":"https://github.com/raw/OAI/OpenAPI-Style-Guide/master/graphics/bitmap/OpenAPI_Logo_Pantone.png","alt":"OpenAPI Initiative","height":48,"url":"https://openapis.org/"}],"otherLinks":[{"key":"Participate","data":[{"value":"GitHub OAI/OpenAPI-Specification","href":"https://github.com/OAI/OpenAPI-Specification/"},{"value":"File a bug","href":"https://github.com/OAI/OpenAPI-Specification/issues"},{"value":"Commit history","href":"https://github.com/OAI/OpenAPI-Specification/commits/main/versions/30.0.1.md"},{"value":"Pull requests","href":"https://github.com/OAI/OpenAPI-Specification/pulls"}]}]};</script></head><body><style>#respec-ui { visibility: hidden; }#title { color: #578000; } #subtitle { color: #578000; }.dt-published { color: #578000; } .dt-published::before { content: "Published "; }h1,h2,h3,h4,h5,h6 { color: #578000; font-weight: normal; font-style: normal; }a[href] { color: #45512c; }body:not(.toc-inline) #toc h2 { color: #45512c; }table { display: block; width: 100%; overflow: auto; }table th { font-weight: 600; }table th, table td { padding: 6px 13px; border: 1px solid #dfe2e5; }table tr { background-color: #fff; border-top: 1px solid #c6cbd1; }table tr:nth-child(2n) { background-color: #f6f8fa; }pre { background-color: #f6f8fa !important; }code { color: #c83500 } th code { color: inherit }a.bibref { text-decoration: underline;}/** * GitHub Gist Theme * Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro */ .hljs { display: block; background: white; padding: 0.5em; color: #333333; overflow-x: auto; } .hljs-comment, .hljs-meta { color: #969896; } .hljs-string, .hljs-variable, .hljs-template-variable, .hljs-strong, .hljs-emphasis, .hljs-quote { color: #df5000; } .hljs-number { color: #008080; } .hljs-keyword, .hljs-selector-tag, .hljs-type { color: #a71d5d; } .hljs-literal, .hljs-symbol, .hljs-bullet, .hljs-attribute { color: #0086b3; } .hljs-section, .hljs-name { color: #63a35c; } .hljs-tag { color: #333333; } .hljs-title, .hljs-attr, .hljs-selector-id, .hljs-selector-class, .hljs-selector-attr, .hljs-selector-pseudo { color: #795da3; } .hljs-addition { color: #55a532; background-color: #eaffea; } .hljs-deletion { color: #bd2c00; background-color: #ffecec; } .hljs-link { text-decoration: underline; } </style><h1 id="title">OpenAPI Specification v30.0.1 </h1><p class="copyright">Copyright © 3001 the Linux Foundation</p><section class="notoc" id="abstract"><h2>What is the OpenAPI Specification?</h2>The OpenAPI Specification (OAS) defines a standard, programming language-agnostic interface description for HTTP APIs, which allows both humans and computers to discover and understand the capabilities of a service without requiring access to source code, additional documentation, or inspection of network traffic. When properly defined via OpenAPI, a consumer can understand and interact with the remote service with a minimal amount of implementation logic. Similar to what interface descriptions have done for lower-level programming, the OpenAPI Specification removes guesswork in calling a service.</section><section class="override" id="sotd" data-max-toc="0"><h2>Status of This Document</h2>The source-of-truth for the specification is the GitHub markdown file referenced above.</section>
2+
<section><h1>Heading 1</h1>
3+
<p>Text for first chapter</p>
4+
<section class="override" id="conformance"><h2>Version 30.0.1</h2>
5+
<p>This is the conformance section</p>
6+
</section></section><section><h1>Heading 2</h1>
7+
<p>Text for first section</p>
8+
<section><h2>Heading 3</h2>
9+
<p>Text for first subsection</p>
10+
<pre class="nohighlight"><code>
11+
<span class="hljs-punctuation">{</span>
12+
<span class="hljs-attr">&quot;foo&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>
13+
<span class="hljs-punctuation">}</span>
14+
</code></pre>
15+
<pre class="nohighlight"><code>
16+
text/plain
17+
</code></pre>
18+
<pre class="highlight "><code>
19+
no language
20+
</code></pre>
21+
<table>
22+
<thead>
23+
<tr>
24+
<th>Version</th>
25+
<th>Date</th>
26+
</tr>
27+
</thead>
28+
<tbody>
29+
<tr>
30+
<td>30.0.1</td>
31+
<td>3001-04-01</td>
32+
</tr>
33+
</tbody>
34+
</table>
35+

tests/md2html/fixtures/basic-new.md

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Heading 1
2+
3+
Text for first chapter
4+
5+
## Version 30.0.1
6+
7+
This is the conformance section
8+
9+
## Heading 2
10+
11+
Text for first section
12+
13+
### Heading 3
14+
15+
Text for first subsection
16+
17+
```json
18+
{
19+
"foo": true
20+
}
21+
```
22+
23+
```text
24+
text/plain
25+
```
26+
27+
```
28+
no language
29+
```
30+
31+
Version | Date
32+
--------|-----------
33+
30.0.1 | 3001-04-01

0 commit comments

Comments
 (0)