Commit graph

169 commits

Author SHA1 Message Date
9d7ac79741
Merge ab2ef3b4c9 into a25829984d 2026-06-12 10:12:58 +00:00
Claude
ab2ef3b4c9
Add mdcms serve and clean-URL hosting documentation
- New `mdcms serve` command: local preview server with SPA clean-URL
  fallback. Unknown extension-less paths (e.g. /section-id) are served
  index.html so reloads and shared clean URLs work; paths with an
  extension still 404, preserving the renderer's category-variant
  fallback. Serves .md as text/markdown and .yml as text/yaml.
  Options: [name], --path, --port (default 8800), --bind.
- New docs/hosting.md: explains why clean URLs 404 on plain static
  hosts and documents the fix per environment (mdcms serve, service
  worker, GitHub Pages 404.html, Netlify/Cloudflare _redirects, nginx,
  Apache, Caddy), plus a standalone Python preview script.
- Update stale boot error message in index.html to point at
  `mdcms serve` instead of the removed "option 8".
- Update CLAUDE.md command table and local-preview note.

https://claude.ai/code/session_018KXUwmSNMGF2UBywTChCcS
2026-06-12 10:12:53 +00:00
Claude
a5127727f0
Enable Back button and fix clean-URL reloads
Renderer (app/index.html):
- navigateTo now pushes a history entry for user navigations (pushState),
  while the initial load, back/forward (popstate/hashchange), and category
  re-renders still replaceState. The browser Back button now returns to the
  previous page instead of leaving the site.

Service worker (mdcms.py generator + app/service-worker.js):
- Serve the cached index.html app shell for navigation requests. Reloading a
  clean URL like /section-id previously 404'd on the static host before any
  JavaScript ran; the shell fallback lets the client-side router resolve the
  path. Also makes pretty-URL reloads work offline.

https://claude.ai/code/session_018KXUwmSNMGF2UBywTChCcS
2026-06-12 07:16:12 +00:00
Claude
df0f179004
Fix renderer XSS/routing bugs and restore CLI fetch-deps
Renderer (app/index.html):
- Guard the router so navigateTo and the hashchange/popstate handlers only
  load relative .md paths (isSafePagePath). Blocks fetching attacker-
  controlled external URLs injected via the location hash.
- Stop treating in-page heading anchors (#heading) as page files, which
  previously replaced the page with a 404.
- HTML-escape meta.title, link href/title attributes, not-found/offline
  messages, and the icon fallback img; block javascript:/data: hrefs via
  safeUrl.
- Hydrate mdcms tags nested inside tabs/accordions/callouts.
- Configure marked once instead of on every render.
- Validate stored theme value; fix text-align center; resolve per-category
  offline message after categories initialise.

CLI (mdcms.py):
- Restore CDN_DEPS, _WOFF2_URL_RE, _fetch_bunny_fonts, _patch_index_html so
  fetch-deps no longer raises NameError.
- Compare site markers against SITE_FORMAT_VERSION with zero-padded version
  comparison, removing the spurious "update available" warning on v0.6 sites.
- Bump CLI to 0.6.1.

https://claude.ai/code/session_018KXUwmSNMGF2UBywTChCcS
2026-06-12 07:07:15 +00:00
a25829984d
Update config file comment for version 0.6.0
Some checks failed
/ mirror (push) Has been cancelled
2026-06-10 22:06:03 +07:00
1f083fd12f
Update version comment from v0.4 to v0.6.0 2026-06-10 22:05:16 +07:00
Claude
c7fde737f2
chore: bump version to 0.6.0 (7 June 2026)
Some checks failed
/ mirror (push) Has been cancelled
https://claude.ai/code/session_01Ai8xRvmrzdhuTKiRQ2fnn9
2026-06-07 18:03:09 +00:00
Claude
c43d8415a4
chore: add Python entries to .gitignore
__pycache__/ and other Python build artifacts were untracked.

https://claude.ai/code/session_01Ai8xRvmrzdhuTKiRQ2fnn9
2026-06-07 18:01:13 +00:00
Claude
8e7f5d3ae9
feat: mdcms build writes mdcms.json; register accepts URLs
mdcms build now calls generate_site_manifest() at the end of every build,
writing mdcms.json to the site root. This file lists all deployable files
and empty directories, and is deployed alongside the site so any mdcms
user can register a copy of the site from its URL.

mdcms register now accepts a GitHub repo URL or plain HTTPS URL as PATH
or via --from. GitHub URLs try mdcms.json (raw content) first and fall
back to the Contents API tree-walk. Plain URLs require mdcms.json to be
present and fail with a clear error if it is not found.

- generate_site_manifest() added; called at end of run_build
- download_template(dest, source=None) dispatches on source type
- _parse_github_url() extracts owner/repo/branch/subpath from GitHub URLs
- _fetch_manifest() / _apply_manifest() handle the manifest protocol
- _download_tree_api() retained as GitHub Contents API fallback
- _http_get_github() carries Accept header for Contents API responses
- MANIFEST_FILENAME = "mdcms.json"; GITHUB_URL_RE added
- app/template-manifest.json replaced by app/mdcms.json
- register command: PATH accepts URL; --from option added

https://claude.ai/code/session_01Ai8xRvmrzdhuTKiRQ2fnn9
2026-06-07 18:00:24 +00:00
be698a2bdd
Update remote repository URL in mirror workflow 2026-06-08 00:55:21 +07:00
Claude
e559e67341
feat: manifest-driven template download
Replace the GitHub Contents API tree-walk with a flat manifest approach.
template-manifest.json lists every file and empty directory in the starter
template; download_template() fetches the manifest then pulls each file
directly as a raw URL, sidestepping git API rate limits and making the
template hostable from any HTTP source.

- GITHUB_CONTENTS_API / _github_get / _download_tree removed
- TEMPLATE_BASE_URL + TEMPLATE_MANIFEST constants added
- _http_get() replaces _github_get() (generic, no GitHub headers)
- download_template() accepts optional base_url for custom sources
- app/template-manifest.json added (v0.4, 35 files, 2 empty dirs)
- Generated files (manifest.json, service-worker.js, search.json)
  excluded from manifest — they belong to mdcms build output, not
  the starter template

https://claude.ai/code/session_01Ai8xRvmrzdhuTKiRQ2fnn9
2026-06-07 17:41:07 +00:00
Claude
810ed975e5
feat: clean URLs for section-id pages
Pages whose filename matches a nav section-id are now accessible at a
clean pathname URL (e.g. /timesheet) rather than /#pages/timesheet.md.
Adds app/404.html for GitHub Pages SPA routing support.

https://claude.ai/code/session_01Ai8xRvmrzdhuTKiRQ2fnn9
2026-06-07 17:33:08 +00:00
Claude
31330d19e2
feat: clean URLs for section-id pages
Pages whose filename matches a nav section-id now get a clean pathname
URL (e.g. /timesheet) instead of the hash-based /#pages/timesheet.md.

- _initialPathname captured at IIFE start; handles ?_route= from 404.html
- basePath determined by initBasePath() after nav data loads; subpath
  deployments (e.g. /mysite/) handled automatically
- navigateTo() uses replaceState to /slug for section-id pages and falls
  back to #hash for everything else
- popstate listener handles browser history if a clean URL was the entry
- resolveSlugToFile() validates that slug is both a section code and has
  a pages/{slug}.md entry in navData
- app/404.html added for GitHub Pages SPA routing

https://claude.ai/code/session_01Ai8xRvmrzdhuTKiRQ2fnn9
2026-06-07 17:23:30 +00:00
8295cbca2c
Merge pull request #21 from kbenestad/development
Some checks failed
/ mirror (push) Has been cancelled
Merge main into development — sync all theme system changes
2026-06-05 10:56:29 +07:00
be1e908615
Merge pull request #25 from kbenestad/claude/mdcms-arm-release-compile-8R4Sa
Add Linux arm64 release binary and .deb package
2026-06-05 10:56:04 +07:00
Claude
0e14e80d1f
Add Linux arm64 release binary and .deb package
Adds an ubuntu-24.04-arm matrix entry so each release produces
mdcms-linux-arm64 and a matching arm64 .deb alongside the existing
amd64 artefacts. Fixes the fpm binary path and .deb artifact name to
be matrix-driven so both Linux builds are independent.

https://claude.ai/code/session_01LScjwzJJgLKsNrqEPLxJS8
2026-06-05 03:52:18 +00:00
21cae07a9b
Update remote repository URL in mirror workflow
Some checks are pending
/ mirror (push) Waiting to run
2026-06-04 17:11:57 +07:00
5af611502a
Add GitHub Actions workflow for repository mirroring 2026-06-04 17:08:50 +07:00
2e2fd2093f
Add files via upload 2026-05-21 23:57:51 +07:00
Claude
ee3a967b86
docs: add tabs and accordion reference to reference-pages.md
Documents all four block types (tab-underline, tab-filled,
accordion-underline, accordion-filled and their aliases) with
per-item key tables and worked examples, in the same style as
the existing callout/toc/posts-* sections.

https://claude.ai/code/session_01SFMh7PDxJjvvo5dYbCCFFs
2026-05-21 16:56:44 +00:00
Claude
a4031bc008
docs: remind Claude to fetch remote branches before assuming one doesn't exist
https://claude.ai/code/session_01SFMh7PDxJjvvo5dYbCCFFs
2026-05-21 16:41:45 +00:00
Claude
a09df3a63c
Add tabs and accordion content components to index.html
Implements four new mdcms fenced-block types:
  tab-underline / tab, tab-filled,
  accordion-underline / accordion, accordion-filled

Each block reads items: from a YAML body. Tab state and accordion
open/close are managed with aria-selected / aria-expanded and
data-open attributes. Markdown content inside each item is rendered
with the same pipeline as the surrounding page.

Adds computeDerivedTokens() — called on every applyTheme() — which
computes --mdcms-bar, --mdcms-filled-bg/border/fg, --mdcms-strip-border
from the active palette. Uses HSL chroma (S × (1-|2L-1|)) instead of raw
HSL S for the bold-nav heuristic, avoiding a false-positive on near-white
nav colours like the default #F8FAFC.

Adds app/pages/tabs-accordions.md as a visual test page and
docs/unreleased.md to track this change ahead of the next release.

https://claude.ai/code/session_01SFMh7PDxJjvvo5dYbCCFFs
2026-05-21 16:41:27 +00:00
099320cde7
Create .gitkeep 2026-05-21 23:21:43 +07:00
Claude
4c8ca31651
fix: hidden categories now auto-switch to default instead of showing error
Two bugs fixed in navigateTo:

1. When a category has visibilityifnocontent: hidden (default) and the
   current page has no variant for it, the renderer now silently switches
   to the default category before fetching. Previously the category stayed
   active (kept visible in the selector via the activeCategory guard),
   the fetch failed, and an error page was shown.

2. The offline message stored in localStorage was shown for any failed
   fetch, not just genuine offline situations. Now gated on !navigator.onLine
   so missing pages always show pagenotfoundmessage instead.
2026-05-21 15:27:10 +00:00
Claude
5f3175497b
Merge branch claude/update-config-docs-NnldI into development 2026-05-21 15:07:09 +00:00
Claude
ef4197fa83
feat: add visibilityifnocontent per-category config key
When set to visible, the category always appears in the selector
even when no variant exists for the current page. Navigating to
such a page shows pagenotfoundmessage with no fallback to
default-category content. Default behaviour (hidden) is unchanged.

Updates pageShouldDisplay and visibleCategoryCodesForCurrentPage
to honour the new key alongside the existing notfoundmessage logic.
Docs updated with key description, summary table, and full example.
2026-05-21 15:02:31 +00:00
Claude
cc4ed7b881
docs: add missing per-category config keys to reference-config.md
Documents all keys that can appear under default-category and
categories entries: message, name-latin, notfoundmessage,
pagenotfoundmessage, font, and line-height. Adds a summary table
and updates the full example to show these keys in context.
2026-05-21 14:46:46 +00:00
a939883bef
Clarify markdown usage in reference pages
Update documentation to clarify markdown usage.
2026-05-21 12:14:37 +07:00
80877cbaea
Fix markdown syntax in reference pages documentation
Correct markdown formatting for code blocks and frontmatter.
2026-05-21 12:14:14 +07:00
7ab7d468e5
Improve markdown structure in reference pages
Update markdown formatting and clarify frontmatter section.
2026-05-21 12:13:45 +07:00
Claude
b9410d4b88
Fix two bugs: SPA-routing page load failure and stale service worker
fetchPageFile now rejects text/html responses so servers with SPA routing
(e.g. Cloudflare Pages with /* /index.html 200) no longer trick the renderer
into treating a fallback index.html as a found markdown file. Category-variant
pages (page.current.md with no plain page.md) now fall through correctly to
their variant URL.

mdcms build now writes a self-unregistering service-worker.js when pwa: no,
evicting any stale caching worker left over from a previous pwa: yes build.
manifest.json is also removed when pwa: no.

https://claude.ai/code/session_01Xs5GyREFhjWxhS1UhW2wA8
2026-05-19 14:55:51 +00:00
Claude
0bf8cf319b
Merge branch claude/config-sitename-title-Dmzsl into development
Picks up blank <title></title> in app/index.html template (cleaner than
the hardcoded MD-CMS value; mdcms build overwrites it with sitename on
every build either way).

https://claude.ai/code/session_01Xs5GyREFhjWxhS1UhW2wA8
2026-05-19 14:23:19 +00:00
2fd48fcb7f
Merge pull request #24 from kbenestad/main
Refactor sidebar behavior and add new favicon
2026-05-19 21:19:00 +07:00
Claude
431b1c054c
Fix: raise on config.yml parse errors instead of silently returning empty dict
A YAML parse error in config.yml (e.g. a stray tab character) caused
read_config to swallow the exception and return {}, disabling categories
and producing a broken nav.yml with no variants fields and wrong filenames.
read_config now raises ClickException on both OSError and YAMLError.

Documented in docs/knownbugs.md and docs/unreleased.md.

https://claude.ai/code/session_01Xs5GyREFhjWxhS1UhW2wA8
2026-05-19 14:15:38 +00:00
893588d89b Updated themes, 2026-05-19
New folder structure plus HTML presentation.
2026-05-19 20:20:10 +07:00
03adf65c62 Merge branch 'main' of https://github.com/kbenestad/mdcms 2026-05-19 15:52:09 +07:00
65c4944a84 New standard favicon added. 2026-05-19 15:52:06 +07:00
Claude
7b2d54da57
Update CLAUDE.md: document <title> patching in run_build 2026-05-19 08:38:19 +00:00
Claude
28b248735f
Patch <title> in index.html with sitename during build
mdcms build now writes the sitename from config.yml into the <title> tag
of index.html. WhatsApp, Slack, and other link-preview crawlers read the
static HTML without executing JavaScript, so the title must be correct in
the raw file. Previously it was blank (or "MD-CMS" in older templates).
2026-05-19 08:37:57 +00:00
Claude
a8fcc79ba9
Set page title from config.sitename instead of hardcoded MD-CMS
The static <title> element previously showed "MD-CMS" before JavaScript
loaded. The JS already sets document.title from config.sitename on boot,
so clearing the initial value ensures the browser tab never displays the
hardcoded string.
2026-05-19 08:37:16 +00:00
Claude
ee3d4872a0
Patch <title> in index.html with sitename during build
mdcms build now writes the sitename from config.yml into the <title> tag
of index.html. WhatsApp, Slack, and other link-preview crawlers read the
static HTML without executing JavaScript, so the title must be correct in
the raw file. Previously it was blank (or "MD-CMS" in older templates).
2026-05-19 08:31:47 +00:00
Claude
269980ea28
Set page title from config.sitename instead of hardcoded MD-CMS
The static <title> element previously showed "MD-CMS" before JavaScript
loaded. The JS already sets document.title from config.sitename on boot,
so clearing the initial value ensures the browser tab never displays the
hardcoded string.
2026-05-19 08:27:53 +00:00
Claude
283e0f8299
Fix hamburger hidden on iOS: hide sidebar with visibility on mobile
iOS Safari can fail to honour transform: translateX(-100%) on position:fixed
elements, leaving the sidebar sitting over the content at z-index 100 and
blocking the mobile-header (z-index 50) that contains the hamburger.

Add visibility: hidden to the closed mobile sidebar. A transition-delay of
0.3s (matching the transform duration) keeps the slide-out animation intact —
the sidebar slides away first, then disappears. The open state resets the
transition immediately so the sidebar becomes visible before sliding in.

https://claude.ai/code/session_017r3kqm4FgEGy2DPPzYcLYQ
2026-05-19 07:22:06 +00:00
Claude
3ac0a89be1
Remove sidebar header and footer dividers from nav
https://claude.ai/code/session_017r3kqm4FgEGy2DPPzYcLYQ
2026-05-19 07:03:28 +00:00
Claude
11dc053118
Scope uncategorized-post fix to posts/ only
Pages without a category suffix still map to the default category.
Only posts/ files without a suffix get uncategorized: true in nav.yml
and category: null in search.json.

https://claude.ai/code/session_01EzU13EL8D5Ud2ngQUKDj9e
2026-05-19 07:00:36 +00:00
Claude
51cb68c4f9
Merge branch 'main' of http://127.0.0.1:45849/git/kbenestad/mdcms into development 2026-05-19 06:58:52 +00:00
Claude
d63fc0035f
Document unreleased.md as a living changelog for development
https://claude.ai/code/session_01EzU13EL8D5Ud2ngQUKDj9e
2026-05-19 06:58:41 +00:00
Claude
1279b8035d
Add unreleased.md documenting development-only changes
https://claude.ai/code/session_01EzU13EL8D5Ud2ngQUKDj9e
2026-05-19 06:57:12 +00:00
Claude
e1527d8e3b
Show category-less posts/pages in all categories
Files without a category suffix (e.g. post.md alongside post.en.md)
previously only appeared in the default category. They now appear in
every category, so untranslated content is always visible.

- mdcms.py: nav entries with a bare variant get `uncategorized: true`;
  search.json keeps `category: null` instead of mapping to default code
- index.html: pageShouldDisplay, posts filter, and category dropdown
  all treat uncategorized/null-category items as universally visible

https://claude.ai/code/session_01EzU13EL8D5Ud2ngQUKDj9e
2026-05-19 06:54:58 +00:00
Claude
cb0bc180a4
Remove default bold-on-hover from content links
Link hover bold was hardcoded to 700 in both light and dark root variables.
Users can opt in via `link-style-hover: ...:bold` in theme.yml.

https://claude.ai/code/session_01EzU13EL8D5Ud2ngQUKDj9e
2026-05-19 06:54:50 +00:00