Replace astronomy/expedition-club content with generic placeholders (AI)
The demo tag registry, site name, and the year-category tag convention
(expa-YYYY) were all modeled on a specific Czech astronomy club. Swapped
in generic, English placeholders instead:
- blog-config/tags.json: 12 generic topic tags (guides, news,
tutorials, ...) replacing the Czech astronomy-themed ones.
- The year/category tag convention is now `year-YYYY` instead of
`expa-YYYY` (discovery.js's category regex, the derived field renamed
expa -> categoryYear, and every views.js/README usage).
- siteName and yearLabel strings (en/cs/sk) and index.html's hardcoded
title/header text no longer say "Expedition Blog(s)" / "Expa {year}".
- README examples updated to match (kometa -> guides, expa-2026 ->
year-2026).
Also regenerated all test content (cmjs/articles/, gitignored) with the
new generic tags and year- prefix.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXSVPS3UmmASiiprPfcnUd
This commit is contained in:
1 parent
997768e2ae
commit
e7f8939ced
9 files changed
+52
-129
No files matched your search
@@ -98,8 +98,8 @@ not in frontmatter. The format is:
|
||||
as permanent: retagging or correcting the date later just means renaming the file (see below),
|
||||
but changing the slug changes the article's URL.
|
||||
- `<DDMMYYYY>` — the publish date, 8 digits, no separators (e.g. `16062026` for 16 June 2026).
|
||||
- `<tag1>+<tag2>+…` — zero or more tag ids, joined with `+`. A tag id matching `expa-YYYY` is
|
||||
treated as the article's "year"/category, shown as a badge linking to `#category/expa-YYYY`;
|
||||
- `<tag1>+<tag2>+…` — zero or more tag ids, joined with `+`. A tag id matching `year-YYYY` is
|
||||
treated as the article's "year"/category, shown as a badge linking to `#category/year-YYYY`;
|
||||
every other tag id is a normal topic tag, shown as a pill linking to `#tag/tag-id`. Omit this
|
||||
whole segment (and its leading `~`) if the article has no tags.
|
||||
|
||||
@@ -120,7 +120,7 @@ Steps:
|
||||
|
||||
1. Create the author directory if it doesn't exist: `cmjs/articles/author/`
|
||||
2. Create the Markdown file directly inside it, using the naming convention above, e.g.
|
||||
`cmjs/articles/author/my-article~16062026~kometa+expa-2026.md`
|
||||
`cmjs/articles/author/my-article~16062026~guides+year-2026.md`
|
||||
3. Optionally add a cover image to that author's shared `cmjs/articles/author/media/` folder
|
||||
(creating it if needed), and reference it from frontmatter with `image: media/photo.jpg`.
|
||||
4. Add a frontmatter block at the top of the Markdown file
|
||||
@@ -135,20 +135,20 @@ section below possible.
|
||||
|
||||
### Tag labels
|
||||
|
||||
A tag in the file name is just an id (e.g. `kometa`) — the human-readable label shown on
|
||||
A tag in the file name is just an id (e.g. `guides`) — the human-readable label shown on
|
||||
tag pills comes from `cmjs/blog-config/tags.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"tags": [
|
||||
{ "id": "kometa", "label": "Comet", "description": "", "aliases": [], "active": true }
|
||||
{ "id": "guides", "label": "Guides", "description": "", "aliases": [], "active": true }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Registering an id here is optional — an unregistered tag id still works, it just displays as
|
||||
its raw id instead of a friendly label. `expa-YYYY` year ids don't need to be registered here;
|
||||
its raw id instead of a friendly label. `year-YYYY` year ids don't need to be registered here;
|
||||
they're recognised automatically by pattern and don't use this label registry.
|
||||
|
||||
### Frontmatter format
|
||||
@@ -216,10 +216,10 @@ The body text below the frontmatter is rendered as markdown and shown as the bio
|
||||
| `#search/linux/page/2` | Same, page 2 |
|
||||
| `#author/alice` | All articles by alice, page 1 |
|
||||
| `#author/alice/page/2` | All articles by alice, page 2 |
|
||||
| `#category/expa-2026` | All articles carrying the "expa-2026" year tag, page 1 |
|
||||
| `#category/expa-2026/page/2` | Same, page 2 |
|
||||
| `#tag/kometa` | All articles tagged "kometa", page 1 |
|
||||
| `#tag/kometa/page/2` | Same, page 2 |
|
||||
| `#category/year-2026` | All articles carrying the "year-2026" year tag, page 1 |
|
||||
| `#category/year-2026/page/2` | Same, page 2 |
|
||||
| `#tag/guides` | All articles tagged "guides", page 1 |
|
||||
| `#tag/guides/page/2` | Same, page 2 |
|
||||
| `#post/alice/my-article` | Single article at `cmjs/articles/alice/my-article~DDMMYYYY~tags.md` |
|
||||
|
||||
Author names and category tags on each card and article are clickable links to their respective filter views. A search box in the header navigates to `#search/query`.
|
||||
|
||||
+24
-101
@@ -2,162 +2,85 @@
|
||||
"schemaVersion": 1,
|
||||
"tags": [
|
||||
{
|
||||
"id": "analogova-astrofotografie",
|
||||
"label": "Analogová astrofotografie",
|
||||
"id": "guides",
|
||||
"label": "Guides",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "astromakers",
|
||||
"label": "Astromakers",
|
||||
"id": "news",
|
||||
"label": "News",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "ccd",
|
||||
"label": "CCD",
|
||||
"id": "tutorials",
|
||||
"label": "Tutorials",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "deep-sky",
|
||||
"label": "Deep-sky",
|
||||
"id": "announcements",
|
||||
"label": "Announcements",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "digitalni-astrofotografie",
|
||||
"label": "Digitální astrofotografie",
|
||||
"id": "interviews",
|
||||
"label": "Interviews",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "existencialni-otazky",
|
||||
"label": "Existenciální otázky",
|
||||
"id": "opinion",
|
||||
"label": "Opinion",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "expedicnici",
|
||||
"label": "Expedičníci",
|
||||
"id": "case-studies",
|
||||
"label": "Case Studies",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "experimenty",
|
||||
"label": "Experimenty",
|
||||
"id": "community",
|
||||
"label": "Community",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "katalog-og",
|
||||
"label": "Katalog OG",
|
||||
"id": "releases",
|
||||
"label": "Releases",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "kometa",
|
||||
"label": "Kometa",
|
||||
"id": "behind-the-scenes",
|
||||
"label": "Behind the Scenes",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "meziplanetarni-hmota",
|
||||
"label": "Meziplanetární hmota",
|
||||
"id": "faq",
|
||||
"label": "FAQ",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "mesic",
|
||||
"label": "Měsíc",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "nezarazene",
|
||||
"label": "Nezařazené",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "nove-objevy",
|
||||
"label": "Nové objevy",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "po-expedici",
|
||||
"label": "Po expedici",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "projekty",
|
||||
"label": "Projekty",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "radioastronomie",
|
||||
"label": "Rádioastronomie",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "scigifoto",
|
||||
"label": "Scigifoto",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "skupiny",
|
||||
"label": "Skupiny",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "spolecenske-aktivity",
|
||||
"label": "Společenské aktivity",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "vedouci",
|
||||
"label": "Vedoucí",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "vysledky-pozorovani",
|
||||
"label": "Výsledky pozorování",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "zivot-na-expedici",
|
||||
"label": "Život na expedici",
|
||||
"id": "resources",
|
||||
"label": "Resources",
|
||||
"description": "",
|
||||
"aliases": [],
|
||||
"active": true
|
||||
|
||||
@@ -197,8 +197,8 @@ function buildStub(author, fileName, mtime, authorRoot) {
|
||||
const { slug, date, tags, draft } = parsed;
|
||||
const path = `${authorRoot}${encodeURIComponent(fileName)}`;
|
||||
// "Category" isn't a separate concept anymore — it's just whichever tag
|
||||
// id (if any) looks like an expedition year.
|
||||
const category = tags.find(id => /^expa-20\d{2}$/i.test(id)) || null;
|
||||
// id (if any) looks like a `year-YYYY` id.
|
||||
const category = tags.find(id => /^year-20\d{2}$/i.test(id)) || null;
|
||||
|
||||
return {
|
||||
author,
|
||||
@@ -207,7 +207,7 @@ function buildStub(author, fileName, mtime, authorRoot) {
|
||||
path,
|
||||
mtime,
|
||||
category,
|
||||
expa: category ? Number(category.replace(/^expa-/i, '')) : null,
|
||||
categoryYear: category ? Number(category.replace(/^year-/i, '')) : null,
|
||||
date,
|
||||
tags,
|
||||
published: !draft,
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
// 3 segments, first = "post" → single article (#post/alice/my-article)
|
||||
// 4 segments, first = "author", third = "page" → author filter, page N (#author/alice/page/2)
|
||||
// 4 segments, first = "category", third = "page" → category filter, page N (#category/linux/page/2)
|
||||
// 4 segments, first = "tag", third = "page" → tag filter, page N (#tag/kometa/page/2)
|
||||
// 4 segments, first = "tag", third = "page" → tag filter, page N (#tag/guides/page/2)
|
||||
|
||||
import { MARKED_URL } from './config.js';
|
||||
import { loadTemplates } from './templates.js';
|
||||
|
||||
+6
-6
@@ -47,7 +47,7 @@ function filterLabel(filter) {
|
||||
if (!filter) return '';
|
||||
if (filter.type === 'author') return t('filterAuthor', { value: filter.value });
|
||||
if (filter.type === 'tag') return t('filterTag', { value: tagLabels.get(filter.value) || filter.value });
|
||||
return t('filterYear', { value: filter.value.replace(/^expa-/i, 'Expa ') });
|
||||
return t('filterYear', { value: filter.value.replace(/^year-/i, '') });
|
||||
}
|
||||
|
||||
function pageHash(page, filter) {
|
||||
@@ -116,7 +116,7 @@ function renderFilterNavigation(articles, activeFilter = null) {
|
||||
years.innerHTML = '';
|
||||
const yearCounts = new Map();
|
||||
articles.forEach(article => {
|
||||
const year = Number(article.expa);
|
||||
const year = Number(article.categoryYear);
|
||||
if (year) yearCounts.set(year, (yearCounts.get(year) || 0) + 1);
|
||||
});
|
||||
const yearList = document.createElement('div');
|
||||
@@ -124,8 +124,8 @@ function renderFilterNavigation(articles, activeFilter = null) {
|
||||
yearList.appendChild(allArticlesLink());
|
||||
for (let year = 2026; year >= 2009; year -= 1) {
|
||||
const count = yearCounts.get(year) || 0;
|
||||
const active = activeFilter?.type === 'category' && activeFilter.value.toLowerCase() === `expa-${year}`;
|
||||
yearList.appendChild(renderFilterLink(t('yearLabel', { year }), `#category/expa-${year}`, count, active));
|
||||
const active = activeFilter?.type === 'category' && activeFilter.value.toLowerCase() === `year-${year}`;
|
||||
yearList.appendChild(renderFilterLink(t('yearLabel', { year }), `#category/year-${year}`, count, active));
|
||||
}
|
||||
years.appendChild(yearList);
|
||||
}
|
||||
@@ -178,7 +178,7 @@ function renderCard(article) {
|
||||
// A post only counts as a "category" when one of its directory-name
|
||||
// tags happens to name an expedition year — not every article has one.
|
||||
setField(field('category'), article.category, (category, value) => {
|
||||
category.textContent = t('yearLabel', { year: article.expa });
|
||||
category.textContent = t('yearLabel', { year: article.categoryYear });
|
||||
category.href = `#category/${encodeURIComponent(value)}`;
|
||||
});
|
||||
renderTags(field('tags'), article.tags);
|
||||
@@ -503,7 +503,7 @@ export async function loadArticle(hash) {
|
||||
if (coverUrl) { image.src = coverUrl; image.alt = meta.title || article.slug; } else image.closest('figure')?.remove();
|
||||
const author = field('author'); author.textContent = meta.authorName || article.author; author.href = `#author/${encodeURIComponent(article.author)}`;
|
||||
setField(field('category'), article.category, (category, value) => {
|
||||
category.textContent = t('yearLabel', { year: article.expa });
|
||||
category.textContent = t('yearLabel', { year: article.categoryYear });
|
||||
category.href = `#category/${encodeURIComponent(value)}`;
|
||||
});
|
||||
renderTags(field('tags'), article.tags);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"siteName": "Expediční blogy",
|
||||
"siteName": "Ukázkový blog",
|
||||
"appStartError": "Blog se nepodařilo spustit: {message}",
|
||||
"articleNotFound": "Článek nebyl nalezen",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"filterTag": "Štítek: {value}",
|
||||
"filterYear": "Ročník: {value}",
|
||||
"filterAllArticles": "Všechny články",
|
||||
"yearLabel": "Expa {year}",
|
||||
"yearLabel": "Ročník {year}",
|
||||
|
||||
"paginationLabel": "Stránkování",
|
||||
"paginationPrevious": "Předchozí",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"siteName": "Expedition Blogs",
|
||||
"siteName": "Example Blog",
|
||||
"appStartError": "Failed to start the blog: {message}",
|
||||
"articleNotFound": "Article not found",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"filterTag": "Tag: {value}",
|
||||
"filterYear": "Year: {value}",
|
||||
"filterAllArticles": "All articles",
|
||||
"yearLabel": "Expa {year}",
|
||||
"yearLabel": "Year {year}",
|
||||
|
||||
"paginationLabel": "Pagination",
|
||||
"paginationPrevious": "Previous",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"siteName": "Expedičné blogy",
|
||||
"siteName": "Ukážkový blog",
|
||||
"appStartError": "Blog sa nepodarilo spustiť: {message}",
|
||||
"articleNotFound": "Článok nebol nájdený",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"filterTag": "Štítok: {value}",
|
||||
"filterYear": "Ročník: {value}",
|
||||
"filterAllArticles": "Všetky články",
|
||||
"yearLabel": "Expa {year}",
|
||||
"yearLabel": "Ročník {year}",
|
||||
|
||||
"paginationLabel": "Stránkovanie",
|
||||
"paginationPrevious": "Predchádzajúca",
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1">
|
||||
<title>Expedition Blogs</title>
|
||||
<title>Example Blog</title>
|
||||
<link rel="stylesheet" href="css/reset.css">
|
||||
<link rel="stylesheet" href="css/header.css">
|
||||
<link rel="stylesheet" href="css/layout.css">
|
||||
@@ -17,7 +17,7 @@
|
||||
<body class="blog-page">
|
||||
<header>
|
||||
<!-- Site title always links back to the article list -->
|
||||
<a href="#" id="site-title">Expedition Blogs</a>
|
||||
<a href="#" id="site-title">Example Blog</a>
|
||||
|
||||
<!-- Search form — submits to #search/query via router.js -->
|
||||
<form id="search-form" role="search">
|
||||
|
||||
Reference in new issue
Block a user