jsdoc-scribe 1.0.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +98 -0
- package/README.md +500 -110
- package/bin/cli.js +115 -115
- package/bin/gen-docs.js +299 -0
- package/lib/config.js +47 -0
- package/lib/docs.js +71 -0
- package/lib/extractor.js +456 -0
- package/lib/index.js +443 -427
- package/lib/renderer.js +575 -0
- package/package.json +21 -5
package/lib/renderer.js
ADDED
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const path = require("path");
|
|
4
|
+
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Themes
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
const THEMES = {
|
|
10
|
+
default: {
|
|
11
|
+
light: `:root{--bg:#f8f9fc;--surface:#fff;--border:#e0e4f0;--text:#1a1a2e;--text2:#666;--text3:#888;--sidebar-bg:#1a1a2e;--sidebar-text:#c8d3f0;--sidebar-active:#2d2d4e;--sidebar-title:#7986cb;--accent:#4361ee;--accent2:#e8eaf6;--search-bg:#2d2d4e;--search-border:#3a3a5e;--search-text:#e0e4f8;--search-panel:#252543;--th-bg:#f5f6fa;--code-bg:#f5f6fa;--sub-label:#7986cb;--method-border:#f0f0f0;--dep-bg:#fff8e1;--dep-text:#e65100;--throws-bg:#fce4ec;--throws-text:#c62828}`,
|
|
12
|
+
dark: `[data-theme=dark]{--bg:#0f0f1a;--surface:#1a1a2e;--border:#2d2d4e;--text:#e0e4f8;--text2:#9aa5c8;--text3:#5a6494;--sidebar-bg:#0a0a14;--sidebar-text:#9aa5c8;--sidebar-active:#1a1a2e;--sidebar-title:#5a6494;--accent:#6b8cff;--accent2:#1a1f3a;--search-bg:#1a1a2e;--search-border:#2d2d4e;--search-text:#c8d3f0;--search-panel:#0f0f1a;--th-bg:#1a1a2e;--code-bg:#1a1a2e;--sub-label:#5a6494;--method-border:#2d2d4e;--dep-bg:#2d2000;--dep-text:#ffb300;--throws-bg:#2d0a14;--throws-text:#ef9a9a}`,
|
|
13
|
+
toggleBtn: true,
|
|
14
|
+
},
|
|
15
|
+
minimal: {
|
|
16
|
+
light: `:root{--bg:#fff;--surface:#fafafa;--border:#e8e8e8;--text:#222;--text2:#555;--text3:#888;--sidebar-bg:#f5f5f5;--sidebar-text:#444;--sidebar-active:#e8e8e8;--sidebar-title:#888;--accent:#0066cc;--accent2:#e8f0fe;--search-bg:#fff;--search-border:#ddd;--search-text:#222;--search-panel:#fff;--th-bg:#f5f5f5;--code-bg:#f5f5f5;--sub-label:#888;--method-border:#efefef;--dep-bg:#fff8e1;--dep-text:#b36b00;--throws-bg:#fff0f0;--throws-text:#c00}`,
|
|
17
|
+
dark: ``,
|
|
18
|
+
toggleBtn: false,
|
|
19
|
+
},
|
|
20
|
+
dark: {
|
|
21
|
+
light: `:root{--bg:#0f0f1a;--surface:#1a1a2e;--border:#2d2d4e;--text:#e0e4f8;--text2:#9aa5c8;--text3:#5a6494;--sidebar-bg:#0a0a14;--sidebar-text:#9aa5c8;--sidebar-active:#1a1a2e;--sidebar-title:#5a6494;--accent:#6b8cff;--accent2:#1a1f3a;--search-bg:#1a1a2e;--search-border:#2d2d4e;--search-text:#c8d3f0;--search-panel:#0f0f1a;--th-bg:#1a1a2e;--code-bg:#1a1a2e;--sub-label:#5a6494;--method-border:#2d2d4e;--dep-bg:#2d2000;--dep-text:#ffb300;--throws-bg:#2d0a14;--throws-text:#ef9a9a}`,
|
|
22
|
+
dark: ``,
|
|
23
|
+
toggleBtn: false,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// CSS (shared structural rules; colors come from theme vars above)
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
const CSS_STRUCTURE = `
|
|
32
|
+
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
|
|
33
|
+
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-size:15px;line-height:1.6;color:var(--text);background:var(--bg);transition:background .2s,color .2s}
|
|
34
|
+
a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}
|
|
35
|
+
code,pre{font-family:'SFMono-Regular',Consolas,'Liberation Mono',Menlo,monospace}
|
|
36
|
+
.layout{display:flex;min-height:100vh}
|
|
37
|
+
.sidebar{width:272px;min-width:272px;background:var(--sidebar-bg);color:var(--sidebar-text);padding:0;display:flex;flex-direction:column;position:sticky;top:0;height:100vh;overflow-y:auto}
|
|
38
|
+
.sidebar-header{padding:18px 20px 12px;display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
|
|
39
|
+
.sidebar-header a{color:var(--text);font-size:15px;font-weight:700}
|
|
40
|
+
.sidebar-header .version{display:block;font-size:11px;color:var(--sidebar-title);margin-top:2px}
|
|
41
|
+
.theme-btn{background:none;border:1px solid var(--search-border);border-radius:5px;padding:3px 8px;font-size:12px;color:var(--sidebar-text);cursor:pointer;white-space:nowrap;flex-shrink:0;margin-top:2px}
|
|
42
|
+
.theme-btn:hover{background:var(--sidebar-active)}
|
|
43
|
+
.search-wrap{position:relative;padding:0 14px 12px;border-bottom:1px solid var(--search-border)}
|
|
44
|
+
.search-box{width:100%;background:var(--search-bg);border:1px solid var(--search-border);border-radius:6px;padding:7px 10px 7px 32px;color:var(--search-text);font-size:13px;outline:none}
|
|
45
|
+
.search-box::placeholder{color:var(--sidebar-title)}
|
|
46
|
+
.search-box:focus{border-color:var(--accent)}
|
|
47
|
+
.search-results{display:none;position:absolute;left:14px;right:14px;background:var(--search-panel);border:1px solid var(--search-border);border-radius:6px;max-height:320px;overflow-y:auto;z-index:100;margin-top:2px}
|
|
48
|
+
.search-results.visible{display:block}
|
|
49
|
+
.search-result-item{display:block;padding:8px 12px;cursor:pointer;border-bottom:1px solid var(--search-border);text-decoration:none}
|
|
50
|
+
.search-result-item:hover{background:var(--sidebar-active)}
|
|
51
|
+
.sr-name{font-size:13px;font-weight:600;color:var(--search-text);font-family:monospace}
|
|
52
|
+
.sr-kind{font-size:11px;color:var(--sidebar-title);margin-left:6px}
|
|
53
|
+
.sr-module{font-size:11px;color:var(--sidebar-title);display:block;margin-top:1px;opacity:.7}
|
|
54
|
+
.search-no-results{padding:10px 12px;color:var(--sidebar-title);font-size:13px}
|
|
55
|
+
.sidebar-section{padding:10px 0 4px}
|
|
56
|
+
.sidebar-section-title{padding:4px 20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--sidebar-title)}
|
|
57
|
+
.sidebar-link{display:block;padding:5px 20px;font-size:13px;color:var(--sidebar-text);transition:background .1s}
|
|
58
|
+
.sidebar-link:hover,.sidebar-link.active{background:var(--sidebar-active);color:var(--text);text-decoration:none}
|
|
59
|
+
.sidebar-dir-toggle{display:flex;align-items:center;gap:4px;cursor:pointer;list-style:none;padding:5px 20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--sidebar-title);user-select:none}
|
|
60
|
+
.sidebar-dir-toggle::-webkit-details-marker{display:none}
|
|
61
|
+
.sidebar-dir-toggle::before{content:'▶';font-size:8px;transition:transform .15s}
|
|
62
|
+
details[open] .sidebar-dir-toggle::before{transform:rotate(90deg)}
|
|
63
|
+
.sidebar-link-indent{padding-left:32px}
|
|
64
|
+
.main{flex:1;padding:40px 48px;max-width:960px}
|
|
65
|
+
.page-title{font-size:28px;font-weight:700;color:var(--text);margin-bottom:4px}
|
|
66
|
+
.page-subtitle{color:var(--text2);font-size:13px;margin-bottom:12px}
|
|
67
|
+
.module-desc{color:var(--text2);font-size:14px;line-height:1.6;margin-bottom:28px;max-width:700px}
|
|
68
|
+
.section{margin-bottom:40px}
|
|
69
|
+
.section-title{font-size:18px;font-weight:700;color:var(--text);margin-bottom:14px;padding-bottom:8px;border-bottom:2px solid var(--accent2)}
|
|
70
|
+
.card{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:18px 22px;margin-bottom:10px;scroll-margin-top:24px}
|
|
71
|
+
.card-header{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
|
|
72
|
+
.card-name{font-size:15px;font-weight:700;color:var(--text);font-family:monospace}
|
|
73
|
+
.card-sig{font-size:12px;color:var(--text2);margin-top:3px;font-family:monospace;word-break:break-all}
|
|
74
|
+
.card-desc{font-size:13px;color:var(--text2);margin-top:8px;line-height:1.5}
|
|
75
|
+
.card-example{margin-top:10px}
|
|
76
|
+
.card-example pre{background:var(--code-bg);border:1px solid var(--border);border-radius:6px;padding:10px 14px;font-size:12px;overflow-x:auto;color:var(--text)}
|
|
77
|
+
.copy-btn{flex-shrink:0;background:none;border:1px solid var(--border);border-radius:5px;padding:3px 8px;font-size:11px;color:var(--text3);cursor:pointer;transition:all .15s;white-space:nowrap}
|
|
78
|
+
.copy-btn:hover{background:var(--accent2);border-color:var(--accent);color:var(--accent)}
|
|
79
|
+
.copy-btn.copied{background:#e8f5e9;border-color:#43a047;color:#2e7d32}
|
|
80
|
+
.badge{display:inline-block;padding:2px 7px;border-radius:4px;font-size:11px;font-weight:600;margin-right:3px;margin-top:5px}
|
|
81
|
+
.badge-exported{background:#e8f5e9;color:#2e7d32}
|
|
82
|
+
.badge-async{background:#e3f2fd;color:#1565c0}
|
|
83
|
+
.badge-abstract{background:#fce4ec;color:#c62828}
|
|
84
|
+
.badge-static{background:#fff3e0;color:#e65100}
|
|
85
|
+
.badge-readonly{background:#f3e5f5;color:#6a1b9a}
|
|
86
|
+
.badge-generator{background:#e0f2f1;color:#00695c}
|
|
87
|
+
.badge-private{background:#fafafa;color:#666;border:1px solid #ddd}
|
|
88
|
+
.badge-protected{background:#fff8e1;color:#f57f17}
|
|
89
|
+
.badge-public{background:#f5f5f5;color:#555}
|
|
90
|
+
.badge-optional{background:#f3e5f5;color:#6a1b9a}
|
|
91
|
+
.badge-const{background:#ede7f6;color:#4527a0}
|
|
92
|
+
.badge-var{background:#fff3e0;color:#e65100}
|
|
93
|
+
.badge-deprecated{background:var(--dep-bg);color:var(--dep-text)}
|
|
94
|
+
.badge-since{background:#e8f5e9;color:#2e7d32}
|
|
95
|
+
.deprecated-notice{background:var(--dep-bg);color:var(--dep-text);border-radius:5px;padding:6px 12px;font-size:12px;margin-top:8px}
|
|
96
|
+
.since-label{font-size:11px;color:var(--text3);margin-top:4px}
|
|
97
|
+
.throws-table{width:100%;border-collapse:collapse;margin-top:8px;font-size:13px;border:1px solid var(--throws-bg)}
|
|
98
|
+
.throws-table th{text-align:left;padding:5px 10px;background:var(--throws-bg);color:var(--throws-text);font-weight:600;font-size:12px}
|
|
99
|
+
.throws-table td{padding:5px 10px;border-top:1px solid var(--border);color:var(--text);vertical-align:top}
|
|
100
|
+
.throws-table td code{font-size:12px}
|
|
101
|
+
.params-table{width:100%;border-collapse:collapse;margin-top:10px;font-size:13px}
|
|
102
|
+
.params-table th{text-align:left;padding:6px 10px;background:var(--th-bg);color:var(--text2);font-weight:600;border-bottom:2px solid var(--border)}
|
|
103
|
+
.params-table td{padding:6px 10px;border-bottom:1px solid var(--method-border);vertical-align:top;color:var(--text)}
|
|
104
|
+
.params-table td code{background:var(--code-bg);padding:1px 5px;border-radius:3px;font-size:12px}
|
|
105
|
+
.returns{margin-top:8px;font-size:13px;color:var(--text2)}
|
|
106
|
+
.returns code{background:var(--code-bg);padding:1px 6px;border-radius:3px;font-family:monospace}
|
|
107
|
+
.collapse-toggle{display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;list-style:none;margin-top:14px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--sub-label);padding:0}
|
|
108
|
+
.collapse-toggle::-webkit-details-marker{display:none}
|
|
109
|
+
.collapse-toggle::before{content:'▶';font-size:9px;display:inline-block;transition:transform .15s;color:var(--sub-label)}
|
|
110
|
+
details[open] .collapse-toggle::before{transform:rotate(90deg)}
|
|
111
|
+
.collapse-body{margin-top:4px}
|
|
112
|
+
.method-row{margin-top:8px;padding:10px 0;border-top:1px solid var(--method-border)}
|
|
113
|
+
.method-sig{font-family:monospace;font-size:13px;color:var(--text)}
|
|
114
|
+
.method-desc{font-size:12px;color:var(--text2);margin-top:4px}
|
|
115
|
+
.module-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:10px;margin-top:4px}
|
|
116
|
+
.module-card{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:16px 20px;transition:border-color .15s,box-shadow .15s}
|
|
117
|
+
.module-card:hover{border-color:var(--accent);box-shadow:0 2px 8px rgba(67,97,238,.1);text-decoration:none}
|
|
118
|
+
.module-card-name{font-size:14px;font-weight:700;color:var(--text);font-family:monospace}
|
|
119
|
+
.module-card-stats{font-size:12px;color:var(--text3);margin-top:4px}
|
|
120
|
+
.module-card-desc{font-size:12px;color:var(--text3);margin-top:6px;line-height:1.4}
|
|
121
|
+
.breadcrumb{font-size:13px;color:var(--text3);margin-bottom:20px}
|
|
122
|
+
.breadcrumb a{color:var(--accent)}
|
|
123
|
+
.anchor-link{color:var(--sidebar-title);opacity:0;font-size:13px;margin-left:6px;transition:opacity .15s}
|
|
124
|
+
.card:hover .anchor-link{opacity:.6}
|
|
125
|
+
.anchor-link:hover{opacity:1;text-decoration:none}
|
|
126
|
+
.empty{color:var(--text3);font-size:13px;font-style:italic}
|
|
127
|
+
.link-ref{color:var(--accent);text-decoration:none;font-size:inherit}
|
|
128
|
+
.link-ref:hover{text-decoration:underline}
|
|
129
|
+
.sr-body{font-size:11px;color:var(--sidebar-title);display:block;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px}
|
|
130
|
+
.sr-preview{font-size:11px;color:var(--text3);font-style:italic;display:block;margin-top:2px}
|
|
131
|
+
|
|
132
|
+
.source-link{font-size:11px;color:var(--text3);font-family:monospace;text-decoration:none;margin-left:6px;opacity:.7}
|
|
133
|
+
.source-link:hover{opacity:1;text-decoration:underline;color:var(--accent)}
|
|
134
|
+
|
|
135
|
+
`;
|
|
136
|
+
|
|
137
|
+
const CLIENT_JS = `
|
|
138
|
+
(function(){
|
|
139
|
+
var THEME_KEY='jsdoc-scribe-theme';
|
|
140
|
+
var saved=localStorage.getItem(THEME_KEY);
|
|
141
|
+
if(saved) document.documentElement.setAttribute('data-theme',saved);
|
|
142
|
+
var btn=document.getElementById('theme-btn');
|
|
143
|
+
if(btn){
|
|
144
|
+
btn.textContent=(saved==='dark')?'Light':'Dark';
|
|
145
|
+
btn.addEventListener('click',function(){
|
|
146
|
+
var cur=document.documentElement.getAttribute('data-theme');
|
|
147
|
+
var next=cur==='dark'?'light':'dark';
|
|
148
|
+
document.documentElement.setAttribute('data-theme',next);
|
|
149
|
+
localStorage.setItem(THEME_KEY,next);
|
|
150
|
+
btn.textContent=next==='dark'?'Light':'Dark';
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
document.addEventListener('click',function(e){
|
|
154
|
+
var b=e.target.closest('.copy-btn');
|
|
155
|
+
if(!b) return;
|
|
156
|
+
navigator.clipboard.writeText(b.dataset.sig||'').then(function(){
|
|
157
|
+
b.textContent='Copied!';b.classList.add('copied');
|
|
158
|
+
setTimeout(function(){b.textContent='Copy';b.classList.remove('copied');},1500);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
var INDEX=window.__SEARCH_INDEX__||[];
|
|
162
|
+
var box=document.getElementById('search-box');
|
|
163
|
+
var panel=document.getElementById('search-results');
|
|
164
|
+
if(!box||!panel) return;
|
|
165
|
+
function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');}
|
|
166
|
+
function render(items){
|
|
167
|
+
panel.innerHTML=items.length
|
|
168
|
+
?items.slice(0,20).map(function(r){return'<a class="search-result-item" href="'+r.url+'"><span class="sr-name">'+esc(r.name)+'</span><span class="sr-kind">'+esc(r.kind)+'</span><span class="sr-module">'+esc(r.module)+'</span>+(r.body?'<span class="sr-preview">'+esc(r.body.slice(0,80))+'</span>':'')+'</a>';}).join('')
|
|
169
|
+
:'<div class="search-no-results">No results</div>';
|
|
170
|
+
panel.classList.add('visible');
|
|
171
|
+
}
|
|
172
|
+
function search(q){
|
|
173
|
+
q=q.trim().toLowerCase();
|
|
174
|
+
if(!q){panel.classList.remove('visible');return;}
|
|
175
|
+
render(INDEX.filter(function(r){
|
|
176
|
+
return r.name.toLowerCase().includes(q)
|
|
177
|
+
||r.module.toLowerCase().includes(q)
|
|
178
|
+
||(r.body&&r.body.toLowerCase().includes(q));
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
box.addEventListener('input',function(){search(box.value);});
|
|
182
|
+
box.addEventListener('focus',function(){if(box.value.trim())search(box.value);});
|
|
183
|
+
document.addEventListener('click',function(e){if(!box.contains(e.target)&&!panel.contains(e.target))panel.classList.remove('visible');});
|
|
184
|
+
document.addEventListener('keydown',function(e){
|
|
185
|
+
if((e.metaKey||e.ctrlKey)&&e.key==='k'){e.preventDefault();box.focus();box.select();}
|
|
186
|
+
if(e.key==='Escape')panel.classList.remove('visible');
|
|
187
|
+
});
|
|
188
|
+
})();
|
|
189
|
+
`;
|
|
190
|
+
|
|
191
|
+
// ---------------------------------------------------------------------------
|
|
192
|
+
// Helpers
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
194
|
+
|
|
195
|
+
function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');}
|
|
196
|
+
function badge(label,cls){return'<span class="badge badge-'+cls+'">'+esc(label)+'</span>';}
|
|
197
|
+
function anchorId(kind,name){return kind+'-'+name.replace(/[^a-zA-Z0-9_]/g,'_');}
|
|
198
|
+
function copyBtn(sig){return'<button class="copy-btn" data-sig="'+esc(sig)+'" title="Copy">Copy</button>';}
|
|
199
|
+
|
|
200
|
+
function metaHtml(item){
|
|
201
|
+
var out='';
|
|
202
|
+
if(item.deprecated!=null) out+='<div class="deprecated-notice">⚠ Deprecated'+(item.deprecated?': '+esc(item.deprecated):'')+'</div>';
|
|
203
|
+
if(item.since) out+='<div class="since-label">Since v'+esc(item.since)+'</div>';
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function descHtml(item,symbolMap,filePath){
|
|
208
|
+
var out='';
|
|
209
|
+
if(item.description) out+='<div class="card-desc">'+(symbolMap?resolveLinks(item.description,symbolMap,filePath):esc(item.description))+'</div>';
|
|
210
|
+
out+=metaHtml(item);
|
|
211
|
+
if(item.example) out+='<div class="card-example"><pre>'+esc(item.example)+'</pre></div>';
|
|
212
|
+
return out;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function renderParams(params, jsdocParams){
|
|
216
|
+
if(!params||!params.length) return '';
|
|
217
|
+
// Build a lookup of JSDoc @param enrichments keyed by name
|
|
218
|
+
var jmap={};
|
|
219
|
+
(jsdocParams||[]).forEach(function(p){jmap[p.name]=p;});
|
|
220
|
+
var html='<table class="params-table"><thead><tr><th>Parameter</th><th>Type</th><th>Optional</th><th>Description</th></tr></thead><tbody>';
|
|
221
|
+
params.forEach(function(p){
|
|
222
|
+
var jp=jmap[p.name]||{};
|
|
223
|
+
var type=jp.type&&jp.type!=='any'?jp.type:p.type;
|
|
224
|
+
html+='<tr><td><code>'+esc(p.name)+'</code></td><td><code>'+esc(type)+'</code></td><td>'+(p.optional||jp.optional?'yes':'')+'</td><td>'+(jp.description?esc(jp.description):'')+'</td></tr>';
|
|
225
|
+
});
|
|
226
|
+
return html+'</tbody></table>';
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function renderReturns(returnType, returnsTag){
|
|
230
|
+
var type=returnsTag&&returnsTag.type&&returnsTag.type!=='any'?returnsTag.type:returnType;
|
|
231
|
+
var desc=returnsTag&&returnsTag.description?'— '+esc(returnsTag.description):'';
|
|
232
|
+
return'<div class="returns">Returns: <code>'+esc(type)+'</code> '+desc+'</div>';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function renderThrows(throws){
|
|
236
|
+
if(!throws||!throws.length) return '';
|
|
237
|
+
var html='<table class="throws-table"><thead><tr><th>Throws</th><th>Description</th></tr></thead><tbody>';
|
|
238
|
+
throws.forEach(function(t){html+='<tr><td><code>'+esc(t.type||'Error')+'</code></td><td>'+esc(t.description||'')+'</td></tr>';});
|
|
239
|
+
return html+'</tbody></table>';
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function resolveLinks(text, symbolMap, filePath, moduleHtmlPathFn, modules){
|
|
243
|
+
if(!text||!symbolMap) return esc(text);
|
|
244
|
+
// Replace {@link Symbol} and {@link Symbol#method} with anchor tags
|
|
245
|
+
return esc(text).replace(/\{@link ([^}]+)\}/g, function(_, ref){
|
|
246
|
+
var parts=ref.trim().split('#');
|
|
247
|
+
var sym=parts[0].trim();
|
|
248
|
+
var method=parts[1]?parts[1].trim():null;
|
|
249
|
+
var entry=symbolMap[sym];
|
|
250
|
+
if(!entry) return'<code>'+esc(ref)+'</code>';
|
|
251
|
+
// Are we on the same module page?
|
|
252
|
+
var targetPath=entry.modulePath;
|
|
253
|
+
var href=targetPath===filePath?'':(targetPath||'');
|
|
254
|
+
if(method) href+='#meth-'+sym+'_'+method;
|
|
255
|
+
else href+=('#'+entry.anchorId);
|
|
256
|
+
return'<a href="'+href+'" class="link-ref"><code>'+esc(sym+(method?'.'+method:''))+'</code></a>';
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function sourceLink(item, filePath, sourceUrl){
|
|
261
|
+
if(item.line==null) return '';
|
|
262
|
+
var label='line '+item.line;
|
|
263
|
+
if(sourceUrl){
|
|
264
|
+
var base=sourceUrl.replace(/\/$/,'');
|
|
265
|
+
var rel=filePath.replace(/\\/g,'/');
|
|
266
|
+
var href=base+'/'+rel+'#L'+item.line;
|
|
267
|
+
return'<a class="source-link" href="'+esc(href)+'" target="_blank" rel="noopener">'+esc(label)+'</a>';
|
|
268
|
+
}
|
|
269
|
+
return'<span class="source-link">'+esc(filePath.replace(/\\/g,'/'))+':'+item.line+'</span>';
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function collapsible(label,html,open){
|
|
273
|
+
return'<details'+(open?' open':'')+'><summary class="collapse-toggle">'+esc(label)+'</summary><div class="collapse-body">'+html+'</div></details>';
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function buildCss(theme){
|
|
277
|
+
var t=THEMES[theme]||THEMES.default;
|
|
278
|
+
return t.light+(t.dark||'')+CSS_STRUCTURE;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function page(title,sidebarHtml,bodyHtml,searchIndex,theme){
|
|
282
|
+
var t=THEMES[theme]||THEMES.default;
|
|
283
|
+
var themeJs=t.toggleBtn?CLIENT_JS:'(function(){var INDEX=window.__SEARCH_INDEX__||[];var box=document.getElementById("search-box");var panel=document.getElementById("search-results");if(!box||!panel)return;function esc(s){return String(s).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");}function render(items){panel.innerHTML=items.length?items.slice(0,20).map(function(r){return\'<a class="search-result-item" href="\'+r.url+\'"><span class="sr-name">\'+esc(r.name)+\'</span><span class="sr-kind">\'+esc(r.kind)+\'</span><span class="sr-module">\'+esc(r.module)+\'</span></a>\';}).join(""):\'<div class="search-no-results">No results</div>\';panel.classList.add("visible");}function search(q){q=q.trim().toLowerCase();if(!q){panel.classList.remove("visible");return;}render(INDEX.filter(function(r){return r.name.toLowerCase().includes(q)||r.module.toLowerCase().includes(q);}));}box.addEventListener("input",function(){search(box.value);});box.addEventListener("focus",function(){if(box.value.trim())search(box.value);});document.addEventListener("click",function(e){if(!box.contains(e.target)&&!panel.contains(e.target))panel.classList.remove("visible");});document.addEventListener("keydown",function(e){if((e.metaKey||e.ctrlKey)&&e.key==="k"){e.preventDefault();box.focus();box.select();}if(e.key==="Escape")panel.classList.remove("visible");});document.addEventListener("click",function(e){var b=e.target.closest(".copy-btn");if(!b)return;navigator.clipboard.writeText(b.dataset.sig||"").then(function(){b.textContent="Copied!";b.classList.add("copied");setTimeout(function(){b.textContent="Copy";b.classList.remove("copied");},1500);});});})();';
|
|
284
|
+
return'<!DOCTYPE html>\n<html lang="en">\n<head>\n<meta charset="UTF-8">\n<meta name="viewport" content="width=device-width,initial-scale=1">\n<title>'+esc(title)+'</title>\n<style>'+buildCss(theme)+'</style>\n</head>\n<body>\n<div class="layout">\n<nav class="sidebar">'+sidebarHtml+'</nav>\n<main class="main">'+bodyHtml+'</main>\n</div>\n<script>window.__SEARCH_INDEX__='+JSON.stringify(searchIndex)+';</script>\n<script>'+themeJs+'</script>\n</body>\n</html>';
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
// Module label helpers
|
|
289
|
+
// ---------------------------------------------------------------------------
|
|
290
|
+
|
|
291
|
+
function commonRoot(modules){
|
|
292
|
+
if(!modules.length) return '';
|
|
293
|
+
var parts=modules.map(function(m){return m.filePath.replace(/\\/g,'/').split('/');});
|
|
294
|
+
var min=Math.min.apply(null,parts.map(function(p){return p.length;}))-1;
|
|
295
|
+
var i=0;
|
|
296
|
+
while(i<min&&parts.every(function(p){return p[i]===parts[0][i];})) i++;
|
|
297
|
+
return parts[0].slice(0,i).join('/');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function moduleLabel(filePath,modules){
|
|
301
|
+
var root=commonRoot(modules);
|
|
302
|
+
var rel=filePath.replace(/\\/g,'/');
|
|
303
|
+
if(root) rel=rel.slice(root.length).replace(/^\//,'');
|
|
304
|
+
return rel.replace(/\.[jt]sx?$/,'');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function moduleHtmlPath(filePath,modules){return'modules/'+moduleLabel(filePath,modules).replace(/\//g,'__')+'.html';}
|
|
308
|
+
|
|
309
|
+
// ---------------------------------------------------------------------------
|
|
310
|
+
// Search index
|
|
311
|
+
// ---------------------------------------------------------------------------
|
|
312
|
+
|
|
313
|
+
function buildBody(item){
|
|
314
|
+
var parts=[];
|
|
315
|
+
if(item.description) parts.push(item.description);
|
|
316
|
+
(item.jsdocParams||[]).forEach(function(p){if(p.description)parts.push(p.name+': '+p.description);});
|
|
317
|
+
if(item.returns&&item.returns.description) parts.push('returns: '+item.returns.description);
|
|
318
|
+
(item.throws||[]).forEach(function(t){if(t.description)parts.push('throws: '+t.description);});
|
|
319
|
+
return parts.join(' | ').slice(0,300)||null;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function buildSearchIndex(modules,prefix){
|
|
323
|
+
prefix=prefix||'';
|
|
324
|
+
var index=[];
|
|
325
|
+
modules.forEach(function(mod){
|
|
326
|
+
var rel=moduleHtmlPath(mod.filePath,modules);
|
|
327
|
+
var label=moduleLabel(mod.filePath,modules);
|
|
328
|
+
function url(a){return prefix+rel+'#'+a;}
|
|
329
|
+
function push(name,kind,anchor,item){index.push({name:name,kind:kind,module:label,url:url(anchor),body:buildBody(item||{})});}
|
|
330
|
+
mod.functions.forEach(function(f){push(f.name,'function',anchorId('fn',f.name),f);});
|
|
331
|
+
mod.classes.forEach(function(c){
|
|
332
|
+
push(c.name,'class',anchorId('cls',c.name),c);
|
|
333
|
+
c.methods.forEach(function(m){push(c.name+'.'+m.name,'method',anchorId('cls',c.name),m);});
|
|
334
|
+
});
|
|
335
|
+
mod.interfaces.forEach(function(i){push(i.name,'interface',anchorId('iface',i.name),i);});
|
|
336
|
+
mod.typeAliases.forEach(function(t){push(t.name,'type',anchorId('type',t.name),t);});
|
|
337
|
+
mod.enums.forEach(function(e){push(e.name,'enum',anchorId('enum',e.name),e);});
|
|
338
|
+
mod.variables.forEach(function(v){push(v.name,v.isConst?'const':'var',anchorId('var',v.name),v);});
|
|
339
|
+
});
|
|
340
|
+
return index;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// ---------------------------------------------------------------------------
|
|
344
|
+
// Sidebar
|
|
345
|
+
// ---------------------------------------------------------------------------
|
|
346
|
+
|
|
347
|
+
function buildSidebar(modules,projectName,version,activePath,rootPrefix,showToggle){
|
|
348
|
+
var prefix=rootPrefix||'';
|
|
349
|
+
var html='<div class="sidebar-header">'
|
|
350
|
+
+'<div><a href="'+prefix+'index.html">'+esc(projectName)+'</a>'+(version?'<span class="version">v'+esc(version)+'</span>':'')+'</div>'
|
|
351
|
+
+(showToggle!==false?'<button id="theme-btn" class="theme-btn">Dark</button>':'')
|
|
352
|
+
+'</div>'
|
|
353
|
+
+'<div class="search-wrap"><input id="search-box" class="search-box" type="search" placeholder="Search... (Ctrl+K)" autocomplete="off"><div id="search-results" class="search-results"></div></div>'
|
|
354
|
+
+'<div class="sidebar-section"><div class="sidebar-section-title">Modules</div>';
|
|
355
|
+
|
|
356
|
+
var groups={},order=[];
|
|
357
|
+
modules.forEach(function(mod){
|
|
358
|
+
var label=moduleLabel(mod.filePath,modules);
|
|
359
|
+
var slash=label.lastIndexOf('/');
|
|
360
|
+
var dir=slash===-1?'':label.slice(0,slash);
|
|
361
|
+
if(!groups[dir]){groups[dir]=[];order.push(dir);}
|
|
362
|
+
groups[dir].push(mod);
|
|
363
|
+
});
|
|
364
|
+
var hasGroups=order.some(function(d){return d!=='';});
|
|
365
|
+
|
|
366
|
+
order.forEach(function(dir){
|
|
367
|
+
var mods=groups[dir];
|
|
368
|
+
if(hasGroups&&dir){
|
|
369
|
+
var anyActive=mods.some(function(m){return moduleHtmlPath(m.filePath,modules)===activePath;});
|
|
370
|
+
html+='<details'+(anyActive?' open':'')+'><summary class="sidebar-dir-toggle">'+esc(dir)+'/</summary>';
|
|
371
|
+
mods.forEach(function(mod){
|
|
372
|
+
var rel=moduleHtmlPath(mod.filePath,modules);
|
|
373
|
+
var label=moduleLabel(mod.filePath,modules);
|
|
374
|
+
var name=label.slice(dir.length+1);
|
|
375
|
+
var active=activePath===rel?' active':'';
|
|
376
|
+
html+='<a class="sidebar-link sidebar-link-indent'+active+'" href="'+esc(prefix+rel)+'">'+esc(name)+'</a>';
|
|
377
|
+
});
|
|
378
|
+
html+='</details>';
|
|
379
|
+
} else {
|
|
380
|
+
mods.forEach(function(mod){
|
|
381
|
+
var rel=moduleHtmlPath(mod.filePath,modules);
|
|
382
|
+
var label=moduleLabel(mod.filePath,modules);
|
|
383
|
+
var name=dir?label.slice(dir.length+1):label;
|
|
384
|
+
var active=activePath===rel?' active':'';
|
|
385
|
+
html+='<a class="sidebar-link'+active+'" href="'+esc(prefix+rel)+'">'+esc(name)+'</a>';
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
return html+'</div>';
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// ---------------------------------------------------------------------------
|
|
393
|
+
// Item renderers
|
|
394
|
+
// ---------------------------------------------------------------------------
|
|
395
|
+
|
|
396
|
+
function renderFunction(fn,filePath,sourceUrl,symbolMap){
|
|
397
|
+
var paramStr=(fn.params||[]).map(function(p){return(p.optional?'[':'')+p.name+': '+p.type+(p.optional?']':'');}).join(', ');
|
|
398
|
+
var sig=fn.name+'('+paramStr+'): '+fn.returnType;
|
|
399
|
+
var id=anchorId('fn',fn.name);
|
|
400
|
+
var badges=[fn.isExported&&badge('exported','exported'),fn.isAsync&&badge('async','async'),fn.isGenerator&&badge('generator','generator'),fn.deprecated!=null&&badge('deprecated','deprecated')].filter(Boolean).join('');
|
|
401
|
+
return'<div class="card" id="'+id+'">'
|
|
402
|
+
+'<div class="card-header"><div><div class="card-name"><a class="anchor-link" href="#'+id+'">#</a>'+esc(fn.name)+sourceLink(fn,filePath,sourceUrl)+'</div><div class="card-sig">'+esc(sig)+'</div></div>'+copyBtn(sig)+'</div>'
|
|
403
|
+
+'<div>'+badges+'</div>'+descHtml(fn,symbolMap,filePath)
|
|
404
|
+
+renderParams(fn.params,fn.jsdocParams)
|
|
405
|
+
+renderReturns(fn.returnType,fn.returns)
|
|
406
|
+
+renderThrows(fn.throws)
|
|
407
|
+
+'</div>';
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function renderClass(cls,filePath,sourceUrl,symbolMap){
|
|
411
|
+
var id=anchorId('cls',cls.name);
|
|
412
|
+
var badges=[cls.isExported&&badge('exported','exported'),cls.isAbstract&&badge('abstract','abstract'),cls.extends.length&&badge('extends '+cls.extends.join(', '),'exported'),cls.implements.length&&badge('implements '+cls.implements.join(', '),'async'),cls.deprecated!=null&&badge('deprecated','deprecated')].filter(Boolean).join('');
|
|
413
|
+
var inner='<div class="card" id="'+id+'">'
|
|
414
|
+
+'<div class="card-header"><div><div class="card-name"><a class="anchor-link" href="#'+id+'">#</a>'+esc(cls.name)+sourceLink(cls,filePath,sourceUrl)+'</div></div>'
|
|
415
|
+
+copyBtn('class '+cls.name+(cls.extends.length?' extends '+cls.extends.join(', '):''))+'</div>'
|
|
416
|
+
+'<div>'+badges+'</div>'+descHtml(cls,symbolMap,filePath);
|
|
417
|
+
|
|
418
|
+
if(cls.constructor){
|
|
419
|
+
var ctorSig='new '+cls.name+'('+(cls.constructor.params||[]).map(function(p){return p.name+': '+p.type;}).join(', ')+')';
|
|
420
|
+
var ctorBody='<div class="method-row"><div class="method-sig">'+esc(ctorSig)+'</div>'+(cls.constructor.description?'<div class="method-desc">'+esc(cls.constructor.description)+'</div>':'')+renderParams(cls.constructor.params,cls.constructor.jsdocParams)+renderThrows(cls.constructor.throws)+'</div>';
|
|
421
|
+
inner+=collapsible('Constructor',ctorBody,true);
|
|
422
|
+
}
|
|
423
|
+
if(cls.properties.length){
|
|
424
|
+
var propBody='<table class="params-table"><thead><tr><th>Name</th><th>Type</th><th>Visibility</th><th>Flags</th><th>Description</th></tr></thead><tbody>';
|
|
425
|
+
cls.properties.forEach(function(p){
|
|
426
|
+
var flags=[p.isStatic&&badge('static','static'),p.isReadonly&&badge('readonly','readonly'),p.isAbstract&&badge('abstract','abstract'),p.deprecated!=null&&badge('deprecated','deprecated')].filter(Boolean).join('');
|
|
427
|
+
propBody+='<tr><td><code>'+esc(p.name)+'</code></td><td><code>'+esc(p.type)+'</code></td><td>'+badge(p.visibility,p.visibility)+'</td><td>'+flags+'</td><td>'+(p.description?esc(p.description):'')+'</td></tr>';
|
|
428
|
+
});
|
|
429
|
+
inner+=collapsible('Properties ('+cls.properties.length+')',propBody+'</tbody></table>',true);
|
|
430
|
+
}
|
|
431
|
+
if(cls.methods.length){
|
|
432
|
+
var methBody='';
|
|
433
|
+
cls.methods.forEach(function(m){
|
|
434
|
+
var ps=(m.params||[]).map(function(p){return p.name+': '+p.type;}).join(', ');
|
|
435
|
+
var mSig=m.name+'('+ps+'): '+m.returnType;
|
|
436
|
+
var mb=[badge(m.visibility,m.visibility),m.isStatic&&badge('static','static'),m.isAbstract&&badge('abstract','abstract'),m.isAsync&&badge('async','async'),m.isGenerator&&badge('generator','generator'),m.deprecated!=null&&badge('deprecated','deprecated')].filter(Boolean).join('');
|
|
437
|
+
methBody+='<div class="method-row"><div class="card-header" style="margin-bottom:4px"><code class="method-sig">'+esc(mSig)+'</code>'+copyBtn(mSig)+'</div><div>'+mb+'</div>'+(m.description?'<div class="method-desc">'+esc(m.description)+'</div>':'')+metaHtml(m)+renderParams(m.params,m.jsdocParams)+renderReturns(m.returnType,m.returns)+renderThrows(m.throws)+'</div>';
|
|
438
|
+
});
|
|
439
|
+
inner+=collapsible('Methods ('+cls.methods.length+')',methBody,true);
|
|
440
|
+
}
|
|
441
|
+
if(cls.getters.length||cls.setters.length){
|
|
442
|
+
var accBody='';
|
|
443
|
+
cls.getters.forEach(function(g){accBody+='<div class="method-row"><code class="method-sig">get '+esc(g.name)+'(): '+esc(g.returnType)+'</code>'+(g.isStatic?badge('static','static'):'')+(g.deprecated!=null?badge('deprecated','deprecated'):'')+(g.description?'<div class="method-desc">'+esc(g.description)+'</div>':'')+'</div>';});
|
|
444
|
+
cls.setters.forEach(function(s){var ps=(s.params||[]).map(function(p){return p.name+': '+p.type;}).join(', ');accBody+='<div class="method-row"><code class="method-sig">set '+esc(s.name)+'('+esc(ps)+')</code>'+(s.isStatic?badge('static','static'):'')+(s.deprecated!=null?badge('deprecated','deprecated'):'')+(s.description?'<div class="method-desc">'+esc(s.description)+'</div>':'')+'</div>';});
|
|
445
|
+
inner+=collapsible('Accessors ('+(cls.getters.length+cls.setters.length)+')',accBody,false);
|
|
446
|
+
}
|
|
447
|
+
return inner+'</div>';
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function renderInterface(iface,filePath,sourceUrl,symbolMap){
|
|
451
|
+
var id=anchorId('iface',iface.name);
|
|
452
|
+
var html='<div class="card" id="'+id+'">'
|
|
453
|
+
+'<div class="card-header"><div><div class="card-name"><a class="anchor-link" href="#'+id+'">#</a>'+esc(iface.name)+sourceLink(iface,filePath,sourceUrl)+'</div></div>'+copyBtn('interface '+iface.name)+'</div>'
|
|
454
|
+
+(iface.isExported?badge('exported','exported'):'')+descHtml(iface,symbolMap,filePath);
|
|
455
|
+
if(iface.properties.length){
|
|
456
|
+
html+='<table class="params-table" style="margin-top:10px"><thead><tr><th>Property</th><th>Type</th><th>Optional</th></tr></thead><tbody>';
|
|
457
|
+
iface.properties.forEach(function(p){html+='<tr><td><code>'+esc(p.name)+'</code></td><td><code>'+esc(p.type)+'</code></td><td>'+(p.optional?'yes':'')+'</td></tr>';});
|
|
458
|
+
html+='</tbody></table>';
|
|
459
|
+
}
|
|
460
|
+
if(iface.methods.length){
|
|
461
|
+
var mb='';
|
|
462
|
+
iface.methods.forEach(function(m){var ps=m.params.map(function(p){return p.name+': '+p.type;}).join(', ');mb+='<div class="method-row"><code class="method-sig">'+esc(m.name)+'('+esc(ps)+'): '+esc(m.returnType)+'</code>'+(m.optional?badge('optional','optional'):'')+'</div>';});
|
|
463
|
+
html+=collapsible('Methods ('+iface.methods.length+')',mb,true);
|
|
464
|
+
}
|
|
465
|
+
return html+'</div>';
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function renderEnum(enm,filePath,sourceUrl,symbolMap){
|
|
469
|
+
var id=anchorId('enum',enm.name);
|
|
470
|
+
var html='<div class="card" id="'+id+'">'
|
|
471
|
+
+'<div class="card-header"><div><div class="card-name"><a class="anchor-link" href="#'+id+'">#</a>'+esc(enm.name)+sourceLink(enm,filePath,sourceUrl)+'</div></div>'+copyBtn('enum '+enm.name)+'</div>'
|
|
472
|
+
+(enm.isExported?badge('exported','exported'):'')+descHtml(enm,symbolMap,filePath)
|
|
473
|
+
+'<table class="params-table" style="margin-top:10px"><thead><tr><th>Member</th><th>Value</th></tr></thead><tbody>';
|
|
474
|
+
enm.members.forEach(function(m){html+='<tr><td><code>'+esc(m.name)+'</code></td><td>'+(m.value!==null?'<code>'+esc(m.value)+'</code>':'')+'</td></tr>';});
|
|
475
|
+
return html+'</tbody></table></div>';
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function renderTypeAlias(ta,filePath,sourceUrl,symbolMap){
|
|
479
|
+
var id=anchorId('type',ta.name);
|
|
480
|
+
return'<div class="card" id="'+id+'">'
|
|
481
|
+
+'<div class="card-header"><div><div class="card-name"><a class="anchor-link" href="#'+id+'">#</a>'+esc(ta.name)+sourceLink(ta,filePath,sourceUrl)+'</div><div class="card-sig">type '+esc(ta.name)+' = '+esc(ta.type)+'</div></div>'+copyBtn('type '+ta.name+' = '+ta.type)+'</div>'
|
|
482
|
+
+(ta.isExported?badge('exported','exported'):'')+descHtml(ta,symbolMap,filePath)+'</div>';
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function renderVariable(v,filePath,sourceUrl,symbolMap){
|
|
486
|
+
var id=anchorId('var',v.name);
|
|
487
|
+
var decl=(v.isConst?'const':'let')+' '+v.name+': '+v.type;
|
|
488
|
+
return'<div class="card" id="'+id+'">'
|
|
489
|
+
+'<div class="card-header"><div><div class="card-name"><a class="anchor-link" href="#'+id+'">#</a>'+esc(v.name)+sourceLink(v,filePath,sourceUrl)+'</div><div class="card-sig">'+esc(decl)+'</div></div>'+copyBtn(decl)+'</div>'
|
|
490
|
+
+(v.isExported?badge('exported','exported'):'')+badge(v.isConst?'const':'var',v.isConst?'const':'var')+(v.deprecated!=null?badge('deprecated','deprecated'):'')+descHtml(v,symbolMap,filePath)+'</div>';
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function section(title,items,renderFn,filePath,sourceUrl,symbolMap){
|
|
494
|
+
if(!items||!items.length) return '';
|
|
495
|
+
return'<div class="section"><div class="section-title">'+esc(title)+'</div>'+items.map(function(item){return renderFn(item,filePath,sourceUrl,symbolMap);}).join('\n')+'</div>';
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// ---------------------------------------------------------------------------
|
|
499
|
+
// Site builder
|
|
500
|
+
// ---------------------------------------------------------------------------
|
|
501
|
+
|
|
502
|
+
function buildSite(modules,options){
|
|
503
|
+
options=options||{};
|
|
504
|
+
var projectName=options.projectName||'Documentation';
|
|
505
|
+
var version=options.version||'';
|
|
506
|
+
var theme=options.theme||'default';
|
|
507
|
+
var sourceUrl=options.sourceUrl||null;
|
|
508
|
+
// Build a symbol → {anchorId, modulePath} map for @link resolution
|
|
509
|
+
var symbolMap={};
|
|
510
|
+
modules.forEach(function(mod){
|
|
511
|
+
var rel=moduleHtmlPath(mod.filePath,modules);
|
|
512
|
+
function reg(name,aid){symbolMap[name]={anchorId:aid,modulePath:rel};}
|
|
513
|
+
mod.functions.forEach(function(f){reg(f.name,anchorId('fn',f.name));});
|
|
514
|
+
mod.classes.forEach(function(c){reg(c.name,anchorId('cls',c.name));c.methods.forEach(function(m){reg(c.name+'.'+m.name,anchorId('cls',c.name));});});
|
|
515
|
+
mod.interfaces.forEach(function(i){reg(i.name,anchorId('iface',i.name));});
|
|
516
|
+
mod.typeAliases.forEach(function(t){reg(t.name,anchorId('type',t.name));});
|
|
517
|
+
mod.enums.forEach(function(e){reg(e.name,anchorId('enum',e.name));});
|
|
518
|
+
mod.variables.forEach(function(v){reg(v.name,anchorId('var',v.name));});
|
|
519
|
+
});
|
|
520
|
+
var showToggle=(THEMES[theme]||THEMES.default).toggleBtn;
|
|
521
|
+
var pages=[];
|
|
522
|
+
var idxIdx=buildSearchIndex(modules,'');
|
|
523
|
+
var modIdx=buildSearchIndex(modules,'../');
|
|
524
|
+
|
|
525
|
+
// index.html
|
|
526
|
+
var sidebar=buildSidebar(modules,projectName,version,'index.html','',showToggle);
|
|
527
|
+
var totalFns=modules.reduce(function(s,m){return s+m.functions.length;},0);
|
|
528
|
+
var totalCls=modules.reduce(function(s,m){return s+m.classes.length;},0);
|
|
529
|
+
var body='<div class="page-title">'+esc(projectName)+'</div>'
|
|
530
|
+
+'<div class="page-subtitle">'+modules.length+' module(s) · '+totalFns+' function(s) · '+totalCls+' class(es)</div>'
|
|
531
|
+
+'<div class="section"><div class="section-title">Modules</div><div class="module-grid">';
|
|
532
|
+
modules.forEach(function(mod){
|
|
533
|
+
var rel=moduleHtmlPath(mod.filePath,modules);
|
|
534
|
+
var label=moduleLabel(mod.filePath,modules);
|
|
535
|
+
var total=mod.functions.length+mod.classes.length+mod.interfaces.length+mod.typeAliases.length+mod.enums.length+mod.variables.length;
|
|
536
|
+
var parts=[mod.functions.length&&mod.functions.length+' fn',mod.classes.length&&mod.classes.length+' class',mod.interfaces.length&&mod.interfaces.length+' iface',mod.enums.length&&mod.enums.length+' enum',mod.variables.length&&mod.variables.length+' const'].filter(Boolean);
|
|
537
|
+
// deprecated count across all items
|
|
538
|
+
var depCount=[].concat(mod.functions,mod.classes,mod.interfaces,mod.typeAliases,mod.enums,mod.variables).filter(function(i){return i.deprecated!=null;}).length;
|
|
539
|
+
// @since version range
|
|
540
|
+
var sinces=[].concat(mod.functions,mod.classes,mod.interfaces,mod.typeAliases,mod.enums,mod.variables).map(function(i){return i.since;}).filter(Boolean);
|
|
541
|
+
var sinceStr=sinces.length?(' · since v'+sinces.sort()[0])+(sinces.length>1&&sinces[sinces.length-1]!==sinces[0]?'–v'+sinces[sinces.length-1]:''):''
|
|
542
|
+
var depStr=depCount?'<span class="badge badge-deprecated" style="font-size:10px;padding:1px 5px;vertical-align:middle">'+depCount+' deprecated</span>':'';
|
|
543
|
+
var desc=mod.description?'<div class="module-card-desc">'+esc(mod.description.slice(0,100))+(mod.description.length>100?'…':'')+'</div>':'';
|
|
544
|
+
body+='<a class="module-card" href="'+esc(rel)+'"><div class="module-card-name">'+esc(label)+depStr+'</div><div class="module-card-stats">'+(parts.join(' · ')||'no exported items')+esc(sinceStr)+'</div>'+desc+'</a>';
|
|
545
|
+
});
|
|
546
|
+
body+='</div></div>';
|
|
547
|
+
pages.push({path:'index.html',html:page(projectName,sidebar,body,idxIdx,theme)});
|
|
548
|
+
|
|
549
|
+
// per-module pages
|
|
550
|
+
modules.forEach(function(mod){
|
|
551
|
+
var rel=moduleHtmlPath(mod.filePath,modules);
|
|
552
|
+
var label=moduleLabel(mod.filePath,modules);
|
|
553
|
+
var modSidebar=buildSidebar(modules,projectName,version,rel,'../',showToggle);
|
|
554
|
+
var mbody='<div class="breadcrumb"><a href="../index.html">'+esc(projectName)+'</a> / '+esc(label)+'</div>'
|
|
555
|
+
+'<div class="page-title">'+esc(label)+'</div>'
|
|
556
|
+
+'<div class="page-subtitle" style="font-family:monospace;font-size:12px">'+esc(mod.filePath)+'</div>'
|
|
557
|
+
+(mod.description?'<p class="module-desc">'+esc(mod.description)+'</p>':'');
|
|
558
|
+
var isEmpty=!mod.functions.length&&!mod.classes.length&&!mod.interfaces.length&&!mod.typeAliases.length&&!mod.enums.length&&!mod.variables.length;
|
|
559
|
+
if(isEmpty){
|
|
560
|
+
mbody+='<p class="empty" style="margin-top:24px">No documented items found.</p>';
|
|
561
|
+
} else {
|
|
562
|
+
mbody+=section('Functions',mod.functions,renderFunction,mod.filePath,sourceUrl,symbolMap);
|
|
563
|
+
mbody+=section('Classes',mod.classes,renderClass,mod.filePath,sourceUrl,symbolMap);
|
|
564
|
+
mbody+=section('Interfaces',mod.interfaces,renderInterface,mod.filePath,sourceUrl,symbolMap);
|
|
565
|
+
mbody+=section('Type Aliases',mod.typeAliases,renderTypeAlias,mod.filePath,sourceUrl,symbolMap);
|
|
566
|
+
mbody+=section('Enums',mod.enums,renderEnum,mod.filePath,sourceUrl,symbolMap);
|
|
567
|
+
mbody+=section('Variables & Constants',mod.variables,renderVariable,mod.filePath,sourceUrl,symbolMap);
|
|
568
|
+
}
|
|
569
|
+
pages.push({path:rel,html:page(label+' - '+projectName,modSidebar,mbody,modIdx,theme)});
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
return pages;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
module.exports = { buildSite, moduleLabel, moduleHtmlPath };
|