living-documentation 3.7.0 → 4.0.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.

Potentially problematic release.


This version of living-documentation might be problematic. Click here for more details.

@@ -0,0 +1,321 @@
1
+ // ── Word Cloud — stop words & logic ───────────────────────────────────────────
2
+ // Loaded by index.html as a plain <script>; all symbols are global.
3
+
4
+ // ── Human stop words (English + French only) ──────────────────────────────────
5
+ const WC_STOP_WORDS = new Set([
6
+ // ── English ──
7
+ "the","and","for","are","but","not","you","all","this","that",
8
+ "with","have","from","they","will","one","been","can","has","was",
9
+ "more","also","when","there","their","what","about","which","would",
10
+ "into","than","then","each","just","over","after","such","here",
11
+ "its","your","our","some","were","very","only","out","had",
12
+ "she","his","her","him","who","how","any","other","these","those",
13
+ "being","may","use","used","using","should","could","shall","must",
14
+ "need","via","per","like","well","make","made","take","taken",
15
+ "same","both","between","before","while","where","since","still",
16
+ "even","able","back","come","down","does","done","good","much",
17
+ "said","them","want","way","without","within","whether","though",
18
+ "although","however","therefore","thus","hence","indeed","rather",
19
+ "either","neither","yet","once","upon","during","against","among",
20
+ "through","because","along","already","always","often","never",
21
+ "again","around","another","every","most","many","least","less",
22
+ "own","off","too","now","new","old","few","see","set",
23
+ "put","got","let","tell","know","think","seem","look","keep",
24
+ "give","show","hear","play","run","move","live","hold","turn",
25
+ "help","start","might","really","actually","simply","directly",
26
+ "basically","generally","normally","especially","currently",
27
+ // ── French ──
28
+ "les","des","une","pour","pas","sur","par","est","qui","que",
29
+ "dans","avec","sont","plus","tout","aux","mais","comme","vous",
30
+ "nous","leur","lui","elle","ils","elles","ces","ses","mon","ton",
31
+ "son","mes","tes","ainsi","donc","alors","car","peut","fait",
32
+ "encore","bien","aussi","très","même","entre","vers","dont","sans",
33
+ "sous","cette","celui","celle","ceux","celles","cela","ceci",
34
+ "avoir","être","faire","aller","voir","savoir","pouvoir","vouloir",
35
+ "devoir","partir","venir","prendre","mettre","dire","donner","tenir",
36
+ "tous","toutes","trop","peu","beaucoup","moins",
37
+ "jamais","toujours","souvent","parfois","déjà","bientôt",
38
+ "maintenant","après","avant","depuis","pendant","selon","afin",
39
+ "quand","parce","puisque","lorsque","tandis","quoique",
40
+ "cependant","néanmoins","pourtant","toutefois","ailleurs","ensuite",
41
+ "enfin","surtout","notamment","seulement","simplement","vraiment",
42
+ "lequel","laquelle","lesquels","lesquelles","duquel","auquel",
43
+ "desquels","auxquels","chaque","plusieurs","certains","certaines",
44
+ "quelques","autres","certaine","aucun","aucune","nul","nulle",
45
+ "chacun","chacune","quoi","quels","quelles","quel","quelle",
46
+ "votre","vos","notre","nos","leurs","puis","lors",
47
+ ]);
48
+
49
+ // ── Language-specific stop words (keyed by file extension) ────────────────────
50
+ const WC_LANG_STOP_WORDS = {
51
+ // shared across all code files
52
+ _code: new Set([
53
+ "true","false","null","undefined","void","this","self","super",
54
+ "return","import","export","from","class","interface","extends","implements",
55
+ "public","private","protected","static","final","abstract","override",
56
+ "function","const","let","var","type","enum","struct","trait","impl",
57
+ "async","await","new","delete","typeof","instanceof","throw","throws",
58
+ "catch","finally","break","continue","default","switch","case","while",
59
+ "else","elif","pass","raise","yield","with","lambda","where","match",
60
+ "package","module","namespace","using","include","require","define",
61
+ "object","string","number","boolean","integer","float","double","long",
62
+ "byte","char","array","list","dict","tuple","bool","none",
63
+ "nil","print","console","stdout","stderr",
64
+ "size","length","count","index","value","result","error","data",
65
+ "args","argv","argc","opts","params","param","props","prop",
66
+ "node","root","tree","left","right","next","prev","head","tail",
67
+ "init","main","test","spec","mock","stub","util","helper","base",
68
+ "read","write","open","close","send","recv","load","save","parse",
69
+ "append","remove","insert","update","create","build",
70
+ "get","set","has","add","push","pull","move","copy","sort","find","filter","reduce","map",
71
+ ]),
72
+ ts: new Set(["interface","namespace","readonly","keyof","infer","never","unknown","declare","satisfies","generic"]),
73
+ tsx: new Set(["interface","namespace","readonly","keyof","infer","never","unknown","declare","satisfies","generic","react","props","children","component","render","state","effect","hook","usestate","useeffect","useref","usecontext","usememo","usecallback"]),
74
+ js: new Set(["prototype","arguments","callee","getter","setter","proxy","promise","resolve","reject","then","catch"]),
75
+ jsx: new Set(["react","props","children","component","render","state","effect","hook"]),
76
+ java: new Set(["override","extends","implements","throws","final","synchronized","volatile","transient","strictfp","instanceof","assert","native","enum","annotation","autowired","bean","component","service","repository","controller","springframework","junit","lombok","getter","setter","builder","tostring","hashcode","equals","arraylist","hashmap","optional","stream","collectors","iterator","comparable","serializable","runnable","callable","exception","runtimeexception"]),
77
+ kt: new Set(["override","extends","object","companion","data","sealed","inner","inline","reified","crossinline","noinline","lateinit","lazy","apply","also","let","with","run","when","vararg","init","constructor","primary","secondary","coroutine","suspend","flow","stateflow","sharedflow","viewmodel","livedata","hilt","inject","module","provides","binds","qualifier","scope","composable","remember","mutablestate","launchedeffect","lifecycle"]),
78
+ py: new Set(["self","none","elif","lambda","yield","with","raise","assert","except","finally","pass","global","nonlocal","import","from","class","isinstance","issubclass","hasattr","getattr","setattr","delattr","super","property","staticmethod","classmethod","abstractmethod","dataclass","field","list","dict","tuple","bool","bytes","range","enumerate","print","input","open","close","append","extend","update","items","values","keys","format","strip","split","join","replace","lower","upper","startswith","endswith","type","len","int","str","float","repr","iter","next","zip","reversed","sorted","filter","reduce","partial","functools","itertools","collections","defaultdict","namedtuple","deque","heapq","bisect","contextlib","pathlib","datetime","argparse","logging","unittest","pytest","numpy","pandas","torch","tensorflow","flask","django","fastapi","sqlalchemy","pydantic","asyncio"]),
79
+ go: new Set(["func","chan","goroutine","defer","panic","recover","make","append","copy","close","delete","complex","imag","real","iota","blank","rune","byte","error","interface","struct","select","range","fallthrough","goto","nil","main","init","println","printf","sprintf","fprintf","scanf","sscanf","fscanf","strings","bytes","errors","context","sync","atomic","mutex","waitgroup","channel","handler","middleware","router","request","response","writer","reader","buffer","scanner","encoder","decoder","marshal","unmarshal"]),
80
+ rs: new Set(["let","mut","impl","trait","enum","struct","match","some","none","okay","unwrap","expect","clone","borrow","lifetime","ownership","move","copy","drop","result","option","vector","string","hashmap","hashset","btreemap","btreeset","refcell","mutex","rwlock","channel","sender","receiver","tokio","async","await","spawn","future","stream","iterator","closure","generic","where","derive","macro","println","format","panic","assert","eprintln","anyhow","thiserror","serde","warp","actix","axum","rocket","diesel","sqlx"]),
81
+ cs: new Set(["using","namespace","sealed","readonly","partial","virtual","abstract","override","base","object","string","bool","int","double","float","decimal","char","byte","short","long","uint","ulong","ushort","sbyte","nullable","async","await","task","void","delegate","event","linq","lambda","expression","predicate","action","func","tuple","list","dictionary","hashset","queue","stack","array","ienumerable","ienumerator","icollection","ilist","idictionary","console","debug","trace","exception","argumentexception","nullreferenceexception","invalidoperationexception","ioexception","attribute","annotation","property","getter","setter","constructor","disposable","dispose","garbage","collector","threading","semaphore","monitor","interlocked","concurrent","entity","framework","controller","service","repository","dependency","injection","middleware","startup","program","appsettings","configuration","logging","dbcontext","dbset","migrations"]),
82
+ swift: new Set(["guard","defer","where","some","opaque","associated","protocol","extension","mutating","nonmutating","lazy","weak","unowned","inout","subscript","operator","precedence","associativity","typealias","throw","rethrows","convenience","required","override","final","open","fileprivate","internal","public","private","static","class","struct","enum","actor","swiftui","view","body","state","binding","observedobject","stateobject","environmentobject","published","viewmodel","modifier","frame","padding","foregroundcolor","background","spacer","vstack","hstack","zstack","list","navigationview","navigationlink","sheet","alert","toolbar","button","text","image","textfield","toggle","picker","slider","stepper","scrollview","grid","path","shape","color","font","gesture","animation","transition","combine","publisher","subscriber","cancellable","sink","assign","flatmap","receive","debounce","throttle"]),
83
+ rb: new Set(["begin","rescue","ensure","raise","yield","lambda","proc","block","method","module","require","include","extend","prepend","attr","accessor","reader","writer","protected","private","public","freeze","frozen","dup","clone","object","class","instance","variable","symbol","hash","array","string","integer","float","boolean","nil","each","map","select","reject","inject","reduce","collect","detect","find","sort","uniq","flatten","compact","zip","take","drop","first","last","push","pull","shift","unshift","pop","min","max","sum","count","size","length","empty","any","all","none","include","respond","send","define","missing","inherited","extended","prepended","included","hook","callback","before","after","around","action","controller","model","view","route","migration","schema","database","activerecord","activemodel","actioncontroller","actionview","rails","rack","gem","bundle","rake","rspec","minitest","capybara","factory","stub","mock","double","expect","allow","receive"]),
84
+ html: new Set(["html","head","body","title","meta","link","script","style","div","span","section","article","header","footer","main","aside","nav","form","input","button","select","option","textarea","table","thead","tbody","tfoot","caption","colgroup","fieldset","legend","label","output","datalist","progress","details","summary","figure","figcaption","picture","source","video","audio","track","canvas","svg","path","circle","rect","line","polygon","polyline","defs","group","class","href","type","name","value","action","method","placeholder","required","checked","disabled","readonly","multiple","accept","enctype","autocomplete","autofocus","novalidate","pattern","minlength","maxlength","charset","content","lang","xmlns","viewport","initial","scale","description","keywords","author","refresh","equiv","property","role","aria","tabindex","draggable","contenteditable","spellcheck","translate","hidden","data","onclick","onchange","onsubmit","onload","onerror","onfocus","onblur","onkeydown","onkeyup","onmousedown","onmouseup","onmouseover","onmouseout","onmousemove","onscroll","onresize","tailwind"]),
85
+ css: new Set(["display","flex","grid","block","inline","position","relative","absolute","fixed","sticky","float","clear","margin","padding","border","outline","width","height","overflow","visibility","opacity","transform","transition","animation","color","background","font","size","weight","family","decoration","align","justify","content","items","self","order","grow","shrink","basis","wrap","direction","columns","rows","template","repeat","auto","minmax","span","area","place","object","fit","cursor","pointer","events","none","user","select","resize","zindex","layer","shadow","radius","filter","backdrop","blur","brightness","contrast","grayscale","hue","invert","saturate","sepia","rotate","scale","translate","skew","matrix","perspective","clip","mask","shape","outside","inside","overflow","ellipsis","nowrap","word","break","letter","spacing","indent","capitalize","uppercase","lowercase","white","space","vertical","baseline","middle","super","sub","list","counter","before","after","hover","focus","active","visited","disabled","checked","valid","invalid","required","optional","first","last","nth","child","root","empty","target","lang","media","screen","print","query","supports","charset","keyframes","viewport","placeholder","selection","scrollbar"]),
86
+ scss: new Set(["mixin","include","extend","each","while","else","error","warn","debug","forward","through","variable","interpolation","parent","selector","namespace","module","sass","scss","nesting","rule","declaration","property","value","default","global","important"]),
87
+ yml: new Set(["true","false","null","name","uses","with","runs","steps","jobs","needs","outputs","inputs","secrets","vars","environment","strategy","matrix","services","container","image","volumes","ports","networks","healthcheck","command","entrypoint","working","directory","timeout","retry","concurrency","permissions","defaults","reusable","workflow","trigger","push","pull","request","release","schedule","cron","branches","tags","paths","types","artifacts","cache","restore","keys","path","upload","download","deployment","approvals","reviewers","pages","packages","registry","docker","build","test","deploy","lint","coverage","report","notify","slack","email","include","exclude"]),
88
+ yaml: new Set(["true","false","null","name","uses","with","runs","steps","jobs","needs","outputs","inputs","secrets","vars","environment","strategy","matrix","services","container","image","volumes","ports","networks","healthcheck","command","entrypoint","working","directory","timeout","retry","concurrency","permissions","defaults","reusable","workflow","trigger","push","pull","request","release","schedule","cron","branches","tags","paths","types","artifacts","cache","restore","keys","path","upload","download","deployment","approvals","reviewers","pages","packages","registry","docker","build","test","deploy","lint","coverage","report","notify","slack","email","include","exclude"]),
89
+ json: new Set(["true","false","null","name","version","description","keywords","license","author","main","module","types","files","scripts","dependencies","devdependencies","peerdependencies","optionaldependencies","engines","repository","bugs","homepage","private","workspaces","exports","imports","type","config","publishconfig","resolutions","overrides"]),
90
+ xml: new Set(["version","encoding","xmlns","xsi","type","schema","location","element","attribute","complextype","simpletype","sequence","choice","restriction","extension","include","redefine","annotation","documentation","appinfo","notation","field","selector","unique","keyref","substitution","group","attributegroup","list","union","enumeration","pattern","minlength","maxlength","length","mininclusive","maxinclusive","minexclusive","maxexclusive","fractiondigits","totaldigits","whitespace","nillable","abstract","block","final","mixed","target","namespace","elementformdefault","attributeformdefault","blockdefault","finaldefault","lang","base","value","fixed","default","form","processcontents"]),
91
+ toml: new Set(["true","false","name","version","description","edition","authors","license","repository","homepage","documentation","keywords","categories","workspace","members","dependencies","devdependencies","builddependencies","features","profile","release","debug","test","bench","default","path","optional","package","build","resolver","patch","replace","source","registry","target","compiler","linker","rustflags","incremental","overflow","checks","panic","codegen","units","lto","strip","debuginfo","splitdebuginfo","rpath","binaries","examples","tests","benches","library"]),
92
+ };
93
+
94
+ // ── Helpers ───────────────────────────────────────────────────────────────────
95
+
96
+ function wcBuildStopWords(exts) {
97
+ const combined = new Set(WC_STOP_WORDS);
98
+ const hasCode = exts.some((e) => e !== "md" && e !== "txt");
99
+ if (hasCode) {
100
+ for (const w of WC_LANG_STOP_WORDS._code) combined.add(w);
101
+ }
102
+ for (const ext of exts) {
103
+ const s = WC_LANG_STOP_WORDS[ext];
104
+ if (s) for (const w of s) combined.add(w);
105
+ }
106
+ return combined;
107
+ }
108
+
109
+ function wcEsc(s) {
110
+ return String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
111
+ }
112
+
113
+ function extractWordsFromMarkdown(text, stopWords = WC_STOP_WORDS) {
114
+ return text
115
+ // Strip import/package/require/include/using/namespace declarations
116
+ .replace(/^\s*(import|export\s+\{[^}]*\}|export\s+\*|package|require|#include|#import|using|namespace|from\s+['"][^'"]+['"]\s*(import)?|@[A-Za-z]+)\b.*/gm, "")
117
+ // Strip markdown code blocks
118
+ .replace(/```[\s\S]*?```/g, "")
119
+ .replace(/`[^`\n]+`/g, "")
120
+ // Strip markdown links (keep label)
121
+ .replace(/\[([^\]]*)\]\([^)]*\)/g, "$1")
122
+ // Strip URLs
123
+ .replace(/https?:\/\/\S+/g, "")
124
+ // Strip punctuation / operators
125
+ .replace(/[#*_~>`|!\[\](){}=\-+]/g, " ")
126
+ .toLowerCase()
127
+ .split(/[^a-zàâäéèêëïîôùûü']+/)
128
+ .map((w) => w.replace(/^'+|'+$/g, ""))
129
+ .filter((w) => w.length > 3 && !stopWords.has(w));
130
+ }
131
+
132
+ function renderWordCloud(list) {
133
+ const canvas = document.getElementById("wc-canvas");
134
+ const body = document.getElementById("wc-body");
135
+ canvas.width = body.clientWidth;
136
+ canvas.height = body.clientHeight;
137
+
138
+ const isDark = document.documentElement.classList.contains("dark");
139
+ const colors = isDark
140
+ ? ["#60a5fa","#34d399","#f9a8d4","#a78bfa","#fbbf24","#6ee7b7","#93c5fd","#fb923c"]
141
+ : ["#1d4ed8","#047857","#7c3aed","#b45309","#be123c","#0369a1","#4338ca","#c2410c"];
142
+
143
+ const maxFreq = list[0][1];
144
+ const wordList = list.map(([w, n]) => [w, Math.max(10, Math.round((72 * n) / maxFreq))]);
145
+
146
+ document.getElementById("wc-status").classList.add("hidden");
147
+ canvas.classList.remove("hidden");
148
+
149
+ WordCloud(canvas, {
150
+ list: wordList,
151
+ gridSize: Math.round((8 * canvas.width) / 1024),
152
+ fontFamily: "ui-sans-serif, system-ui, sans-serif",
153
+ color: () => colors[Math.floor(Math.random() * colors.length)],
154
+ backgroundColor: isDark ? "#030712" : "#ffffff",
155
+ rotateRatio: 0.3,
156
+ minSize: 10,
157
+ });
158
+ }
159
+
160
+ // ── Browser (folder picker) ───────────────────────────────────────────────────
161
+
162
+ let _wcBrowseParent = null;
163
+ let _wcBrowseCurrent = "";
164
+
165
+ function wcToggleBrowser() {
166
+ const browser = document.getElementById("wc-browser");
167
+ const isHidden = browser.classList.toggle("hidden");
168
+ if (!isHidden) wcLoadBrowse(_wcBrowseCurrent || document.getElementById("wc-root").value || "/");
169
+ }
170
+
171
+ async function wcLoadBrowse(dirPath) {
172
+ const list = document.getElementById("wc-browse-list");
173
+ list.innerHTML = '<p class="px-3 py-4 text-xs text-gray-400 text-center">Loading…</p>';
174
+ try {
175
+ const data = await fetch("/api/browse?path=" + encodeURIComponent(dirPath)).then((r) => r.json());
176
+ _wcBrowseCurrent = data.current;
177
+ _wcBrowseParent = data.parent;
178
+ document.getElementById("wc-browse-path").textContent = data.current;
179
+ document.getElementById("wc-browse-up").disabled = !data.parent;
180
+
181
+ const rows = data.dirs.map((dir) =>
182
+ `<button data-path="${wcEsc(dir.path)}" onclick="wcLoadBrowse(this.dataset.path)"
183
+ class="w-full flex items-center gap-2 px-3 py-2 text-sm text-left hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
184
+ <span class="text-gray-400 shrink-0">&#128193;</span>
185
+ <span class="text-gray-700 dark:text-gray-300 truncate">${wcEsc(dir.name)}</span>
186
+ </button>`
187
+ );
188
+
189
+ const selectBtn = `<button onclick="wcSelectFolder()" class="w-full px-3 py-2 text-xs text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-blue-950/30 text-left font-medium border-t border-gray-100 dark:border-gray-800">
190
+ &#10003; Select: <span class="font-mono">${wcEsc(data.current)}</span>
191
+ </button>`;
192
+
193
+ list.innerHTML = (rows.length
194
+ ? rows.join("")
195
+ : '<p class="px-3 py-3 text-xs text-gray-400 text-center">No sub-folders</p>'
196
+ ) + selectBtn;
197
+ } catch {
198
+ list.innerHTML = '<p class="px-3 py-4 text-xs text-red-400 text-center">Cannot read directory</p>';
199
+ }
200
+ }
201
+
202
+ function wcBrowseUp() {
203
+ if (_wcBrowseParent) wcLoadBrowse(_wcBrowseParent);
204
+ }
205
+
206
+ function wcSelectFolder() {
207
+ document.getElementById("wc-root").value = _wcBrowseCurrent;
208
+ localStorage.setItem("wc-root", _wcBrowseCurrent);
209
+ document.getElementById("wc-browser").classList.add("hidden");
210
+ }
211
+
212
+ // ── Persistence (localStorage) ────────────────────────────────────────────────
213
+
214
+ function wcSaveExts() {
215
+ const exts = [...document.querySelectorAll(".wc-ext:checked")].map((cb) => cb.value);
216
+ localStorage.setItem("wc-exts", JSON.stringify(exts));
217
+ }
218
+
219
+ function wcRestorePrefs() {
220
+ const savedRoot = localStorage.getItem("wc-root");
221
+ if (savedRoot) {
222
+ document.getElementById("wc-root").value = savedRoot;
223
+ _wcBrowseCurrent = savedRoot;
224
+ }
225
+ const savedExts = localStorage.getItem("wc-exts");
226
+ if (savedExts) {
227
+ try {
228
+ const exts = JSON.parse(savedExts);
229
+ document.querySelectorAll(".wc-ext").forEach((cb) => {
230
+ cb.checked = exts.includes(cb.value);
231
+ });
232
+ } catch { /* ignore corrupt data */ }
233
+ }
234
+ document.querySelectorAll(".wc-ext").forEach((cb) => {
235
+ cb.addEventListener("change", wcSaveExts);
236
+ });
237
+ }
238
+
239
+ // ── Open / Launch / Close ─────────────────────────────────────────────────────
240
+
241
+ async function openWordCloud() {
242
+ const overlay = document.getElementById("wc-overlay");
243
+ const status = document.getElementById("wc-status");
244
+ const canvas = document.getElementById("wc-canvas");
245
+ overlay.classList.remove("hidden");
246
+ status.textContent = "Choose a root folder and click Launch.";
247
+ status.classList.remove("hidden");
248
+ canvas.classList.add("hidden");
249
+
250
+ const rootInput = document.getElementById("wc-root");
251
+ if (!rootInput.value) {
252
+ try {
253
+ const cfg = await fetch("/api/config").then((r) => r.json());
254
+ if (cfg.docsFolder) {
255
+ rootInput.value = cfg.docsFolder;
256
+ _wcBrowseCurrent = cfg.docsFolder;
257
+ }
258
+ } catch { /* ignore */ }
259
+ }
260
+ }
261
+
262
+ async function launchWordCloud() {
263
+ const status = document.getElementById("wc-status");
264
+ const canvas = document.getElementById("wc-canvas");
265
+ const root = document.getElementById("wc-root").value.trim();
266
+
267
+ if (!root) {
268
+ status.textContent = "Please select a root folder first.";
269
+ status.classList.remove("hidden");
270
+ return;
271
+ }
272
+
273
+ const exts = [...document.querySelectorAll(".wc-ext:checked")].map((cb) => cb.value);
274
+ if (!exts.length) {
275
+ status.textContent = "Please select at least one extension.";
276
+ status.classList.remove("hidden");
277
+ return;
278
+ }
279
+
280
+ document.getElementById("wc-browser").classList.add("hidden");
281
+ status.textContent = "Reading files…";
282
+ status.classList.remove("hidden");
283
+ canvas.classList.add("hidden");
284
+
285
+ try {
286
+ const params = new URLSearchParams({ path: root });
287
+ exts.forEach((e) => params.append("ext", e));
288
+ const res = await fetch("/api/wordcloud?" + params);
289
+ if (!res.ok) {
290
+ const err = await res.json();
291
+ status.textContent = "Error: " + (err.error || res.statusText);
292
+ return;
293
+ }
294
+ const { files, text } = await res.json();
295
+ status.textContent = `Analyzing ${files} file(s)…`;
296
+
297
+ const stopWords = wcBuildStopWords(exts);
298
+ const freq = {};
299
+ for (const w of extractWordsFromMarkdown(text, stopWords)) {
300
+ freq[w] = (freq[w] || 0) + 1;
301
+ }
302
+
303
+ const list = Object.entries(freq)
304
+ .filter(([, n]) => n >= 2)
305
+ .sort((a, b) => b[1] - a[1])
306
+ .slice(0, 150);
307
+
308
+ if (!list.length) {
309
+ status.textContent = "Not enough words found.";
310
+ return;
311
+ }
312
+
313
+ renderWordCloud(list);
314
+ } catch (err) {
315
+ status.textContent = "Error: " + err.message;
316
+ }
317
+ }
318
+
319
+ function closeWordCloud() {
320
+ document.getElementById("wc-overlay").classList.add("hidden");
321
+ }
@@ -0,0 +1,3 @@
1
+ import { Router } from 'express';
2
+ export declare function wordcloudRouter(): Router;
3
+ //# sourceMappingURL=wordcloud.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wordcloud.d.ts","sourceRoot":"","sources":["../../../src/routes/wordcloud.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAsBpD,wBAAgB,eAAe,IAAI,MAAM,CAyCxC"}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.wordcloudRouter = wordcloudRouter;
7
+ const express_1 = require("express");
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ function collectFiles(dir, exts, out = []) {
11
+ let entries;
12
+ try {
13
+ entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
14
+ }
15
+ catch {
16
+ return out;
17
+ }
18
+ for (const e of entries) {
19
+ if (e.isDirectory() && !e.name.startsWith('.')) {
20
+ collectFiles(path_1.default.join(dir, e.name), exts, out);
21
+ }
22
+ else if (e.isFile()) {
23
+ const ext = path_1.default.extname(e.name).slice(1).toLowerCase();
24
+ if (exts.includes(ext))
25
+ out.push(path_1.default.join(dir, e.name));
26
+ }
27
+ }
28
+ return out;
29
+ }
30
+ function wordcloudRouter() {
31
+ const router = (0, express_1.Router)();
32
+ // GET /api/wordcloud?path=<absolute_path>&ext=md&ext=ts&ext=java
33
+ // Returns { files: number, text: string }
34
+ router.get('/', (req, res) => {
35
+ const rawPath = req.query.path || '/';
36
+ const target = path_1.default.resolve(rawPath);
37
+ const rawExt = req.query.ext;
38
+ const exts = rawExt
39
+ ? (Array.isArray(rawExt) ? rawExt : [rawExt]).map((e) => e.toLowerCase().replace(/^\./, ''))
40
+ : ['md'];
41
+ let stat;
42
+ try {
43
+ stat = fs_1.default.statSync(target);
44
+ }
45
+ catch {
46
+ res.status(400).json({ error: 'Path not found' });
47
+ return;
48
+ }
49
+ let files;
50
+ if (stat.isFile()) {
51
+ const ext = path_1.default.extname(target).slice(1).toLowerCase();
52
+ files = exts.includes(ext) ? [target] : [];
53
+ }
54
+ else if (stat.isDirectory()) {
55
+ files = collectFiles(target, exts);
56
+ }
57
+ else {
58
+ res.status(400).json({ error: 'Path must be a directory or a file' });
59
+ return;
60
+ }
61
+ const text = files
62
+ .map((f) => { try {
63
+ return fs_1.default.readFileSync(f, 'utf-8');
64
+ }
65
+ catch {
66
+ return '';
67
+ } })
68
+ .join('\n\n');
69
+ res.json({ files: files.length, text });
70
+ });
71
+ return router;
72
+ }
73
+ //# sourceMappingURL=wordcloud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wordcloud.js","sourceRoot":"","sources":["../../../src/routes/wordcloud.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,WAAW,CAAC,EAChC,QAAQ,EACR,IAAI,EACJ,WAAmB,GACpB,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAoD/B"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,WAAW,CAAC,EAChC,QAAQ,EACR,IAAI,EACJ,WAAmB,GACpB,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAqD/B"}
@@ -12,6 +12,7 @@ const config_1 = require("./routes/config");
12
12
  const browse_1 = require("./routes/browse");
13
13
  const images_1 = require("./routes/images");
14
14
  const diagrams_1 = require("./routes/diagrams");
15
+ const wordcloud_1 = require("./routes/wordcloud");
15
16
  const config_2 = require("./lib/config");
16
17
  async function startServer({ docsPath, port, openBrowser = false, }) {
17
18
  const app = (0, express_1.default)();
@@ -24,6 +25,7 @@ async function startServer({ docsPath, port, openBrowser = false, }) {
24
25
  app.use('/api/browse', (0, browse_1.browseRouter)());
25
26
  app.use('/api/images', (0, images_1.imagesRouter)(docsPath));
26
27
  app.use('/api/diagrams', (0, diagrams_1.diagramsRouter)(docsPath));
28
+ app.use('/api/wordcloud', (0, wordcloud_1.wordcloudRouter)());
27
29
  // Static frontend assets
28
30
  const frontendPath = path_1.default.join(__dirname, 'frontend');
29
31
  app.use(express_1.default.static(frontendPath));
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "living-documentation",
3
- "version": "3.7.0",
3
+ "version": "4.0.0",
4
4
  "description": "A CLI tool that serves a local Markdown documentation viewer",
5
5
  "main": "dist/src/server.js",
6
6
  "bin": {