apex-ruby 1.0.17 → 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
@@ -1221,6 +1221,94 @@ typedef enum {
1221
1221
  static term_img_tool_t g_term_img_tool = TERM_IMG_NONE;
1222
1222
  static int g_term_img_width = 50;
1223
1223
  static bool g_term_has_curl = false;
1224
+ static bool g_term_use_256 = false;
1225
+ static bool g_term_paginate_symbols = false;
1226
+ static size_t g_terminal_output_len = 0;
1227
+
1228
+ static bool terminal_debug_enabled(void) {
1229
+ return getenv("APEX_DEBUG_TERMINAL") != NULL;
1230
+ }
1231
+
1232
+ static const char *term_img_tool_name(term_img_tool_t tool) {
1233
+ switch (tool) {
1234
+ case TERM_IMG_IMGCAT: return "imgcat";
1235
+ case TERM_IMG_CHAFA: return "chafa";
1236
+ case TERM_IMG_VIU: return "viu";
1237
+ case TERM_IMG_CATIMG: return "catimg";
1238
+ default: return "(none)";
1239
+ }
1240
+ }
1241
+
1242
+ static void terminal_debug_log_tool_path(const char *name) {
1243
+ if (!terminal_debug_enabled()) {
1244
+ return;
1245
+ }
1246
+ char path[PATH_MAX];
1247
+ const char *pathenv = getenv("PATH");
1248
+ bool found = false;
1249
+ if (pathenv && *pathenv) {
1250
+ const char *p = pathenv;
1251
+ while (*p) {
1252
+ const char *colon = strchr(p, ':');
1253
+ size_t dirlen = colon ? (size_t)(colon - p) : strlen(p);
1254
+ if (dirlen > 0 && dirlen + strlen(name) + 2 < sizeof(path)) {
1255
+ memcpy(path, p, dirlen);
1256
+ path[dirlen] = '\0';
1257
+ snprintf(path + dirlen, sizeof(path) - dirlen, "/%s", name);
1258
+ if (access(path, X_OK) == 0) {
1259
+ fprintf(stderr, "[APEX_DEBUG_TERMINAL] %s: %s\n", name, path);
1260
+ found = true;
1261
+ break;
1262
+ }
1263
+ }
1264
+ if (!colon) {
1265
+ break;
1266
+ }
1267
+ p = colon + 1;
1268
+ }
1269
+ }
1270
+ if (!found) {
1271
+ fprintf(stderr, "[APEX_DEBUG_TERMINAL] %s: (not on PATH)\n", name);
1272
+ }
1273
+ }
1274
+
1275
+ static void terminal_debug_log_argv(const char *const *argv) {
1276
+ if (!terminal_debug_enabled() || !argv || !argv[0]) {
1277
+ return;
1278
+ }
1279
+ fprintf(stderr, "[APEX_DEBUG_TERMINAL] exec:");
1280
+ for (int i = 0; argv[i]; i++) {
1281
+ fprintf(stderr, " %s", argv[i]);
1282
+ }
1283
+ fputc('\n', stderr);
1284
+ }
1285
+
1286
+ static bool terminal_is_iterm(void) {
1287
+ const char *tp = getenv("TERM_PROGRAM");
1288
+ return tp && strstr(tp, "iTerm") != NULL;
1289
+ }
1290
+
1291
+ static bool terminal_is_kitty(void) {
1292
+ return getenv("KITTY_WINDOW_ID") != NULL;
1293
+ }
1294
+
1295
+ static bool terminal_is_wezterm(void) {
1296
+ return getenv("WEZTERM_EXECUTABLE") != NULL || getenv("WEZTERM_PANE") != NULL;
1297
+ }
1298
+
1299
+ static bool terminal_supports_inline_graphics(void) {
1300
+ return terminal_is_iterm() || terminal_is_kitty() || terminal_is_wezterm();
1301
+ }
1302
+
1303
+ static const char *terminal_chafa_format(void) {
1304
+ if (terminal_is_iterm() || terminal_is_wezterm()) {
1305
+ return "iterm";
1306
+ }
1307
+ if (terminal_is_kitty()) {
1308
+ return "kitty";
1309
+ }
1310
+ return "symbols";
1311
+ }
1224
1312
 
1225
1313
  static bool terminal_url_is_http(const char *url) {
1226
1314
  if (!url || !*url) {
@@ -1346,18 +1434,25 @@ static bool executable_on_path(const char *name) {
1346
1434
  }
1347
1435
 
1348
1436
  static term_img_tool_t probe_terminal_image_tool(void) {
1349
- if (executable_on_path("imgcat")) {
1437
+ if (g_term_paginate_symbols) {
1438
+ if (executable_on_path("chafa")) {
1439
+ return TERM_IMG_CHAFA;
1440
+ }
1441
+ return TERM_IMG_NONE;
1442
+ }
1443
+ /* imgcat only works in iTerm2; using it elsewhere emits opaque escape data. */
1444
+ if (terminal_is_iterm() && executable_on_path("imgcat")) {
1350
1445
  return TERM_IMG_IMGCAT;
1351
1446
  }
1352
1447
  if (executable_on_path("chafa")) {
1353
1448
  return TERM_IMG_CHAFA;
1354
1449
  }
1355
- if (executable_on_path("viu")) {
1356
- return TERM_IMG_VIU;
1357
- }
1358
1450
  if (executable_on_path("catimg")) {
1359
1451
  return TERM_IMG_CATIMG;
1360
1452
  }
1453
+ if (executable_on_path("viu")) {
1454
+ return TERM_IMG_VIU;
1455
+ }
1361
1456
  return TERM_IMG_NONE;
1362
1457
  }
1363
1458
 
@@ -1458,7 +1553,7 @@ static bool run_terminal_image_tool(terminal_buffer *buf, term_img_tool_t tool,
1458
1553
  char wstr[32];
1459
1554
  snprintf(wstr, sizeof(wstr), "%d", width);
1460
1555
 
1461
- const char *argv[8];
1556
+ const char *argv[16];
1462
1557
  int argc = 0;
1463
1558
  switch (tool) {
1464
1559
  case TERM_IMG_IMGCAT:
@@ -1467,14 +1562,24 @@ static bool run_terminal_image_tool(terminal_buffer *buf, term_img_tool_t tool,
1467
1562
  argv[argc++] = wstr;
1468
1563
  argv[argc++] = (char *)abspath;
1469
1564
  break;
1470
- case TERM_IMG_CHAFA:
1565
+ case TERM_IMG_CHAFA: {
1566
+ const char *colors = g_term_use_256 ? "256" : "16";
1567
+ const char *format = g_term_paginate_symbols ? "symbols" : terminal_chafa_format();
1471
1568
  argv[argc++] = "chafa";
1569
+ argv[argc++] = "-f";
1570
+ argv[argc++] = format;
1571
+ argv[argc++] = "-c";
1572
+ argv[argc++] = colors;
1472
1573
  argv[argc++] = "-s";
1473
1574
  argv[argc++] = wstr;
1474
1575
  argv[argc++] = (char *)abspath;
1475
1576
  break;
1577
+ }
1476
1578
  case TERM_IMG_VIU:
1477
1579
  argv[argc++] = "viu";
1580
+ if (!terminal_supports_inline_graphics()) {
1581
+ argv[argc++] = "-b";
1582
+ }
1478
1583
  argv[argc++] = "-w";
1479
1584
  argv[argc++] = wstr;
1480
1585
  argv[argc++] = (char *)abspath;
@@ -1490,6 +1595,8 @@ static bool run_terminal_image_tool(terminal_buffer *buf, term_img_tool_t tool,
1490
1595
  }
1491
1596
  argv[argc] = NULL;
1492
1597
 
1598
+ terminal_debug_log_argv(argv);
1599
+
1493
1600
  int out_pipe[2];
1494
1601
  if (pipe(out_pipe) != 0) {
1495
1602
  return false;
@@ -1559,10 +1666,17 @@ static bool run_terminal_image_tool(terminal_buffer *buf, term_img_tool_t tool,
1559
1666
  waitpid(pid, &status, 0);
1560
1667
 
1561
1668
  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
1669
+ if (terminal_debug_enabled()) {
1670
+ fprintf(stderr, "[APEX_DEBUG_TERMINAL] image tool exit status=%d\n", status);
1671
+ }
1562
1672
  free(out);
1563
1673
  return false;
1564
1674
  }
1565
1675
 
1676
+ if (terminal_debug_enabled()) {
1677
+ fprintf(stderr, "[APEX_DEBUG_TERMINAL] image tool wrote %zu bytes\n", size);
1678
+ }
1679
+
1566
1680
  bool need_nl = (size == 0 || out[size - 1] != '\n');
1567
1681
  buffer_append(buf, out, size);
1568
1682
  free(out);
@@ -1595,7 +1709,7 @@ static void serialize_inline(terminal_buffer *buf,
1595
1709
  char *emoji_replaced = NULL;
1596
1710
  if (options &&
1597
1711
  (options->mode == APEX_MODE_GFM ||
1598
- options->mode == APEX_MODE_UNIFIED)) {
1712
+ apex_mode_is_unified_family(options->mode))) {
1599
1713
  emoji_replaced = apex_replace_emoji_text(literal);
1600
1714
  if (emoji_replaced) {
1601
1715
  text_src = emoji_replaced;
@@ -1745,6 +1859,11 @@ static void serialize_inline(terminal_buffer *buf,
1745
1859
  char altbuf[512];
1746
1860
  collect_image_alt_text(node, altbuf, sizeof(altbuf));
1747
1861
  const char *title = cmark_node_get_title(node);
1862
+ if (terminal_debug_enabled()) {
1863
+ fprintf(stderr,
1864
+ "[APEX_DEBUG_TERMINAL] image url=%s path=%s tool=%s\n",
1865
+ url, path_to_show, term_img_tool_name(g_term_img_tool));
1866
+ }
1748
1867
  if (run_terminal_image_tool(buf, g_term_img_tool, g_term_img_width, path_to_show)) {
1749
1868
  append_terminal_image_caption(buf, path_to_show, title, altbuf, options, theme,
1750
1869
  use_256_color);
@@ -1758,6 +1877,21 @@ static void serialize_inline(terminal_buffer *buf,
1758
1877
  }
1759
1878
  }
1760
1879
  if (!did_inline) {
1880
+ if (terminal_debug_enabled() && url) {
1881
+ const char *reason = "unknown";
1882
+ if (!options || !options->terminal_inline_images) {
1883
+ reason = "terminal_inline_images disabled";
1884
+ } else if (!isatty(STDOUT_FILENO)) {
1885
+ reason = "stdout is not a TTY";
1886
+ } else if (g_term_img_tool == TERM_IMG_NONE) {
1887
+ reason = "no image viewer on PATH";
1888
+ } else {
1889
+ reason = "path resolve or viewer failed";
1890
+ }
1891
+ fprintf(stderr,
1892
+ "[APEX_DEBUG_TERMINAL] image fallback (%s) url=%s\n",
1893
+ reason, url);
1894
+ }
1761
1895
  serialize_terminal_image_as_link(buf, node, url, options, theme, use_256_color);
1762
1896
  }
1763
1897
  break;
@@ -2589,6 +2723,9 @@ static void serialize_block(terminal_buffer *buf,
2589
2723
  }
2590
2724
 
2591
2725
  if (cmd[0]) {
2726
+ if (terminal_debug_enabled()) {
2727
+ fprintf(stderr, "[APEX_DEBUG_TERMINAL] highlight: %s\n", cmd);
2728
+ }
2592
2729
  /* Reuse run_command-style helper from syntax_highlight.c (local copy) */
2593
2730
  int in_pipe[2];
2594
2731
  int out_pipe[2];
@@ -2933,12 +3070,46 @@ char *apex_cmark_to_terminal(cmark_node *document,
2933
3070
  g_term_img_tool = TERM_IMG_NONE;
2934
3071
  g_term_img_width = 50;
2935
3072
  g_term_has_curl = executable_on_path("curl");
3073
+ g_term_use_256 = use_256;
3074
+ g_term_paginate_symbols = (options && options->paginate_symbols);
3075
+ g_terminal_output_len = 0;
2936
3076
  if (options && options->terminal_inline_images && isatty(STDOUT_FILENO)) {
2937
3077
  int w = options->terminal_image_width > 0 ? options->terminal_image_width : 50;
2938
3078
  g_term_img_width = w;
2939
3079
  g_term_img_tool = probe_terminal_image_tool();
2940
3080
  }
2941
3081
 
3082
+ if (terminal_debug_enabled()) {
3083
+ fprintf(stderr,
3084
+ "[APEX_DEBUG_TERMINAL] use_256=%d stdout_tty=%d paginate=%d paginate_symbols=%d inline_images=%d\n",
3085
+ use_256 ? 1 : 0,
3086
+ isatty(STDOUT_FILENO) ? 1 : 0,
3087
+ (options && options->paginate) ? 1 : 0,
3088
+ g_term_paginate_symbols ? 1 : 0,
3089
+ (options && options->terminal_inline_images) ? 1 : 0);
3090
+ fprintf(stderr,
3091
+ "[APEX_DEBUG_TERMINAL] TERM_PROGRAM=%s iterm=%d kitty=%d wezterm=%d chafa_format=%s\n",
3092
+ getenv("TERM_PROGRAM") ? getenv("TERM_PROGRAM") : "(unset)",
3093
+ terminal_is_iterm() ? 1 : 0,
3094
+ terminal_is_kitty() ? 1 : 0,
3095
+ terminal_is_wezterm() ? 1 : 0,
3096
+ g_term_paginate_symbols ? "symbols" : terminal_chafa_format());
3097
+ terminal_debug_log_tool_path("imgcat");
3098
+ terminal_debug_log_tool_path("chafa");
3099
+ terminal_debug_log_tool_path("catimg");
3100
+ terminal_debug_log_tool_path("viu");
3101
+ terminal_debug_log_tool_path("curl");
3102
+ fprintf(stderr,
3103
+ "[APEX_DEBUG_TERMINAL] selected image tool: %s (width=%d)\n",
3104
+ term_img_tool_name(g_term_img_tool), g_term_img_width);
3105
+ if (options && options->code_highlighter) {
3106
+ fprintf(stderr,
3107
+ "[APEX_DEBUG_TERMINAL] code_highlighter=%s theme=%s\n",
3108
+ options->code_highlighter,
3109
+ options->code_highlight_theme ? options->code_highlight_theme : "(default)");
3110
+ }
3111
+ }
3112
+
2942
3113
  terminal_theme *theme = load_theme(options);
2943
3114
  if (getenv("APEX_DEBUG_THEME")) {
2944
3115
  const char *tname = (options && options->theme_name) ? options->theme_name : "(null)";
@@ -2959,9 +3130,15 @@ char *apex_cmark_to_terminal(cmark_node *document,
2959
3130
  /* Fallback: empty string */
2960
3131
  char *empty = (char *)malloc(1);
2961
3132
  if (empty) empty[0] = '\0';
3133
+ g_terminal_output_len = 0;
2962
3134
  return empty;
2963
3135
  }
2964
3136
 
3137
+ g_terminal_output_len = buf.len;
2965
3138
  return buf.buf;
2966
3139
  }
2967
3140
 
3141
+ size_t apex_terminal_output_length(void) {
3142
+ return g_terminal_output_len;
3143
+ }
3144
+
@@ -129,9 +129,13 @@ abbr_item *apex_extract_abbreviations(char **text_ptr) {
129
129
  while ((line_end = strchr(line_start, '\n')) != NULL || *line_start) {
130
130
  if (!line_end) line_end = line_start + strlen(line_start);
131
131
 
132
- size_t line_len = line_end - line_start;
133
- char line[1024];
134
- if (line_len >= sizeof(line)) line_len = sizeof(line) - 1;
132
+ size_t line_len = (size_t)(line_end - line_start);
133
+ char *line = malloc(line_len + 1);
134
+ if (!line) {
135
+ apex_free_abbreviations(abbrs);
136
+ free(output);
137
+ return NULL;
138
+ }
135
139
  memcpy(line, line_start, line_len);
136
140
  line[line_len] = '\0';
137
141
 
@@ -157,6 +161,7 @@ abbr_item *apex_extract_abbreviations(char **text_ptr) {
157
161
  }
158
162
 
159
163
  /* Skip this line in output */
164
+ free(line);
160
165
  line_start = *line_end ? line_end + 1 : line_end;
161
166
  continue;
162
167
  }
@@ -184,6 +189,7 @@ abbr_item *apex_extract_abbreviations(char **text_ptr) {
184
189
  }
185
190
 
186
191
  /* Skip this line in output */
192
+ free(line);
187
193
  line_start = *line_end ? line_end + 1 : line_end;
188
194
  continue;
189
195
  }
@@ -192,6 +198,7 @@ abbr_item *apex_extract_abbreviations(char **text_ptr) {
192
198
  /* Not an abbreviation, copy line to output */
193
199
  memcpy(output_write, line_start, line_len);
194
200
  output_write += line_len;
201
+ free(line);
195
202
  if (*line_end) {
196
203
  *output_write++ = '\n';
197
204
  line_start = line_end + 1;
@@ -1643,12 +1643,9 @@ cmark_node *apex_process_advanced_tables(cmark_node *root) {
1643
1643
  }
1644
1644
  }
1645
1645
  }
1646
- /* Found non-blank paragraph that's not a caption - continue looking
1647
- * backwards in case there's a caption further up (e.g., after a header
1648
- * and regular paragraph) */
1649
- prev = cmark_node_previous(prev);
1650
- /* Continue loop to check the next node (prev is checked at start of while) */
1651
- continue;
1646
+ /* Found the nearest non-blank paragraph and it is not a caption.
1647
+ * Stop searching so a distant caption cannot leak forward to this table. */
1648
+ break;
1652
1649
  }
1653
1650
  /* This paragraph is blank, continue to previous sibling */
1654
1651
  prev = cmark_node_previous(prev);
@@ -1659,13 +1656,12 @@ cmark_node *apex_process_advanced_tables(cmark_node *root) {
1659
1656
  /* Headers can appear between caption and table, so continue looking */
1660
1657
  /* But stop for other block types that shouldn't have captions after them */
1661
1658
  if (prev_type == CMARK_NODE_HEADING) {
1662
- /* Header found - continue looking backwards for caption */
1663
- prev = cmark_node_previous(prev);
1664
- continue;
1665
- } else {
1666
- /* Other block type - stop looking */
1659
+ /* The closest previous non-blank node is a heading, so stop.
1660
+ * Do not skip backwards across headings when resolving captions. */
1667
1661
  break;
1668
1662
  }
1663
+ /* Other block type - stop looking */
1664
+ break;
1669
1665
  }
1670
1666
  }
1671
1667