Mojito
view release on metacpan or search on metacpan
files/syntax_highlight/prettify.js view on Meta::CPAN
* successive chunks of text, and will maintain its own internal state to
* keep track of how tabs are expanded.
* @return {function (string) : string} a function that takes
* plain text and return the text with tabs expanded.
* @private
*/
function makeTabExpander(tabWidth) {
var SPACES = ' ';
var charInLine = 0;
return function (plainText) {
// walk over each character looking for tabs and newlines.
// On tabs, expand them. On newlines, reset charInLine.
// Otherwise increment charInLine
var out = null;
var pos = 0;
for (var i = 0, n = plainText.length; i < n; ++i) {
var ch = plainText.charAt(i);
switch (ch) {
case '\t':
if (!out) { out = []; }
out.push(plainText.substring(pos, i));
// calculate how much space we need in front of this part
// nSpaces is the amount of padding -- the number of spaces needed
// to move us to the next column, where columns occur at factors of
// tabWidth.
var nSpaces = tabWidth - (charInLine % tabWidth);
charInLine += nSpaces;
for (; nSpaces >= 0; nSpaces -= SPACES.length) {
out.push(SPACES.substring(0, nSpaces));
}
pos = i + 1;
break;
case '\n':
charInLine = 0;
break;
default:
++charInLine;
}
}
if (!out) { return plainText; }
out.push(plainText.substring(pos));
return out.join('');
};
}
var pr_chunkPattern = new RegExp(
'[^<]+' // A run of characters other than '<'
+ '|<\!--[\\s\\S]*?--\>' // an HTML comment
+ '|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>' // a CDATA section
// a probable tag that should not be highlighted
+ '|<\/?[a-zA-Z](?:[^>\"\']|\'[^\']*\'|\"[^\"]*\")*>'
+ '|<', // A '<' that does not begin a larger chunk
'g');
var pr_commentPrefix = /^<\!--/;
var pr_cdataPrefix = /^<!\[CDATA\[/;
var pr_brPrefix = /^<br\b/i;
var pr_tagNameRe = /^<(\/?)([a-zA-Z][a-zA-Z0-9]*)/;
/** split markup into chunks of html tags (style null) and
* plain text (style {@link #PR_PLAIN}), converting tags which are
* significant for tokenization (<br>) into their textual equivalent.
*
* @param {string} s html where whitespace is considered significant.
* @return {Object} source code and extracted tags.
* @private
*/
function extractTags(s) {
// since the pattern has the 'g' modifier and defines no capturing groups,
// this will return a list of all chunks which we then classify and wrap as
// PR_Tokens
var matches = s.match(pr_chunkPattern);
var sourceBuf = [];
var sourceBufLen = 0;
var extractedTags = [];
if (matches) {
for (var i = 0, n = matches.length; i < n; ++i) {
var match = matches[i];
if (match.length > 1 && match.charAt(0) === '<') {
if (pr_commentPrefix.test(match)) { continue; }
if (pr_cdataPrefix.test(match)) {
// strip CDATA prefix and suffix. Don't unescape since it's CDATA
sourceBuf.push(match.substring(9, match.length - 3));
sourceBufLen += match.length - 12;
} else if (pr_brPrefix.test(match)) {
// <br> tags are lexically significant so convert them to text.
// This is undone later.
sourceBuf.push('\n');
++sourceBufLen;
} else {
if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) {
// A <span class="nocode"> will start a section that should be
// ignored. Continue walking the list until we see a matching end
// tag.
var name = match.match(pr_tagNameRe)[2];
var depth = 1;
var j;
end_tag_loop:
for (j = i + 1; j < n; ++j) {
var name2 = matches[j].match(pr_tagNameRe);
if (name2 && name2[2] === name) {
if (name2[1] === '/') {
if (--depth === 0) { break end_tag_loop; }
} else {
++depth;
}
}
}
if (j < n) {
extractedTags.push(
sourceBufLen, matches.slice(i, j + 1).join(''));
i = j;
} else { // Ignore unclosed sections.
extractedTags.push(sourceBufLen, match);
}
} else {
extractedTags.push(sourceBufLen, match);
}
}
} else {
( run in 3.919 seconds using v1.01-cache-2.11-cpan-71847e10f99 )