Spaces:
Running
Running
Download chart.html from smapoles/dynamicsystemsmodeling: direct link, hf CLI and curl.
- Browser
- Download file 7.06 kB
-
https://huggingface.co/spaces/smapoles/dynamicsystemsmodeling/resolve/main/chart.html
- Command line
-
hf download hf://spaces/smapoles/dynamicsystemsmodeling/chart.html
-
curl -L -o chart.html https://huggingface.co/spaces/smapoles/dynamicsystemsmodeling/resolve/main/chart.html
7.06 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>chart · single view</title> | |
| <!-- Same-origin sibling assets (this file lives at repo root). --> | |
| <link rel="stylesheet" href="./styles/VAR_config.css"> | |
| <link rel="stylesheet" href="./styles/base.css"> | |
| <link rel="stylesheet" href="./renderers/_shared/cell.css"> | |
| <link rel="stylesheet" href="./renderers/_shared/tooltip.css"> | |
| <!-- the ONE shared import map: vendored three.js, no CDN. Root-relative. --> | |
| <script type="importmap"> | |
| { "imports": { "three": "./styles/vendor/three.module.js" } } | |
| </script> | |
| <style> | |
| body { padding: var(--space-five); max-width: 1100px; margin: 0 auto; } | |
| .view-head { font-size: var(--size-footnote); color: var(--text-muted); | |
| text-transform: var(--lowercase); letter-spacing: 0.04em; | |
| margin-bottom: var(--space-four); } | |
| .view-head b { color: var(--text-body); } | |
| .view-head a { color: inherit; } | |
| .view-stamps { margin-top: var(--space-one); } | |
| #host { container-type: inline-size; } | |
| #err { color: var(--chart_color_biased); font-size: var(--size-body); } | |
| /* Curated Method & Results — mirrors the .cf-method / .cf-results grammar. */ | |
| #prose { margin-top: var(--space-five); } | |
| #prose:empty { margin-top: 0; } | |
| .prose-note { color: var(--text-muted); font-size: var(--size-footnote); | |
| text-transform: var(--lowercase); } | |
| #prose h1, #prose h2, #prose h3, #prose h4 { | |
| color: var(--text-body); margin: var(--space-four) 0 var(--space-two); } | |
| #prose p, #prose li { color: var(--text-secondary); font-size: var(--size-body); | |
| line-height: 1.6; } | |
| #prose ul, #prose ol { padding-left: var(--space-four); } | |
| #prose code { font-size: var(--size-footnote); } | |
| /* Provenance footer. */ | |
| .provenance { margin-top: var(--space-five); padding-top: var(--space-four); | |
| border-top: 1px solid var(--ink-15); | |
| font-size: var(--size-footnote); color: var(--text-secondary); } | |
| .provenance h4 { color: var(--text-body); text-transform: var(--lowercase); | |
| letter-spacing: 0.04em; margin: 0 0 var(--space-two); } | |
| .provenance dl { display: grid; grid-template-columns: max-content 1fr; | |
| gap: var(--space-one) var(--space-three); margin: 0 0 var(--space-three); } | |
| .provenance dt { color: var(--text-muted); text-transform: var(--lowercase); } | |
| .provenance dd { margin: 0; word-break: break-word; } | |
| .provenance dd code { font-size: 0.9em; } | |
| .provenance ul { margin: 0; padding-left: var(--space-four); } | |
| .provenance li { margin-bottom: var(--space-one); } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="view-head"> | |
| single-chart view · <b id="chart-id">—</b> · | |
| <a href="gallery/index.html">← all charts</a> · | |
| switch with <code>?chart=<id></code> | |
| <div class="view-stamps" id="stamps"></div> | |
| </div> | |
| <div id="host"></div> | |
| <div id="err"></div> | |
| <section id="prose" aria-label="Curated method and results"></section> | |
| <footer class="provenance" id="provenance" hidden></footer> | |
| <script type="module"> | |
| const DEFAULT = 'dfa_loadings_panel'; | |
| const id = new URLSearchParams(location.search).get('chart') || DEFAULT; | |
| document.getElementById('chart-id').textContent = id; | |
| document.title = `${id} · chart`; | |
| const host = document.getElementById('host'); | |
| const proseEl = document.getElementById('prose'); | |
| const stampsEl = document.getElementById('stamps'); | |
| const provEl = document.getElementById('provenance'); | |
| const fail = (m) => { document.getElementById('err').textContent = m; }; | |
| const esc = (s) => String(s ?? '').replace(/[&<>]/g, (c) => | |
| ({ '&': '&', '<': '<', '>': '>' }[c])); | |
| // 3. Curated Method & Results — bare HTML fragment produced by the deploy | |
| // script at ./charts/<id>/prose.html. Missing during dev → graceful note. | |
| async function loadProse() { | |
| try { | |
| const res = await fetch(new URL(`./charts/${id}/prose.html`, import.meta.url).href); | |
| if (!res.ok) throw new Error(String(res.status)); | |
| proseEl.innerHTML = await res.text(); | |
| } catch { | |
| proseEl.innerHTML = | |
| '<p class="prose-note">curated method & results not yet built for this chart.</p>'; | |
| } | |
| } | |
| function renderStamps(meta) { | |
| const bits = []; | |
| if (meta?.generated_at) bits.push(`generated ${esc(meta.generated_at)}`); | |
| if (meta?.synced_at) bits.push(`synced ${esc(meta.synced_at)}`); | |
| stampsEl.innerHTML = bits.join(' · '); | |
| } | |
| // 4. Provenance footer — input_hash, params, source.table, APA citations. | |
| function renderProvenance(meta, citations) { | |
| const rows = []; | |
| if (meta?.input_hash) | |
| rows.push(`<dt>input hash</dt><dd><code>${esc(meta.input_hash)}</code></dd>`); | |
| if (meta?.source?.table) | |
| rows.push(`<dt>source table</dt><dd><code>${esc(meta.source.table)}</code></dd>`); | |
| if (meta?.params) | |
| rows.push(`<dt>params</dt><dd><code>${esc(JSON.stringify(meta.params))}</code></dd>`); | |
| let cites = ''; | |
| if (citations && citations.length) { | |
| const items = citations | |
| .map((c) => `<li>${esc(c.apa ?? c.key ?? '')}</li>`) | |
| .join(''); | |
| cites = `<h4>citations</h4><ul>${items}</ul>`; | |
| } | |
| if (!rows.length && !cites) return; | |
| provEl.innerHTML = | |
| `<h4>provenance</h4><dl>${rows.join('')}</dl>${cites}`; | |
| provEl.hidden = false; | |
| } | |
| try { | |
| const dmod = await import(new URL(`./charts/${id}/data.js`, import.meta.url).href); | |
| const payload = dmod.payload ?? dmod.default; | |
| if (!payload) throw new Error('data.js exports no `payload`'); | |
| // Read provenance BEFORE we strip payload.method (citations live there). | |
| const meta = payload.meta ?? {}; | |
| const citations = payload.method?.citations ?? []; | |
| renderStamps(meta); | |
| renderProvenance(meta, citations); | |
| const rid = meta.renderer; | |
| if (!rid) throw new Error('no renderer declared in payload.meta'); | |
| const rmod = await import(new URL(`./renderers/${rid}/index.js`, import.meta.url).href); | |
| // Suppress the TERSE engine prose: the shared renderMethodology / | |
| // renderResults guard on presence, so removing these keeps mount() from | |
| // drawing them. The curated fragment below is the authoritative write-up. | |
| delete payload.method; | |
| delete payload.results; | |
| rmod.mount(host, payload); // mounts chart + stat cells + table only | |
| // Belt-and-suspenders for any renderer that doesn't guard on presence: | |
| // drop any terse Method/Results nodes it may still have produced. | |
| host.querySelectorAll('[data-cf-method], [data-cf-results]') | |
| .forEach((n) => n.remove()); | |
| await loadProse(); | |
| } catch (e) { | |
| fail(`could not mount "${id}": ${e.message}. ` + | |
| `Check the id (a folder under charts/) — e.g. ?chart=scalar_vs_topography`); | |
| console.error(e); | |
| } | |
| </script> | |
| </body> | |
| </html> | |