diff --git a/components/prism-markup-templating.js b/components/prism-markup-templating.js index 24dbc26fae..1c22f943b1 100644 --- a/components/prism-markup-templating.js +++ b/components/prism-markup-templating.js @@ -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); + } } - } -}); \ No newline at end of file + }); + +}(Prism)); diff --git a/components/prism-markup-templating.min.js b/components/prism-markup-templating.min.js index 6e7b30de03..daef928f57 100644 --- a/components/prism-markup-templating.min.js +++ b/components/prism-markup-templating.min.js @@ -1 +1 @@ -Prism.languages["markup-templating"]={},Object.defineProperties(Prism.languages["markup-templating"],{buildPlaceholders:{value:function(e,t,n,a){e.language===t&&(e.tokenStack=[],e.code=e.code.replace(n,function(n){if("function"==typeof a&&!a(n))return n;for(var r=e.tokenStack.length;-1!==e.code.indexOf("___"+t.toUpperCase()+r+"___");)++r;return e.tokenStack[r]=n,"___"+t.toUpperCase()+r+"___"}),e.grammar=Prism.languages.markup)}},tokenizePlaceholders:{value:function(e,t){if(e.language===t&&e.tokenStack){e.grammar=Prism.languages[t];var n=0,a=Object.keys(e.tokenStack),r=function(o){if(!(n>=a.length))for(var i=0;i-1){++n;var f,u=l.substring(0,p),_=new Prism.Token(t,Prism.tokenize(s,e.grammar,t),"language-"+t,s),k=l.substring(p+("___"+t.toUpperCase()+c+"___").length);if(u||k?(f=[u,_,k].filter(function(e){return!!e}),r(f)):f=_,"string"==typeof g?Array.prototype.splice.apply(o,[i,1].concat(f)):g.content=f,n>=a.length)break}}else g.content&&"string"!=typeof g.content&&r(g.content)}};r(e.tokens)}}}}); \ No newline at end of file +!function(e){function n(e,n){return"___"+e.toUpperCase()+n+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(t,a,r,o){if(t.language===a){var c=t.tokenStack=[];t.code=t.code.replace(r,function(e){if("function"==typeof o&&!o(e))return e;for(var r,i=c.length;-1!==t.code.indexOf(r=n(a,i));)++i;return c[i]=e,r}),t.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(t,a){function r(i){for(var u=0;u=c.length);u++){var g=i[u];if("string"==typeof g||g.content&&"string"==typeof g.content){var l=c[o],s=t.tokenStack[l],f="string"==typeof g?g:g.content,p=n(a,l),k=f.indexOf(p);if(k>-1){++o;var m=f.substring(0,k),d=new e.Token(a,e.tokenize(s,t.grammar),"language-"+a,s),h=f.substring(k+p.length),v=[];m&&v.push.apply(v,r([m])),v.push(d),h&&v.push.apply(v,r([h])),"string"==typeof g?i.splice.apply(i,[u,1].concat(v)):g.content=v}}else g.content&&r(g.content)}return i}if(t.language===a&&t.tokenStack){t.grammar=e.languages[a];var o=0,c=Object.keys(t.tokenStack);r(t.tokens)}}}})}(Prism); \ No newline at end of file