Commit cfaf681db9018bd1d6e296b526db3e1467986fb3

Lea Verou 2012-07-26T18:17:55

Removed the need for .prism

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
diff --git a/code.js b/code.js
index 41d610b..d2b611c 100644
--- a/code.js
+++ b/code.js
@@ -29,8 +29,6 @@ document.body.addEventListener('contentreceived', function(evt) {
 		'svg': 'markup'
 	}[(evt.src.match(/\.(\w+)$/) || [,''])[1]];
 	
-	pre.className = 'prism';
-	
 	var code = document.createElement('code');
 	
 	code.className = 'lang-' + language;
diff --git a/components/prism-core.js b/components/prism-core.js
index 5d2a88d..0bc8030 100644
--- a/components/prism-core.js
+++ b/components/prism-core.js
@@ -7,7 +7,7 @@
 (function(){
 
 // Private helper vars
-var langRegex = /lang(?:uage)?-(\w+)/i;
+var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;
 
 var _ = self.Prism = {
 	grammar: {
@@ -16,33 +16,40 @@ var _ = self.Prism = {
 	
 	languages: {},
 
-	highlightAll: function(useWorkers, callback) {
-		var elements = document.querySelectorAll('pre.prism, pre.prism > code, code.prism');
+	highlightAll: function(async, callback) {
+		var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');
 
 		for (var i=0, element; element = elements[i++];) {
-			if (/pre/i.test(element.nodeName) && element.children.length > 0) {
-				continue;
-			}
-			
-			_.highlightElement(element, useWorkers === true, callback);
+			_.highlightElement(element, async === true, callback);
 		}
 	},
 		
-	highlightElement: function(element, useWorkers, callback) {
-		if(!element) {
-			return;
+	highlightElement: function(element, async, callback) {
+		// Find language
+		var language, grammar, parent = element;
+		
+		while (parent && !lang.test(parent.className)) {
+			parent = parent.parentNode;
 		}
 		
-		var language = (
-				element.className.match(langRegex) 
-				|| element.parentNode.className.match(langRegex)
-				|| [,_.defaultLanguage])[1],
-		    grammar = _.languages[language];
+		if (parent) {
+			language = (parent.className.match(lang) || [])[1];
+			grammar = _.languages[language];
+		}
 
 		if (!grammar) {
 			return;
 		}
 		
+		parent = element.parentNode;
+		
+		if (/pre/i.test(parent.nodeName) && !lang.test(parent.className)) {
+			parent.className += ' language-*';
+		}
+		
+		// Set language on the element, if not present
+		element.className = element.className.replace(lang, '') + ' language-' + language;
+		
 		var code = element.textContent || element.innerText;
 		
 		if(!code) {
@@ -62,7 +69,7 @@ var _ = self.Prism = {
 		
 		_.hooks.run('before-highlight', env);
 		
-		if (useWorkers && self.Worker) {
+		if (async && self.Worker) {
 			var worker = new Worker(_.filename);	
 			
 			worker.onmessage = function(evt) {
@@ -260,8 +267,6 @@ script = script[script.length - 1];
 if (script) {
 	_.filename = script.src;
 	
-	_.defaultLanguage = script.getAttribute('data-default-language') || null;
-	
 	if (!script.hasAttribute('data-manual')) {
 		if(document.addEventListener) {
 			document.addEventListener('DOMContentLoaded', _.highlightAll);
diff --git a/components/prism-core.min.js b/components/prism-core.min.js
index 29abff1..a11974b 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=/lang(?:uage)?-(\w+)/i,t=self.Prism={grammar:{url:/[a-z]{3,4}s?:\/\/\S+/g},languages:{},highlightAll:function(e,n){var r=document.querySelectorAll("pre.prism, pre.prism > code, code.prism");for(var i=0,s;s=r[i++];){if(/pre/i.test(s.nodeName)&&s.children.length>0)continue;t.highlightElement(s,e===!0,n)}},highlightElement:function(r,i,s){if(!r)return;var o=(r.className.match(e)||r.parentNode.className.match(e)||[,t.defaultLanguage])[1],u=t.languages[o];if(!u)return;var a=r.textContent||r.innerText;if(!a)return;a=a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\u00a0/g," ");var f={element:r,language:o,grammar:u,code:a};t.hooks.run("before-highlight",f);if(i&&self.Worker){var l=new Worker(t.filename);l.onmessage=function(e){f.highlightedCode=n.stringify(JSON.parse(e.data));f.element.innerHTML=f.highlightedCode;s&&s.call(f.element);t.hooks.run("after-highlight",f)};l.postMessage(JSON.stringify({language:f.language,code:f.code}))}else{f.highlightedCode=t.highlight(f.code,f.grammar);f.element.innerHTML=f.highlightedCode;s&&s.call(r);t.hooks.run("after-highlight",f)}},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;t.defaultLanguage=r.getAttribute("data-default-language")||null;r.hasAttribute("data-manual")||(document.addEventListener?document.addEventListener("DOMContentLoaded",t.highlightAll):window.attachEvent&&attachEvent("onload",t.highlightAll))}})();
\ No newline at end of file
+ */(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={grammar:{url:/[a-z]{3,4}s?:\/\/\S+/g},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;a=r.parentNode;/pre/i.test(a.nodeName)&&!e.test(a.className)&&(a.className+=" language-*");r.className=r.className.replace(e,"")+" language-"+o;var f=r.textContent||r.innerText;if(!f)return;f=f.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\u00a0/g," ");var l={element:r,language:o,grammar:u,code:f};t.hooks.run("before-highlight",l);if(i&&self.Worker){var c=new Worker(t.filename);c.onmessage=function(e){l.highlightedCode=n.stringify(JSON.parse(e.data));l.element.innerHTML=l.highlightedCode;s&&s.call(l.element);t.hooks.run("after-highlight",l)};c.postMessage(JSON.stringify({language:l.language,code:l.code}))}else{l.highlightedCode=t.highlight(l.code,l.grammar);l.element.innerHTML=l.highlightedCode;s&&s.call(r);t.hooks.run("after-highlight",l)}},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;r.hasAttribute("data-manual")||(document.addEventListener?document.addEventListener("DOMContentLoaded",t.highlightAll):window.attachEvent&&attachEvent("onload",t.highlightAll))}})();
\ No newline at end of file
diff --git a/examples.html b/examples.html
index 7b53042..eee1e24 100644
--- a/examples.html
+++ b/examples.html
@@ -18,6 +18,32 @@
 	<p>The examples in this page serve a dual purpose: They act as unit tests, making it easy to spot bugs, and at the same time demonstrate what Prism can do, on simple and on edge cases.</p>
 </header>
 
+<section class="language-markup">
+	<h1>Different markup</h1>
+	
+	<h2>code.language-css</h2>
+	<code class="language-css">p { color: red; }</code>
+	
+	<h2>pre.language-css > code</h2>
+	<pre class="language-css"><code>p { color: red; }</code></pre>
+	
+	<h2>pre.language-css > code.language-*</h2>
+	<pre class="language-css"><code class="language-*">p { color: red; }</code></pre>
+	
+	<h2>.lang-css</h2>
+	<code class="lang-css">p { color: red; }</code>
+	<pre class="lang-css"><code>p { color: red; }</code></pre>
+	
+	<h2>pre > code (No language, should inherit .language-markup)</h2>
+	<pre><code>&lt;p>hi!&lt;/p></code></pre>
+	
+	<h2>code.language-* (No language, should inherit .language-markup)</h2>
+	<code class="language-*">&lt;p>hi!&lt;/p></code>
+	
+	<h2>code.language-none (Should not be highlighted)</h2>
+	<code class="language-none">&lt;p>hi!&lt;/p></code>
+</section>
+
 <section>
 	<h1>Markup</h1>
 	
diff --git a/index.html b/index.html
index a261440..f88f630 100644
--- a/index.html
+++ b/index.html
@@ -45,7 +45,7 @@
 		<li><strong>Only 1.5KB</strong> minified &amp; gzipped (core). Each language definition adds roughly 300-500 bytes.</li>
 		<li>Supports <strong>parallelism with Web Workers</strong>, if available. Disabled by default.</li>
 		<li>Very easy to extend without modifying the code, due to Prism’s <a href="#plugins">plugin architecture</a>. Multiple hooks are scattered throughout the source.</li>
-		<li>Very easy to <a href="#language-definitions">define new languages</a>. Only thing you need is a good understanding of regular expressions</li>
+		<li>Very easy to <a href="extending.html#language-definitions">define new languages</a>. Only thing you need is a good understanding of regular expressions</li>
 		<li>All styling is done through CSS, with sensible class names rather than ugly namespaced abbreviated nonsense.</li>
 		<li>Wide browser support: IE8+, Firefox, Chrome, Safari, Opera, most Mobile browsers</li>
 		<li>Highlight specific lines and/or line ranges (requires <a href="plugins/line-highlight/">plugin</a>)</li>
@@ -78,29 +78,36 @@
 	<p>If you’re still not sold, you can <a href="examples.html">view more examples</a>.</p>
 </section>
 
-<section id="basic-usage">
+<section id="basic-usage" class="language-markup">
 	<h1>Basic usage</h1>
 	
-	<p>You will need to include the <code>prism.css</code> and <code>prism.js</code> files you downloaded in your page. Include the CSS file by putting this code on your <code class="prism">&lt;head></code> element:
-	<pre class="prism"><code>&lt;link href="prism.css" rel="stylesheet" /></code></pre>
+	<p>You will need to include the <code>prism.css</code> and <code>prism.js</code> files you downloaded in your page. Example:
+	<pre><code>&lt;!DOCTYPE html>
+&lt;html>
+&lt;head>
+	...
+	</code><code class="highlight">&lt;link href="prism.css" rel="stylesheet" /></code><code>
+&lt;/head>
+&lt;body>
+	...
+	</code><code class="highlight">&lt;script src="prism.js">&lt;/script></code><code>
+&lt;/body>
+&lt;/html></code></pre>
 	
-	<p>To include the JavaScript file add this code somewhere in your HTML document, preferably at the bottom, right before the closing <code class="prism">&lt;/body></code> tag:
-	<pre class="prism"><code>&lt;script src="prism.js">&lt;/script></code></pre>
+	<p>Prism does its best to encourage good authoring practices. Therefore, it only works with <code>&lt;code></code> elements, since marking up code without a <code>&lt;code></code> element is semantically invalid. 
+	<a href="http://www.w3.org/TR/html5/the-code-element.html#the-code-element">According to the HTML5 spec</a>, the recommended way to define a code language is a <code>language-xxxx</code> class, which is what Prism uses.
+	To make things easier however, Prism assumes that this language definition is inherited. Therefore, if multiple <code>&lt;code></code> elements have the same language, you can add the <code>language-xxxx</code> class on one of their common ancestors.
+	This way, you can also define a document-wide default language, by adding a <code>language-xxxx</code> class on the <code>&lt;body></code> or <code>&lt;html></code> element.
 	
-	<p>Then, you need to add two CSS classes to any element you want to be automatically processed by Prism: <code>prism</code> and <code>language-xxxx</code> where <code>xxxx</code> is the language of the code.
-	The class name <code>language-xxxx</code> is actually the W3C recommended way to <a href="http://www.w3.org/TR/html5/the-code-element.html#the-code-element">declare code languages</a>.
-	For example:
-	<pre class="prism"><code>&lt;code class="prism language-css">* { margin: 0; }&lt;/code></code></pre>
+	<p>If you want to opt-out of highlighting for a <code>&lt;code></code> element that is a descendant of an element with a declared code language, you can add the class <code>language-none</code> to it (or any non-existing language, really).</p>
 	
-	<p>If you are following the recommended way of presenting code blocks and using a <code class="prism">&lt;pre></code> with a <code class="prism">&lt;code></code> inside it, you will get better visual results by applying the <code class="prism language-css">.prism</code> class to the <code class="prism">&lt;pre></code>, like so:</p>
-	<pre class="prism"><code>&lt;pre class="prism">&lt;code class="language-css">* { margin: 0; }&lt;/code>&lt;pre></code></pre>
+	<p>The <a href="http://www.w3.org/TR/html5/the-pre-element.html#the-pre-element">recommended way to mark up a code block</a> (both for semantics and for Prism) is a <code>&lt;pre></code> inside a <code>&lt;code></code> element, like so:</p>
+	<pre><code>&lt;pre>&lt;code class="language-css">p { color: red }&lt;/code>&lt;/pre></code></pre>
+	<p>If you use that pattern, the <code>&lt;pre></code> will automatically get the <code>language-xxxx</code> class (if it doesn’t already have it) and will be styled as a code block.</p>
 	
-	<p>The <code>prism</code> class is not required if you plan to manually call <code class="prism language-javascript">Prism.highlightElement()</code> on the element and neither is the <code>language-xxxx</code> class if you plan to manually call <code class="prism language-javascript">Prism.highlight()</code>. 
-	To learn how these methods work, refer to the <a href="extending.html#api">API Documentation</a> section. However, the <code>.prism</code> class will add some nice styling to the code block.</p>
-	
-	<p>If you want to prevent elements with the class <code>prism</code> to be automatically highlighted, you can use the attribute <code>data-manual</code> on the <code class="prism">&lt;script></code> element you used for prism.
-	You can also set a default language by using the attribute <code>data-default-language</code> on the same element. Example of both being used:</p>
-	<pre class="prism"><code>&lt;script src="prism.js" data-default-language="css" data-manual>&lt;/script></code></pre>
+	<p>If you want to prevent any elements from being automatically highlighted, you can use the attribute <code>data-manual</code> on the <code>&lt;script></code> element you used for prism.
+	Example:</p>
+	<pre><code>&lt;script src="prism.js" data-manual>&lt;/script></code></pre>
 </p>
 </section>
 
diff --git a/prism.css b/prism.css
index 6df7031..cd22145 100644
--- a/prism.css
+++ b/prism.css
@@ -4,7 +4,8 @@
  * @author Lea Verou
  */
 
-.prism {
+code[class*="language-"],
+pre[class*="language-"] {
 	background: #f5f2f0;
 	color: black;
 	text-shadow: 0 1px white;
@@ -24,67 +25,73 @@
 	hyphens: none;
 }
 
-pre.prism {
+/* Code blocks */
+pre[class*="language-"] {
 	padding: 1em;
 	margin: .5em 0;
 	overflow: auto;	
 }
 
-code.prism {
+/* Inline code */
+code[class*="language-"] {
 	padding: .1em;
 	border-radius: .3em;
 }
 
-.comment,
-.line-comment,
-.prolog,
-.doctype,
-.cdata {
+	pre > code[class*="language-"] {
+		padding: 0;
+	}
+
+.token.comment,
+.token.line-comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
 	color: slategray;
 }
 
-.punctuation {
+.token.punctuation {
 	color: #999;
 }
 
-.property,
-.tag,
-.boolean,
-.number {
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number {
 	color: #905;
 }
 
-	.tag > .namespace {
+	.tag > .token.namespace {
 		color: #b37298; /* 70% of .tag on .prism’s background */
 	}
 
-.selector,
-.attr-name,
-.string {
+.token.selector,
+.token.attr-name,
+.token.string {
 	color: #690;
 }
 
-	.attr-name > .namespace {
+	.attr-name > .token.namespace {
 		color: #ab6; /* 70% of .attr-name on .prism’s background */
 	}
 
-.operator {
+.token.operator {
 	color: #a67f59;
 	background: hsla(0,0%,100%,.5);
 }
 
-.atrule,
-.attr-value,
-.keyword {
+.token.atrule,
+.token.attr-value,
+.token.keyword {
 	color: #07a;
 }
 
 
-.regex,
-.important {
+.token.regex,
+.token.important {
 	color: #e90;
 }
 
-.important {
+.token.important {
 	font-weight: bold;
 }
\ No newline at end of file
diff --git a/prism.js b/prism.js
index 955cf74..94b6c42 100644
--- a/prism.js
+++ b/prism.js
@@ -13,7 +13,7 @@
 (function(){
 
 // Private helper vars
-var langRegex = /lang(?:uage)?-(\w+)/i;
+var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;
 
 var _ = self.Prism = {
 	grammar: {
@@ -22,33 +22,40 @@ var _ = self.Prism = {
 	
 	languages: {},
 
-	highlightAll: function(useWorkers, callback) {
-		var elements = document.querySelectorAll('pre.prism, pre.prism > code, code.prism');
+	highlightAll: function(async, callback) {
+		var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');
 
 		for (var i=0, element; element = elements[i++];) {
-			if (/pre/i.test(element.nodeName) && element.children.length > 0) {
-				continue;
-			}
-			
-			_.highlightElement(element, useWorkers === true, callback);
+			_.highlightElement(element, async === true, callback);
 		}
 	},
 		
-	highlightElement: function(element, useWorkers, callback) {
-		if(!element) {
-			return;
+	highlightElement: function(element, async, callback) {
+		// Find language
+		var language, grammar, parent = element;
+		
+		while (parent && !lang.test(parent.className)) {
+			parent = parent.parentNode;
 		}
 		
-		var language = (
-				element.className.match(langRegex) 
-				|| element.parentNode.className.match(langRegex)
-				|| [,_.defaultLanguage])[1],
-		    grammar = _.languages[language];
+		if (parent) {
+			language = (parent.className.match(lang) || [])[1];
+			grammar = _.languages[language];
+		}
 
 		if (!grammar) {
 			return;
 		}
 		
+		parent = element.parentNode;
+		
+		if (/pre/i.test(parent.nodeName) && !lang.test(parent.className)) {
+			parent.className += ' language-*';
+		}
+		
+		// Set language on the element, if not present
+		element.className = element.className.replace(lang, '') + ' language-' + language;
+		
 		var code = element.textContent || element.innerText;
 		
 		if(!code) {
@@ -68,7 +75,7 @@ var _ = self.Prism = {
 		
 		_.hooks.run('before-highlight', env);
 		
-		if (useWorkers && self.Worker) {
+		if (async && self.Worker) {
 			var worker = new Worker(_.filename);	
 			
 			worker.onmessage = function(evt) {
@@ -266,8 +273,6 @@ script = script[script.length - 1];
 if (script) {
 	_.filename = script.src;
 	
-	_.defaultLanguage = script.getAttribute('data-default-language') || null;
-	
 	if (!script.hasAttribute('data-manual')) {
 		if(document.addEventListener) {
 			document.addEventListener('DOMContentLoaded', _.highlightAll);
diff --git a/style.css b/style.css
index 0a28784..b725ba9 100644
--- a/style.css
+++ b/style.css
@@ -73,11 +73,10 @@ pre {
 	max-height: 30em;
 }
 
-	body > pre:only-child {
-		padding: 1em;
-		min-height: 100%;
-		box-sizing: border-box;
-	}
+pre > code.highlight {
+	background: white;
+	box-shadow: 0 0 .8em .4em white;
+}
 
 header,
 body > section {