apex-ruby 1.0.18 → 1.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +17 -3
- data/ext/apex_ext/apex_ext.c +260 -91
- data/ext/apex_ext/apex_src/CHANGELOG.md +440 -0
- data/ext/apex_ext/apex_src/CMakeLists.txt +15 -1
- data/ext/apex_ext/apex_src/Formula/apex.rb +7 -2
- data/ext/apex_ext/apex_src/Package.swift +15 -4
- data/ext/apex_ext/apex_src/README.md +94 -35
- data/ext/apex_ext/apex_src/VERSION +1 -1
- data/ext/apex_ext/apex_src/apex-debug.log +4 -0
- data/ext/apex_ext/apex_src/apex.code-workspace +38 -0
- data/ext/apex_ext/apex_src/apex.taskpaper +12 -0
- data/ext/apex_ext/apex_src/apex_deflist_debug.log +25 -0
- data/ext/apex_ext/apex_src/buildnotes.md +1435 -0
- data/ext/apex_ext/apex_src/cli/main.c +262 -33
- data/ext/apex_ext/apex_src/debug.log +7 -0
- data/ext/apex_ext/apex_src/docs/CITATIONS_EXAMPLES.md +274 -0
- data/ext/apex_ext/apex_src/docs/CITATIONS_IMPLEMENTATION_PLAN.md +749 -0
- data/ext/apex_ext/apex_src/docs/CITATIONS_PLAN.md +744 -0
- data/ext/apex_ext/apex_src/docs/INDEX_IMPLEMENTATION_ANALYSIS.md +382 -0
- data/ext/apex_ext/apex_src/docs/plans/2025-02-27-man-page-output-implementation.md +351 -0
- data/ext/apex_ext/apex_src/docs/superpowers/plans/2026-07-12-toc-output-format.md +745 -0
- data/ext/apex_ext/apex_src/docs/superpowers/plans/2026-07-18-bear-image-attributes.md +829 -0
- data/ext/apex_ext/apex_src/docs/superpowers/plans/2026-07-19-apex-node-npm.md +1148 -0
- data/ext/apex_ext/apex_src/docs/superpowers/specs/2026-07-12-toc-output-format-design.md +161 -0
- data/ext/apex_ext/apex_src/docs/superpowers/specs/2026-07-18-bear-image-attributes-design.md +184 -0
- data/ext/apex_ext/apex_src/docs/superpowers/specs/2026-07-19-apex-node-npm-design.md +211 -0
- data/ext/apex_ext/apex_src/documentation/app-settings-table.md +67 -0
- data/ext/apex_ext/apex_src/documentation/app-transformed/Citations.md +340 -0
- data/ext/apex_ext/apex_src/documentation/app-transformed/Credits.md +11 -0
- data/ext/apex_ext/apex_src/documentation/app-transformed/Header-IDs.md +234 -0
- data/ext/apex_ext/apex_src/documentation/app-transformed/Inline-Attribute-Lists.md +516 -0
- data/ext/apex_ext/apex_src/documentation/app-transformed/Metadata-Transforms.md +461 -0
- data/ext/apex_ext/apex_src/documentation/app-transformed/Modes.md +193 -0
- data/ext/apex_ext/apex_src/documentation/app-transformed/Multi-File-Documents.md +201 -0
- data/ext/apex_ext/apex_src/documentation/app-transformed/Plugins.md +678 -0
- data/ext/apex_ext/apex_src/documentation/app-transformed/Syntax.md +1367 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex Command Line Options.cheatsheet.txt +6 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/C-API.html +774 -300
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Callouts.html +1194 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Citations.html +416 -216
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Command-Line-Options.html +3544 -1094
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Configuration.html +371 -97
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Credits.html +153 -23
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Examples.html +358 -124
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Filters.html +1656 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Generating-Man-Pages.html +1226 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Getting-Started.html +201 -56
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Header-IDs.html +279 -109
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Home.html +200 -53
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Indices.html +2327 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Inline-Attribute-Lists.html +690 -271
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Installation.html +201 -55
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Limitations-and-Roadmap.html +238 -68
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Metadata-Transforms.html +421 -221
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Modes.html +340 -78
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Multi-File-Documents.html +251 -86
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Multi-Format-Images.html +1362 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Pandoc-Integration.html +277 -90
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Plugins.html +673 -346
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Quarto-Mode.html +1405 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Rendering-Markdown-In-Terminal.html +1902 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Syntax.html +1939 -1698
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Tables.html +1781 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Troubleshooting.html +315 -140
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Usage.html +307 -113
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Using-Apex-with-Jekyll.html +1132 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Writing-Tests.html +1754 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/Documents/Xcode-Integration.html +872 -376
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/docSet.dsidx +0 -0
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/optimizedIndex.dsidx +0 -0
- data/ext/apex_ext/apex_src/documentation/html/apex-app-docs.html +8746 -0
- data/ext/apex_ext/apex_src/documentation/shared_styles.css +20 -15
- data/ext/apex_ext/apex_src/documentation/transform_for_app.md +55 -0
- data/ext/apex_ext/apex_src/escaping-repro.md +103 -0
- data/ext/apex_ext/apex_src/examples/quick-actions/Markdown to RTF.workflow/Contents/Info.plist +8 -0
- data/ext/apex_ext/apex_src/examples/quick-actions/Markdown to RTF.workflow/Contents/QuickLook/Preview.png +0 -0
- data/ext/apex_ext/apex_src/examples/quick-actions/Markdown to RTF.workflow/Contents/document.wflow +547 -0
- data/ext/apex_ext/apex_src/examples/quick-actions/Markdown-to-RTF.workflow.zip +0 -0
- data/ext/apex_ext/apex_src/examples/quick-actions/README.md +33 -0
- data/ext/apex_ext/apex_src/include/apex/apex.h +92 -6
- data/ext/apex_ext/apex_src/include/apex/ast_rtf.h +23 -0
- data/ext/apex_ext/apex_src/include/apex/ast_terminal.h +6 -0
- data/ext/apex_ext/apex_src/include/apex/module.modulemap +5 -0
- data/ext/apex_ext/apex_src/include/apex/plugins.h +105 -0
- data/ext/apex_ext/apex_src/include/apexc.h +1 -0
- data/ext/apex_ext/apex_src/man/apex.1 +82 -78
- data/ext/apex_ext/apex_src/man/apex.1.md +81 -4
- data/ext/apex_ext/apex_src/objc/Apex.swift +73 -0
- data/ext/apex_ext/apex_src/objc/ApexPlugins.swift +79 -0
- data/ext/apex_ext/apex_src/objc/NSString+Apex.h +83 -5
- data/ext/apex_ext/apex_src/objc/NSString+Apex.m +244 -1
- data/ext/apex_ext/apex_src/objc/NSString+ApexPlugins.h +76 -0
- data/ext/apex_ext/apex_src/objc/NSString+ApexPlugins.m +169 -0
- data/ext/apex_ext/apex_src/output.html +87 -0
- data/ext/apex_ext/apex_src/plans/quarto-mode.md +442 -0
- data/ext/apex_ext/apex_src/src/_README.md +85 -32
- data/ext/apex_ext/apex_src/src/apex.c +770 -200
- data/ext/apex_ext/apex_src/src/ast_rtf.c +848 -0
- data/ext/apex_ext/apex_src/src/ast_terminal.c +184 -7
- data/ext/apex_ext/apex_src/src/extensions/abbreviations.c +10 -3
- data/ext/apex_ext/apex_src/src/extensions/advanced_tables.c +7 -11
- data/ext/apex_ext/apex_src/src/extensions/bear_image_attrs.c +467 -0
- data/ext/apex_ext/apex_src/src/extensions/bear_image_attrs.h +27 -0
- data/ext/apex_ext/apex_src/src/extensions/callouts.c +400 -4
- data/ext/apex_ext/apex_src/src/extensions/callouts.h +15 -5
- data/ext/apex_ext/apex_src/src/extensions/citations.c +26 -5
- data/ext/apex_ext/apex_src/src/extensions/code_fence_attrs.c +632 -0
- data/ext/apex_ext/apex_src/src/extensions/code_fence_attrs.h +22 -0
- data/ext/apex_ext/apex_src/src/extensions/concordance.c +632 -0
- data/ext/apex_ext/apex_src/src/extensions/definition_list.c +129 -15
- data/ext/apex_ext/apex_src/src/extensions/grid_tables.c +1050 -121
- data/ext/apex_ext/apex_src/src/extensions/html_markdown.c +569 -16
- data/ext/apex_ext/apex_src/src/extensions/ial.c +502 -52
- data/ext/apex_ext/apex_src/src/extensions/ial.h +2 -1
- data/ext/apex_ext/apex_src/src/extensions/includes.c +532 -33
- data/ext/apex_ext/apex_src/src/extensions/includes.h +7 -1
- data/ext/apex_ext/apex_src/src/extensions/index.c +1427 -140
- data/ext/apex_ext/apex_src/src/extensions/index.h +28 -0
- data/ext/apex_ext/apex_src/src/extensions/metadata.c +200 -161
- data/ext/apex_ext/apex_src/src/extensions/quarto_diagrams.c +251 -0
- data/ext/apex_ext/apex_src/src/extensions/quarto_diagrams.h +22 -0
- data/ext/apex_ext/apex_src/src/extensions/quarto_lists.c +624 -0
- data/ext/apex_ext/apex_src/src/extensions/quarto_lists.h +35 -0
- data/ext/apex_ext/apex_src/src/extensions/quarto_polish.c +264 -0
- data/ext/apex_ext/apex_src/src/extensions/quarto_polish.h +23 -0
- data/ext/apex_ext/apex_src/src/extensions/quarto_shortcodes.c +307 -0
- data/ext/apex_ext/apex_src/src/extensions/quarto_shortcodes.h +21 -0
- data/ext/apex_ext/apex_src/src/extensions/raw_content.c +351 -0
- data/ext/apex_ext/apex_src/src/extensions/raw_content.h +20 -0
- data/ext/apex_ext/apex_src/src/extensions/relaxed_tables.c +117 -3
- data/ext/apex_ext/apex_src/src/extensions/special_markers.c +53 -0
- data/ext/apex_ext/apex_src/src/extensions/syntax_highlight.c +23 -1
- data/ext/apex_ext/apex_src/src/extensions/table_html_postprocess.c +83 -92
- data/ext/apex_ext/apex_src/src/extensions/toc.c +446 -25
- data/ext/apex_ext/apex_src/src/extensions/toc.h +26 -1
- data/ext/apex_ext/apex_src/src/extensions/wiki_links.c +28 -0
- data/ext/apex_ext/apex_src/src/html_renderer.c +387 -17
- data/ext/apex_ext/apex_src/src/plugin_catalog.c +517 -0
- data/ext/apex_ext/apex_src/src/plugins_remote.c +88 -14
- data/ext/apex_ext/apex_src/src/plugins_remote.h +34 -0
- data/ext/apex_ext/apex_src/src/pretty_html.c +6 -1
- data/ext/apex_ext/apex_src/tests/fixtures/comprehensive_test.md +21 -0
- data/ext/apex_ext/apex_src/tests/fixtures/images/bear_image_attributes.md +10 -0
- data/ext/apex_ext/apex_src/tests/fixtures/includes/sections.md +19 -0
- data/ext/apex_ext/apex_src/tests/fixtures/includes/sections.txt +11 -0
- data/ext/apex_ext/apex_src/tests/fixtures/minimal_pb.md +2 -0
- data/ext/apex_ext/apex_src/tests/fixtures/obsidian-callouts.md +46 -0
- data/ext/apex_ext/apex_src/tests/fixtures/pagebreak_html_repro.md +5 -0
- data/ext/apex_ext/apex_src/tests/fixtures/python-callouts.md +47 -0
- data/ext/apex_ext/apex_src/tests/fixtures/quarto/callouts.md +3 -0
- data/ext/apex_ext/apex_src/tests/fixtures/quarto/code-attrs.md +3 -0
- data/ext/apex_ext/apex_src/tests/fixtures/quarto/diagrams.md +8 -0
- data/ext/apex_ext/apex_src/tests/fixtures/quarto/lists.md +19 -0
- data/ext/apex_ext/apex_src/tests/fixtures/quarto/raw-content.md +5 -0
- data/ext/apex_ext/apex_src/tests/fixtures/quarto/shortcodes.md +7 -0
- data/ext/apex_ext/apex_src/tests/fixtures/quarto/smoke.md +81 -0
- data/ext/apex_ext/apex_src/tests/fixtures/quarto/spans.md +5 -0
- data/ext/apex_ext/apex_src/tests/fixtures/quarto-callouts.md +47 -0
- data/ext/apex_ext/apex_src/tests/fixtures/speed.md +192 -0
- data/ext/apex_ext/apex_src/tests/fixtures/tables/grid-tables.md +37 -0
- data/ext/apex_ext/apex_src/tests/paginate_cli_test.sh +16 -0
- data/ext/apex_ext/apex_src/tests/test_bear_image_attrs.c +301 -0
- data/ext/apex_ext/apex_src/tests/test_concordance.tsv +4 -0
- data/ext/apex_ext/apex_src/tests/test_escaping_repro.c +82 -0
- data/ext/apex_ext/apex_src/tests/test_extensions.c +821 -1
- data/ext/apex_ext/apex_src/tests/test_ial.c +7 -0
- data/ext/apex_ext/apex_src/tests/test_marked_integration.c +25 -0
- data/ext/apex_ext/apex_src/tests/test_metadata.c +129 -0
- data/ext/apex_ext/apex_src/tests/test_output.c +568 -2
- data/ext/apex_ext/apex_src/tests/test_runner.c +11 -0
- data/ext/apex_ext/apex_src/tests/test_tables.c +420 -0
- data/ext/apex_ext/apex_src/vendor/cmark-gfm/CMakeLists.txt +1 -1
- data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/autolink.c +77 -1
- data/ext/apex_ext/apex_src/vendor/cmark-gfm/extensions/table.c +135 -5
- data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/blocks.c +56 -1
- data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/config.h +38 -0
- data/ext/apex_ext/apex_src/vendor/cmark-gfm/src/main.c +1 -1
- data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/__pycache__/cmark.cpython-314.pyc +0 -0
- data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/__pycache__/normalize.cpython-314.pyc +0 -0
- data/ext/apex_ext/apex_src/vendor/cmark-gfm/test/extensions.txt +69 -0
- data/ext/apex_ext/apex_src/xcode_build/CMakeScripts/ReRunCMake.make +74 -0
- data/ext/apex_ext/apex_src/xcode_build/CTestTestfile.cmake +22 -0
- data/ext/apex_ext/apex_src/xcode_build/Debug/Apex.framework/Versions/A/Apex +0 -0
- data/ext/apex_ext/apex_src/xcode_build/Debug/Apex.framework/Versions/A/Resources/Info.plist +44 -0
- data/ext/apex_ext/apex_src/xcode_build/Debug/Apex.framework/Versions/A/_CodeSignature/CodeResources +128 -0
- data/ext/apex_ext/apex_src/xcode_build/apex.xcodeproj/project.pbxproj +5118 -0
- data/ext/apex_ext/apex_src/xcode_build/apex.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +8 -0
- data/ext/apex_ext/apex_src/xcode_build/apex.xcodeproj/project.xcworkspace/xcuserdata/ttscoff.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- data/ext/apex_ext/apex_src/xcode_build/apex.xcodeproj/project.xcworkspace/xcuserdata/ttscoff.xcuserdatad/WorkspaceSettings.xcsettings +8 -0
- data/ext/apex_ext/apex_src/xcode_build/apex.xcodeproj/xcuserdata/ttscoff.xcuserdatad/xcschemes/xcschememanagement.plist +99 -0
- data/ext/apex_ext/apex_src/xcode_build/cmake_install.cmake +452 -0
- data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/CMakeScripts/ReRunCMake.make +52 -0
- data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/cmake_install.cmake +55 -0
- data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/cmark-gfm.xcodeproj/project.pbxproj +2455 -0
- data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/cmark-gfm.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +8 -0
- data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/extensions/cmake_install.cmake +171 -0
- data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/man/cmake_install.cmake +55 -0
- data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/src/cmake_install.cmake +220 -0
- data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/src/cmark-gfm_export.h +43 -0
- data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/src/cmark-gfm_version.h +7 -0
- data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/src/config.h +76 -0
- data/ext/apex_ext/apex_src/xcode_build/vendor/cmark-gfm/src/libcmark-gfm.pc +10 -0
- data/ext/apex_ext/extconf.rb +35 -0
- data/lib/apex/version.rb +2 -2
- metadata +117 -2
- data/ext/apex_ext/apex_src/documentation/docsets/Apex.docset/Contents/Resources/tempOptimizedIndex.dsidx +0 -0
|
@@ -339,8 +339,11 @@ static char *get_caption_from_paragraph(cmark_node *para) {
|
|
|
339
339
|
if (!link_text || cmark_node_get_type(link_text) != CMARK_NODE_TEXT) return NULL;
|
|
340
340
|
const char *text = cmark_node_get_literal(link_text);
|
|
341
341
|
if (!text) return NULL;
|
|
342
|
-
/* Only treat as caption if
|
|
343
|
-
|
|
342
|
+
/* Only treat as caption if paragraph contains exactly one link node.
|
|
343
|
+
* Footnote definitions like "[^1]: ..." can parse as LINK + TEXT;
|
|
344
|
+
* those must never be treated as table captions. */
|
|
345
|
+
if (cmark_node_next(link_text) != NULL) return NULL; /* extra content inside link */
|
|
346
|
+
if (cmark_node_next(child) != NULL) return NULL; /* extra paragraph content after link */
|
|
344
347
|
return strdup(text);
|
|
345
348
|
}
|
|
346
349
|
return NULL;
|
|
@@ -1089,49 +1092,14 @@ char *apex_inject_table_attributes(const char *html, cmark_node *document, int c
|
|
|
1089
1092
|
col_idx = 0;
|
|
1090
1093
|
prev_cell_matching = NULL; /* Reset previous cell matching for new row */
|
|
1091
1094
|
|
|
1092
|
-
/* Map HTML row index to AST row index.
|
|
1093
|
-
* HTML rows skip separator rows (which are marked for removal in AST).
|
|
1094
|
-
* So we need to find the AST row that corresponds to this HTML row.
|
|
1095
|
+
/* Map HTML row index to AST row index 1:1.
|
|
1095
1096
|
*
|
|
1096
|
-
*
|
|
1097
|
-
*
|
|
1098
|
-
*
|
|
1099
|
-
*
|
|
1100
|
-
*
|
|
1101
|
-
|
|
1102
|
-
* Note: This mapping is only needed when we have attributes to process. */
|
|
1103
|
-
ast_row_idx = -1;
|
|
1104
|
-
if (all_cells) {
|
|
1105
|
-
int html_row_count = -1; /* Start at -1, will be 0 for header */
|
|
1106
|
-
for (int r = 0; r < 100; r++) { /* Check up to 100 AST rows */
|
|
1107
|
-
/* Check if this AST row has any non-removed cells */
|
|
1108
|
-
bool has_non_removed = false;
|
|
1109
|
-
for (all_cell *c = all_cells; c; c = c->next) {
|
|
1110
|
-
if (c->table_index == table_idx &&
|
|
1111
|
-
c->row_index == r &&
|
|
1112
|
-
!c->is_removed) {
|
|
1113
|
-
has_non_removed = true;
|
|
1114
|
-
break;
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
/* If this AST row has non-removed cells, it appears in HTML */
|
|
1118
|
-
if (has_non_removed) {
|
|
1119
|
-
html_row_count++;
|
|
1120
|
-
if (html_row_count == row_idx) {
|
|
1121
|
-
ast_row_idx = r;
|
|
1122
|
-
break;
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
} else {
|
|
1127
|
-
/* No all_cells available (alignment-only processing) - use row_idx directly */
|
|
1128
|
-
ast_row_idx = row_idx;
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
if (ast_row_idx == -1) {
|
|
1132
|
-
/* Fallback: use row_idx directly */
|
|
1133
|
-
ast_row_idx = row_idx;
|
|
1134
|
-
}
|
|
1097
|
+
* cmark still emits rows that the AST marks data-remove (dummy headerless
|
|
1098
|
+
* thead, em-dash separator leftovers, === markers). Those <tr> tags are
|
|
1099
|
+
* present in the HTML we walk here and are stripped only when we decide
|
|
1100
|
+
* should_skip_row. Counting only non-removed AST rows desyncs indices and
|
|
1101
|
+
* can apply a later row's colspan onto earlier blank cells (| |). */
|
|
1102
|
+
ast_row_idx = row_idx;
|
|
1135
1103
|
|
|
1136
1104
|
/* Pre-calculate which original columns will be visible in this row's HTML.
|
|
1137
1105
|
* This creates a mapping: HTML position -> original column index.
|
|
@@ -1406,13 +1374,55 @@ char *apex_inject_table_attributes(const char *html, cmark_node *document, int c
|
|
|
1406
1374
|
/* Note: Once we're in tfoot, we stay in tfoot - don't reopen tbody */
|
|
1407
1375
|
/* tfoot rows should be at the end of the table */
|
|
1408
1376
|
|
|
1409
|
-
/* Check if this row should be completely removed (all cells marked for removal)
|
|
1410
|
-
|
|
1411
|
-
|
|
1377
|
+
/* Check if this row should be completely removed (all cells marked for removal).
|
|
1378
|
+
* Always skip fully-removed rows (dummy headerless thead, em-dash separators, ===),
|
|
1379
|
+
* even among the first HTML rows — force_keep only protects real data rows. */
|
|
1412
1380
|
bool should_skip_row = false;
|
|
1381
|
+
bool row_fully_removed = false;
|
|
1382
|
+
|
|
1383
|
+
if (all_cells) {
|
|
1384
|
+
int total_cells_in_row = 0;
|
|
1385
|
+
int removed_cells_in_row = 0;
|
|
1386
|
+
for (all_cell *c = all_cells; c; c = c->next) {
|
|
1387
|
+
if (c->table_index == table_idx && c->row_index == ast_row_idx) {
|
|
1388
|
+
total_cells_in_row++;
|
|
1389
|
+
if (c->is_removed) {
|
|
1390
|
+
removed_cells_in_row++;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
if (total_cells_in_row > 0 && total_cells_in_row == removed_cells_in_row) {
|
|
1395
|
+
/* Fully-removed === marker rows: drop the whole <tr>.
|
|
1396
|
+
* Em-dash separators and empty dummy headers: keep <tr>, remove
|
|
1397
|
+
* cells individually so an empty <tr></tr> remains (needed for
|
|
1398
|
+
* relaxed-header detection and empty-thead cleanup). */
|
|
1399
|
+
bool is_equals_row = false;
|
|
1400
|
+
if (attrs) {
|
|
1401
|
+
for (cell_attr *a = attrs; a; a = a->next) {
|
|
1402
|
+
if (a->table_index != table_idx || a->row_index != ast_row_idx)
|
|
1403
|
+
continue;
|
|
1404
|
+
if (!a->cell_text) continue;
|
|
1405
|
+
const char *text = a->cell_text;
|
|
1406
|
+
while (*text && isspace((unsigned char)*text)) text++;
|
|
1407
|
+
if (text[0] == '=' && text[1] == '=' && text[2] == '=') {
|
|
1408
|
+
is_equals_row = true;
|
|
1409
|
+
break;
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
if (is_equals_row) {
|
|
1414
|
+
row_fully_removed = true;
|
|
1415
|
+
should_skip_row = true;
|
|
1416
|
+
} else {
|
|
1417
|
+
row_fully_removed = false;
|
|
1418
|
+
should_skip_row = false;
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1413
1422
|
|
|
1414
1423
|
/* CRITICAL SAFEGUARD: If this is one of the first few rows (row_idx <= 3), it's
|
|
1415
|
-
* almost certainly in tbody, not tfoot.
|
|
1424
|
+
* almost certainly in tbody, not tfoot. Do not skip via tfoot/=== heuristics.
|
|
1425
|
+
* Fully-removed rows stay skipped (row_fully_removed).
|
|
1416
1426
|
* Note: row_idx is incremented before this check (line 894), so:
|
|
1417
1427
|
* - row_idx 1 = header
|
|
1418
1428
|
* - row_idx 2 = first data row
|
|
@@ -1423,7 +1433,7 @@ char *apex_inject_table_attributes(const char *html, cmark_node *document, int c
|
|
|
1423
1433
|
* This check must run FIRST, before any other skip logic, to ensure these rows
|
|
1424
1434
|
* are always rendered. */
|
|
1425
1435
|
bool force_keep_row = false;
|
|
1426
|
-
if (row_idx <= 3) {
|
|
1436
|
+
if (!row_fully_removed && row_idx <= 3) {
|
|
1427
1437
|
/* First few rows (header + first two data rows) are always in tbody - never skip them */
|
|
1428
1438
|
force_keep_row = true;
|
|
1429
1439
|
should_skip_row = false;
|
|
@@ -1434,11 +1444,11 @@ char *apex_inject_table_attributes(const char *html, cmark_node *document, int c
|
|
|
1434
1444
|
/* CRITICAL: Only check if row should be skipped if we haven't already determined
|
|
1435
1445
|
* it should be in tbody. If current_row_is_tfoot is false, this row was either
|
|
1436
1446
|
* never marked as tfoot OR was forced to tbody because it appears before === in HTML.
|
|
1437
|
-
*
|
|
1447
|
+
* Fully-removed rows are already handled via row_fully_removed.
|
|
1438
1448
|
*
|
|
1439
1449
|
* IMPORTANT: We must check this AFTER setting current_row_is_tfoot, so we know
|
|
1440
1450
|
* if the row was forced to tbody. */
|
|
1441
|
-
if (!force_keep_row && current_row_is_tfoot) {
|
|
1451
|
+
if (!row_fully_removed && !force_keep_row && current_row_is_tfoot) {
|
|
1442
1452
|
/* Count ALL cells in this row (using all_cells) to see if any are non-removed */
|
|
1443
1453
|
int total_cells_in_row = 0;
|
|
1444
1454
|
int removed_cells_in_row = 0;
|
|
@@ -1574,15 +1584,16 @@ char *apex_inject_table_attributes(const char *html, cmark_node *document, int c
|
|
|
1574
1584
|
*
|
|
1575
1585
|
* FINAL OVERRIDE: This is the last check before skipping, so it must override any
|
|
1576
1586
|
* previous skip decisions. Also check force_keep_row flag. */
|
|
1577
|
-
if (force_keep_row || was_forced_to_tbody || (final_min_equals_row_idx >= 0 && row_idx <= 3) ||
|
|
1578
|
-
(min_equals_row_idx >= 0 && row_idx <= 3)) {
|
|
1587
|
+
if (!row_fully_removed && (force_keep_row || was_forced_to_tbody || (final_min_equals_row_idx >= 0 && row_idx <= 3) ||
|
|
1588
|
+
(min_equals_row_idx >= 0 && row_idx <= 3))) {
|
|
1579
1589
|
should_skip_row = false;
|
|
1580
1590
|
current_row_is_tfoot = false;
|
|
1581
1591
|
}
|
|
1582
1592
|
|
|
1583
1593
|
/* FINAL CHECK: If force_keep_row is true, NEVER skip this row, regardless of should_skip_row.
|
|
1584
|
-
* Also, if row_idx <= 3, protect it as an extra safeguard.
|
|
1585
|
-
|
|
1594
|
+
* Also, if row_idx <= 3, protect it as an extra safeguard.
|
|
1595
|
+
* Fully-removed rows (dummy/separator/===) stay skipped. */
|
|
1596
|
+
if (!row_fully_removed && (force_keep_row || row_idx <= 3)) {
|
|
1586
1597
|
should_skip_row = false;
|
|
1587
1598
|
/* If this is one of the first few rows and there's a === row, it's definitely in tbody */
|
|
1588
1599
|
if (row_idx <= 3 && min_equals_row_idx >= 0) {
|
|
@@ -1875,6 +1886,10 @@ char *apex_inject_table_attributes(const char *html, cmark_node *document, int c
|
|
|
1875
1886
|
/* Compare (case-sensitive, but we can make it more lenient if needed) */
|
|
1876
1887
|
content_matches = (strncmp(attr_text, html_text, strlen(attr_text)) == 0 &&
|
|
1877
1888
|
(html_text[strlen(attr_text)] == '\0' || isspace((unsigned char)html_text[strlen(attr_text)])));
|
|
1889
|
+
} else {
|
|
1890
|
+
/* Non-empty AST text must not match an empty HTML cell.
|
|
1891
|
+
* Otherwise colspan from |full||||| attaches to | | blanks. */
|
|
1892
|
+
content_matches = false;
|
|
1878
1893
|
}
|
|
1879
1894
|
}
|
|
1880
1895
|
if (content_matches) {
|
|
@@ -1884,47 +1899,25 @@ char *apex_inject_table_attributes(const char *html, cmark_node *document, int c
|
|
|
1884
1899
|
}
|
|
1885
1900
|
}
|
|
1886
1901
|
|
|
1887
|
-
/* If no match found in current row, also check the previous AST row
|
|
1888
|
-
*
|
|
1889
|
-
*
|
|
1902
|
+
/* If no match found in current row, also check the previous AST row —
|
|
1903
|
+
* but ONLY for === tfoot marker cells. Em-dash separator rows are also
|
|
1904
|
+
* data-remove; applying those to the next row would delete legitimate
|
|
1905
|
+
* blank cells (| |). */
|
|
1890
1906
|
if (!matching && ast_row_idx > 0) {
|
|
1891
1907
|
for (cell_attr *a = attrs; a; a = a->next) {
|
|
1892
1908
|
if (a->table_index == table_idx &&
|
|
1893
1909
|
a->row_index == ast_row_idx - 1 &&
|
|
1894
1910
|
a->col_index == target_original_col &&
|
|
1895
|
-
strstr(a->attributes, "data-remove")
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
const char *close_tag = is_th ? "</th>" : "</td>";
|
|
1902
|
-
const char *content_start = strchr(read, '>');
|
|
1903
|
-
if (content_start) {
|
|
1904
|
-
const char *content_end = strstr(content_start + 1, close_tag);
|
|
1905
|
-
if (content_end && content_end - content_start - 1 < 99) {
|
|
1906
|
-
size_t len = content_end - content_start - 1;
|
|
1907
|
-
strncpy(cell_preview, content_start + 1, len);
|
|
1908
|
-
cell_preview[len] = '\0';
|
|
1909
|
-
while (len > 0 && (cell_preview[len-1] == '\n' || cell_preview[len-1] == '\r' || isspace((unsigned char)cell_preview[len-1]))) {
|
|
1910
|
-
cell_preview[--len] = '\0';
|
|
1911
|
-
}
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
}
|
|
1915
|
-
if (cell_preview[0] != '\0') {
|
|
1916
|
-
const char *attr_text = a->cell_text;
|
|
1917
|
-
const char *html_text = cell_preview;
|
|
1918
|
-
while (*attr_text && isspace((unsigned char)*attr_text)) attr_text++;
|
|
1919
|
-
while (*html_text && isspace((unsigned char)*html_text)) html_text++;
|
|
1920
|
-
content_matches = (strncmp(attr_text, html_text, strlen(attr_text)) == 0 &&
|
|
1921
|
-
(html_text[strlen(attr_text)] == '\0' || isspace((unsigned char)html_text[strlen(attr_text)])));
|
|
1922
|
-
}
|
|
1923
|
-
}
|
|
1924
|
-
if (content_matches) {
|
|
1925
|
-
matching = a;
|
|
1926
|
-
break;
|
|
1911
|
+
strstr(a->attributes, "data-remove") &&
|
|
1912
|
+
a->cell_text) {
|
|
1913
|
+
const char *marker = a->cell_text;
|
|
1914
|
+
while (*marker && isspace((unsigned char)*marker)) marker++;
|
|
1915
|
+
if (!(marker[0] == '=' && marker[1] == '=' && marker[2] == '=')) {
|
|
1916
|
+
continue;
|
|
1927
1917
|
}
|
|
1918
|
+
/* === marker from previous row — treat as match for removal */
|
|
1919
|
+
matching = a;
|
|
1920
|
+
break;
|
|
1928
1921
|
}
|
|
1929
1922
|
}
|
|
1930
1923
|
}
|
|
@@ -2065,8 +2058,6 @@ char *apex_inject_table_attributes(const char *html, cmark_node *document, int c
|
|
|
2065
2058
|
if (attr_len > 0 && html_len > 0 &&
|
|
2066
2059
|
attr_len == html_len &&
|
|
2067
2060
|
strncmp(attr_text, html_text, attr_len) == 0) {
|
|
2068
|
-
fprintf(stderr, "DEBUG MATCH: Found colspan cell by content fallback (same row) - text=[%s] attrs=[%s]\n",
|
|
2069
|
-
html_text, a->attributes);
|
|
2070
2061
|
matching = a;
|
|
2071
2062
|
break;
|
|
2072
2063
|
}
|