document.title was already set from the siteName string, but a
visible #site-title header link stayed hardcoded in whatever language
it was typed in — a translated site showed a translated tab title
next to an untranslated header. Set once in router.js's init() rather
than showListView(), so a page that loads straight into an article
route still gets it. Documented #site-title as optional embedding
markup and corrected README's claim that <title> isn't JS-templated.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Updates every in-repo mention: README.md title/prose/example paths,
code comments in config-default.js and router.js, and the IndexedDB
DB_NAME prefix in cache.js (cmjs-cache-v3 -> cmkiss-cache-v3).
The DB_NAME change has the same effect as a schema-version bump --
every returning visitor's browser opens a fresh, empty cache under the
new name and the old cmjs-cache-v3 database is left as orphaned
storage. Harmless (cache.js degrades to live-fetch when the cache is
empty), noted in a comment there rather than left as an unexplained
side effect.
Two things this commit does NOT cover, both outside this checkout:
- The local directory itself (still /home/user/Projects/cmjs) --
renamed separately right after this commit.
- The git hosting-side repo name/remote URL
(git.astronomickaexpedice.cz, Astronomicka_Expedice/cmjs.git) --
requires server-side access this session doesn't have; needs a
manual rename on the host plus a local `git remote set-url` update
to match.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A plain static `import ... from './config.js'` can't gracefully
degrade if that file doesn't exist -- a missing module breaks the
whole graph before any application code can catch it. So the four
consumers (discovery.js, i18n.js, templates.js, router.js) now import
BASE_URL/MARKED_URL/ARTICLES_URL from config-default.js instead, which
tries a dynamic import() of the optional config.js (catchable, unlike
a static import) and merges in whatever it exports, falling back to
its own shipped defaults for anything config.js doesn't override --
or doesn't exist at all. Top-level await makes every importing module
wait for that resolution first, same as a plain synchronous export.
config.js itself is now just an optional, empty-by-default file: only
export the specific constant(s) you want to change. Updated the
README's "Local configuration" section (and its three cross-references
in Running locally / Embedding in an existing page / Pointing
articles/ somewhere else) to drop the now-unnecessary "copy this file
before first use" step entirely.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXSVPS3UmmASiiprPfcnUd
Real bugs:
- loadArticle()/loadAuthorView() had no stale-render guard (unlike
loadArticleList()/loadSearch()) -- a slower, superseded request could
overwrite a newer one's render. Both now capture and check a
generation snapshot.
- #post/... links interpolated article.hash (raw, unencoded
"author/slug") directly, but router.js unconditionally
decodeURIComponent()s each segment when parsing -- would throw
(silently swallowed) for any author/slug containing a literal "%" or
other reserved character. Links now go through a new postHref()
helper that encodes each segment individually.
- A startup failure replaced the entire document.body, which would
wipe out a host site's own page content when cmjs is embedded
alongside it. Now scoped to cmjs's own mount points when at least
one exists.
- hydrateArticle() had no in-flight de-duplication -- two concurrent
callers for the same not-yet-hydrated stub (e.g. a page's hydration
racing the next page's prefetch) could each fire a duplicate fetch.
Now tracked via a WeakMap keyed by the stub.
- Leftover "expedition blog"/"expedition year" wording missed by the
earlier astronomy-club genericization pass (that pass's grep didn't
cover the English word "expedition").
Robustness gaps:
- cache.js no longer permanently disables the whole IndexedDB cache
after a single failed transaction -- only openDb() itself failing
does that now.
- Listing mtimes are normalized to minute precision at the one point
they enter the system, so cache comparisons stay consistent even if
a server flips between JSON and HTML-fallback autoindex.
- The root author-listing fetch failing outright is now treated like
"every author's listing failed" (a new rootFailed crawl stat) instead
of surfacing a generic, less-specific error.
- router.js now checks both required mount points exist right after
startup and fails with a clear, catchable message instead of a bare
TypeError the first time showListView()/showArticleView() runs.
- The article view's "back" link now returns to whatever list/search/
filter page the user actually came from (tracked via lastListHash)
instead of always resetting to page 1 of everything.
- filterLabel() now checks filter.type === 'category' explicitly
instead of falling through to it as the default case.
- Author-name filtering is now case-sensitive, matching how author
paths/profile lookups are looked up everywhere else.
- Documented (in code comments and a new README note) that article/bio
Markdown renders via marked.js with no HTML-sanitization pass --
only trusted authors should be adding content.
Minor:
- Extracted applyArticleMetaFields() to share the date/reading-time/
category-badge logic between renderCard() and loadArticle() instead
of duplicating it.
- Clarified resolveMediaUrl()'s WordPress-migration special case as
legacy compatibility, not a general-purpose feature.
- frontmatter.js no longer requires a trailing newline after the
closing "---" -- a file that's nothing but frontmatter now parses
instead of falling through to "no frontmatter at all".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXSVPS3UmmASiiprPfcnUd
The repo is already named cmjs, so the nested cmjs/ subfolder was
redundant. Moved css/, js/, strings/, templates/, and the gitignored
articles/ up to the repo root and removed the empty cmjs/ directory,
so the whole repo (or just css/js/strings/templates/articles) can be
dropped into an existing site and embedded as-is — no wrapper folder
required.
This also fixes a real bug: js/config.js's MARKED_URL previously
reached outside cmjs/ (../../js/marked.min.js) to find the vendored
marked.min.js, which already lived at the repo root as a sibling of
cmjs/ rather than inside it. Now that both files sit in the same js/
folder, MARKED_URL is a same-directory reference and no longer depends
on anything outside this one folder tree. BASE_URL's own formula is
unchanged (config.js is still exactly one level below whatever holds
articles/, strings/, and templates/ — previously that was cmjs/, now
it's the repo root).
Updated index.html, .gitignore (/cmjs/articles/ -> /articles/), and
every path reference throughout README.md (project structure diagram,
embedding instructions, nginx config, discovery/caching docs) to match.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXSVPS3UmmASiiprPfcnUd