You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kafka.apache.org by gu...@apache.org on 2017/06/01 23:24:24 UTC

[1/3] kafka-site git commit: Add auto syntax highlighter

Repository: kafka-site
Updated Branches:
  refs/heads/asf-site 13d458201 -> c48d9d36a


http://git-wip-us.apache.org/repos/asf/kafka-site/blob/c48d9d36/styles.css
----------------------------------------------------------------------
diff --git a/styles.css b/styles.css
deleted file mode 100644
index b3b95cd..0000000
--- a/styles.css
+++ /dev/null
@@ -1,693 +0,0 @@
-/* globals */
-html, body {
-	height: 100%;
-}
-html {
-	font-size: 62.5%;
-}
-body {
-	display:flex;
-	flex-direction: column;
-	min-width: 32rem;
-	font-size: 1.4rem;
-	line-height: 1.6;
-	font-family: 'Roboto', sans-serif;
-	margin: 0;
-}
-code, pre {
-	font-family: 'Cutive Mono', monospace;
-}
-pre {
-	border-style: solid;
-	border-color: #E5E5E5;
-	border-width: .1rem .5rem;
-	overflow-x: scroll;
-	padding: 1rem 2rem 1.5rem;
-	color: #444444;
-	margin: 2rem 0;
-}
-code {
-	border: .1rem solid #E5E5E5;
-	margin: 0 .3rem;
-	padding: .2rem .4rem;
-}
-code b, pre b,
-h1, h2, h3, h4 {
-	line-height: 1.2;
-}
-h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
-	color: #000000;
-}
-h1 {
-	font-size: 5.6rem;
-	font-weight: 900;
-	margin: 0;
-}
-h2 {
-	text-transform: uppercase;
-	font-size: 2rem;
-	font-weight: 700;
-	margin: 0;
-}
-h3, h4 {
-	font-size: 2rem;
-	font-weight: 700;
-}
-h5 {
-	font-size: 1.6rem;
-}
-h3.bullet {
-	margin-bottom: 1rem;
-}
-h3.bullet::after {
-	content: "";
-	display: block;
-	background-color: #000000;
-	height: .2rem;
-	width: 5rem;
-}
-a {
-	color: #0B6D88;
-	text-decoration: none;
-}
-a:hover {
-	color: #0C637B;
-}
-img {
-	max-width: 100%;
-}
-.btn {
-	background-color: #0B6D88;
-	color: #FFFFFF;
-	border-radius: .2rem;
-	-moz-border-radius: .2rem;
-	-webkit-border-radius: .2rem;
-	text-align: center;
-	text-transform: capitalize;
-	padding: .9rem 2rem;
-}
-.btn--secondary {
-	color: #0B6D88;
-	border: .2rem solid #0B6D88;
-	background-color: transparent;
-}
-.btn--sm {
-	padding: .5rem 1rem;
-}
-.btn:hover {
-	background-color: #0C637B;
-	color: #FFFFFF;
-}
-ul {
-	padding-left: 2rem;
-	margin:1rem 0 1rem 0;
-}
-.toc {
-	padding: 0;
-	list-style: none;
-	text-transform: uppercase;
-	margin-bottom: 5rem;
-}
-.toc li {
-	margin-bottom: .5rem;
-}
-.toc > li {
-	margin-bottom: .6rem;
-}
-.toc a {
-	color: #000000;
-}
-.toc ul {
-	padding: .5rem 1.7rem 0;
-	text-transform: none;
-	font-weight: 400;
-	margin: 0 0 2rem;
-}
-.toc a:hover,
-.toc ul a {
-	color: #0B6D88;
-}
-.toc ul ul {
-	padding: 0 1.8rem;
-	margin-bottom: 0;
-}
-ol.toc {
-	list-style: decimal;
-	padding: 0 0 0 2rem;
-}
-ol.toc > li {
-	padding-left: .2rem;
-}
-.data-table {
-	display: block;
-  border: none;
-  border-collapse: collapse;
-  width: 100%;
-	overflow-x: scroll;
-	margin: 2rem 0;
-}
-.data-table tbody {
-	border-style: solid;
-	border-color: #E5E5E5;
-	border-width: 0 .5rem;
-}
-.data-table td, .data-table th {
-  border: .1rem solid #cccccc;
-  padding: .5rem 1rem;
-	min-width: 10rem;
-}
-.data-table th {
-	text-align: left;
-  background-color: #000000;
-	border: .1rem solid #222222;
-	color: #ffffff;
-	font-weight: 400;
-	padding: 1rem;
-	text-transform: uppercase;
-	overflow: hidden;
-}
-.data-table td {
-	/* These are technically the same, but use both */
-	overflow-wrap: break-word;
-	word-wrap: break-word;
-
-	-ms-word-break: break-all;
-	/* This is the dangerous one in WebKit, as it breaks things wherever */
-	word-break: break-all;
-	/* Instead use this non-standard one: */
-	word-break: break-word;
-
-	/* Adds a hyphen where the word breaks, if supported (No Blink) */
-	-ms-hyphens: auto;
-	-moz-hyphens: auto;
-	-webkit-hyphens: auto;
-	hyphens: auto;
-}
-
-/* helper classes */
-.centered {
-	display: block;
-	margin: auto;
-}
-.pb-10 {
-	display: inline-block;
-	padding-bottom: 1rem;
-}
-
-/* components */
-.main {
-	margin: 0 auto;
-	width: 120rem;
-	padding: 0 2rem 8rem 2rem;
-}
-.header {
-	padding: 2rem 0 1rem;
-	background-color: #FFFFFF;
-}
-.footer {
-	flex: 1;
-	position: relative;
-}
-.footer__inner {
-	position: absolute;
-	bottom: 0;
-	left: 0;
-	width: 100%;
-	border-top: .1rem solid #dedede;
-	font-size: .9rem;
-	line-height: 1.2rem;
-	color: #888888;
-	padding: 2rem 0;
-}
-.footer__legal {
-	margin: 0 2rem;
-}
-.footer__legal a {
-	color: #666666;
-}
-.sub-header {
-	overflow: hidden;
-	margin: 3rem 0 1rem;
-}
-.breadcrumbs {
-	list-style: none;
-    padding: 0;
-    text-transform: uppercase;
-	overflow: hidden;
-	margin-bottom: 0;
-}
-.breadcrumbs li {
-	display: flex;
-	align-items: center;
-}
-.breadcrumbs li::after {
-	content: '\00BB';
-    margin-left: .5rem;
-	height: 1rem;
-    line-height: .9rem;
-}
-.breadcrumbs a {
-	color: #000000;
-}
-.breadcrumbs a:hover {
-	color: #0B6D88;
-}
-.content {
-	margin-top: 3rem;
-}
-nav {
-	float: left;
-	text-transform: uppercase;
-	width: 16rem;
-}
-.nav__item,
-.nav__item__with__subs {
-	color: #000000;
-	border-right: 2px solid #000000;
-	display: block;
-	padding-top: 1.5rem;
-	position: relative;
-}
-.nav__item__with__subs {
-	padding-top: 0;
-}
-.nav__sub__anchor,
-.nav__sub__item {
-	border-right: none;
-}
-.nav__sub__item {
-	display: none;
-	color: #888888;
-	font-size: 1.2rem;
-	text-transform: capitalize;
-}
-.nav__item__with__subs--expanded .nav__sub__item {
-	display: block;
-}
-.nav__item:first-of-type {
-	padding-top: 0;
-}
-.nav__item__with__subs .nav__item:first-of-type {
-	padding-top: 1.5rem;
-}
-.nav__item::after {
-	content: "";
-	display: block;
-	height: 1.1rem;
-	width: 1.1rem;
-	border-radius: 1rem;
-	-moz-border-radius: 1rem;
-	-webkit-border-radius: 1rem;
-	border: 2px solid #000000;
-	background: #FFFFFF;
-	position: absolute;
-	right: -.9rem;
-	top: 1.7rem;
-	opacity: 0;
-	transition: opacity .2s ease-out;
-}
-.nav__item.selected::after {
-	opacity: 1;
-}
-.nav__item.selected:first-of-type::after {
-	top: .2rem;
-}
-.nav__item__with__subs .nav__item:first-of-type::after {
-	top: 1.7rem;
-}
-nav .btn {
-	display: block;
-	margin-top: 4rem;
-}
-.social-links {
-	margin: 2rem 0 3rem;
-	font-size: 1.2rem;
-}
-.twitter {
-	color: #888888;
-	text-transform: none;
-	background-image: url(/images/twitter_logo.png);
-	background-size: contain;
-	background-repeat: no-repeat;
-	padding-left: 1.9rem;
-}
-.twitter:hover {
-	color: #888888;
-	opacity: 0.8;
-}
-.right {
-	margin-left: 22rem;
-	min-height: 60rem;
-	overflow: hidden;
-}
-.apache-feather {
-	position: absolute;
-	bottom: 2rem;
-	right: 2rem;
-
-}
-.apache-feather:hover {
-	-webkit-animation-name: spin;
-  -webkit-animation-duration: 200ms;
-  -webkit-animation-iteration-count: infinite;
-  -webkit-animation-timing-function: linear;
-  -moz-animation-name: spin;
-  -moz-animation-duration: 200ms;
-  -moz-animation-iteration-count: infinite;
-  -moz-animation-timing-function: linear;
-  -ms-animation-name: spin;
-  -ms-animation-duration: 200ms;
-  -ms-animation-iteration-count: infinite;
-  -ms-animation-timing-function: linear;
-
-  animation-name: spin;
-  animation-duration: 200ms;
-  animation-iteration-count: infinite;
-  animation-timing-function: linear;
-}
-
-
-@-ms-keyframes spin {
-    from { -ms-transform: rotate(0deg); }
-    to { -ms-transform: rotate(360deg); }
-}
-@-moz-keyframes spin {
-    from { -moz-transform: rotate(0deg); }
-    to { -moz-transform: rotate(360deg); }
-}
-@-webkit-keyframes spin {
-    from { -webkit-transform: rotate(0deg); }
-    to { -webkit-transform: rotate(360deg); }
-}
-@keyframes spin {
-    from {
-        transform:rotate(0deg);
-    }
-    to {
-        transform:rotate(360deg);
-    }
-}
-
-/* pages */
-.index {
-	text-align: center;
-	padding-right: 25%;
-}
-.desc {
-	margin-left: 3rem;
-	margin-bottom: 6rem;
-	overflow: hidden;
-}
-.desc-item {
-	float: left;
-	width: 18rem;
-	margin-left: 4.2rem;
-}
-.desc-item:first-of-type {
-	width: 25rem;
-	margin-right: 1rem;
-	margin-left: 0;
-}
-.desc-item p {
-	margin: 0;
-	width: 18rem;
-}
-.desc-item p:before {
-	content: "";
-	border-top: 2px solid #000000;
-	display: block;
-	width: 5rem;
-	margin: .2rem 0 1rem;
-}
-.callout {
-	background-color: #F0F0F0;
-	padding: 1.5rem 2rem 3rem;
-	width: 33rem;
-	margin: 2rem auto 0;
-	position: relative;
-	text-align: center;
-}
-.callout--basic {
-	width: auto;
-}
-.callout::before {
-	content: "";
-	width: 0;
-	height: 0;
-	border-style: solid;
-	border-width: 8rem 0 0 5rem;
-	border-color: transparent transparent transparent #F0F0F0;
-	top: -6rem;
-	right: 10rem;
-	position: absolute;
-	-ms-transform: rotate(-10deg);
-  -webkit-transform: rotate(-10deg);
-  transform: rotate(-10deg);
-}
-.callout--basic::before {
-	display: none;
-}
-.callout__action {
-	display: inline-block;
-	width: 10rem;
-}
-
-.documentation__banner {
-	background-color: rgba(0,0,0,0.8);
-	color: #ffffff;
-	display: block;
-	padding: 1.5rem 2rem;
-	margin-bottom: 3rem
-}
-
-.documentation__banner:hover {
-	background-color: #888888;
-	color: #ffffff;
-	cursor: pointer;
-}
-
-.documentation--current .documentation__banner {
-	display: none;
-}
-
-.grid {
-	margin-top: 2rem;
-}
-
-.grid__item {
-  width: 20rem;
-  margin: .5rem;
-  border-radius: .4rem;
-  overflow: hidden;
-  border: 1px solid #888888;
-}
-
-.grid__item__link {
-	display: block;
-	height: 8rem;
-	margin-bottom: -.1rem;
-	text-align: center;
-	padding-top: 2rem;
-}
-
-.grid__item__link:hover {
-	opacity: .8;
-}
-
-.grid__item__logo {
-	margin: auto;
-	width: 16rem;
-	height: 6rem;
-	display: block;
-	background-size: contain;
-    background-repeat: no-repeat;
-    background-position: center center;
-}
-
-.grid__item__description {
-  margin: 0 2rem 2rem;
-  padding-top: 2rem;
-  border-top: 1px solid #888888;
-}
-
-
-
-/* Responsive styles */
-@media only screen and (max-width: 1240px) {
-	.main {
-		width: auto;
-		max-width: 100%;
-		margin: 0 2rem;
-	}
-	.footer__legal__one {
-		display:block;
-	}
-}
-
-@media only screen and (max-width: 1035px) {
-	.desc {
-		margin-left: 0;
-		margin-bottom: 2rem;
-	}
-  .desc-item,
-	.desc-item:first-of-type {
-		float: none;
-		width: auto;
-		margin-left: 0;
-		margin-bottom: 4rem;
-	}
-	.desc-item p {
-		width: auto;
-	}
-	.index {
-		padding-right: 0;
-		text-align: left;
-	}
-	.callout {
-		margin: 2rem 1.5rem;
-	}
-	.apache-feather {
-		bottom: 2.8rem;
-	}
-}
-
-@media only screen and (max-width: 800px) {
-	.desc-item,
-	.desc-item:first-of-type {
-		margin-bottom: 3rem;
-	}
-	.kafka-diagram {
-		width: 80%;
-		min-width: 28rem;
-		height: auto;
-	}
-	.callout {
-		width: 60%;
-		min-width: 21rem;
-	}
-	.callout::before {
-		right: 25%;
-	}
-	.footer__legal__two {
-		display:block;
-	}
-}
-
-@media only screen and (max-width: 650px) {
-	html, body {
-		overflow-y: auto;
-		-webkit-overflow-scrolling: touch;
-	}
-	.main {
-		padding: 0 1rem;
-		margin: 0;
-	}
-	.kafka-diagram {
-		display: block;
-		margin: 0 auto;
-	}
-	.callout {
-		margin: 2rem auto;
-	}
-	.right {
-		padding-bottom: 10rem;
-	}
-	.navindicator {
-		min-width: 32rem;
-		position: absolute;
-		top: -0.8rem;
-		left: 0;
-		width: 100%;
-		text-align: center;
-		z-index: 2;
-	}
-	.navindicator__item {
-		height: .2rem;
-		width: calc(79% / 12); /* Note: width of mobile nav indicator should be divided by number of top level pages */
-		background-color: #888888;
-		display: inline-block;
-		margin: 0 .5%;
-	}
-	.navindicator__item.selected {
-		background-color: #FFFFFF;
-	}
-	nav {
-		display: block;
-    position: fixed;
-    background-color: #000000;
-    bottom: 0;
-		left: 0;
-		z-index: 1;
-    width: 100%;
-	}
-	.nav-scroller {
-		white-space: nowrap;
-		overflow-y: hidden;
-		overflow-x: scroll;
-		-webkit-overflow-scrolling: touch;
-		box-shadow: 0 0 1rem rgba(0,0,0,0.3);
-	}
-	.nav__inner {
-		width: 2000px;
-	}
-	.nav__item,
-	.nav__item:first-of-type {
-		color: #888888;
-		float: left;
-		padding: 2.6rem 1.1rem 1.8rem;
-		border: none;
-	}
-	.nav__item.selected,
-	.nav__item:hover {
-		color: #FFFFFF;
-	}
-	.nav__item::after,
-	.nav__item.selected::after,
-	nav.hovering .nav__item:hover::after,
-	nav .btn,
-	.social-links,
-	.footer {
-		display: none;
-	}
-	.nav__item__with__subs .nav__item:first-of-type,
-	.nav__item .nav__item {
-		padding: 0;
-	}
-	.nav__sub__item {
-		margin-left: 2rem;
-		line-height: 2.2rem;
-	}
-	.right {
-		margin: 0;
-		min-height: auto;
-	}
-}
-
-@media only screen and (max-width: 460px) {
-	body {
-		font-size: 1.2rem;
-	}
-	h1 {
-		font-size: 3.6rem;
-	}
-	h2, h3, h4 {
-		font-size: 1.6rem;
-	}
-	.logo {
-		width: 21.667rem;
-		height: auto;
-	}
-	.desc-item,
-	.desc-item:first-of-type {
-		margin-bottom: 2rem;
-	}
-
-	.grid__item {
-		width: 96% !important;
-		position: relative !important;
-    	float: left !important;
-    	top: auto !important;
-    	left: auto !important;
-		margin-bottom: 2rem;
-	}
-}


[3/3] kafka-site git commit: Add auto syntax highlighter

Posted by gu...@apache.org.
Add auto syntax highlighter

Added plugin to do auto syntax highlighting for code snippets in our docs. (https://github.com/syntaxhighlighter/syntaxhighlighter/wiki)

Here's an example of how to syntax highlight some java code:
`<pre class="brush: java;">your code goes here</pre>`

Here's what this would look like:
![image](https://cloud.githubusercontent.com/assets/271961/26610631/a5e4341a-455d-11e7-9fe4-7e6bc801f8a9.png)

Author: Derrick Or <de...@gmail.com>

Reviewers: Guozhang Wang <wa...@gmail.com>

Closes #59 from derrickdoo/syntax-highlighting


Project: http://git-wip-us.apache.org/repos/asf/kafka-site/repo
Commit: http://git-wip-us.apache.org/repos/asf/kafka-site/commit/c48d9d36
Tree: http://git-wip-us.apache.org/repos/asf/kafka-site/tree/c48d9d36
Diff: http://git-wip-us.apache.org/repos/asf/kafka-site/diff/c48d9d36

Branch: refs/heads/asf-site
Commit: c48d9d36ae8bfdbe84197e04770cb143c8830987
Parents: 13d4582
Author: Derrick Or <de...@gmail.com>
Authored: Thu Jun 1 16:24:20 2017 -0700
Committer: Guozhang Wang <wa...@gmail.com>
Committed: Thu Jun 1 16:24:20 2017 -0700

----------------------------------------------------------------------
 css/styles.css              |  694 +++++
 css/syntax-highlighting.css |  270 ++
 includes/_footer.htm        |    1 +
 includes/_header.htm        |    3 +-
 js/syntaxhighlighter.js     | 5394 ++++++++++++++++++++++++++++++++++++++
 styles.css                  |  693 -----
 6 files changed, 6361 insertions(+), 694 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kafka-site/blob/c48d9d36/css/styles.css
----------------------------------------------------------------------
diff --git a/css/styles.css b/css/styles.css
new file mode 100644
index 0000000..2a78465
--- /dev/null
+++ b/css/styles.css
@@ -0,0 +1,694 @@
+/* globals */
+html, body {
+	height: 100%;
+}
+html {
+	font-size: 62.5%;
+}
+body {
+	display:flex;
+	flex-direction: column;
+	min-width: 32rem;
+	font-size: 1.4rem;
+	line-height: 1.8;
+	font-family: 'Roboto', sans-serif;
+	margin: 0;
+}
+code, pre {
+	font-family: Menlo, Consolas, monospace;
+}
+pre {
+	border-style: solid;
+	border-color: #E5E5E5;
+	border-width: .1rem .5rem;
+	overflow-x: scroll;
+	padding: 1rem 2rem 1.5rem;
+	color: #444444;
+	margin: 2rem 0;
+}
+code {
+	border: .1rem solid #E5E5E5;
+	margin: 0 .3rem;
+	padding: .2rem .4rem;
+	background-color: #F4F9F9;
+}
+code b, pre b,
+h1, h2, h3, h4 {
+	line-height: 1.2;
+}
+h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
+	color: #000000;
+}
+h1 {
+	font-size: 5.6rem;
+	font-weight: 900;
+	margin: 0;
+}
+h2 {
+	text-transform: uppercase;
+	font-size: 2rem;
+	font-weight: 700;
+	margin: 0;
+}
+h3, h4 {
+	font-size: 2rem;
+	font-weight: 700;
+}
+h5 {
+	font-size: 1.6rem;
+}
+h3.bullet {
+	margin-bottom: 1rem;
+}
+h3.bullet::after {
+	content: "";
+	display: block;
+	background-color: #000000;
+	height: .2rem;
+	width: 5rem;
+}
+a {
+	color: #0B6D88;
+	text-decoration: none;
+}
+a:hover {
+	color: #0C637B;
+}
+img {
+	max-width: 100%;
+}
+.btn {
+	background-color: #0B6D88;
+	color: #FFFFFF;
+	border-radius: .2rem;
+	-moz-border-radius: .2rem;
+	-webkit-border-radius: .2rem;
+	text-align: center;
+	text-transform: capitalize;
+	padding: .9rem 2rem;
+}
+.btn--secondary {
+	color: #0B6D88;
+	border: .2rem solid #0B6D88;
+	background-color: transparent;
+}
+.btn--sm {
+	padding: .5rem 1rem;
+}
+.btn:hover {
+	background-color: #0C637B;
+	color: #FFFFFF;
+}
+ul {
+	padding-left: 2rem;
+	margin:1rem 0 1rem 0;
+}
+.toc {
+	padding: 0;
+	list-style: none;
+	text-transform: uppercase;
+	margin-bottom: 5rem;
+}
+.toc li {
+	margin-bottom: .5rem;
+}
+.toc > li {
+	margin-bottom: .6rem;
+}
+.toc a {
+	color: #000000;
+}
+.toc ul {
+	padding: .5rem 1.7rem 0;
+	text-transform: none;
+	font-weight: 400;
+	margin: 0 0 2rem;
+}
+.toc a:hover,
+.toc ul a {
+	color: #0B6D88;
+}
+.toc ul ul {
+	padding: 0 1.8rem;
+	margin-bottom: 0;
+}
+ol.toc {
+	list-style: decimal;
+	padding: 0 0 0 2rem;
+}
+ol.toc > li {
+	padding-left: .2rem;
+}
+.data-table {
+	display: block;
+  border: none;
+  border-collapse: collapse;
+  width: 100%;
+	overflow-x: scroll;
+	margin: 2rem 0;
+}
+.data-table tbody {
+	border-style: solid;
+	border-color: #E5E5E5;
+	border-width: 0 .5rem;
+}
+.data-table td, .data-table th {
+  border: .1rem solid #cccccc;
+  padding: .5rem 1rem;
+	min-width: 10rem;
+}
+.data-table th {
+	text-align: left;
+  background-color: #000000;
+	border: .1rem solid #222222;
+	color: #ffffff;
+	font-weight: 400;
+	padding: 1rem;
+	text-transform: uppercase;
+	overflow: hidden;
+}
+.data-table td {
+	/* These are technically the same, but use both */
+	overflow-wrap: break-word;
+	word-wrap: break-word;
+
+	-ms-word-break: break-all;
+	/* This is the dangerous one in WebKit, as it breaks things wherever */
+	word-break: break-all;
+	/* Instead use this non-standard one: */
+	word-break: break-word;
+
+	/* Adds a hyphen where the word breaks, if supported (No Blink) */
+	-ms-hyphens: auto;
+	-moz-hyphens: auto;
+	-webkit-hyphens: auto;
+	hyphens: auto;
+}
+
+/* helper classes */
+.centered {
+	display: block;
+	margin: auto;
+}
+.pb-10 {
+	display: inline-block;
+	padding-bottom: 1rem;
+}
+
+/* components */
+.main {
+	margin: 0 auto;
+	width: 120rem;
+	padding: 0 2rem 8rem 2rem;
+}
+.header {
+	padding: 2rem 0 1rem;
+	background-color: #FFFFFF;
+}
+.footer {
+	flex: 1;
+	position: relative;
+}
+.footer__inner {
+	position: absolute;
+	bottom: 0;
+	left: 0;
+	width: 100%;
+	border-top: .1rem solid #dedede;
+	font-size: .9rem;
+	line-height: 1.2rem;
+	color: #888888;
+	padding: 2rem 0;
+}
+.footer__legal {
+	margin: 0 2rem;
+}
+.footer__legal a {
+	color: #666666;
+}
+.sub-header {
+	overflow: hidden;
+	margin: 3rem 0 1rem;
+}
+.breadcrumbs {
+	list-style: none;
+    padding: 0;
+    text-transform: uppercase;
+	overflow: hidden;
+	margin-bottom: 0;
+}
+.breadcrumbs li {
+	display: flex;
+	align-items: center;
+}
+.breadcrumbs li::after {
+	content: '\00BB';
+    margin-left: .5rem;
+	height: 1rem;
+    line-height: .9rem;
+}
+.breadcrumbs a {
+	color: #000000;
+}
+.breadcrumbs a:hover {
+	color: #0B6D88;
+}
+.content {
+	margin-top: 3rem;
+}
+nav {
+	float: left;
+	text-transform: uppercase;
+	width: 16rem;
+}
+.nav__item,
+.nav__item__with__subs {
+	color: #000000;
+	border-right: 2px solid #000000;
+	display: block;
+	padding-top: 1.5rem;
+	position: relative;
+}
+.nav__item__with__subs {
+	padding-top: 0;
+}
+.nav__sub__anchor,
+.nav__sub__item {
+	border-right: none;
+}
+.nav__sub__item {
+	display: none;
+	color: #888888;
+	font-size: 1.2rem;
+	text-transform: capitalize;
+}
+.nav__item__with__subs--expanded .nav__sub__item {
+	display: block;
+}
+.nav__item:first-of-type {
+	padding-top: 0;
+}
+.nav__item__with__subs .nav__item:first-of-type {
+	padding-top: 1.5rem;
+}
+.nav__item::after {
+	content: "";
+	display: block;
+	height: 1.1rem;
+	width: 1.1rem;
+	border-radius: 1rem;
+	-moz-border-radius: 1rem;
+	-webkit-border-radius: 1rem;
+	border: 2px solid #000000;
+	background: #FFFFFF;
+	position: absolute;
+	right: -.9rem;
+	top: 1.7rem;
+	opacity: 0;
+	transition: opacity .2s ease-out;
+}
+.nav__item.selected::after {
+	opacity: 1;
+}
+.nav__item.selected:first-of-type::after {
+	top: .2rem;
+}
+.nav__item__with__subs .nav__item:first-of-type::after {
+	top: 1.7rem;
+}
+nav .btn {
+	display: block;
+	margin-top: 4rem;
+}
+.social-links {
+	margin: 2rem 0 3rem;
+	font-size: 1.2rem;
+}
+.twitter {
+	color: #888888;
+	text-transform: none;
+	background-image: url(/images/twitter_logo.png);
+	background-size: contain;
+	background-repeat: no-repeat;
+	padding-left: 1.9rem;
+}
+.twitter:hover {
+	color: #888888;
+	opacity: 0.8;
+}
+.right {
+	margin-left: 22rem;
+	min-height: 60rem;
+	overflow: hidden;
+}
+.apache-feather {
+	position: absolute;
+	bottom: 2rem;
+	right: 2rem;
+
+}
+.apache-feather:hover {
+	-webkit-animation-name: spin;
+  -webkit-animation-duration: 200ms;
+  -webkit-animation-iteration-count: infinite;
+  -webkit-animation-timing-function: linear;
+  -moz-animation-name: spin;
+  -moz-animation-duration: 200ms;
+  -moz-animation-iteration-count: infinite;
+  -moz-animation-timing-function: linear;
+  -ms-animation-name: spin;
+  -ms-animation-duration: 200ms;
+  -ms-animation-iteration-count: infinite;
+  -ms-animation-timing-function: linear;
+
+  animation-name: spin;
+  animation-duration: 200ms;
+  animation-iteration-count: infinite;
+  animation-timing-function: linear;
+}
+
+
+@-ms-keyframes spin {
+    from { -ms-transform: rotate(0deg); }
+    to { -ms-transform: rotate(360deg); }
+}
+@-moz-keyframes spin {
+    from { -moz-transform: rotate(0deg); }
+    to { -moz-transform: rotate(360deg); }
+}
+@-webkit-keyframes spin {
+    from { -webkit-transform: rotate(0deg); }
+    to { -webkit-transform: rotate(360deg); }
+}
+@keyframes spin {
+    from {
+        transform:rotate(0deg);
+    }
+    to {
+        transform:rotate(360deg);
+    }
+}
+
+/* pages */
+.index {
+	text-align: center;
+	padding-right: 25%;
+}
+.desc {
+	margin-left: 3rem;
+	margin-bottom: 6rem;
+	overflow: hidden;
+}
+.desc-item {
+	float: left;
+	width: 18rem;
+	margin-left: 4.2rem;
+}
+.desc-item:first-of-type {
+	width: 25rem;
+	margin-right: 1rem;
+	margin-left: 0;
+}
+.desc-item p {
+	margin: 0;
+	width: 18rem;
+}
+.desc-item p:before {
+	content: "";
+	border-top: 2px solid #000000;
+	display: block;
+	width: 5rem;
+	margin: .2rem 0 1rem;
+}
+.callout {
+	background-color: #F0F0F0;
+	padding: 1.5rem 2rem 3rem;
+	width: 33rem;
+	margin: 2rem auto 0;
+	position: relative;
+	text-align: center;
+}
+.callout--basic {
+	width: auto;
+}
+.callout::before {
+	content: "";
+	width: 0;
+	height: 0;
+	border-style: solid;
+	border-width: 8rem 0 0 5rem;
+	border-color: transparent transparent transparent #F0F0F0;
+	top: -6rem;
+	right: 10rem;
+	position: absolute;
+	-ms-transform: rotate(-10deg);
+  -webkit-transform: rotate(-10deg);
+  transform: rotate(-10deg);
+}
+.callout--basic::before {
+	display: none;
+}
+.callout__action {
+	display: inline-block;
+	width: 10rem;
+}
+
+.documentation__banner {
+	background-color: rgba(0,0,0,0.8);
+	color: #ffffff;
+	display: block;
+	padding: 1.5rem 2rem;
+	margin-bottom: 3rem
+}
+
+.documentation__banner:hover {
+	background-color: #888888;
+	color: #ffffff;
+	cursor: pointer;
+}
+
+.documentation--current .documentation__banner {
+	display: none;
+}
+
+.grid {
+	margin-top: 2rem;
+}
+
+.grid__item {
+  width: 20rem;
+  margin: .5rem;
+  border-radius: .4rem;
+  overflow: hidden;
+  border: 1px solid #888888;
+}
+
+.grid__item__link {
+	display: block;
+	height: 8rem;
+	margin-bottom: -.1rem;
+	text-align: center;
+	padding-top: 2rem;
+}
+
+.grid__item__link:hover {
+	opacity: .8;
+}
+
+.grid__item__logo {
+	margin: auto;
+	width: 16rem;
+	height: 6rem;
+	display: block;
+	background-size: contain;
+    background-repeat: no-repeat;
+    background-position: center center;
+}
+
+.grid__item__description {
+  margin: 0 2rem 2rem;
+  padding-top: 2rem;
+  border-top: 1px solid #888888;
+}
+
+
+
+/* Responsive styles */
+@media only screen and (max-width: 1240px) {
+	.main {
+		width: auto;
+		max-width: 100%;
+		margin: 0 2rem;
+	}
+	.footer__legal__one {
+		display:block;
+	}
+}
+
+@media only screen and (max-width: 1035px) {
+	.desc {
+		margin-left: 0;
+		margin-bottom: 2rem;
+	}
+  .desc-item,
+	.desc-item:first-of-type {
+		float: none;
+		width: auto;
+		margin-left: 0;
+		margin-bottom: 4rem;
+	}
+	.desc-item p {
+		width: auto;
+	}
+	.index {
+		padding-right: 0;
+		text-align: left;
+	}
+	.callout {
+		margin: 2rem 1.5rem;
+	}
+	.apache-feather {
+		bottom: 2.8rem;
+	}
+}
+
+@media only screen and (max-width: 800px) {
+	.desc-item,
+	.desc-item:first-of-type {
+		margin-bottom: 3rem;
+	}
+	.kafka-diagram {
+		width: 80%;
+		min-width: 28rem;
+		height: auto;
+	}
+	.callout {
+		width: 60%;
+		min-width: 21rem;
+	}
+	.callout::before {
+		right: 25%;
+	}
+	.footer__legal__two {
+		display:block;
+	}
+}
+
+@media only screen and (max-width: 650px) {
+	html, body {
+		overflow-y: auto;
+		-webkit-overflow-scrolling: touch;
+	}
+	.main {
+		padding: 0 1rem;
+		margin: 0;
+	}
+	.kafka-diagram {
+		display: block;
+		margin: 0 auto;
+	}
+	.callout {
+		margin: 2rem auto;
+	}
+	.right {
+		padding-bottom: 10rem;
+	}
+	.navindicator {
+		min-width: 32rem;
+		position: absolute;
+		top: -0.8rem;
+		left: 0;
+		width: 100%;
+		text-align: center;
+		z-index: 2;
+	}
+	.navindicator__item {
+		height: .2rem;
+		width: calc(79% / 12); /* Note: width of mobile nav indicator should be divided by number of top level pages */
+		background-color: #888888;
+		display: inline-block;
+		margin: 0 .5%;
+	}
+	.navindicator__item.selected {
+		background-color: #FFFFFF;
+	}
+	nav {
+		display: block;
+    position: fixed;
+    background-color: #000000;
+    bottom: 0;
+		left: 0;
+		z-index: 1;
+    width: 100%;
+	}
+	.nav-scroller {
+		white-space: nowrap;
+		overflow-y: hidden;
+		overflow-x: scroll;
+		-webkit-overflow-scrolling: touch;
+		box-shadow: 0 0 1rem rgba(0,0,0,0.3);
+	}
+	.nav__inner {
+		width: 2000px;
+	}
+	.nav__item,
+	.nav__item:first-of-type {
+		color: #888888;
+		float: left;
+		padding: 2.6rem 1.1rem 1.8rem;
+		border: none;
+	}
+	.nav__item.selected,
+	.nav__item:hover {
+		color: #FFFFFF;
+	}
+	.nav__item::after,
+	.nav__item.selected::after,
+	nav.hovering .nav__item:hover::after,
+	nav .btn,
+	.social-links,
+	.footer {
+		display: none;
+	}
+	.nav__item__with__subs .nav__item:first-of-type,
+	.nav__item .nav__item {
+		padding: 0;
+	}
+	.nav__sub__item {
+		margin-left: 2rem;
+		line-height: 2.2rem;
+	}
+	.right {
+		margin: 0;
+		min-height: auto;
+	}
+}
+
+@media only screen and (max-width: 460px) {
+	body {
+		font-size: 1.2rem;
+	}
+	h1 {
+		font-size: 3.6rem;
+	}
+	h2, h3, h4 {
+		font-size: 1.6rem;
+	}
+	.logo {
+		width: 21.667rem;
+		height: auto;
+	}
+	.desc-item,
+	.desc-item:first-of-type {
+		margin-bottom: 2rem;
+	}
+
+	.grid__item {
+		width: 96% !important;
+		position: relative !important;
+    	float: left !important;
+    	top: auto !important;
+    	left: auto !important;
+		margin-bottom: 2rem;
+	}
+}

http://git-wip-us.apache.org/repos/asf/kafka-site/blob/c48d9d36/css/syntax-highlighting.css
----------------------------------------------------------------------
diff --git a/css/syntax-highlighting.css b/css/syntax-highlighting.css
new file mode 100644
index 0000000..d608c48
--- /dev/null
+++ b/css/syntax-highlighting.css
@@ -0,0 +1,270 @@
+/**
+ * Emulates Apple Swift documentation syntax highlighting
+ * Contributed by Nate Cook
+ * http://natecook.com
+ */
+.syntaxhighlighter a,
+.syntaxhighlighter div,
+.syntaxhighlighter code,
+.syntaxhighlighter table,
+.syntaxhighlighter table td,
+.syntaxhighlighter table tr,
+.syntaxhighlighter table tbody,
+.syntaxhighlighter table thead,
+.syntaxhighlighter table caption,
+.syntaxhighlighter textarea {
+  -moz-border-radius: 0 0 0 0 !important;
+  -webkit-border-radius: 0 0 0 0 !important;
+  background: none !important;
+  border: 0 !important;
+  bottom: auto !important;
+  float: none !important;
+  height: auto !important;
+  left: auto !important;
+  line-height: 1.1em !important;
+  margin: 0 !important;
+  outline: 0 !important;
+  overflow: visible !important;
+  padding: 0 !important;
+  position: static !important;
+  right: auto !important;
+  text-align: left !important;
+  top: auto !important;
+  vertical-align: baseline !important;
+  width: auto !important;
+  box-sizing: content-box !important;
+  font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
+  font-weight: normal !important;
+  font-style: normal !important;
+  font-size: 1.4rem !important;
+  min-height: inherit !important;
+  min-height: auto !important; }
+
+.syntaxhighlighter {
+  width: 100% !important;
+  margin: 1em 0 1em 0 !important;
+  position: relative !important;
+  overflow: auto !important;
+  font-size: 1em !important; }
+  .syntaxhighlighter .container:before, .syntaxhighlighter .container:after {
+    content: none !important; }
+  .syntaxhighlighter.source {
+    overflow: hidden !important; }
+  .syntaxhighlighter .bold {
+    font-weight: bold !important; }
+  .syntaxhighlighter .italic {
+    font-style: italic !important; }
+  .syntaxhighlighter .line {
+    white-space: pre !important; }
+  .syntaxhighlighter table {
+    width: 100% !important; }
+    .syntaxhighlighter table caption {
+      text-align: left !important;
+      padding: .5em 0 0.5em 1em !important; }
+    .syntaxhighlighter table td.code {
+      width: 100% !important; }
+      .syntaxhighlighter table td.code .container {
+        position: relative !important; }
+        .syntaxhighlighter table td.code .container textarea {
+          box-sizing: border-box !important;
+          position: absolute !important;
+          left: 0 !important;
+          top: 0 !important;
+          width: 100% !important;
+          height: 100% !important;
+          border: none !important;
+          background: white !important;
+          padding-left: 1em !important;
+          overflow: hidden !important;
+          white-space: pre !important; }
+    .syntaxhighlighter table td.gutter .line {
+      text-align: right !important;
+      padding: 0 0.5em 0 1em !important; }
+    .syntaxhighlighter table td.code .line {
+      padding: 0 1em !important; }
+  .syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line {
+    padding-left: 0em !important; }
+  .syntaxhighlighter.show {
+    display: block !important; }
+  .syntaxhighlighter.collapsed table {
+    display: none !important; }
+  .syntaxhighlighter.collapsed .toolbar {
+    padding: 0.1em 0.8em 0em 0.8em !important;
+    font-size: 1em !important;
+    position: static !important;
+    width: auto !important;
+    height: auto !important; }
+    .syntaxhighlighter.collapsed .toolbar span {
+      display: inline !important;
+      margin-right: 1em !important; }
+      .syntaxhighlighter.collapsed .toolbar span a {
+        padding: 0 !important;
+        display: none !important; }
+        .syntaxhighlighter.collapsed .toolbar span a.expandSource {
+          display: inline !important; }
+  .syntaxhighlighter .toolbar {
+    position: absolute !important;
+    right: 1px !important;
+    top: 1px !important;
+    width: 11px !important;
+    height: 11px !important;
+    font-size: 10px !important;
+    z-index: 10 !important; }
+    .syntaxhighlighter .toolbar span.title {
+      display: inline !important; }
+    .syntaxhighlighter .toolbar a {
+      display: block !important;
+      text-align: center !important;
+      text-decoration: none !important;
+      padding-top: 1px !important; }
+      .syntaxhighlighter .toolbar a.expandSource {
+        display: none !important; }
+  .syntaxhighlighter.ie {
+    font-size: .9em !important;
+    padding: 1px 0 1px 0 !important; }
+    .syntaxhighlighter.ie .toolbar {
+      line-height: 8px !important; }
+      .syntaxhighlighter.ie .toolbar a {
+        padding-top: 0px !important; }
+  .syntaxhighlighter.printing .line.alt1 .content,
+  .syntaxhighlighter.printing .line.alt2 .content,
+  .syntaxhighlighter.printing .line.highlighted .number,
+  .syntaxhighlighter.printing .line.highlighted.alt1 .content,
+  .syntaxhighlighter.printing .line.highlighted.alt2 .content {
+    background: none !important; }
+  .syntaxhighlighter.printing .line .number {
+    color: #bbbbbb !important; }
+  .syntaxhighlighter.printing .line .content {
+    color: black !important; }
+  .syntaxhighlighter.printing .toolbar {
+    display: none !important; }
+  .syntaxhighlighter.printing a {
+    text-decoration: none !important; }
+  .syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a {
+    color: black !important; }
+  .syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a {
+    color: #008200 !important; }
+  .syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a {
+    color: blue !important; }
+  .syntaxhighlighter.printing .keyword {
+    color: #006699 !important;
+    font-weight: bold !important; }
+  .syntaxhighlighter.printing .preprocessor {
+    color: gray !important; }
+  .syntaxhighlighter.printing .variable {
+    color: #aa7700 !important; }
+  .syntaxhighlighter.printing .value {
+    color: #009900 !important; }
+  .syntaxhighlighter.printing .functions {
+    color: #ff1493 !important; }
+  .syntaxhighlighter.printing .constants {
+    color: #0066cc !important; }
+  .syntaxhighlighter.printing .script {
+    font-weight: bold !important; }
+  .syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a {
+    color: gray !important; }
+  .syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a {
+    color: #ff1493 !important; }
+  .syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a {
+    color: red !important; }
+  .syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a {
+    color: black !important; }
+
+.syntaxhighlighter {
+  background-color: white !important; }
+  .syntaxhighlighter .line.alt1 {
+    background-color: white !important; }
+  .syntaxhighlighter .line.alt2 {
+    background-color: white !important; }
+  .syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
+    background-color: #e9e9e9 !important; }
+  .syntaxhighlighter .line.highlighted.number {
+    color: white !important; }
+  .syntaxhighlighter table caption {
+    color: #353535 !important; }
+  .syntaxhighlighter table td.code .container textarea {
+    background: white;
+    color: black; }
+  .syntaxhighlighter .gutter {
+    color: gray !important; }
+    .syntaxhighlighter .gutter .line {
+      border-right: none !important; }
+      .syntaxhighlighter .gutter .line.highlighted {
+        background-color: #6ce26c !important;
+        color: white !important; }
+  .syntaxhighlighter.printing .line .content {
+    border: none !important; }
+  .syntaxhighlighter.collapsed {
+    overflow: visible !important; }
+    .syntaxhighlighter.collapsed .toolbar {
+      color: #00f !important;
+      background: #fff !important;
+      border: 1px solid #6ce26c !important; }
+      .syntaxhighlighter.collapsed .toolbar a {
+        color: #00f !important; }
+        .syntaxhighlighter.collapsed .toolbar a:hover {
+          color: #f00 !important; }
+  .syntaxhighlighter .toolbar {
+    color: #fff !important;
+    background: #6ce26c !important;
+    border: none !important; }
+    .syntaxhighlighter .toolbar a {
+      color: #fff !important; }
+      .syntaxhighlighter .toolbar a:hover {
+        color: #000 !important; }
+  .syntaxhighlighter .plain, .syntaxhighlighter .plain a {
+    color: black !important; }
+  .syntaxhighlighter .comments, .syntaxhighlighter .comments a {
+    color: #008312 !important; }
+  .syntaxhighlighter .string, .syntaxhighlighter .string a {
+    color: #c41a16 !important; }
+  .syntaxhighlighter .keyword {
+    font-weight: bold !important;
+    color: #b833a1 !important; }
+  .syntaxhighlighter .preprocessor {
+    color: gray !important; }
+  .syntaxhighlighter .variable {
+    color: #508187 !important; }
+  .syntaxhighlighter .value {
+    color: #1c00cf !important; }
+  .syntaxhighlighter .functions {
+    color: #ff1493 !important; }
+  .syntaxhighlighter .constants {
+    color: #0066cc !important; }
+  .syntaxhighlighter .script {
+    font-weight: bold !important;
+    color: #b833a1 !important;
+    background-color: none !important; }
+  .syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
+    color: #b833a1 !important; }
+  .syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
+    color: #6f41a7 !important; }
+  .syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
+    color: red !important; }
+
+.syntaxhighlighter {
+  font-size: 0.75em !important; }
+  .syntaxhighlighter a,
+  .syntaxhighlighter div,
+  .syntaxhighlighter code,
+  .syntaxhighlighter table,
+  .syntaxhighlighter table td,
+  .syntaxhighlighter table tr,
+  .syntaxhighlighter table tbody,
+  .syntaxhighlighter table thead,
+  .syntaxhighlighter table caption,
+  .syntaxhighlighter textarea {
+    font-family: Menlo, Consolas, monospace !important; }
+  .syntaxhighlighter table td.gutter .line {
+    text-align: right !important;
+    padding: 0.2em 0.5em !important; }
+  .syntaxhighlighter table td.code .line {
+    padding: 0.2em 1em !important; }
+  .syntaxhighlighter table td.code .container textarea {
+    padding-top: 0.1em !important;
+    line-height: 1.48em !important; }
+  .syntaxhighlighter .gutter .line {
+    background: #f9f9f9 !important; }
+    .syntaxhighlighter .gutter .line.highlighted {
+      background-color: #898989 !important;
+      color: white !important; }

http://git-wip-us.apache.org/repos/asf/kafka-site/blob/c48d9d36/includes/_footer.htm
----------------------------------------------------------------------
diff --git a/includes/_footer.htm b/includes/_footer.htm
index 356a58a..f303623 100644
--- a/includes/_footer.htm
+++ b/includes/_footer.htm
@@ -15,6 +15,7 @@
 		</div>
 	</body>
 
+    <script type="text/javascript" src="/js/syntaxhighlighter.js"></script>
 	<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.js"></script>
 	<script>
 		$(function () {

http://git-wip-us.apache.org/repos/asf/kafka-site/blob/c48d9d36/includes/_header.htm
----------------------------------------------------------------------
diff --git a/includes/_header.htm b/includes/_header.htm
index a58bff7..0518356 100644
--- a/includes/_header.htm
+++ b/includes/_header.htm
@@ -2,7 +2,8 @@
 <html xmlns:og="http://ogp.me/ns#">
 	<head>
 		<title>Apache Kafka</title>
-		<link rel='stylesheet' href='/styles.css' type='text/css'>
+		<link rel='stylesheet' href='/css/styles.css' type='text/css'>
+		<link rel='stylesheet' href='/css/syntax-highlighting.css' type='text/css'>
 		<link rel="icon" type="image/gif" href="/images/apache_feather.gif">
 		<meta name="robots" content="index,follow" />
 		<meta name="language" content="en" />


[2/3] kafka-site git commit: Add auto syntax highlighter

Posted by gu...@apache.org.
http://git-wip-us.apache.org/repos/asf/kafka-site/blob/c48d9d36/js/syntaxhighlighter.js
----------------------------------------------------------------------
diff --git a/js/syntaxhighlighter.js b/js/syntaxhighlighter.js
new file mode 100644
index 0000000..38769dd
--- /dev/null
+++ b/js/syntaxhighlighter.js
@@ -0,0 +1,5394 @@
+/*!
+ * SyntaxHighlighter
+ * https://github.com/syntaxhighlighter/syntaxhighlighter
+ * 
+ * SyntaxHighlighter is donationware. If you are using it, please donate.
+ * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
+ * 
+ * @version
+ * 4.0.1 (Wed, 31 May 2017 00:06:41 GMT)
+ * 
+ * @copyright
+ * Copyright (C) 2004-2016 Alex Gorbatchev.
+ * 
+ * @license
+ * Dual licensed under the MIT and GPL licenses.
+ */
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+/******/
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	
+	var _core = __webpack_require__(1);
+	
+	Object.keys(_core).forEach(function (key) {
+	  if (key === "default" || key === "__esModule") return;
+	  Object.defineProperty(exports, key, {
+	    enumerable: true,
+	    get: function get() {
+	      return _core[key];
+	    }
+	  });
+	});
+	
+	var _domready = __webpack_require__(52);
+	
+	var _domready2 = _interopRequireDefault(_domready);
+	
+	var _core2 = _interopRequireDefault(_core);
+	
+	var _dasherize = __webpack_require__(53);
+	
+	var dasherize = _interopRequireWildcard(_dasherize);
+	
+	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+	
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+	
+	// configured through the `--compat` parameter.
+	if (false) {
+	  require('./compatibility_layer_v3');
+	}
+	
+	(0, _domready2.default)(function () {
+	  return _core2.default.highlight(dasherize.object(window.syntaxhighlighterConfig || {}));
+	});
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	var optsParser = __webpack_require__(2),
+	    match = __webpack_require__(5),
+	    Renderer = __webpack_require__(9).default,
+	    utils = __webpack_require__(10),
+	    transformers = __webpack_require__(11),
+	    dom = __webpack_require__(17),
+	    config = __webpack_require__(18),
+	    defaults = __webpack_require__(19),
+	    HtmlScript = __webpack_require__(20);
+	
+	var sh = {
+	  Match: match.Match,
+	  Highlighter: __webpack_require__(22),
+	
+	  config: __webpack_require__(18),
+	  regexLib: __webpack_require__(3).commonRegExp,
+	
+	  /** Internal 'global' variables. */
+	  vars: {
+	    discoveredBrushes: null,
+	    highlighters: {}
+	  },
+	
+	  /** This object is populated by user included external brush files. */
+	  brushes: {},
+	
+	  /**
+	   * Finds all elements on the page which should be processes by SyntaxHighlighter.
+	   *
+	   * @param {Object} globalParams   Optional parameters which override element's
+	   *                  parameters. Only used if element is specified.
+	   *
+	   * @param {Object} element  Optional element to highlight. If none is
+	   *              provided, all elements in the current document
+	   *              are returned which qualify.
+	   *
+	   * @return {Array}  Returns list of <code>{ target: DOMElement, params: Object }</code> objects.
+	   */
+	  findElements: function findElements(globalParams, element) {
+	    var elements = element ? [element] : utils.toArray(document.getElementsByTagName(sh.config.tagName)),
+	        conf = sh.config,
+	        result = [];
+	
+	    // support for <SCRIPT TYPE="syntaxhighlighter" /> feature
+	    elements = elements.concat(dom.getSyntaxHighlighterScriptTags());
+	
+	    if (elements.length === 0) return result;
+	
+	    for (var i = 0, l = elements.length; i < l; i++) {
+	      var item = {
+	        target: elements[i],
+	        // local params take precedence over globals
+	        params: optsParser.defaults(optsParser.parse(elements[i].className), globalParams)
+	      };
+	
+	      if (item.params['brush'] == null) continue;
+	
+	      result.push(item);
+	    }
+	
+	    return result;
+	  },
+	
+	  /**
+	   * Shorthand to highlight all elements on the page that are marked as
+	   * SyntaxHighlighter source code.
+	   *
+	   * @param {Object} globalParams   Optional parameters which override element's
+	   *                  parameters. Only used if element is specified.
+	   *
+	   * @param {Object} element  Optional element to highlight. If none is
+	   *              provided, all elements in the current document
+	   *              are highlighted.
+	   */
+	  highlight: function highlight(globalParams, element) {
+	    var elements = sh.findElements(globalParams, element),
+	        propertyName = 'innerHTML',
+	        brush = null,
+	        renderer,
+	        conf = sh.config;
+	
+	    if (elements.length === 0) return;
+	
+	    for (var i = 0, l = elements.length; i < l; i++) {
+	      var element = elements[i],
+	          target = element.target,
+	          params = element.params,
+	          brushName = params.brush,
+	          brush,
+	          matches,
+	          code;
+	
+	      if (brushName == null) continue;
+	
+	      brush = findBrush(brushName);
+	
+	      if (!brush) continue;
+	
+	      // local params take precedence over defaults
+	      params = optsParser.defaults(params || {}, defaults);
+	      params = optsParser.defaults(params, config);
+	
+	      // Instantiate a brush
+	      if (params['html-script'] == true || defaults['html-script'] == true) {
+	        brush = new HtmlScript(findBrush('xml'), brush);
+	        brushName = 'htmlscript';
+	      } else {
+	        brush = new brush();
+	      }
+	
+	      code = target[propertyName];
+	
+	      // remove CDATA from <SCRIPT/> tags if it's present
+	      if (conf.useScriptTags) code = stripCData(code);
+	
+	      // Inject title if the attribute is present
+	      if ((target.title || '') != '') params.title = target.title;
+	
+	      params['brush'] = brushName;
+	
+	      code = transformers(code, params);
+	      matches = match.applyRegexList(code, brush.regexList, params);
+	      renderer = new Renderer(code, matches, params);
+	
+	      element = dom.create('div');
+	      element.innerHTML = renderer.getHtml();
+	
+	      // id = utils.guid();
+	      // element.id = highlighters.id(id);
+	      // highlighters.set(id, element);
+	
+	      if (params.quickCode) dom.attachEvent(dom.findElement(element, '.code'), 'dblclick', dom.quickCodeHandler);
+	
+	      // carry over ID
+	      if ((target.id || '') != '') element.id = target.id;
+	
+	      target.parentNode.replaceChild(element, target);
+	    }
+	  }
+	}; // end of sh
+	
+	/**
+	 * Displays an alert.
+	 * @param {String} str String to display.
+	 */
+	function alert(str) {
+	  window.alert('SyntaxHighlighter\n\n' + str);
+	};
+	
+	/**
+	 * Finds a brush by its alias.
+	 *
+	 * @param {String} alias    Brush alias.
+	 * @param {Boolean} showAlert Suppresses the alert if false.
+	 * @return {Brush}        Returns bursh constructor if found, null otherwise.
+	 */
+	function findBrush(alias, showAlert) {
+	  var brushes = sh.vars.discoveredBrushes,
+	      result = null;
+	
+	  if (brushes == null) {
+	    brushes = {};
+	
+	    // Find all brushes
+	    for (var brushName in sh.brushes) {
+	      var brush = sh.brushes[brushName],
+	          aliases = brush.aliases;
+	
+	      if (aliases == null) {
+	        continue;
+	      }
+	
+	      brush.className = brush.className || brush.aliases[0];
+	      brush.brushName = brush.className || brushName.toLowerCase();
+	
+	      for (var i = 0, l = aliases.length; i < l; i++) {
+	        brushes[aliases[i]] = brushName;
+	      }
+	    }
+	
+	    sh.vars.discoveredBrushes = brushes;
+	  }
+	
+	  result = sh.brushes[brushes[alias]];
+	
+	  if (result == null && showAlert) alert(sh.config.strings.noBrush + alias);
+	
+	  return result;
+	};
+	
+	/**
+	 * Strips <![CDATA[]]> from <SCRIPT /> content because it should be used
+	 * there in most cases for XHTML compliance.
+	 * @param {String} original Input code.
+	 * @return {String} Returns code without leading <![CDATA[]]> tags.
+	 */
+	function stripCData(original) {
+	  var left = '<![CDATA[',
+	      right = ']]>',
+	
+	  // for some reason IE inserts some leading blanks here
+	  copy = utils.trim(original),
+	      changed = false,
+	      leftLength = left.length,
+	      rightLength = right.length;
+	
+	  if (copy.indexOf(left) == 0) {
+	    copy = copy.substring(leftLength);
+	    changed = true;
+	  }
+	
+	  var copyLength = copy.length;
+	
+	  if (copy.indexOf(right) == copyLength - rightLength) {
+	    copy = copy.substring(0, copyLength - rightLength);
+	    changed = true;
+	  }
+	
+	  return changed ? copy : original;
+	};
+	
+	var brushCounter = 0;
+	
+	exports.default = sh;
+	var registerBrush = exports.registerBrush = function registerBrush(brush) {
+	  return sh.brushes['brush' + brushCounter++] = brush.default || brush;
+	};
+	var clearRegisteredBrushes = exports.clearRegisteredBrushes = function clearRegisteredBrushes() {
+	  sh.brushes = {};
+	  brushCounter = 0;
+	};
+	
+	/* an EJS hook for `gulp build --brushes` command
+	 * */
+	
+	registerBrush(__webpack_require__(23));
+	
+	registerBrush(__webpack_require__(24));
+	
+	registerBrush(__webpack_require__(22));
+	
+	registerBrush(__webpack_require__(25));
+	
+	registerBrush(__webpack_require__(26));
+	
+	registerBrush(__webpack_require__(27));
+	
+	registerBrush(__webpack_require__(28));
+	
+	registerBrush(__webpack_require__(29));
+	
+	registerBrush(__webpack_require__(30));
+	
+	registerBrush(__webpack_require__(31));
+	
+	registerBrush(__webpack_require__(32));
+	
+	registerBrush(__webpack_require__(33));
+	
+	registerBrush(__webpack_require__(34));
+	
+	registerBrush(__webpack_require__(35));
+	
+	registerBrush(__webpack_require__(36));
+	
+	registerBrush(__webpack_require__(37));
+	
+	registerBrush(__webpack_require__(38));
+	
+	registerBrush(__webpack_require__(39));
+	
+	registerBrush(__webpack_require__(40));
+	
+	registerBrush(__webpack_require__(41));
+	
+	registerBrush(__webpack_require__(42));
+	
+	registerBrush(__webpack_require__(43));
+	
+	registerBrush(__webpack_require__(44));
+	
+	registerBrush(__webpack_require__(45));
+	
+	registerBrush(__webpack_require__(46));
+	
+	registerBrush(__webpack_require__(47));
+	
+	registerBrush(__webpack_require__(48));
+	
+	registerBrush(__webpack_require__(49));
+	
+	registerBrush(__webpack_require__(50));
+	
+	registerBrush(__webpack_require__(51));
+	
+	/*
+	
+	 */
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var XRegExp = __webpack_require__(3).XRegExp;
+	
+	var BOOLEANS = { 'true': true, 'false': false };
+	
+	function camelize(key) {
+	  return key.replace(/-(\w+)/g, function (match, word) {
+	    return word.charAt(0).toUpperCase() + word.substr(1);
+	  });
+	}
+	
+	function process(value) {
+	  var result = BOOLEANS[value];
+	  return result == null ? value : result;
+	}
+	
+	module.exports = {
+	  defaults: function defaults(target, source) {
+	    for (var key in source || {}) {
+	      if (!target.hasOwnProperty(key)) target[key] = target[camelize(key)] = source[key];
+	    }return target;
+	  },
+	
+	  parse: function parse(str) {
+	    var match,
+	        key,
+	        result = {},
+	        arrayRegex = XRegExp("^\\[(?<values>(.*?))\\]$"),
+	        pos = 0,
+	        regex = XRegExp("(?<name>[\\w-]+)" + "\\s*:\\s*" + "(?<value>" + "[\\w%#-]+|" + // word
+	    "\\[.*?\\]|" + // [] array
+	    '".*?"|' + // "" string
+	    "'.*?'" + // '' string
+	    ")\\s*;?", "g");
+	
+	    while ((match = XRegExp.exec(str, regex, pos)) != null) {
+	      var value = match.value.replace(/^['"]|['"]$/g, '') // strip quotes from end of strings
+	      ;
+	
+	      // try to parse array value
+	      if (value != null && arrayRegex.test(value)) {
+	        var m = XRegExp.exec(value, arrayRegex);
+	        value = m.values.length > 0 ? m.values.split(/\s*,\s*/) : [];
+	      }
+	
+	      value = process(value);
+	      result[match.name] = result[camelize(match.name)] = value;
+	      pos = match.index + match[0].length;
+	    }
+	
+	    return result;
+	  }
+	};
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	exports.commonRegExp = exports.XRegExp = undefined;
+	
+	var _xregexp = __webpack_require__(4);
+	
+	var _xregexp2 = _interopRequireDefault(_xregexp);
+	
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+	
+	exports.XRegExp = _xregexp2.default;
+	var commonRegExp = exports.commonRegExp = {
+	  multiLineCComments: (0, _xregexp2.default)('/\\*.*?\\*/', 'gs'),
+	  singleLineCComments: /\/\/.*$/gm,
+	  singleLinePerlComments: /#.*$/gm,
+	  doubleQuotedString: /"([^\\"\n]|\\.)*"/g,
+	  singleQuotedString: /'([^\\'\n]|\\.)*'/g,
+	  multiLineDoubleQuotedString: (0, _xregexp2.default)('"([^\\\\"]|\\\\.)*"', 'gs'),
+	  multiLineSingleQuotedString: (0, _xregexp2.default)("'([^\\\\']|\\\\.)*'", 'gs'),
+	  xmlComments: (0, _xregexp2.default)('(&lt;|<)!--.*?--(&gt;|>)', 'gs'),
+	  url: /\w+:\/\/[\w-.\/?%&=:@;#]*/g,
+	  phpScriptTags: { left: /(&lt;|<)\?(?:=|php)?/g, right: /\?(&gt;|>)/g, 'eof': true },
+	  aspScriptTags: { left: /(&lt;|<)%=?/g, right: /%(&gt;|>)/g },
+	  scriptScriptTags: { left: /(&lt;|<)\s*script.*?(&gt;|>)/gi, right: /(&lt;|<)\/\s*script\s*(&gt;|>)/gi }
+	};
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * XRegExp 3.1.0-dev
+	 * <xregexp.com>
+	 * Steven Levithan (c) 2007-2015 MIT License
+	 */
+	
+	/**
+	 * XRegExp provides augmented, extensible regular expressions. You get additional regex syntax and
+	 * flags, beyond what browsers support natively. XRegExp is also a regex utility belt with tools to
+	 * make your client-side grepping simpler and more powerful, while freeing you from related
+	 * cross-browser inconsistencies.
+	 */
+	
+	'use strict';
+	
+	/* ==============================
+	 * Private variables
+	 * ============================== */
+	
+	// Property name used for extended regex instance data
+	
+	var REGEX_DATA = 'xregexp';
+	// Optional features that can be installed and uninstalled
+	var features = {
+	    astral: false,
+	    natives: false
+	};
+	// Native methods to use and restore ('native' is an ES3 reserved keyword)
+	var nativ = {
+	    exec: RegExp.prototype.exec,
+	    test: RegExp.prototype.test,
+	    match: String.prototype.match,
+	    replace: String.prototype.replace,
+	    split: String.prototype.split
+	};
+	// Storage for fixed/extended native methods
+	var fixed = {};
+	// Storage for regexes cached by `XRegExp.cache`
+	var regexCache = {};
+	// Storage for pattern details cached by the `XRegExp` constructor
+	var patternCache = {};
+	// Storage for regex syntax tokens added internally or by `XRegExp.addToken`
+	var tokens = [];
+	// Token scopes
+	var defaultScope = 'default';
+	var classScope = 'class';
+	// Regexes that match native regex syntax, including octals
+	var nativeTokens = {
+	    // Any native multicharacter token in default scope, or any single character
+	    'default': /\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u(?:[\dA-Fa-f]{4}|{[\dA-Fa-f]+})|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??|[\s\S]/,
+	    // Any native multicharacter token in character class scope, or any single character
+	    'class': /\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u(?:[\dA-Fa-f]{4}|{[\dA-Fa-f]+})|c[A-Za-z]|[\s\S])|[\s\S]/
+	};
+	// Any backreference or dollar-prefixed character in replacement strings
+	var replacementToken = /\$(?:{([\w$]+)}|(\d\d?|[\s\S]))/g;
+	// Check for correct `exec` handling of nonparticipating capturing groups
+	var correctExecNpcg = nativ.exec.call(/()??/, '')[1] === undefined;
+	// Check for ES6 `u` flag support
+	var hasNativeU = function () {
+	    var isSupported = true;
+	    try {
+	        new RegExp('', 'u');
+	    } catch (exception) {
+	        isSupported = false;
+	    }
+	    return isSupported;
+	}();
+	// Check for ES6 `y` flag support
+	var hasNativeY = function () {
+	    var isSupported = true;
+	    try {
+	        new RegExp('', 'y');
+	    } catch (exception) {
+	        isSupported = false;
+	    }
+	    return isSupported;
+	}();
+	// Check for ES6 `flags` prop support
+	var hasFlagsProp = /a/.flags !== undefined;
+	// Tracker for known flags, including addon flags
+	var registeredFlags = {
+	    g: true,
+	    i: true,
+	    m: true,
+	    u: hasNativeU,
+	    y: hasNativeY
+	};
+	// Shortcut to `Object.prototype.toString`
+	var toString = {}.toString;
+	
+	/* ==============================
+	 * Private functions
+	 * ============================== */
+	
+	/**
+	 * Attaches extended data and `XRegExp.prototype` properties to a regex object.
+	 *
+	 * @private
+	 * @param {RegExp} regex Regex to augment.
+	 * @param {Array} captureNames Array with capture names, or `null`.
+	 * @param {String} xSource XRegExp pattern used to generate `regex`, or `null` if N/A.
+	 * @param {String} xFlags XRegExp flags used to generate `regex`, or `null` if N/A.
+	 * @param {Boolean} [isInternalOnly=false] Whether the regex will be used only for internal
+	 *   operations, and never exposed to users. For internal-only regexes, we can improve perf by
+	 *   skipping some operations like attaching `XRegExp.prototype` properties.
+	 * @returns {RegExp} Augmented regex.
+	 */
+	function augment(regex, captureNames, xSource, xFlags, isInternalOnly) {
+	    var p;
+	
+	    regex[REGEX_DATA] = {
+	        captureNames: captureNames
+	    };
+	
+	    if (isInternalOnly) {
+	        return regex;
+	    }
+	
+	    // Can't auto-inherit these since the XRegExp constructor returns a nonprimitive value
+	    if (regex.__proto__) {
+	        regex.__proto__ = XRegExp.prototype;
+	    } else {
+	        for (p in XRegExp.prototype) {
+	            // An `XRegExp.prototype.hasOwnProperty(p)` check wouldn't be worth it here, since
+	            // this is performance sensitive, and enumerable `Object.prototype` or
+	            // `RegExp.prototype` extensions exist on `regex.prototype` anyway
+	            regex[p] = XRegExp.prototype[p];
+	        }
+	    }
+	
+	    regex[REGEX_DATA].source = xSource;
+	    // Emulate the ES6 `flags` prop by ensuring flags are in alphabetical order
+	    regex[REGEX_DATA].flags = xFlags ? xFlags.split('').sort().join('') : xFlags;
+	
+	    return regex;
+	}
+	
+	/**
+	 * Removes any duplicate characters from the provided string.
+	 *
+	 * @private
+	 * @param {String} str String to remove duplicate characters from.
+	 * @returns {String} String with any duplicate characters removed.
+	 */
+	function clipDuplicates(str) {
+	    return nativ.replace.call(str, /([\s\S])(?=[\s\S]*\1)/g, '');
+	}
+	
+	/**
+	 * Copies a regex object while preserving extended data and augmenting with `XRegExp.prototype`
+	 * properties. The copy has a fresh `lastIndex` property (set to zero). Allows adding and removing
+	 * flags g and y while copying the regex.
+	 *
+	 * @private
+	 * @param {RegExp} regex Regex to copy.
+	 * @param {Object} [options] Options object with optional properties:
+	 *   <li>`addG` {Boolean} Add flag g while copying the regex.
+	 *   <li>`addY` {Boolean} Add flag y while copying the regex.
+	 *   <li>`removeG` {Boolean} Remove flag g while copying the regex.
+	 *   <li>`removeY` {Boolean} Remove flag y while copying the regex.
+	 *   <li>`isInternalOnly` {Boolean} Whether the copied regex will be used only for internal
+	 *     operations, and never exposed to users. For internal-only regexes, we can improve perf by
+	 *     skipping some operations like attaching `XRegExp.prototype` properties.
+	 * @returns {RegExp} Copy of the provided regex, possibly with modified flags.
+	 */
+	function copyRegex(regex, options) {
+	    if (!XRegExp.isRegExp(regex)) {
+	        throw new TypeError('Type RegExp expected');
+	    }
+	
+	    var xData = regex[REGEX_DATA] || {},
+	        flags = getNativeFlags(regex),
+	        flagsToAdd = '',
+	        flagsToRemove = '',
+	        xregexpSource = null,
+	        xregexpFlags = null;
+	
+	    options = options || {};
+	
+	    if (options.removeG) {
+	        flagsToRemove += 'g';
+	    }
+	    if (options.removeY) {
+	        flagsToRemove += 'y';
+	    }
+	    if (flagsToRemove) {
+	        flags = nativ.replace.call(flags, new RegExp('[' + flagsToRemove + ']+', 'g'), '');
+	    }
+	
+	    if (options.addG) {
+	        flagsToAdd += 'g';
+	    }
+	    if (options.addY) {
+	        flagsToAdd += 'y';
+	    }
+	    if (flagsToAdd) {
+	        flags = clipDuplicates(flags + flagsToAdd);
+	    }
+	
+	    if (!options.isInternalOnly) {
+	        if (xData.source !== undefined) {
+	            xregexpSource = xData.source;
+	        }
+	        // null or undefined; don't want to add to `flags` if the previous value was null, since
+	        // that indicates we're not tracking original precompilation flags
+	        if (xData.flags != null) {
+	            // Flags are only added for non-internal regexes by `XRegExp.globalize`. Flags are
+	            // never removed for non-internal regexes, so don't need to handle it
+	            xregexpFlags = flagsToAdd ? clipDuplicates(xData.flags + flagsToAdd) : xData.flags;
+	        }
+	    }
+	
+	    // Augment with `XRegExp.prototype` properties, but use the native `RegExp` constructor to
+	    // avoid searching for special tokens. That would be wrong for regexes constructed by
+	    // `RegExp`, and unnecessary for regexes constructed by `XRegExp` because the regex has
+	    // already undergone the translation to native regex syntax
+	    regex = augment(new RegExp(regex.source, flags), hasNamedCapture(regex) ? xData.captureNames.slice(0) : null, xregexpSource, xregexpFlags, options.isInternalOnly);
+	
+	    return regex;
+	}
+	
+	/**
+	 * Converts hexadecimal to decimal.
+	 *
+	 * @private
+	 * @param {String} hex
+	 * @returns {Number}
+	 */
+	function dec(hex) {
+	    return parseInt(hex, 16);
+	}
+	
+	/**
+	 * Returns native `RegExp` flags used by a regex object.
+	 *
+	 * @private
+	 * @param {RegExp} regex Regex to check.
+	 * @returns {String} Native flags in use.
+	 */
+	function getNativeFlags(regex) {
+	    return hasFlagsProp ? regex.flags :
+	    // Explicitly using `RegExp.prototype.toString` (rather than e.g. `String` or
+	    // concatenation with an empty string) allows this to continue working predictably when
+	    // `XRegExp.proptotype.toString` is overriden
+	    nativ.exec.call(/\/([a-z]*)$/i, RegExp.prototype.toString.call(regex))[1];
+	}
+	
+	/**
+	 * Determines whether a regex has extended instance data used to track capture names.
+	 *
+	 * @private
+	 * @param {RegExp} regex Regex to check.
+	 * @returns {Boolean} Whether the regex uses named capture.
+	 */
+	function hasNamedCapture(regex) {
+	    return !!(regex[REGEX_DATA] && regex[REGEX_DATA].captureNames);
+	}
+	
+	/**
+	 * Converts decimal to hexadecimal.
+	 *
+	 * @private
+	 * @param {Number|String} dec
+	 * @returns {String}
+	 */
+	function hex(dec) {
+	    return parseInt(dec, 10).toString(16);
+	}
+	
+	/**
+	 * Returns the first index at which a given value can be found in an array.
+	 *
+	 * @private
+	 * @param {Array} array Array to search.
+	 * @param {*} value Value to locate in the array.
+	 * @returns {Number} Zero-based index at which the item is found, or -1.
+	 */
+	function indexOf(array, value) {
+	    var len = array.length,
+	        i;
+	
+	    for (i = 0; i < len; ++i) {
+	        if (array[i] === value) {
+	            return i;
+	        }
+	    }
+	
+	    return -1;
+	}
+	
+	/**
+	 * Determines whether a value is of the specified type, by resolving its internal [[Class]].
+	 *
+	 * @private
+	 * @param {*} value Object to check.
+	 * @param {String} type Type to check for, in TitleCase.
+	 * @returns {Boolean} Whether the object matches the type.
+	 */
+	function isType(value, type) {
+	    return toString.call(value) === '[object ' + type + ']';
+	}
+	
+	/**
+	 * Checks whether the next nonignorable token after the specified position is a quantifier.
+	 *
+	 * @private
+	 * @param {String} pattern Pattern to search within.
+	 * @param {Number} pos Index in `pattern` to search at.
+	 * @param {String} flags Flags used by the pattern.
+	 * @returns {Boolean} Whether the next token is a quantifier.
+	 */
+	function isQuantifierNext(pattern, pos, flags) {
+	    return nativ.test.call(flags.indexOf('x') > -1 ?
+	    // Ignore any leading whitespace, line comments, and inline comments
+	    /^(?:\s+|#.*|\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/ :
+	    // Ignore any leading inline comments
+	    /^(?:\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/, pattern.slice(pos));
+	}
+	
+	/**
+	 * Pads the provided string with as many leading zeros as needed to get to length 4. Used to produce
+	 * fixed-length hexadecimal values.
+	 *
+	 * @private
+	 * @param {String} str
+	 * @returns {String}
+	 */
+	function pad4(str) {
+	    while (str.length < 4) {
+	        str = '0' + str;
+	    }
+	    return str;
+	}
+	
+	/**
+	 * Checks for flag-related errors, and strips/applies flags in a leading mode modifier. Offloads
+	 * the flag preparation logic from the `XRegExp` constructor.
+	 *
+	 * @private
+	 * @param {String} pattern Regex pattern, possibly with a leading mode modifier.
+	 * @param {String} flags Any combination of flags.
+	 * @returns {Object} Object with properties `pattern` and `flags`.
+	 */
+	function prepareFlags(pattern, flags) {
+	    var i;
+	
+	    // Recent browsers throw on duplicate flags, so copy this behavior for nonnative flags
+	    if (clipDuplicates(flags) !== flags) {
+	        throw new SyntaxError('Invalid duplicate regex flag ' + flags);
+	    }
+	
+	    // Strip and apply a leading mode modifier with any combination of flags except g or y
+	    pattern = nativ.replace.call(pattern, /^\(\?([\w$]+)\)/, function ($0, $1) {
+	        if (nativ.test.call(/[gy]/, $1)) {
+	            throw new SyntaxError('Cannot use flag g or y in mode modifier ' + $0);
+	        }
+	        // Allow duplicate flags within the mode modifier
+	        flags = clipDuplicates(flags + $1);
+	        return '';
+	    });
+	
+	    // Throw on unknown native or nonnative flags
+	    for (i = 0; i < flags.length; ++i) {
+	        if (!registeredFlags[flags.charAt(i)]) {
+	            throw new SyntaxError('Unknown regex flag ' + flags.charAt(i));
+	        }
+	    }
+	
+	    return {
+	        pattern: pattern,
+	        flags: flags
+	    };
+	}
+	
+	/**
+	 * Prepares an options object from the given value.
+	 *
+	 * @private
+	 * @param {String|Object} value Value to convert to an options object.
+	 * @returns {Object} Options object.
+	 */
+	function prepareOptions(value) {
+	    var options = {};
+	
+	    if (isType(value, 'String')) {
+	        XRegExp.forEach(value, /[^\s,]+/, function (match) {
+	            options[match] = true;
+	        });
+	
+	        return options;
+	    }
+	
+	    return value;
+	}
+	
+	/**
+	 * Registers a flag so it doesn't throw an 'unknown flag' error.
+	 *
+	 * @private
+	 * @param {String} flag Single-character flag to register.
+	 */
+	function registerFlag(flag) {
+	    if (!/^[\w$]$/.test(flag)) {
+	        throw new Error('Flag must be a single character A-Za-z0-9_$');
+	    }
+	
+	    registeredFlags[flag] = true;
+	}
+	
+	/**
+	 * Runs built-in and custom regex syntax tokens in reverse insertion order at the specified
+	 * position, until a match is found.
+	 *
+	 * @private
+	 * @param {String} pattern Original pattern from which an XRegExp object is being built.
+	 * @param {String} flags Flags being used to construct the regex.
+	 * @param {Number} pos Position to search for tokens within `pattern`.
+	 * @param {Number} scope Regex scope to apply: 'default' or 'class'.
+	 * @param {Object} context Context object to use for token handler functions.
+	 * @returns {Object} Object with properties `matchLength`, `output`, and `reparse`; or `null`.
+	 */
+	function runTokens(pattern, flags, pos, scope, context) {
+	    var i = tokens.length,
+	        leadChar = pattern.charAt(pos),
+	        result = null,
+	        match,
+	        t;
+	
+	    // Run in reverse insertion order
+	    while (i--) {
+	        t = tokens[i];
+	        if (t.leadChar && t.leadChar !== leadChar || t.scope !== scope && t.scope !== 'all' || t.flag && flags.indexOf(t.flag) === -1) {
+	            continue;
+	        }
+	
+	        match = XRegExp.exec(pattern, t.regex, pos, 'sticky');
+	        if (match) {
+	            result = {
+	                matchLength: match[0].length,
+	                output: t.handler.call(context, match, scope, flags),
+	                reparse: t.reparse
+	            };
+	            // Finished with token tests
+	            break;
+	        }
+	    }
+	
+	    return result;
+	}
+	
+	/**
+	 * Enables or disables implicit astral mode opt-in. When enabled, flag A is automatically added to
+	 * all new regexes created by XRegExp. This causes an error to be thrown when creating regexes if
+	 * the Unicode Base addon is not available, since flag A is registered by that addon.
+	 *
+	 * @private
+	 * @param {Boolean} on `true` to enable; `false` to disable.
+	 */
+	function setAstral(on) {
+	    features.astral = on;
+	}
+	
+	/**
+	 * Enables or disables native method overrides.
+	 *
+	 * @private
+	 * @param {Boolean} on `true` to enable; `false` to disable.
+	 */
+	function setNatives(on) {
+	    RegExp.prototype.exec = (on ? fixed : nativ).exec;
+	    RegExp.prototype.test = (on ? fixed : nativ).test;
+	    String.prototype.match = (on ? fixed : nativ).match;
+	    String.prototype.replace = (on ? fixed : nativ).replace;
+	    String.prototype.split = (on ? fixed : nativ).split;
+	
+	    features.natives = on;
+	}
+	
+	/**
+	 * Returns the object, or throws an error if it is `null` or `undefined`. This is used to follow
+	 * the ES5 abstract operation `ToObject`.
+	 *
+	 * @private
+	 * @param {*} value Object to check and return.
+	 * @returns {*} The provided object.
+	 */
+	function toObject(value) {
+	    // null or undefined
+	    if (value == null) {
+	        throw new TypeError('Cannot convert null or undefined to object');
+	    }
+	
+	    return value;
+	}
+	
+	/* ==============================
+	 * Constructor
+	 * ============================== */
+	
+	/**
+	 * Creates an extended regular expression object for matching text with a pattern. Differs from a
+	 * native regular expression in that additional syntax and flags are supported. The returned object
+	 * is in fact a native `RegExp` and works with all native methods.
+	 *
+	 * @class XRegExp
+	 * @constructor
+	 * @param {String|RegExp} pattern Regex pattern string, or an existing regex object to copy.
+	 * @param {String} [flags] Any combination of flags.
+	 *   Native flags:
+	 *     <li>`g` - global
+	 *     <li>`i` - ignore case
+	 *     <li>`m` - multiline anchors
+	 *     <li>`u` - unicode (ES6)
+	 *     <li>`y` - sticky (Firefox 3+, ES6)
+	 *   Additional XRegExp flags:
+	 *     <li>`n` - explicit capture
+	 *     <li>`s` - dot matches all (aka singleline)
+	 *     <li>`x` - free-spacing and line comments (aka extended)
+	 *     <li>`A` - astral (requires the Unicode Base addon)
+	 *   Flags cannot be provided when constructing one `RegExp` from another.
+	 * @returns {RegExp} Extended regular expression object.
+	 * @example
+	 *
+	 * // With named capture and flag x
+	 * XRegExp('(?<year>  [0-9]{4} ) -?  # year  \n\
+	 *          (?<month> [0-9]{2} ) -?  # month \n\
+	 *          (?<day>   [0-9]{2} )     # day   ', 'x');
+	 *
+	 * // Providing a regex object copies it. Native regexes are recompiled using native (not XRegExp)
+	 * // syntax. Copies maintain extended data, are augmented with `XRegExp.prototype` properties, and
+	 * // have fresh `lastIndex` properties (set to zero).
+	 * XRegExp(/regex/);
+	 */
+	function XRegExp(pattern, flags) {
+	    var context = {
+	        hasNamedCapture: false,
+	        captureNames: []
+	    },
+	        scope = defaultScope,
+	        output = '',
+	        pos = 0,
+	        result,
+	        token,
+	        generated,
+	        appliedPattern,
+	        appliedFlags;
+	
+	    if (XRegExp.isRegExp(pattern)) {
+	        if (flags !== undefined) {
+	            throw new TypeError('Cannot supply flags when copying a RegExp');
+	        }
+	        return copyRegex(pattern);
+	    }
+	
+	    // Copy the argument behavior of `RegExp`
+	    pattern = pattern === undefined ? '' : String(pattern);
+	    flags = flags === undefined ? '' : String(flags);
+	
+	    if (XRegExp.isInstalled('astral') && flags.indexOf('A') === -1) {
+	        // This causes an error to be thrown if the Unicode Base addon is not available
+	        flags += 'A';
+	    }
+	
+	    if (!patternCache[pattern]) {
+	        patternCache[pattern] = {};
+	    }
+	
+	    if (!patternCache[pattern][flags]) {
+	        // Check for flag-related errors, and strip/apply flags in a leading mode modifier
+	        result = prepareFlags(pattern, flags);
+	        appliedPattern = result.pattern;
+	        appliedFlags = result.flags;
+	
+	        // Use XRegExp's tokens to translate the pattern to a native regex pattern.
+	        // `appliedPattern.length` may change on each iteration if tokens use `reparse`
+	        while (pos < appliedPattern.length) {
+	            do {
+	                // Check for custom tokens at the current position
+	                result = runTokens(appliedPattern, appliedFlags, pos, scope, context);
+	                // If the matched token used the `reparse` option, splice its output into the
+	                // pattern before running tokens again at the same position
+	                if (result && result.reparse) {
+	                    appliedPattern = appliedPattern.slice(0, pos) + result.output + appliedPattern.slice(pos + result.matchLength);
+	                }
+	            } while (result && result.reparse);
+	
+	            if (result) {
+	                output += result.output;
+	                pos += result.matchLength || 1;
+	            } else {
+	                // Get the native token at the current position
+	                token = XRegExp.exec(appliedPattern, nativeTokens[scope], pos, 'sticky')[0];
+	                output += token;
+	                pos += token.length;
+	                if (token === '[' && scope === defaultScope) {
+	                    scope = classScope;
+	                } else if (token === ']' && scope === classScope) {
+	                    scope = defaultScope;
+	                }
+	            }
+	        }
+	
+	        patternCache[pattern][flags] = {
+	            // Cleanup token cruft: repeated `(?:)(?:)` and leading/trailing `(?:)`
+	            pattern: nativ.replace.call(output, /\(\?:\)(?:[*+?]|\{\d+(?:,\d*)?})?\??(?=\(\?:\))|^\(\?:\)(?:[*+?]|\{\d+(?:,\d*)?})?\??|\(\?:\)(?:[*+?]|\{\d+(?:,\d*)?})?\??$/g, ''),
+	            // Strip all but native flags
+	            flags: nativ.replace.call(appliedFlags, /[^gimuy]+/g, ''),
+	            // `context.captureNames` has an item for each capturing group, even if unnamed
+	            captures: context.hasNamedCapture ? context.captureNames : null
+	        };
+	    }
+	
+	    generated = patternCache[pattern][flags];
+	    return augment(new RegExp(generated.pattern, generated.flags), generated.captures, pattern, flags);
+	};
+	
+	// Add `RegExp.prototype` to the prototype chain
+	XRegExp.prototype = new RegExp();
+	
+	/* ==============================
+	 * Public properties
+	 * ============================== */
+	
+	/**
+	 * The XRegExp version number as a string containing three dot-separated parts. For example,
+	 * '2.0.0-beta-3'.
+	 *
+	 * @static
+	 * @memberOf XRegExp
+	 * @type String
+	 */
+	XRegExp.version = '3.1.0-dev';
+	
+	/* ==============================
+	 * Public methods
+	 * ============================== */
+	
+	/**
+	 * Extends XRegExp syntax and allows custom flags. This is used internally and can be used to
+	 * create XRegExp addons. If more than one token can match the same string, the last added wins.
+	 *
+	 * @memberOf XRegExp
+	 * @param {RegExp} regex Regex object that matches the new token.
+	 * @param {Function} handler Function that returns a new pattern string (using native regex syntax)
+	 *   to replace the matched token within all future XRegExp regexes. Has access to persistent
+	 *   properties of the regex being built, through `this`. Invoked with three arguments:
+	 *   <li>The match array, with named backreference properties.
+	 *   <li>The regex scope where the match was found: 'default' or 'class'.
+	 *   <li>The flags used by the regex, including any flags in a leading mode modifier.
+	 *   The handler function becomes part of the XRegExp construction process, so be careful not to
+	 *   construct XRegExps within the function or you will trigger infinite recursion.
+	 * @param {Object} [options] Options object with optional properties:
+	 *   <li>`scope` {String} Scope where the token applies: 'default', 'class', or 'all'.
+	 *   <li>`flag` {String} Single-character flag that triggers the token. This also registers the
+	 *     flag, which prevents XRegExp from throwing an 'unknown flag' error when the flag is used.
+	 *   <li>`optionalFlags` {String} Any custom flags checked for within the token `handler` that are
+	 *     not required to trigger the token. This registers the flags, to prevent XRegExp from
+	 *     throwing an 'unknown flag' error when any of the flags are used.
+	 *   <li>`reparse` {Boolean} Whether the `handler` function's output should not be treated as
+	 *     final, and instead be reparseable by other tokens (including the current token). Allows
+	 *     token chaining or deferring.
+	 *   <li>`leadChar` {String} Single character that occurs at the beginning of any successful match
+	 *     of the token (not always applicable). This doesn't change the behavior of the token unless
+	 *     you provide an erroneous value. However, providing it can increase the token's performance
+	 *     since the token can be skipped at any positions where this character doesn't appear.
+	 * @example
+	 *
+	 * // Basic usage: Add \a for the ALERT control code
+	 * XRegExp.addToken(
+	 *   /\\a/,
+	 *   function() {return '\\x07';},
+	 *   {scope: 'all'}
+	 * );
+	 * XRegExp('\\a[\\a-\\n]+').test('\x07\n\x07'); // -> true
+	 *
+	 * // Add the U (ungreedy) flag from PCRE and RE2, which reverses greedy and lazy quantifiers.
+	 * // Since `scope` is not specified, it uses 'default' (i.e., transformations apply outside of
+	 * // character classes only)
+	 * XRegExp.addToken(
+	 *   /([?*+]|{\d+(?:,\d*)?})(\??)/,
+	 *   function(match) {return match[1] + (match[2] ? '' : '?');},
+	 *   {flag: 'U'}
+	 * );
+	 * XRegExp('a+', 'U').exec('aaa')[0]; // -> 'a'
+	 * XRegExp('a+?', 'U').exec('aaa')[0]; // -> 'aaa'
+	 */
+	XRegExp.addToken = function (regex, handler, options) {
+	    options = options || {};
+	    var optionalFlags = options.optionalFlags,
+	        i;
+	
+	    if (options.flag) {
+	        registerFlag(options.flag);
+	    }
+	
+	    if (optionalFlags) {
+	        optionalFlags = nativ.split.call(optionalFlags, '');
+	        for (i = 0; i < optionalFlags.length; ++i) {
+	            registerFlag(optionalFlags[i]);
+	        }
+	    }
+	
+	    // Add to the private list of syntax tokens
+	    tokens.push({
+	        regex: copyRegex(regex, {
+	            addG: true,
+	            addY: hasNativeY,
+	            isInternalOnly: true
+	        }),
+	        handler: handler,
+	        scope: options.scope || defaultScope,
+	        flag: options.flag,
+	        reparse: options.reparse,
+	        leadChar: options.leadChar
+	    });
+	
+	    // Reset the pattern cache used by the `XRegExp` constructor, since the same pattern and
+	    // flags might now produce different results
+	    XRegExp.cache.flush('patterns');
+	};
+	
+	/**
+	 * Caches and returns the result of calling `XRegExp(pattern, flags)`. On any subsequent call with
+	 * the same pattern and flag combination, the cached copy of the regex is returned.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} pattern Regex pattern string.
+	 * @param {String} [flags] Any combination of XRegExp flags.
+	 * @returns {RegExp} Cached XRegExp object.
+	 * @example
+	 *
+	 * while (match = XRegExp.cache('.', 'gs').exec(str)) {
+	 *   // The regex is compiled once only
+	 * }
+	 */
+	XRegExp.cache = function (pattern, flags) {
+	    if (!regexCache[pattern]) {
+	        regexCache[pattern] = {};
+	    }
+	    return regexCache[pattern][flags] || (regexCache[pattern][flags] = XRegExp(pattern, flags));
+	};
+	
+	// Intentionally undocumented
+	XRegExp.cache.flush = function (cacheName) {
+	    if (cacheName === 'patterns') {
+	        // Flush the pattern cache used by the `XRegExp` constructor
+	        patternCache = {};
+	    } else {
+	        // Flush the regex cache populated by `XRegExp.cache`
+	        regexCache = {};
+	    }
+	};
+	
+	/**
+	 * Escapes any regular expression metacharacters, for use when matching literal strings. The result
+	 * can safely be used at any point within a regex that uses any flags.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to escape.
+	 * @returns {String} String with regex metacharacters escaped.
+	 * @example
+	 *
+	 * XRegExp.escape('Escaped? <.>');
+	 * // -> 'Escaped\?\ <\.>'
+	 */
+	XRegExp.escape = function (str) {
+	    return nativ.replace.call(toObject(str), /[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
+	};
+	
+	/**
+	 * Executes a regex search in a specified string. Returns a match array or `null`. If the provided
+	 * regex uses named capture, named backreference properties are included on the match array.
+	 * Optional `pos` and `sticky` arguments specify the search start position, and whether the match
+	 * must start at the specified position only. The `lastIndex` property of the provided regex is not
+	 * used, but is updated for compatibility. Also fixes browser bugs compared to the native
+	 * `RegExp.prototype.exec` and can be used reliably cross-browser.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {RegExp} regex Regex to search with.
+	 * @param {Number} [pos=0] Zero-based index at which to start the search.
+	 * @param {Boolean|String} [sticky=false] Whether the match must start at the specified position
+	 *   only. The string `'sticky'` is accepted as an alternative to `true`.
+	 * @returns {Array} Match array with named backreference properties, or `null`.
+	 * @example
+	 *
+	 * // Basic use, with named backreference
+	 * var match = XRegExp.exec('U+2620', XRegExp('U\\+(?<hex>[0-9A-F]{4})'));
+	 * match.hex; // -> '2620'
+	 *
+	 * // With pos and sticky, in a loop
+	 * var pos = 2, result = [], match;
+	 * while (match = XRegExp.exec('<1><2><3><4>5<6>', /<(\d)>/, pos, 'sticky')) {
+	 *   result.push(match[1]);
+	 *   pos = match.index + match[0].length;
+	 * }
+	 * // result -> ['2', '3', '4']
+	 */
+	XRegExp.exec = function (str, regex, pos, sticky) {
+	    var cacheKey = 'g',
+	        addY = false,
+	        match,
+	        r2;
+	
+	    addY = hasNativeY && !!(sticky || regex.sticky && sticky !== false);
+	    if (addY) {
+	        cacheKey += 'y';
+	    }
+	
+	    regex[REGEX_DATA] = regex[REGEX_DATA] || {};
+	
+	    // Shares cached copies with `XRegExp.match`/`replace`
+	    r2 = regex[REGEX_DATA][cacheKey] || (regex[REGEX_DATA][cacheKey] = copyRegex(regex, {
+	        addG: true,
+	        addY: addY,
+	        removeY: sticky === false,
+	        isInternalOnly: true
+	    }));
+	
+	    r2.lastIndex = pos = pos || 0;
+	
+	    // Fixed `exec` required for `lastIndex` fix, named backreferences, etc.
+	    match = fixed.exec.call(r2, str);
+	
+	    if (sticky && match && match.index !== pos) {
+	        match = null;
+	    }
+	
+	    if (regex.global) {
+	        regex.lastIndex = match ? r2.lastIndex : 0;
+	    }
+	
+	    return match;
+	};
+	
+	/**
+	 * Executes a provided function once per regex match. Searches always start at the beginning of the
+	 * string and continue until the end, regardless of the state of the regex's `global` property and
+	 * initial `lastIndex`.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {RegExp} regex Regex to search with.
+	 * @param {Function} callback Function to execute for each match. Invoked with four arguments:
+	 *   <li>The match array, with named backreference properties.
+	 *   <li>The zero-based match index.
+	 *   <li>The string being traversed.
+	 *   <li>The regex object being used to traverse the string.
+	 * @example
+	 *
+	 * // Extracts every other digit from a string
+	 * var evens = [];
+	 * XRegExp.forEach('1a2345', /\d/, function(match, i) {
+	 *   if (i % 2) evens.push(+match[0]);
+	 * });
+	 * // evens -> [2, 4]
+	 */
+	XRegExp.forEach = function (str, regex, callback) {
+	    var pos = 0,
+	        i = -1,
+	        match;
+	
+	    while (match = XRegExp.exec(str, regex, pos)) {
+	        // Because `regex` is provided to `callback`, the function could use the deprecated/
+	        // nonstandard `RegExp.prototype.compile` to mutate the regex. However, since
+	        // `XRegExp.exec` doesn't use `lastIndex` to set the search position, this can't lead
+	        // to an infinite loop, at least. Actually, because of the way `XRegExp.exec` caches
+	        // globalized versions of regexes, mutating the regex will not have any effect on the
+	        // iteration or matched strings, which is a nice side effect that brings extra safety
+	        callback(match, ++i, str, regex);
+	
+	        pos = match.index + (match[0].length || 1);
+	    }
+	};
+	
+	/**
+	 * Copies a regex object and adds flag `g`. The copy maintains extended data, is augmented with
+	 * `XRegExp.prototype` properties, and has a fresh `lastIndex` property (set to zero). Native
+	 * regexes are not recompiled using XRegExp syntax.
+	 *
+	 * @memberOf XRegExp
+	 * @param {RegExp} regex Regex to globalize.
+	 * @returns {RegExp} Copy of the provided regex with flag `g` added.
+	 * @example
+	 *
+	 * var globalCopy = XRegExp.globalize(/regex/);
+	 * globalCopy.global; // -> true
+	 */
+	XRegExp.globalize = function (regex) {
+	    return copyRegex(regex, { addG: true });
+	};
+	
+	/**
+	 * Installs optional features according to the specified options. Can be undone using
+	 * {@link #XRegExp.uninstall}.
+	 *
+	 * @memberOf XRegExp
+	 * @param {Object|String} options Options object or string.
+	 * @example
+	 *
+	 * // With an options object
+	 * XRegExp.install({
+	 *   // Enables support for astral code points in Unicode addons (implicitly sets flag A)
+	 *   astral: true,
+	 *
+	 *   // Overrides native regex methods with fixed/extended versions that support named
+	 *   // backreferences and fix numerous cross-browser bugs
+	 *   natives: true
+	 * });
+	 *
+	 * // With an options string
+	 * XRegExp.install('astral natives');
+	 */
+	XRegExp.install = function (options) {
+	    options = prepareOptions(options);
+	
+	    if (!features.astral && options.astral) {
+	        setAstral(true);
+	    }
+	
+	    if (!features.natives && options.natives) {
+	        setNatives(true);
+	    }
+	};
+	
+	/**
+	 * Checks whether an individual optional feature is installed.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} feature Name of the feature to check. One of:
+	 *   <li>`natives`
+	 *   <li>`astral`
+	 * @returns {Boolean} Whether the feature is installed.
+	 * @example
+	 *
+	 * XRegExp.isInstalled('natives');
+	 */
+	XRegExp.isInstalled = function (feature) {
+	    return !!features[feature];
+	};
+	
+	/**
+	 * Returns `true` if an object is a regex; `false` if it isn't. This works correctly for regexes
+	 * created in another frame, when `instanceof` and `constructor` checks would fail.
+	 *
+	 * @memberOf XRegExp
+	 * @param {*} value Object to check.
+	 * @returns {Boolean} Whether the object is a `RegExp` object.
+	 * @example
+	 *
+	 * XRegExp.isRegExp('string'); // -> false
+	 * XRegExp.isRegExp(/regex/i); // -> true
+	 * XRegExp.isRegExp(RegExp('^', 'm')); // -> true
+	 * XRegExp.isRegExp(XRegExp('(?s).')); // -> true
+	 */
+	XRegExp.isRegExp = function (value) {
+	    return toString.call(value) === '[object RegExp]';
+	    //return isType(value, 'RegExp');
+	};
+	
+	/**
+	 * Returns the first matched string, or in global mode, an array containing all matched strings.
+	 * This is essentially a more convenient re-implementation of `String.prototype.match` that gives
+	 * the result types you actually want (string instead of `exec`-style array in match-first mode,
+	 * and an empty array instead of `null` when no matches are found in match-all mode). It also lets
+	 * you override flag g and ignore `lastIndex`, and fixes browser bugs.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {RegExp} regex Regex to search with.
+	 * @param {String} [scope='one'] Use 'one' to return the first match as a string. Use 'all' to
+	 *   return an array of all matched strings. If not explicitly specified and `regex` uses flag g,
+	 *   `scope` is 'all'.
+	 * @returns {String|Array} In match-first mode: First match as a string, or `null`. In match-all
+	 *   mode: Array of all matched strings, or an empty array.
+	 * @example
+	 *
+	 * // Match first
+	 * XRegExp.match('abc', /\w/); // -> 'a'
+	 * XRegExp.match('abc', /\w/g, 'one'); // -> 'a'
+	 * XRegExp.match('abc', /x/g, 'one'); // -> null
+	 *
+	 * // Match all
+	 * XRegExp.match('abc', /\w/g); // -> ['a', 'b', 'c']
+	 * XRegExp.match('abc', /\w/, 'all'); // -> ['a', 'b', 'c']
+	 * XRegExp.match('abc', /x/, 'all'); // -> []
+	 */
+	XRegExp.match = function (str, regex, scope) {
+	    var global = regex.global && scope !== 'one' || scope === 'all',
+	        cacheKey = (global ? 'g' : '') + (regex.sticky ? 'y' : '') || 'noGY',
+	        result,
+	        r2;
+	
+	    regex[REGEX_DATA] = regex[REGEX_DATA] || {};
+	
+	    // Shares cached copies with `XRegExp.exec`/`replace`
+	    r2 = regex[REGEX_DATA][cacheKey] || (regex[REGEX_DATA][cacheKey] = copyRegex(regex, {
+	        addG: !!global,
+	        addY: !!regex.sticky,
+	        removeG: scope === 'one',
+	        isInternalOnly: true
+	    }));
+	
+	    result = nativ.match.call(toObject(str), r2);
+	
+	    if (regex.global) {
+	        regex.lastIndex = scope === 'one' && result ?
+	        // Can't use `r2.lastIndex` since `r2` is nonglobal in this case
+	        result.index + result[0].length : 0;
+	    }
+	
+	    return global ? result || [] : result && result[0];
+	};
+	
+	/**
+	 * Retrieves the matches from searching a string using a chain of regexes that successively search
+	 * within previous matches. The provided `chain` array can contain regexes and or objects with
+	 * `regex` and `backref` properties. When a backreference is specified, the named or numbered
+	 * backreference is passed forward to the next regex or returned.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {Array} chain Regexes that each search for matches within preceding results.
+	 * @returns {Array} Matches by the last regex in the chain, or an empty array.
+	 * @example
+	 *
+	 * // Basic usage; matches numbers within <b> tags
+	 * XRegExp.matchChain('1 <b>2</b> 3 <b>4 a 56</b>', [
+	 *   XRegExp('(?is)<b>.*?</b>'),
+	 *   /\d+/
+	 * ]);
+	 * // -> ['2', '4', '56']
+	 *
+	 * // Passing forward and returning specific backreferences
+	 * html = '<a href="http://xregexp.com/api/">XRegExp</a>\
+	 *         <a href="http://www.google.com/">Google</a>';
+	 * XRegExp.matchChain(html, [
+	 *   {regex: /<a href="([^"]+)">/i, backref: 1},
+	 *   {regex: XRegExp('(?i)^https?://(?<domain>[^/?#]+)'), backref: 'domain'}
+	 * ]);
+	 * // -> ['xregexp.com', 'www.google.com']
+	 */
+	XRegExp.matchChain = function (str, chain) {
+	    return function recurseChain(values, level) {
+	        var item = chain[level].regex ? chain[level] : { regex: chain[level] },
+	            matches = [],
+	            addMatch = function addMatch(match) {
+	            if (item.backref) {
+	                /* Safari 4.0.5 (but not 5.0.5+) inappropriately uses sparse arrays to hold
+	                 * the `undefined`s for backreferences to nonparticipating capturing
+	                 * groups. In such cases, a `hasOwnProperty` or `in` check on its own would
+	                 * inappropriately throw the exception, so also check if the backreference
+	                 * is a number that is within the bounds of the array.
+	                 */
+	                if (!(match.hasOwnProperty(item.backref) || +item.backref < match.length)) {
+	                    throw new ReferenceError('Backreference to undefined group: ' + item.backref);
+	                }
+	
+	                matches.push(match[item.backref] || '');
+	            } else {
+	                matches.push(match[0]);
+	            }
+	        },
+	            i;
+	
+	        for (i = 0; i < values.length; ++i) {
+	            XRegExp.forEach(values[i], item.regex, addMatch);
+	        }
+	
+	        return level === chain.length - 1 || !matches.length ? matches : recurseChain(matches, level + 1);
+	    }([str], 0);
+	};
+	
+	/**
+	 * Returns a new string with one or all matches of a pattern replaced. The pattern can be a string
+	 * or regex, and the replacement can be a string or a function to be called for each match. To
+	 * perform a global search and replace, use the optional `scope` argument or include flag g if using
+	 * a regex. Replacement strings can use `${n}` for named and numbered backreferences. Replacement
+	 * functions can use named backreferences via `arguments[0].name`. Also fixes browser bugs compared
+	 * to the native `String.prototype.replace` and can be used reliably cross-browser.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {RegExp|String} search Search pattern to be replaced.
+	 * @param {String|Function} replacement Replacement string or a function invoked to create it.
+	 *   Replacement strings can include special replacement syntax:
+	 *     <li>$$ - Inserts a literal $ character.
+	 *     <li>$&, $0 - Inserts the matched substring.
+	 *     <li>$` - Inserts the string that precedes the matched substring (left context).
+	 *     <li>$' - Inserts the string that follows the matched substring (right context).
+	 *     <li>$n, $nn - Where n/nn are digits referencing an existent capturing group, inserts
+	 *       backreference n/nn.
+	 *     <li>${n} - Where n is a name or any number of digits that reference an existent capturing
+	 *       group, inserts backreference n.
+	 *   Replacement functions are invoked with three or more arguments:
+	 *     <li>The matched substring (corresponds to $& above). Named backreferences are accessible as
+	 *       properties of this first argument.
+	 *     <li>0..n arguments, one for each backreference (corresponding to $1, $2, etc. above).
+	 *     <li>The zero-based index of the match within the total search string.
+	 *     <li>The total string being searched.
+	 * @param {String} [scope='one'] Use 'one' to replace the first match only, or 'all'. If not
+	 *   explicitly specified and using a regex with flag g, `scope` is 'all'.
+	 * @returns {String} New string with one or all matches replaced.
+	 * @example
+	 *
+	 * // Regex search, using named backreferences in replacement string
+	 * var name = XRegExp('(?<first>\\w+) (?<last>\\w+)');
+	 * XRegExp.replace('John Smith', name, '${last}, ${first}');
+	 * // -> 'Smith, John'
+	 *
+	 * // Regex search, using named backreferences in replacement function
+	 * XRegExp.replace('John Smith', name, function(match) {
+	 *   return match.last + ', ' + match.first;
+	 * });
+	 * // -> 'Smith, John'
+	 *
+	 * // String search, with replace-all
+	 * XRegExp.replace('RegExp builds RegExps', 'RegExp', 'XRegExp', 'all');
+	 * // -> 'XRegExp builds XRegExps'
+	 */
+	XRegExp.replace = function (str, search, replacement, scope) {
+	    var isRegex = XRegExp.isRegExp(search),
+	        global = search.global && scope !== 'one' || scope === 'all',
+	        cacheKey = (global ? 'g' : '') + (search.sticky ? 'y' : '') || 'noGY',
+	        s2 = search,
+	        result;
+	
+	    if (isRegex) {
+	        search[REGEX_DATA] = search[REGEX_DATA] || {};
+	
+	        // Shares cached copies with `XRegExp.exec`/`match`. Since a copy is used, `search`'s
+	        // `lastIndex` isn't updated *during* replacement iterations
+	        s2 = search[REGEX_DATA][cacheKey] || (search[REGEX_DATA][cacheKey] = copyRegex(search, {
+	            addG: !!global,
+	            addY: !!search.sticky,
+	            removeG: scope === 'one',
+	            isInternalOnly: true
+	        }));
+	    } else if (global) {
+	        s2 = new RegExp(XRegExp.escape(String(search)), 'g');
+	    }
+	
+	    // Fixed `replace` required for named backreferences, etc.
+	    result = fixed.replace.call(toObject(str), s2, replacement);
+	
+	    if (isRegex && search.global) {
+	        // Fixes IE, Safari bug (last tested IE 9, Safari 5.1)
+	        search.lastIndex = 0;
+	    }
+	
+	    return result;
+	};
+	
+	/**
+	 * Performs batch processing of string replacements. Used like {@link #XRegExp.replace}, but
+	 * accepts an array of replacement details. Later replacements operate on the output of earlier
+	 * replacements. Replacement details are accepted as an array with a regex or string to search for,
+	 * the replacement string or function, and an optional scope of 'one' or 'all'. Uses the XRegExp
+	 * replacement text syntax, which supports named backreference properties via `${name}`.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {Array} replacements Array of replacement detail arrays.
+	 * @returns {String} New string with all replacements.
+	 * @example
+	 *
+	 * str = XRegExp.replaceEach(str, [
+	 *   [XRegExp('(?<name>a)'), 'z${name}'],
+	 *   [/b/gi, 'y'],
+	 *   [/c/g, 'x', 'one'], // scope 'one' overrides /g
+	 *   [/d/, 'w', 'all'],  // scope 'all' overrides lack of /g
+	 *   ['e', 'v', 'all'],  // scope 'all' allows replace-all for strings
+	 *   [/f/g, function($0) {
+	 *     return $0.toUpperCase();
+	 *   }]
+	 * ]);
+	 */
+	XRegExp.replaceEach = function (str, replacements) {
+	    var i, r;
+	
+	    for (i = 0; i < replacements.length; ++i) {
+	        r = replacements[i];
+	        str = XRegExp.replace(str, r[0], r[1], r[2]);
+	    }
+	
+	    return str;
+	};
+	
+	/**
+	 * Splits a string into an array of strings using a regex or string separator. Matches of the
+	 * separator are not included in the result array. However, if `separator` is a regex that contains
+	 * capturing groups, backreferences are spliced into the result each time `separator` is matched.
+	 * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
+	 * cross-browser.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to split.
+	 * @param {RegExp|String} separator Regex or string to use for separating the string.
+	 * @param {Number} [limit] Maximum number of items to include in the result array.
+	 * @returns {Array} Array of substrings.
+	 * @example
+	 *
+	 * // Basic use
+	 * XRegExp.split('a b c', ' ');
+	 * // -> ['a', 'b', 'c']
+	 *
+	 * // With limit
+	 * XRegExp.split('a b c', ' ', 2);
+	 * // -> ['a', 'b']
+	 *
+	 * // Backreferences in result array
+	 * XRegExp.split('..word1..', /([a-z]+)(\d+)/i);
+	 * // -> ['..', 'word', '1', '..']
+	 */
+	XRegExp.split = function (str, separator, limit) {
+	    return fixed.split.call(toObject(str), separator, limit);
+	};
+	
+	/**
+	 * Executes a regex search in a specified string. Returns `true` or `false`. Optional `pos` and
+	 * `sticky` arguments specify the search start position, and whether the match must start at the
+	 * specified position only. The `lastIndex` property of the provided regex is not used, but is
+	 * updated for compatibility. Also fixes browser bugs compared to the native
+	 * `RegExp.prototype.test` and can be used reliably cross-browser.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {RegExp} regex Regex to search with.
+	 * @param {Number} [pos=0] Zero-based index at which to start the search.
+	 * @param {Boolean|String} [sticky=false] Whether the match must start at the specified position
+	 *   only. The string `'sticky'` is accepted as an alternative to `true`.
+	 * @returns {Boolean} Whether the regex matched the provided value.
+	 * @example
+	 *
+	 * // Basic use
+	 * XRegExp.test('abc', /c/); // -> true
+	 *
+	 * // With pos and sticky
+	 * XRegExp.test('abc', /c/, 0, 'sticky'); // -> false
+	 * XRegExp.test('abc', /c/, 2, 'sticky'); // -> true
+	 */
+	XRegExp.test = function (str, regex, pos, sticky) {
+	    // Do this the easy way :-)
+	    return !!XRegExp.exec(str, regex, pos, sticky);
+	};
+	
+	/**
+	 * Uninstalls optional features according to the specified options. All optional features start out
+	 * uninstalled, so this is used to undo the actions of {@link #XRegExp.install}.
+	 *
+	 * @memberOf XRegExp
+	 * @param {Object|String} options Options object or string.
+	 * @example
+	 *
+	 * // With an options object
+	 * XRegExp.uninstall({
+	 *   // Disables support for astral code points in Unicode addons
+	 *   astral: true,
+	 *
+	 *   // Restores native regex methods
+	 *   natives: true
+	 * });
+	 *
+	 * // With an options string
+	 * XRegExp.uninstall('astral natives');
+	 */
+	XRegExp.uninstall = function (options) {
+	    options = prepareOptions(options);
+	
+	    if (features.astral && options.astral) {
+	        setAstral(false);
+	    }
+	
+	    if (features.natives && options.natives) {
+	        setNatives(false);
+	    }
+	};
+	
+	/**
+	 * Returns an XRegExp object that is the union of the given patterns. Patterns can be provided as
+	 * regex objects or strings. Metacharacters are escaped in patterns provided as strings.
+	 * Backreferences in provided regex objects are automatically renumbered to work correctly within
+	 * the larger combined pattern. Native flags used by provided regexes are ignored in favor of the
+	 * `flags` argument.
+	 *
+	 * @memberOf XRegExp
+	 * @param {Array} patterns Regexes and strings to combine.
+	 * @param {String} [flags] Any combination of XRegExp flags.
+	 * @returns {RegExp} Union of the provided regexes and strings.
+	 * @example
+	 *
+	 * XRegExp.union(['a+b*c', /(dogs)\1/, /(cats)\1/], 'i');
+	 * // -> /a\+b\*c|(dogs)\1|(cats)\2/i
+	 */
+	XRegExp.union = function (patterns, flags) {
+	    var parts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g,
+	        output = [],
+	        numCaptures = 0,
+	        numPriorCaptures,
+	        captureNames,
+	        pattern,
+	        rewrite = function rewrite(match, paren, backref) {
+	        var name = captureNames[numCaptures - numPriorCaptures];
+	
+	        // Capturing group
+	        if (paren) {
+	            ++numCaptures;
+	            // If the current capture has a name, preserve the name
+	            if (name) {
+	                return '(?<' + name + '>';
+	            }
+	            // Backreference
+	        } else if (backref) {
+	            // Rewrite the backreference
+	            return '\\' + (+backref + numPriorCaptures);
+	        }
+	
+	        return match;
+	    },
+	        i;
+	
+	    if (!(isType(patterns, 'Array') && patterns.length)) {
+	        throw new TypeError('Must provide a nonempty array of patterns to merge');
+	    }
+	
+	    for (i = 0; i < patterns.length; ++i) {
+	        pattern = patterns[i];
+	
+	        if (XRegExp.isRegExp(pattern)) {
+	            numPriorCaptures = numCaptures;
+	            captureNames = pattern[REGEX_DATA] && pattern[REGEX_DATA].captureNames || [];
+	
+	            // Rewrite backreferences. Passing to XRegExp dies on octals and ensures patterns
+	            // are independently valid; helps keep this simple. Named captures are put back
+	            output.push(nativ.replace.call(XRegExp(pattern.source).source, parts, rewrite));
+	        } else {
+	            output.push(XRegExp.escape(pattern));
+	        }
+	    }
+	
+	    return XRegExp(output.join('|'), flags);
+	};
+	
+	/* ==============================
+	 * Fixed/extended native methods
+	 * ============================== */
+	
+	/**
+	 * Adds named capture support (with backreferences returned as `result.name`), and fixes browser
+	 * bugs in the native `RegExp.prototype.exec`. Calling `XRegExp.install('natives')` uses this to
+	 * override the native method. Use via `XRegExp.exec` without overriding natives.
+	 *
+	 * @private
+	 * @param {String} str String to search.
+	 * @returns {Array} Match array with named backreference properties, or `null`.
+	 */
+	fixed.exec = function (str) {
+	    var origLastIndex = this.lastIndex,
+	        match = nativ.exec.apply(this, arguments),
+	        name,
+	        r2,
+	        i;
+	
+	    if (match) {
+	        // Fix browsers whose `exec` methods don't return `undefined` for nonparticipating
+	        // capturing groups. This fixes IE 5.5-8, but not IE 9's quirks mode or emulation of
+	        // older IEs. IE 9 in standards mode follows the spec
+	        if (!correctExecNpcg && match.length > 1 && indexOf(match, '') > -1) {
+	            r2 = copyRegex(this, {
+	                removeG: true,
+	                isInternalOnly: true
+	            });
+	            // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed
+	            // matching due to characters outside the match
+	            nativ.replace.call(String(str).slice(match.index), r2, function () {
+	                var len = arguments.length,
+	                    i;
+	                // Skip index 0 and the last 2
+	                for (i = 1; i < len - 2; ++i) {
+	                    if (arguments[i] === undefined) {
+	                        match[i] = undefined;
+	                    }
+	                }
+	            });
+	        }
+	
+	        // Attach named capture properties
+	        if (this[REGEX_DATA] && this[REGEX_DATA].captureNames) {
+	            // Skip index 0
+	            for (i = 1; i < match.length; ++i) {
+	                name = this[REGEX_DATA].captureNames[i - 1];
+	                if (name) {
+	                    match[name] = match[i];
+	                }
+	            }
+	        }
+	
+	        // Fix browsers that increment `lastIndex` after zero-length matches
+	        if (this.global && !match[0].length && this.lastIndex > match.index) {
+	            this.lastIndex = match.index;
+	        }
+	    }
+	
+	    if (!this.global) {
+	        // Fixes IE, Opera bug (last tested IE 9, Opera 11.6)
+	        this.lastIndex = origLastIndex;
+	    }
+	
+	    return match;
+	};
+	
+	/**
+	 * Fixes browser bugs in the native `RegExp.prototype.test`. Calling `XRegExp.install('natives')`
+	 * uses this to override the native method.
+	 *
+	 * @private
+	 * @param {String} str String to search.
+	 * @returns {Boolean} Whether the regex matched the provided value.
+	 */
+	fixed.test = function (str) {
+	    // Do this the easy way :-)
+	    return !!fixed.exec.call(this, str);
+	};
+	
+	/**
+	 * Adds named capture support (with backreferences returned as `result.name`), and fixes browser
+	 * bugs in the native `String.prototype.match`. Calling `XRegExp.install('natives')` uses this to
+	 * override the native method.
+	 *
+	 * @private
+	 * @param {RegExp|*} regex Regex to search with. If not a regex object, it is passed to `RegExp`.
+	 * @returns {Array} If `regex` uses flag g, an array of match strings or `null`. Without flag g,
+	 *   the result of calling `regex.exec(this)`.
+	 */
+	fixed.match = function (regex) {
+	    var result;
+	
+	    if (!XRegExp.isRegExp(regex)) {
+	        // Use the native `RegExp` rather than `XRegExp`
+	        regex = new RegExp(regex);
+	    } else if (regex.global) {
+	        result = nativ.match.apply(this, arguments);
+	        // Fixes IE bug
+	        regex.lastIndex = 0;
+	
+	        return result;
+	    }
+	
+	    return fixed.exec.call(regex, toObject(this));
+	};
+	
+	/**
+	 * Adds support for `${n}` tokens for named and numbered backreferences in replacement text, and
+	 * provides named backreferences to replacement functions as `arguments[0].name`. Also fixes browser
+	 * bugs in replacement text syntax when performing a replacement using a nonregex search value, and
+	 * the value of a replacement regex's `lastIndex` property during replacement iterations and upon
+	 * completion. Calling `XRegExp.install('natives')` uses this to override the native method. Note
+	 * that this doesn't support SpiderMonkey's proprietary third (`flags`) argument. Use via
+	 * `XRegExp.replace` without overriding natives.
+	 *
+	 * @private
+	 * @param {RegExp|String} search Search pattern to be replaced.
+	 * @param {String|Function} replacement Replacement string or a function invoked to create it.
+	 * @returns {String} New string with one or all matches replaced.
+	 */
+	fixed.replace = function (search, replacement) {
+	    var isRegex = XRegExp.isRegExp(search),
+	        origLastIndex,
+	        captureNames,
+	        result;
+	
+	    if (isRegex) {
+	        if (search[REGEX_DATA]) {
+	            captureNames = search[REGEX_DATA].captureNames;
+	        }
+	        // Only needed if `search` is nonglobal
+	        origLastIndex = search.lastIndex;
+	    } else {
+	        search += ''; // Type-convert
+	    }
+	
+	    // Don't use `typeof`; some older browsers return 'function' for regex objects
+	    if (isType(replacement, 'Function')) {
+	        // Stringifying `this` fixes a bug in IE < 9 where the last argument in replacement
+	        // functions isn't type-converted to a string
+	        result = nativ.replace.call(String(this), search, function () {
+	            var args = arguments,
+	                i;
+	            if (captureNames) {
+	                // Change the `arguments[0]` string primitive to a `String` object that can
+	                // store properties. This really does need to use `String` as a constructor
+	                args[0] = new String(args[0]);
+	                // Store named backreferences on the first argument
+	                for (i = 0; i < captureNames.length; ++i) {
+	                    if (captureNames[i]) {
+	                        args[0][captureNames[i]] = args[i + 1];
+	                    }
+	                }
+	            }
+	            // Update `lastIndex` before calling `replacement`. Fixes IE, Chrome, Firefox,
+	            // Safari bug (last tested IE 9, Chrome 17, Firefox 11, Safari 5.1)
+	            if (isRegex && search.global) {
+	                search.lastIndex = args[args.length - 2] + args[0].length;
+	            }
+	            // ES6 specs the context for replacement functions as `undefined`
+	            return replacement.apply(undefined, args);
+	        });
+	    } else {
+	        // Ensure that the last value of `args` will be a string when given nonstring `this`,
+	        // while still throwing on null or undefined context
+	        result = nativ.replace.call(this == null ? this : String(this), search, function () {
+	            // Keep this function's `arguments` available through closure
+	            var args = arguments;
+	            return nativ.replace.call(String(replacement), replacementToken, function ($0, $1, $2) {
+	                var n;
+	                // Named or numbered backreference with curly braces
+	                if ($1) {
+	                    // XRegExp behavior for `${n}`:
+	                    // 1. Backreference to numbered capture, if `n` is an integer. Use `0` for
+	                    //    for the entire match. Any number of leading zeros may be used.
+	                    // 2. Backreference to named capture `n`, if it exists and is not an
+	                    //    integer overridden by numbered capture. In practice, this does not
+	                    //    overlap with numbered capture since XRegExp does not allow named
+	                    //    capture to use a bare integer as the name.
+	                    // 3. If the name or number does not refer to an existing capturing group,
+	                    //    it's an error.
+	                    n = +$1; // Type-convert; drop leading zeros
+	                    if (n <= args.length - 3) {
+	                        return args[n] || '';
+	                    }
+	                    // Groups with the same name is an error, else would need `lastIndexOf`
+	                    n = captureNames ? indexOf(captureNames, $1) : -1;
+	                    if (n < 0) {
+	                        throw new SyntaxError('Backreference to undefined group ' + $0);
+	                    }
+	                    return args[n + 1] || '';
+	                }
+	                // Else, special variable or numbered backreference without curly braces
+	                if ($2 === '$') {
+	                    // $$
+	                    return '$';
+	                }
+	                if ($2 === '&' || +$2 === 0) {
+	                    // $&, $0 (not followed by 1-9), $00
+	                    return args[0];
+	                }
+	                if ($2 === '`') {
+	                    // $` (left context)
+	                    return args[args.length - 1].slice(0, args[args.length - 2]);
+	                }
+	                if ($2 === "'") {
+	                    // $' (right context)
+	                    return args[args.length - 1].slice(args[args.length - 2] + args[0].length);
+	                }
+	                // Else, numbered backreference without curly braces
+	                $2 = +$2; // Type-convert; drop leading zero
+	                // XRegExp behavior for `$n` and `$nn`:
+	                // - Backrefs end after 1 or 2 digits. Use `${..}` for more digits.
+	                // - `$1` is an error if no capturing groups.
+	                // - `$10` is an error if less than 10 capturing groups. Use `${1}0` instead.
+	                // - `$01` is `$1` if at least one capturing group, else it's an error.
+	                // - `$0` (not followed by 1-9) and `$00` are the entire match.
+	                // Native behavior, for comparison:
+	                // - Backrefs end after 1 or 2 digits. Cannot reference capturing group 100+.
+	                // - `$1` is a literal `$1` if no capturing groups.
+	                // - `$10` is `$1` followed by a literal `0` if less than 10 capturing groups.
+	                // - `$01` is `$1` if at least one capturing group, else it's a literal `$01`.
+	                // - `$0` is a literal `$0`.
+	                if (!isNaN($2)) {
+	                    if ($2 > args.length - 3) {
+	                        throw new SyntaxError('Backreference to undefined group ' + $0);
+	                    }
+	                    return args[$2] || '';
+	                }
+	                // `$` followed by an unsupported char is an error, unlike native JS
+	                throw new SyntaxError('Invalid token ' + $0);
+	            });
+	        });
+	    }
+	
+	    if (isRegex) {
+	        if (search.global) {
+	            // Fixes IE, Safari bug (last tested IE 9, Safari 5.1)
+	            search.lastIndex = 0;
+	        } else {
+	            // Fixes IE, Opera bug (last tested IE 9, Opera 11.6)
+	            search.lastIndex = origLastIndex;
+	        }
+	    }
+	
+	    return result;
+	};
+	
+	/**
+	 * Fixes browser bugs in the native `String.prototype.split`. Calling `XRegExp.install('natives')`
+	 * uses this to override the native method. Use via `XRegExp.split` without overriding natives.
+	 *
+	 * @private
+	 * @param {RegExp|String} separator Regex or string to use for separating the string.
+	 * @param {Number} [limit] Maximum number of items to include in the result array.
+	 * @returns {Array} Array of substrings.
+	 */
+	fixed.split = function (separator, limit) {
+	    if (!XRegExp.isRegExp(separator)) {
+	        // Browsers handle nonregex split correctly, so use the faster native method
+	        return nativ.split.apply(this, arguments);
+	    }
+	
+	    var str = String(this),
+	        output = [],
+	        origLastIndex = separator.lastIndex,
+	        lastLastIndex = 0,
+	        lastLength;
+	
+	    // Values for `limit`, per the spec:
+	    // If undefined: pow(2,32) - 1
+	    // If 0, Infinity, or NaN: 0
+	    // If positive number: limit = floor(limit); if (limit >= pow(2,32)) limit -= pow(2,32);
+	    // If negative number: pow(2,32) - floor(abs(limit))
+	    // If other: Type-convert, then use the above rules
+	    // This line fails in very strange ways for some values of `limit` in Opera 10.5-10.63,
+	    // unless Opera Dragonfly is open (go figure). It works in at least Opera 9.5-10.1 and 11+
+	    limit = (limit === undefined ? -1 : limit) >>> 0;
+	
+	    XRegExp.forEach(str, separator, function (match) {
+	        // This condition is not the same as `if (match[0].length)`
+	        if (match.index + match[0].length > lastLastIndex) {
+	            output.push(str.slice(lastLastIndex, match.index));
+	            if (match.length > 1 && match.index < str.length) {
+	                Array.prototype.push.apply(output, match.slice(1));
+	            }
+	            lastLength = match[0].length;
+	            lastLastIndex = match.index + lastLength;
+	        }
+	    });
+	
+	    if (lastLastIndex === str.length) {
+	        if (!nativ.test.call(separator, '') || lastLength) {
+	            output.push('');
+	        }
+	    } else {
+	        output.push(str.slice(lastLastIndex));
+	    }
+	
+	    separator.lastIndex = origLastIndex;
+	    return output.length > limit ? output.slice(0, limit) : output;
+	};
+	
+	/* ==============================
+	 * Built-in syntax/flag tokens
+	 * ============================== */
+	
+	/*
+	 * Letter escapes that natively match literal characters: `\a`, `\A`, etc. These should be
+	 * SyntaxErrors but are allowed in web reality. XRegExp makes them errors for cross-browser
+	 * consistency and to reserve their syntax, but lets them be superseded by addons.
+	 */
+	XRegExp.addToken(/\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4}|{[\dA-Fa-f]+})|x(?![\dA-Fa-f]{2}))/, function (match, scope) {
+	    // \B is allowed in default scope only
+	    if (match[1] === 'B' && scope === defaultScope) {
+	        return match[0];
+	    }
+	    throw new SyntaxError('Invalid escape ' + match[0]);
+	}, {
+	    scope: 'all',
+	    leadChar: '\\'
+	});
+	
+	/*
+	 * Unicode code point escape with curly braces: `\u{N..}`. `N..` is any one or more digit
+	 * hexadecimal number from 0-10FFFF, and can include leading zeros. Requires the native ES6 `u` flag
+	 * to support code points greater than U+FFFF. Avoids converting code points above U+FFFF to
+	 * surrogate pairs (which could be done without flag `u`), since that could lead to broken behavior
+	 * if you follow a `\u{N..}` token that references a code point above U+FFFF with a quantifier, or
+	 * if you use the same in a character class.
+	 */
+	XRegExp.addToken(/\\u{([\dA-Fa-f]+)}/, function (match, scope, flags) {
+	    var code = dec(match[1]);
+	    if (code > 0x10FFFF) {
+	        throw new SyntaxError('Invalid Unicode code point ' + match[0]);
+	    }
+	    if (code <= 0xFFFF) {
+	        // Converting to \uNNNN avoids needing to escape the literal character and keep it
+	        // separate from preceding tokens
+	        return '\\u' + pad4(hex(code));
+	    }
+	    // If `code` is between 0xFFFF and 0x10FFFF, require and defer to native handling
+	    if (hasNativeU && flags.indexOf('u') > -1) {
+	        return match[0];
+	    }
+	    throw new SyntaxError('Cannot use Unicode code point above \\u{FFFF} without flag u');
+	}, {
+	    scope: 'all',
+	    leadChar: '\\'
+	});
+	
+	/*
+	 * Empty character class: `[]` or `[^]`. This fixes a critical cross-browser syntax inconsistency.
+	 * Unless this is standardized (per the ES spec), regex syntax can't be accurately parsed because
+	 * character class endings can't be determined.
+	 */
+	XRegExp.addToken(/\[(\^?)]/, function (match) {
+	    // For cross-browser compatibility with ES3, convert [] to \b\B and [^] to [\s\S].
+	    // (?!) should work like \b\B, but is unreliable in some versions of Firefox
+	    return match[1] ? '[\\s\\S]' : '\\b\\B';
+	}, { leadChar: '[' });
+	
+	/*
+	 * Comment pattern: `(?# )`. Inline comments are an alternative to the line comments allowed in
+	 * free-spacing mode (flag x).
+	 */
+	XRegExp.addToken(/\(\?#[^)]*\)/, function (match, scope, flags) {
+	    // Keep tokens separated unless the following token is a quantifier
+	    return isQuantifierNext(match.input, match.index + match[0].length, flags) ? '' : '(?:)';
+	}, { leadChar: '(' });
+	
+	/*
+	 * Whitespace and line comments, in free-spacing mode (aka extended mode, flag x) only.
+	 */
+	XRegExp.addToken(/\s+|#.*/, function (match, scope, flags) {
+	    // Keep tokens separated unless the following token is a quantifier
+	    return isQuantifierNext(match.input, match.index + match[0].length, flags) ? '' : '(?:)';
+	}, { flag: 'x' });
+	
+	/*
+	 * Dot, in dotall mode (aka singleline mode, flag s) only.
+	 */
+	XRegExp.addToken(/\./, function () {
+	    return '[\\s\\S]';
+	}, {
+	    flag: 's',
+	    leadChar: '.'
+	});
+	
+	/*
+	 * Named backreference: `\k<name>`. Backreference names can use the characters A-Z, a-z, 0-9, _,
+	 * and $ only. Also allows numbered backreferences as `\k<n>`.
+	 */
+	XRegExp.addToken(/\\k<([\w$]+)>/, function (match) {
+	    // Groups with the same name is an error, else would need `lastIndexOf`
+	    var index = isNaN(match[1]) ? indexOf(this.captureNames, match[1]) + 1 : +match[1],
+	        endIndex = match.index + match[0].length;
+	    if (!index || index > this.captureNames.length) {
+	        throw new SyntaxError('Backreference to undefined group ' + match[0]);
+	    }
+	    // Keep backreferences separate from subsequent literal numbers
+	    return '\\' + index + (endIndex === match.input.length || isNaN(match.input.charAt(endIndex)) ? '' : '(?:)');
+	}, { leadChar: '\\' });
+	
+	/*
+	 * Numbered backreference or octal, plus any following digits: `\0`, `\11`, etc. Octals except `\0`
+	 * not followed by 0-9 and backreferences to unopened capture groups throw an error. Other matches
+	 * are returned unaltered. IE < 9 doesn't support backreferences above `\99` in regex syntax.
+	 */
+	XRegExp.addToken(/\\(\d+)/, function (match, scope) {
+	    if (!(scope === defaultScope && /^[1-9]/.test(match[1]) && +match[1] <= this.captureNames.length) && match[1] !== '0') {
+	        throw new SyntaxError('Cannot use octal escape or backreference to undefined group ' + match[0]);
+	    }
+	    return match[0];
+	}, {
+	    scope: 'all',
+	    leadChar: '\\'
+	});
+	
+	/*
+	 * Named capturing group; match the opening delimiter only: `(?<name>`. Capture names can use the
+	 * characters A-Z, a-z, 0-9, _, and $ only. Names can't be integers. Supports Python-style
+	 * `(?P<name>` as an alternate syntax to avoid issues in some older versions of Opera which natively
+	 * supported the Python-style syntax. Otherwise, XRegExp might treat numbered backreferences to
+	 * Python-style named capture as octals.
+	 */
+	XRegExp.addToken(/\(\?P?<([\w$]+)>/, function (match) {
+	    // Disallow bare integers as names because named backreferences are added to match
+	    // arrays and therefore numeric properties may lead to incorrect lookups
+	    if (!isNaN(match[1])) {
+	        throw new SyntaxError('Cannot use integer as capture name ' + match[0]);
+	    }
+	    if (match[1] === 'length' || match[1] === '__proto__') {
+	        throw new SyntaxError('Cannot use reserved word as capture name ' + match[0]);
+	    }
+	    if (indexOf(this.captureNames, match[1]) > -1) {
+	        throw new SyntaxError('Cannot use same name for multiple groups ' + match[0]);
+	    }
+	    this.captureNames.push(match[1]);
+	    this.hasNamedCapture = true;
+	    return '(';
+	}, { leadChar: '(' });
+	
+	/*
+	 * Capturing group; match the opening parenthesis only. Required for support of named capturing
+	 * groups. Also adds explicit capture mode (flag n).
+	 */
+	XRegExp.addToken(/\((?!\?)/, function (match, scope, flags) {
+	    if (flags.indexOf('n') > -1) {
+	        return '(?:';
+	    }
+	    this.captureNames.push(null);
+	    return '(';
+	}, {
+	    optionalFlags: 'n',
+	    leadChar: '('
+	});
+	
+	/* ==============================
+	 * Expose XRegExp
+	 * ============================== */
+	
+	module.exports = XRegExp;
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	
+	var _match = __webpack_require__(6);
+	
+	Object.keys(_match).forEach(function (key) {
+	  if (key === "default" || key === "__esModule") return;
+	  Object.defineProperty(exports, key, {
+	    enumerable: true,
+	    get: function get() {
+	      return _match[key];
+	    }
+	  });
+	});
+	
+	var _applyRegexList = __webpack_require__(7);
+	
+	Object.keys(_applyRegexList).forEach(function (key) {
+	  if (key === "default" || key === "__esModule") return;
+	  Object.defineProperty(exports, key, {
+	    enumerable: true,
+	    get: function get() {
+	      return _applyRegexList[key];
+	    }
+	  });
+	});
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports) {
+
+	"use strict";
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	
+	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+	
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+	
+	var Match = exports.Match = function () {
+	  function Match(value, index, css) {
+	    _classCallCheck(this, Match);
+	
+	    this.value = value;
+	    this.index = index;
+	    this.length = value.length;
+	    this.css = css;
+	    this.brushName = null;
+	  }
+	
+	  _createClass(Match, [{
+	    key: "toString",
+	    value: function toString() {
+	      return this.value;
+	    }
+	  }]);
+
+	  return Match;
+	}();
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	
+	var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+	
+	exports.applyRegexList = applyRegexList;
+	
+	var _matches = __webpack_require__(8);
+	
+	/**
+	 * Applies all regular expression to the code and sto

<TRUNCATED>