text: /**
   * Process Markdown `<pre><code>` blocks.
   */
  showdown.subParser('codeBlocks', function (text, options, globals) {
    'use strict';
  
    text = globals.converter._dispatch('codeBlocks.before', text, options);
    /*
     text = text.replace(text,
     /(?:\n\n|^)
     (								// $1 = the code block -- one or more lines, starting with a space/tab
     (?:
     (?:[ ]{4}|\t)			// Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
     .*\n+
     )+
     )
     (\n*[ ]{0,3}[^ \t\n]|(?=~0))	// attacklab: g_tab_width
     /g,function(){...});
     */
  
    // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
    text += '~0';
  
    var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g;
    text = text.replace(pattern, function (wholeMatch, m1, m2) {
      var codeblock = m1,
          nextChar = m2,
          end = '\n';
  
      codeblock = showdown.subParser('outdent')(codeblock);
      codeblock = showdown.subParser('encodeCode')(codeblock);
      codeblock = showdown.subParser('detab')(codeblock);
      codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
      codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
  
      if (options.omitExtraWLInCodeBlocks) {
        end = '';
      }
  
      codeblock = '<pre><code>' + codeblock + end + '</code></pre>';
  
      return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
    });
  
    // attacklab: strip sentinel
    text = text.replace(/~0/, '');
  
    text = globals.converter._dispatch('codeBlocks.after', text, options);
    return text;
  });
  