Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,22 @@ jobs:
timeout-minutes: 30
steps:
- name: Checkout doc
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: doc

- name: Checkout cordlang
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: ${{ github.repository_owner }}/cordlang
ref: master
path: cordlang

- name: Install toolchain
run: sudo apt-get update && sudo apt-get install -y build-essential

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "22"

Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,12 @@ Thumbs.db
*.log
.vscode/
.idea/

# Secrets / credentials
.env
.env.*
!.env.example
*.pem
*.p12
*.key
credentials.json
50 changes: 31 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
Sitio de documentación oficial escrito en **Cordlang** y generado a **React**.
Todo el contenido visible está en español; la fuente de verdad es `src/**/*.cord` (no editar `dist/`).

**Posicionamiento (manda sobre otras lecturas):** Cordlang es un **IR de UI para vibecode e IA** — fuentes densas, **menos tokens** que JSX, `check` determinista, sin LLM en `compile`. Si alguna página o doc hermano prioriza “otro framework” o amplitud de backends, gana este contrato. Contrato agentes: ruta `/ia` y `../cordlang/docs/AI_CONTEXT.md`.

Dirección visual: **Signal Precision** (tinta + acento `#3DFFB5`, tipografías Syne / IBM Plex). Atmósfera y motion en `public/site.css` + helpers en `public/site.js`.

## Notas de backends (2026)

Además de React (foco de este sitio), el CLI hermano `../cordlang` ya emite **Vue 3**, **Solid**, **email** HTML estático y **PDF** (HTML + herramienta externa), más meta **Next** / **SvelteKit**. Detalle en `../cordlang/docs/` (`VUE.md`, `SOLID.md`, `EMAIL.md`, …).
**Contrato default (loop IA):** React / Svelte / HTML preview.
Además, el CLI emite **Vue 3**, **Solid**, **email**, **PDF**, y meta **Next** / **SvelteKit** como destinos **experimentales** — útiles, pero **no** el norte de producto ni el contrato IA. Detalle en `../cordlang/docs/`.

Ecosistema reciente: `cordlang init --template <id>`, `cordlang add` (paquetes locales), playground stub WASM.
Playground WASM: stub (`PLAYGROUND.md`) — aplazado respecto al loop IA.

## Requisitos

Expand All @@ -21,30 +26,33 @@ src/
app.cord # theme + layout + routes
layouts/docs.cord # shell con sidebar
components/
DocNav.cord # navegación
CodeSample.cord # bloques de ejemplo
SiteHeader.cord # nav + buscar + tema
SiteFooter.cord
DocNav.cord # sidebar (NavLink / aria-current)
DocToc.cord # TOC on-page
CodeSample.cord # chrome + copiar
LiveCounter.cord # demo state
LiveListDemo.cord # demo if/select
pages/
HomePage.cord
InstalacionPage.cord
GuiaPage.cord
CheatsheetPage.cord
EjemplosPage.cord
ReactMapaPage.cord
ParaIaPage.cord
RoadmapPage.cord
HomePage.cord # showcase / hero
public/
site.css # atmósfera, motion, dark theme
site.js # tema, búsqueda, copy
search-index.json
cordlang.json
```

## Rutas

| Ruta | Página |
|------|--------|
| `/` | Inicio |
| `/` | Inicio (showcase) |
| `/instalacion` | Instalación |
| `/guia` | Guía práctica |
| `/guia` | Guía práctica (+ demos) |
| `/cheatsheet` | Cheatsheet |
| `/ejemplos` | Catálogo de ejemplos |
| `/ejemplos` | Catálogo + demos vivas |
| `/templates` | Templates Cord (`init --template`) |
| `/react` | Mapa Cordlang ↔ React |
| `/ia` | Contrato para modelos / agentes |
| `/roadmap` | Roadmap resumido |
Expand Down Expand Up @@ -78,6 +86,7 @@ npm run dev
- **Comillas en strings:** `"say \"hi\""` ya funciona (lexer unescape). Prefiere ejemplos sin comillas anidadas cuando se pueda.
- **Nombres con punto:** `"build.bat"` es texto literal (no expresión JS).
- **`slot`:** en layouts → outlet de router; en componentes (`CodeSample`) → `children`.
- **Clases CSS del sitio:** `class=hero-shell` (una clase) o `class="a b"` (varias). No uses bool attrs inventados (`reveal` solo).
- **No edites `dist/`** como fuente de verdad.

## Scaffold / meta HTML
Expand All @@ -87,10 +96,13 @@ En `cordlang.json` puedes fijar:
- `lang` — atributo `html lang` (este sitio usa `"es"`)
- `title` — `<title>` (si falta, se usa `name`)

El scaffold React envuelve la app en `ErrorBoundary`.
El scaffold React envuelve la app en `ErrorBoundary`, carga fuentes Google y enlaza `/site.css` + `/site.js` desde `public/`.

## Limitaciones UX documentadas
## UX del sitio

- **Nav activa** (`aria-current` / `NavLink`): diferida — Cord aún no expone un primitivo de link activo; el sidebar lista rutas sin resaltar la actual.
- **Nav activa:** `link` emite `NavLink` (React) con `aria-current="page"`.
- **Dark mode:** botón Tema en el header (`site.js` + `[data-theme=dark]`).
- **Búsqueda:** panel en header; filtrado client-side.
- **CodeSample:** botón Copiar vía `data-copy` + `site.js`.
- **Mapa Svelte:** diferido; ver Roadmap. Este sitio documenta el backend React.
- **Responsive:** el scaffold apila `aside` bajo ~768px; el header sticky usa `z-40`.
- **Responsive:** el scaffold apila `aside` bajo ~768px; header sticky con `z-index`.
3 changes: 2 additions & 1 deletion cordlang.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"defaultBackend": "react",
"outDir": "dist",
"lang": "es",
"title": "Cordlang — documentación"
"title": "Cordlang — documentación",
"presets": ["tailwind", "icons", "motion"]
}
120 changes: 120 additions & 0 deletions docs/superpowers/specs/2026-07-24-docs-search-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Docs site search — design spec

**Status:** draft for review
**Date:** 2026-07-24
**Repo:** `doc/` (Cordlang documentation site)
**Choice:** Approach A — static search index + `site.js` (panel global + in-page highlight)

## Problem

The header search only filters a hardcoded list of page links by title/`data-search`. It does not scan page bodies, surface section-level hits, or highlight matches in content.

## Goals

1. **Global panel** — typing queries an index of all doc pages; results show page + section + snippet with query emphasis.
2. **In-page highlight** — after navigating to a hit (or when a query is active on the current page), matching text in `main` is marked; clearing search / Escape removes marks.
3. **Fast / offline-friendly** — no runtime crawl of other SPA routes.

## Non-goals

- Full-text ranking / fuzzy / typo tolerance beyond substring match.
- Searching generated `dist/` JS bundles or `node_modules`.
- Server-side search API.
- Indexing interactive demo widget internals beyond visible copy already in source text.

## Architecture

```
src/pages/*.cord ──► scripts/build_search_index.* ──► public/search-index.json
SiteHeader (panel UI) ◄── site.js (query, render hits, navigate, highlight)
```

### Index schema (`public/search-index.json`)

```json
{
"generatedAt": "ISO-8601",
"entries": [
{
"path": "/guia",
"pageTitle": "Guía práctica",
"sectionId": "state",
"heading": "Componente con state y props",
"text": "plain text excerpt used for matching and snippets…"
}
]
}
```

Rules:

- One entry per content section: prefer elements with `id=` that wrap an `h2` (current Guia pattern); otherwise synthesize from consecutive `h2` + following prose until next `h2`.
- `path` matches Cord routes in `src/app.cord`.
- `text` is lowercased for matching at query time (store original case for snippets, or store once and casefold in JS).
- Skip pure chrome (nav labels duplicated elsewhere) when extracting from page sources.
- **CodeSample bodies:** include a short line of the sample title / first lines so code keywords remain findable, but cap length (~400 chars per section) to avoid noisy results.

### Index build

- Script: `doc/scripts/build_search_index.mjs` (Node, no Cord CLI dependency for parsing).
- Input: walk `src/pages/*.cord` (+ optional `HomePage`).
- Heuristic Cord scrape: strip comments (`#` lines), collect `h1`/`h2` strings, `id=…`, and `p "…"` / text attrs; map page file → route via a small table mirrored from `app.cord` (or parse `route` lines from `app.cord`).
- Output: write `public/search-index.json`.
- Wire: document in `doc/README.md`; run before `cordlang run react` / in CI dogfood job after checkout (cheap).

### Panel UI (`SiteHeader.cord` + `site.js`)

- Keep open/close + input `#doc-search`.
- Replace static-only filter with:
1. Lazy-fetch `/search-index.json` once (cache in memory).
2. Debounced input (~150ms).
3. Empty query → short page list (current curated links OK as fallback).
4. Non-empty → render hit list into a dedicated container `#doc-search-results` (Cord can emit empty shell; JS fills it to avoid re-implementing list virtualization in Cord state).

Each hit row:

- Page title (muted) + section heading (primary)
- Snippet with `<mark>` around the first match
- `href` = `${path}#${sectionId}` when `sectionId` present, else `path`
- On click: store `sessionStorage['doc-search-q'] = query`, navigate (normal link / router)

### In-page highlight

On `DOMContentLoaded`, hashchange, and after SPA route paint (MutationObserver on `main` or existing site.js observers):

1. Read query from `sessionStorage['doc-search-q']` or `URLSearchParams` `?q=` (optional; sessionStorage is enough for SPA).
2. If query length ≥ 2, walk `main.page-enter` / `.docs-main` text nodes (skip `pre`/`.code-chrome__body` if too noisy — **default: highlight prose + headings; skip code chrome**).
3. Wrap matches in `<mark class="doc-search-hit">`.
4. If `location.hash` targets a section, `scrollIntoView` that section; prefer first mark inside it.
5. Escape / clear input: clear `sessionStorage`, remove marks, restore panel empty state.

### Accessibility

- Results list: `role="listbox"` / options or simple links with clear focus order.
- `aria-live="polite"` count (“N resultados”).
- Marks must keep readable contrast (use existing accent / selection tokens).

## File touch list

| File | Change |
|------|--------|
| `scripts/build_search_index.mjs` | New — generate index |
| `public/search-index.json` | Generated artifact (commit or CI-generate; **prefer commit** for static hosting simplicity) |
| `public/site.js` | Index fetch, filter, render, highlight |
| `src/components/SiteHeader.cord` | Results shell + a11y hooks; keep curated empty-state links |
| `doc/README.md` | How to regenerate index |
| `.github/workflows/ci.yml` | Optional: run index script before `cordlang check` / build |

## Success criteria

- Query `state` returns Guia § “Componente con state y props” (and other real hits), not only the Guia nav link.
- Clicking a hit lands on the section and shows yellow/accent marks for the query.
- Escape clears marks and closes/clears search.
- `cordlang check` still green; smoke of docs build still works.

## Out of scope / later

- Keyboard shortcut `/` to focus search.
- Fuse.js fuzzy ranking.
- Multi-language index.
24 changes: 18 additions & 6 deletions public/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
# Static assets
# Static assets (`public/`)

Files here are copied into `dist/react/public` and `dist/svelte/public`
on `cordlang run react|svelte`, and served at the site root by Vite.
Copied into the React app as `/…` when you run `cordlang run react`.

Examples:
- `public/logo.png` → `/logo.png`
- `public/api/products.json` → `/api/products.json`
## Brand (Signal Precision)

| File | Use |
|------|-----|
| `logo.svg` | Mark vector (favicon SVG + UI) |
| `logo.png` | Mark raster 512 |
| `logo-wordmark.svg` | Mark + wordmark (claro) |
| `logo-wordmark-dark.svg` | Mark + wordmark (oscuro) |
| `favicon.ico` | Browser tab |
| `favicon-16.png` / `favicon-32.png` | Fallback sizes |
| `apple-touch-icon.png` | iOS home screen |
| `icon-192.png` / `icon-512.png` | PWA / Android |
| `og.png` | Open Graph / social (1200×630) |
| `site.webmanifest` | PWA manifest |

Also: `site.css`, `site.js`, `search-index.json`.
Binary file added public/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon-16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon-32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon.ico
Binary file not shown.
Binary file added public/icon-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icon-512-art.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions public/logo-wordmark-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions public/logo-wordmark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions public/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/og.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions public/search-index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{"path": "/", "title": "Inicio", "excerpt": "Cordlang showcase UI compacta multi-backend"},
{"path": "/instalacion", "title": "Instalación", "excerpt": "Build del CLI make cmake primeros comandos"},
{"path": "/guia", "title": "Guía práctica", "excerpt": "Sintaxis state props rutas fetch theme demos"},
{"path": "/cheatsheet", "title": "Cheatsheet", "excerpt": "Referencia rápida declaraciones UI"},
{"path": "/ejemplos", "title": "Ejemplos", "excerpt": "Catálogo counter fetch hooks demos vivas"},
{"path": "/templates", "title": "Templates", "excerpt": "counter landing dashboard form-fetch docs-shell ui-kit init"},
{"path": "/react", "title": "Mapa React", "excerpt": "Equivalencias Cordlang React hooks"},
{"path": "/ia", "title": "Para IA", "excerpt": "Contrato do don't para modelos agentes"},
{"path": "/roadmap", "title": "Roadmap", "excerpt": "Estado del lenguaje próximos pasos"}
]
Loading
Loading