When other plugins collide

n: smd_wrap | v: 0.3.0 | f: /

Documentation for the Textpattern plugin smd_wrap by Stef Dawson follows this short message from our sponsor ;-)

Plugin list button Plugin download button Compressed plugin download button

smd_wrap / smd_wrap_all

Wrap text with HTML, class, prefix, suffix, and apply tranforms to it in the process (linkify, format as date, trim, escape, sanitize, etc).

If the Textpattern tags inside the item you are intending to wrap returns nothing then no wrap is applied and nothing is displayed. This makes it an ideal candidate for placing around other tags and saves having to do the “assign content to <txp:variable>, check if variable exists” dance. <txp:else /> is supported so you may take action if the contained content is empty.

If you want the plugin to wrap your content if there is any content in its form/container (e.g. if you are using it to wrap around a {replacement} tag or something) then use <txp:smd_wrap_all /> instead.

Installation / uninstallation

Download the plugin from either GitHub, or the software page, paste the code into the TXP Admin->Plugins pane, install and enable the plugin.

To uninstall the plugin, simply delete the plugin from the Admin->Plugins page

Visit the forum thread for more info or to report on the success or otherwise of the plugin.

Tags: <txp:smd_wrap> / <txp:smd_wrap_all>

Wrap the item or tag’s container with standard Txp wraptag paraphernalia. The content is parsed so you can include other Txp tags. If the results of the parse return nothing, the plugin does nothing, though you may fire an optional <txp:else /> if you wish inside your container. The following attributes configure the plugin:

item
The thing to wrap. Can be text, a tag-in-tag or some {replacement} from other smd_ plugins. If not specifed, the container is used as input unless form is given. If you use this attribute you should probably self-close <txp:smd_wrap />.
form
An alternative to item for specifying the thing to wrap. If not used, and no item is given, the container is used as input.
If you employ a container as well, you can use <txp:yield /> inside your form to plug the contained content in. Any contained content is trimmed (if trim="1") and parsed before insertion.
wraptag
Wrap this HTML tag around the item. Specify it without angle brackets, e.g. wraptag="span"
class
Assign this CSS class to the wraptag. Unused if wraptag is empty.
html_id
Assign this HTML id value to the wraptag. Unused if wraptag is empty.
attr
Supply your own name=value pairs to add to the wraptag. For example, attr="rel|external, title|My useful popup title" would add rel="external" title="My useful popup title" as attributes to the wraptag.
label
Put this text as a heading / label before the item.
labeltag
Wrap the label with this HTML tag. Specify without angle brackets, e.g. labeltag="h4"
trim
Strip leading and trailing whitespace from the item before it has prefix and suffix applied. Use trim="0" to turn this feature off.
Default: 1
prefix
Put this text before the item. It is prepended prior to the item being passed through any transform chain.
suffix
Put this text after the item. It is appended prior to the item being passed through any transform chain.
transform
Apply transformations to the item. Transforms can be chained and are applied in order, each one separated by delim. Transform configuration parameters are separated by param_delim. The following transforms are defined (see the examples below for more information) :
add — append some text to the item. This is not the same as using prefix / suffix because the add transform can be inserted into the chain at any point. Use the second argument to determine in which position to add the new text; the text itself is the third argument. Here are the positional options:
before — add the text at the start of the item.
after — add the text at the end of the item.
both — add the text at both start and end of the item.
case — change the case of the item. You may chain case transforms in sequence, e.g. transform="case|lower|ucfirst". Choose from:
upper — upper case.
lower — lower case.
ucfirst — upper case first character of sentence.
ucwords — upper case first character of every word.
title — intelligent(ish) version of ucwords that ignores small words and tries to leave intentional first-lower-case words (e.g. iPhone) alone. Works best on English but does support Unicode up to a point. You can specify your own list of words by creating a hidden pref called smd_wrap_small_words. List each word separated by a pipe. You may use regex strings if you wish but no sanitization is done so be careful! The default list of ignored short words are: a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|vs?[.]?|via
currency — format as a monetary value. Optional parameters:
format string as defined in PHP’s money_format. If not set, %.2n is used
locale string. Current locale used if not set
cut — chop the item at the given character/word limit, providing it is longer than the passed value. Note that if the item contains HTML tags then the output is likely to be spurious (wrong count, or with unclosed tags) so it’s best to employ strip_tags first. See example 7. Arguments can be of the following form:
some_number (plus optional c): chop at the given number of characters
some_number (plus w): chop at the given number of words
some_string: the continuation character(s) to add to the end of the item if it has been truncated (e.g. ... or &hellip;)
date or time — treat the item as a date and/or time, formatting it according to the strftime() compatible string given as the first argument. The item can either be a numeric (UNIX) timestamp or an English date string in an acceptable format. For datetime fields you could split the string first just to get the date portion.
escape — run the item through htmlspecialchars(). Use additional parameters to list optional flags or use any of the following special values:
no_quotesENT_NOQUOTES
double_quotesENT_COMPAT
all_quotesENT_QUOTES
fordb — run the item through Txp’s doSlash(). Always consider using this if you are posting the item back to the database (beware that other plugins may do this for you, so be careful not to duplicate it or you’ll get backslashes where there shouldn’t be backslashes).
form — pass the item through the nominated forms. Specify each form as an argument, and inside those forms place <txp:smd_wrap_info /> where you wish the item to be inserted. You may also use {smd_wrap_it} but this may not be as secure as using the tag.
link — turn the item into a clickable URL anchor. Without an argument, the link text will be the link itself. If you specify an argument, the link text will be set to whatever you choose.
no_widow — whether to allow the last word of the item to word-wrap to the next line. If you specify 0 as the argument, word-wrap will be allowed. Specifying 1 means the last word will never be allowed to wrap on its own. Without an argument, the Advanced Pref determines the behaviour.
number — treat the item as numeric. The first parameter is optional and specifies the locale to assume (default: current locale). After that, three further optional parameters may be supplied:
1: decimal places
2: decimal point character
3: thousands separator character
replace — find a string or regex and replace it with something else. Additional parameters are:
1: type: either string (or omitted) for a regular replace, or regex for a regular expression
2: from: the string to search for. If using a regex, you MUST specify the regular expression delimiters as well or you’ll get an error
3: to: the text with which to replace any found strings. If omited, the found strings will simply be removed
round — treat the item as a number and round it to the nearest whole number or positive value. One optional argument can either be:
down — round down
up — round up
positive — ignore sign
some number — the decimal precision to round the value to
sanitize — clean the item either for:
url — address bar use.
file — filename use.
url_title — use as a URL title.
encode — percent-encoded URL use
raw — raw percent-encoded URL use compliant with RFC 3986
split — split the item at the given character(s) and return one or more parts, optionally joined by the given characters. Parameters:
1: split character(s)
2: join character(s)
3+: which pieces to return, each separated by param_delim. You can either use numeric indices to specify discrete parts, e.g. 1|4 returns the first and 4th parts. You can specify negative numbers to get parts starting from the end, e.g. -1|-2 returns the last and penultimate elements. last is a synonym for -1, all returns every piece, and rand chooses one piece at random. In addition you can also use greater-than and less-than symbols before a value to only return elements higher or lower than the given value, e.g. >2 returns the 3rd, 4th, 5th,… elements. See example 3 for details.
strip_tags — remove all HTML / PHP tags from the item.
textile — pass the item through the Textile processor.
trim — remove leading and trailing characters from the item. Specify a list of characters as the argument. Without an argument, whitespace will be removed.
delim
The plugin delimiter.
Default: comma (,)
param_delim
The argument delimiter.
Default: pipe (|)
debug
Display the item the tag is trying to wrap.

Example 1: Link anchor

<txp:variable name="docs" value="https://docs.textpattern.com/" />
<txp:smd_wrap wraptag="div" class="external"
     transform="link|Textpattern documentation">
   <txp:variable name="wiki" />
</txp:smd_wrap>

Returns:

<a href="https://docs.textpattern.com/">Textpattern documentation</a>

Example 2: Date formatting

Notice that because we’re using a comma in the formatted string, the delim needs to be altered to some other (in this case arbitrary) string:

<txp:smd_wrap delim="@"
     transform="date|%A, %d %B, %Y %l:%M%p">
2011-9-12 05:30:00
</txp:smd_wrap>

Returns: Monday, 12 September, 2011 5:30AM

Example 3: Split and join

3a: Get a filename extension

Notice no join character is specified in the third argument (although it doesn’t hurt to include one; it won’t be used in this case):

<txp:smd_wrap transform="split|.||last"
     item="/path/to/some/really.big.file.name.jpg" />

Returns: jpg

3b: Get the file path and filename extension

Separated by colon (last is the same as -1) :

<txp:smd_wrap transform="split|.|:|1|-1">
/path/to/some/really.big.file.name.jpg
</txp:smd_wrap>

Returns: /path/to/some/really:jpg

3c: Split the date portion of a combined datetime

<txp:smd_wrap delim="@"
     transform="split| ||1 @ date|%A, %d %B, %Y">
2011-9-12 05:30:00
</txp:smd_wrap>

Returns: Monday, 12 September, 2011

3d: Make an HTML list from some other markup system

<txp:smd_wrap wraptag="ul"
     transform="split|#|</li><li>|>1, add|before|<li>, add|after|</li>">
# First
# Second
# Third
# Fourth
</txp:smd_wrap>

Returns:

<ul>
   <li> First</li>
   <li> Second</li>
   <li> Third</li>
   <li> Fourth</li>
</ul>

A couple of things to note about this example:

  • The add transform is used instead of prefix / suffix. This is because the latter pair become part of the item/container and are then split with the transform attribute. In this case we need to add the opening and closing tags afterwards.
  • Splitting at ‘#’ renders an empty element before the “First” entry, so the transform is instructed to return items >1.

Example 4: with smd_query {replacements}

Wrap the custom_6 value with a div and sanitize it for use in a URL. If custom_6 is empty, nothing would be displayed.

<txp:smd_query query="SELECT * FROM wherever">
   <txp:smd_wrap item="{custom_6}" wraptag="div"
     transform="sanitize|url" />
</txp:smd_query>

If you wanted to trap the condition when custom_6 might be empty:

<txp:smd_query query="SELECT * FROM wherever">
   <txp:smd_wrap wraptag="div" transform="sanitize|url">
      {custom_6}
   <txp:else />
      <p>Sorry, custom_6 is empty</p>
   </txp:smd_wrap>
</txp:smd_query>

Example 5: find / replace

<txp:smd_wrap
     transform="replace||fox|badger">
Farewell my fox, it's been fun!
</txp:smd_wrap>

Returns: Farewell my badger, it's been fun!

Note that the 2nd parameter (‘type’) has been omitted. You could specify ‘string’ here if you wished.

Example 6: form + container + yield

If pulling data from the user table from, say, smd_query you could reformat it:

<txp:smd_wrap form="wrap_me"
     transform="replace||agent_hunt|Ethan Hunt">
{author}, is to explain the use of smd_wrap
</txp:smd_wrap>

where wrap_me contains:

Your mission, <txp:yield />.
This message will self-destruct in 5 seconds.

That will:

  • stuff the {author} into the container from the surrounding plugin’s replacement tag
  • inject the container into the form where the yield tag is
  • run the transform so if the author was agent_hunt the entire message would read: “Your mission, Ethan Hunt, is to explain the use of smd_wrap. This message will self-destruct in 5 seconds.”

Example 7: truncate to excerpt

Useful for excerpting data:

<txp:smd_wrap_all
     transform="strip_tags, cut|180|25w|&hellip;">
Bacon ipsum dolor sit amet shoulder drumstick boudin
frankfurter. Andouille shoulder pastrami, rump cow
sausage ribeye shankle swine. Tail meatball cow pork.
Rump ham salami meatloaf sirloin beef ribs.
</txp:smd_wrap_all>

That will write out the string and cut it first at 180 characters, then make sure there are no more than 25 words in it. Thus it will end at: Rump ham salami…

If you omitted the 25w or your chosen word count was higher than the number of remaining words you would see the following: Rump ham salami meatlo…

Author / credits

Written by Stef Dawson. Thanks to the jakob for making a business case for creating this plugin, and of course the adi_wrap plugin for inspiration.

Source code

If you’d rather frolic in the raw code halls, you’ll need to step into the view source page.

Legacy software

If, for some inexplicable reason, you need an ancient version of a plugin, it can probably be found on the plugin archive page.

Experimental software

If you’re feeling brave, or fancy swimming with piranhas, you can test out some of my beta code. It can be found on the plugin beta page.