Flatten a JS/TS `template_string` node into plain text (issue #1006). * String fragments are kept verbatim; each ${...} substitution becomes the * "{}" placeholder so client URLs built from template literals share the * canonical parameter shape of server-side route paths * (`/things/${id}/x` -> "/things/{}/x"). Returns NULL when the node yields * no text or exceeds the route-sized buffer. */
| 1633 | * (`/things/${id}/x` -> "/things/{}/x"). Returns NULL when the node yields |
| 1634 | * no text or exceeds the route-sized buffer. */ |
| 1635 | const char *cbm_template_string_text(CBMArena *a, TSNode node, const char *source) { |
| 1636 | enum { TPL_BUF = 512 }; |
| 1637 | char buf[TPL_BUF]; |
| 1638 | size_t pos = 0; |
| 1639 | uint32_t nc = ts_node_named_child_count(node); |
| 1640 | for (uint32_t i = 0; i < nc; i++) { |
| 1641 | TSNode c = ts_node_named_child(node, i); |
| 1642 | const char *k = ts_node_type(c); |
| 1643 | if (strcmp(k, "string_fragment") == 0) { |
| 1644 | char *frag = cbm_node_text(a, c, source); |
| 1645 | if (!frag) { |
| 1646 | continue; |
| 1647 | } |
| 1648 | size_t fl = strlen(frag); |
| 1649 | if (pos + fl >= TPL_BUF) { |
| 1650 | return NULL; |
| 1651 | } |
| 1652 | memcpy(buf + pos, frag, fl); |
| 1653 | pos += fl; |
| 1654 | } else if (strcmp(k, "template_substitution") == 0) { |
| 1655 | if (pos + PAIR_LEN >= TPL_BUF) { |
| 1656 | return NULL; |
| 1657 | } |
| 1658 | buf[pos++] = '{'; |
| 1659 | buf[pos++] = '}'; |
| 1660 | } |
| 1661 | } |
| 1662 | if (pos == 0) { |
| 1663 | return NULL; |
| 1664 | } |
| 1665 | return cbm_arena_strndup(a, buf, pos); |
| 1666 | } |
no test coverage detected