JSFiddle - React, Tailwind, and code Playground

by Daniel Lizik

HTML

<span
  class="trends-sc trendsShow-sc"
  data-trends-default-text="[[n]] some blah? [[n]]"
  data-trends-default-text-placeholder="[[n]]"
  data-trends-doors="DOORS OPEN IN [[n]] DAYS"
>
  
</span>

CSS

.trends-sc:before {
  content: attr(data-trends-display)
}

JavaScript

(function(root, app, name, factory) {

	if (typeof module === 'object' && module.exports)
    module.exports = factory();
  else if (typeof define === 'function')
    define(name, [factory]);
  else if (typeof window === 'object' && typeof root[app] === 'object')
    root[app][name] = factory();
  else if (typeof window === 'object' && typeof root[app] === 'undefined')
    root[name] = factory();

  return __sco[name] = factory();
})(this, '__sco', 'trendsTextManipulator', function() {
  'use strict';

  /**
   * @factory trendsTextManipulator
   * Abstracts away need for doing dangerous inner html.
   * Works by keeping copy/text requirements in the html
   * and manipulating the html attributes on the element.
   * The CSS, via content: attr(), is what actually displays the text in the pseudo :before element
   *
   * @param el {object} dom object
   * @param config {object} hash of options
   * @property config.defaultAttr {string}
   * @property cofnig.prefixAttr {string}
   */
   
  return function(el, userConfig) {
    var config = userConfig || {},
        defaults = {
          displayAttr: config.displayAttr || 'data-trends-display',
          paramPrefix: config.paramPrefix || 'data-trends-',
        },
        attrs = {},
        placeholderRx = null,
        originalText = el.textContent.trim(),
        p, key, val, index;
        
    for (p in el.attributes) {
      key = el.attributes[p].nodeName || '';
      index = key.indexOf(defaults.paramPrefix) > -1;
      val = el.attributes[p].nodeValue;
      if (index === true)
        attrs[key.slice(defaults.paramPrefix.length)] = val;   
    }
    
    placeholderRx = new RegExp( attrs['default-text-placeholder'].replace(/./g, function(s) { 
      return /[a-zA-Z]/.test(s) ? s : '\\' + s; 
    }), 'g' );
    
    try {
      if (!attrs['default-text'])
        throw new Error('trends text manipulator: you must supply the html element with a "data-trends-default-text" attribute');
      else if...