apex-ruby 1.0.18 → 1.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +17 -3
  3. data/ext/apex_ext/apex_ext.c +260 -91
  4. data/ext/apex_ext/apex_src/CHANGELOG.md +440 -0
  5. data/ext/apex_ext/apex_src/CMakeLists.txt +15 -1
  6. data/ext/apex_ext/apex_src/Formula/apex.rb +7 -2
  7. data/ext/apex_ext/apex_src/Package.swift +15 -4
  8. data/ext/apex_ext/apex_src/README.md +94 -35
  9. data/ext/apex_ext/apex_src/VERSION +1 -1
  10. data/ext/apex_ext/apex_src/apex-debug.log +4 -0
  11. data/ext/apex_ext/apex_src/apex.code-workspace +38 -0
  12. data/ext/apex_ext/apex_src/apex.taskpaper +12 -0
  13. data/ext/apex_ext/apex_src/apex_deflist_debug.log +25 -0
  14. data/ext/apex_ext/apex_src/buildnotes.md +1435 -0
  15. data/ext/apex_ext/apex_src/cli/main.c +262 -33
  16. data/ext/apex_ext/apex_src/debug.log +7 -0
  17. data/ext/apex_ext/apex_src/docs/CITATIONS_EXAMPLES.md +274 -0
  18. data/ext/apex_ext/apex_src/docs/CITATIONS_IMPLEMENTATION_PLAN.md +749 -0
  19. data/ext/apex_ext/apex_src/docs/CITATIONS_PLAN.md +744 -0
  20. data/ext/apex_ext/apex_src/docs/INDEX_IMPLEMENTATION_ANALYSIS.md +382 -0
  21. data/ext/apex_ext/apex_src/docs/plans/2025-02-27-man-page-output-implementation.md +351 -0
  22. data/ext/apex_ext/apex_src/docs/superpowers/plans/2026-07-12-toc-output-format.md +745 -0
  23. data/ext/apex_ext/apex_src/docs/superpowers/plans/2026-07-18-bear-image-attributes.md +829 -0
  24. data/ext/apex_ext/apex_src/docs/superpowers/plans/2026-07-19-apex-node-npm.md +1148 -0
  25. data/ext/apex_ext/apex_src/docs/superpowers/specs/2026-07-12-toc-output-format-design.md +161 -0
  26. data/ext/apex_ext/apex_src/docs/superpowers/specs/2026-07-18-bear-image-attributes-design.md +184 -0
  27. data/ext/apex_ext/apex_src/docs/superpowers/specs/2026-07-19-apex-node-npm-design.md +211 -0
  28. data/ext/apex_ext/apex_src/documentation/app-settings-table.md +67 -0
  29. data/ext/apex_ext/apex_src/documentation/app-transformed/Citations.md +340 -0
  30. data/ext/apex_ext/apex_src/documentation/app-transformed/Credits.md +11 -0
  31. data/ext/apex_ext/apex_src/documentation/app-transformed/Header-IDs.md +234 -0
  32. data/ext/apex_ext/apex_src/documentation/app-transformed/Inline-Attribute-Lists.md +516 -0
  33. data/ext/apex_ext/apex_src/documentation/app-transformed/Metadata-Transforms.md +461 -0
  34. data/ext/apex_ext/apex_src/documentation/app-transformed/Modes.md +193 -0
  35. data/ext/apex_ext/apex_src/documentation/app-transformed/Multi-File-Documents.md +201 -0
  36. data/ext/apex_ext/apex_src/documentation/app-transformed/Plugins.md +678 -0
  37. data/ext/apex_ext/apex_src/documentation/app-transformed/Syntax.md +1367 -0
  38. data/ext/apex_ext/apex_src/documentation/docsets/Apex Command Line Options.cheatsheet.txt +6 -0
  39. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/C-API.html +774 -300
  40. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Callouts.html +1194 -0
  41. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Citations.html +416 -216
  42. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Command-Line-Options.html +3544 -1094
  43. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Configuration.html +371 -97
  44. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Credits.html +153 -23
  45. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Examples.html +358 -124
  46. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Filters.html +1656 -0
  47. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Generating-Man-Pages.html +1226 -0
  48. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Getting-Started.html +201 -56
  49. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Header-IDs.html +279 -109
  50. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Home.html +200 -53
  51. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Indices.html +2327 -0
  52. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Inline-Attribute-Lists.html +690 -271
  53. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Installation.html +201 -55
  54. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Limitations-and-Roadmap.html +238 -68
  55. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Metadata-Transforms.html +421 -221
  56. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Modes.html +340 -78
  57. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Multi-File-Documents.html +251 -86
  58. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Multi-Format-Images.html +1362 -0
  59. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Pandoc-Integration.html +277 -90
  60. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Plugins.html +673 -346
  61. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Quarto-Mode.html +1405 -0
  62. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Rendering-Markdown-In-Terminal.html +1902 -0
  63. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Syntax.html +1939 -1698
  64. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Tables.html +1781 -0
  65. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Troubleshooting.html +315 -140
  66. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Usage.html +307 -113
  67. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Using-Apex-with-Jekyll.html +1132 -0
  68. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Writing-Tests.html +1754 -0
  69. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Xcode-Integration.html +872 -376
  70. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/docSet.dsidx +0 -0
  71. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/optimizedIndex.dsidx +0 -0
  72. data/ext/apex_ext/apex_src/documentation/html/apex-app-docs.html +8746 -0
  73. data/ext/apex_ext/apex_src/documentation/shared_styles.css +20 -15
  74. data/ext/apex_ext/apex_src/documentation/transform_for_app.md +55 -0
  75. data/ext/apex_ext/apex_src/escaping-repro.md +103 -0
  76. data/ext/apex_ext/apex_src/examples/quick-actions/Markdown to RTF.workflow/Contents/Info.plist +8 -0
  77. data/ext/apex_ext/apex_src/examples/quick-actions/Markdown to RTF.workflow/Contents/QuickLook/Preview.png +0 -0
  78. data/ext/apex_ext/apex_src/examples/quick-actions/Markdown to RTF.workflow/Contents/document.wflow +547 -0
  79. data/ext/apex_ext/apex_src/examples/quick-actions/Markdown-to-RTF.workflow.zip +0 -0
  80. data/ext/apex_ext/apex_src/examples/quick-actions/README.md +33 -0
  81. data/ext/apex_ext/apex_src/include/apex/apex.h +92 -6
  82. data/ext/apex_ext/apex_src/include/apex/ast_rtf.h +23 -0
  83. data/ext/apex_ext/apex_src/include/apex/ast_terminal.h +6 -0
  84. data/ext/apex_ext/apex_src/include/apex/module.modulemap +5 -0
  85. data/ext/apex_ext/apex_src/include/apex/plugins.h +105 -0
  86. data/ext/apex_ext/apex_src/include/apexc.h +1 -0
  87. data/ext/apex_ext/apex_src/man/apex.1 +82 -78
  88. data/ext/apex_ext/apex_src/man/apex.1.md +81 -4
  89. data/ext/apex_ext/apex_src/objc/Apex.swift +73 -0
  90. data/ext/apex_ext/apex_src/objc/ApexPlugins.swift +79 -0
  91. data/ext/apex_ext/apex_src/objc/NSString+Apex.h +83 -5
  92. data/ext/apex_ext/apex_src/objc/NSString+Apex.m +244 -1
  93. data/ext/apex_ext/apex_src/objc/NSString+ApexPlugins.h +76 -0
  94. data/ext/apex_ext/apex_src/objc/NSString+ApexPlugins.m +169 -0
  95. data/ext/apex_ext/apex_src/output.html +87 -0
  96. data/ext/apex_ext/apex_src/plans/quarto-mode.md +442 -0
  97. data/ext/apex_ext/apex_src/src/_README.md +85 -32
  98. data/ext/apex_ext/apex_src/src/apex.c +770 -200
  99. data/ext/apex_ext/apex_src/src/ast_rtf.c +848 -0
  100. data/ext/apex_ext/apex_src/src/ast_terminal.c +184 -7
  101. data/ext/apex_ext/apex_src/src/extensions/abbreviations.c +10 -3
  102. data/ext/apex_ext/apex_src/src/extensions/advanced_tables.c +7 -11
  103. data/ext/apex_ext/apex_src/src/extensions/bear_image_attrs.c +467 -0
  104. data/ext/apex_ext/apex_src/src/extensions/bear_image_attrs.h +27 -0
  105. data/ext/apex_ext/apex_src/src/extensions/callouts.c +400 -4
  106. data/ext/apex_ext/apex_src/src/extensions/callouts.h +15 -5
  107. data/ext/apex_ext/apex_src/src/extensions/citations.c +26 -5
  108. data/ext/apex_ext/apex_src/src/extensions/code_fence_attrs.c +632 -0
  109. data/ext/apex_ext/apex_src/src/extensions/code_fence_attrs.h +22 -0
  110. data/ext/apex_ext/apex_src/src/extensions/concordance.c +632 -0
  111. data/ext/apex_ext/apex_src/src/extensions/definition_list.c +129 -15
  112. data/ext/apex_ext/apex_src/src/extensions/grid_tables.c +1050 -121
  113. data/ext/apex_ext/apex_src/src/extensions/html_markdown.c +569 -16
  114. data/ext/apex_ext/apex_src/src/extensions/ial.c +502 -52
  115. data/ext/apex_ext/apex_src/src/extensions/ial.h +2 -1
  116. data/ext/apex_ext/apex_src/src/extensions/includes.c +532 -33
  117. data/ext/apex_ext/apex_src/src/extensions/includes.h +7 -1
  118. data/ext/apex_ext/apex_src/src/extensions/index.c +1427 -140
  119. data/ext/apex_ext/apex_src/src/extensions/index.h +28 -0
  120. data/ext/apex_ext/apex_src/src/extensions/metadata.c +200 -161
  121. data/ext/apex_ext/apex_src/src/extensions/quarto_diagrams.c +251 -0
  122. data/ext/apex_ext/apex_src/src/extensions/quarto_diagrams.h +22 -0
  123. data/ext/apex_ext/apex_src/src/extensions/quarto_lists.c +624 -0
  124. data/ext/apex_ext/apex_src/src/extensions/quarto_lists.h +35 -0
  125. data/ext/apex_ext/apex_src/src/extensions/quarto_polish.c +264 -0
  126. data/ext/apex_ext/apex_src/src/extensions/quarto_polish.h +23 -0
  127. data/ext/apex_ext/apex_src/src/extensions/quarto_shortcodes.c +307 -0
  128. data/ext/apex_ext/apex_src/src/extensions/quarto_shortcodes.h +21 -0
  129. data/ext/apex_ext/apex_src/src/extensions/raw_content.c +351 -0
  130. data/ext/apex_ext/apex_src/src/extensions/raw_content.h +20 -0
  131. data/ext/apex_ext/apex_src/src/extensions/relaxed_tables.c +117 -3
  132. data/ext/apex_ext/apex_src/src/extensions/special_markers.c +53 -0
  133. data/ext/apex_ext/apex_src/src/extensions/syntax_highlight.c +23 -1
  134. data/ext/apex_ext/apex_src/src/extensions/table_html_postprocess.c +83 -92
  135. data/ext/apex_ext/apex_src/src/extensions/toc.c +446 -25
  136. data/ext/apex_ext/apex_src/src/extensions/toc.h +26 -1
  137. data/ext/apex_ext/apex_src/src/extensions/wiki_links.c +28 -0
  138. data/ext/apex_ext/apex_src/src/html_renderer.c +387 -17
  139. data/ext/apex_ext/apex_src/src/plugin_catalog.c +517 -0
  140. data/ext/apex_ext/apex_src/src/plugins_remote.c +88 -14
  141. data/ext/apex_ext/apex_src/src/plugins_remote.h +34 -0
  142. data/ext/apex_ext/apex_src/src/pretty_html.c +6 -1
  143. data/ext/apex_ext/apex_src/tests/fixtures/comprehensive_test.md +21 -0
  144. data/ext/apex_ext/apex_src/tests/fixtures/images/bear_image_attributes.md +10 -0
  145. data/ext/apex_ext/apex_src/tests/fixtures/includes/sections.md +19 -0
  146. data/ext/apex_ext/apex_src/tests/fixtures/includes/sections.txt +11 -0
  147. data/ext/apex_ext/apex_src/tests/fixtures/minimal_pb.md +2 -0
  148. data/ext/apex_ext/apex_src/tests/fixtures/obsidian-callouts.md +46 -0
  149. data/ext/apex_ext/apex_src/tests/fixtures/pagebreak_html_repro.md +5 -0
  150. data/ext/apex_ext/apex_src/tests/fixtures/python-callouts.md +47 -0
  151. data/ext/apex_ext/apex_src/tests/fixtures/quarto/callouts.md +3 -0
  152. data/ext/apex_ext/apex_src/tests/fixtures/quarto/code-attrs.md +3 -0
  153. data/ext/apex_ext/apex_src/tests/fixtures/quarto/diagrams.md +8 -0
  154. data/ext/apex_ext/apex_src/tests/fixtures/quarto/lists.md +19 -0
  155. data/ext/apex_ext/apex_src/tests/fixtures/quarto/raw-content.md +5 -0
  156. data/ext/apex_ext/apex_src/tests/fixtures/quarto/shortcodes.md +7 -0
  157. data/ext/apex_ext/apex_src/tests/fixtures/quarto/smoke.md +81 -0
  158. data/ext/apex_ext/apex_src/tests/fixtures/quarto/spans.md +5 -0
  159. data/ext/apex_ext/apex_src/tests/fixtures/quarto-callouts.md +47 -0
  160. data/ext/apex_ext/apex_src/tests/fixtures/speed.md +192 -0
  161. data/ext/apex_ext/apex_src/tests/fixtures/tables/grid-tables.md +37 -0
  162. data/ext/apex_ext/apex_src/tests/paginate_cli_test.sh +16 -0
  163. data/ext/apex_ext/apex_src/tests/test_bear_image_attrs.c +301 -0
  164. data/ext/apex_ext/apex_src/tests/test_concordance.tsv +4 -0
  165. data/ext/apex_ext/apex_src/tests/test_escaping_repro.c +82 -0
  166. data/ext/apex_ext/apex_src/tests/test_extensions.c +821 -1
  167. data/ext/apex_ext/apex_src/tests/test_ial.c +7 -0
  168. data/ext/apex_ext/apex_src/tests/test_marked_integration.c +25 -0
  169. data/ext/apex_ext/apex_src/tests/test_metadata.c +129 -0
  170. data/ext/apex_ext/apex_src/tests/test_output.c +568 -2
  171. data/ext/apex_ext/apex_src/tests/test_runner.c +11 -0
  172. data/ext/apex_ext/apex_src/tests/test_tables.c +420 -0
  173. data/ext/apex_ext/apex_src/vendor/cmark-gfm/CMakeLists.txt +1 -1
  174. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/autolink.c +77 -1
  175. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/table.c +135 -5
  176. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/blocks.c +56 -1
  177. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/config.h +38 -0
  178. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/main.c +1 -1
  179. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/__pycache__/cmark.cpython-314.pyc +0 -0
  180. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/__pycache__/normalize.cpython-314.pyc +0 -0
  181. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/extensions.txt +69 -0
  182. data/ext/apex_ext/apex_src/xcode_build/CMakeScripts/ReRunCMake.make +74 -0
  183. data/ext/apex_ext/apex_src/xcode_build/CTestTestfile.cmake +22 -0
  184. data/ext/apex_ext/apex_src/xcode_build/Debug/Apex.framework/Versions/A/Apex +0 -0
  185. data/ext/apex_ext/apex_src/xcode_build/Debug/Apex.framework/Versions/A/Resources/Info.plist +44 -0
  186. data/ext/apex_ext/apex_src/xcode_build/Debug/Apex.framework/Versions/A/_CodeSignature/CodeResources +128 -0
  187. data/ext/apex_ext/apex_src/xcode_build/apex.xcodeproj/project.pbxproj +5118 -0
  188. data/ext/apex_ext/apex_src/xcode_build/apex.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +8 -0
  189. data/ext/apex_ext/apex_src/xcode_build/apex.xcodeproj/project.xcworkspace/xcuserdata/ttscoff.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  190. data/ext/apex_ext/apex_src/xcode_build/apex.xcodeproj/project.xcworkspace/xcuserdata/ttscoff.xcuserdatad/WorkspaceSettings.xcsettings +8 -0
  191. data/ext/apex_ext/apex_src/xcode_build/apex.xcodeproj/xcuserdata/ttscoff.xcuserdatad/xcschemes/xcschememanagement.plist +99 -0
  192. data/ext/apex_ext/apex_src/xcode_build/cmake_install.cmake +452 -0
  193. data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/CMakeScripts/ReRunCMake.make +52 -0
  194. data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/cmake_install.cmake +55 -0
  195. data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/cmark-gfm.xcodeproj/project.pbxproj +2455 -0
  196. data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/cmark-gfm.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +8 -0
  197. data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/extensions/cmake_install.cmake +171 -0
  198. data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/man/cmake_install.cmake +55 -0
  199. data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/src/cmake_install.cmake +220 -0
  200. data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/src/cmark-gfm_export.h +43 -0
  201. data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/src/cmark-gfm_version.h +7 -0
  202. data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/src/config.h +76 -0
  203. data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/src/libcmark-gfm.pc +10 -0
  204. data/ext/apex_ext/extconf.rb +35 -0
  205. data/lib/apex/version.rb +2 -2
  206. metadata +117 -2
  207. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/tempOptimizedIndex.dsidx +0 -0
@@ -0,0 +1,745 @@
1
+ # TOC Output Format Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Add `-t toc` that emits a Markdown unordered list of heading links, plus `--toc-min-max` defaults shared with HTML TOC markers.
6
+
7
+ **Architecture:** Early-exit `APEX_OUTPUT_TOC` after AST prep (same point as markdown/json-filtered). Refactor `src/extensions/toc.c` to share heading collection/ID assignment between HTML marker TOC and a new Markdown TOC emitter. Option defaults (`toc_min`/`toc_max`, default 1,3) seed both paths; marker-specified ranges still override.
8
+
9
+ **Tech Stack:** C (Apex + cmark-gfm), existing `tests/test_output.c` suite runner, man page / wiki docs.
10
+
11
+ **Spec:** `docs/superpowers/specs/2026-07-12-toc-output-format-design.md`
12
+
13
+ ---
14
+
15
+ ## File map
16
+
17
+ | File | Responsibility |
18
+ |------|----------------|
19
+ | `include/apex/apex.h` | `APEX_OUTPUT_TOC`; `toc_min` / `toc_max` on `apex_options` |
20
+ | `src/apex.c` | Defaults; early-exit for TOC; pass defaults into `apex_process_toc` |
21
+ | `src/extensions/toc.h` | Public Markdown helper; update `apex_process_toc` signature |
22
+ | `src/extensions/toc.c` | Prefer manual IDs; Markdown emitter; default min/max when marker omits range |
23
+ | `cli/main.c` | `-t toc`, `--toc-min-max`, help, option mask |
24
+ | `src/extensions/metadata.c` | `toc-min-max` metadata key |
25
+ | `tests/test_output.c` | `-t toc` + default-depth HTML TOC tests |
26
+ | `tests/test_metadata.c` | Metadata `toc-min-max` parsing |
27
+ | `man/apex.1.md` (+ regenerate `man/apex.1`) | Document format + flag |
28
+ | `apex.wiki/Command-Line-Options.md`, `Syntax.md`, `Header-IDs.md` as needed | User docs |
29
+
30
+ ---
31
+
32
+ ### Task 1: Options + enum surface
33
+
34
+ **Files:**
35
+ - Modify: `include/apex/apex.h`
36
+ - Modify: `src/apex.c` (`apex_options_default`, and any `apex_options_for_mode` copies that re-init options)
37
+
38
+ - [ ] **Step 1: Add enum value and option fields**
39
+
40
+ In `include/apex/apex.h`, extend the output format enum:
41
+
42
+ ```c
43
+ APEX_OUTPUT_MAN = 10, /* roff (man page source) */
44
+ APEX_OUTPUT_MAN_HTML = 11, /* styled HTML man page */
45
+ APEX_OUTPUT_TOC = 12 /* Markdown TOC list only */
46
+ ```
47
+
48
+ Near the header ID fields on `apex_options` (after `id_format`), add:
49
+
50
+ ```c
51
+ /* TOC depth defaults (used by -t toc and by HTML TOC markers without an explicit range) */
52
+ int toc_min; /* Inclusive min heading level (default 1) */
53
+ int toc_max; /* Inclusive max heading level (default 3) */
54
+ ```
55
+
56
+ - [ ] **Step 2: Initialize defaults in `apex_options_default`**
57
+
58
+ In `src/apex.c` inside `apex_options_default()`, after `opts.id_format = 0;`:
59
+
60
+ ```c
61
+ opts.toc_min = 1;
62
+ opts.toc_max = 3;
63
+ ```
64
+
65
+ If `apex_options_for_mode()` rebuilds options via `apex_options_default()`, no extra work. If any mode path zeroes the struct without going through default, set `toc_min`/`toc_max` there too.
66
+
67
+ - [ ] **Step 3: Commit**
68
+
69
+ ```bash
70
+ git add include/apex/apex.h src/apex.c
71
+ git commit -m "Add APEX_OUTPUT_TOC and toc_min/toc_max options"
72
+ ```
73
+
74
+ ---
75
+
76
+ ### Task 2: Prefer manual heading IDs in TOC collection
77
+
78
+ **Files:**
79
+ - Modify: `src/extensions/toc.c`
80
+ - Test: `tests/test_output.c`
81
+
82
+ - [ ] **Step 1: Write failing test for manual ID in HTML TOC**
83
+
84
+ Append inside `test_toc()` in `tests/test_output.c` (before suite_end):
85
+
86
+ ```c
87
+ /* Manual {#id} must appear in TOC hrefs */
88
+ const char *manual_id_toc =
89
+ "# Custom {#my-custom}\n\n{{TOC}}\n\n## Other";
90
+ html = apex_markdown_to_html(manual_id_toc, strlen(manual_id_toc), &opts);
91
+ assert_contains(html, "href=\"#my-custom\"", "TOC uses manual heading ID");
92
+ apex_free_string(html);
93
+ ```
94
+
95
+ - [ ] **Step 2: Run test to verify it fails**
96
+
97
+ ```bash
98
+ cd /Users/ttscoff/Desktop/Code/apex/build && make apex_test_runner -j4 && ./apex_test_runner toc 2>&1 | rg -i "manual|FAIL|passed|failed"
99
+ ```
100
+
101
+ Expected: failure on "TOC uses manual heading ID" (current code always regenerates from text).
102
+
103
+ - [ ] **Step 3: Assign IDs from `user_data` when present**
104
+
105
+ In `src/extensions/toc.c`, replace the ID assignment loop in `apex_process_toc` (and share later with Markdown) with a helper:
106
+
107
+ ```c
108
+ static char *heading_id_from_attrs_or_text(const char *attrs, const char *text,
109
+ apex_id_format_t id_format) {
110
+ if (attrs) {
111
+ const char *id_attr = strstr(attrs, "id=\"");
112
+ if (id_attr) {
113
+ const char *id_start = id_attr + 4;
114
+ const char *id_end = strchr(id_start, '"');
115
+ if (id_end && id_end > id_start) {
116
+ size_t id_len = (size_t)(id_end - id_start);
117
+ char *id = malloc(id_len + 1);
118
+ if (id) {
119
+ memcpy(id, id_start, id_len);
120
+ id[id_len] = '\0';
121
+ return id;
122
+ }
123
+ }
124
+ }
125
+ }
126
+ return apex_generate_header_id(text, id_format);
127
+ }
128
+ ```
129
+
130
+ Update `collect_headers` to store attrs (or look them up again). Simplest: keep attrs on the node and, when assigning IDs, pass `cmark_node` — better: store `char *attrs_copy` is unnecessary if we assign IDs during collection:
131
+
132
+ In `collect_headers`, after creating `item`:
133
+
134
+ ```c
135
+ const char *attrs = (const char *)cmark_node_get_user_data(node);
136
+ /* no_toc check already uses attrs */
137
+ item->id = NULL; /* assigned in assign_header_ids */
138
+ ```
139
+
140
+ Add:
141
+
142
+ ```c
143
+ static void assign_header_ids(header_item *headers, cmark_node *document,
144
+ int id_format) {
145
+ /* Walk headers list in document order; for each, find matching heading
146
+ * OR store attrs on header_item during collect. Prefer storing attrs: */
147
+ }
148
+ ```
149
+
150
+ Preferred approach — extend `header_item`:
151
+
152
+ ```c
153
+ typedef struct header_item {
154
+ int level;
155
+ char *text;
156
+ char *id;
157
+ char *attrs; /* borrowed? NO — strdup user_data or extract id immediately */
158
+ struct header_item *next;
159
+ } header_item;
160
+ ```
161
+
162
+ Simplest reliable approach: extract ID during `collect_headers` once you know `id_format` — change signature to:
163
+
164
+ ```c
165
+ static header_item *collect_headers(cmark_node *node, header_item **tail,
166
+ int id_format);
167
+ ```
168
+
169
+ and inside, after `normalize_toc_text`:
170
+
171
+ ```c
172
+ item->id = heading_id_from_attrs_or_text(attrs, item->text,
173
+ (apex_id_format_t)id_format);
174
+ ```
175
+
176
+ Update `free_headers` (already frees `id`). Remove the separate ID loop in `apex_process_toc`.
177
+
178
+ - [ ] **Step 4: Run test to verify it passes**
179
+
180
+ ```bash
181
+ cd /Users/ttscoff/Desktop/Code/apex/build && make apex_test_runner -j4 && ./apex_test_runner toc 2>&1 | rg -i "manual|FAIL|Results"
182
+ ```
183
+
184
+ Expected: "TOC uses manual heading ID" passes; suite overall green enough to proceed (note: Task 3 will change bare-marker max depth).
185
+
186
+ - [ ] **Step 5: Commit**
187
+
188
+ ```bash
189
+ git add src/extensions/toc.c tests/test_output.c
190
+ git commit -m "Prefer manual heading IDs when building TOC links"
191
+ ```
192
+
193
+ ---
194
+
195
+ ### Task 3: Thread default min/max into HTML TOC markers
196
+
197
+ **Files:**
198
+ - Modify: `src/extensions/toc.h`
199
+ - Modify: `src/extensions/toc.c`
200
+ - Modify: `src/apex.c` (call site)
201
+ - Test: `tests/test_output.c`
202
+
203
+ - [ ] **Step 1: Write failing tests for option defaults on bare markers**
204
+
205
+ In `test_toc()`:
206
+
207
+ ```c
208
+ /* Bare {{TOC}} should use option defaults (1-3): exclude H4 */
209
+ const char *bare_default_depth =
210
+ "# H1\n\n{{TOC}}\n\n## H2\n\n### H3\n\n#### H4";
211
+ html = apex_markdown_to_html(bare_default_depth, strlen(bare_default_depth), &opts);
212
+ assert_contains(html, "href=\"#h1\"", "Bare TOC includes H1 by default");
213
+ assert_contains(html, "href=\"#h3\"", "Bare TOC includes H3 by default");
214
+ assert_not_contains(html, "href=\"#h4\"", "Bare TOC excludes H4 by default (max 3)");
215
+ apex_free_string(html);
216
+
217
+ /* --toc-min-max via options: 2,4 */
218
+ apex_options depth_opts = opts;
219
+ depth_opts.toc_min = 2;
220
+ depth_opts.toc_max = 4;
221
+ html = apex_markdown_to_html(bare_default_depth, strlen(bare_default_depth), &depth_opts);
222
+ assert_not_contains(html, "href=\"#h1\"", "toc_min=2 excludes H1");
223
+ assert_contains(html, "href=\"#h4\"", "toc_max=4 includes H4");
224
+ apex_free_string(html);
225
+
226
+ /* Marker override wins over options */
227
+ const char *override_toc =
228
+ "# H1\n\n{{TOC:1-6}}\n\n## H2\n\n### H3\n\n#### H4\n\n##### H5";
229
+ html = apex_markdown_to_html(override_toc, strlen(override_toc), &depth_opts);
230
+ assert_contains(html, "href=\"#h1\"", "Marker range overrides toc_min");
231
+ assert_contains(html, "href=\"#h5\"", "Marker range overrides toc_max");
232
+ apex_free_string(html);
233
+ ```
234
+
235
+ - [ ] **Step 2: Run tests to verify failure on H4 exclusion**
236
+
237
+ ```bash
238
+ cd /Users/ttscoff/Desktop/Code/apex/build && make apex_test_runner -j4 && ./apex_test_runner toc 2>&1 | rg -i "Bare TOC excludes|FAIL|Results"
239
+ ```
240
+
241
+ Expected: "Bare TOC excludes H4 by default" fails (today bare marker uses max 6).
242
+
243
+ - [ ] **Step 3: Update API and `parse_toc_marker`**
244
+
245
+ `src/extensions/toc.h`:
246
+
247
+ ```c
248
+ char *apex_process_toc(const char *html, cmark_node *document, int id_format,
249
+ int default_min, int default_max);
250
+ ```
251
+
252
+ In `toc.c`, change `parse_toc_marker` to accept defaults:
253
+
254
+ ```c
255
+ static void parse_toc_marker(const char *marker, int *min_level, int *max_level,
256
+ int default_min, int default_max) {
257
+ *min_level = default_min;
258
+ *max_level = default_max;
259
+ /* ... existing parsing that overwrites when marker specifies min/max ... */
260
+ }
261
+ ```
262
+
263
+ Clamp after parse:
264
+
265
+ ```c
266
+ if (*min_level < 1) *min_level = 1;
267
+ if (*max_level > 6) *max_level = 6;
268
+ if (*min_level > *max_level) *max_level = *min_level;
269
+ ```
270
+
271
+ Update `apex_process_toc` signature and call:
272
+
273
+ ```c
274
+ parse_toc_marker(marker, &min_level, &max_level, default_min, default_max);
275
+ ```
276
+
277
+ In `src/apex.c`:
278
+
279
+ ```c
280
+ char *with_toc = apex_process_toc(html, document, options->id_format,
281
+ options->toc_min, options->toc_max);
282
+ ```
283
+
284
+ - [ ] **Step 4: Run `toc` suite**
285
+
286
+ ```bash
287
+ cd /Users/ttscoff/Desktop/Code/apex/build && make apex_test_runner -j4 && ./apex_test_runner toc
288
+ ```
289
+
290
+ Expected: all TOC tests pass. If any older test assumed H4+ from bare `{{TOC}}`, update that test to use an explicit marker range.
291
+
292
+ - [ ] **Step 5: Commit**
293
+
294
+ ```bash
295
+ git add src/extensions/toc.h src/extensions/toc.c src/apex.c tests/test_output.c
296
+ git commit -m "Use toc_min/toc_max defaults for HTML TOC markers without a range"
297
+ ```
298
+
299
+ ---
300
+
301
+ ### Task 4: Markdown TOC emitter + `-t toc` early exit
302
+
303
+ **Files:**
304
+ - Modify: `src/extensions/toc.h`
305
+ - Modify: `src/extensions/toc.c`
306
+ - Modify: `src/apex.c`
307
+ - Test: `tests/test_output.c`
308
+
309
+ - [ ] **Step 1: Write failing `-t toc` tests**
310
+
311
+ Add to `test_toc()`:
312
+
313
+ ```c
314
+ /* -t toc: Markdown list, default depth 1-3 */
315
+ apex_options toc_opts = apex_options_default();
316
+ toc_opts.output_format = APEX_OUTPUT_TOC;
317
+ const char *doc =
318
+ "# Introduction\n\n"
319
+ "## Getting Started\n\n"
320
+ "### Installation\n\n"
321
+ "#### Too Deep\n\n"
322
+ "## Configuration\n\n"
323
+ "# API\n"
324
+ "{: .no_toc}\n";
325
+ char *md = apex_markdown_to_html(doc, strlen(doc), &toc_opts);
326
+ assert_contains(md, "- [Introduction](#introduction)\n", "TOC md has H1");
327
+ assert_contains(md, " - [Getting Started](#getting-started)\n", "TOC md indents H2");
328
+ assert_contains(md, " - [Installation](#installation)\n", "TOC md indents H3");
329
+ assert_not_contains(md, "Too Deep", "TOC md excludes H4 by default");
330
+ assert_not_contains(md, "API", "TOC md excludes no_toc heading");
331
+ assert_not_contains(md, "<nav", "TOC md is not HTML");
332
+ apex_free_string(md);
333
+
334
+ toc_opts.toc_min = 2;
335
+ toc_opts.toc_max = 4;
336
+ md = apex_markdown_to_html(doc, strlen(doc), &toc_opts);
337
+ assert_not_contains(md, "Introduction", "toc-min-max excludes H1");
338
+ assert_contains(md, "Too Deep", "toc-min-max includes H4");
339
+ apex_free_string(md);
340
+
341
+ /* id-format mmd */
342
+ toc_opts = apex_options_default();
343
+ toc_opts.output_format = APEX_OUTPUT_TOC;
344
+ toc_opts.id_format = 1; /* MMD */
345
+ md = apex_markdown_to_html("# Hello World\n", 14, &toc_opts);
346
+ assert_contains(md, "- [Hello World](#HelloWorld)\n", "TOC md respects MMD id-format");
347
+ apex_free_string(md);
348
+
349
+ /* empty */
350
+ toc_opts = apex_options_default();
351
+ toc_opts.output_format = APEX_OUTPUT_TOC;
352
+ md = apex_markdown_to_html("No headings here.\n", 18, &toc_opts);
353
+ if (md && (md[0] == '\0' || strcmp(md, "\n") == 0)) {
354
+ test_result(true, "TOC md empty when no headings");
355
+ } else {
356
+ test_result(false, "TOC md empty when no headings");
357
+ }
358
+ apex_free_string(md);
359
+ ```
360
+
361
+ Adjust the MMD id expectation if `apex_generate_header_id` for "Hello World" differs — run a quick HTML render with `--id-format mmd` if needed and match that slug.
362
+
363
+ - [ ] **Step 2: Run tests — expect missing format / wrong output**
364
+
365
+ ```bash
366
+ cd /Users/ttscoff/Desktop/Code/apex/build && make apex_test_runner -j4 && ./apex_test_runner toc 2>&1 | rg -i "TOC md|FAIL|Results"
367
+ ```
368
+
369
+ Expected: failures (TOC still goes through HTML path or ignores `APEX_OUTPUT_TOC`).
370
+
371
+ - [ ] **Step 3: Implement `apex_generate_toc_markdown`**
372
+
373
+ `toc.h`:
374
+
375
+ ```c
376
+ char *apex_generate_toc_markdown(cmark_node *document, int id_format,
377
+ int min_level, int max_level);
378
+ ```
379
+
380
+ `toc.c` — mirror nesting logic of `generate_toc_html`, but emit Markdown:
381
+
382
+ ```c
383
+ char *apex_generate_toc_markdown(cmark_node *document, int id_format,
384
+ int min_level, int max_level) {
385
+ if (!document) return strdup("");
386
+ if (min_level < 1) min_level = 1;
387
+ if (max_level > 6) max_level = 6;
388
+ if (min_level > max_level) max_level = min_level;
389
+
390
+ header_item *tail = NULL;
391
+ header_item *headers = collect_headers(document, &tail, id_format);
392
+ if (!headers) return strdup("");
393
+
394
+ size_t capacity = 4096;
395
+ char *out = malloc(capacity);
396
+ if (!out) {
397
+ free_headers(headers);
398
+ return strdup("");
399
+ }
400
+ char *write = out;
401
+ size_t remaining = capacity;
402
+
403
+ #define ENSURE(n) do { \
404
+ if ((size_t)(n) >= remaining) { \
405
+ size_t used = (size_t)(write - out); \
406
+ capacity = used + (size_t)(n) + 1024; \
407
+ char *nbuf = realloc(out, capacity); \
408
+ if (!nbuf) { free(out); free_headers(headers); return strdup(""); } \
409
+ out = nbuf; write = out + used; remaining = capacity - used; \
410
+ } \
411
+ } while (0)
412
+
413
+ #define APPEND(str) do { \
414
+ size_t len = strlen(str); \
415
+ ENSURE(len + 1); \
416
+ memcpy(write, str, len); \
417
+ write += len; \
418
+ remaining -= len; \
419
+ } while (0)
420
+
421
+ for (header_item *h = headers; h; h = h->next) {
422
+ if (h->level < min_level || h->level > max_level) continue;
423
+ int depth = h->level - min_level; /* 0 = flush */
424
+ ENSURE((size_t)depth * 2 + strlen(h->text) + strlen(h->id) + 16);
425
+ for (int i = 0; i < depth; i++) APPEND(" ");
426
+ APPEND("- [");
427
+ APPEND(h->text);
428
+ APPEND("](#");
429
+ APPEND(h->id);
430
+ APPEND(")\n");
431
+ }
432
+
433
+ #undef APPEND
434
+ #undef ENSURE
435
+
436
+ *write = '\0';
437
+ free_headers(headers);
438
+ return out;
439
+ }
440
+ ```
441
+
442
+ - [ ] **Step 4: Early-exit in `apex_markdown_to_html`**
443
+
444
+ In `src/apex.c`, immediately after the JSON_FILTERED early return (before Markdown dialects), add:
445
+
446
+ ```c
447
+ if (options->output_format == APEX_OUTPUT_TOC) {
448
+ char *toc_md = apex_generate_toc_markdown(document, options->id_format,
449
+ options->toc_min, options->toc_max);
450
+ return toc_md ? toc_md : strdup("");
451
+ }
452
+ ```
453
+
454
+ Include `toc.h` if not already included at the top of `apex.c`.
455
+
456
+ - [ ] **Step 5: Run tests**
457
+
458
+ ```bash
459
+ cd /Users/ttscoff/Desktop/Code/apex/build && make apex_test_runner -j4 && ./apex_test_runner toc
460
+ ```
461
+
462
+ Expected: all pass. Fix MMD slug assertion if the actual slug differs.
463
+
464
+ - [ ] **Step 6: Commit**
465
+
466
+ ```bash
467
+ git add src/extensions/toc.h src/extensions/toc.c src/apex.c tests/test_output.c
468
+ git commit -m "Add -t toc Markdown TOC output format"
469
+ ```
470
+
471
+ ---
472
+
473
+ ### Task 5: CLI `--to toc` and `--toc-min-max`
474
+
475
+ **Files:**
476
+ - Modify: `cli/main.c`
477
+
478
+ - [ ] **Step 1: Add option mask fields**
479
+
480
+ In `apex_cli_option_mask`:
481
+
482
+ ```c
483
+ bool toc_min_max;
484
+ ```
485
+
486
+ In `apex_apply_cli_option_mask` (or equivalent merge helper), copy when masked:
487
+
488
+ ```c
489
+ if (m->toc_min_max) {
490
+ opts->toc_min = snap->toc_min;
491
+ opts->toc_max = snap->toc_max;
492
+ }
493
+ ```
494
+
495
+ - [ ] **Step 2: Parse `-t toc` and `--toc-min-max`**
496
+
497
+ In the `-t` / `--to` branch, after `man-html`:
498
+
499
+ ```c
500
+ } else if (strcmp(format, "toc") == 0) {
501
+ options.output_format = APEX_OUTPUT_TOC;
502
+ ```
503
+
504
+ Add flag parsing near `--id-format`:
505
+
506
+ ```c
507
+ } else if (strncmp(argv[i], "--toc-min-max=", 14) == 0 ||
508
+ strcmp(argv[i], "--toc-min-max") == 0) {
509
+ const char *val = NULL;
510
+ if (strncmp(argv[i], "--toc-min-max=", 14) == 0) {
511
+ val = argv[i] + 14;
512
+ } else {
513
+ if (i + 1 >= argc) {
514
+ fprintf(stderr, "Error: --toc-min-max requires MIN,MAX (e.g. 1,3)\n");
515
+ return 1;
516
+ }
517
+ val = argv[++i];
518
+ }
519
+ int min = 0, max = 0;
520
+ if (sscanf(val, "%d,%d", &min, &max) != 2 ||
521
+ min < 1 || max > 6 || min > max) {
522
+ fprintf(stderr, "Error: --toc-min-max must be MIN,MAX with 1 <= MIN <= MAX <= 6\n");
523
+ return 1;
524
+ }
525
+ cli_opt_mask.toc_min_max = true;
526
+ options.toc_min = min;
527
+ options.toc_max = max;
528
+ ```
529
+
530
+ - [ ] **Step 3: Help text**
531
+
532
+ In `print_usage` / help:
533
+
534
+ - Add `toc` to the `-t` formats list.
535
+ - Add:
536
+
537
+ ```c
538
+ fprintf(stderr, " --toc-min-max MIN,MAX TOC heading depth range (default: 1,3); also seeds HTML TOC markers without an explicit range\n");
539
+ ```
540
+
541
+ - [ ] **Step 4: Manual CLI smoke check**
542
+
543
+ ```bash
544
+ cd /Users/ttscoff/Desktop/Code/apex/build && make apex -j4
545
+ ./apex -t toc --toc-min-max=2,4 <<'MD'
546
+ # A
547
+ ## B
548
+ ### C
549
+ #### D
550
+ MD
551
+ ```
552
+
553
+ Expected:
554
+
555
+ ```markdown
556
+ - [B](#b)
557
+ - [C](#c)
558
+ - [D](#d)
559
+ ```
560
+
561
+ Invalid flag:
562
+
563
+ ```bash
564
+ ./apex -t toc --toc-min-max=0,9 </dev/null; echo exit:$?
565
+ ```
566
+
567
+ Expected: non-zero exit and error message.
568
+
569
+ - [ ] **Step 5: Commit**
570
+
571
+ ```bash
572
+ git add cli/main.c
573
+ git commit -m "Add CLI -t toc and --toc-min-max"
574
+ ```
575
+
576
+ ---
577
+
578
+ ### Task 6: Metadata `toc-min-max`
579
+
580
+ **Files:**
581
+ - Modify: `src/extensions/metadata.c`
582
+ - Test: `tests/test_metadata.c` (suite that covers option keys — `test_metadata_control_options` or nearest)
583
+
584
+ - [ ] **Step 1: Write failing metadata test**
585
+
586
+ Follow existing `id-format` metadata tests in `tests/test_metadata.c`:
587
+
588
+ ```c
589
+ opts = apex_options_default();
590
+ /* build metadata list with key toc-min-max value 2,4 — same pattern as id-format test */
591
+ apex_apply_metadata_to_options(metadata, &opts); /* use actual helper name from nearby tests */
592
+ assert_option_bool(opts.toc_min == 2, true, "toc-min-max sets toc_min");
593
+ assert_option_bool(opts.toc_max == 4, true, "toc-min-max sets toc_max");
594
+ ```
595
+
596
+ Read the surrounding `id-format` test and mirror its metadata list construction exactly.
597
+
598
+ - [ ] **Step 2: Run test — expect fail**
599
+
600
+ ```bash
601
+ cd /Users/ttscoff/Desktop/Code/apex/build && make apex_test_runner -j4 && ./apex_test_runner metadata_control_options 2>&1 | rg -i "toc-min|FAIL|Results"
602
+ ```
603
+
604
+ (If the suite name differs, use the suite that contains the id-format metadata assertions.)
605
+
606
+ - [ ] **Step 3: Parse in `metadata.c`**
607
+
608
+ Near the `id-format` branch:
609
+
610
+ ```c
611
+ } else if (strcasecmp(key, "toc-min-max") == 0 || strcasecmp(key, "toc_min_max") == 0) {
612
+ int min = 0, max = 0;
613
+ if (sscanf(value, "%d,%d", &min, &max) == 2 &&
614
+ min >= 1 && max <= 6 && min <= max) {
615
+ options->toc_min = min;
616
+ options->toc_max = max;
617
+ }
618
+ ```
619
+
620
+ Ignore invalid values silently (match how other metadata keys behave) unless nearby keys error loudly — stay consistent.
621
+
622
+ - [ ] **Step 4: Run metadata + toc suites**
623
+
624
+ ```bash
625
+ cd /Users/ttscoff/Desktop/Code/apex/build && make apex_test_runner -j4 && ./apex_test_runner toc && ./apex_test_runner metadata_control_options
626
+ ```
627
+
628
+ - [ ] **Step 5: Commit**
629
+
630
+ ```bash
631
+ git add src/extensions/metadata.c tests/test_metadata.c
632
+ git commit -m "Support toc-min-max metadata for TOC depth defaults"
633
+ ```
634
+
635
+ ---
636
+
637
+ ### Task 7: Documentation
638
+
639
+ **Files:**
640
+ - Modify: `man/apex.1.md` (then `make man`)
641
+ - Modify: `/Users/ttscoff/Desktop/Code/apex.wiki/Command-Line-Options.md`
642
+ - Modify: `/Users/ttscoff/Desktop/Code/apex.wiki/Syntax.md` (TOC section)
643
+ - Optionally: `/Users/ttscoff/Desktop/Code/apex.wiki/Header-IDs.md` (note `-t toc` uses same IDs)
644
+
645
+ - [ ] **Step 1: Man page**
646
+
647
+ Under `-t` / `--to` list, add:
648
+
649
+ ```markdown
650
+ - **toc** - Markdown unordered list of heading links only (default depth `#`–`###`)
651
+ ```
652
+
653
+ Add flag section:
654
+
655
+ ```markdown
656
+ **--toc-min-max** *MIN,MAX*
657
+ : Inclusive heading depth range for **--to toc** and for HTML TOC markers that do not specify their own range. Default **1,3**. Marker syntax such as `{{TOC:2-5}}` still overrides. Values must satisfy `1 <= MIN <= MAX <= 6`.
658
+ ```
659
+
660
+ Regenerate:
661
+
662
+ ```bash
663
+ cd /Users/ttscoff/Desktop/Code/apex && make man
664
+ ```
665
+
666
+ - [ ] **Step 2: Wiki**
667
+
668
+ In `Command-Line-Options.md`, document `-t toc` and `--toc-min-max` near other output/format flags.
669
+
670
+ In `Syntax.md` TOC section, note:
671
+
672
+ - Bare `{{TOC}}` / `<!--TOC-->` / `{:toc}` now default to levels 1–3 (or `--toc-min-max` / `toc-min-max` metadata).
673
+ - `-t toc` extracts a Markdown TOC without markers.
674
+
675
+ - [ ] **Step 3: Commit**
676
+
677
+ ```bash
678
+ git add man/apex.1.md man/apex.1
679
+ # wiki is a separate repo:
680
+ cd /Users/ttscoff/Desktop/Code/apex.wiki && git add Command-Line-Options.md Syntax.md Header-IDs.md && git status
681
+ ```
682
+
683
+ Commit apex and wiki separately with clear messages. Do not push unless asked.
684
+
685
+ ---
686
+
687
+ ### Task 8: Final verification
688
+
689
+ - [ ] **Step 1: Full relevant test pass**
690
+
691
+ ```bash
692
+ cd /Users/ttscoff/Desktop/Code/apex/build && make -j4 && ./apex_test_runner toc && ./apex_test_runner header_ids && ./apex_test_runner metadata_control_options
693
+ ```
694
+
695
+ - [ ] **Step 2: End-to-end smoke**
696
+
697
+ ```bash
698
+ ./apex -t toc <<'MD'
699
+ # Intro
700
+ ## Details
701
+ ### Deep
702
+ #### Deeper
703
+ MD
704
+ ./apex -t toc --toc-min-max=1,6 <<'MD'
705
+ # Intro
706
+ ## Details
707
+ ### Deep
708
+ #### Deeper
709
+ MD
710
+ ./apex -t html <<'MD'
711
+ # Intro
712
+ {{TOC}}
713
+ ## Details
714
+ ### Deep
715
+ #### Deeper
716
+ MD
717
+ ```
718
+
719
+ Confirm Markdown TOC and HTML bare TOC both stop at `###` by default; `--toc-min-max=1,6` includes `####`.
720
+
721
+ - [ ] **Step 3: Update `commit_message.txt` only if the user asks for a changelog commit message**
722
+
723
+ ---
724
+
725
+ ## Spec coverage checklist
726
+
727
+ | Spec requirement | Task |
728
+ |------------------|------|
729
+ | `-t toc` Markdown list `[Title](#id)` | 4, 5 |
730
+ | Default depth 1–3 | 1, 3, 4 |
731
+ | `--toc-min-max` | 5 |
732
+ | Flag seeds HTML markers; marker overrides | 3 |
733
+ | `.no_toc` excluded | 4 (existing collect_headers) |
734
+ | IDs match `--id-format` / manual IDs | 2, 4 |
735
+ | Metadata `toc-min-max` | 6 |
736
+ | Docs / man | 7 |
737
+ | Empty doc behavior | 4 |
738
+ | Invalid CLI values rejected | 5 |
739
+
740
+ ## Notes for implementers
741
+
742
+ - `apex_markdown_to_html` is the library entry for all formats despite the name — follow existing early-return patterns for JSON/markdown.
743
+ - Bare HTML TOC default change (1–6 → 1–3) is intentional; call it out in changelog with `@changed` when the user requests a commit message.
744
+ - Do not add separate `--toc-min` / `--toc-max` flags.
745
+ - Wiki lives in `/Users/ttscoff/Desktop/Code/apex.wiki` (separate git repo).