Last active
August 10, 2026 11:16
-
-
Save watershed/cb3fced9bb62c0debae41c15df8960ae to your computer and use it in GitHub Desktop.
Segmenting text via a Twig macro for Craft CMS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {# Arguments: | |
| - text: string segmented with `|` -- with optional incorporation of: | |
| - `^text^` to denote visual emphasis | |
| - `:delim` to denote a delimiting character that can be inclusively hidden via CSS | |
| - Markdown syntax for inline scopes | |
| - Inline emphasis must *not* span segment boundaries that are invoked by `|` | |
| - classArr: optional array of class names to be applied to each respective segment | |
| #} | |
| {% macro segText(text, classArr) %} | |
| {% set html = [] %} | |
| {% set segs = text|split('|') %} | |
| {% for seg in segs %} | |
| {% set seg = seg|trim %} | |
| {# A default class name for each segment #} | |
| {% set class = ["seg-#{loop.index}"] %} | |
| {% if classArr %} | |
| {# Extend the default class name with the relevant one from the array #} | |
| {% set custom = classArr[loop.index0] is defined ? classArr[loop.index0] : null %} | |
| {% set class = custom ? class|merge([custom]) : class %} | |
| {% endif %} | |
| {# Look for a sub-string of the form: ^text^, to denote a visually emphasised segment #} | |
| {% set patt = '/^\\^([^\\^]+)\\^/' %} | |
| {% set class = seg matches patt ? class|merge(['em']) : class %} | |
| {# Remove any use of '^' #} | |
| {% set seg = seg matches patt ? seg|replace(patt, '$1') : seg %} | |
| {# Look for the presence of a delimter to provide the option to inclusively hide it #} | |
| {% set patt = '/^(.*)(:|;|,)delim/' %} | |
| {% set seg = seg matches patt ? seg|replace(patt, '$1<span class="delim">$2</span>') : seg %} | |
| {# Allow for use of inline Markdown in the input text #} | |
| {% set seg = seg|md(inlineOnly=true)|replace('&', '&') %} | |
| {# Create the segment and merge it into the html array #} | |
| {% set elem = tag('span', { class: class|join(' '), html: seg }) %} | |
| {% set html = html|merge([ elem ]) %} | |
| {% endfor %} | |
| {{ html|join(' ')|raw }} | |
| {% endmacro %} |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example input string aiming for visual emphasis:
HTML outcome:
Example input with punctuation that is not structurally classified as a delimiter:
HTML outcome:
Example input with delimiter:
HTML outcome:
Example input with inline emphasis
HTML outcome: