diff --git a/.gitignore b/.gitignore index 29ff363..5352b6c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.swp token.txt +.claude \ No newline at end of file diff --git a/openspec/changes/fix-remote-first-heading/.openspec.yaml b/openspec/changes/archive/2026-09-27-add-landing-page/.openspec.yaml similarity index 100% rename from openspec/changes/fix-remote-first-heading/.openspec.yaml rename to openspec/changes/archive/2026-09-27-add-landing-page/.openspec.yaml diff --git a/openspec/changes/archive/2026-09-27-add-landing-page/design.md b/openspec/changes/archive/2026-09-27-add-landing-page/design.md new file mode 100644 index 0000000..9b12820 --- /dev/null +++ b/openspec/changes/archive/2026-09-27-add-landing-page/design.md @@ -0,0 +1,234 @@ +# Design + +## Context + +See proposal.md for motivation and specs/landing/spec.md for requirements. + +Current state that shapes the approach: + +- GitHub Pages is not enabled for the repository; there is no `docs/`, no `gh-pages` + branch, and no user site repository, so the page is a project site under + `/github-markdown-toc/`. +- The version is single-sourced in `gh_toc_version` (`gh-md-toc`). `make release` + and the `--version` bats test both depend on it. +- README installs from `master` (`raw.githubusercontent.com/.../master/gh-md-toc`), + so what a visitor downloads is always master's version. +- Releases are created by hand; `dockerimage.yml` pushes `evkalinin/gh-md-toc:` + when a release is published. Docker Hub tags equal the release tags, which equal + `gh_toc_version`. +- Remote mode is broken for GitHub file URLs (#166); wiki URLs work. Checked with + 0.10.0: `./gh-md-toc README.md https://github.com/ekalinin/nodeenv/wiki/Who-Uses-Nodeenv` + produces a correct TOC for both inputs. +- `tests/tests.bats` pins README's headings, so README-based example output stays + valid while the tests pass. + +## Goals / Non-Goals + +**Goals:** + +- No build tooling in the repository: two hand-written files plus one workflow. +- Deployment needs only the default `GITHUB_TOKEN`, with no extra secrets. +- Every version on the page comes from `gh_toc_version`, with no second copy in the + repository. + +**Non-Goals:** + +- A local build target in `Makefile`; local preview is a plain static file. +- Automated checks of the page in CI (link checking, HTML validation). +- Automatic refresh of example outputs or action versions shown on the page. + +## Decisions + +### Deploy through GitHub Actions, not from a branch + +The workflow uploads the built `site/` as a Pages artifact and deploys it with +`actions/deploy-pages`. + +- Alternative: "Deploy from a branch" with `master:/docs`. Rejected: it serves files + as-is, so the version would have to be copied into the HTML and bumped by hand, + which breaks single-sourcing. +- Alternative: a `gh-pages` branch. Rejected: same version problem, and page changes + would bypass pull requests on `master`. +- Alternative: fetch the version in the browser at runtime. Rejected: an external + request, which the spec forbids. + +### Source folder `site/` + +- Alternative: `docs/`. Rejected: implies documentation (README remains the docs) + and is the folder name for branch-based deploys, which this design does not use. +- Alternative: repository root. Rejected: mixes page files with the tool. + +Files: `site/index.html` (content, sidebar, inline copy script) and +`site/styles.css`. No separate JavaScript file: the copy script is a few lines. + +### Version substitution at deploy time + +`site/index.html` contains the placeholder `{{VERSION}}` (hero, Docker section). The +workflow: + +1. `VERSION="$(./gh-md-toc --version | head -n 1)"` +2. copies `site/` to `_site/` and writes `_site/index.html` with + `sed "s|{{VERSION}}|$VERSION|g" site/index.html > _site/index.html` (a pipe, not + `sed -i`, to stay portable between GNU and BSD sed when run locally) +3. fails if `grep -n '{{' _site/index.html` finds anything + +- Why `--version`: it is the tool's public interface and is covered by the + `--version` bats test. +- Alternative: parse the `gh_toc_version=` line with a regex. Rejected: it depends on + the assignment's formatting, and the `Makefile` regex already requires a + two-digit minor. + +### Triggers track `master`, not releases + +`on: push` to `master` with `paths: [site/**, gh-md-toc, .github/workflows/pages.yml]`, +plus `workflow_dispatch`. No `pull_request` trigger. + +- Why: installation downloads master's `gh-md-toc`, so the page shows the version a + visitor actually gets. A version bump changes `gh-md-toc` and redeploys the page. +- Alternative: `on: release`. Rejected: between a bump and the release, the page + would show an older version than the installation commands download. + +Workflow settings: `permissions: {contents: read, pages: write, id-token: write}`; +`concurrency: {group: pages, cancel-in-progress: false}`; the deploy job uses the +`github-pages` environment. Actions (checked 2026-09-27): `actions/checkout@v7`, +`actions/configure-pages@v6`, `actions/upload-pages-artifact@v5`, +`actions/deploy-pages@v5`. + +### Pages is enabled once by hand + +Pages is enabled manually with Source "GitHub Actions" (Settings -> Pages, or +`gh api -X POST repos/ekalinin/github-markdown-toc/pages -f build_type=workflow`). + +- Alternative: `configure-pages` with `enablement: true`. Rejected: per its + `action.yml`, it requires a token other than `GITHUB_TOKEN` (a PAT or GitHub App), + which would add a secret. + +### Page structure and headings + +One `h1` and `h2`/`h3` sections, so the sidebar matches gh-md-toc's output for a +markdown document with the same headings: + +``` +* [gh-md-toc](#gh-md-toc) + * [Installation](#installation) + * [Why](#why) + * [Usage](#usage) + * [STDIN](#stdin) + * [Local files](#local-files) + * [Remote files](#remote-files) + * [Multiple files](#multiple-files) + * [Auto insert and update TOC](#auto-insert-and-update-toc) + * [GitHub Actions](#github-actions) + * [GitHub token](#github-token) + * [Docker](#docker) + * [Windows](#windows) +``` + +Heading `id`s equal these anchors. The hero is the `h1` "gh-md-toc". Landmarks: +`header` (hero), `nav` (table of contents), `main` (sections), `footer`. + +### Sidebar rendering + +Each TOC line is one `` rendered with `white-space: pre` in a +monospace font. Its visible text is the full markdown line. The markdown syntax +(`* [`, `](#anchor)`) is wrapped in `