├── dummy ├── images │ ├── example-cat.jpg │ └── example-graph.png └── index.html ├── template ├── images │ ├── cccs-logo.png │ ├── colorbar.png │ └── cccs-logo-small.png ├── cccs.css ├── styles.css ├── slides.js └── prettify.js └── README.md /dummy/images/example-cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccs/html5slides/master/dummy/images/example-cat.jpg -------------------------------------------------------------------------------- /template/images/cccs-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccs/html5slides/master/template/images/cccs-logo.png -------------------------------------------------------------------------------- /template/images/colorbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccs/html5slides/master/template/images/colorbar.png -------------------------------------------------------------------------------- /dummy/images/example-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccs/html5slides/master/dummy/images/example-graph.png -------------------------------------------------------------------------------- /template/images/cccs-logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccs/html5slides/master/template/images/cccs-logo-small.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CCCS Slides Template 2 | ==================== 3 | 4 | Vorlage für Vorträge des CCCS, basierend auf "[Google HTML5 slide template](https://code.google.com/p/html5slides/)". 5 | -------------------------------------------------------------------------------- /template/cccs.css: -------------------------------------------------------------------------------- 1 | /* 2 | CCC Stuttgart HTML5 slides template 3 | 4 | Authors: Marco Ziesing (code and design) 5 | 6 | */ 7 | 8 | 9 | /* Framework */ 10 | 11 | .slides.template-cccs > article:not(.nobackground):not(.biglogo) { 12 | background: white url(images/cccs-logo-small.png) 690px 565px no-repeat !important; 13 | } 14 | 15 | /* Slide styles */ 16 | 17 | .slides.template-cccs article.biglogo { 18 | background: white url(images/cccs-logo.png) 50% 50% no-repeat !important; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /dummy/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | 16 | 17 | 18 | Presentation 19 | 20 | 21 | 23 | 24 | 25 | 26 | 32 | 33 | 34 | 35 |
36 | 37 | 39 | 40 | 41 | 42 | 44 | 45 |
46 |

47 | Title Goes Here Up 48 |
49 | To Two Lines 50 |

51 |

52 | Sergey Brin 53 |
54 | May 10, 2011 55 |

56 |
57 | 58 |
59 |

60 | This is a slide with just text. This is a slide with just text. 61 | This is a slide with just text. This is a slide with just text. 62 | This is a slide with just text. This is a slide with just text. 63 |

64 |

65 | There is more text just underneath. 66 |

67 |
68 | 69 |
70 |

71 | Simple slide with header and text 72 |

73 |

74 | This is a slide with just text. This is a slide with just text. 75 | This is a slide with just text. This is a slide with just text. 76 | This is a slide with just text. This is a slide with just text. 77 |

78 |

79 | There is more text just underneath with a code sample: 5px. 80 |

81 |
82 | 83 |
84 |

85 | Simple slide with header and text (small font) 86 |

87 |

88 | This is a slide with just text. This is a slide with just text. 89 | This is a slide with just text. This is a slide with just text. 90 | This is a slide with just text. This is a slide with just text. 91 |

92 |

93 | There is more text just underneath with a code sample: 5px. 94 |

95 |
96 | 97 |
98 |

99 | Slide with bullet points and a longer title, just because we 100 | can make it longer 101 |

102 | 118 |
119 | 120 |
121 |

122 | Slide with bullet points that builds 123 |

124 | 135 | 136 |
137 |

Any element with child nodes can build.

138 |

It doesn't have to be a list.

139 |
140 |
141 | 142 |
143 |

144 | Slide with bullet points (small font) 145 |

146 | 158 |
159 | 160 |
161 |

162 | Slide with a table 163 |

164 | 165 | 166 | 167 | 172 | 177 |
168 | Name 169 | 170 | Occupation 171 |
173 | Luke Mahé 174 | 175 | V.P. of Keepin’ It Real 176 |
178 | Marcin Wichary 179 | 180 | The Michael Bay of Doodles 181 |
182 |
183 | 184 |
185 |

186 | Slide with a table (smaller text) 187 |

188 | 189 | 190 | 191 | 196 | 201 |
192 | Name 193 | 194 | Occupation 195 |
197 | Luke Mahé 198 | 199 | V.P. of Keepin’ It Real 200 |
202 | Marcin Wichary 203 | 204 | The Michael Bay of Doodles 205 |
206 |
207 | 208 |
209 |

210 | Styles 211 |

212 | 228 |
229 | 230 |
231 |

232 | Segue slide 233 |

234 |
235 | 236 |
237 |

238 | Slide with an image 239 |

240 |

241 | 242 |

243 |
244 | Source: Sergey Brin 245 |
246 |
247 | 248 |
249 |

250 | Slide with an image (centered) 251 |

252 |

253 | 254 |

255 |
256 | Source: Larry Page 257 |
258 |
259 | 260 |
261 |

262 | Image filling the slide (with optional header) 263 |

264 |

265 | 266 |

267 |
268 | Source: Eric Schmidt 269 |
270 |
271 | 272 |
273 |

274 | This slide has some code 275 |

276 |
277 |
278 | <script type='text/javascript'>
279 |   // Say hello world until the user starts questioning
280 |   // the meaningfulness of their existence.
281 |   function helloWorld(world) {
282 |     for (var i = 42; --i >= 0;) {
283 |       alert('Hello ' + String(world));
284 |     }
285 |   }
286 | </script>
287 | <style>
288 |   p { color: pink }
289 |   b { color: blue }
290 |   u { color: 'umber' }
291 | </style>
292 | 
293 |
294 |
295 | 296 |
297 |

298 | This slide has some code (small font) 299 |

300 |
301 |
302 | <script type='text/javascript'>
303 |   // Say hello world until the user starts questioning
304 |   // the meaningfulness of their existence.
305 |   function helloWorld(world) {
306 |     for (var i = 42; --i >= 0;) {
307 |       alert('Hello ' + String(world));
308 |     }
309 |   }
310 | </script>
311 | <style>
312 |   p { color: pink }
313 |   b { color: blue }
314 |   u { color: 'umber' }
315 | </style>
316 | 
317 |
318 |
319 | 320 |
321 | 322 | The best way to predict the future is to invent it. 323 | 324 |
325 | Alan Kay 326 |
327 |
328 | 329 |
330 | 331 | A distributed system is one in which the failure of a computer 332 | you didn’t even know existed can render your own computer unusable. 333 | 334 |
335 | Leslie Lamport 336 |
337 |
338 | 339 |
340 |

341 | A slide with an embed + title 342 |

343 | 344 | 345 |
346 | 347 |
348 | 349 |
350 | 351 |
352 |

353 | Full-slide embed with (optional) slide title on top 354 |

355 | 356 |
357 | 358 |
359 |

360 | Thank you! 361 |

362 | 363 | 367 |
368 | 369 |
370 | 371 | 372 | 373 | -------------------------------------------------------------------------------- /template/styles.css: -------------------------------------------------------------------------------- 1 | /* 2 | Google HTML5 slides template 3 | 4 | Authors: Luke Mahé (code) 5 | Marcin Wichary (code and design) 6 | 7 | Dominic Mazzoni (browser compatibility) 8 | Charles Chen (ChromeVox support) 9 | 10 | URL: http://code.google.com/p/html5slides/ 11 | */ 12 | 13 | /* Framework */ 14 | 15 | html { 16 | height: 100%; 17 | } 18 | 19 | body { 20 | margin: 0; 21 | padding: 0; 22 | 23 | display: block !important; 24 | 25 | height: 100%; 26 | min-height: 740px; 27 | 28 | overflow-x: hidden; 29 | overflow-y: auto; 30 | 31 | background: rgb(215, 215, 215); 32 | background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 33 | background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 34 | background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 35 | background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgb(240, 240, 240)), to(rgb(190, 190, 190))); 36 | 37 | -webkit-font-smoothing: antialiased; 38 | } 39 | 40 | .slides { 41 | width: 100%; 42 | height: 100%; 43 | left: 0; 44 | top: 0; 45 | 46 | position: absolute; 47 | 48 | -webkit-transform: translate3d(0, 0, 0); 49 | } 50 | 51 | .slides > article { 52 | display: block; 53 | 54 | position: absolute; 55 | overflow: hidden; 56 | 57 | width: 900px; 58 | height: 700px; 59 | 60 | left: 50%; 61 | top: 50%; 62 | 63 | margin-left: -450px; 64 | margin-top: -350px; 65 | 66 | padding: 40px 60px; 67 | 68 | box-sizing: border-box; 69 | -o-box-sizing: border-box; 70 | -moz-box-sizing: border-box; 71 | -webkit-box-sizing: border-box; 72 | 73 | border-radius: 10px; 74 | -o-border-radius: 10px; 75 | -moz-border-radius: 10px; 76 | -webkit-border-radius: 10px; 77 | 78 | background-color: white; 79 | 80 | box-shadow: 0 2px 6px rgba(0, 0, 0, .1); 81 | border: 1px solid rgba(0, 0, 0, .3); 82 | 83 | transition: transform .3s ease-out; 84 | -o-transition: -o-transform .3s ease-out; 85 | -moz-transition: -moz-transform .3s ease-out; 86 | -webkit-transition: -webkit-transform .3s ease-out; 87 | } 88 | .slides.layout-widescreen > article { 89 | margin-left: -550px; 90 | width: 1100px; 91 | } 92 | .slides.layout-faux-widescreen > article { 93 | margin-left: -550px; 94 | width: 1100px; 95 | 96 | padding: 40px 160px; 97 | } 98 | 99 | .slides.template-default > article:not(.nobackground):not(.biglogo) { 100 | background: url(images/google-logo-small.png) 710px 625px no-repeat; 101 | 102 | background-color: white; 103 | } 104 | 105 | .slides.template-io2011 > article:not(.nobackground):not(.biglogo) { 106 | background: url(images/colorbar.png) 0 600px repeat-x, 107 | url(images/googleio-logo.png) 640px 625px no-repeat; 108 | 109 | background-size: 100%, 225px; 110 | 111 | background-color: white; 112 | } 113 | 114 | .slides.template-cccs > article:not(.nobackground):not(.biglogo) { 115 | background: url(images/cccs-logo-small.png) 710px 600px no-repeat; 116 | 117 | background-color: white; 118 | } 119 | .slides.layout-widescreen > article:not(.nobackground):not(.biglogo), 120 | .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) { 121 | background-position-x: 0, 840px; 122 | } 123 | 124 | /* Clickable/tappable areas */ 125 | 126 | .slide-area { 127 | z-index: 1000; 128 | 129 | position: absolute; 130 | left: 0; 131 | top: 0; 132 | width: 150px; 133 | height: 700px; 134 | 135 | left: 50%; 136 | top: 50%; 137 | 138 | cursor: pointer; 139 | margin-top: -350px; 140 | 141 | tap-highlight-color: transparent; 142 | -o-tap-highlight-color: transparent; 143 | -moz-tap-highlight-color: transparent; 144 | -webkit-tap-highlight-color: transparent; 145 | } 146 | #prev-slide-area { 147 | margin-left: -550px; 148 | } 149 | #next-slide-area { 150 | margin-left: 400px; 151 | } 152 | .slides.layout-widescreen #prev-slide-area, 153 | .slides.layout-faux-widescreen #prev-slide-area { 154 | margin-left: -650px; 155 | } 156 | .slides.layout-widescreen #next-slide-area, 157 | .slides.layout-faux-widescreen #next-slide-area { 158 | margin-left: 500px; 159 | } 160 | 161 | /* Slide styles */ 162 | 163 | .slides.template-default article.biglogo { 164 | background: white url(images/google-logo.png) 50% 50% no-repeat; 165 | } 166 | 167 | .slides.template-io2011 article.biglogo { 168 | background: white url(images/googleio-logo.png) 50% 50% no-repeat; 169 | 170 | background-size: 600px; 171 | } 172 | 173 | .slides.template-cccs article.biglogo { 174 | background: white url(images/cccs-logo.png) 50% 50% no-repeat; 175 | } 176 | 177 | 178 | /* Slides */ 179 | 180 | .slides > article { 181 | display: none; 182 | } 183 | .slides > article.far-past { 184 | display: block; 185 | transform: translate(-2040px); 186 | -o-transform: translate(-2040px); 187 | -moz-transform: translate(-2040px); 188 | -webkit-transform: translate3d(-2040px, 0, 0); 189 | } 190 | .slides > article.past { 191 | display: block; 192 | transform: translate(-1020px); 193 | -o-transform: translate(-1020px); 194 | -moz-transform: translate(-1020px); 195 | -webkit-transform: translate3d(-1020px, 0, 0); 196 | } 197 | .slides > article.current { 198 | display: block; 199 | transform: translate(0); 200 | -o-transform: translate(0); 201 | -moz-transform: translate(0); 202 | -webkit-transform: translate3d(0, 0, 0); 203 | } 204 | .slides > article.next { 205 | display: block; 206 | transform: translate(1020px); 207 | -o-transform: translate(1020px); 208 | -moz-transform: translate(1020px); 209 | -webkit-transform: translate3d(1020px, 0, 0); 210 | } 211 | .slides > article.far-next { 212 | display: block; 213 | transform: translate(2040px); 214 | -o-transform: translate(2040px); 215 | -moz-transform: translate(2040px); 216 | -webkit-transform: translate3d(2040px, 0, 0); 217 | } 218 | 219 | .slides.layout-widescreen > article.far-past, 220 | .slides.layout-faux-widescreen > article.far-past { 221 | display: block; 222 | transform: translate(-2260px); 223 | -o-transform: translate(-2260px); 224 | -moz-transform: translate(-2260px); 225 | -webkit-transform: translate3d(-2260px, 0, 0); 226 | } 227 | .slides.layout-widescreen > article.past, 228 | .slides.layout-faux-widescreen > article.past { 229 | display: block; 230 | transform: translate(-1130px); 231 | -o-transform: translate(-1130px); 232 | -moz-transform: translate(-1130px); 233 | -webkit-transform: translate3d(-1130px, 0, 0); 234 | } 235 | .slides.layout-widescreen > article.current, 236 | .slides.layout-faux-widescreen > article.current { 237 | display: block; 238 | transform: translate(0); 239 | -o-transform: translate(0); 240 | -moz-transform: translate(0); 241 | -webkit-transform: translate3d(0, 0, 0); 242 | } 243 | .slides.layout-widescreen > article.next, 244 | .slides.layout-faux-widescreen > article.next { 245 | display: block; 246 | transform: translate(1130px); 247 | -o-transform: translate(1130px); 248 | -moz-transform: translate(1130px); 249 | -webkit-transform: translate3d(1130px, 0, 0); 250 | } 251 | .slides.layout-widescreen > article.far-next, 252 | .slides.layout-faux-widescreen > article.far-next { 253 | display: block; 254 | transform: translate(2260px); 255 | -o-transform: translate(2260px); 256 | -moz-transform: translate(2260px); 257 | -webkit-transform: translate3d(2260px, 0, 0); 258 | } 259 | 260 | /* Styles for slides */ 261 | 262 | .slides > article { 263 | font-family: 'Open Sans', Arial, sans-serif; 264 | 265 | color: rgb(102, 102, 102); 266 | text-shadow: 0 1px 1px rgba(0, 0, 0, .1); 267 | 268 | font-size: 30px; 269 | line-height: 36px; 270 | 271 | letter-spacing: -1px; 272 | } 273 | 274 | b { 275 | font-weight: 600; 276 | } 277 | 278 | .blue { 279 | color: rgb(0, 102, 204); 280 | } 281 | .yellow { 282 | color: rgb(255, 211, 25); 283 | } 284 | .green { 285 | color: rgb(0, 138, 53); 286 | } 287 | .red { 288 | color: rgb(255, 0, 0); 289 | } 290 | .black { 291 | color: black; 292 | } 293 | .white { 294 | color: white; 295 | } 296 | 297 | a { 298 | color: rgb(0, 102, 204); 299 | } 300 | a:visited { 301 | color: rgba(0, 102, 204, .75); 302 | } 303 | a:hover { 304 | color: black; 305 | } 306 | 307 | p { 308 | margin: 0; 309 | padding: 0; 310 | 311 | margin-top: 20px; 312 | } 313 | p:first-child { 314 | margin-top: 0; 315 | } 316 | 317 | h1 { 318 | font-size: 60px; 319 | line-height: 60px; 320 | 321 | padding: 0; 322 | margin: 0; 323 | margin-top: 200px; 324 | padding-right: 40px; 325 | 326 | font-weight: 600; 327 | 328 | letter-spacing: -3px; 329 | 330 | color: rgb(51, 51, 51); 331 | } 332 | 333 | h2 { 334 | font-size: 45px; 335 | line-height: 45px; 336 | 337 | position: absolute; 338 | bottom: 150px; 339 | 340 | padding: 0; 341 | margin: 0; 342 | padding-right: 40px; 343 | 344 | font-weight: 600; 345 | 346 | letter-spacing: -2px; 347 | 348 | color: rgb(51, 51, 51); 349 | } 350 | 351 | h3 { 352 | font-size: 30px; 353 | line-height: 36px; 354 | 355 | padding: 0; 356 | margin: 0; 357 | padding-right: 40px; 358 | 359 | font-weight: 600; 360 | 361 | letter-spacing: -1px; 362 | 363 | color: rgb(51, 51, 51); 364 | } 365 | 366 | article.fill h3 { 367 | background: rgba(255, 255, 255, .75); 368 | padding-top: .2em; 369 | padding-bottom: .3em; 370 | margin-top: -.2em; 371 | margin-left: -60px; 372 | padding-left: 60px; 373 | margin-right: -60px; 374 | padding-right: 60px; 375 | } 376 | 377 | ul { 378 | list-style: none; 379 | margin: 0; 380 | padding: 0; 381 | 382 | margin-top: 40px; 383 | 384 | margin-left: .75em; 385 | } 386 | ul:first-child { 387 | margin-top: 0; 388 | } 389 | ul ul { 390 | margin-top: .5em; 391 | } 392 | li { 393 | padding: 0; 394 | margin: 0; 395 | 396 | margin-bottom: .5em; 397 | } 398 | li::before { 399 | content: '·'; 400 | 401 | width: .75em; 402 | margin-left: -.75em; 403 | 404 | position: absolute; 405 | } 406 | 407 | li li { padding: 0 0 0 1em; } 408 | 409 | pre { 410 | font-family: 'Droid Sans Mono', 'Courier New', monospace; 411 | 412 | font-size: 20px; 413 | line-height: 28px; 414 | padding: 5px 10px; 415 | 416 | letter-spacing: -1px; 417 | 418 | margin-top: 40px; 419 | margin-bottom: 40px; 420 | 421 | color: black; 422 | background: rgb(240, 240, 240); 423 | border: 1px solid rgb(224, 224, 224); 424 | box-shadow: inset 0 2px 6px rgba(0, 0, 0, .1); 425 | 426 | overflow: hidden; 427 | } 428 | 429 | code { 430 | font-size: 95%; 431 | font-family: 'Droid Sans Mono', 'Courier New', monospace; 432 | 433 | color: black; 434 | } 435 | 436 | iframe { 437 | width: 100%; 438 | 439 | height: 620px; 440 | 441 | background: white; 442 | border: 1px solid rgb(192, 192, 192); 443 | margin: -1px; 444 | /*box-shadow: inset 0 2px 6px rgba(0, 0, 0, .1);*/ 445 | } 446 | 447 | h3 + iframe { 448 | margin-top: 40px; 449 | height: 540px; 450 | } 451 | 452 | article.fill iframe { 453 | position: absolute; 454 | left: 0; 455 | top: 0; 456 | width: 100%; 457 | height: 100%; 458 | 459 | border: 0; 460 | margin: 0; 461 | 462 | border-radius: 10px; 463 | -o-border-radius: 10px; 464 | -moz-border-radius: 10px; 465 | -webkit-border-radius: 10px; 466 | 467 | z-index: -1; 468 | } 469 | 470 | article.fill img { 471 | position: absolute; 472 | left: 0; 473 | top: 0; 474 | min-width: 100%; 475 | min-height: 100%; 476 | 477 | border-radius: 10px; 478 | -o-border-radius: 10px; 479 | -moz-border-radius: 10px; 480 | -webkit-border-radius: 10px; 481 | 482 | z-index: -1; 483 | } 484 | img.centered { 485 | margin: 0 auto; 486 | display: block; 487 | } 488 | 489 | table { 490 | width: 100%; 491 | border-collapse: collapse; 492 | margin-top: 40px; 493 | } 494 | th { 495 | font-weight: 600; 496 | text-align: left; 497 | } 498 | td, 499 | th { 500 | border: 1px solid rgb(224, 224, 224); 501 | padding: 5px 10px; 502 | vertical-align: top; 503 | } 504 | 505 | .source { 506 | position: absolute; 507 | left: 60px; 508 | top: 644px; 509 | padding-right: 175px; 510 | 511 | font-size: 15px; 512 | letter-spacing: 0; 513 | line-height: 18px; 514 | } 515 | 516 | q { 517 | display: block; 518 | font-size: 60px; 519 | line-height: 72px; 520 | 521 | margin-left: 20px; 522 | 523 | margin-top: 100px; 524 | margin-right: 150px; 525 | } 526 | q::before { 527 | content: '“'; 528 | 529 | position: absolute; 530 | display: inline-block; 531 | margin-left: -2.1em; 532 | width: 2em; 533 | text-align: right; 534 | 535 | font-size: 90px; 536 | color: rgb(192, 192, 192); 537 | } 538 | q::after { 539 | content: '”'; 540 | 541 | position: absolute; 542 | margin-left: .1em; 543 | 544 | font-size: 90px; 545 | color: rgb(192, 192, 192); 546 | } 547 | div.author { 548 | text-align: right; 549 | font-size: 40px; 550 | 551 | margin-top: 20px; 552 | margin-right: 150px; 553 | } 554 | div.author::before { 555 | content: '—'; 556 | } 557 | 558 | /* Size variants */ 559 | 560 | article.smaller p, 561 | article.smaller ul { 562 | font-size: 20px; 563 | line-height: 24px; 564 | letter-spacing: 0; 565 | } 566 | article.smaller table { 567 | font-size: 20px; 568 | line-height: 24px; 569 | letter-spacing: 0; 570 | } 571 | article.smaller pre { 572 | font-size: 15px; 573 | line-height: 20px; 574 | letter-spacing: 0; 575 | } 576 | article.smaller q { 577 | font-size: 40px; 578 | line-height: 48px; 579 | } 580 | article.smaller q::before, 581 | article.smaller q::after { 582 | font-size: 60px; 583 | } 584 | 585 | /* Builds */ 586 | 587 | .build > * { 588 | transition: opacity 0.5s ease-in-out 0.2s; 589 | -o-transition: opacity 0.5s ease-in-out 0.2s; 590 | -moz-transition: opacity 0.5s ease-in-out 0.2s; 591 | -webkit-transition: opacity 0.5s ease-in-out 0.2s; 592 | } 593 | 594 | .to-build { 595 | opacity: 0; 596 | } 597 | 598 | /* Pretty print */ 599 | 600 | .prettyprint .str, /* string content */ 601 | .prettyprint .atv { /* a markup attribute value */ 602 | color: rgb(0, 138, 53); 603 | } 604 | .prettyprint .kwd, /* a keyword */ 605 | .prettyprint .tag { /* a markup tag name */ 606 | color: rgb(0, 102, 204); 607 | } 608 | .prettyprint .com { /* a comment */ 609 | color: rgb(127, 127, 127); 610 | font-style: italic; 611 | } 612 | .prettyprint .lit { /* a literal value */ 613 | color: rgb(127, 0, 0); 614 | } 615 | .prettyprint .pun, /* punctuation, lisp open bracket, lisp close bracket */ 616 | .prettyprint .opn, 617 | .prettyprint .clo { 618 | color: rgb(127, 127, 127); 619 | } 620 | .prettyprint .typ, /* a type name */ 621 | .prettyprint .atn, /* a markup attribute name */ 622 | .prettyprint .dec, 623 | .prettyprint .var { /* a declaration; a variable name */ 624 | color: rgb(127, 0, 127); 625 | } 626 | -------------------------------------------------------------------------------- /template/slides.js: -------------------------------------------------------------------------------- 1 | /* 2 | Google HTML5 slides template 3 | 4 | Authors: Luke Mahé (code) 5 | Marcin Wichary (code and design) 6 | 7 | Dominic Mazzoni (browser compatibility) 8 | Charles Chen (ChromeVox support) 9 | 10 | URL: http://code.google.com/p/html5slides/ 11 | */ 12 | 13 | var PERMANENT_URL_PREFIX = '../template/'; 14 | 15 | var SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next']; 16 | 17 | var PM_TOUCH_SENSITIVITY = 15; 18 | 19 | var curSlide; 20 | 21 | /* ---------------------------------------------------------------------- */ 22 | /* classList polyfill by Eli Grey 23 | * (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */ 24 | 25 | if (typeof document !== "undefined" && !("classList" in document.createElement("a"))) { 26 | 27 | (function (view) { 28 | 29 | var 30 | classListProp = "classList" 31 | , protoProp = "prototype" 32 | , elemCtrProto = (view.HTMLElement || view.Element)[protoProp] 33 | , objCtr = Object 34 | strTrim = String[protoProp].trim || function () { 35 | return this.replace(/^\s+|\s+$/g, ""); 36 | } 37 | , arrIndexOf = Array[protoProp].indexOf || function (item) { 38 | for (var i = 0, len = this.length; i < len; i++) { 39 | if (i in this && this[i] === item) { 40 | return i; 41 | } 42 | } 43 | return -1; 44 | } 45 | // Vendors: please allow content code to instantiate DOMExceptions 46 | , DOMEx = function (type, message) { 47 | this.name = type; 48 | this.code = DOMException[type]; 49 | this.message = message; 50 | } 51 | , checkTokenAndGetIndex = function (classList, token) { 52 | if (token === "") { 53 | throw new DOMEx( 54 | "SYNTAX_ERR" 55 | , "An invalid or illegal string was specified" 56 | ); 57 | } 58 | if (/\s/.test(token)) { 59 | throw new DOMEx( 60 | "INVALID_CHARACTER_ERR" 61 | , "String contains an invalid character" 62 | ); 63 | } 64 | return arrIndexOf.call(classList, token); 65 | } 66 | , ClassList = function (elem) { 67 | var 68 | trimmedClasses = strTrim.call(elem.className) 69 | , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [] 70 | ; 71 | for (var i = 0, len = classes.length; i < len; i++) { 72 | this.push(classes[i]); 73 | } 74 | this._updateClassName = function () { 75 | elem.className = this.toString(); 76 | }; 77 | } 78 | , classListProto = ClassList[protoProp] = [] 79 | , classListGetter = function () { 80 | return new ClassList(this); 81 | } 82 | ; 83 | // Most DOMException implementations don't allow calling DOMException's toString() 84 | // on non-DOMExceptions. Error's toString() is sufficient here. 85 | DOMEx[protoProp] = Error[protoProp]; 86 | classListProto.item = function (i) { 87 | return this[i] || null; 88 | }; 89 | classListProto.contains = function (token) { 90 | token += ""; 91 | return checkTokenAndGetIndex(this, token) !== -1; 92 | }; 93 | classListProto.add = function (token) { 94 | token += ""; 95 | if (checkTokenAndGetIndex(this, token) === -1) { 96 | this.push(token); 97 | this._updateClassName(); 98 | } 99 | }; 100 | classListProto.remove = function (token) { 101 | token += ""; 102 | var index = checkTokenAndGetIndex(this, token); 103 | if (index !== -1) { 104 | this.splice(index, 1); 105 | this._updateClassName(); 106 | } 107 | }; 108 | classListProto.toggle = function (token) { 109 | token += ""; 110 | if (checkTokenAndGetIndex(this, token) === -1) { 111 | this.add(token); 112 | } else { 113 | this.remove(token); 114 | } 115 | }; 116 | classListProto.toString = function () { 117 | return this.join(" "); 118 | }; 119 | 120 | if (objCtr.defineProperty) { 121 | var classListPropDesc = { 122 | get: classListGetter 123 | , enumerable: true 124 | , configurable: true 125 | }; 126 | try { 127 | objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); 128 | } catch (ex) { // IE 8 doesn't support enumerable:true 129 | if (ex.number === -0x7FF5EC54) { 130 | classListPropDesc.enumerable = false; 131 | objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); 132 | } 133 | } 134 | } else if (objCtr[protoProp].__defineGetter__) { 135 | elemCtrProto.__defineGetter__(classListProp, classListGetter); 136 | } 137 | 138 | }(self)); 139 | 140 | } 141 | /* ---------------------------------------------------------------------- */ 142 | 143 | /* Slide movement */ 144 | 145 | function getSlideEl(no) { 146 | if ((no < 0) || (no >= slideEls.length)) { 147 | return null; 148 | } else { 149 | return slideEls[no]; 150 | } 151 | }; 152 | 153 | function updateSlideClass(slideNo, className) { 154 | var el = getSlideEl(slideNo); 155 | 156 | if (!el) { 157 | return; 158 | } 159 | 160 | if (className) { 161 | el.classList.add(className); 162 | } 163 | 164 | for (var i in SLIDE_CLASSES) { 165 | if (className != SLIDE_CLASSES[i]) { 166 | el.classList.remove(SLIDE_CLASSES[i]); 167 | } 168 | } 169 | }; 170 | 171 | function updateSlides() { 172 | for (var i = 0; i < slideEls.length; i++) { 173 | switch (i) { 174 | case curSlide - 2: 175 | updateSlideClass(i, 'far-past'); 176 | break; 177 | case curSlide - 1: 178 | updateSlideClass(i, 'past'); 179 | break; 180 | case curSlide: 181 | updateSlideClass(i, 'current'); 182 | break; 183 | case curSlide + 1: 184 | updateSlideClass(i, 'next'); 185 | break; 186 | case curSlide + 2: 187 | updateSlideClass(i, 'far-next'); 188 | break; 189 | default: 190 | updateSlideClass(i); 191 | break; 192 | } 193 | } 194 | 195 | triggerLeaveEvent(curSlide - 1); 196 | triggerEnterEvent(curSlide); 197 | 198 | window.setTimeout(function() { 199 | // Hide after the slide 200 | disableSlideFrames(curSlide - 2); 201 | }, 301); 202 | 203 | enableSlideFrames(curSlide - 1); 204 | enableSlideFrames(curSlide + 2); 205 | 206 | if (isChromeVoxActive()) { 207 | speakAndSyncToNode(slideEls[curSlide]); 208 | } 209 | 210 | updateHash(); 211 | }; 212 | 213 | function buildNextItem() { 214 | var toBuild = slideEls[curSlide].querySelectorAll('.to-build'); 215 | 216 | if (!toBuild.length) { 217 | return false; 218 | } 219 | 220 | toBuild[0].classList.remove('to-build', ''); 221 | 222 | if (isChromeVoxActive()) { 223 | speakAndSyncToNode(toBuild[0]); 224 | } 225 | 226 | return true; 227 | }; 228 | 229 | function prevSlide() { 230 | if (curSlide > 0) { 231 | curSlide--; 232 | 233 | updateSlides(); 234 | } 235 | }; 236 | 237 | function nextSlide() { 238 | if (buildNextItem()) { 239 | return; 240 | } 241 | 242 | if (curSlide < slideEls.length - 1) { 243 | curSlide++; 244 | 245 | updateSlides(); 246 | } 247 | }; 248 | 249 | /* Slide events */ 250 | 251 | function triggerEnterEvent(no) { 252 | var el = getSlideEl(no); 253 | if (!el) { 254 | return; 255 | } 256 | 257 | var onEnter = el.getAttribute('onslideenter'); 258 | if (onEnter) { 259 | new Function(onEnter).call(el); 260 | } 261 | 262 | var evt = document.createEvent('Event'); 263 | evt.initEvent('slideenter', true, true); 264 | evt.slideNumber = no + 1; // Make it readable 265 | 266 | el.dispatchEvent(evt); 267 | }; 268 | 269 | function triggerLeaveEvent(no) { 270 | var el = getSlideEl(no); 271 | if (!el) { 272 | return; 273 | } 274 | 275 | var onLeave = el.getAttribute('onslideleave'); 276 | if (onLeave) { 277 | new Function(onLeave).call(el); 278 | } 279 | 280 | var evt = document.createEvent('Event'); 281 | evt.initEvent('slideleave', true, true); 282 | evt.slideNumber = no + 1; // Make it readable 283 | 284 | el.dispatchEvent(evt); 285 | }; 286 | 287 | /* Touch events */ 288 | 289 | function handleTouchStart(event) { 290 | if (event.touches.length == 1) { 291 | touchDX = 0; 292 | touchDY = 0; 293 | 294 | touchStartX = event.touches[0].pageX; 295 | touchStartY = event.touches[0].pageY; 296 | 297 | document.body.addEventListener('touchmove', handleTouchMove, true); 298 | document.body.addEventListener('touchend', handleTouchEnd, true); 299 | } 300 | }; 301 | 302 | function handleTouchMove(event) { 303 | if (event.touches.length > 1) { 304 | cancelTouch(); 305 | } else { 306 | touchDX = event.touches[0].pageX - touchStartX; 307 | touchDY = event.touches[0].pageY - touchStartY; 308 | } 309 | }; 310 | 311 | function handleTouchEnd(event) { 312 | var dx = Math.abs(touchDX); 313 | var dy = Math.abs(touchDY); 314 | 315 | if ((dx > PM_TOUCH_SENSITIVITY) && (dy < (dx * 2 / 3))) { 316 | if (touchDX > 0) { 317 | prevSlide(); 318 | } else { 319 | nextSlide(); 320 | } 321 | } 322 | 323 | cancelTouch(); 324 | }; 325 | 326 | function cancelTouch() { 327 | document.body.removeEventListener('touchmove', handleTouchMove, true); 328 | document.body.removeEventListener('touchend', handleTouchEnd, true); 329 | }; 330 | 331 | /* Preloading frames */ 332 | 333 | function disableSlideFrames(no) { 334 | var el = getSlideEl(no); 335 | if (!el) { 336 | return; 337 | } 338 | 339 | var frames = el.getElementsByTagName('iframe'); 340 | for (var i = 0, frame; frame = frames[i]; i++) { 341 | disableFrame(frame); 342 | } 343 | }; 344 | 345 | function enableSlideFrames(no) { 346 | var el = getSlideEl(no); 347 | if (!el) { 348 | return; 349 | } 350 | 351 | var frames = el.getElementsByTagName('iframe'); 352 | for (var i = 0, frame; frame = frames[i]; i++) { 353 | enableFrame(frame); 354 | } 355 | }; 356 | 357 | function disableFrame(frame) { 358 | frame.src = 'about:blank'; 359 | }; 360 | 361 | function enableFrame(frame) { 362 | var src = frame._src; 363 | 364 | if (frame.src != src && src != 'about:blank') { 365 | frame.src = src; 366 | } 367 | }; 368 | 369 | function setupFrames() { 370 | var frames = document.querySelectorAll('iframe'); 371 | for (var i = 0, frame; frame = frames[i]; i++) { 372 | frame._src = frame.src; 373 | disableFrame(frame); 374 | } 375 | 376 | enableSlideFrames(curSlide); 377 | enableSlideFrames(curSlide + 1); 378 | enableSlideFrames(curSlide + 2); 379 | }; 380 | 381 | function setupInteraction() { 382 | /* Clicking and tapping */ 383 | 384 | var el = document.createElement('div'); 385 | el.className = 'slide-area'; 386 | el.id = 'prev-slide-area'; 387 | el.addEventListener('click', prevSlide, false); 388 | document.querySelector('section.slides').appendChild(el); 389 | 390 | var el = document.createElement('div'); 391 | el.className = 'slide-area'; 392 | el.id = 'next-slide-area'; 393 | el.addEventListener('click', nextSlide, false); 394 | document.querySelector('section.slides').appendChild(el); 395 | 396 | /* Swiping */ 397 | 398 | document.body.addEventListener('touchstart', handleTouchStart, false); 399 | } 400 | 401 | /* ChromeVox support */ 402 | 403 | function isChromeVoxActive() { 404 | if (typeof(cvox) == 'undefined') { 405 | return false; 406 | } else { 407 | return true; 408 | } 409 | }; 410 | 411 | function speakAndSyncToNode(node) { 412 | if (!isChromeVoxActive()) { 413 | return; 414 | } 415 | 416 | cvox.ChromeVox.navigationManager.switchToStrategy( 417 | cvox.ChromeVoxNavigationManager.STRATEGIES.LINEARDOM, 0, true); 418 | cvox.ChromeVox.navigationManager.syncToNode(node); 419 | cvox.ChromeVoxUserCommands.finishNavCommand(''); 420 | var target = node; 421 | while (target.firstChild) { 422 | target = target.firstChild; 423 | } 424 | cvox.ChromeVox.navigationManager.syncToNode(target); 425 | }; 426 | 427 | function speakNextItem() { 428 | if (!isChromeVoxActive()) { 429 | return; 430 | } 431 | 432 | cvox.ChromeVox.navigationManager.switchToStrategy( 433 | cvox.ChromeVoxNavigationManager.STRATEGIES.LINEARDOM, 0, true); 434 | cvox.ChromeVox.navigationManager.next(true); 435 | if (!cvox.DomUtil.isDescendantOfNode( 436 | cvox.ChromeVox.navigationManager.getCurrentNode(), slideEls[curSlide])){ 437 | var target = slideEls[curSlide]; 438 | while (target.firstChild) { 439 | target = target.firstChild; 440 | } 441 | cvox.ChromeVox.navigationManager.syncToNode(target); 442 | cvox.ChromeVox.navigationManager.next(true); 443 | } 444 | cvox.ChromeVoxUserCommands.finishNavCommand(''); 445 | }; 446 | 447 | function speakPrevItem() { 448 | if (!isChromeVoxActive()) { 449 | return; 450 | } 451 | 452 | cvox.ChromeVox.navigationManager.switchToStrategy( 453 | cvox.ChromeVoxNavigationManager.STRATEGIES.LINEARDOM, 0, true); 454 | cvox.ChromeVox.navigationManager.previous(true); 455 | if (!cvox.DomUtil.isDescendantOfNode( 456 | cvox.ChromeVox.navigationManager.getCurrentNode(), slideEls[curSlide])){ 457 | var target = slideEls[curSlide]; 458 | while (target.lastChild){ 459 | target = target.lastChild; 460 | } 461 | cvox.ChromeVox.navigationManager.syncToNode(target); 462 | cvox.ChromeVox.navigationManager.previous(true); 463 | } 464 | cvox.ChromeVoxUserCommands.finishNavCommand(''); 465 | }; 466 | 467 | /* Hash functions */ 468 | 469 | function getCurSlideFromHash() { 470 | var slideNo = parseInt(location.hash.substr(1)); 471 | 472 | if (slideNo) { 473 | curSlide = slideNo - 1; 474 | } else { 475 | curSlide = 0; 476 | } 477 | }; 478 | 479 | function updateHash() { 480 | location.replace('#' + (curSlide + 1)); 481 | }; 482 | 483 | /* Event listeners */ 484 | 485 | function handleBodyKeyDown(event) { 486 | switch (event.keyCode) { 487 | case 39: // right arrow 488 | case 13: // Enter 489 | case 32: // space 490 | case 34: // PgDn 491 | nextSlide(); 492 | event.preventDefault(); 493 | break; 494 | 495 | case 37: // left arrow 496 | case 8: // Backspace 497 | case 33: // PgUp 498 | prevSlide(); 499 | event.preventDefault(); 500 | break; 501 | 502 | case 40: // down arrow 503 | if (isChromeVoxActive()) { 504 | speakNextItem(); 505 | } else { 506 | nextSlide(); 507 | } 508 | event.preventDefault(); 509 | break; 510 | 511 | case 38: // up arrow 512 | if (isChromeVoxActive()) { 513 | speakPrevItem(); 514 | } else { 515 | prevSlide(); 516 | } 517 | event.preventDefault(); 518 | break; 519 | } 520 | }; 521 | 522 | function addEventListeners() { 523 | document.addEventListener('keydown', handleBodyKeyDown, false); 524 | }; 525 | 526 | /* Initialization */ 527 | 528 | function addPrettify() { 529 | var els = document.querySelectorAll('pre'); 530 | for (var i = 0, el; el = els[i]; i++) { 531 | if (!el.classList.contains('noprettyprint')) { 532 | el.classList.add('prettyprint'); 533 | } 534 | } 535 | 536 | var el = document.createElement('script'); 537 | el.type = 'text/javascript'; 538 | el.src = PERMANENT_URL_PREFIX + 'prettify.js'; 539 | el.onload = function() { 540 | prettyPrint(); 541 | } 542 | document.body.appendChild(el); 543 | }; 544 | 545 | function addFontStyle() { 546 | var el = document.createElement('link'); 547 | el.rel = 'stylesheet'; 548 | el.type = 'text/css'; 549 | el.href = 'http://fonts.googleapis.com/css?family=' + 550 | 'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono'; 551 | 552 | document.body.appendChild(el); 553 | }; 554 | 555 | function addGeneralStyle() { 556 | var el = document.createElement('link'); 557 | el.rel = 'stylesheet'; 558 | el.type = 'text/css'; 559 | el.href = PERMANENT_URL_PREFIX + 'styles.css'; 560 | document.body.appendChild(el); 561 | 562 | var el = document.createElement('meta'); 563 | el.name = 'viewport'; 564 | el.content = 'width=1100,height=750'; 565 | document.querySelector('head').appendChild(el); 566 | 567 | var el = document.createElement('meta'); 568 | el.name = 'apple-mobile-web-app-capable'; 569 | el.content = 'yes'; 570 | document.querySelector('head').appendChild(el); 571 | }; 572 | 573 | function makeBuildLists() { 574 | for (var i = curSlide, slide; slide = slideEls[i]; i++) { 575 | var items = slide.querySelectorAll('.build > *'); 576 | for (var j = 0, item; item = items[j]; j++) { 577 | if (item.classList) { 578 | item.classList.add('to-build'); 579 | } 580 | } 581 | } 582 | }; 583 | 584 | function handleDomLoaded() { 585 | slideEls = document.querySelectorAll('section.slides > article'); 586 | 587 | setupFrames(); 588 | 589 | addFontStyle(); 590 | addGeneralStyle(); 591 | addPrettify(); 592 | addEventListeners(); 593 | 594 | updateSlides(); 595 | 596 | setupInteraction(); 597 | makeBuildLists(); 598 | 599 | document.body.classList.add('loaded'); 600 | }; 601 | 602 | function initialize() { 603 | getCurSlideFromHash(); 604 | 605 | if (window['_DEBUG']) { 606 | PERMANENT_URL_PREFIX = '../'; 607 | } 608 | 609 | if (window['_DCL']) { 610 | handleDomLoaded(); 611 | } else { 612 | document.addEventListener('DOMContentLoaded', handleDomLoaded, false); 613 | } 614 | } 615 | 616 | // If ?debug exists then load the script relative instead of absolute 617 | if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) { 618 | document.addEventListener('DOMContentLoaded', function() { 619 | // Avoid missing the DomContentLoaded event 620 | window['_DCL'] = true 621 | }, false); 622 | 623 | window['_DEBUG'] = true; 624 | var script = document.createElement('script'); 625 | script.type = 'text/javascript'; 626 | script.src = '../slides.js'; 627 | var s = document.getElementsByTagName('script')[0]; 628 | s.parentNode.insertBefore(script, s); 629 | 630 | // Remove this script 631 | s.parentNode.removeChild(s); 632 | } else { 633 | initialize(); 634 | } 635 | -------------------------------------------------------------------------------- /template/prettify.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2006 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | /** 17 | * @fileoverview 18 | * some functions for browser-side pretty printing of code contained in html. 19 | * 20 | *

21 | * For a fairly comprehensive set of languages see the 22 | * README 23 | * file that came with this source. At a minimum, the lexer should work on a 24 | * number of languages including C and friends, Java, Python, Bash, SQL, HTML, 25 | * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk 26 | * and a subset of Perl, but, because of commenting conventions, doesn't work on 27 | * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class. 28 | *

29 | * Usage:

    30 | *
  1. include this source file in an html page via 31 | * {@code } 32 | *
  2. define style rules. See the example page for examples. 33 | *
  3. mark the {@code
    } and {@code } tags in your source with
      34 |  *    {@code class=prettyprint.}
      35 |  *    You can also use the (html deprecated) {@code } tag, but the pretty
      36 |  *    printer needs to do more substantial DOM manipulations to support that, so
      37 |  *    some css styles may not be preserved.
      38 |  * </ol>
      39 |  * That's it.  I wanted to keep the API as simple as possible, so there's no
      40 |  * need to specify which language the code is in, but if you wish, you can add
      41 |  * another class to the {@code <pre>} or {@code <code>} element to specify the
      42 |  * language, as in {@code <pre class="prettyprint lang-java">}.  Any class that
      43 |  * starts with "lang-" followed by a file extension, specifies the file type.
      44 |  * See the "lang-*.js" files in this directory for code that implements
      45 |  * per-language file handlers.
      46 |  * <p>
      47 |  * Change log:<br>
      48 |  * cbeust, 2006/08/22
      49 |  * <blockquote>
      50 |  *   Java annotations (start with "@") are now captured as literals ("lit")
      51 |  * </blockquote>
      52 |  * @requires console
      53 |  */
      54 | 
      55 | // JSLint declarations
      56 | /*global console, document, navigator, setTimeout, window */
      57 | 
      58 | /**
      59 |  * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
      60 |  * UI events.
      61 |  * If set to {@code false}, {@code prettyPrint()} is synchronous.
      62 |  */
      63 | window['PR_SHOULD_USE_CONTINUATION'] = true;
      64 | 
      65 | /** the number of characters between tab columns */
      66 | window['PR_TAB_WIDTH'] = 8;
      67 | 
      68 | /** Contains functions for creating and registering new language handlers.
      69 |   * @type {Object}
      70 |   */
      71 | window['PR']
      72 | 
      73 | /** Pretty print a chunk of code.
      74 |   *
      75 |   * @param {string} sourceCodeHtml code as html
      76 |   * @return {string} code as html, but prettier
      77 |   */
      78 |   = window['prettyPrintOne']
      79 | /** Find all the {@code <pre>} and {@code <code>} tags in the DOM with
      80 |   * {@code class=prettyprint} and prettify them.
      81 |   * @param {Function?} opt_whenDone if specified, called when the last entry
      82 |   *     has been finished.
      83 |   */
      84 |   = window['prettyPrint'] = void 0;
      85 | 
      86 | 
      87 | (function () {
      88 |   // Keyword lists for various languages.
      89 |   var FLOW_CONTROL_KEYWORDS =
      90 |       "break continue do else for if return while ";
      91 |   var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " +
      92 |       "double enum extern float goto int long register short signed sizeof " +
      93 |       "static struct switch typedef union unsigned void volatile ";
      94 |   var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " +
      95 |       "new operator private protected public this throw true try typeof ";
      96 |   var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " +
      97 |       "concept concept_map const_cast constexpr decltype " +
      98 |       "dynamic_cast explicit export friend inline late_check " +
      99 |       "mutable namespace nullptr reinterpret_cast static_assert static_cast " +
     100 |       "template typeid typename using virtual wchar_t where ";
     101 |   var JAVA_KEYWORDS = COMMON_KEYWORDS +
     102 |       "abstract boolean byte extends final finally implements import " +
     103 |       "instanceof null native package strictfp super synchronized throws " +
     104 |       "transient ";
     105 |   var CSHARP_KEYWORDS = JAVA_KEYWORDS +
     106 |       "as base by checked decimal delegate descending dynamic event " +
     107 |       "fixed foreach from group implicit in interface internal into is lock " +
     108 |       "object out override orderby params partial readonly ref sbyte sealed " +
     109 |       "stackalloc string select uint ulong unchecked unsafe ushort var ";
     110 |   var COFFEE_KEYWORDS = "all and by catch class else extends false finally " +
     111 |       "for if in is isnt loop new no not null of off on or return super then " +
     112 |       "true try unless until when while yes ";
     113 |   var JSCRIPT_KEYWORDS = COMMON_KEYWORDS +
     114 |       "debugger eval export function get null set undefined var with " +
     115 |       "Infinity NaN ";
     116 |   var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " +
     117 |       "goto if import last local my next no our print package redo require " +
     118 |       "sub undef unless until use wantarray while BEGIN END ";
     119 |   var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " +
     120 |       "elif except exec finally from global import in is lambda " +
     121 |       "nonlocal not or pass print raise try with yield " +
     122 |       "False True None ";
     123 |   var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" +
     124 |       " defined elsif end ensure false in module next nil not or redo rescue " +
     125 |       "retry self super then true undef unless until when yield BEGIN END ";
     126 |   var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " +
     127 |       "function in local set then until ";
     128 |   var ALL_KEYWORDS = (
     129 |       CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS +
     130 |       PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS);
     131 | 
     132 |   // token style names.  correspond to css classes
     133 |   /** token style for a string literal */
     134 |   var PR_STRING = 'str';
     135 |   /** token style for a keyword */
     136 |   var PR_KEYWORD = 'kwd';
     137 |   /** token style for a comment */
     138 |   var PR_COMMENT = 'com';
     139 |   /** token style for a type */
     140 |   var PR_TYPE = 'typ';
     141 |   /** token style for a literal value.  e.g. 1, null, true. */
     142 |   var PR_LITERAL = 'lit';
     143 |   /** token style for a punctuation string. */
     144 |   var PR_PUNCTUATION = 'pun';
     145 |   /** token style for a punctuation string. */
     146 |   var PR_PLAIN = 'pln';
     147 | 
     148 |   /** token style for an sgml tag. */
     149 |   var PR_TAG = 'tag';
     150 |   /** token style for a markup declaration such as a DOCTYPE. */
     151 |   var PR_DECLARATION = 'dec';
     152 |   /** token style for embedded source. */
     153 |   var PR_SOURCE = 'src';
     154 |   /** token style for an sgml attribute name. */
     155 |   var PR_ATTRIB_NAME = 'atn';
     156 |   /** token style for an sgml attribute value. */
     157 |   var PR_ATTRIB_VALUE = 'atv';
     158 | 
     159 |   /**
     160 |    * A class that indicates a section of markup that is not code, e.g. to allow
     161 |    * embedding of line numbers within code listings.
     162 |    */
     163 |   var PR_NOCODE = 'nocode';
     164 | 
     165 |   /** A set of tokens that can precede a regular expression literal in
     166 |     * javascript.
     167 |     * http://www.mozilla.org/js/language/js20/rationale/syntax.html has the full
     168 |     * list, but I've removed ones that might be problematic when seen in
     169 |     * languages that don't support regular expression literals.
     170 |     *
     171 |     * <p>Specifically, I've removed any keywords that can't precede a regexp
     172 |     * literal in a syntactically legal javascript program, and I've removed the
     173 |     * "in" keyword since it's not a keyword in many languages, and might be used
     174 |     * as a count of inches.
     175 |     *
     176 |     * <p>The link a above does not accurately describe EcmaScript rules since
     177 |     * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
     178 |     * very well in practice.
     179 |     *
     180 |     * @private
     181 |     */
     182 |   var REGEXP_PRECEDER_PATTERN = function () {
     183 |       var preceders = [
     184 |           "!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=",
     185 |           "&=", "(", "*", "*=", /* "+", */ "+=", ",", /* "-", */ "-=",
     186 |           "->", /*".", "..", "...", handled below */ "/", "/=", ":", "::", ";",
     187 |           "<", "<<", "<<=", "<=", "=", "==", "===", ">",
     188 |           ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[",
     189 |           "^", "^=", "^^", "^^=", "{", "|", "|=", "||",
     190 |           "||=", "~" /* handles =~ and !~ */,
     191 |           "break", "case", "continue", "delete",
     192 |           "do", "else", "finally", "instanceof",
     193 |           "return", "throw", "try", "typeof"
     194 |           ];
     195 |       var pattern = '(?:^^|[+-]';
     196 |       for (var i = 0; i < preceders.length; ++i) {
     197 |         pattern += '|' + preceders[i].replace(/([^=<>:&a-z])/g, '\\$1');
     198 |       }
     199 |       pattern += ')\\s*';  // matches at end, and matches empty string
     200 |       return pattern;
     201 |       // CAVEAT: this does not properly handle the case where a regular
     202 |       // expression immediately follows another since a regular expression may
     203 |       // have flags for case-sensitivity and the like.  Having regexp tokens
     204 |       // adjacent is not valid in any language I'm aware of, so I'm punting.
     205 |       // TODO: maybe style special characters inside a regexp as punctuation.
     206 |     }();
     207 | 
     208 |   
     209 |   /**
     210 |    * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
     211 |    * matches the union of the sets of strings matched by the input RegExp.
     212 |    * Since it matches globally, if the input strings have a start-of-input
     213 |    * anchor (/^.../), it is ignored for the purposes of unioning.
     214 |    * @param {Array.<RegExp>} regexs non multiline, non-global regexs.
     215 |    * @return {RegExp} a global regex.
     216 |    */
     217 |   function combinePrefixPatterns(regexs) {
     218 |     var capturedGroupIndex = 0;
     219 |   
     220 |     var needToFoldCase = false;
     221 |     var ignoreCase = false;
     222 |     for (var i = 0, n = regexs.length; i < n; ++i) {
     223 |       var regex = regexs[i];
     224 |       if (regex.ignoreCase) {
     225 |         ignoreCase = true;
     226 |       } else if (/[a-z]/i.test(regex.source.replace(
     227 |                      /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) {
     228 |         needToFoldCase = true;
     229 |         ignoreCase = false;
     230 |         break;
     231 |       }
     232 |     }
     233 |   
     234 |     function decodeEscape(charsetPart) {
     235 |       if (charsetPart.charAt(0) !== '\\') { return charsetPart.charCodeAt(0); }
     236 |       switch (charsetPart.charAt(1)) {
     237 |         case 'b': return 8;
     238 |         case 't': return 9;
     239 |         case 'n': return 0xa;
     240 |         case 'v': return 0xb;
     241 |         case 'f': return 0xc;
     242 |         case 'r': return 0xd;
     243 |         case 'u': case 'x':
     244 |           return parseInt(charsetPart.substring(2), 16)
     245 |               || charsetPart.charCodeAt(1);
     246 |         case '0': case '1': case '2': case '3': case '4':
     247 |         case '5': case '6': case '7':
     248 |           return parseInt(charsetPart.substring(1), 8);
     249 |         default: return charsetPart.charCodeAt(1);
     250 |       }
     251 |     }
     252 |   
     253 |     function encodeEscape(charCode) {
     254 |       if (charCode < 0x20) {
     255 |         return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16);
     256 |       }
     257 |       var ch = String.fromCharCode(charCode);
     258 |       if (ch === '\\' || ch === '-' || ch === '[' || ch === ']') {
     259 |         ch = '\\' + ch;
     260 |       }
     261 |       return ch;
     262 |     }
     263 |   
     264 |     function caseFoldCharset(charSet) {
     265 |       var charsetParts = charSet.substring(1, charSet.length - 1).match(
     266 |           new RegExp(
     267 |               '\\\\u[0-9A-Fa-f]{4}'
     268 |               + '|\\\\x[0-9A-Fa-f]{2}'
     269 |               + '|\\\\[0-3][0-7]{0,2}'
     270 |               + '|\\\\[0-7]{1,2}'
     271 |               + '|\\\\[\\s\\S]'
     272 |               + '|-'
     273 |               + '|[^-\\\\]',
     274 |               'g'));
     275 |       var groups = [];
     276 |       var ranges = [];
     277 |       var inverse = charsetParts[0] === '^';
     278 |       for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
     279 |         var p = charsetParts[i];
     280 |         switch (p) {
     281 |           case '\\B': case '\\b':
     282 |           case '\\D': case '\\d':
     283 |           case '\\S': case '\\s':
     284 |           case '\\W': case '\\w':
     285 |             groups.push(p);
     286 |             continue;
     287 |         }
     288 |         var start = decodeEscape(p);
     289 |         var end;
     290 |         if (i + 2 < n && '-' === charsetParts[i + 1]) {
     291 |           end = decodeEscape(charsetParts[i + 2]);
     292 |           i += 2;
     293 |         } else {
     294 |           end = start;
     295 |         }
     296 |         ranges.push([start, end]);
     297 |         // If the range might intersect letters, then expand it.
     298 |         if (!(end < 65 || start > 122)) {
     299 |           if (!(end < 65 || start > 90)) {
     300 |             ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);
     301 |           }
     302 |           if (!(end < 97 || start > 122)) {
     303 |             ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);
     304 |           }
     305 |         }
     306 |       }
     307 |   
     308 |       // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
     309 |       // -> [[1, 12], [14, 14], [16, 17]]
     310 |       ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });
     311 |       var consolidatedRanges = [];
     312 |       var lastRange = [NaN, NaN];
     313 |       for (var i = 0; i < ranges.length; ++i) {
     314 |         var range = ranges[i];
     315 |         if (range[0] <= lastRange[1] + 1) {
     316 |           lastRange[1] = Math.max(lastRange[1], range[1]);
     317 |         } else {
     318 |           consolidatedRanges.push(lastRange = range);
     319 |         }
     320 |       }
     321 |   
     322 |       var out = ['['];
     323 |       if (inverse) { out.push('^'); }
     324 |       out.push.apply(out, groups);
     325 |       for (var i = 0; i < consolidatedRanges.length; ++i) {
     326 |         var range = consolidatedRanges[i];
     327 |         out.push(encodeEscape(range[0]));
     328 |         if (range[1] > range[0]) {
     329 |           if (range[1] + 1 > range[0]) { out.push('-'); }
     330 |           out.push(encodeEscape(range[1]));
     331 |         }
     332 |       }
     333 |       out.push(']');
     334 |       return out.join('');
     335 |     }
     336 |   
     337 |     function allowAnywhereFoldCaseAndRenumberGroups(regex) {
     338 |       // Split into character sets, escape sequences, punctuation strings
     339 |       // like ('(', '(?:', ')', '^'), and runs of characters that do not
     340 |       // include any of the above.
     341 |       var parts = regex.source.match(
     342 |           new RegExp(
     343 |               '(?:'
     344 |               + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]'  // a character set
     345 |               + '|\\\\u[A-Fa-f0-9]{4}'  // a unicode escape
     346 |               + '|\\\\x[A-Fa-f0-9]{2}'  // a hex escape
     347 |               + '|\\\\[0-9]+'  // a back-reference or octal escape
     348 |               + '|\\\\[^ux0-9]'  // other escape sequence
     349 |               + '|\\(\\?[:!=]'  // start of a non-capturing group
     350 |               + '|[\\(\\)\\^]'  // start/emd of a group, or line start
     351 |               + '|[^\\x5B\\x5C\\(\\)\\^]+'  // run of other characters
     352 |               + ')',
     353 |               'g'));
     354 |       var n = parts.length;
     355 |   
     356 |       // Maps captured group numbers to the number they will occupy in
     357 |       // the output or to -1 if that has not been determined, or to
     358 |       // undefined if they need not be capturing in the output.
     359 |       var capturedGroups = [];
     360 |   
     361 |       // Walk over and identify back references to build the capturedGroups
     362 |       // mapping.
     363 |       for (var i = 0, groupIndex = 0; i < n; ++i) {
     364 |         var p = parts[i];
     365 |         if (p === '(') {
     366 |           // groups are 1-indexed, so max group index is count of '('
     367 |           ++groupIndex;
     368 |         } else if ('\\' === p.charAt(0)) {
     369 |           var decimalValue = +p.substring(1);
     370 |           if (decimalValue && decimalValue <= groupIndex) {
     371 |             capturedGroups[decimalValue] = -1;
     372 |           }
     373 |         }
     374 |       }
     375 |   
     376 |       // Renumber groups and reduce capturing groups to non-capturing groups
     377 |       // where possible.
     378 |       for (var i = 1; i < capturedGroups.length; ++i) {
     379 |         if (-1 === capturedGroups[i]) {
     380 |           capturedGroups[i] = ++capturedGroupIndex;
     381 |         }
     382 |       }
     383 |       for (var i = 0, groupIndex = 0; i < n; ++i) {
     384 |         var p = parts[i];
     385 |         if (p === '(') {
     386 |           ++groupIndex;
     387 |           if (capturedGroups[groupIndex] === undefined) {
     388 |             parts[i] = '(?:';
     389 |           }
     390 |         } else if ('\\' === p.charAt(0)) {
     391 |           var decimalValue = +p.substring(1);
     392 |           if (decimalValue && decimalValue <= groupIndex) {
     393 |             parts[i] = '\\' + capturedGroups[groupIndex];
     394 |           }
     395 |         }
     396 |       }
     397 |   
     398 |       // Remove any prefix anchors so that the output will match anywhere.
     399 |       // ^^ really does mean an anchored match though.
     400 |       for (var i = 0, groupIndex = 0; i < n; ++i) {
     401 |         if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }
     402 |       }
     403 |   
     404 |       // Expand letters to groups to handle mixing of case-sensitive and
     405 |       // case-insensitive patterns if necessary.
     406 |       if (regex.ignoreCase && needToFoldCase) {
     407 |         for (var i = 0; i < n; ++i) {
     408 |           var p = parts[i];
     409 |           var ch0 = p.charAt(0);
     410 |           if (p.length >= 2 && ch0 === '[') {
     411 |             parts[i] = caseFoldCharset(p);
     412 |           } else if (ch0 !== '\\') {
     413 |             // TODO: handle letters in numeric escapes.
     414 |             parts[i] = p.replace(
     415 |                 /[a-zA-Z]/g,
     416 |                 function (ch) {
     417 |                   var cc = ch.charCodeAt(0);
     418 |                   return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';
     419 |                 });
     420 |           }
     421 |         }
     422 |       }
     423 |   
     424 |       return parts.join('');
     425 |     }
     426 |   
     427 |     var rewritten = [];
     428 |     for (var i = 0, n = regexs.length; i < n; ++i) {
     429 |       var regex = regexs[i];
     430 |       if (regex.global || regex.multiline) { throw new Error('' + regex); }
     431 |       rewritten.push(
     432 |           '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');
     433 |     }
     434 |   
     435 |     return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');
     436 |   }
     437 | 
     438 | 
     439 |   /**
     440 |    * Split markup into a string of source code and an array mapping ranges in
     441 |    * that string to the text nodes in which they appear.
     442 |    *
     443 |    * <p>
     444 |    * The HTML DOM structure:</p>
     445 |    * <pre>
     446 |    * (Element   "p"
     447 |    *   (Element "b"
     448 |    *     (Text  "print "))       ; #1
     449 |    *   (Text    "'Hello '")      ; #2
     450 |    *   (Element "br")            ; #3
     451 |    *   (Text    "  + 'World';")) ; #4
     452 |    * </pre>
     453 |    * <p>
     454 |    * corresponds to the HTML
     455 |    * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>
     456 |    *
     457 |    * <p>
     458 |    * It will produce the output:</p>
     459 |    * <pre>
     460 |    * {
     461 |    *   source: "print 'Hello '\n  + 'World';",
     462 |    *   //                 1         2
     463 |    *   //       012345678901234 5678901234567
     464 |    *   spans: [0, #1, 6, #2, 14, #3, 15, #4]
     465 |    * }
     466 |    * </pre>
     467 |    * <p>
     468 |    * where #1 is a reference to the {@code "print "} text node above, and so
     469 |    * on for the other text nodes.
     470 |    * </p>
     471 |    *
     472 |    * <p>
     473 |    * The {@code} spans array is an array of pairs.  Even elements are the start
     474 |    * indices of substrings, and odd elements are the text nodes (or BR elements)
     475 |    * that contain the text for those substrings.
     476 |    * Substrings continue until the next index or the end of the source.
     477 |    * </p>
     478 |    *
     479 |    * @param {Node} node an HTML DOM subtree containing source-code.
     480 |    * @return {Object} source code and the text nodes in which they occur.
     481 |    */
     482 |   function extractSourceSpans(node) {
     483 |     var nocode = /(?:^|\s)nocode(?:\s|$)/;
     484 |   
     485 |     var chunks = [];
     486 |     var length = 0;
     487 |     var spans = [];
     488 |     var k = 0;
     489 |   
     490 |     var whitespace;
     491 |     if (node.currentStyle) {
     492 |       whitespace = node.currentStyle.whiteSpace;
     493 |     } else if (window.getComputedStyle) {
     494 |       whitespace = document.defaultView.getComputedStyle(node, null)
     495 |           .getPropertyValue('white-space');
     496 |     }
     497 |     var isPreformatted = whitespace && 'pre' === whitespace.substring(0, 3);
     498 |   
     499 |     function walk(node) {
     500 |       switch (node.nodeType) {
     501 |         case 1:  // Element
     502 |           if (nocode.test(node.className)) { return; }
     503 |           for (var child = node.firstChild; child; child = child.nextSibling) {
     504 |             walk(child);
     505 |           }
     506 |           var nodeName = node.nodeName;
     507 |           if ('BR' === nodeName || 'LI' === nodeName) {
     508 |             chunks[k] = '\n';
     509 |             spans[k << 1] = length++;
     510 |             spans[(k++ << 1) | 1] = node;
     511 |           }
     512 |           break;
     513 |         case 3: case 4:  // Text
     514 |           var text = node.nodeValue;
     515 |           if (text.length) {
     516 |             if (!isPreformatted) {
     517 |               text = text.replace(/[ \t\r\n]+/g, ' ');
     518 |             } else {
     519 |               text = text.replace(/\r\n?/g, '\n');  // Normalize newlines.
     520 |             }
     521 |             // TODO: handle tabs here?
     522 |             chunks[k] = text;
     523 |             spans[k << 1] = length;
     524 |             length += text.length;
     525 |             spans[(k++ << 1) | 1] = node;
     526 |           }
     527 |           break;
     528 |       }
     529 |     }
     530 |   
     531 |     walk(node);
     532 |   
     533 |     return {
     534 |       source: chunks.join('').replace(/\n$/, ''),
     535 |       spans: spans
     536 |     };
     537 |   }
     538 | 
     539 | 
     540 |   /**
     541 |    * Apply the given language handler to sourceCode and add the resulting
     542 |    * decorations to out.
     543 |    * @param {number} basePos the index of sourceCode within the chunk of source
     544 |    *    whose decorations are already present on out.
     545 |    */
     546 |   function appendDecorations(basePos, sourceCode, langHandler, out) {
     547 |     if (!sourceCode) { return; }
     548 |     var job = {
     549 |       source: sourceCode,
     550 |       basePos: basePos
     551 |     };
     552 |     langHandler(job);
     553 |     out.push.apply(out, job.decorations);
     554 |   }
     555 | 
     556 |   /** Given triples of [style, pattern, context] returns a lexing function,
     557 |     * The lexing function interprets the patterns to find token boundaries and
     558 |     * returns a decoration list of the form
     559 |     * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
     560 |     * where index_n is an index into the sourceCode, and style_n is a style
     561 |     * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to
     562 |     * all characters in sourceCode[index_n-1:index_n].
     563 |     *
     564 |     * The stylePatterns is a list whose elements have the form
     565 |     * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
     566 |     *
     567 |     * Style is a style constant like PR_PLAIN, or can be a string of the
     568 |     * form 'lang-FOO', where FOO is a language extension describing the
     569 |     * language of the portion of the token in $1 after pattern executes.
     570 |     * E.g., if style is 'lang-lisp', and group 1 contains the text
     571 |     * '(hello (world))', then that portion of the token will be passed to the
     572 |     * registered lisp handler for formatting.
     573 |     * The text before and after group 1 will be restyled using this decorator
     574 |     * so decorators should take care that this doesn't result in infinite
     575 |     * recursion.  For example, the HTML lexer rule for SCRIPT elements looks
     576 |     * something like ['lang-js', /<[s]cript>(.+?)<\/script>/].  This may match
     577 |     * '<script>foo()<\/script>', which would cause the current decorator to
     578 |     * be called with '<script>' which would not match the same rule since
     579 |     * group 1 must not be empty, so it would be instead styled as PR_TAG by
     580 |     * the generic tag rule.  The handler registered for the 'js' extension would
     581 |     * then be called with 'foo()', and finally, the current decorator would
     582 |     * be called with '<\/script>' which would not match the original rule and
     583 |     * so the generic tag rule would identify it as a tag.
     584 |     *
     585 |     * Pattern must only match prefixes, and if it matches a prefix, then that
     586 |     * match is considered a token with the same style.
     587 |     *
     588 |     * Context is applied to the last non-whitespace, non-comment token
     589 |     * recognized.
     590 |     *
     591 |     * Shortcut is an optional string of characters, any of which, if the first
     592 |     * character, gurantee that this pattern and only this pattern matches.
     593 |     *
     594 |     * @param {Array} shortcutStylePatterns patterns that always start with
     595 |     *   a known character.  Must have a shortcut string.
     596 |     * @param {Array} fallthroughStylePatterns patterns that will be tried in
     597 |     *   order if the shortcut ones fail.  May have shortcuts.
     598 |     *
     599 |     * @return {function (Object)} a
     600 |     *   function that takes source code and returns a list of decorations.
     601 |     */
     602 |   function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {
     603 |     var shortcuts = {};
     604 |     var tokenizer;
     605 |     (function () {
     606 |       var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);
     607 |       var allRegexs = [];
     608 |       var regexKeys = {};
     609 |       for (var i = 0, n = allPatterns.length; i < n; ++i) {
     610 |         var patternParts = allPatterns[i];
     611 |         var shortcutChars = patternParts[3];
     612 |         if (shortcutChars) {
     613 |           for (var c = shortcutChars.length; --c >= 0;) {
     614 |             shortcuts[shortcutChars.charAt(c)] = patternParts;
     615 |           }
     616 |         }
     617 |         var regex = patternParts[1];
     618 |         var k = '' + regex;
     619 |         if (!regexKeys.hasOwnProperty(k)) {
     620 |           allRegexs.push(regex);
     621 |           regexKeys[k] = null;
     622 |         }
     623 |       }
     624 |       allRegexs.push(/[\0-\uffff]/);
     625 |       tokenizer = combinePrefixPatterns(allRegexs);
     626 |     })();
     627 | 
     628 |     var nPatterns = fallthroughStylePatterns.length;
     629 |     var notWs = /\S/;
     630 | 
     631 |     /**
     632 |      * Lexes job.source and produces an output array job.decorations of style
     633 |      * classes preceded by the position at which they start in job.source in
     634 |      * order.
     635 |      *
     636 |      * @param {Object} job an object like {@code
     637 |      *    source: {string} sourceText plain text,
     638 |      *    basePos: {int} position of job.source in the larger chunk of
     639 |      *        sourceCode.
     640 |      * }
     641 |      */
     642 |     var decorate = function (job) {
     643 |       var sourceCode = job.source, basePos = job.basePos;
     644 |       /** Even entries are positions in source in ascending order.  Odd enties
     645 |         * are style markers (e.g., PR_COMMENT) that run from that position until
     646 |         * the end.
     647 |         * @type {Array.<number|string>}
     648 |         */
     649 |       var decorations = [basePos, PR_PLAIN];
     650 |       var pos = 0;  // index into sourceCode
     651 |       var tokens = sourceCode.match(tokenizer) || [];
     652 |       var styleCache = {};
     653 | 
     654 |       for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
     655 |         var token = tokens[ti];
     656 |         var style = styleCache[token];
     657 |         var match = void 0;
     658 | 
     659 |         var isEmbedded;
     660 |         if (typeof style === 'string') {
     661 |           isEmbedded = false;
     662 |         } else {
     663 |           var patternParts = shortcuts[token.charAt(0)];
     664 |           if (patternParts) {
     665 |             match = token.match(patternParts[1]);
     666 |             style = patternParts[0];
     667 |           } else {
     668 |             for (var i = 0; i < nPatterns; ++i) {
     669 |               patternParts = fallthroughStylePatterns[i];
     670 |               match = token.match(patternParts[1]);
     671 |               if (match) {
     672 |                 style = patternParts[0];
     673 |                 break;
     674 |               }
     675 |             }
     676 | 
     677 |             if (!match) {  // make sure that we make progress
     678 |               style = PR_PLAIN;
     679 |             }
     680 |           }
     681 | 
     682 |           isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);
     683 |           if (isEmbedded && !(match && typeof match[1] === 'string')) {
     684 |             isEmbedded = false;
     685 |             style = PR_SOURCE;
     686 |           }
     687 | 
     688 |           if (!isEmbedded) { styleCache[token] = style; }
     689 |         }
     690 | 
     691 |         var tokenStart = pos;
     692 |         pos += token.length;
     693 | 
     694 |         if (!isEmbedded) {
     695 |           decorations.push(basePos + tokenStart, style);
     696 |         } else {  // Treat group 1 as an embedded block of source code.
     697 |           var embeddedSource = match[1];
     698 |           var embeddedSourceStart = token.indexOf(embeddedSource);
     699 |           var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;
     700 |           if (match[2]) {
     701 |             // If embeddedSource can be blank, then it would match at the
     702 |             // beginning which would cause us to infinitely recurse on the
     703 |             // entire token, so we catch the right context in match[2].
     704 |             embeddedSourceEnd = token.length - match[2].length;
     705 |             embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;
     706 |           }
     707 |           var lang = style.substring(5);
     708 |           // Decorate the left of the embedded source
     709 |           appendDecorations(
     710 |               basePos + tokenStart,
     711 |               token.substring(0, embeddedSourceStart),
     712 |               decorate, decorations);
     713 |           // Decorate the embedded source
     714 |           appendDecorations(
     715 |               basePos + tokenStart + embeddedSourceStart,
     716 |               embeddedSource,
     717 |               langHandlerForExtension(lang, embeddedSource),
     718 |               decorations);
     719 |           // Decorate the right of the embedded section
     720 |           appendDecorations(
     721 |               basePos + tokenStart + embeddedSourceEnd,
     722 |               token.substring(embeddedSourceEnd),
     723 |               decorate, decorations);
     724 |         }
     725 |       }
     726 |       job.decorations = decorations;
     727 |     };
     728 |     return decorate;
     729 |   }
     730 | 
     731 |   /** returns a function that produces a list of decorations from source text.
     732 |     *
     733 |     * This code treats ", ', and ` as string delimiters, and \ as a string
     734 |     * escape.  It does not recognize perl's qq() style strings.
     735 |     * It has no special handling for double delimiter escapes as in basic, or
     736 |     * the tripled delimiters used in python, but should work on those regardless
     737 |     * although in those cases a single string literal may be broken up into
     738 |     * multiple adjacent string literals.
     739 |     *
     740 |     * It recognizes C, C++, and shell style comments.
     741 |     *
     742 |     * @param {Object} options a set of optional parameters.
     743 |     * @return {function (Object)} a function that examines the source code
     744 |     *     in the input job and builds the decoration list.
     745 |     */
     746 |   function sourceDecorator(options) {
     747 |     var shortcutStylePatterns = [], fallthroughStylePatterns = [];
     748 |     if (options['tripleQuotedStrings']) {
     749 |       // '''multi-line-string''', 'single-line-string', and double-quoted
     750 |       shortcutStylePatterns.push(
     751 |           [PR_STRING,  /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
     752 |            null, '\'"']);
     753 |     } else if (options['multiLineStrings']) {
     754 |       // 'multi-line-string', "multi-line-string"
     755 |       shortcutStylePatterns.push(
     756 |           [PR_STRING,  /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
     757 |            null, '\'"`']);
     758 |     } else {
     759 |       // 'single-line-string', "single-line-string"
     760 |       shortcutStylePatterns.push(
     761 |           [PR_STRING,
     762 |            /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
     763 |            null, '"\'']);
     764 |     }
     765 |     if (options['verbatimStrings']) {
     766 |       // verbatim-string-literal production from the C# grammar.  See issue 93.
     767 |       fallthroughStylePatterns.push(
     768 |           [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
     769 |     }
     770 |     var hc = options['hashComments'];
     771 |     if (hc) {
     772 |       if (options['cStyleComments']) {
     773 |         if (hc > 1) {  // multiline hash comments
     774 |           shortcutStylePatterns.push(
     775 |               [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);
     776 |         } else {
     777 |           // Stop C preprocessor declarations at an unclosed open comment
     778 |           shortcutStylePatterns.push(
     779 |               [PR_COMMENT, /^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,
     780 |                null, '#']);
     781 |         }
     782 |         fallthroughStylePatterns.push(
     783 |             [PR_STRING,
     784 |              /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,
     785 |              null]);
     786 |       } else {
     787 |         shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
     788 |       }
     789 |     }
     790 |     if (options['cStyleComments']) {
     791 |       fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
     792 |       fallthroughStylePatterns.push(
     793 |           [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
     794 |     }
     795 |     if (options['regexLiterals']) {
     796 |       var REGEX_LITERAL = (
     797 |           // A regular expression literal starts with a slash that is
     798 |           // not followed by * or / so that it is not confused with
     799 |           // comments.
     800 |           '/(?=[^/*])'
     801 |           // and then contains any number of raw characters,
     802 |           + '(?:[^/\\x5B\\x5C]'
     803 |           // escape sequences (\x5C),
     804 |           +    '|\\x5C[\\s\\S]'
     805 |           // or non-nesting character sets (\x5B\x5D);
     806 |           +    '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+'
     807 |           // finally closed by a /.
     808 |           + '/');
     809 |       fallthroughStylePatterns.push(
     810 |           ['lang-regex',
     811 |            new RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')
     812 |            ]);
     813 |     }
     814 | 
     815 |     var keywords = options['keywords'].replace(/^\s+|\s+$/g, '');
     816 |     if (keywords.length) {
     817 |       fallthroughStylePatterns.push(
     818 |           [PR_KEYWORD,
     819 |            new RegExp('^(?:' + keywords.replace(/\s+/g, '|') + ')\\b'), null]);
     820 |     }
     821 | 
     822 |     shortcutStylePatterns.push([PR_PLAIN,       /^\s+/, null, ' \r\n\t\xA0']);
     823 |     fallthroughStylePatterns.push(
     824 |         // TODO(mikesamuel): recognize non-latin letters and numerals in idents
     825 |         [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],
     826 |         [PR_TYPE,        /^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/, null],
     827 |         [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],
     828 |         [PR_LITERAL,
     829 |          new RegExp(
     830 |              '^(?:'
     831 |              // A hex number
     832 |              + '0x[a-f0-9]+'
     833 |              // or an octal or decimal number,
     834 |              + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
     835 |              // possibly in scientific notation
     836 |              + '(?:e[+\\-]?\\d+)?'
     837 |              + ')'
     838 |              // with an optional modifier like UL for unsigned long
     839 |              + '[a-z]*', 'i'),
     840 |          null, '0123456789'],
     841 |         // Don't treat escaped quotes in bash as starting strings.  See issue 144.
     842 |         [PR_PLAIN,       /^\\[\s\S]?/, null],
     843 |         [PR_PUNCTUATION, /^.[^\s\w\.$@\'\"\`\/\#\\]*/, null]);
     844 | 
     845 |     return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
     846 |   }
     847 | 
     848 |   var decorateSource = sourceDecorator({
     849 |         'keywords': ALL_KEYWORDS,
     850 |         'hashComments': true,
     851 |         'cStyleComments': true,
     852 |         'multiLineStrings': true,
     853 |         'regexLiterals': true
     854 |       });
     855 | 
     856 |   /**
     857 |    * Given a DOM subtree, wraps it in a list, and puts each line into its own
     858 |    * list item.
     859 |    *
     860 |    * @param {Node} node modified in place.  Its content is pulled into an
     861 |    *     HTMLOListElement, and each line is moved into a separate list item.
     862 |    *     This requires cloning elements, so the input might not have unique
     863 |    *     IDs after numbering.
     864 |    */
     865 |   function numberLines(node, opt_startLineNum) {
     866 |     var nocode = /(?:^|\s)nocode(?:\s|$)/;
     867 |     var lineBreak = /\r\n?|\n/;
     868 |   
     869 |     var document = node.ownerDocument;
     870 |   
     871 |     var whitespace;
     872 |     if (node.currentStyle) {
     873 |       whitespace = node.currentStyle.whiteSpace;
     874 |     } else if (window.getComputedStyle) {
     875 |       whitespace = document.defaultView.getComputedStyle(node, null)
     876 |           .getPropertyValue('white-space');
     877 |     }
     878 |     // If it's preformatted, then we need to split lines on line breaks
     879 |     // in addition to <BR>s.
     880 |     var isPreformatted = whitespace && 'pre' === whitespace.substring(0, 3);
     881 |   
     882 |     var li = document.createElement('LI');
     883 |     while (node.firstChild) {
     884 |       li.appendChild(node.firstChild);
     885 |     }
     886 |     // An array of lines.  We split below, so this is initialized to one
     887 |     // un-split line.
     888 |     var listItems = [li];
     889 |   
     890 |     function walk(node) {
     891 |       switch (node.nodeType) {
     892 |         case 1:  // Element
     893 |           if (nocode.test(node.className)) { break; }
     894 |           if ('BR' === node.nodeName) {
     895 |             breakAfter(node);
     896 |             // Discard the <BR> since it is now flush against a </LI>.
     897 |             if (node.parentNode) {
     898 |               node.parentNode.removeChild(node);
     899 |             }
     900 |           } else {
     901 |             for (var child = node.firstChild; child; child = child.nextSibling) {
     902 |               walk(child);
     903 |             }
     904 |           }
     905 |           break;
     906 |         case 3: case 4:  // Text
     907 |           if (isPreformatted) {
     908 |             var text = node.nodeValue;
     909 |             var match = text.match(lineBreak);
     910 |             if (match) {
     911 |               var firstLine = text.substring(0, match.index);
     912 |               node.nodeValue = firstLine;
     913 |               var tail = text.substring(match.index + match[0].length);
     914 |               if (tail) {
     915 |                 var parent = node.parentNode;
     916 |                 parent.insertBefore(
     917 |                     document.createTextNode(tail), node.nextSibling);
     918 |               }
     919 |               breakAfter(node);
     920 |               if (!firstLine) {
     921 |                 // Don't leave blank text nodes in the DOM.
     922 |                 node.parentNode.removeChild(node);
     923 |               }
     924 |             }
     925 |           }
     926 |           break;
     927 |       }
     928 |     }
     929 |   
     930 |     // Split a line after the given node.
     931 |     function breakAfter(lineEndNode) {
     932 |       // If there's nothing to the right, then we can skip ending the line
     933 |       // here, and move root-wards since splitting just before an end-tag
     934 |       // would require us to create a bunch of empty copies.
     935 |       while (!lineEndNode.nextSibling) {
     936 |         lineEndNode = lineEndNode.parentNode;
     937 |         if (!lineEndNode) { return; }
     938 |       }
     939 |   
     940 |       function breakLeftOf(limit, copy) {
     941 |         // Clone shallowly if this node needs to be on both sides of the break.
     942 |         var rightSide = copy ? limit.cloneNode(false) : limit;
     943 |         var parent = limit.parentNode;
     944 |         if (parent) {
     945 |           // We clone the parent chain.
     946 |           // This helps us resurrect important styling elements that cross lines.
     947 |           // E.g. in <i>Foo<br>Bar</i>
     948 |           // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.
     949 |           var parentClone = breakLeftOf(parent, 1);
     950 |           // Move the clone and everything to the right of the original
     951 |           // onto the cloned parent.
     952 |           var next = limit.nextSibling;
     953 |           parentClone.appendChild(rightSide);
     954 |           for (var sibling = next; sibling; sibling = next) {
     955 |             next = sibling.nextSibling;
     956 |             parentClone.appendChild(sibling);
     957 |           }
     958 |         }
     959 |         return rightSide;
     960 |       }
     961 |   
     962 |       var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);
     963 |   
     964 |       // Walk the parent chain until we reach an unattached LI.
     965 |       for (var parent;
     966 |            // Check nodeType since IE invents document fragments.
     967 |            (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {
     968 |         copiedListItem = parent;
     969 |       }
     970 |       // Put it on the list of lines for later processing.
     971 |       listItems.push(copiedListItem);
     972 |     }
     973 |   
     974 |     // Split lines while there are lines left to split.
     975 |     for (var i = 0;  // Number of lines that have been split so far.
     976 |          i < listItems.length;  // length updated by breakAfter calls.
     977 |          ++i) {
     978 |       walk(listItems[i]);
     979 |     }
     980 |   
     981 |     // Make sure numeric indices show correctly.
     982 |     if (opt_startLineNum === (opt_startLineNum|0)) {
     983 |       listItems[0].setAttribute('value', opt_startLineNum);
     984 |     }
     985 |   
     986 |     var ol = document.createElement('OL');
     987 |     ol.className = 'linenums';
     988 |     var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;
     989 |     for (var i = 0, n = listItems.length; i < n; ++i) {
     990 |       li = listItems[i];
     991 |       // Stick a class on the LIs so that stylesheets can
     992 |       // color odd/even rows, or any other row pattern that
     993 |       // is co-prime with 10.
     994 |       li.className = 'L' + ((i + offset) % 10);
     995 |       if (!li.firstChild) {
     996 |         li.appendChild(document.createTextNode('\xA0'));
     997 |       }
     998 |       ol.appendChild(li);
     999 |     }
    1000 |   
    1001 |     node.appendChild(ol);
    1002 |   }
    1003 | 
    1004 |   /**
    1005 |    * Breaks {@code job.source} around style boundaries in {@code job.decorations}
    1006 |    * and modifies {@code job.sourceNode} in place.
    1007 |    * @param {Object} job like <pre>{
    1008 |    *    source: {string} source as plain text,
    1009 |    *    spans: {Array.<number|Node>} alternating span start indices into source
    1010 |    *       and the text node or element (e.g. {@code <BR>}) corresponding to that
    1011 |    *       span.
    1012 |    *    decorations: {Array.<number|string} an array of style classes preceded
    1013 |    *       by the position at which they start in job.source in order
    1014 |    * }</pre>
    1015 |    * @private
    1016 |    */
    1017 |   function recombineTagsAndDecorations(job) {
    1018 |     var isIE = /\bMSIE\b/.test(navigator.userAgent);
    1019 |     var newlineRe = /\n/g;
    1020 |   
    1021 |     var source = job.source;
    1022 |     var sourceLength = source.length;
    1023 |     // Index into source after the last code-unit recombined.
    1024 |     var sourceIndex = 0;
    1025 |   
    1026 |     var spans = job.spans;
    1027 |     var nSpans = spans.length;
    1028 |     // Index into spans after the last span which ends at or before sourceIndex.
    1029 |     var spanIndex = 0;
    1030 |   
    1031 |     var decorations = job.decorations;
    1032 |     var nDecorations = decorations.length;
    1033 |     // Index into decorations after the last decoration which ends at or before sourceIndex.
    1034 |     var decorationIndex = 0;
    1035 |   
    1036 |     // Simplify decorations.
    1037 |     var decPos = 0;
    1038 |     for (var i = 0; i < nDecorations;) {
    1039 |       // Skip over any zero-length decorations.
    1040 |       var startPos = decorations[i];
    1041 |       var start = i;
    1042 |       while (start + 2 < nDecorations && decorations[start + 2] === startPos) {
    1043 |         start += 2;
    1044 |       }
    1045 |       // Conflate all adjacent decorations that use the same style.
    1046 |       var startDec = decorations[start + 1];
    1047 |       var end = start + 2;
    1048 |       while (end + 2 <= nDecorations
    1049 |              && (decorations[end + 1] === startDec
    1050 |                  || decorations[end] === decorations[end + 2])) {
    1051 |         end += 2;
    1052 |       }
    1053 |       decorations[decPos++] = startPos;
    1054 |       decorations[decPos++] = startDec;
    1055 |       i = end;
    1056 |     }
    1057 |   
    1058 |     // Strip any zero-length decoration at the end.
    1059 |     if (decPos && decorations[decPos - 2] === sourceLength) { decPos -= 2; }
    1060 |     nDecorations = decorations.length = decPos;
    1061 |   
    1062 |     var decoration = null;
    1063 |     while (spanIndex < nSpans) {
    1064 |       var spanStart = spans[spanIndex];
    1065 |       var spanEnd = spans[spanIndex + 2] || sourceLength;
    1066 |   
    1067 |       var decStart = decorations[decorationIndex];
    1068 |       var decEnd = decorations[decorationIndex + 2] || sourceLength;
    1069 |   
    1070 |       var end = Math.min(spanEnd, decEnd);
    1071 |   
    1072 |       var textNode = spans[spanIndex + 1];
    1073 |       if (textNode.nodeType !== 1) {  // Don't muck with <BR>s or <LI>s
    1074 |         var styledText = source.substring(sourceIndex, end);
    1075 |         // This may seem bizarre, and it is.  Emitting LF on IE causes the
    1076 |         // code to display with spaces instead of line breaks.
    1077 |         // Emitting Windows standard issue linebreaks (CRLF) causes a blank
    1078 |         // space to appear at the beginning of every line but the first.
    1079 |         // Emitting an old Mac OS 9 line separator makes everything spiffy.
    1080 |         if (isIE) { styledText = styledText.replace(newlineRe, '\r'); }
    1081 |         textNode.nodeValue = styledText;
    1082 |         var document = textNode.ownerDocument;
    1083 |         var span = document.createElement('SPAN');
    1084 |         span.className = decorations[decorationIndex + 1];
    1085 |         var parentNode = textNode.parentNode;
    1086 |         parentNode.replaceChild(span, textNode);
    1087 |         span.appendChild(textNode);
    1088 |         if (sourceIndex < spanEnd) {  // Split off a text node.
    1089 |           spans[spanIndex + 1] = textNode
    1090 |               // TODO: Possibly optimize by using '' if there's no flicker.
    1091 |               = document.createTextNode(source.substring(end, spanEnd));
    1092 |           parentNode.insertBefore(textNode, span.nextSibling);
    1093 |         }
    1094 |       }
    1095 |   
    1096 |       sourceIndex = end;
    1097 |   
    1098 |       if (sourceIndex >= spanEnd) {
    1099 |         spanIndex += 2;
    1100 |       }
    1101 |       if (sourceIndex >= decEnd) {
    1102 |         decorationIndex += 2;
    1103 |       }
    1104 |     }
    1105 |   }
    1106 | 
    1107 | 
    1108 |   /** Maps language-specific file extensions to handlers. */
    1109 |   var langHandlerRegistry = {};
    1110 |   /** Register a language handler for the given file extensions.
    1111 |     * @param {function (Object)} handler a function from source code to a list
    1112 |     *      of decorations.  Takes a single argument job which describes the
    1113 |     *      state of the computation.   The single parameter has the form
    1114 |     *      {@code {
    1115 |     *        source: {string} as plain text.
    1116 |     *        decorations: {Array.<number|string>} an array of style classes
    1117 |     *                     preceded by the position at which they start in
    1118 |     *                     job.source in order.
    1119 |     *                     The language handler should assigned this field.
    1120 |     *        basePos: {int} the position of source in the larger source chunk.
    1121 |     *                 All positions in the output decorations array are relative
    1122 |     *                 to the larger source chunk.
    1123 |     *      } }
    1124 |     * @param {Array.<string>} fileExtensions
    1125 |     */
    1126 |   function registerLangHandler(handler, fileExtensions) {
    1127 |     for (var i = fileExtensions.length; --i >= 0;) {
    1128 |       var ext = fileExtensions[i];
    1129 |       if (!langHandlerRegistry.hasOwnProperty(ext)) {
    1130 |         langHandlerRegistry[ext] = handler;
    1131 |       } else if ('console' in window) {
    1132 |         console['warn']('cannot override language handler %s', ext);
    1133 |       }
    1134 |     }
    1135 |   }
    1136 |   function langHandlerForExtension(extension, source) {
    1137 |     if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {
    1138 |       // Treat it as markup if the first non whitespace character is a < and
    1139 |       // the last non-whitespace character is a >.
    1140 |       extension = /^\s*</.test(source)
    1141 |           ? 'default-markup'
    1142 |           : 'default-code';
    1143 |     }
    1144 |     return langHandlerRegistry[extension];
    1145 |   }
    1146 |   registerLangHandler(decorateSource, ['default-code']);
    1147 |   registerLangHandler(
    1148 |       createSimpleLexer(
    1149 |           [],
    1150 |           [
    1151 |            [PR_PLAIN,       /^[^<?]+/],
    1152 |            [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/],
    1153 |            [PR_COMMENT,     /^<\!--[\s\S]*?(?:-\->|$)/],
    1154 |            // Unescaped content in an unknown language
    1155 |            ['lang-',        /^<\?([\s\S]+?)(?:\?>|$)/],
    1156 |            ['lang-',        /^<%([\s\S]+?)(?:%>|$)/],
    1157 |            [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],
    1158 |            ['lang-',        /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
    1159 |            // Unescaped content in javascript.  (Or possibly vbscript).
    1160 |            ['lang-js',      /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],
    1161 |            // Contains unescaped stylesheet content
    1162 |            ['lang-css',     /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],
    1163 |            ['lang-in.tag',  /^(<\/?[a-z][^<>]*>)/i]
    1164 |           ]),
    1165 |       ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);
    1166 |   registerLangHandler(
    1167 |       createSimpleLexer(
    1168 |           [
    1169 |            [PR_PLAIN,        /^[\s]+/, null, ' \t\r\n'],
    1170 |            [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\'']
    1171 |            ],
    1172 |           [
    1173 |            [PR_TAG,          /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
    1174 |            [PR_ATTRIB_NAME,  /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],
    1175 |            ['lang-uq.val',   /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
    1176 |            [PR_PUNCTUATION,  /^[=<>\/]+/],
    1177 |            ['lang-js',       /^on\w+\s*=\s*\"([^\"]+)\"/i],
    1178 |            ['lang-js',       /^on\w+\s*=\s*\'([^\']+)\'/i],
    1179 |            ['lang-js',       /^on\w+\s*=\s*([^\"\'>\s]+)/i],
    1180 |            ['lang-css',      /^style\s*=\s*\"([^\"]+)\"/i],
    1181 |            ['lang-css',      /^style\s*=\s*\'([^\']+)\'/i],
    1182 |            ['lang-css',      /^style\s*=\s*([^\"\'>\s]+)/i]
    1183 |            ]),
    1184 |       ['in.tag']);
    1185 |   registerLangHandler(
    1186 |       createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']);
    1187 |   registerLangHandler(sourceDecorator({
    1188 |           'keywords': CPP_KEYWORDS,
    1189 |           'hashComments': true,
    1190 |           'cStyleComments': true
    1191 |         }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);
    1192 |   registerLangHandler(sourceDecorator({
    1193 |           'keywords': 'null true false'
    1194 |         }), ['json']);
    1195 |   registerLangHandler(sourceDecorator({
    1196 |           'keywords': CSHARP_KEYWORDS,
    1197 |           'hashComments': true,
    1198 |           'cStyleComments': true,
    1199 |           'verbatimStrings': true
    1200 |         }), ['cs']);
    1201 |   registerLangHandler(sourceDecorator({
    1202 |           'keywords': JAVA_KEYWORDS,
    1203 |           'cStyleComments': true
    1204 |         }), ['java']);
    1205 |   registerLangHandler(sourceDecorator({
    1206 |           'keywords': SH_KEYWORDS,
    1207 |           'hashComments': true,
    1208 |           'multiLineStrings': true
    1209 |         }), ['bsh', 'csh', 'sh']);
    1210 |   registerLangHandler(sourceDecorator({
    1211 |           'keywords': PYTHON_KEYWORDS,
    1212 |           'hashComments': true,
    1213 |           'multiLineStrings': true,
    1214 |           'tripleQuotedStrings': true
    1215 |         }), ['cv', 'py']);
    1216 |   registerLangHandler(sourceDecorator({
    1217 |           'keywords': PERL_KEYWORDS,
    1218 |           'hashComments': true,
    1219 |           'multiLineStrings': true,
    1220 |           'regexLiterals': true
    1221 |         }), ['perl', 'pl', 'pm']);
    1222 |   registerLangHandler(sourceDecorator({
    1223 |           'keywords': RUBY_KEYWORDS,
    1224 |           'hashComments': true,
    1225 |           'multiLineStrings': true,
    1226 |           'regexLiterals': true
    1227 |         }), ['rb']);
    1228 |   registerLangHandler(sourceDecorator({
    1229 |           'keywords': JSCRIPT_KEYWORDS,
    1230 |           'cStyleComments': true,
    1231 |           'regexLiterals': true
    1232 |         }), ['js']);
    1233 |   registerLangHandler(sourceDecorator({
    1234 |           'keywords': COFFEE_KEYWORDS,
    1235 |           'hashComments': 3,  // ### style block comments
    1236 |           'cStyleComments': true,
    1237 |           'multilineStrings': true,
    1238 |           'tripleQuotedStrings': true,
    1239 |           'regexLiterals': true
    1240 |         }), ['coffee']);
    1241 |   registerLangHandler(createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
    1242 | 
    1243 |   function applyDecorator(job) {
    1244 |     var opt_langExtension = job.langExtension;
    1245 | 
    1246 |     try {
    1247 |       // Extract tags, and convert the source code to plain text.
    1248 |       var sourceAndSpans = extractSourceSpans(job.sourceNode);
    1249 |       /** Plain text. @type {string} */
    1250 |       var source = sourceAndSpans.source;
    1251 |       job.source = source;
    1252 |       job.spans = sourceAndSpans.spans;
    1253 |       job.basePos = 0;
    1254 | 
    1255 |       // Apply the appropriate language handler
    1256 |       langHandlerForExtension(opt_langExtension, source)(job);
    1257 | 
    1258 |       // Integrate the decorations and tags back into the source code,
    1259 |       // modifying the sourceNode in place.
    1260 |       recombineTagsAndDecorations(job);
    1261 |     } catch (e) {
    1262 |       if ('console' in window) {
    1263 |         console['log'](e && e['stack'] ? e['stack'] : e);
    1264 |       }
    1265 |     }
    1266 |   }
    1267 | 
    1268 |   /**
    1269 |    * @param sourceCodeHtml {string} The HTML to pretty print.
    1270 |    * @param opt_langExtension {string} The language name to use.
    1271 |    *     Typically, a filename extension like 'cpp' or 'java'.
    1272 |    * @param opt_numberLines {number|boolean} True to number lines,
    1273 |    *     or the 1-indexed number of the first line in sourceCodeHtml.
    1274 |    */
    1275 |   function prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {
    1276 |     var container = document.createElement('PRE');
    1277 |     // This could cause images to load and onload listeners to fire.
    1278 |     // E.g. <img onerror="alert(1337)" src="nosuchimage.png">.
    1279 |     // We assume that the inner HTML is from a trusted source.
    1280 |     container.innerHTML = sourceCodeHtml;
    1281 |     if (opt_numberLines) {
    1282 |       numberLines(container, opt_numberLines);
    1283 |     }
    1284 | 
    1285 |     var job = {
    1286 |       langExtension: opt_langExtension,
    1287 |       numberLines: opt_numberLines,
    1288 |       sourceNode: container
    1289 |     };
    1290 |     applyDecorator(job);
    1291 |     return container.innerHTML;
    1292 |   }
    1293 | 
    1294 |   function prettyPrint(opt_whenDone) {
    1295 |     function byTagName(tn) { return document.getElementsByTagName(tn); }
    1296 |     // fetch a list of nodes to rewrite
    1297 |     var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];
    1298 |     var elements = [];
    1299 |     for (var i = 0; i < codeSegments.length; ++i) {
    1300 |       for (var j = 0, n = codeSegments[i].length; j < n; ++j) {
    1301 |         elements.push(codeSegments[i][j]);
    1302 |       }
    1303 |     }
    1304 |     codeSegments = null;
    1305 | 
    1306 |     var clock = Date;
    1307 |     if (!clock['now']) {
    1308 |       clock = { 'now': function () { return (new Date).getTime(); } };
    1309 |     }
    1310 | 
    1311 |     // The loop is broken into a series of continuations to make sure that we
    1312 |     // don't make the browser unresponsive when rewriting a large page.
    1313 |     var k = 0;
    1314 |     var prettyPrintingJob;
    1315 | 
    1316 |     function doWork() {
    1317 |       var endTime = (window['PR_SHOULD_USE_CONTINUATION'] ?
    1318 |                      clock.now() + 250 /* ms */ :
    1319 |                      Infinity);
    1320 |       for (; k < elements.length && clock.now() < endTime; k++) {
    1321 |         var cs = elements[k];
    1322 |         if (cs.className && cs.className.indexOf('prettyprint') >= 0) {
    1323 |           // If the classes includes a language extensions, use it.
    1324 |           // Language extensions can be specified like
    1325 |           //     <pre class="prettyprint lang-cpp">
    1326 |           // the language extension "cpp" is used to find a language handler as
    1327 |           // passed to PR.registerLangHandler.
    1328 |           var langExtension = cs.className.match(/\blang-(\w+)\b/);
    1329 |           if (langExtension) { langExtension = langExtension[1]; }
    1330 | 
    1331 |           // make sure this is not nested in an already prettified element
    1332 |           var nested = false;
    1333 |           for (var p = cs.parentNode; p; p = p.parentNode) {
    1334 |             if ((p.tagName === 'pre' || p.tagName === 'code' ||
    1335 |                  p.tagName === 'xmp') &&
    1336 |                 p.className && p.className.indexOf('prettyprint') >= 0) {
    1337 |               nested = true;
    1338 |               break;
    1339 |             }
    1340 |           }
    1341 |           if (!nested) {
    1342 |             // Look for a class like linenums or linenums:<n> where <n> is the
    1343 |             // 1-indexed number of the first line.
    1344 |             var lineNums = cs.className.match(/\blinenums\b(?::(\d+))?/);
    1345 |             lineNums = lineNums
    1346 |                   ? lineNums[1] && lineNums[1].length ? +lineNums[1] : true
    1347 |                   : false;
    1348 |             if (lineNums) { numberLines(cs, lineNums); }
    1349 | 
    1350 |             // do the pretty printing
    1351 |             prettyPrintingJob = {
    1352 |               langExtension: langExtension,
    1353 |               sourceNode: cs,
    1354 |               numberLines: lineNums
    1355 |             };
    1356 |             applyDecorator(prettyPrintingJob);
    1357 |           }
    1358 |         }
    1359 |       }
    1360 |       if (k < elements.length) {
    1361 |         // finish up in a continuation
    1362 |         setTimeout(doWork, 250);
    1363 |       } else if (opt_whenDone) {
    1364 |         opt_whenDone();
    1365 |       }
    1366 |     }
    1367 | 
    1368 |     doWork();
    1369 |   }
    1370 | 
    1371 |   window['prettyPrintOne'] = prettyPrintOne;
    1372 |   window['prettyPrint'] = prettyPrint;
    1373 |   window['PR'] = {
    1374 |         'createSimpleLexer': createSimpleLexer,
    1375 |         'registerLangHandler': registerLangHandler,
    1376 |         'sourceDecorator': sourceDecorator,
    1377 |         'PR_ATTRIB_NAME': PR_ATTRIB_NAME,
    1378 |         'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,
    1379 |         'PR_COMMENT': PR_COMMENT,
    1380 |         'PR_DECLARATION': PR_DECLARATION,
    1381 |         'PR_KEYWORD': PR_KEYWORD,
    1382 |         'PR_LITERAL': PR_LITERAL,
    1383 |         'PR_NOCODE': PR_NOCODE,
    1384 |         'PR_PLAIN': PR_PLAIN,
    1385 |         'PR_PUNCTUATION': PR_PUNCTUATION,
    1386 |         'PR_SOURCE': PR_SOURCE,
    1387 |         'PR_STRING': PR_STRING,
    1388 |         'PR_TAG': PR_TAG,
    1389 |         'PR_TYPE': PR_TYPE
    1390 |       };
    1391 | })();
    1392 | 
    
    
    --------------------------------------------------------------------------------