diff --git a/site/.gitignore b/site/.gitignore index 1da12d8ae..556e3b841 100644 --- a/site/.gitignore +++ b/site/.gitignore @@ -7,6 +7,7 @@ blog/feed.xml changelist.html news/ files/news.json +files/blog.json # Playground: vendored from web/ui/src/ for local-dev preview only. # CI rebuilds these from source on every publish. To preview locally: diff --git a/site/blog/build_blog.py b/site/blog/build_blog.py index 30e1f87ee..e30796bdc 100644 --- a/site/blog/build_blog.py +++ b/site/blog/build_blog.py @@ -536,6 +536,19 @@ def main(): (out / 'files' / 'news.json').write_text( json.dumps(top_news, indent=2), encoding='utf-8') + # 7. blog.json — drives the "N NEW" nav chip. baseline_date is the + # date of the second-newest post: a first-time visitor (no + # localStorage) sees exactly one post counted as new (the newest). + newest_date = posts[0].date if posts else '1970-01-01' + baseline_date = posts[1].date if len(posts) >= 2 else '1970-01-01' + blog_data = { + 'newest_date': newest_date, + 'baseline_date': baseline_date, + 'posts': [{'slug': p.slug, 'date': p.date} for p in posts], + } + (out / 'files' / 'blog.json').write_text( + json.dumps(blog_data, indent=2), encoding='utf-8') + print(f"built {len(posts)} posts, {len(news)} news entries → {out}/") diff --git a/site/blog/template.html b/site/blog/template.html index e3cf7b666..5c9ee9fc3 100644 --- a/site/blog/template.html +++ b/site/blog/template.html @@ -12,6 +12,11 @@ + + + +
diff --git a/site/downloads.html b/site/downloads.html index 0955da5f4..884069eee 100644 --- a/site/downloads.html +++ b/site/downloads.html @@ -202,5 +202,6 @@

Where to learn more.

+ diff --git a/site/files/blog-counter.js b/site/files/blog-counter.js new file mode 100644 index 000000000..0badfb5f4 --- /dev/null +++ b/site/files/blog-counter.js @@ -0,0 +1,103 @@ +/* Forge nav — "N NEW" blog chip. + * + * Data source: files/blog.json (built by site/blog/build_blog.py). + * Storage: localStorage["daslang:blog:lastSeen"] = "YYYY-MM-DD". + * + * Semantics: + * - First-time visitor (no key) → seeded from blog.json baseline_date, + * which is the 2nd-newest post's date. + * So count = 1 (just the newest). + * - Visiting /blog/ (the index) → key set to newest_date; chip clears. + * - count > 9 → render "9+ NEW". + * - count === 0 → chip not rendered. + */ +(function () { + 'use strict'; + + var STORAGE_KEY = 'daslang:blog:lastSeen'; + + function isBlogIndex() { + var p = window.location.pathname; + return p.endsWith('/blog/') || p.endsWith('/blog/index.html'); + } + + function readLastSeen() { + try { return window.localStorage.getItem(STORAGE_KEY); } + catch (_) { return null; } + } + + function writeLastSeen(date) { + try { window.localStorage.setItem(STORAGE_KEY, date); } + catch (_) { /* private mode / quota — silent */ } + } + + function blogJsonUrl() { + // Locate our own
@@ -378,5 +382,6 @@

Recent activity.

+