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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 55f4be7471b1a5d14cc4f772e5a92fed588dfa22f746d2ebc8417fb9b13758d7
|
|
4
|
+
data.tar.gz: 27aa2109e8bdad8f123f5cdfd6f7dee7a56947f4f47a06d653ca6fde9adf558c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
25
|
-
#define APEX_VERSION_STRING "1.1.
|
|
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=
|
|
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:  */
|
|
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
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
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
|
-
/*
|
|
2080
|
-
|
|
2081
|
-
bool
|
|
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 "<<" (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, "<<") != NULL);
|
|
2100
|
-
if (!is_colspan_marker) {
|
|
2101
|
-
/* Also check the actual HTML content for "<< " or "<<" */
|
|
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, "<<") != 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, "<<", "<<");
|
|
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