From 57127701e43efa99b1c70818efeeb6265f9b7c3d Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Mon, 4 Mar 2019 23:12:46 +0100 Subject: [PATCH] Markup: Added support for CSS and JS inside of CDATAs (#1660) This adds support for CSS/JS inside of (any number of) CDATAs. --- components/prism-css.js | 10 +-- components/prism-css.min.js | 2 +- components/prism-javascript.js | 10 +-- components/prism-javascript.min.js | 2 +- components/prism-markup.js | 44 +++++++++++ components/prism-markup.min.js | 2 +- prism.js | 64 ++++++++++----- .../markup!+css+javascript/issue1240.test | 17 ++-- .../languages/markup!+css/css_inclusion.test | 78 +++++++++++++++---- .../javascript_inclusion.test | 75 +++++++++++++++--- .../script_feature.test | 6 +- 11 files changed, 239 insertions(+), 71 deletions(-) diff --git a/components/prism-css.js b/components/prism-css.js index c19692070c..4570d8f2f4 100644 --- a/components/prism-css.js +++ b/components/prism-css.js @@ -22,15 +22,7 @@ Prism.languages.css = { Prism.languages.css['atrule'].inside.rest = Prism.languages.css; if (Prism.languages.markup) { - Prism.languages.insertBefore('markup', 'tag', { - 'style': { - pattern: /()[\s\S]*?(?=<\/style>)/i, - lookbehind: true, - inside: Prism.languages.css, - alias: 'language-css', - greedy: true - } - }); + Prism.languages.markup.tag.addInlined('style', 'css'); Prism.languages.insertBefore('inside', 'attr-value', { 'style-attr': { diff --git a/components/prism-css.min.js b/components/prism-css.min.js index 8e569afdbd..56b69ee0fc 100644 --- a/components/prism-css.min.js +++ b/components/prism-css.min.js @@ -1 +1 @@ -Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?[\s\S]*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},Prism.languages.css.atrule.inside.rest=Prism.languages.css,Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/()[\s\S]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css",greedy:!0}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag)); \ No newline at end of file +Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?[\s\S]*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},Prism.languages.css.atrule.inside.rest=Prism.languages.css,Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("style","css"),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag)); \ No newline at end of file diff --git a/components/prism-javascript.js b/components/prism-javascript.js index a564895d9e..4b389e612d 100644 --- a/components/prism-javascript.js +++ b/components/prism-javascript.js @@ -77,15 +77,7 @@ Prism.languages.insertBefore('javascript', 'string', { }); if (Prism.languages.markup) { - Prism.languages.insertBefore('markup', 'tag', { - 'script': { - pattern: /()[\s\S]*?(?=<\/script>)/i, - lookbehind: true, - inside: Prism.languages.javascript, - alias: 'language-javascript', - greedy: true - } - }); + Prism.languages.markup.tag.addInlined('script', 'javascript'); } Prism.languages.js = Prism.languages.javascript; diff --git a/components/prism-javascript.min.js b/components/prism-javascript.min.js index df9ba772b5..912c02569e 100644 --- a/components/prism-javascript.min.js +++ b/components/prism-javascript.min.js @@ -1 +1 @@ -Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},/\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/],number:/\b(?:(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+)n?|\d+n|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,"function":/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\${[^}]+}/,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript",greedy:!0}}),Prism.languages.js=Prism.languages.javascript; \ No newline at end of file +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},/\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/],number:/\b(?:(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+)n?|\d+n|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,"function":/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\${[^}]+}/,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript; \ No newline at end of file diff --git a/components/prism-markup.js b/components/prism-markup.js index 39d456d9b9..ca365e2786 100644 --- a/components/prism-markup.js +++ b/components/prism-markup.js @@ -50,6 +50,50 @@ Prism.hooks.add('wrap', function(env) { } }); +Object.defineProperty(Prism.languages.markup.tag, 'addInlined', { + /** + * Adds an inlined language to markup. + * + * An example of an inlined language is CSS with `\r\n\t`"]]], - ["punctuation", ";"] + ["language-javascript", [ + ["keyword", "let"], + " str ", + ["operator", "="], + ["template-string", [ + ["string", "`\r\n\t\t\r\n\t`"] + ]], + ["punctuation", ";"] + ]] ]], ["tag", [ ["tag", [ @@ -35,4 +38,4 @@ ---------------------------------------------------- -Checks for Javascript usage inside Markup, using + +'; +]]> +"foo" + + ---------------------------------------------------- [ - ["tag", [ ["tag", [ ["punctuation", "<"], "script" ]], - ["attr-name", [ - "type" - ]], + ["attr-name", ["type"]], ["attr-value", [ ["punctuation", "="], ["punctuation", "\""], @@ -24,9 +30,11 @@ ["punctuation", ">"] ]], ["script", [ - ["function", "foo"], - ["punctuation", "("], - ["punctuation", ")"] + ["language-javascript", [ + ["function", "foo"], + ["punctuation", "("], + ["punctuation", ")"] + ]] ]], ["tag", [ ["tag", [ @@ -44,7 +52,56 @@ ["punctuation", ">"] ]], ["script", [ - ["string", "\"foo bar\""] + ["language-javascript", [ + ["string", "\"foo bar\""] + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "script" + ]], + ["attr-name", ["type"]], + ["attr-value", [ + ["punctuation", "="], + ["punctuation", "\""], + "application/javascript", + ["punctuation", "\""] + ]], + ["punctuation", ">"] + ]], + ["script", [ + ["language-javascript", [ + ["keyword", "var"], + " a ", + ["operator", "="], + ["number", "0"], + ["punctuation", ";"] + ]], + ["included-cdata", [ + ["cdata", "'"], + ["punctuation", ";"] + ]] + ]], + ["cdata", "]]>"] + ]], + ["language-javascript", [ + ["string", "\"foo\""] + ]] ]], ["tag", [ ["tag", [ @@ -57,4 +114,4 @@ ---------------------------------------------------- -Checks for Javascript usage inside Markup, using