` containing `` `text` ``
- For `code` tags: skip if parent is `pre`
3. **`convertBlockCodeToMarkdown($, tags: string[])`**
- For `pre>code`: get language from `class`, get `.text()` from code, replaceWith `` containing `` ```lang\ntext\n``` ``
- For `emu-eqn` block: get `.text()`, replaceWith `` containing `` ```\ntext\n``` ``
4. **`convertGrammarToMarkdown($, selector: string)`**
- Walk inner tags (emu-nt, emu-t, emu-rhs, emu-geq), build text representation
- ReplaceWith `` containing `` ```bnf\ntext\n``` ``
5. **`convertListsToMarkdown($, ordered: string[], unordered: string[])`**
- For each `ol`/`ul`: recursive function `listToMarkdown(elem, depth, isOrdered)`
- Process `li` children, add `1. ` / `- ` prefix with indentation
- ReplaceWith `` containing markdown text
6. **`formatForIngestion($, config?)`** — orchestrator, calls all in order
### Modify existing functions
- **`convertTablesToMarkdown($)`**: No changes needed. `.text()` already extracts markdown text from pre-processed `` elements.
### Modify `setup/ingest.ts`
- Replace individual calls to `convertTablesToMarkdown($)` and `addNewlinesAfterBlocks($)` with single call to `formatForIngestion($)`.
- The child `emu-clause` replacement and deep nesting cleanup remain as-is (before `formatForIngestion`).
Updated call order in `buildSpecDocuments()`:
```typescript
// 1. Child clause replacement (existing)
$section.children("emu-clause").each(...);
$section.find("emu-clause").remove();
// 2. All formatting transformations (single call)
formatForIngestion($);
```
## Files to Modify
1. **`setup/utils/formatHTMLForIngestion.ts`** — add config interface, 5 new functions, orchestrating function
2. **`setup/ingest.ts`** — replace individual calls with `formatForIngestion($)` call
3. **New test file: `setup/utils/formatHTMLForIngestion.test.ts`** — unit tests for each transformation
No new dependencies. Cheerio only.
## Verification
1. **Unit tests**: Write tests for each transformation with sample HTML snippets from the spec:
- `emu-xref a` → markdown link
- `var`/`emu-val`/`emu-const` → inline code
- `pre>code` → fenced code
- `emu-grammar` → fenced bnf
- `ol`/`ul` with nesting → markdown lists
- `table` → markdown table (with links inside cells preserved)
- Full pipeline via `formatForIngestion`
2. **Manual verification**: Run `bun run setup/ingest.ts` and inspect output chunks for correct markdown syntax
3. **Run lint/typecheck**: `bun run lint` and `bun run typecheck` (if available)