apex-ruby 1.0.6

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 (501) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +119 -0
  3. data/apex-ruby.gemspec +31 -0
  4. data/ext/apex_ext/apex_ext.c +215 -0
  5. data/ext/apex_ext/apex_src/BENCHMARK.md +32 -0
  6. data/ext/apex_ext/apex_src/BENCHMARK_COMPARISON.md +67 -0
  7. data/ext/apex_ext/apex_src/CHANGELOG.md +2454 -0
  8. data/ext/apex_ext/apex_src/CMakeLists.txt +454 -0
  9. data/ext/apex_ext/apex_src/Dockerfile.linux-build +15 -0
  10. data/ext/apex_ext/apex_src/Formula/apex.rb +38 -0
  11. data/ext/apex_ext/apex_src/Info.plist.in +27 -0
  12. data/ext/apex_ext/apex_src/LICENSE +21 -0
  13. data/ext/apex_ext/apex_src/Package.swift +160 -0
  14. data/ext/apex_ext/apex_src/PackageSupport/README.md +17 -0
  15. data/ext/apex_ext/apex_src/PackageSupport/cmark-gfm/cmark-gfm_export.h +20 -0
  16. data/ext/apex_ext/apex_src/PackageSupport/cmark-gfm/cmark-gfm_version.h +14 -0
  17. data/ext/apex_ext/apex_src/PackageSupport/cmark-gfm/cmark_gfm_spm_stub.c +4 -0
  18. data/ext/apex_ext/apex_src/PackageSupport/cmark-gfm/config.h +41 -0
  19. data/ext/apex_ext/apex_src/README.md +452 -0
  20. data/ext/apex_ext/apex_src/VERSION +1 -0
  21. data/ext/apex_ext/apex_src/apex-header-2-rb@2x.webp +0 -0
  22. data/ext/apex_ext/apex_src/apex-plugins.json.example +20 -0
  23. data/ext/apex_ext/apex_src/apex.pc.in +11 -0
  24. data/ext/apex_ext/apex_src/cli/main.c +2720 -0
  25. data/ext/apex_ext/apex_src/debug_test.sh +22 -0
  26. data/ext/apex_ext/apex_src/docs/API_REFERENCE.md +451 -0
  27. data/ext/apex_ext/apex_src/docs/ARCHITECTURE.md +166 -0
  28. data/ext/apex_ext/apex_src/docs/CMARK_INTEGRATION.md +220 -0
  29. data/ext/apex_ext/apex_src/docs/CRITICMARKUP.md +501 -0
  30. data/ext/apex_ext/apex_src/docs/DEBUGGING.md +73 -0
  31. data/ext/apex_ext/apex_src/docs/FINAL_STATUS.md +391 -0
  32. data/ext/apex_ext/apex_src/docs/FINAL_STATUS_UPDATE.md +237 -0
  33. data/ext/apex_ext/apex_src/docs/FUTURE_FEATURES.md +456 -0
  34. data/ext/apex_ext/apex_src/docs/IAL_FEATURES.md +210 -0
  35. data/ext/apex_ext/apex_src/docs/IAL_STATUS.md +344 -0
  36. data/ext/apex_ext/apex_src/docs/INTEGRATION_EXAMPLE.m +144 -0
  37. data/ext/apex_ext/apex_src/docs/LIMITATIONS_RESOLVED.md +278 -0
  38. data/ext/apex_ext/apex_src/docs/OUTPUT_MODES.md +321 -0
  39. data/ext/apex_ext/apex_src/docs/PROGRESS.md +167 -0
  40. data/ext/apex_ext/apex_src/docs/STANDALONE_FEATURE.md +174 -0
  41. data/ext/apex_ext/apex_src/docs/TABLE_SPANS_STATUS.md +243 -0
  42. data/ext/apex_ext/apex_src/docs/TEST_COVERAGE.md +316 -0
  43. data/ext/apex_ext/apex_src/docs/USER_GUIDE.md +803 -0
  44. data/ext/apex_ext/apex_src/docs/WIKI_LINKS_ISSUE.md +91 -0
  45. data/ext/apex_ext/apex_src/documentation/README.md +160 -0
  46. data/ext/apex_ext/apex_src/documentation/docsets/Apex Command Line Options.cheatsheet.txt +365 -0
  47. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Info.plist +24 -0
  48. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/C-API.html +1737 -0
  49. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Citations.html +1420 -0
  50. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Command-Line-Options.html +3574 -0
  51. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Configuration.html +1603 -0
  52. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Credits.html +910 -0
  53. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Examples.html +1168 -0
  54. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Getting-Started.html +1003 -0
  55. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Header-IDs.html +1308 -0
  56. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Home.html +1078 -0
  57. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Inline-Attribute-Lists.html +1622 -0
  58. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Installation.html +1168 -0
  59. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Limitations-and-Roadmap.html +1698 -0
  60. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Metadata-Transforms.html +1531 -0
  61. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Modes.html +1980 -0
  62. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Multi-File-Documents.html +1368 -0
  63. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Pandoc-Integration.html +1151 -0
  64. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Plugins.html +2861 -0
  65. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Syntax.html +3981 -0
  66. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Troubleshooting.html +1454 -0
  67. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Usage.html +1200 -0
  68. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Xcode-Integration.html +2066 -0
  69. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/docSet.dsidx +0 -0
  70. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/optimizedIndex.dsidx +0 -0
  71. data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/tempOptimizedIndex.dsidx +0 -0
  72. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Info.plist +22 -0
  73. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/Documents/cheatset_resources/Open_Sans.woff +0 -0
  74. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/Documents/cheatset_resources/Open_Sans_Bold.woff +0 -0
  75. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/Documents/cheatset_resources/Open_Sans_Bold_Italic.woff +0 -0
  76. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/Documents/cheatset_resources/Open_Sans_Extrabold.woff +0 -0
  77. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/Documents/cheatset_resources/Open_Sans_Extrabold_Italic.woff +0 -0
  78. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/Documents/cheatset_resources/Open_Sans_Italic.woff +0 -0
  79. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/Documents/cheatset_resources/Open_Sans_Semibold.woff +0 -0
  80. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/Documents/cheatset_resources/Open_Sans_Semibold_Italic.woff +0 -0
  81. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/Documents/index.html +914 -0
  82. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/Documents/style.css +399 -0
  83. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/docSet.dsidx +0 -0
  84. data/ext/apex_ext/apex_src/documentation/docsets/ApexCLI.docset/Contents/Resources/optimizedIndex.dsidx +0 -0
  85. data/ext/apex_ext/apex_src/documentation/generate_app_docs.rb +772 -0
  86. data/ext/apex_ext/apex_src/documentation/generate_app_docs_ai.rb +678 -0
  87. data/ext/apex_ext/apex_src/documentation/generate_docset.rb +873 -0
  88. data/ext/apex_ext/apex_src/documentation/generate_single_html.rb +733 -0
  89. data/ext/apex_ext/apex_src/documentation/html/apex-docs.html +17073 -0
  90. data/ext/apex_ext/apex_src/documentation/shared_scripts.js +64 -0
  91. data/ext/apex_ext/apex_src/documentation/shared_styles.css +646 -0
  92. data/ext/apex_ext/apex_src/documentation/transform_for_app.example.md +260 -0
  93. data/ext/apex_ext/apex_src/examples/bracketed_spans_demo.md +119 -0
  94. data/ext/apex_ext/apex_src/examples/emoji_span_plugin.yml +11 -0
  95. data/ext/apex_ext/apex_src/examples/example.html +53 -0
  96. data/ext/apex_ext/apex_src/examples/example.md +85 -0
  97. data/ext/apex_ext/apex_src/examples/fenced_divs_demo.md +158 -0
  98. data/ext/apex_ext/apex_src/examples/kbd.md +8 -0
  99. data/ext/apex_ext/apex_src/examples/kbd_plugin.rb +250 -0
  100. data/ext/apex_ext/apex_src/examples/kbd_plugin.yml +9 -0
  101. data/ext/apex_ext/apex_src/icon/apexicon-outline-black.png +0 -0
  102. data/ext/apex_ext/apex_src/icon/apexicon-outline-black@2x.png +0 -0
  103. data/ext/apex_ext/apex_src/icon/apexicon-outline-mark.png +0 -0
  104. data/ext/apex_ext/apex_src/icon/apexicon-outline-mark@2x.png +0 -0
  105. data/ext/apex_ext/apex_src/icon/apexicon-outline-white.png +0 -0
  106. data/ext/apex_ext/apex_src/icon/apexicon-outline-white@2x.png +0 -0
  107. data/ext/apex_ext/apex_src/icon/apexicon.png +0 -0
  108. data/ext/apex_ext/apex_src/icon/apexicon@2x.png +0 -0
  109. data/ext/apex_ext/apex_src/include/apex/apex.h +247 -0
  110. data/ext/apex_ext/apex_src/include/apex/buffer.h +93 -0
  111. data/ext/apex_ext/apex_src/include/apex/module.modulemap +16 -0
  112. data/ext/apex_ext/apex_src/include/apex/parser.h +150 -0
  113. data/ext/apex_ext/apex_src/include/apex/renderer.h +39 -0
  114. data/ext/apex_ext/apex_src/man/apex-config.5 +374 -0
  115. data/ext/apex_ext/apex_src/man/apex-config.5.md +260 -0
  116. data/ext/apex_ext/apex_src/man/apex-plugins.7 +456 -0
  117. data/ext/apex_ext/apex_src/man/apex-plugins.7.md +365 -0
  118. data/ext/apex_ext/apex_src/man/apex.1 +828 -0
  119. data/ext/apex_ext/apex_src/man/apex.1.md +643 -0
  120. data/ext/apex_ext/apex_src/man/apex.1.new +338 -0
  121. data/ext/apex_ext/apex_src/objc/Apex.swift +237 -0
  122. data/ext/apex_ext/apex_src/objc/NSString+Apex.h +117 -0
  123. data/ext/apex_ext/apex_src/objc/NSString+Apex.m +332 -0
  124. data/ext/apex_ext/apex_src/src/_README.md +358 -0
  125. data/ext/apex_ext/apex_src/src/apex.c +6326 -0
  126. data/ext/apex_ext/apex_src/src/buffer.c +93 -0
  127. data/ext/apex_ext/apex_src/src/extensions/abbreviations.c +362 -0
  128. data/ext/apex_ext/apex_src/src/extensions/abbreviations.h +45 -0
  129. data/ext/apex_ext/apex_src/src/extensions/advanced_footnotes.c +184 -0
  130. data/ext/apex_ext/apex_src/src/extensions/advanced_footnotes.h +50 -0
  131. data/ext/apex_ext/apex_src/src/extensions/advanced_tables.c +1897 -0
  132. data/ext/apex_ext/apex_src/src/extensions/advanced_tables.h +42 -0
  133. data/ext/apex_ext/apex_src/src/extensions/callouts.c +215 -0
  134. data/ext/apex_ext/apex_src/src/extensions/callouts.h +53 -0
  135. data/ext/apex_ext/apex_src/src/extensions/citations.c +2042 -0
  136. data/ext/apex_ext/apex_src/src/extensions/citations.h +163 -0
  137. data/ext/apex_ext/apex_src/src/extensions/critic.c +329 -0
  138. data/ext/apex_ext/apex_src/src/extensions/critic.h +48 -0
  139. data/ext/apex_ext/apex_src/src/extensions/definition_list.c +1670 -0
  140. data/ext/apex_ext/apex_src/src/extensions/definition_list.h +42 -0
  141. data/ext/apex_ext/apex_src/src/extensions/emoji.c +710 -0
  142. data/ext/apex_ext/apex_src/src/extensions/emoji.h +38 -0
  143. data/ext/apex_ext/apex_src/src/extensions/emoji_data.h +942 -0
  144. data/ext/apex_ext/apex_src/src/extensions/fenced_divs.c +925 -0
  145. data/ext/apex_ext/apex_src/src/extensions/fenced_divs.h +43 -0
  146. data/ext/apex_ext/apex_src/src/extensions/github-emoji.txt +869 -0
  147. data/ext/apex_ext/apex_src/src/extensions/grid_tables.c +1121 -0
  148. data/ext/apex_ext/apex_src/src/extensions/grid_tables.h +33 -0
  149. data/ext/apex_ext/apex_src/src/extensions/header_ids.c +626 -0
  150. data/ext/apex_ext/apex_src/src/extensions/header_ids.h +60 -0
  151. data/ext/apex_ext/apex_src/src/extensions/highlight.c +135 -0
  152. data/ext/apex_ext/apex_src/src/extensions/highlight.h +16 -0
  153. data/ext/apex_ext/apex_src/src/extensions/html_markdown.c +408 -0
  154. data/ext/apex_ext/apex_src/src/extensions/html_markdown.h +42 -0
  155. data/ext/apex_ext/apex_src/src/extensions/ial.c +4084 -0
  156. data/ext/apex_ext/apex_src/src/extensions/ial.h +145 -0
  157. data/ext/apex_ext/apex_src/src/extensions/includes.c +1536 -0
  158. data/ext/apex_ext/apex_src/src/extensions/includes.h +54 -0
  159. data/ext/apex_ext/apex_src/src/extensions/index.c +967 -0
  160. data/ext/apex_ext/apex_src/src/extensions/index.h +90 -0
  161. data/ext/apex_ext/apex_src/src/extensions/inline_footnotes.c +205 -0
  162. data/ext/apex_ext/apex_src/src/extensions/inline_footnotes.h +34 -0
  163. data/ext/apex_ext/apex_src/src/extensions/inline_tables.c +332 -0
  164. data/ext/apex_ext/apex_src/src/extensions/inline_tables.h +13 -0
  165. data/ext/apex_ext/apex_src/src/extensions/insert.c +248 -0
  166. data/ext/apex_ext/apex_src/src/extensions/insert.h +18 -0
  167. data/ext/apex_ext/apex_src/src/extensions/math.c +279 -0
  168. data/ext/apex_ext/apex_src/src/extensions/math.h +32 -0
  169. data/ext/apex_ext/apex_src/src/extensions/metadata.c +3046 -0
  170. data/ext/apex_ext/apex_src/src/extensions/metadata.h +125 -0
  171. data/ext/apex_ext/apex_src/src/extensions/relaxed_tables.c +1297 -0
  172. data/ext/apex_ext/apex_src/src/extensions/relaxed_tables.h +39 -0
  173. data/ext/apex_ext/apex_src/src/extensions/special_markers.c +194 -0
  174. data/ext/apex_ext/apex_src/src/extensions/special_markers.h +29 -0
  175. data/ext/apex_ext/apex_src/src/extensions/sup_sub.c +405 -0
  176. data/ext/apex_ext/apex_src/src/extensions/sup_sub.h +16 -0
  177. data/ext/apex_ext/apex_src/src/extensions/syntax_highlight.c +468 -0
  178. data/ext/apex_ext/apex_src/src/extensions/syntax_highlight.h +44 -0
  179. data/ext/apex_ext/apex_src/src/extensions/table_html_postprocess.c +2679 -0
  180. data/ext/apex_ext/apex_src/src/extensions/table_html_postprocess.h +23 -0
  181. data/ext/apex_ext/apex_src/src/extensions/toc.c +255 -0
  182. data/ext/apex_ext/apex_src/src/extensions/toc.h +34 -0
  183. data/ext/apex_ext/apex_src/src/extensions/wiki_links.c +624 -0
  184. data/ext/apex_ext/apex_src/src/extensions/wiki_links.h +58 -0
  185. data/ext/apex_ext/apex_src/src/html_renderer.c +2762 -0
  186. data/ext/apex_ext/apex_src/src/html_renderer.h +126 -0
  187. data/ext/apex_ext/apex_src/src/parser.c +227 -0
  188. data/ext/apex_ext/apex_src/src/plugins.c +895 -0
  189. data/ext/apex_ext/apex_src/src/plugins.h +39 -0
  190. data/ext/apex_ext/apex_src/src/plugins_env.c +187 -0
  191. data/ext/apex_ext/apex_src/src/plugins_remote.c +263 -0
  192. data/ext/apex_ext/apex_src/src/pretty_html.c +358 -0
  193. data/ext/apex_ext/apex_src/src/renderer.c +241 -0
  194. data/ext/apex_ext/apex_src/src/utf8.c +56 -0
  195. data/ext/apex_ext/apex_src/test-linux-build.sh +20 -0
  196. data/ext/apex_ext/apex_src/test.html +103 -0
  197. data/ext/apex_ext/apex_src/test_coverage.sh +121 -0
  198. data/ext/apex_ext/apex_src/test_ial_fenced.md +6 -0
  199. data/ext/apex_ext/apex_src/test_math_norm.py +79 -0
  200. data/ext/apex_ext/apex_src/test_pandoc_output.html +48 -0
  201. data/ext/apex_ext/apex_src/test_spm.sh +107 -0
  202. data/ext/apex_ext/apex_src/tests/ApexSPMTest/main.swift +50 -0
  203. data/ext/apex_ext/apex_src/tests/BENCHMARK_RESULTS.md +229 -0
  204. data/ext/apex_ext/apex_src/tests/CMakeLists.txt +24 -0
  205. data/ext/apex_ext/apex_src/tests/README.md +146 -0
  206. data/ext/apex_ext/apex_src/tests/benchmark.sh +113 -0
  207. data/ext/apex_ext/apex_src/tests/benchmark_comparison.sh +166 -0
  208. data/ext/apex_ext/apex_src/tests/compare_header_ids.sh +31 -0
  209. data/ext/apex_ext/apex_src/tests/fixtures/basic/headers.md +25 -0
  210. data/ext/apex_ext/apex_src/tests/fixtures/basic/list-interruption.md +24 -0
  211. data/ext/apex_ext/apex_src/tests/fixtures/basic/misc_markup.md +33 -0
  212. data/ext/apex_ext/apex_src/tests/fixtures/basic/test_basic.md +26 -0
  213. data/ext/apex_ext/apex_src/tests/fixtures/code/code-blocks.md +260 -0
  214. data/ext/apex_ext/apex_src/tests/fixtures/combine_summary/SUMMARY.md +6 -0
  215. data/ext/apex_ext/apex_src/tests/fixtures/combine_summary/chapter1.md +7 -0
  216. data/ext/apex_ext/apex_src/tests/fixtures/combine_summary/index.txt +9 -0
  217. data/ext/apex_ext/apex_src/tests/fixtures/combine_summary/intro.md +5 -0
  218. data/ext/apex_ext/apex_src/tests/fixtures/combine_summary/section1_1.md +5 -0
  219. data/ext/apex_ext/apex_src/tests/fixtures/comprehensive_test.md +620 -0
  220. data/ext/apex_ext/apex_src/tests/fixtures/debug_ref_image_ial.md +3 -0
  221. data/ext/apex_ext/apex_src/tests/fixtures/demos/ial.md +11 -0
  222. data/ext/apex_ext/apex_src/tests/fixtures/demos/ial_demo.md +177 -0
  223. data/ext/apex_ext/apex_src/tests/fixtures/extensions/emoji-autocorrect.md +94 -0
  224. data/ext/apex_ext/apex_src/tests/fixtures/extensions/emoji_test.md +3 -0
  225. data/ext/apex_ext/apex_src/tests/fixtures/extensions/kbd_test.md +3 -0
  226. data/ext/apex_ext/apex_src/tests/fixtures/ial/bracketed_spans_test.md +74 -0
  227. data/ext/apex_ext/apex_src/tests/fixtures/images/image_and_encoding_test.md +27 -0
  228. data/ext/apex_ext/apex_src/tests/fixtures/images/multimarkdown_image_attributes_test.md +60 -0
  229. data/ext/apex_ext/apex_src/tests/fixtures/images/pandoc_ial_image_test.md +27 -0
  230. data/ext/apex_ext/apex_src/tests/fixtures/images/width_height_conversion_test.md +94 -0
  231. data/ext/apex_ext/apex_src/tests/fixtures/img-in-div.md +16 -0
  232. data/ext/apex_ext/apex_src/tests/fixtures/includes/code.py +4 -0
  233. data/ext/apex_ext/apex_src/tests/fixtures/includes/data.csv +5 -0
  234. data/ext/apex_ext/apex_src/tests/fixtures/includes/data.tsv +5 -0
  235. data/ext/apex_ext/apex_src/tests/fixtures/includes/image.png +2 -0
  236. data/ext/apex_ext/apex_src/tests/fixtures/includes/metadata_options.yml +11 -0
  237. data/ext/apex_ext/apex_src/tests/fixtures/includes/nested.md +8 -0
  238. data/ext/apex_ext/apex_src/tests/fixtures/includes/raw.html +4 -0
  239. data/ext/apex_ext/apex_src/tests/fixtures/includes/simple.md +7 -0
  240. data/ext/apex_ext/apex_src/tests/fixtures/includes/test_image.png +0 -0
  241. data/ext/apex_ext/apex_src/tests/fixtures/large_doc.md +1094 -0
  242. data/ext/apex_ext/apex_src/tests/fixtures/metadata_options.yml +11 -0
  243. data/ext/apex_ext/apex_src/tests/fixtures/output/gfm_header_id_test.md +96 -0
  244. data/ext/apex_ext/apex_src/tests/fixtures/output/test_citations.md +43 -0
  245. data/ext/apex_ext/apex_src/tests/fixtures/output/test_def_list_links.md +12 -0
  246. data/ext/apex_ext/apex_src/tests/fixtures/output/test_index_mmark.md +53 -0
  247. data/ext/apex_ext/apex_src/tests/fixtures/output/test_index_textindex.md +37 -0
  248. data/ext/apex_ext/apex_src/tests/fixtures/tables/advanced_tables_test.md +93 -0
  249. data/ext/apex_ext/apex_src/tests/fixtures/tables/inline_tables_test.md +38 -0
  250. data/ext/apex_ext/apex_src/tests/fixtures/tables/relaxed-table.md +12 -0
  251. data/ext/apex_ext/apex_src/tests/fixtures/tables/table_cr_line_endings.md +15 -0
  252. data/ext/apex_ext/apex_src/tests/fixtures/tables/table_no_trailing_newline.md +15 -0
  253. data/ext/apex_ext/apex_src/tests/generate_gfm_ids.sh +105 -0
  254. data/ext/apex_ext/apex_src/tests/generate_ial_demo.sh +143 -0
  255. data/ext/apex_ext/apex_src/tests/gfm_id_comparison_summary.md +96 -0
  256. data/ext/apex_ext/apex_src/tests/gh_api_test.md +6 -0
  257. data/ext/apex_ext/apex_src/tests/ial_demo.html +186 -0
  258. data/ext/apex_ext/apex_src/tests/include_code.py +19 -0
  259. data/ext/apex_ext/apex_src/tests/include_snippet.md +15 -0
  260. data/ext/apex_ext/apex_src/tests/multi_file_cli_test.sh +64 -0
  261. data/ext/apex_ext/apex_src/tests/sample_data.csv +7 -0
  262. data/ext/apex_ext/apex_src/tests/table_escaped_ltlt.md +4 -0
  263. data/ext/apex_ext/apex_src/tests/test_basic.c +74 -0
  264. data/ext/apex_ext/apex_src/tests/test_extensions.c +2116 -0
  265. data/ext/apex_ext/apex_src/tests/test_helpers.c +183 -0
  266. data/ext/apex_ext/apex_src/tests/test_helpers.h +91 -0
  267. data/ext/apex_ext/apex_src/tests/test_ial.c +282 -0
  268. data/ext/apex_ext/apex_src/tests/test_links.c +418 -0
  269. data/ext/apex_ext/apex_src/tests/test_marked_integration.c +265 -0
  270. data/ext/apex_ext/apex_src/tests/test_metadata.c +908 -0
  271. data/ext/apex_ext/apex_src/tests/test_output.c +1118 -0
  272. data/ext/apex_ext/apex_src/tests/test_plugins.c +219 -0
  273. data/ext/apex_ext/apex_src/tests/test_refs.bib +31 -0
  274. data/ext/apex_ext/apex_src/tests/test_runner.c +244 -0
  275. data/ext/apex_ext/apex_src/tests/test_syntax_highlight.c +198 -0
  276. data/ext/apex_ext/apex_src/tests/test_tables.c +862 -0
  277. data/ext/apex_ext/apex_src/tests/update_benchmarks.sh +9 -0
  278. data/ext/apex_ext/apex_src/tests/yaml_test.md +13 -0
  279. data/ext/apex_ext/apex_src/tests.rb +39 -0
  280. data/ext/apex_ext/apex_src/vendor/cmark-gfm/CMakeLists.txt +48 -0
  281. data/ext/apex_ext/apex_src/vendor/cmark-gfm/COPYING +170 -0
  282. data/ext/apex_ext/apex_src/vendor/cmark-gfm/CheckFileOffsetBits.c +14 -0
  283. data/ext/apex_ext/apex_src/vendor/cmark-gfm/CheckFileOffsetBits.cmake +43 -0
  284. data/ext/apex_ext/apex_src/vendor/cmark-gfm/FindAsan.cmake +74 -0
  285. data/ext/apex_ext/apex_src/vendor/cmark-gfm/Makefile.nmake +38 -0
  286. data/ext/apex_ext/apex_src/vendor/cmark-gfm/README.md +206 -0
  287. data/ext/apex_ext/apex_src/vendor/cmark-gfm/api_test/CMakeLists.txt +30 -0
  288. data/ext/apex_ext/apex_src/vendor/cmark-gfm/api_test/cplusplus.cpp +15 -0
  289. data/ext/apex_ext/apex_src/vendor/cmark-gfm/api_test/cplusplus.h +16 -0
  290. data/ext/apex_ext/apex_src/vendor/cmark-gfm/api_test/harness.c +111 -0
  291. data/ext/apex_ext/apex_src/vendor/cmark-gfm/api_test/harness.h +35 -0
  292. data/ext/apex_ext/apex_src/vendor/cmark-gfm/api_test/main.c +1169 -0
  293. data/ext/apex_ext/apex_src/vendor/cmark-gfm/appveyor.yml +21 -0
  294. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-bq-flat.md +16 -0
  295. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-bq-nested.md +13 -0
  296. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-code.md +11 -0
  297. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-fences.md +14 -0
  298. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-heading.md +9 -0
  299. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-hr.md +10 -0
  300. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-html.md +32 -0
  301. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-lheading.md +8 -0
  302. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-list-flat.md +67 -0
  303. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-list-nested.md +36 -0
  304. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-ref-flat.md +15 -0
  305. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/block-ref-nested.md +17 -0
  306. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/inline-autolink.md +14 -0
  307. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/inline-backticks.md +3 -0
  308. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/inline-em-flat.md +5 -0
  309. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/inline-em-nested.md +5 -0
  310. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/inline-em-worst.md +5 -0
  311. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/inline-entity.md +11 -0
  312. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/inline-escape.md +15 -0
  313. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/inline-html.md +44 -0
  314. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/inline-links-flat.md +23 -0
  315. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/inline-links-nested.md +13 -0
  316. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/inline-newlines.md +24 -0
  317. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/lorem1.md +13 -0
  318. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/samples/rawtabs.md +18 -0
  319. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/statistics.py +595 -0
  320. data/ext/apex_ext/apex_src/vendor/cmark-gfm/bench/stats.py +19 -0
  321. data/ext/apex_ext/apex_src/vendor/cmark-gfm/benchmarks.md +33 -0
  322. data/ext/apex_ext/apex_src/vendor/cmark-gfm/changelog.txt +1245 -0
  323. data/ext/apex_ext/apex_src/vendor/cmark-gfm/data/CaseFolding.txt +1495 -0
  324. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/CMakeLists.txt +119 -0
  325. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/autolink.c +508 -0
  326. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/autolink.h +8 -0
  327. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/cmark-gfm-core-extensions.h +54 -0
  328. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/core-extensions.c +27 -0
  329. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/ext_scanners.c +879 -0
  330. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/ext_scanners.h +24 -0
  331. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/ext_scanners.re +92 -0
  332. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/strikethrough.c +167 -0
  333. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/strikethrough.h +9 -0
  334. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/table.c +917 -0
  335. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/table.h +12 -0
  336. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/tagfilter.c +60 -0
  337. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/tagfilter.h +8 -0
  338. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/tasklist.c +156 -0
  339. data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/tasklist.h +8 -0
  340. data/ext/apex_ext/apex_src/vendor/cmark-gfm/fuzz/CMakeLists.txt +22 -0
  341. data/ext/apex_ext/apex_src/vendor/cmark-gfm/fuzz/README.md +12 -0
  342. data/ext/apex_ext/apex_src/vendor/cmark-gfm/fuzz/fuzz_quadratic.c +91 -0
  343. data/ext/apex_ext/apex_src/vendor/cmark-gfm/fuzz/fuzz_quadratic_brackets.c +110 -0
  344. data/ext/apex_ext/apex_src/vendor/cmark-gfm/fuzz/fuzzloop.sh +28 -0
  345. data/ext/apex_ext/apex_src/vendor/cmark-gfm/man/CMakeLists.txt +10 -0
  346. data/ext/apex_ext/apex_src/vendor/cmark-gfm/man/make_man_page.py +133 -0
  347. data/ext/apex_ext/apex_src/vendor/cmark-gfm/man/man1/cmark-gfm.1 +78 -0
  348. data/ext/apex_ext/apex_src/vendor/cmark-gfm/man/man3/cmark-gfm.3 +1041 -0
  349. data/ext/apex_ext/apex_src/vendor/cmark-gfm/nmake.bat +1 -0
  350. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/CMakeLists.txt +230 -0
  351. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/arena.c +104 -0
  352. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/blocks.c +1622 -0
  353. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/buffer.c +278 -0
  354. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/buffer.h +116 -0
  355. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/case_fold_switch.inc +4327 -0
  356. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/chunk.h +135 -0
  357. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/cmark-gfm-extension_api.h +737 -0
  358. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/cmark-gfm.h +833 -0
  359. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/cmark-gfm_version.h.in +7 -0
  360. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/cmark.c +55 -0
  361. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/cmark_ctype.c +44 -0
  362. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/cmark_ctype.h +33 -0
  363. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/commonmark.c +514 -0
  364. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/config.h.in +76 -0
  365. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/entities.inc +2138 -0
  366. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/footnotes.c +63 -0
  367. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/footnotes.h +27 -0
  368. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/houdini.h +57 -0
  369. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/houdini_href_e.c +100 -0
  370. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/houdini_html_e.c +66 -0
  371. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/houdini_html_u.c +149 -0
  372. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/html.c +502 -0
  373. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/html.h +27 -0
  374. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/inlines.c +1788 -0
  375. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/inlines.h +29 -0
  376. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/iterator.c +159 -0
  377. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/iterator.h +26 -0
  378. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/latex.c +468 -0
  379. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/libcmark-gfm.pc.in +10 -0
  380. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/linked_list.c +37 -0
  381. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/main.c +328 -0
  382. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/man.c +274 -0
  383. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/map.c +129 -0
  384. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/map.h +44 -0
  385. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/node.c +1045 -0
  386. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/node.h +167 -0
  387. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/parser.h +59 -0
  388. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/plaintext.c +218 -0
  389. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/plugin.c +36 -0
  390. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/plugin.h +34 -0
  391. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/references.c +43 -0
  392. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/references.h +26 -0
  393. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/registry.c +63 -0
  394. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/registry.h +24 -0
  395. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/render.c +213 -0
  396. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/render.h +62 -0
  397. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/scanners.c +14056 -0
  398. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/scanners.h +70 -0
  399. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/scanners.re +365 -0
  400. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/syntax_extension.c +149 -0
  401. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/syntax_extension.h +34 -0
  402. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/utf8.c +317 -0
  403. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/utf8.h +35 -0
  404. data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/xml.c +182 -0
  405. data/ext/apex_ext/apex_src/vendor/cmark-gfm/suppressions +10 -0
  406. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/CMakeLists.txt +114 -0
  407. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/afl_test_cases/test.md +49 -0
  408. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/cmark-fuzz.c +58 -0
  409. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/cmark.py +105 -0
  410. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/entity_tests.py +67 -0
  411. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/extensions-full-info-string.txt +0 -0
  412. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/extensions-table-prefer-style-attributes.txt +38 -0
  413. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/extensions.txt +920 -0
  414. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/fuzzing_dictionary +67 -0
  415. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/normalize.py +194 -0
  416. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/pathological_tests.py +160 -0
  417. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/regression.txt +375 -0
  418. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/roundtrip_tests.py +50 -0
  419. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/run-cmark-fuzz +4 -0
  420. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/smart_punct.txt +177 -0
  421. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/spec.txt +10212 -0
  422. data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/spec_tests.py +152 -0
  423. data/ext/apex_ext/apex_src/vendor/cmark-gfm/toolchain-mingw32.cmake +17 -0
  424. data/ext/apex_ext/apex_src/vendor/cmark-gfm/tools/Dockerfile +41 -0
  425. data/ext/apex_ext/apex_src/vendor/cmark-gfm/tools/appveyor-build.bat +13 -0
  426. data/ext/apex_ext/apex_src/vendor/cmark-gfm/tools/make_entities_inc.py +32 -0
  427. data/ext/apex_ext/apex_src/vendor/cmark-gfm/tools/mkcasefold.pl +22 -0
  428. data/ext/apex_ext/apex_src/vendor/cmark-gfm/tools/xml2md.xsl +319 -0
  429. data/ext/apex_ext/apex_src/vendor/cmark-gfm/tools/xml2md_gfm.xsl +80 -0
  430. data/ext/apex_ext/apex_src/vendor/cmark-gfm/why-cmark-and-not-x.md +104 -0
  431. data/ext/apex_ext/apex_src/vendor/cmark-gfm/wrappers/wrapper.js +6 -0
  432. data/ext/apex_ext/apex_src/vendor/cmark-gfm/wrappers/wrapper.py +37 -0
  433. data/ext/apex_ext/apex_src/vendor/cmark-gfm/wrappers/wrapper.rb +15 -0
  434. data/ext/apex_ext/apex_src/vendor/cmark-gfm/wrappers/wrapper.rkt +208 -0
  435. data/ext/apex_ext/apex_src/vendor/cmark-gfm/wrappers/wrapper_ext.py +109 -0
  436. data/ext/apex_ext/apex_src/vendor/libyaml/CMakeLists.txt +160 -0
  437. data/ext/apex_ext/apex_src/vendor/libyaml/Changes +372 -0
  438. data/ext/apex_ext/apex_src/vendor/libyaml/License +20 -0
  439. data/ext/apex_ext/apex_src/vendor/libyaml/Makefile.am +51 -0
  440. data/ext/apex_ext/apex_src/vendor/libyaml/ReadMe.md +46 -0
  441. data/ext/apex_ext/apex_src/vendor/libyaml/announcement.msg +89 -0
  442. data/ext/apex_ext/apex_src/vendor/libyaml/bootstrap +3 -0
  443. data/ext/apex_ext/apex_src/vendor/libyaml/cmake/config.h.in +4 -0
  444. data/ext/apex_ext/apex_src/vendor/libyaml/configure.ac +73 -0
  445. data/ext/apex_ext/apex_src/vendor/libyaml/doc/doxygen.cfg +222 -0
  446. data/ext/apex_ext/apex_src/vendor/libyaml/docker/README.mkd +17 -0
  447. data/ext/apex_ext/apex_src/vendor/libyaml/docker/alpine-3.7 +26 -0
  448. data/ext/apex_ext/apex_src/vendor/libyaml/docker/fedora-25 +26 -0
  449. data/ext/apex_ext/apex_src/vendor/libyaml/docker/ubuntu-14.04 +29 -0
  450. data/ext/apex_ext/apex_src/vendor/libyaml/docker/ubuntu-16.04 +24 -0
  451. data/ext/apex_ext/apex_src/vendor/libyaml/examples/anchors.yaml +10 -0
  452. data/ext/apex_ext/apex_src/vendor/libyaml/examples/array.yaml +2 -0
  453. data/ext/apex_ext/apex_src/vendor/libyaml/examples/global-tag.yaml +14 -0
  454. data/ext/apex_ext/apex_src/vendor/libyaml/examples/json.yaml +1 -0
  455. data/ext/apex_ext/apex_src/vendor/libyaml/examples/mapping.yaml +2 -0
  456. data/ext/apex_ext/apex_src/vendor/libyaml/examples/numbers.yaml +1 -0
  457. data/ext/apex_ext/apex_src/vendor/libyaml/examples/strings.yaml +7 -0
  458. data/ext/apex_ext/apex_src/vendor/libyaml/examples/tags.yaml +7 -0
  459. data/ext/apex_ext/apex_src/vendor/libyaml/examples/yaml-version.yaml +3 -0
  460. data/ext/apex_ext/apex_src/vendor/libyaml/include/Makefile.am +17 -0
  461. data/ext/apex_ext/apex_src/vendor/libyaml/include/yaml.h +1999 -0
  462. data/ext/apex_ext/apex_src/vendor/libyaml/pkg/ReadMe.md +77 -0
  463. data/ext/apex_ext/apex_src/vendor/libyaml/pkg/docker/Dockerfile +32 -0
  464. data/ext/apex_ext/apex_src/vendor/libyaml/pkg/docker/output/ReadMe +1 -0
  465. data/ext/apex_ext/apex_src/vendor/libyaml/pkg/docker/scripts/libyaml-dist.sh +23 -0
  466. data/ext/apex_ext/apex_src/vendor/libyaml/regression-inputs/clusterfuzz-testcase-minimized-5607885063061504.yml +1 -0
  467. data/ext/apex_ext/apex_src/vendor/libyaml/src/Makefile.am +4 -0
  468. data/ext/apex_ext/apex_src/vendor/libyaml/src/api.c +1393 -0
  469. data/ext/apex_ext/apex_src/vendor/libyaml/src/dumper.c +394 -0
  470. data/ext/apex_ext/apex_src/vendor/libyaml/src/emitter.c +2358 -0
  471. data/ext/apex_ext/apex_src/vendor/libyaml/src/loader.c +544 -0
  472. data/ext/apex_ext/apex_src/vendor/libyaml/src/parser.c +1416 -0
  473. data/ext/apex_ext/apex_src/vendor/libyaml/src/reader.c +469 -0
  474. data/ext/apex_ext/apex_src/vendor/libyaml/src/scanner.c +3598 -0
  475. data/ext/apex_ext/apex_src/vendor/libyaml/src/writer.c +141 -0
  476. data/ext/apex_ext/apex_src/vendor/libyaml/src/yaml_private.h +684 -0
  477. data/ext/apex_ext/apex_src/vendor/libyaml/tests/CMakeLists.txt +27 -0
  478. data/ext/apex_ext/apex_src/vendor/libyaml/tests/Makefile.am +9 -0
  479. data/ext/apex_ext/apex_src/vendor/libyaml/tests/ReadMe.md +63 -0
  480. data/ext/apex_ext/apex_src/vendor/libyaml/tests/example-deconstructor-alt.c +800 -0
  481. data/ext/apex_ext/apex_src/vendor/libyaml/tests/example-deconstructor.c +1127 -0
  482. data/ext/apex_ext/apex_src/vendor/libyaml/tests/example-reformatter-alt.c +217 -0
  483. data/ext/apex_ext/apex_src/vendor/libyaml/tests/example-reformatter.c +202 -0
  484. data/ext/apex_ext/apex_src/vendor/libyaml/tests/run-all-tests.sh +29 -0
  485. data/ext/apex_ext/apex_src/vendor/libyaml/tests/run-dumper.c +314 -0
  486. data/ext/apex_ext/apex_src/vendor/libyaml/tests/run-emitter-test-suite.c +290 -0
  487. data/ext/apex_ext/apex_src/vendor/libyaml/tests/run-emitter.c +327 -0
  488. data/ext/apex_ext/apex_src/vendor/libyaml/tests/run-loader.c +63 -0
  489. data/ext/apex_ext/apex_src/vendor/libyaml/tests/run-parser-test-suite.c +196 -0
  490. data/ext/apex_ext/apex_src/vendor/libyaml/tests/run-parser.c +88 -0
  491. data/ext/apex_ext/apex_src/vendor/libyaml/tests/run-scanner.c +63 -0
  492. data/ext/apex_ext/apex_src/vendor/libyaml/tests/test-reader.c +354 -0
  493. data/ext/apex_ext/apex_src/vendor/libyaml/tests/test-version.c +29 -0
  494. data/ext/apex_ext/apex_src/vendor/libyaml/yaml-0.1.pc.in +10 -0
  495. data/ext/apex_ext/apex_src/vendor/libyaml/yamlConfig.cmake.in +16 -0
  496. data/ext/apex_ext/extconf.rb +103 -0
  497. data/lib/apex/configurable.rb +46 -0
  498. data/lib/apex/document.rb +66 -0
  499. data/lib/apex/version.rb +15 -0
  500. data/lib/apex.rb +28 -0
  501. metadata +544 -0
@@ -0,0 +1,1536 @@
1
+ /**
2
+ * File Includes Extension for Apex
3
+ * Implementation
4
+ */
5
+
6
+ #include "includes.h"
7
+ #include "metadata.h"
8
+ #include <stdio.h>
9
+ #include <stdlib.h>
10
+ #include <string.h>
11
+ #include <sys/stat.h>
12
+ #include <libgen.h>
13
+ #include <unistd.h>
14
+ #include <ctype.h>
15
+ #include <stdbool.h>
16
+ #include <strings.h>
17
+ #include <regex.h>
18
+ #include <glob.h>
19
+
20
+ /**
21
+ * Read file contents
22
+ */
23
+ static char *read_file_contents(const char *filepath) {
24
+ FILE *fp = fopen(filepath, "rb");
25
+ if (!fp) return NULL;
26
+
27
+ /* Get file size */
28
+ fseek(fp, 0, SEEK_END);
29
+ long size = ftell(fp);
30
+ fseek(fp, 0, SEEK_SET);
31
+
32
+ if (size < 0 || size > 10 * 1024 * 1024) { /* Limit to 10MB */
33
+ fclose(fp);
34
+ return NULL;
35
+ }
36
+
37
+ /* Read content */
38
+ char *content = malloc(size + 1);
39
+ if (!content) {
40
+ fclose(fp);
41
+ return NULL;
42
+ }
43
+
44
+ size_t read = fread(content, 1, size, fp);
45
+ content[read] = '\0';
46
+ fclose(fp);
47
+
48
+ return content;
49
+ }
50
+
51
+ /**
52
+ * Resolve relative path from base directory
53
+ */
54
+ static char *resolve_path(const char *filepath, const char *base_dir) {
55
+ if (!filepath) return NULL;
56
+
57
+ /* If absolute path, return as-is */
58
+ if (filepath[0] == '/') {
59
+ return strdup(filepath);
60
+ }
61
+
62
+ /* Relative path - combine with base_dir */
63
+ if (!base_dir || !*base_dir) {
64
+ return strdup(filepath);
65
+ }
66
+
67
+ size_t len = strlen(base_dir) + strlen(filepath) + 2;
68
+ char *resolved = malloc(len);
69
+ if (!resolved) return NULL;
70
+
71
+ snprintf(resolved, len, "%s/%s", base_dir, filepath);
72
+ return resolved;
73
+ }
74
+
75
+ /**
76
+ * Get directory of a file path
77
+ */
78
+ static char *get_directory(const char *filepath) {
79
+ if (!filepath) return strdup(".");
80
+
81
+ char *path_copy = strdup(filepath);
82
+ if (!path_copy) return strdup(".");
83
+
84
+ char *dir = dirname(path_copy);
85
+ char *result = strdup(dir);
86
+ free(path_copy);
87
+
88
+ return result ? result : strdup(".");
89
+ }
90
+
91
+ /**
92
+ * Check if a file exists
93
+ */
94
+ bool apex_file_exists(const char *filepath) {
95
+ if (!filepath) return false;
96
+ struct stat st;
97
+ return (stat(filepath, &st) == 0);
98
+ }
99
+
100
+ /**
101
+ * File type enum
102
+ */
103
+ typedef enum {
104
+ FILE_TYPE_MARKDOWN,
105
+ FILE_TYPE_IMAGE,
106
+ FILE_TYPE_CODE,
107
+ FILE_TYPE_HTML,
108
+ FILE_TYPE_CSV,
109
+ FILE_TYPE_TSV,
110
+ FILE_TYPE_TEXT
111
+ } apex_file_type_t;
112
+
113
+ /**
114
+ * Address specification structure
115
+ */
116
+ typedef struct {
117
+ bool is_line_range;
118
+ bool is_regex_range;
119
+ int start_line; // 1-based
120
+ int end_line; // 1-based, -1 means to end
121
+ char *regex_start; // NULL if not regex
122
+ char *regex_end; // NULL if not regex
123
+ char *prefix; // NULL if no prefix
124
+ } address_spec_t;
125
+
126
+ /**
127
+ * Detect file type from extension
128
+ */
129
+ static apex_file_type_t apex_detect_file_type(const char *filepath) {
130
+ if (!filepath) return FILE_TYPE_TEXT;
131
+
132
+ const char *ext = strrchr(filepath, '.');
133
+ if (!ext) return FILE_TYPE_TEXT;
134
+ ext++;
135
+
136
+ /* Images */
137
+ if (strcasecmp(ext, "jpg") == 0 || strcasecmp(ext, "jpeg") == 0 ||
138
+ strcasecmp(ext, "png") == 0 || strcasecmp(ext, "gif") == 0 ||
139
+ strcasecmp(ext, "webp") == 0 || strcasecmp(ext, "svg") == 0) {
140
+ return FILE_TYPE_IMAGE;
141
+ }
142
+
143
+ /* CSV/TSV */
144
+ if (strcasecmp(ext, "csv") == 0) return FILE_TYPE_CSV;
145
+ if (strcasecmp(ext, "tsv") == 0) return FILE_TYPE_TSV;
146
+
147
+ /* HTML */
148
+ if (strcasecmp(ext, "html") == 0 || strcasecmp(ext, "htm") == 0) {
149
+ return FILE_TYPE_HTML;
150
+ }
151
+
152
+ /* Markdown */
153
+ if (strcasecmp(ext, "md") == 0 || strcasecmp(ext, "markdown") == 0 ||
154
+ strcasecmp(ext, "mmd") == 0) {
155
+ return FILE_TYPE_MARKDOWN;
156
+ }
157
+
158
+ /* Code files */
159
+ if (strcasecmp(ext, "c") == 0 || strcasecmp(ext, "h") == 0 ||
160
+ strcasecmp(ext, "cpp") == 0 || strcasecmp(ext, "py") == 0 ||
161
+ strcasecmp(ext, "js") == 0 || strcasecmp(ext, "java") == 0 ||
162
+ strcasecmp(ext, "swift") == 0 || strcasecmp(ext, "go") == 0 ||
163
+ strcasecmp(ext, "rs") == 0 || strcasecmp(ext, "sh") == 0) {
164
+ return FILE_TYPE_CODE;
165
+ }
166
+
167
+ return FILE_TYPE_TEXT;
168
+ }
169
+
170
+ /**
171
+ * Convert CSV/TSV to Markdown table
172
+ *
173
+ * Alignment handling:
174
+ * - First row is always treated as header.
175
+ * - If the second row cells are all one of: left, right, center, auto (case-insensitive),
176
+ * it is treated as an alignment row and converted to :---, ---:, :---:, or ---.
177
+ * The alignment row itself is NOT emitted as a data row.
178
+ * - Otherwise, a default '---' separator row is generated after the header.
179
+ * The second row (including rows that contain only '-' and ':' characters) is emitted
180
+ * as normal data.
181
+ */
182
+ char *apex_csv_to_table(const char *csv_content, bool is_tsv) {
183
+ if (!csv_content) return NULL;
184
+
185
+ char delim = is_tsv ? '\t' : ',';
186
+ size_t len = strlen(csv_content);
187
+ if (len == 0) return NULL;
188
+
189
+ /* First pass: parse into rows and cells */
190
+ typedef struct {
191
+ char **cells;
192
+ int cell_count;
193
+ } csv_row_t;
194
+
195
+ int row_cap = 8;
196
+ int row_count = 0;
197
+ csv_row_t *rows = calloc(row_cap, sizeof(csv_row_t));
198
+ if (!rows) return NULL;
199
+
200
+ const char *line_start = csv_content;
201
+ while (*line_start) {
202
+ const char *line_end = strchr(line_start, '\n');
203
+ if (!line_end) line_end = csv_content + strlen(csv_content);
204
+
205
+ /* Allocate new row */
206
+ if (row_count >= row_cap) {
207
+ row_cap *= 2;
208
+ csv_row_t *tmp = realloc(rows, (size_t)row_cap * sizeof(csv_row_t));
209
+ if (!tmp) {
210
+ /* Cleanup already allocated cells */
211
+ for (int r = 0; r < row_count; r++) {
212
+ for (int c = 0; c < rows[r].cell_count; c++) {
213
+ free(rows[r].cells[c]);
214
+ }
215
+ free(rows[r].cells);
216
+ }
217
+ free(rows);
218
+ return NULL;
219
+ }
220
+ rows = tmp;
221
+ }
222
+
223
+ csv_row_t *row = &rows[row_count];
224
+ row->cells = NULL;
225
+ row->cell_count = 0;
226
+
227
+ int cell_cap = 8;
228
+ row->cells = malloc((size_t)cell_cap * sizeof(char *));
229
+ if (!row->cells) {
230
+ for (int r = 0; r < row_count; r++) {
231
+ for (int c = 0; c < rows[r].cell_count; c++) {
232
+ free(rows[r].cells[c]);
233
+ }
234
+ free(rows[r].cells);
235
+ }
236
+ free(rows);
237
+ return NULL;
238
+ }
239
+
240
+ const char *cell_start = line_start;
241
+ while (cell_start <= line_end) {
242
+ const char *cell_end = cell_start;
243
+ while (cell_end < line_end && *cell_end != delim) cell_end++;
244
+
245
+ if (row->cell_count >= cell_cap) {
246
+ cell_cap *= 2;
247
+ char **tmp_cells = realloc(row->cells, (size_t)cell_cap * sizeof(char *));
248
+ if (!tmp_cells) {
249
+ /* Cleanup */
250
+ for (int r = 0; r <= row_count; r++) {
251
+ int max_c = (r == row_count) ? row->cell_count : rows[r].cell_count;
252
+ char **cell_arr = (r == row_count) ? row->cells : rows[r].cells;
253
+ if (cell_arr) {
254
+ for (int c = 0; c < max_c; c++) {
255
+ free(cell_arr[c]);
256
+ }
257
+ free(cell_arr);
258
+ }
259
+ }
260
+ free(rows);
261
+ return NULL;
262
+ }
263
+ row->cells = tmp_cells;
264
+ }
265
+
266
+ size_t cell_len = (size_t)(cell_end - cell_start);
267
+ char *cell = malloc(cell_len + 1);
268
+ if (!cell) {
269
+ for (int r = 0; r <= row_count; r++) {
270
+ int max_c = (r == row_count) ? row->cell_count : rows[r].cell_count;
271
+ char **cell_arr = (r == row_count) ? row->cells : rows[r].cells;
272
+ if (cell_arr) {
273
+ for (int c = 0; c < max_c; c++) {
274
+ free(cell_arr[c]);
275
+ }
276
+ free(cell_arr);
277
+ }
278
+ }
279
+ free(rows);
280
+ return NULL;
281
+ }
282
+ memcpy(cell, cell_start, cell_len);
283
+ cell[cell_len] = '\0';
284
+ row->cells[row->cell_count++] = cell;
285
+
286
+ if (cell_end < line_end) cell_start = cell_end + 1;
287
+ else break;
288
+ }
289
+
290
+ row_count++;
291
+
292
+ line_start = line_end;
293
+ if (*line_start == '\n') line_start++;
294
+ }
295
+
296
+ if (row_count == 0) {
297
+ free(rows);
298
+ return NULL;
299
+ }
300
+
301
+ /* Determine column count from first row */
302
+ int col_count = rows[0].cell_count;
303
+ if (col_count <= 0) {
304
+ for (int r = 0; r < row_count; r++) {
305
+ for (int c = 0; c < rows[r].cell_count; c++) free(rows[r].cells[c]);
306
+ free(rows[r].cells);
307
+ }
308
+ free(rows);
309
+ return NULL;
310
+ }
311
+
312
+ /* Check for alignment row (second row with keywords) */
313
+ bool has_alignment_row = false;
314
+ enum { ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_AUTO } *align = NULL;
315
+
316
+ if (row_count > 1) {
317
+ csv_row_t *arow = &rows[1];
318
+ bool all_keywords = (arow->cell_count == col_count);
319
+
320
+ if (all_keywords) {
321
+ align = malloc((size_t)col_count * sizeof(*align));
322
+ if (!align) {
323
+ for (int r = 0; r < row_count; r++) {
324
+ for (int c = 0; c < rows[r].cell_count; c++) free(rows[r].cells[c]);
325
+ free(rows[r].cells);
326
+ }
327
+ free(rows);
328
+ return NULL;
329
+ }
330
+
331
+ for (int i = 0; i < col_count; i++) {
332
+ char *cell = arow->cells[i];
333
+ /* Trim whitespace */
334
+ char *start = cell;
335
+ while (*start && isspace((unsigned char)*start)) start++;
336
+ char *end = start + strlen(start);
337
+ while (end > start && isspace((unsigned char)end[-1])) end--;
338
+ size_t tlen = (size_t)(end - start);
339
+
340
+ if (tlen == 0) { all_keywords = false; break; }
341
+
342
+ /* Lowercase copy for comparison */
343
+ char buf[16];
344
+ if (tlen >= sizeof(buf)) { all_keywords = false; break; }
345
+ for (size_t j = 0; j < tlen; j++) {
346
+ buf[j] = (char)tolower((unsigned char)start[j]);
347
+ }
348
+ buf[tlen] = '\0';
349
+
350
+ if (strcmp(buf, "left") == 0) {
351
+ align[i] = ALIGN_LEFT;
352
+ } else if (strcmp(buf, "right") == 0) {
353
+ align[i] = ALIGN_RIGHT;
354
+ } else if (strcmp(buf, "center") == 0) {
355
+ align[i] = ALIGN_CENTER;
356
+ } else if (strcmp(buf, "auto") == 0) {
357
+ align[i] = ALIGN_AUTO;
358
+ } else {
359
+ all_keywords = false;
360
+ break;
361
+ }
362
+ }
363
+
364
+ if (!all_keywords) {
365
+ free(align);
366
+ align = NULL;
367
+ } else {
368
+ has_alignment_row = true;
369
+ }
370
+ }
371
+ }
372
+
373
+ /* Allocate output buffer: original size * 4 should be enough with extra alignment row */
374
+ char *output = malloc(len * 4 + 64);
375
+ if (!output) {
376
+ if (align) free(align);
377
+ for (int r = 0; r < row_count; r++) {
378
+ for (int c = 0; c < rows[r].cell_count; c++) free(rows[r].cells[c]);
379
+ free(rows[r].cells);
380
+ }
381
+ free(rows);
382
+ return NULL;
383
+ }
384
+
385
+ char *write = output;
386
+
387
+ /* Emit header row (first row) */
388
+ {
389
+ csv_row_t *row = &rows[0];
390
+ *write++ = '|';
391
+ for (int c = 0; c < col_count; c++) {
392
+ *write++ = ' ';
393
+ if (c < row->cell_count && row->cells[c]) {
394
+ const char *val = row->cells[c];
395
+ size_t vlen = strlen(val);
396
+ memcpy(write, val, vlen);
397
+ write += vlen;
398
+ }
399
+ *write++ = ' ';
400
+ *write++ = '|';
401
+ }
402
+ *write++ = '\n';
403
+ }
404
+
405
+ /* Emit separator/alignment row */
406
+ *write++ = '|';
407
+ for (int c = 0; c < col_count; c++) {
408
+ const char *spec = " --- ";
409
+ if (has_alignment_row && align) {
410
+ switch (align[c]) {
411
+ case ALIGN_LEFT: spec = " :--- "; break;
412
+ case ALIGN_RIGHT: spec = " ---: "; break;
413
+ case ALIGN_CENTER: spec = " :---: "; break;
414
+ case ALIGN_AUTO: spec = " --- "; break;
415
+ }
416
+ }
417
+ size_t slen = strlen(spec);
418
+ memcpy(write, spec, slen);
419
+ write += slen;
420
+ *write++ = '|';
421
+ }
422
+ *write++ = '\n';
423
+
424
+ /* Emit data rows (skip alignment row if present) */
425
+ int start_row = has_alignment_row ? 2 : 1;
426
+ for (int r = start_row; r < row_count; r++) {
427
+ csv_row_t *row = &rows[r];
428
+ *write++ = '|';
429
+ for (int c = 0; c < col_count; c++) {
430
+ *write++ = ' ';
431
+ if (c < row->cell_count && row->cells[c]) {
432
+ const char *val = row->cells[c];
433
+ size_t vlen = strlen(val);
434
+ memcpy(write, val, vlen);
435
+ write += vlen;
436
+ }
437
+ *write++ = ' ';
438
+ *write++ = '|';
439
+ }
440
+ *write++ = '\n';
441
+ }
442
+
443
+ *write = '\0';
444
+
445
+ if (align) free(align);
446
+ for (int r = 0; r < row_count; r++) {
447
+ for (int c = 0; c < rows[r].cell_count; c++) free(rows[r].cells[c]);
448
+ free(rows[r].cells);
449
+ }
450
+ free(rows);
451
+
452
+ return output;
453
+ }
454
+
455
+ /**
456
+ * Free address specification
457
+ */
458
+ static void free_address_spec(address_spec_t *spec) {
459
+ if (!spec) return;
460
+ if (spec->regex_start) free(spec->regex_start);
461
+ if (spec->regex_end) free(spec->regex_end);
462
+ if (spec->prefix) free(spec->prefix);
463
+ free(spec);
464
+ }
465
+
466
+ /**
467
+ * Parse address specification
468
+ * Supports:
469
+ * - Line numbers: N,M or N,
470
+ * - Regex: /pattern1/,/pattern2/
471
+ * - Prefix: prefix="..."
472
+ */
473
+ static address_spec_t *parse_address_spec(const char *address_str) {
474
+ if (!address_str || *address_str == '\0') {
475
+ return NULL;
476
+ }
477
+
478
+ address_spec_t *spec = calloc(1, sizeof(address_spec_t));
479
+ if (!spec) return NULL;
480
+
481
+ const char *pos = address_str;
482
+
483
+ /* Skip leading whitespace */
484
+ while (*pos && isspace(*pos)) pos++;
485
+
486
+ /* Check if it's just a prefix parameter (starts with prefix=) */
487
+ if (strncmp(pos, "prefix=\"", 8) == 0) {
488
+ /* Just a prefix, no line range or regex */
489
+ pos += 8;
490
+ const char *prefix_start = pos;
491
+ const char *prefix_end = strchr(prefix_start, '"');
492
+
493
+ if (prefix_end) {
494
+ size_t prefix_len = prefix_end - prefix_start;
495
+ spec->prefix = malloc(prefix_len + 1);
496
+ if (spec->prefix) {
497
+ memcpy(spec->prefix, prefix_start, prefix_len);
498
+ spec->prefix[prefix_len] = '\0';
499
+ }
500
+ }
501
+ return spec;
502
+ }
503
+
504
+ /* Check if it's a regex pattern (starts with /) */
505
+ if (*pos == '/') {
506
+ spec->is_regex_range = true;
507
+ const char *regex_start_begin = pos + 1;
508
+ const char *regex_start_end = strchr(regex_start_begin, '/');
509
+
510
+ if (!regex_start_end) {
511
+ free_address_spec(spec);
512
+ return NULL;
513
+ }
514
+
515
+ /* Extract first regex pattern */
516
+ size_t regex_start_len = regex_start_end - regex_start_begin;
517
+ spec->regex_start = malloc(regex_start_len + 1);
518
+ if (!spec->regex_start) {
519
+ free_address_spec(spec);
520
+ return NULL;
521
+ }
522
+ memcpy(spec->regex_start, regex_start_begin, regex_start_len);
523
+ spec->regex_start[regex_start_len] = '\0';
524
+
525
+ pos = regex_start_end + 1;
526
+
527
+ /* Skip comma and whitespace */
528
+ while (*pos && (isspace(*pos) || *pos == ',')) pos++;
529
+
530
+ /* Check for second regex pattern */
531
+ if (*pos == '/') {
532
+ const char *regex_end_begin = pos + 1;
533
+ const char *regex_end_end = strchr(regex_end_begin, '/');
534
+
535
+ if (regex_end_end) {
536
+ size_t regex_end_len = regex_end_end - regex_end_begin;
537
+ spec->regex_end = malloc(regex_end_len + 1);
538
+ if (spec->regex_end) {
539
+ memcpy(spec->regex_end, regex_end_begin, regex_end_len);
540
+ spec->regex_end[regex_end_len] = '\0';
541
+ }
542
+ pos = regex_end_end + 1;
543
+ }
544
+ }
545
+ } else {
546
+ /* Line number format */
547
+ spec->is_line_range = true;
548
+ char *endptr;
549
+ spec->start_line = (int)strtol(pos, &endptr, 10);
550
+
551
+ if (endptr == pos || spec->start_line < 1) {
552
+ /* Invalid start line, check if it's just a prefix */
553
+ spec->is_line_range = false;
554
+ spec->start_line = 0;
555
+ spec->end_line = -1;
556
+ } else {
557
+ pos = endptr;
558
+
559
+ /* Skip whitespace */
560
+ while (*pos && isspace(*pos)) pos++;
561
+
562
+ if (*pos == ',') {
563
+ pos++;
564
+ /* Skip whitespace after comma */
565
+ while (*pos && isspace(*pos)) pos++;
566
+
567
+ if (*pos == '\0' || *pos == ';') {
568
+ /* N, format - from line N to end */
569
+ spec->end_line = -1;
570
+ } else {
571
+ /* N,M format */
572
+ spec->end_line = (int)strtol(pos, &endptr, 10);
573
+ if (endptr == pos || spec->end_line < spec->start_line) {
574
+ /* Invalid end line */
575
+ spec->end_line = -1;
576
+ }
577
+ pos = endptr;
578
+ }
579
+ } else {
580
+ /* Just N - single line */
581
+ spec->end_line = spec->start_line;
582
+ }
583
+ }
584
+ }
585
+
586
+ /* Look for prefix parameter */
587
+ while (*pos && isspace(*pos)) pos++;
588
+ if (*pos == ';') {
589
+ pos++;
590
+ while (*pos && isspace(*pos)) pos++;
591
+
592
+ /* Check for prefix="..." */
593
+ if (strncmp(pos, "prefix=\"", 8) == 0) {
594
+ pos += 8;
595
+ const char *prefix_start = pos;
596
+ const char *prefix_end = strchr(prefix_start, '"');
597
+
598
+ if (prefix_end) {
599
+ size_t prefix_len = prefix_end - prefix_start;
600
+ spec->prefix = malloc(prefix_len + 1);
601
+ if (spec->prefix) {
602
+ memcpy(spec->prefix, prefix_start, prefix_len);
603
+ spec->prefix[prefix_len] = '\0';
604
+ }
605
+ }
606
+ }
607
+ }
608
+
609
+ return spec;
610
+ }
611
+
612
+ /**
613
+ * Extract lines from content based on address specification
614
+ */
615
+ static char *extract_lines(const char *content, address_spec_t *spec) {
616
+ if (!content || !spec) return NULL;
617
+
618
+ /* If no specification, return full content */
619
+ if (!spec->is_line_range && !spec->is_regex_range) {
620
+ if (spec->prefix) {
621
+ /* Apply prefix to all lines */
622
+ size_t content_len = strlen(content);
623
+ size_t prefix_len = strlen(spec->prefix);
624
+ size_t lines = 0;
625
+ const char *p = content;
626
+ while (*p) {
627
+ if (*p == '\n') lines++;
628
+ p++;
629
+ }
630
+ if (*p == '\0' && p > content && p[-1] != '\n') lines++;
631
+
632
+ size_t output_size = content_len + (lines * prefix_len) + 1;
633
+ char *output = malloc(output_size);
634
+ if (!output) return NULL;
635
+
636
+ char *write = output;
637
+ const char *read = content;
638
+ bool at_line_start = true;
639
+
640
+ while (*read) {
641
+ if (at_line_start && *read != '\n') {
642
+ strcpy(write, spec->prefix);
643
+ write += prefix_len;
644
+ at_line_start = false;
645
+ }
646
+ *write++ = *read++;
647
+ if (read[-1] == '\n') {
648
+ at_line_start = true;
649
+ }
650
+ }
651
+ *write = '\0';
652
+ return output;
653
+ }
654
+ return strdup(content);
655
+ }
656
+
657
+ /* Count lines in content */
658
+ int total_lines = 1;
659
+ const char *p = content;
660
+ while (*p) {
661
+ if (*p == '\n') total_lines++;
662
+ p++;
663
+ }
664
+
665
+ if (spec->is_regex_range) {
666
+ /* Regex-based extraction */
667
+ regex_t regex_start, regex_end;
668
+ int ret_start = 0, ret_end = 0;
669
+ bool compiled_start = false, compiled_end = false;
670
+
671
+ /* Compile start regex */
672
+ if (spec->regex_start) {
673
+ ret_start = regcomp(&regex_start, spec->regex_start, REG_EXTENDED);
674
+ if (ret_start == 0) {
675
+ compiled_start = true;
676
+ }
677
+ }
678
+
679
+ /* Compile end regex */
680
+ if (spec->regex_end) {
681
+ ret_end = regcomp(&regex_end, spec->regex_end, REG_EXTENDED);
682
+ if (ret_end == 0) {
683
+ compiled_end = true;
684
+ }
685
+ }
686
+
687
+ if (!compiled_start && !compiled_end) {
688
+ /* No valid regex, return full content */
689
+ if (compiled_start) regfree(&regex_start);
690
+ if (compiled_end) regfree(&regex_end);
691
+ return spec->prefix ? extract_lines(content, spec) : strdup(content);
692
+ }
693
+
694
+ /* Find line numbers matching regex patterns */
695
+ int start_line = 1;
696
+ int end_line = total_lines;
697
+ regmatch_t match;
698
+ int line_num = 1;
699
+ const char *line_start = content;
700
+ bool found_start = false;
701
+
702
+ while (*line_start && line_num <= total_lines) {
703
+ const char *line_end = strchr(line_start, '\n');
704
+ if (!line_end) line_end = line_start + strlen(line_start);
705
+
706
+ size_t line_len = line_end - line_start;
707
+ char *line = malloc(line_len + 1);
708
+ if (!line) {
709
+ if (compiled_start) regfree(&regex_start);
710
+ if (compiled_end) regfree(&regex_end);
711
+ return NULL;
712
+ }
713
+ memcpy(line, line_start, line_len);
714
+ line[line_len] = '\0';
715
+
716
+ /* Check start pattern */
717
+ if (compiled_start && !found_start) {
718
+ if (regexec(&regex_start, line, 1, &match, 0) == 0) {
719
+ start_line = line_num;
720
+ found_start = true;
721
+ }
722
+ }
723
+
724
+ /* Check end pattern (only if start found or no start pattern) */
725
+ if (compiled_end && (found_start || !compiled_start)) {
726
+ if (regexec(&regex_end, line, 1, &match, 0) == 0) {
727
+ end_line = line_num;
728
+ break;
729
+ }
730
+ }
731
+
732
+ free(line);
733
+ line_start = line_end;
734
+ if (*line_start == '\n') line_start++;
735
+ line_num++;
736
+ }
737
+
738
+ if (compiled_start) regfree(&regex_start);
739
+ if (compiled_end) regfree(&regex_end);
740
+
741
+ /* If start not found and we have a start pattern, return empty */
742
+ if (compiled_start && !found_start) {
743
+ return strdup("");
744
+ }
745
+
746
+ /* Extract lines from start_line to end_line */
747
+ line_num = 1;
748
+ line_start = content;
749
+ size_t output_size = strlen(content) + 1024;
750
+ char *output = malloc(output_size);
751
+ if (!output) return NULL;
752
+ char *write = output;
753
+ size_t remaining = output_size;
754
+
755
+ while (*line_start && line_num <= total_lines) {
756
+ const char *line_end = strchr(line_start, '\n');
757
+ if (!line_end) line_end = line_start + strlen(line_start);
758
+
759
+ if (line_num >= start_line && line_num < end_line) {
760
+ size_t line_len = line_end - line_start;
761
+ if (line_len + 100 < remaining) {
762
+ if (spec->prefix) {
763
+ size_t prefix_len = strlen(spec->prefix);
764
+ if (prefix_len + line_len + 10 < remaining) {
765
+ strcpy(write, spec->prefix);
766
+ write += prefix_len;
767
+ remaining -= prefix_len;
768
+ }
769
+ }
770
+ memcpy(write, line_start, line_len);
771
+ write += line_len;
772
+ remaining -= line_len;
773
+ *write++ = '\n';
774
+ remaining--;
775
+ }
776
+ }
777
+
778
+ line_start = line_end;
779
+ if (*line_start == '\n') line_start++;
780
+ line_num++;
781
+ }
782
+
783
+ *write = '\0';
784
+ return output;
785
+ } else {
786
+ /* Line number-based extraction */
787
+ if (spec->start_line < 1 || spec->start_line > total_lines) {
788
+ return strdup("");
789
+ }
790
+
791
+ int end = spec->end_line;
792
+ if (end == -1) {
793
+ end = total_lines;
794
+ } else if (end > total_lines) {
795
+ end = total_lines;
796
+ }
797
+ if (end < spec->start_line) {
798
+ return strdup("");
799
+ }
800
+
801
+ /* Extract lines */
802
+ int line_num = 1;
803
+ const char *line_start = content;
804
+ size_t output_size = strlen(content) + 1024;
805
+ char *output = malloc(output_size);
806
+ if (!output) return NULL;
807
+ char *write = output;
808
+ size_t remaining = output_size;
809
+
810
+ while (*line_start && line_num <= total_lines) {
811
+ const char *line_end = strchr(line_start, '\n');
812
+ if (!line_end) line_end = line_start + strlen(line_start);
813
+
814
+ if (line_num >= spec->start_line && line_num < end) {
815
+ size_t line_len = line_end - line_start;
816
+ if (line_len + 100 < remaining) {
817
+ if (spec->prefix) {
818
+ size_t prefix_len = strlen(spec->prefix);
819
+ if (prefix_len + line_len + 10 < remaining) {
820
+ strcpy(write, spec->prefix);
821
+ write += prefix_len;
822
+ remaining -= prefix_len;
823
+ }
824
+ }
825
+ memcpy(write, line_start, line_len);
826
+ write += line_len;
827
+ remaining -= line_len;
828
+ *write++ = '\n';
829
+ remaining--;
830
+ }
831
+ }
832
+
833
+ line_start = line_end;
834
+ if (*line_start == '\n') line_start++;
835
+ line_num++;
836
+ }
837
+
838
+ *write = '\0';
839
+ return output;
840
+ }
841
+ }
842
+
843
+ /**
844
+ * Resolve wildcard path.
845
+ *
846
+ * Supported patterns:
847
+ * - Legacy "file.*" patterns:
848
+ * - Preferentially resolve to file.html, file.md, file.txt, file.tex (in that order)
849
+ * - General globbing using standard shell-style patterns:
850
+ * - '*' and '?' wildcards
851
+ * - Character classes '[]'
852
+ * - Brace expansion '{a,b}.md', '*.{html,md}' where supported by the platform
853
+ *
854
+ * The path is resolved relative to base_dir (or current directory) before globbing.
855
+ * Returns a newly-allocated path string or NULL if no match is found.
856
+ */
857
+ char *apex_resolve_wildcard(const char *filepath, const char *base_dir) {
858
+ if (!filepath) return NULL;
859
+
860
+ /* Fast path: legacy "file.*" handling with explicit extension preference.
861
+ * Only trigger this when the pattern ends with ".*" and contains no
862
+ * other glob characters. This preserves the documented MMD-style
863
+ * wildcard behavior while allowing more general globbing for
864
+ * patterns like "*.c" or "{intro,part1}.md".
865
+ */
866
+ const char *wildcard = strstr(filepath, ".*");
867
+ bool has_other_glob = (strpbrk(filepath, "*?[{") != NULL &&
868
+ !(wildcard && wildcard[1] == '\0'));
869
+
870
+ if (wildcard && !has_other_glob) {
871
+ /* Extract base filename (before .*) */
872
+ size_t base_len = (size_t)(wildcard - filepath);
873
+ char base_filename[1024];
874
+ if (base_len >= sizeof(base_filename)) return NULL;
875
+
876
+ memcpy(base_filename, filepath, base_len);
877
+ base_filename[base_len] = '\0';
878
+
879
+ /* Try common extensions in preferred order */
880
+ const char *extensions[] = {".html", ".md", ".txt", ".tex", NULL};
881
+
882
+ for (int i = 0; extensions[i]; i++) {
883
+ char test_path[1024];
884
+ snprintf(test_path, sizeof(test_path), "%s%s", base_filename, extensions[i]);
885
+
886
+ char *resolved = resolve_path(test_path, base_dir);
887
+ if (resolved && apex_file_exists(resolved)) {
888
+ return resolved;
889
+ }
890
+ free(resolved);
891
+ }
892
+
893
+ /* No match found for legacy pattern, fall through to globbing
894
+ * so that users can still benefit from more general patterns
895
+ * if they mixed syntax.
896
+ */
897
+ }
898
+
899
+ /* General case: use glob() to resolve shell-style patterns
900
+ * (supports *, ?, [], and optionally brace expansion).
901
+ */
902
+ if (strpbrk(filepath, "*?[{") != NULL) {
903
+ char *pattern_path = resolve_path(filepath, base_dir);
904
+ if (!pattern_path) return NULL;
905
+
906
+ glob_t results;
907
+ int flags = 0;
908
+ #ifdef GLOB_BRACE
909
+ /* Enable brace expansion where available (BSD/macOS, some libcs) */
910
+ if (strchr(pattern_path, '{') || strchr(pattern_path, '}')) {
911
+ flags |= GLOB_BRACE;
912
+ }
913
+ #endif
914
+
915
+ int rc = glob(pattern_path, flags, NULL, &results);
916
+ free(pattern_path);
917
+
918
+ if (rc == 0 && results.gl_pathc > 0 && results.gl_pathv[0]) {
919
+ char *match = strdup(results.gl_pathv[0]);
920
+ globfree(&results);
921
+ return match;
922
+ }
923
+
924
+ globfree(&results);
925
+ return NULL;
926
+ }
927
+
928
+ /* No wildcard characters - behave like resolve_path */
929
+ return resolve_path(filepath, base_dir);
930
+ }
931
+
932
+ /**
933
+ * Get transclude base from metadata, or return default base_dir
934
+ * Returns newly allocated string (caller must free) or NULL
935
+ */
936
+ static char *get_transclude_base(const char *base_dir, apex_metadata_item *metadata) {
937
+ if (!metadata) {
938
+ return base_dir ? strdup(base_dir) : NULL;
939
+ }
940
+
941
+ /* Note: apex_metadata_get now handles case-insensitive matching and spaces being removed
942
+ * So "transclude base", "Transclude Base", "transcludebase" all work
943
+ */
944
+ const char *transclude_base = apex_metadata_get(metadata, "transclude base");
945
+
946
+ if (transclude_base) {
947
+ /* If absolute path, return as-is */
948
+ if (transclude_base[0] == '/') {
949
+ return strdup(transclude_base);
950
+ }
951
+
952
+ /* If relative path starting with ".", use current file's directory */
953
+ if (transclude_base[0] == '.' && (transclude_base[1] == '/' || transclude_base[1] == '\0')) {
954
+ if (base_dir) {
955
+ return strdup(base_dir);
956
+ }
957
+ return strdup(".");
958
+ }
959
+
960
+ /* Relative path - combine with base_dir */
961
+ if (base_dir) {
962
+ size_t len = strlen(base_dir) + strlen(transclude_base) + 2;
963
+ char *result = malloc(len);
964
+ if (result) {
965
+ snprintf(result, len, "%s/%s", base_dir, transclude_base);
966
+ }
967
+ return result;
968
+ }
969
+
970
+ return strdup(transclude_base);
971
+ }
972
+
973
+ /* No transclude base metadata, use default */
974
+ return base_dir ? strdup(base_dir) : NULL;
975
+ }
976
+
977
+ /**
978
+ * Normalize fenced code block delimiters to use odd numbers of backticks.
979
+ * This ensures our simple toggle-based code span detection works correctly.
980
+ * Only modifies fence delimiters at the start of lines, not backticks
981
+ * inside code blocks.
982
+ */
983
+ static char *normalize_fence_delimiters(const char *text) {
984
+ if (!text) return NULL;
985
+
986
+ size_t len = strlen(text);
987
+ char *output = malloc(len * 2 + 1); /* Allocate generously */
988
+ if (!output) return NULL;
989
+
990
+ char *write = output;
991
+ const char *read = text;
992
+ bool in_fenced_block = false;
993
+ int original_fence_length = 0; /* Original count from opening fence */
994
+ int normalized_fence_length = 0; /* Normalized count (always odd) */
995
+
996
+ while (*read) {
997
+ /* Check if we're at the start of a line */
998
+ bool at_line_start = (read == text || read[-1] == '\n');
999
+
1000
+ if (at_line_start && *read == '`') {
1001
+ /* Count consecutive backticks */
1002
+ int backtick_count = 0;
1003
+ const char *backtick_start = read;
1004
+ while (*read == '`') {
1005
+ backtick_count++;
1006
+ read++;
1007
+ }
1008
+
1009
+ /* Check if this looks like a fence delimiter:
1010
+ * - At least 3 backticks
1011
+ * - Followed by optional language info and newline or end of text
1012
+ */
1013
+ bool is_fence = (backtick_count >= 3);
1014
+ if (is_fence) {
1015
+ /* Check what follows - should be whitespace, language info, or newline */
1016
+ const char *after_backticks = read;
1017
+ while (*after_backticks && *after_backticks != '\n' &&
1018
+ *after_backticks != '\r') {
1019
+ after_backticks++;
1020
+ }
1021
+
1022
+ /* If we're closing a fence, check if it matches the original length */
1023
+ if (in_fenced_block && backtick_count == original_fence_length) {
1024
+ /* Closing fence that matches opening - normalize to match the normalized opening fence */
1025
+ for (int i = 0; i < normalized_fence_length; i++) {
1026
+ *write++ = '`';
1027
+ }
1028
+ in_fenced_block = false;
1029
+ original_fence_length = 0;
1030
+ normalized_fence_length = 0;
1031
+ } else if (!in_fenced_block) {
1032
+ /* Opening fence - normalize to odd number */
1033
+ if (backtick_count % 2 == 0) {
1034
+ /* Even number - add one backtick */
1035
+ normalized_fence_length = backtick_count + 1;
1036
+ for (int i = 0; i < normalized_fence_length; i++) {
1037
+ *write++ = '`';
1038
+ }
1039
+ } else {
1040
+ /* Already odd - copy as-is */
1041
+ normalized_fence_length = backtick_count;
1042
+ memcpy(write, backtick_start, backtick_count);
1043
+ write += backtick_count;
1044
+ }
1045
+ original_fence_length = backtick_count;
1046
+ in_fenced_block = true;
1047
+ } else {
1048
+ /* Inside a code block but this doesn't match our fence - copy as-is */
1049
+ memcpy(write, backtick_start, backtick_count);
1050
+ write += backtick_count;
1051
+ }
1052
+
1053
+ /* Copy the rest of the line */
1054
+ while (read < after_backticks) {
1055
+ *write++ = *read++;
1056
+ }
1057
+ } else {
1058
+ /* Not a fence delimiter - copy backticks as-is */
1059
+ memcpy(write, backtick_start, backtick_count);
1060
+ write += backtick_count;
1061
+ }
1062
+ } else {
1063
+ /* Not at start of line or not a backtick - copy character */
1064
+ *write++ = *read++;
1065
+ }
1066
+ }
1067
+
1068
+ *write = '\0';
1069
+ return output;
1070
+ }
1071
+
1072
+ /**
1073
+ * Process file includes in text
1074
+ */
1075
+ char *apex_process_includes(const char *text, const char *base_dir, apex_metadata_item *metadata, int depth) {
1076
+ if (!text) return NULL;
1077
+ if (depth > MAX_INCLUDE_DEPTH) {
1078
+ return strdup(text); /* Silently return original text */
1079
+ }
1080
+
1081
+ /* Normalize fenced code block delimiters to odd numbers of backticks
1082
+ * so our toggle-based code span detection works correctly */
1083
+ char *normalized_text = normalize_fence_delimiters(text);
1084
+ if (!normalized_text) return NULL;
1085
+
1086
+ const char *text_to_process = normalized_text;
1087
+
1088
+ size_t text_len = strlen(text_to_process);
1089
+ size_t output_capacity = text_len * 10; /* Generous for includes */
1090
+ if (output_capacity < 1024 * 1024) output_capacity = 1024 * 1024; /* At least 1MB */
1091
+ char *output = malloc(output_capacity);
1092
+ if (!output) {
1093
+ free(normalized_text);
1094
+ return NULL;
1095
+ }
1096
+
1097
+ /* Get effective base directory from transclude base metadata */
1098
+ char *effective_base_dir = get_transclude_base(base_dir, metadata);
1099
+ if (!effective_base_dir && base_dir) {
1100
+ effective_base_dir = strdup(base_dir);
1101
+ }
1102
+
1103
+ const char *read_pos = text_to_process;
1104
+ char *write_pos = output;
1105
+ size_t remaining = output_capacity;
1106
+ bool in_code_span = false; /* Tracks inline/fenced code spans delimited by backticks */
1107
+
1108
+ while (*read_pos) {
1109
+ bool processed_include = false;
1110
+
1111
+ /* Toggle code-span state on backticks so we can avoid
1112
+ * processing include syntax that appears inside inline
1113
+ * or fenced code (e.g. `<<[path/file]`). This is a simple
1114
+ * state machine that treats all backticks as paired; it
1115
+ * correctly covers common cases like single backtick code
1116
+ * spans and triple-backtick fences. */
1117
+ if (*read_pos == '`') {
1118
+ in_code_span = !in_code_span;
1119
+ }
1120
+
1121
+ /* Look for iA Writer transclusion /filename (at start of line only) */
1122
+ if (!in_code_span && read_pos[0] == '/' && (read_pos == text_to_process || read_pos[-1] == '\n')) {
1123
+ const char *filepath_start = read_pos + 1;
1124
+ const char *filepath_end = filepath_start;
1125
+
1126
+ /* Find end of filename */
1127
+ while (*filepath_end && *filepath_end != ' ' && *filepath_end != '\t' &&
1128
+ *filepath_end != '\n' && *filepath_end != '\r') {
1129
+ filepath_end++;
1130
+ }
1131
+
1132
+ if (filepath_end > filepath_start && (filepath_end - filepath_start) < 1024) {
1133
+ char filepath[1024];
1134
+ size_t filepath_len = filepath_end - filepath_start;
1135
+ memcpy(filepath, filepath_start, filepath_len);
1136
+ filepath[filepath_len] = '\0';
1137
+
1138
+ /* Resolve and check file exists */
1139
+ char *resolved_path = resolve_path(filepath, effective_base_dir);
1140
+ if (resolved_path && apex_file_exists(resolved_path)) {
1141
+ apex_file_type_t file_type = apex_detect_file_type(resolved_path);
1142
+ char *content = read_file_contents(resolved_path);
1143
+
1144
+ if (content) {
1145
+ char *to_insert = NULL;
1146
+
1147
+ if (file_type == FILE_TYPE_IMAGE) {
1148
+ /* Image: create ![](path) */
1149
+ size_t buf_size = strlen(filepath) + 10;
1150
+ to_insert = malloc(buf_size);
1151
+ if (to_insert) snprintf(to_insert, buf_size, "![](%s)\n", filepath);
1152
+ } else if (file_type == FILE_TYPE_CSV || file_type == FILE_TYPE_TSV) {
1153
+ /* CSV/TSV: convert to table */
1154
+ to_insert = apex_csv_to_table(content, file_type == FILE_TYPE_TSV);
1155
+ } else if (file_type == FILE_TYPE_CODE) {
1156
+ /* Code: wrap in fenced code block */
1157
+ const char *ext = strrchr(filepath, '.');
1158
+ const char *lang = ext ? ext + 1 : "";
1159
+ size_t buf_size = strlen(content) + strlen(lang) + 20;
1160
+ to_insert = malloc(buf_size);
1161
+ if (to_insert) snprintf(to_insert, buf_size, "\n```%s\n%s\n```\n", lang, content);
1162
+ } else {
1163
+ /* Text/Markdown: process and include */
1164
+ /* Extract metadata from transcluded file */
1165
+ char *file_content_for_metadata = strdup(content);
1166
+ apex_metadata_item *file_metadata = NULL;
1167
+ char *file_text_after_metadata = file_content_for_metadata;
1168
+ if (file_content_for_metadata) {
1169
+ file_metadata = apex_extract_metadata(&file_text_after_metadata);
1170
+ }
1171
+
1172
+ /* Get transclude base from file's metadata, or use file's directory */
1173
+ char *transclude_base = NULL;
1174
+ if (file_metadata) {
1175
+ transclude_base = get_transclude_base(get_directory(resolved_path), file_metadata);
1176
+ }
1177
+ if (!transclude_base) {
1178
+ transclude_base = get_directory(resolved_path);
1179
+ }
1180
+
1181
+ to_insert = apex_process_includes(content, transclude_base, file_metadata, depth + 1);
1182
+
1183
+ /* Cleanup */
1184
+ if (transclude_base) free(transclude_base);
1185
+ if (file_metadata) apex_free_metadata(file_metadata);
1186
+ if (file_content_for_metadata) free(file_content_for_metadata);
1187
+ }
1188
+
1189
+ if (to_insert) {
1190
+ size_t insert_len = strlen(to_insert);
1191
+ if (insert_len < remaining) {
1192
+ memcpy(write_pos, to_insert, insert_len);
1193
+ write_pos += insert_len;
1194
+ remaining -= insert_len;
1195
+ }
1196
+ if (to_insert != content) free(to_insert);
1197
+ }
1198
+
1199
+ free(content);
1200
+ free(resolved_path);
1201
+ read_pos = filepath_end;
1202
+ processed_include = true;
1203
+ } else {
1204
+ free(resolved_path);
1205
+ }
1206
+ } else if (resolved_path) {
1207
+ free(resolved_path);
1208
+ }
1209
+ }
1210
+ }
1211
+
1212
+ /* Look for MMD transclusion {{file}} */
1213
+ if (!processed_include && !in_code_span && read_pos[0] == '{' && read_pos[1] == '{') {
1214
+ const char *filepath_start = read_pos + 2;
1215
+ const char *filepath_end = strstr(filepath_start, "}}");
1216
+
1217
+ if (filepath_end && (filepath_end - filepath_start) > 0 && (filepath_end - filepath_start) < 1024) {
1218
+ /* Extract filepath */
1219
+ int filepath_len = filepath_end - filepath_start;
1220
+ char filepath[1024];
1221
+ memcpy(filepath, filepath_start, filepath_len);
1222
+ filepath[filepath_len] = '\0';
1223
+
1224
+ /* Check for address specification [address] */
1225
+ const char *address_start = filepath_end + 2;
1226
+ const char *address_end = NULL;
1227
+ address_spec_t *address_spec = NULL;
1228
+
1229
+ if (*address_start == '[') {
1230
+ address_start++;
1231
+ address_end = strchr(address_start, ']');
1232
+ if (address_end) {
1233
+ int address_len = address_end - address_start;
1234
+ char address_str[1024];
1235
+ if (address_len > 0 && address_len < (int)sizeof(address_str)) {
1236
+ memcpy(address_str, address_start, address_len);
1237
+ address_str[address_len] = '\0';
1238
+ address_spec = parse_address_spec(address_str);
1239
+ }
1240
+ }
1241
+ }
1242
+
1243
+ /* Resolve path (handle wildcards) */
1244
+ char *resolved_path = apex_resolve_wildcard(filepath, effective_base_dir);
1245
+ if (!resolved_path) {
1246
+ /* Try without wildcard resolution */
1247
+ resolved_path = resolve_path(filepath, effective_base_dir);
1248
+ }
1249
+
1250
+ if (resolved_path) {
1251
+ apex_file_type_t file_type = apex_detect_file_type(resolved_path);
1252
+ char *content = read_file_contents(resolved_path);
1253
+ if (content) {
1254
+ /* Extract metadata from original file content FIRST (before any processing) */
1255
+ char *file_content_for_metadata = strdup(content);
1256
+ apex_metadata_item *file_metadata = NULL;
1257
+ char *file_text_after_metadata = file_content_for_metadata;
1258
+ if (file_content_for_metadata) {
1259
+ file_metadata = apex_extract_metadata(&file_text_after_metadata);
1260
+ }
1261
+
1262
+ /* Apply address specification if present */
1263
+ char *extracted_content = content;
1264
+ bool free_extracted = false;
1265
+
1266
+ if (address_spec) {
1267
+ extracted_content = extract_lines(content, address_spec);
1268
+ if (extracted_content && extracted_content != content) {
1269
+ free_extracted = true;
1270
+ }
1271
+ }
1272
+
1273
+ char *to_process = extracted_content;
1274
+ bool free_to_process = false;
1275
+
1276
+ /* Convert CSV/TSV to table */
1277
+ if (file_type == FILE_TYPE_CSV || file_type == FILE_TYPE_TSV) {
1278
+ char *table = apex_csv_to_table(extracted_content, file_type == FILE_TYPE_TSV);
1279
+ if (table) {
1280
+ to_process = table;
1281
+ free_to_process = true;
1282
+ }
1283
+ }
1284
+
1285
+ /* Get transclude base from file's metadata, or use file's directory */
1286
+ char *transclude_base = NULL;
1287
+ if (file_metadata) {
1288
+ transclude_base = get_transclude_base(get_directory(resolved_path), file_metadata);
1289
+ }
1290
+ if (!transclude_base) {
1291
+ transclude_base = get_directory(resolved_path);
1292
+ }
1293
+
1294
+ /* Recursively process with file's metadata and transclude base */
1295
+ char *processed = apex_process_includes(to_process, transclude_base, file_metadata, depth + 1);
1296
+
1297
+ /* Cleanup */
1298
+ if (transclude_base) free(transclude_base);
1299
+ if (file_metadata) apex_free_metadata(file_metadata);
1300
+ if (file_content_for_metadata) free(file_content_for_metadata);
1301
+
1302
+ if (processed) {
1303
+ size_t proc_len = strlen(processed);
1304
+ if (proc_len < remaining) {
1305
+ memcpy(write_pos, processed, proc_len);
1306
+ write_pos += proc_len;
1307
+ remaining -= proc_len;
1308
+ }
1309
+ free(processed);
1310
+ }
1311
+
1312
+ if (free_to_process) free(to_process);
1313
+ if (free_extracted) free(extracted_content);
1314
+ free(content);
1315
+
1316
+ if (address_end) {
1317
+ read_pos = address_end + 1;
1318
+ } else {
1319
+ read_pos = filepath_end + 2;
1320
+ }
1321
+ free(resolved_path);
1322
+ if (address_spec) free_address_spec(address_spec);
1323
+ processed_include = true;
1324
+ } else {
1325
+ free(resolved_path);
1326
+ if (address_spec) free_address_spec(address_spec);
1327
+ }
1328
+ } else {
1329
+ if (address_spec) free_address_spec(address_spec);
1330
+ }
1331
+ }
1332
+ }
1333
+
1334
+ /* Look for << (Marked syntax) at the very start of a line */
1335
+ if (!processed_include && !in_code_span &&
1336
+ (read_pos == text_to_process || read_pos[-1] == '\n') &&
1337
+ read_pos[0] == '<' && read_pos[1] == '<') {
1338
+ char bracket_type = 0;
1339
+ const char *filepath_start = NULL;
1340
+ const char *filepath_end = NULL;
1341
+
1342
+ /* Determine include type */
1343
+ if (read_pos[2] == '[') {
1344
+ /* <<[file.md] - Markdown include */
1345
+ bracket_type = '[';
1346
+ filepath_start = read_pos + 3;
1347
+ filepath_end = strchr(filepath_start, ']');
1348
+ } else if (read_pos[2] == '(') {
1349
+ /* <<(file.ext) - Code block include */
1350
+ bracket_type = '(';
1351
+ filepath_start = read_pos + 3;
1352
+ filepath_end = strchr(filepath_start, ')');
1353
+ } else if (read_pos[2] == '{') {
1354
+ /* <<{file.html} - Raw HTML include */
1355
+ bracket_type = '{';
1356
+ filepath_start = read_pos + 3;
1357
+ filepath_end = strchr(filepath_start, '}');
1358
+ }
1359
+
1360
+ if (bracket_type && filepath_start && filepath_end) {
1361
+ /* Extract filepath */
1362
+ int filepath_len = filepath_end - filepath_start;
1363
+ char filepath[1024];
1364
+ if (filepath_len > 0 && filepath_len < (int)sizeof(filepath)) {
1365
+ memcpy(filepath, filepath_start, filepath_len);
1366
+ filepath[filepath_len] = '\0';
1367
+
1368
+ /* Check for address specification [address] */
1369
+ const char *address_start = filepath_end + 1;
1370
+ /* Skip whitespace */
1371
+ while (*address_start && isspace(*address_start)) address_start++;
1372
+ const char *address_end = NULL;
1373
+ address_spec_t *address_spec = NULL;
1374
+
1375
+ if (*address_start == '[') {
1376
+ address_start++;
1377
+ address_end = strchr(address_start, ']');
1378
+ if (address_end) {
1379
+ int address_len = address_end - address_start;
1380
+ char address_str[1024];
1381
+ if (address_len > 0 && address_len < (int)sizeof(address_str)) {
1382
+ memcpy(address_str, address_start, address_len);
1383
+ address_str[address_len] = '\0';
1384
+ address_spec = parse_address_spec(address_str);
1385
+ }
1386
+ }
1387
+ }
1388
+
1389
+ /* Resolve path */
1390
+ char *resolved_path = resolve_path(filepath, effective_base_dir);
1391
+ if (resolved_path) {
1392
+ apex_file_type_t file_type = apex_detect_file_type(resolved_path);
1393
+ char *content = read_file_contents(resolved_path);
1394
+ if (content) {
1395
+ /* Extract metadata from original file content FIRST (before any processing) */
1396
+ char *file_content_for_metadata = strdup(content);
1397
+ apex_metadata_item *file_metadata = NULL;
1398
+ char *file_text_after_metadata = file_content_for_metadata;
1399
+ if (file_content_for_metadata) {
1400
+ file_metadata = apex_extract_metadata(&file_text_after_metadata);
1401
+ }
1402
+
1403
+ /* Apply address specification if present */
1404
+ char *extracted_content = content;
1405
+ bool free_extracted = false;
1406
+
1407
+ if (address_spec) {
1408
+ extracted_content = extract_lines(content, address_spec);
1409
+ if (extracted_content && extracted_content != content) {
1410
+ free_extracted = true;
1411
+ }
1412
+ }
1413
+
1414
+ /* Process based on include type */
1415
+ if (bracket_type == '[') {
1416
+ char *to_process = extracted_content;
1417
+ bool free_to_process = false;
1418
+
1419
+ /* Convert CSV/TSV to table */
1420
+ if (file_type == FILE_TYPE_CSV || file_type == FILE_TYPE_TSV) {
1421
+ char *table = apex_csv_to_table(extracted_content, file_type == FILE_TYPE_TSV);
1422
+ if (table) {
1423
+ to_process = table;
1424
+ free_to_process = true;
1425
+ }
1426
+ }
1427
+
1428
+ /* Markdown include - recursively process */
1429
+
1430
+ /* Get transclude base from file's metadata, or use file's directory */
1431
+ char *transclude_base = NULL;
1432
+ if (file_metadata) {
1433
+ transclude_base = get_transclude_base(get_directory(resolved_path), file_metadata);
1434
+ }
1435
+ if (!transclude_base) {
1436
+ transclude_base = get_directory(resolved_path);
1437
+ }
1438
+
1439
+ char *processed = apex_process_includes(to_process, transclude_base, file_metadata, depth + 1);
1440
+
1441
+ /* Cleanup */
1442
+ if (transclude_base) free(transclude_base);
1443
+ if (file_metadata) apex_free_metadata(file_metadata);
1444
+ if (file_content_for_metadata) free(file_content_for_metadata);
1445
+
1446
+ if (processed) {
1447
+ size_t proc_len = strlen(processed);
1448
+ if (proc_len < remaining) {
1449
+ memcpy(write_pos, processed, proc_len);
1450
+ write_pos += proc_len;
1451
+ remaining -= proc_len;
1452
+ }
1453
+ free(processed);
1454
+ }
1455
+
1456
+ if (free_to_process) free(to_process);
1457
+ } else if (bracket_type == '(') {
1458
+ /* Code block include - wrap in code fence */
1459
+ /* Try to detect language from extension */
1460
+ const char *ext = strrchr(filepath, '.');
1461
+ const char *lang = "";
1462
+ if (ext) {
1463
+ ext++;
1464
+ if (strcmp(ext, "c") == 0 || strcmp(ext, "h") == 0) lang = "c";
1465
+ else if (strcmp(ext, "cpp") == 0 || strcmp(ext, "cc") == 0) lang = "cpp";
1466
+ else if (strcmp(ext, "py") == 0) lang = "python";
1467
+ else if (strcmp(ext, "js") == 0) lang = "javascript";
1468
+ else if (strcmp(ext, "rb") == 0) lang = "ruby";
1469
+ else if (strcmp(ext, "sh") == 0) lang = "bash";
1470
+ else lang = ext;
1471
+ }
1472
+
1473
+ char code_header[128];
1474
+ snprintf(code_header, sizeof(code_header), "\n```%s\n", lang);
1475
+ const char *code_footer = "\n```\n";
1476
+
1477
+ size_t total_len = strlen(code_header) + strlen(extracted_content) + strlen(code_footer);
1478
+ if (total_len < remaining) {
1479
+ strcpy(write_pos, code_header);
1480
+ write_pos += strlen(code_header);
1481
+ strcpy(write_pos, extracted_content);
1482
+ write_pos += strlen(extracted_content);
1483
+ strcpy(write_pos, code_footer);
1484
+ write_pos += strlen(code_footer);
1485
+ remaining -= total_len;
1486
+ }
1487
+ } else if (bracket_type == '{') {
1488
+ /* Raw HTML - will be inserted after processing */
1489
+ /* For now, insert a placeholder marker */
1490
+ char marker[1024];
1491
+ snprintf(marker, sizeof(marker), "<!--APEX_RAW_INCLUDE:%s-->", resolved_path);
1492
+ size_t marker_len = strlen(marker);
1493
+ if (marker_len < remaining) {
1494
+ memcpy(write_pos, marker, marker_len);
1495
+ write_pos += marker_len;
1496
+ remaining -= marker_len;
1497
+ }
1498
+ }
1499
+
1500
+ if (free_extracted) free(extracted_content);
1501
+ free(content);
1502
+ }
1503
+ free(resolved_path);
1504
+ }
1505
+
1506
+ /* Skip past the include syntax */
1507
+ if (address_end) {
1508
+ read_pos = address_end + 1;
1509
+ } else {
1510
+ read_pos = filepath_end + 1;
1511
+ }
1512
+ if (address_spec) free_address_spec(address_spec);
1513
+ processed_include = true;
1514
+ }
1515
+ }
1516
+ }
1517
+
1518
+ /* Not an include, copy character */
1519
+ if (!processed_include) {
1520
+ if (remaining > 0) {
1521
+ *write_pos++ = *read_pos;
1522
+ remaining--;
1523
+ }
1524
+ read_pos++;
1525
+ }
1526
+ }
1527
+
1528
+ *write_pos = '\0';
1529
+
1530
+ /* Cleanup */
1531
+ if (effective_base_dir) free(effective_base_dir);
1532
+ if (normalized_text) free(normalized_text);
1533
+
1534
+ return output;
1535
+ }
1536
+