mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Learn: a /learn/ deep-dive section — markdown lessons as before/after spec progressions
This commit is contained in:
@@ -47,6 +47,7 @@ about user-facing widgets. At that overlap, one rule keeps them from drifting:
|
||||
| 08 | [vega/editor Techniques](08-vega-editor-techniques.md) | Reference brief: borrowable Monaco-schema wiring, vega-embed lifecycle, two-tier validation, and data-flow/debounce techniques distilled from the official Vega-Lite editor — plus where we do better. |
|
||||
| 09 | [Visual Design Language](09-visual-design.md) | The _visual_ contract: principles inspired by IBM/Carbon, deliberate divergences (square chrome, free color/theming), the token system (Plex type, 8px spacing, role-based color, motion), component conventions, and where to mine the Carbon/IBM source repos for more. Companion: [`visual-specimen.html`](visual-specimen.html). |
|
||||
| 10 | [Interaction & Feedback](10-interaction-and-feedback.md) | The _interaction_ contract: the feedback-channel decision table, latency/feedback budgets, the non-happy-path triad, the recovery & data-safety contract, the keyboard/focus contract, and the resolved widget patterns (window splitter, toolbar, segmented controls, selectable lists, search, sort, empty states, modals). Cites `spec/` for behavior; owns the _how_. |
|
||||
| 11 | [Learning Section](11-learning-section.md) | The `/learn/` deep-dive: a marketing-surface Vite entry reusing core + the landing chart embed; markdown-authored lessons (`import.meta.glob`) parsed into an ordered block model; the authoring/engine split (pure parser in core; `marked` only in `src/learn`). |
|
||||
|
||||
## The non-negotiable layering (every doc assumes this)
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# 11 — The Learning Section (`/learn/`)
|
||||
|
||||
An interactive deep-dive into Vega-Lite, served at `/learn/`: a marketing surface separate
|
||||
from the app, where each lesson walks a spec from an 80%-naive version to a polished one to
|
||||
teach the grammar's dormant power and funnel readers into the app.
|
||||
|
||||
## A marketing surface, like the landing
|
||||
|
||||
`/learn/` is a third Vite entry (`learn/index.html` → `src/learn/`) alongside the landing
|
||||
(`/`) and the app (`/app/`), under the same marketing-surface rules:
|
||||
|
||||
- Reuses **`src/core` and the landing's `LandingChart`** only — never stores, modals,
|
||||
orchestration, or app components. Vega is lazy-loaded through `LandingChart`, so the entry
|
||||
stays light.
|
||||
- **Out of PWA scope.** The service worker is scoped to `/app/`, so the learning pages stay
|
||||
uncontrolled, always-fresh, and indexable — the point for organic-reach content.
|
||||
|
||||
## Lessons are markdown; the renderer is general
|
||||
|
||||
A lesson is a `.md` file in `src/learn/lessons/`, discovered with `import.meta.glob` — so
|
||||
**adding a lesson is dropping a file**, with no registry to edit. A lesson is a _free-form
|
||||
document of ordered blocks_, not a fixed template:
|
||||
|
||||
| Authored as | Block | Rendered by |
|
||||
| ---------------------------------------------------- | ------------- | --------------------------- |
|
||||
| plain markdown | `prose` | `Markdown` |
|
||||
| `:::progression` wrapping `##` stages + fenced specs | `progression` | `SpecProgression` |
|
||||
| a bare fenced `vega-lite` block | `chart` | `LandingChart` |
|
||||
| `:::name … :::` | `callout` | `Markdown` (styled by name) |
|
||||
|
||||
Inside a `:::progression`, each `##` heading is a stage: heading → tab label, prose → note,
|
||||
the following fenced `vega-lite` block → spec. Inline data repeats per fenced block — there
|
||||
is no shared-data construct.
|
||||
|
||||
## The pipeline
|
||||
|
||||
`lessons/*.md` → `import.meta.glob` (in `LearnPage`) → `parseLesson` (`core/lesson-parse`) →
|
||||
`LessonBlock[]` → `LearnPage` block dispatch → `Markdown` | `SpecProgression` | `LandingChart`.
|
||||
`SpecProgression` renders each stage's spec with `formatSpec` (`core/json-format`) and
|
||||
highlights what the stage changed with `changedLines` (`core/spec-diff`, an LCS line-diff).
|
||||
|
||||
## Rules
|
||||
|
||||
- **The engine consumes plain data, so the authoring surface is swappable.**
|
||||
`SpecProgression`, `spec-diff`, and `formatSpec` take parsed blocks and specs and know
|
||||
nothing about markdown — the parser is the only thing coupled to the `.md` format. The
|
||||
authoring format can change without touching the widget.
|
||||
- **Parsing, diff, and formatting are pure and live in `core`** (tested hardest); rendering
|
||||
and the markdown library live in `src/learn`. **Core stays dependency-free** — `marked` is
|
||||
imported only by `src/learn/Markdown`.
|
||||
- **`dangerouslySetInnerHTML` renders first-party lesson files** (repo content authored by
|
||||
us), never user input — not an XSS surface.
|
||||
- Lesson specs are fenced JSON parsed with `JSON.parse`; the source pane re-formats them with
|
||||
`formatSpec` so the shown JSON matches the editor's house style.
|
||||
Reference in New Issue
Block a user