apex-ruby 1.0.35 → 1.0.37

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: b213f78349fcb6d156e9cae279f5f161f145001e4aebe8b1441813cdd2408e7d
4
- data.tar.gz: 0255dcf57b9a66d64c5b264b786e388b305097e6461d34c7e33423ee88095510
3
+ metadata.gz: 70423c8b7b3f13723cfee24afc52bbf12c049950b241aee21e8f53dc3b971f4f
4
+ data.tar.gz: 1ea75f8a208a30aa92d886b4435d6bf246dbecb1d5fe627e87c3f211dcb9f656
5
5
  SHA512:
6
- metadata.gz: 554d9a71943f8e42901269a03c7ba3f20e3d1b3ff5a9122e70d1ecc0c23544b0d47472829be3bce9fb31d39e589547d4f0cd5a4f684805830f0366c5debd81a6
7
- data.tar.gz: 127e6d7d384cca60b47331f0a2034be2a00ac37ffb78c0772802bc9f548f2622ee02cb6ddade0a8a5dc2a8b9d073a9e6bc607dc64623957ab367f27181f4dd90
6
+ metadata.gz: 35f0ff23c943b29e0cc7d73fd75a8d28304a7e8bcaf490705c60dcbfe97096b2357174e77270ec00abfda417a8f9dfc0d863682e56468619f40b1275d7eb7e80
7
+ data.tar.gz: 0aa1da7ad8a6d607b1b54467e25ef386e644a653221d2cf01abf7a0455571d6607340cb19b143ae718344ec2ce660ddf9480155cc0be5cfb3ee198b9913f6e99
@@ -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 37
25
- #define APEX_VERSION_STRING "1.1.37"
24
+ #define APEX_VERSION_PATCH 39
25
+ #define APEX_VERSION_STRING "1.1.39"
26
26
 
27
27
  /**
28
28
  * Processor compatibility modes
@@ -140,8 +140,11 @@ static int parse_pandoc_citation(const char *text, int pos, int len,
140
140
  char *suffix = NULL;
141
141
  char *key = NULL;
142
142
 
143
- /* Check for @key (author-in-text, no brackets) */
144
- if (*p == '@') {
143
+ /* Check for @key (author-in-text, no brackets).
144
+ * Same boundary as the early-out scan: start of text, whitespace, or '('.
145
+ * Mid-token '@' (ah-original@2x.png, user@example.com) is not a citation. */
146
+ if (*p == '@' &&
147
+ (p == text || isspace((unsigned char)p[-1]) || p[-1] == '(')) {
145
148
  p++;
146
149
  int key_len = extract_citation_key(text, apex_ptrdiff_to_int(p - text), len, &key);
147
150
  if (key_len > 0 && key) {
@@ -364,6 +364,32 @@ static header_item *collect_headers(cmark_node *node, header_item **tail,
364
364
  return headers;
365
365
  }
366
366
 
367
+ typedef struct {
368
+ char *data;
369
+ size_t length;
370
+ size_t capacity;
371
+ bool failed;
372
+ } toc_buffer;
373
+
374
+ static void toc_buffer_append(toc_buffer *buf, const char *str) {
375
+ if (buf->failed || !str) return;
376
+ size_t len = strlen(str);
377
+ if (buf->length + len + 1 > buf->capacity) {
378
+ size_t capacity = buf->capacity ? buf->capacity : 4096;
379
+ while (buf->length + len + 1 > capacity) capacity *= 2;
380
+ char *grown = realloc(buf->data, capacity);
381
+ if (!grown) {
382
+ buf->failed = true;
383
+ return;
384
+ }
385
+ buf->data = grown;
386
+ buf->capacity = capacity;
387
+ }
388
+ memcpy(buf->data + buf->length, str, len);
389
+ buf->length += len;
390
+ buf->data[buf->length] = '\0';
391
+ }
392
+
367
393
  /**
368
394
  * Generate TOC HTML from headers
369
395
  * Produces valid ul > li > ul nesting (nested lists inside list items)
@@ -371,81 +397,64 @@ static header_item *collect_headers(cmark_node *node, header_item **tail,
371
397
  static char *generate_toc_html(header_item *headers, int min_level, int max_level) {
372
398
  if (!headers) return strdup("");
373
399
 
374
- size_t capacity = 4096;
375
- char *html = malloc(capacity);
376
- if (!html) return strdup("");
400
+ toc_buffer buf = {0};
401
+ /* depth: open <ul> elements. level_at[d] is the shallowest heading level
402
+ * listed at depth d. A deeper heading nests one level under the open <li>,
403
+ * however many heading levels it skips; headings at that same level stay
404
+ * siblings. */
405
+ int depth = 0;
406
+ int level_at[8] = {0};
407
+ bool li_open = false;
377
408
 
378
- char *write = html;
379
- size_t remaining = capacity;
380
- int current_level = 0;
381
- int last_level = 0; /* normalized level of last item added (0 = none yet) */
382
-
383
- #define APPEND(str) do { \
384
- size_t len = strlen(str); \
385
- if (len < remaining) { \
386
- memcpy(write, str, len); \
387
- write += len; \
388
- remaining -= len; \
389
- } \
390
- } while(0)
391
-
392
- APPEND("<nav class=\"toc\">\n");
409
+ toc_buffer_append(&buf, "<nav class=\"toc\">\n");
393
410
 
394
411
  for (header_item *h = headers; h; h = h->next) {
395
- /* Skip headers outside min/max range */
396
412
  if (h->level < min_level || h->level > max_level) continue;
397
413
  int target_level = h->level - min_level + 1;
398
414
  if (target_level < 1) target_level = 1;
399
415
 
400
- /* Going up: close </ul></li> for each level (nested ul inside parent li) */
401
- while (current_level > target_level) {
402
- APPEND("</ul>\n</li>\n");
403
- current_level--;
404
- }
405
-
406
- /* Going down: open one <ul> inside the previous li before adding child.
407
- * At root (current_level 0): only open one ul - never ul > ul.
408
- * When going deeper: open exactly one ul per step - never ul > ul. */
409
- while (current_level < target_level) {
410
- if (current_level == 0) {
411
- APPEND("<ul>\n");
412
- current_level = 1;
413
- break;
414
- }
415
- if (last_level > 0) {
416
- APPEND("<ul>\n");
417
- current_level++;
418
- break;
419
- } else {
420
- break; /* No parent li - add as direct child of root ul */
416
+ if (depth == 0) {
417
+ toc_buffer_append(&buf, "<ul>\n");
418
+ depth = 1;
419
+ level_at[depth] = target_level;
420
+ } else if (target_level > level_at[depth] && li_open && depth < 7) {
421
+ toc_buffer_append(&buf, "<ul>\n");
422
+ depth++;
423
+ level_at[depth] = target_level;
424
+ li_open = false;
425
+ } else {
426
+ while (depth > 1 && target_level <= level_at[depth - 1]) {
427
+ if (li_open) toc_buffer_append(&buf, "</li>\n");
428
+ toc_buffer_append(&buf, "</ul>\n");
429
+ depth--;
430
+ li_open = true;
421
431
  }
432
+ if (li_open) toc_buffer_append(&buf, "</li>\n");
433
+ if (target_level < level_at[depth]) level_at[depth] = target_level;
422
434
  }
423
435
 
424
- /* Close previous li when adding sibling (same or shallower level) */
425
- if (last_level > 0 && target_level <= last_level) {
426
- APPEND("</li>\n");
427
- }
428
-
429
- /* Add list item (leave open - may contain nested ul) */
430
- char item[1024];
431
- snprintf(item, sizeof(item), "<li><a href=\"#%s\">%s</a>",
432
- h->id, h->text);
433
- APPEND(item);
434
- last_level = target_level;
436
+ toc_buffer_append(&buf, "<li><a href=\"#");
437
+ toc_buffer_append(&buf, h->id);
438
+ toc_buffer_append(&buf, "\">");
439
+ toc_buffer_append(&buf, h->text);
440
+ toc_buffer_append(&buf, "</a>");
441
+ li_open = true;
435
442
  }
436
443
 
437
- /* Close remaining: </li></ul> for each open level */
438
- while (current_level > 0) {
439
- APPEND("</li>\n</ul>\n");
440
- current_level--;
444
+ while (depth > 0) {
445
+ if (li_open) toc_buffer_append(&buf, "</li>\n");
446
+ toc_buffer_append(&buf, "</ul>\n");
447
+ depth--;
448
+ li_open = depth > 0;
441
449
  }
442
450
 
443
- APPEND("</nav>\n");
451
+ toc_buffer_append(&buf, "</nav>\n");
444
452
 
445
- #undef APPEND
446
-
447
- *write = '\0';
448
- return html;
453
+ if (buf.failed || !buf.data) {
454
+ free(buf.data);
455
+ return strdup("");
456
+ }
457
+ return buf.data;
449
458
  }
450
459
 
451
460
  void apex_toc_entries_free(apex_toc_entry *entries, size_t count) {
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.35"
9
+ VERSION = "1.0.37"
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.35
4
+ version: 1.0.37
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra