Download docs.js from PYTHAI/mindX: direct link, hf CLI and curl.
- Browser
- Download file 15.8 kB
-
https://huggingface.co/spaces/PYTHAI/mindX/resolve/main/docs.js
- Command line
-
hf download hf://spaces/PYTHAI/mindX/docs.js
-
curl -L -o docs.js https://huggingface.co/spaces/PYTHAI/mindX/resolve/main/docs.js
15.8 kB
| // mindX docs reader: the three public documents in full (bundled, hashed in the browser against | |
| // the map), the Thesis and Manifesto read aloud, and the library of every document linked to its | |
| // page on mindx.pythai.net. Markdown goes through marked, then DOMPurify, then the link rewriter. | |
| (function () { | |
| 'use strict'; | |
| var SITE = 'https://mindx.pythai.net'; | |
| var HUB = 'https://huggingface.co/datasets/PYTHAI/mindX-docs/blob/main/docs/'; | |
| var HERE = { THESIS: 1, MANIFESTO: 1, NAV: 1 }; // bundled in this Space, byte-identical to the node | |
| var LABEL = { THESIS: 'Thesis', MANIFESTO: 'Manifesto', NAV: 'Navigation' }; | |
| var index = { docs: [] }, byName = {}, audio = {}; | |
| var tierFilter = 'all', query = ''; | |
| function $(id) { return document.getElementById(id); } | |
| function el(tag, cls, text) { | |
| var e = document.createElement(tag); | |
| if (cls) e.className = cls; | |
| if (text != null) e.textContent = String(text); | |
| return e; | |
| } | |
| function link(href, text, cls, internal) { | |
| var a = el('a', cls, text); | |
| a.href = href; | |
| if (internal) a.target = '_self'; else a.rel = 'noopener'; | |
| return a; | |
| } | |
| function nameOf(path) { return path.replace(/\.md$/i, ''); } | |
| function mins(sec) { var m = Math.round(sec / 60); return m + ' min'; } | |
| function fmt(n) { return Number(n).toLocaleString('en-US'); } | |
| function clear(n) { while (n.firstChild) n.removeChild(n.firstChild); } | |
| function slug(s) { | |
| return String(s).toLowerCase().trim().replace(/[^\w\s-]/g, '').replace(/\s+/g, '-'); | |
| } | |
| // ---------- listen ---------- | |
| // audio/index.json has two shapes: the old {parts, voice} per document, and the new | |
| // {voices: {id: {label, parts, start?}}, default_voice, start?}. Both become {voices, order, def}. | |
| function norm(name) { | |
| var d = audio[name]; if (!d) return null; | |
| var voices = {}, order = []; | |
| function add(id, v, label) { | |
| var parts = (v.parts || []).filter(function (p) { return p && p.file; }); | |
| if (!parts.length) return; | |
| var secs = parts.reduce(function (s, p) { return s + (+p.seconds || 0); }, 0); | |
| var st = v.start || d.start || null; | |
| voices[id] = { label: v.label || label, parts: parts, seconds: secs || +v.seconds || 0, start: st && isFinite(+st.seconds) && +st.seconds >= 0 && +st.seconds < secs ? st : null }; | |
| order.push(id); | |
| } | |
| if (d.voices) Object.keys(d.voices).forEach(function (id) { add(id, d.voices[id], id.toUpperCase()); }); | |
| else if (d.parts) add('default', d, String(d.voice || '').replace('piper:', 'piper · ')); | |
| if (!order.length) return null; | |
| return { voices: voices, order: order, def: d.default_voice && voices[d.default_voice] ? d.default_voice : order[0], listen_url: d.listen_url }; | |
| } | |
| function player(name) { | |
| var n = norm(name); if (!n) return null; | |
| var vid = n.def, a = n.voices[vid]; | |
| var card = el('div', 'card player'); | |
| var kind = el('span', 'kind', ''); | |
| card.appendChild(kind); | |
| card.appendChild(el('h3', null, LABEL[name])); | |
| var d = byName[name]; | |
| if (d) card.appendChild(el('p', 'muted', d.title)); | |
| var au = document.createElement('audio'); | |
| au.controls = true; au.preload = 'none'; | |
| var part = 0, started = false, pending = null; | |
| var status = el('div', 'part-status'); | |
| var list = el('div', 'parts'); | |
| function offset(i) { var o = 0; for (var k = 0; k < i; k++) o += +a.parts[k].seconds || 0; return o; } | |
| function load(i, play, at) { | |
| part = i; au.src = a.parts[i].file; pending = at || null; | |
| status.textContent = 'part ' + (i + 1) + ' of ' + a.parts.length + ' · ' + mins(a.parts[i].seconds); | |
| Array.prototype.forEach.call(list.children, function (b, j) { b.classList.toggle('on', j === i); }); | |
| if (play) au.play().catch(function () {}); | |
| } | |
| function seek(T, play) { // a time across the concatenated parts | |
| started = true; | |
| var i = 0; for (var k = 0; k < a.parts.length; k++) if (T >= offset(k)) i = k; | |
| load(i, play, T - offset(i)); | |
| } | |
| au.addEventListener('loadedmetadata', function () { if (pending) { try { au.currentTime = pending; } catch (e) {} pending = null; } }); | |
| // the first play begins at the document's default start (the thesis statement), not at its title | |
| au.addEventListener('play', function () { | |
| if (started) return; started = true; | |
| if (a.start && part === 0 && (au.currentTime || 0) < 1) seek(+a.start.seconds, true); | |
| }); | |
| au.addEventListener('ended', function () { if (part + 1 < a.parts.length) load(part + 1, true); }); | |
| card.appendChild(au); | |
| var jumps = el('div', 'actions'); | |
| function render() { | |
| kind.textContent = 'listen · ' + mins(a.seconds) + ' · ' + a.parts.length + ' parts'; | |
| while (list.firstChild) list.removeChild(list.firstChild); | |
| a.parts.forEach(function (p, i) { | |
| var b = el('button', 'chip', (i + 1) + ' · ' + mins(p.seconds)); | |
| b.type = 'button'; | |
| b.addEventListener('click', function () { started = true; load(i, true); }); | |
| list.appendChild(b); | |
| }); | |
| while (jumps.firstChild) jumps.removeChild(jumps.firstChild); | |
| if (a.start) { | |
| var s = +a.start.seconds, lab = a.start.label || (name === 'THESIS' ? 'start of thesis statement' : 'default start'); | |
| var j1 = el('button', 'chip on', '⚑ ' + lab + ' · ' + Math.floor(s / 60) + ':' + ('0' + Math.floor(s % 60)).slice(-2)); j1.type = 'button'; | |
| j1.title = a.start.anchor ? '“' + a.start.anchor + '…”' : (a.start.note || ''); | |
| j1.addEventListener('click', function () { seek(s, true); }); | |
| var j2 = el('button', 'chip', '⏮ from the beginning'); j2.type = 'button'; | |
| j2.addEventListener('click', function () { seek(0, true); }); | |
| jumps.appendChild(j1); jumps.appendChild(j2); | |
| } | |
| credit.textContent = (/savante/i.test(vid + ' ' + a.label) | |
| ? 'SAVANTE — voice of mindX and DeltaVerse, evolved by survival of the fittest from NEURAL · JAIMLA · LEADER · OVERLORD' | |
| : 'Read by ' + a.label) + ', rendered on my node from exactly these bytes · Ogg Opus'; | |
| started = false; load(0, false); | |
| } | |
| card.appendChild(status); | |
| card.appendChild(list); | |
| card.appendChild(jumps); | |
| if (n.order.length > 1) { | |
| var vs = el('div', 'parts'); | |
| n.order.forEach(function (id) { | |
| var b = el('button', 'chip' + (id === vid ? ' on' : ''), n.voices[id].label); b.type = 'button'; | |
| b.addEventListener('click', function () { | |
| vid = id; a = n.voices[id]; | |
| Array.prototype.forEach.call(vs.children, function (x) { x.classList.toggle('on', x === b); }); | |
| render(); | |
| }); | |
| vs.appendChild(b); | |
| }); | |
| card.appendChild(vs); | |
| } | |
| var actions = el('div', 'actions'); | |
| actions.appendChild(link('docs.html?doc=' + name, 'read along ↓', 'more', true)); | |
| actions.lastChild.addEventListener('click', function (e) { e.preventDefault(); open(name, true); }); | |
| actions.appendChild(link('studio.html?doc=' + name, 'open in the studio →', 'more', true)); | |
| if (n.listen_url) actions.appendChild(link(n.listen_url, 'listen on mindx.pythai.net ↗', 'more')); | |
| actions.appendChild(link(SITE + '/doc/' + name, 'read on mindx.pythai.net ↗', 'more')); | |
| card.appendChild(actions); | |
| var credit = el('p', 'fine', ''); | |
| card.appendChild(credit); | |
| render(); | |
| return card; | |
| } | |
| // ---------- library ---------- | |
| function renderLibrary() { | |
| var ul = $('lib-list'); clear(ul); | |
| var q = query.toLowerCase(), shown = 0; | |
| var docs = index.docs.slice().sort(function (a, b) { | |
| var ta = a.tier === 'public' ? 0 : a.tier === 'member' ? 1 : 2, tb = b.tier === 'public' ? 0 : b.tier === 'member' ? 1 : 2; | |
| return ta - tb || a.path.localeCompare(b.path); | |
| }); | |
| docs.forEach(function (d) { | |
| if (tierFilter !== 'all' && d.tier !== tierFilter) return; | |
| if (q && (d.title + ' ' + d.path).toLowerCase().indexOf(q) < 0) return; | |
| shown++; | |
| if (shown > 400) return; | |
| var li = el('li', 'lib-item tier-' + d.tier); | |
| var name = nameOf(d.path); | |
| var a = HERE[name] | |
| ? link('docs.html?doc=' + name, d.title, 'lib-title', true) | |
| : link(d.url, d.title, 'lib-title'); | |
| if (HERE[name]) a.addEventListener('click', function (e) { e.preventDefault(); open(name, true); }); | |
| li.appendChild(a); | |
| var meta = el('span', 'lib-meta', d.path + ' · ' + fmt(d.words) + ' words'); | |
| li.appendChild(meta); | |
| li.appendChild(el('span', 'tag ' + (d.tier === 'public' ? 'ok' : d.tier === 'member' ? 'warn' : 'dim'), d.tier)); | |
| ul.appendChild(li); | |
| }); | |
| if (shown > 400) ul.appendChild(el('li', 'lib-more', (shown - 400) + ' more. Refine the search.')); | |
| if (!shown) ul.appendChild(el('li', 'lib-more', 'Nothing matches.')); | |
| var c = index.counts || {}; | |
| $('lib-count').textContent = fmt(index.docs.length) + ' documents · ' + (c.public || 0) + ' public'; | |
| } | |
| // ---------- reader ---------- | |
| function rewrite(root, current) { | |
| Array.prototype.slice.call(root.querySelectorAll('a[href]')).forEach(function (a) { | |
| var href = a.getAttribute('href') || ''; | |
| if (/^(https?:|mailto:)/i.test(href)) { a.target = '_blank'; a.rel = 'noopener'; return; } | |
| if (href.charAt(0) === '#') { | |
| a.target = '_self'; | |
| a.addEventListener('click', function (e) { | |
| var t = document.getElementById('h-' + slug(decodeURIComponent(href.slice(1)))); | |
| if (t) { e.preventDefault(); t.scrollIntoView({ behavior: 'smooth', block: 'start' }); } | |
| }); | |
| return; | |
| } | |
| var u; try { u = new URL(href, 'https://x.invalid/docs/'); } catch (e) { u = null; } | |
| var path = u ? u.pathname : ''; | |
| var md = /\.md$/i.test(path); | |
| if (md && path.indexOf('/docs/') === 0) { | |
| var name = decodeURIComponent(path.slice(6).replace(/\.md$/i, '')); | |
| if (HERE[name]) { | |
| a.href = 'docs.html?doc=' + name; a.target = '_self'; | |
| a.addEventListener('click', function (e) { e.preventDefault(); open(name, true); }); | |
| } else { | |
| a.href = SITE + '/doc/' + name; a.target = '_blank'; a.rel = 'noopener'; | |
| var d = byName[name]; | |
| a.title = d ? d.title + ' · ' + d.tier + ' · on mindx.pythai.net' : 'on mindx.pythai.net'; | |
| a.classList.add('ext-doc'); | |
| } | |
| return; | |
| } | |
| if (md) { // a Markdown file outside docs/: the node resolves it by name | |
| a.href = SITE + '/doc/' + path.split('/').pop().replace(/\.md$/i, ''); | |
| a.target = '_blank'; a.rel = 'noopener'; a.classList.add('ext-doc'); | |
| return; | |
| } | |
| // a source file: the active repository is private, so the reference stays as text | |
| var span = el('span', 'src-ref', a.textContent); | |
| span.title = 'in mindX’s source: ' + path.replace(/^\/+/, ''); | |
| a.parentNode.replaceChild(span, a); | |
| }); | |
| Array.prototype.slice.call(root.querySelectorAll('img')).forEach(function (img) { | |
| if (!/^https:/i.test(img.getAttribute('src') || '')) img.remove(); | |
| }); | |
| Array.prototype.slice.call(root.querySelectorAll('h1,h2,h3,h4')).forEach(function (h) { | |
| h.id = 'h-' + slug(h.textContent); | |
| }); | |
| } | |
| function hashHex(buf) { | |
| return crypto.subtle.digest('SHA-256', buf).then(function (d) { | |
| return Array.prototype.map.call(new Uint8Array(d), function (b) { return ('0' + b.toString(16)).slice(-2); }).join(''); | |
| }); | |
| } | |
| function meta(name, d, verdict) { | |
| var m = $('doc-meta'); clear(m); | |
| var row = el('div', 'meta-row'); | |
| row.appendChild(el('span', 'tag ' + (d.tier === 'public' ? 'ok' : 'dim'), d.tier)); | |
| row.appendChild(el('span', 'fine', d.path + ' · ' + fmt(d.words) + ' words')); | |
| if (verdict) row.appendChild(el('span', 'fine ' + (verdict.ok ? 'ok-text' : 'bad-text'), verdict.text)); | |
| m.appendChild(row); | |
| var actions = el('div', 'actions'); | |
| actions.appendChild(link(SITE + '/doc/' + name, 'read on mindx.pythai.net ↗', 'btn small')); | |
| if (audio[name]) { | |
| var l = link('#listen', 'listen here', 'btn small', true); | |
| l.addEventListener('click', function (e) { e.preventDefault(); $('listen').scrollIntoView({ behavior: 'smooth' }); }); | |
| actions.appendChild(l); | |
| actions.appendChild(link('studio.html?doc=' + name, 'studio', 'btn small', true)); | |
| if (audio[name].listen_url) actions.appendChild(link(audio[name].listen_url, 'listen on mindx.pythai.net ↗', 'btn small')); | |
| } | |
| if (HERE[name]) actions.appendChild(link(HUB + name + '.md', 'Markdown on the Hub ↗', 'btn small')); | |
| m.appendChild(actions); | |
| } | |
| function open(name, scroll) { | |
| var d = byName[name] || byName.NAV; name = nameOf(d.path); | |
| try { history.replaceState(null, '', 'docs.html?doc=' + encodeURIComponent(name)); } catch (e) {} | |
| var body = $('doc-body'); | |
| if (!HERE[name]) { // the library links these straight to the node; this is the fallback view | |
| meta(name, d, null); clear(body); | |
| body.appendChild(el('h1', null, d.title)); | |
| body.appendChild(el('p', null, 'This document is ' + d.tier + '-tier. It is on my node, behind the same gate as everything else there.')); | |
| body.appendChild(link(d.url, 'open it on mindx.pythai.net ↗', 'btn')); | |
| return; | |
| } | |
| meta(name, d, { ok: true, text: 'checking sha256…' }); | |
| clear(body); body.appendChild(el('p', 'muted', 'Loading ' + LABEL[name] + '…')); | |
| fetch('docs/' + name + '.md', { cache: 'no-cache' }).then(function (r) { | |
| if (!r.ok) throw new Error(r.status); | |
| return r.arrayBuffer(); | |
| }).then(function (buf) { | |
| var text = new TextDecoder('utf-8').decode(buf); | |
| var html = window.DOMPurify.sanitize(window.marked.parse(text), { USE_PROFILES: { html: true } }); | |
| clear(body); | |
| var frag = document.createElement('div'); frag.innerHTML = html; | |
| rewrite(frag, name); | |
| while (frag.firstChild) body.appendChild(frag.firstChild); | |
| if (scroll) $('reader').scrollIntoView({ behavior: 'smooth', block: 'start' }); | |
| return (window.crypto && crypto.subtle) ? hashHex(buf).then(function (hex) { | |
| meta(name, d, hex === d.sha256 | |
| ? { ok: true, text: 'sha256 ' + hex.slice(0, 12) + '… matches the map' } | |
| : { ok: false, text: 'sha256 ' + hex.slice(0, 12) + '… differs from the map' }); | |
| }) : meta(name, d, null); | |
| }).catch(function () { | |
| clear(body); | |
| body.appendChild(el('p', null, 'This copy did not load.')); | |
| body.appendChild(link(SITE + '/doc/' + name, 'read it on mindx.pythai.net ↗', 'btn')); | |
| }); | |
| } | |
| // ---------- boot ---------- | |
| $('lib-search').addEventListener('input', function (e) { query = e.target.value; renderLibrary(); }); | |
| Array.prototype.forEach.call(document.querySelectorAll('#lib-chips .chip'), function (b) { | |
| b.addEventListener('click', function () { | |
| tierFilter = b.getAttribute('data-tier'); | |
| Array.prototype.forEach.call(document.querySelectorAll('#lib-chips .chip'), function (x) { x.classList.toggle('on', x === b); }); | |
| renderLibrary(); | |
| }); | |
| }); | |
| Promise.all([ | |
| fetch('docs/index.json').then(function (r) { return r.json(); }).catch(function () { return { docs: [] }; }), | |
| fetch('audio/index.json').then(function (r) { return r.json(); }).catch(function () { return {}; }) | |
| ]).then(function (res) { | |
| index = res[0]; audio = res[1]; | |
| index.docs.forEach(function (d) { byName[nameOf(d.path)] = d; }); | |
| var box = $('players'); | |
| ['THESIS', 'MANIFESTO'].forEach(function (n) { var p = player(n); if (p) box.appendChild(p); }); | |
| renderLibrary(); | |
| var want = (new URLSearchParams(location.search).get('doc') || '').toUpperCase(); | |
| open(HERE[want] ? want : 'THESIS', false); | |
| if (location.hash === '#listen') $('listen').scrollIntoView(); | |
| }); | |
| })(); | |