From 7e04feff9f5e179cc187a1253ecd286da6f3499d Mon Sep 17 00:00:00 2001 From: Andrew Senetar Date: Fri, 7 Jun 2013 01:49:35 -0400 Subject: [PATCH] First Version ( v0.1 ) First Version of the PrismHighlight Mediawiki extension. --- .gitattributes | 22 ++ .gitignore | 36 +++ LICENSE.md | 65 +++++ PrismHighlight.base.php | 66 +++++ PrismHighlight.i18n.php | 39 +++ PrismHighlight.php | 158 +++++++++++ README.md | 100 +++++++ init.js | 6 + overrides.css | 4 + prism/components/prism-bash.js | 24 ++ prism/components/prism-c.js | 9 + prism/components/prism-clike.js | 26 ++ prism/components/prism-coffeescript.js | 16 ++ prism/components/prism-cpp.js | 4 + prism/components/prism-css-extras.js | 16 ++ prism/components/prism-css.js | 26 ++ prism/components/prism-groovy.js | 30 ++ prism/components/prism-java.js | 8 + prism/components/prism-javascript.js | 26 ++ prism/components/prism-markup.js | 41 +++ prism/components/prism-php.js | 60 ++++ prism/components/prism-python.js | 14 + prism/components/prism-scss.js | 36 +++ prism/components/prism-sql.js | 13 + prism/plugins/prism-autolinker.css | 3 + prism/plugins/prism-autolinker.js | 61 ++++ prism/plugins/prism-file-highlight.js | 52 ++++ prism/plugins/prism-ie8.css | 3 + prism/plugins/prism-ie8.js | 42 +++ prism/plugins/prism-line-highlight.css | 47 ++++ prism/plugins/prism-line-highlight.js | 94 +++++++ prism/plugins/prism-line-numbers.css | 40 +++ prism/plugins/prism-line-numbers.js | 24 ++ prism/plugins/prism-show-invisibles.css | 17 ++ prism/plugins/prism-show-invisibles.js | 15 + prism/plugins/prism-wpd.css | 11 + prism/plugins/prism-wpd.js | 159 +++++++++++ prism/prism-core.js | 356 ++++++++++++++++++++++++ prism/prism.css | 106 +++++++ prism/themes/prism-dark.css | 111 ++++++++ prism/themes/prism-funky.css | 100 +++++++ prism/themes/prism-okaidia.css | 108 +++++++ prism/themes/prism-tomorrow.css | 107 +++++++ prism/themes/prism-twilight.css | 172 ++++++++++++ 44 files changed, 2473 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 LICENSE.md create mode 100644 PrismHighlight.base.php create mode 100644 PrismHighlight.i18n.php create mode 100644 PrismHighlight.php create mode 100644 README.md create mode 100644 init.js create mode 100644 overrides.css create mode 100644 prism/components/prism-bash.js create mode 100644 prism/components/prism-c.js create mode 100644 prism/components/prism-clike.js create mode 100644 prism/components/prism-coffeescript.js create mode 100644 prism/components/prism-cpp.js create mode 100644 prism/components/prism-css-extras.js create mode 100644 prism/components/prism-css.js create mode 100644 prism/components/prism-groovy.js create mode 100644 prism/components/prism-java.js create mode 100644 prism/components/prism-javascript.js create mode 100644 prism/components/prism-markup.js create mode 100644 prism/components/prism-php.js create mode 100644 prism/components/prism-python.js create mode 100644 prism/components/prism-scss.js create mode 100644 prism/components/prism-sql.js create mode 100644 prism/plugins/prism-autolinker.css create mode 100644 prism/plugins/prism-autolinker.js create mode 100644 prism/plugins/prism-file-highlight.js create mode 100644 prism/plugins/prism-ie8.css create mode 100644 prism/plugins/prism-ie8.js create mode 100644 prism/plugins/prism-line-highlight.css create mode 100644 prism/plugins/prism-line-highlight.js create mode 100644 prism/plugins/prism-line-numbers.css create mode 100644 prism/plugins/prism-line-numbers.js create mode 100644 prism/plugins/prism-show-invisibles.css create mode 100644 prism/plugins/prism-show-invisibles.js create mode 100644 prism/plugins/prism-wpd.css create mode 100644 prism/plugins/prism-wpd.js create mode 100644 prism/prism-core.js create mode 100644 prism/prism.css create mode 100644 prism/themes/prism-dark.css create mode 100644 prism/themes/prism-funky.css create mode 100644 prism/themes/prism-okaidia.css create mode 100644 prism/themes/prism-tomorrow.css create mode 100644 prism/themes/prism-twilight.css diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5cca118 --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +############# +## Windows +############# + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +############# +## OSX +############# +.DS_Store +.AppleDouble +.LSOverride +Icon + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +############# +## Linux +############# +.* +!.gitignore +!.gitattributes +*~ \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..2a78d06 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,65 @@ +Licenses +========= + +The licenses for PrismHighlight and all components are listed below. + + +Project License +---------------- + +~~~ +MIT LICENSE + +Copyright (c) 2013 Andrew Senetar + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +~~~ + +Component Licenses +------------------- + +### Prism + +~~~ +MIT LICENSE + +Copyright (c) 2012-2013 Lea Verou + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +~~~ + diff --git a/PrismHighlight.base.php b/PrismHighlight.base.php new file mode 100644 index 0000000..9890c79 --- /dev/null +++ b/PrismHighlight.base.php @@ -0,0 +1,66 @@ + + * + * @file + * @link http:// + * @ingroup Extensions + * @author Andrew Senetar + * @copyright (c) 2013 by Andrew Senetar + * @license http://opensource.org/licenses/MIT MIT License + */ + +/** + * Implements the AuthPlugin for the SimpleSSO extension + * + * @author Andrew Senetar + */ + + class PrismHighlight { + + public static function parserHook($text, $args = array(), $parser) { + $code_classes = ''; + $pre_args =''; + if(!isset($args['lang']) || !isset($args['language'])) + $args['lang'] = 'markup'; + foreach( $args as $key => $value ){ + switch ($key) { + case 'lang': + case 'language': + $code_classes .= " language-$value"; + break; + case 'class': + $code_classes .= " $value"; + break; + case 'line-numbers': + $pre_args .= " class=$key"; + break; + case 'data-start': + $pre_args .= " data-line-offset=$value"; //should make sure this is set + default; + $pre_args .= " $key=$value"; + } + } + + # Replace all '&', '<,' and '>' with their HTML entitites. Order is + # important. You have to do '&' first. + # not sure if this helps us + $text = str_replace('&', '&', $text); + $text = str_replace('<', '<', $text); + $text = str_replace('>', '>', $text); + $text = trim($text); // trim any begining / end whitespace as it is ugly + + return"
$text
"; + } + + // load modules + public static function beforePageDisplay(&$wgOut, &$sk) { + $wgOut->addModules('ext.PrismHighlight'); + $wgOut->addModules('ext.PrismHighlight.core'); + // Continue + return true; + } + } diff --git a/PrismHighlight.i18n.php b/PrismHighlight.i18n.php new file mode 100644 index 0000000..5d32330 --- /dev/null +++ b/PrismHighlight.i18n.php @@ -0,0 +1,39 @@ + + * + * @file + * @link http:// + * @ingroup Extensions + * @author Andrew Senetar + * @copyright (c) 2013 by Andrew Senetar + * @license http://opensource.org/licenses/MIT MIT License + */ + +$messages = array(); + +/** + * English + * + * @author Andrew Senetar + */ +$messages[ 'en' ] = array( + 'prismhighlight-desc' => 'Code highlighting using the prismjs highlighter', +); + +/** + * Message Documentation + * + * @author Andrew Senetar + */ +$messages[ 'qqq' ] = array( + 'prismhighlight-desc' => '{{desc|name=PrismHighlight|url=http://}}', +); + +/** + * Add other languages below here + */ + diff --git a/PrismHighlight.php b/PrismHighlight.php new file mode 100644 index 0000000..23cde19 --- /dev/null +++ b/PrismHighlight.php @@ -0,0 +1,158 @@ + + * @copyright (c) 2013 by Andrew Senetar + * @license http://opensource.org/licenses/MIT MIT License + */ + +$wgExtensionCredits['other'][] = array( + 'path' => __FILE__, + 'name' => 'PrismHighlight', + 'version' => 0.1, + 'author' => 'Andrew Senetar', + //'url' => 'http://', + 'descriptionmsg' =>'prismhighlight-desc', +); + +/** + * Configuration variables for the extension + */ + + // Default languages to load +if (! isset($wgPrismHighlightLanguages)) { + $wgPrismHighlightLanguages = array( + 'bash', + 'c', + 'css', + 'javascript', + 'python', + 'php', + 'sql', + 'markup', + ); +} + +// List of plugins to load (none by default) +// autolinker does not appear to work nor does show-invisibles +// line-number and line-highlight should not be used together since it breaks visual +if (! isset($wgPrismHighlightPlugins)) { + $wgPrismHighlightPlugins = array( + ); +} + +// Allow highlighting source tags +if (! isset($wgPrismHighlightSource)) { + $wgPrismHighlightSource = true; +} + +// The theme to use (false for default) +if (! isset($wgPrismHighlightTheme)) { + $wgPrismHighlightTheme = false; +} + +// Build the list for the js includes +function efPrismHighlight_Scripts() { + global $wgPrismHighlightPlugins, $wgPrismHighlightLanguages; + + // some languages depend on others + $plugin_deps = array( + 'bash' => 'clike', + 'c' => 'clike', + 'coffeescript' => 'javascript', + 'cpp' => 'c', + 'groovy' => 'clike', + 'java' => 'clike', + 'javascript' => 'clike', + 'php' => 'clike', + 'scss' => 'css', + ); + + // make sure all needed languages are loaded + $langs = $wgPrismHighlightLanguages; + foreach($langs as $lang ){ + if( array_key_exists( $lang, $plugin_deps ) ) + $langs[] = $plugin_deps[$lang]; + } + // remove duplicates order matters... + $langs = array_unique( array_reverse( $langs ) ); + + // load plugins + foreach( $wgPrismHighlightPlugins as $plugin ) + $scripts[] = "prism/plugins/prism-$plugin.js"; + + // load languages + foreach( $langs as $lang ) + $scripts[] = "prism/components/prism-$lang.js"; + return $scripts; +} + +// build list of styles to include +function efPrismHighlight_Styles() { + global $wgPrismHighlightPlugins, $wgPrismHighlightTheme; + + // stop mediawiki from causing problems + $styles[] = 'overrides.css'; + + // load the theme or not + if( $wgPrismHighlightTheme != false ) + $styles[] = "prism/themes/prism-$wgPrismHighlightTheme.css"; + else + $styles[] = "prism/prism.css"; + + // load plugin styles + foreach($wgPrismHighlightPlugins as $plugin) + $styles[] = "prism/plugins/prism-$plugin.css"; + return $styles; +} + +/** + * Setup for the extension + */ +$wgAutoloadClasses['PrismHighlight'] = dirname(__FILE__) . '/PrismHighlight.base.php'; +$wgExtensionMessagesFiles['PrismHighlight'] = dirname(__FILE__) . '/PrismHighlight.i18n.php'; + +/** + * Resource Modules + */ + + // styles and scripts to load after core is in place +$wgResourceModules['ext.PrismHighlight'] = array( + 'localBasePath' => dirname(__FILE__), + 'remoteExtPath' => 'PrismHighlight', + 'styles' => efPrismHighlight_Styles(), + 'scripts' => efPrismHighlight_Scripts(), + 'dependencies' => 'ext.PrismHighlight.core', +); + +// the core +$wgResourceModules['ext.PrismHighlight.core'] = array( + 'localBasePath' => dirname(__FILE__), + 'remoteExtPath' => 'PrismHighlight', + 'scripts' => array( 'prism/prism-core.js', 'init.js' ), +); + +/** + * Hooks + */ +// Register parser hook +$wgHooks['ParserFirstCallInit'][] = 'efPrismHighlight_Setup'; +// Register before display hook to load css / js files +$wgHooks['BeforePageDisplay'][] = 'PrismHighlight::beforePageDisplay'; + +/** + * Register parser hook + */ +function efPrismHighlight_Setup( &$parser ) { + global $wgPrismHighlightSource; + if( $wgPrismHighlightSource) + $parser->setHook('source', array('PrismHighlight', 'parserHook')); + $parser->setHook('syntaxhighlight', array('PrismHighlight', 'parserHook')); + return true; +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..c1657fb --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +PrismHighlight +=============== + Prism highlight is a syntax highlighting extension for [Mediawiki](http://www.mediawiki.org/ "MediaWiki") which uses the [Prism](http://prismjs.com/ "Prism") JavaScript syntax highlighter. + +Installation +------------- +To install the extension clone the source into your extensions directory: +~~~ +cd /path/to/wiki/extensions +git clone https://github.com/arsenetar/PrismHighlight.git +~~~ +Alternatively you may download the source via [zip](https://github.com/arsenetar/PrismHighlight/archive/master.zip). + +To activate the extension open your `LocalSettings.php` file and add the following: +~~~ +require_once("$IP/extensions/PrismHighlight/PrismHighlight.php"); +~~~ + +Configuration +-------------- +The following are the configuration options for the `Localsettings.php` file ( defaults shown ): +~~~ +/** + * Theme to use + * options: dark, funky, okaidia, tomoorrow, twilight, false ( default ) + * / +$wgPrismHighlightTheme = false; + +/** + * Allow to highlight tags + * options: true / false + */ +$wgPrismHighlightSource = true; + +/** + * Plugins to use + * options: autolinker, file-highlight, ie8, line-highlight, line-numbers, + * show-invisibles, wpd + * note: autolinker and show-invisibles do not appear to work for some reason + */ +$wgPrismHighlightPlugins = array( + ); + +/** + * Languages to load + * options: bash, c, clike, coffeescript, cpp, css, css-extras, groovy, + * java, javascript, markup, php, python, scss, sql + */ +$wgPrismHighlightLanguages = array( + 'bash', + 'c', + 'css', + 'javascript', + 'python', + 'php', + 'sql', + 'markup', + ); +~~~ + +Use +---- +To use the syntax highlighter in wiki markup create the following: +~~~ + + //[...] + +~~~ +Place your code where `//[...]` is. + +Now the following parameters may be passed to the `` tag: + +- `lang` or `language` - language to use (none specified uses markup) +- `data-start` - the starting line number for numbering or highlight +- `data-lines` - the lines to highlight +- `line-numbers` - used as a flag to specify line numbers should be used + +### Example +~~~ + + foreach( $args as $key => $value ){ + switch ($key) { + case 'lang': + case 'language': + $code_classes .= " language-$value"; + break; + case 'class': + $code_classes .= " $value"; + break; + case 'line-numbers': + $pre_args .= " class=$key"; + break; + case 'data-start': + $pre_args .= " data-line-offset=$value"; //should make sure this is set + default; + $pre_args .= " $key=$value"; + } + } + +~~~ diff --git a/init.js b/init.js new file mode 100644 index 0000000..cb18b66 --- /dev/null +++ b/init.js @@ -0,0 +1,6 @@ +// jQuery.ready() fires when still at 'interactive' which is does not work for this script +document.onreadystatechange = function () { + if (document.readyState == "complete") { + Prism.highlightAll(); + } +} \ No newline at end of file diff --git a/overrides.css b/overrides.css new file mode 100644 index 0000000..72708f8 --- /dev/null +++ b/overrides.css @@ -0,0 +1,4 @@ +/* Stop Mediawiki from changing the background of code tags */ +@media screen{ + code{ background: inherit !important;} +} diff --git a/prism/components/prism-bash.js b/prism/components/prism-bash.js new file mode 100644 index 0000000..ad6e9f1 --- /dev/null +++ b/prism/components/prism-bash.js @@ -0,0 +1,24 @@ +Prism.languages.bash = Prism.languages.extend('clike', { + 'comment': { + pattern: /(^|[^"{\\])(#.*?(\r?\n|$))/g, + lookbehind: true + }, + 'string': { + //allow multiline string + pattern: /("|')(\\?[\s\S])*?\1/g, + inside: { + //'property' class reused for bash variables + 'property': /\$([a-zA-Z0-9_#\?\-\*!@]+|\{[^\}]+\})/g + } + }, + 'keyword': /\b(if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)\b/g +}); + +Prism.languages.insertBefore('bash', 'keyword', { + //'property' class reused for bash variables + 'property': /\$([a-zA-Z0-9_#\?\-\*!@]+|\{[^}]+\})/g +}); +Prism.languages.insertBefore('bash', 'comment', { + //shebang must be before comment, 'important' class from css reused + 'important': /(^#!\s*\/bin\/bash)|(^#!\s*\/bin\/sh)/g +}); diff --git a/prism/components/prism-c.js b/prism/components/prism-c.js new file mode 100644 index 0000000..a0a8933 --- /dev/null +++ b/prism/components/prism-c.js @@ -0,0 +1,9 @@ +Prism.languages.c = Prism.languages.extend('clike', { + 'keyword': /\b(asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/g, + 'operator': /[-+]{1,2}|!=?|<{1,2}=?|>{1,2}=?|\->|={1,2}|\^|~|%|(&){1,2}|\|?\||\?|\*|\//g +}); + +Prism.languages.insertBefore('c', 'keyword', { + //property class reused for macro statements + 'property': /#\s*[a-zA-Z]+/g +}); diff --git a/prism/components/prism-clike.js b/prism/components/prism-clike.js new file mode 100644 index 0000000..d29e3fd --- /dev/null +++ b/prism/components/prism-clike.js @@ -0,0 +1,26 @@ +Prism.languages.clike = { + 'comment': { + pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g, + lookbehind: true + }, + 'string': /("|')(\\?.)*?\1/g, + 'class-name': { + pattern: /((?:class|interface|extends|implements|trait|instanceof|new)\s+)[a-z0-9_\.\\]+/ig, + lookbehind: true, + inside: { + punctuation: /(\.|\\)/ + } + }, + 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|catch|finally|null|break|continue)\b/g, + 'boolean': /\b(true|false)\b/g, + 'function': { + pattern: /[a-z0-9_]+\(/ig, + inside: { + punctuation: /\(/ + } + }, + 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g, + 'operator': /[-+]{1,2}|!|=?<|=?>|={1,2}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g, + 'ignore': /&(lt|gt|amp);/gi, + 'punctuation': /[{}[\];(),.:]/g +}; \ No newline at end of file diff --git a/prism/components/prism-coffeescript.js b/prism/components/prism-coffeescript.js new file mode 100644 index 0000000..99c0edb --- /dev/null +++ b/prism/components/prism-coffeescript.js @@ -0,0 +1,16 @@ +Prism.languages.coffeescript = Prism.languages.extend('javascript', { + 'block-comment': /([#]{3}\s*\r?\n(.*\s*\r*\n*)\s*?\r?\n[#]{3})/g, + 'comment': /(\s|^)([#]{1}[^#^\r^\n]{2,}?(\r?\n|$))/g, + 'keyword': /\b(this|window|delete|class|extends|namespace|extend|ar|let|if|else|while|do|for|each|of|return|in|instanceof|new|with|typeof|try|catch|finally|null|undefined|break|continue)\b/g +}); + +Prism.languages.insertBefore('coffeescript', 'keyword', { + 'function': { + pattern: /[a-z|A-z]+\s*[:|=]\s*(\([.|a-z\s|,|:|{|}|\"|\'|=]*\))?\s*->/gi, + inside: { + 'function-name': /[_?a-z-|A-Z-]+(\s*[:|=])| @[_?$?a-z-|A-Z-]+(\s*)| /g, + 'operator': /[-+]{1,2}|!|=?<|=?>|={1,2}|(&){1,2}|\|?\||\?|\*|\//g + } + }, + 'attr-name': /[_?a-z-|A-Z-]+(\s*:)| @[_?$?a-z-|A-Z-]+(\s*)| /g +}); diff --git a/prism/components/prism-cpp.js b/prism/components/prism-cpp.js new file mode 100644 index 0000000..c4006c5 --- /dev/null +++ b/prism/components/prism-cpp.js @@ -0,0 +1,4 @@ +Prism.languages.cpp = Prism.languages.extend('c', { + 'keyword': /\b(alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|delete\[\]|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|new\[\]|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/g, + 'operator': /[-+]{1,2}|!=?|<{1,2}=?|>{1,2}=?|\->|:{1,2}|={1,2}|\^|~|%|(&){1,2}|\|?\||\?|\*|\/|\b(and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/g +}); diff --git a/prism/components/prism-css-extras.js b/prism/components/prism-css-extras.js new file mode 100644 index 0000000..706490c --- /dev/null +++ b/prism/components/prism-css-extras.js @@ -0,0 +1,16 @@ +Prism.languages.css.selector = { + pattern: /[^\{\}\s][^\{\}]*(?=\s*\{)/g, + inside: { + 'pseudo-element': /:(?:after|before|first-letter|first-line|selection)|::[-\w]+/g, + 'pseudo-class': /:[-\w]+(?:\(.*\))?/g, + 'class': /\.[-:\.\w]+/g, + 'id': /#[-:\.\w]+/g + } +}; + +Prism.languages.insertBefore('css', 'ignore', { + 'hexcode': /#[\da-f]{3,6}/gi, + 'entity': /\\[\da-f]{1,8}/gi, + 'number': /[\d%\.]+/g, + 'function': /(attr|calc|cross-fade|cycle|element|hsl|hsla|image|lang|linear-gradient|matrix|matrix3d|perspective|radial-gradient|repeating-linear-gradient|repeating-radial-gradient|rgb|rgba|rotate|rotatex|rotatey|rotatez|rotate3d|scale|scalex|scaley|scalez|scale3d|skew|skewx|skewy|steps|translate|translatex|translatey|translatez|translate3d|url|var)/ig +}); \ No newline at end of file diff --git a/prism/components/prism-css.js b/prism/components/prism-css.js new file mode 100644 index 0000000..77f94d4 --- /dev/null +++ b/prism/components/prism-css.js @@ -0,0 +1,26 @@ +Prism.languages.css = { + 'comment': /\/\*[\w\W]*?\*\//g, + 'atrule': /@[\w-]+?(\s+[^;{]+)?(?=\s*{|\s*;)/gi, + 'url': /url\((["']?).*?\1\)/gi, + 'selector': /[^\{\}\s][^\{\}]*(?=\s*\{)/g, + 'property': /(\b|\B)[a-z-]+(?=\s*:)/ig, + 'string': /("|')(\\?.)*?\1/g, + 'important': /\B!important\b/gi, + 'ignore': /&(lt|gt|amp);/gi, + 'punctuation': /[\{\};:]/g +}; + +if (Prism.languages.markup) { + Prism.languages.insertBefore('markup', 'tag', { + 'style': { + pattern: /(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/ig, + inside: { + 'tag': { + pattern: /(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/ig, + inside: Prism.languages.markup.tag.inside + }, + rest: Prism.languages.css + } + } + }); +} \ No newline at end of file diff --git a/prism/components/prism-groovy.js b/prism/components/prism-groovy.js new file mode 100644 index 0000000..e5ab3ac --- /dev/null +++ b/prism/components/prism-groovy.js @@ -0,0 +1,30 @@ +Prism.languages.groovy = Prism.languages.extend('clike', { + 'keyword': /\b(as|def|in|abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|transient|try|void|volatile|while)\b/g, + 'string': /("""|''')[\W\w]*?\1|("|'|\/)[\W\w]*?\2/g, + 'number': /\b0b[01_]+\b|\b0x[\da-f_]+(\.[\da-f_p\-]+)?\b|\b[\d_]+(\.[\d_]+[e]?[\d]*)?[glidf]\b|[\d_]+(\.[\d_]+)?\b/gi, + 'operator': /={0,2}~|\?\.|\*?\.@|\.&|\.(?=\w)|\.{2}(<)?(?=\w)|->|\?:|[-+]{1,2}|!|<=>|(>){1,3}|(<){1,2}|={1,2}|(&){1,2}|\|{1,2}|\?|\*{1,2}|\/|\^|%/g, + 'punctuation': /\.+|[{}[\];(),:$]/g, + 'annotation': /@\w+/ +}); + +Prism.languages.insertBefore('groovy', 'punctuation', { + 'spock-block': /\b(setup|given|when|then|and|cleanup|expect|where):/g +}); + +Prism.hooks.add('wrap', function(env) { + if (env.language === 'groovy' && env.type === 'string') { + var delimiter = env.content[0]; + + if (delimiter != "'") { + env.content = Prism.highlight(env.content, { + 'expression': { + pattern: /([^\\])(\$(\{.*?\}|[\w\.]*))/, + lookbehind: true, + inside: Prism.languages.groovy + } + }); + + env.classes.push(delimiter === '/' ? 'regex' : 'gstring'); + } + } +}); diff --git a/prism/components/prism-java.js b/prism/components/prism-java.js new file mode 100644 index 0000000..1e61ad0 --- /dev/null +++ b/prism/components/prism-java.js @@ -0,0 +1,8 @@ +Prism.languages.java = Prism.languages.extend('clike', { + 'keyword': /\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/g, + 'number': /\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+[e]?[\d]*[df]\b|\W\d*\.?\d+\b/gi, + 'operator': { + pattern: /([^\.]|^)([-+]{1,2}|!|=?<|=?>|={1,2}|(&){1,2}|\|?\||\?|\*|\/|%|\^|(<){2}|($gt;){2,3}|:|~)/g, + lookbehind: true + } +}); \ No newline at end of file diff --git a/prism/components/prism-javascript.js b/prism/components/prism-javascript.js new file mode 100644 index 0000000..48c07d3 --- /dev/null +++ b/prism/components/prism-javascript.js @@ -0,0 +1,26 @@ +Prism.languages.javascript = Prism.languages.extend('clike', { + 'keyword': /\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|catch|finally|null|break|continue)\b/g, + 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g +}); + +Prism.languages.insertBefore('javascript', 'keyword', { + 'regex': { + pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g, + lookbehind: true + } +}); + +if (Prism.languages.markup) { + Prism.languages.insertBefore('markup', 'tag', { + 'script': { + pattern: /(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig, + inside: { + 'tag': { + pattern: /(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig, + inside: Prism.languages.markup.tag.inside + }, + rest: Prism.languages.javascript + } + } + }); +} \ No newline at end of file diff --git a/prism/components/prism-markup.js b/prism/components/prism-markup.js new file mode 100644 index 0000000..a2dda33 --- /dev/null +++ b/prism/components/prism-markup.js @@ -0,0 +1,41 @@ +Prism.languages.markup = { + 'comment': /<!--[\w\W]*?--(>|>)/g, + 'prolog': /<\?.+?\?>/, + 'doctype': /<!DOCTYPE.+?>/, + 'cdata': /<!\[CDATA\[[\w\W]*?]]>/i, + 'tag': { + pattern: /<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|\w+))?\s*)*\/?>/gi, + inside: { + 'tag': { + pattern: /^<\/?[\w:-]+/i, + inside: { + 'punctuation': /^<\/?/, + 'namespace': /^[\w-]+?:/ + } + }, + 'attr-value': { + pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi, + inside: { + 'punctuation': /=|>|"/g + } + }, + 'punctuation': /\/?>/g, + 'attr-name': { + pattern: /[\w:-]+/g, + inside: { + 'namespace': /^[\w-]+?:/ + } + } + + } + }, + 'entity': /&#?[\da-z]{1,8};/gi +}; + +// Plugin to make entity title show the real entity, idea by Roman Komarov +Prism.hooks.add('wrap', function(env) { + + if (env.type === 'entity') { + env.attributes['title'] = env.content.replace(/&/, '&'); + } +}); \ No newline at end of file diff --git a/prism/components/prism-php.js b/prism/components/prism-php.js new file mode 100644 index 0000000..c87a375 --- /dev/null +++ b/prism/components/prism-php.js @@ -0,0 +1,60 @@ +/** + * Original by Aaron Harun: http://aahacreative.com/2012/07/31/php-syntax-highlighting-prism/ + * Modified by Miles Johnson: http://milesj.me + * + * Supports the following: + * - Extends clike syntax + * - Support for PHP 5.3 and 5.4 (namespaces, traits, etc) + * - Smarter constant and function matching + * + * Adds the following new token classes: + * constant, deliminator, variable, function, scope, package, this + */ + +Prism.languages.php = Prism.languages.extend('clike', { + 'keyword': /\b(and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|extends|private|protected|parent|static|throw|null|echo|print|trait|namespace|use|final|yield|goto)\b/ig, + 'constant': /[A-Z0-9_]{2,}/g +}); + +Prism.languages.insertBefore('php', 'keyword', { + 'deliminator': /(\?>|\?>|<\?php|<\?php)/ig, + 'this': /\$this/, + 'variable': /(\$\w+)\b/ig, + 'scope': { + pattern: /\b[a-z0-9_\\]+::/ig, + inside: { + keyword: /(static|self|parent)/, + punctuation: /(::|\\)/ + } + }, + 'package': { + pattern: /(\\|namespace\s+|use\s+)[a-z0-9_\\]+/ig, + lookbehind: true, + inside: { + punctuation: /\\/ + } + } +}); + +Prism.languages.insertBefore('php', 'operator', { + 'property': { + pattern: /(->)[a-z0-9_]+/ig, + lookbehind: true + } +}); + +if (Prism.languages.markup) { + Prism.languages.insertBefore('php', 'comment', { + 'markup': { + pattern: /(\?>|\?>)[\w\W]*?(?=(<\?php|<\?php))/ig, + lookbehind : true, + inside: { + 'markup': { + pattern: /<\/?[\w:-]+\s*[\w\W]*?>/gi, + inside: Prism.languages.markup.tag.inside + }, + rest: Prism.languages.php + } + } + }); +} \ No newline at end of file diff --git a/prism/components/prism-python.js b/prism/components/prism-python.js new file mode 100644 index 0000000..34ac317 --- /dev/null +++ b/prism/components/prism-python.js @@ -0,0 +1,14 @@ +Prism.languages.python= { + 'comment': { + pattern: /(^|[^\\])#.*?(\r?\n|$)/g, + lookbehind: true + }, + 'string' : /("|')(\\?.)*?\1/g, + 'keyword' : /\b(as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/g, + 'boolean' : /\b(True|False)\b/g, + 'number' : /\b-?(0x)?\d*\.?[\da-f]+\b/g, + 'operator' : /[-+]{1,2}|=?<|=?>|!|={1,2}|(&){1,2}|(&){1,2}|\|?\||\?|\*|\/|~|\^|%|\b(or|and|not)\b/g, + 'ignore' : /&(lt|gt|amp);/gi, + 'punctuation' : /[{}[\];(),.:]/g +}; + diff --git a/prism/components/prism-scss.js b/prism/components/prism-scss.js new file mode 100644 index 0000000..86dc002 --- /dev/null +++ b/prism/components/prism-scss.js @@ -0,0 +1,36 @@ +Prism.languages.scss = Prism.languages.extend('css', { + 'comment': { + pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g, + lookbehind: true + }, + // aturle is just the @***, not the entire rule (to highlight var & stuffs) + // + add ability to highlight number & unit for media queries + 'atrule': /@[\w-]+(?=\s+(\(|\{|;))/gi, + // url, compassified + 'url': /([-a-z]+-)*url(?=\()/gi, + // CSS selector regex is not appropriate for Sass + // since there can be lot more things (var, @ directive, nesting..) + // a selector must start at the end of a property or after a brace (end of other rules or nesting) + // it can contain some caracters that aren't used for defining rules or end of selector, & (parent selector), or interpolated variable + // the end of a selector is found when there is no rules in it ( {} or {\s}) or if there is a property (because an interpolated var + // can "pass" as a selector- e.g: proper#{$erty}) + // this one was ard to do, so please be careful if you edit this one :) + 'selector': /([^@;\{\}\(\)]?([^@;\{\}\(\)]|&|\#\{\$[-_\w]+\})+)(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/gm +}); + +Prism.languages.insertBefore('scss', 'atrule', { + 'keyword': /@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return)|(?=@for\s+\$[-_\w]+\s)+from/i +}); + +Prism.languages.insertBefore('scss', 'property', { + // var and interpolated vars + 'variable': /((\$[-_\w]+)|(#\{\$[-_\w]+\}))/i +}); + +Prism.languages.insertBefore('scss', 'ignore', { + 'placeholder': /%[-_\w]+/i, + 'statement': /\B!(default|optional)\b/gi, + 'boolean': /\b(true|false)\b/g, + 'null': /\b(null)\b/g, + 'operator': /\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g +}); diff --git a/prism/components/prism-sql.js b/prism/components/prism-sql.js new file mode 100644 index 0000000..8a7d685 --- /dev/null +++ b/prism/components/prism-sql.js @@ -0,0 +1,13 @@ +Prism.languages.sql= { + 'comment': { + pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|((--)|(\/\/)).*?(\r?\n|$))/g, + lookbehind: true + }, + 'string' : /("|')(\\?.)*?\1/g, + 'keyword' : /\b(ACTION|ADD|AFTER|ALGORITHM|ALTER|ANALYZE|APPLY|AS|ASC|AUTHORIZATION|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADE|CASCADED|CASE|CHAIN|CHAR VARYING|CHARACTER VARYING|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLUMN|COLUMNS|COMMENT|COMMIT|COMMITTED|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATA|DATABASE|DATABASES|DATETIME|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DOUBLE PRECISION|DROP|DUMMY|DUMP|DUMPFILE|DUPLICATE KEY|ELSE|ENABLE|ENCLOSED BY|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPE|ESCAPED BY|EXCEPT|EXEC|EXECUTE|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR|FOR EACH ROW|FORCE|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GEOMETRY|GEOMETRYCOLLECTION|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|IDENTITY|IDENTITY_INSERT|IDENTITYCOL|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTO|INVOKER|ISOLATION LEVEL|JOIN|KEY|KEYS|KILL|LANGUAGE SQL|LAST|LEFT|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONGBLOB|LONGTEXT|MATCH|MATCHED|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MERGE|MIDDLEINT|MODIFIES SQL DATA|MODIFY|MULTILINESTRING|MULTIPOINT|MULTIPOLYGON|NATIONAL|NATIONAL CHAR VARYING|NATIONAL CHARACTER|NATIONAL CHARACTER VARYING|NATIONAL VARCHAR|NATURAL|NCHAR|NCHAR VARCHAR|NEXT|NO|NO SQL|NOCHECK|NOCYCLE|NONCLUSTERED|NULLIF|NUMERIC|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPTIMIZE|OPTION|OPTIONALLY|ORDER|OUT|OUTER|OUTFILE|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREV|PRIMARY|PRINT|PRIVILEGES|PROC|PROCEDURE|PUBLIC|PURGE|QUICK|RAISERROR|READ|READS SQL DATA|READTEXT|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEATABLE|REPLICATION|REQUIRE|RESTORE|RESTRICT|RETURN|RETURNS|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROWCOUNT|ROWGUIDCOL|ROWS?|RTREE|RULE|SAVE|SAVEPOINT|SCHEMA|SELECT|SERIAL|SERIALIZABLE|SESSION|SESSION_USER|SET|SETUSER|SHARE MODE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|START|STARTING BY|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLE|TABLES|TABLESPACE|TEMPORARY|TEMPTABLE|TERMINATED BY|TEXT|TEXTSIZE|THEN|TIMESTAMP|TINYBLOB|TINYINT|TINYTEXT|TO|TOP|TRAN|TRANSACTION|TRANSACTIONS|TRIGGER|TRUNCATE|TSEQUAL|TYPE|TYPES|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNPIVOT|UPDATE|UPDATETEXT|USAGE|USE|USER|USING|VALUE|VALUES|VARBINARY|VARCHAR|VARCHARACTER|VARYING|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH|WITH ROLLUP|WITHIN|WORK|WRITE|WRITETEXT)\b/gi, + 'boolean' : /\b(TRUE|FALSE|NULL)\b/gi, + 'number' : /\b-?(0x)?\d*\.?[\da-f]+\b/g, + 'operator' : /\b(ALL|AND|ANY|BETWEEN|EXISTS|IN|LIKE|NOT|OR|IS|UNIQUE|CHARACTER SET|COLLATE|DIV|OFFSET|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b|[-+]{1}|!|=?<|=?>|={1}|(&){1,2}|\|?\||\?|\*|\//gi, + 'ignore' : /&(lt|gt|amp);/gi, + 'punctuation' : /[;[\]()`,.]/g +}; diff --git a/prism/plugins/prism-autolinker.css b/prism/plugins/prism-autolinker.css new file mode 100644 index 0000000..b5f7630 --- /dev/null +++ b/prism/plugins/prism-autolinker.css @@ -0,0 +1,3 @@ +.token a { + color: inherit; +} \ No newline at end of file diff --git a/prism/plugins/prism-autolinker.js b/prism/plugins/prism-autolinker.js new file mode 100644 index 0000000..0d96c5c --- /dev/null +++ b/prism/plugins/prism-autolinker.js @@ -0,0 +1,61 @@ +(function(){ + +if (!self.Prism) { + return; +} + +var url = /\b([a-z]{3,7}:\/\/|tel:)[\w-+%~/.]+/, + email = /\b\S+@[\w.]+[a-z]{2}/, + linkMd = /\[([^\]]+)]\(([^)]+)\)/, + + // Tokens that may contain URLs and emails + candidates = ['comment', 'url', 'attr-value', 'string']; + +for (var language in Prism.languages) { + var tokens = Prism.languages[language]; + + Prism.languages.DFS(tokens, function (type, def) { + if (candidates.indexOf(type) > -1) { + if (!def.pattern) { + def = this[type] = { + pattern: def + }; + } + + def.inside = def.inside || {}; + + if (type == 'comment') { + def.inside['md-link'] = linkMd; + } + + def.inside['url-link'] = url; + def.inside['email-link'] = email; + } + }); + + tokens['url-link'] = url; + tokens['email-link'] = email; +} + +Prism.hooks.add('wrap', function(env) { + if (/-link$/.test(env.type)) { + env.tag = 'a'; + + var href = env.content; + + if (env.type == 'email-link') { + href = 'mailto:' + href; + } + else if (env.type == 'md-link') { + // Markdown + var match = env.content.match(linkMd); + + href = match[2]; + env.content = match[1]; + } + + env.attributes.href = href; + } +}); + +})(); \ No newline at end of file diff --git a/prism/plugins/prism-file-highlight.js b/prism/plugins/prism-file-highlight.js new file mode 100644 index 0000000..8c4b941 --- /dev/null +++ b/prism/plugins/prism-file-highlight.js @@ -0,0 +1,52 @@ +(function(){ + +if (!window.Prism || !document.querySelector) { + return; +} + +var Extensions = { + 'js': 'javascript', + 'html': 'markup', + 'svg': 'markup' +}; + +Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function(pre) { + var src = pre.getAttribute('data-src'); + var extension = (src.match(/\.(\w+)$/) || [,''])[1]; + var language = Extensions[extension] || extension; + + var code = document.createElement('code'); + code.className = 'language-' + language; + + pre.textContent = ''; + + code.textContent = 'Loading…'; + + pre.appendChild(code); + + var xhr = new XMLHttpRequest(); + + xhr.open('GET', src, true); + + xhr.onreadystatechange = function() { + console.log(xhr.readyState, xhr.status, src); + if (xhr.readyState == 4) { + + if (xhr.status < 400 && xhr.responseText) { + code.textContent = xhr.responseText; + + Prism.highlightElement(code); + } + else if (xhr.status >= 400) { + code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText; + } + else { + code.textContent = '✖ Error: File does not exist or is empty'; + } + } + }; + + xhr.send(null); +}); + +})(); \ No newline at end of file diff --git a/prism/plugins/prism-ie8.css b/prism/plugins/prism-ie8.css new file mode 100644 index 0000000..b5f7630 --- /dev/null +++ b/prism/plugins/prism-ie8.css @@ -0,0 +1,3 @@ +.token a { + color: inherit; +} \ No newline at end of file diff --git a/prism/plugins/prism-ie8.js b/prism/plugins/prism-ie8.js new file mode 100644 index 0000000..0cd83ec --- /dev/null +++ b/prism/plugins/prism-ie8.js @@ -0,0 +1,42 @@ +(function(){ + +if (!window.Prism) { + return; +} + +var dummy = document.createElement('header'); + +if (!String.prototype.trim) { + String.prototype.trim = function () { + return this.replace(/^\s+/g, '').replace(/\s+$/g, ''); + }; +} + +// textContent polyfill +if (!('textContent' in dummy) && ('innerText' in dummy) && Object.defineProperty) { + Object.defineProperty(Element.prototype, 'textContent', { + get: function() { + return this.innerText; + }, + set: function(text) { + this.innerText = text; + } + }); +} + +// IE8 doesn't have DOMContentLoaded +if (!document.addEventListener && 'textContent' in dummy) { + setTimeout(Prism.highlightAll, 10); +} + +// Test if innerHTML line break bug is present +dummy.innerHTML = '\r\n'; + +if (dummy.textContent.indexOf('\n') === -1) { + // IE8 innerHTML bug: Discards line breaks + Prism.hooks.add('after-highlight', function(env) { + env.element.innerHTML = env.highlightedCode.replace(/\r?\n/g, '
'); + }); +} + +})(); \ No newline at end of file diff --git a/prism/plugins/prism-line-highlight.css b/prism/plugins/prism-line-highlight.css new file mode 100644 index 0000000..9eb3173 --- /dev/null +++ b/prism/plugins/prism-line-highlight.css @@ -0,0 +1,47 @@ +pre[data-line] { + position: relative; + padding: 1em 0 1em 3em; +} + +.line-highlight { + position: absolute; + left: 0; + right: 0; + padding: inherit 0; + margin-top: 1em; /* Same as .prism’s padding-top */ + + background: hsla(24, 20%, 50%,.08); + background: -moz-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); + background: -webkit-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); + background: -o-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); + background: linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); + + pointer-events: none; + + line-height: inherit; + white-space: pre; +} + + .line-highlight:before, + .line-highlight[data-end]:after { + content: attr(data-start); + position: absolute; + top: .4em; + left: .6em; + min-width: 1em; + padding: 0 .5em; + background-color: hsla(24, 20%, 50%,.4); + color: hsl(24, 20%, 95%); + font: bold 65%/1.5 sans-serif; + text-align: center; + vertical-align: .3em; + border-radius: 999px; + text-shadow: none; + box-shadow: 0 1px white; + } + + .line-highlight[data-end]:after { + content: attr(data-end); + top: auto; + bottom: .4em; + } \ No newline at end of file diff --git a/prism/plugins/prism-line-highlight.js b/prism/plugins/prism-line-highlight.js new file mode 100644 index 0000000..930e938 --- /dev/null +++ b/prism/plugins/prism-line-highlight.js @@ -0,0 +1,94 @@ +(function(){ + +if(!window.Prism) { + return; +} + +function $$(expr, con) { + return Array.prototype.slice.call((con || document).querySelectorAll(expr)); +} + +var CRLF = crlf = /\r?\n|\r/g; + +function highlightLines(pre, lines, classes) { + var ranges = lines.replace(/\s+/g, '').split(','), + offset = +pre.getAttribute('data-line-offset') || 0; + + var lineHeight = parseFloat(getComputedStyle(pre).lineHeight); + + for (var i=0, range; range = ranges[i++];) { + range = range.split('-'); + + var start = +range[0], + end = +range[1] || start; + + var line = document.createElement('div'); + + line.textContent = Array(end - start + 2).join(' \r\n'); + line.className = (classes || '') + ' line-highlight'; + line.setAttribute('data-start', start); + + if(end > start) { + line.setAttribute('data-end', end); + } + + line.style.top = (start - offset - 1) * lineHeight + 'px'; + + (pre.querySelector('code') || pre).appendChild(line); + } +} + +function applyHash() { + var hash = location.hash.slice(1); + + // Remove pre-existing temporary lines + $$('.temporary.line-highlight').forEach(function (line) { + line.parentNode.removeChild(line); + }); + + var range = (hash.match(/\.([\d,-]+)$/) || [,''])[1]; + + if (!range || document.getElementById(hash)) { + return; + } + + var id = hash.slice(0, hash.lastIndexOf('.')), + pre = document.getElementById(id); + + if (!pre) { + return; + } + + if (!pre.hasAttribute('data-line')) { + pre.setAttribute('data-line', ''); + } + + highlightLines(pre, range, 'temporary '); + + document.querySelector('.temporary.line-highlight').scrollIntoView(); +} + +var fakeTimer = 0; // Hack to limit the number of times applyHash() runs + +Prism.hooks.add('after-highlight', function(env) { + var pre = env.element.parentNode; + var lines = pre && pre.getAttribute('data-line'); + + if (!pre || !lines || !/pre/i.test(pre.nodeName)) { + return; + } + + clearTimeout(fakeTimer); + + $$('.line-highlight', pre).forEach(function (line) { + line.parentNode.removeChild(line); + }); + + highlightLines(pre, lines); + + fakeTimer = setTimeout(applyHash, 1); +}); + +addEventListener('hashchange', applyHash); + +})(); \ No newline at end of file diff --git a/prism/plugins/prism-line-numbers.css b/prism/plugins/prism-line-numbers.css new file mode 100644 index 0000000..284cc0a --- /dev/null +++ b/prism/plugins/prism-line-numbers.css @@ -0,0 +1,40 @@ +pre.line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; +} + +pre.line-numbers > code { + position: relative; +} + +.line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid #999; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + +} + + .line-numbers-rows > span { + pointer-events: none; + display: block; + counter-increment: linenumber; + } + + .line-numbers-rows > span:before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: 0.8em; + text-align: right; + } \ No newline at end of file diff --git a/prism/plugins/prism-line-numbers.js b/prism/plugins/prism-line-numbers.js new file mode 100644 index 0000000..e340049 --- /dev/null +++ b/prism/plugins/prism-line-numbers.js @@ -0,0 +1,24 @@ +Prism.hooks.add('after-highlight', function (env) { + // works only for wrapped inside
 (not inline)
+	var pre = env.element.parentNode;
+	if (!pre || !/pre/i.test(pre.nodeName) || pre.className.indexOf('line-numbers') === -1) {
+		return;
+	}
+
+	var linesNum = (1 + env.code.split('\n').length);
+	var lineNumbersWrapper;
+
+	lines = new Array(linesNum);
+	lines = lines.join('');
+
+	lineNumbersWrapper = document.createElement('span');
+	lineNumbersWrapper.className = 'line-numbers-rows';
+	lineNumbersWrapper.innerHTML = lines;
+
+	if (pre.hasAttribute('data-start')) {
+		pre.style.counterReset = 'linenumber ' + (parseInt(pre.getAttribute('data-start'), 10) - 1);
+	}
+
+	env.element.appendChild(lineNumbersWrapper);
+
+});
\ No newline at end of file
diff --git a/prism/plugins/prism-show-invisibles.css b/prism/plugins/prism-show-invisibles.css
new file mode 100644
index 0000000..4603a71
--- /dev/null
+++ b/prism/plugins/prism-show-invisibles.css
@@ -0,0 +1,17 @@
+.token.tab:not(:empty):before,
+.token.cr:before,
+.token.lf:before {
+	color: hsl(24, 20%, 85%);
+}
+
+.token.tab:not(:empty):before {
+	content: '▸';
+}
+
+.token.cr:before {
+	content: '␍';
+}
+
+.token.lf:before {
+	content: '␊';
+}
\ No newline at end of file
diff --git a/prism/plugins/prism-show-invisibles.js b/prism/plugins/prism-show-invisibles.js
new file mode 100644
index 0000000..19681a8
--- /dev/null
+++ b/prism/plugins/prism-show-invisibles.js
@@ -0,0 +1,15 @@
+(function(){
+
+if(!window.Prism) {
+	return;
+}
+
+for (var language in Prism.languages) {
+	var tokens = Prism.languages[language];
+	
+	tokens.tab = /\t/g;
+	tokens.lf = /\n/g;
+	tokens.cr = /\r/g;
+}
+
+})();
\ No newline at end of file
diff --git a/prism/plugins/prism-wpd.css b/prism/plugins/prism-wpd.css
new file mode 100644
index 0000000..43b7165
--- /dev/null
+++ b/prism/plugins/prism-wpd.css
@@ -0,0 +1,11 @@
+code[class*="language-"] a[href],
+pre[class*="language-"] a[href] {
+	cursor: help;
+	text-decoration: none;
+}
+
+code[class*="language-"] a[href]:hover,
+pre[class*="language-"] a[href]:hover {
+	cursor: help;
+	text-decoration: underline;
+}
\ No newline at end of file
diff --git a/prism/plugins/prism-wpd.js b/prism/plugins/prism-wpd.js
new file mode 100644
index 0000000..f423050
--- /dev/null
+++ b/prism/plugins/prism-wpd.js
@@ -0,0 +1,159 @@
+(function(){
+
+if (!self.Prism) {
+	return;
+}
+
+if (Prism.languages.css) {
+	Prism.languages.css.atrule = {
+		pattern: Prism.languages.css.atrule,
+		inside: {
+			'atrule-id': /^@[\w-]+/
+		}
+	};
+	
+	Prism.languages.css.selector = {
+		pattern: Prism.languages.css.selector,
+		inside: {
+			'pseudo-class': /:[\w-]+/,
+			'pseudo-element': /::[\w-]+/
+		}
+	};
+}
+
+if (Prism.languages.markup) {
+	Prism.languages.markup.tag.inside.tag.inside['tag-id'] = /[\w-]+/;
+	
+	var Tags = {
+		HTML: {
+			'a': 1, 'abbr': 1, 'acronym': 1, 'b': 1, 'basefont': 1, 'bdo': 1, 'big': 1, 'blink': 1, 'cite': 1, 'code': 1, 'dfn': 1, 'em': 1, 'kbd': 1,  'i': 1, 
+			'rp': 1, 'rt': 1, 'ruby': 1, 's': 1, 'samp': 1, 'small': 1, 'spacer': 1, 'strike': 1, 'strong': 1, 'sub': 1, 'sup': 1, 'time': 1, 'tt': 1,  'u': 1, 
+			'var': 1, 'wbr': 1, 'noframes': 1, 'summary': 1, 'command': 1, 'dt': 1, 'dd': 1, 'figure': 1, 'figcaption': 1, 'center': 1, 'section': 1, 'nav': 1,
+			'article': 1, 'aside': 1, 'hgroup': 1, 'header': 1, 'footer': 1, 'address': 1, 'noscript': 1, 'isIndex': 1, 'main': 1, 'mark': 1, 'marquee': 1,
+			'meter': 1, 'menu': 1
+		},
+		SVG: {
+			'animateColor': 1, 'animateMotion': 1, 'animateTransform': 1, 'glyph': 1, 'feBlend': 1, 'feColorMatrix': 1, 'feComponentTransfer': 1, 
+			'feFuncR': 1, 'feFuncG': 1, 'feFuncB': 1, 'feFuncA': 1, 'feComposite': 1, 'feConvolveMatrix': 1, 'feDiffuseLighting': 1, 'feDisplacementMap': 1, 
+			'feFlood': 1, 'feGaussianBlur': 1, 'feImage': 1, 'feMerge': 1, 'feMergeNode': 1, 'feMorphology': 1, 'feOffset': 1, 'feSpecularLighting': 1, 
+			'feTile': 1, 'feTurbulence': 1, 'feDistantLight': 1, 'fePointLight': 1, 'feSpotLight': 1, 'linearGradient': 1, 'radialGradient': 1, 'altGlyph': 1, 
+			'textPath': 1, 'tref': 1, 'altglyph': 1, 'textpath': 1, 'tref': 1, 'altglyphdef': 1, 'altglyphitem': 1, 'clipPath': 1, 'color-profile': 1, 'cursor': 1, 
+			'font-face': 1, 'font-face-format': 1, 'font-face-name': 1, 'font-face-src': 1, 'font-face-uri': 1, 'foreignObject': 1, 'glyph': 1, 'glyphRef': 1, 
+			'hkern': 1, 'vkern': 1, 
+		},
+		MathML: {}
+	}
+}
+
+var language;
+
+Prism.hooks.add('wrap', function(env) {
+	if ((['tag-id'].indexOf(env.type) > -1
+		|| (env.type == 'property' && env.content.indexOf('-') != 0)
+		|| (env.type == 'atrule-id'&& env.content.indexOf('@-') != 0)
+		|| (env.type == 'pseudo-class'&& env.content.indexOf(':-') != 0) 
+		|| (env.type == 'pseudo-element'&& env.content.indexOf('::-') != 0) 
+	    || (env.type == 'attr-name' && env.content.indexOf('data-') != 0)
+	    ) && env.content.indexOf('<') === -1
+	) {
+		var searchURL = 'w/index.php?fulltext&search=';
+		
+		env.tag = 'a';
+		
+		var href = 'http://docs.webplatform.org/';
+		
+		if (env.language == 'css') {
+			href += 'wiki/css/'
+			
+			if (env.type == 'property') {
+				href += 'properties/';
+			}
+			else if (env.type == 'atrule-id') {
+				href += 'atrules/';
+			}
+			else if (env.type == 'pseudo-class') {
+				href += 'selectors/pseudo-classes/';
+			}
+			else if (env.type == 'pseudo-element') {
+				href += 'selectors/pseudo-elements/';
+			}
+		}
+		else if (env.language == 'markup') {
+			if (env.type == 'tag-id') {
+				// Check language
+				language = getLanguage(env.content) || language;
+				
+				if (language) {
+					href += 'wiki/' + language + '/elements/';
+				}
+				else {
+					href += searchURL;
+				}
+			}
+			else if (env.type == 'attr-name') {
+				if (language) {
+					href += 'wiki/' + language + '/attributes/';
+				}
+				else {
+					href += searchURL;
+				}
+			}
+		}
+		
+		href += env.content;
+		
+		env.attributes.href = href;
+		env.attributes.target = '_blank';
+	}
+});
+
+function getLanguage(tag) {
+	var tagL = tag.toLowerCase();
+	
+	if (Tags.HTML[tagL]) {
+		return 'html';
+	}
+	else if (Tags.SVG[tag]) {
+		return 'svg';
+	}
+	else if (Tags.MathML[tag]) {
+		return 'mathml';
+	}
+	
+	// Not in dictionary, perform check
+	if (Tags.HTML[tagL] !== 0) {
+		var htmlInterface = (document.createElement(tag).toString().match(/\[object HTML(.+)Element\]/) || [])[1];
+		
+		if (htmlInterface && htmlInterface != 'Unknown') {
+			Tags.HTML[tagL] = 1;
+			return 'html';
+		}
+	}
+	
+	Tags.HTML[tagL] = 0;
+	
+	if (Tags.SVG[tag] !== 0) {
+		var svgInterface = (document.createElementNS('http://www.w3.org/2000/svg', tag).toString().match(/\[object SVG(.+)Element\]/) || [])[1];
+		
+		if (svgInterface && svgInterface != 'Unknown') {
+			Tags.SVG[tag] = 1;
+			return 'svg';
+		}
+	}
+	
+	Tags.SVG[tag] = 0;
+	
+	// Lame way to detect MathML, but browsers don’t expose interface names there :(
+	if (Tags.MathML[tag] !== 0) {
+		if (tag.indexOf('m') === 0) {
+			Tags.MathML[tag] = 1;
+			return 'mathml';
+		}
+	}
+	
+	Tags.MathML[tag] = 0;
+	
+	return null;
+}
+
+})();
\ No newline at end of file
diff --git a/prism/prism-core.js b/prism/prism-core.js
new file mode 100644
index 0000000..8a9cae0
--- /dev/null
+++ b/prism/prism-core.js
@@ -0,0 +1,356 @@
+/**
+ * Prism: Lightweight, robust, elegant syntax highlighting
+ * MIT license http://www.opensource.org/licenses/mit-license.php/
+ * @author Lea Verou http://lea.verou.me
+ */
+
+(function(){
+
+// Private helper vars
+var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;
+
+var _ = self.Prism = {
+	util: {
+		type: function (o) { 
+			return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1];
+		},
+		
+		// Deep clone a language definition (e.g. to extend it)
+		clone: function (o) {
+			var type = _.util.type(o);
+
+			switch (type) {
+				case 'Object':
+					var clone = {};
+					
+					for (var key in o) {
+						if (o.hasOwnProperty(key)) {
+							clone[key] = _.util.clone(o[key]);
+						}
+					}
+					
+					return clone;
+					
+				case 'Array':
+					return o.slice();
+			}
+			
+			return o;
+		}
+	},
+	
+	languages: {
+		extend: function (id, redef) {
+			var lang = _.util.clone(_.languages[id]);
+			
+			for (var key in redef) {
+				lang[key] = redef[key];
+			}
+			
+			return lang;
+		},
+		
+		// Insert a token before another token in a language literal
+		insertBefore: function (inside, before, insert, root) {
+			root = root || _.languages;
+			var grammar = root[inside];
+			var ret = {};
+				
+			for (var token in grammar) {
+			
+				if (grammar.hasOwnProperty(token)) {
+					
+					if (token == before) {
+					
+						for (var newToken in insert) {
+						
+							if (insert.hasOwnProperty(newToken)) {
+								ret[newToken] = insert[newToken];
+							}
+						}
+					}
+					
+					ret[token] = grammar[token];
+				}
+			}
+			
+			return root[inside] = ret;
+		},
+		
+		// Traverse a language definition with Depth First Search
+		DFS: function(o, callback) {
+			for (var i in o) {
+				callback.call(o, i, o[i]);
+				
+				if (_.util.type(o) === 'Object') {
+					_.languages.DFS(o[i], callback);
+				}
+			}
+		}
+	},
+
+	highlightAll: function(async, callback) {
+		var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');
+
+		for (var i=0, element; element = elements[i++];) {
+			_.highlightElement(element, async === true, callback);
+		}
+	},
+		
+	highlightElement: function(element, async, callback) {
+		// Find language
+		var language, grammar, parent = element;
+		
+		while (parent && !lang.test(parent.className)) {
+			parent = parent.parentNode;
+		}
+		
+		if (parent) {
+			language = (parent.className.match(lang) || [,''])[1];
+			grammar = _.languages[language];
+		}
+
+		if (!grammar) {
+			return;
+		}
+		
+		// Set language on the element, if not present
+		element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
+		
+		// Set language on the parent, for styling
+		parent = element.parentNode;
+		
+		if (/pre/i.test(parent.nodeName)) {
+			parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; 
+		}
+
+		var code = element.textContent;
+		
+		if(!code) {
+			return;
+		}
+		
+		code = code.replace(/&/g, '&').replace(//g, '>').replace(/\u00a0/g, ' ');
+		//console.time(code.slice(0,50));
+		
+		var env = {
+			element: element,
+			language: language,
+			grammar: grammar,
+			code: code
+		};
+		
+		_.hooks.run('before-highlight', env);
+		
+		if (async && self.Worker) {
+			var worker = new Worker(_.filename);	
+			
+			worker.onmessage = function(evt) {
+				env.highlightedCode = Token.stringify(JSON.parse(evt.data), language);
+
+				_.hooks.run('before-insert', env);
+
+				env.element.innerHTML = env.highlightedCode;
+				
+				callback && callback.call(env.element);
+				//console.timeEnd(code.slice(0,50));
+				_.hooks.run('after-highlight', env);
+			};
+			
+			worker.postMessage(JSON.stringify({
+				language: env.language,
+				code: env.code
+			}));
+		}
+		else {
+			env.highlightedCode = _.highlight(env.code, env.grammar, env.language)
+
+			_.hooks.run('before-insert', env);
+
+			env.element.innerHTML = env.highlightedCode;
+			
+			callback && callback.call(element);
+			
+			_.hooks.run('after-highlight', env);
+			//console.timeEnd(code.slice(0,50));
+		}
+	},
+	
+	highlight: function (text, grammar, language) {
+		return Token.stringify(_.tokenize(text, grammar), language);
+	},
+	
+	tokenize: function(text, grammar, language) {
+		var Token = _.Token;
+		
+		var strarr = [text];
+		
+		var rest = grammar.rest;
+		
+		if (rest) {
+			for (var token in rest) {
+				grammar[token] = rest[token];
+			}
+			
+			delete grammar.rest;
+		}
+								
+		tokenloop: for (var token in grammar) {
+			if(!grammar.hasOwnProperty(token) || !grammar[token]) {
+				continue;
+			}
+			
+			var pattern = grammar[token], 
+				inside = pattern.inside,
+				lookbehind = !!pattern.lookbehind,
+				lookbehindLength = 0;
+			
+			pattern = pattern.pattern || pattern;
+			
+			for (var i=0; i text.length) {
+					// Something went terribly wrong, ABORT, ABORT!
+					break tokenloop;
+				}
+				
+				if (str instanceof Token) {
+					continue;
+				}
+				
+				pattern.lastIndex = 0;
+				
+				var match = pattern.exec(str);
+				
+				if (match) {
+					if(lookbehind) {
+						lookbehindLength = match[1].length;
+					}
+
+					var from = match.index - 1 + lookbehindLength,
+					    match = match[0].slice(lookbehindLength),
+					    len = match.length,
+					    to = from + len,
+						before = str.slice(0, from + 1),
+						after = str.slice(to + 1); 
+
+					var args = [i, 1];
+					
+					if (before) {
+						args.push(before);
+					}
+					
+					var wrapped = new Token(token, inside? _.tokenize(match, inside) : match);
+					
+					args.push(wrapped);
+					
+					if (after) {
+						args.push(after);
+					}
+					
+					Array.prototype.splice.apply(strarr, args);
+				}
+			}
+		}
+
+		return strarr;
+	},
+	
+	hooks: {
+		all: {},
+		
+		add: function (name, callback) {
+			var hooks = _.hooks.all;
+			
+			hooks[name] = hooks[name] || [];
+			
+			hooks[name].push(callback);
+		},
+		
+		run: function (name, env) {
+			var callbacks = _.hooks.all[name];
+			
+			if (!callbacks || !callbacks.length) {
+				return;
+			}
+			
+			for (var i=0, callback; callback = callbacks[i++];) {
+				callback(env);
+			}
+		}
+	}
+};
+
+var Token = _.Token = function(type, content) {
+	this.type = type;
+	this.content = content;
+};
+
+Token.stringify = function(o, language, parent) {
+	if (typeof o == 'string') {
+		return o;
+	}
+
+	if (Object.prototype.toString.call(o) == '[object Array]') {
+		return o.map(function(element) {
+			return Token.stringify(element, language, o);
+		}).join('');
+	}
+	
+	var env = {
+		type: o.type,
+		content: Token.stringify(o.content, language, parent),
+		tag: 'span',
+		classes: ['token', o.type],
+		attributes: {},
+		language: language,
+		parent: parent
+	};
+	
+	if (env.type == 'comment') {
+		env.attributes['spellcheck'] = 'true';
+	}
+	
+	_.hooks.run('wrap', env);
+	
+	var attributes = '';
+	
+	for (var name in env.attributes) {
+		attributes += name + '="' + (env.attributes[name] || '') + '"';
+	}
+	
+	return '<' + env.tag + ' class="' + env.classes.join(' ') + '" ' + attributes + '>' + env.content + '';
+	
+};
+
+if (!self.document) {
+	// In worker
+	self.addEventListener('message', function(evt) {
+		var message = JSON.parse(evt.data),
+		    lang = message.language,
+		    code = message.code;
+		
+		self.postMessage(JSON.stringify(_.tokenize(code, _.languages[lang])));
+		self.close();
+	}, false);
+	
+	return;
+}
+
+// Get current script and highlight
+var script = document.getElementsByTagName('script');
+
+script = script[script.length - 1];
+
+if (script) {
+	_.filename = script.src;
+	
+	if (document.addEventListener && !script.hasAttribute('data-manual')) {
+		document.addEventListener('DOMContentLoaded', _.highlightAll);
+	}
+}
+
+})();
\ No newline at end of file
diff --git a/prism/prism.css b/prism/prism.css
new file mode 100644
index 0000000..7c64441
--- /dev/null
+++ b/prism/prism.css
@@ -0,0 +1,106 @@
+/**
+ * prism.js default theme for JavaScript, CSS and HTML
+ * Based on dabblet (http://dabblet.com)
+ * @author Lea Verou
+ */
+code[class*="language-"],
+pre[class*="language-"] {
+	color: black;
+	text-shadow: 0 1px white;
+	font-family: Consolas, Monaco, 'Andale Mono', monospace;
+	direction: ltr;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+	
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+@media print {
+	code[class*="language-"],
+	pre[class*="language-"] {
+		text-shadow: none;
+	}
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	padding: 1em;
+	margin: .5em 0;
+	overflow: auto;	
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+	background: #f5f2f0;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	padding: .1em;
+	border-radius: .3em;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: slategray;
+}
+
+.token.punctuation {
+	color: #999;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number {
+	color: #905;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string {
+	color: #690;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+	color: #a67f59;
+	background: hsla(0,0%,100%,.5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+	color: #07a;
+}
+
+
+.token.regex,
+.token.important {
+	color: #e90;
+}
+
+.token.important {
+	font-weight: bold;
+}
+
+.token.entity {
+	cursor: help;
+}
\ No newline at end of file
diff --git a/prism/themes/prism-dark.css b/prism/themes/prism-dark.css
new file mode 100644
index 0000000..f014552
--- /dev/null
+++ b/prism/themes/prism-dark.css
@@ -0,0 +1,111 @@
+/**
+ * prism.js Dark theme for JavaScript, CSS and HTML
+ * Based on the slides of the talk “/Reg(exp){2}lained/”
+ * @author Lea Verou
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+	color: white;
+	text-shadow: 0 -.1em .2em black;
+	font-family: Consolas, Monaco, 'Andale Mono', monospace;
+	direction: ltr;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+	
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+@media print {
+	code[class*="language-"],
+	pre[class*="language-"] {
+		text-shadow: none;
+	}
+}
+
+pre[class*="language-"],
+:not(pre) > code[class*="language-"] {
+	background: hsl(30,20%,25%);
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	padding: 1em;
+	margin: .5em 0;
+	overflow: auto;	
+	border: .3em solid hsl(30,20%,40%);
+	border-radius: .5em;
+	box-shadow: 1px 1px .5em black inset;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	padding: .15em .2em .05em;
+	border-radius: .3em;
+	border: .13em solid hsl(30,20%,40%);
+	box-shadow: 1px 1px .3em -.1em black inset;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: hsl(30,20%,50%);
+}
+
+.token.punctuation {
+	opacity: .7;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number {
+	color: hsl(350, 40%, 70%);
+}
+
+.token.selector,
+.token.attr-name,
+.token.string {
+	color: hsl(75, 70%, 60%);
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+	color: hsl(40, 90%, 60%);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+	color: hsl(350, 40%, 70%);
+}
+
+
+.token.regex,
+.token.important {
+	color: #e90;
+}
+
+.token.important {
+	font-weight: bold;
+}
+
+.token.entity {
+	cursor: help;
+}
\ No newline at end of file
diff --git a/prism/themes/prism-funky.css b/prism/themes/prism-funky.css
new file mode 100644
index 0000000..ba31709
--- /dev/null
+++ b/prism/themes/prism-funky.css
@@ -0,0 +1,100 @@
+/**
+ * prism.js Funky theme
+ * Based on “Polyfilling the gaps” talk slides http://lea.verou.me/polyfilling-the-gaps/
+ * @author Lea Verou
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+	font-family: Consolas, Monaco, 'Andale Mono', monospace;
+	direction: ltr;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+	
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	padding: .4em .8em;
+	margin: .5em 0;
+	overflow: auto;
+	background: url('data:image/svg+xml;charset=utf-8,%0D%0A%0D%0A%0D%0A<%2Fsvg>');
+	background-size: 1em 1em;
+}
+
+code[class*="language-"] {
+	background: black;
+	color: white;
+	box-shadow: -.3em 0 0 .3em black, .3em 0 0 .3em black;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	padding: .2em;
+	border-radius: .3em;
+	box-shadow: none;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: #aaa;
+}
+
+.token.punctuation {
+	color: #999;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number {
+	color: #0cf;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string {
+	color: yellow;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string {
+	color: yellowgreen;
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+	color: deeppink;
+}
+
+
+.token.regex,
+.token.important {
+	color: orange;
+}
+
+.token.important {
+	font-weight: bold;
+}
+
+.token.entity {
+	cursor: help;
+}
\ No newline at end of file
diff --git a/prism/themes/prism-okaidia.css b/prism/themes/prism-okaidia.css
new file mode 100644
index 0000000..3be83fc
--- /dev/null
+++ b/prism/themes/prism-okaidia.css
@@ -0,0 +1,108 @@
+/**
+ * okaidia theme for JavaScript, CSS and HTML
+ * Loosely based on Monokai textmate theme by http://www.monokai.nl/
+ * @author ocodia
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+	color: #f8f8f2;
+	text-shadow: 0 1px rgba(0,0,0,0.3);
+	font-family: Consolas, Monaco, 'Andale Mono', monospace;
+	direction: ltr;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+	
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	padding: 1em;
+	margin: .5em 0;
+	overflow: auto;	
+	border-radius: 0.3em;
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+	background: #272822;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	padding: .1em;
+	border-radius: .3em;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: slategray;
+}
+
+.token.punctuation {
+	color: #f8f8f2;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.property,
+.token.tag {
+	color: #f92672;
+}
+
+.token.boolean,
+.token.number{
+	color: #ae81ff;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string {
+	color: #a6e22e;
+}
+
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+	color: #f8f8f2;
+}
+
+.token.atrule,
+.token.attr-value
+{
+	color: #e6db74;
+}
+
+
+.token.keyword{
+color: #66d9ef;
+}
+
+.token.regex,
+.token.important {
+	color: #fd971f;
+}
+
+.token.important {
+	font-weight: bold;
+}
+
+.token.entity {
+	cursor: help;
+}
\ No newline at end of file
diff --git a/prism/themes/prism-tomorrow.css b/prism/themes/prism-tomorrow.css
new file mode 100644
index 0000000..0d6aad9
--- /dev/null
+++ b/prism/themes/prism-tomorrow.css
@@ -0,0 +1,107 @@
+/**
+ * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
+ * Based on https://github.com/chriskempson/tomorrow-theme
+ * @author Rose Pritchard
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+  color: #ccc;
+  font-family: Consolas, Monaco, 'Andale Mono', monospace;
+  direction: ltr;
+  text-align: left;
+  white-space: pre;
+  word-spacing: normal;
+
+  -moz-tab-size: 4;
+  -o-tab-size: 4;
+  tab-size: 4;
+
+  -webkit-hyphens: none;
+  -moz-hyphens: none;
+  -ms-hyphens: none;
+  hyphens: none;
+
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+  padding: 1em;
+  margin: .5em 0;
+  overflow: auto;
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+  background: #2d2d2d;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+  padding: .1em;
+  border-radius: .3em;
+}
+
+.token.comment,
+.token.block-comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+  color: #999;
+}
+
+.token.punctuation {
+  color: #ccc;
+}
+
+
+.token.tag,
+.token.attr-name,
+.token.namespace {
+  color: #e2777a;
+}
+
+.token.function-name {
+  color: #6196cc;
+}
+
+
+.token.boolean,
+.token.number,
+.token.function {
+  color: #f08d49;
+}
+
+.token.property,
+.token.class-name  {
+  color: #f8c555;
+}
+
+.token.selector,
+.token.important,
+.token.atrule,
+.token.keyword {
+  color: #cc99cd;
+}
+
+.token.string,
+.token.attr-value,
+.token.regex {
+  color: #7ec699;
+}
+
+.token.operator,
+.token.entity,
+.token.url
+{
+  color: #67cdcc;
+}
+
+
+.token.important {
+  font-weight: bold;
+}
+
+.token.entity {
+  cursor: help;
+}
diff --git a/prism/themes/prism-twilight.css b/prism/themes/prism-twilight.css
new file mode 100644
index 0000000..9128617
--- /dev/null
+++ b/prism/themes/prism-twilight.css
@@ -0,0 +1,172 @@
+/**
+ * prism.js Twilight theme
+ * Based (more or less) on the Twilight theme originally of Textmate fame.
+ * @author Remy Bach
+ */
+code[class*="language-"],
+pre[class*="language-"] {
+	color: white;
+	direction: ltr;
+	font-family: Consolas, Monaco, 'Andale Mono', monospace;
+	text-align: left;
+	text-shadow: 0 -.1em .2em black;
+	white-space: pre;
+	word-spacing: normal;
+	
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+	
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+pre[class*="language-"],
+:not(pre) > code[class*="language-"] {
+	background:hsl(0, 0%, 8%); /* #141414 */
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	border-radius: .5em;
+	border: .3em solid hsl(0,0%,33%); /* #282A2B */
+	box-shadow: 1px 1px .5em black inset;
+	margin: .5em 0;
+	overflow: auto;	
+	padding: 1em;
+}
+pre[class*="language-"]::selection { /* Safari */
+	background:hsl(200, 4%, 16%); /* #282A2B */
+}
+pre[class*="language-"]::selection { /* Firefox */
+	background:hsl(200, 4%, 16%); /* #282A2B */
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	border-radius: .3em;
+	border: .13em solid hsl(0,0%,33%); /* #545454 */
+	box-shadow: 1px 1px .3em -.1em black inset;
+	padding: .15em .2em .05em;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: hsl(0, 0%, 47%); /* #777777 */
+}
+
+.token.punctuation {
+	opacity: .7;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.tag,
+.token.boolean,
+.token.number {
+	color: hsl(14, 58%, 55%); /* #CF6A4C */
+}
+
+.token.keyword,
+.token.property,
+.token.selector {
+	color:hsl(53, 89%, 79%); /* #F9EE98 */
+}
+.token.attr-name,
+.token.attr-value,
+.token.string,
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+	color:hsl(76, 21%, 52%); /* #8F9D6A */
+}
+
+.token.atrule {
+	color:hsl(218, 22%, 55%); /* #7587A6 */
+}
+
+.token.regex,
+.token.important {
+	color: hsl(42, 75%, 65%); /* #E9C062 */
+}
+
+.token.important {
+	font-weight: bold;
+}
+
+.token.entity {
+	cursor: help;
+}
+pre[data-line] {
+	padding: 1em 0 1em 3em;
+	position: relative;
+}
+
+/* Markup */
+.language-markup .token.tag,
+.language-markup .token.attr-name,
+.language-markup .token.punctuation  {
+	color: hsl(33, 33%, 52%); /* #AC885B */
+}
+
+/* Text Selection colour */
+::selection {
+	background: hsla(0,0%,93%,0.15); /* #EDEDED */
+}
+::-moz-selection {
+	background: hsla(0,0%,93%,0.15); /* #EDEDED */
+}
+
+/* Make the tokens sit above the line highlight so the colours don't look faded. */
+.token {
+	position:relative;
+	z-index:1;
+}
+.line-highlight {
+	background: -moz-linear-gradient(left, hsl(0, 0%, 33%,.1) 70%, hsl(0, 0%, 33%,0)); /* #545454 */
+	background: -o-linear-gradient(left, hsl(0, 0%, 33%,.1) 70%, hsl(0, 0%, 33%,0)); /* #545454 */
+	background: -webkit-linear-gradient(left, hsl(0, 0%, 33%,.1) 70%, hsl(0, 0%, 33%,0)); /* #545454 */
+	background: hsla(0, 0%, 33%, 0.25); /* #545454 */
+	background: linear-gradient(left, hsl(0, 0%, 33%,.1) 70%, hsl(0, 0%, 33%,0)); /* #545454 */
+	border-bottom:1px dashed hsl(0, 0%, 33%); /* #545454 */
+	border-top:1px dashed hsl(0, 0%, 33%); /* #545454 */
+	left: 0;
+	line-height: inherit;
+	margin-top: 0.75em; /* Same as .prism’s padding-top */
+	padding: inherit 0;
+	pointer-events: none;
+	position: absolute;
+	right: 0;
+	white-space: pre;
+	z-index:0;
+}
+.line-highlight:before,
+.line-highlight[data-end]:after {
+	background-color: hsl(215, 15%, 59%); /* #8794A6 */
+	border-radius: 999px;
+	box-shadow: 0 1px white;
+	color: hsl(24, 20%, 95%); /* #F5F2F0 */
+	content: attr(data-start);
+	font: bold 65%/1.5 sans-serif;
+	left: .6em;
+	min-width: 1em;
+	padding: 0 .5em;
+	position: absolute;
+	text-align: center;
+	text-shadow: none;
+	top: .4em;
+	vertical-align: .3em;
+}
+.line-highlight[data-end]:after {
+	bottom: .4em;
+	content: attr(data-end);
+	top: auto;
+}
\ No newline at end of file