Skip to content

Commit 49e95c6

Browse files
authored
Merge pull request #204 from pajoma/docs/189-docs-sync-1.1.0
Docs/189 docs sync 1.1.0
2 parents 1cee3d6 + 29ecf40 commit 49e95c6

4 files changed

Lines changed: 212 additions & 0 deletions

File tree

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Plan: Deduplicate week-navigation logic (R3) — #200
2+
3+
**Reference spec:** [docs/specs/2026-05-17-200-refactor-week-nav-dedup.md](../specs/2026-05-17-200-refactor-week-nav-dedup.md)
4+
5+
## Approach
6+
7+
Surgical extraction: move the 6-line block into a new exported function and replace both call sites. No behaviour change. All existing tests are regression guards — they run unchanged and must stay green. New unit tests cover the extracted function directly, without going through the full command layer.
8+
9+
Trade-off: importing `Input` from `'../model'` in `navigation.ts` adds a domain→model dependency that wasn't there before. This is acceptable; `navigation.ts` already returns `Date` objects and `Anchor` structs that the command layer converts to `Input`. Returning an `Input` directly shortens the command glue to two lines.
10+
11+
## Steps
12+
13+
### 1 — Add imports to `src/actions/navigation.ts`
14+
15+
Add at top of file:
16+
17+
```typescript
18+
import { getWeekFromURIAndConfig } from '../util/paths';
19+
import { Input } from '../model';
20+
import moment = require("moment");
21+
```
22+
23+
**Why:** the new function delegates to `getWeekFromURIAndConfig` (already used by the two command files) and returns an `Input` so callers need zero additional allocation.
24+
25+
### 2 — Add `getAdjacentWeekInput` to `src/actions/navigation.ts`
26+
27+
Export the following function (full body in spec):
28+
29+
```typescript
30+
export async function getAdjacentWeekInput(
31+
editor: vscode.TextEditor | undefined,
32+
ctrl: Ctrl,
33+
direction: Direction
34+
): Promise<Input | undefined>
35+
```
36+
37+
Implementation detail:
38+
- Guard: if no editorreturn `undefined`.
39+
- Call `getWeekFromURIAndConfig(editor.document.uri, ctrl.config)`.
40+
- If no matchreturn `undefined` (caller falls through to daily-entry navigation).
41+
- Compute adjacent week with `moment().week(weekInfo.week).weekYear(weekInfo.year)[direction === 'previous' ? 'subtract' : 'add'](1, 'week')`.
42+
- Set `input.week = adj.week()` and return.
43+
44+
**Why:** ternary on `direction` eliminates the only difference between the two duplicated blocks.
45+
46+
### 3Refactor `src/provider/commands/open-previous-entry.ts`
47+
48+
- Remove `import { getWeekFromURIAndConfig } from '../../util/paths'`.
49+
- Remove `import moment = require("moment")`.
50+
- Replace the duplicated 6-line block with:
51+
52+
```typescript
53+
const weekInput = await getAdjacentWeekInput(editor, this.ctrl, 'previous');
54+
if (weekInput) {
55+
await this.execute(weekInput);
56+
return;
57+
}
58+
```
59+
60+
Add `getAdjacentWeekInput` to the import from `'../../actions/navigation'`.
61+
62+
**Why:** removes the dead imports, leaves command as pure glue.
63+
64+
### 4Refactor `src/provider/commands/open-next-entry.ts`
65+
66+
Identical to Step 3, but `direction` = `'next'`.
67+
68+
### 5Add unit tests
69+
70+
Add a new `suite('getAdjacentWeekInput')` block in `src/test/suite/commands-prev-next.test.ts`, under the existing `helper layer with seeded base` suite. Scenarios:
71+
72+
| # | Name | Setup | Expected |
73+
|---|------|-------|----------|
74+
| T1 | no editor | `editor = undefined` | returns `undefined` |
75+
| T2 | non-weekly file | open a day entry `${tmpBase}/2026/05/16.md` as active | returns `undefined` |
76+
| T3 | weekly file + next | create and open `${tmpBase}/2026/w20.md`; call with `'next'` | `input.week === 21` |
77+
| T4 | weekly file + previous | same weekly file; call with `'previous'` | `input.week === 19` |
78+
79+
Seed weekly files using the same `vscode.workspace.fs.createDirectory` + `writeFile` pattern as `seedEntry`. Weekly file naming follows the default pattern: `${year}/w${week}.md`.
80+
81+
**Why:** tests target the pure extracted logic, not the full command stackfast and focused.
82+
83+
### 6Compile and test
84+
85+
```bash
86+
npm run compile-tests && npm test
87+
```
88+
89+
Full `npm run check` must pass (lint + compile + test).
90+
91+
## Test scenarios summary
92+
93+
- **T1T2** (non-weekly): guard conditions; confirm function does not return an Input for inapplicable files.
94+
- **T3–T4** (weekly): confirm direction-to-add/subtract mapping and that the returned `Input.week` is correct.
95+
- **Regression**: all 16 existing navigation tests in `commands-prev-next.test.ts` must pass unchanged — they cover the command-layer behaviour end-to-end.
96+
97+
## Dependencies
98+
99+
None. Work is self-contained within this repo and does not require any other PR to land first.
100+
101+
## Risk
102+
103+
**Week-boundary crossing (week 52/53week 1):** pre-existing moment behaviour, not changed by this refactoring. Covered by the fact that moment's `.weekYear()` handles it correctly; no test added here since behaviour is unchanged.
104+
105+
**Import cycle:** `navigation.ts``../model`no back-edge into `navigation.ts`. No cycle introduced.
106+
107+
## Rollback
108+
109+
`git revert <commit>` on the single implementation commit. No data migrations, no schema changes.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Spec: Deduplicate week-navigation logic (R3) — #200
2+
3+
## Goal
4+
5+
Extract the identical week-navigation block from `OpenNextEntryCommand` and `OpenPreviousEntryCommand` into a single shared function in `src/actions/navigation.ts`.
6+
7+
## Why now
8+
9+
The block was added to both commands in the same PR (navigation 1.1.0 work). It is not yet stable, so the duplication has not yet masked a divergence bug — but the longer it lives in two places the more likely a future fix lands in only one.
10+
11+
## In scope
12+
13+
- New exported function `getAdjacentWeekInput(editor, ctrl, direction)` in `src/actions/navigation.ts`.
14+
- Replace the 6-line duplicated block in `open-next-entry.ts` and `open-previous-entry.ts` with a call to the new function.
15+
- Unit test for `getAdjacentWeekInput` covering: weekly file → correct week returned; non-weekly file → `undefined` returned; direction `next` adds one week; direction `previous` subtracts one week.
16+
17+
## Out of scope
18+
19+
- Any change to the week-number/year-crossing logic (pre-existing moment behaviour).
20+
- `getWeekFromURIAndConfig` itself (stays in `paths.ts`).
21+
- UI or command registration changes.
22+
23+
## Acceptance criteria
24+
25+
1. No duplicated week-navigation code remains in the command files.
26+
2. Both commands behave identically to before — existing navigation tests pass unchanged.
27+
3. New unit tests for `getAdjacentWeekInput` green.
28+
4. `npm run check` (lint + compile + test) passes.
29+
30+
## New function contract
31+
32+
```typescript
33+
// src/actions/navigation.ts
34+
export async function getAdjacentWeekInput(
35+
editor: vscode.TextEditor | undefined,
36+
ctrl: Ctrl,
37+
direction: Direction // 'previous' | 'next'
38+
): Promise<J.Model.Input | undefined>
39+
```
40+
41+
Returns a populated `Input` (with `input.week` set to the adjacent week number) when the active file is a weekly note, `undefined` otherwise (callers proceed to daily-entry navigation).
42+
43+
**Internals** (replaces the duplicated block):
44+
45+
```typescript
46+
if (!editor) return undefined;
47+
const weekInfo = await getWeekFromURIAndConfig(editor.document.uri, ctrl.config);
48+
if (!weekInfo) return undefined;
49+
const adj = moment()
50+
.week(weekInfo.week)
51+
.weekYear(weekInfo.year)
52+
[direction === 'previous' ? 'subtract' : 'add'](1, 'week');
53+
const input = new J.Model.Input();
54+
input.week = adj.week();
55+
return input;
56+
```
57+
58+
## Constraints
59+
60+
- Keep `moment` import in `navigation.ts` (already present).
61+
- Must remain testable without a live `vscode.TextEditor`the non-`undefined` code path reaches `getWeekFromURIAndConfig` which calls `config` methods; spy/stub those in tests as done elsewhere.
62+
63+
## Open questions
64+
65+
None.
66+
67+
## Related issues
68+
69+
- Spawned from the navigation work tracked in #144 / docs-sync #189.

l10n/bundle.l10n.de.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"Today": "Heute",
3+
"Tomorrow": "Morgen",
4+
"Select entry": "Eintrag auswählen",
5+
"Select/Create a note": "Notiz auswählen oder erstellen",
6+
"Jump to today's entry.": "Zum Eintrag für heute wechseln.",
7+
"Jump to tomorrow's entry.": "Zum Eintrag für morgen wechseln.",
8+
"Select from the last journal entries.": "Wählen Sie aus den letzten Journaleinträgen aus.",
9+
"Create a new note or select from recently created or updated notes.": "Erstellen Sie eine neue Notiz oder wählen Sie aus den letzten Notizen aus.",
10+
"Open notes for week {week}": "Notizen für Kalenderwoche {week} öffnen",
11+
"Add task to entry for week {week}": "Aufgabe zum Eintrag für Woche {week} hinzufügen",
12+
"Add task to entry {day}": "Aufgabe zum Eintrag {day} hinzufügen",
13+
"Add memo to entry {day}": "Memo zum Eintrag {day} hinzufügen",
14+
"Create or open entry {day}": "Eintrag {day} erstellen oder öffnen",
15+
"[from] dddd": "[vom] dddd",
16+
"[from] ll": "[von] ll",
17+
"No earlier journal entry found.": "Kein früherer Journaleintrag gefunden.",
18+
"No later journal entry found.": "Kein späterer Journaleintrag gefunden."
19+
}

package.nls.de.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"command.category.journal": "Journal",
3+
"command.journal.today.title": "Heute öffnen",
4+
"command.journal.yesterday.title": "Gestern öffnen",
5+
"command.journal.tomorrow.title": "Morgen öffnen",
6+
"command.journal.memo.title": "Schnellmemo eingeben",
7+
"command.journal.note.title": "Neue Journalnotiz",
8+
"command.journal.printTime.title": "Uhrzeit einfügen",
9+
"command.journal.printDuration.title": "Differenz zwischen ausgewählten Zeiten einfügen",
10+
"command.journal.printSum.title": "Summe der ausgewählten Zahlen einfügen",
11+
"command.journal.day.title": "Bestimmten Tag öffnen",
12+
"command.journal.open.title": "Journal öffnen",
13+
"command.journal.openPrevious.title": "Vorherigen Journaleintrag öffnen",
14+
"command.journal.openNext.title": "Nächsten Journaleintrag öffnen"
15+
}

0 commit comments

Comments
 (0)