FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

daScript/site at master · feiyunwill/daScript · GitHub

Latest commit

 

History

History
 
 

README.md

daslang.io - local development

The site published at daslang.io and deployed by .github/workflows/pages.yml. This README is the canonical guide for running each surface locally - pages.yml references the same commands and treats this file as the source of truth.

What's in site/

site/
+-- index.html              # landing - hand-authored
+-- downloads.html          # downloads & links - hand-authored
+-- dasllama.html           # dasLLAMA benchmarks - pair tables/bars from files/dasllama/bench_records.json
+-- performance.html        # data-queries (linq) benchmarks - matrix from files/performance_bench.json
+-- files/
|   +-- dasllama.js         # dasLLAMA page renderer (bars + tables + receipts, all derived from the records)
|   +-- dasllama/
|   |   +-- bench_records.json  # COMMITTED - merged per-box stores, written by gen_site_records
|   +-- performance.js      # data-queries page renderer (matrix + engine board, INTERP/JIT toggles, derived from the records)
|   +-- performance_bench.json  # COMMITTED - written by benchmarks/sql/_update_results.das --site-json
|   +-- performance_engines.json  # COMMITTED - written by examples/benchmarks/sql/_update_results.das --site-json
|   +-- forge.css           # tokens + components (source of truth) - includes responsive rules + mobile nav
|   +-- forge.js            # sample switcher * install tabs * bench * news (skips CM init on mobile)
|   +-- highlight.js        # daslang tokenizer (hero + blog code blocks)
|   +-- runner.js           # mini-playground WASM shim
|   +-- cm/                 # CodeMirror bundle: codemirror.min.{js,css}, simple-mode.js,
|   |                       # daslang-keywords.js, daslang-mode.js, cm-forge.css (Forge theme)
|   +-- lz-string.min.js    # share URL compressor (used by /playground/)
|   +-- daslang.svg            # master logo (single path, currentColor-tinted)
|   +-- daslang-favicon.svg    # yellow-on-black tile favicon
|   +-- daslang.ico            # multi-size .ico fallback
|   +-- profile_results.json   # fetched by CI from borisbat/dasProfile (gitignored)
|   +-- news.json              # generated by build_blog.py (gitignored)
|   +-- wasm/                  # daslang_static.{js,wasm} from CI (gitignored)
+-- blog/
|   +-- _posts/*.md         # 25 posts (source of truth - Markdown w/ Hexo extensions)
|   +-- template.html       # Forge chrome (used by build_blog.py for posts + index)
|   +-- build_blog.py       # generates blog/, news/, changelist.html, news.json
|   +-- index.html          # GENERATED - post listing
|   +-- <slug>.html         # GENERATED - one per post
|   +-- feed.xml            # GENERATED - Atom feed
+-- _news/*.md              # short news entries (one .md per item, body optional)
+-- changelist.html         # GENERATED by build_blog.py - full news list
+-- news/<slug>.html        # GENERATED - micro-pages for news entries with bodies
+-- playground/
|   +-- index.html              # Forge nav + IDE body (mobile gate at top of <body>)
|   +-- forge-skin.css          # CSS overrides on web/examples/ui/src/main.css + mobile notice + splitter
|   +-- playground-init.js      # URL-hash dispatch (#code= legacy / #z= multi-file)
|   +-- playground-tabs.js      # multi-file state, tab strip, autosave to localStorage
|   +-- playground-share.js     # up share popover, is.gd shortener
|   +-- playground-splitter.js  # draggable code | output column splitter
|   +-- samples/                # multi-file sample bundles (gitignored, mirrored from web/examples/ui/samples)
|   +-- *.{js,css}              # other vendored bits from web/examples/ui/src/ for local-dev (gitignored)
+-- tests/
|   +-- playground/             # Playwright e2e suite (28 specs, ~5 s no-WASM)
+-- doc/                        # Sphinx HTML output (gitignored, deployed by CI)

Sources (forge.css, *.md, *.py, template.html, *.html hand-authored) are committed. Build artifacts (blog/<slug>.html, news/, changelist.html, files/wasm/, files/news.json, files/profile_results.json, doc/) are generated and gitignored - see site/.gitignore.

Surface map (what runs where)

Surface Desktop Mobile (<768 px)
Landing hero CodeMirror editor with sample picker, -> run, up playground handoff Static <pre><code class="language-daslang"> block, no CM init. Hero buttons + sample tabs hidden via CSS.
/playground/ Full multi-file IDE - tabs, splitter, share via #z= hash, -> run via WASM "Open this on a laptop" notice (CSS overlay); the IDE and the runtime still initialize underneath it.
/blog/ Full post + Disqus comments at the bottom (shortname https-borisbat-github-io-dascf-blog, identifier = slug, Auto theme picks dark via :root { color-scheme: dark }) Same. Disqus is responsive.
Nav Inline links: docs * benchmarks * downloads * blog * community + v0.6.4, github up, install == hamburger toggles a dropdown panel with the same links. v0.6.4 chip is hidden at <480 px.

The mobile fallbacks are pure CSS + a tiny synchronous gate script - no UA sniffing, no JS feature-detection. Viewport-width is the only signal. Open Chrome DevTools -> device toolbar (Cmd+Shift+M) and reload to test, or browse from a phone on the same WiFi using your LAN IP (ipconfig getifaddr en0).

Quick start (landing only)

cd site && python3 -m http.server 8000
open http://localhost:8000/

The landing page works on its own (no build step). Open DevTools - the benchmarks section, install-tab toggle, and hero sample switcher should all work without errors. The hero -> run button is degraded until you build the WASM artifact (see below).

Building the blog + news + changelist

pip install --user markdown   # one time
python3 site/blog/build_blog.py \
    --posts site/blog/_posts \
    --news site/_news \
    --template site/blog/template.html \
    --out site/

This regenerates:

  • site/blog/index.html, site/blog/<slug>.html for all 25 posts
  • site/blog/feed.xml (Atom)
  • site/changelist.html (full news list)
  • site/news/<slug>.html for news entries with bodies
  • site/files/news.json (top 8 for landing sec. 05)

Then re-run the http.server. Refresh.

Adding a new blog post

# 1. Create a Markdown file under site/blog/_posts/<slug>.md with front matter:
cat > site/blog/_posts/<slug>.md <<'EOF'
---
title: Your post title
date: 2026-05-13 14:30:00
tags:
    - daslang
    - performance
---
Body in Markdown. Use ```daslang fenced blocks for code. <!-- more -->
Content after the marker only shows on the post page, not on the index.

Cross-link another post: {% post_link other-slug %}
EOF

# 2. Rebuild (see above)
python3 site/blog/build_blog.py --posts site/blog/_posts --news site/_news \
    --template site/blog/template.html --out site/

# 3. Push - pages.yml rebuilds and deploys.

Adding a short news entry (one-liner on the landing)

# Create a file under site/_news/<slug>.md (no body for a one-liner):
cat > site/_news/<slug>.md <<'EOF'
---
date: 2026-05-13
tag: 0.6.2
title: One-line description
link: https://github.com/.../releases/tag/v0.6.2
---
EOF

# Rebuild - same command as the blog. The entry lands in the top-5 sec. 05 feed
# on the landing AND in the full /changelist.html. If you add body content
# after the closing ---, build_blog.py also emits /news/<slug>.html.

Sphinx docs (retokened to Forge)

# Local sphinx-build inside the project's venv.
sphinx-build -W --keep-going -b html doc/source build/site
open build/site/index.html

(Memory note: on Boris's machine, an alternative path is /Users/borisbatkin/Library/Python/3.11/bin/sphinx-build, version 7.2.6.)

Verify: dark #0d0c0a background, amber #e8a13a accent on links and the active sidebar item, JetBrains Mono code blocks, the > typographic logo in the top-left. Build must complete with -W (zero warnings).

Mini playground (hero "-> run")

The mini playground needs the WASM artifact at site/files/wasm/. Build it once (then pip install-free; subsequent ninja rebuilds are fast):

# Install emcc (see web/README.md), then:
source ~/emsdk/emsdk_env.sh
emcmake cmake -S web -B web/cmake_temp -G Ninja -DCMAKE_BUILD_TYPE=Release && cmake --build web/cmake_temp
# stage_site_playground auto-drops daslang_static.{js,wasm} into site/files/wasm/.

Re-run the http.server. The hero -> run button should now compile and run the sample. Edits to the code block re-tokenize on input; click -> run to re-execute.

Full playground (/playground/)

The full IDE is web/examples/ui/ (CodeMirror, samples picker, multi-file). For local preview, vendor its source files into site/playground/ and copy the sample bundles:

# stage_site_playground (from the WASM build above) auto-vendors UI + samples
# + daslang_static.{js,wasm} into site/playground/.
# Forge skin auto-loads from site/playground/forge-skin.css.
# CodeMirror itself + the Forge CM theme load from /files/cm/ (already in site/).

JIT (wasm) engine

Optional: build precompiled .wasm per sample so the playground's "JIT (wasm)" radio works. all_wasm auto-stages them into site/playground/samples/examples/.

cmake -B build -DDAS_LLVM_DISABLED=OFF -DDAS_BUILD_WASM=ON && cmake --build build --target all_wasm

Open http://localhost:8000/playground/. Forge nav at the top, multi-file tab strip + Select example + up share + -> run on the left of a unified toolbar, clear on the right. Below: code | output split by a draggable handle (drag to resize, double-click to reset to 50/50). Layout is one container - code and output share a single outer border.

Multi-file workflow

  • Tabs: main.das is the fixed entry point - non-renameable, non-deletable. + adds untitled1.das, untitled2.das, ... Double-click a tab name to rename (validates .das suffix, rejects duplicates). x deletes (confirms if non-empty).
  • Run: writes every open file to MEMFS, then Module.callMain(['main.das']). require utils in main.das resolves against MEMFS as a normal filesystem lookup, so multi-file modules / macros work out of the box (see the "Macros (multi-file)" sample).
  • Share (up share): builds location + '#z=' + LZString.compressToEncodedURIComponent(JSON.stringify(state)). The popover offers a clipboard copy and an is.gd shorten button. Opening a #z=... URL in a fresh browser restores the full multi-file state. The legacy #code=<percent> hash (emitted by the landing hero's up playground handoff) is still accepted and routes the content into main.das.
  • Autosave: 250 ms debounced write of the full state to localStorage['daslang.playground.state.v1']. Restored on next load only if neither #code= nor #z= is present in the URL.
  • Splitter position is persisted to localStorage['daslang.playground.splitLeftPct'].

Full _site preview (everything stitched together)

Replicate pages.yml end-to-end locally:

mkdir -p _site
cp site/*.html _site/
cp site/robots.txt _site/
cp -r site/files _site/files

# Blog
python3 site/blog/build_blog.py \
    --posts site/blog/_posts \
    --news site/_news \
    --template site/blog/template.html \
    --out _site/

# Playground (assumes web/ has been built - see above)
mkdir -p _site/playground _site/files/wasm
cp -r web/examples/ui/src/* _site/playground/
cp web/output/daslang_static.{js,wasm} _site/playground/
cp web/output/daslang_static.{js,wasm} _site/files/wasm/
cp site/playground/index.html _site/playground/index.html
cp site/playground/{forge-skin,cm-forge}.css _site/playground/

# Sphinx (requires daslang binary for das2rst - see doc/ build instructions)
sphinx-build -b html doc/source _site/doc

cd _site && python3 -m http.server 8000

Click through: landing -> blog -> a post -> docs (Sphinx) -> playground -> run a sample. No broken links, consistent Forge chrome on every page.

Updating the dasLLAMA benchmarks page

site/dasllama.html renders entirely from site/files/dasllama/bench_records.json - every row is a das measurement paired with its reference run, every ratio derived in files/dasllama.js, nothing hand-placed. The JSON is generated from the per-box record stores and COMMITTED (no CI fetch):

bin/daslang modules/dasLLAMA/performance/gen_site_records.das
cd site && python3 -m http.server 8000    # eyeball all three sections before pushing

Measurement methodology and the sweep tooling live in modules/dasLLAMA/METHODOLOGY.md (published at /doc/reference/dasllama_methodology.html) and modules/dasLLAMA/BRINGUP.md. Hand-written per-row notes go in modules/dasLLAMA/performance/records/annotations.json - never edit the JSON by hand.

Updating the data-queries performance page

site/performance.html renders entirely from two committed records, each written by its suite's updater from the same sweep output that regenerates that suite's results.md - the page and the results files can never disagree, and the JSON is never edited by hand:

  • site/files/performance_bench.json - benchmarks/sql/_update_results.das (the six-source matrix)
  • site/files/performance_engines.json - examples/benchmarks/sql/_update_results.das (the SQLite/DuckDB/PostgreSQL/Array board)

Re-run each sweep and updater per the "How to re-run" section of its results.md, adding --site-json site/files/<record>.json --machine "<capture box>". The engine suite needs the external providers (-load_module or a daspkg install) and, for a lit PostgreSQL column, a reachable server - see examples/benchmarks/sql/README.md.

Updating dasProfile snapshot

The benchmark numbers come from borisbat/dasProfile/profile_results.json. CI fetches the latest on every publish. Local dev:

curl -sSL -o site/files/profile_results.json \
    https://raw.githubusercontent.com/borisbat/dasProfile/main/profile_results.json

The benchmarks chart on the landing reads it directly - no rebuild needed.

Playwright e2e suite (site/tests/playground/)

Specs cover: dropdowns, tab strip CRUD, multi-file persistence, share-URL round-trip, splitter drag, hero up playground handoff, engine toggle, the shared runtime module, and dead-page revival. Tests that need the daslang runtime carry @wasm in their title and only run when the WASM artifacts are staged; the per-PR lane runs the rest with --grep-invert '@wasm'.

# Start the dev server from site/ (so paths resolve like prod).
cd site && python3 -m http.server 8765 &

# In another shell:
cd site/tests/playground
npm ci                                  # one-time
npx playwright install chromium         # one-time
npx playwright test --grep-invert "@wasm"   # ~5 s, no WASM needed
npx playwright test                     # full suite, requires WASM at site/playground/

CI runs the no-WASM subset on every PR via .github/workflows/playground-e2e.yml. The @wasm-tagged specs are gated on the WASM build being present locally - no dedicated CI tier yet.

Common gotchas

  • Hero -> run shows "WASM runtime not deployed" - you haven't built the WASM artifact yet. Either follow "Mini playground" above, or just preview the static landing without it (the run button is the only thing that won't work).
  • /playground/ shows a blank page - you forgot to cp web/examples/ui/src/* site/playground/. main.js, main.css, and jquery-3.6.0.min.js are needed; CodeMirror itself lives at site/files/cm/ and is already in the repo.
  • Mobile gate doesn't fire - open Chrome DevTools, toggle the device toolbar (Cmd+Shift+M), pick a phone preset, then hard-refresh (Cmd+Shift+R). The mobile detector is a synchronous script that runs once on page load - toggling the toolbar after load doesn't retrigger it.
  • Blog code blocks aren't syntax-highlighted - make sure site/files/highlight.js is loaded. The blog template includes it; if you built with --out /tmp/foo/ and serve from there, your asset paths may diverge from the ../files/ prefix the template uses.
  • /changelist.html is empty - re-run build_blog.py; it generates the changelist from site/_news/*.md.

How CI differs from local dev

The CI flow in .github/workflows/pages.yml mirrors the steps above. Differences worth knowing:

  • CI installs emsdk fresh every run (cached across runs by GitHub).
  • CI fetches profile_results.json on each publish.
  • CI builds Sphinx with -W (treats warnings as errors). Local builds should do the same before pushing.
  • CI deploys to the VPS over rsync (pages.yml - a release dir + atomic symlink flip; Caddy serves it directly).

If something works locally but fails on CI, walk through the workflow file side-by-side with this README - the commands should match.


Back | FazBrowse Home | New Git URL