Skip to content

Commit b7f2489

Browse files
Split docs/SPECIFICATION.html (closes #238)
1 parent 6346554 commit b7f2489

14 files changed

Lines changed: 2028 additions & 1286 deletions

docs/SPECIFICATION.html

Lines changed: 0 additions & 1150 deletions
This file was deleted.

docs/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
Prefix is a statement-based, imperative language focused on explicit, readable code.
2020

21-
- [Prefix Specification](./SPECIFICATION.html)
21+
- [Prefix Specification](./specification/0-toc-and-preamble.html)
2222
- [Change log](./CHANGELOG.html)
2323
- [Unlicense](./UNLICENSE.html)
2424

docs/render-md.js

Lines changed: 141 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,141 @@
1-
/* Centralized markdown renderer for the docs.
2-
Loads marked.js if necessary, then renders the markdown embedded
3-
in the page's `#md` element into `#content` and normalizes heading ids. */
4-
(function(){
5-
function slugify(text) {
6-
return (text || '')
7-
.trim()
8-
.toLowerCase()
9-
.replace(/<[^>]+>/g, '')
10-
.replace(/[^a-z0-9\s-]/g, '')
11-
.replace(/\s+/g, '-');
12-
}
13-
14-
function ensureTocStyle() {
15-
if (document.getElementById('generated-toc-style')) return;
16-
var style = document.createElement('style');
17-
style.id = 'generated-toc-style';
18-
style.textContent = '\n' +
19-
'.generated-toc { padding-left: 1.2rem; }\n' +
20-
'.generated-toc > li { margin: 0.6rem 0; }\n' +
21-
'.generated-toc li ul { margin-top: 0.25rem; margin-bottom: 0.25rem; }\n';
22-
document.head.appendChild(style);
23-
}
24-
25-
function findTocHeading(root) {
26-
return Array.from(root.querySelectorAll('h2')).find(function(h){
27-
return (h.textContent || '').trim().toLowerCase() === 'table of contents';
28-
});
29-
}
30-
31-
function buildTocList(root, tocHeading) {
32-
var tocLevels = new Set([2,3,4]);
33-
var items = Array.from(root.querySelectorAll('h2,h3,h4')).filter(function(h){ return h !== tocHeading; });
34-
if (items.length === 0) return null;
35-
36-
var tocRoot = document.createElement('ul');
37-
tocRoot.className = 'generated-toc';
38-
var listStack = [tocRoot];
39-
var currentLevel = 2;
40-
41-
items.forEach(function(h){
42-
var level = Number(h.tagName.slice(1));
43-
if (!tocLevels.has(level)) return;
44-
45-
while (currentLevel < level) {
46-
var parentList = listStack[listStack.length - 1];
47-
var parentLi = parentList.lastElementChild;
48-
if (!parentLi || parentLi.tagName.toLowerCase() !== 'li') {
49-
parentLi = document.createElement('li');
50-
parentLi.textContent = '';
51-
parentList.appendChild(parentLi);
52-
}
53-
var nested = document.createElement('ul');
54-
parentLi.appendChild(nested);
55-
listStack.push(nested);
56-
currentLevel += 1;
57-
}
58-
59-
while (currentLevel > level) {
60-
listStack.pop();
61-
currentLevel -= 1;
62-
}
63-
64-
var li = document.createElement('li');
65-
var a = document.createElement('a');
66-
a.href = '#' + h.id;
67-
a.textContent = (h.textContent || '').trim();
68-
li.appendChild(a);
69-
listStack[listStack.length - 1].appendChild(li);
70-
});
71-
72-
return tocRoot;
73-
}
74-
75-
function replaceTocBlock(root) {
76-
var tocHeading = findTocHeading(root);
77-
if (!tocHeading) return;
78-
79-
var stop = tocHeading.nextElementSibling;
80-
while (stop && stop.tagName.toLowerCase() !== 'hr') {
81-
stop = stop.nextElementSibling;
82-
}
83-
84-
var node = tocHeading.nextSibling;
85-
while (node && node !== stop) {
86-
var next = node.nextSibling;
87-
node.remove();
88-
node = next;
89-
}
90-
91-
ensureTocStyle();
92-
var tocList = buildTocList(root, tocHeading);
93-
if (!tocList) return;
94-
95-
if (stop) {
96-
root.insertBefore(tocList, stop);
97-
} else {
98-
root.appendChild(tocList);
99-
}
100-
}
101-
102-
function render() {
103-
var mdEl = document.getElementById('md');
104-
if (!mdEl) return;
105-
var md = mdEl.textContent;
106-
var rendered = (window.marked && typeof marked.parse === 'function') ? marked.parse(md) : md;
107-
var container = document.getElementById('content');
108-
if (container) container.innerHTML = rendered;
109-
110-
var headings = container ? container.querySelectorAll('h1,h2,h3,h4,h5,h6') : [];
111-
Array.prototype.forEach.call(headings, function(h){
112-
if (!h.id || h.id.trim() === '') {
113-
h.id = slugify(h.textContent || h.innerText || '');
114-
}
115-
});
116-
117-
replaceTocBlock(container);
118-
}
119-
120-
function ensureMarked(cb) {
121-
if (window.marked && typeof marked.parse === 'function') {
122-
cb();
123-
return;
124-
}
125-
var s = document.createElement('script');
126-
s.src = 'https://cdn.jsdelivr.net/npm/marked/marked.min.js';
127-
s.onload = cb;
128-
s.onerror = cb;
129-
document.head.appendChild(s);
130-
}
131-
132-
document.addEventListener('DOMContentLoaded', function(){
133-
ensureMarked(render);
134-
});
135-
})();
1+
/* Centralized markdown renderer + fully auto-generated multi-file TOC.
2+
- Renders the markdown in #md into #content (using marked.js).
3+
- Assigns github-slugger-style unique ids to every heading.
4+
- Builds a Table of Contents covering EVERY spec file and ALL of their
5+
subheadings, straight from window.SPEC_INDEX (generated from source).
6+
Links belonging to the current file are marked .current (bold). */
7+
(function () {
8+
'use strict';
9+
10+
function slugify(text) {
11+
return (text || '')
12+
.trim()
13+
.toLowerCase()
14+
.replace(/<[^>]+>/g, '')
15+
.replace(/[^a-z0-9\s-]/g, '')
16+
.replace(/\s+/g, '-');
17+
}
18+
19+
function ensureTocStyle() {
20+
if (document.getElementById('generated-toc-style')) return;
21+
var style = document.createElement('style');
22+
style.id = 'generated-toc-style';
23+
style.textContent =
24+
'\n' +
25+
'.generated-toc { padding-left: 1.2rem; }\n' +
26+
'.generated-toc > li { margin: 0.6rem 0; }\n' +
27+
'.generated-toc li ul { margin-top: 0.25rem; margin-bottom: 0.25rem; }\n' +
28+
'.generated-toc a.current { font-weight: 700; }\n' +
29+
'.toc-title { text-align: left; }\n';
30+
document.head.appendChild(style);
31+
}
32+
33+
function render() {
34+
var mdEl = document.getElementById('md');
35+
if (!mdEl) return;
36+
var md = mdEl.textContent;
37+
var rendered =
38+
window.marked && typeof marked.parse === 'function' ? marked.parse(md) : md;
39+
var container = document.getElementById('content');
40+
if (container) container.innerHTML = rendered;
41+
42+
var headings = container
43+
? container.querySelectorAll('h1,h2,h3,h4,h5,h6')
44+
: [];
45+
var used = Object.create(null);
46+
Array.prototype.forEach.call(headings, function (h) {
47+
var slug = slugify(h.textContent || h.innerText || '');
48+
var cand = slug,
49+
n = 1;
50+
while (used[cand]) {
51+
cand = slug + '-' + n;
52+
n++;
53+
}
54+
used[cand] = true;
55+
h.id = cand;
56+
});
57+
58+
buildMultiFileToc(container);
59+
}
60+
61+
function buildMultiFileToc(container) {
62+
var index = window.SPEC_INDEX;
63+
if (!index || !index.length || !container) return;
64+
65+
var cur = (location.pathname.split('/').pop() || location.href.split('/').pop() || '')
66+
.toLowerCase();
67+
68+
ensureTocStyle();
69+
70+
var nav = document.createElement('nav');
71+
nav.id = 'spec-toc';
72+
73+
var title = document.createElement('h2');
74+
title.className = 'toc-title';
75+
title.textContent = 'Table of contents';
76+
nav.appendChild(title);
77+
78+
var rootUl = document.createElement('ul');
79+
rootUl.className = 'generated-toc';
80+
81+
// One continuous stack across every file so each file's top-level
82+
// heading is a sibling of the others (no empty wrapper <li>).
83+
var listStack = [rootUl];
84+
var currentLevel = 2;
85+
86+
index.forEach(function (fileEntry) {
87+
(fileEntry.headings || []).forEach(function (h) {
88+
var level = h.level;
89+
while (currentLevel < level) {
90+
var parentList = listStack[listStack.length - 1];
91+
var parentLi = parentList.lastElementChild;
92+
if (!parentLi || parentLi.tagName.toLowerCase() !== 'li') {
93+
parentLi = document.createElement('li');
94+
parentList.appendChild(parentLi);
95+
}
96+
var nested = document.createElement('ul');
97+
parentLi.appendChild(nested);
98+
listStack.push(nested);
99+
currentLevel += 1;
100+
}
101+
while (currentLevel > level) {
102+
listStack.pop();
103+
currentLevel -= 1;
104+
}
105+
var li = document.createElement('li');
106+
var a = document.createElement('a');
107+
var sameFile = (fileEntry.file || '').toLowerCase() === cur;
108+
a.href = (sameFile ? '#' : fileEntry.file + '#') + h.slug;
109+
a.textContent = h.text;
110+
if (sameFile) a.className = 'current';
111+
li.appendChild(a);
112+
listStack[listStack.length - 1].appendChild(li);
113+
});
114+
});
115+
116+
nav.appendChild(rootUl);
117+
118+
var hr = document.createElement('hr');
119+
120+
var h1 = container.querySelector('h1');
121+
var ref = h1 && h1.nextSibling ? h1.nextSibling : container.firstChild;
122+
container.insertBefore(hr, ref);
123+
container.insertBefore(nav, ref);
124+
}
125+
126+
function ensureMarked(cb) {
127+
if (window.marked && typeof marked.parse === 'function') {
128+
cb();
129+
return;
130+
}
131+
var s = document.createElement('script');
132+
s.src = 'https://cdn.jsdelivr.net/npm/marked/marked.min.js';
133+
s.onload = cb;
134+
s.onerror = cb;
135+
document.head.appendChild(s);
136+
}
137+
138+
document.addEventListener('DOMContentLoaded', function () {
139+
ensureMarked(render);
140+
});
141+
})();
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width,initial-scale=1" />
6+
<title>Prefix Specification</title>
7+
<link rel="icon" href="../icon.png" />
8+
<link rel="stylesheet" href="../style.css" />
9+
</head>
10+
<body>
11+
<div class="container" id="content">Rendering specification…</div>
12+
13+
<!-- Markdown source is embedded below. marked.js renders it; the TOC is auto-generated. -->
14+
<script id="md" type="text/markdown">
15+
# <a href="../index.html"><img class="title-icon" alt="Prefix icon" src="../icon.png"></a> <span class="semibold">Pre<span class="grey">fix</span></span> Specification
16+
17+
18+
## 1. Preamble
19+
20+
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [IETF RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119), as clarified in [IETF RFC 8174](https://datatracker.ietf.org/doc/html/rfc8174).
21+
22+
Prefix is a statically typed, imperative, interpreted programming language focused on explicit, readable source code.
23+
24+
Programs MUST consist of variable declarations via assignment, expressions, and control-flow constructs.
25+
26+
---
27+
28+
</script>
29+
30+
<script src="./index.js"></script>
31+
<script src="../render-md.js"></script>
32+
</body>
33+
</html>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width,initial-scale=1" />
6+
<title>Prefix Specification</title>
7+
<link rel="icon" href="../icon.png" />
8+
<link rel="stylesheet" href="../style.css" />
9+
</head>
10+
<body>
11+
<div class="container" id="content">Rendering specification…</div>
12+
13+
<!-- Markdown source is embedded below. marked.js renders it; the TOC is auto-generated. -->
14+
<script id="md" type="text/markdown">
15+
# <a href="../index.html"><img class="title-icon" alt="Prefix icon" src="../icon.png"></a> <span class="semibold">Pre<span class="grey">fix</span></span> Specification
16+
17+
18+
## 10. Standard library
19+
20+
The standard library is a set of packages and modules bundled with the interpreter that provide a set of common utilities.
21+
22+
Bundled standard-library modules MUST live under `lib/std/`. User-installed modules and packages MUST live under `lib/usr/`. Module and package search paths used by `IMPORT` and `IMPORT_PATH` MUST consult `lib/std/` immediately before `lib/usr/`, so bundled modules are preferred over user-installed copies.
23+
24+
Bundled extensions shipped with the interpreter MUST live under `ext/std/`. User-installed extensions MUST live under `ext/usr/`. Extension search paths MUST consult `ext/std/` immediately before `ext/usr/`, so bundled extensions are preferred over user-installed copies with the same name.
25+
26+
At present, most of the standard library is not defined by the specification, and any reasonable set of standard utilities is acceptable for a conforming implementation. Backwards-incompatible changes to the standard library MUST NOT increment the major version number of the specification, unless the incompatible change is altering a behaviour defined in this specification.
27+
28+
### 10.1 Path
29+
30+
Path is a standard-library module that provides utilities for working with filesystem paths. It is implemented as a single module importable under the name `path`.
31+
32+
#### 10.1.1 API
33+
34+
- `str NORMALIZE_PATH(str path)` = Replace all backslashes in the path with forward slashes.
35+
- `str WINPATH(str path)` = Replace all forward slashes in the path with backslashes.
36+
- `str BASEPATH(str path)` = Return the directory part of the path, excluding the file name.
37+
- `str BASENAME(str path)` = Return the file name part of the path, excluding the directory.
38+
- `tensor SPLITEXT(str path)` = Split the path into a tensor containing the base name and the extension.
39+
- `str EXTNAME(str path)` = Return the file extension from the path, without the dot.
40+
- `str DELEXT(str path)` = Return the path without the file extension.
41+
- `str TEMPFILE(str prefix, str suffix)` = Modify the path to originate in the system's temporary directory.
42+
- `str interpreter` = The path to the Prefix interpreter executable.
43+
- `str interpreter_dir` = The directory containing the Prefix interpreter executable.
44+
- `str script` = The path to the currently executing script.
45+
- `str script_dir` = The directory containing the currently executing script.
46+
47+
48+
</script>
49+
50+
<script src="./index.js"></script>
51+
<script src="../render-md.js"></script>
52+
</body>
53+
</html>

0 commit comments

Comments
 (0)