Skip to content

Commit 373c946

Browse files
pajomaclaude
andcommitted
docs(spec): add spec for TemplateEngine DRY consolidation (#211)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 25997ea commit 373c946

1 file changed

Lines changed: 76 additions & 0 deletions

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Spec: Consolidate Template and Date Replacement Logic (DRY) — #211
2+
3+
## Goal
4+
Extract duplicated `${variable}` template resolution into a single `TemplateEngine` service so that adding or changing a template variable requires editing exactly one place.
5+
6+
## Why now
7+
feat-210 (rich domain models) is in progress. Once its types land on `develop`, a `TemplateEngine` becomes a natural next refactoring step — the timing avoids double-churn on `src/model/`.
8+
9+
## In scope
10+
- Extract `replaceDateFormats` and `replaceDateTemplatesWithMomentsFormats` from `src/util/dates.ts` into a new `TemplateEngine` module.
11+
- Replace the two parallel switch/case blocks with a single central variable map (`TEMPLATE_VARIABLE_MAP`) that holds both the moment format string and resolution logic per variable.
12+
- Expose two public functions from the engine:
13+
- `resolveDate(template, date, locale?)` — replaces `${var}` with actual formatted values (replaces `replaceDateFormats`)
14+
- `toMomentFormat(template)` — replaces `${var}` with moment format tokens (replaces `replaceDateTemplatesWithMomentsFormats`)
15+
- Delete the duplicate implementation in `src/test/direct/path-parse-with-date.ts:124`.
16+
- Update all callers: `src/journal/paths.ts`, `src/vscode/conf.ts`, `src/features/sync/sync-daily-links.ts`.
17+
- Keep `replaceVariableValue` in `src/util/strings.ts` (generic key/value; not template-engine-specific).
18+
- Update barrel exports in `src/util/index.ts`.
19+
20+
## Out of scope
21+
- Changing the set of supported template variables (no new variables in this PR).
22+
- Replacing `replaceVariableValue` with the engine.
23+
- Any changes to `src/vscode/conf.ts` beyond updating the import path.
24+
- feat-210 rich domain model changes.
25+
26+
## Acceptance criteria
27+
1. `replaceDateFormats` and `replaceDateTemplatesWithMomentsFormats` no longer exist in `src/util/dates.ts`.
28+
2. Adding a new template variable requires editing only `TEMPLATE_VARIABLE_MAP` (one location).
29+
3. All existing tests pass without modification to test assertions.
30+
4. The duplicate in `src/test/direct/path-parse-with-date.ts` is removed; that file imports from the engine instead.
31+
5. `npm run compile` (or equivalent) succeeds.
32+
6. No behavior change — output of `resolveDate` matches the old `replaceDateFormats` output for all supported variables.
33+
34+
## Entities / contracts
35+
36+
### TEMPLATE_VARIABLE_MAP
37+
```typescript
38+
// Central map — the single source of truth
39+
interface TemplateVariableEntry {
40+
momentFormat: string; // used by toMomentFormat
41+
}
42+
const TEMPLATE_VARIABLE_MAP: Record<string, TemplateVariableEntry> = {
43+
year: { momentFormat: 'YYYY' },
44+
month: { momentFormat: 'MM' },
45+
day: { momentFormat: 'DD' },
46+
localTime: { momentFormat: 'LT' },
47+
localDate: { momentFormat: 'LL' },
48+
weekday: { momentFormat: 'dddd' },
49+
week: { momentFormat: 'w' }, // only in resolveDate currently; add to toMomentFormat for symmetry
50+
};
51+
```
52+
53+
### Public API (new module)
54+
```typescript
55+
export function resolveDate(template: string, date: Date, locale?: string): string
56+
export function toMomentFormat(template: string): string
57+
// regex stays module-private
58+
const TEMPLATE_VAR_REGEX = /\$\{(?:(year|month|day|localTime|localDate|weekday|week)|(d:[\s\S]+?))\}/g;
59+
```
60+
61+
### Module location — OPEN QUESTION
62+
Issue suggests `src/core/templates/engine.ts` (new `core` layer). No `src/core/` directory exists today. Alternative: `src/util/template-engine.ts` (fits existing structure; minimal disruption). **Preferred: `src/util/template-engine.ts`** unless the author wants to introduce the `core` layer for future domain-pure modules.
63+
64+
## Constraints
65+
- Moment.js is the only date library in use; stay with it.
66+
- No new runtime dependencies.
67+
- Must not break `src/test/direct/replace-variables-in-string.ts` (imports `replaceDateFormats` from `../../util/dates` — update import).
68+
69+
## Open questions
70+
1. `src/core/templates/engine.ts` vs `src/util/template-engine.ts`? The `core` layer would be a new architectural boundary. Is that intentional for #211 or a future concern?
71+
2. `week` variable is present in `replaceDateFormats` but absent from `replaceDateTemplatesWithMomentsFormats`. Intentional gap or bug? Should `toMomentFormat` also map `${week}``'w'`?
72+
73+
## Related issues
74+
- Blocks: none
75+
- Related: #210 (rich domain models — avoid double-churn; implement after feat-210 lands)
76+
- Related: #209 (domain module naming — completed; barrel keys already aligned)

0 commit comments

Comments
 (0)