Commit 54e2eeab093ad6ba4a25f929fbd35bcab4d6cdd0

Lea Verou 2012-07-29T00:26:50

Added (and documented) Prism.languages.insertBefore

diff --git a/components/prism-core.js b/components/prism-core.js
index 948e9af..a9d4874 100644
--- a/components/prism-core.js
+++ b/components/prism-core.js
@@ -10,7 +10,33 @@
 var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;
 
 var _ = self.Prism = {
-	languages: {},
+	languages: {
+		insertBefore: function (inside, before, insert, root) {
+			root = root || _.languages;
+			var grammar = root[inside];
+			var ret = {};
+				
+			for (var token in grammar) {
+			
+				if (grammar.hasOwnProperty(token)) {
+					
+					if (token == before) {
+					
+						for (var newToken in insert) {
+						
+							if (insert.hasOwnProperty(newToken)) {
+								ret[newToken] = insert[newToken];
+							}
+						}
+					}
+					
+					ret[token] = grammar[token];
+				}
+			}
+			
+			return root[inside] = ret;
+		}
+	},
 
 	highlightAll: function(async, callback) {
 		var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');
diff --git a/components/prism-core.min.js b/components/prism-core.min.js
index e2202ba..833c650 100644
--- a/components/prism-core.min.js
+++ b/components/prism-core.min.js
@@ -2,4 +2,4 @@
  * Prism: Lightweight, robust, elegant syntax highlighting
  * MIT license http://www.opensource.org/licenses/mit-license.php/
  * @author Lea Verou http://lea.verou.me
- */(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={languages:{},highlightAll:function(e,n){var r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,s;s=r[i++];)t.highlightElement(s,e===!0,n)},highlightElement:function(r,i,s){var o,u,a=r;while(a&&!e.test(a.className))a=a.parentNode;if(a){o=(a.className.match(e)||[,""])[1];u=t.languages[o]}if(!u)return;r.className=r.className.replace(e,"")+" language-"+o;a=r.parentNode;if(/pre/i.test(a.nodeName)){var f=(a.className.match(e)||[,""])[1];a.className=a.className.replace(e,"")+" language-"+f}var l=r.textContent.trim();if(!l)return;l=l.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\u00a0/g," ");var c={element:r,language:o,grammar:u,code:l};t.hooks.run("before-highlight",c);if(i&&self.Worker){var h=new Worker(t.filename);h.onmessage=function(e){c.highlightedCode=n.stringify(JSON.parse(e.data));c.element.innerHTML=c.highlightedCode;s&&s.call(c.element);t.hooks.run("after-highlight",c)};h.postMessage(JSON.stringify({language:c.language,code:c.code}))}else{c.highlightedCode=t.highlight(c.code,c.grammar);c.element.innerHTML=c.highlightedCode;s&&s.call(r);t.hooks.run("after-highlight",c)}},highlight:function(e,r){return n.stringify(t.tokenize(e,r))},tokenize:function(e,n){var r=t.Token,i=[e],s=n.rest;if(s){for(var o in s)n[o]=s[o];delete n.rest}e:for(var o in n){if(!n.hasOwnProperty(o)||!n[o])continue;var u=n[o],a=u.inside,f=!!u.lookbehind||0;u=u.pattern||u;for(var l=0;l<i.length;l++){var c=i[l];if(i.length>e.length)break e;if(c instanceof r)continue;u.lastIndex=0;var h=u.exec(c);if(h){f&&(f=h[1].length);var p=h.index-1+f,h=h[0].slice(f),d=h.length,v=p+d,m=c.slice(0,p+1),g=c.slice(v+1),y=[l,1];m&&y.push(m);var b=new r(o,a?t.tokenize(h,a):h);y.push(b);g&&y.push(g);Array.prototype.splice.apply(i,y)}}}return i},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]"){for(var r=0;r<e.length;r++)e[r]=n.stringify(e[r]);return e.join("")}var i={type:e.type,content:n.stringify(e.content),tag:"span",classes:["token",e.type],attributes:{}};i.type=="comment"&&(i.attributes.spellcheck="true");t.hooks.run("wrap",i);var s="";for(var o in i.attributes)s+=o+'="'+(i.attributes[o]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+s+">"+i.content+"</"+i.tag+">"};if(!self.document){self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language;code=n.code;self.postMessage(JSON.stringify(t.tokenize(code,t.languages[r])));self.close()},!1);return}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}})();
\ No newline at end of file
+ */(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={languages:{insertBefore:function(e,n,r,i){i=i||t.languages;var s=i[e],o={};for(var u in s)if(s.hasOwnProperty(u)){if(u==n)for(var a in r)r.hasOwnProperty(a)&&(o[a]=r[a]);o[u]=s[u]}return i[e]=o}},highlightAll:function(e,n){var r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,s;s=r[i++];)t.highlightElement(s,e===!0,n)},highlightElement:function(r,i,s){var o,u,a=r;while(a&&!e.test(a.className))a=a.parentNode;if(a){o=(a.className.match(e)||[,""])[1];u=t.languages[o]}if(!u)return;r.className=r.className.replace(e,"")+" language-"+o;a=r.parentNode;if(/pre/i.test(a.nodeName)){var f=(a.className.match(e)||[,""])[1];a.className=a.className.replace(e,"")+" language-"+f}var l=r.textContent.trim();if(!l)return;l=l.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\u00a0/g," ");var c={element:r,language:o,grammar:u,code:l};t.hooks.run("before-highlight",c);if(i&&self.Worker){var h=new Worker(t.filename);h.onmessage=function(e){c.highlightedCode=n.stringify(JSON.parse(e.data));c.element.innerHTML=c.highlightedCode;s&&s.call(c.element);t.hooks.run("after-highlight",c)};h.postMessage(JSON.stringify({language:c.language,code:c.code}))}else{c.highlightedCode=t.highlight(c.code,c.grammar);c.element.innerHTML=c.highlightedCode;s&&s.call(r);t.hooks.run("after-highlight",c)}},highlight:function(e,r){return n.stringify(t.tokenize(e,r))},tokenize:function(e,n){var r=t.Token,i=[e],s=n.rest;if(s){for(var o in s)n[o]=s[o];delete n.rest}e:for(var o in n){if(!n.hasOwnProperty(o)||!n[o])continue;var u=n[o],a=u.inside,f=!!u.lookbehind||0;u=u.pattern||u;for(var l=0;l<i.length;l++){var c=i[l];if(i.length>e.length)break e;if(c instanceof r)continue;u.lastIndex=0;var h=u.exec(c);if(h){f&&(f=h[1].length);var p=h.index-1+f,h=h[0].slice(f),d=h.length,v=p+d,m=c.slice(0,p+1),g=c.slice(v+1),y=[l,1];m&&y.push(m);var b=new r(o,a?t.tokenize(h,a):h);y.push(b);g&&y.push(g);Array.prototype.splice.apply(i,y)}}}return i},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]"){for(var r=0;r<e.length;r++)e[r]=n.stringify(e[r]);return e.join("")}var i={type:e.type,content:n.stringify(e.content),tag:"span",classes:["token",e.type],attributes:{}};i.type=="comment"&&(i.attributes.spellcheck="true");t.hooks.run("wrap",i);var s="";for(var o in i.attributes)s+=o+'="'+(i.attributes[o]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+s+">"+i.content+"</"+i.tag+">"};if(!self.document){self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language;code=n.code;self.postMessage(JSON.stringify(t.tokenize(code,t.languages[r])));self.close()},!1);return}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}})();
\ No newline at end of file
diff --git a/components/prism-markup.js b/components/prism-markup.js
index 8e9314b..24e09a3 100644
--- a/components/prism-markup.js
+++ b/components/prism-markup.js
@@ -2,8 +2,6 @@ Prism.languages.markup = {
 	'comment': /&lt;!--[\w\W]*?--(>|&gt;)/g,
 	'prolog': /&lt;\?.+?\?(>|&gt;)/,
 	'doctype': /&lt;!DOCTYPE.+?(>|&gt;)/,
-	'script': null,
-	'style': null,
 	'cdata': /&lt;!\[CDATA\[[\w\W]+]]&gt;/i,
 	'tag': {
 		pattern: /(&lt;|<)\/?[\w:-]+\s*[\w\W]*?(>|&gt;)/gi,
@@ -35,35 +33,33 @@ Prism.languages.markup = {
 };
 
 if (Prism.languages.javascript) {
-	Prism.languages.markup.script = {
-		pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,
-		inside: {
-			'tag': {
-				pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,
-				inside: Prism.languages.markup.tag.inside
-			},
-			rest: Prism.languages.javascript
+	Prism.languages.insertBefore('markup', 'cdata', {
+		'script': {
+			pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,
+			inside: {
+				'tag': {
+					pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,
+					inside: Prism.languages.markup.tag.inside
+				},
+				rest: Prism.languages.javascript
+			}
 		}
-	};
-}
-else {
-	delete Prism.languages.markup.script;
+	});
 }
 
 if (Prism.languages.css) {
-	Prism.languages.markup.style = {
-		pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,
-		inside: {
-			'tag': {
-				pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,
-				inside: Prism.languages.markup.tag.inside
-			},
-			rest: Prism.languages.css
+	Prism.languages.insertBefore('markup', 'cdata', {
+		'style': {
+			pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,
+			inside: {
+				'tag': {
+					pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,
+					inside: Prism.languages.markup.tag.inside
+				},
+				rest: Prism.languages.css
+			}
 		}
-	};
-}
-else {
-	delete Prism.languages.markup.style;
+	});
 }
 
 // Plugin to make entity title show the real entity, idea by Roman Komarov
diff --git a/components/prism-markup.min.js b/components/prism-markup.min.js
index 6840234..195b170 100644
--- a/components/prism-markup.min.js
+++ b/components/prism-markup.min.js
@@ -1 +1 @@
-Prism.languages.markup={comment:/&lt;!--[\w\W]*?--(>|&gt;)/g,prolog:/&lt;\?.+?\?(>|&gt;)/,doctype:/&lt;!DOCTYPE.+?(>|&gt;)/,script:null,style:null,cdata:/&lt;!\[CDATA\[[\w\W]+]]&gt;/i,tag:{pattern:/(&lt;|<)\/?[\w:-]+\s*[\w\W]*?(>|&gt;)/gi,inside:{tag:{pattern:/^(&lt;|<)\/?[\w:-]+/i,inside:{punctuation:/^(&lt;|<)\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(('|")[\w\W]*?(\2)|[^\s>]+)/gi,inside:{punctuation:/=/g}},punctuation:/\/?&gt;|\/?>/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&amp;#?[\da-z]{1,8};/gi};Prism.languages.javascript?Prism.languages.markup.script={pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,inside:{tag:{pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}:delete Prism.languages.markup.script;Prism.languages.css?Prism.languages.markup.style={pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,inside:{tag:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}:delete Prism.languages.markup.style;Prism.hooks.add("wrap",function(e){e.type==="entity"&&(e.attributes.title=e.content.replace(/&amp;/,"&"))});
\ No newline at end of file
+Prism.languages.markup={comment:/&lt;!--[\w\W]*?--(>|&gt;)/g,prolog:/&lt;\?.+?\?(>|&gt;)/,doctype:/&lt;!DOCTYPE.+?(>|&gt;)/,cdata:/&lt;!\[CDATA\[[\w\W]+]]&gt;/i,tag:{pattern:/(&lt;|<)\/?[\w:-]+\s*[\w\W]*?(>|&gt;)/gi,inside:{tag:{pattern:/^(&lt;|<)\/?[\w:-]+/i,inside:{punctuation:/^(&lt;|<)\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(('|")[\w\W]*?(\2)|[^\s>]+)/gi,inside:{punctuation:/=/g}},punctuation:/\/?&gt;|\/?>/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&amp;#?[\da-z]{1,8};/gi};Prism.languages.javascript&&Prism.languages.insertBefore("markup","cdata",{script:{pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,inside:{tag:{pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});Prism.languages.css&&Prism.languages.insertBefore("markup","cdata",{style:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,inside:{tag:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}});Prism.hooks.add("wrap",function(e){e.type==="entity"&&(e.attributes.title=e.content.replace(/&amp;/,"&"))});
\ No newline at end of file
diff --git a/extending.html b/extending.html
index a7d386d..c0ff002 100644
--- a/extending.html
+++ b/extending.html
@@ -9,7 +9,7 @@
 <script src="../prefixfree/prefixfree.min.js"></script>
 
 </head>
-<body>
+<body class="language-javascript">
 
 <header>
 	<div class="intro" data-src="templates/header-main.html" data-type="text/html"></div>
@@ -25,7 +25,7 @@
 	<pre data-src="components/prism-css.js"></pre>
 	
 	<p>A regular expression literal is the simplest way to express a token. An alternative way, with more options, is by using an object literal. With that notation, the regular expression describing the token would be the <code>pattern</code> attribute:</p>
-	<pre class="prism"><code class="language-javascript">...
+	<pre><code class="language-javascript">...
 'tokenname': {
 	pattern: /regex/
 }
@@ -40,25 +40,63 @@
 		<pre data-src="components/prism-markup.js"></pre></dd>
 		
 		<dt>lookbehind</dt>
-		<dd>This option mitigates JavaScript’s lack of lookbehind. When set to <code class="prism language-javascript">true</code>, 
+		<dd>This option mitigates JavaScript’s lack of lookbehind. When set to <code>true</code>, 
 		the first capturing group in the regex <code>pattern</code> is discarded when matching this token, so it effectively behaves 
-		as if it was lookbehind.</dd>
+		as if it was lookbehind. For an example of this, check out the JavaScript language definition, in particular the regex and line-comment tokens:
+		<pre data-src="components/prism-javascript.js"></pre></dd>
 		
 		<dt>rest</dt>
 		<dd>Accepts an object literal with tokens and appends them to the end of the current object literal. Useful for referring to tokens defined elsewhere. For an example where <code>rest</code> is useful, check the Markup definitions above.</dd>
 	</dl>
 	
  	<p>Unless explicitly allowed through the <code>inside</code> property, each token cannot contain other tokens, so their order is significant. Although per the ECMAScript specification, objects are not required to have a specific ordering of their properties, in practice they do in every modern browser.</p>
+ 	
+ 	<section>
+	 	<h1><code>Prism.languages.insertBefore(inside, before, insert<span class="optional" title="Default value: Prism.languages">, root</span>)</code></h1>
+ 	
+	 	<p>This is a helper method to ease modifying existing languages. For example, the CSS language definition not only defines CSS highlighting for CSS documents,
+	 	but also needs to define highlighting for CSS embedded in HTML through <code class="language-markup">&lt;style></code> elements. To do this, it needs to modify
+	 	<code>Prism.languages.markup</code> and add the appropriate tokens. However, <code>Prism.languages.markup</code>
+	 	is a regular JavaScript object literal, so if you do this:</p>
+	 	
+	 	<pre><code >Prism.languages.markup.style = {
+ 	/* tokens */
+ };</code></pre>
+	 	
+	 	<p>then the <code>style</code> token will be added (and processed) at the end. <code>Prism.languages.insertBefore</code> allows you to insert
+	 	tokens <em>before</em> existing tokens. For the CSS example above, you would use it like this:</p>
+	 	
+	 	<pre><code>Prism.languages.insertBefore('markup', 'cdata', {
+	'style': {
+		/* tokens */
+	}
+});</code></pre>
+		
+		<h2>Parameters</h2>
+		<dl>
+			<dt>inside</dt>
+			<dd>The property of <code>root</code> that contains the object to be modified.</dd>
+			
+			<dt>before</dt>
+			<dd>Key to insert before (String)</dd>
+			
+			<dt>insert</dt>
+			<dd>An object containing the key-value pairs to be inserted</dd>
+			
+			<dt>root</dt>
+			<dd>The root object, i.e. the object that contains the object that will be modified. Optional, default value is <code>Prism.languages</code>.</dd>
+		</dl>
+	</section>
 </section>
 
 <section id="writing-plugins">
 	<h1>Writing plugins</h1>
 	
-	<p>Prism’s plugin architecture is fairly simple. To add a callback, you use <code class="prism language-javascript">Prism.hooks.add(hookname, callback)</code>. 
+	<p>Prism’s plugin architecture is fairly simple. To add a callback, you use <code class="language-javascript">Prism.hooks.add(hookname, callback)</code>. 
 	<code>hookname</code> is a string with the hook id, that uniquely identifies the hook your code should run at.
 	<code>callback</code> is a function that accepts one parameter: an object with various variables that can be modified, since objects in JavaScript are passed by reference.
-	For example, here’s a plugin that enchances HTML/XML entities to include a tooltip that shows the actual character:
-	<pre class="prism"><code class="language-javascript">Prism.hooks.add('wrap', function(env) {
+	For example, here’s a plugin from the Markup language definition that adds a tooltip to entity tokens which shows the actual character encoded:
+	<pre><code class="language-javascript">Prism.hooks.add('wrap', function(env) {
 	if (env.token === 'entity') {
 		env.attributes['title'] = env.content.replace(/&amp;amp;/, '&amp;');
 	}
diff --git a/prism.js b/prism.js
index 9f1cd30..280437d 100644
--- a/prism.js
+++ b/prism.js
@@ -16,7 +16,33 @@
 var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;
 
 var _ = self.Prism = {
-	languages: {},
+	languages: {
+		insertBefore: function (inside, before, insert, root) {
+			root = root || _.languages;
+			var grammar = root[inside];
+			var ret = {};
+				
+			for (var token in grammar) {
+			
+				if (grammar.hasOwnProperty(token)) {
+					
+					if (token == before) {
+					
+						for (var newToken in insert) {
+						
+							if (insert.hasOwnProperty(newToken)) {
+								ret[newToken] = insert[newToken];
+							}
+						}
+					}
+					
+					ret[token] = grammar[token];
+				}
+			}
+			
+			return root[inside] = ret;
+		}
+	},
 
 	highlightAll: function(async, callback) {
 		var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');
@@ -325,8 +351,6 @@ Prism.languages.markup = {
 	'comment': /&lt;!--[\w\W]*?--(>|&gt;)/g,
 	'prolog': /&lt;\?.+?\?(>|&gt;)/,
 	'doctype': /&lt;!DOCTYPE.+?(>|&gt;)/,
-	'script': null,
-	'style': null,
 	'cdata': /&lt;!\[CDATA\[[\w\W]+]]&gt;/i,
 	'tag': {
 		pattern: /(&lt;|<)\/?[\w:-]+\s*[\w\W]*?(>|&gt;)/gi,
@@ -358,35 +382,33 @@ Prism.languages.markup = {
 };
 
 if (Prism.languages.javascript) {
-	Prism.languages.markup.script = {
-		pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,
-		inside: {
-			'tag': {
-				pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,
-				inside: Prism.languages.markup.tag.inside
-			},
-			rest: Prism.languages.javascript
+	Prism.languages.insertBefore('markup', 'cdata', {
+		'script': {
+			pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,
+			inside: {
+				'tag': {
+					pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,
+					inside: Prism.languages.markup.tag.inside
+				},
+				rest: Prism.languages.javascript
+			}
 		}
-	};
-}
-else {
-	delete Prism.languages.markup.script;
+	});
 }
 
 if (Prism.languages.css) {
-	Prism.languages.markup.style = {
-		pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,
-		inside: {
-			'tag': {
-				pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,
-				inside: Prism.languages.markup.tag.inside
-			},
-			rest: Prism.languages.css
+	Prism.languages.insertBefore('markup', 'cdata', {
+		'style': {
+			pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,
+			inside: {
+				'tag': {
+					pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,
+					inside: Prism.languages.markup.tag.inside
+				},
+				rest: Prism.languages.css
+			}
 		}
-	};
-}
-else {
-	delete Prism.languages.markup.style;
+	});
 }
 
 // Plugin to make entity title show the real entity, idea by Roman Komarov