Skip to content

Commit fe1437e

Browse files
committed
plan 89: address Copilot review on PR #147
- Renumber MDS036 → MDS037 for the toc rule. Plan 51 shipped first and took MDS036 for max-section-length; MDS034 stays reserved for plan 86. - Replace the hand-rolled slug algorithm with a directive to move the existing slugify / duplicate-disambiguation logic out of crossfilereferenceintegrity into a shared helper (internal/mdtext) that both rules call. Drops incorrect goldmark-meta reference. - Drop fictitious <?listindent?> directive reference; describe indentation as MDS016 list-indent.spaces (default 2). - Correct MDS015 interaction note: MDS015 only covers fenced code blocks, so blank-line padding around <?toc?> is MDS035 Fix's responsibility. - Unify the canonical empty-body form as <?toc?>\n<?/toc?> throughout design, tasks, and acceptance criteria. - Add task 1 (move slug helper to shared package) and renumber downstream tasks. - Grammar pass: "GitHub-style" consistently. Follow-up to PR #147 (already merged).
1 parent 7958dcd commit fe1437e

1 file changed

Lines changed: 72 additions & 48 deletions

File tree

plan/89_toc-generator-directive.md

Lines changed: 72 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ summary: >-
66
Add a `<?toc?>...<?/toc?>` generated-section
77
directive that emits a nested list of the
88
current document's headings linked to their
9-
anchors (MDS036). Upgrade MDS035 (plan 88) to
9+
anchors (MDS037). Upgrade MDS035 (plan 88) to
1010
auto-fix each detected renderer-specific TOC
1111
token by replacing it with a `<?toc?>` block,
1212
which the directive then regenerates on
@@ -85,19 +85,31 @@ produces with default settings.
8585
### Generated content
8686

8787
A nested unordered list, one item per heading
88-
in source order. Each item links to a
89-
GitHub-flavor slug of the heading text:
90-
91-
- Lowercase the heading plain text.
92-
- Replace spaces with `-`.
93-
- Strip characters outside `[a-z0-9-_]`.
94-
- Disambiguate repeats by appending `-1`, `-2`, …
95-
in source order (matching goldmark-meta /
96-
GitHub's behavior).
97-
98-
Indentation is `<?listindent?>`-aware: use the
99-
same per-level indent as MDS016 (two spaces by
100-
default).
88+
in source order. Each item links to the same
89+
heading anchor mdsmith already computes for
90+
cross-file heading references.
91+
92+
Do not define a TOC-specific slug algorithm.
93+
Reuse the `slugify` function and
94+
duplicate-disambiguation logic currently in
95+
[`internal/rules/crossfilereferenceintegrity/rule.go`][cfri]
96+
(around lines 349 and 389). Move that helper
97+
into a shared package — `internal/mdtext/` is
98+
the natural home — and have both rules call
99+
the shared code so anchors stay consistent
100+
across rules. Repeated headings must receive
101+
the same `-1`, `-2`, … suffixes in source
102+
order as the existing reference-integrity
103+
rule.
104+
105+
[cfri]: ../internal/rules/crossfilereferenceintegrity/rule.go
106+
107+
Indentation uses the same per-level indent as
108+
the MDS016 `list-indent` rule (config key
109+
`list-indent.spaces`, default 2). There is no
110+
`<?listindent?>` directive; indentation is a
111+
property of the emitted output, not a
112+
configurable parameter of `<?toc?>`.
101113

102114
List items respect the heading structure, not
103115
the raw level. Given H2 → H4 → H2, the tree is:
@@ -110,9 +122,14 @@ the raw level. Given H2 → H4 → H2, the tree is:
110122

111123
…not a flat list keyed on absolute level.
112124

113-
### Rule: MDS036 (toc)
125+
### Rule: MDS037 (toc)
126+
127+
Note on numbering: plan 89 originally claimed
128+
MDS036, but plan 51 shipped first and took
129+
MDS036 for `max-section-length`. MDS034 remains
130+
reserved for plan 86. Plan 89 takes MDS037.
114131

115-
- ID: `MDS036`
132+
- ID: `MDS037`
116133
- Name: `toc`
117134
- Category: `meta`
118135
- Default: enabled (generated sections are
@@ -135,25 +152,25 @@ MDS035 becomes a `FixableRule`. On `Fix`, for
135152
each matched directive line inside a paragraph:
136153

137154
- `[TOC]` (unresolved), `[[_TOC_]]`, `[[toc]]`,
138-
`${toc}` → replace the single line with:
155+
`${toc}` → replace the single line with the
156+
canonical empty generated-section block:
139157

140158
```text
141-
<?toc
142-
?>
159+
<?toc?>
143160
<?/toc?>
144161
```
145162

146-
The empty YAML body means "use defaults". A
147-
trailing newline separator is inserted if the
148-
surrounding paragraph would otherwise fuse
149-
the directive into adjacent text.
163+
The empty body means "use defaults". MDS035's
164+
Fix must also insert surrounding blank lines
165+
when the directive would otherwise fuse into
166+
adjacent paragraph text.
150167

151168
- `[TOC]` with a matching link reference
152169
definition → leave untouched (already
153170
suppressed by Check; must stay out of Fix).
154171

155172
The Fix output is plain `<?toc?>...<?/toc?>`
156-
with an **empty** body. MDS036 runs in a
173+
with an **empty** body. MDS037 runs in a
157174
subsequent pass of the same `mdsmith fix`
158175
invocation (mdsmith already supports
159176
multi-pass fix, used by MDS019/MDS021) and
@@ -165,10 +182,11 @@ and fall back only if needed.
165182

166183
### Interaction with existing rules
167184

168-
- MDS015 (blank line around fenced code /
169-
generated sections): the Fix output adds the
170-
required blank-line padding around the
171-
inserted block.
185+
- MDS015 only enforces blank lines around
186+
fenced code blocks, not generated-section
187+
markers. Blank-line padding around inserted
188+
`<?toc?>` blocks is MDS035's responsibility
189+
at Fix time, not MDS015's.
172190
- MDS020 (required-structure): no change; TOC
173191
blocks are not a required section.
174192
- MDS019 (catalog), MDS021 (include): orthogonal
@@ -191,39 +209,45 @@ and fall back only if needed.
191209

192210
## Tasks
193211

194-
1. Create the `<?toc?>` directive in a new
212+
1. Move `slugify` and the duplicate-anchor
213+
counter from
214+
`internal/rules/crossfilereferenceintegrity/`
215+
into a shared helper in `internal/mdtext/`.
216+
Update the reference-integrity rule to call
217+
the shared helper. No behavior change.
218+
2. Create the `<?toc?>` directive in a new
195219
`internal/rules/toc/` package using the
196220
shared `internal/archetype/gensection.Engine`
197-
(same engine as `catalog`). Add a slug
198-
helper in `internal/mdtext/` or the toc
199-
package. Register as MDS036 in category
200-
`meta`, enabled by default, `FixableRule`.
201-
2. Add MDS036 fixtures under
202-
`internal/rules/MDS036-toc/`: `good/` with a
221+
(same engine as `catalog`) and the shared
222+
slug helper from task 1. Register as MDS037
223+
in category `meta`, enabled by default,
224+
`FixableRule`.
225+
3. Add MDS037 fixtures under
226+
`internal/rules/MDS037-toc/`: `good/` with a
203227
correct body, `bad/` with a stale body to
204228
verify Check, `fixed/` with the expected
205229
output after Fix. Cover default parameters,
206230
custom `min-level`/`max-level`, single-level
207231
docs, and deeply nested structures.
208-
3. Upgrade MDS035 to `FixableRule`: replace
209-
matched directive lines with
210-
`<?toc?>\n<?/toc?>` blocks preserving
211-
surrounding blank lines; leave `[TOC]`
212-
untouched when a link-ref definition
232+
4. Upgrade MDS035 to `FixableRule`: replace
233+
matched directive lines with the canonical
234+
empty block `<?toc?>\n<?/toc?>`, inserting
235+
blank lines above and below as needed; leave
236+
`[TOC]` untouched when a link-ref definition
213237
suppresses Check; add `fixed/` fixtures for
214238
each of the four variants.
215-
4. Update MDS035's diagnostic message to point
216-
at `<?toc?>` (MDS036) instead of
239+
5. Update MDS035's diagnostic message to point
240+
at `<?toc?>` (MDS037) instead of
217241
`<?catalog?>` (MDS019); wording:
218-
`unsupported TOC directive \`{token}\`; use \`<?toc?>\` (MDS036)`
219-
5. Update MDS035 README (message + examples),
242+
`unsupported TOC directive \`{token}\`; use \`<?toc?>\` (MDS037)`
243+
6. Update MDS035 README (message + examples),
220244
plan 88 status/deviation note, and the
221245
renderer-portability section in
222246
[docs/background/markdown-linters.md][lnt].
223-
6. Update the generated-section archetype doc
247+
7. Update the generated-section archetype doc
224248
to list `toc` alongside `catalog` and
225249
`include`.
226-
7. Verify multi-pass `mdsmith fix` end-to-end:
250+
8. Verify multi-pass `mdsmith fix` end-to-end:
227251
starting from a document containing `[TOC]`,
228252
a single `fix` run must yield a populated
229253
`<?toc?>...<?/toc?>` block. Add an
@@ -240,7 +264,7 @@ and fall back only if needed.
240264
- [ ] `min-level` and `max-level` parameters
241265
gate which headings appear
242266
- [ ] `<?toc?>` with a stale body produces
243-
an MDS036 diagnostic on `check`
267+
an MDS037 diagnostic on `check`
244268
- [ ] MDS035 `fix` rewrites `[TOC]`,
245269
`[[_TOC_]]`, `[[toc]]`, and `${toc}`
246270
on their own line to
@@ -254,7 +278,7 @@ and fall back only if needed.
254278
- [ ] Merge driver regenerates `<?toc?>`
255279
bodies on conflict, same as `<?catalog?>`
256280
- [ ] MDS035 diagnostic message names
257-
`<?toc?>` (MDS036) as the replacement
281+
`<?toc?>` (MDS037) as the replacement
258282
- [ ] All tests pass: `go test ./...`
259283
- [ ] `go tool golangci-lint run` reports
260284
no issues

0 commit comments

Comments
 (0)