Skip to content

Commit

Permalink
Markup-templating improvements (#1653)
Browse files Browse the repository at this point in the history
This makes minor improvements to markup-templating.
  • Loading branch information
RunDevelopment committed Mar 2, 2019
1 parent 6c9fe25 commit b62e282
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 73 deletions.
178 changes: 106 additions & 72 deletions components/prism-markup-templating.js
Original file line number Diff line number Diff line change
@@ -1,89 +1,123 @@
Prism.languages['markup-templating'] = {};

Object.defineProperties(Prism.languages['markup-templating'], {
buildPlaceholders: {
// Tokenize all inline templating expressions matching placeholderPattern
// If the replaceFilter function is provided, it will be called with every match.
// If it returns false, the match will not be replaced.
value: function (env, language, placeholderPattern, replaceFilter) {
if (env.language !== language) {
return;
}
(function (Prism) {

env.tokenStack = [];
/**
* Returns the placeholder for the given language id and index.
*
* @param {string} language
* @param {string|number} index
* @returns {string}
*/
function getPlaceholder(language, index) {
return '___' + language.toUpperCase() + index + '___';
}

env.code = env.code.replace(placeholderPattern, function(match) {
if (typeof replaceFilter === 'function' && !replaceFilter(match)) {
return match;
Object.defineProperties(Prism.languages['markup-templating'] = {}, {
buildPlaceholders: {
/**
* Tokenize all inline templating expressions matching `placeholderPattern`.
*
* If `replaceFilter` is provided, only matches of `placeholderPattern` for which `replaceFilter` returns
* `true` will be replaced.
*
* @param {object} env The environment of the `before-tokenize` hook.
* @param {string} language The language id.
* @param {RegExp} placeholderPattern The matches of this pattern will be replaced by placeholders.
* @param {(match: string) => boolean} [replaceFilter]
*/
value: function (env, language, placeholderPattern, replaceFilter) {
if (env.language !== language) {
return;
}
var i = env.tokenStack.length;
// Check for existing strings
while (env.code.indexOf('___' + language.toUpperCase() + i + '___') !== -1)
++i;

// Create a sparse array
env.tokenStack[i] = match;
var tokenStack = env.tokenStack = [];

return '___' + language.toUpperCase() + i + '___';
});
env.code = env.code.replace(placeholderPattern, function (match) {
if (typeof replaceFilter === 'function' && !replaceFilter(match)) {
return match;
}
var i = tokenStack.length;
var placeholder;

// Switch the grammar to markup
env.grammar = Prism.languages.markup;
}
},
tokenizePlaceholders: {
// Replace placeholders with proper tokens after tokenizing
value: function (env, language) {
if (env.language !== language || !env.tokenStack) {
return;
}
// Check for existing strings
while (env.code.indexOf(placeholder = getPlaceholder(language, i)) !== -1)
++i;

// Switch the grammar back
env.grammar = Prism.languages[language];
// Create a sparse array
tokenStack[i] = match;

var j = 0;
var keys = Object.keys(env.tokenStack);
var walkTokens = function (tokens) {
if (j >= keys.length) {
return placeholder;
});

// Switch the grammar to markup
env.grammar = Prism.languages.markup;
}
},
tokenizePlaceholders: {
/**
* Replace placeholders with proper tokens after tokenizing.
*
* @param {object} env The environment of the `after-tokenize` hook.
* @param {string} language The language id.
*/
value: function (env, language) {
if (env.language !== language || !env.tokenStack) {
return;
}
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (typeof token === 'string' || (token.content && typeof token.content === 'string')) {
var k = keys[j];
var t = env.tokenStack[k];
var s = typeof token === 'string' ? token : token.content;

var index = s.indexOf('___' + language.toUpperCase() + k + '___');
if (index > -1) {
++j;
var before = s.substring(0, index);
var middle = new Prism.Token(language, Prism.tokenize(t, env.grammar, language), 'language-' + language, t);
var after = s.substring(index + ('___' + language.toUpperCase() + k + '___').length);
var replacement;
if (before || after) {
replacement = [before, middle, after].filter(function (v) { return !!v; });
walkTokens(replacement);
} else {
replacement = middle;
}
if (typeof token === 'string') {
Array.prototype.splice.apply(tokens, [i, 1].concat(replacement));
} else {
token.content = replacement;
}

if (j >= keys.length) {
break;
// Switch the grammar back
env.grammar = Prism.languages[language];

var j = 0;
var keys = Object.keys(env.tokenStack);

function walkTokens(tokens) {
for (var i = 0; i < tokens.length; i++) {
// all placeholders are replaced already
if (j >= keys.length) {
break;
}

var token = tokens[i];
if (typeof token === 'string' || (token.content && typeof token.content === 'string')) {
var k = keys[j];
var t = env.tokenStack[k];
var s = typeof token === 'string' ? token : token.content;
var placeholder = getPlaceholder(language, k);

var index = s.indexOf(placeholder);
if (index > -1) {
++j;

var before = s.substring(0, index);
var middle = new Prism.Token(language, Prism.tokenize(t, env.grammar), 'language-' + language, t);
var after = s.substring(index + placeholder.length);

var replacement = [];
if (before) {
replacement.push.apply(replacement, walkTokens([before]));
}
replacement.push(middle);
if (after) {
replacement.push.apply(replacement, walkTokens([after]));
}

if (typeof token === 'string') {
tokens.splice.apply(tokens, [i, 1].concat(replacement));
} else {
token.content = replacement;
}
}
} else if (token.content /* && typeof token.content !== 'string' */) {
walkTokens(token.content);
}
} else if (token.content && typeof token.content !== 'string') {
walkTokens(token.content);
}

return tokens;
}
};

walkTokens(env.tokens);
walkTokens(env.tokens);
}
}
}
});
});

}(Prism));
2 changes: 1 addition & 1 deletion components/prism-markup-templating.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b62e282

Please sign in to comment.