feat(layer): add 'd' shortcut to toggle color mode#30
Merged
Conversation
Press 'd' to toggle between light and dark color modes. The shortcut is configurable via app.config.ts (docs.shortcuts.toggleColorMode) and can be disabled by setting it to an empty string. The handler bails out when: - the color mode is forced (colorMode.forced === true) - the keystroke originated from an editable element (<input>, <textarea>, <select>, [contenteditable]) - any modifier key (meta / ctrl / alt / shift) is pressed Reimplemented from upstream docus commit 61c36d03 (feat(layer): add d shortcut to toggle color mode (#1377)) using @vueuse/core's onKeyStroke instead of @nuxt/ui's defineShortcuts, since this project does not depend on @nuxt/ui. Refs: docs/docus-upstream-changes.md item #11
There was a problem hiding this comment.
Code Review
This pull request introduces keyboard shortcuts configuration and implementation for the documentation layer, specifically adding a shortcut (defaulting to 'd') to toggle between light and dark color modes. The feedback suggests explicitly importing computed from vue to improve IDE support and unit testing compatibility, and refining the isEditableTarget utility to traverse up the DOM tree so that non-HTMLElement targets (like SVGs) inside editable containers do not unexpectedly trigger the shortcut.
There was a problem hiding this comment.
No issues found across 5 files
Architecture diagram
sequenceDiagram
participant User as End User
participant Browser
participant Nuxt as Nuxt App
participant Vue as Vue Composition API
participant ColorMode as @nuxtjs/color-mode
participant DOM as DOM
Note over User,DOM: Color Mode Toggle via 'd' Key
User->>Browser: Presses 'd' key
Browser->>DOM: keydown event
DOM->>Vue: onKeyStroke listener (useDocsShortcuts.ts)
Vue->>Vue: Check isEditableTarget(event.target)
alt Editable element (input/textarea/contenteditable)
Vue->>Vue: Bail out - ignore shortcut
else Non-editable element
Vue->>Vue: Check modifier keys (meta/ctrl/alt/shift)
alt Modifier pressed
Vue->>Vue: Bail out
else No modifier
Vue->>Vue: Check colorMode.forced
alt forced === true
Vue->>Vue: Bail out
else not forced
Vue->>Vue: Read toggleColorModeShortcut from appConfig
alt Shortcut empty
Vue->>Vue: Bail out
else Non-empty (default 'd')
Vue->>Vue: Read current colorMode.value
alt dark currently
Vue->>ColorMode: Set preference = 'light'
else light currently
Vue->>ColorMode: Set preference = 'dark'
end
ColorMode->>DOM: Apply CSS class change (light/dark)
ColorMode->>Browser: Persist preference (cookie/localStorage)
Browser-->>User: Visual theme toggled
end
end
end
end
Note over Nuxt,Vue: Initialization (client-only)
Nuxt->>Vue: Setup plugin (shortcuts.client.ts)
Vue->>Vue: Call useDocsShortcuts()
Vue->>Vue: Read appConfig.docs.shortcuts.toggleColorMode
alt toggleColorMode defined
Vue->>Vue: Register onKeyStroke listener
else undefined
Vue->>Vue: Use default 'd'
end
Deploying docs-please with
|
| Latest commit: |
e8b70d2
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://78768df7.docs-please.pages.dev |
| Branch Preview URL: | https://feat-layer-toggle-color-mode.docs-please.pages.dev |
Applies feedback from gemini-code-assist review: - Explicitly import `computed` from vue for IDE/test environments - Traverse up the DOM in `isEditableTarget` so non-HTMLElement targets (SVGElement, MathMLElement) inside contenteditable containers are still treated as editable and do not trigger the shortcut
|
amondnet
added a commit
that referenced
this pull request
May 28, 2026
* feat(layer): add Vercel markdown-rewrite module
Adds a Nuxt module that injects Vercel build-output rewrite rules so
that AI agents (anything sending `Accept: text/markdown` or
`User-Agent: curl/*`) get served raw markdown instead of the SPA shell.
Behaviour:
- No-op on every non-Vercel preset (matches `vercel`, `vercel-edge`,
`vercel-static`, etc. via `preset.startsWith('vercel')`).
- On Vercel: read `<output.publicDir>/../config.json`, validate that
`llms.txt` was emitted, and unshift route pairs onto `routes` so
they fire before the SPA fallback.
- Rules:
- `/` -> `/llms.txt`
- `/<locale>` -> `/llms.txt` (per `runtimeConfig.public.i18n.locales`)
- `/<page>` -> `/raw<page>.md` for every `/raw/...md` link found
in `llms.txt`
- Vercel's `has` array is AND-ed, so OR semantics between the
`Accept` and `User-Agent` matchers require emitting two rules per
`src` -> `dest` pair.
- Locale codes are regex-escaped before being joined into the
alternation so exotic codes can't break the pattern.
Ports upstream docus commits `6fd8686b` and `9ceafe6f` -- see
`docs/docus-upstream-changes.md` item #9.
Verification:
- `bun lint` -> clean
- `bun typecheck` -> no new errors in `markdown-rewrite.ts`
- `NITRO_PRESET=vercel bun --filter @pleaseai/docs-site build`
injects two routes (homepage / Accept + User-Agent) into
`.vercel/output/config.json`.
- Default (cloudflare) build is unchanged; module bails silently.
* fix(layer): apply review suggestions
Apply review feedback from cubic-dev-ai and gemini-code-assist on
the markdown-rewrite module:
- Read locale config from `nuxt.options.i18n` instead of
`runtimeConfig.public.i18n` (matching the pattern used by the
`nitro:config` hook in nuxt.config.ts). The i18n module does
not always populate `runtimeConfig.public.i18n`, so the previous
source could silently miss locale routes. (cubic)
- Decode the URL pathname with `decodeURIComponent` so that paths
with URL-encoded characters (e.g. `%20`) match Vercel's router,
which compares against decoded request pathnames. (gemini)
- Allow an optional trailing slash on docs page route patterns
(`/?$` instead of `$`) so requests like
`/en/getting-started/installation/` are matched consistently
with the per-locale homepage routes. (cubic, gemini)
* Merge branch 'main' into worktree-agent-a1a3a89e87faf9e6d
Resolve modules-array conflict in packages/layer/nuxt.config.ts by
keeping both new module registrations from #29/#30/#31 and this PR's
markdown-rewrite module.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



개요
발송 마법사(Step1~5Controller)를 선택 단계화·건너뛰기 가능한 플로우로 재구성합니다. (Epic #107, 작업분해 E2-2-1)
변경 요지
SendStepenum 도입 — 정수step가드(1~5) 대체Step2_5Controller(PDF),Step2_7Controller(등기자료),StepPhotoController(사진)step_2_5.html/step_2_7.htmlmock 의 라우팅 채움 (DESIGN ONLY → routed)핵심 수용 기준 (이슈 #112 본문)
Spec / Plan
.please/docs/tracks/active/send-flow-stepwise-20260528/spec.md.please/docs/tracks/active/send-flow-stepwise-20260528/plan.md영향 모듈
mail-talk-web(SSR 컨트롤러·템플릿·서비스)mail-talk-app(Flutter WebView 브릿지 — 회귀 검증만)주의사항
Constants.AES_KEY/AES_IV/channelcallHandler 변경 0건. 본 PR 의 모든 reviewer 는git diff로 확인 필수.Refs
Summary by cubic
Added a keyboard shortcut to toggle between light and dark mode. Press 'd' to switch. Configure via
docs.shortcuts.toggleColorModeinapp.config.ts(set to empty string to disable).useDocsShortcutscomposable using@vueuse/coreonKeyStroke, installed viashortcuts.client.ts.'d'inapp.config.tsandmodules/config.ts; option schema innuxt.schema.ts.<input>,<textarea>,<select>,[contenteditable]).Written for commit e8b70d2. Summary will update on new commits.
Verification Checklist
git diff origin/main -- mail-talk-app/lib/controller/letter/letter_step1_web_view_controller.dart—AES_KEY/AES_IV/channel/callHandler변경 0건git diff origin/main -- mail-talk-app/lib/core/setting/constants.dart(또는 동등) —AES_KEY/AES_IV상수 변경 0건Step5ControllerTest기존 시나리오가 enum 전환 후에도 통과 (시그니처만 변경, 의미 보존)Step2_5Controller,Step2_7Controller,StepPhotoController) 각각 MockMvc 권한/소유/UHL 가드 케이스 보유 (NewStepControllersTest)Step4Controller콘텐츠 0건 차단 케이스(AC-9) 포함 (NewStepControllersTest.Step4Tests)step_1.html/step_2.html/step_photo.html에 "건너뛰기" 버튼 + 다음 단계 URL 정확"발송할 콘텐츠를 한 가지 이상 선택해 주세요."moveStep3WithSave가/editor/step_photo로 redirect (편지작성 다음이 사진 단계)Known Limitations / Follow-ups
Step1Controller가defaultModelSetter를 호출하지 않음 (pre-existing 설계, UHL 가드 미적용) — 별도 chore 권장moveStep3WithSave함수명이 레거시 명명 잔재 — 후속 chore 에서moveStepPhotoWithSave등으로 rename 가능