in src/prettify/parser/Prettify.java [506:593]
public void decorate(Job job) {
String sourceCode = job.getSourceCode();
int basePos = job.getBasePos();
/** Even entries are positions in source in ascending order. Odd enties
* are style markers (e.g., PR_COMMENT) that run from that position until
* the end.
* @type {Array.<number|string>}
*/
List<Object> decorations = new ArrayList<Object>(Arrays.asList(new Object[]{basePos, PR_PLAIN}));
int pos = 0; // index into sourceCode
String[] tokens = Util.match(tokenizer, sourceCode, true);
Map<String, String> styleCache = new HashMap<String, String>();
for (int ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
String token = tokens[ti];
String style = styleCache.get(token);
String[] match = null;
boolean isEmbedded;
if (style != null) {
isEmbedded = false;
} else {
List<Object> patternParts = shortcuts.get(token.charAt(0));
if (patternParts != null) {
match = Util.match((Pattern) patternParts.get(1), token, false);
style = (String) patternParts.get(0);
} else {
for (int i = 0; i < nPatterns; ++i) {
patternParts = fallthroughStylePatterns.get(i);
match = Util.match((Pattern) patternParts.get(1), token, false);
if (match.length != 0) {
style = (String) patternParts.get(0);
break;
}
}
if (match.length == 0) { // make sure that we make progress
style = PR_PLAIN;
}
}
isEmbedded = style != null && style.length() >= 5 && style.startsWith("lang-");
if (isEmbedded && !(match.length > 1 && match[1] != null)) {
isEmbedded = false;
style = PR_SOURCE;
}
if (!isEmbedded) {
styleCache.put(token, style);
}
}
int tokenStart = pos;
pos += token.length();
if (!isEmbedded) {
decorations.add(basePos + tokenStart);
decorations.add(style);
} else { // Treat group 1 as an embedded block of source code.
String embeddedSource = match[1];
int embeddedSourceStart = token.indexOf(embeddedSource);
int embeddedSourceEnd = embeddedSourceStart + embeddedSource.length();
if (match.length > 2 && match[2] != null) {
// If embeddedSource can be blank, then it would match at the
// beginning which would cause us to infinitely recurse on the
// entire token, so we catch the right context in match[2].
embeddedSourceEnd = token.length() - match[2].length();
embeddedSourceStart = embeddedSourceEnd - embeddedSource.length();
}
String lang = style.substring(5);
// Decorate the left of the embedded source
appendDecorations(basePos + tokenStart,
token.substring(0, embeddedSourceStart),
this, decorations);
// Decorate the embedded source
appendDecorations(basePos + tokenStart + embeddedSourceStart,
embeddedSource,
langHandlerForExtension(lang, embeddedSource),
decorations);
// Decorate the right of the embedded section
appendDecorations(basePos + tokenStart + embeddedSourceEnd,
token.substring(embeddedSourceEnd),
this, decorations);
}
}
job.setDecorations(Util.removeDuplicates(decorations, job.getSourceCode()));
}