module

Hwaro::Utils::TextUtils

Constants

RAW_TEXT_ELEMENT = /<(script|style)(?:\s[^>]*)?>[\s\S]*?<\/\1\s*>/i

Raw-text HTML elements whose content is code, not display text. &lt;style&gt;/&lt;script&gt; bodies must be dropped along with their tags; otherwise the CSS/JS source survives tag-stripping and pollutes search indexes, feed summaries, and excerpts (a page with an inline &lt;style&gt; gallery block had its whole search entry replaced by CSS). [\s\S] matches across newlines (CSS/JS span multiple lines) without relying on a dotall flag; \1 ties the close tag to the open tag. A self-closing or unterminated tag won't match and is left to the tag stripper below.

Instance methods

cjk_char?(char : Char) : Bool

Check if a character is in a CJK Unicode range

Source
disambiguated_slugs(terms : Array(String)) : Hash(String, String)

Map a set of terms to UNIQUE slugs. Distinct terms can slugify to the same value (&quot;C++&quot;/&quot;C#&quot; โ†’ &quot;c&quot;, &quot;Hello World&quot;/&quot;hello-world&quot; โ†’ &quot;hello-world&quot;); on a clash the later term (in sorted order) gets a numeric suffix, and the candidate is re-checked so it never collides with another generated slug or a real term whose base slug already ends in &quot;-2&quot;. Sorting makes the result deterministic across builds regardless of input order.

This is the single source of truth for taxonomy term slugs: the taxonomy generator (term-page paths + index links) and the get_taxonomy / get_taxonomy_url template helpers must all run terms through here so the links they emit point at the pages that were actually written.

Source
encode_url_path(url : String) : String

Percent-encode the path component of a URL for spec-strict XML outputs (sitemap &lt;loc&gt;, RSS/Atom &lt;link&gt;/&lt;id&gt;): the sitemap protocol and RSS require RFC 3986 URIs, so non-ASCII paths like /posts/ํ•œ๊ธ€/ must become /posts/%ED%95%9C%EA%B8%80/.

The scheme/host prefix (if any) is left untouched, and paths that already contain a percent-escape are passed through unchanged so pre-encoded URLs don't get double-encoded.

Source
escape_xml(text : String) : String

Escape XML special characters

Escapes: &amp; &lt; &gt; &quot; '

Example: escape_xml(&quot;Tom &amp; Jerry&quot;) # =&gt; &quot;Tom &amp;amp; Jerry&quot; escape_xml(&quot;&quot;) # =&gt; &quot;&lt;script&gt;&quot;

Source
safe_slugify(text : String) : String

Like slugify but never returns &quot;&quot;. An all-symbol/emoji input (e.g. a tag of &quot;!!!&quot; or &quot;๐ŸŽ‰&quot;) slugifies to &quot;&quot;, which would make distinct terms collide onto the same URL/output path and create a // path segment. Falls back to a deterministic, stable token derived from the input's UTF-8 bytes so distinct inputs stay distinct and the slug is identical across builds (unlike String#hash, which is per-process seeded).

Source
slugify(text : String) : String

Convert text to a URL-friendly slug

Supports Unicode characters (CJK, Hangul, etc.) in addition to ASCII.

Examples: slugify(&quot;Hello World!&quot;) # =&gt; &quot;hello-world&quot; slugify(&quot;My Blog Post&quot;) # =&gt; &quot;my-blog-post&quot; slugify(&quot;ํ•œ๊ธ€ ์ œ๋ชฉ&quot;) # =&gt; &quot;ํ•œ๊ธ€-์ œ๋ชฉ&quot; slugify(&quot;CJK ํ…Œ์ŠคํŠธ!&quot;) # =&gt; &quot;cjk-ํ…Œ์ŠคํŠธ&quot;

Source
strip_html(text : String) : String

Strip HTML tags from text (single-pass)

Example: strip_html(&quot;

Hello World

&quot;) # =&gt; &quot;Hello World&quot;

Source
tokenize_cjk(text : String) : String

Tokenize CJK text into overlapping bigrams for search indexing

CJK languages (Chinese, Japanese, Korean) often lack spaces between words. This splits CJK character runs into overlapping 2-character pairs (bigrams) so search libraries can match substrings.

Example: tokenize_cjk(&quot;๊ฒ€์ƒ‰์—”์ง„&quot;) # =&gt; &quot;๊ฒ€์ƒ‰ ์ƒ‰์—” ์—”์ง„&quot; tokenize_cjk(&quot;helloไธ–็•Œๆต‹่ฏ•&quot;) # =&gt; &quot;helloไธ–็•Œ ็•Œๆต‹ ๆต‹่ฏ•&quot;

Source