apex-ruby 1.0.32 → 1.0.34

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89a42e9eb766a3bae89c288dad1c44f1f8db2adcc558053835c64a157359a49b
4
- data.tar.gz: 12da83980eb83177a45bc3796df1d52e0e62edd9c3ff94974db77f02099fc90b
3
+ metadata.gz: 55f4be7471b1a5d14cc4f772e5a92fed588dfa22f746d2ebc8417fb9b13758d7
4
+ data.tar.gz: 27aa2109e8bdad8f123f5cdfd6f7dee7a56947f4f47a06d653ca6fde9adf558c
5
5
  SHA512:
6
- metadata.gz: 1da4b9b6b8cf73e42f8034584975c8b11b9be7833c7e22bcb6dee7151f5426836edf8984c27dbaabc67e5e855d4cf092f4cd8b45d8fd7f87851c37ca448c53a9
7
- data.tar.gz: 599ee35216be91ff2fa7cf1b981e8c6d7001744310f6ae463277068331317440cdeab9e8edbcd299ecd29e459ce5932004dbb3776eaeca200efdfe5ad3f11762
6
+ metadata.gz: e3d8fb224ae6eaebe856a9651319c806e3031d3720a7261c264063f8f0777dd522a8547175dfdd393bb83aafb1f5a7ad8b7ee7a49d18cdae9124f279051e7bf9
7
+ data.tar.gz: a60e981f839d51dae0b93e4e088ba43fe575800b951e85d97b35379af434a93ef968d84ebcab74e137dd916023682ff06b1023c4a14574a0224a720490054c88
@@ -21,8 +21,8 @@ typedef struct cmark_node cmark_node;
21
21
 
22
22
  #define APEX_VERSION_MAJOR 1
23
23
  #define APEX_VERSION_MINOR 1
24
- #define APEX_VERSION_PATCH 34
25
- #define APEX_VERSION_STRING "1.1.34"
24
+ #define APEX_VERSION_PATCH 36
25
+ #define APEX_VERSION_STRING "1.1.36"
26
26
 
27
27
  /**
28
28
  * Processor compatibility modes
@@ -150,7 +150,7 @@ typedef struct apex_options {
150
150
  bool enable_grid_tables; /* Enable Pandoc grid table syntax (preprocess to pipe tables) */
151
151
 
152
152
  /* Critic markup mode */
153
- int critic_mode; /* 0=markup (default), 1=accept, 2=reject */
153
+ int critic_mode; /* 0=accept, 1=reject, 2=markup (default) */
154
154
 
155
155
  /* Metadata handling */
156
156
  bool strip_metadata;
@@ -807,8 +807,8 @@ static char *apex_preprocess_autolinks(const char *text, const apex_options *opt
807
807
 
808
808
  /* Then: check for reference link definitions: [id]: URL */
809
809
  line_start = r;
810
- /* Skip leading whitespace */
811
- while (*line_start == ' ' || *line_start == '\t') {
810
+ /* Skip leading whitespace and blockquote markers */
811
+ while (*line_start == ' ' || *line_start == '\t' || *line_start == '>') {
812
812
  line_start++;
813
813
  }
814
814
  /* Check for [id]: pattern */
@@ -2781,6 +2781,130 @@ static bool looks_like_attr_key_equals(const char *p, const char *end) {
2781
2781
  return (p > key_start && p < end && *p == '=');
2782
2782
  }
2783
2783
 
2784
+ static const char *ial_next_line(const char *p) {
2785
+ while (*p && *p != '\n' && *p != '\r') p++;
2786
+ if (*p == '\r' && p[1] == '\n') return p + 2;
2787
+ return *p ? p + 1 : p;
2788
+ }
2789
+
2790
+ /* Length of a ``` or ~~~ fence run opening the line (after indentation and
2791
+ * blockquote markers), or 0 if the line is not a fence. */
2792
+ static size_t ial_fence_run(const char *line, char *fence_char, const char **after_run) {
2793
+ const char *p = line;
2794
+ while (*p == ' ' || *p == '\t' || *p == '>') p++;
2795
+ if (*p != '`' && *p != '~') return 0;
2796
+ char c = *p;
2797
+ const char *run = p;
2798
+ while (*p == c) p++;
2799
+ if (p - run < 3) return 0;
2800
+ *fence_char = c;
2801
+ *after_run = p;
2802
+ return (size_t)(p - run);
2803
+ }
2804
+
2805
+ /**
2806
+ * Number of bytes at pos that are code (a closed fenced block starting at
2807
+ * this line, a code span, or an unmatched backtick run) and must be copied
2808
+ * through untouched. Returns 0 when pos does not start code.
2809
+ */
2810
+ static size_t ial_code_region_len(const char *base, const char *pos) {
2811
+ bool line_start = (pos == base || pos[-1] == '\n' || pos[-1] == '\r');
2812
+ if (line_start) {
2813
+ char fence_char;
2814
+ const char *after;
2815
+ size_t open_len = ial_fence_run(pos, &fence_char, &after);
2816
+ if (open_len) {
2817
+ bool valid = true;
2818
+ if (fence_char == '`') {
2819
+ for (const char *q = after; *q && *q != '\n' && *q != '\r'; q++) {
2820
+ if (*q == '`') { valid = false; break; }
2821
+ }
2822
+ }
2823
+ if (valid) {
2824
+ const char *line = ial_next_line(pos);
2825
+ while (*line) {
2826
+ char close_char;
2827
+ const char *close_after;
2828
+ size_t close_len = ial_fence_run(line, &close_char, &close_after);
2829
+ if (close_len >= open_len && close_char == fence_char) {
2830
+ while (*close_after == ' ' || *close_after == '\t') close_after++;
2831
+ if (!*close_after || *close_after == '\n' || *close_after == '\r') {
2832
+ return (size_t)(ial_next_line(line) - pos);
2833
+ }
2834
+ }
2835
+ line = ial_next_line(line);
2836
+ }
2837
+ /* Unclosed fence: protect only the opening line */
2838
+ return (size_t)(ial_next_line(pos) - pos);
2839
+ }
2840
+ }
2841
+ }
2842
+
2843
+ if (*pos != '`') return 0;
2844
+
2845
+ size_t backslashes = 0;
2846
+ for (const char *b = pos; b > base && b[-1] == '\\'; b--) backslashes++;
2847
+ if (backslashes % 2) return 1;
2848
+
2849
+ const char *p = pos;
2850
+ while (*p == '`') p++;
2851
+ size_t open_len = (size_t)(p - pos);
2852
+
2853
+ /* Code spans may wrap lines but end at a blank line */
2854
+ while (*p) {
2855
+ if (*p == '\n' || *p == '\r') {
2856
+ const char *next = ial_next_line(p);
2857
+ const char *q = next;
2858
+ while (*q == ' ' || *q == '\t' || *q == '>') q++;
2859
+ if (!*q || *q == '\n' || *q == '\r') break;
2860
+ p = next;
2861
+ continue;
2862
+ }
2863
+ if (*p == '`') {
2864
+ const char *run = p;
2865
+ while (*p == '`') p++;
2866
+ if ((size_t)(p - run) == open_len) return (size_t)(p - pos);
2867
+ continue;
2868
+ }
2869
+ p++;
2870
+ }
2871
+ return open_len;
2872
+ }
2873
+
2874
+ /* A reference definition label must open its line, after at most three
2875
+ * spaces of indentation (blockquote markers allowed). */
2876
+ static bool ial_at_definition_start(const char *base, const char *pos) {
2877
+ const char *p = pos;
2878
+ for (;;) {
2879
+ int spaces = 0;
2880
+ while (p > base && p[-1] == ' ') {
2881
+ p--;
2882
+ spaces++;
2883
+ }
2884
+ if (spaces > 3) return false;
2885
+ if (p == base || p[-1] == '\n' || p[-1] == '\r') return true;
2886
+ if (p[-1] != '>') return false;
2887
+ p--;
2888
+ }
2889
+ }
2890
+
2891
+ static bool ial_append_verbatim(char **buf, char **write, size_t *remaining,
2892
+ const char *src, size_t len) {
2893
+ if (len >= *remaining) {
2894
+ size_t written = (size_t)(*write - *buf);
2895
+ size_t new_cap = (written + len + 1) * 2;
2896
+ char *grown = realloc(*buf, new_cap);
2897
+ if (!grown) return false;
2898
+ *buf = grown;
2899
+ *write = grown + written;
2900
+ *remaining = new_cap - written - 1;
2901
+ }
2902
+ memcpy(*write, src, len);
2903
+ *write += len;
2904
+ *remaining -= len;
2905
+ return true;
2906
+ }
2907
+
2784
2908
  /**
2785
2909
  * Preprocess markdown to extract image attributes and URL-encode all link URLs
2786
2910
  */
@@ -2826,6 +2950,17 @@ char *apex_preprocess_image_attributes(const char *text, image_attr_entry **img_
2826
2950
  int image_index = 0;
2827
2951
 
2828
2952
  while (*read) {
2953
+ size_t code_len = ial_code_region_len(text, read);
2954
+ if (code_len) {
2955
+ if (!ial_append_verbatim(&output, &write, &remaining, read, code_len)) {
2956
+ free(output);
2957
+ apex_free_image_attributes(local_img_attrs);
2958
+ return NULL;
2959
+ }
2960
+ read += code_len;
2961
+ continue;
2962
+ }
2963
+
2829
2964
  /* Look for inline images: ![alt](url attributes) */
2830
2965
  if (*read == '!' && read[1] == '[') {
2831
2966
  const char *img_start = read;
@@ -3244,7 +3379,7 @@ char *apex_preprocess_image_attributes(const char *text, image_attr_entry **img_
3244
3379
 
3245
3380
  /* Look for reference-style link definitions: [ref]: url attributes */
3246
3381
  /* Process to URL-encode URLs and extract image attributes if present */
3247
- if (*read == '[') {
3382
+ if (*read == '[' && ial_at_definition_start(text, read)) {
3248
3383
  const char *ref_start = read;
3249
3384
  const char *ref_end = strchr(ref_start, ']');
3250
3385
  if (ref_end && ref_end[1] == ':' && (ref_end[2] == ' ' || ref_end[2] == '\t')) {
@@ -4111,6 +4246,18 @@ char *apex_preprocess_image_attributes(const char *text, image_attr_entry **img_
4111
4246
  bool made_expansions = false;
4112
4247
 
4113
4248
  while (*read2) {
4249
+ size_t code_len2 = ial_code_region_len(output, read2);
4250
+ if (code_len2) {
4251
+ if (!ial_append_verbatim(&expanded_output, &write2, &remaining2, read2, code_len2)) {
4252
+ free(expanded_output);
4253
+ free(output);
4254
+ apex_free_image_attributes(local_img_attrs);
4255
+ return NULL;
4256
+ }
4257
+ read2 += code_len2;
4258
+ continue;
4259
+ }
4260
+
4114
4261
  /* Look for full, collapsed, and shortcut reference images. */
4115
4262
  if (*read2 == '!' && read2[1] == '[') {
4116
4263
  const char *img_start = read2;
@@ -4311,6 +4458,17 @@ char *apex_preprocess_image_attributes(const char *text, image_attr_entry **img_
4311
4458
  size_t proc_remaining = strlen(output) * 2;
4312
4459
 
4313
4460
  while (*proc_read) {
4461
+ size_t code_len3 = ial_code_region_len(output, proc_read);
4462
+ if (code_len3) {
4463
+ if (!ial_append_verbatim(&proc_output, &proc_write, &proc_remaining, proc_read, code_len3)) {
4464
+ free(proc_output);
4465
+ proc_output = NULL;
4466
+ break;
4467
+ }
4468
+ proc_read += code_len3;
4469
+ continue;
4470
+ }
4471
+
4314
4472
  /* Look for inline images that were just expanded */
4315
4473
  if (*proc_read == '!' && proc_read[1] == '[') {
4316
4474
  const char *img_start = proc_read;
@@ -4446,9 +4604,11 @@ char *apex_preprocess_image_attributes(const char *text, image_attr_entry **img_
4446
4604
  }
4447
4605
  }
4448
4606
 
4449
- *proc_write = '\0';
4450
- free(output);
4451
- output = proc_output;
4607
+ if (proc_output) {
4608
+ *proc_write = '\0';
4609
+ free(output);
4610
+ output = proc_output;
4611
+ }
4452
4612
  }
4453
4613
  }
4454
4614
  }
@@ -113,6 +113,22 @@ static all_cell *collect_all_cells(cmark_node *document) {
113
113
  /**
114
114
  * Walk AST and collect cells with attributes
115
115
  */
116
+ /* True when the cell whose opening tag starts at `cell` contains only `marker`
117
+ * (or `alt`), ignoring surrounding whitespace. */
118
+ static bool cell_is_only_marker(const char *cell, const char *marker, const char *alt) {
119
+ bool is_th = strncmp(cell, "<th", 3) == 0;
120
+ const char *content = strchr(cell, '>');
121
+ if (!content) return false;
122
+ content++;
123
+ const char *end = strstr(content, is_th ? "</th>" : "</td>");
124
+ if (!end) return false;
125
+ while (content < end && isspace((unsigned char)*content)) content++;
126
+ while (end > content && isspace((unsigned char)end[-1])) end--;
127
+ size_t len = (size_t)(end - content);
128
+ if (len == strlen(marker) && strncmp(content, marker, len) == 0) return true;
129
+ return alt && len == strlen(alt) && strncmp(content, alt, len) == 0;
130
+ }
131
+
116
132
  static cell_attr *collect_table_cell_attributes(cmark_node *document) {
117
133
  cell_attr *list = NULL;
118
134
 
@@ -181,8 +197,7 @@ static cell_attr *collect_table_cell_attributes(cmark_node *document) {
181
197
  attr->attributes = strdup(attrs);
182
198
  attr->cell_text = cell_text ? strdup(cell_text) : NULL;
183
199
  attr->next = list;
184
- list = attr;
185
- }
200
+ list = attr; }
186
201
  }
187
202
  /* Count all cells (including removed ones) to match the column indices
188
203
  * used in advanced_tables.c when finding target cells for rowspan.
@@ -2076,41 +2091,9 @@ char *apex_inject_table_attributes(const char *html, cmark_node *document, int c
2076
2091
  }
2077
2092
  }
2078
2093
 
2079
- /* Also check if this cell contains "^^" (rowspan marker) - these should be removed */
2080
- /* Check both the preview and the actual content in the HTML */
2081
- bool is_rowspan_marker = (strstr(cell_preview, "^^") != NULL);
2082
- if (!is_rowspan_marker) {
2083
- /* Also check the actual HTML content for "^^" */
2084
- const char *content_check = strstr(read, ">");
2085
- if (content_check) {
2086
- const char *close_check = strstr(content_check + 1, "</td>");
2087
- if (!close_check) close_check = strstr(content_check + 1, "</th>");
2088
- if (close_check && close_check - content_check - 1 < 100) {
2089
- char check_buf[100];
2090
- strncpy(check_buf, content_check + 1, close_check - content_check - 1);
2091
- check_buf[close_check - content_check - 1] = '\0';
2092
- is_rowspan_marker = (strstr(check_buf, "^^") != NULL);
2093
- }
2094
- }
2095
- }
2096
-
2097
- /* Also check if this cell contains "<< " or "&lt;&lt;" (colspan marker) - these should be removed */
2098
- /* Check both the preview and the actual content in the HTML */
2099
- bool is_colspan_marker = (strstr(cell_preview, "<<") != NULL || strstr(cell_preview, "&lt;&lt;") != NULL);
2100
- if (!is_colspan_marker) {
2101
- /* Also check the actual HTML content for "<< " or "&lt;&lt;" */
2102
- const char *content_check = strstr(read, ">");
2103
- if (content_check) {
2104
- const char *close_check = strstr(content_check + 1, "</td>");
2105
- if (!close_check) close_check = strstr(content_check + 1, "</th>");
2106
- if (close_check && close_check - content_check - 1 < 100) {
2107
- char check_buf[100];
2108
- strncpy(check_buf, content_check + 1, close_check - content_check - 1);
2109
- check_buf[close_check - content_check - 1] = '\0';
2110
- is_colspan_marker = (strstr(check_buf, "<<") != NULL || strstr(check_buf, "&lt;&lt;") != NULL);
2111
- }
2112
- }
2113
- }
2094
+ /* Cells holding only a span marker (^^ or <<) are removed */
2095
+ bool is_rowspan_marker = cell_is_only_marker(read, "^^", NULL);
2096
+ bool is_colspan_marker = cell_is_only_marker(read, "&lt;&lt;", "<<");
2114
2097
 
2115
2098
  /* Check if this cell should be removed:
2116
2099
  * 1. If it's matched and marked for removal
data/lib/apex/version.rb CHANGED
@@ -6,7 +6,7 @@ module Apex
6
6
  # via Apex::Native.version.
7
7
  module Version
8
8
  # Current gem version.
9
- VERSION = "1.0.32"
9
+ VERSION = "1.0.34"
10
10
  end
11
11
 
12
12
  # Shortcut to gem version string.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apex-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.32
4
+ version: 1.0.34
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra