docs: function processListItems (listStr, trimTrailing) {
      // The $g_list_level global keeps track of when we're inside a list.
      // Each time we enter a list, we increment it; when we leave a list,
      // we decrement. If it's zero, we're not in a list anymore.
      //
      // We do this because when we're not inside a list, we want to treat
      // something like this:
      //
      //    I recommend upgrading to version
      //    8. Oops, now this line is treated
      //    as a sub-list.
      //
      // As a single paragraph, despite the fact that the second line starts
      // with a digit-period-space sequence.
      //
      // Whereas when we're inside a list (or sub-list), that line will be
      // treated as the start of a sub-list. What a kludge, huh? This is
      // an aspect of Markdown's syntax that's hard to parse perfectly
      // without resorting to mind-reading. Perhaps the solution is to
      // change the syntax rules such that sub-lists must start with a
      // starting cardinal number; e.g. "1." or "a.".
      globals.gListLevel++;
  
      // trim trailing blank lines:
      listStr = listStr.replace(/\n{2,}$/, '\n');
  
      // attacklab: add sentinel to emulate \z
      listStr += '~0';
  
      var rgx = /(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+((\[(x| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
          isParagraphed = (/\n[ \t]*\n(?!~0)/.test(listStr));
  
      listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {
        checked = (checked && checked.trim() !== '');
        var item = showdown.subParser('outdent')(m4, options, globals),
            bulletStyle = '';
  
        // Support for github tasklists
        if (taskbtn && options.tasklists) {
          bulletStyle = ' class="task-list-item" style="list-style-type: none;"';
          item = item.replace(/^[ \t]*\[(x| )?]/m, function () {
            var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"';
            if (checked) {
              otp += ' checked';
            }
            otp += '>';
            return otp;
          });
        }
        // m1 - Leading line or
        // Has a double return (multi paragraph) or
        // Has sublist
        if (m1 || (item.search(/\n{2,}/) > -1)) {
          item = showdown.subParser('githubCodeBlocks')(item, options, globals);
          item = showdown.subParser('blockGamut')(item, options, globals);
        } else {
          // Recursion for sub-lists:
          item = showdown.subParser('lists')(item, options, globals);
          item = item.replace(/\n$/, ''); // chomp(item)
          if (isParagraphed) {
            item = showdown.subParser('paragraphs')(item, options, globals);
          } else {
            item = showdown.subParser('spanGamut')(item, options, globals);
          }
        }
        item =  '\n<li' + bulletStyle + '>' + item + '</li>\n';
        return item;
      });
  
      // attacklab: strip sentinel
      listStr = listStr.replace(/~0/g, '');
  
      globals.gListLevel--;
  
      if (trimTrailing) {
        listStr = listStr.replace(/\s+$/, '');
      }
  
      return listStr;
    }