* docs: refresh docs for 3.2.0 — correct stale content, document recent features
The hand-maintained VitePress docs under doc/ had drifted behind a lot of
recent work. They are authored prose (not generated from the OpenAPI spec),
so they need manual upkeep. This pass corrects content that was actively
wrong and documents features shipped since they were last touched.
Corrections (was wrong / misleading):
- cli.md: every command used `node bin/foo.js`, but the scripts are
TypeScript run via pnpm — copy-paste failed. Rewrote to
`pnpm run --filter bin <script>`, documented ~13 previously-undocumented
operator tools, and split running-vs-stopped requirements. Registered the
missing `compactStalePads` script in bin/package.json so the documented
invocation actually works.
- stats.md: described a pre-Prometheus world. Rewrote for the gated
`/stats` (JSON) and `/stats/prometheus` endpoints, the live metric set,
the opt-in `scalingDiveMetrics` instruments (#7756), and `measured-core`.
- admin/updates.md: removed three false "SMTP not yet wired" claims (it is,
via nodemailer + the `mail.*` block), documented the `node-engine-mismatch`
preflight check and the rollback/preflight failure emails, and stripped
obsolete "PR 1 / PR 2" staging language now that all tiers ship.
- api/http_api.md: added the undocumented `anonymizeAuthor` (GDPR Art. 17)
call, fixed copyPad/movePad version annotations (1.2.8 → 1.2.9), corrected
getPadID's param name (readOnlyID → roID), and dropped a reference to a
non-existent `getEtherpad` API call.
- skins.md: colibris is the current default, not an "experimental" skin for
a future 2.0.
- localization.md: bare `window._('key')` is unbound and returns undefined;
recommend `window.html10n.get(...)` / data-l10n-id instead.
- README.md: bumped the v2.2.5 upgrade example to v3.2.0; fixed a
docker.adoc link to docker.md.
- docker.md: added MAIL_*, ENABLE_METRICS, GDPR_AUTHOR_ERASURE_ENABLED,
PRIVACY_BANNER_*, PUBLIC_URL, AUTHENTICATION_METHOD, ENABLE_DARK_MODE,
ENABLE_PAD_WIDE_SETTINGS; fixed the SOCKETIO_MAX_HTTP_BUFFER_SIZE default
(50000 → 1000000).
New documentation:
- configuration.md (new): how settings + `${VAR:default}` substitution work,
trustProxy, and — the previously-undocumented feature — running under a
subpath/ingress via x-proxy-path / X-Forwarded-Prefix / X-Ingress-Path,
with the sanitizer rules and Traefik/NGINX examples. Wired into the
VitePress sidebar and the index hero.
- hooks_server-side.md: ccRegisterBlockElements (the server-side companion
plugin authors miss), exportConvert, exportHTMLSend, createServer,
restartServer, and clientReady (marked deprecated).
- hooks_client-side.md: aceDrop, acePaste, handleClientTimesliderMessage_<name>.
VitePress build passes. The legacy .adoc set was intentionally left in place
— it still feeds the per-version doc archives published to ether.github.com
at release time (bin/release.ts), so it is not dead and is out of scope here.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: address Qodo review — drop .js invocations from configuration.md and CLI help
- configuration.md: the settings-override example referenced a nonexistent
`node src/node/server.js`. Use the supported launcher instead
(`bin/run.sh -s <file>`), and note the runtime is server.ts via tsx.
- compactStalePads.ts / compactPad.ts / compactAllPads.ts: their header
comments and runtime usage output still printed `node bin/*.js`, which
points at files that don't exist. Switched to the documented
`pnpm run --filter bin <script>` form so the --help text matches the docs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(userlist): click a user to open chat with @<name> prefilled
Newcomers to a multi-user pad regularly fail to discover the chat
panel and the @-mention convention. Make the user list itself the
discovery affordance: clicking another user's row opens chat (if
hidden) and prefills the input with "@<their_name> ", ready to send.
The skin gets a small visual cue — pointer cursor on .usertdname and
an underline on hover — so the affordance is visible without
requiring a redesign. The color swatch keeps its own click semantics
(color picker), so the swatch cell is excluded from the new handler.
To let bot/AI plugins substitute their trigger string for an
otherwise-useless @-mention of the bot's display name (e.g.
"@AI Assistant" → "@ai"), this adds a new client-side hook,
chatPrefillFromUser, that takes {authorId, name, prefill} and lets
the first plugin to return a non-empty string override the default
prefill. Documented in doc/api/hooks_client-side.md alongside
chatSendMessage.
Plugin errors in the hook are caught — a misbehaving plugin can't
break the click. If chat is hidden by pad settings, chat.show() is
a no-op and the click effectively does nothing, which matches the
existing behavior of "no chat means no chat-related affordances".
The new prefill never clobbers a real partial message in the input;
if the user was mid-typing something, the @-mention is appended
rather than replacing.
* fix(userlist): don't steal rename focus + add Playwright coverage
Two follow-ups on review of the click-to-chat handler:
1. Bug (Qodo, correctness): clicking the rename <input> on an unnamed
user's row triggered the new row handler, which then focused
#chatinput and made it impossible to name unnamed users from the
user list. Add an early-return that skips form controls inside
the row (input/textarea/select/button/a/[contenteditable=true]).
The swatch was already excluded; this widens the same idea to
anything that's interactive on its own merits.
2. Test coverage: add a frontend Playwright spec
(userlist_click_to_chat.spec.ts) covering the supported flows
and the new regression:
- clicking another named user opens chat and prefills "@<name> "
- clicking the swatch opens color picker, not chat
- clicking the rename <input> on an unnamed user keeps focus
on the input (regression test for the bug above)
- partial chat message is preserved when prefilling
* test: stabilise the partial-message preservation case
The 'partial message in chat input is preserved when prefilling'
case was flaking on CI. Three small changes:
- Seed the chat input with fill() rather than click() + keyboard.type().
Earlier the test was racing chat.focus()'s own setTimeout(100) — when
the keyboard.type started before that timer fired, the typing landed
in whatever element had focus at the time, which wasn't always the
chat input. fill() bypasses focus state entirely.
- Wait for the chat box to be visible before filling, so we don't race
the chaticon click handler.
- Replace the two sequential expect/wait pairs after the daveRow click
with one waitForFunction that asserts both 'hi there' and '@Dave' are
in the input together. The prefill is async (setTimeout(50) inside
the click handler), so a combined wait is more reliable than checking
one piece, then snapshotting and asserting the other.
The other three cases in this file passed unchanged on CI; only this
fourth one was racy.
* fix: don't commit local .claude worktrees / var state
These were accidentally added in ffe947706 by an over-broad git add -A.
Both paths are workspace-local and unrelated to this PR.
* Add docs for aceRegisterLineAttributes hook
Documents the new hook in both .md and .adoc client-side hook references.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix: correct source file path from .js to .ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Before, the hook always ignored the return values provided by the hook
functions. Now the hook functions can change the text by either
returning a string or setting `context.text` to the desired value.
Also drop the `styl` and `cls` context properties. They were never
documented and they were always null.
OK, first up, SOMEBODY *cough*analphabet*cough* screwed up the docs
by making them all use the wrong heading level. Not cool, guy. I
had to change them so they would compile right.
But anyway, now the docs will build into sexy-looking HTML and will
shortly be hosted on marktraceur.info.
Fixed the makefile to work properly.
Run:
* `make clean` for removing old doc-build(s)
* `make docs` for running new doc-build(s)