From 6de0ab3293246196cc32ef6567f7c025de6660ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Wed, 29 May 2013 12:57:33 -0700 Subject: [PATCH] v0.3.0 --- css/codemirror.css | 239 + css/main.css | 165 + css/react.css | 1 + css/syntax.css | 409 ++ docs/advanced-components.html | 218 + docs/api.html | 202 + docs/common-questions.html | 117 + docs/component-basics.html | 161 + docs/component-data.html | 231 + docs/component-lifecycle.html | 172 + docs/event-handling.html | 206 + docs/getting-started.html | 179 + docs/syntax.html | 235 + docs/tutorial.html | 700 +++ downloads.html | 109 + downloads/react-0.3.0.zip | Bin 0 -> 396526 bytes extractCode.js | 37 + favicon.ico | Bin 0 -> 24838 bytes img/logo_og.png | Bin 0 -> 24516 bytes img/logo_small.png | Bin 0 -> 2834 bytes img/logo_small@2x.png | Bin 0 -> 6806 bytes img/noise.png | Bin 0 -> 23367 bytes index.html | 157 + js/JSXTransformer.js | 10139 ++++++++++++++++++++++++++++++++ js/codemirror.js | 5230 ++++++++++++++++ js/examples/hello.js | 19 + js/examples/markdown.js | 42 + js/examples/timer.js | 32 + js/examples/todo.js | 57 + js/javascript.js | 425 ++ js/live_editor.js | 98 + js/react.min.js | 19 + js/showdown.js | 1302 ++++ support.html | 82 + 34 files changed, 20983 insertions(+) create mode 100644 css/codemirror.css create mode 100755 css/main.css create mode 100644 css/react.css create mode 100644 css/syntax.css create mode 100644 docs/advanced-components.html create mode 100644 docs/api.html create mode 100644 docs/common-questions.html create mode 100644 docs/component-basics.html create mode 100644 docs/component-data.html create mode 100644 docs/component-lifecycle.html create mode 100644 docs/event-handling.html create mode 100644 docs/getting-started.html create mode 100644 docs/syntax.html create mode 100644 docs/tutorial.html create mode 100644 downloads.html create mode 100644 downloads/react-0.3.0.zip create mode 100644 extractCode.js create mode 100644 favicon.ico create mode 100644 img/logo_og.png create mode 100644 img/logo_small.png create mode 100644 img/logo_small@2x.png create mode 100644 img/noise.png create mode 100644 index.html create mode 100644 js/JSXTransformer.js create mode 100644 js/codemirror.js create mode 100644 js/examples/hello.js create mode 100644 js/examples/markdown.js create mode 100644 js/examples/timer.js create mode 100644 js/examples/todo.js create mode 100644 js/javascript.js create mode 100644 js/live_editor.js create mode 100644 js/react.min.js create mode 100644 js/showdown.js create mode 100644 support.html diff --git a/css/codemirror.css b/css/codemirror.css new file mode 100644 index 0000000000..9113866392 --- /dev/null +++ b/css/codemirror.css @@ -0,0 +1,239 @@ +/* BASICS */ + +.CodeMirror { + /* Set height, width, borders, and global font properties here */ + font-family: monospace; +} +.CodeMirror-scroll { + /* Set scrolling behaviour here */ + overflow: auto; +} + +/* PADDING */ + +.CodeMirror-lines { + padding: 14px 0; /* Vertical padding around content */ +} +.CodeMirror pre { + padding: 0 14px; /* Horizontal padding of content */ +} + +.CodeMirror-scrollbar-filler { + background-color: white; /* The little square between H and V scrollbars */ +} + +/* GUTTER */ + +.CodeMirror-gutters { + border-right: 1px solid #ddd; + background-color: #f7f7f7; +} +.CodeMirror-linenumbers {} +.CodeMirror-linenumber { + padding: 0 3px 0 5px; + min-width: 20px; + text-align: right; + color: #999; +} + +/* CURSOR */ + +.CodeMirror div.CodeMirror-cursor { + border-left: 1px solid black; +} +/* Shown when moving in bi-directional text */ +.CodeMirror div.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} +.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { + width: auto; + border: 0; + background: transparent; + background: rgba(0, 200, 0, .4); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800); +} +/* Kludge to turn off filter in ie9+, which also accepts rgba */ +.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor:not(#nonsense_id) { + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} +/* Can style cursor different in overwrite (non-insert) mode */ +.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {} + +/* DEFAULT THEME */ + +.cm-s-default .cm-keyword {color: #708;} +.cm-s-default .cm-atom {color: #219;} +.cm-s-default .cm-number {color: #164;} +.cm-s-default .cm-def {color: #00f;} +.cm-s-default .cm-variable {color: black;} +.cm-s-default .cm-variable-2 {color: #05a;} +.cm-s-default .cm-variable-3 {color: #085;} +.cm-s-default .cm-property {color: black;} +.cm-s-default .cm-operator {color: black;} +.cm-s-default .cm-comment {color: #a50;} +.cm-s-default .cm-string {color: #a11;} +.cm-s-default .cm-string-2 {color: #f50;} +.cm-s-default .cm-meta {color: #555;} +.cm-s-default .cm-error {color: #f00;} +.cm-s-default .cm-qualifier {color: #555;} +.cm-s-default .cm-builtin {color: #30a;} +.cm-s-default .cm-bracket {color: #997;} +.cm-s-default .cm-tag {color: #170;} +.cm-s-default .cm-attribute {color: #00c;} +.cm-s-default .cm-header {color: blue;} +.cm-s-default .cm-quote {color: #090;} +.cm-s-default .cm-hr {color: #999;} +.cm-s-default .cm-link {color: #00c;} + +.cm-negative {color: #d44;} +.cm-positive {color: #292;} +.cm-header, .cm-strong {font-weight: bold;} +.cm-em {font-style: italic;} +.cm-emstrong {font-style: italic; font-weight: bold;} +.cm-link {text-decoration: underline;} + +.cm-invalidchar {color: #f00;} + +div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} +div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} + +/* STOP */ + +/* The rest of this file contains styles related to the mechanics of + the editor. You probably shouldn't touch them. */ + +.CodeMirror { + line-height: 1; + position: relative; + overflow: hidden; +} + +.CodeMirror-scroll { + /* 30px is the magic margin used to hide the element's real scrollbars */ + /* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */ + margin-bottom: -30px; margin-right: -30px; + padding-bottom: 30px; padding-right: 30px; + height: 100%; + outline: none; /* Prevent dragging from highlighting the element */ + position: relative; +} +.CodeMirror-sizer { + position: relative; +} + +/* The fake, visible scrollbars. Used to force redraw during scrolling + before actuall scrolling happens, thus preventing shaking and + flickering artifacts. */ +.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler { + position: absolute; + z-index: 6; + display: none; +} +.CodeMirror-vscrollbar { + right: 0; top: 0; + overflow-x: hidden; + overflow-y: scroll; +} +.CodeMirror-hscrollbar { + bottom: 0; left: 0; + overflow-y: hidden; + overflow-x: scroll; +} +.CodeMirror-scrollbar-filler { + right: 0; bottom: 0; + z-index: 6; +} + +.CodeMirror-gutters { + position: absolute; left: 0; top: 0; + height: 100%; + z-index: 3; +} +.CodeMirror-gutter { + height: 100%; + display: inline-block; + /* Hack to make IE7 behave */ + *zoom:1; + *display:inline; +} +.CodeMirror-gutter-elt { + position: absolute; + cursor: default; + z-index: 4; +} + +.CodeMirror-lines { + cursor: text; +} +.CodeMirror pre { + /* Reset some styles that the rest of the page might have set */ + -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0; + border-width: 0; + background: transparent; + font-family: inherit; + font-size: inherit; + margin: 0; + white-space: pre; + word-wrap: normal; + line-height: inherit; + color: inherit; + z-index: 2; + position: relative; + overflow: visible; +} +.CodeMirror-wrap pre { + word-wrap: break-word; + white-space: pre-wrap; + word-break: normal; +} +.CodeMirror-linebackground { + position: absolute; + left: 0; right: 0; top: 0; bottom: 0; + z-index: 0; +} + +.CodeMirror-linewidget { + position: relative; + z-index: 2; + overflow: auto; +} + +.CodeMirror-wrap .CodeMirror-scroll { + overflow-x: hidden; +} + +.CodeMirror-measure { + position: absolute; + width: 100%; height: 0px; + overflow: hidden; + visibility: hidden; +} +.CodeMirror-measure pre { position: static; } + +.CodeMirror div.CodeMirror-cursor { + position: absolute; + visibility: hidden; + border-right: none; + width: 0; +} +.CodeMirror-focused div.CodeMirror-cursor { + visibility: visible; +} + +.CodeMirror-selected { background: #d9d9d9; } +.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } + +.cm-searching { + background: #ffa; + background: rgba(255, 255, 0, .4); +} + +/* IE7 hack to prevent it from returning funny offsetTops on the spans */ +.CodeMirror span { *vertical-align: text-bottom; } + +@media print { + /* Hide the cursor when printing */ + .CodeMirror div.CodeMirror-cursor { + visibility: hidden; + } +} diff --git a/css/main.css b/css/main.css new file mode 100755 index 0000000000..ffd4641819 --- /dev/null +++ b/css/main.css @@ -0,0 +1,165 @@ +/*****************************************************************************/ +/* +/* Common +/* +/*****************************************************************************/ + +/* Global Reset */ +* { + margin: 0; + padding: 0; +} + +html, body { height: 100%; } + +body { + background-color: #FFF; + font: 13.34px Helvetica, Arial, sans-serif; + font-size: small; + text-align: center; +} + +h1, h2, h3, h4, h5, h6 { + font-size: 100%; } + +h1 { margin-bottom: 1em; } +p { margin: 1em 0; } + +a { color: #00a; } +a:hover { color: #000; } +a:visited { color: #a0a; } + +table { + font-size: inherit; + font: 100%; +} + +/*****************************************************************************/ +/* +/* Home +/* +/*****************************************************************************/ +ul.posts { + list-style-type: none; + margin-bottom: 2em; +} + +ul.posts li { + line-height: 1.75em; +} + +ul.posts span { + color: #aaa; + font-family: Monaco, "Courier New", monospace; + font-size: 80%; +} + +/*****************************************************************************/ +/* +/* Site +/* +/*****************************************************************************/ + +.site { + font-size: 115%; + text-align: justify; + width: 42em; + margin: 3em auto 2em; + line-height: 1.5em; +} + +.site .header a { + font-weight: bold; + text-decoration: none; +} + +.site .header h1.title { + display: inline-block; + margin-bottom: 2em; +} + +.site .header h1.title a { + color: #a00; +} + +.site .header h1.title a:hover { + color: #000; +} + +.site .header a.extra { + color: #aaa; + margin-left: 1em; +} + +.site .header a.extra:hover { + color: #000; +} + +.site .meta { + color: #aaa; +} + +.site .footer { + font-size: 80%; + color: #666; + border-top: 4px solid #eee; + margin-top: 2em; + overflow: hidden; +} + +.site .footer .contact { + float: left; + margin-right: 3em; +} + +.site .footer .contact a { + color: #8085C1; +} + +.site .footer .rss { + margin-top: 1.1em; + margin-right: -.2em; + float: right; +} + +.site .footer .rss img { + border: 0; +} + +/*****************************************************************************/ +/* +/* Posts +/* +/*****************************************************************************/ + +/* standard */ +#post pre { + border: 1px solid #ddd; + background-color: #eef; + padding: 0 .4em; +} + +#post ul, #post ol { + margin-left: 1.35em; +} + +#post code { + border: 1px solid #ddd; + background-color: #eef; + padding: 0 .2em; +} + +#post pre code { + border: none; +} + +/* terminal */ +#post pre.terminal { + border: 1px solid #000; + background-color: #333; + color: #FFF; +} + +#post pre.terminal code { + background-color: #333; +} \ No newline at end of file diff --git a/css/react.css b/css/react.css new file mode 100644 index 0000000000..9a5779d1d2 --- /dev/null +++ b/css/react.css @@ -0,0 +1 @@ +html{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-family:proxima-nova,"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:300;color:#484848;line-height:1.28}p{margin:0 0 10px}.subHeader{font-size:21px;font-weight:200;line-height:30px;margin-bottom:10px}em{font-style:italic}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;color:#7b7b7b}h1,h2,h3{line-height:40px}h1{font-size:39px}h2{font-size:31px}h3{font-size:23px}h4{font-size:17px}h5{font-size:14px}h6{font-size:11px}h1 small{font-size:24px}h2 small{font-size:18px}h3 small{font-size:16px}h4 small{font-size:14px}ul,ol{margin:0 0 10px 25px;padding:0}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}a{color:#c05b4d;text-decoration:none}a:hover,a:focus{color:#a5473a;text-decoration:underline}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.center{text-align:center}html *{color-profile:sRGB;rendering-intent:auto}.cm-s-solarized-light{background-color:#f8f5ec;color:#637c84}.cm-s-solarized-light .emphasis{font-weight:bold}.cm-s-solarized-light .dotted{border-bottom:1px dotted #cb4b16}.cm-s-solarized-light .CodeMirror-gutter{background-color:#eee8d5;border-right:3px solid #eee8d5}.cm-s-solarized-light .CodeMirror-gutter .CodeMirror-gutter-text{color:#93a1a1}.cm-s-solarized-light .CodeMirror-cursor{border-left-color:#002b36 !important}.cm-s-solarized-light .CodeMirror-matchingbracket{color:#002b36;background-color:#eee8d5;box-shadow:0 0 10px #eee8d5;font-weight:bold}.cm-s-solarized-light .CodeMirror-nonmatchingbracket{color:#002b36;background-color:#eee8d5;box-shadow:0 0 10px #eee8d5;font-weight:bold;color:#dc322f;border-bottom:1px dotted #cb4b16}.cm-s-solarized-light span.cm-keyword{color:#268bd2}.cm-s-solarized-light span.cm-atom{color:#2aa198}.cm-s-solarized-light span.cm-number{color:#586e75}.cm-s-solarized-light span.cm-def{color:#637c84}.cm-s-solarized-light span.cm-variable{color:#637c84}.cm-s-solarized-light span.cm-variable-2{color:#b58900}.cm-s-solarized-light span.cm-variable-3{color:#cb4b16}.cm-s-solarized-light span.cm-comment{color:#93a1a1}.cm-s-solarized-light span.cm-property{color:#637c84}.cm-s-solarized-light span.cm-operator{color:#657b83}.cm-s-solarized-light span.cm-string{color:#36958e}.cm-s-solarized-light span.cm-error{font-weight:bold;border-bottom:1px dotted #cb4b16}.cm-s-solarized-light span.cm-bracket{color:#cb4b16}.cm-s-solarized-light span.cm-tag{color:#657b83}.cm-s-solarized-light span.cm-attribute{color:#586e75;font-weight:bold}.cm-s-solarized-light span.cm-meta{color:#268bd2}.cm-s-solarized-dark{background-color:#002b36;color:#839496}.cm-s-solarized-dark .emphasis{font-weight:bold}.cm-s-solarized-dark .dotted{border-bottom:1px dotted #cb4b16}.cm-s-solarized-dark .CodeMirror-gutter{background-color:#073642;border-right:3px solid #073642}.cm-s-solarized-dark .CodeMirror-gutter .CodeMirror-gutter-text{color:#586e75}.cm-s-solarized-dark .CodeMirror-cursor{border-left-color:#fdf6e3 !important}.cm-s-solarized-dark .CodeMirror-matchingbracket{color:#fdf6e3;background-color:#073642;box-shadow:0 0 10px #073642;font-weight:bold}.cm-s-solarized-dark .CodeMirror-nonmatchingbracket{color:#fdf6e3;background-color:#073642;box-shadow:0 0 10px #073642;font-weight:bold;color:#dc322f;border-bottom:1px dotted #cb4b16}.cm-s-solarized-dark span.cm-keyword{color:#839496;font-weight:bold}.cm-s-solarized-dark span.cm-atom{color:#2aa198}.cm-s-solarized-dark span.cm-number{color:#93a1a1}.cm-s-solarized-dark span.cm-def{color:#268bd2}.cm-s-solarized-dark span.cm-variable{color:#cb4b16}.cm-s-solarized-dark span.cm-variable-2{color:#cb4b16}.cm-s-solarized-dark span.cm-variable-3{color:#cb4b16}.cm-s-solarized-dark span.cm-comment{color:#586e75}.cm-s-solarized-dark span.cm-property{color:#b58900}.cm-s-solarized-dark span.cm-operator{color:#839496}.cm-s-solarized-dark span.cm-string{color:#6c71c4}.cm-s-solarized-dark span.cm-error{font-weight:bold;border-bottom:1px dotted #cb4b16}.cm-s-solarized-dark span.cm-bracket{color:#cb4b16}.cm-s-solarized-dark span.cm-tag{color:#839496}.cm-s-solarized-dark span.cm-attribute{color:#93a1a1;font-weight:bold}.cm-s-solarized-dark span.cm-meta{color:#268bd2}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:none;margin:0;padding:0}html{background:#f9f9f9}.left{float:left}.right{float:right}.container{padding-top:50px;min-width:960px}.wrap{width:960px;margin-left:auto;margin-right:auto;padding-left:20px;padding-right:20px}.skinnyWrap{width:690px;margin-left:auto;margin-right:auto;padding-left:20px;padding-right:20px}hr{height:0;border-top:1px solid #ccc;border-bottom:1px solid #eee}ul,li{margin-left:20px}.nav-main{*zoom:1;background:#222;color:#fafafa;position:fixed;top:0;height:50px;box-shadow:0 0 5px rgba(0,0,0,0.5);width:100%;z-index:100}.nav-main:before,.nav-main:after{content:" ";display:table}.nav-main:after{clear:both}.nav-main a{color:#e9e9e9;text-decoration:none}.nav-main .nav-site{float:right;margin:0}.nav-main .nav-site li{margin:0}.nav-main .nav-site a{padding:0 8px;text-transform:uppercase;letter-spacing:1px;line-height:50px;display:inline-block;height:50px;color:#aaa}.nav-main .nav-site a:hover{color:#fafafa}.nav-main .nav-site a.active{color:#fafafa;border-bottom:3px solid #cc7a6f;background:#333}.nav-main .nav-home{color:#00d8ff;font-size:24px;line-height:50px}.nav-main .nav-logo{background-image:url("../img/logo_small.png");vertical-align:middle}@media only screen and (-webkit-min-device-pixel-ratio: 1.3), only screen and (min--moz-device-pixel-ratio: 1.3), only screen and (-o-min-device-pixel-ratio: 1.3 / 1), only screen and (min-resolution: 125dpi), only screen and (min-resolution: 1.3dppx){.nav-main .nav-logo{background-image:url("../img/logo_small@2x.png");background-size:38px 38px}}.nav-main ul{display:inline}.nav-main li{display:inline}.hero{height:300px;background:#2d2d2d;padding-top:50px;color:#e9e9e9;font-weight:300}.hero .text{font-size:64px;text-align:center}.hero .minitext{font-size:16px;text-align:center;text-transform:uppercase}.hero strong{color:#61dafb;font-weight:400}.buttons-unit{margin-top:60px;text-align:center}.buttons-unit a{color:#61dafb}.buttons-unit .button{font-size:24px;background:#cc7a6f;color:#fafafa}.buttons-unit .button:active{background:#c5695c}.buttons-unit.downloads{margin:30px 0}.nav-docs{color:#2d2d2d;font-size:14px;float:left;top:100px;width:180px}.nav-docs ul{list-style:none;margin:0}.nav-docs li{margin:0}.nav-docs h3{text-transform:uppercase;font-size:14px}.nav-docs a{color:#666;display:block}.nav-docs a:hover{text-decoration:none;color:#cc7a6f}.nav-docs a.active{color:#cc7a6f}.nav-docs .nav-docs-section{border-bottom:1px solid #ccc;border-top:1px solid #eee;padding:12px 0}.nav-docs .nav-docs-section:first-child{padding-top:0;border-top:0}.nav-docs .nav-docs-section:last-child{padding-bottom:0;border-bottom:0}.home-section{margin:50px 0}.home-divider{border-top-color:#bbb;margin:0 auto;width:400px}.marketing-row{*zoom:1;margin:50px 0}.marketing-row:before,.marketing-row:after{content:" ";display:table}.marketing-row:after{clear:both}.marketing-col{float:left;margin-right:40px;width:280px}.marketing-col h3{color:#2d2d2d;font-size:24px;font-weight:normal;text-transform:uppercase}.marketing-col p{font-size:16px}.marketing-col:last-child{margin-right:0}#examples h3{color:#2d2d2d;font-size:24px;font-weight:normal;margin-bottom:5px}#examples p{margin:0 0 25px 0;max-width:600px}#examples .example{margin-top:60px}#examples #todoExample{font-size:14px}#examples #todoExample ul{list-style-type:square;margin:0 0 10px 0}#examples #todoExample input{border:1px solid #ccc;font:14px proxima-nova,"Helvetica Neue",Helvetica,Arial,sans-serif;padding:3px;width:150px}#examples #todoExample button{font:14px proxima-nova,"Helvetica Neue",Helvetica,Arial,sans-serif;margin-left:5px;padding:4px 10px}#examples #markdownExample textarea{border:1px solid #ccc;font:14px proxima-nova,"Helvetica Neue",Helvetica,Arial,sans-serif;margin-bottom:10px;padding:5px}.home-bottom-section{margin-bottom:100px}.docs-nextprev{*zoom:1}.docs-nextprev:before,.docs-nextprev:after{content:" ";display:table}.docs-nextprev:after{clear:both}.docs-prev{float:left}.docs-next{float:right}footer{font-size:13px;font-weight:600;margin-top:36px;margin-bottom:18px;overflow:auto}section.black content{padding-bottom:18px}.documentationContent{*zoom:1;padding-top:20px}.documentationContent:before,.documentationContent:after{content:" ";display:table}.documentationContent:after{clear:both}.documentationContent .subHeader{font-size:24px}.documentationContent h2{margin-top:30px}.documentationContent blockquote{padding:15px 30px 15px 15px;margin:20px 0;background-color:rgba(204,122,111,0.1);border-left:5px solid rgba(191,87,73,0.2)}.documentationContent blockquote h4{margin-top:0}.documentationContent blockquote p:last-child{margin-bottom:0}.documentationContent blockquote p:first-child{font-weight:bold;font-size:17.5px;line-height:20px;margin-top:0;text-rendering:optimizelegibility}.docs-prevnext{padding-top:40px;padding-bottom:40px}.button{background:-webkit-linear-gradient( #9a9a9a,#646464);background:linear-gradient( #9a9a9a,#646464);border-radius:4px;padding:8px 16px;font-size:18px;font-weight:400;margin:0 12px;display:inline-block;color:#fafafa;text-decoration:none;text-shadow:0 1px 3px rgba(0,0,0,0.3);box-shadow:0 1px 1px rgba(0,0,0,0.2);text-decoration:none}.button:hover{text-decoration:none}.button:active{box-shadow:none}.hero .button{box-shadow:1px 3px 3px rgba(0,0,0,0.3)}.button.blue{background:-webkit-linear-gradient( #77a3d2,#4783c2);background:linear-gradient( #77a3d2,#4783c2)}.row{padding-bottom:4px}.row .span4{width:33.33%;display:table-cell}.row .span8{width:66.66%;display:table-cell}.row .span6{width:50%;display:table-cell}p{margin:10px 0}.highlight{padding:10px;margin-bottom:20px}.inner-content{float:right;width:650px}.nosidebar .inner-content{float:none;margin:0 auto}div.CodeMirror pre,div.CodeMirror-linenumber,code{font-family:'source-code-pro', Menlo, 'Courier New', Consolas, monospace;font-size:13px;line-height:20px}div.CodeMirror-linenumber:after{content:'.'}.CodeMirror,div.CodeMirror-gutters,div.highlight{border:none}small code,li code,p code{color:#555;background-color:rgba(0,0,0,0.04);padding:1px 3px}.cm-s-default span.cm-string-2{color:inherit}.playground{*zoom:1}.playground:before,.playground:after{content:" ";display:table}.playground:after{clear:both}.playground::before{border-bottom:none !important;border-radius:3px 3px 0 0;padding:3px 7px;font-size:12px;font-weight:bold;color:#c2c0bc;background-color:#f1ede4;content:'Live editor'}.playground::before,.playgroundCode,.playgroundPreview{border:1px solid rgba(16,16,16,0.1)}.playgroundCode{border-radius:0 3px 3px 3px;float:left;overflow:hidden;width:600px}.playgroundPreview{background-color:white;border-radius:3px;float:right;padding:15px 20px;width:280px}.MarkdownEditor textarea{width:100%;height:100px}.hll{background-color:#f7ebc6;border-left:5px solid #f7d87c;display:block;margin-left:-14px;margin-right:-14px;padding-left:9px}.highlight .javascript .err{background-color:transparent;color:inherit}.highlight{position:relative;margin-bottom:14px;padding:30px 14px 14px;border:none;border-radius:0;overflow:auto}.highlight pre{padding:0;margin-top:0;margin-bottom:0;background-color:transparent;border:0}.highlight pre code{font-size:inherit}.highlight pre .lineno{display:inline-block;width:22px;padding-right:5px;margin-right:10px;color:#bebec5;text-align:right}.highlight:after{position:absolute;top:0;right:0;left:0;padding:3px 7px;font-size:12px;font-weight:bold;color:#c2c0bc;background-color:#f1ede4;content:"Code"}.downloadCenter{text-align:center;margin-top:20px;margin-bottom:25px}.downloadSection:hover{text-decoration:none !important}@media screen and (max-width: 960px){.nav-main{position:static}.container{padding-top:0}} diff --git a/css/syntax.css b/css/syntax.css new file mode 100644 index 0000000000..2728fc0edc --- /dev/null +++ b/css/syntax.css @@ -0,0 +1,409 @@ +.highlight pre code { + color: #637c84; +} + +.highlight { + color: #333333; + background: #f8f5ec; +} + +.highlight .c { + color: #93a1a1; +} + + +.highlight .g { + color: #637c84; +} + +/* Generic */ + +.highlight .k { + color: #859900; +} + +/* Keyword */ + +.highlight .l { + color: #637c84; +} + +/* Literal */ + +.highlight .n { + color: #637c84; +} + +/* Name */ + +.highlight .o { + color: #859900; +} + +/* Operator */ + +.highlight .x { + color: #cc7a6f; +} + +/* Other */ + +.highlight .p { + color: #637c84; +} + +/* Punctuation */ + +.highlight .cm { + color: #93a1a1; +} + +/* Comment.Multiline */ + +.highlight .cp { + color: #859900; +} + +/* Comment.Preproc */ + +.highlight .c1 { + color: #93a1a1; +} + +/* Comment.Single */ + +.highlight .cs { + color: #859900; +} + +/* Comment.Special */ + +.highlight .gd { + color: #36958e; +} + +/* Generic.Deleted */ + +.highlight .ge { + font-style: italic; + color: #637c84; +} + +/* Generic.Emph */ + +.highlight .gr { + color: #dc322f; +} + +/* Generic.Error */ + +.highlight .gh { + color: #cc7a6f; +} + +/* Generic.Heading */ + +.highlight .gi { + color: #859900; +} + +/* Generic.Inserted */ + +.highlight .go { + color: #637c84; +} + +/* Generic.Output */ + +.highlight .gp { + color: #637c84; +} + +/* Generic.Prompt */ + +.highlight .gs { + font-weight: bold; + color: #637c84; +} + +/* Generic.Strong */ + +.highlight .gu { + color: #cc7a6f; +} + +/* Generic.Subheading */ + +.highlight .gt { + color: #637c84; +} + +/* Generic.Traceback */ + +.highlight .kc { + color: #cc7a6f; +} + +/* Keyword.Constant */ + +.highlight .kd { + color: #268bd2; +} + +/* Keyword.Declaration */ + +.highlight .kn { + color: #859900; +} + +/* Keyword.Namespace */ + +.highlight .kp { + color: #859900; +} + +/* Keyword.Pseudo */ + +.highlight .kr { + color: #268bd2; +} + +/* Keyword.Reserved */ + +.highlight .kt { + color: #dc322f; +} + +/* Keyword.Type */ + +.highlight .ld { + color: #637c84; +} + +/* Literal.Date */ + +.highlight .m { + color: #36958e; +} + +/* Literal.Number */ + +.highlight .s { + color: #36958e; +} + +/* Literal.String */ + +.highlight .na { + color: #637c84; +} + +/* Name.Attribute */ + +.highlight .nb { + color: #b58900; +} + +/* Name.Builtin */ + +.highlight .nc { + color: #268bd2; +} + +/* Name.Class */ + +.highlight .no { + color: #cc7a6f; +} + +/* Name.Constant */ + +.highlight .nd { + color: #268bd2; +} + +/* Name.Decorator */ + +.highlight .ni { + color: #cc7a6f; +} + +/* Name.Entity */ + +.highlight .ne { + color: #cc7a6f; +} + +/* Name.Exception */ + +.highlight .nf { + color: #268bd2; +} + +/* Name.Function */ + +.highlight .nl { + color: #637c84; +} + +/* Name.Label */ + +.highlight .nn { + color: #637c84; +} + +/* Name.Namespace */ + +.highlight .nx { + color: #637c84; +} + +/* Name.Other */ + +.highlight .py { + color: #637c84; +} + +/* Name.Property */ + +.highlight .nt { + color: #268bd2; +} + +/* Name.Tag */ + +.highlight .nv { + color: #268bd2; +} + +/* Name.Variable */ + +.highlight .ow { + color: #859900; +} + +/* Operator.Word */ + +.highlight .w { + color: #637c84; +} + +/* Text.Whitespace */ + +.highlight .mf { + color: #36958e; +} + +/* Literal.Number.Float */ + +.highlight .mh { + color: #36958e; +} + +/* Literal.Number.Hex */ + +.highlight .mi { + color: #36958e; +} + +/* Literal.Number.Integer */ + +.highlight .mo { + color: #36958e; +} + +/* Literal.Number.Oct */ + +.highlight .sb { + color: #93a1a1; +} + +/* Literal.String.Backtick */ + +.highlight .sc { + color: #36958e; +} + +/* Literal.String.Char */ + +.highlight .sd { + color: #637c84; +} + +/* Literal.String.Doc */ + +.highlight .s2 { + color: #36958e; +} + +/* Literal.String.Double */ + +.highlight .se { + color: #cc7a6f; +} + +/* Literal.String.Escape */ + +.highlight .sh { + color: #637c84; +} + +/* Literal.String.Heredoc */ + +.highlight .si { + color: #36958e; +} + +/* Literal.String.Interpol */ + +.highlight .sx { + color: #36958e; +} + +/* Literal.String.Other */ + +.highlight .sr { + color: #dc322f; +} + +/* Literal.String.Regex */ + +.highlight .s1 { + color: #36958e; +} + +/* Literal.String.Single */ + +.highlight .ss { + color: #36958e; +} + +/* Literal.String.Symbol */ + +.highlight .bp { + color: #268bd2; +} + +/* Name.Builtin.Pseudo */ + +.highlight .vc { + color: #268bd2; +} + +/* Name.Variable.Class */ + +.highlight .vg { + color: #268bd2; +} + +/* Name.Variable.Global */ + +.highlight .vi { + color: #268bd2; +} + +/* Name.Variable.Instance */ + +.highlight .il { + color: #36958e; +} diff --git a/docs/advanced-components.html b/docs/advanced-components.html new file mode 100644 index 0000000000..71056a1dd6 --- /dev/null +++ b/docs/advanced-components.html @@ -0,0 +1,218 @@ + + + + + + React | Advanced Components + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

Advanced Components

+
How to build advanced composite components.
+

Composite components extend a ReactCompositeComponent base class that provides +a very powerful API that makes React flexible and able to easily work with other +libraries and frameworks.

+ +

Lifecycle Methods

+ +

Composite components can optionally implement lifecycle methods that are invoked +at various stages in the component lifecycle that +each have unique guarantees.

+ +

Mounting

+ +
    +
  • getInitialState(): object is invoked before a component is mounted. +Stateful components should implement this and return the initial state data.
  • +
  • componentWillMount() is invoked immediately before mounting occurs.
  • +
  • componentDidMount(DOMElement rootNode) is invoked immediately after +mounting occurs. Initialization that requires DOM nodes should go here.
  • +
+ +

Updating

+ +
    +
  • componentWillReceiveProps(object nextProps) is invoked when a mounted +component receives new props. This method should be used to compare +this.props and nextProps to perform state transitions using +this.setState().
  • +
  • shouldComponentUpdate(object nextProps, object nextState): boolean is +invoked when a component decides whether any changes warrant an update to the +DOM. Implement this as an optimization to compare this.props with +nextProps and this.state with nextState and return false if React +should skip updating.
  • +
  • componentWillUpdate(object nextProps, object nextState) is invoked +immediately before updating occurs. You cannot call this.setState() here.
  • +
  • componentDidUpdate(object prevProps, object prevState, DOMElement rootNode) +is invoked immediately after updating occurs.
  • +
+ +

Unmounting

+ +
    +
  • componentWillUnmount() is invoked immediately before a component is +unmounted and destroyed. Cleanup should go here.
  • +
+ +

Mounted Methods

+ +

Mounted composite components also support the following methods:

+ +
    +
  • getDOMNode(): DOMElement can be invoked on any mounted component in order +to obtain a reference to its rendered DOM node.
  • +
  • forceUpdate() can be invoked on any mounted component when you know that +some deeper aspect of the component's state has changed without using +this.setState().
  • +
+ +
+

Note:

+ +

The DOMElement rootNode argument of componentDidMount() and +componentDidUpdate() is a convenience. The same node can be obtained by +calling this.getDOMNode().

+
+ +

Component Refs

+ +

A common use case of event callbacks or the lifecycle methods is to operate on a +component returned by render(). For example, consider a search component that +should auto-focus the input once mounted:

+
var SearchForm = React.createClass({
+  render: function() {
+    return (
+      <form action={this.props.action}>
+        <input type="search" placeholder="Search..." />
+      </form>
+    );
+  },
+  componentDidMount: function(rootNode) {
+    var searchInput = rootNode.firstChild;
+    searchInput.focus();
+  }
+});
+
+

Although this implementation works, it is fragile because componentDidMount() +now relies on render() returning a particular DOM structure.

+ +

React provides a better way for composite components to reference components +that it constructs in its render() method through the use of refs. A component +can assign a ref to any component it constructs. This will create a reference +to those components on this.refs. For example:

+
var SearchForm = React.createClass({
+  render: function() {
+    return (
+      <form action={this.props.action}>
+        <input type="search" placeholder="Search..." ref="searchInput" />
+      </form>
+    );
+  },
+  componentDidMount: function(rootNode) {
+    var searchInput = this.refs.searchInput.getDOMNode();
+    searchInput.focus();
+  }
+});
+
+

In this example, this.refs.searchInput will reference the <input> component +and is available in most lifecycle methods and event callbacks. We obtain a +reference to the <input>'s DOM node using getDOMNode().

+ +
+

Note:

+ +

If you want to preserve compatibility with Google Closure Compiler's +property crushing in ADVANCED_OPTIMIZATIONS mode, make sure to use string +literals with this.refs.

+
+ + +
+ + ← Prev + + + Next → + +
+
+
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/docs/api.html b/docs/api.html new file mode 100644 index 0000000000..a93aa661bc --- /dev/null +++ b/docs/api.html @@ -0,0 +1,202 @@ + + + + + + React | React API + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

React API

+
+

React

+ +

React is the entry point to the React framework. If you're using one of the prebuilt packages it's available as a global; if you're using CommonJS modules you can require() it.

+ +

DOM

+ +

React.DOM provides all of the standard HTML tags needed to build a React app. You generally don't use it directly; instead, just include it as part of the /** @jsx React.DOM */ docblock.

+ +

initializeTouchEvents(boolean shouldUseTouch)

+ +

Configure React's event system to handle touch events on mobile devices.

+ +

function autoBind(function method)

+ +

Marks the provided function to be automatically bound to each React component instance created. This allows React components to define automatically bound methods and ensure that when called they will always reference their current instance.

+ +

Example:

+
React.createClass({
+  click: React.autoBind(function(evt) {
+    this.setState({jumping: true});
+  }),
+  render: function() {
+    // Look: no bind!
+    return <a onClick={this.click}>Jump</a>;
+  }
+});
+
+

function createClass(object specification)

+ +

Creates a component given a specification. A component implements a render method which returns a single child. That child may have an arbitrarily deep child structure. One thing that makes components different than a standard prototypal classes is that you don't need to call new on them. They are convenience wrappers that construct backing instances (via new) for you.

+ +

ReactComponent renderComponent(ReactComponent container, DOMElement mountPoint)

+ +

Renders a React component into the DOM in the supplied container.

+ +

If the React component was previously rendered into container, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React component.

+ +

AbstractEvent

+ +

Your event handlers will be passed instances of AbstractEvent, a cross-browser wrapper around the browser's native event. It has the same interface as the browser's native event (such as stopPropagation() and preventDefault()) except they work exactly the same across all browsers.

+ +

If you find that you need the underlying browser event for some reason, simply use the nativeEvent attribute to get it.

+ +

ReactComponent

+ +

Component classses created by createClass() return instances of ReactComponent when called. Most of the time when you're using React you're either creating or consuming ReactComponents.

+ +

DOMElement getDOMNode()

+ +

If this component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements.

+ +

setProps(object nextProps)

+ +

When you're integrating with an external JavaScript application you may want to signal a change to a React component rendered with renderComponent(). Simply call setProps() to change its properties and trigger a re-render.

+ +

Note: This method can only be called on a root-level component. That is, it's only available on the component passed directly to renderComponent() and none of its children. If you're inclined to use setProps() on a child component, instead take advantage of reactive updates and pass the new prop to the child component when it's created in render().

+ +

replaceProps(object nextProps)

+ +

Like setProps() but deletes any pre-existing props that are not in nextProps.

+ +

ReactComponent transferPropsTo(ReactComponent targetComponent)

+ +

Transfer properties from this component to a target component that have not already been set on the target component. This is usually used to pass down properties to the returned root component. targetComponent, now updated with some new props is returned as a convenience.

+ +

setState(object nextState)

+ +

Merges nextState with the current state. This is the primary method you use to trigger UI updates from event handlers and server request callbacks.

+ +

Note: NEVER mutate this.state directly. As calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

+ +

Note: setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

+ +

replaceState(object nextState)

+ +

Like setState() but deletes any pre-existing state keys that are not in nextState.

+ +

forceUpdate()

+ +

If your render() method reads from something other than this.props or this.state you'll need to tell React when it needs to re-run render(). Use forceUpdate() to cause React to automatically re-render. This will cause render() to be called on the component and all of its children but React will only update the DOM if the markup changes.

+ +

Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your application much simpler and more efficient.

+ +

object getInitialState()

+ +

componentWillMount()

+ +

componentDidMount(DOMElement domNode)

+ +

componentWillReceiveProps(object nextProps)

+ +

boolean shouldComponentUpdate(object nextProps, object nextState)

+ +

componentWillUpdate(object nextProps, object nextState)

+ +

ReactComponent render()

+ +

componentDidUpdate(object prevProps, object prevState, DOMElement domNode)

+ +

componentWillUnmount()

+ +

These are overridable lifecycle methods; see the lifecycle methods documentation for more information.

+ + +
+ + ← Prev + + +
+
+
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/docs/common-questions.html b/docs/common-questions.html new file mode 100644 index 0000000000..b6287556a2 --- /dev/null +++ b/docs/common-questions.html @@ -0,0 +1,117 @@ + + + + + + React | Common Questions + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

Common Questions

+
+

What browsers does React support?

+ +

React supports the latest two Chrome, Firefox, Safari, and Internet Explorer versions. React can work with Internet Explorer 8 with polyfills.

+ +

How do I get React to support Internet Explorer 8?

+ +

React requires ES5 JavaScript shims to run in Internet Explorer 8. Include the ES5 Shims to implement these shims.

+ +

Who uses React?

+ +

The Instagram website is built entirely in React. The Facebook website is also increasingly using React, including the common commenting plugin across the site.

+ +

Can I integrate with other JavaScript libraries?

+ +

Absolutely! In fact, we encourage it! See our GitHub repo for a TodoMVC example using Backbone and a jQuery + Bootstrap modal demo.

+ + +
+ + ← Prev + + + Next → + +
+
+
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/docs/component-basics.html b/docs/component-basics.html new file mode 100644 index 0000000000..feb23ed32b --- /dev/null +++ b/docs/component-basics.html @@ -0,0 +1,161 @@ + + + + + + React | Component Basics + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

Component Basics

+
What are components?
+

Components are the basic units of composition in React. Components encapsulate +the logic necessary to take input parameters and render markup. Components can +be rendered into an existing DOM element on the page by using +React.renderComponent:

+
// Replaces everything in `document.body` with <div>Hello, world!</div>;
+React.renderComponent(<div>Hello, world!</div>, document.body);
+
+

Keep in mind that <div> is not a DOM element! Keep reading...

+ +

Types of Components

+ +

There are two types of components:

+ +
    +
  • Composite Components
  • +
  • DOM Components
  • +
+ +

Composite Components such as TodoApp and Typeahead.

+ +

The majority of your React code will be implementing composite components.

+ +

Composite components are higher-level components with custom rendering logic +that may compose other composite components or DOM components.

+
/** @jsx React.DOM */
+var LinkButton = React.createClass({
+  render: function() {
+    return <a className="btn" />;
+  }
+});
+
+var myButton = <LinkButton />;
+
+

This example defines a LinkButton component class using React.createClass(), +and its render() method composes the <a> DOM component.

+ +

DOM Components such as div and span.

+ +

DOM components are the set of classes that correspond to browser DOM elements. +They are defined in React.DOM and can be brought "into scope" by setting +@jsx React.DOM in the docblock. See JSX Syntax for more +details.

+ +

Although React.DOM components look like browser DOM elements, they differ in a +few ways:

+ +
    +
  • All property names, including event handlers, are camelCased.
  • +
  • JavaScript identifiers should be used, namely className and htmlFor.
  • +
  • The style prop expects an object instead of a string. The object should map +camelCased style properties to values, e.g. {backgroundColor: '#fff'}.
  • +
+ +

Here is an example of a React link styled as a button with a click handler:

+
/** @jsx React.DOM */
+var handleClick = function() {alert('Clicked!');};
+var inlineStyle = {textDecoration: 'none'};
+
+var myLink = <a className="btn" onClick={handleClick} style={inlineStyle} />;
+
+ +
+ + ← Prev + + + Next → + +
+
+
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/docs/component-data.html b/docs/component-data.html new file mode 100644 index 0000000000..1e5e6fea19 --- /dev/null +++ b/docs/component-data.html @@ -0,0 +1,231 @@ + + + + + + React | Component Data + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

Component Data

+
How is data passed into a component?
+

Props

+ +

Components use data to determine what should be rendered. For example:

+
var LikeLink = React.createClass({
+  render: function() {
+    var text = this.props.liked ? 'Liked' : 'Like';
+    return <a>{text}</a>;
+  }
+});
+var myLikeLink = <LikeLink liked={false} />;
+
+

In this example, LikeLink takes liked as boolean data. This type of data +that is passed in is called a "prop". Examples of props on DOM components +include className and onClick.

+ +

Whenever a component's props change, its render() function will be +re-evaluated and the DOM will be updated. React will ensure that the DOM is +always kept up-to-date.

+ +

State

+ +

Let's build a small LikeApp application that makes use of the <LikeLink> +component from above. It should start off unliked and we should be able to like +it by clicking the link:

+
var LikeApp = React.createClass({
+  render: function() {
+    var isClicked = false;
+    return <LikeLink liked={isClicked} onClick={this.handleClick.bind(this)} />;
+  },
+  handleClick: function() {
+    // Somehow update `isClicked`.
+  }
+});
+
+

This renders a <LikeLink> with a click listener. However, it is not clear how +handleClick should update isClicked to true. LikeApp needs a way to store +state about whether or not it has been clicked.

+ +

State vs. Props

+ +

State is data that is managed internally by a composite component. Like props, +the render() function will be re-evaluated whenever state changes. Props and +state differ in that:

+ +
    +
  • Props are passed in from the creator.
  • +
  • State is private to and managed by the component.
  • +
+ +

Managing State

+ +

Let's update our LikeApp component using state:

+
var LikeApp = React.createClass({
+  getInitialState: function() {
+    return {isClicked: false};
+  },
+  render: function() {
+    var isClicked = this.state.isClicked;
+    return <LikeLink liked={isClicked} onClick={this.handleClick.bind(this)} />;
+  },
+  handleClick: function() {
+    this.setState({isClicked: true});
+  }
+});
+
+

There's a lot going on here, so let's work our way from top to bottom:

+ +
    +
  • getInitialState() describes what state data looks like when the component +is created.
  • +
  • In render(), state data can be accessed via this.state.
  • +
  • When the link is clicked, we update state using setState().
  • +
+ +

Now when we click the link, the <LikeLink> will get updated, right? Wrong.

+ +

Transferring Props

+ +

If you have been following carefully, you may have noticed that although we pass +a click handler into <LikeLink> as a prop, LikeLink does not do anything +with this.props.onClick! Let's fix that.

+
var LikeLink = React.createClass({
+  render: function() {
+    var text = this.props.liked ? 'Liked' : 'Like';
+    return <a onClick={this.props.onClick}>{text}</a>;
+  }
+});
+
+

Although this works, realize that this would quickly become tedious if we wanted +to also transfer href, title, target, and other events from this to the +rendered <a>. React provides a convenience method, transferPropsTo(), for +transferring props:

+
var LikeLink = React.createClass({
+  render: function() {
+    var text = this.props.liked ? 'Liked' : 'Like';
+    return this.transferPropsTo(<a>{text}</a>);
+  }
+});
+
+

This will transfer all props from this to the specified component (including +onClick).

+ +

Summary

+ +

Now we are done. LikeApp renders an unliked link which, when clicked, will:

+ +
    +
  1. Update the internal state of LikeApp.
  2. +
  3. Change the props passed into LikeLink.
  4. +
  5. Change the return value of render().
  6. +
  7. Trigger an update to the DOM.
  8. +
+ +

It's worth noting that React will handle new return values of render() by +making the mininal set of mutations necessary to bring the DOM up-to-date. In +this case, only the textContent of the rendered link will be mutated.

+ +

In summary:

+ +
    +
  • Props are passed in whereas state is managed internally by a component.
  • +
  • Never mutate this.props or this.state. You should pass props into other +components and mutate state using setState().
  • +
  • State is private. Never read state or call setState() on +anything but this.
  • +
  • Whenever props or state changes, render() will be re-evaluated and the DOM +updated. Also, render() should not depend on anything besides this.props +and this.state.
  • +
+ + +
+ + ← Prev + + + Next → + +
+
+
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/docs/component-lifecycle.html b/docs/component-lifecycle.html new file mode 100644 index 0000000000..832a2b73de --- /dev/null +++ b/docs/component-lifecycle.html @@ -0,0 +1,172 @@ + + + + + + React | Component Lifecycle + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

Component Lifecycle

+
What happens when I render a React component?
+

Mounting

+ +

We have previously seen how to render components into +existing DOM elements on the page:

+
React.renderComponent(<div>Hello, world!</div>, document.body);
+
+

In this one simple line, we have accomplished the following:

+ +
    +
  • A <div> (defined by React.DOM.div) component is instantiated.
  • +
  • The component is mounted into document.body.
  • +
+ +

Mounting is the process of initializing a React component by creating its +DOM nodes and inserting the them into a supplied container node.

+ +

At this point, the entire page consists of a single <div> with "Hello, +world!".

+ +

Updating

+ +

Let's add a second call to React.renderComponent() after three +seconds:

+
React.renderComponent(<div>Hello, world!</div>, document.body);
+setTimeout(function() {
+  React.renderComponent(<div>Goodbye, world.</div>, document.body);
+}, 3000);
+
+

The second call to React.renderComponent() will trigger the following:

+ +
    +
  • The <div> component will check the new props to see if anything changed.
  • +
  • The set of changes are used to update the DOM node as necessary.
  • +
+ +

Updating is the process of mutating the rendered DOM nodes and occurs +whenever either props or state has changed. This ensures that the rendered DOM +is consistent with the data.

+ +

Unmounting

+ +

Let's add one final call to React.renderComponent() after another three +seconds:

+
React.renderComponent(<div>Hello, world!</div>, document.body);
+setTimeout(function() {
+  React.renderComponent(<div>Goodbye, world.</div>, document.body);
+}, 3000);
+setTimeout(function() {
+  React.renderComponent(<img src="/images/fin.png" />, document.body);
+}, 6000);
+
+

The third call to React.renderComponent() will trigger the following:

+ +
    +
  • An <img> (defined by React.DOM.img) component is instantiated.
  • +
  • React will compare the <div> component with the <img> component.
  • +
  • Since the component class is different, the <div> component will be +unmounted.
  • +
  • The <img> component will then be mounted into document.body.
  • +
+ +

Unmounting is the process of releasing resources that have been allocated by +a component. This allows user interfaces built with React to live long without +memory leaks.

+ +

Components can also be unmounted using +React.unmountAndReleaseReactRootNode():

+
React.unmountAndReleaseReactRootNode(document.body);
+
+

This will unmount any components mounted immediately within document.body.

+ + +
+ + ← Prev + + + Next → + +
+
+
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/docs/event-handling.html b/docs/event-handling.html new file mode 100644 index 0000000000..8922245376 --- /dev/null +++ b/docs/event-handling.html @@ -0,0 +1,206 @@ + + + + + + React | Event Handling + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

Event Handling

+
How do events work with React components?
+

Events in React work the way they do with HTML, except the event names are +camelCased.

+
var Clicker = React.createClass({
+  render: function() {
+    return <span onClick={this.handleClick}>Click me!</span>;
+  },
+  handleClick: function(event) {
+    alert('You clicked me!');
+  }
+});
+
+

When <Clicker> is clicked, the handleClick() function will get fired. Under +the hood, React uses top-level event delegation to achieve high performance.

+ +

Automatically Binding Callbacks

+ +

Just like any callback in JavaScript, if you want to refer to the component as +this from the callback, you need to bind the callback to the component:

+
var Clicker = React.createClass({
+  render: function() {
+    var handleClick = this.handleClick.bind(this);
+    return <span onClick={handleClick}>Click me!</span>;
+  },
+  handleClick: function(event) {
+    alert(this.ALERT_MESSAGE);
+  },
+  ALERT_MESSAGE: 'You clicked me!'
+});
+
+

React provides a convenient and efficient way to bind methods using +React.autoBind():

+
var Clicker = React.createClass({
+  render: function() {
+    return <span onClick={this.handleClick}>Click me!</span>;
+  },
+  handleClick: React.autoBind(function(event) {
+    alert(this.ALERT_MESSAGE);
+  }),
+  ALERT_MESSAGE: 'You clicked me!'
+});
+
+
+

Note:

+ +

Binding a function allocates memory to create a new bound function. Since +render() may be invoked many times, it is a bad place to bind functions. +React.autoBind() sidesteps this issue by only binding once at instantiation +time.

+
+ +

DOM Events

+ +

React uses top-level event delegation +to achieve high performance when implementing DOM events. For each type of DOM +event, React adds a single top-level listener and determines which event +handlers to execute by simulating event capturing and bubbling.

+ +

DOM event handlers are called with a normalized AbstractEvent object that has +cross-browser compatible implementations of stopPropagation and +preventDefault(). If you need access to the raw browser event, you can use the +nativeEvent property.

+ +
+

Note:

+ +

The AbstractEvent object is JSON serializable so that React applications can +be executed inside web workers.

+
+ +

Touch Events

+ +

If you want to use touch events, you must configure React's event system to +initialize them:

+
// Invoke before calling `React.renderComponent()`.
+React.initializeTouchEvents(true);
+
+

Custom Events

+ +

Notice that event listeners are attached by simply passing them into components +as props. For DOM components, events are handled using top-level event +delegation. For composite components, event handling is up to the component's +implementation.

+ +

Here is an example of a toggle link that fires a custom onToggle event:

+
var ToggleLink = React.createClass({
+  getInitialState: function() {
+    return {isEnabled: false};
+  },
+  render: function() {
+    return <a onClick={this.handleClick}>Toggle</a>;
+  },
+  handleClick: React.autoBind(function() {
+    var willEnable = !this.state.isEnabled;
+    if (this.props.onToggle) {
+      this.props.onToggle(willEnable)
+    }
+    this.setState({isEnabled: willEnable});
+  })
+});
+
+var handleToggle = function(enabled) {
+  alert(enabled ? 'Enabled.' : 'Disabled.');
+};
+var myToggleLink = <ToggleLink onToggle={handleToggle} />;
+
+ +
+ + ← Prev + + + Next → + +
+
+
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/docs/getting-started.html b/docs/getting-started.html new file mode 100644 index 0000000000..d6fa5c9ce6 --- /dev/null +++ b/docs/getting-started.html @@ -0,0 +1,179 @@ + + + + + + React | Getting Started + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

Getting Started

+
+

Download the starter kit to get started.

+ + + +

Hello, world!

+ +

In the root directory of the starter kit, create a helloworld.html with the following contents.

+
<!DOCTYPE html>
+<html>
+  <head>
+    <script src="build/react.min.js"></script>
+    <script src="build/JSXTransformer.js"></script>
+  </head>
+  <body>
+    <div id="example"></div>
+    <script type="text/jsx">
+      /** @jsx React.DOM */
+      React.renderComponent(
+        <h1>Hello, world!</h1>,
+        document.getElementById('example')
+      );
+    </script>
+  </body>
+</html>
+
+

The XML syntax inside of JavaScript is called JSX; check out the JSX syntax to learn more about it. In order to translate it to vanilla JavaScript we use <script type="text/jsx"> and include JSXTransformer.js to actually perform the transformation in the browser.

+ +

Separate File

+ +

Your React JSX file can live in a separate file. Create the following src/helloworld.js.

+
/** @jsx React.DOM */
+React.renderComponent(
+  <h1>Hello, world!</h1>,
+  document.getElementById('example')
+);
+
+

Then reference it from helloworld.html:

+
<script type="text/jsx" src="src/helloworld.js"></script>
+
+

Offline Transform

+ +

First install the command-line tools (requires npm):

+
npm install -g react-tools
+
+

Then, translate your src/helloworld.js file to plain JavaScript:

+
jsx --watch src/ build/
+
+

The file build/helloworld.js is autogenerated whenever you make a change.

+
/** @jsx React.DOM */
+React.renderComponent(
+  React.DOM.h1(null, 'Hello, world!'),
+  document.getElementyById('example')
+);
+
+

Update your HTML file as below:

+
<!DOCTYPE html>
+<html>
+  <head>
+    <title>Hello React!</title>
+    <script src="build/react.min.js"></script>
+    <!-- No need for JSXTransformer! -->
+  </head>
+  <body>
+    <div id="example"></div>
+    <script src="build/helloworld.js"></script>
+  </body>
+</html>
+
+

Want CommonJS?

+ +

If you want to use React within a module system, fork our repo, npm install and run grunt. A nice set of CommonJS modules will be generated. Our jsx build tool can be integrated into most packaging systems (not just CommonJS) quite easily.

+ +

Next Steps

+ +

Check out the tutorial and the other examples in the /examples directory to learn more. Good luck, and welcome!

+ + +
+ + + Next → + +
+
+
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/docs/syntax.html b/docs/syntax.html new file mode 100644 index 0000000000..63b71bc09f --- /dev/null +++ b/docs/syntax.html @@ -0,0 +1,235 @@ + + + + + + React | JSX Syntax + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

JSX Syntax

+
Writing JavaScript with XML syntax.
+

JSX is a JavaScript XML syntax extension recommended (but not required) for use +with React.

+ +

JSX makes code that deeply nested React components more readable, and writing it +feels like writing HTML. React documentation examples make use of JSX.

+ +

The Transform

+ +

JSX transforms XML-like syntax into native JavaScript. It turns XML elements and +attributes into function calls and objects, respectively.

+
var Nav;
+// Input (JSX):
+var app = <Nav color="blue" />;
+// Output (JS):
+var app = Nav({color:'blue'});
+
+

Notice that in order to use <Nav />, the Nav variable must be in scope.

+ +

JSX also allows specifying children using XML syntax:

+
var Nav, Profile;
+// Input (JSX):
+var app = <Nav color="blue"><Profile>click</Profile></Nav>;
+// Output (JS):
+var app = Nav({color:'blue'}, Profile({}, 'click'));
+
+

The Getting Started guide shows how to setup JSX +compilation.

+ +
+

Note:

+ +

Details about the code transform are given here to increase understanding, but +your code should not rely on these implementation details.

+
+ +

React and JSX

+ +

React and JSX are independent technologies, but JSX was primarily built with +React in mind. The two valid uses of JSX are:

+ +
    +
  • To construct instances of React DOM components (React.DOM.*).
  • +
  • To construct instances of composite components created with +React.createClass().
  • +
+ +

React DOM Components

+ +

To construct a <div> is to create a variable that refers to React.DOM.div.

+
var div = React.DOM.div;
+var app = <div className="appClass">Hello, React!</div>;
+
+

React Component Components

+ +

To construct an instance of a composite component, create a variable that +references the class.

+
var MyComponent = React.createClass({/*...*/});
+var app = <MyComponent someProperty={true} />;
+
+

See Component Basics to learn more about components.

+ +
+

Note:

+ +

Since JSX is JavaScript, identifiers such as class and for are discouraged +as XML attribute names. Instead, React DOM components expect attributes like +className and htmlFor, respectively.

+
+ +

DOM Convenience

+ +

Having to define variables for every type of DOM element can get tedious +(e.g. var div, span, h1, h2, ...). JSX provides a convenience to address this +problem by allowing you to specify a variable in an @jsx docblock field. JSX +will use that field to find DOM components.

+
/**
+ * @jsx React.DOM
+ */
+var Nav;
+// Input (JSX):
+var tree = <Nav><span /></Nav>;
+// Output (JS):
+var tree = Nav({}, React.DOM.span({}));
+
+
+

Remember:

+ +

JSX simply transforms elements into function calls and has no notion of the +DOM. The docblock parameter is only a convenience to resolve the most commonly +used elements. In general, JSX has no notion of the DOM.

+
+ +

JavaScript Expressions

+ +

Attribute Expressions

+ +

To use a JavaScript expression as an attribute value, wrap the expression in a +pair of curly braces ({}) instead of quotes ("").

+
// Input (JSX):
+var person = <Person name={window.isLoggedIn ? window.name : ''} />;
+// Output (JS):
+var person = Person({name: window.isLoggedIn ? window.name : ''});
+
+

Child Expressions

+ +

Likewise, JavaScript expressions may be used to express children:

+
// Input (JSX):
+var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
+// Output (JS):
+var content = Container({}, window.isLoggedIn ? <Nav /> : <Login />);
+
+

Tooling

+ +

Beyond the compilation step, JSX does not require any special tools.

+ +
    +
  • Many editors already include reasonable support for JSX (Vim, Emacs js2-mode).
  • +
  • Linting provides accurate line numbers after compiling without sourcemaps.
  • +
  • Elements use standard scoping so linters can find usage of out-of-scope +components.
  • +
+ +

Prior Work

+ +

JSX is similar to several other JavaScript embedded XML language +proposals/projects. Some of the features of JSX that distinguish it from similar +efforts include:

+ +
    +
  • JSX is a simple syntactic transform.
  • +
  • JSX neither provides nor requires a runtime library.
  • +
  • JSX does not alter or add to the semantics of JavaScript.
  • +
+ + +
+ + ← Prev + + + Next → + +
+
+
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/docs/tutorial.html b/docs/tutorial.html new file mode 100644 index 0000000000..9e12fbe3ab --- /dev/null +++ b/docs/tutorial.html @@ -0,0 +1,700 @@ + + + + + + React | Tutorial + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

Tutorial

+
+

We'll be building a simple, but realistic comments box that you can drop into a blog, similar to Disqus, LiveFyre or Facebook comments.

+ +

We'll provide:

+ +
    +
  • A view of all of the comments
  • +
  • A form to submit a comment
  • +
  • Hooks for you to provide a custom backend
  • +
+ +

It'll also have a few neat features:

+ +
    +
  • Optimistic commenting: comments appear in the list before they're saved on the server so it feels fast.
  • +
  • Live updates: as other users comment we'll pop them into the comment view in real time
  • +
  • Markdown formatting: users can use Markdown to format their text
  • +
+ +

Getting started

+ +

For this tutorial we'll use prebuilt JavaScript files on a CDN. Open up your favorite editor and create a new HTML document:

+
<!-- template.html -->
+<html>
+  <head>
+    <title>Hello React</title>
+    <script src="http://fb.me/react-0.3.0.js"></script>
+    <script src="http://fb.me/JSXTransformer-0.3.0.js"></script>
+  </head>
+  <body>
+    <div id="content"></div>
+    <script type="text/jsx">
+      /**
+       * @jsx React.DOM
+       */
+      // Your code here
+    </script>
+  </body>
+</html>
+
+

For the remainder of this tutorial, we'll be writing our JavaScript code in this script tag.

+ +

Your first component

+ +

React is all about modular, composable components. For our comment box example, we'll have the following component structure:

+
- CommentBox
+  - CommentList
+    - Comment
+  - CommentForm
+
+

Let's build the CommentBox component, which is just a simple <div>:

+
// tutorial1.js
+var CommentBox = React.createClass({
+  render: function() {
+    return (
+      <div class="commentBox">
+        Hello, world! I am a CommentBox.
+      </div>
+    );
+  }
+});
+React.renderComponent(
+  <CommentBox />,
+  document.getElementById('content')
+);
+
+

JSX Syntax

+ +

The first thing you'll notice is the XML-ish syntax in your JavaScript. We have a simple precompiler that translates the syntactic sugar to this plain JavaScript:

+
// tutorial1-raw.js
+var CommentBox = React.createClass({
+  render: function() {
+    return (
+      ReactDOM.div({
+        className: 'commentBox',
+        children: 'Hello, world! I am a CommentBox.'
+      })
+    );
+  }
+});
+React.renderComponent(
+  CommentBox({}),
+  document.getElementById('content')
+);
+
+

Its use is optional but we've found JSX syntax easier to use than plain JavaScript. Read more on the JSX Syntax article.

+ +

What's going on

+ +

We pass some methods in a JavaScript object to React.createClass() to create a new React component. The most important of these methods is called render which returns a tree of React components that will eventually render to HTML.

+ +

The <div> tags are not actual DOM nodes; they are instantiations of React div components. You can think of these as markers or pieces of data that React knows how to handle. React is safe. We are not generating HTML strings so XSS protection is the default.

+ +

You do not have to return basic HTML. You can return a tree of components that you (or someone else built). This is what makes React composable: a key tenet of maintainable frontends.

+ +

React.renderComponent() instantiates the root component, starts the framework, and injects the markup into a raw DOM element, provided as the second argument.

+ +

Composing components

+ +

Let's build skeletons for CommentList and CommentForm which will, again, be simple <div>s:

+
// tutorial2.js
+var CommentList = React.createClass({
+  render: function() {
+    return (
+      <div class="commentList">
+        Hello, world! I am a CommentList.
+      </div>
+    );
+  }
+});
+
+var CommentForm = React.createClass({
+  render: function() {
+    return (
+      <div class="commentForm">
+        Hello, world! I am a CommentForm.
+      </div>
+    );
+  }
+});
+
+

Next, update the CommentBox component to use its new friends:

+
// tutorial3.js
+var CommentBox = React.createClass({
+  render: function() {
+    return (
+      <div class="commentBox">
+        <h1>Comments</h1>
+        <CommentList />
+        <CommentForm />
+      </div>
+    );
+  }
+});
+
+

Notice how we're mixing HTML tags and components we've built. HTML components are regular React components, just like the ones you define, with one difference. The JSX compiler will automatically rewrite HTML tags to "ReactDOM.tagName" expressions and leave everything else alone. This is to prevent the pollution of the global namespace.

+ +

Component Properties

+ +

Let's create our third component, Comment. We will want to pass it the author name and comment text so we can reuse the same code for each unique comment. First let's add some comments to the CommentList:

+
// tutorial4.js
+var CommentList = React.createClass({
+  render: function() {
+    return (
+      <div class="commentList">
+        <Comment author="Pete Hunt">This is one comment</Comment>
+        <Comment author="Jordan Walke">This is *another* comment</Comment>
+      </div>
+    );
+  }
+});
+
+

Note that we have passed some data from the parent CommentList component to the child Comment component as both XML-like children and attributes. Data passed from parent to child is called props, short for properties.

+ +

Using props

+ +

Let's create the Comment component. It will read the data passed to it from the CommentList and render some markup:

+
// tutorial5.js
+var Comment = React.createClass({
+  render: function() {
+    return (
+      <div class="comment">
+        <h2 class="commentAuthor">
+          {this.props.author}
+        </h2>
+        {this.props.children}
+      </div>
+    );
+  }
+});
+
+

By surrounding a JavaScript expression in braces inside JSX (as either an attribute or child), you can drop text or React components into the tree. We access named attributes passed to the component as keys on this.props and any nested elements as this.props.children.

+ +

Adding Markdown

+ +

Markdown is a simple way to format your text inline. For example, surrounding text with asterisks will make it emphasized.

+ +

First, add the third-party Showdown library to your application. This is a JavaScript library which takes Markdown text and converts it to raw HTML. This requires a script tag in your head (which we have already included in the React playground).

+ +

Next, let's convert the comment text to Markdown and output it:

+
// tutorial6.js
+var converter = new Showdown.converter();
+var Comment = React.createClass({
+  render: function() {
+    return (
+      <div class="comment">
+        <h2 class="commentAuthor">
+          {this.props.author}
+        </h2>
+        {converter.makeHtml(this.props.children.toString())}
+      </div>
+    );
+  }
+});
+
+

All we're doing here is calling the Showdown library. We need to convert this.props.children from React's wrapped text to a raw string that Showdown will understand so we explicitly call toString().

+ +

But there's a problem! Our rendered comments look like this in the browser: "<p>This is <em>another</em> comment</p>". We want those tags to actually render as HTML.

+ +

That's React protecting you from an XSS attack. There's a way to get around it but the framework warns you not to use it:

+
// tutorial7.js
+var converter = new Showdown.converter();
+var Comment = React.createClass({
+  render: function() {
+    var rawMarkup = converter.makeHtml(this.props.children.toString());
+    return (
+      <div class="comment">
+        <h2 class="commentAuthor">
+          {this.props.author}
+        </h2>
+        <span dangerouslySetInnerHTML={{__html: rawMarkup}} />
+      </div>
+    );
+  }
+});
+
+

This is a special API that intentionally makes it difficult to insert raw HTML, but for Showdown we'll take advantage of this backdoor.

+ +

Remember: by using this feature you're relying on Showdown to be secure.

+ +

Hook up the data model

+ +

So far we've been inserting the comments directly in the source code. Instead, let's render a blob of JSON data into the comment list. Eventually this will come from the server, but for now, write it in your source:

+
// tutorial8.js
+var data = [
+  {author: 'Pete Hunt', text: 'This is one comment'},
+  {author: 'Jordan Walke', text: 'This is *another* comment'}
+];
+
+

We need to get this data into CommentList in a modular way. Modify CommentBox and the renderComponent() call to pass this data into the CommentList via props:

+
// tutorial9.js
+var CommentBox = React.createClass({
+  render: function() {
+    return (
+      <div class="commentBox">
+        <h1>Comments</h1>
+        <CommentList data={this.props.data} />
+        <CommentForm />
+      </div>
+    );
+  }
+});
+
+React.renderComponent(
+  <CommentBox data={data} />,
+  document.getElementById('content')
+);
+
+

Now that the data is available in the CommentList, let's render the comments dynamically:

+
// tutorial10.js
+var CommentList = React.createClass({
+  render: function() {
+    var commentNodes = this.props.data.map(function (comment) {
+      return <Comment author={comment.author}>{comment.text}</Comment>;
+    });
+    return (
+      <div class="commentList">
+        {commentNodes}
+      </div>
+    );
+  }
+});
+
+

That's it!

+ +

Fetching from the server

+ +

Let's replace the hard-coded data with some dynamic data from the server. We will remove the data prop and replace it with a URL to fetch:

+
// tutorial11.js
+React.renderComponent(
+  <CommentBox url="comments.json" />,
+  document.getElementById('example')
+);
+
+

This component is different from the prior components because it will have to re-render itself. The component won't have any data until the request from the server comes back, at which point the component may need to render some new comments.

+ +

Reactive state

+ +

So far, each component has rendered itself once based on its props. props are immutable: they are passed from the parent and are "owned" by the parent. To implement interactions, we introduce mutable state to the component. this.state is private to the component and can be changed by calling this.setState(). When the state is updated, the component re-renders itself.

+ +

render() methods are written declaratively as functions of this.props and this.state. The framework guarantees the UI is always consistent with the inputs.

+ +

When the server fetches data, we will be changing the comment data we have. Let's add an array of comment data to the CommentBox component as its state:

+
// tutorial12.js
+var CommentBox = React.createClass({
+  getInitialState: function() {
+    return {data: []};
+  },
+  render: function() {
+    return (
+      <div class="commentBox">
+        <h1>Comments</h1>
+        <CommentList data={this.state.data} />
+        <CommentForm />
+      </div>
+    );
+  }
+});
+
+

getInitialState() executes exactly once during the lifecycle of the component and sets up the initial state of the component.

+ +

Updating state

+ +

When the component is first created, we want to GET some JSON from the server and update the state to reflect the latest data. In a real application this would be a dynamic endpoint, but for this example, we will use a static JSON file to keep things simple:

+
// tutorial13.json
+[
+  {'author': 'Pete Hunt', 'text': 'This is one comment'},
+  {'author': 'Jordan Walke', 'text': 'This is *another* comment'}
+]
+
+

We will use jQuery 1.5 to help make an asynchronous request to the server.

+ +

Note: because this is becoming an AJAX application you'll need to develop your app using a web server rather than as a file sitting on your file system. The easiest way to do this is to run python -m SimpleHTTPServer in your application's directory.

+
// tutorial13.js
+var CommentBox = React.createClass({
+  getInitialState: function() {
+    $.ajax({
+      url: 'comments.json',
+      dataType: 'json',
+      mimeType: 'textPlain',
+      success: function(data) {
+        this.setState({data: data});
+      }.bind(this)
+    });
+    return {data: []};
+  },
+  render: function() {
+    return (
+      <div class="commentBox">
+        <h1>Comments</h1>
+        <CommentList data={this.state.data} />
+        <CommentForm />
+      </div>
+    );
+  }
+});
+
+

The key is the call to this.setState(). We replace the old array of comments with the new one from the server and the UI automatically updates itself. Because of this reactivity, it is trivial to add live updates. We will use simple polling here but you could easily use WebSockets or other technologies.

+
// tutorial14.js
+var CommentBox = React.createClass({
+  loadCommentsFromServer: function() {
+    $.ajax({
+      url: this.props.url,
+      dataType: 'json',
+      mimeType: 'textPlain',
+      success: function(data) {
+        this.setState({data: data});
+      }.bind(this)
+    });
+  },
+  getInitialState: function() {
+    return {data: []};
+  },
+  componentWillMount: function() {
+    this.loadCommentsFromServer();
+    setInterval(
+      this.loadCommentsFromServer.bind(this),
+      this.props.pollInterval
+    );
+  },
+  render: function() {
+    return (
+      <div class="commentBox">
+        <h1>Comments</h1>
+        <CommentList data={this.state.data} />
+        <CommentForm />
+      </div>
+    );
+  }
+});
+
+React.renderComponent(
+  <CommentBox url="comments.json" pollInterval={5000} />,
+  document.getElementById('content')
+);
+
+

All we have done here is move the AJAX call to a separate method and call it when the component is first loaded and every 60 seconds after that. Try running this in your browser and changing the comments.json file; within 5 seconds, the changes will show!

+ +

Adding new comments

+ +

Now it's time to build the form. Our CommentForm component should ask the user for their name and comment text and send a request to the server to save the comment.

+
// tutorial15.js
+var CommentForm = React.createClass({
+  render: function() {
+    return (
+      <form class="commentForm">
+        <input type="text" placeholder="Your name" />
+        <input type="text" placeholder="Say something..." />
+      </form>
+    );
+  }
+});
+
+

Let's make the form interactive. When the user presses enter, we should clear the form, submit a request to the server, and refresh the list of comments. To start, let's listen for this event and just clear the form.

+
// tutorial16.js
+var CommentForm = React.createClass({
+  handleSubmit: React.autoBind(function() {
+    var author = this.refs.author.getDOMNode().value.trim();
+    var text = this.refs.text.getDOMNode().value.trim();
+    if (!text || !author) {
+      return;
+    }
+    // TODO: send request to the server
+    this.refs.author.getDOMNode().value = '';
+    this.refs.text.getDOMNode().value = '';
+  }),
+  render: function() {
+    return (
+      <form class="commentForm" onSubmit={this.handleSubmit}>
+        <input type="text" placeholder="Your name" ref="author" />
+        <input
+          type="text"
+          placeholder="Say something..."
+          ref="text"
+        />
+      </form>
+    );
+  }
+});
+
+

Events

+ +

React attaches event handlers to components using a camelCase naming convention. We attach an onKeyUp handler to the text field, check if the user has entered text and pressed the enter key and then clear the form fields.

+ +

React.autoBind() is a simple way to ensure that a method is always bound to its component. Inside the method, this will be bound to the component instance.

+ +

Refs

+ +

We use the ref attribute to assign a name to a child component and this.refs to reference the component. We can call getDOMNode() on a component to get the native browser DOM element.

+ +

Callbacks as props

+ +

When a user submits a comment, we will need to refresh the list of comments to include the new one. It makes sense to do all of this logic in CommentBox since CommentBox owns the state that represents the list of comments.

+ +

We need to pass data from the child component to its parent. We do this by passing a callback in props from parent to child:

+
// tutorial17.js
+var CommentBox = React.createClass({
+  loadCommentsFromServer: function() {
+    $.ajax({
+      url: this.props.url,
+      dataType: 'json',
+      mimeType: 'textPlain',
+      success: function(data) {
+        this.setState({data: data});
+      }.bind(this)
+    });
+  },
+  handleCommentSubmit: React.autoBind(function(comment) {
+    // TODO: submit to the server and refresh the list
+  }),
+  getInitialState: function() {
+    return {data: []};
+  },
+  componentWillMount: function() {
+    this.loadCommentsFromServer();
+    setInterval(
+      this.loadCommentsFromServer.bind(this),
+      this.props.pollInterval
+    );
+  },
+  render: function() {
+    return (
+      <div class="commentBox">
+        <h1>Comments</h1>
+        <CommentList data={this.state.data} />
+        <CommentForm
+          onCommentSubmit={this.handleCommentSubmit}
+        />
+      </div>
+    );
+  }
+});
+
+

Let's call the callback from the CommentForm when the user presses enter:

+
// tutorial18.js
+var CommentForm = React.createClass({
+  handleSubmit: React.autoBind(function() {
+    var author = this.refs.author.getDOMNode().value.trim();
+    var text = this.refs.text.getDOMNode().value.trim();
+    this.props.onCommentSubmit({author: author, text: text});
+    this.refs.author.getDOMNode().value = '';
+    this.refs.text.getDOMNode().value = '';
+  }),
+  render: function() {
+    return (
+      <form class="commentForm" onSubmit={this.handleSubmit}>
+        <input type="text" placeholder="Your name" ref="author" />
+        <input
+          type="text"
+          placeholder="Say something..."
+          ref="text"
+        />
+      </form>
+    );
+  }
+});
+
+

Now that the callbacks are in place, all we have to do is submit to the server and refresh the list:

+
// tutorial19.js
+var CommentBox = React.createClass({
+  loadCommentsFromServer: function() {
+    $.ajax({
+      url: this.props.url,
+      dataType: 'json',
+      mimeType: 'textPlain',
+      success: function(data) {
+        this.setState({data: data});
+      }.bind(this)
+    });
+  },
+  handleCommentSubmit: React.autoBind(function(comment) {
+    $.ajax({
+      url: this.props.url,
+      data: comment,
+      dataType: 'json',
+      mimeType: 'textPlain',
+      success: function(data) {
+        this.setState({data: data});
+      }.bind(this)
+    });
+  }),
+  getInitialState: function() {
+    return {data: []};
+  },
+  componentWillMount: function() {
+    this.loadCommentsFromServer();
+    setInterval(
+      this.loadCommentsFromServer.bind(this),
+      this.props.pollInterval
+    );
+  },
+  render: function() {
+    return (
+      <div class="commentBox">
+        <h1>Comments</h1>
+        <CommentList data={this.state.data} />
+        <CommentForm
+          onCommentSubmit={this.handleCommentSubmit}
+        />
+      </div>
+    );
+  }
+});
+
+

Optimization: optimistic updates

+ +

Our application is now feature complete but it feels slow to have to wait for the request to complete before your comment appears in the list. We can optimistically add this comment to the list to make the app feel faster.

+
// tutorial20.js
+var CommentBox = React.createClass({
+  loadCommentsFromServer: function() {
+    $.ajax({
+      url: this.props.url,
+      dataType: 'json',
+      mimeType: 'textPlain',
+      success: function(data) {
+        this.setState({data: data});
+      }.bind(this)
+    });
+  },
+  handleCommentSubmit: React.autoBind(function(comment) {
+    var comments = this.state.data;
+    comments.push(comment);
+    this.setState({data: comments});
+    $.ajax({
+      url: this.props.url,
+      data: comment,
+      dataType: 'json',
+      mimeType: 'textPlain',
+      success: function(data) {
+        this.setState({data: data});
+      }.bind(this)
+    });
+  }),
+  getInitialState: function() {
+    return {data: []};
+  },
+  componentWillMount: function() {
+    this.loadCommentsFromServer();
+    setInterval(
+      this.loadCommentsFromServer.bind(this),
+      this.props.pollInterval
+    );
+  },
+  render: function() {
+    return (
+      <div class="commentBox">
+        <h1>Comments</h1>
+        <CommentList data={this.state.data} />
+        <CommentForm
+          onCommentSubmit={this.handleCommentSubmit}
+        />
+      </div>
+    );
+  }
+});
+
+

Congrats!

+ +

You have just built a comment box in a few simple steps. Learn more about React in the reference or start hacking! Good luck!

+ + +
+ + ← Prev + + + Next → + +
+
+
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/downloads.html b/downloads.html new file mode 100644 index 0000000000..e2aa65997f --- /dev/null +++ b/downloads.html @@ -0,0 +1,109 @@ + + + + + + React | Downloads + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+

Downloads

+
+

Download the starter kit to get everything you need to +get started with React.

+ + + +

Individual Downloads

+ +

React Core 0.3.0 (production)

+ +

The compressed, production version of React core

+ +

React Core 0.3.0 (development)

+ +

The uncompressed, development version of React core with inline documentation.

+ +

JSX Transform

+ +

The JSX transformer used to support XML syntax in JavaScript.

+ +

Bower

+
$ bower install react
+
+

NPM

+
$ npm install -g react-tools
+
+

Release Notes

+ +

0.3 Initial public release.

+ +

0.2 Standardize API & refactor component lifecycle. Normalize DOM interactions.

+ +

0.1 Initial release.

+ + +
+ + +
+
+
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/downloads/react-0.3.0.zip b/downloads/react-0.3.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..665a39d7a88208b57d7c72fa92f2a39898baa9a4 GIT binary patch literal 396526 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 z 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%0A^WpWvJMM-1W&wv|;oJ3l^8hdzKIz*UVM? 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

X}sBS8!Y!j>wqPLEVgA787Ir^yZp1#> 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 z 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', ''); + var extracted = codeSample.match(PARTS); + if (!extracted) { + throw new Error('Code sample did not match correct format in ' + filename + ': ' + truncate(codeSample)); + } + var filename = extracted[1]; + var content = extracted[2].replace(/\*\*/g, ''); + fs.writeFileSync(argv.dest + '/' + filename, content); + }); + }); +} + +main(argv.dest, argv._); \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5c125de5d897c1ff5692a656485b3216123dcd89 GIT binary patch literal 24838 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 S;((SPO-)H#vF3?I`2PWAQ(w*i literal 0 HcmV?d00001 diff --git a/img/logo_small.png b/img/logo_small.png new file mode 100644 index 0000000000000000000000000000000000000000..eea1f6744ae2534b360b70f8682ff49f409b2a9c GIT binary patch literal 2834 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 + + + + + React | A JavaScript library for building user interfaces + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + +
+
+
React
+
+ A JavaScript library for building user interfaces +
+ + +
+
+ + +
+

+
+
+

Declarative

+

+ React uses a declarative paradigm that makes it easier to reason about + your application. +

+
+
+

Efficient

+

+ React minimizes interactions with the DOM by using a mock representation + of the DOM. +

+
+
+

Flexible

+

+ React works with the libraries and frameworks that you already know. +

+
+
+
+
+
+
+
+

A Simple Component

+

+ React components implement a render() method that takes input data and + returns what to display. This example constructs the component using an + XML-like syntax called JSX. Input data is passed to the component as XML + attributes, and render() accesses this data via this.props. +

+
+
+
+

A Stateful Component

+

+ In addition to taking data from its creator (accessed via this.props), + a component can maintain internal state data (accessed via + this.state). When a component's state data changes, the rendered + markup will be updated by re-invoking render(). +

+
+
+
+

An Application

+

+ Using properties and state, we can put together a small Todo + application. React provides an interface to the DOM via refs. Although + event handlers appear to be rendered inline, they will be + collected and implemented using event delegation. +

+
+
+
+

A Component Using External Plugins

+

+ React is flexible and provides hooks that allow you to interface with + other libraries and frameworks. This example uses Showdown, an external + Markdown library, to convert the textarea's value in real-time. +

+
+
+
+ + + + +
+
+
+ +

+ +
+ + +
+
A Facebook & Instagram collaboration.
+
© 2013 Facebook Inc.
+
+
+ + + diff --git a/js/JSXTransformer.js b/js/JSXTransformer.js new file mode 100644 index 0000000000..9b8f610bc8 --- /dev/null +++ b/js/JSXTransformer.js @@ -0,0 +1,10139 @@ +/** + * JSXTransformer v0.3.0 + */ +(function(e){if("function"==typeof bootstrap)bootstrap("jsxtransformer",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeJSXTransformer=e}else"undefined"!=typeof window?window.JSXTransformer=e():global.JSXTransformer=e()})(function(){var define,ses,bootstrap,module,exports; +return (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s orderedListOfVisitors. + */ +var transformVisitors = { + 'es6-classes': [ + classes.visitClassExpression, + classes.visitClassDeclaration, + classes.visitSuperCall, + classes.visitPrivateProperty + ] +}; + +transformVisitors.react = transformVisitors[ + "es6-classes" +].concat([ + react.visitReactTag, + reactDisplayName.visitReactDisplayName +]); + +/** + * Specifies the order in which each transform should run. + */ +var transformRunOrder = [ + 'es6-classes', + 'react' +]; + +/** + * Given a list of transform names, return the ordered list of visitors to be + * passed to the transform() function. + * + * @param {array?} excludes + * @return {array} + */ +function getVisitorsList(excludes) { + var ret = []; + for (var i = 0, il = transformRunOrder.length; i < il; i++) { + if (!excludes || excludes.indexOf(transformRunOrder[i]) === -1) { + ret = ret.concat(transformVisitors[transformRunOrder[i]]); + } + } + return ret; +} + +exports.getVisitorsList = getVisitorsList; +exports.transformVisitors = transformVisitors; + +})() +},{"./transforms/classes":5,"./transforms/react":6,"./transforms/reactDisplayName":7}],8:[function(require,module,exports){ +(function(){/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*global exports:true*/ + +/** + * State represents the given parser state. It has a local and global parts. + * Global contains parser position, source, etc. Local contains scope based + * properties, like current class name. State should contain all the info + * required for transformation. It's the only mandatory object that is being + * passed to every function in transform chain. + * + * @param {String} source + * @param {Object} transformOptions + * @return {Object} + */ +function createState(source, transformOptions) { + return { + /** + * Name of the super class variable + * @type {String} + */ + superVar: '', + /** + * Name of the enclosing class scope + * @type {String} + */ + scopeName: '', + /** + * Global state (not affected by updateState) + * @type {Object} + */ + g: { + /** + * A set of general options that transformations can consider while doing + * a transformation: + * + * - minify + * Specifies that transformation steps should do their best to minify + * the output source when possible. This is useful for places where + * minification optimizations are possible with higher-level context + * info than what jsxmin can provide. + * + * For example, the ES6 class transform will minify munged private + * variables if this flag is set. + */ + opts: transformOptions, + /** + * Current position in the source code + * @type {Number} + */ + position: 0, + /** + * Buffer containing the result + * @type {String} + */ + buffer: '', + /** + * Indentation offset (only negative offset is supported now) + * @type {Number} + */ + indentBy: 0, + /** + * Source that is being transformed + * @type {String} + */ + source: source, + + /** + * Cached parsed docblock (see getDocblock) + * @type {object} + */ + docblock: null, + + /** + * Whether the thing was used + * @type {Boolean} + */ + tagNamespaceUsed: false, + + /** + * If using bolt xjs transformation + * @type {Boolean} + */ + isBolt: undefined, + + /** + * Whether to record source map (expensive) or not + * @type {SourceMapGenerator|null} + */ + sourceMap: null, + + /** + * Filename of the file being processed. Will be returned as a source + * attribute in the source map + */ + sourceMapFilename: 'source.js', + + /** + * Only when source map is used: last line in the source for which + * source map was generated + * @type {Number} + */ + sourceLine: 1, + + /** + * Only when source map is used: last line in the buffer for which + * source map was generated + * @type {Number} + */ + bufferLine: 1, + + /** + * The top-level Program AST for the original file. + */ + originalProgramAST: null, + + sourceColumn: 0, + bufferColumn: 0 + } + }; +} + +/** + * Updates a copy of a given state with "update" and returns an updated state. + * + * @param {Object} state + * @param {Object} update + * @return {Object} + */ +function updateState(state, update) { + return { + g: state.g, + superVar: update.superVar || state.superVar, + scopeName: update.scopeName || state.scopeName + }; +} + +/** + * Given a state fill the resulting buffer from the original source up to + * the end + * @param {Number} end + * @param {Object} state + * @param {Function?} contentTransformer Optional callback to transform newly + * added content. + */ +function catchup(end, state, contentTransformer) { + if (end < state.g.position) { + // cannot move backwards + return; + } + var source = state.g.source.substring(state.g.position, end); + var transformed = updateIndent(source, state); + if (state.g.sourceMap && transformed) { + // record where we are + state.g.sourceMap.addMapping({ + generated: { line: state.g.bufferLine, column: state.g.bufferColumn }, + original: { line: state.g.sourceLine, column: state.g.sourceColumn }, + source: state.g.sourceMapFilename + }); + + // record line breaks in transformed source + var sourceLines = source.split('\n'); + var transformedLines = transformed.split('\n'); + // Add line break mappings between last known mapping and the end of the + // added piece. So for the code piece + // (foo, bar); + // > var x = 2; + // > var b = 3; + // var c = + // only add lines marked with ">": 2, 3. + for (var i = 1; i < sourceLines.length - 1; i++) { + state.g.sourceMap.addMapping({ + generated: { line: state.g.bufferLine, column: 0 }, + original: { line: state.g.sourceLine, column: 0 }, + source: state.g.sourceMapFilename + }); + state.g.sourceLine++; + state.g.bufferLine++; + } + // offset for the last piece + if (sourceLines.length > 1) { + state.g.sourceLine++; + state.g.bufferLine++; + state.g.sourceColumn = 0; + state.g.bufferColumn = 0; + } + state.g.sourceColumn += sourceLines[sourceLines.length - 1].length; + state.g.bufferColumn += + transformedLines[transformedLines.length - 1].length; + } + state.g.buffer += + contentTransformer ? contentTransformer(transformed) : transformed; + state.g.position = end; +} + +/** + * Applies `catchup` but passing in a function that removes any non-whitespace + * characters. + */ +var re = /(\S)/g; +function stripNonWhite(value) { + return value.replace(re, function() { + return ''; + }); +} +/** + * Catches up as `catchup` but turns each non-white character into a space. + */ +function catchupWhiteSpace(end, state) { + catchup(end, state, stripNonWhite); +} + +/** + * Same as catchup but does not touch the buffer + * @param {Number} end + * @param {Object} state + */ +function move(end, state) { + // move the internal cursors + if (state.g.sourceMap) { + if (end < state.g.position) { + state.g.position = 0; + state.g.sourceLine = 1; + state.g.sourceColumn = 0; + } + + var source = state.g.source.substring(state.g.position, end); + var sourceLines = source.split('\n'); + if (sourceLines.length > 1) { + state.g.sourceLine += sourceLines.length - 1; + state.g.sourceColumn = 0; + } + state.g.sourceColumn += sourceLines[sourceLines.length - 1].length; + } + state.g.position = end; +} + +/** + * Appends a string of text to the buffer + * @param {String} string + * @param {Object} state + */ +function append(string, state) { + if (state.g.sourceMap && string) { + state.g.sourceMap.addMapping({ + generated: { line: state.g.bufferLine, column: state.g.bufferColumn }, + original: { line: state.g.sourceLine, column: state.g.sourceColumn }, + source: state.g.sourceMapFilename + }); + var transformedLines = string.split('\n'); + if (transformedLines.length > 1) { + state.g.bufferLine += transformedLines.length - 1; + state.g.bufferColumn = 0; + } + state.g.bufferColumn += + transformedLines[transformedLines.length - 1].length; + } + state.g.buffer += string; +} + +/** + * Update indent using state.indentBy property. Indent is measured in + * double spaces. Updates a single line only. + * + * @param {String} str + * @param {Object} state + * @return {String} + */ +function updateIndent(str, state) { + for (var i = 0; i < -state.g.indentBy; i++) { + str = str.replace(/(^|\n)( {2}|\t)/g, '$1'); + } + return str; +} + +/** + * Calculates indent from the beginning of the line until "start" or the first + * character before start. + * @example + * " foo.bar()" + * ^ + * start + * indent will be 2 + * + * @param {Number} start + * @param {Object} state + * @return {Number} + */ +function indentBefore(start, state) { + var end = start; + start = start - 1; + + while (start > 0 && state.g.source[start] != '\n') { + if (!state.g.source[start].match(/[ \t]/)) { + end = start; + } + start--; + } + return state.g.source.substring(start + 1, end); +} + +function getDocblock(state) { + if (!state.g.docblock) { + var docblock = require('./docblock'); + state.g.docblock = + docblock.parseAsObject(docblock.extract(state.g.source)); + } + return state.g.docblock; +} + +exports.catchup = catchup; +exports.catchupWhiteSpace = catchupWhiteSpace; +exports.append = append; +exports.move = move; +exports.updateIndent = updateIndent; +exports.indentBefore = indentBefore; +exports.updateState = updateState; +exports.createState = createState; +exports.getDocblock = getDocblock; + +})() +},{"./docblock":4}],2:[function(require,module,exports){ +(function(){/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*global exports:true*/ +/*jslint node: true*/ +"use strict"; + +/** + * Syntax transfomer for javascript. Takes the source in, spits the source + * out. Tries to maintain readability and preserve whitespace and line numbers + * where posssible. + * + * Support + * - ES6 class transformation + private property munging, see ./classes.js + * - React XHP style syntax transformations, see ./react.js + * - Bolt XHP style syntax transformations, see ./bolt.js + * + * The general flow is the following: + * - Parse the source with our customized esprima-parser + * https://github.com/voloko/esprima. We have to customize the parser to + * support non-standard XHP-style syntax. We parse the source range: true + * option that forces esprima to return positions in the source within + * resulting parse tree. + * + * - Traverse resulting syntax tree, trying to apply a set of visitors to each + * node. Each visitor should provide a .test() function that tests if the + * visitor can process a given node. + * + * - Visitor is responsible for code generation for a given syntax node. + * Generated code is stored in state.g.buffer that is passed to every + * visitor. It's up to the visitor to process the code the way it sees fit. + * All of the current visitors however use both the node and the original + * source to generate transformed code. They use nodes to generate new + * code and they copy the original source, preserving whitespace and comments, + * for the parts they don't care about. + */ +var esprima = require('esprima'); + +var createState = require('./utils').createState; +var catchup = require('./utils').catchup; + +/** + * @param {object} object + * @param {function} visitor + * @param {array} path + * @param {object} state + */ +function traverse(object, path, state) { + var key, child; + + if (walker(traverse, object, path, state) === false) { + return; + } + path.unshift(object); + for (key in object) { + // skip obviously wrong attributes + if (key === 'range' || key === 'loc') { + continue; + } + if (object.hasOwnProperty(key)) { + child = object[key]; + if (typeof child === 'object' && child !== null) { + child.range && catchup(child.range[0], state); + traverse(child, path, state); + child.range && catchup(child.range[1], state); + } + } + } + path.shift(); +} + +function walker(traverse, object, path, state) { + var visitors = state.g.visitors; + for (var i = 0; i < visitors.length; i++) { + if (visitors[i].test(object, path, state)) { + return visitors[i](traverse, object, path, state); + } + } +} + +function runPass(source, visitors, options) { + var ast = esprima.parse(source, { comment: true, loc: true, range: true }); + var state = createState(source, options); + state.g.originalProgramAST = ast; + state.g.visitors = visitors; + + if (options.sourceMap) { + var SourceMapGenerator = require('source-map').SourceMapGenerator; + state.g.sourceMap = new SourceMapGenerator({ file: 'transformed.js' }); + } + traverse(ast, [], state); + catchup(source.length, state); + return state; +} + +/** + * Applies all available transformations to the source + * @param {array} visitors + * @param {string} source + * @param {?object} options + * @return {object} + */ +function transform(visitors, source, options) { + options = options || {}; + + var state = runPass(source, visitors, options); + var sourceMap = state.g.sourceMap; + + if (sourceMap) { + return { + sourceMap: sourceMap, + sourceMapFilename: options.filename || 'source.js', + code: state.g.buffer + }; + } else { + return { + code: state.g.buffer + }; + } +} + + +exports.transform = transform; + +})() +},{"./utils":8,"esprima":9,"source-map":10}],9:[function(require,module,exports){ +(function(){/* + Copyright (C) 2013 Thaddee Tyl + Copyright (C) 2012 Ariya Hidayat + Copyright (C) 2012 Mathias Bynens + Copyright (C) 2012 Joost-Wim Boekesteijn + Copyright (C) 2012 Kris Kowal + Copyright (C) 2012 Yusuke Suzuki + Copyright (C) 2012 Arpad Borsos + Copyright (C) 2011 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*jslint bitwise:true plusplus:true */ +/*global esprima:true, define:true, exports:true, window: true, +throwError: true, generateStatement: true, peek: true, +parseAssignmentExpression: true, parseBlock: true, +parseClassExpression: true, parseClassDeclaration: true, parseExpression: true, +parseForStatement: true, +parseFunctionDeclaration: true, parseFunctionExpression: true, +parseFunctionSourceElements: true, parseVariableIdentifier: true, +parseImportSpecifier: true, +parseLeftHandSideExpression: true, parseParams: true, validateParam: true, +parseSpreadOrAssignmentExpression: true, +parseStatement: true, parseSourceElement: true, parseModuleBlock: true, parseConciseBody: true, +advanceXJSChild: true, isXJSIdentifierStart: true, isXJSIdentifierPart: true, +scanXJSStringLiteral: true, scanXJSIdentifier: true, +parseXJSAttributeValue: true, parseXJSChild: true, parseXJSElement: true, parseXJSExpression: true, +parseYieldExpression: true +*/ + +(function (root, factory) { + 'use strict'; + + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // Rhino, and plain browser loading. + if (typeof define === 'function' && define.amd) { + define(['exports'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory((root.esprima = {})); + } +}(this, function (exports) { + 'use strict'; + + var Token, + TokenName, + FnExprTokens, + Syntax, + PropertyKind, + Messages, + Regex, + SyntaxTreeDelegate, + XHTMLEntities, + ClassPropertyType, + source, + strict, + index, + lineNumber, + lineStart, + length, + delegate, + lookahead, + state, + extra; + + Token = { + BooleanLiteral: 1, + EOF: 2, + Identifier: 3, + Keyword: 4, + NullLiteral: 5, + NumericLiteral: 6, + Punctuator: 7, + StringLiteral: 8, + RegularExpression: 9, + Template: 10, + XJSIdentifier: 11, + XJSText: 12 + }; + + TokenName = {}; + TokenName[Token.BooleanLiteral] = 'Boolean'; + TokenName[Token.EOF] = ''; + TokenName[Token.Identifier] = 'Identifier'; + TokenName[Token.Keyword] = 'Keyword'; + TokenName[Token.NullLiteral] = 'Null'; + TokenName[Token.NumericLiteral] = 'Numeric'; + TokenName[Token.Punctuator] = 'Punctuator'; + TokenName[Token.StringLiteral] = 'String'; + TokenName[Token.XJSIdentifier] = 'XJSIdentifier'; + TokenName[Token.XJSText] = 'XJSText'; + TokenName[Token.RegularExpression] = 'RegularExpression'; + + // A function following one of those tokens is an expression. + FnExprTokens = ["(", "{", "[", "in", "typeof", "instanceof", "new", + "return", "case", "delete", "throw", "void", + // assignment operators + "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", + "&=", "|=", "^=", ",", + // binary/unary operators + "+", "-", "*", "/", "%", "++", "--", "<<", ">>", ">>>", "&", + "|", "^", "!", "~", "&&", "||", "?", ":", "===", "==", ">=", + "<=", "<", ">", "!=", "!=="]; + + Syntax = { + ArrayExpression: 'ArrayExpression', + ArrayPattern: 'ArrayPattern', + ArrowFunctionExpression: 'ArrowFunctionExpression', + AssignmentExpression: 'AssignmentExpression', + BinaryExpression: 'BinaryExpression', + BlockStatement: 'BlockStatement', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ClassBody: 'ClassBody', + ClassDeclaration: 'ClassDeclaration', + ClassExpression: 'ClassExpression', + ClassHeritage: 'ClassHeritage', + ComprehensionBlock: 'ComprehensionBlock', + ComprehensionExpression: 'ComprehensionExpression', + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DebuggerStatement: 'DebuggerStatement', + DoWhileStatement: 'DoWhileStatement', + EmptyStatement: 'EmptyStatement', + ExportDeclaration: 'ExportDeclaration', + ExportSpecifier: 'ExportSpecifier', + ExportSpecifierSet: 'ExportSpecifierSet', + ExpressionStatement: 'ExpressionStatement', + ForInStatement: 'ForInStatement', + ForOfStatement: 'ForOfStatement', + ForStatement: 'ForStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + Glob: 'Glob', + Identifier: 'Identifier', + IfStatement: 'IfStatement', + ImportDeclaration: 'ImportDeclaration', + ImportSpecifier: 'ImportSpecifier', + LabeledStatement: 'LabeledStatement', + Literal: 'Literal', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + MethodDefinition: 'MethodDefinition', + ModuleDeclaration: 'ModuleDeclaration', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + ObjectPattern: 'ObjectPattern', + Path: 'Path', + Program: 'Program', + Property: 'Property', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SpreadElement: 'SpreadElement', + SwitchCase: 'SwitchCase', + SwitchStatement: 'SwitchStatement', + TaggedTemplateExpression: 'TaggedTemplateExpression', + TemplateElement: 'TemplateElement', + TemplateLiteral: 'TemplateLiteral', + ThisExpression: 'ThisExpression', + ThrowStatement: 'ThrowStatement', + TryStatement: 'TryStatement', + UnaryExpression: 'UnaryExpression', + UpdateExpression: 'UpdateExpression', + VariableDeclaration: 'VariableDeclaration', + VariableDeclarator: 'VariableDeclarator', + WhileStatement: 'WhileStatement', + WithStatement: 'WithStatement', + XJSIdentifier: 'XJSIdentifier', + XJSExpression: 'XJSExpression', + XJSElement: 'XJSElement', + XJSClosingElement: 'XJSClosingElement', + XJSOpeningElement: 'XJSOpeningElement', + XJSAttribute: 'XJSAttribute', + XJSText: 'XJSText', + YieldExpression: 'YieldExpression' + }; + + PropertyKind = { + Data: 1, + Get: 2, + Set: 4 + }; + + ClassPropertyType = { + static: 1, + prototype: 2 + }; + + // Error messages should be identical to V8. + Messages = { + UnexpectedToken: 'Unexpected token %0', + UnexpectedNumber: 'Unexpected number', + UnexpectedString: 'Unexpected string', + UnexpectedIdentifier: 'Unexpected identifier', + UnexpectedReserved: 'Unexpected reserved word', + UnexpectedTemplate: 'Unexpected quasi %0', + UnexpectedEOS: 'Unexpected end of input', + NewlineAfterThrow: 'Illegal newline after throw', + InvalidRegExp: 'Invalid regular expression', + UnterminatedRegExp: 'Invalid regular expression: missing /', + InvalidLHSInAssignment: 'Invalid left-hand side in assignment', + InvalidLHSInFormalsList: 'Invalid left-hand side in formals list', + InvalidLHSInForIn: 'Invalid left-hand side in for-in', + MultipleDefaultsInSwitch: 'More than one default clause in switch statement', + NoCatchOrFinally: 'Missing catch or finally after try', + UnknownLabel: 'Undefined label \'%0\'', + Redeclaration: '%0 \'%1\' has already been declared', + IllegalContinue: 'Illegal continue statement', + IllegalBreak: 'Illegal break statement', + IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition', + IllegalReturn: 'Illegal return statement', + IllegalYield: 'Illegal yield expression', + IllegalSpread: 'Illegal spread element', + StrictModeWith: 'Strict mode code may not include a with statement', + StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', + StrictVarName: 'Variable name may not be eval or arguments in strict mode', + StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', + StrictParamDupe: 'Strict mode function may not have duplicate parameter names', + ParameterAfterRestParameter: 'Rest parameter must be final parameter of an argument list', + ElementAfterSpreadElement: 'Spread must be the final element of an element list', + ObjectPatternAsRestParameter: 'Invalid rest parameter', + ObjectPatternAsSpread: 'Invalid spread argument', + StrictFunctionName: 'Function name may not be eval or arguments in strict mode', + StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', + StrictDelete: 'Delete of an unqualified identifier in strict mode.', + StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', + AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', + AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', + StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', + StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', + StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', + StrictReservedWord: 'Use of future reserved word in strict mode', + NoFromAfterImport: 'Missing from after import', + NoYieldInGenerator: 'Missing yield in generator', + NoUnintializedConst: 'Const must be initialized', + ComprehensionRequiresBlock: 'Comprehension must have at least one block', + ComprehensionError: 'Comprehension Error', + EachNotAllowed: 'Each is not supported', + InvalidXJSTagName: 'XJS tag name can not be empty', + InvalidXJSAttributeValue: 'XJS value should be either an expression or a quoted XJS text', + ExpectedXJSClosingTag: 'Expected corresponding XJS closing tag for %0' + }; + + // See also tools/generate-unicode-regex.py. + Regex = { + NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), + NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') + }; + + // Ensure the condition is true, otherwise throw an error. + // This is only to have a better contract semantic, i.e. another safety net + // to catch a logic error. The condition shall be fulfilled in normal case. + // Do NOT use this to enforce a certain condition on any user input. + + function assert(condition, message) { + if (!condition) { + throw new Error('ASSERT: ' + message); + } + } + + function isDecimalDigit(ch) { + return (ch >= 48 && ch <= 57); // 0..9 + } + + function isHexDigit(ch) { + return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; + } + + function isOctalDigit(ch) { + return '01234567'.indexOf(ch) >= 0; + } + + + // 7.2 White Space + + function isWhiteSpace(ch) { + return (ch === 32) || // space + (ch === 9) || // tab + (ch === 0xB) || + (ch === 0xC) || + (ch === 0xA0) || + (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0); + } + + // 7.3 Line Terminators + + function isLineTerminator(ch) { + return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029); + } + + // 7.6 Identifier Names and Identifiers + + function isIdentifierStart(ch) { + return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) + (ch >= 65 && ch <= 90) || // A..Z + (ch >= 97 && ch <= 122) || // a..z + (ch === 92) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch))); + } + + function isIdentifierPart(ch) { + return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) + (ch >= 65 && ch <= 90) || // A..Z + (ch >= 97 && ch <= 122) || // a..z + (ch >= 48 && ch <= 57) || // 0..9 + (ch === 92) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch))); + } + + // 7.6.1.2 Future Reserved Words + + function isFutureReservedWord(id) { + switch (id) { + case 'class': + case 'enum': + case 'export': + case 'extends': + case 'import': + case 'super': + return true; + default: + return false; + } + } + + function isStrictModeReservedWord(id) { + switch (id) { + case 'implements': + case 'interface': + case 'package': + case 'private': + case 'protected': + case 'public': + case 'static': + case 'yield': + case 'let': + return true; + default: + return false; + } + } + + function isRestrictedWord(id) { + return id === 'eval' || id === 'arguments'; + } + + // 7.6.1.1 Keywords + + function isKeyword(id) { + if (strict && isStrictModeReservedWord(id)) { + return true; + } + + // 'const' is specialized as Keyword in V8. + // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next. + // Some others are from future reserved words. + + switch (id.length) { + case 2: + return (id === 'if') || (id === 'in') || (id === 'do'); + case 3: + return (id === 'var') || (id === 'for') || (id === 'new') || + (id === 'try') || (id === 'let'); + case 4: + return (id === 'this') || (id === 'else') || (id === 'case') || + (id === 'void') || (id === 'with') || (id === 'enum'); + case 5: + return (id === 'while') || (id === 'break') || (id === 'catch') || + (id === 'throw') || (id === 'const') || (id === 'yield') || + (id === 'class') || (id === 'super'); + case 6: + return (id === 'return') || (id === 'typeof') || (id === 'delete') || + (id === 'switch') || (id === 'export') || (id === 'import'); + case 7: + return (id === 'default') || (id === 'finally') || (id === 'extends'); + case 8: + return (id === 'function') || (id === 'continue') || (id === 'debugger'); + case 10: + return (id === 'instanceof'); + default: + return false; + } + } + + // 7.4 Comments + + function skipComment() { + var ch, blockComment, lineComment; + + blockComment = false; + lineComment = false; + + while (index < length) { + ch = source.charCodeAt(index); + + if (lineComment) { + ++index; + if (isLineTerminator(ch)) { + lineComment = false; + if (ch === 13 && source.charCodeAt(index) === 10) { + ++index; + } + ++lineNumber; + lineStart = index; + } + } else if (blockComment) { + if (isLineTerminator(ch)) { + if (ch === 13 && source.charCodeAt(index + 1) === 10) { + ++index; + } + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + ch = source.charCodeAt(index++); + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + // Block comment ends with '*/' (char #42, char #47). + if (ch === 42) { + ch = source.charCodeAt(index); + if (ch === 47) { + ++index; + blockComment = false; + } + } + } + } else if (ch === 47) { + ch = source.charCodeAt(index + 1); + // Line comment starts with '//' (char #47, char #47). + if (ch === 47) { + index += 2; + lineComment = true; + } else if (ch === 42) { + // Block comment starts with '/*' (char #47, char #42). + index += 2; + blockComment = true; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + break; + } + } else if (isWhiteSpace(ch)) { + ++index; + } else if (isLineTerminator(ch)) { + ++index; + if (ch === 13 && source.charCodeAt(index) === 10) { + ++index; + } + ++lineNumber; + lineStart = index; + } else { + break; + } + } + } + + function scanHexEscape(prefix) { + var i, len, ch, code = 0; + + len = (prefix === 'u') ? 4 : 2; + for (i = 0; i < len; ++i) { + if (index < length && isHexDigit(source[index])) { + ch = source[index++]; + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } else { + return ''; + } + } + return String.fromCharCode(code); + } + + function scanUnicodeCodePointEscape() { + var ch, code, cu1, cu2; + + ch = source[index]; + code = 0; + + // At least, one hex digit is required. + if (ch === '}') { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + while (index < length) { + ch = source[index++]; + if (!isHexDigit(ch)) { + break; + } + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } + + if (code > 0x10FFFF || ch !== '}') { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + // UTF-16 Encoding + if (code <= 0xFFFF) { + return String.fromCharCode(code); + } + cu1 = ((code - 0x10000) >> 10) + 0xD800; + cu2 = ((code - 0x10000) & 1023) + 0xDC00; + return String.fromCharCode(cu1, cu2); + } + + function getEscapedIdentifier() { + var ch, id; + + ch = source.charCodeAt(index++); + id = String.fromCharCode(ch); + + // '\u' (char #92, char #117) denotes an escaped character. + if (ch === 92) { + if (source.charCodeAt(index) !== 117) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + ++index; + ch = scanHexEscape('u'); + if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + id = ch; + } + + while (index < length) { + ch = source.charCodeAt(index); + if (!isIdentifierPart(ch)) { + break; + } + ++index; + id += String.fromCharCode(ch); + + // '\u' (char #92, char #117) denotes an escaped character. + if (ch === 92) { + id = id.substr(0, id.length - 1); + if (source.charCodeAt(index) !== 117) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + ++index; + ch = scanHexEscape('u'); + if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + id += ch; + } + } + + return id; + } + + function getIdentifier() { + var start, ch; + + start = index++; + while (index < length) { + ch = source.charCodeAt(index); + if (ch === 92) { + // Blackslash (char #92) marks Unicode escape sequence. + index = start; + return getEscapedIdentifier(); + } + if (isIdentifierPart(ch)) { + ++index; + } else { + break; + } + } + + return source.slice(start, index); + } + + function scanIdentifier() { + var start, id, type; + + start = index; + + // Backslash (char #92) starts an escaped character. + id = (source.charCodeAt(index) === 92) ? getEscapedIdentifier() : getIdentifier(); + + // There is no keyword or literal with only one character. + // Thus, it must be an identifier. + if (id.length === 1) { + type = Token.Identifier; + } else if (isKeyword(id)) { + type = Token.Keyword; + } else if (id === 'null') { + type = Token.NullLiteral; + } else if (id === 'true' || id === 'false') { + type = Token.BooleanLiteral; + } else { + type = Token.Identifier; + } + + return { + type: type, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + + // 7.7 Punctuators + + function scanPunctuator() { + var start = index, + code = source.charCodeAt(index), + code2, + ch1 = source[index], + ch2, + ch3, + ch4; + + switch (code) { + // Check for most common single-character punctuators. + case 40: // ( open bracket + case 41: // ) close bracket + case 59: // ; semicolon + case 44: // , comma + case 123: // { open curly brace + case 125: // } close curly brace + case 91: // [ + case 93: // ] + case 58: // : + case 63: // ? + case 126: // ~ + ++index; + if (extra.tokenize) { + if (code === 40) { + extra.openParenToken = extra.tokens.length; + } else if (code === 123) { + extra.openCurlyToken = extra.tokens.length; + } + } + return { + type: Token.Punctuator, + value: String.fromCharCode(code), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + + default: + code2 = source.charCodeAt(index + 1); + + // '=' (char #61) marks an assignment or comparison operator. + if (code2 === 61) { + switch (code) { + case 37: // % + case 38: // & + case 42: // *: + case 43: // + + case 45: // - + case 47: // / + case 60: // < + case 62: // > + case 94: // ^ + case 124: // | + index += 2; + return { + type: Token.Punctuator, + value: String.fromCharCode(code) + String.fromCharCode(code2), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + + case 33: // ! + case 61: // = + index += 2; + + // !== and === + if (source.charCodeAt(index) === 61) { + ++index; + } + return { + type: Token.Punctuator, + value: source.slice(start, index), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + default: + break; + } + } + break; + } + + // Peek more characters. + + ch2 = source[index + 1]; + ch3 = source[index + 2]; + ch4 = source[index + 3]; + + // 4-character punctuator: >>>= + + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { + if (ch4 === '=') { + index += 4; + return { + type: Token.Punctuator, + value: '>>>=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + + // 3-character punctuators: === !== >>> <<= >>= + + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { + index += 3; + return { + type: Token.Punctuator, + value: '>>>', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '<' && ch2 === '<' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '<<=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '>' && ch2 === '>' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '>>=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '.' && ch2 === '.' && ch3 === '.') { + index += 3; + return { + type: Token.Punctuator, + value: '...', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // Other 2-character punctuators: ++ -- << >> && || + + if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) { + index += 2; + return { + type: Token.Punctuator, + value: ch1 + ch2, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '=' && ch2 === '>') { + index += 2; + return { + type: Token.Punctuator, + value: '=>', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { + ++index; + return { + type: Token.Punctuator, + value: ch1, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '.') { + ++index; + return { + type: Token.Punctuator, + value: ch1, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + // 7.8.3 Numeric Literals + + function scanHexLiteral(start) { + var number = ''; + + while (index < length) { + if (!isHexDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.NumericLiteral, + value: parseInt('0x' + number, 16), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanOctalLiteral(prefix, start) { + var number, octal; + + if (isOctalDigit(prefix)) { + octal = true; + number = '0' + source[index++]; + } else { + octal = false; + ++index; + number = ''; + } + + while (index < length) { + if (!isOctalDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (!octal && number.length === 0) { + // only 0o or 0O + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.NumericLiteral, + value: parseInt(number, 8), + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanNumericLiteral() { + var number, start, ch, octal; + + ch = source[index]; + assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), + 'Numeric literal must start with a decimal digit or a decimal point'); + + start = index; + number = ''; + if (ch !== '.') { + number = source[index++]; + ch = source[index]; + + // Hex number starts with '0x'. + // Octal number starts with '0'. + // Octal number in ES6 starts with '0o'. + // Binary number in ES6 starts with '0b'. + if (number === '0') { + if (ch === 'x' || ch === 'X') { + ++index; + return scanHexLiteral(start); + } + if (ch === 'b' || ch === 'B') { + ++index; + number = ''; + + while (index < length) { + ch = source[index]; + if (ch !== '0' && ch !== '1') { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + // only 0b or 0B + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (index < length) { + ch = source.charCodeAt(index); + if (isIdentifierStart(ch) || isDecimalDigit(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + return { + type: Token.NumericLiteral, + value: parseInt(number, 2), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + if (ch === 'o' || ch === 'O' || isOctalDigit(ch)) { + return scanOctalLiteral(ch, start); + } + // decimal number starts with '0' such as '09' is illegal. + if (ch && isDecimalDigit(ch.charCodeAt(0))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === '.') { + number += source[index++]; + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === 'e' || ch === 'E') { + number += source[index++]; + + ch = source[index]; + if (ch === '+' || ch === '-') { + number += source[index++]; + } + if (isDecimalDigit(source.charCodeAt(index))) { + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + } else { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.NumericLiteral, + value: parseFloat(number), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 7.8.4 String Literals + + function scanStringLiteral() { + var str = '', quote, start, ch, code, unescaped, restore, octal = false; + + quote = source[index]; + assert((quote === '\'' || quote === '"'), + 'String literal must starts with a quote'); + + start = index; + ++index; + + while (index < length) { + ch = source[index++]; + + if (ch === quote) { + quote = ''; + break; + } else if (ch === '\\') { + ch = source[index++]; + if (!ch || !isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'n': + str += '\n'; + break; + case 'r': + str += '\r'; + break; + case 't': + str += '\t'; + break; + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + str += scanUnicodeCodePointEscape(); + } else { + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + str += unescaped; + } else { + index = restore; + str += ch; + } + } + break; + case 'b': + str += '\b'; + break; + case 'f': + str += '\f'; + break; + case 'v': + str += '\x0B'; + break; + + default: + if (isOctalDigit(ch)) { + code = '01234567'.indexOf(ch); + + // \0 is not octal escape sequence + if (code !== 0) { + octal = true; + } + + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + str += String.fromCharCode(code); + } else { + str += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + break; + } else { + str += ch; + } + } + + if (quote !== '') { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.StringLiteral, + value: str, + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanTemplate() { + var cooked = '', ch, start, terminated, tail, restore, unescaped, code, octal; + + terminated = false; + tail = false; + start = index; + + ++index; + + while (index < length) { + ch = source[index++]; + if (ch === '`') { + tail = true; + terminated = true; + break; + } else if (ch === '$') { + if (source[index] === '{') { + ++index; + terminated = true; + break; + } + cooked += ch; + } else if (ch === '\\') { + ch = source[index++]; + if (!isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'n': + cooked += '\n'; + break; + case 'r': + cooked += '\r'; + break; + case 't': + cooked += '\t'; + break; + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + cooked += scanUnicodeCodePointEscape(); + } else { + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + cooked += unescaped; + } else { + index = restore; + cooked += ch; + } + } + break; + case 'b': + cooked += '\b'; + break; + case 'f': + cooked += '\f'; + break; + case 'v': + cooked += '\v'; + break; + + default: + if (isOctalDigit(ch)) { + code = '01234567'.indexOf(ch); + + // \0 is not octal escape sequence + if (code !== 0) { + octal = true; + } + + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + cooked += String.fromCharCode(code); + } else { + cooked += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + } else { + cooked += ch; + } + } + + if (!terminated) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.Template, + value: { + cooked: cooked, + raw: source.slice(start + 1, index - ((tail) ? 1 : 2)) + }, + tail: tail, + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanTemplateElement(option) { + var startsWith, template; + + lookahead = null; + skipComment(); + + startsWith = (option.head) ? '`' : '}'; + + if (source[index] !== startsWith) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + template = scanTemplate(); + + peek(); + + return template; + } + + function scanRegExp() { + var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false; + + lookahead = null; + skipComment(); + + start = index; + ch = source[index]; + assert(ch === '/', 'Regular expression literal must start with a slash'); + str = source[index++]; + + while (index < length) { + ch = source[index++]; + str += ch; + if (classMarker) { + if (ch === ']') { + classMarker = false; + } + } else { + if (ch === '\\') { + ch = source[index++]; + // ECMA-262 7.8.5 + if (isLineTerminator(ch.charCodeAt(0))) { + throwError({}, Messages.UnterminatedRegExp); + } + str += ch; + } else if (ch === '/') { + terminated = true; + break; + } else if (ch === '[') { + classMarker = true; + } else if (isLineTerminator(ch.charCodeAt(0))) { + throwError({}, Messages.UnterminatedRegExp); + } + } + } + + if (!terminated) { + throwError({}, Messages.UnterminatedRegExp); + } + + // Exclude leading and trailing slash. + pattern = str.substr(1, str.length - 2); + + flags = ''; + while (index < length) { + ch = source[index]; + if (!isIdentifierPart(ch.charCodeAt(0))) { + break; + } + + ++index; + if (ch === '\\' && index < length) { + ch = source[index]; + if (ch === 'u') { + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + flags += ch; + for (str += '\\u'; restore < index; ++restore) { + str += source[restore]; + } + } else { + index = restore; + flags += 'u'; + str += '\\u'; + } + } else { + str += '\\'; + } + } else { + flags += ch; + str += ch; + } + } + + try { + value = new RegExp(pattern, flags); + } catch (e) { + throwError({}, Messages.InvalidRegExp); + } + + peek(); + + + if (extra.tokenize) { + return { + type: Token.RegularExpression, + value: value, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + return { + literal: str, + value: value, + range: [start, index] + }; + } + + function isIdentifierName(token) { + return token.type === Token.Identifier || + token.type === Token.Keyword || + token.type === Token.BooleanLiteral || + token.type === Token.NullLiteral; + } + + function advanceSlash() { + var prevToken, + checkToken; + // Using the following algorithm: + // https://github.com/mozilla/sweet.js/wiki/design + prevToken = extra.tokens[extra.tokens.length - 1]; + if (!prevToken) { + // Nothing before that: it cannot be a division. + return scanRegExp(); + } + if (prevToken.type === "Punctuator") { + if (prevToken.value === ")") { + checkToken = extra.tokens[extra.openParenToken - 1]; + if (checkToken && + checkToken.type === "Keyword" && + (checkToken.value === "if" || + checkToken.value === "while" || + checkToken.value === "for" || + checkToken.value === "with")) { + return scanRegExp(); + } + return scanPunctuator(); + } + if (prevToken.value === "}") { + // Dividing a function by anything makes little sense, + // but we have to check for that. + if (extra.tokens[extra.openCurlyToken - 3] && + extra.tokens[extra.openCurlyToken - 3].type === "Keyword") { + // Anonymous function. + checkToken = extra.tokens[extra.openCurlyToken - 4]; + if (!checkToken) { + return scanPunctuator(); + } + } else if (extra.tokens[extra.openCurlyToken - 4] && + extra.tokens[extra.openCurlyToken - 4].type === "Keyword") { + // Named function. + checkToken = extra.tokens[extra.openCurlyToken - 5]; + if (!checkToken) { + return scanRegExp(); + } + } else { + return scanPunctuator(); + } + // checkToken determines whether the function is + // a declaration or an expression. + if (FnExprTokens.indexOf(checkToken.value) >= 0) { + // It is an expression. + return scanPunctuator(); + } + // It is a declaration. + return scanRegExp(); + } + return scanRegExp(); + } + if (prevToken.type === "Keyword") { + return scanRegExp(); + } + return scanPunctuator(); + } + + function advance() { + var ch; + + if (state.inXJSChild) { + return advanceXJSChild(); + } + + skipComment(); + + if (index >= length) { + return { + type: Token.EOF, + lineNumber: lineNumber, + lineStart: lineStart, + range: [index, index] + }; + } + + ch = source.charCodeAt(index); + + // Very common: ( and ) and ; + if (ch === 40 || ch === 41 || ch === 58) { + return scanPunctuator(); + } + + // String literal starts with single quote (#39) or double quote (#34). + if (ch === 39 || ch === 34) { + if (state.inXJSTag) { + return scanXJSStringLiteral(); + } + return scanStringLiteral(); + } + + if (state.inXJSTag && isXJSIdentifierStart(ch)) { + return scanXJSIdentifier(); + } + + if (ch === 96) { + return scanTemplate(); + } + if (isIdentifierStart(ch)) { + return scanIdentifier(); + } + + // Dot (.) char #46 can also start a floating-point number, hence the need + // to check the next character. + if (ch === 46) { + if (isDecimalDigit(source.charCodeAt(index + 1))) { + return scanNumericLiteral(); + } + return scanPunctuator(); + } + + if (isDecimalDigit(ch)) { + return scanNumericLiteral(); + } + + // Slash (/) char #47 can also start a regex. + if (extra.tokenize && ch === 47) { + return advanceSlash(); + } + + return scanPunctuator(); + } + + function lex() { + var token; + + token = lookahead; + index = token.range[1]; + lineNumber = token.lineNumber; + lineStart = token.lineStart; + + lookahead = advance(); + + index = token.range[1]; + lineNumber = token.lineNumber; + lineStart = token.lineStart; + + return token; + } + + function peek() { + var pos, line, start; + + pos = index; + line = lineNumber; + start = lineStart; + lookahead = advance(); + index = pos; + lineNumber = line; + lineStart = start; + } + + function lookahead2() { + var adv, pos, line, start, result; + + // If we are collecting the tokens, don't grab the next one yet. + adv = (typeof extra.advance === 'function') ? extra.advance : advance; + + pos = index; + line = lineNumber; + start = lineStart; + + // Scan for the next immediate token. + if (lookahead === null) { + lookahead = adv(); + } + index = lookahead.range[1]; + lineNumber = lookahead.lineNumber; + lineStart = lookahead.lineStart; + + // Grab the token right after. + result = adv(); + index = pos; + lineNumber = line; + lineStart = start; + + return result; + } + + SyntaxTreeDelegate = { + + name: 'SyntaxTree', + + postProcess: function (node) { + return node; + }, + + createArrayExpression: function (elements) { + return { + type: Syntax.ArrayExpression, + elements: elements + }; + }, + + createAssignmentExpression: function (operator, left, right) { + return { + type: Syntax.AssignmentExpression, + operator: operator, + left: left, + right: right + }; + }, + + createBinaryExpression: function (operator, left, right) { + var type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : + Syntax.BinaryExpression; + return { + type: type, + operator: operator, + left: left, + right: right + }; + }, + + createBlockStatement: function (body) { + return { + type: Syntax.BlockStatement, + body: body + }; + }, + + createBreakStatement: function (label) { + return { + type: Syntax.BreakStatement, + label: label + }; + }, + + createCallExpression: function (callee, args) { + return { + type: Syntax.CallExpression, + callee: callee, + 'arguments': args + }; + }, + + createCatchClause: function (param, body) { + return { + type: Syntax.CatchClause, + param: param, + body: body + }; + }, + + createConditionalExpression: function (test, consequent, alternate) { + return { + type: Syntax.ConditionalExpression, + test: test, + consequent: consequent, + alternate: alternate + }; + }, + + createContinueStatement: function (label) { + return { + type: Syntax.ContinueStatement, + label: label + }; + }, + + createDebuggerStatement: function () { + return { + type: Syntax.DebuggerStatement + }; + }, + + createDoWhileStatement: function (body, test) { + return { + type: Syntax.DoWhileStatement, + body: body, + test: test + }; + }, + + createEmptyStatement: function () { + return { + type: Syntax.EmptyStatement + }; + }, + + createExpressionStatement: function (expression) { + return { + type: Syntax.ExpressionStatement, + expression: expression + }; + }, + + createForStatement: function (init, test, update, body) { + return { + type: Syntax.ForStatement, + init: init, + test: test, + update: update, + body: body + }; + }, + + createForInStatement: function (left, right, body) { + return { + type: Syntax.ForInStatement, + left: left, + right: right, + body: body, + each: false + }; + }, + + createForOfStatement: function (left, right, body) { + return { + type: Syntax.ForOfStatement, + left: left, + right: right, + body: body, + }; + }, + + createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression) { + return { + type: Syntax.FunctionDeclaration, + id: id, + params: params, + defaults: defaults, + body: body, + rest: rest, + generator: generator, + expression: expression + }; + }, + + createFunctionExpression: function (id, params, defaults, body, rest, generator, expression) { + return { + type: Syntax.FunctionExpression, + id: id, + params: params, + defaults: defaults, + body: body, + rest: rest, + generator: generator, + expression: expression + }; + }, + + createIdentifier: function (name) { + return { + type: Syntax.Identifier, + name: name + }; + }, + + createXJSAttribute: function (name, value) { + return { + type: Syntax.XJSAttribute, + name: name, + value: value + }; + }, + + createXJSIdentifier: function (name, namespace) { + return { + type: Syntax.XJSIdentifier, + name: name, + namespace: namespace + }; + }, + + createXJSElement: function (openingElement, closingElement, children) { + return { + type: Syntax.XJSElement, + name: openingElement.name, + selfClosing: openingElement.selfClosing, + openingElement: openingElement, + closingElement: closingElement, + attributes: openingElement.attributes, + children: children + }; + }, + + createXJSExpression: function (expression) { + return { + type: Syntax.XJSExpression, + value: expression + }; + }, + + createXJSOpeningElement: function (name, attributes, selfClosing) { + return { + type: Syntax.XJSOpeningElement, + name: name, + selfClosing: selfClosing, + attributes: attributes + }; + }, + + createXJSClosingElement: function (name) { + return { + type: Syntax.XJSClosingElement, + name: name + }; + }, + + createIfStatement: function (test, consequent, alternate) { + return { + type: Syntax.IfStatement, + test: test, + consequent: consequent, + alternate: alternate + }; + }, + + createLabeledStatement: function (label, body) { + return { + type: Syntax.LabeledStatement, + label: label, + body: body + }; + }, + + createLiteral: function (token) { + return { + type: Syntax.Literal, + value: token.value, + raw: source.slice(token.range[0], token.range[1]) + }; + }, + + createMemberExpression: function (accessor, object, property) { + return { + type: Syntax.MemberExpression, + computed: accessor === '[', + object: object, + property: property + }; + }, + + createNewExpression: function (callee, args) { + return { + type: Syntax.NewExpression, + callee: callee, + 'arguments': args + }; + }, + + createObjectExpression: function (properties) { + return { + type: Syntax.ObjectExpression, + properties: properties + }; + }, + + createPostfixExpression: function (operator, argument) { + return { + type: Syntax.UpdateExpression, + operator: operator, + argument: argument, + prefix: false + }; + }, + + createProgram: function (body) { + return { + type: Syntax.Program, + body: body + }; + }, + + createProperty: function (kind, key, value, method, shorthand) { + return { + type: Syntax.Property, + key: key, + value: value, + kind: kind, + method: method, + shorthand: shorthand + }; + }, + + createReturnStatement: function (argument) { + return { + type: Syntax.ReturnStatement, + argument: argument + }; + }, + + createSequenceExpression: function (expressions) { + return { + type: Syntax.SequenceExpression, + expressions: expressions + }; + }, + + createSwitchCase: function (test, consequent) { + return { + type: Syntax.SwitchCase, + test: test, + consequent: consequent + }; + }, + + createSwitchStatement: function (discriminant, cases) { + return { + type: Syntax.SwitchStatement, + discriminant: discriminant, + cases: cases + }; + }, + + createThisExpression: function () { + return { + type: Syntax.ThisExpression + }; + }, + + createThrowStatement: function (argument) { + return { + type: Syntax.ThrowStatement, + argument: argument + }; + }, + + createTryStatement: function (block, guardedHandlers, handlers, finalizer) { + return { + type: Syntax.TryStatement, + block: block, + guardedHandlers: guardedHandlers, + handlers: handlers, + finalizer: finalizer + }; + }, + + createUnaryExpression: function (operator, argument) { + if (operator === '++' || operator === '--') { + return { + type: Syntax.UpdateExpression, + operator: operator, + argument: argument, + prefix: true + }; + } + return { + type: Syntax.UnaryExpression, + operator: operator, + argument: argument + }; + }, + + createVariableDeclaration: function (declarations, kind) { + return { + type: Syntax.VariableDeclaration, + declarations: declarations, + kind: kind + }; + }, + + createVariableDeclarator: function (id, init) { + return { + type: Syntax.VariableDeclarator, + id: id, + init: init + }; + }, + + createWhileStatement: function (test, body) { + return { + type: Syntax.WhileStatement, + test: test, + body: body + }; + }, + + createWithStatement: function (object, body) { + return { + type: Syntax.WithStatement, + object: object, + body: body + }; + }, + + createTemplateElement: function (value, tail) { + return { + type: Syntax.TemplateElement, + value: value, + tail: tail + }; + }, + + createTemplateLiteral: function (quasis, expressions) { + return { + type: Syntax.TemplateLiteral, + quasis: quasis, + expressions: expressions + }; + }, + + createSpreadElement: function (argument) { + return { + type: Syntax.SpreadElement, + argument: argument + }; + }, + + createTaggedTemplateExpression: function (tag, quasi) { + return { + type: Syntax.TaggedTemplateExpression, + tag: tag, + quasi: quasi + }; + }, + + createArrowFunctionExpression: function (params, defaults, body, rest, expression) { + return { + type: Syntax.ArrowFunctionExpression, + id: null, + params: params, + defaults: defaults, + body: body, + rest: rest, + generator: false, + expression: expression + }; + }, + + createMethodDefinition: function (propertyType, kind, key, value) { + return { + type: Syntax.MethodDefinition, + key: key, + value: value, + kind: kind, + 'static': propertyType === ClassPropertyType.static + }; + }, + + createClassBody: function (body) { + return { + type: Syntax.ClassBody, + body: body + }; + }, + + createClassExpression: function (id, superClass, body) { + return { + type: Syntax.ClassExpression, + id: id, + superClass: superClass, + body: body + }; + }, + + createClassDeclaration: function (id, superClass, body) { + return { + type: Syntax.ClassDeclaration, + id: id, + superClass: superClass, + body: body + }; + }, + + createPath: function (body) { + return { + type: Syntax.Path, + body: body + }; + }, + + createGlob: function () { + return { + type: Syntax.Glob + }; + }, + + createExportSpecifier: function (id, from) { + return { + type: Syntax.ExportSpecifier, + id: id, + from: from + }; + }, + + createExportSpecifierSet: function (specifiers) { + return { + type: Syntax.ExportSpecifierSet, + specifiers: specifiers + }; + }, + + createExportDeclaration: function (declaration, specifiers) { + return { + type: Syntax.ExportDeclaration, + declaration: declaration, + specifiers: specifiers + }; + }, + + createImportSpecifier: function (id, from) { + return { + type: Syntax.ImportSpecifier, + id: id, + from: from + }; + }, + + createImportDeclaration: function (specifiers, from) { + return { + type: Syntax.ImportDeclaration, + specifiers: specifiers, + from: from + }; + }, + + createYieldExpression: function (argument, delegate) { + return { + type: Syntax.YieldExpression, + argument: argument, + delegate: delegate + }; + }, + + createModuleDeclaration: function (id, from, body) { + return { + type: Syntax.ModuleDeclaration, + id: id, + from: from, + body: body + }; + } + + + }; + + // Return true if there is a line terminator before the next token. + + function peekLineTerminator() { + var pos, line, start, found; + + pos = index; + line = lineNumber; + start = lineStart; + skipComment(); + found = lineNumber !== line; + index = pos; + lineNumber = line; + lineStart = start; + + return found; + } + + // Throw an exception + + function throwError(token, messageFormat) { + var error, + args = Array.prototype.slice.call(arguments, 2), + msg = messageFormat.replace( + /%(\d)/g, + function (whole, index) { + assert(index < args.length, 'Message reference must be in range'); + return args[index]; + } + ); + + if (typeof token.lineNumber === 'number') { + error = new Error('Line ' + token.lineNumber + ': ' + msg); + error.index = token.range[0]; + error.lineNumber = token.lineNumber; + error.column = token.range[0] - lineStart + 1; + } else { + error = new Error('Line ' + lineNumber + ': ' + msg); + error.index = index; + error.lineNumber = lineNumber; + error.column = index - lineStart + 1; + } + + error.description = msg; + throw error; + } + + function throwErrorTolerant() { + try { + throwError.apply(null, arguments); + } catch (e) { + if (extra.errors) { + extra.errors.push(e); + } else { + throw e; + } + } + } + + + // Throw an exception because of the token. + + function throwUnexpected(token) { + if (token.type === Token.EOF) { + throwError(token, Messages.UnexpectedEOS); + } + + if (token.type === Token.NumericLiteral) { + throwError(token, Messages.UnexpectedNumber); + } + + if (token.type === Token.StringLiteral) { + throwError(token, Messages.UnexpectedString); + } + + if (token.type === Token.Identifier) { + throwError(token, Messages.UnexpectedIdentifier); + } + + if (token.type === Token.Keyword) { + if (isFutureReservedWord(token.value)) { + throwError(token, Messages.UnexpectedReserved); + } else if (strict && isStrictModeReservedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictReservedWord); + return; + } + throwError(token, Messages.UnexpectedToken, token.value); + } + + if (token.type === Token.Template) { + throwError(token, Messages.UnexpectedTemplate, token.value.raw); + } + + // BooleanLiteral, NullLiteral, or Punctuator. + throwError(token, Messages.UnexpectedToken, token.value); + } + + // Expect the next token to match the specified punctuator. + // If not, an exception will be thrown. + + function expect(value) { + var token = lex(); + if (token.type !== Token.Punctuator || token.value !== value) { + throwUnexpected(token); + } + } + + // Expect the next token to match the specified keyword. + // If not, an exception will be thrown. + + function expectKeyword(keyword) { + var token = lex(); + if (token.type !== Token.Keyword || token.value !== keyword) { + throwUnexpected(token); + } + } + + // Return true if the next token matches the specified punctuator. + + function match(value) { + return lookahead.type === Token.Punctuator && lookahead.value === value; + } + + // Return true if the next token matches the specified keyword + + function matchKeyword(keyword) { + return lookahead.type === Token.Keyword && lookahead.value === keyword; + } + + + // Return true if the next token matches the specified contextual keyword + + function matchContextualKeyword(keyword) { + return lookahead.type === Token.Identifier && lookahead.value === keyword; + } + + // Return true if the next token is an assignment operator + + function matchAssign() { + var op; + + if (lookahead.type !== Token.Punctuator) { + return false; + } + op = lookahead.value; + return op === '=' || + op === '*=' || + op === '/=' || + op === '%=' || + op === '+=' || + op === '-=' || + op === '<<=' || + op === '>>=' || + op === '>>>=' || + op === '&=' || + op === '^=' || + op === '|='; + } + + function consumeSemicolon() { + var line; + + // Catch the very common case first: immediately a semicolon (char #59). + if (source.charCodeAt(index) === 59) { + lex(); + return; + } + + line = lineNumber; + skipComment(); + if (lineNumber !== line) { + return; + } + + if (match(';')) { + lex(); + return; + } + + if (lookahead.type !== Token.EOF && !match('}')) { + throwUnexpected(lookahead); + } + } + + // Return true if provided expression is LeftHandSideExpression + + function isLeftHandSide(expr) { + return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression; + } + + function isAssignableLeftHandSide(expr) { + return isLeftHandSide(expr) || expr.type === Syntax.ObjectPattern || expr.type === Syntax.ArrayPattern; + } + + // 11.1.4 Array Initialiser + + function parseArrayInitialiser() { + var elements = [], blocks = [], filter = null, tmp, possiblecomprehension = true, body; + + expect('['); + while (!match(']')) { + if (lookahead.value === 'for' && + lookahead.type === Token.Keyword) { + if (!possiblecomprehension) { + throwError({}, Messages.ComprehensionError); + } + matchKeyword('for'); + tmp = parseForStatement({ignore_body: true}); + tmp.of = tmp.type === Syntax.ForOfStatement; + tmp.type = Syntax.ComprehensionBlock; + if (tmp.left.kind) { // can't be let or const + throwError({}, Messages.ComprehensionError); + } + blocks.push(tmp); + } else if (lookahead.value === 'if' && + lookahead.type === Token.Keyword) { + if (!possiblecomprehension) { + throwError({}, Messages.ComprehensionError); + } + expectKeyword('if'); + expect('('); + filter = parseExpression(); + expect(')'); + } else if (lookahead.value === ',' && + lookahead.type === Token.Punctuator) { + possiblecomprehension = false; // no longer allowed. + lex(); + elements.push(null); + } else { + tmp = parseSpreadOrAssignmentExpression(); + elements.push(tmp); + if (tmp && tmp.type === Syntax.SpreadElement) { + if (!match(']')) { + throwError({}, Messages.ElementAfterSpreadElement); + } + } else if (!(match(']') || matchKeyword('for') || matchKeyword('if'))) { + expect(','); // this lexes. + possiblecomprehension = false; + } + } + } + + expect(']'); + + if (filter && !blocks.length) { + throwError({}, Messages.ComprehensionRequiresBlock); + } + + if (blocks.length) { + if (elements.length !== 1) { + throwError({}, Messages.ComprehensionError); + } + return { + type: Syntax.ComprehensionExpression, + filter: filter, + blocks: blocks, + body: elements[0] + }; + } + return delegate.createArrayExpression(elements); + } + + // 11.1.5 Object Initialiser + + function parsePropertyFunction(options) { + var previousStrict, previousYieldAllowed, params, body; + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = options.generator; + params = options.params || []; + + body = parseConciseBody(); + if (options.name && strict && isRestrictedWord(params[0].name)) { + throwErrorTolerant(options.name, Messages.StrictParamName); + } + if (state.yieldAllowed && !state.yieldFound) { + throwError({}, Messages.NoYieldInGenerator); + } + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createFunctionExpression(null, params, [], body, options.rest || null, options.generator, body.type !== Syntax.BlockStatement); + } + + + function parsePropertyMethodFunction(options) { + var previousStrict, tmp, method; + + previousStrict = strict; + strict = true; + + tmp = parseParams(); + + if (tmp.stricted) { + throwErrorTolerant(tmp.stricted, tmp.message); + } + + + method = parsePropertyFunction({ + params: tmp.params, + rest: tmp.rest, + generator: options.generator + }); + + strict = previousStrict; + + return method; + } + + + function parseObjectPropertyKey() { + var token = lex(); + + // Note: This function is called only from parseObjectProperty(), where + // EOF and Punctuator tokens are already filtered out. + + if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { + if (strict && token.octal) { + throwErrorTolerant(token, Messages.StrictOctalLiteral); + } + return delegate.createLiteral(token); + } + + return delegate.createIdentifier(token.value); + } + + function parseObjectProperty() { + var token, key, id, value, param; + + token = lookahead; + + if (token.type === Token.Identifier) { + + id = parseObjectPropertyKey(); + + // Property Assignment: Getter and Setter. + + if (token.value === 'get' && !(match(':') || match('('))) { + key = parseObjectPropertyKey(); + expect('('); + expect(')'); + return delegate.createProperty('get', key, parsePropertyFunction({ generator: false }), false, false); + } + if (token.value === 'set' && !(match(':') || match('('))) { + key = parseObjectPropertyKey(); + expect('('); + token = lookahead; + param = [ parseVariableIdentifier() ]; + expect(')'); + return delegate.createProperty('set', key, parsePropertyFunction({ params: param, generator: false, name: token }), false, false); + } + if (match(':')) { + lex(); + return delegate.createProperty('init', id, parseAssignmentExpression(), false, false); + } + if (match('(')) { + return delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: false }), true, false); + } + return delegate.createProperty('init', id, id, false, true); + } + if (token.type === Token.EOF || token.type === Token.Punctuator) { + if (!match('*')) { + throwUnexpected(token); + } + lex(); + + id = parseObjectPropertyKey(); + + if (!match('(')) { + throwUnexpected(lex()); + } + + return delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: true }), true, false); + } + key = parseObjectPropertyKey(); + if (match(':')) { + lex(); + return delegate.createProperty('init', key, parseAssignmentExpression(), false, false); + } + if (match('(')) { + return delegate.createProperty('init', key, parsePropertyMethodFunction({ generator: false }), true, false); + } + throwUnexpected(lex()); + } + + function parseObjectInitialiser() { + var properties = [], property, name, key, kind, map = {}, toString = String; + + expect('{'); + + while (!match('}')) { + property = parseObjectProperty(); + + if (property.key.type === Syntax.Identifier) { + name = property.key.name; + } else { + name = toString(property.key.value); + } + kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; + + key = '$' + name; + if (Object.prototype.hasOwnProperty.call(map, key)) { + if (map[key] === PropertyKind.Data) { + if (strict && kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.StrictDuplicateProperty); + } else if (kind !== PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } + } else { + if (kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } else if (map[key] & kind) { + throwErrorTolerant({}, Messages.AccessorGetSet); + } + } + map[key] |= kind; + } else { + map[key] = kind; + } + + properties.push(property); + + if (!match('}')) { + expect(','); + } + } + + expect('}'); + + return delegate.createObjectExpression(properties); + } + + function parseTemplateElement(option) { + var token = scanTemplateElement(option); + if (strict && token.octal) { + throwError(token, Messages.StrictOctalLiteral); + } + return delegate.createTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail); + } + + function parseTemplateLiteral() { + var quasi, quasis, expressions; + + quasi = parseTemplateElement({ head: true }); + quasis = [ quasi ]; + expressions = []; + + while (!quasi.tail) { + expressions.push(parseExpression()); + quasi = parseTemplateElement({ head: false }); + quasis.push(quasi); + } + + return delegate.createTemplateLiteral(quasis, expressions); + } + + // 11.1.6 The Grouping Operator + + function parseGroupExpression() { + var expr; + + expect('('); + + ++state.parenthesizedCount; + + state.allowArrowFunction = !state.allowArrowFunction; + expr = parseExpression(); + state.allowArrowFunction = false; + + if (expr.type !== Syntax.ArrowFunctionExpression) { + expect(')'); + } + + return expr; + } + + + // 11.1 Primary Expressions + + function parsePrimaryExpression() { + var type, token; + + token = lookahead; + type = lookahead.type; + + if (type === Token.Identifier) { + lex(); + return delegate.createIdentifier(token.value); + } + + if (type === Token.StringLiteral || type === Token.NumericLiteral) { + if (strict && lookahead.octal) { + throwErrorTolerant(lookahead, Messages.StrictOctalLiteral); + } + return delegate.createLiteral(lex()); + } + + if (type === Token.Keyword) { + if (matchKeyword('this')) { + lex(); + return delegate.createThisExpression(); + } + + if (matchKeyword('function')) { + return parseFunctionExpression(); + } + + if (matchKeyword('class')) { + return parseClassExpression(); + } + + if (matchKeyword('super')) { + lex(); + return delegate.createIdentifier('super'); + } + } + + if (type === Token.BooleanLiteral) { + token = lex(); + token.value = (token.value === 'true'); + return delegate.createLiteral(token); + } + + if (type === Token.NullLiteral) { + token = lex(); + token.value = null; + return delegate.createLiteral(token); + } + + if (match('[')) { + return parseArrayInitialiser(); + } + + if (match('{')) { + return parseObjectInitialiser(); + } + + if (match('(')) { + return parseGroupExpression(); + } + + if (match('/') || match('/=')) { + return delegate.createLiteral(scanRegExp()); + } + + if (type === Token.Template) { + return parseTemplateLiteral(); + } + + if (match('<')) { + return parseXJSElement(); + } + + return throwUnexpected(lex()); + } + + // 11.2 Left-Hand-Side Expressions + + function parseArguments() { + var args = [], arg; + + expect('('); + + if (!match(')')) { + while (index < length) { + arg = parseSpreadOrAssignmentExpression(); + args.push(arg); + + if (match(')')) { + break; + } else if (arg.type === Syntax.SpreadElement) { + throwError({}, Messages.ElementAfterSpreadElement); + } + + expect(','); + } + } + + expect(')'); + + return args; + } + + function parseSpreadOrAssignmentExpression() { + if (match('...')) { + lex(); + return delegate.createSpreadElement(parseAssignmentExpression()); + } + return parseAssignmentExpression(); + } + + function parseNonComputedProperty() { + var token = lex(); + + if (!isIdentifierName(token)) { + throwUnexpected(token); + } + + return delegate.createIdentifier(token.value); + } + + function parseNonComputedMember() { + expect('.'); + + return parseNonComputedProperty(); + } + + function parseComputedMember() { + var expr; + + expect('['); + + expr = parseExpression(); + + expect(']'); + + return expr; + } + + function parseNewExpression() { + var callee, args; + + expectKeyword('new'); + callee = parseLeftHandSideExpression(); + args = match('(') ? parseArguments() : []; + + return delegate.createNewExpression(callee, args); + } + + function parseLeftHandSideExpressionAllowCall() { + var expr, args, property; + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || match('(') || lookahead.type === Token.Template) { + if (match('(')) { + args = parseArguments(); + expr = delegate.createCallExpression(expr, args); + } else if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + } + } + + return expr; + } + + + function parseLeftHandSideExpression() { + var expr, property; + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || lookahead.type === Token.Template) { + if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + } + } + + return expr; + } + + // 11.3 Postfix Expressions + + function parsePostfixExpression() { + var expr = parseLeftHandSideExpressionAllowCall(), + token = lookahead; + + if (lookahead.type !== Token.Punctuator) { + return expr; + } + + if ((match('++') || match('--')) && !peekLineTerminator()) { + // 11.3.1, 11.3.2 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant({}, Messages.StrictLHSPostfix); + } + + if (!isLeftHandSide(expr)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + + token = lex(); + expr = delegate.createPostfixExpression(token.value, expr); + } + + return expr; + } + + // 11.4 Unary Operators + + function parseUnaryExpression() { + var token, expr; + + if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { + return parsePostfixExpression(); + } + + if (match('++') || match('--')) { + token = lex(); + expr = parseUnaryExpression(); + // 11.4.4, 11.4.5 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant({}, Messages.StrictLHSPrefix); + } + + if (!isLeftHandSide(expr)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + + return delegate.createUnaryExpression(token.value, expr); + } + + if (match('+') || match('-') || match('~') || match('!')) { + token = lex(); + expr = parseUnaryExpression(); + return delegate.createUnaryExpression(token.value, expr); + } + + if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { + token = lex(); + expr = parseUnaryExpression(); + expr = delegate.createUnaryExpression(token.value, expr); + if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { + throwErrorTolerant({}, Messages.StrictDelete); + } + return expr; + } + + return parsePostfixExpression(); + } + + function binaryPrecedence(token, allowIn) { + var prec = 0; + + if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { + return 0; + } + + switch (token.value) { + case '||': + prec = 1; + break; + + case '&&': + prec = 2; + break; + + case '|': + prec = 3; + break; + + case '^': + prec = 4; + break; + + case '&': + prec = 5; + break; + + case '==': + case '!=': + case '===': + case '!==': + prec = 6; + break; + + case '<': + case '>': + case '<=': + case '>=': + case 'instanceof': + prec = 7; + break; + + case 'in': + prec = allowIn ? 7 : 0; + break; + + case '<<': + case '>>': + case '>>>': + prec = 8; + break; + + case '+': + case '-': + prec = 9; + break; + + case '*': + case '/': + case '%': + prec = 11; + break; + + default: + break; + } + + return prec; + } + + // 11.5 Multiplicative Operators + // 11.6 Additive Operators + // 11.7 Bitwise Shift Operators + // 11.8 Relational Operators + // 11.9 Equality Operators + // 11.10 Binary Bitwise Operators + // 11.11 Binary Logical Operators + + function parseBinaryExpression() { + var expr, token, prec, previousAllowIn, stack, right, operator, left, i; + + previousAllowIn = state.allowIn; + state.allowIn = true; + + expr = parseUnaryExpression(); + + token = lookahead; + prec = binaryPrecedence(token, previousAllowIn); + if (prec === 0) { + return expr; + } + token.prec = prec; + lex(); + + stack = [expr, token, parseUnaryExpression()]; + + while ((prec = binaryPrecedence(lookahead, previousAllowIn)) > 0) { + + // Reduce: make a binary expression from the three topmost entries. + while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { + right = stack.pop(); + operator = stack.pop().value; + left = stack.pop(); + stack.push(delegate.createBinaryExpression(operator, left, right)); + } + + // Shift. + token = lex(); + token.prec = prec; + stack.push(token); + stack.push(parseUnaryExpression()); + } + + state.allowIn = previousAllowIn; + + // Final reduce to clean-up the stack. + i = stack.length - 1; + expr = stack[i]; + while (i > 1) { + expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr); + i -= 2; + } + return expr; + } + + + // 11.12 Conditional Operator + + function parseConditionalExpression() { + var expr, previousAllowIn, consequent, alternate; + + expr = parseBinaryExpression(); + + if (match('?')) { + lex(); + previousAllowIn = state.allowIn; + state.allowIn = true; + consequent = parseAssignmentExpression(); + state.allowIn = previousAllowIn; + expect(':'); + alternate = parseAssignmentExpression(); + + expr = delegate.createConditionalExpression(expr, consequent, alternate); + } + + return expr; + } + + // 11.13 Assignment Operators + + function reinterpretAsAssignmentBindingPattern(expr) { + var i, len, property, element; + + if (expr.type === Syntax.ObjectExpression) { + expr.type = Syntax.ObjectPattern; + for (i = 0, len = expr.properties.length; i < len; i += 1) { + property = expr.properties[i]; + if (property.kind !== 'init') { + throwError({}, Messages.InvalidLHSInAssignment); + } + reinterpretAsAssignmentBindingPattern(property.value); + } + } else if (expr.type === Syntax.ArrayExpression) { + expr.type = Syntax.ArrayPattern; + for (i = 0, len = expr.elements.length; i < len; i += 1) { + element = expr.elements[i]; + if (element) { + reinterpretAsAssignmentBindingPattern(element); + } + } + } else if (expr.type === Syntax.Identifier) { + if (isRestrictedWord(expr.name)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + } else if (expr.type === Syntax.SpreadElement) { + reinterpretAsAssignmentBindingPattern(expr.argument); + if (expr.argument.type === Syntax.ObjectPattern) { + throwError({}, Messages.ObjectPatternAsSpread); + } + } else { + if (expr.type !== Syntax.MemberExpression && expr.type !== Syntax.CallExpression && expr.type !== Syntax.NewExpression) { + throwError({}, Messages.InvalidLHSInAssignment); + } + } + } + + + function reinterpretAsDestructuredParameter(options, expr) { + var i, len, property, element; + + if (expr.type === Syntax.ObjectExpression) { + expr.type = Syntax.ObjectPattern; + for (i = 0, len = expr.properties.length; i < len; i += 1) { + property = expr.properties[i]; + if (property.kind !== 'init') { + throwError({}, Messages.InvalidLHSInFormalsList); + } + reinterpretAsDestructuredParameter(options, property.value); + } + } else if (expr.type === Syntax.ArrayExpression) { + expr.type = Syntax.ArrayPattern; + for (i = 0, len = expr.elements.length; i < len; i += 1) { + element = expr.elements[i]; + if (element) { + reinterpretAsDestructuredParameter(options, element); + } + } + } else if (expr.type === Syntax.Identifier) { + validateParam(options, expr, expr.name); + } else { + if (expr.type !== Syntax.MemberExpression) { + throwError({}, Messages.InvalidLHSInFormalsList); + } + } + } + + function reinterpretAsCoverFormalsList(expressions) { + var i, len, param, params, options, rest; + + params = []; + rest = null; + options = { + paramSet: {} + }; + + for (i = 0, len = expressions.length; i < len; i += 1) { + param = expressions[i]; + if (param.type === Syntax.Identifier) { + params.push(param); + validateParam(options, param, param.name); + } else if (param.type === Syntax.ObjectExpression || param.type === Syntax.ArrayExpression) { + reinterpretAsDestructuredParameter(options, param); + params.push(param); + } else if (param.type === Syntax.SpreadElement) { + assert(i === len - 1, "It is guaranteed that SpreadElement is last element by parseExpression"); + reinterpretAsDestructuredParameter(options, param.argument); + rest = param.argument; + } else { + return null; + } + } + + if (options.firstRestricted) { + throwError(options.firstRestricted, options.message); + } + if (options.stricted) { + throwErrorTolerant(options.stricted, options.message); + } + + return { params: params, rest: rest }; + } + + function parseArrowFunctionExpression(options) { + var previousStrict, previousYieldAllowed, body; + + expect('=>'); + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + strict = true; + state.yieldAllowed = false; + body = parseConciseBody(); + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createArrowFunctionExpression(options.params, [], body, options.rest, body.type !== Syntax.BlockStatement); + } + + function parseAssignmentExpression() { + var expr, token, params, oldParenthesizedCount; + + if (matchKeyword('yield')) { + return parseYieldExpression(); + } + + oldParenthesizedCount = state.parenthesizedCount; + + if (match('(')) { + token = lookahead2(); + if ((token.type === Token.Punctuator && token.value === ')') || token.value === '...') { + params = parseParams(); + if (!match('=>')) { + throwUnexpected(lex()); + } + return parseArrowFunctionExpression(params); + } + } + + token = lookahead; + expr = parseConditionalExpression(); + + if (match('=>') && expr.type === Syntax.Identifier) { + if (state.parenthesizedCount === oldParenthesizedCount || state.parenthesizedCount === (oldParenthesizedCount + 1)) { + if (isRestrictedWord(expr.name)) { + throwError({}, Messages.StrictParamName); + } + return parseArrowFunctionExpression({ params: [ expr ], rest: null }); + } + } + + if (matchAssign()) { + // 11.13.1 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant(token, Messages.StrictLHSAssignment); + } + + // ES.next draf 11.13 Runtime Semantics step 1 + if (match('=') && (expr.type === Syntax.ObjectExpression || expr.type === Syntax.ArrayExpression)) { + reinterpretAsAssignmentBindingPattern(expr); + } else if (!isLeftHandSide(expr)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + + expr = delegate.createAssignmentExpression(lex().value, expr, parseAssignmentExpression()); + } + + return expr; + } + + // 11.14 Comma Operator + + function parseExpression() { + var expr, expressions, sequence, coverFormalsList, spreadFound, token; + + expr = parseAssignmentExpression(); + expressions = [ expr ]; + + if (match(',')) { + while (index < length) { + if (!match(',')) { + break; + } + + lex(); + expr = parseSpreadOrAssignmentExpression(); + expressions.push(expr); + + if (expr.type === Syntax.SpreadElement) { + spreadFound = true; + if (!match(')')) { + throwError({}, Messages.ElementAfterSpreadElement); + } + break; + } + } + + sequence = delegate.createSequenceExpression(expressions); + } + + if (state.allowArrowFunction && match(')')) { + token = lookahead2(); + if (token.value === '=>') { + lex(); + + state.allowArrowFunction = false; + expr = expressions; + coverFormalsList = reinterpretAsCoverFormalsList(expr); + if (coverFormalsList) { + return parseArrowFunctionExpression(coverFormalsList); + } + + throwUnexpected(token); + } + } + + if (spreadFound) { + throwError({}, Messages.IllegalSpread); + } + + return sequence || expr; + } + + // 12.1 Block + + function parseStatementList() { + var list = [], + statement; + + while (index < length) { + if (match('}')) { + break; + } + statement = parseSourceElement(); + if (typeof statement === 'undefined') { + break; + } + list.push(statement); + } + + return list; + } + + function parseBlock() { + var block; + + expect('{'); + + block = parseStatementList(); + + expect('}'); + + return delegate.createBlockStatement(block); + } + + // 12.2 Variable Statement + + function parseVariableIdentifier() { + var token = lex(); + + if (token.type !== Token.Identifier) { + throwUnexpected(token); + } + + return delegate.createIdentifier(token.value); + } + + function parseVariableDeclaration(kind) { + var id, + init = null; + if (match('{')) { + id = parseObjectInitialiser(); + reinterpretAsAssignmentBindingPattern(id); + } else if (match('[')) { + id = parseArrayInitialiser(); + reinterpretAsAssignmentBindingPattern(id); + } else { + id = parseVariableIdentifier(); + // 12.2.1 + if (strict && isRestrictedWord(id.name)) { + throwErrorTolerant({}, Messages.StrictVarName); + } + } + + if (kind === 'const') { + if (!match('=')) { + throwError({}, Messages.NoUnintializedConst); + } + expect('='); + init = parseAssignmentExpression(); + } else if (match('=')) { + lex(); + init = parseAssignmentExpression(); + } + + return delegate.createVariableDeclarator(id, init); + } + + function parseVariableDeclarationList(kind) { + var list = []; + + do { + list.push(parseVariableDeclaration(kind)); + if (!match(',')) { + break; + } + lex(); + } while (index < length); + + return list; + } + + function parseVariableStatement() { + var declarations; + + expectKeyword('var'); + + declarations = parseVariableDeclarationList(); + + consumeSemicolon(); + + return delegate.createVariableDeclaration(declarations, 'var'); + } + + // kind may be `const` or `let` + // Both are experimental and not in the specification yet. + // see http://wiki.ecmascript.org/doku.php?id=harmony:const + // and http://wiki.ecmascript.org/doku.php?id=harmony:let + function parseConstLetDeclaration(kind) { + var declarations; + + expectKeyword(kind); + + declarations = parseVariableDeclarationList(kind); + + consumeSemicolon(); + + return delegate.createVariableDeclaration(declarations, kind); + } + + // http://wiki.ecmascript.org/doku.php?id=harmony:modules + + function parsePath() { + var body = []; + + while (true) { + body.push(parseVariableIdentifier()); + if (!match('.')) { + break; + } + lex(); + } + + return delegate.createPath(body); + } + + function parseGlob() { + expect('*'); + return delegate.createGlob(); + } + + function parseModuleDeclaration() { + var id, token, from = null; + + lex(); + + id = parseVariableIdentifier(); + + if (match('{')) { + return delegate.createModuleDeclaration(id, from, parseModuleBlock()); + } + + expect('='); + + token = lookahead; + if (token.type === Token.StringLiteral) { + from = parsePrimaryExpression(); + } else { + from = parsePath(); + } + + consumeSemicolon(); + + return delegate.createModuleDeclaration(id, from, null); + } + + function parseExportSpecifierSetProperty() { + var id, from = null; + + id = parseVariableIdentifier(); + + if (match(':')) { + lex(); + from = parsePath(); + } + + return delegate.createExportSpecifier(id, from); + } + + function parseExportSpecifier() { + var specifiers, id, from; + + if (match('{')) { + lex(); + specifiers = []; + + do { + specifiers.push(parseExportSpecifierSetProperty()); + } while (match(',') && lex()); + + expect('}'); + + return delegate.createExportSpecifierSet(specifiers); + } + + from = null; + + if (match('*')) { + id = parseGlob(); + if (matchContextualKeyword('from')) { + lex(); + from = parsePath(); + } + } else { + id = parseVariableIdentifier(); + } + return delegate.createExportSpecifier(id, from); + } + + function parseExportDeclaration() { + var token, specifiers; + + expectKeyword('export'); + + token = lookahead; + + if (token.type === Token.Keyword || (token.type === Token.Identifier && token.value === 'module')) { + switch (token.value) { + case 'function': + return delegate.createExportDeclaration(parseFunctionDeclaration(), null); + case 'module': + return delegate.createExportDeclaration(parseModuleDeclaration(), null); + case 'let': + case 'const': + return delegate.createExportDeclaration(parseConstLetDeclaration(token.value), null); + case 'var': + return delegate.createExportDeclaration(parseStatement(), null); + case 'class': + return delegate.createExportDeclaration(parseClassDeclaration(), null); + } + throwUnexpected(lex()); + } + + specifiers = [ parseExportSpecifier() ]; + if (match(',')) { + while (index < length) { + if (!match(',')) { + break; + } + lex(); + specifiers.push(parseExportSpecifier()); + } + } + + consumeSemicolon(); + + return delegate.createExportDeclaration(null, specifiers); + } + + function parseImportDeclaration() { + var specifiers, from; + + expectKeyword('import'); + + if (match('*')) { + specifiers = [parseGlob()]; + } else if (match('{')) { + lex(); + specifiers = []; + + do { + specifiers.push(parseImportSpecifier()); + } while (match(',') && lex()); + + expect('}'); + } else { + specifiers = [parseVariableIdentifier()]; + } + + if (!matchContextualKeyword('from')) { + throwError({}, Messages.NoFromAfterImport); + } + + lex(); + + if (lookahead.type === Token.StringLiteral) { + from = parsePrimaryExpression(); + } else { + from = parsePath(); + } + + consumeSemicolon(); + + return delegate.createImportDeclaration(specifiers, from); + } + + function parseImportSpecifier() { + var id, from; + + id = parseVariableIdentifier(); + from = null; + + if (match(':')) { + lex(); + from = parsePath(); + } + + return delegate.createImportSpecifier(id, from); + } + + // 12.3 Empty Statement + + function parseEmptyStatement() { + expect(';'); + return delegate.createEmptyStatement(); + } + + // 12.4 Expression Statement + + function parseExpressionStatement() { + var expr = parseExpression(); + consumeSemicolon(); + return delegate.createExpressionStatement(expr); + } + + // 12.5 If statement + + function parseIfStatement() { + var test, consequent, alternate; + + expectKeyword('if'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + consequent = parseStatement(); + + if (matchKeyword('else')) { + lex(); + alternate = parseStatement(); + } else { + alternate = null; + } + + return delegate.createIfStatement(test, consequent, alternate); + } + + // 12.6 Iteration Statements + + function parseDoWhileStatement() { + var body, test, oldInIteration; + + expectKeyword('do'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + if (match(';')) { + lex(); + } + + return delegate.createDoWhileStatement(body, test); + } + + function parseWhileStatement() { + var test, body, oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + return delegate.createWhileStatement(test, body); + } + + function parseForVariableDeclaration() { + var token = lex(), + declarations = parseVariableDeclarationList(); + + return delegate.createVariableDeclaration(declarations, token.value); + } + + function parseForStatement(opts) { + var init, test, update, left, right, body, operator, oldInIteration; + init = test = update = null; + expectKeyword('for'); + + // http://wiki.ecmascript.org/doku.php?id=proposals:iterators_and_generators&s=each + if (matchContextualKeyword("each")) { + throwError({}, Messages.EachNotAllowed); + } + + expect('('); + + if (match(';')) { + lex(); + } else { + if (matchKeyword('var') || matchKeyword('let') || matchKeyword('const')) { + state.allowIn = false; + init = parseForVariableDeclaration(); + state.allowIn = true; + + if (init.declarations.length === 1) { + if (matchKeyword('in') || matchContextualKeyword('of')) { + operator = lookahead; + if (!((operator.value === 'in' || init.kind !== 'var') && init.declarations[0].init)) { + lex(); + left = init; + right = parseExpression(); + init = null; + } + } + } + } else { + state.allowIn = false; + init = parseExpression(); + state.allowIn = true; + + if (matchContextualKeyword('of')) { + operator = lex(); + left = init; + right = parseExpression(); + init = null; + } else if (matchKeyword('in')) { + // LeftHandSideExpression + if (!isAssignableLeftHandSide(init)) { + throwError({}, Messages.InvalidLHSInForIn); + } + operator = lex(); + left = init; + right = parseExpression(); + init = null; + } + } + + if (typeof left === 'undefined') { + expect(';'); + } + } + + if (typeof left === 'undefined') { + + if (!match(';')) { + test = parseExpression(); + } + expect(';'); + + if (!match(')')) { + update = parseExpression(); + } + } + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + if (!(opts !== undefined && opts.ignore_body)) { + body = parseStatement(); + } + + state.inIteration = oldInIteration; + + if (typeof left === 'undefined') { + return delegate.createForStatement(init, test, update, body); + } + + if (operator.value === 'in') { + return delegate.createForInStatement(left, right, body); + } + return delegate.createForOfStatement(left, right, body); + } + + // 12.7 The continue statement + + function parseContinueStatement() { + var label = null, key; + + expectKeyword('continue'); + + // Optimize the most common form: 'continue;'. + if (source.charCodeAt(index) === 59) { + lex(); + + if (!state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return delegate.createContinueStatement(null); + } + + if (peekLineTerminator()) { + if (!state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return delegate.createContinueStatement(null); + } + + if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError({}, Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return delegate.createContinueStatement(label); + } + + // 12.8 The break statement + + function parseBreakStatement() { + var label = null, key; + + expectKeyword('break'); + + // Catch the very common case first: immediately a semicolon (char #59). + if (source.charCodeAt(index) === 59) { + lex(); + + if (!(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return delegate.createBreakStatement(null); + } + + if (peekLineTerminator()) { + if (!(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return delegate.createBreakStatement(null); + } + + if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError({}, Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return delegate.createBreakStatement(label); + } + + // 12.9 The return statement + + function parseReturnStatement() { + var argument = null; + + expectKeyword('return'); + + if (!state.inFunctionBody) { + throwErrorTolerant({}, Messages.IllegalReturn); + } + + // 'return' followed by a space and an identifier is very common. + if (source.charCodeAt(index) === 32) { + if (isIdentifierStart(source.charCodeAt(index + 1))) { + argument = parseExpression(); + consumeSemicolon(); + return delegate.createReturnStatement(argument); + } + } + + if (peekLineTerminator()) { + return delegate.createReturnStatement(null); + } + + if (!match(';')) { + if (!match('}') && lookahead.type !== Token.EOF) { + argument = parseExpression(); + } + } + + consumeSemicolon(); + + return delegate.createReturnStatement(argument); + } + + // 12.10 The with statement + + function parseWithStatement() { + var object, body; + + if (strict) { + throwErrorTolerant({}, Messages.StrictModeWith); + } + + expectKeyword('with'); + + expect('('); + + object = parseExpression(); + + expect(')'); + + body = parseStatement(); + + return delegate.createWithStatement(object, body); + } + + // 12.10 The swith statement + + function parseSwitchCase() { + var test, + consequent = [], + sourceElement; + + if (matchKeyword('default')) { + lex(); + test = null; + } else { + expectKeyword('case'); + test = parseExpression(); + } + expect(':'); + + while (index < length) { + if (match('}') || matchKeyword('default') || matchKeyword('case')) { + break; + } + sourceElement = parseSourceElement(); + if (typeof sourceElement === 'undefined') { + break; + } + consequent.push(sourceElement); + } + + return delegate.createSwitchCase(test, consequent); + } + + function parseSwitchStatement() { + var discriminant, cases, clause, oldInSwitch, defaultFound; + + expectKeyword('switch'); + + expect('('); + + discriminant = parseExpression(); + + expect(')'); + + expect('{'); + + if (match('}')) { + lex(); + return delegate.createSwitchStatement(discriminant); + } + + cases = []; + + oldInSwitch = state.inSwitch; + state.inSwitch = true; + defaultFound = false; + + while (index < length) { + if (match('}')) { + break; + } + clause = parseSwitchCase(); + if (clause.test === null) { + if (defaultFound) { + throwError({}, Messages.MultipleDefaultsInSwitch); + } + defaultFound = true; + } + cases.push(clause); + } + + state.inSwitch = oldInSwitch; + + expect('}'); + + return delegate.createSwitchStatement(discriminant, cases); + } + + // 12.13 The throw statement + + function parseThrowStatement() { + var argument; + + expectKeyword('throw'); + + if (peekLineTerminator()) { + throwError({}, Messages.NewlineAfterThrow); + } + + argument = parseExpression(); + + consumeSemicolon(); + + return delegate.createThrowStatement(argument); + } + + // 12.14 The try statement + + function parseCatchClause() { + var param, body; + + expectKeyword('catch'); + + expect('('); + if (match(')')) { + throwUnexpected(lookahead); + } + + param = parseExpression(); + // 12.14.1 + if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) { + throwErrorTolerant({}, Messages.StrictCatchVariable); + } + + expect(')'); + body = parseBlock(); + return delegate.createCatchClause(param, body); + } + + function parseTryStatement() { + var block, handlers = [], finalizer = null; + + expectKeyword('try'); + + block = parseBlock(); + + if (matchKeyword('catch')) { + handlers.push(parseCatchClause()); + } + + if (matchKeyword('finally')) { + lex(); + finalizer = parseBlock(); + } + + if (handlers.length === 0 && !finalizer) { + throwError({}, Messages.NoCatchOrFinally); + } + + return delegate.createTryStatement(block, [], handlers, finalizer); + } + + // 12.15 The debugger statement + + function parseDebuggerStatement() { + expectKeyword('debugger'); + + consumeSemicolon(); + + return delegate.createDebuggerStatement(); + } + + // 12 Statements + + function parseStatement() { + var type = lookahead.type, + expr, + labeledBody, + key; + + if (type === Token.EOF) { + throwUnexpected(lookahead); + } + + if (type === Token.Punctuator) { + switch (lookahead.value) { + case ';': + return parseEmptyStatement(); + case '{': + return parseBlock(); + case '(': + return parseExpressionStatement(); + default: + break; + } + } + + if (type === Token.Keyword) { + switch (lookahead.value) { + case 'break': + return parseBreakStatement(); + case 'continue': + return parseContinueStatement(); + case 'debugger': + return parseDebuggerStatement(); + case 'do': + return parseDoWhileStatement(); + case 'for': + return parseForStatement(); + case 'function': + return parseFunctionDeclaration(); + case 'class': + return parseClassDeclaration(); + case 'if': + return parseIfStatement(); + case 'return': + return parseReturnStatement(); + case 'switch': + return parseSwitchStatement(); + case 'throw': + return parseThrowStatement(); + case 'try': + return parseTryStatement(); + case 'var': + return parseVariableStatement(); + case 'while': + return parseWhileStatement(); + case 'with': + return parseWithStatement(); + default: + break; + } + } + + expr = parseExpression(); + + // 12.12 Labelled Statements + if ((expr.type === Syntax.Identifier) && match(':')) { + lex(); + + key = '$' + expr.name; + if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError({}, Messages.Redeclaration, 'Label', expr.name); + } + + state.labelSet[key] = true; + labeledBody = parseStatement(); + delete state.labelSet[key]; + return delegate.createLabeledStatement(expr, labeledBody); + } + + consumeSemicolon(); + + return delegate.createExpressionStatement(expr); + } + + // 13 Function Definition + + function parseConciseBody() { + if (match('{')) { + return parseFunctionSourceElements(); + } + return parseAssignmentExpression(); + } + + function parseFunctionSourceElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted, + oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesizedCount; + + expect('{'); + + while (index < length) { + if (lookahead.type !== Token.StringLiteral) { + break; + } + token = lookahead; + + sourceElement = parseSourceElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.range[0] + 1, token.range[1] - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + oldLabelSet = state.labelSet; + oldInIteration = state.inIteration; + oldInSwitch = state.inSwitch; + oldInFunctionBody = state.inFunctionBody; + oldParenthesizedCount = state.parenthesizedCount; + + state.labelSet = {}; + state.inIteration = false; + state.inSwitch = false; + state.inFunctionBody = true; + state.parenthesizedCount = 0; + + while (index < length) { + if (match('}')) { + break; + } + sourceElement = parseSourceElement(); + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + + expect('}'); + + state.labelSet = oldLabelSet; + state.inIteration = oldInIteration; + state.inSwitch = oldInSwitch; + state.inFunctionBody = oldInFunctionBody; + state.parenthesizedCount = oldParenthesizedCount; + + return delegate.createBlockStatement(sourceElements); + } + + function validateParam(options, param, name) { + var key = '$' + name; + if (strict) { + if (isRestrictedWord(name)) { + options.stricted = param; + options.message = Messages.StrictParamName; + } + if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.stricted = param; + options.message = Messages.StrictParamDupe; + } + } else if (!options.firstRestricted) { + if (isRestrictedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictParamName; + } else if (isStrictModeReservedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictReservedWord; + } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.firstRestricted = param; + options.message = Messages.StrictParamDupe; + } + } + options.paramSet[key] = true; + } + + function parseParam(options) { + var token, rest, param; + + token = lookahead; + if (token.value === '...') { + token = lex(); + rest = true; + } + + if (match('[')) { + param = parseArrayInitialiser(); + reinterpretAsDestructuredParameter(options, param); + } else if (match('{')) { + if (rest) { + throwError({}, Messages.ObjectPatternAsRestParameter); + } + param = parseObjectInitialiser(); + reinterpretAsDestructuredParameter(options, param); + } else { + param = parseVariableIdentifier(); + validateParam(options, token, token.value); + } + + if (rest) { + if (!match(')')) { + throwError({}, Messages.ParameterAfterRestParameter); + } + options.rest = param; + return false; + } + + options.params.push(param); + return !match(')'); + } + + function parseParams(firstRestricted) { + var options; + + options = { + params: [], + rest: null, + firstRestricted: firstRestricted + }; + + expect('('); + + if (!match(')')) { + options.paramSet = {}; + while (index < length) { + if (!parseParam(options)) { + break; + } + expect(','); + } + } + + expect(')'); + + return options; + } + + function parseFunctionDeclaration() { + var id, body, token, tmp, firstRestricted, message, previousStrict, previousYieldAllowed, generator, expression; + + expectKeyword('function'); + + generator = false; + if (match('*')) { + lex(); + generator = true; + } + + token = lookahead; + + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + + tmp = parseParams(firstRestricted); + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = generator; + + // here we redo some work in order to set 'expression' + expression = !match('{'); + body = parseConciseBody(); + + if (strict && firstRestricted) { + throwError(firstRestricted, message); + } + if (strict && tmp.stricted) { + throwErrorTolerant(tmp.stricted, message); + } + if (state.yieldAllowed && !state.yieldFound) { + throwError({}, Messages.NoYieldInGenerator); + } + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createFunctionDeclaration(id, tmp.params, [], body, tmp.rest, generator, expression); + } + + function parseFunctionExpression() { + var token, id = null, firstRestricted, message, tmp, body, previousStrict, previousYieldAllowed, generator, expression; + + expectKeyword('function'); + + generator = false; + + if (match('*')) { + lex(); + generator = true; + } + + if (!match('(')) { + token = lookahead; + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + } + + tmp = parseParams(firstRestricted); + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = generator; + + // here we redo some work in order to set 'expression' + expression = !match('{'); + body = parseConciseBody(); + + if (strict && firstRestricted) { + throwError(firstRestricted, message); + } + if (strict && tmp.stricted) { + throwErrorTolerant(tmp.stricted, message); + } + if (state.yieldAllowed && !state.yieldFound) { + throwError({}, Messages.NoYieldInGenerator); + } + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createFunctionExpression(id, tmp.params, [], body, tmp.rest, generator, expression); + } + + function parseYieldExpression() { + var delegateFlag, expr, previousYieldAllowed; + + expectKeyword('yield'); + + if (!state.yieldAllowed) { + throwErrorTolerant({}, Messages.IllegalYield); + } + + delegateFlag = false; + if (match('*')) { + lex(); + delegateFlag = true; + } + + // It is a Syntax Error if any AssignmentExpression Contains YieldExpression. + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = false; + expr = parseAssignmentExpression(); + state.yieldAllowed = previousYieldAllowed; + state.yieldFound = true; + + return delegate.createYieldExpression(expr, delegateFlag); + } + + // 14 Classes + + function parseMethodDefinition(existingPropNames) { + var token, key, param, propType, isValidDuplicateProp = false; + + if (strict ? matchKeyword('static') : matchContextualKeyword('static')) { + propType = ClassPropertyType.static; + lex(); + } else { + propType = ClassPropertyType.prototype; + } + + if (match('*')) { + lex(); + return delegate.createMethodDefinition( + propType, + '', + parseObjectPropertyKey(), + parsePropertyMethodFunction({ generator: true }) + ); + } + + token = lookahead; + key = parseObjectPropertyKey(); + + if (token.value === 'get' && !match('(')) { + key = parseObjectPropertyKey(); + + // It is a syntax error if any other properties have a name + // duplicating this one unless they are a setter + if (existingPropNames[propType].hasOwnProperty(key.name)) { + isValidDuplicateProp = + // There isn't already a getter for this prop + existingPropNames[propType][key.name].get === undefined + // There isn't already a data prop by this name + && existingPropNames[propType][key.name].data === undefined + // The only existing prop by this name is a setter + && existingPropNames[propType][key.name].set !== undefined; + if (!isValidDuplicateProp) { + throwError(key, Messages.IllegalDuplicateClassProperty); + } + } else { + existingPropNames[propType][key.name] = {}; + } + existingPropNames[propType][key.name].get = true; + + expect('('); + expect(')'); + return delegate.createMethodDefinition( + propType, + 'get', + key, + parsePropertyFunction({ generator: false }) + ); + } + if (token.value === 'set' && !match('(')) { + key = parseObjectPropertyKey(); + + // It is a syntax error if any other properties have a name + // duplicating this one unless they are a getter + if (existingPropNames[propType].hasOwnProperty(key.name)) { + isValidDuplicateProp = + // There isn't already a setter for this prop + existingPropNames[propType][key.name].set === undefined + // There isn't already a data prop by this name + && existingPropNames[propType][key.name].data === undefined + // The only existing prop by this name is a getter + && existingPropNames[propType][key.name].get !== undefined; + if (!isValidDuplicateProp) { + throwError(key, Messages.IllegalDuplicateClassProperty); + } + } else { + existingPropNames[propType][key.name] = {}; + } + existingPropNames[propType][key.name].set = true; + + expect('('); + token = lookahead; + param = [ parseVariableIdentifier() ]; + expect(')'); + return delegate.createMethodDefinition( + propType, + 'set', + key, + parsePropertyFunction({ params: param, generator: false, name: token }) + ); + } + + // It is a syntax error if any other properties have the same name as a + // non-getter, non-setter method + if (existingPropNames[propType].hasOwnProperty(key.name)) { + throwError(key, Messages.IllegalDuplicateClassProperty); + } else { + existingPropNames[propType][key.name] = {}; + } + existingPropNames[propType][key.name].data = true; + + return delegate.createMethodDefinition( + propType, + '', + key, + parsePropertyMethodFunction({ generator: false }) + ); + } + + function parseClassElement(existingProps) { + if (match(';')) { + lex(); + return; + } + return parseMethodDefinition(existingProps); + } + + function parseClassBody() { + var classElement, classElements = [], existingProps = {}; + + existingProps[ClassPropertyType.static] = {}; + existingProps[ClassPropertyType.prototype] = {}; + + expect('{'); + + while (index < length) { + if (match('}')) { + break; + } + classElement = parseClassElement(existingProps); + + if (typeof classElement !== 'undefined') { + classElements.push(classElement); + } + } + + expect('}'); + + return delegate.createClassBody(classElements); + } + + function parseClassExpression() { + var id, previousYieldAllowed, superClass = null; + + expectKeyword('class'); + + if (!matchKeyword('extends') && !match('{')) { + id = parseVariableIdentifier(); + } + + if (matchKeyword('extends')) { + expectKeyword('extends'); + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = false; + superClass = parseAssignmentExpression(); + state.yieldAllowed = previousYieldAllowed; + } + + return delegate.createClassExpression(id, superClass, parseClassBody()); + } + + function parseClassDeclaration() { + var token, id, previousYieldAllowed, superClass = null; + + expectKeyword('class'); + + token = lookahead; + id = parseVariableIdentifier(); + + if (matchKeyword('extends')) { + expectKeyword('extends'); + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = false; + superClass = parseAssignmentExpression(); + state.yieldAllowed = previousYieldAllowed; + } + + return delegate.createClassDeclaration(id, superClass, parseClassBody()); + } + + // 15 Program + + function parseSourceElement() { + if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'const': + case 'let': + return parseConstLetDeclaration(lookahead.value); + case 'function': + return parseFunctionDeclaration(); + default: + return parseStatement(); + } + } + + if (lookahead.type !== Token.EOF) { + return parseStatement(); + } + } + + function parseProgramElement() { + var lineNumber, token; + + if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'export': + return parseExportDeclaration(); + case 'import': + return parseImportDeclaration(); + } + } + + if (lookahead.value === 'module' && lookahead.type === Token.Identifier) { + lineNumber = lookahead.lineNumber; + token = lookahead2(); + if (token.type === Token.Identifier && token.lineNumber === lineNumber) { + return parseModuleDeclaration(); + } + } + + return parseSourceElement(); + } + + function parseProgramElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted; + + while (index < length) { + token = lookahead; + if (token.type !== Token.StringLiteral) { + break; + } + + sourceElement = parseProgramElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.range[0] + 1, token.range[1] - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + while (index < length) { + sourceElement = parseProgramElement(); + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + return sourceElements; + } + + function parseModuleElement() { + return parseProgramElement(); + } + + function parseModuleElements() { + var list = [], + statement; + + while (index < length) { + if (match('}')) { + break; + } + statement = parseModuleElement(); + if (typeof statement === 'undefined') { + break; + } + list.push(statement); + } + + return list; + } + + function parseModuleBlock() { + var block; + + expect('{'); + + block = parseModuleElements(); + + expect('}'); + + return delegate.createBlockStatement(block); + } + + function parseProgram() { + var body; + strict = false; + peek(); + body = parseProgramElements(); + return delegate.createProgram(body); + } + + // The following functions are needed only when the option to preserve + // the comments is active. + + function addComment(type, value, start, end, loc) { + assert(typeof start === 'number', 'Comment must have valid position'); + + // Because the way the actual token is scanned, often the comments + // (if any) are skipped twice during the lexical analysis. + // Thus, we need to skip adding a comment if the comment array already + // handled it. + if (extra.comments.length > 0) { + if (extra.comments[extra.comments.length - 1].range[1] > start) { + return; + } + } + + extra.comments.push({ + type: type, + value: value, + range: [start, end], + loc: loc + }); + } + + function scanComment() { + var comment, ch, loc, start, blockComment, lineComment; + + comment = ''; + blockComment = false; + lineComment = false; + + while (index < length) { + ch = source[index]; + + if (lineComment) { + ch = source[index++]; + if (isLineTerminator(ch.charCodeAt(0))) { + loc.end = { + line: lineNumber, + column: index - lineStart - 1 + }; + lineComment = false; + addComment('Line', comment, start, index - 1, loc); + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + comment = ''; + } else if (index >= length) { + lineComment = false; + comment += ch; + loc.end = { + line: lineNumber, + column: length - lineStart + }; + addComment('Line', comment, start, length, loc); + } else { + comment += ch; + } + } else if (blockComment) { + if (isLineTerminator(ch.charCodeAt(0))) { + if (ch === '\r' && source[index + 1] === '\n') { + ++index; + comment += '\r\n'; + } else { + comment += ch; + } + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + ch = source[index++]; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + comment += ch; + if (ch === '*') { + ch = source[index]; + if (ch === '/') { + comment = comment.substr(0, comment.length - 1); + blockComment = false; + ++index; + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Block', comment, start, index, loc); + comment = ''; + } + } + } + } else if (ch === '/') { + ch = source[index + 1]; + if (ch === '/') { + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + start = index; + index += 2; + lineComment = true; + if (index >= length) { + loc.end = { + line: lineNumber, + column: index - lineStart + }; + lineComment = false; + addComment('Line', comment, start, index, loc); + } + } else if (ch === '*') { + start = index; + index += 2; + blockComment = true; + loc = { + start: { + line: lineNumber, + column: index - lineStart - 2 + } + }; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + break; + } + } else if (isWhiteSpace(ch.charCodeAt(0))) { + ++index; + } else if (isLineTerminator(ch.charCodeAt(0))) { + ++index; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + } else { + break; + } + } + } + + function filterCommentLocation() { + var i, entry, comment, comments = []; + + for (i = 0; i < extra.comments.length; ++i) { + entry = extra.comments[i]; + comment = { + type: entry.type, + value: entry.value + }; + if (extra.range) { + comment.range = entry.range; + } + if (extra.loc) { + comment.loc = entry.loc; + } + comments.push(comment); + } + + extra.comments = comments; + } + + // 16 XJS + + XHTMLEntities = { + quot: '\u0022', + amp: '&', + apos: "\u0027", + lt: "<", + gt: ">", + nbsp: "\u00A0", + iexcl: "\u00A1", + cent: "\u00A2", + pound: "\u00A3", + curren: "\u00A4", + yen: "\u00A5", + brvbar: "\u00A6", + sect: "\u00A7", + uml: "\u00A8", + copy: "\u00A9", + ordf: "\u00AA", + laquo: "\u00AB", + not: "\u00AC", + shy: "\u00AD", + reg: "\u00AE", + macr: "\u00AF", + deg: "\u00B0", + plusmn: "\u00B1", + sup2: "\u00B2", + sup3: "\u00B3", + acute: "\u00B4", + micro: "\u00B5", + para: "\u00B6", + middot: "\u00B7", + cedil: "\u00B8", + sup1: "\u00B9", + ordm: "\u00BA", + raquo: "\u00BB", + frac14: "\u00BC", + frac12: "\u00BD", + frac34: "\u00BE", + iquest: "\u00BF", + Agrave: "\u00C0", + Aacute: "\u00C1", + Acirc: "\u00C2", + Atilde: "\u00C3", + Auml: "\u00C4", + Aring: "\u00C5", + AElig: "\u00C6", + Ccedil: "\u00C7", + Egrave: "\u00C8", + Eacute: "\u00C9", + Ecirc: "\u00CA", + Euml: "\u00CB", + Igrave: "\u00CC", + Iacute: "\u00CD", + Icirc: "\u00CE", + Iuml: "\u00CF", + ETH: "\u00D0", + Ntilde: "\u00D1", + Ograve: "\u00D2", + Oacute: "\u00D3", + Ocirc: "\u00D4", + Otilde: "\u00D5", + Ouml: "\u00D6", + times: "\u00D7", + Oslash: "\u00D8", + Ugrave: "\u00D9", + Uacute: "\u00DA", + Ucirc: "\u00DB", + Uuml: "\u00DC", + Yacute: "\u00DD", + THORN: "\u00DE", + szlig: "\u00DF", + agrave: "\u00E0", + aacute: "\u00E1", + acirc: "\u00E2", + atilde: "\u00E3", + auml: "\u00E4", + aring: "\u00E5", + aelig: "\u00E6", + ccedil: "\u00E7", + egrave: "\u00E8", + eacute: "\u00E9", + ecirc: "\u00EA", + euml: "\u00EB", + igrave: "\u00EC", + iacute: "\u00ED", + icirc: "\u00EE", + iuml: "\u00EF", + eth: "\u00F0", + ntilde: "\u00F1", + ograve: "\u00F2", + oacute: "\u00F3", + ocirc: "\u00F4", + otilde: "\u00F5", + ouml: "\u00F6", + divide: "\u00F7", + oslash: "\u00F8", + ugrave: "\u00F9", + uacute: "\u00FA", + ucirc: "\u00FB", + uuml: "\u00FC", + yacute: "\u00FD", + thorn: "\u00FE", + yuml: "\u00FF", + OElig: "\u0152", + oelig: "\u0153", + Scaron: "\u0160", + scaron: "\u0161", + Yuml: "\u0178", + fnof: "\u0192", + circ: "\u02C6", + tilde: "\u02DC", + Alpha: "\u0391", + Beta: "\u0392", + Gamma: "\u0393", + Delta: "\u0394", + Epsilon: "\u0395", + Zeta: "\u0396", + Eta: "\u0397", + Theta: "\u0398", + Iota: "\u0399", + Kappa: "\u039A", + Lambda: "\u039B", + Mu: "\u039C", + Nu: "\u039D", + Xi: "\u039E", + Omicron: "\u039F", + Pi: "\u03A0", + Rho: "\u03A1", + Sigma: "\u03A3", + Tau: "\u03A4", + Upsilon: "\u03A5", + Phi: "\u03A6", + Chi: "\u03A7", + Psi: "\u03A8", + Omega: "\u03A9", + alpha: "\u03B1", + beta: "\u03B2", + gamma: "\u03B3", + delta: "\u03B4", + epsilon: "\u03B5", + zeta: "\u03B6", + eta: "\u03B7", + theta: "\u03B8", + iota: "\u03B9", + kappa: "\u03BA", + lambda: "\u03BB", + mu: "\u03BC", + nu: "\u03BD", + xi: "\u03BE", + omicron: "\u03BF", + pi: "\u03C0", + rho: "\u03C1", + sigmaf: "\u03C2", + sigma: "\u03C3", + tau: "\u03C4", + upsilon: "\u03C5", + phi: "\u03C6", + chi: "\u03C7", + psi: "\u03C8", + omega: "\u03C9", + thetasym: "\u03D1", + upsih: "\u03D2", + piv: "\u03D6", + ensp: "\u2002", + emsp: "\u2003", + thinsp: "\u2009", + zwnj: "\u200C", + zwj: "\u200D", + lrm: "\u200E", + rlm: "\u200F", + ndash: "\u2013", + mdash: "\u2014", + lsquo: "\u2018", + rsquo: "\u2019", + sbquo: "\u201A", + ldquo: "\u201C", + rdquo: "\u201D", + bdquo: "\u201E", + dagger: "\u2020", + Dagger: "\u2021", + bull: "\u2022", + hellip: "\u2026", + permil: "\u2030", + prime: "\u2032", + Prime: "\u2033", + lsaquo: "\u2039", + rsaquo: "\u203A", + oline: "\u203E", + frasl: "\u2044", + euro: "\u20AC", + image: "\u2111", + weierp: "\u2118", + real: "\u211C", + trade: "\u2122", + alefsym: "\u2135", + larr: "\u2190", + uarr: "\u2191", + rarr: "\u2192", + darr: "\u2193", + harr: "\u2194", + crarr: "\u21B5", + lArr: "\u21D0", + uArr: "\u21D1", + rArr: "\u21D2", + dArr: "\u21D3", + hArr: "\u21D4", + forall: "\u2200", + part: "\u2202", + exist: "\u2203", + empty: "\u2205", + nabla: "\u2207", + isin: "\u2208", + notin: "\u2209", + ni: "\u220B", + prod: "\u220F", + sum: "\u2211", + minus: "\u2212", + lowast: "\u2217", + radic: "\u221A", + prop: "\u221D", + infin: "\u221E", + ang: "\u2220", + and: "\u2227", + or: "\u2228", + cap: "\u2229", + cup: "\u222A", + "int": "\u222B", + there4: "\u2234", + sim: "\u223C", + cong: "\u2245", + asymp: "\u2248", + ne: "\u2260", + equiv: "\u2261", + le: "\u2264", + ge: "\u2265", + sub: "\u2282", + sup: "\u2283", + nsub: "\u2284", + sube: "\u2286", + supe: "\u2287", + oplus: "\u2295", + otimes: "\u2297", + perp: "\u22A5", + sdot: "\u22C5", + lceil: "\u2308", + rceil: "\u2309", + lfloor: "\u230A", + rfloor: "\u230B", + lang: "\u2329", + rang: "\u232A", + loz: "\u25CA", + spades: "\u2660", + clubs: "\u2663", + hearts: "\u2665", + diams: "\u2666" + }; + + function isXJSIdentifierStart(ch) { + // exclude backslash (\) + return (ch !== 92) && isIdentifierStart(ch); + } + + function isXJSIdentifierPart(ch) { + // exclude backslash (\) and add hyphen (-) + return (ch !== 92) && (ch === 45 || isIdentifierPart(ch)); + } + + function scanXJSIdentifier() { + var ch, start, id = '', namespace; + + start = index; + while (index < length) { + ch = source.charCodeAt(index); + if (!isXJSIdentifierPart(ch)) { + break; + } + id += source[index++]; + } + + if (ch === 58) { // : + ++index; + namespace = id; + id = ''; + + while (index < length) { + ch = source.charCodeAt(index); + if (!isXJSIdentifierPart(ch)) { + break; + } + id += source[index++]; + } + } + + if (!id) { + throwError({}, Messages.InvalidXJSTagName); + } + + return { + type: Token.XJSIdentifier, + value: id, + namespace: namespace, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanXJSEntity() { + var ch, str = '', count = 0, entity; + ch = source[index]; + assert(ch === '&', 'Entity must start with an ampersand'); + index++; + while (index < length && count++ < 10) { + ch = source[index++]; + if (ch === ';') { + break; + } + str += ch; + } + + if (str[0] === '#' && str[1] === 'x') { + entity = String.fromCharCode(parseInt(str.substr(2), 16)); + } else if (str[0] === '#') { + entity = String.fromCharCode(parseInt(str.substr(1), 10)); + } else { + entity = XHTMLEntities[str]; + } + return entity; + } + + function scanXJSText(stopChars) { + var ch, str = '', start; + start = index; + while (index < length) { + ch = source[index]; + if (stopChars.indexOf(ch) !== -1) { + break; + } + if (ch === '&') { + str += scanXJSEntity(); + } else { + ch = source[index++]; + if (isLineTerminator(ch.charCodeAt(0))) { + ++lineNumber; + } + str += ch; + } + } + return { + type: Token.XJSText, + value: str, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanXJSStringLiteral() { + var innerToken, quote, start; + + quote = source[index]; + assert((quote === '\'' || quote === '"'), + 'String literal must starts with a quote'); + + start = index; + ++index; + + innerToken = scanXJSText([quote]); + + if (quote !== source[index]) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + ++index; + + innerToken.range = [start, index]; + + return innerToken; + } + + /** + * Between XJS opening and closing tags (e.g. HERE), anything that + * is not another XJS tag and is not an expression wrapped by {} is text. + */ + function advanceXJSChild() { + var ch = source.charCodeAt(index); + + // { (123) and < (60) + if (ch !== 123 && ch !== 60) { + return scanXJSText(['<', '{']); + } + + return scanPunctuator(); + } + + function parseXJSIdentifier() { + var token; + + if (lookahead.type !== Token.XJSIdentifier) { + throwError({}, Messages.InvalidXJSTagName); + } + + token = lex(); + return delegate.createXJSIdentifier(token.value, token.namespace); + } + + function parseXJSAttributeValue() { + var value; + if (lookahead.value === '{') { + value = parseXJSExpression(); + } else if (lookahead.type === Token.XJSText) { + value = delegate.createLiteral(lex()); + } else { + throwError({}, Messages.InvalidXJSAttributeValue); + } + return value; + } + + function parseXJSExpression() { + var value, origInXJSChild, origInXJSTag; + + origInXJSChild = state.inXJSChild; + origInXJSTag = state.inXJSTag; + state.inXJSChild = false; + state.inXJSTag = false; + + expect('{'); + + value = parseExpression(); + + state.inXJSChild = origInXJSChild; + state.inXJSTag = origInXJSTag; + + expect('}'); + + return delegate.createXJSExpression(value); + } + + function parseXJSAttribute() { + var token, name, value; + + name = parseXJSIdentifier(); + + // HTML empty attribute + if (match('=')) { + lex(); + return delegate.createXJSAttribute(name, parseXJSAttributeValue()); + } + + return delegate.createXJSAttribute(name); + } + + function parseXJSChild() { + var token; + if (lookahead.value === '{') { + token = parseXJSExpression(); + } else if (lookahead.type === Token.XJSText) { + token = delegate.createLiteral(lex()); + } else { + state.inXJSChild = false; + token = parseXJSElement(); + state.inXJSChild = true; + } + return token; + } + + function parseXJSClosingElement() { + var name, origInXJSTag; + origInXJSTag = state.inXJSTag; + state.inXJSTag = true; + state.inXJSChild = false; + expect('<'); + expect('/'); + name = parseXJSIdentifier(); + state.inXJSTag = origInXJSTag; + expect('>'); + return delegate.createXJSClosingElement(name); + } + + function parseXJSOpeningElement() { + var name, attribute, attributes = [], selfClosing = false, origInXJSTag; + + origInXJSTag = state.inXJSTag; + state.inXJSTag = true; + + expect('<'); + + name = parseXJSIdentifier(); + + while (index < length && + lookahead.value !== '/' && + lookahead.value !== '>') { + attributes.push(parseXJSAttribute()); + } + + state.inXJSTag = origInXJSTag; + + if (lookahead.value === '/') { + expect('/'); + expect('>'); + selfClosing = true; + } else { + state.inXJSChild = true; + expect('>'); + } + return delegate.createXJSOpeningElement(name, attributes, selfClosing); + } + + function parseXJSElement() { + var openingElement, closingElement, children = [], origInXJSChild; + + openingElement = parseXJSOpeningElement(); + + if (!openingElement.selfClosing) { + origInXJSChild = state.inXJSChild; + while (index < length) { + state.inXJSChild = false; // 0) { + token = extra.tokens[extra.tokens.length - 1]; + if (token.range[0] === pos && token.type === 'Punctuator') { + if (token.value === '/' || token.value === '/=') { + extra.tokens.pop(); + } + } + } + + extra.tokens.push({ + type: 'RegularExpression', + value: regex.literal, + range: [pos, index], + loc: loc + }); + } + + return regex; + } + + function filterTokenLocation() { + var i, entry, token, tokens = []; + + for (i = 0; i < extra.tokens.length; ++i) { + entry = extra.tokens[i]; + token = { + type: entry.type, + value: entry.value + }; + if (extra.range) { + token.range = entry.range; + } + if (extra.loc) { + token.loc = entry.loc; + } + tokens.push(token); + } + + extra.tokens = tokens; + } + + function createLocationMarker() { + var marker = {}; + + marker.range = [index, index]; + marker.loc = { + start: { + line: lineNumber, + column: index - lineStart + }, + end: { + line: lineNumber, + column: index - lineStart + } + }; + + marker.end = function () { + this.range[1] = index; + this.loc.end.line = lineNumber; + this.loc.end.column = index - lineStart; + }; + + marker.applyGroup = function (node) { + if (extra.range) { + node.groupRange = [this.range[0], this.range[1]]; + } + if (extra.loc) { + node.groupLoc = { + start: { + line: this.loc.start.line, + column: this.loc.start.column + }, + end: { + line: this.loc.end.line, + column: this.loc.end.column + } + }; + node = delegate.postProcess(node); + } + }; + + marker.apply = function (node) { + if (extra.range) { + node.range = [this.range[0], this.range[1]]; + } + if (extra.loc) { + node.loc = { + start: { + line: this.loc.start.line, + column: this.loc.start.column + }, + end: { + line: this.loc.end.line, + column: this.loc.end.column + } + }; + node = delegate.postProcess(node); + } + }; + + return marker; + } + + function trackGroupExpression() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + expect('('); + + ++state.parenthesizedCount; + + state.allowArrowFunction = !state.allowArrowFunction; + expr = parseExpression(); + state.allowArrowFunction = false; + + if (expr.type === 'ArrowFunctionExpression') { + marker.end(); + marker.apply(expr); + } else { + expect(')'); + marker.end(); + marker.applyGroup(expr); + } + + return expr; + } + + function trackLeftHandSideExpression() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || lookahead.type === Token.Template) { + if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + marker.end(); + marker.apply(expr); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + marker.end(); + marker.apply(expr); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + marker.end(); + marker.apply(expr); + } + } + + return expr; + } + + function trackLeftHandSideExpressionAllowCall() { + var marker, expr, args; + + skipComment(); + marker = createLocationMarker(); + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || match('(') || lookahead.type === Token.Template) { + if (match('(')) { + args = parseArguments(); + expr = delegate.createCallExpression(expr, args); + marker.end(); + marker.apply(expr); + } else if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + marker.end(); + marker.apply(expr); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + marker.end(); + marker.apply(expr); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + marker.end(); + marker.apply(expr); + } + } + + return expr; + } + + function filterGroup(node) { + var n, i, entry; + + n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {}; + for (i in node) { + if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') { + entry = node[i]; + if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) { + n[i] = entry; + } else { + n[i] = filterGroup(entry); + } + } + } + return n; + } + + function wrapTrackingFunction(range, loc, preserveWhitespace) { + + return function (parseFunction) { + + function isBinary(node) { + return node.type === Syntax.LogicalExpression || + node.type === Syntax.BinaryExpression; + } + + function visit(node) { + var start, end; + + if (isBinary(node.left)) { + visit(node.left); + } + if (isBinary(node.right)) { + visit(node.right); + } + + if (range) { + if (node.left.groupRange || node.right.groupRange) { + start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0]; + end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1]; + node.range = [start, end]; + } else if (typeof node.range === 'undefined') { + start = node.left.range[0]; + end = node.right.range[1]; + node.range = [start, end]; + } + } + if (loc) { + if (node.left.groupLoc || node.right.groupLoc) { + start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start; + end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end; + node.loc = { + start: start, + end: end + }; + node = delegate.postProcess(node); + } else if (typeof node.loc === 'undefined') { + node.loc = { + start: node.left.loc.start, + end: node.right.loc.end + }; + node = delegate.postProcess(node); + } + } + } + + return function () { + var marker, node; + + if (!preserveWhitespace) { + skipComment(); + } + + marker = createLocationMarker(); + node = parseFunction.apply(null, arguments); + marker.end(); + + if (range && typeof node.range === 'undefined') { + marker.apply(node); + } + + if (loc && typeof node.loc === 'undefined') { + marker.apply(node); + } + + if (isBinary(node)) { + visit(node); + } + + return node; + }; + }; + } + + function patch() { + + var wrapTracking, wrapTrackingPreserveWhitespace; + + if (extra.comments) { + extra.skipComment = skipComment; + skipComment = scanComment; + } + + if (extra.range || extra.loc) { + + extra.parseGroupExpression = parseGroupExpression; + extra.parseLeftHandSideExpression = parseLeftHandSideExpression; + extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall; + parseGroupExpression = trackGroupExpression; + parseLeftHandSideExpression = trackLeftHandSideExpression; + parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall; + + wrapTracking = wrapTrackingFunction(extra.range, extra.loc); + wrapTrackingPreserveWhitespace = + wrapTrackingFunction(extra.range, extra.loc, true); + + extra.parseAssignmentExpression = parseAssignmentExpression; + extra.parseBinaryExpression = parseBinaryExpression; + extra.parseBlock = parseBlock; + extra.parseFunctionSourceElements = parseFunctionSourceElements; + extra.parseCatchClause = parseCatchClause; + extra.parseComputedMember = parseComputedMember; + extra.parseConditionalExpression = parseConditionalExpression; + extra.parseConstLetDeclaration = parseConstLetDeclaration; + extra.parseExportDeclaration = parseExportDeclaration; + extra.parseExportSpecifier = parseExportSpecifier; + extra.parseExportSpecifierSetProperty = parseExportSpecifierSetProperty; + extra.parseExpression = parseExpression; + extra.parseForVariableDeclaration = parseForVariableDeclaration; + extra.parseFunctionDeclaration = parseFunctionDeclaration; + extra.parseFunctionExpression = parseFunctionExpression; + extra.parseParams = parseParams; + extra.parseGlob = parseGlob; + extra.parseImportDeclaration = parseImportDeclaration; + extra.parseImportSpecifier = parseImportSpecifier; + extra.parseModuleDeclaration = parseModuleDeclaration; + extra.parseModuleBlock = parseModuleBlock; + extra.parseNewExpression = parseNewExpression; + extra.parseNonComputedProperty = parseNonComputedProperty; + extra.parseObjectProperty = parseObjectProperty; + extra.parseObjectPropertyKey = parseObjectPropertyKey; + extra.parsePath = parsePath; + extra.parsePostfixExpression = parsePostfixExpression; + extra.parsePrimaryExpression = parsePrimaryExpression; + extra.parseProgram = parseProgram; + extra.parsePropertyFunction = parsePropertyFunction; + extra.parseSpreadOrAssignmentExpression = parseSpreadOrAssignmentExpression; + extra.parseTemplateElement = parseTemplateElement; + extra.parseTemplateLiteral = parseTemplateLiteral; + extra.parseStatement = parseStatement; + extra.parseSwitchCase = parseSwitchCase; + extra.parseUnaryExpression = parseUnaryExpression; + extra.parseVariableDeclaration = parseVariableDeclaration; + extra.parseVariableIdentifier = parseVariableIdentifier; + extra.parseMethodDefinition = parseMethodDefinition; + extra.parseClassDeclaration = parseClassDeclaration; + extra.parseClassExpression = parseClassExpression; + extra.parseClassBody = parseClassBody; + extra.parseXJSIdentifier = parseXJSIdentifier; + extra.parseXJSChild = parseXJSChild; + extra.parseXJSAttribute = parseXJSAttribute; + extra.parseXJSAttributeValue = parseXJSAttributeValue; + extra.parseXJSExpression = parseXJSExpression; + extra.parseXJSElement = parseXJSElement; + extra.parseXJSClosingElement = parseXJSClosingElement; + extra.parseXJSOpeningElement = parseXJSOpeningElement; + + parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression); + parseBinaryExpression = wrapTracking(extra.parseBinaryExpression); + parseBlock = wrapTracking(extra.parseBlock); + parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements); + parseCatchClause = wrapTracking(extra.parseCatchClause); + parseComputedMember = wrapTracking(extra.parseComputedMember); + parseConditionalExpression = wrapTracking(extra.parseConditionalExpression); + parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration); + parseExportDeclaration = wrapTracking(parseExportDeclaration); + parseExportSpecifier = wrapTracking(parseExportSpecifier); + parseExportSpecifierSetProperty = wrapTracking(parseExportSpecifierSetProperty); + parseExpression = wrapTracking(extra.parseExpression); + parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration); + parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration); + parseFunctionExpression = wrapTracking(extra.parseFunctionExpression); + parseParams = wrapTracking(extra.parseParams); + parseGlob = wrapTracking(extra.parseGlob); + parseImportDeclaration = wrapTracking(extra.parseImportDeclaration); + parseImportSpecifier = wrapTracking(extra.parseImportSpecifier); + parseModuleDeclaration = wrapTracking(extra.parseModuleDeclaration); + parseModuleBlock = wrapTracking(extra.parseModuleBlock); + parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression); + parseNewExpression = wrapTracking(extra.parseNewExpression); + parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty); + parseObjectProperty = wrapTracking(extra.parseObjectProperty); + parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey); + parsePath = wrapTracking(extra.parsePath); + parsePostfixExpression = wrapTracking(extra.parsePostfixExpression); + parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression); + parseProgram = wrapTracking(extra.parseProgram); + parsePropertyFunction = wrapTracking(extra.parsePropertyFunction); + parseTemplateElement = wrapTracking(extra.parseTemplateElement); + parseTemplateLiteral = wrapTracking(extra.parseTemplateLiteral); + parseSpreadOrAssignmentExpression = wrapTracking(extra.parseSpreadOrAssignmentExpression); + parseStatement = wrapTracking(extra.parseStatement); + parseSwitchCase = wrapTracking(extra.parseSwitchCase); + parseUnaryExpression = wrapTracking(extra.parseUnaryExpression); + parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration); + parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier); + parseMethodDefinition = wrapTracking(extra.parseMethodDefinition); + parseClassDeclaration = wrapTracking(extra.parseClassDeclaration); + parseClassExpression = wrapTracking(extra.parseClassExpression); + parseClassBody = wrapTracking(extra.parseClassBody); + parseXJSIdentifier = wrapTracking(extra.parseXJSIdentifier); + parseXJSChild = wrapTrackingPreserveWhitespace(extra.parseXJSChild); + parseXJSAttribute = wrapTracking(extra.parseXJSAttribute); + parseXJSAttributeValue = wrapTracking(extra.parseXJSAttributeValue); + parseXJSExpression = wrapTracking(extra.parseXJSExpression); + parseXJSElement = wrapTracking(extra.parseXJSElement); + parseXJSClosingElement = wrapTracking(extra.parseXJSClosingElement); + parseXJSOpeningElement = wrapTracking(extra.parseXJSOpeningElement); + } + + if (typeof extra.tokens !== 'undefined') { + extra.advance = advance; + extra.scanRegExp = scanRegExp; + + advance = collectToken; + scanRegExp = collectRegex; + } + } + + function unpatch() { + if (typeof extra.skipComment === 'function') { + skipComment = extra.skipComment; + } + + if (extra.range || extra.loc) { + parseAssignmentExpression = extra.parseAssignmentExpression; + parseBinaryExpression = extra.parseBinaryExpression; + parseBlock = extra.parseBlock; + parseFunctionSourceElements = extra.parseFunctionSourceElements; + parseCatchClause = extra.parseCatchClause; + parseComputedMember = extra.parseComputedMember; + parseConditionalExpression = extra.parseConditionalExpression; + parseConstLetDeclaration = extra.parseConstLetDeclaration; + parseExportDeclaration = extra.parseExportDeclaration; + parseExportSpecifier = extra.parseExportSpecifier; + parseExportSpecifierSetProperty = extra.parseExportSpecifierSetProperty; + parseExpression = extra.parseExpression; + parseForVariableDeclaration = extra.parseForVariableDeclaration; + parseFunctionDeclaration = extra.parseFunctionDeclaration; + parseFunctionExpression = extra.parseFunctionExpression; + parseGlob = extra.parseGlob; + parseImportDeclaration = extra.parseImportDeclaration; + parseImportSpecifier = extra.parseImportSpecifier; + parseGroupExpression = extra.parseGroupExpression; + parseLeftHandSideExpression = extra.parseLeftHandSideExpression; + parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall; + parseModuleDeclaration = extra.parseModuleDeclaration; + parseModuleBlock = extra.parseModuleBlock; + parseNewExpression = extra.parseNewExpression; + parseNonComputedProperty = extra.parseNonComputedProperty; + parseObjectProperty = extra.parseObjectProperty; + parseObjectPropertyKey = extra.parseObjectPropertyKey; + parsePath = extra.parsePath; + parsePostfixExpression = extra.parsePostfixExpression; + parsePrimaryExpression = extra.parsePrimaryExpression; + parseProgram = extra.parseProgram; + parsePropertyFunction = extra.parsePropertyFunction; + parseTemplateElement = extra.parseTemplateElement; + parseTemplateLiteral = extra.parseTemplateLiteral; + parseSpreadOrAssignmentExpression = extra.parseSpreadOrAssignmentExpression; + parseStatement = extra.parseStatement; + parseSwitchCase = extra.parseSwitchCase; + parseUnaryExpression = extra.parseUnaryExpression; + parseVariableDeclaration = extra.parseVariableDeclaration; + parseVariableIdentifier = extra.parseVariableIdentifier; + parseMethodDefinition = extra.parseMethodDefinition; + parseClassDeclaration = extra.parseClassDeclaration; + parseClassExpression = extra.parseClassExpression; + parseClassBody = extra.parseClassBody; + parseXJSIdentifier = extra.parseXJSIdentifier; + parseXJSChild = extra.parseXJSChild; + parseXJSAttribute = extra.parseXJSAttribute; + parseXJSAttributeValue = extra.parseXJSAttributeValue; + parseXJSExpression = extra.parseXJSExpression; + parseXJSElement = extra.parseXJSElement; + parseXJSClosingElement = extra.parseXJSClosingElement; + parseXJSOpeningElement = extra.parseXJSOpeningElement; + } + + if (typeof extra.scanRegExp === 'function') { + advance = extra.advance; + scanRegExp = extra.scanRegExp; + } + } + + // This is used to modify the delegate. + + function extend(object, properties) { + var entry, result = {}; + + for (entry in object) { + if (object.hasOwnProperty(entry)) { + result[entry] = object[entry]; + } + } + + for (entry in properties) { + if (properties.hasOwnProperty(entry)) { + result[entry] = properties[entry]; + } + } + + return result; + } + + function tokenize(code, options) { + var toString, + token, + tokens; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + delegate = SyntaxTreeDelegate; + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + length = source.length; + lookahead = null; + state = { + allowIn: true, + labelSet: {}, + inFunctionBody: false, + inIteration: false, + inSwitch: false + }; + + extra = {}; + + // Options matching. + options = options || {}; + + // Of course we collect tokens here. + options.tokens = true; + extra.tokens = []; + extra.tokenize = true; + // The following two fields are necessary to compute the Regex tokens. + extra.openParenToken = -1; + extra.openCurlyToken = -1; + + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + + if (length > 0) { + if (typeof source[0] === 'undefined') { + // Try first to convert to a string. This is good as fast path + // for old IE which understands string indexing for string + // literals only and not for string object. + if (code instanceof String) { + source = code.valueOf(); + } + } + } + + patch(); + + try { + peek(); + if (lookahead.type === Token.EOF) { + return extra.tokens; + } + + token = lex(); + while (lookahead.type !== Token.EOF) { + try { + token = lex(); + } catch (lexError) { + token = lookahead; + if (extra.errors) { + extra.errors.push(lexError); + // We have to break on the first error + // to avoid infinite loops. + break; + } else { + throw lexError; + } + } + } + + filterTokenLocation(); + tokens = extra.tokens; + if (typeof extra.comments !== 'undefined') { + filterCommentLocation(); + tokens.comments = extra.comments; + } + if (typeof extra.errors !== 'undefined') { + tokens.errors = extra.errors; + } + } catch (e) { + throw e; + } finally { + unpatch(); + extra = {}; + } + return tokens; + } + + function parse(code, options) { + var program, toString; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + delegate = SyntaxTreeDelegate; + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + length = source.length; + lookahead = null; + state = { + allowIn: true, + labelSet: {}, + parenthesizedCount: 0, + inFunctionBody: false, + inIteration: false, + inSwitch: false, + yieldAllowed: false, + yieldFound: false + }; + + extra = {}; + if (typeof options !== 'undefined') { + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + + if (extra.loc && options.source !== null && options.source !== undefined) { + delegate = extend(delegate, { + 'postProcess': function (node) { + node.loc.source = toString(options.source); + return node; + } + }); + } + + if (typeof options.tokens === 'boolean' && options.tokens) { + extra.tokens = []; + } + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + } + + if (length > 0) { + if (typeof source[0] === 'undefined') { + // Try first to convert to a string. This is good as fast path + // for old IE which understands string indexing for string + // literals only and not for string object. + if (code instanceof String) { + source = code.valueOf(); + } + } + } + + patch(); + try { + program = parseProgram(); + if (typeof extra.comments !== 'undefined') { + filterCommentLocation(); + program.comments = extra.comments; + } + if (typeof extra.tokens !== 'undefined') { + filterTokenLocation(); + program.tokens = extra.tokens; + } + if (typeof extra.errors !== 'undefined') { + program.errors = extra.errors; + } + if (extra.range || extra.loc) { + program.body = filterGroup(program.body); + } + } catch (e) { + throw e; + } finally { + unpatch(); + extra = {}; + } + + return program; + } + + // Sync with package.json and component.json. + exports.version = '1.1.0-dev-harmony'; + + exports.tokenize = tokenize; + + exports.parse = parse; + + // Deep copy. + exports.Syntax = (function () { + var name, types = {}; + + if (typeof Object.create === 'function') { + types = Object.create(null); + } + + for (name in Syntax) { + if (Syntax.hasOwnProperty(name)) { + types[name] = Syntax[name]; + } + } + + if (typeof Object.freeze === 'function') { + Object.freeze(types); + } + + return types; + }()); + +})); +/* vim: set sw=4 ts=4 et tw=80 : */ + +})() +},{}],11:[function(require,module,exports){ +(function(){/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*global exports:true*/ +"use strict"; +var catchup = require('../lib/utils').catchup; +var append = require('../lib/utils').append; +var move = require('../lib/utils').move; + +var knownTags = { + a: true, + abbr: true, + address: true, + applet: true, + area: true, + article: true, + aside: true, + audio: true, + b: true, + base: true, + bdi: true, + bdo: true, + blockquote: true, + body: true, + br: true, + button: true, + canvas: true, + circle: true, + ellipse: true, + caption: true, + cite: true, + code: true, + col: true, + colgroup: true, + command: true, + data: true, + datalist: true, + dd: true, + del: true, + details: true, + dfn: true, + dialog: true, + div: true, + dl: true, + dt: true, + em: true, + embed: true, + fieldset: true, + figcaption: true, + figure: true, + footer: true, + form: true, + g: true, + h1: true, + h2: true, + h3: true, + h4: true, + h5: true, + h6: true, + head: true, + header: true, + hgroup: true, + hr: true, + html: true, + i: true, + iframe: true, + img: true, + input: true, + ins: true, + kbd: true, + keygen: true, + label: true, + legend: true, + li: true, + line: true, + link: true, + map: true, + mark: true, + marquee: true, + menu: true, + meta: true, + meter: true, + nav: true, + noscript: true, + object: true, + ol: true, + optgroup: true, + option: true, + output: true, + p: true, + path: true, + param: true, + pre: true, + progress: true, + q: true, + rect: true, + rp: true, + rt: true, + ruby: true, + s: true, + samp: true, + script: true, + section: true, + select: true, + small: true, + source: true, + span: true, + strong: true, + style: true, + sub: true, + summary: true, + sup: true, + svg: true, + table: true, + tbody: true, + td: true, + text: true, + textarea: true, + tfoot: true, + th: true, + thead: true, + time: true, + title: true, + tr: true, + track: true, + u: true, + ul: true, + 'var': true, + video: true, + wbr: true +}; + +function safeTrim(string) { + return string.replace(/^[ \t]+/, '').replace(/[ \t]+$/, ''); +} + +// Replace all trailing whitespace characters with a single space character +function trimWithSingleSpace(string) { + return string.replace(/^[ \t\xA0]{2,}/, ' '). + replace(/[ \t\xA0]{2,}$/, ' ').replace(/^\s+$/, ''); +} + +/** + * Special handling for multiline string literals + * print lines: + * + * line + * line + * + * as: + * + * "line "+ + * "line" + */ +function renderXJSLiteral(object, isLast, state, start, end) { + /** Added blank check filtering and triming*/ + var trimmedChildValue = safeTrim(object.value); + + if (trimmedChildValue) { + // head whitespace + append(object.value.match(/^[\t ]*/)[0], state); + if (start) { + append(start, state); + } + + var trimmedChildValueWithSpace = trimWithSingleSpace(object.value); + + /** + */ + var initialLines = trimmedChildValue.split(/\r\n|\n|\r/); + + var lines = initialLines.filter(function(line) { + return safeTrim(line).length > 0; + }); + + var hasInitialNewLine = initialLines[0] !== lines[0]; + var hasFinalNewLine = + initialLines[initialLines.length - 1] !== lines[lines.length - 1]; + + var numLines = lines.length; + lines.forEach(function (line, ii) { + var lastLine = ii === numLines - 1; + var trimmedLine = safeTrim(line); + if (trimmedLine === '' && !lastLine) { + append(line, state); + } else { + var preString = ''; + var postString = ''; + var leading = ''; + + if (ii === 0) { + if (hasInitialNewLine) { + preString = ' '; + leading = '\n'; + } + if (trimmedChildValueWithSpace.substring(0, 1) === ' ') { + // If this is the first line, and the original content starts with + // whitespace, place a single space at the beginning. + preString = ' '; + } + } else { + leading = line.match(/^[ \t]*/)[0]; + } + if (!lastLine || trimmedChildValueWithSpace.substr( + trimmedChildValueWithSpace.length - 1, 1) === ' ' || + hasFinalNewLine + ) { + // If either not on the last line, or the original content ends with + // whitespace, place a single character at the end. + postString = ' '; + } + + append( + leading + + JSON.stringify( + preString + trimmedLine + postString + ) + + (lastLine ? '' : '+') + + line.match(/[ \t]*$/)[0], + state); + } + if (!lastLine) { + append('\n', state); + } + }); + } else { + if (start) { + append(start, state); + } + append('""', state); + } + if (end) { + append(end, state); + } + + // add comma before trailing whitespace + if (!isLast) { + append(',', state); + } + + // tail whitespace + append(object.value.match(/[ \t]*$/)[0], state); + move(object.range[1], state); +} + +function renderXJSExpression(traverse, object, isLast, path, state) { + // Plus 1 to skip `{`. + move(object.range[0] + 1, state); + traverse(object.value, path, state); + if (!isLast) { + // If we need to append a comma, make sure to do so after the expression. + catchup(object.value.range[1], state); + append(',', state); + } + // Minus 1 to skip `}`. + catchup(object.range[1] - 1, state); + move(object.range[1], state); + return false; +} + +function quoteAttrName(attr) { + // Quote invalid JS identifiers. + if (!/^[a-z_$][a-z\d_$]*$/i.test(attr)) { + return "'" + attr + "'"; + } + return attr; +} + +exports.knownTags = knownTags; +exports.renderXJSExpression = renderXJSExpression; +exports.renderXJSLiteral = renderXJSLiteral; +exports.quoteAttrName = quoteAttrName; + +})() +},{"../lib/utils":8}],10:[function(require,module,exports){ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./source-map/source-node').SourceNode; + +},{"./source-map/source-map-generator":12,"./source-map/source-map-consumer":13,"./source-map/source-node":14}],5:[function(require,module,exports){ +(function(){/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*global exports:true*/ +"use strict"; + +/** + * Desugarizer for ES6 minimal class proposal. See + * http://wiki.ecmascript.org/doku.php?id=harmony:proposals + * + * Does not require any runtime. Preserves whitespace and comments. + * Supports a class declaration with methods, super calls and inheritance. + * Currently does not support for getters and setters, since there's a very + * low probability we're going to use them anytime soon. + * + * Additional features: + * - Any member with private name (the name with prefix _, such _name) inside + * the class's scope will be munged. This would will to eliminate the case + * of sub-class accidentally overriding the super-class's provate properties + * also discouage people from accessing private members that they should not + * access. However, quoted property names don't get munged. + * + * class SkinnedMesh extends require('THREE').Mesh { + * + * update(camera) { + * camera.code = 'iphone' + * super.update(camera); + * } + * + * / + * * @constructor + * / + * constructor(geometry, materials) { + * super(geometry, materials); + * + * super.update(1); + * + * this.identityMatrix = new THREE.Matrix4(); + * this.bones = []; + * this.boneMatrices = []; + * this._name = 'foo'; + * } + * + * / + * * some other code + * / + * readMore() { + * + * } + * + * _doSomething() { + * + * } + * } + * + * should be converted to + * + * var SkinnedMesh = (function() { + * var __super = require('parent').Mesh; + * + * / + * * @constructor + * / + * function SkinnedMesh(geometry, materials) { + * __super.call(this, geometry, materials); + * + * __super.prototype.update.call(this, 1); + * + * this.identityMatrix = new THREE.Matrix4(); + * this.bones = []; + * this.boneMatrices = []; + * this.$SkinnedMesh_name = 'foo'; + * } + * SkinnedMesh.prototype = Object.create(__super.prototype); + * SkinnedMesh.prototype.constructor = SkinnedMesh; + * + * / + * * @param camera + * / + * SkinnedMesh.prototype.update = function(camera) { + * camera.code = 'iphone' + * __super.prototype.update.call(this, camera); + * }; + * + * SkinnedMesh.prototype.readMore = function() { + * + * }; + * + * SkinnedMesh.prototype.$SkinnedMesh_doSomething = function() { + * + * }; + * + * return SkinnedMesh; + * })(); + * + */ +var Syntax = require('esprima').Syntax; +var base62 = require('base62'); + +var catchup = require('../lib/utils').catchup; +var append = require('../lib/utils').append; +var move = require('../lib/utils').move; +var indentBefore = require('../lib/utils').indentBefore; +var updateIndent = require('../lib/utils').updateIndent; +var updateState = require('../lib/utils').updateState; + +function findConstructorIndex(object) { + var classElements = object.body && object.body.body || []; + for (var i = 0; i < classElements.length; i++) { + if (classElements[i].type === Syntax.MethodDefinition && + classElements[i].key.name === 'constructor') { + return i; + } + } + return -1; +} + +var _mungedSymbolMaps = {}; +function getMungedName(scopeName, name, minify) { + if (minify) { + if (!_mungedSymbolMaps[scopeName]) { + _mungedSymbolMaps[scopeName] = { + symbolMap: {}, + identifierUUIDCounter: 0 + }; + } + + var symbolMap = _mungedSymbolMaps[scopeName].symbolMap; + if (!symbolMap[name]) { + symbolMap[name] = + base62.encode(_mungedSymbolMaps[scopeName].identifierUUIDCounter); + _mungedSymbolMaps[scopeName].identifierUUIDCounter++; + } + name = symbolMap[name]; + } + return '$' + scopeName + name; +} + +function shouldMungeName(scopeName, name, state) { + // only run when @preventMunge is not present in the docblock + if (state.g.preventMunge === undefined) { + var docblock = require('../lib/docblock'); + state.g.preventMunge = docblock.parseAsObject( + docblock.extract(state.g.source)).preventMunge !== undefined; + } + // Starts with only a single underscore (i.e. don't count double-underscores) + return !state.g.preventMunge && scopeName ? /^_(?!_)/.test(name) : false; +} + + +function getProtoOfPrototypeVariableName(superVar) { + return superVar + 'ProtoOfPrototype'; +} + +function getSuperKeyName(superVar) { + return superVar + 'Key'; +} + +function getSuperProtoOfPrototypeVariable(superVariableName, indent) { + var string = (indent + + 'var $proto = $superName && $superName.prototype ? ' + + '$superName.prototype : $superName;\n' + ).replace(/\$proto/g, getProtoOfPrototypeVariableName(superVariableName)) + .replace(/\$superName/g, superVariableName); + return string; +} + + +function getInheritanceSetup(superClassToken, className, indent, superName) { + var string = ''; + if (superClassToken) { + string += getStaticMethodsOnConstructorSetup(className, indent, superName); + string += getPrototypeOnConstructorSetup(className, indent, superName); + string += getConstructorPropertySetup(className, indent); + } + return string; +} + +function getStaticMethodsOnConstructorSetup(className, indent, superName) { + var string = ( indent + + 'for (var $keyName in $superName) {\n' + indent + + ' if ($superName.hasOwnProperty($keyName)) {\n' + indent + + ' $className[$keyName] = $superName[$keyName];\n' + indent + + ' }\n' + indent + + '}\n') + .replace(/\$className/g, className) + .replace(/\$keyName/g, getSuperKeyName(superName)) + .replace(/\$superName/g, superName); + return string; +} + +function getPrototypeOnConstructorSetup(className, indent, superName) { + var string = ( indent + + '$className.prototype = Object.create($protoPrototype);\n') + .replace(/\$protoPrototype/g, getProtoOfPrototypeVariableName(superName)) + .replace(/\$className/g, className); + return string; +} + +function getConstructorPropertySetup(className, indent) { + var string = ( indent + + '$className.prototype.constructor = $className;\n') + .replace(/\$className/g, className); + + return string; +} + +function getSuperConstructorSetup(superClassToken, indent, superName) { + if (!superClassToken) return ''; + var string = ( '\n' + indent + + ' if ($superName && $superName.prototype) {\n' + indent + + ' $superName.apply(this, arguments);\n' + indent + + ' }\n' + indent) + .replace(/\$superName/g, superName); + return string; +} + +function getMemberFunctionCall(superVar, propertyName, superArgs) { + var string = ( + '$superPrototype.$propertyName.call($superArguments)') + .replace(/\$superPrototype/g, getProtoOfPrototypeVariableName(superVar)) + .replace(/\$propertyName/g, propertyName) + .replace(/\$superArguments/g, superArgs); + return string; +} + +function getCallParams(classElement, state) { + var params = classElement.value.params; + if (!params.length) { + return ''; + } + return state.g.source.substring( + params[0].range[0], + params[params.length - 1].range[1]); +} + +function getSuperArguments(callExpression, state) { + var args = callExpression.arguments; + if (!args.length) { + return 'this'; + } + return 'this, ' + state.g.source.substring( + args[0].range[0], + args[args.length - 1].range[1]); +} + +// The seed is used to generate the name for an anonymous class, +// and this seed should be unique per browser's session. +// The value of the seed looks like this: 1229588505.2969012. +var classIDSeed = Date.now() % (60 * 60 * 1000) + Math.random(); + +/** + * Generates a name for an anonymous class. The generated value looks like + * this: "Classkc6pcn_mniza1yvi" + * @param {String} scopeName + * @return {string} the scope name for Anonymous Class + */ +function generateAnonymousClassName(scopeName) { + classIDSeed++; + return 'Class' + + (classIDSeed).toString(36).replace('.', '_') + + (scopeName || ''); +} + +function renderMethods(traverse, object, name, path, state) { + var classElements = object.body && object.body.body || []; + + move(object.body.range[0] + 1, state); + for (var i = 0; i < classElements.length; i++) { + if (classElements[i].key.name !== 'constructor') { + catchup(classElements[i].range[0], state); + + var memberName = classElements[i].key.name; + if (shouldMungeName(state.scopeName, memberName, state)) { + memberName = getMungedName( + state.scopeName, + memberName, + state.g.opts.minify + ); + } + + var prototypeOrStatic; + if (classElements[i]['static']) { + prototypeOrStatic = ''; + } else { + prototypeOrStatic = 'prototype.'; + } + + append(name + '.' + prototypeOrStatic + memberName + ' = ', state); + renderMethod(traverse, classElements[i], null, path, state); + append(';', state); + } + move(classElements[i].range[1], state); + } + if (classElements.length) { + append('\n', state); + } + move(object.range[1], state); +} + +function renderMethod(traverse, method, name, path, state) { + append(name ? 'function ' + name + '(' : 'function(', state); + append(getCallParams(method, state) + ') {', state); + move(method.value.body.range[0] + 1, state); + traverse(method.value.body, path, state); + catchup(method.value.body.range[1] - 1, state); + append('}', state); +} + +function renderSuperClass(traverse, superClass, path, state) { + append('var ' + state.superVar + ' = ', state); + move(superClass.range[0], state); + traverse(superClass, path, state); + catchup(superClass.range[1], state); + append(';\n', state); +} + +function renderConstructor(traverse, object, name, indent, path, state) { + var classElements = object.body && object.body.body || []; + var constructorIndex = findConstructorIndex(object); + var constructor = constructorIndex === -1 ? + null : + classElements[constructorIndex]; + if (constructor) { + move(constructorIndex === 0 ? + object.body.range[0] + 1 : + classElements[constructorIndex - 1].range[1], state); + catchup(constructor.range[0], state); + renderMethod(traverse, constructor, name, path, state); + append('\n', state); + } else { + if (object.superClass) { + append('\n' + indent, state); + } + append('function ', state); + if (object.id) { + move(object.id.range[0], state); + } + append(name, state); + if (object.id) { + move(object.id.range[1], state); + } + append('(){ ', state); + if (object.body) { + move(object.body.range[0], state); + } + append(getSuperConstructorSetup( + object.superClass, + indent, + state.superVar), state); + append('}\n', state); + } +} + +var superId = 0; +function renderClassBody(traverse, object, path, state) { + var name = object.id ? object.id.name : 'constructor'; + var superClass = object.superClass; + var indent = updateIndent( + indentBefore(object.range[0], state) + ' ', + state); + + state = updateState( + state, + { + scopeName: object.id ? object.id.name : + generateAnonymousClassName(state.scopeName), + superVar: superClass ? '__super' + superId++ : '' + }); + + // super class + if (superClass) { + append(indent, state); + renderSuperClass(traverse, superClass, path, state); + append(getSuperProtoOfPrototypeVariable(state.superVar, indent), state); + } + + renderConstructor(traverse, object, name, indent, path, state); + append(getInheritanceSetup(superClass, name, indent, state.superVar), state); + renderMethods(traverse, object, name, path, state); +} + + +/** + * @public + */ +function visitClassExpression(traverse, object, path, state) { + var indent = updateIndent( + indentBefore(object.range[0], state) + ' ', + state); + var name = object.id ? object.id.name : 'constructor'; + + append('(function() {\n', state); + renderClassBody(traverse, object, path, state); + append(indent + 'return ' + name + ';\n', state); + append(indent.substring(0, indent.length - 2) + '})()', state); + return false +} + +visitClassExpression.test = function(object, path, state) { + return object.type === Syntax.ClassExpression; +}; + +/** + * @public + */ +function visitClassDeclaration(traverse, object, path, state) { + state.g.indentBy--; + renderClassBody(traverse, object, path, state); + state.g.indentBy++; + return false; +} + +visitClassDeclaration.test = function(object, path, state) { + return object.type === Syntax.ClassDeclaration; +}; + + +/** + * @public + */ +function visitSuperCall(traverse, object, path, state) { + if (path[0].type === Syntax.CallExpression) { + append(state.superVar + + '.call(' + getSuperArguments(path[0], state) + ')', state); + move(path[0].range[1], state); + } else if (path[0].type === Syntax.MemberExpression) { + append(getMemberFunctionCall( + state.superVar, + path[0].property.name, + getSuperArguments(path[1], state)), state); + move(path[1].range[1], state); + } + return false; +} + +visitSuperCall.test = function(object, path, state) { + return state.superVar && object.type === Syntax.Identifier && + object.name === 'super'; +}; + +/** + * @public + */ +function visitPrivateProperty(traverse, object, path, state) { + var type = path[0] ? path[0].type : null; + if (type !== Syntax.Property) { + if (type === Syntax.MemberExpression) { + type = path[0].object ? path[0].object.type : null; + if (type === Syntax.Identifier && + path[0].object.range[0] === object.range[0]) { + // Identifier is a variable that appears "private". + return; + } + } else { + // Other syntax that are neither Property nor MemberExpression. + return; + } + } + + var oldName = object.name; + var newName = getMungedName( + state.scopeName, + oldName, + state.g.opts.minify + ); + append(newName, state); + move(object.range[1], state); +} + +visitPrivateProperty.test = function(object, path, state) { + return object.type === Syntax.Identifier && + shouldMungeName(state.scopeName, object.name, state); +}; + + +exports.visitClassDeclaration = visitClassDeclaration; +exports.visitClassExpression = visitClassExpression; +exports.visitSuperCall = visitSuperCall; +exports.visitPrivateProperty = visitPrivateProperty; + +})() +},{"../lib/utils":8,"../lib/docblock":4,"esprima":9,"base62":15}],6:[function(require,module,exports){ +(function(){/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*global exports:true*/ +"use strict"; + +var Syntax = require('esprima').Syntax; + +var catchup = require('../lib/utils').catchup; +var append = require('../lib/utils').append; +var move = require('../lib/utils').move; +var getDocblock = require('../lib/utils').getDocblock; + +var FALLBACK_TAGS = require('./xjs').knownTags; +var renderXJSExpression = require('./xjs').renderXJSExpression; +var renderXJSLiteral = require('./xjs').renderXJSLiteral; +var quoteAttrName = require('./xjs').quoteAttrName; + +/** + * Customized desugar processor. + * + * Currently: (Somewhat tailored to React) + * => X(null, null) + * => X({prop: '1'}, null) + * => X({prop:'2'}, Y(null, null)) + * => X({prop:'2'}, [Y(null, null), Z(null, null)]) + * + * Exceptions to the simple rules above: + * if a property is named "class" it will be changed to "className" in the + * javascript since "class" is not a valid object key in javascript. + */ + +var JSX_ATTRIBUTE_RENAMES = { + 'class': 'className', + cxName: 'className' +}; + +var JSX_ATTRIBUTE_TRANSFORMS = { + cxName: function(attr) { + if (attr.value.type !== Syntax.Literal) { + throw new Error("cx only accepts a string literal"); + } else { + var classNames = attr.value.value.split(/\s+/g); + return 'cx(' + classNames.map(JSON.stringify).join(',') + ')'; + } + } +}; + +function visitReactTag(traverse, object, path, state) { + var jsxObjIdent = getDocblock(state).jsx; + + catchup(object.openingElement.range[0], state); + + if (object.name.namespace) { + throw new Error( + 'Namespace tags are not supported. ReactJSX is not XML.'); + } + + var isFallbackTag = FALLBACK_TAGS[object.name.name]; + append( + (isFallbackTag ? jsxObjIdent + '.' : '') + (object.name.name) + '(', + state + ); + + move(object.name.range[1], state); + + var childrenToRender = object.children.filter(function(child) { + return !(child.type === Syntax.Literal && !child.value.match(/\S/)); + }); + + // if we don't have any attributes, pass in null + if (object.attributes.length === 0) { + append('null', state); + } + + // write attributes + object.attributes.forEach(function(attr, index) { + catchup(attr.range[0], state); + if (attr.name.namespace) { + throw new Error( + 'Namespace attributes are not supported. ReactJSX is not XML.'); + } + var name = JSX_ATTRIBUTE_RENAMES[attr.name.name] || attr.name.name; + var isFirst = index === 0; + var isLast = index === object.attributes.length - 1; + + if (isFirst) { + append('{', state); + } + + append(quoteAttrName(name), state); + append(':', state); + + if (!attr.value) { + state.g.buffer += 'true'; + state.g.position = attr.name.range[1]; + if (!isLast) { + append(',', state); + } + } else if (JSX_ATTRIBUTE_TRANSFORMS[attr.name.name]) { + move(attr.value.range[0], state); + append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state); + move(attr.value.range[1], state); + if (!isLast) { + append(',', state); + } + } else if (attr.value.type === Syntax.Literal) { + move(attr.value.range[0], state); + renderXJSLiteral(attr.value, isLast, state); + } else { + move(attr.value.range[0], state); + renderXJSExpression(traverse, attr.value, isLast, path, state); + } + + if (isLast) { + append('}', state); + } + + catchup(attr.range[1], state); + }); + + if (!object.selfClosing) { + catchup(object.openingElement.range[1] - 1, state); + move(object.openingElement.range[1], state); + } + + // separate props and children arguments + append(', ', state); + + // filter out whitespace + if (childrenToRender.length > 0) { + if (childrenToRender.length > 1) { + append('[', state); + } + object.children.forEach(function(child) { + if (child.type === Syntax.Literal && !child.value.match(/\S/)) { + return; + } + catchup(child.range[0], state); + + var isLast = child === childrenToRender[childrenToRender.length - 1]; + + if (child.type === Syntax.Literal) { + renderXJSLiteral(child, isLast, state); + } else if (child.type === Syntax.XJSExpression) { + renderXJSExpression(traverse, child, isLast, path, state); + } else { + traverse(child, path, state); + if (!isLast) { + append(',', state); + state.g.buffer = state.g.buffer.replace(/(\s*),$/, ',$1'); + } + } + + catchup(child.range[1], state); + }); + } else { + append('null', state); + } + + if (object.selfClosing) { + // everything up to /> + catchup(object.openingElement.range[1] - 2, state); + move(object.openingElement.range[1], state); + } else { + // everything up to + catchup(object.closingElement.range[0], state); + move(object.closingElement.range[1], state); + } + + if (childrenToRender.length > 0) { + if (childrenToRender.length > 1) { + append(']', state); + } + } + append(')', state); + return false; +} + +visitReactTag.test = function(object, path, state) { + // only run react when react @jsx namespace is specified in docblock + var jsx = getDocblock(state).jsx; + return object.type === Syntax.XJSElement && jsx && jsx.length; +}; + +exports.visitReactTag = visitReactTag; + +})() +},{"../lib/utils":8,"./xjs":11,"esprima":9}],7:[function(require,module,exports){ +(function(){/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*global exports:true*/ +"use strict"; + +var Syntax = require('esprima').Syntax; +var catchup = require('../lib/utils').catchup; +var append = require('../lib/utils').append; +var getDocblock = require('../lib/utils').getDocblock; + +/** + * Transforms the following: + * + * var MyComponent = React.createClass({ + * render: ... + * }); + * + * into: + * + * var MyComponent = React.createClass({ + * displayName: 'MyComponent', + * render: ... + * }); + */ +function visitReactDisplayName(traverse, object, path, state) { + object.declarations.forEach(function(dec) { + if (dec.type === Syntax.VariableDeclarator && + dec.id.type === Syntax.Identifier && + dec.init && + dec.init.type === Syntax.CallExpression && + dec.init.callee.type === Syntax.MemberExpression && + dec.init.callee.object.type === Syntax.Identifier && + dec.init.callee.object.name === 'React' && + dec.init.callee.property.type === Syntax.Identifier && + dec.init.callee.property.name === 'createClass' && + dec.init['arguments'].length === 1 && + dec.init['arguments'][0].type === Syntax.ObjectExpression) { + + var displayName = dec.id.name; + catchup(dec.init['arguments'][0].range[0] + 1, state); + append("displayName: '" + displayName + "',", state); + } + }); +} + + +/** + * Will only run on @jsx files for now. + */ +visitReactDisplayName.test = function(object, path, state) { + return object.type === Syntax.VariableDeclaration && !!getDocblock(state).jsx; +}; + +exports.visitReactDisplayName = visitReactDisplayName; + +})() +},{"../lib/utils":8,"esprima":9}],15:[function(require,module,exports){ +var Base62 = (function (my) { + my.chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] + + my.encode = function(i){ + if (i === 0) {return '0'} + var s = '' + while (i > 0) { + s = this.chars[i % 62] + s + i = Math.floor(i/62) + } + return s + }; + my.decode = function(a,b,c,d){ + for ( + b = c = ( + a === (/\W|_|^$/.test(a += "") || a) + ) - 1; + d = a.charCodeAt(c++); + ) + b = b * 62 + d - [, 48, 29, 87][d >> 5]; + return b + }; + + return my; +}({})); + +module.exports = Base62 +},{}],12:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. To create a new one, you must pass an object + * with the following properties: + * + * - file: The filename of the generated source. + * - sourceRoot: An optional root for all URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + this._file = util.getArg(aArgs, 'file'); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = []; + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source) { + newMapping.source = mapping.source; + if (sourceRoot) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + this._validateMapping(generated, original, source, name); + + if (source && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.push({ + generated: generated, + original: original, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent !== null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (!aSourceFile) { + aSourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "aSourceFile" relative if an absolute Url is passed. + if (sourceRoot) { + aSourceFile = util.relative(sourceRoot, aSourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "aSourceFile" + this._mappings.forEach(function (mapping) { + if (mapping.source === aSourceFile && mapping.original) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.original.line, + column: mapping.original.column + }); + if (original.source !== null) { + // Copy mapping + if (sourceRoot) { + mapping.source = util.relative(sourceRoot, original.source); + } else { + mapping.source = original.source; + } + mapping.original.line = original.line; + mapping.original.column = original.column; + if (original.name !== null && mapping.name !== null) { + // Only use the identifier name if it's an identifier + // in both SourceMaps + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + if (sourceRoot) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping.'); + } + }; + + function cmpLocation(loc1, loc2) { + var cmp = (loc1 && loc1.line) - (loc2 && loc2.line); + return cmp ? cmp : (loc1 && loc1.column) - (loc2 && loc2.column); + } + + function strcmp(str1, str2) { + str1 = str1 || ''; + str2 = str2 || ''; + return (str1 > str2) - (str1 < str2); + } + + function cmpMapping(mappingA, mappingB) { + return cmpLocation(mappingA.generated, mappingB.generated) || + cmpLocation(mappingA.original, mappingB.original) || + strcmp(mappingA.source, mappingB.source) || + strcmp(mappingA.name, mappingB.name); + } + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + // The mappings must be guarenteed to be in sorted order before we start + // serializing them or else the generated line numbers (which are defined + // via the ';' separators) will be all messed up. Note: it might be more + // performant to maintain the sorting as we insert them, rather than as we + // serialize them, but the big O is the same either way. + this._mappings.sort(cmpMapping); + + for (var i = 0, len = this._mappings.length; i < len; i++) { + mapping = this._mappings[i]; + + if (mapping.generated.line !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generated.line !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!cmpMapping(mapping, this._mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generated.column + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generated.column; + + if (mapping.source && mapping.original) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.original.line - 1 + - previousOriginalLine); + previousOriginalLine = mapping.original.line - 1; + + result += base64VLQ.encode(mapping.original.column + - previousOriginalColumn); + previousOriginalColumn = mapping.original.column; + + if (mapping.name) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + file: this._file, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._sourceRoot) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = map.sources.map(function (source) { + if (map.sourceRoot) { + source = util.relative(map.sourceRoot, source); + } + return Object.prototype.hasOwnProperty.call( + this._sourcesContents, util.toSetString(source)) + ? this._sourcesContents[util.toSetString(source)] + : null; + }, this); + } + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); + +},{"./base64-vlq":16,"./util":17,"./array-set":18,"amdefine":19}],13:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + var names = util.getArg(sourceMap, 'names'); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file'); + + if (version !== this._version) { + throw new Error('Unsupported version: ' + version); + } + + this._names = ArraySet.fromArray(names); + this._sources = ArraySet.fromArray(sources); + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this.file = file; + + // `this._generatedMappings` and `this._originalMappings` hold the parsed + // mapping coordinates from the source map's "mappings" attribute. Each + // object in the array is of the form + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `this._generatedMappings` is ordered by the generated positions. + // + // `this._originalMappings` is ordered by the original positions. + this._generatedMappings = []; + this._originalMappings = []; + this._parseMappings(mappings, sourceRoot); + } + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (an ordered list in this._generatedMappings). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var mappingSeparator = /^[,;]/; + var str = aStr; + var mapping; + var temp; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + temp = base64VLQ.decode(str); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original source. + temp = base64VLQ.decode(str); + mapping.source = this._sources.at(previousSource + temp.value); + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + temp = base64VLQ.decode(str); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + temp = base64VLQ.decode(str); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original name. + temp = base64VLQ.decode(str); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this._generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + this._originalMappings.push(mapping); + } + } + } + + this._originalMappings.sort(this._compareOriginalPositions); + }; + + /** + * Comparator between two mappings where the original positions are compared. + */ + SourceMapConsumer.prototype._compareOriginalPositions = + function SourceMapConsumer_compareOriginalPositions(mappingA, mappingB) { + if (mappingA.source > mappingB.source) { + return 1; + } + else if (mappingA.source < mappingB.source) { + return -1; + } + else { + var cmp = mappingA.originalLine - mappingB.originalLine; + return cmp === 0 + ? mappingA.originalColumn - mappingB.originalColumn + : cmp; + } + }; + + /** + * Comparator between two mappings where the generated positions are compared. + */ + SourceMapConsumer.prototype._compareGeneratedPositions = + function SourceMapConsumer_compareGeneratedPositions(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + return cmp === 0 + ? mappingA.generatedColumn - mappingB.generatedColumn + : cmp; + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var mapping = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + this._compareGeneratedPositions); + + if (mapping) { + var source = util.getArg(mapping, 'source', null); + if (source && this.sourceRoot) { + source = util.join(this.sourceRoot, source); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Returns the original source content. The only argument is + * the url of the original source file. Returns null if no + * original source content is availible. + */ + SourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot) { + // Try to remove the sourceRoot + var relativeUrl = util.relative(this.sourceRoot, aSource); + if (this._sources.has(relativeUrl)) { + return this.sourcesContent[this._sources.indexOf(relativeUrl)]; + } + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + throw new Error('"' + aSource + '" is not in the SourceMap.'); + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + if (this.sourceRoot) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var mapping = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + this._compareOriginalPositions); + + if (mapping) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null) + }; + } + + return { + line: null, + column: null + }; + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source; + if (source && sourceRoot) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name + }; + }).forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + +}); + +},{"./util":17,"./binary-search":20,"./array-set":18,"./base64-vlq":16,"amdefine":19}],14:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + var util = require('./util'); + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine === undefined ? null : aLine; + this.column = aColumn === undefined ? null : aColumn; + this.source = aSource === undefined ? null : aSource; + this.name = aName === undefined ? null : aName; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // The generated code + // Processed fragments are removed from this array. + var remainingLines = aGeneratedCode.split('\n'); + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping === null) { + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(remainingLines.shift() + "\n"); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + } else { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate full lines with "lastMapping" + do { + code += remainingLines.shift() + "\n"; + lastGeneratedLine++; + lastGeneratedColumn = 0; + } while (lastGeneratedLine < mapping.generatedLine); + // When we reached the correct line, we add code until we + // reach the correct column too. + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + code += nextLine.substr(0, mapping.generatedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + // Create the SourceNode. + addMappingWithCode(lastMapping, code); + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + } + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + // Associate the remaining code in the current line with "lastMapping" + // and add the remaining lines without any mapping + addMappingWithCode(lastMapping, remainingLines.join("\n")); + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping.source === undefined) { + node.add(code); + } else { + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + mapping.source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + this.children.forEach(function (chunk) { + if (chunk instanceof SourceNode) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + }, this); + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild instanceof SourceNode) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + this.children.forEach(function (chunk) { + if (chunk instanceof SourceNode) { + chunk.walkSourceContents(aFn); + } + }, this); + Object.keys(this.sourceContents).forEach(function (sourceFileKey) { + aFn(util.fromSetString(sourceFileKey), this.sourceContents[sourceFileKey]); + }, this); + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + sourceMappingActive = false; + } + chunk.split('').forEach(function (ch) { + if (ch === '\n') { + generated.line++; + generated.column = 0; + } else { + generated.column++; + } + }); + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + +}); + +},{"./source-map-generator":12,"./util":17,"amdefine":19}],21:[function(require,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; + +process.nextTick = (function () { + var canSetImmediate = typeof window !== 'undefined' + && window.setImmediate; + var canPost = typeof window !== 'undefined' + && window.postMessage && window.addEventListener + ; + + if (canSetImmediate) { + return function (f) { return window.setImmediate(f) }; + } + + if (canPost) { + var queue = []; + window.addEventListener('message', function (ev) { + if (ev.source === window && ev.data === 'process-tick') { + ev.stopPropagation(); + if (queue.length > 0) { + var fn = queue.shift(); + fn(); + } + } + }, true); + + return function nextTick(fn) { + queue.push(fn); + window.postMessage('process-tick', '*'); + }; + } + + return function nextTick(fn) { + setTimeout(fn, 0); + }; +})(); + +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +} + +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; + +},{}],19:[function(require,module,exports){ +(function(process,__filename){/** vim: et:ts=4:sw=4:sts=4 + * @license amdefine 0.0.5 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/amdefine for details + */ + +/*jslint node: true */ +/*global module, process */ +'use strict'; + +var path = require('path'); + +/** + * Creates a define for node. + * @param {Object} module the "module" object that is defined by Node for the + * current module. + * @param {Function} [require]. Node's require function for the current module. + * It only needs to be passed in Node versions before 0.5, when module.require + * did not exist. + * @returns {Function} a define function that is usable for the current node + * module. + */ +function amdefine(module, require) { + var defineCache = {}, + loaderCache = {}, + alreadyCalled = false, + makeRequire, stringRequire; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i+= 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + function normalize(name, baseName) { + var baseParts; + + //Adjust any relative paths. + if (name && name.charAt(0) === '.') { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + baseParts = baseName.split('/'); + baseParts = baseParts.slice(0, baseParts.length - 1); + baseParts = baseParts.concat(name.split('/')); + trimDots(baseParts); + name = baseParts.join('/'); + } + } + + return name; + } + + /** + * Create the normalize() function passed to a loader plugin's + * normalize method. + */ + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(id) { + function load(value) { + loaderCache[id] = value; + } + + load.fromText = function (id, text) { + //This one is difficult because the text can/probably uses + //define, and any relative paths and requires should be relative + //to that id was it would be found on disk. But this would require + //bootstrapping a module/require fairly deeply from node core. + //Not sure how best to go about that yet. + throw new Error('amdefine does not implement load.fromText'); + }; + + return load; + } + + makeRequire = function (systemRequire, exports, module, relId) { + function amdRequire(deps, callback) { + if (typeof deps === 'string') { + //Synchronous, single module require('') + return stringRequire(systemRequire, exports, module, deps, relId); + } else { + //Array of dependencies with a callback. + + //Convert the dependencies to modules. + deps = deps.map(function (depName) { + return stringRequire(systemRequire, exports, module, depName, relId); + }); + + //Wait for next tick to call back the require call. + process.nextTick(function () { + callback.apply(null, deps); + }); + } + } + + amdRequire.toUrl = function (filePath) { + if (filePath.indexOf('.') === 0) { + return normalize(filePath, path.dirname(module.filename)); + } else { + return filePath; + } + }; + + return amdRequire; + }; + + //Favor explicit value, passed in if the module wants to support Node 0.4. + require = require || function req() { + return module.require.apply(module, arguments); + }; + + function runFactory(id, deps, factory) { + var r, e, m, result; + + if (id) { + e = loaderCache[id] = {}; + m = { + id: id, + uri: __filename, + exports: e + }; + r = makeRequire(require, e, m, id); + } else { + //Only support one define call per file + if (alreadyCalled) { + throw new Error('amdefine with no module ID cannot be called more than once per file.'); + } + alreadyCalled = true; + + //Use the real variables from node + //Use module.exports for exports, since + //the exports in here is amdefine exports. + e = module.exports; + m = module; + r = makeRequire(require, e, m, module.id); + } + + //If there are dependencies, they are strings, so need + //to convert them to dependency values. + if (deps) { + deps = deps.map(function (depName) { + return r(depName); + }); + } + + //Call the factory with the right dependencies. + if (typeof factory === 'function') { + result = factory.apply(module.exports, deps); + } else { + result = factory; + } + + if (result !== undefined) { + m.exports = result; + if (id) { + loaderCache[id] = m.exports; + } + } + } + + stringRequire = function (systemRequire, exports, module, id, relId) { + //Split the ID by a ! so that + var index = id.indexOf('!'), + originalId = id, + prefix, plugin; + + if (index === -1) { + id = normalize(id, relId); + + //Straight module lookup. If it is one of the special dependencies, + //deal with it, otherwise, delegate to node. + if (id === 'require') { + return makeRequire(systemRequire, exports, module, relId); + } else if (id === 'exports') { + return exports; + } else if (id === 'module') { + return module; + } else if (loaderCache.hasOwnProperty(id)) { + return loaderCache[id]; + } else if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } else { + if(systemRequire) { + return systemRequire(originalId); + } else { + throw new Error('No module with ID: ' + id); + } + } + } else { + //There is a plugin in play. + prefix = id.substring(0, index); + id = id.substring(index + 1, id.length); + + plugin = stringRequire(systemRequire, exports, module, prefix, relId); + + if (plugin.normalize) { + id = plugin.normalize(id, makeNormalize(relId)); + } else { + //Normalize the ID normally. + id = normalize(id, relId); + } + + if (loaderCache[id]) { + return loaderCache[id]; + } else { + plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); + + return loaderCache[id]; + } + } + }; + + //Create a define function specific to the module asking for amdefine. + function define(id, deps, factory) { + if (Array.isArray(id)) { + factory = deps; + deps = id; + id = undefined; + } else if (typeof id !== 'string') { + factory = id; + id = deps = undefined; + } + + if (deps && !Array.isArray(deps)) { + factory = deps; + deps = undefined; + } + + if (!deps) { + deps = ['require', 'exports', 'module']; + } + + //Set up properties for this module. If an ID, then use + //internal cache. If no ID, then use the external variables + //for this node module. + if (id) { + //Put the module in deep freeze until there is a + //require call for it. + defineCache[id] = [id, deps, factory]; + } else { + runFactory(id, deps, factory); + } + } + + //define.require, which has access to all the values in the + //cache. Useful for AMD modules that all have IDs in the file, + //but need to finally export a value to node based on one of those + //IDs. + define.require = function (id) { + if (loaderCache[id]) { + return loaderCache[id]; + } + + if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } + }; + + define.amd = {}; + + return define; +} + +module.exports = amdefine; + +})(require("__browserify_process"),"/../node_modules/source-map/node_modules/amdefine/amdefine.js") +},{"path":22,"__browserify_process":21}],22:[function(require,module,exports){ +(function(process){function filter (xs, fn) { + var res = []; + for (var i = 0; i < xs.length; i++) { + if (fn(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length; i >= 0; i--) { + var last = parts[i]; + if (last == '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Regex to split a filename into [*, dir, basename, ext] +// posix version +var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { +var resolvedPath = '', + resolvedAbsolute = false; + +for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) + ? arguments[i] + : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string' || !path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; +} + +// At this point the path should be resolved to a full absolute path, but +// handle relative paths to be safe (might happen when process.cwd() fails) + +// Normalize the path +resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { +var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.slice(-1) === '/'; + +// Normalize the path +path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + return p && typeof p === 'string'; + }).join('/')); +}; + + +exports.dirname = function(path) { + var dir = splitPathRe.exec(path)[1] || ''; + var isWindows = false; + if (!dir) { + // No dirname + return '.'; + } else if (dir.length === 1 || + (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) { + // It is just a slash or a drive letter with a slash + return dir; + } else { + // It is a full dirname, strip trailing slash + return dir.substring(0, dir.length - 1); + } +}; + + +exports.basename = function(path, ext) { + var f = splitPathRe.exec(path)[2] || ''; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPathRe.exec(path)[3] || ''; +}; + +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +})(require("__browserify_process")) +},{"__browserify_process":21}],16:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string. + */ + exports.decode = function base64VLQ_decode(aStr) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + return { + value: fromVLQSigned(result), + rest: aStr.slice(i) + }; + }; + +}); + +},{"./base64":23,"amdefine":19}],17:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[3], + host: match[4], + port: match[6], + path: match[7] + }; + } + + function join(aRoot, aPath) { + var url; + + if (aPath.match(urlRegexp)) { + return aPath; + } + + if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { + return aRoot.replace(url.path, '') + aPath; + } + + return aRoot.replace(/\/$/, '') + '/' + aPath; + } + exports.join = join; + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + exports.toSetString = toSetString; + + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; + + function relative(aRoot, aPath) { + aRoot = aRoot.replace(/\/$/, ''); + return aPath.indexOf(aRoot + '/') === 0 + ? aPath.substr(aRoot.length + 1) + : aPath; + } + exports.relative = relative; + +}); + +},{"amdefine":19}],18:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i]); + } + return set; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr) { + if (this.has(aStr)) { + // Already a member; nothing to do. + return; + } + var idx = this._array.length; + this._array.push(aStr); + this._set[util.toSetString(aStr)] = idx; + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + +}); + +},{"./util":17,"amdefine":19}],20:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the next + // closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return null. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid]); + if (cmp === 0) { + // Found the element we are looking for. + return aHaystack[mid]; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return aHaystack[mid]; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + } + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 + ? null + : aHaystack[aLow]; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the next lowest value checked if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + */ + exports.search = function search(aNeedle, aHaystack, aCompare) { + return aHaystack.length > 0 + ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + : null; + }; + +}); + +},{"amdefine":19}],23:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + +}); + +},{"amdefine":19}]},{},[1])(1) +}); +; \ No newline at end of file diff --git a/js/codemirror.js b/js/codemirror.js new file mode 100644 index 0000000000..acabd861dc --- /dev/null +++ b/js/codemirror.js @@ -0,0 +1,5230 @@ +// CodeMirror is the only global var we claim +window.CodeMirror = (function() { + "use strict"; + + // BROWSER SNIFFING + + // Crude, but necessary to handle a number of hard-to-feature-detect + // bugs and behavior differences. + var gecko = /gecko\/\d/i.test(navigator.userAgent); + var ie = /MSIE \d/.test(navigator.userAgent); + var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8); + var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9); + var webkit = /WebKit\//.test(navigator.userAgent); + var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent); + var chrome = /Chrome\//.test(navigator.userAgent); + var opera = /Opera\//.test(navigator.userAgent); + var safari = /Apple Computer/.test(navigator.vendor); + var khtml = /KHTML\//.test(navigator.userAgent); + var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent); + var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent); + var phantom = /PhantomJS/.test(navigator.userAgent); + + var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent); + // This is woefully incomplete. Suggestions for alternative methods welcome. + var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent); + var mac = ios || /Mac/.test(navigator.platform); + var windows = /windows/i.test(navigator.platform); + + var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/); + if (opera_version) opera_version = Number(opera_version[1]); + // Some browsers use the wrong event properties to signal cmd/ctrl on OS X + var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11)); + var captureMiddleClick = gecko || (ie && !ie_lt9); + + // Optimize some code when these features are not used + var sawReadOnlySpans = false, sawCollapsedSpans = false; + + // CONSTRUCTOR + + function CodeMirror(place, options) { + if (!(this instanceof CodeMirror)) return new CodeMirror(place, options); + + this.options = options = options || {}; + // Determine effective options based on given values and defaults. + for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt)) + options[opt] = defaults[opt]; + setGuttersForLineNumbers(options); + + var docStart = typeof options.value == "string" ? 0 : options.value.first; + var display = this.display = makeDisplay(place, docStart); + display.wrapper.CodeMirror = this; + updateGutters(this); + if (options.autofocus && !mobile) focusInput(this); + + this.state = {keyMaps: [], + overlays: [], + modeGen: 0, + overwrite: false, focused: false, + suppressEdits: false, pasteIncoming: false, + draggingText: false, + highlight: new Delayed()}; + + this.nextOpId = 0; + themeChanged(this); + if (options.lineWrapping) + this.display.wrapper.className += " CodeMirror-wrap"; + + var doc = options.value; + if (typeof doc == "string") doc = new Doc(options.value, options.mode); + operation(this, attachDoc)(this, doc); + + // Override magic textarea content restore that IE sometimes does + // on our hidden textarea on reload + if (ie) setTimeout(bind(resetInput, this, true), 20); + + registerEventHandlers(this); + // IE throws unspecified error in certain cases, when + // trying to access activeElement before onload + var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { } + if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20); + else onBlur(this); + + operation(this, function() { + for (var opt in optionHandlers) + if (optionHandlers.propertyIsEnumerable(opt)) + optionHandlers[opt](this, options[opt], Init); + for (var i = 0; i < initHooks.length; ++i) initHooks[i](this); + })(); + } + + // DISPLAY CONSTRUCTOR + + function makeDisplay(place, docStart) { + var d = {}; + var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none;"); + if (webkit) input.style.width = "1000px"; + else input.setAttribute("wrap", "off"); + input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); + // Wraps and hides input textarea + d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); + // The actual fake scrollbars. + d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar"); + d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar"); + d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); + // DIVs containing the selection and the actual code + d.lineDiv = elt("div"); + d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); + // Blinky cursor, and element used to ensure cursor fits at the end of a line + d.cursor = elt("div", "\u00a0", "CodeMirror-cursor"); + // Secondary cursor, shown when on a 'jump' in bi-directional text + d.otherCursor = elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"); + // Used to measure text size + d.measure = elt("div", null, "CodeMirror-measure"); + // Wraps everything that needs to exist inside the vertically-padded coordinate system + d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor], + null, "position: relative; outline: none"); + // Moved around its parent to cover visible view + d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative"); + // Set to the height of the text, causes scrolling + d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); + // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers + d.heightForcer = elt("div", "\u00a0", null, "position: absolute; height: " + scrollerCutOff + "px"); + // Will contain the gutters, if any + d.gutters = elt("div", null, "CodeMirror-gutters"); + d.lineGutter = null; + // Helper element to properly size the gutter backgrounds + var scrollerInner = elt("div", [d.sizer, d.heightForcer, d.gutters], null, "position: relative; min-height: 100%"); + // Provides scrolling + d.scroller = elt("div", [scrollerInner], "CodeMirror-scroll"); + d.scroller.setAttribute("tabIndex", "-1"); + // The element in which the editor lives. + d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV, + d.scrollbarFiller, d.scroller], "CodeMirror"); + // Work around IE7 z-index bug + if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } + if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper); + + // Needed to hide big blue blinking cursor on Mobile Safari + if (ios) input.style.width = "0px"; + if (!webkit) d.scroller.draggable = true; + // Needed to handle Tab key in KHTML + if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; } + // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). + else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px"; + + // Current visible range (may be bigger than the view window). + d.viewOffset = d.lastSizeC = 0; + d.showingFrom = d.showingTo = docStart; + + // Used to only resize the line number gutter when necessary (when + // the amount of lines crosses a boundary that makes its width change) + d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; + // See readInput and resetInput + d.prevInput = ""; + // Set to true when a non-horizontal-scrolling widget is added. As + // an optimization, widget aligning is skipped when d is false. + d.alignWidgets = false; + // Flag that indicates whether we currently expect input to appear + // (after some event like 'keypress' or 'input') and are polling + // intensively. + d.pollingFast = false; + // Self-resetting timeout for the poller + d.poll = new Delayed(); + // True when a drag from the editor is active + d.draggingText = false; + + d.cachedCharWidth = d.cachedTextHeight = null; + d.measureLineCache = []; + d.measureLineCachePos = 0; + + // Tracks when resetInput has punted to just putting a short + // string instead of the (large) selection. + d.inaccurateSelection = false; + + // Tracks the maximum line length so that the horizontal scrollbar + // can be kept static when scrolling. + d.maxLine = null; + d.maxLineLength = 0; + d.maxLineChanged = false; + + // Used for measuring wheel scrolling granularity + d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; + + return d; + } + + // STATE UPDATES + + // Used to get the editor into a consistent state again when options change. + + function loadMode(cm) { + cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption); + cm.doc.iter(function(line) { + if (line.stateAfter) line.stateAfter = null; + if (line.styles) line.styles = null; + }); + cm.doc.frontier = cm.doc.first; + startWorker(cm, 100); + cm.state.modeGen++; + if (cm.curOp) regChange(cm); + } + + function wrappingChanged(cm) { + if (cm.options.lineWrapping) { + cm.display.wrapper.className += " CodeMirror-wrap"; + cm.display.sizer.style.minWidth = ""; + } else { + cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", ""); + computeMaxLength(cm); + } + estimateLineHeights(cm); + regChange(cm); + clearCaches(cm); + setTimeout(function(){updateScrollbars(cm.display, cm.doc.height);}, 100); + } + + function estimateHeight(cm) { + var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; + var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); + return function(line) { + if (lineIsHidden(cm.doc, line)) + return 0; + else if (wrapping) + return (Math.ceil(line.text.length / perLine) || 1) * th; + else + return th; + }; + } + + function estimateLineHeights(cm) { + var doc = cm.doc, est = estimateHeight(cm); + doc.iter(function(line) { + var estHeight = est(line); + if (estHeight != line.height) updateLineHeight(line, estHeight); + }); + } + + function keyMapChanged(cm) { + var style = keyMap[cm.options.keyMap].style; + cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") + + (style ? " cm-keymap-" + style : ""); + } + + function themeChanged(cm) { + cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); + clearCaches(cm); + } + + function guttersChanged(cm) { + updateGutters(cm); + regChange(cm); + } + + function updateGutters(cm) { + var gutters = cm.display.gutters, specs = cm.options.gutters; + removeChildren(gutters); + for (var i = 0; i < specs.length; ++i) { + var gutterClass = specs[i]; + var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)); + if (gutterClass == "CodeMirror-linenumbers") { + cm.display.lineGutter = gElt; + gElt.style.width = (cm.display.lineNumWidth || 1) + "px"; + } + } + gutters.style.display = i ? "" : "none"; + } + + function lineLength(doc, line) { + if (line.height == 0) return 0; + var len = line.text.length, merged, cur = line; + while (merged = collapsedSpanAtStart(cur)) { + var found = merged.find(); + cur = getLine(doc, found.from.line); + len += found.from.ch - found.to.ch; + } + cur = line; + while (merged = collapsedSpanAtEnd(cur)) { + var found = merged.find(); + len -= cur.text.length - found.from.ch; + cur = getLine(doc, found.to.line); + len += cur.text.length - found.to.ch; + } + return len; + } + + function computeMaxLength(cm) { + var d = cm.display, doc = cm.doc; + d.maxLine = getLine(doc, doc.first); + d.maxLineLength = lineLength(doc, d.maxLine); + d.maxLineChanged = true; + doc.iter(function(line) { + var len = lineLength(doc, line); + if (len > d.maxLineLength) { + d.maxLineLength = len; + d.maxLine = line; + } + }); + } + + // Make sure the gutters options contains the element + // "CodeMirror-linenumbers" when the lineNumbers option is true. + function setGuttersForLineNumbers(options) { + var found = false; + for (var i = 0; i < options.gutters.length; ++i) { + if (options.gutters[i] == "CodeMirror-linenumbers") { + if (options.lineNumbers) found = true; + else options.gutters.splice(i--, 1); + } + } + if (!found && options.lineNumbers) + options.gutters.push("CodeMirror-linenumbers"); + } + + // SCROLLBARS + + // Re-synchronize the fake scrollbars with the actual size of the + // content. Optionally force a scrollTop. + function updateScrollbars(d /* display */, docHeight) { + var totalHeight = docHeight + 2 * paddingTop(d); + d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px"; + var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight); + var needsH = d.scroller.scrollWidth > d.scroller.clientWidth; + var needsV = scrollHeight > d.scroller.clientHeight; + if (needsV) { + d.scrollbarV.style.display = "block"; + d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0"; + d.scrollbarV.firstChild.style.height = + (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px"; + } else d.scrollbarV.style.display = ""; + if (needsH) { + d.scrollbarH.style.display = "block"; + d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0"; + d.scrollbarH.firstChild.style.width = + (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px"; + } else d.scrollbarH.style.display = ""; + if (needsH && needsV) { + d.scrollbarFiller.style.display = "block"; + d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px"; + } else d.scrollbarFiller.style.display = ""; + + if (mac_geLion && scrollbarWidth(d.measure) === 0) + d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px"; + } + + function visibleLines(display, doc, viewPort) { + var top = display.scroller.scrollTop, height = display.wrapper.clientHeight; + if (typeof viewPort == "number") top = viewPort; + else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;} + top = Math.floor(top - paddingTop(display)); + var bottom = Math.ceil(top + height); + return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)}; + } + + // LINE NUMBERS + + function alignHorizontally(cm) { + var display = cm.display; + if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return; + var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; + var gutterW = display.gutters.offsetWidth, l = comp + "px"; + for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) { + for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l; + } + if (cm.options.fixedGutter) + display.gutters.style.left = (comp + gutterW) + "px"; + } + + function maybeUpdateLineNumberWidth(cm) { + if (!cm.options.lineNumbers) return false; + var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; + if (last.length != display.lineNumChars) { + var test = display.measure.appendChild(elt("div", [elt("div", last)], + "CodeMirror-linenumber CodeMirror-gutter-elt")); + var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; + display.lineGutter.style.width = ""; + display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding); + display.lineNumWidth = display.lineNumInnerWidth + padding; + display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; + display.lineGutter.style.width = display.lineNumWidth + "px"; + return true; + } + return false; + } + + function lineNumberFor(options, i) { + return String(options.lineNumberFormatter(i + options.firstLineNumber)); + } + function compensateForHScroll(display) { + return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left; + } + + // DISPLAY DRAWING + + function updateDisplay(cm, changes, viewPort) { + var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo; + var updated = updateDisplayInner(cm, changes, viewPort); + if (updated) { + signalLater(cm, "update", cm); + if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo) + signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo); + } + updateSelection(cm); + updateScrollbars(cm.display, cm.doc.height); + + return updated; + } + + // Uses a set of changes plus the current scroll position to + // determine which DOM updates have to be made, and makes the + // updates. + function updateDisplayInner(cm, changes, viewPort) { + var display = cm.display, doc = cm.doc; + if (!display.wrapper.clientWidth) { + display.showingFrom = display.showingTo = doc.first; + display.viewOffset = 0; + return; + } + + // Compute the new visible window + // If scrollTop is specified, use that to determine which lines + // to render instead of the current scrollbar position. + var visible = visibleLines(display, doc, viewPort); + // Bail out if the visible area is already rendered and nothing changed. + if (changes.length == 0 && + visible.from > display.showingFrom && visible.to < display.showingTo) + return; + + if (maybeUpdateLineNumberWidth(cm)) + changes = [{from: doc.first, to: doc.first + doc.size}]; + var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px"; + display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0"; + + // When merged lines are present, the line that needs to be + // redrawn might not be the one that was changed. + if (sawCollapsedSpans) + for (var i = 0; i < changes.length; ++i) { + var ch = changes[i], merged; + while (merged = collapsedSpanAtStart(getLine(doc, ch.from))) { + var from = merged.find().from.line; + if (ch.diff) ch.diff -= ch.from - from; + ch.from = from; + } + } + + // Used to determine which lines need their line numbers updated + var positionsChangedFrom = Infinity; + if (cm.options.lineNumbers) + for (var i = 0; i < changes.length; ++i) + if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; } + + var end = doc.first + doc.size; + var from = Math.max(visible.from - cm.options.viewportMargin, doc.first); + var to = Math.min(end, visible.to + cm.options.viewportMargin); + if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom); + if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo); + if (sawCollapsedSpans) { + from = lineNo(visualLine(doc, getLine(doc, from))); + while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to; + } + + // Create a range of theoretically intact lines, and punch holes + // in that using the change info. + var intact = computeIntact([{from: display.showingFrom, to: display.showingTo}], changes); + + // Clip off the parts that won't be visible + var intactLines = 0; + for (var i = 0; i < intact.length; ++i) { + var range = intact[i]; + if (range.from < from) range.from = from; + if (range.to > to) range.to = to; + if (range.from >= range.to) intact.splice(i--, 1); + else intactLines += range.to - range.from; + } + if (intactLines == to - from && from == display.showingFrom && to == display.showingTo) { + updateViewOffset(cm); + return; + } + intact.sort(function(a, b) {return a.from - b.from;}); + + var focused = document.activeElement; + if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none"; + patchDisplay(cm, from, to, intact, positionsChangedFrom); + display.lineDiv.style.display = ""; + if (document.activeElement != focused && focused.offsetHeight) focused.focus(); + + var different = from != display.showingFrom || to != display.showingTo || + display.lastSizeC != display.wrapper.clientHeight; + // This is just a bogus formula that detects when the editor is + // resized or the font size changes. + if (different) display.lastSizeC = display.wrapper.clientHeight; + display.showingFrom = from; display.showingTo = to; + startWorker(cm, 100); + + var prevBottom = display.lineDiv.offsetTop; + for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) { + if (ie_lt8) { + var bot = node.offsetTop + node.offsetHeight; + height = bot - prevBottom; + prevBottom = bot; + } else { + var box = node.getBoundingClientRect(); + height = box.bottom - box.top; + } + var diff = node.lineObj.height - height; + if (height < 2) height = textHeight(display); + if (diff > .001 || diff < -.001) { + updateLineHeight(node.lineObj, height); + var widgets = node.lineObj.widgets; + if (widgets) for (var i = 0; i < widgets.length; ++i) + widgets[i].height = widgets[i].node.offsetHeight; + } + } + updateViewOffset(cm); + + if (visibleLines(display, doc, viewPort).to >= to) + updateDisplayInner(cm, [], viewPort); + return true; + } + + function updateViewOffset(cm) { + var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom)); + // Position the mover div to align with the current virtual scroll position + cm.display.mover.style.top = off + "px"; + } + + function computeIntact(intact, changes) { + for (var i = 0, l = changes.length || 0; i < l; ++i) { + var change = changes[i], intact2 = [], diff = change.diff || 0; + for (var j = 0, l2 = intact.length; j < l2; ++j) { + var range = intact[j]; + if (change.to <= range.from && change.diff) { + intact2.push({from: range.from + diff, to: range.to + diff}); + } else if (change.to <= range.from || change.from >= range.to) { + intact2.push(range); + } else { + if (change.from > range.from) + intact2.push({from: range.from, to: change.from}); + if (change.to < range.to) + intact2.push({from: change.to + diff, to: range.to + diff}); + } + } + intact = intact2; + } + return intact; + } + + function getDimensions(cm) { + var d = cm.display, left = {}, width = {}; + for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { + left[cm.options.gutters[i]] = n.offsetLeft; + width[cm.options.gutters[i]] = n.offsetWidth; + } + return {fixedPos: compensateForHScroll(d), + gutterTotalWidth: d.gutters.offsetWidth, + gutterLeft: left, + gutterWidth: width, + wrapperWidth: d.wrapper.clientWidth}; + } + + function patchDisplay(cm, from, to, intact, updateNumbersFrom) { + var dims = getDimensions(cm); + var display = cm.display, lineNumbers = cm.options.lineNumbers; + if (!intact.length && (!webkit || !cm.display.currentWheelTarget)) + removeChildren(display.lineDiv); + var container = display.lineDiv, cur = container.firstChild; + + function rm(node) { + var next = node.nextSibling; + if (webkit && mac && cm.display.currentWheelTarget == node) { + node.style.display = "none"; + node.lineObj = null; + } else { + node.parentNode.removeChild(node); + } + return next; + } + + var nextIntact = intact.shift(), lineN = from; + cm.doc.iter(from, to, function(line) { + if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift(); + if (lineIsHidden(cm.doc, line)) { + if (line.height != 0) updateLineHeight(line, 0); + if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) + if (line.widgets[i].showIfHidden) { + var prev = cur.previousSibling; + if (/pre/i.test(prev.nodeName)) { + var wrap = elt("div", null, null, "position: relative"); + prev.parentNode.replaceChild(wrap, prev); + wrap.appendChild(prev); + prev = wrap; + } + var wnode = prev.appendChild(elt("div", [line.widgets[i].node], "CodeMirror-linewidget")); + positionLineWidget(line.widgets[i], wnode, prev, dims); + } + } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) { + // This line is intact. Skip to the actual node. Update its + // line number if needed. + while (cur.lineObj != line) cur = rm(cur); + if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber) + setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN)); + cur = cur.nextSibling; + } else { + // For lines with widgets, make an attempt to find and reuse + // the existing element, so that widgets aren't needlessly + // removed and re-inserted into the dom + if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling) + if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; } + // This line needs to be generated. + var lineNode = buildLineElement(cm, line, lineN, dims, reuse); + if (lineNode != reuse) { + container.insertBefore(lineNode, cur); + } else { + while (cur != reuse) cur = rm(cur); + cur = cur.nextSibling; + } + + lineNode.lineObj = line; + } + ++lineN; + }); + while (cur) cur = rm(cur); + } + + function buildLineElement(cm, line, lineNo, dims, reuse) { + var lineElement = lineContent(cm, line); + var markers = line.gutterMarkers, display = cm.display, wrap; + + if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets) + return lineElement; + + // Lines with gutter elements, widgets or a background class need + // to be wrapped again, and have the extra elements added to the + // wrapper div + + if (reuse) { + reuse.alignable = null; + var isOk = true, widgetsSeen = 0; + for (var n = reuse.firstChild, next; n; n = next) { + next = n.nextSibling; + if (!/\bCodeMirror-linewidget\b/.test(n.className)) { + reuse.removeChild(n); + } else { + for (var i = 0, first = true; i < line.widgets.length; ++i) { + var widget = line.widgets[i], isFirst = false; + if (!widget.above) { isFirst = first; first = false; } + if (widget.node == n.firstChild) { + positionLineWidget(widget, n, reuse, dims); + ++widgetsSeen; + if (isFirst) reuse.insertBefore(lineElement, n); + break; + } + } + if (i == line.widgets.length) { isOk = false; break; } + } + } + if (isOk && widgetsSeen == line.widgets.length) { + wrap = reuse; + reuse.className = line.wrapClass || ""; + } + } + if (!wrap) { + wrap = elt("div", null, line.wrapClass, "position: relative"); + wrap.appendChild(lineElement); + } + // Kludge to make sure the styled element lies behind the selection (by z-index) + if (line.bgClass) + wrap.insertBefore(elt("div", "\u00a0", line.bgClass + " CodeMirror-linebackground"), wrap.firstChild); + if (cm.options.lineNumbers || markers) { + var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " + + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"), + wrap.firstChild); + if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap); + if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) + wrap.lineNumber = gutterWrap.appendChild( + elt("div", lineNumberFor(cm.options, lineNo), + "CodeMirror-linenumber CodeMirror-gutter-elt", + "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: " + + display.lineNumInnerWidth + "px")); + if (markers) + for (var k = 0; k < cm.options.gutters.length; ++k) { + var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]; + if (found) + gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " + + dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px")); + } + } + if (ie_lt8) wrap.style.zIndex = 2; + if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) { + var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget"); + positionLineWidget(widget, node, wrap, dims); + if (widget.above) + wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement); + else + wrap.appendChild(node); + signalLater(widget, "redraw"); + } + return wrap; + } + + function positionLineWidget(widget, node, wrap, dims) { + if (widget.noHScroll) { + (wrap.alignable || (wrap.alignable = [])).push(node); + var width = dims.wrapperWidth; + node.style.left = dims.fixedPos + "px"; + if (!widget.coverGutter) { + width -= dims.gutterTotalWidth; + node.style.paddingLeft = dims.gutterTotalWidth + "px"; + } + node.style.width = width + "px"; + } + if (widget.coverGutter) { + node.style.zIndex = 5; + node.style.position = "relative"; + if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px"; + } + } + + // SELECTION / CURSOR + + function updateSelection(cm) { + var display = cm.display; + var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to); + if (collapsed || cm.options.showCursorWhenSelecting) + updateSelectionCursor(cm); + else + display.cursor.style.display = display.otherCursor.style.display = "none"; + if (!collapsed) + updateSelectionRange(cm); + else + display.selectionDiv.style.display = "none"; + + // Move the hidden textarea near the cursor to prevent scrolling artifacts + var headPos = cursorCoords(cm, cm.doc.sel.head, "div"); + var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); + display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10, + headPos.top + lineOff.top - wrapOff.top)) + "px"; + display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10, + headPos.left + lineOff.left - wrapOff.left)) + "px"; + } + + // No selection, plain cursor + function updateSelectionCursor(cm) { + var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div"); + display.cursor.style.left = pos.left + "px"; + display.cursor.style.top = pos.top + "px"; + display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; + display.cursor.style.display = ""; + + if (pos.other) { + display.otherCursor.style.display = ""; + display.otherCursor.style.left = pos.other.left + "px"; + display.otherCursor.style.top = pos.other.top + "px"; + display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; + } else { display.otherCursor.style.display = "none"; } + } + + // Highlight selection + function updateSelectionRange(cm) { + var display = cm.display, doc = cm.doc, sel = cm.doc.sel; + var fragment = document.createDocumentFragment(); + var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display); + + function add(left, top, width, bottom) { + if (top < 0) top = 0; + fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + + "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) + + "px; height: " + (bottom - top) + "px")); + } + + function drawForLine(line, fromArg, toArg, retTop) { + var lineObj = getLine(doc, line); + var lineLen = lineObj.text.length, rVal = retTop ? Infinity : -Infinity; + function coords(ch) { + return charCoords(cm, Pos(line, ch), "div", lineObj); + } + + iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) { + var leftPos = coords(dir == "rtl" ? to - 1 : from); + var rightPos = coords(dir == "rtl" ? from : to - 1); + var left = leftPos.left, right = rightPos.right; + if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part + add(left, leftPos.top, null, leftPos.bottom); + left = pl; + if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top); + } + if (toArg == null && to == lineLen) right = clientWidth; + if (fromArg == null && from == 0) left = pl; + rVal = retTop ? Math.min(rightPos.top, rVal) : Math.max(rightPos.bottom, rVal); + if (left < pl + 1) left = pl; + add(left, rightPos.top, right - left, rightPos.bottom); + }); + return rVal; + } + + if (sel.from.line == sel.to.line) { + drawForLine(sel.from.line, sel.from.ch, sel.to.ch); + } else { + var fromObj = getLine(doc, sel.from.line); + var cur = fromObj, merged, path = [sel.from.line, sel.from.ch], singleLine; + while (merged = collapsedSpanAtEnd(cur)) { + var found = merged.find(); + path.push(found.from.ch, found.to.line, found.to.ch); + if (found.to.line == sel.to.line) { + path.push(sel.to.ch); + singleLine = true; + break; + } + cur = getLine(doc, found.to.line); + } + + // This is a single, merged line + if (singleLine) { + for (var i = 0; i < path.length; i += 3) + drawForLine(path[i], path[i+1], path[i+2]); + } else { + var middleTop, middleBot, toObj = getLine(doc, sel.to.line); + if (sel.from.ch) + // Draw the first line of selection. + middleTop = drawForLine(sel.from.line, sel.from.ch, null, false); + else + // Simply include it in the middle block. + middleTop = heightAtLine(cm, fromObj) - display.viewOffset; + + if (!sel.to.ch) + middleBot = heightAtLine(cm, toObj) - display.viewOffset; + else + middleBot = drawForLine(sel.to.line, collapsedSpanAtStart(toObj) ? null : 0, sel.to.ch, true); + + if (middleTop < middleBot) add(pl, middleTop, null, middleBot); + } + } + + removeChildrenAndAdd(display.selectionDiv, fragment); + display.selectionDiv.style.display = ""; + } + + // Cursor-blinking + function restartBlink(cm) { + var display = cm.display; + clearInterval(display.blinker); + var on = true; + display.cursor.style.visibility = display.otherCursor.style.visibility = ""; + display.blinker = setInterval(function() { + if (!display.cursor.offsetHeight) return; + display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden"; + }, cm.options.cursorBlinkRate); + } + + // HIGHLIGHT WORKER + + function startWorker(cm, time) { + if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo) + cm.state.highlight.set(time, bind(highlightWorker, cm)); + } + + function highlightWorker(cm) { + var doc = cm.doc; + if (doc.frontier < doc.first) doc.frontier = doc.first; + if (doc.frontier >= cm.display.showingTo) return; + var end = +new Date + cm.options.workTime; + var state = copyState(doc.mode, getStateBefore(cm, doc.frontier)); + var changed = [], prevChange; + doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) { + if (doc.frontier >= cm.display.showingFrom) { // Visible + var oldStyles = line.styles; + line.styles = highlightLine(cm, line, state); + var ischange = !oldStyles || oldStyles.length != line.styles.length; + for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i]; + if (ischange) { + if (prevChange && prevChange.end == doc.frontier) prevChange.end++; + else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1}); + } + line.stateAfter = copyState(doc.mode, state); + } else { + processLine(cm, line, state); + line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null; + } + ++doc.frontier; + if (+new Date > end) { + startWorker(cm, cm.options.workDelay); + return true; + } + }); + if (changed.length) + operation(cm, function() { + for (var i = 0; i < changed.length; ++i) + regChange(this, changed[i].start, changed[i].end); + })(); + } + + // Finds the line to start with when starting a parse. Tries to + // find a line with a stateAfter, so that it can start with a + // valid state. If that fails, it returns the line with the + // smallest indentation, which tends to need the least context to + // parse correctly. + function findStartLine(cm, n) { + var minindent, minline, doc = cm.doc; + for (var search = n, lim = n - 100; search > lim; --search) { + if (search <= doc.first) return doc.first; + var line = getLine(doc, search - 1); + if (line.stateAfter) return search; + var indented = countColumn(line.text, null, cm.options.tabSize); + if (minline == null || minindent > indented) { + minline = search - 1; + minindent = indented; + } + } + return minline; + } + + function getStateBefore(cm, n) { + var doc = cm.doc, display = cm.display; + if (!doc.mode.startState) return true; + var pos = findStartLine(cm, n), state = pos > doc.first && getLine(doc, pos-1).stateAfter; + if (!state) state = startState(doc.mode); + else state = copyState(doc.mode, state); + doc.iter(pos, n, function(line) { + processLine(cm, line, state); + var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo; + line.stateAfter = save ? copyState(doc.mode, state) : null; + ++pos; + }); + return state; + } + + // POSITION MEASUREMENT + + function paddingTop(display) {return display.lineSpace.offsetTop;} + function paddingLeft(display) { + var e = removeChildrenAndAdd(display.measure, elt("pre")).appendChild(elt("span", "x")); + return e.offsetLeft; + } + + function measureChar(cm, line, ch, data) { + var dir = -1; + data = data || measureLine(cm, line); + + for (var pos = ch;; pos += dir) { + var r = data[pos]; + if (r) break; + if (dir < 0 && pos == 0) dir = 1; + } + return {left: pos < ch ? r.right : r.left, + right: pos > ch ? r.left : r.right, + top: r.top, bottom: r.bottom}; + } + + function measureLine(cm, line) { + // First look in the cache + var display = cm.display, cache = cm.display.measureLineCache; + for (var i = 0; i < cache.length; ++i) { + var memo = cache[i]; + if (memo.text == line.text && memo.markedSpans == line.markedSpans && + display.scroller.clientWidth == memo.width && + memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass) + return memo.measure; + } + + var measure = measureLineInner(cm, line); + // Store result in the cache + var memo = {text: line.text, width: display.scroller.clientWidth, + markedSpans: line.markedSpans, measure: measure, + classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass}; + if (cache.length == 16) cache[++display.measureLineCachePos % 16] = memo; + else cache.push(memo); + return measure; + } + + function measureLineInner(cm, line) { + var display = cm.display, measure = emptyArray(line.text.length); + var pre = lineContent(cm, line, measure); + + // IE does not cache element positions of inline elements between + // calls to getBoundingClientRect. This makes the loop below, + // which gathers the positions of all the characters on the line, + // do an amount of layout work quadratic to the number of + // characters. When line wrapping is off, we try to improve things + // by first subdividing the line into a bunch of inline blocks, so + // that IE can reuse most of the layout information from caches + // for those blocks. This does interfere with line wrapping, so it + // doesn't work when wrapping is on, but in that case the + // situation is slightly better, since IE does cache line-wrapping + // information and only recomputes per-line. + if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) { + var fragment = document.createDocumentFragment(); + var chunk = 10, n = pre.childNodes.length; + for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) { + var wrap = elt("div", null, null, "display: inline-block"); + for (var j = 0; j < chunk && n; ++j) { + wrap.appendChild(pre.firstChild); + --n; + } + fragment.appendChild(wrap); + } + pre.appendChild(fragment); + } + + removeChildrenAndAdd(display.measure, pre); + + var outer = display.lineDiv.getBoundingClientRect(); + var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight; + // Work around an IE7/8 bug where it will sometimes have randomly + // replaced our pre with a clone at this point. + if (ie_lt9 && display.measure.first != pre) + removeChildrenAndAdd(display.measure, pre); + + for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) { + var size = cur.getBoundingClientRect(); + var top = Math.max(0, size.top - outer.top), bot = Math.min(size.bottom - outer.top, maxBot); + for (var j = 0; j < vranges.length; j += 2) { + var rtop = vranges[j], rbot = vranges[j+1]; + if (rtop > bot || rbot < top) continue; + if (rtop <= top && rbot >= bot || + top <= rtop && bot >= rbot || + Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) { + vranges[j] = Math.min(top, rtop); + vranges[j+1] = Math.max(bot, rbot); + break; + } + } + if (j == vranges.length) vranges.push(top, bot); + data[i] = {left: size.left - outer.left, right: size.right - outer.left, top: j}; + } + for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) { + var vr = cur.top; + cur.top = vranges[vr]; cur.bottom = vranges[vr+1]; + } + if (!cm.options.lineWrapping) { + var last = pre.lastChild; + if (last.nodeType == 3) last = pre.appendChild(elt("span", "\u200b")); + data.width = last.getBoundingClientRect().right - outer.left; + } + + return data; + } + + function clearCaches(cm) { + cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0; + cm.display.cachedCharWidth = cm.display.cachedTextHeight = null; + cm.display.maxLineChanged = true; + cm.display.lineNumChars = null; + } + + // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page" + function intoCoordSystem(cm, lineObj, rect, context) { + if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) { + var size = widgetHeight(lineObj.widgets[i]); + rect.top += size; rect.bottom += size; + } + if (context == "line") return rect; + if (!context) context = "local"; + var yOff = heightAtLine(cm, lineObj); + if (context != "local") yOff -= cm.display.viewOffset; + if (context == "page") { + var lOff = cm.display.lineSpace.getBoundingClientRect(); + yOff += lOff.top + (window.pageYOffset || (document.documentElement || document.body).scrollTop); + var xOff = lOff.left + (window.pageXOffset || (document.documentElement || document.body).scrollLeft); + rect.left += xOff; rect.right += xOff; + } + rect.top += yOff; rect.bottom += yOff; + return rect; + } + + function charCoords(cm, pos, context, lineObj) { + if (!lineObj) lineObj = getLine(cm.doc, pos.line); + return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch), context); + } + + function cursorCoords(cm, pos, context, lineObj, measurement) { + lineObj = lineObj || getLine(cm.doc, pos.line); + if (!measurement) measurement = measureLine(cm, lineObj); + function get(ch, right) { + var m = measureChar(cm, lineObj, ch, measurement); + if (right) m.left = m.right; else m.right = m.left; + return intoCoordSystem(cm, lineObj, m, context); + } + var order = getOrder(lineObj), ch = pos.ch; + if (!order) return get(ch); + var main, other, linedir = order[0].level; + for (var i = 0; i < order.length; ++i) { + var part = order[i], rtl = part.level % 2, nb, here; + if (part.from < ch && part.to > ch) return get(ch, rtl); + var left = rtl ? part.to : part.from, right = rtl ? part.from : part.to; + if (left == ch) { + // Opera and IE return bogus offsets and widths for edges + // where the direction flips, but only for the side with the + // lower level. So we try to use the side with the higher + // level. + if (i && part.level < (nb = order[i-1]).level) here = get(nb.level % 2 ? nb.from : nb.to - 1, true); + else here = get(rtl && part.from != part.to ? ch - 1 : ch); + if (rtl == linedir) main = here; else other = here; + } else if (right == ch) { + var nb = i < order.length - 1 && order[i+1]; + if (!rtl && nb && nb.from == nb.to) continue; + if (nb && part.level < nb.level) here = get(nb.level % 2 ? nb.to - 1 : nb.from); + else here = get(rtl ? ch : ch - 1, true); + if (rtl == linedir) main = here; else other = here; + } + } + if (linedir && !ch) other = get(order[0].to - 1); + if (!main) return other; + if (other) main.other = other; + return main; + } + + // Coords must be lineSpace-local + function coordsChar(cm, x, y) { + var doc = cm.doc; + y += cm.display.viewOffset; + if (y < 0) return {line: doc.first, ch: 0, outside: true}; + var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1; + if (lineNo > last) + return Pos(doc.size - 1, getLine(doc, last).text.length); + if (x < 0) x = 0; + + for (;;) { + var lineObj = getLine(doc, lineNo); + var found = coordsCharInner(cm, lineObj, lineNo, x, y); + var merged = collapsedSpanAtEnd(lineObj); + var mergedPos = merged && merged.find(); + if (merged && found.ch >= mergedPos.from.ch) + lineNo = mergedPos.to.line; + else + return found; + } + } + + function coordsCharInner(cm, lineObj, lineNo, x, y) { + var innerOff = y - heightAtLine(cm, lineObj); + var wrongLine = false, cWidth = cm.display.wrapper.clientWidth; + var measurement = measureLine(cm, lineObj); + + function getX(ch) { + var sp = cursorCoords(cm, Pos(lineNo, ch), "line", + lineObj, measurement); + wrongLine = true; + if (innerOff > sp.bottom) return Math.max(0, sp.left - cWidth); + else if (innerOff < sp.top) return sp.left + cWidth; + else wrongLine = false; + return sp.left; + } + + var bidi = getOrder(lineObj), dist = lineObj.text.length; + var from = lineLeft(lineObj), to = lineRight(lineObj); + var fromX = getX(from), toX = getX(to); + + if (x > toX) return {line: lineNo, ch: to, outside: wrongLine}; + // Do a binary search between these bounds. + for (;;) { + if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) { + var after = x - fromX < toX - x, ch = after ? from : to; + while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch; + return {line: lineNo, ch: ch, after: after, outside: wrongLine}; + } + var step = Math.ceil(dist / 2), middle = from + step; + if (bidi) { + middle = from; + for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1); + } + var middleX = getX(middle); + if (middleX > x) {to = middle; toX = middleX; if (wrongLine) toX += 1000; dist -= step;} + else {from = middle; fromX = middleX; dist = step;} + } + } + + var measureText; + function textHeight(display) { + if (display.cachedTextHeight != null) return display.cachedTextHeight; + if (measureText == null) { + measureText = elt("pre"); + // Measure a bunch of lines, for browsers that compute + // fractional heights. + for (var i = 0; i < 49; ++i) { + measureText.appendChild(document.createTextNode("x")); + measureText.appendChild(elt("br")); + } + measureText.appendChild(document.createTextNode("x")); + } + removeChildrenAndAdd(display.measure, measureText); + var height = measureText.offsetHeight / 50; + if (height > 3) display.cachedTextHeight = height; + removeChildren(display.measure); + return height || 1; + } + + function charWidth(display) { + if (display.cachedCharWidth != null) return display.cachedCharWidth; + var anchor = elt("span", "x"); + var pre = elt("pre", [anchor]); + removeChildrenAndAdd(display.measure, pre); + var width = anchor.offsetWidth; + if (width > 2) display.cachedCharWidth = width; + return width || 10; + } + + // OPERATIONS + + // Operations are used to wrap changes in such a way that each + // change won't have to update the cursor and display (which would + // be awkward, slow, and error-prone), but instead updates are + // batched and then all combined and executed at once. + + function startOperation(cm) { + cm.curOp = { + // An array of ranges of lines that have to be updated. See + // updateDisplay. + changes: [], + updateInput: null, + userSelChange: null, + textChanged: null, + selectionChanged: false, + updateMaxLine: false, + updateScrollPos: false, + id: ++cm.nextOpId + }; + if (!delayedCallbackDepth++) delayedCallbacks = []; + } + + function endOperation(cm) { + var op = cm.curOp, doc = cm.doc, display = cm.display; + cm.curOp = null; + + if (op.updateMaxLine) computeMaxLength(cm); + if (display.maxLineChanged && !cm.options.lineWrapping) { + var width = measureLine(cm, display.maxLine).width; + display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px"; + display.maxLineChanged = false; + var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth); + if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos) + setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true); + } + var newScrollPos, updated; + if (op.updateScrollPos) { + newScrollPos = op.updateScrollPos; + } else if (op.selectionChanged) { + var coords = cursorCoords(cm, doc.sel.head); + newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom); + } + if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null) + updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop); + if (!updated && op.selectionChanged) updateSelection(cm); + if (op.updateScrollPos) { + display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop; + display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft; + alignHorizontally(cm); + } else if (newScrollPos) { + scrollCursorIntoView(cm); + } + if (op.selectionChanged) restartBlink(cm); + + if (cm.state.focused && op.updateInput) + resetInput(cm, op.userSelChange); + + var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; + if (hidden) for (var i = 0; i < hidden.length; ++i) + if (!hidden[i].lines.length) signal(hidden[i], "hide"); + if (unhidden) for (var i = 0; i < unhidden.length; ++i) + if (unhidden[i].lines.length) signal(unhidden[i], "unhide"); + + var delayed; + if (!--delayedCallbackDepth) { + delayed = delayedCallbacks; + delayedCallbacks = null; + } + if (op.textChanged) + signal(cm, "change", cm, op.textChanged); + if (op.selectionChanged) signal(cm, "cursorActivity", cm); + if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i](cm); + } + + // Wraps a function in an operation. Returns the wrapped function. + function operation(cm1, f) { + return function() { + var cm = cm1 || this, withOp = !cm.curOp; + if (withOp) startOperation(cm); + try { var result = f.apply(cm, arguments); } + finally { if (withOp) endOperation(cm); } + return result; + }; + } + function docOperation(f) { + return function() { + var withOp = this.cm && !this.cm.curOp, result; + if (withOp) startOperation(this.cm); + try { result = f.apply(this, arguments); } + finally { if (withOp) endOperation(this.cm); } + return result; + }; + } + function runInOp(cm, f) { + var withOp = !cm.curOp, result; + if (withOp) startOperation(cm); + try { result = f(); } + finally { if (withOp) endOperation(cm); } + return result; + } + + function regChange(cm, from, to, lendiff) { + if (from == null) from = cm.doc.first; + if (to == null) to = cm.doc.first + cm.doc.size; + cm.curOp.changes.push({from: from, to: to, diff: lendiff}); + } + + // INPUT HANDLING + + function slowPoll(cm) { + if (cm.display.pollingFast) return; + cm.display.poll.set(cm.options.pollInterval, function() { + readInput(cm); + if (cm.state.focused) slowPoll(cm); + }); + } + + function fastPoll(cm) { + var missed = false; + cm.display.pollingFast = true; + function p() { + var changed = readInput(cm); + if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);} + else {cm.display.pollingFast = false; slowPoll(cm);} + } + cm.display.poll.set(20, p); + } + + // prevInput is a hack to work with IME. If we reset the textarea + // on every change, that breaks IME. So we look for changes + // compared to the previous content instead. (Modern browsers have + // events that indicate IME taking place, but these are not widely + // supported or compatible enough yet to rely on.) + function readInput(cm) { + var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel; + if (!cm.state.focused || hasSelection(input) || isReadOnly(cm)) return false; + var text = input.value; + if (text == prevInput && posEq(sel.from, sel.to)) return false; + var withOp = !cm.curOp; + if (withOp) startOperation(cm); + sel.shift = false; + var same = 0, l = Math.min(prevInput.length, text.length); + while (same < l && prevInput[same] == text[same]) ++same; + var from = sel.from, to = sel.to; + if (same < prevInput.length) + from = Pos(from.line, from.ch - (prevInput.length - same)); + else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming) + to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same))); + var updateInput = cm.curOp.updateInput; + makeChange(cm.doc, {from: from, to: to, text: splitLines(text.slice(same)), + origin: cm.state.pasteIncoming ? "paste" : "+input"}, "end"); + + cm.curOp.updateInput = updateInput; + if (text.length > 1000) input.value = cm.display.prevInput = ""; + else cm.display.prevInput = text; + if (withOp) endOperation(cm); + cm.state.pasteIncoming = false; + return true; + } + + function resetInput(cm, user) { + var minimal, selected, doc = cm.doc; + if (!posEq(doc.sel.from, doc.sel.to)) { + cm.display.prevInput = ""; + minimal = hasCopyEvent && + (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000); + if (minimal) cm.display.input.value = "-"; + else cm.display.input.value = selected || cm.getSelection(); + if (cm.state.focused) selectInput(cm.display.input); + } else if (user) cm.display.prevInput = cm.display.input.value = ""; + cm.display.inaccurateSelection = minimal; + } + + function focusInput(cm) { + if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input)) + cm.display.input.focus(); + } + + function isReadOnly(cm) { + return cm.options.readOnly || cm.doc.cantEdit; + } + + // EVENT HANDLERS + + function registerEventHandlers(cm) { + var d = cm.display; + on(d.scroller, "mousedown", operation(cm, onMouseDown)); + on(d.scroller, "dblclick", operation(cm, e_preventDefault)); + on(d.lineSpace, "selectstart", function(e) { + if (!eventInWidget(d, e)) e_preventDefault(e); + }); + // Gecko browsers fire contextmenu *after* opening the menu, at + // which point we can't mess with it anymore. Context menu is + // handled in onMouseDown for Gecko. + if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);}); + + on(d.scroller, "scroll", function() { + setScrollTop(cm, d.scroller.scrollTop); + setScrollLeft(cm, d.scroller.scrollLeft, true); + signal(cm, "scroll", cm); + }); + on(d.scrollbarV, "scroll", function() { + setScrollTop(cm, d.scrollbarV.scrollTop); + }); + on(d.scrollbarH, "scroll", function() { + setScrollLeft(cm, d.scrollbarH.scrollLeft); + }); + + on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);}); + on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);}); + + function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); } + on(d.scrollbarH, "mousedown", reFocus); + on(d.scrollbarV, "mousedown", reFocus); + // Prevent wrapper from ever scrolling + on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); + + function onResize() { + // Might be a text scaling operation, clear size caches. + d.cachedCharWidth = d.cachedTextHeight = null; + clearCaches(cm); + runInOp(cm, bind(regChange, cm)); + } + on(window, "resize", onResize); + // Above handler holds on to the editor and its data structures. + // Here we poll to unregister it when the editor is no longer in + // the document, so that it can be garbage-collected. + function unregister() { + for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {} + if (p) setTimeout(unregister, 5000); + else off(window, "resize", onResize); + } + setTimeout(unregister, 5000); + + on(d.input, "keyup", operation(cm, function(e) { + if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; + if (e_prop(e, "keyCode") == 16) cm.doc.sel.shift = false; + })); + on(d.input, "input", bind(fastPoll, cm)); + on(d.input, "keydown", operation(cm, onKeyDown)); + on(d.input, "keypress", operation(cm, onKeyPress)); + on(d.input, "focus", bind(onFocus, cm)); + on(d.input, "blur", bind(onBlur, cm)); + + function drag_(e) { + if (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return; + e_stop(e); + } + if (cm.options.dragDrop) { + on(d.scroller, "dragstart", function(e){onDragStart(cm, e);}); + on(d.scroller, "dragenter", drag_); + on(d.scroller, "dragover", drag_); + on(d.scroller, "drop", operation(cm, onDrop)); + } + on(d.scroller, "paste", function(e){ + if (eventInWidget(d, e)) return; + focusInput(cm); + fastPoll(cm); + }); + on(d.input, "paste", function() { + cm.state.pasteIncoming = true; + fastPoll(cm); + }); + + function prepareCopy() { + if (d.inaccurateSelection) { + d.prevInput = ""; + d.inaccurateSelection = false; + d.input.value = cm.getSelection(); + selectInput(d.input); + } + } + on(d.input, "cut", prepareCopy); + on(d.input, "copy", prepareCopy); + + // Needed to handle Tab key in KHTML + if (khtml) on(d.sizer, "mouseup", function() { + if (document.activeElement == d.input) d.input.blur(); + focusInput(cm); + }); + } + + function eventInWidget(display, e) { + for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { + if (!n) return true; + if (/\bCodeMirror-(?:line)?widget\b/.test(n.className) || + n.parentNode == display.sizer && n != display.mover) return true; + } + } + + function posFromMouse(cm, e, liberal) { + var display = cm.display; + if (!liberal) { + var target = e_target(e); + if (target == display.scrollbarH || target == display.scrollbarH.firstChild || + target == display.scrollbarV || target == display.scrollbarV.firstChild || + target == display.scrollbarFiller) return null; + } + var x, y, space = display.lineSpace.getBoundingClientRect(); + // Fails unpredictably on IE[67] when mouse is dragged around quickly. + try { x = e.clientX; y = e.clientY; } catch (e) { return null; } + return coordsChar(cm, x - space.left, y - space.top); + } + + var lastClick, lastDoubleClick; + function onMouseDown(e) { + var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel; + sel.shift = e_prop(e, "shiftKey"); + + if (eventInWidget(display, e)) { + if (!webkit) { + display.scroller.draggable = false; + setTimeout(function(){display.scroller.draggable = true;}, 100); + } + return; + } + if (clickInGutter(cm, e)) return; + var start = posFromMouse(cm, e); + + switch (e_button(e)) { + case 3: + if (captureMiddleClick) onContextMenu.call(cm, cm, e); + return; + case 2: + if (start) extendSelection(cm.doc, start); + setTimeout(bind(focusInput, cm), 20); + e_preventDefault(e); + return; + } + // For button 1, if it was clicked inside the editor + // (posFromMouse returning non-null), we have to adjust the + // selection. + if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;} + + if (!cm.state.focused) onFocus(cm); + + var now = +new Date, type = "single"; + if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) { + type = "triple"; + e_preventDefault(e); + setTimeout(bind(focusInput, cm), 20); + selectLine(cm, start.line); + } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) { + type = "double"; + lastDoubleClick = {time: now, pos: start}; + e_preventDefault(e); + var word = findWordAt(getLine(doc, start.line).text, start); + extendSelection(cm.doc, word.from, word.to); + } else { lastClick = {time: now, pos: start}; } + + var last = start; + if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) && + !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") { + var dragEnd = operation(cm, function(e2) { + if (webkit) display.scroller.draggable = false; + cm.state.draggingText = false; + off(document, "mouseup", dragEnd); + off(display.scroller, "drop", dragEnd); + if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { + e_preventDefault(e2); + extendSelection(cm.doc, start); + focusInput(cm); + } + }); + // Let the drag handler handle this. + if (webkit) display.scroller.draggable = true; + cm.state.draggingText = dragEnd; + // IE's approach to draggable + if (display.scroller.dragDrop) display.scroller.dragDrop(); + on(document, "mouseup", dragEnd); + on(display.scroller, "drop", dragEnd); + return; + } + e_preventDefault(e); + if (type == "single") extendSelection(cm.doc, clipPos(doc, start)); + + var startstart = sel.from, startend = sel.to; + + function doSelect(cur) { + if (type == "single") { + extendSelection(cm.doc, clipPos(doc, start), cur); + return; + } + + startstart = clipPos(doc, startstart); + startend = clipPos(doc, startend); + if (type == "double") { + var word = findWordAt(getLine(doc, cur.line).text, cur); + if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend); + else extendSelection(cm.doc, startstart, word.to); + } else if (type == "triple") { + if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0))); + else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0))); + } + } + + var editorSize = display.wrapper.getBoundingClientRect(); + // Used to ensure timeout re-tries don't fire when another extend + // happened in the meantime (clearTimeout isn't reliable -- at + // least on Chrome, the timeouts still happen even when cleared, + // if the clear happens after their scheduled firing time). + var counter = 0; + + function extend(e) { + var curCount = ++counter; + var cur = posFromMouse(cm, e, true); + if (!cur) return; + if (!posEq(cur, last)) { + if (!cm.state.focused) onFocus(cm); + last = cur; + doSelect(cur); + var visible = visibleLines(display, doc); + if (cur.line >= visible.to || cur.line < visible.from) + setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150); + } else { + var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; + if (outside) setTimeout(operation(cm, function() { + if (counter != curCount) return; + display.scroller.scrollTop += outside; + extend(e); + }), 50); + } + } + + function done(e) { + counter = Infinity; + var cur = posFromMouse(cm, e); + if (cur) doSelect(cur); + e_preventDefault(e); + focusInput(cm); + off(document, "mousemove", move); + off(document, "mouseup", up); + } + + var move = operation(cm, function(e) { + if (!ie && !e_button(e)) done(e); + else extend(e); + }); + var up = operation(cm, done); + on(document, "mousemove", move); + on(document, "mouseup", up); + } + + function onDrop(e) { + var cm = this; + if (eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e)))) + return; + e_preventDefault(e); + var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; + if (!pos || isReadOnly(cm)) return; + if (files && files.length && window.FileReader && window.File) { + var n = files.length, text = Array(n), read = 0; + var loadFile = function(file, i) { + var reader = new FileReader; + reader.onload = function() { + text[i] = reader.result; + if (++read == n) { + pos = clipPos(cm.doc, pos); + replaceRange(cm.doc, text.join(""), pos, "around", "paste"); + } + }; + reader.readAsText(file); + }; + for (var i = 0; i < n; ++i) loadFile(files[i], i); + } else { + // Don't do a replace if the drop happened inside of the selected text. + if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) { + cm.state.draggingText(e); + // Ensure the editor is re-focused + setTimeout(bind(focusInput, cm), 20); + return; + } + try { + var text = e.dataTransfer.getData("Text"); + if (text) { + var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to; + setSelection(cm.doc, pos, pos); + if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste"); + cm.replaceSelection(text, null, "paste"); + focusInput(cm); + onFocus(cm); + } + } + catch(e){} + } + } + + function clickInGutter(cm, e) { + var display = cm.display; + try { var mX = e.clientX, mY = e.clientY; } + catch(e) { return false; } + + if (mX >= Math.floor(display.gutters.getBoundingClientRect().right)) return false; + e_preventDefault(e); + if (!hasHandler(cm, "gutterClick")) return true; + + var lineBox = display.lineDiv.getBoundingClientRect(); + if (mY > lineBox.bottom) return true; + mY -= lineBox.top - display.viewOffset; + + for (var i = 0; i < cm.options.gutters.length; ++i) { + var g = display.gutters.childNodes[i]; + if (g && g.getBoundingClientRect().right >= mX) { + var line = lineAtHeight(cm.doc, mY); + var gutter = cm.options.gutters[i]; + signalLater(cm, "gutterClick", cm, line, gutter, e); + break; + } + } + return true; + } + + function onDragStart(cm, e) { + if (eventInWidget(cm.display, e)) return; + + var txt = cm.getSelection(); + e.dataTransfer.setData("Text", txt); + + // Use dummy image instead of default browsers image. + // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. + if (e.dataTransfer.setDragImage && !safari) { + var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); + if (opera) { + img.width = img.height = 1; + cm.display.wrapper.appendChild(img); + // Force a relayout, or Opera won't use our image for some obscure reason + img._top = img.offsetTop; + } + e.dataTransfer.setDragImage(img, 0, 0); + if (opera) img.parentNode.removeChild(img); + } + } + + function setScrollTop(cm, val) { + if (Math.abs(cm.doc.scrollTop - val) < 2) return; + cm.doc.scrollTop = val; + if (!gecko) updateDisplay(cm, [], val); + if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val; + if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val; + if (gecko) updateDisplay(cm, []); + } + function setScrollLeft(cm, val, isScroller) { + if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return; + val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth); + cm.doc.scrollLeft = val; + alignHorizontally(cm); + if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val; + if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val; + } + + // Since the delta values reported on mouse wheel events are + // unstandardized between browsers and even browser versions, and + // generally horribly unpredictable, this code starts by measuring + // the scroll effect that the first few mouse wheel events have, + // and, from that, detects the way it can convert deltas to pixel + // offsets afterwards. + // + // The reason we want to know the amount a wheel event will scroll + // is that it gives us a chance to update the display before the + // actual scrolling happens, reducing flickering. + + var wheelSamples = 0, wheelPixelsPerUnit = null; + // Fill in a browser-detected starting value on browsers where we + // know one. These don't have to be accurate -- the result of them + // being wrong would just be a slight flicker on the first wheel + // scroll (if it is large enough). + if (ie) wheelPixelsPerUnit = -.53; + else if (gecko) wheelPixelsPerUnit = 15; + else if (chrome) wheelPixelsPerUnit = -.7; + else if (safari) wheelPixelsPerUnit = -1/3; + + function onScrollWheel(cm, e) { + var dx = e.wheelDeltaX, dy = e.wheelDeltaY; + if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail; + if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail; + else if (dy == null) dy = e.wheelDelta; + + // Webkit browsers on OS X abort momentum scrolls when the target + // of the scroll event is removed from the scrollable element. + // This hack (see related code in patchDisplay) makes sure the + // element is kept around. + if (dy && mac && webkit) { + for (var cur = e.target; cur != scroll; cur = cur.parentNode) { + if (cur.lineObj) { + cm.display.currentWheelTarget = cur; + break; + } + } + } + + var display = cm.display, scroll = display.scroller; + // On some browsers, horizontal scrolling will cause redraws to + // happen before the gutter has been realigned, causing it to + // wriggle around in a most unseemly way. When we have an + // estimated pixels/delta value, we just handle horizontal + // scrolling entirely here. It'll be slightly off from native, but + // better than glitching out. + if (dx && !gecko && !opera && wheelPixelsPerUnit != null) { + if (dy) + setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))); + setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth))); + e_preventDefault(e); + display.wheelStartX = null; // Abort measurement, if in progress + return; + } + + if (dy && wheelPixelsPerUnit != null) { + var pixels = dy * wheelPixelsPerUnit; + var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; + if (pixels < 0) top = Math.max(0, top + pixels - 50); + else bot = Math.min(cm.doc.height, bot + pixels + 50); + updateDisplay(cm, [], {top: top, bottom: bot}); + } + + if (wheelSamples < 20) { + if (display.wheelStartX == null) { + display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; + display.wheelDX = dx; display.wheelDY = dy; + setTimeout(function() { + if (display.wheelStartX == null) return; + var movedX = scroll.scrollLeft - display.wheelStartX; + var movedY = scroll.scrollTop - display.wheelStartY; + var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || + (movedX && display.wheelDX && movedX / display.wheelDX); + display.wheelStartX = display.wheelStartY = null; + if (!sample) return; + wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); + ++wheelSamples; + }, 200); + } else { + display.wheelDX += dx; display.wheelDY += dy; + } + } + } + + function doHandleBinding(cm, bound, dropShift) { + if (typeof bound == "string") { + bound = commands[bound]; + if (!bound) return false; + } + // Ensure previous input has been read, so that the handler sees a + // consistent view of the document + if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false; + var doc = cm.doc, prevShift = doc.sel.shift; + try { + if (isReadOnly(cm)) cm.state.suppressEdits = true; + if (dropShift) doc.sel.shift = false; + bound(cm); + } finally { + doc.sel.shift = prevShift; + cm.state.suppressEdits = false; + } + return true; + } + + function allKeyMaps(cm) { + var maps = cm.state.keyMaps.slice(0); + maps.push(cm.options.keyMap); + if (cm.options.extraKeys) maps.unshift(cm.options.extraKeys); + return maps; + } + + var maybeTransition; + function handleKeyBinding(cm, e) { + // Handle auto keymap transitions + var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto; + clearTimeout(maybeTransition); + if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() { + if (getKeyMap(cm.options.keyMap) == startMap) + cm.options.keyMap = (next.call ? next.call(null, cm) : next); + }, 50); + + var name = keyName(e, true), handled = false; + if (!name) return false; + var keymaps = allKeyMaps(cm); + + if (e_prop(e, "shiftKey")) { + // First try to resolve full name (including 'Shift-'). Failing + // that, see if there is a cursor-motion command (starting with + // 'go') bound to the keyname without 'Shift-'. + handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);}) + || lookupKey(name, keymaps, function(b) { + if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(cm, b); + }); + } else { + handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); }); + } + if (handled == "stop") handled = false; + + if (handled) { + e_preventDefault(e); + restartBlink(cm); + if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; } + } + return handled; + } + + function handleCharBinding(cm, e, ch) { + var handled = lookupKey("'" + ch + "'", allKeyMaps(cm), + function(b) { return doHandleBinding(cm, b, true); }); + if (handled) { + e_preventDefault(e); + restartBlink(cm); + } + return handled; + } + + var lastStoppedKey = null; + function onKeyDown(e) { + var cm = this; + if (!cm.state.focused) onFocus(cm); + if (ie && e.keyCode == 27) { e.returnValue = false; } + if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; + var code = e_prop(e, "keyCode"); + // IE does strange things with escape. + cm.doc.sel.shift = code == 16 || e_prop(e, "shiftKey"); + // First give onKeyEvent option a chance to handle this. + var handled = handleKeyBinding(cm, e); + if (opera) { + lastStoppedKey = handled ? code : null; + // Opera has no cut event... we try to at least catch the key combo + if (!handled && code == 88 && !hasCopyEvent && e_prop(e, mac ? "metaKey" : "ctrlKey")) + cm.replaceSelection(""); + } + } + + function onKeyPress(e) { + var cm = this; + if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; + var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode"); + if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} + if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return; + var ch = String.fromCharCode(charCode == null ? keyCode : charCode); + if (this.options.electricChars && this.doc.mode.electricChars && + this.options.smartIndent && !isReadOnly(this) && + this.doc.mode.electricChars.indexOf(ch) > -1) + setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75); + if (handleCharBinding(cm, e, ch)) return; + fastPoll(cm); + } + + function onFocus(cm) { + if (cm.options.readOnly == "nocursor") return; + if (!cm.state.focused) { + signal(cm, "focus", cm); + cm.state.focused = true; + if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1) + cm.display.wrapper.className += " CodeMirror-focused"; + resetInput(cm, true); + } + slowPoll(cm); + restartBlink(cm); + } + function onBlur(cm) { + if (cm.state.focused) { + signal(cm, "blur", cm); + cm.state.focused = false; + cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", ""); + } + clearInterval(cm.display.blinker); + setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150); + } + + var detectingSelectAll; + function onContextMenu(cm, e) { + var display = cm.display, sel = cm.doc.sel; + if (eventInWidget(display, e)) return; + + var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; + if (!pos || opera) return; // Opera is difficult. + if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)) + operation(cm, setSelection)(cm.doc, pos, pos); + + var oldCSS = display.input.style.cssText; + display.inputDiv.style.position = "absolute"; + display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) + + "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" + + "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);"; + focusInput(cm); + resetInput(cm, true); + // Adds "Select all" to context menu in FF + if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " "; + + function rehide() { + display.inputDiv.style.position = "relative"; + display.input.style.cssText = oldCSS; + if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos; + slowPoll(cm); + + // Try to detect the user choosing select-all + if (display.input.selectionStart != null && (!ie || ie_lt9)) { + clearTimeout(detectingSelectAll); + var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value), i = 0; + display.prevInput = " "; + display.input.selectionStart = 1; display.input.selectionEnd = extval.length; + var poll = function(){ + if (display.prevInput == " " && display.input.selectionStart == 0) + operation(cm, commands.selectAll)(cm); + else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500); + else resetInput(cm); + }; + detectingSelectAll = setTimeout(poll, 200); + } + } + + if (captureMiddleClick) { + e_stop(e); + var mouseup = function() { + off(window, "mouseup", mouseup); + setTimeout(rehide, 20); + }; + on(window, "mouseup", mouseup); + } else { + setTimeout(rehide, 50); + } + } + + // UPDATING + + function changeEnd(change) { + return Pos(change.from.line + change.text.length - 1, + lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)); + } + + // Hint can be null|"end"|"start"|"around"|{anchor,head} + function computeSelAfterChange(sel, change, hint) { + if (hint && typeof hint == "object") return hint; // Assumed to be {from, to} object + if (hint == "start") return {anchor: change.from, head: change.from}; + + var end = changeEnd(change); + if (hint == "around") return {anchor: change.from, head: end}; + if (hint == "end") return {anchor: end, head: end}; + + // hint is null, leave the selection alone as much as possible + var adjustPos = function(pos) { + if (posLess(pos, change.from)) return pos; + if (!posLess(change.to, pos)) return end; + + var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; + if (pos.line == change.to.line) ch += end.ch - change.to.ch; + return Pos(line, ch); + }; + return {anchor: adjustPos(sel.anchor), head: adjustPos(sel.head)}; + } + + // Replace the range from from to to by the strings in replacement. + // change is a {from, to, text [, origin]} object + function makeChange(doc, change, selUpdate, ignoreReadOnly) { + if (doc.cm) { + if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly); + if (doc.cm.state.suppressEdits) return; + } + + // Possibly split or suppress the update based on the presence + // of read-only spans in its range. + var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); + if (split) { + for (var i = split.length - 1; i >= 1; --i) + makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]}); + if (split.length) + makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate); + } else { + makeChangeNoReadonly(doc, change, selUpdate); + } + } + + function makeChangeNoReadonly(doc, change, selUpdate) { + var selAfter = computeSelAfterChange(doc.sel, change, selUpdate); + addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); + + makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); + var rebased = []; + + linkedDocs(doc, function(doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); + }); + } + + function makeChangeFromHistory(doc, type) { + var hist = doc.history; + var event = (type == "undo" ? hist.done : hist.undone).pop(); + if (!event) return; + hist.dirtyCounter += type == "undo" ? -1 : 1; + + var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter, + anchorAfter: event.anchorBefore, headAfter: event.headBefore}; + (type == "undo" ? hist.undone : hist.done).push(anti); + + for (var i = event.changes.length - 1; i >= 0; --i) { + var change = event.changes[i]; + change.origin = type; + anti.changes.push(historyChangeFromChange(doc, change)); + + var after = i ? computeSelAfterChange(doc.sel, change, null) + : {anchor: event.anchorBefore, head: event.headBefore}; + makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); + var rebased = []; + + linkedDocs(doc, function(doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); + }); + } + } + + function shiftDoc(doc, distance) { + function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);} + doc.first += distance; + if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance); + doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor); + doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to); + } + + function makeChangeSingleDoc(doc, change, selAfter, spans) { + if (doc.cm && !doc.cm.curOp) + return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans); + + if (change.to.line < doc.first) { + shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); + return; + } + if (change.from.line > doc.lastLine()) return; + + // Clip the change to the size of this doc + if (change.from.line < doc.first) { + var shift = change.text.length - 1 - (doc.first - change.from.line); + shiftDoc(doc, shift); + change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), + text: [lst(change.text)], origin: change.origin}; + } + var last = doc.lastLine(); + if (change.to.line > last) { + change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), + text: [change.text[0]], origin: change.origin}; + } + + if (!selAfter) selAfter = computeSelAfterChange(doc.sel, change, null); + if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter); + else updateDoc(doc, change, spans, selAfter); + } + + function makeChangeSingleDocInEditor(cm, change, spans, selAfter) { + var doc = cm.doc, display = cm.display, from = change.from, to = change.to; + + var recomputeMaxLength = false, checkWidthStart = from.line; + if (!cm.options.lineWrapping) { + checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line))); + doc.iter(checkWidthStart, to.line + 1, function(line) { + if (line == display.maxLine) { + recomputeMaxLength = true; + return true; + } + }); + } + + updateDoc(doc, change, spans, selAfter, estimateHeight(cm)); + + if (!cm.options.lineWrapping) { + doc.iter(checkWidthStart, from.line + change.text.length, function(line) { + var len = lineLength(doc, line); + if (len > display.maxLineLength) { + display.maxLine = line; + display.maxLineLength = len; + display.maxLineChanged = true; + recomputeMaxLength = false; + } + }); + if (recomputeMaxLength) cm.curOp.updateMaxLine = true; + } + + // Adjust frontier, schedule worker + doc.frontier = Math.min(doc.frontier, from.line); + startWorker(cm, 400); + + var lendiff = change.text.length - (to.line - from.line) - 1; + // Remember that these lines changed, for updating the display + regChange(cm, from.line, to.line + 1, lendiff); + if (hasHandler(cm, "change")) { + var changeObj = {from: from, to: to, text: change.text, origin: change.origin}; + if (cm.curOp.textChanged) { + for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {} + cur.next = changeObj; + } else cm.curOp.textChanged = changeObj; + } + } + + function replaceRange(doc, code, from, to, origin) { + if (!to) to = from; + if (posLess(to, from)) { var tmp = to; to = from; from = tmp; } + if (typeof code == "string") code = splitLines(code); + makeChange(doc, {from: from, to: to, text: code, origin: origin}, null); + } + + // POSITION OBJECT + + function Pos(line, ch) { + if (!(this instanceof Pos)) return new Pos(line, ch); + this.line = line; this.ch = ch; + } + CodeMirror.Pos = Pos; + + function posEq(a, b) {return a.line == b.line && a.ch == b.ch;} + function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);} + function copyPos(x) {return Pos(x.line, x.ch);} + + // SELECTION + + function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));} + function clipPos(doc, pos) { + if (pos.line < doc.first) return Pos(doc.first, 0); + var last = doc.first + doc.size - 1; + if (pos.line > last) return Pos(last, getLine(doc, last).text.length); + var ch = pos.ch, linelen = getLine(doc, pos.line).text.length; + if (ch == null || ch > linelen) return Pos(pos.line, linelen); + else if (ch < 0) return Pos(pos.line, 0); + else return pos; + } + function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;} + + // If shift is held, this will move the selection anchor. Otherwise, + // it'll set the whole selection. + function extendSelection(doc, pos, other, bias) { + if (doc.sel.shift || doc.sel.extend) { + var anchor = doc.sel.anchor; + if (other) { + var posBefore = posLess(pos, anchor); + if (posBefore != posLess(other, anchor)) { + anchor = pos; + pos = other; + } else if (posBefore != posLess(pos, other)) { + pos = other; + } + } + setSelection(doc, anchor, pos, bias); + } else { + setSelection(doc, pos, other || pos, bias); + } + if (doc.cm) doc.cm.curOp.userSelChange = true; + } + + // Update the selection. Last two args are only used by + // updateDoc, since they have to be expressed in the line + // numbers before the update. + function setSelection(doc, anchor, head, bias, checkAtomic) { + var sel = doc.sel; + sel.goalColumn = null; + // Skip over atomic spans. + if (checkAtomic || !posEq(anchor, sel.anchor)) + anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push"); + if (checkAtomic || !posEq(head, sel.head)) + head = skipAtomic(doc, head, bias, checkAtomic != "push"); + + if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return; + + sel.anchor = anchor; sel.head = head; + var inv = posLess(head, anchor); + sel.from = inv ? head : anchor; + sel.to = inv ? anchor : head; + + if (doc.cm) + doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true; + } + + function reCheckSelection(cm) { + setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push"); + } + + function skipAtomic(doc, pos, bias, mayClear) { + var flipped = false, curPos = pos; + var dir = bias || 1; + doc.cantEdit = false; + search: for (;;) { + var line = getLine(doc, curPos.line), toClear; + if (line.markedSpans) { + for (var i = 0; i < line.markedSpans.length; ++i) { + var sp = line.markedSpans[i], m = sp.marker; + if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) && + (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) { + if (mayClear && m.clearOnEnter) { + (toClear || (toClear = [])).push(m); + continue; + } else if (!m.atomic) continue; + var newPos = m.find()[dir < 0 ? "from" : "to"]; + if (posEq(newPos, curPos)) { + newPos.ch += dir; + if (newPos.ch < 0) { + if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1)); + else newPos = null; + } else if (newPos.ch > line.text.length) { + if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0); + else newPos = null; + } + if (!newPos) { + if (flipped) { + // Driven in a corner -- no valid cursor position found at all + // -- try again *with* clearing, if we didn't already + if (!mayClear) return skipAtomic(doc, pos, bias, true); + // Otherwise, turn off editing until further notice, and return the start of the doc + doc.cantEdit = true; + return Pos(doc.first, 0); + } + flipped = true; newPos = pos; dir = -dir; + } + } + curPos = newPos; + continue search; + } + } + if (toClear) for (var i = 0; i < toClear.length; ++i) toClear[i].clear(); + } + return curPos; + } + } + + // SCROLLING + + function scrollCursorIntoView(cm) { + var coords = scrollPosIntoView(cm, cm.doc.sel.head); + if (!cm.state.focused) return; + var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; + if (coords.top + box.top < 0) doScroll = true; + else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; + if (doScroll != null && !phantom) { + var hidden = display.cursor.style.display == "none"; + if (hidden) { + display.cursor.style.display = ""; + display.cursor.style.left = coords.left + "px"; + display.cursor.style.top = (coords.top - display.viewOffset) + "px"; + } + display.cursor.scrollIntoView(doScroll); + if (hidden) display.cursor.style.display = "none"; + } + } + + function scrollPosIntoView(cm, pos) { + for (;;) { + var changed = false, coords = cursorCoords(cm, pos); + var scrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom); + var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; + if (scrollPos.scrollTop != null) { + setScrollTop(cm, scrollPos.scrollTop); + if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true; + } + if (scrollPos.scrollLeft != null) { + setScrollLeft(cm, scrollPos.scrollLeft); + if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true; + } + if (!changed) return coords; + } + } + + function scrollIntoView(cm, x1, y1, x2, y2) { + var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2); + if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop); + if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft); + } + + function calculateScrollPos(cm, x1, y1, x2, y2) { + var display = cm.display, pt = paddingTop(display); + y1 += pt; y2 += pt; + var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {}; + var docBottom = cm.doc.height + 2 * pt; + var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10; + if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1); + else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen; + + var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft; + x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth; + var gutterw = display.gutters.offsetWidth; + var atLeft = x1 < gutterw + 10; + if (x1 < screenleft + gutterw || atLeft) { + if (atLeft) x1 = 0; + result.scrollLeft = Math.max(0, x1 - 10 - gutterw); + } else if (x2 > screenw + screenleft - 3) { + result.scrollLeft = x2 + 10 - screenw; + } + return result; + } + + // API UTILITIES + + function indentLine(cm, n, how, aggressive) { + var doc = cm.doc; + if (!how) how = "add"; + if (how == "smart") { + if (!cm.doc.mode.indent) how = "prev"; + else var state = getStateBefore(cm, n); + } + + var tabSize = cm.options.tabSize; + var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); + var curSpaceString = line.text.match(/^\s*/)[0], indentation; + if (how == "smart") { + indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); + if (indentation == Pass) { + if (!aggressive) return; + how = "prev"; + } + } + if (how == "prev") { + if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize); + else indentation = 0; + } else if (how == "add") { + indentation = curSpace + cm.options.indentUnit; + } else if (how == "subtract") { + indentation = curSpace - cm.options.indentUnit; + } + indentation = Math.max(0, indentation); + + var indentString = "", pos = 0; + if (cm.options.indentWithTabs) + for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} + if (pos < indentation) indentString += spaceStr(indentation - pos); + + if (indentString != curSpaceString) + replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); + line.stateAfter = null; + } + + function changeLine(cm, handle, op) { + var no = handle, line = handle, doc = cm.doc; + if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle)); + else no = lineNo(handle); + if (no == null) return null; + if (op(line, no)) regChange(cm, no, no + 1); + else return null; + return line; + } + + function findPosH(doc, dir, unit, visually) { + var end = doc.sel.head, line = end.line, ch = end.ch; + var lineObj = getLine(doc, line); + function findNextLine() { + var l = line + dir; + if (l < doc.first || l >= doc.first + doc.size) return false; + line = l; + return lineObj = getLine(doc, l); + } + function moveOnce(boundToLine) { + var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true); + if (next == null) { + if (!boundToLine && findNextLine()) { + if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj); + else ch = dir < 0 ? lineObj.text.length : 0; + } else return false; + } else ch = next; + return true; + } + if (unit == "char") moveOnce(); + else if (unit == "column") moveOnce(true); + else if (unit == "word") { + var sawWord = false; + for (;;) { + if (dir < 0) if (!moveOnce()) break; + if (isWordChar(lineObj.text.charAt(ch))) sawWord = true; + else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;} + if (dir > 0) if (!moveOnce()) break; + } + } + return skipAtomic(doc, Pos(line, ch), dir, true); + } + + function findWordAt(line, pos) { + var start = pos.ch, end = pos.ch; + if (line) { + if (pos.after === false || end == line.length) --start; else ++end; + var startChar = line.charAt(start); + var check = isWordChar(startChar) ? isWordChar : + /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} : + function(ch) {return !/\s/.test(ch) && !isWordChar(ch);}; + while (start > 0 && check(line.charAt(start - 1))) --start; + while (end < line.length && check(line.charAt(end))) ++end; + } + return {from: Pos(pos.line, start), to: Pos(pos.line, end)}; + } + + function selectLine(cm, line) { + extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0))); + } + + // PROTOTYPE + + // The publicly visible API. Note that operation(null, f) means + // 'wrap f in an operation, performed on its `this` parameter' + + CodeMirror.prototype = { + focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);}, + + setOption: function(option, value) { + var options = this.options, old = options[option]; + if (options[option] == value && option != "mode") return; + options[option] = value; + if (optionHandlers.hasOwnProperty(option)) + operation(this, optionHandlers[option])(this, value, old); + }, + + getOption: function(option) {return this.options[option];}, + getDoc: function() {return this.doc;}, + + addKeyMap: function(map) { + this.state.keyMaps.push(map); + }, + removeKeyMap: function(map) { + var maps = this.state.keyMaps; + for (var i = 0; i < maps.length; ++i) + if ((typeof map == "string" ? maps[i].name : maps[i]) == map) { + maps.splice(i, 1); + return true; + } + }, + + addOverlay: operation(null, function(spec, options) { + var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); + if (mode.startState) throw new Error("Overlays may not be stateful."); + this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque}); + this.state.modeGen++; + regChange(this); + }), + removeOverlay: operation(null, function(spec) { + var overlays = this.state.overlays; + for (var i = 0; i < overlays.length; ++i) { + if (overlays[i].modeSpec == spec) { + overlays.splice(i, 1); + this.state.modeGen++; + regChange(this); + return; + } + } + }), + + indentLine: operation(null, function(n, dir, aggressive) { + if (typeof dir != "string") { + if (dir == null) dir = this.options.smartIndent ? "smart" : "prev"; + else dir = dir ? "add" : "subtract"; + } + if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive); + }), + indentSelection: operation(null, function(how) { + var sel = this.doc.sel; + if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how); + var e = sel.to.line - (sel.to.ch ? 0 : 1); + for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how); + }), + + // Fetch the parser token for a given character. Useful for hacks + // that want to inspect the mode state (say, for completion). + getTokenAt: function(pos) { + var doc = this.doc; + pos = clipPos(doc, pos); + var state = getStateBefore(this, pos.line), mode = this.doc.mode; + var line = getLine(doc, pos.line); + var stream = new StringStream(line.text, this.options.tabSize); + while (stream.pos < pos.ch && !stream.eol()) { + stream.start = stream.pos; + var style = mode.token(stream, state); + } + return {start: stream.start, + end: stream.pos, + string: stream.current(), + className: style || null, // Deprecated, use 'type' instead + type: style || null, + state: state}; + }, + + getStateAfter: function(line) { + var doc = this.doc; + line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); + return getStateBefore(this, line + 1); + }, + + cursorCoords: function(start, mode) { + var pos, sel = this.doc.sel; + if (start == null) pos = sel.head; + else if (typeof start == "object") pos = clipPos(this.doc, start); + else pos = start ? sel.from : sel.to; + return cursorCoords(this, pos, mode || "page"); + }, + + charCoords: function(pos, mode) { + return charCoords(this, clipPos(this.doc, pos), mode || "page"); + }, + + coordsChar: function(coords) { + var off = this.display.lineSpace.getBoundingClientRect(); + var scrollY = window.pageYOffset || (document.documentElement || document.body).scrollTop; + var scrollX = window.pageXOffset || (document.documentElement || document.body).scrollLeft; + return coordsChar(this, coords.left - off.left - scrollX, coords.top - off.top - scrollY); + }, + + defaultTextHeight: function() { return textHeight(this.display); }, + + setGutterMarker: operation(null, function(line, gutterID, value) { + return changeLine(this, line, function(line) { + var markers = line.gutterMarkers || (line.gutterMarkers = {}); + markers[gutterID] = value; + if (!value && isEmpty(markers)) line.gutterMarkers = null; + return true; + }); + }), + + clearGutter: operation(null, function(gutterID) { + var cm = this, doc = cm.doc, i = doc.first; + doc.iter(function(line) { + if (line.gutterMarkers && line.gutterMarkers[gutterID]) { + line.gutterMarkers[gutterID] = null; + regChange(cm, i, i + 1); + if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null; + } + ++i; + }); + }), + + addLineClass: operation(null, function(handle, where, cls) { + return changeLine(this, handle, function(line) { + var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass"; + if (!line[prop]) line[prop] = cls; + else if (new RegExp("\\b" + cls + "\\b").test(line[prop])) return false; + else line[prop] += " " + cls; + return true; + }); + }), + + removeLineClass: operation(null, function(handle, where, cls) { + return changeLine(this, handle, function(line) { + var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass"; + var cur = line[prop]; + if (!cur) return false; + else if (cls == null) line[prop] = null; + else { + var upd = cur.replace(new RegExp("^" + cls + "\\b\\s*|\\s*\\b" + cls + "\\b"), ""); + if (upd == cur) return false; + line[prop] = upd || null; + } + return true; + }); + }), + + addLineWidget: operation(null, function(handle, node, options) { + return addLineWidget(this, handle, node, options); + }), + + removeLineWidget: function(widget) { widget.clear(); }, + + lineInfo: function(line) { + if (typeof line == "number") { + if (!isLine(this.doc, line)) return null; + var n = line; + line = getLine(this.doc, line); + if (!line) return null; + } else { + var n = lineNo(line); + if (n == null) return null; + } + return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, + textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, + widgets: line.widgets}; + }, + + getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};}, + + addWidget: function(pos, node, scroll, vert, horiz) { + var display = this.display; + pos = cursorCoords(this, clipPos(this.doc, pos)); + var top = pos.bottom, left = pos.left; + node.style.position = "absolute"; + display.sizer.appendChild(node); + if (vert == "over") { + top = pos.top; + } else if (vert == "above" || vert == "near") { + var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), + hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); + // Default to positioning above (if specified and possible); otherwise default to positioning below + if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) + top = pos.top - node.offsetHeight; + else if (pos.bottom + node.offsetHeight <= vspace) + top = pos.bottom; + if (left + node.offsetWidth > hspace) + left = hspace - node.offsetWidth; + } + node.style.top = (top + paddingTop(display)) + "px"; + node.style.left = node.style.right = ""; + if (horiz == "right") { + left = display.sizer.clientWidth - node.offsetWidth; + node.style.right = "0px"; + } else { + if (horiz == "left") left = 0; + else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2; + node.style.left = left + "px"; + } + if (scroll) + scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight); + }, + + triggerOnKeyDown: operation(null, onKeyDown), + + execCommand: function(cmd) {return commands[cmd](this);}, + + // Stuff used by commands, probably not much use to outside code. + moveH: operation(null, function(dir, unit) { + var sel = this.doc.sel, pos = dir < 0 ? sel.from : sel.to; + if (sel.shift || sel.extend || posEq(sel.from, sel.to)) + pos = findPosH(this.doc, dir, unit, this.options.rtlMoveVisually); + extendSelection(this.doc, pos, pos, dir); + }), + + deleteH: operation(null, function(dir, unit) { + var sel = this.doc.sel; + if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete"); + else replaceRange(this.doc, "", sel.from, findPosH(this.doc, dir, unit, false), "+delete"); + this.curOp.userSelChange = true; + }), + + moveV: operation(null, function(dir, unit) { + var doc = this.doc, display = this.display; + var cur = doc.sel.head, pos = cursorCoords(this, cur, "div"); + var x = pos.left, y; + if (doc.sel.goalColumn != null) x = doc.sel.goalColumn; + if (unit == "page") { + var pageSize = Math.min(display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); + y = pos.top + dir * pageSize; + } else if (unit == "line") { + y = dir > 0 ? pos.bottom + 3 : pos.top - 3; + } + do { + var target = coordsChar(this, x, y); + y += dir * 5; + } while (target.outside && (dir < 0 ? y > 0 : y < doc.height)); + + if (unit == "page") display.scrollbarV.scrollTop += charCoords(this, target, "div").top - pos.top; + extendSelection(this.doc, target, target, dir); + doc.sel.goalColumn = x; + }), + + toggleOverwrite: function() { + if (this.state.overwrite = !this.state.overwrite) + this.display.cursor.className += " CodeMirror-overwrite"; + else + this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", ""); + }, + + scrollTo: operation(null, function(x, y) { + this.curOp.updateScrollPos = {scrollLeft: x, scrollTop: y}; + }), + getScrollInfo: function() { + var scroller = this.display.scroller, co = scrollerCutOff; + return {left: scroller.scrollLeft, top: scroller.scrollTop, + height: scroller.scrollHeight - co, width: scroller.scrollWidth - co, + clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co}; + }, + + scrollIntoView: function(pos) { + if (typeof pos == "number") pos = Pos(pos, 0); + if (!pos || pos.line != null) { + pos = pos ? clipPos(this.doc, pos) : this.doc.sel.head; + scrollPosIntoView(this, pos); + } else { + scrollIntoView(this, pos.left, pos.top, pos.right, pos.bottom); + } + }, + + setSize: function(width, height) { + function interpret(val) { + return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; + } + if (width != null) this.display.wrapper.style.width = interpret(width); + if (height != null) this.display.wrapper.style.height = interpret(height); + this.refresh(); + }, + + on: function(type, f) {on(this, type, f);}, + off: function(type, f) {off(this, type, f);}, + + operation: function(f){return runInOp(this, f);}, + + refresh: operation(null, function() { + clearCaches(this); + this.curOp.updateScrollPos = {scrollTop: this.doc.scrollTop, scrollLeft: this.doc.scrollLeft}; + regChange(this); + }), + + swapDoc: operation(null, function(doc) { + var old = this.doc; + old.cm = null; + attachDoc(this, doc); + clearCaches(this); + this.curOp.updateScrollPos = {scrollTop: doc.scrollTop, scrollLeft: doc.scrollLeft}; + return old; + }), + + getInputField: function(){return this.display.input;}, + getWrapperElement: function(){return this.display.wrapper;}, + getScrollerElement: function(){return this.display.scroller;}, + getGutterElement: function(){return this.display.gutters;} + }; + + // OPTION DEFAULTS + + var optionHandlers = CodeMirror.optionHandlers = {}; + + // The default configuration options. + var defaults = CodeMirror.defaults = {}; + + function option(name, deflt, handle, notOnInit) { + CodeMirror.defaults[name] = deflt; + if (handle) optionHandlers[name] = + notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle; + } + + var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}}; + + // These two are, on init, called from the constructor because they + // have to be initialized before the editor can start at all. + option("value", "", function(cm, val) { + cm.setValue(val); + }, true); + option("mode", null, function(cm, val) { + cm.doc.modeOption = val; + loadMode(cm); + }, true); + + option("indentUnit", 2, loadMode, true); + option("indentWithTabs", false); + option("smartIndent", true); + option("tabSize", 4, function(cm) { + loadMode(cm); + clearCaches(cm); + regChange(cm); + }, true); + option("electricChars", true); + option("rtlMoveVisually", !windows); + + option("theme", "default", function(cm) { + themeChanged(cm); + guttersChanged(cm); + }, true); + option("keyMap", "default", keyMapChanged); + option("extraKeys", null); + + option("onKeyEvent", null); + option("onDragEvent", null); + + option("lineWrapping", false, wrappingChanged, true); + option("gutters", [], function(cm) { + setGuttersForLineNumbers(cm.options); + guttersChanged(cm); + }, true); + option("fixedGutter", true, function(cm, val) { + cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; + cm.refresh(); + }, true); + option("lineNumbers", false, function(cm) { + setGuttersForLineNumbers(cm.options); + guttersChanged(cm); + }, true); + option("firstLineNumber", 1, guttersChanged, true); + option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true); + option("showCursorWhenSelecting", false, updateSelection, true); + + option("readOnly", false, function(cm, val) { + if (val == "nocursor") {onBlur(cm); cm.display.input.blur();} + else if (!val) resetInput(cm, true); + }); + option("dragDrop", true); + + option("cursorBlinkRate", 530); + option("cursorHeight", 1); + option("workTime", 100); + option("workDelay", 100); + option("flattenSpans", true); + option("pollInterval", 100); + option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;}); + option("viewportMargin", 10, function(cm){cm.refresh();}, true); + + option("tabindex", null, function(cm, val) { + cm.display.input.tabIndex = val || ""; + }); + option("autofocus", null); + + // MODE DEFINITION AND QUERYING + + // Known modes, by name and by MIME + var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; + + CodeMirror.defineMode = function(name, mode) { + if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; + if (arguments.length > 2) { + mode.dependencies = []; + for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]); + } + modes[name] = mode; + }; + + CodeMirror.defineMIME = function(mime, spec) { + mimeModes[mime] = spec; + }; + + CodeMirror.resolveMode = function(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) + spec = mimeModes[spec]; + else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) + return CodeMirror.resolveMode("application/xml"); + if (typeof spec == "string") return {name: spec}; + else return spec || {name: "null"}; + }; + + CodeMirror.getMode = function(options, spec) { + spec = CodeMirror.resolveMode(spec); + var mfactory = modes[spec.name]; + if (!mfactory) return CodeMirror.getMode(options, "text/plain"); + var modeObj = mfactory(options, spec); + if (modeExtensions.hasOwnProperty(spec.name)) { + var exts = modeExtensions[spec.name]; + for (var prop in exts) { + if (!exts.hasOwnProperty(prop)) continue; + if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop]; + modeObj[prop] = exts[prop]; + } + } + modeObj.name = spec.name; + return modeObj; + }; + + CodeMirror.defineMode("null", function() { + return {token: function(stream) {stream.skipToEnd();}}; + }); + CodeMirror.defineMIME("text/plain", "null"); + + var modeExtensions = CodeMirror.modeExtensions = {}; + CodeMirror.extendMode = function(mode, properties) { + var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); + copyObj(properties, exts); + }; + + // EXTENSIONS + + CodeMirror.defineExtension = function(name, func) { + CodeMirror.prototype[name] = func; + }; + + CodeMirror.defineOption = option; + + var initHooks = []; + CodeMirror.defineInitHook = function(f) {initHooks.push(f);}; + + // MODE STATE HANDLING + + // Utility functions for working with state. Exported because modes + // sometimes need to do this. + function copyState(mode, state) { + if (state === true) return state; + if (mode.copyState) return mode.copyState(state); + var nstate = {}; + for (var n in state) { + var val = state[n]; + if (val instanceof Array) val = val.concat([]); + nstate[n] = val; + } + return nstate; + } + CodeMirror.copyState = copyState; + + function startState(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true; + } + CodeMirror.startState = startState; + + CodeMirror.innerMode = function(mode, state) { + while (mode.innerMode) { + var info = mode.innerMode(state); + state = info.state; + mode = info.mode; + } + return info || {mode: mode, state: state}; + }; + + // STANDARD COMMANDS + + var commands = CodeMirror.commands = { + selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));}, + killLine: function(cm) { + var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to); + if (!sel && cm.getLine(from.line).length == from.ch) + cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete"); + else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete"); + }, + deleteLine: function(cm) { + var l = cm.getCursor().line; + cm.replaceRange("", Pos(l, 0), Pos(l), "+delete"); + }, + undo: function(cm) {cm.undo();}, + redo: function(cm) {cm.redo();}, + goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));}, + goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));}, + goLineStart: function(cm) { + cm.extendSelection(lineStart(cm, cm.getCursor().line)); + }, + goLineStartSmart: function(cm) { + var cur = cm.getCursor(), start = lineStart(cm, cur.line); + var line = cm.getLineHandle(start.line); + var order = getOrder(line); + if (!order || order[0].level == 0) { + var firstNonWS = Math.max(0, line.text.search(/\S/)); + var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch; + cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS)); + } else cm.extendSelection(start); + }, + goLineEnd: function(cm) { + cm.extendSelection(lineEnd(cm, cm.getCursor().line)); + }, + goLineUp: function(cm) {cm.moveV(-1, "line");}, + goLineDown: function(cm) {cm.moveV(1, "line");}, + goPageUp: function(cm) {cm.moveV(-1, "page");}, + goPageDown: function(cm) {cm.moveV(1, "page");}, + goCharLeft: function(cm) {cm.moveH(-1, "char");}, + goCharRight: function(cm) {cm.moveH(1, "char");}, + goColumnLeft: function(cm) {cm.moveH(-1, "column");}, + goColumnRight: function(cm) {cm.moveH(1, "column");}, + goWordLeft: function(cm) {cm.moveH(-1, "word");}, + goWordRight: function(cm) {cm.moveH(1, "word");}, + delCharBefore: function(cm) {cm.deleteH(-1, "char");}, + delCharAfter: function(cm) {cm.deleteH(1, "char");}, + delWordBefore: function(cm) {cm.deleteH(-1, "word");}, + delWordAfter: function(cm) {cm.deleteH(1, "word");}, + indentAuto: function(cm) {cm.indentSelection("smart");}, + indentMore: function(cm) {cm.indentSelection("add");}, + indentLess: function(cm) {cm.indentSelection("subtract");}, + insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");}, + defaultTab: function(cm) { + if (cm.somethingSelected()) cm.indentSelection("add"); + else cm.replaceSelection("\t", "end", "+input"); + }, + transposeChars: function(cm) { + var cur = cm.getCursor(), line = cm.getLine(cur.line); + if (cur.ch > 0 && cur.ch < line.length - 1) + cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1), + Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1)); + }, + newlineAndIndent: function(cm) { + operation(cm, function() { + cm.replaceSelection("\n", "end", "+input"); + cm.indentLine(cm.getCursor().line, null, true); + })(); + }, + toggleOverwrite: function(cm) {cm.toggleOverwrite();} + }; + + // STANDARD KEYMAPS + + var keyMap = CodeMirror.keyMap = {}; + keyMap.basic = { + "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", + "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", + "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto", + "Enter": "newlineAndIndent", "Insert": "toggleOverwrite" + }; + // Note that the save and find-related commands aren't defined by + // default. Unknown commands are simply ignored. + keyMap.pcDefault = { + "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", + "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd", + "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", + "Ctrl-Backspace": "delWordBefore", "Ctrl-Delete": "delWordAfter", "Ctrl-S": "save", "Ctrl-F": "find", + "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", + "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", + fallthrough: "basic" + }; + keyMap.macDefault = { + "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", + "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft", + "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordBefore", + "Ctrl-Alt-Backspace": "delWordAfter", "Alt-Delete": "delWordAfter", "Cmd-S": "save", "Cmd-F": "find", + "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", + "Cmd-[": "indentLess", "Cmd-]": "indentMore", + fallthrough: ["basic", "emacsy"] + }; + keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; + keyMap.emacsy = { + "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", + "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", + "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", + "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars" + }; + + // KEYMAP DISPATCH + + function getKeyMap(val) { + if (typeof val == "string") return keyMap[val]; + else return val; + } + + function lookupKey(name, maps, handle) { + function lookup(map) { + map = getKeyMap(map); + var found = map[name]; + if (found === false) return "stop"; + if (found != null) { + try { var done = handle(found); } + catch (e) { if (e != Pass) throw e; } + if (done) return true; + } + if (map.nofallthrough) return "stop"; + + var fallthrough = map.fallthrough; + if (fallthrough == null) return false; + if (Object.prototype.toString.call(fallthrough) != "[object Array]") + return lookup(fallthrough); + for (var i = 0, e = fallthrough.length; i < e; ++i) { + var done = lookup(fallthrough[i]); + if (done) return done; + } + return false; + } + + for (var i = 0; i < maps.length; ++i) { + var done = lookup(maps[i]); + if (done) return done; + } + } + function isModifierKey(event) { + var name = keyNames[e_prop(event, "keyCode")]; + return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; + } + function keyName(event, noShift) { + var name = keyNames[e_prop(event, "keyCode")]; + if (name == null || event.altGraphKey) return false; + if (e_prop(event, "altKey")) name = "Alt-" + name; + if (e_prop(event, flipCtrlCmd ? "metaKey" : "ctrlKey")) name = "Ctrl-" + name; + if (e_prop(event, flipCtrlCmd ? "ctrlKey" : "metaKey")) name = "Cmd-" + name; + if (!noShift && e_prop(event, "shiftKey")) name = "Shift-" + name; + return name; + } + CodeMirror.lookupKey = lookupKey; + CodeMirror.isModifierKey = isModifierKey; + CodeMirror.keyName = keyName; + + // FROMTEXTAREA + + CodeMirror.fromTextArea = function(textarea, options) { + if (!options) options = {}; + options.value = textarea.value; + if (!options.tabindex && textarea.tabindex) + options.tabindex = textarea.tabindex; + // Set autofocus to true if this textarea is focused, or if it has + // autofocus and no other element is focused. + if (options.autofocus == null) { + var hasFocus = document.body; + // doc.activeElement occasionally throws on IE + try { hasFocus = document.activeElement; } catch(e) {} + options.autofocus = hasFocus == textarea || + textarea.getAttribute("autofocus") != null && hasFocus == document.body; + } + + function save() {textarea.value = cm.getValue();} + if (textarea.form) { + // Deplorable hack to make the submit method do the right thing. + on(textarea.form, "submit", save); + var form = textarea.form, realSubmit = form.submit; + try { + var wrappedSubmit = form.submit = function() { + save(); + form.submit = realSubmit; + form.submit(); + form.submit = wrappedSubmit; + }; + } catch(e) {} + } + + textarea.style.display = "none"; + var cm = CodeMirror(function(node) { + textarea.parentNode.insertBefore(node, textarea.nextSibling); + }, options); + cm.save = save; + cm.getTextArea = function() { return textarea; }; + cm.toTextArea = function() { + save(); + textarea.parentNode.removeChild(cm.getWrapperElement()); + textarea.style.display = ""; + if (textarea.form) { + off(textarea.form, "submit", save); + if (typeof textarea.form.submit == "function") + textarea.form.submit = realSubmit; + } + }; + return cm; + }; + + // STRING STREAM + + // Fed to the mode parsers, provides helper functions to make + // parsers more succinct. + + // The character stream used by a mode's parser. + function StringStream(string, tabSize) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + } + + StringStream.prototype = { + eol: function() {return this.pos >= this.string.length;}, + sol: function() {return this.pos == 0;}, + peek: function() {return this.string.charAt(this.pos) || undefined;}, + next: function() { + if (this.pos < this.string.length) + return this.string.charAt(this.pos++); + }, + eat: function(match) { + var ch = this.string.charAt(this.pos); + if (typeof match == "string") var ok = ch == match; + else var ok = ch && (match.test ? match.test(ch) : match(ch)); + if (ok) {++this.pos; return ch;} + }, + eatWhile: function(match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start; + }, + eatSpace: function() { + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; + return this.pos > start; + }, + skipToEnd: function() {this.pos = this.string.length;}, + skipTo: function(ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true;} + }, + backUp: function(n) {this.pos -= n;}, + column: function() {return countColumn(this.string, this.start, this.tabSize);}, + indentation: function() {return countColumn(this.string, null, this.tabSize);}, + match: function(pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; + if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) { + if (consume !== false) this.pos += pattern.length; + return true; + } + } else { + var match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) return null; + if (match && consume !== false) this.pos += match[0].length; + return match; + } + }, + current: function(){return this.string.slice(this.start, this.pos);} + }; + CodeMirror.StringStream = StringStream; + + // TEXTMARKERS + + function TextMarker(doc, type) { + this.lines = []; + this.type = type; + this.doc = doc; + } + CodeMirror.TextMarker = TextMarker; + + TextMarker.prototype.clear = function() { + if (this.explicitlyCleared) return; + var cm = this.doc.cm, withOp = cm && !cm.curOp; + if (withOp) startOperation(cm); + var min = null, max = null; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (span.to != null) max = lineNo(line); + line.markedSpans = removeMarkedSpan(line.markedSpans, span); + if (span.from != null) + min = lineNo(line); + else if (this.collapsed && !lineIsHidden(this.doc, line) && cm) + updateLineHeight(line, textHeight(cm.display)); + } + if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) { + var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual); + if (len > cm.display.maxLineLength) { + cm.display.maxLine = visual; + cm.display.maxLineLength = len; + cm.display.maxLineChanged = true; + } + } + + if (min != null && cm) regChange(cm, min, max + 1); + this.lines.length = 0; + this.explicitlyCleared = true; + if (this.collapsed && this.doc.cantEdit) { + this.doc.cantEdit = false; + if (cm) reCheckSelection(cm); + } + if (withOp) endOperation(cm); + signalLater(this, "clear"); + }; + + TextMarker.prototype.find = function() { + var from, to; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (span.from != null || span.to != null) { + var found = lineNo(line); + if (span.from != null) from = Pos(found, span.from); + if (span.to != null) to = Pos(found, span.to); + } + } + if (this.type == "bookmark") return from; + return from && {from: from, to: to}; + }; + + TextMarker.prototype.getOptions = function(copyWidget) { + var repl = this.replacedWith; + return {className: this.className, + inclusiveLeft: this.inclusiveLeft, inclusiveRight: this.inclusiveRight, + atomic: this.atomic, + collapsed: this.collapsed, + clearOnEnter: this.clearOnEnter, + replacedWith: copyWidget ? repl && repl.cloneNode(true) : repl, + readOnly: this.readOnly, + startStyle: this.startStyle, endStyle: this.endStyle}; + }; + + TextMarker.prototype.attachLine = function(line) { + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp; + if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) + (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); + } + this.lines.push(line); + }; + TextMarker.prototype.detachLine = function(line) { + this.lines.splice(indexOf(this.lines, line), 1); + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp; + (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); + } + }; + + function markText(doc, from, to, options, type) { + if (options && options.shared) return markTextShared(doc, from, to, options, type); + if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type); + + var marker = new TextMarker(doc, type); + if (type == "range" && !posLess(from, to)) return marker; + if (options) copyObj(options, marker); + if (marker.replacedWith) { + marker.collapsed = true; + marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget"); + } + if (marker.collapsed) sawCollapsedSpans = true; + + var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine; + doc.iter(curLine, to.line + 1, function(line) { + if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine) + updateMaxLine = true; + var span = {from: null, to: null, marker: marker}; + size += line.text.length; + if (curLine == from.line) {span.from = from.ch; size -= from.ch;} + if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;} + if (marker.collapsed) { + if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch); + if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch); + else updateLineHeight(line, 0); + } + addMarkedSpan(line, span); + ++curLine; + }); + if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) { + if (lineIsHidden(doc, line)) updateLineHeight(line, 0); + }); + + if (marker.readOnly) { + sawReadOnlySpans = true; + if (doc.history.done.length || doc.history.undone.length) + doc.clearHistory(); + } + if (marker.collapsed) { + if (collapsedAtStart != collapsedAtEnd) + throw new Error("Inserting collapsed marker overlapping an existing one"); + marker.size = size; + marker.atomic = true; + } + if (cm) { + if (updateMaxLine) cm.curOp.updateMaxLine = true; + if (marker.className || marker.startStyle || marker.endStyle || marker.collapsed) + regChange(cm, from.line, to.line + 1); + if (marker.atomic) reCheckSelection(cm); + } + return marker; + } + + // SHARED TEXTMARKERS + + function SharedTextMarker(markers, primary) { + this.markers = markers; + this.primary = primary; + for (var i = 0, me = this; i < markers.length; ++i) { + markers[i].parent = this; + on(markers[i], "clear", function(){me.clear();}); + } + } + CodeMirror.SharedTextMarker = SharedTextMarker; + + SharedTextMarker.prototype.clear = function() { + if (this.explicitlyCleared) return; + this.explicitlyCleared = true; + for (var i = 0; i < this.markers.length; ++i) + this.markers[i].clear(); + signalLater(this, "clear"); + }; + SharedTextMarker.prototype.find = function() { + return this.primary.find(); + }; + SharedTextMarker.prototype.getOptions = function(copyWidget) { + var inner = this.primary.getOptions(copyWidget); + inner.shared = true; + return inner; + }; + + function markTextShared(doc, from, to, options, type) { + options = copyObj(options); + options.shared = false; + var markers = [markText(doc, from, to, options, type)], primary = markers[0]; + linkedDocs(doc, function(doc) { + markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); + for (var i = 0; i < doc.linked.length; ++i) + if (doc.linked[i].isParent) return; + primary = lst(markers); + }); + return new SharedTextMarker(markers, primary); + } + + // TEXTMARKER SPANS + + function getMarkedSpanFor(spans, marker) { + if (spans) for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.marker == marker) return span; + } + } + function removeMarkedSpan(spans, span) { + for (var r, i = 0; i < spans.length; ++i) + if (spans[i] != span) (r || (r = [])).push(spans[i]); + return r; + } + function addMarkedSpan(line, span) { + line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; + span.marker.attachLine(line); + } + + function markedSpansBefore(old, startCh, isInsert) { + if (old) for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); + if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) { + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); + (nw || (nw = [])).push({from: span.from, + to: endsAfter ? null : span.to, + marker: marker}); + } + } + return nw; + } + + function markedSpansAfter(old, endCh, isInsert) { + if (old) for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); + if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) { + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); + (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh, + to: span.to == null ? null : span.to - endCh, + marker: marker}); + } + } + return nw; + } + + function stretchSpansOverChange(doc, change) { + var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; + var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; + if (!oldFirst && !oldLast) return null; + + var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to); + // Get the spans that 'stick out' on both sides + var first = markedSpansBefore(oldFirst, startCh, isInsert); + var last = markedSpansAfter(oldLast, endCh, isInsert); + + // Next, merge those two ends + var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); + if (first) { + // Fix up .to properties of first + for (var i = 0; i < first.length; ++i) { + var span = first[i]; + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker); + if (!found) span.to = startCh; + else if (sameLine) span.to = found.to == null ? null : found.to + offset; + } + } + } + if (last) { + // Fix up .from in last (or move them into first in case of sameLine) + for (var i = 0; i < last.length; ++i) { + var span = last[i]; + if (span.to != null) span.to += offset; + if (span.from == null) { + var found = getMarkedSpanFor(first, span.marker); + if (!found) { + span.from = offset; + if (sameLine) (first || (first = [])).push(span); + } + } else { + span.from += offset; + if (sameLine) (first || (first = [])).push(span); + } + } + } + + var newMarkers = [first]; + if (!sameLine) { + // Fill gap with whole-line-spans + var gap = change.text.length - 2, gapMarkers; + if (gap > 0 && first) + for (var i = 0; i < first.length; ++i) + if (first[i].to == null) + (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker}); + for (var i = 0; i < gap; ++i) + newMarkers.push(gapMarkers); + newMarkers.push(last); + } + return newMarkers; + } + + function mergeOldSpans(doc, change) { + var old = getOldSpans(doc, change); + var stretched = stretchSpansOverChange(doc, change); + if (!old) return stretched; + if (!stretched) return old; + + for (var i = 0; i < old.length; ++i) { + var oldCur = old[i], stretchCur = stretched[i]; + if (oldCur && stretchCur) { + spans: for (var j = 0; j < stretchCur.length; ++j) { + var span = stretchCur[j]; + for (var k = 0; k < oldCur.length; ++k) + if (oldCur[k].marker == span.marker) continue spans; + oldCur.push(span); + } + } else if (stretchCur) { + old[i] = stretchCur; + } + } + return old; + } + + function removeReadOnlyRanges(doc, from, to) { + var markers = null; + doc.iter(from.line, to.line + 1, function(line) { + if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) { + var mark = line.markedSpans[i].marker; + if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) + (markers || (markers = [])).push(mark); + } + }); + if (!markers) return null; + var parts = [{from: from, to: to}]; + for (var i = 0; i < markers.length; ++i) { + var mk = markers[i], m = mk.find(); + for (var j = 0; j < parts.length; ++j) { + var p = parts[j]; + if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue; + var newParts = [j, 1]; + if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from)) + newParts.push({from: p.from, to: m.from}); + if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to)) + newParts.push({from: m.to, to: p.to}); + parts.splice.apply(parts, newParts); + j += newParts.length - 1; + } + } + return parts; + } + + function collapsedSpanAt(line, ch) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) for (var sp, i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (!sp.marker.collapsed) continue; + if ((sp.from == null || sp.from < ch) && + (sp.to == null || sp.to > ch) && + (!found || found.width < sp.marker.width)) + found = sp.marker; + } + return found; + } + function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); } + function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); } + + function visualLine(doc, line) { + var merged; + while (merged = collapsedSpanAtStart(line)) + line = getLine(doc, merged.find().from.line); + return line; + } + + function lineIsHidden(doc, line) { + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) for (var sp, i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (!sp.marker.collapsed) continue; + if (sp.from == null) return true; + if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) + return true; + } + } + function lineIsHiddenInner(doc, line, span) { + if (span.to == null) { + var end = span.marker.find().to, endLine = getLine(doc, end.line); + return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker)); + } + if (span.marker.inclusiveRight && span.to == line.text.length) + return true; + for (var sp, i = 0; i < line.markedSpans.length; ++i) { + sp = line.markedSpans[i]; + if (sp.marker.collapsed && sp.from == span.to && + (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && + lineIsHiddenInner(doc, line, sp)) return true; + } + } + + function detachMarkedSpans(line) { + var spans = line.markedSpans; + if (!spans) return; + for (var i = 0; i < spans.length; ++i) + spans[i].marker.detachLine(line); + line.markedSpans = null; + } + + function attachMarkedSpans(line, spans) { + if (!spans) return; + for (var i = 0; i < spans.length; ++i) + spans[i].marker.attachLine(line); + line.markedSpans = spans; + } + + // LINE WIDGETS + + var LineWidget = CodeMirror.LineWidget = function(cm, node, options) { + for (var opt in options) if (options.hasOwnProperty(opt)) + this[opt] = options[opt]; + this.cm = cm; + this.node = node; + }; + function widgetOperation(f) { + return function() { + var withOp = !this.cm.curOp; + if (withOp) startOperation(this.cm); + try {var result = f.apply(this, arguments);} + finally {if (withOp) endOperation(this.cm);} + return result; + }; + } + LineWidget.prototype.clear = widgetOperation(function() { + var ws = this.line.widgets, no = lineNo(this.line); + if (no == null || !ws) return; + for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1); + if (!ws.length) this.line.widgets = null; + updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this))); + regChange(this.cm, no, no + 1); + }); + LineWidget.prototype.changed = widgetOperation(function() { + var oldH = this.height; + this.height = null; + var diff = widgetHeight(this) - oldH; + if (!diff) return; + updateLineHeight(this.line, this.line.height + diff); + var no = lineNo(this.line); + regChange(this.cm, no, no + 1); + }); + + function widgetHeight(widget) { + if (widget.height != null) return widget.height; + if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1) + removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative")); + return widget.height = widget.node.offsetHeight; + } + + function addLineWidget(cm, handle, node, options) { + var widget = new LineWidget(cm, node, options); + if (widget.noHScroll) cm.display.alignWidgets = true; + changeLine(cm, handle, function(line) { + (line.widgets || (line.widgets = [])).push(widget); + widget.line = line; + if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) { + var aboveVisible = heightAtLine(cm, line) < cm.display.scroller.scrollTop; + updateLineHeight(line, line.height + widgetHeight(widget)); + if (aboveVisible) + cm.curOp.updateScrollPos = {scrollTop: cm.doc.scrollTop + widget.height, + scrollLeft: cm.doc.scrollLeft}; + } + return true; + }); + return widget; + } + + // LINE DATA STRUCTURE + + // Line objects. These hold state related to a line, including + // highlighting info (the styles array). + function makeLine(text, markedSpans, estimateHeight) { + var line = {text: text}; + attachMarkedSpans(line, markedSpans); + line.height = estimateHeight ? estimateHeight(line) : 1; + return line; + } + + function updateLine(line, text, markedSpans, estimateHeight) { + line.text = text; + if (line.stateAfter) line.stateAfter = null; + if (line.styles) line.styles = null; + if (line.order != null) line.order = null; + detachMarkedSpans(line); + attachMarkedSpans(line, markedSpans); + var estHeight = estimateHeight ? estimateHeight(line) : 1; + if (estHeight != line.height) updateLineHeight(line, estHeight); + signalLater(line, "change"); + } + + function cleanUpLine(line) { + line.parent = null; + detachMarkedSpans(line); + } + + // Run the given mode's parser over a line, update the styles + // array, which contains alternating fragments of text and CSS + // classes. + function runMode(cm, text, mode, state, f) { + var flattenSpans = cm.options.flattenSpans; + var curText = "", curStyle = null; + var stream = new StringStream(text, cm.options.tabSize); + if (text == "" && mode.blankLine) mode.blankLine(state); + while (!stream.eol()) { + var style = mode.token(stream, state); + if (stream.pos > 5000) { + flattenSpans = false; + // Webkit seems to refuse to render text nodes longer than 57444 characters + stream.pos = Math.min(text.length, stream.start + 50000); + style = null; + } + var substr = stream.current(); + stream.start = stream.pos; + if (!flattenSpans || curStyle != style) { + if (curText) f(curText, curStyle); + curText = substr; curStyle = style; + } else curText = curText + substr; + } + if (curText) f(curText, curStyle); + } + + function highlightLine(cm, line, state) { + // A styles array always starts with a number identifying the + // mode/overlays that it is based on (for easy invalidation). + var st = [cm.state.modeGen]; + // Compute the base array of styles + runMode(cm, line.text, cm.doc.mode, state, function(txt, style) {st.push(txt, style);}); + + // Run overlays, adjust style array. + for (var o = 0; o < cm.state.overlays.length; ++o) { + var overlay = cm.state.overlays[o], i = 1; + runMode(cm, line.text, overlay.mode, true, function(txt, style) { + var start = i, len = txt.length; + // Ensure there's a token end at the current position, and that i points at it + while (len) { + var cur = st[i], len_ = cur.length; + if (len_ <= len) { + len -= len_; + } else { + st.splice(i, 1, cur.slice(0, len), st[i+1], cur.slice(len)); + len = 0; + } + i += 2; + } + if (!style) return; + if (overlay.opaque) { + st.splice(start, i - start, txt, style); + i = start + 2; + } else { + for (; start < i; start += 2) { + var cur = st[start+1]; + st[start+1] = cur ? cur + " " + style : style; + } + } + }); + } + + return st; + } + + function getLineStyles(cm, line) { + if (!line.styles || line.styles[0] != cm.state.modeGen) + line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line))); + return line.styles; + } + + // Lightweight form of highlight -- proceed over this line and + // update state, but don't save a style array. + function processLine(cm, line, state) { + var mode = cm.doc.mode; + var stream = new StringStream(line.text, cm.options.tabSize); + if (line.text == "" && mode.blankLine) mode.blankLine(state); + while (!stream.eol() && stream.pos <= 5000) { + mode.token(stream, state); + stream.start = stream.pos; + } + } + + var styleToClassCache = {}; + function styleToClass(style) { + if (!style) return null; + return styleToClassCache[style] || + (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-")); + } + + function lineContent(cm, realLine, measure) { + var merged, line = realLine, lineBefore, sawBefore, simple = true; + while (merged = collapsedSpanAtStart(line)) { + simple = false; + line = getLine(cm.doc, merged.find().from.line); + if (!lineBefore) lineBefore = line; + } + + var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure, + measure: null, addedOne: false, cm: cm}; + if (line.textClass) builder.pre.className = line.textClass; + + do { + builder.measure = line == realLine && measure; + builder.pos = 0; + builder.addToken = builder.measure ? buildTokenMeasure : buildToken; + if (measure && sawBefore && line != realLine && !builder.addedOne) { + measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure)); + builder.addedOne = true; + } + var next = insertLineContent(line, builder, getLineStyles(cm, line)); + sawBefore = line == lineBefore; + if (next) { + line = getLine(cm.doc, next.to.line); + simple = false; + } + } while (next); + + if (measure && !builder.addedOne) + measure[0] = builder.pre.appendChild(simple ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure)); + if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine)) + builder.pre.appendChild(document.createTextNode("\u00a0")); + + return builder.pre; + } + + var tokenSpecialChars = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g; + function buildToken(builder, text, style, startStyle, endStyle) { + if (!text) return; + if (!tokenSpecialChars.test(text)) { + builder.col += text.length; + var content = document.createTextNode(text); + } else { + var content = document.createDocumentFragment(), pos = 0; + while (true) { + tokenSpecialChars.lastIndex = pos; + var m = tokenSpecialChars.exec(text); + var skipped = m ? m.index - pos : text.length - pos; + if (skipped) { + content.appendChild(document.createTextNode(text.slice(pos, pos + skipped))); + builder.col += skipped; + } + if (!m) break; + pos += skipped + 1; + if (m[0] == "\t") { + var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; + content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); + builder.col += tabWidth; + } else { + var token = elt("span", "\u2022", "cm-invalidchar"); + token.title = "\\u" + m[0].charCodeAt(0).toString(16); + content.appendChild(token); + builder.col += 1; + } + } + } + if (style || startStyle || endStyle || builder.measure) { + var fullStyle = style || ""; + if (startStyle) fullStyle += startStyle; + if (endStyle) fullStyle += endStyle; + return builder.pre.appendChild(elt("span", [content], fullStyle)); + } + builder.pre.appendChild(content); + } + + function buildTokenMeasure(builder, text, style, startStyle, endStyle) { + for (var i = 0; i < text.length; ++i) { + if (i && i < text.length && + builder.cm.options.lineWrapping && + spanAffectsWrapping.test(text.slice(i - 1, i + 1))) + builder.pre.appendChild(elt("wbr")); + builder.measure[builder.pos++] = + buildToken(builder, text.charAt(i), style, + i == 0 && startStyle, i == text.length - 1 && endStyle); + } + if (text.length) builder.addedOne = true; + } + + function buildCollapsedSpan(builder, size, widget) { + if (widget) { + if (!builder.display) widget = widget.cloneNode(true); + builder.pre.appendChild(widget); + if (builder.measure && size) { + builder.measure[builder.pos] = widget; + builder.addedOne = true; + } + } + builder.pos += size; + } + + // Outputs a number of spans to make up a line, taking highlighting + // and marked text into account. + function insertLineContent(line, builder, styles) { + var spans = line.markedSpans; + if (!spans) { + for (var i = 1; i < styles.length; i+=2) + builder.addToken(builder, styles[i], styleToClass(styles[i+1])); + return; + } + + var allText = line.text, len = allText.length; + var pos = 0, i = 1, text = "", style; + var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed; + for (;;) { + if (nextChange == pos) { // Update current marker set + spanStyle = spanEndStyle = spanStartStyle = ""; + collapsed = null; nextChange = Infinity; + var foundBookmark = null; + for (var j = 0; j < spans.length; ++j) { + var sp = spans[j], m = sp.marker; + if (sp.from <= pos && (sp.to == null || sp.to > pos)) { + if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; } + if (m.className) spanStyle += " " + m.className; + if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle; + if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle; + if (m.collapsed && (!collapsed || collapsed.marker.width < m.width)) + collapsed = sp; + } else if (sp.from > pos && nextChange > sp.from) { + nextChange = sp.from; + } + if (m.type == "bookmark" && sp.from == pos && m.replacedWith) + foundBookmark = m.replacedWith; + } + if (collapsed && (collapsed.from || 0) == pos) { + buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos, + collapsed.from != null && collapsed.marker.replacedWith); + if (collapsed.to == null) return collapsed.marker.find(); + } + if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark); + } + if (pos >= len) break; + + var upto = Math.min(len, nextChange); + while (true) { + if (text) { + var end = pos + text.length; + if (!collapsed) { + var tokenText = end > upto ? text.slice(0, upto - pos) : text; + builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, + spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : ""); + } + if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;} + pos = end; + spanStartStyle = ""; + } + text = styles[i++]; style = styleToClass(styles[i++]); + } + } + } + + // DOCUMENT DATA STRUCTURE + + function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) { + function spansFor(n) {return markedSpans ? markedSpans[n] : null;} + + var from = change.from, to = change.to, text = change.text; + var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); + var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; + + // First adjust the line structure + if (from.ch == 0 && to.ch == 0 && lastText == "") { + // This is a whole-line replace. Treated specially to make + // sure line objects move the way they are supposed to. + for (var i = 0, e = text.length - 1, added = []; i < e; ++i) + added.push(makeLine(text[i], spansFor(i), estimateHeight)); + updateLine(lastLine, lastLine.text, lastSpans, estimateHeight); + if (nlines) doc.remove(from.line, nlines); + if (added.length) doc.insert(from.line, added); + } else if (firstLine == lastLine) { + if (text.length == 1) { + updateLine(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), + lastSpans, estimateHeight); + } else { + for (var added = [], i = 1, e = text.length - 1; i < e; ++i) + added.push(makeLine(text[i], spansFor(i), estimateHeight)); + added.push(makeLine(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)); + updateLine(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0), estimateHeight); + doc.insert(from.line + 1, added); + } + } else if (text.length == 1) { + updateLine(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), + spansFor(0), estimateHeight); + doc.remove(from.line + 1, nlines); + } else { + updateLine(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0), estimateHeight); + updateLine(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans, estimateHeight); + for (var i = 1, e = text.length - 1, added = []; i < e; ++i) + added.push(makeLine(text[i], spansFor(i), estimateHeight)); + if (nlines > 1) doc.remove(from.line + 1, nlines - 1); + doc.insert(from.line + 1, added); + } + + setSelection(doc, selAfter.anchor, selAfter.head, null, true); + } + + function LeafChunk(lines) { + this.lines = lines; + this.parent = null; + for (var i = 0, e = lines.length, height = 0; i < e; ++i) { + lines[i].parent = this; + height += lines[i].height; + } + this.height = height; + } + + LeafChunk.prototype = { + chunkSize: function() { return this.lines.length; }, + removeInner: function(at, n) { + for (var i = at, e = at + n; i < e; ++i) { + var line = this.lines[i]; + this.height -= line.height; + cleanUpLine(line); + signalLater(line, "delete"); + } + this.lines.splice(at, n); + }, + collapse: function(lines) { + lines.splice.apply(lines, [lines.length, 0].concat(this.lines)); + }, + insertInner: function(at, lines, height) { + this.height += height; + this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); + for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this; + }, + iterN: function(at, n, op) { + for (var e = at + n; at < e; ++at) + if (op(this.lines[at])) return true; + } + }; + + function BranchChunk(children) { + this.children = children; + var size = 0, height = 0; + for (var i = 0, e = children.length; i < e; ++i) { + var ch = children[i]; + size += ch.chunkSize(); height += ch.height; + ch.parent = this; + } + this.size = size; + this.height = height; + this.parent = null; + } + + BranchChunk.prototype = { + chunkSize: function() { return this.size; }, + removeInner: function(at, n) { + this.size -= n; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var rm = Math.min(n, sz - at), oldHeight = child.height; + child.removeInner(at, rm); + this.height -= oldHeight - child.height; + if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } + if ((n -= rm) == 0) break; + at = 0; + } else at -= sz; + } + if (this.size - n < 25) { + var lines = []; + this.collapse(lines); + this.children = [new LeafChunk(lines)]; + this.children[0].parent = this; + } + }, + collapse: function(lines) { + for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines); + }, + insertInner: function(at, lines, height) { + this.size += lines.length; + this.height += height; + for (var i = 0, e = this.children.length; i < e; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at <= sz) { + child.insertInner(at, lines, height); + if (child.lines && child.lines.length > 50) { + while (child.lines.length > 50) { + var spilled = child.lines.splice(child.lines.length - 25, 25); + var newleaf = new LeafChunk(spilled); + child.height -= newleaf.height; + this.children.splice(i + 1, 0, newleaf); + newleaf.parent = this; + } + this.maybeSpill(); + } + break; + } + at -= sz; + } + }, + maybeSpill: function() { + if (this.children.length <= 10) return; + var me = this; + do { + var spilled = me.children.splice(me.children.length - 5, 5); + var sibling = new BranchChunk(spilled); + if (!me.parent) { // Become the parent node + var copy = new BranchChunk(me.children); + copy.parent = me; + me.children = [copy, sibling]; + me = copy; + } else { + me.size -= sibling.size; + me.height -= sibling.height; + var myIndex = indexOf(me.parent.children, me); + me.parent.children.splice(myIndex + 1, 0, sibling); + } + sibling.parent = me.parent; + } while (me.children.length > 10); + me.parent.maybeSpill(); + }, + iterN: function(at, n, op) { + for (var i = 0, e = this.children.length; i < e; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var used = Math.min(n, sz - at); + if (child.iterN(at, used, op)) return true; + if ((n -= used) == 0) break; + at = 0; + } else at -= sz; + } + } + }; + + var nextDocId = 0; + var Doc = CodeMirror.Doc = function(text, mode, firstLine) { + if (!(this instanceof Doc)) return new Doc(text, mode, firstLine); + if (firstLine == null) firstLine = 0; + + BranchChunk.call(this, [new LeafChunk([makeLine("", null)])]); + this.first = firstLine; + this.scrollTop = this.scrollLeft = 0; + this.cantEdit = false; + this.history = makeHistory(); + this.frontier = firstLine; + var start = Pos(firstLine, 0); + this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null}; + this.id = ++nextDocId; + this.modeOption = mode; + + if (typeof text == "string") text = splitLines(text); + updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start}); + }; + + Doc.prototype = createObj(BranchChunk.prototype, { + iter: function(from, to, op) { + if (op) this.iterN(from - this.first, to - (from - this.first), op); + else this.iterN(this.first, this.first + this.size, from); + }, + + insert: function(at, lines) { + var height = 0; + for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height; + this.insertInner(at - this.first, lines, height); + }, + remove: function(at, n) { this.removeInner(at - this.first, n); }, + + getValue: function(lineSep) { + var lines = getLines(this, this.first, this.first + this.size); + if (lineSep === false) return lines; + return lines.join(lineSep || "\n"); + }, + setValue: function(code) { + var top = Pos(this.first, 0), last = this.first + this.size - 1; + makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), + text: splitLines(code), origin: "setValue"}, + {head: top, anchor: top}, true); + }, + replaceRange: function(code, from, to, origin) { + from = clipPos(this, from); + to = to ? clipPos(this, to) : from; + replaceRange(this, code, from, to, origin); + }, + getRange: function(from, to, lineSep) { + var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); + if (lineSep === false) return lines; + return lines.join(lineSep || "\n"); + }, + + getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;}, + setLine: function(line, text) { + if (isLine(this, line)) + replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line))); + }, + removeLine: function(line) { + if (isLine(this, line)) + replaceRange(this, "", Pos(line, 0), clipPos(this, Pos(line + 1, 0))); + }, + + getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);}, + getLineNumber: function(line) {return lineNo(line);}, + + lineCount: function() {return this.size;}, + firstLine: function() {return this.first;}, + lastLine: function() {return this.first + this.size - 1;}, + + clipPos: function(pos) {return clipPos(this, pos);}, + + getCursor: function(start) { + var sel = this.sel, pos; + if (start == null || start == "head") pos = sel.head; + else if (start == "anchor") pos = sel.anchor; + else if (start == "end" || start === false) pos = sel.to; + else pos = sel.from; + return copyPos(pos); + }, + somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);}, + + setCursor: docOperation(function(line, ch, extend) { + var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line); + if (extend) extendSelection(this, pos); + else setSelection(this, pos, pos); + }), + setSelection: docOperation(function(anchor, head) { + setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor)); + }), + extendSelection: docOperation(function(from, to) { + extendSelection(this, clipPos(this, from), to && clipPos(this, to)); + }), + + getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);}, + replaceSelection: function(code, collapse, origin) { + makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around"); + }, + undo: docOperation(function() {makeChangeFromHistory(this, "undo");}), + redo: docOperation(function() {makeChangeFromHistory(this, "redo");}), + + setExtending: function(val) {this.sel.extend = val;}, + + historySize: function() { + var hist = this.history; + return {undo: hist.done.length, redo: hist.undone.length}; + }, + clearHistory: function() {this.history = makeHistory();}, + + markClean: function() { + this.history.dirtyCounter = 0; + this.history.lastOp = this.history.lastOrigin = null; + }, + isClean: function () {return this.history.dirtyCounter == 0;}, + + getHistory: function() { + return {done: copyHistoryArray(this.history.done), + undone: copyHistoryArray(this.history.undone)}; + }, + setHistory: function(histData) { + var hist = this.history = makeHistory(); + hist.done = histData.done.slice(0); + hist.undone = histData.undone.slice(0); + }, + + markText: function(from, to, options) { + return markText(this, clipPos(this, from), clipPos(this, to), options, "range"); + }, + setBookmark: function(pos, options) { + var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), + insertLeft: options && options.insertLeft}; + pos = clipPos(this, pos); + return markText(this, pos, pos, realOpts, "bookmark"); + }, + findMarksAt: function(pos) { + pos = clipPos(this, pos); + var markers = [], spans = getLine(this, pos.line).markedSpans; + if (spans) for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if ((span.from == null || span.from <= pos.ch) && + (span.to == null || span.to >= pos.ch)) + markers.push(span.marker.parent || span.marker); + } + return markers; + }, + + posFromIndex: function(off) { + var ch, lineNo = this.first; + this.iter(function(line) { + var sz = line.text.length + 1; + if (sz > off) { ch = off; return true; } + off -= sz; + ++lineNo; + }); + return clipPos(this, Pos(lineNo, ch)); + }, + indexFromPos: function (coords) { + coords = clipPos(this, coords); + var index = coords.ch; + if (coords.line < this.first || coords.ch < 0) return 0; + this.iter(this.first, coords.line, function (line) { + index += line.text.length + 1; + }); + return index; + }, + + copy: function(copyHistory) { + var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first); + doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; + doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor, + shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn}; + if (copyHistory) { + doc.history.undoDepth = this.history.undoDepth; + doc.setHistory(this.getHistory()); + } + return doc; + }, + + linkedDoc: function(options) { + if (!options) options = {}; + var from = this.first, to = this.first + this.size; + if (options.from != null && options.from > from) from = options.from; + if (options.to != null && options.to < to) to = options.to; + var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from); + if (options.sharedHist) copy.history = this.history; + (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); + copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; + return copy; + }, + unlinkDoc: function(other) { + if (other instanceof CodeMirror) other = other.doc; + if (this.linked) for (var i = 0; i < this.linked.length; ++i) { + var link = this.linked[i]; + if (link.doc != other) continue; + this.linked.splice(i, 1); + other.unlinkDoc(this); + break; + } + // If the histories were shared, split them again + if (other.history == this.history) { + var splitIds = [other.id]; + linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true); + other.history = makeHistory(); + other.history.done = copyHistoryArray(this.history.done, splitIds); + other.history.undone = copyHistoryArray(this.history.undone, splitIds); + } + }, + iterLinkedDocs: function(f) {linkedDocs(this, f);}, + + getMode: function() {return this.mode;}, + getEditor: function() {return this.cm;} + }); + + Doc.prototype.eachLine = Doc.prototype.iter; + + // The Doc methods that should be available on CodeMirror instances + var toDelegate = ("setValue getValue getSelection replaceSelection eachLine undo redo historySize clearHistory markClean isClean " + + "getHistory setHistory markText setBookmark findMarksAt lineCount firstLine lastLine clipPos getCursor " + + "somethingSelected setCursor setSelection extendSelection setExtending getLine setLine removeLine getMode " + + "replaceRange getRange getLineHandle getLineNumber posFromIndex indexFromPos linkedDoc unlinkDoc iterLinkedDocs").split(" "); + for (var i = 0; i < toDelegate.length; ++i) (function(method) { + var target = Doc.prototype[method]; + CodeMirror.prototype[method] = function() {return target.apply(this.doc, arguments);}; + })(toDelegate[i]); + + function linkedDocs(doc, f, sharedHistOnly) { + function propagate(doc, skip, sharedHist) { + if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) { + var rel = doc.linked[i]; + if (rel.doc == skip) continue; + var shared = sharedHist && rel.sharedHist; + if (sharedHistOnly && !shared) continue; + f(rel.doc, shared); + propagate(rel.doc, doc, shared); + } + } + propagate(doc, null, true); + } + + function attachDoc(cm, doc) { + if (doc.cm) throw new Error("This document is already in use."); + cm.doc = doc; + doc.cm = cm; + estimateLineHeights(cm); + loadMode(cm); + if (!cm.options.lineWrapping) computeMaxLength(cm); + cm.options.mode = doc.modeOption; + regChange(cm); + } + + // LINE UTILITIES + + function getLine(chunk, n) { + n -= chunk.first; + while (!chunk.lines) { + for (var i = 0;; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; break; } + n -= sz; + } + } + return chunk.lines[n]; + } + + function getBetween(doc, start, end) { + var out = [], n = start.line; + doc.iter(start.line, end.line + 1, function(line) { + var text = line.text; + if (n == end.line) text = text.slice(0, end.ch); + if (n == start.line) text = text.slice(start.ch); + out.push(text); + ++n; + }); + return out; + } + function getLines(doc, from, to) { + var out = []; + doc.iter(from, to, function(line) { out.push(line.text); }); + return out; + } + + function updateLineHeight(line, height) { + var diff = height - line.height; + for (var n = line; n; n = n.parent) n.height += diff; + } + + function lineNo(line) { + if (line.parent == null) return null; + var cur = line.parent, no = indexOf(cur.lines, line); + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0;; ++i) { + if (chunk.children[i] == cur) break; + no += chunk.children[i].chunkSize(); + } + } + return no + cur.first; + } + + function lineAtHeight(chunk, h) { + var n = chunk.first; + outer: do { + for (var i = 0, e = chunk.children.length; i < e; ++i) { + var child = chunk.children[i], ch = child.height; + if (h < ch) { chunk = child; continue outer; } + h -= ch; + n += child.chunkSize(); + } + return n; + } while (!chunk.lines); + for (var i = 0, e = chunk.lines.length; i < e; ++i) { + var line = chunk.lines[i], lh = line.height; + if (h < lh) break; + h -= lh; + } + return n + i; + } + + function heightAtLine(cm, lineObj) { + lineObj = visualLine(cm.doc, lineObj); + + var h = 0, chunk = lineObj.parent; + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i]; + if (line == lineObj) break; + else h += line.height; + } + for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { + for (var i = 0; i < p.children.length; ++i) { + var cur = p.children[i]; + if (cur == chunk) break; + else h += cur.height; + } + } + return h; + } + + function getOrder(line) { + var order = line.order; + if (order == null) order = line.order = bidiOrdering(line.text); + return order; + } + + // HISTORY + + function makeHistory() { + return { + // Arrays of history events. Doing something adds an event to + // done and clears undo. Undoing moves events from done to + // undone, redoing moves them in the other direction. + done: [], undone: [], undoDepth: Infinity, + // Used to track when changes can be merged into a single undo + // event + lastTime: 0, lastOp: null, lastOrigin: null, + // Used by the isClean() method + dirtyCounter: 0 + }; + } + + function attachLocalSpans(doc, change, from, to) { + var existing = change["spans_" + doc.id], n = 0; + doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) { + if (line.markedSpans) + (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; + ++n; + }); + } + + function historyChangeFromChange(doc, change) { + var histChange = {from: change.from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; + attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); + linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true); + return histChange; + } + + function addToHistory(doc, change, selAfter, opId) { + var hist = doc.history; + hist.undone.length = 0; + var time = +new Date, cur = lst(hist.done); + + if (cur && + (hist.lastOp == opId || + hist.lastOrigin == change.origin && change.origin && + ((change.origin.charAt(0) == "+" && hist.lastTime > time - 600) || change.origin.charAt(0) == "*"))) { + // Merge this change into the last event + var last = lst(cur.changes); + if (posEq(change.from, change.to) && posEq(change.from, last.to)) { + // Optimized case for simple insertion -- don't want to add + // new changesets for every character typed + last.to = changeEnd(change); + } else { + // Add new sub-event + cur.changes.push(historyChangeFromChange(doc, change)); + } + cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head; + } else { + // Can not be merged, start a new event. + cur = {changes: [historyChangeFromChange(doc, change)], + anchorBefore: doc.sel.anchor, headBefore: doc.sel.head, + anchorAfter: selAfter.anchor, headAfter: selAfter.head}; + hist.done.push(cur); + while (hist.done.length > hist.undoDepth) + hist.done.shift(); + if (hist.dirtyCounter < 0) + // The user has made a change after undoing past the last clean state. + // We can never get back to a clean state now until markClean() is called. + hist.dirtyCounter = NaN; + else + hist.dirtyCounter++; + } + hist.lastTime = time; + hist.lastOp = opId; + hist.lastOrigin = change.origin; + } + + function removeClearedSpans(spans) { + if (!spans) return null; + for (var i = 0, out; i < spans.length; ++i) { + if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); } + else if (out) out.push(spans[i]); + } + return !out ? spans : out.length ? out : null; + } + + function getOldSpans(doc, change) { + var found = change["spans_" + doc.id]; + if (!found) return null; + for (var i = 0, nw = []; i < change.text.length; ++i) + nw.push(removeClearedSpans(found[i])); + return nw; + } + + // Used both to provide a JSON-safe object in .getHistory, and, when + // detaching a document, to split the history in two + function copyHistoryArray(events, newGroup) { + for (var i = 0, copy = []; i < events.length; ++i) { + var event = events[i], changes = event.changes, newChanges = []; + copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore, + anchorAfter: event.anchorAfter, headAfter: event.headAfter}); + for (var j = 0; j < changes.length; ++j) { + var change = changes[j], m; + newChanges.push({from: change.from, to: change.to, text: change.text}); + if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) { + if (indexOf(newGroup, Number(m[1])) > -1) { + lst(newChanges)[prop] = change[prop]; + delete change[prop]; + } + } + } + } + return copy; + } + + // Rebasing/resetting history to deal with externally-sourced changes + + function rebaseHistSel(pos, from, to, diff) { + if (to < pos.line) { + pos.line += diff; + } else if (from < pos.line) { + pos.line = from; + pos.ch = 0; + } + } + + // Tries to rebase an array of history events given a change in the + // document. If the change touches the same lines as the event, the + // event, and everything 'behind' it, is discarded. If the change is + // before the event, the event's positions are updated. Uses a + // copy-on-write scheme for the positions, to avoid having to + // reallocate them all on every rebase, but also avoid problems with + // shared position objects being unsafely updated. + function rebaseHistArray(array, from, to, diff) { + for (var i = 0; i < array.length; ++i) { + var sub = array[i], ok = true; + for (var j = 0; j < sub.changes.length; ++j) { + var cur = sub.changes[j]; + if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); } + if (to < cur.from.line) { + cur.from.line += diff; + cur.to.line += diff; + } else if (from <= cur.to.line) { + ok = false; + break; + } + } + if (!sub.copied) { + sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore); + sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter); + sub.copied = true; + } + if (!ok) { + array.splice(0, i + 1); + i = 0; + } else { + rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore); + rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter); + } + } + } + + function rebaseHist(hist, change) { + var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; + rebaseHistArray(hist.done, from, to, diff); + rebaseHistArray(hist.undone, from, to, diff); + } + + // EVENT OPERATORS + + function stopMethod() {e_stop(this);} + // Ensure an event has a stop method. + function addStop(event) { + if (!event.stop) event.stop = stopMethod; + return event; + } + + function e_preventDefault(e) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + function e_stopPropagation(e) { + if (e.stopPropagation) e.stopPropagation(); + else e.cancelBubble = true; + } + function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} + CodeMirror.e_stop = e_stop; + CodeMirror.e_preventDefault = e_preventDefault; + CodeMirror.e_stopPropagation = e_stopPropagation; + + function e_target(e) {return e.target || e.srcElement;} + function e_button(e) { + var b = e.which; + if (b == null) { + if (e.button & 1) b = 1; + else if (e.button & 2) b = 3; + else if (e.button & 4) b = 2; + } + if (mac && e.ctrlKey && b == 1) b = 3; + return b; + } + + // Allow 3rd-party code to override event properties by adding an override + // object to an event object. + function e_prop(e, prop) { + var overridden = e.override && e.override.hasOwnProperty(prop); + return overridden ? e.override[prop] : e[prop]; + } + + // EVENT HANDLING + + function on(emitter, type, f) { + if (emitter.addEventListener) + emitter.addEventListener(type, f, false); + else if (emitter.attachEvent) + emitter.attachEvent("on" + type, f); + else { + var map = emitter._handlers || (emitter._handlers = {}); + var arr = map[type] || (map[type] = []); + arr.push(f); + } + } + + function off(emitter, type, f) { + if (emitter.removeEventListener) + emitter.removeEventListener(type, f, false); + else if (emitter.detachEvent) + emitter.detachEvent("on" + type, f); + else { + var arr = emitter._handlers && emitter._handlers[type]; + if (!arr) return; + for (var i = 0; i < arr.length; ++i) + if (arr[i] == f) { arr.splice(i, 1); break; } + } + } + + function signal(emitter, type /*, values...*/) { + var arr = emitter._handlers && emitter._handlers[type]; + if (!arr) return; + var args = Array.prototype.slice.call(arguments, 2); + for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args); + } + + var delayedCallbacks, delayedCallbackDepth = 0; + function signalLater(emitter, type /*, values...*/) { + var arr = emitter._handlers && emitter._handlers[type]; + if (!arr) return; + var args = Array.prototype.slice.call(arguments, 2); + function bnd(f) {return function(){f.apply(null, args);};}; + for (var i = 0; i < arr.length; ++i) + if (delayedCallbacks) delayedCallbacks.push(bnd(arr[i])); + else arr[i].apply(null, args); + } + + function hasHandler(emitter, type) { + var arr = emitter._handlers && emitter._handlers[type]; + return arr && arr.length > 0; + } + + CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal; + + // MISC UTILITIES + + // Number of pixels added to scroller and sizer to hide scrollbar + var scrollerCutOff = 30; + + // Returned or thrown by various protocols to signal 'I'm not + // handling this'. + var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}}; + + function Delayed() {this.id = null;} + Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}}; + + // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + function countColumn(string, end, tabSize) { + if (end == null) { + end = string.search(/[^\s\u00a0]/); + if (end == -1) end = string.length; + } + for (var i = 0, n = 0; i < end; ++i) { + if (string.charAt(i) == "\t") n += tabSize - (n % tabSize); + else ++n; + } + return n; + } + CodeMirror.countColumn = countColumn; + + var spaceStrs = [""]; + function spaceStr(n) { + while (spaceStrs.length <= n) + spaceStrs.push(lst(spaceStrs) + " "); + return spaceStrs[n]; + } + + function lst(arr) { return arr[arr.length-1]; } + + function selectInput(node) { + if (ios) { // Mobile Safari apparently has a bug where select() is broken. + node.selectionStart = 0; + node.selectionEnd = node.value.length; + } else node.select(); + } + + function indexOf(collection, elt) { + if (collection.indexOf) return collection.indexOf(elt); + for (var i = 0, e = collection.length; i < e; ++i) + if (collection[i] == elt) return i; + return -1; + } + + function createObj(base, props) { + if (!base) return; + createObj.prototype = base; + var inst = new createObj(); + if (props) copyObj(props, inst); + return inst; + } + + function copyObj(obj, target) { + if (!target) target = {}; + for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop]; + return target; + } + + function emptyArray(size) { + for (var a = [], i = 0; i < size; ++i) a.push(undefined); + return a; + } + + function bind(f) { + var args = Array.prototype.slice.call(arguments, 1); + return function(){return f.apply(null, args);}; + } + + var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/; + function isWordChar(ch) { + return /\w/.test(ch) || ch > "\x80" && + (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); + } + + function isEmpty(obj) { + for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false; + return true; + } + + var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F]/; + + // DOM UTILITIES + + function elt(tag, content, className, style) { + var e = document.createElement(tag); + if (className) e.className = className; + if (style) e.style.cssText = style; + if (typeof content == "string") setTextContent(e, content); + else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]); + return e; + } + + function removeChildren(e) { + // IE will break all parent-child relations in subnodes when setting innerHTML + if (!ie) e.innerHTML = ""; + else while (e.firstChild) e.removeChild(e.firstChild); + return e; + } + + function removeChildrenAndAdd(parent, e) { + return removeChildren(parent).appendChild(e); + } + + function setTextContent(e, str) { + if (ie_lt9) { + e.innerHTML = ""; + e.appendChild(document.createTextNode(str)); + } else e.textContent = str; + } + + // FEATURE DETECTION + + // Detect drag-and-drop + var dragAndDrop = function() { + // There is *some* kind of drag-and-drop support in IE6-8, but I + // couldn't get it to work yet. + if (ie_lt9) return false; + var div = elt('div'); + return "draggable" in div || "dragDrop" in div; + }(); + + // For a reason I have yet to figure out, some browsers disallow + // word wrapping between certain characters *only* if a new inline + // element is started between them. This makes it hard to reliably + // measure the position of things, since that requires inserting an + // extra span. This terribly fragile set of regexps matches the + // character combinations that suffer from this phenomenon on the + // various browsers. + var spanAffectsWrapping = /^$/; // Won't match any two-character string + if (gecko) spanAffectsWrapping = /$'/; + else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/; + else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/; + + var knownScrollbarWidth; + function scrollbarWidth(measure) { + if (knownScrollbarWidth != null) return knownScrollbarWidth; + var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll"); + removeChildrenAndAdd(measure, test); + if (test.offsetWidth) + knownScrollbarWidth = test.offsetHeight - test.clientHeight; + return knownScrollbarWidth || 0; + } + + var zwspSupported; + function zeroWidthElement(measure) { + if (zwspSupported == null) { + var test = elt("span", "\u200b"); + removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); + if (measure.firstChild.offsetHeight != 0) + zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8; + } + if (zwspSupported) return elt("span", "\u200b"); + else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); + } + + // See if "".split is the broken IE version, if so, provide an + // alternative way to split lines. + var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { + var pos = 0, result = [], l = string.length; + while (pos <= l) { + var nl = string.indexOf("\n", pos); + if (nl == -1) nl = string.length; + var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); + var rt = line.indexOf("\r"); + if (rt != -1) { + result.push(line.slice(0, rt)); + pos += rt + 1; + } else { + result.push(line); + pos = nl + 1; + } + } + return result; + } : function(string){return string.split(/\r\n?|\n/);}; + CodeMirror.splitLines = splitLines; + + var hasSelection = window.getSelection ? function(te) { + try { return te.selectionStart != te.selectionEnd; } + catch(e) { return false; } + } : function(te) { + try {var range = te.ownerDocument.selection.createRange();} + catch(e) {} + if (!range || range.parentElement() != te) return false; + return range.compareEndPoints("StartToEnd", range) != 0; + }; + + var hasCopyEvent = (function() { + var e = elt("div"); + if ("oncopy" in e) return true; + e.setAttribute("oncopy", "return;"); + return typeof e.oncopy == 'function'; + })(); + + // KEY NAMING + + var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", + 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", + 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", + 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete", + 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", + 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home", + 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"}; + CodeMirror.keyNames = keyNames; + (function() { + // Number keys + for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i); + // Alphabetic keys + for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); + // Function keys + for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; + })(); + + // BIDI HELPERS + + function iterateBidiSections(order, from, to, f) { + if (!order) return f(from, to, "ltr"); + for (var i = 0; i < order.length; ++i) { + var part = order[i]; + if (part.from < to && part.to > from || from == to && part.to == from) + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr"); + } + } + + function bidiLeft(part) { return part.level % 2 ? part.to : part.from; } + function bidiRight(part) { return part.level % 2 ? part.from : part.to; } + + function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; } + function lineRight(line) { + var order = getOrder(line); + if (!order) return line.text.length; + return bidiRight(lst(order)); + } + + function lineStart(cm, lineN) { + var line = getLine(cm.doc, lineN); + var visual = visualLine(cm.doc, line); + if (visual != line) lineN = lineNo(visual); + var order = getOrder(visual); + var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual); + return Pos(lineN, ch); + } + function lineEnd(cm, lineN) { + var merged, line; + while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN))) + lineN = merged.find().to.line; + var order = getOrder(line); + var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line); + return Pos(lineN, ch); + } + + // This is somewhat involved. It is needed in order to move + // 'visually' through bi-directional text -- i.e., pressing left + // should make the cursor go left, even when in RTL text. The + // tricky part is the 'jumps', where RTL and LTR text touch each + // other. This often requires the cursor offset to move more than + // one unit, in order to visually move one unit. + function moveVisually(line, start, dir, byUnit) { + var bidi = getOrder(line); + if (!bidi) return moveLogically(line, start, dir, byUnit); + var moveOneUnit = byUnit ? function(pos, dir) { + do pos += dir; + while (pos > 0 && isExtendingChar.test(line.text.charAt(pos))); + return pos; + } : function(pos, dir) { return pos + dir; }; + var linedir = bidi[0].level; + for (var i = 0; i < bidi.length; ++i) { + var part = bidi[i], sticky = part.level % 2 == linedir; + if ((part.from < start && part.to > start) || + (sticky && (part.from == start || part.to == start))) break; + } + var target = moveOneUnit(start, part.level % 2 ? -dir : dir); + + while (target != null) { + if (part.level % 2 == linedir) { + if (target < part.from || target > part.to) { + part = bidi[i += dir]; + target = part && (dir > 0 == part.level % 2 ? moveOneUnit(part.to, -1) : moveOneUnit(part.from, 1)); + } else break; + } else { + if (target == bidiLeft(part)) { + part = bidi[--i]; + target = part && bidiRight(part); + } else if (target == bidiRight(part)) { + part = bidi[++i]; + target = part && bidiLeft(part); + } else break; + } + } + + return target < 0 || target > line.text.length ? null : target; + } + + function moveLogically(line, start, dir, byUnit) { + var target = start + dir; + if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir; + return target < 0 || target > line.text.length ? null : target; + } + + // Bidirectional ordering algorithm + // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm + // that this (partially) implements. + + // One-char codes used for character types: + // L (L): Left-to-Right + // R (R): Right-to-Left + // r (AL): Right-to-Left Arabic + // 1 (EN): European Number + // + (ES): European Number Separator + // % (ET): European Number Terminator + // n (AN): Arabic Number + // , (CS): Common Number Separator + // m (NSM): Non-Spacing Mark + // b (BN): Boundary Neutral + // s (B): Paragraph Separator + // t (S): Segment Separator + // w (WS): Whitespace + // N (ON): Other Neutrals + + // Returns null if characters are ordered as they appear + // (left-to-right), or an array of sections ({from, to, level} + // objects) in the order in which they occur visually. + var bidiOrdering = (function() { + // Character types for codepoints 0 to 0xff + var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL"; + // Character types for codepoints 0x600 to 0x6ff + var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr"; + function charType(code) { + if (code <= 0xff) return lowTypes.charAt(code); + else if (0x590 <= code && code <= 0x5f4) return "R"; + else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600); + else if (0x700 <= code && code <= 0x8ac) return "r"; + else return "L"; + } + + var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; + var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; + // Browsers seem to always treat the boundaries of block elements as being L. + var outerType = "L"; + + return function(str) { + if (!bidiRE.test(str)) return false; + var len = str.length, types = []; + for (var i = 0, type; i < len; ++i) + types.push(type = charType(str.charCodeAt(i))); + + // W1. Examine each non-spacing mark (NSM) in the level run, and + // change the type of the NSM to the type of the previous + // character. If the NSM is at the start of the level run, it will + // get the type of sor. + for (var i = 0, prev = outerType; i < len; ++i) { + var type = types[i]; + if (type == "m") types[i] = prev; + else prev = type; + } + + // W2. Search backwards from each instance of a European number + // until the first strong type (R, L, AL, or sor) is found. If an + // AL is found, change the type of the European number to Arabic + // number. + // W3. Change all ALs to R. + for (var i = 0, cur = outerType; i < len; ++i) { + var type = types[i]; + if (type == "1" && cur == "r") types[i] = "n"; + else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; } + } + + // W4. A single European separator between two European numbers + // changes to a European number. A single common separator between + // two numbers of the same type changes to that type. + for (var i = 1, prev = types[0]; i < len - 1; ++i) { + var type = types[i]; + if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1"; + else if (type == "," && prev == types[i+1] && + (prev == "1" || prev == "n")) types[i] = prev; + prev = type; + } + + // W5. A sequence of European terminators adjacent to European + // numbers changes to all European numbers. + // W6. Otherwise, separators and terminators change to Other + // Neutral. + for (var i = 0; i < len; ++i) { + var type = types[i]; + if (type == ",") types[i] = "N"; + else if (type == "%") { + for (var end = i + 1; end < len && types[end] == "%"; ++end) {} + var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N"; + for (var j = i; j < end; ++j) types[j] = replace; + i = end - 1; + } + } + + // W7. Search backwards from each instance of a European number + // until the first strong type (R, L, or sor) is found. If an L is + // found, then change the type of the European number to L. + for (var i = 0, cur = outerType; i < len; ++i) { + var type = types[i]; + if (cur == "L" && type == "1") types[i] = "L"; + else if (isStrong.test(type)) cur = type; + } + + // N1. A sequence of neutrals takes the direction of the + // surrounding strong text if the text on both sides has the same + // direction. European and Arabic numbers act as if they were R in + // terms of their influence on neutrals. Start-of-level-run (sor) + // and end-of-level-run (eor) are used at level run boundaries. + // N2. Any remaining neutrals take the embedding direction. + for (var i = 0; i < len; ++i) { + if (isNeutral.test(types[i])) { + for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {} + var before = (i ? types[i-1] : outerType) == "L"; + var after = (end < len - 1 ? types[end] : outerType) == "L"; + var replace = before || after ? "L" : "R"; + for (var j = i; j < end; ++j) types[j] = replace; + i = end - 1; + } + } + + // Here we depart from the documented algorithm, in order to avoid + // building up an actual levels array. Since there are only three + // levels (0, 1, 2) in an implementation that doesn't take + // explicit embedding into account, we can build up the order on + // the fly, without following the level-based algorithm. + var order = [], m; + for (var i = 0; i < len;) { + if (countsAsLeft.test(types[i])) { + var start = i; + for (++i; i < len && countsAsLeft.test(types[i]); ++i) {} + order.push({from: start, to: i, level: 0}); + } else { + var pos = i, at = order.length; + for (++i; i < len && types[i] != "L"; ++i) {} + for (var j = pos; j < i;) { + if (countsAsNum.test(types[j])) { + if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1}); + var nstart = j; + for (++j; j < i && countsAsNum.test(types[j]); ++j) {} + order.splice(at, 0, {from: nstart, to: j, level: 2}); + pos = j; + } else ++j; + } + if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1}); + } + } + if (order[0].level == 1 && (m = str.match(/^\s+/))) { + order[0].from = m[0].length; + order.unshift({from: 0, to: m[0].length, level: 0}); + } + if (lst(order).level == 1 && (m = str.match(/\s+$/))) { + lst(order).to -= m[0].length; + order.push({from: len - m[0].length, to: len, level: 0}); + } + if (order[0].level != lst(order).level) + order.push({from: len, to: len, level: order[0].level}); + + return order; + }; + })(); + + // THE END + + CodeMirror.version = "3.02 +"; + + return CodeMirror; +})(); diff --git a/js/examples/hello.js b/js/examples/hello.js new file mode 100644 index 0000000000..0e16593e1a --- /dev/null +++ b/js/examples/hello.js @@ -0,0 +1,19 @@ +/** + * @jsx React.DOM + */ + +var HELLO_COMPONENT = "\ +/** @jsx React.DOM */\n\ +var HelloMessage = React.createClass({\n\ + render: function() {\n\ + return
{'Hello ' + this.props.name}
;\n\ + }\n\ +});\n\ +\n\ +React.renderComponent(, mountNode);\ +"; + +React.renderComponent( + ReactPlayground( {codeText:HELLO_COMPONENT}, null ), + document.getElementById('helloExample') +); diff --git a/js/examples/markdown.js b/js/examples/markdown.js new file mode 100644 index 0000000000..53a6d8c5ff --- /dev/null +++ b/js/examples/markdown.js @@ -0,0 +1,42 @@ +/** + * @jsx React.DOM + */ + +var MARKDOWN_COMPONENT = "\ +/** @jsx React.DOM */\n\ +\n\ +var converter = new Showdown.converter();\n\ +\n\ +var MarkdownEditor = React.createClass({\n\ + getInitialState: function() {\n\ + return {value: 'Type some *markdown* here!'};\n\ + },\n\ + handleKeyUp: React.autoBind(function() {\n\ + this.setState({value: this.refs.textarea.getDOMNode().value});\n\ + }),\n\ + render: function() {\n\ + return (\n\ +
\n\ +

Input

\n\ + \n\ +

Output

\n\ + \n\ +
\n\ + );\n\ + }\n\ +});\n\ +\n\ +React.renderComponent(, mountNode);\ +"; + +React.renderComponent( + ReactPlayground( {codeText:MARKDOWN_COMPONENT}, null ), + document.getElementById('markdownExample') +); diff --git a/js/examples/timer.js b/js/examples/timer.js new file mode 100644 index 0000000000..5d4d0b7c6b --- /dev/null +++ b/js/examples/timer.js @@ -0,0 +1,32 @@ +/** + * @jsx React.DOM + */ + +var TIMER_COMPONENT = "\ +/** @jsx React.DOM */\n\ +var Timer = React.createClass({\n\ + getInitialState: function() {\n\ + return {secondsElapsed: 0};\n\ + },\n\ + tick: React.autoBind(function() {\n\ + this.setState({secondsElapsed: this.state.secondsElapsed + 1});\n\ + }),\n\ + componentDidMount: function() {\n\ + setInterval(this.tick, 1000);\n\ + },\n\ + render: function() {\n\ + return (\n\ +
\n\ + {'Seconds Ellapsed: ' + this.state.secondsElapsed}\n\ +
\n\ + );\n\ + }\n\ +});\n\ +\n\ +React.renderComponent(, mountNode);\ +"; + +React.renderComponent( + ReactPlayground( {codeText:TIMER_COMPONENT}, null ), + document.getElementById('timerExample') +); diff --git a/js/examples/todo.js b/js/examples/todo.js new file mode 100644 index 0000000000..8cfe0b9cd3 --- /dev/null +++ b/js/examples/todo.js @@ -0,0 +1,57 @@ +/** + * @jsx React.DOM + */ + +var TODO_COMPONENT = "\ +/** @jsx React.DOM */\n\ +var TodoList = React.createClass({\n\ + render: function() {\n\ + var items = this.props.items.map(function(item) {\n\ + return
  • {item}
  • ;\n\ + });\n\ + return
      {items}
    ;\n\ + }\n\ +});\n\ +\n\ +var TodoCreate = React.createClass({\n\ + handleSubmit: function() {\n\ + var textInput = this.refs.textInput.getDOMNode();\n\ + this.props.onCreate(textInput.value);\n\ + textInput.value = '';\n\ + return false;\n\ + },\n\ + render: function() {\n\ + return (\n\ +
    \n\ + \n\ + \n\ +
    \n\ + );\n\ + }\n\ +});\n\ +\n\ +var TodoApp = React.createClass({\n\ + getInitialState: function() {\n\ + return {items: []};\n\ + },\n\ + onItemCreate: function(value) {\n\ + this.setState({items: this.state.items.concat([value])});\n\ + },\n\ + render: function() {\n\ + return (\n\ +
    \n\ +

    TODO

    \n\ + \n\ + \n\ +
    \n\ + );\n\ + }\n\ +});\n\ +\n\ +React.renderComponent(, mountNode);\ +"; + +React.renderComponent( + ReactPlayground( {codeText:TODO_COMPONENT}, null ), + document.getElementById('todoExample') +); diff --git a/js/javascript.js b/js/javascript.js new file mode 100644 index 0000000000..c734555047 --- /dev/null +++ b/js/javascript.js @@ -0,0 +1,425 @@ +// TODO actually recognize syntax of TypeScript constructs + +CodeMirror.defineMode("javascript", function(config, parserConfig) { + var indentUnit = config.indentUnit; + var jsonMode = parserConfig.json; + var isTS = parserConfig.typescript; + + // Tokenizer + + var keywords = function(){ + function kw(type) {return {type: type, style: "keyword"};} + var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); + var operator = kw("operator"), atom = {type: "atom", style: "atom"}; + + var jsKeywords = { + "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, + "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, + "var": kw("var"), "const": kw("var"), "let": kw("var"), + "function": kw("function"), "catch": kw("catch"), + "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), + "in": operator, "typeof": operator, "instanceof": operator, + "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom + }; + + // Extend the 'normal' keywords with the TypeScript language extensions + if (isTS) { + var type = {type: "variable", style: "variable-3"}; + var tsKeywords = { + // object-like things + "interface": kw("interface"), + "class": kw("class"), + "extends": kw("extends"), + "constructor": kw("constructor"), + + // scope modifiers + "public": kw("public"), + "private": kw("private"), + "protected": kw("protected"), + "static": kw("static"), + + "super": kw("super"), + + // types + "string": type, "number": type, "bool": type, "any": type + }; + + for (var attr in tsKeywords) { + jsKeywords[attr] = tsKeywords[attr]; + } + } + + return jsKeywords; + }(); + + var isOperatorChar = /[+\-*&%=<>!?|]/; + + function chain(stream, state, f) { + state.tokenize = f; + return f(stream, state); + } + + function nextUntilUnescaped(stream, end) { + var escaped = false, next; + while ((next = stream.next()) != null) { + if (next == end && !escaped) + return false; + escaped = !escaped && next == "\\"; + } + return escaped; + } + + // Used as scratch variables to communicate multiple values without + // consing up tons of objects. + var type, content; + function ret(tp, style, cont) { + type = tp; content = cont; + return style; + } + + function jsTokenBase(stream, state) { + var ch = stream.next(); + if (ch == '"' || ch == "'") + return chain(stream, state, jsTokenString(ch)); + else if (/[\[\]{}\(\),;\:\.]/.test(ch)) + return ret(ch); + else if (ch == "0" && stream.eat(/x/i)) { + stream.eatWhile(/[\da-f]/i); + return ret("number", "number"); + } + else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) { + stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); + return ret("number", "number"); + } + else if (ch == "/") { + if (stream.eat("*")) { + return chain(stream, state, jsTokenComment); + } + else if (stream.eat("/")) { + stream.skipToEnd(); + return ret("comment", "comment"); + } + else if (state.lastType == "operator" || state.lastType == "keyword c" || + /^[\[{}\(,;:]$/.test(state.lastType)) { + nextUntilUnescaped(stream, "/"); + stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla + return ret("regexp", "string-2"); + } + else { + stream.eatWhile(isOperatorChar); + return ret("operator", null, stream.current()); + } + } + else if (ch == "#") { + stream.skipToEnd(); + return ret("error", "error"); + } + else if (isOperatorChar.test(ch)) { + stream.eatWhile(isOperatorChar); + return ret("operator", null, stream.current()); + } + else { + stream.eatWhile(/[\w\$_]/); + var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; + return (known && state.lastType != ".") ? ret(known.type, known.style, word) : + ret("variable", "variable", word); + } + } + + function jsTokenString(quote) { + return function(stream, state) { + if (!nextUntilUnescaped(stream, quote)) + state.tokenize = jsTokenBase; + return ret("string", "string"); + }; + } + + function jsTokenComment(stream, state) { + var maybeEnd = false, ch; + while (ch = stream.next()) { + if (ch == "/" && maybeEnd) { + state.tokenize = jsTokenBase; + break; + } + maybeEnd = (ch == "*"); + } + return ret("comment", "comment"); + } + + // Parser + + var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true}; + + function JSLexical(indented, column, type, align, prev, info) { + this.indented = indented; + this.column = column; + this.type = type; + this.prev = prev; + this.info = info; + if (align != null) this.align = align; + } + + function inScope(state, varname) { + for (var v = state.localVars; v; v = v.next) + if (v.name == varname) return true; + } + + function parseJS(state, style, type, content, stream) { + var cc = state.cc; + // Communicate our context to the combinators. + // (Less wasteful than consing up a hundred closures on every call.) + cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; + + if (!state.lexical.hasOwnProperty("align")) + state.lexical.align = true; + + while(true) { + var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; + if (combinator(type, content)) { + while(cc.length && cc[cc.length - 1].lex) + cc.pop()(); + if (cx.marked) return cx.marked; + if (type == "variable" && inScope(state, content)) return "variable-2"; + return style; + } + } + } + + // Combinator utils + + var cx = {state: null, column: null, marked: null, cc: null}; + function pass() { + for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); + } + function cont() { + pass.apply(null, arguments); + return true; + } + function register(varname) { + function inList(list) { + for (var v = list; v; v = v.next) + if (v.name == varname) return true; + return false; + } + var state = cx.state; + if (state.context) { + cx.marked = "def"; + if (inList(state.localVars)) return; + state.localVars = {name: varname, next: state.localVars}; + } else { + if (inList(state.globalVars)) return; + state.globalVars = {name: varname, next: state.globalVars}; + } + } + + // Combinators + + var defaultVars = {name: "this", next: {name: "arguments"}}; + function pushcontext() { + cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; + cx.state.localVars = defaultVars; + } + function popcontext() { + cx.state.localVars = cx.state.context.vars; + cx.state.context = cx.state.context.prev; + } + function pushlex(type, info) { + var result = function() { + var state = cx.state; + state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info); + }; + result.lex = true; + return result; + } + function poplex() { + var state = cx.state; + if (state.lexical.prev) { + if (state.lexical.type == ")") + state.indented = state.lexical.indented; + state.lexical = state.lexical.prev; + } + } + poplex.lex = true; + + function expect(wanted) { + return function(type) { + if (type == wanted) return cont(); + else if (wanted == ";") return pass(); + else return cont(arguments.callee); + }; + } + + function statement(type) { + if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex); + if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); + if (type == "keyword b") return cont(pushlex("form"), statement, poplex); + if (type == "{") return cont(pushlex("}"), block, poplex); + if (type == ";") return cont(); + if (type == "function") return cont(functiondef); + if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), + poplex, statement, poplex); + if (type == "variable") return cont(pushlex("stat"), maybelabel); + if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), + block, poplex, poplex); + if (type == "case") return cont(expression, expect(":")); + if (type == "default") return cont(expect(":")); + if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), + statement, poplex, popcontext); + return pass(pushlex("stat"), expression, expect(";"), poplex); + } + function expression(type) { + if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator); + if (type == "function") return cont(functiondef); + if (type == "keyword c") return cont(maybeexpression); + if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator); + if (type == "operator") return cont(expression); + if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator); + if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator); + return cont(); + } + function maybeexpression(type) { + if (type.match(/[;\}\)\],]/)) return pass(); + return pass(expression); + } + + function maybeoperator(type, value) { + if (type == "operator") { + if (/\+\+|--/.test(value)) return cont(maybeoperator); + if (value == "?") return cont(expression, expect(":"), expression); + return cont(expression); + } + if (type == ";") return; + if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator); + if (type == ".") return cont(property, maybeoperator); + if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); + } + function maybelabel(type) { + if (type == ":") return cont(poplex, statement); + return pass(maybeoperator, expect(";"), poplex); + } + function property(type) { + if (type == "variable") {cx.marked = "property"; return cont();} + } + function objprop(type) { + if (type == "variable") cx.marked = "property"; + if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression); + } + function commasep(what, end) { + function proceed(type) { + if (type == ",") return cont(what, proceed); + if (type == end) return cont(); + return cont(expect(end)); + } + return function(type) { + if (type == end) return cont(); + else return pass(what, proceed); + }; + } + function block(type) { + if (type == "}") return cont(); + return pass(statement, block); + } + function maybetype(type) { + if (type == ":") return cont(typedef); + return pass(); + } + function typedef(type) { + if (type == "variable"){cx.marked = "variable-3"; return cont();} + return pass(); + } + function vardef1(type, value) { + if (type == "variable") { + register(value); + return isTS ? cont(maybetype, vardef2) : cont(vardef2); + } + return pass(); + } + function vardef2(type, value) { + if (value == "=") return cont(expression, vardef2); + if (type == ",") return cont(vardef1); + } + function forspec1(type) { + if (type == "var") return cont(vardef1, expect(";"), forspec2); + if (type == ";") return cont(forspec2); + if (type == "variable") return cont(formaybein); + return cont(forspec2); + } + function formaybein(_type, value) { + if (value == "in") return cont(expression); + return cont(maybeoperator, forspec2); + } + function forspec2(type, value) { + if (type == ";") return cont(forspec3); + if (value == "in") return cont(expression); + return cont(expression, expect(";"), forspec3); + } + function forspec3(type) { + if (type != ")") cont(expression); + } + function functiondef(type, value) { + if (type == "variable") {register(value); return cont(functiondef);} + if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext); + } + function funarg(type, value) { + if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();} + } + + // Interface + + return { + startState: function(basecolumn) { + return { + tokenize: jsTokenBase, + lastType: null, + cc: [], + lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), + localVars: parserConfig.localVars, + globalVars: parserConfig.globalVars, + context: parserConfig.localVars && {vars: parserConfig.localVars}, + indented: 0 + }; + }, + + token: function(stream, state) { + if (stream.sol()) { + if (!state.lexical.hasOwnProperty("align")) + state.lexical.align = false; + state.indented = stream.indentation(); + } + if (stream.eatSpace()) return null; + var style = state.tokenize(stream, state); + if (type == "comment") return style; + state.lastType = type; + return parseJS(state, style, type, content, stream); + }, + + indent: function(state, textAfter) { + if (state.tokenize == jsTokenComment) return CodeMirror.Pass; + if (state.tokenize != jsTokenBase) return 0; + var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; + if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; + var type = lexical.type, closing = firstChar == type; + if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0); + else if (type == "form" && firstChar == "{") return lexical.indented; + else if (type == "form") return lexical.indented + indentUnit; + else if (type == "stat") + return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? indentUnit : 0); + else if (lexical.info == "switch" && !closing) + return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); + else if (lexical.align) return lexical.column + (closing ? 0 : 1); + else return lexical.indented + (closing ? 0 : indentUnit); + }, + + electricChars: ":{}", + + jsonMode: jsonMode + }; +}); + +CodeMirror.defineMIME("text/javascript", "javascript"); +CodeMirror.defineMIME("text/ecmascript", "javascript"); +CodeMirror.defineMIME("application/javascript", "javascript"); +CodeMirror.defineMIME("application/ecmascript", "javascript"); +CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); +CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); +CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); diff --git a/js/live_editor.js b/js/live_editor.js new file mode 100644 index 0000000000..fc2e63379a --- /dev/null +++ b/js/live_editor.js @@ -0,0 +1,98 @@ +/** + * @jsx React.DOM + */ + +var CodeMirrorEditor = React.createClass({displayName: 'CodeMirrorEditor', + componentDidMount: function(root) { + this.editor = CodeMirror.fromTextArea(this.refs.editor.getDOMNode(), { + mode: 'javascript', + lineNumbers: false, + matchBrackets: true, + theme: 'solarized-light' + }); + this.editor.on('change', this.onChange.bind(this)); + this.onChange(); + }, + onChange: function() { + if (this.props.onChange) { + var content = this.editor.getValue(); + this.props.onChange(content); + } + }, + render: function() { + // wrap in a div to fully contain CodeMirror + return ( + React.DOM.div( {className:this.props.className}, + React.DOM.textarea( {ref:"editor"}, this.props.codeText) + ) + ); + } +}); + +var ReactPlayground = React.createClass({displayName: 'ReactPlayground', + MODES: {XJS: 'XJS', JS: 'JS'}, //keyMirror({XJS: true, JS: true}), + + getInitialState: function() { + return {mode: this.MODES.XJS, code: this.props.codeText}; + }, + + bindState: function(name) { + return function(value) { + var newState = {}; + newState[name] = value; + this.setState(newState); + }.bind(this); + }, + + getDesugaredCode: function() { + return JSXTransformer.transform(this.state.code).code; + }, + + render: function() { + var content; + if (this.state.mode === this.MODES.XJS) { + content = + CodeMirrorEditor( + {onChange:this.bindState('code'), + className:"playgroundStage", + codeText:this.state.code}, null + ); + } else if (this.state.mode === this.MODES.JS) { + content = + React.DOM.div( {className:{playgroundJS: true, playgroundStage: true}}, + this.getDesugaredCode() + ); + } + + return ( + React.DOM.div( {className:"playground"}, [ + React.DOM.div( {className:"playgroundCode"}, + content + ), + React.DOM.div( {className:"playgroundPreview"}, + React.DOM.div( {ref:"mount"}, null ) + ) + ]) + ); + }, + componentDidMount: function() { + this.executeCode(); + }, + componentDidUpdate: function() { + this.executeCode(); + }, + executeCode: function() { + var mountNode = this.refs.mount.getDOMNode(); + + try { + React.unmountAndReleaseReactRootNode(mountNode); + } catch (e) { } + + try { + eval(this.getDesugaredCode()); + } catch (e) { + React.renderComponent(React.DOM.div( {content:e.toString(), className:{playgroundError: true}}, null ), mountNode); + } + } +}); + diff --git a/js/react.min.js b/js/react.min.js new file mode 100644 index 0000000000..8804f15e00 --- /dev/null +++ b/js/react.min.js @@ -0,0 +1,19 @@ +/** + * React v0.3.0 + * + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +!function(e){if("function"==typeof bootstrap)bootstrap("react",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeReact=e}else"undefined"!=typeof window?window.React=e():global.React=e()}(function(){return function(e,t,n){function o(n,i){if(!t[n]){if(!e[n]){var a="function"==typeof require&&require;if(!i&&a)return a(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var s=t[n]={exports:{}};e[n][0].call(s.exports,function(t){var r=e[n][1][t];return o(r?r:t)},s,s.exports)}return t[n].exports}for(var r="function"==typeof require&&require,i=0;i=t+n+o,"Can only set one of `children`, `props.content`, or `props.dangerouslySetInnerHTML`."),p(null==e.style||"object"==typeof e.style,"The `style` prop expects a mapping from style properties to values, not a string.")}}function o(e,t){this._tagOpen="<"+e+" ",this._tagClose=t?"":"",this.tagName=e.toUpperCase()}var r=e("./CSSPropertyOperations"),i=e("./DOMPropertyOperations"),a=e("./ReactComponent"),s=e("./ReactEvent"),u=e("./ReactMultiChild"),c=e("./escapeTextForBrowser"),l=e("./flattenChildren"),p=e("./invariant"),d=e("./keyOf"),h=e("./merge"),f=e("./mixInto"),m=s.putListener,v=s.registrationNames,g={string:!0,number:!0},y=d({content:null}),E=d({dangerouslySetInnerHTML:null}),C=d({style:null});o.Mixin={mountComponent:function(e,t){return a.Mixin.mountComponent.call(this,e,t),n(this.props),this._createOpenTagMarkup()+this._createContentMarkup(t)+this._tagClose},_createOpenTagMarkup:function(){var e=this.props,t=this._tagOpen;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n];if(null!=o)if(v[n])m(this._rootNodeID,n,o);else{n===C&&(o&&(o=e.style=h(e.style)),o=r.createMarkupForStyles(o));var a=i.createMarkupForProperty(n,o);a&&(t+=" "+a)}}return t+' id="'+this._rootNodeID+'">'},_createContentMarkup:function(e){var t=this.props.dangerouslySetInnerHTML;if(null!=t){if(null!=t.__html)return t.__html}else{var n=null!=this.props.content?this.props.content:g[typeof this.props.children]?this.props.children:null,o=null!=n?null:this.props.children;if(null!=n)return c(n);if(null!=o)return this.mountMultiChild(l(o),e)}return""},receiveProps:function(e,t){p(this._rootNodeID,"Trying to control a native dom element without a backing id"),n(e),a.Mixin.receiveProps.call(this,e,t),this._updateDOMProperties(e),this._updateDOMChildren(e,t),this.props=e},_updateDOMProperties:function(e){var t=this.props;for(var n in e){var o=e[n],r=t[n];if(e.hasOwnProperty(n)&&o!==r)if(n===C){o&&(o=e.style=h(o));var i;for(var s in o)o.hasOwnProperty(s)&&(r&&r[s]===o[s]||(i||(i={}),i[s]=o[s]));i&&a.DOMIDOperations.updateStylesByID(this._rootNodeID,i)}else if(n===E){var u=r&&r.__html,c=o&&o.__html;u!==c&&a.DOMIDOperations.updateInnerHTMLByID(this._rootNodeID,o)}else n===y?a.DOMIDOperations.updateTextContentByID(this._rootNodeID,""+o):v[n]?m(this._rootNodeID,n,o):a.DOMIDOperations.updatePropertyByID(this._rootNodeID,n,o)}},_updateDOMChildren:function(e,t){var n=typeof this.props.content,o=null==this.props.content||"boolean"===n,r=typeof e.content,i=null==e.content||"boolean"===r,s=o?g[typeof this.props.children]?this.props.children:null:this.props.content,u=i?g[typeof e.children]?e.children:null:e.content,c=null!=s?null:this.props.children,p=null!=u?null:e.children;if(null!=u){var d=null!=c&&null==p;d&&this.updateMultiChild(null,t),s!==u&&a.DOMIDOperations.updateTextContentByID(this._rootNodeID,""+u)}else{var h=null!=s&&null==u;h&&a.DOMIDOperations.updateTextContentByID(this._rootNodeID,""),this.updateMultiChild(l(e.children),t)}},unmountComponent:function(){a.Mixin.unmountComponent.call(this),this.unmountMultiChild(),s.deleteAllListeners(this._rootNodeID)}},f(o,a.Mixin),f(o,o.Mixin),f(o,u.Mixin),t.exports=o},{"./CSSPropertyOperations":32,"./DOMPropertyOperations":34,"./ReactComponent":3,"./ReactEvent":20,"./ReactMultiChild":41,"./escapeTextForBrowser":42,"./flattenChildren":43,"./invariant":10,"./keyOf":44,"./merge":12,"./mixInto":13}],18:[function(e,t){"use strict";function n(e,t){if(r(e),null!=t){r(t);for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])}}var o=e("./mergeHelpers"),r=o.checkMergeObjectArg;t.exports=n},{"./mergeHelpers":45}],20:[function(e,t){"use strict";function n(e,t,n){C(n,t,R.TopLevelCallbackCreator.createTopLevelCallback(e))}function o(e,t,n){D(n,t,R.TopLevelCallbackCreator.createTopLevelCallback(e))}function r(){C(window,"scroll",function(e){e.target===window&&p.refreshAuthoritativeScrollValues()})}function i(){C(window,"resize",function(e){e.target===window&&p.refreshAuthoritativeScrollValues()})}function a(e){v(!M,"listenAtTopLevel(...): Cannot setup top-level listener more than once.");var t=document;r(),i(),n(E.topMouseOver,"mouseover",t),n(E.topMouseDown,"mousedown",t),n(E.topMouseUp,"mouseup",t),n(E.topMouseMove,"mousemove",t),n(E.topMouseOut,"mouseout",t),n(E.topClick,"click",t),n(E.topDoubleClick,"dblclick",t),n(E.topMouseWheel,"mousewheel",t),e&&(n(E.topTouchStart,"touchstart",t),n(E.topTouchEnd,"touchend",t),n(E.topTouchMove,"touchmove",t),n(E.topTouchCancel,"touchcancel",t)),n(E.topKeyUp,"keyup",t),n(E.topKeyPress,"keypress",t),n(E.topKeyDown,"keydown",t),n(E.topChange,"change",t),n(E.topDOMCharacterDataModified,"DOMCharacterDataModified",t),n(E.topMouseWheel,"DOMMouseScroll",t),g("scroll",!0)?o(E.topScroll,"scroll",t):n(E.topScroll,"scroll",window),g("focus",!0)?(o(E.topFocus,"focus",t),o(E.topBlur,"blur",t)):g("focusin")&&(n(E.topFocus,"focusin",t),n(E.topBlur,"focusout",t))}function s(e,t,n,o){var r=h.extractAbstractEvents(e,t,n,o);h.enqueueAbstractEvents(r),h.processAbstractEventQueue()}function u(e){v(f.canUseDOM,"setEnabled(...): Cannot toggle event listening in a Worker thread. This is likely a bug in the framework. Please report immediately."),R.TopLevelCallbackCreator.setEnabled(e)}function c(){return R.TopLevelCallbackCreator.isEnabled()}function l(e,t){v(f.canUseDOM,"ensureListening(...): Cannot toggle event listening in a Worker thread. This is likely a bug in the framework. Please report immediately."),M||(R.TopLevelCallbackCreator=t,a(e),M=!0)}var p=e("./BrowserEnv"),d=e("./EventConstants"),h=e("./EventPluginHub"),f=e("./ExecutionEnvironment"),m=e("./NormalizedEventListener"),v=e("./invariant"),g=e("./isEventSupported"),y=h.registrationNames,E=d.topLevelTypes,C=m.listen,D=m.capture,M=!1,R={TopLevelCallbackCreator:null,handleTopLevel:s,setEnabled:u,isEnabled:c,ensureListening:l,registrationNames:y,putListener:h.putListener,getListener:h.getListener,deleteAllListeners:h.deleteAllListeners,trapBubbledEvent:n,trapCapturedEvent:o};t.exports=R},{"./BrowserEnv":46,"./EventConstants":47,"./EventPluginHub":27,"./ExecutionEnvironment":14,"./NormalizedEventListener":48,"./invariant":10,"./isEventSupported":49}],21:[function(e,t){"use strict";function n(e,t){return e.charAt(t)===c||t===e.length}function o(e){return""===e||e.charAt(0)===c&&e.charAt(e.length-1)!==c}function r(e){var t=s(e);return t&&t.charAt(0)===c}function i(e){return e?e.substr(0,e.lastIndexOf(c)):""}function a(e,t,n,o,r,a){e=e||"",t=t||"",u(e!==t,"traverseParentPath(...): Cannot traverse from and to the same ID, `%s`.",e);var s=d.getFirstCommonAncestorID(e,t),c=s===t;u(c||s===e,"traverseParentPath(%s, %s, ...): Cannot traverse from two IDs that do not have a parent path.",e,t);for(var l=0,h=c?i:d.nextDescendantID,f=e;r&&f===e||a&&f===t||n(f,c,o),f!==t;f=h(f,t))u(l++=a;a++)if(n(e,a)&&n(t,a))i=a;else if(e.charAt(a)!==t.charAt(a))break;var s=e.substr(0,i);return u(o(s),"getFirstCommonAncestorID(%s, %s): Expected a valid React DOM ID: %s",e,t,s),s},getReactRootID:function(e){return".reactRoot["+e+"]"},getReactRootIDFromNodeID:function(e){var t=/\.reactRoot\[[^\]]+\]/.exec(e);return t&&t[0]},traverseEnterLeave:function(e,t,n,o,r){var i=d.getFirstCommonAncestorID(e,t);i!==e&&a(e,i,n,o,!1,!0),i!==t&&a(i,t,n,r,!0,!1)},traverseTwoPhase:function(e,t,n){e&&(a("",e,t,n,!0,!1),a(e,"",t,n,!1,!0))},nextDescendantID:function(e,t){u(o(e)&&o(t),"nextDescendantID(%s, %s): Received an invalid React DOM ID.",e,t);var r=d.getFirstCommonAncestorID(e,t);if(u(r===e,"nextDescendantID(...): React has made an invalid assumption about the DOM hierarchy. Expected `%s` to be an ancestor of `%s`.",e,t),e===t)return e;for(var i=e.length+l,a=i;as;s++){var u=i[s],l=u&&u.extractAbstractEvents(e,t,n,o); +l&&(r=c(r,l))}return r},M=function(e){e&&(E=c(E,e))},R=function(e){if(e){var t=o(e),n=t&&t.executeDispatch;a.executeDispatchesInOrder(e,n||a.executeDispatch),r.release(e)}},I=function(){var e=E;E=null,l(e,R)},O={registrationNames:g,registrationNamesArr:y,putListener:i.putListener,getListener:i.getListener,deleteAllListeners:C,extractAbstractEvents:D,enqueueAbstractEvents:M,processAbstractEventQueue:I,injection:v};u.canUseDOM&&(window.EventPluginHub=O),t.exports=O}()},{"./AbstractEvent":53,"./CallbackRegistry":54,"./EventPluginUtils":55,"./EventPropagators":52,"./ExecutionEnvironment":14,"./accumulate":56,"./forEachAccumulated":57,"./keyMirror":11,"./merge":12,"./throwIf":31}],28:[function(e,t){"use strict";var n=e("./AbstractEvent"),o=e("./EventConstants"),r=e("./EventPropagators"),i=e("./keyOf"),a=o.topLevelTypes,s={abstractEventTypes:{mouseDown:{phasedRegistrationNames:{bubbled:i({onMouseDown:!0}),captured:i({onMouseDownCapture:!0})}},mouseUp:{phasedRegistrationNames:{bubbled:i({onMouseUp:!0}),captured:i({onMouseUpCapture:!0})}},mouseMove:{phasedRegistrationNames:{bubbled:i({onMouseMove:!0}),captured:i({onMouseMoveCapture:!0})}},doubleClick:{phasedRegistrationNames:{bubbled:i({onDoubleClick:!0}),captured:i({onDoubleClickCapture:!0})}},click:{phasedRegistrationNames:{bubbled:i({onClick:!0}),captured:i({onClickCapture:!0})}},mouseWheel:{phasedRegistrationNames:{bubbled:i({onMouseWheel:!0}),captured:i({onMouseWheelCapture:!0})}},touchStart:{phasedRegistrationNames:{bubbled:i({onTouchStart:!0}),captured:i({onTouchStartCapture:!0})}},touchEnd:{phasedRegistrationNames:{bubbled:i({onTouchEnd:!0}),captured:i({onTouchEndCapture:!0})}},touchCancel:{phasedRegistrationNames:{bubbled:i({onTouchCancel:!0}),captured:i({onTouchCancelCapture:!0})}},touchMove:{phasedRegistrationNames:{bubbled:i({onTouchMove:!0}),captured:i({onTouchMoveCapture:!0})}},keyUp:{phasedRegistrationNames:{bubbled:i({onKeyUp:!0}),captured:i({onKeyUpCapture:!0})}},keyPress:{phasedRegistrationNames:{bubbled:i({onKeyPress:!0}),captured:i({onKeyPressCapture:!0})}},keyDown:{phasedRegistrationNames:{bubbled:i({onKeyDown:!0}),captured:i({onKeyDownCapture:!0})}},focus:{phasedRegistrationNames:{bubbled:i({onFocus:!0}),captured:i({onFocusCapture:!0})}},blur:{phasedRegistrationNames:{bubbled:i({onBlur:!0}),captured:i({onBlurCapture:!0})}},scroll:{phasedRegistrationNames:{bubbled:i({onScroll:!0}),captured:i({onScrollCapture:!0})}},change:{phasedRegistrationNames:{bubbled:i({onChange:!0}),captured:i({onChangeCapture:!0})}},submit:{phasedRegistrationNames:{bubbled:i({onSubmit:!0}),captured:i({onSubmitCapture:!0})}},DOMCharacterDataModified:{phasedRegistrationNames:{bubbled:i({onDOMCharacterDataModified:!0}),captured:i({onDOMCharacterDataModifiedCapture:!0})}}},executeDispatch:function(e,t,n){var o=t(e,n);o===!1&&(e.stopPropagation(),e.preventDefault())},extractAbstractEvents:function(e,t,o,i){var u,c=s.topLevelTypesToAbstract[e];if(!c)return null;switch(e){case a.topMouseWheel:u=n.normalizeMouseWheelData(t);break;case a.topScroll:u=n.normalizeScrollDataFromTarget(i);break;case a.topClick:case a.topDoubleClick:case a.topChange:case a.topDOMCharacterDataModified:case a.topMouseDown:case a.topMouseUp:case a.topMouseMove:case a.topTouchMove:case a.topTouchStart:case a.topTouchEnd:u=n.normalizePointerData(t);break;default:u=null}var l=n.getPooled(c,o,e,t,u);return r.accumulateTwoPhaseDispatches(l),l}};s.topLevelTypesToAbstract={topMouseDown:s.abstractEventTypes.mouseDown,topMouseUp:s.abstractEventTypes.mouseUp,topMouseMove:s.abstractEventTypes.mouseMove,topClick:s.abstractEventTypes.click,topDoubleClick:s.abstractEventTypes.doubleClick,topMouseWheel:s.abstractEventTypes.mouseWheel,topTouchStart:s.abstractEventTypes.touchStart,topTouchEnd:s.abstractEventTypes.touchEnd,topTouchMove:s.abstractEventTypes.touchMove,topTouchCancel:s.abstractEventTypes.touchCancel,topKeyUp:s.abstractEventTypes.keyUp,topKeyPress:s.abstractEventTypes.keyPress,topKeyDown:s.abstractEventTypes.keyDown,topFocus:s.abstractEventTypes.focus,topBlur:s.abstractEventTypes.blur,topScroll:s.abstractEventTypes.scroll,topChange:s.abstractEventTypes.change,topSubmit:s.abstractEventTypes.submit,topDOMCharacterDataModified:s.abstractEventTypes.DOMCharacterDataModified},t.exports=s},{"./AbstractEvent":53,"./EventConstants":47,"./EventPropagators":52,"./keyOf":44}],30:[function(e,t){"use strict";function n(e){e||(e="");var t,n=arguments.length;if(n>1)for(var o=1;n>o;o++)t=arguments[o],t&&(e+=" "+t);return e}t.exports=n},{}],31:[function(e,t){"use strict";var n=function(e,t){if(e)throw new Error(t)};t.exports=n},{}],37:[function(e,t){"use strict";var n=function(e){var t=this;if(t.instancePool.length){var n=t.instancePool.pop();return t.call(n,e),n}return new t(e)},o=function(e,t){var n=this;if(n.instancePool.length){var o=n.instancePool.pop();return n.call(o,e,t),o}return new n(e,t)},r=function(e,t,n,o,r){var i=this;if(i.instancePool.length){var a=i.instancePool.pop();return i.call(a,e,t,n,o,r),a}return new i(e,t,n,o,r)},i=function(e){var t=this;e.destructor&&e.destructor(),t.instancePool.lengtht;t++){var o=e[t].component,r=e[t].callback;r.call(o,o.getDOMNode())}e.length=0}},reset:function(){this._queue=null},destructor:function(){this.reset()}}),o.addPoolingTo(n),t.exports=n},{"./PooledClass":37,"./mixInto":13}],40:[function(e,t){!function(){"use strict";var n=e("./throwIf"),o="DUAL_TRANSACTION",r="MISSING_TRANSACTION",i={reinitializeTransaction:function(){this.transactionWrappers=this.getTransactionWrappers(),this.wrapperInitData?this.wrapperInitData.length=0:this.wrapperInitData=[],this.timingMetrics||(this.timingMetrics={}),this.timingMetrics.methodInvocationTime=0,this.timingMetrics.wrapperInitTimes?this.timingMetrics.wrapperInitTimes.length=0:this.timingMetrics.wrapperInitTimes=[],this.timingMetrics.wrapperCloseTimes?this.timingMetrics.wrapperCloseTimes.length=0:this.timingMetrics.wrapperCloseTimes=[],this._isInTransaction=!1},_isInTransaction:!1,getTransactionWrappers:null,isInTransaction:function(){return!!this._isInTransaction},perform:function(e,t,r,i,a,s,u,c){n(this.isInTransaction(),o);var l,p=Date.now(),d=null;try{this.initializeAll(),l=e.call(t,r,i,a,s,u,c)}catch(h){d=h}finally{var f=Date.now();this.methodInvocationTime+=f-p;try{this.closeAll()}catch(m){d=d||m}}if(d)throw d;return l},initializeAll:function(){this._isInTransaction=!0;for(var e=this.transactionWrappers,t=this.timingMetrics.wrapperInitTimes,n=null,o=0;o":">","<":"<",'"':""","'":"'","/":"/"},r=function(e){var t=typeof e,o="object"===t;return""===e||o?"":"string"===t?e.replace(/[&><"'\/]/g,n):(""+e).replace(/[&><"'\/]/g,n)};t.exports=r},{"./throwIf":31}],43:[function(e,t){"use strict";function n(e){if(null===e||void 0===e)return e;var t={};return u(t,e,""),t}var o=e("./ReactTextComponent"),r=e("./escapeTextForBrowser"),i=e("./throwIf"),a="INVALID_CHILD",s="0",u=function(e,t,n){if(Array.isArray(t))for(var c=0;c=r,i.MERGE_DEEP_MAX_LEVELS)},checkArrayStrategy:function(e){o(void 0!==e&&!(e in s.ArrayStrategies),i.MERGE_DEEP_NO_ARR_STRATEGY)},ArrayStrategies:n({Clobber:!0,IndexByIndex:!0}),ERRORS:i};t.exports=s},{"./keyMirror":11,"./throwIf":31}],47:[function(e,t){"use strict";var n=e("./keyMirror"),o=n({bubbled:null,captured:null}),r=n({topBlur:null,topChange:null,topClick:null,topDOMCharacterDataModified:null,topDoubleClick:null,topFocus:null,topKeyDown:null,topKeyPress:null,topKeyUp:null,topMouseDown:null,topMouseMove:null,topMouseOut:null,topMouseOver:null,topMouseUp:null,topMouseWheel:null,topScroll:null,topSubmit:null,topTouchCancel:null,topTouchEnd:null,topTouchMove:null,topTouchStart:null}),i={topLevelTypes:r,PropagationPhases:o};t.exports=i},{"./keyMirror":11}],48:[function(e,t){"use strict";function n(e){var t=e||window.event,n="target"in t,o=t.target||t.srcElement||window,r=3===o.nodeType?o.parentNode:o;return n&&t.target===r||(t=Object.create(t),t.target=r),t}function o(e){return function(t){e(n(t))}}var r=e("./EventListener"),i={listen:function(e,t,n){r.listen(e,t,o(n))},capture:function(e,t,n){r.capture(e,t,o(n))}};t.exports=i},{"./EventListener":66}],49:[function(e,t){"use strict";function n(e,t){if(!o||t&&!o.addEventListener)return!1;var n=document.createElement("div"),r="on"+e,i=r in n;return i||(n.setAttribute(r,""),i="function"==typeof n[r],"undefined"!=typeof n[r]&&(n[r]=void 0),n.removeAttribute(r)),n=null,i}var o,r=e("./ExecutionEnvironment");r.canUseDOM&&(o=document.createElement("div")),t.exports=n},{"./ExecutionEnvironment":14}],52:[function(e,t){"use strict";function n(e,t,n){var o=t.type.phasedRegistrationNames[n];return f(e,o)}function o(e,t,o){var r=t?m.bubbled:m.captured,i=n(e,o,r);i&&(o._dispatchListeners=d(o._dispatchListeners,i),o._dispatchIDs=d(o._dispatchIDs,e))}function r(e){e&&e.type.phasedRegistrationNames&&v.InstanceHandle.traverseTwoPhase(e.abstractTargetID,o,e)}function i(e,t,n){if(n&&n.type.registrationName){var o=f(e,n.type.registrationName);o&&(n._dispatchListeners=d(n._dispatchListeners,o),n._dispatchIDs=d(n._dispatchIDs,e))}}function a(e){e&&e.type.registrationName&&i(e.abstractTargetID,null,e)}function s(e){h(e,r)}function u(e,t,n,o){v.InstanceHandle.traverseEnterLeave(n,o,i,e,t)}function c(e){h(e,a)}var l=e("./CallbackRegistry"),p=e("./EventConstants"),d=e("./accumulate"),h=e("./forEachAccumulated"),f=l.getListener,m=p.PropagationPhases,v={InstanceHandle:null,injectInstanceHandle:function(e){v.InstanceHandle=e},validate:function(){var e=!v.InstanceHandle||!v.InstanceHandle.traverseTwoPhase||!v.InstanceHandle.traverseEnterLeave;if(e)throw new Error("InstanceHandle not injected before use!")}},g={accumulateTwoPhaseDispatches:s,accumulateDirectDispatches:c,accumulateEnterLeaveDispatches:u,injection:v};t.exports=g},{"./CallbackRegistry":54,"./EventConstants":47,"./accumulate":56,"./forEachAccumulated":57}],53:[function(e,t){"use strict";function n(e,t,n,o,r){this.type=e,this.abstractTargetID=t||"",this.originatingTopLevelEventType=n,this.nativeEvent=o,this.data=r,this.target=o&&o.target,this._dispatchListeners=null,this._dispatchIDs=null,this.isPropagationStopped=!1}var o=e("./BrowserEnv"),r=e("./PooledClass"),i=e("./TouchEventUtils");e("./throwIf");var a=20;n.poolSize=a,n.prototype.destructor=function(){this.target=null,this._dispatchListeners=null,this._dispatchIDs=null},r.addPoolingTo(n,r.fiveArgumentPooler),n.prototype.stopPropagation=function(){this.isPropagationStopped=!0,this.nativeEvent.stopPropagation&&this.nativeEvent.stopPropagation(),this.nativeEvent.cancelBubble=!0},n.prototype.preventDefault=function(){n.preventDefaultOnNativeEvent(this.nativeEvent)},n.preventDefaultOnNativeEvent=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},n.normalizeScrollDataFromTarget=function(e){return{scrollTop:e.scrollTop,scrollLeft:e.scrollLeft,clientWidth:e.clientWidth,clientHeight:e.clientHeight,scrollHeight:e.scrollHeight,scrollWidth:e.scrollWidth}},n.normalizeMouseWheelData=function(e){var t=0,n=0,o=0;return e.wheelDelta&&(t=e.wheelDelta/120),e.detail&&(t=-e.detail/3),o=t,void 0!==e.axis&&e.axis===e.HORIZONTAL_AXIS&&(o=0,n=-t),void 0!==e.wheelDeltaY&&(o=e.wheelDeltaY/120),void 0!==e.wheelDeltaX&&(n=-e.wheelDeltaX/120),{delta:t,deltaX:n,deltaY:o}},n.isNativeClickEventRightClick=function(e){return e.which?3===e.which:e.button?2===e.button:!1},n.normalizePointerData=function(e){return{globalX:n.eventPageX(e),globalY:n.eventPageY(e),rightMouseButton:n.isNativeClickEventRightClick(e)}},n.normalizeDragEventData=function(e,t,n,o,r){return{globalX:t,globalY:n,startX:o,startY:r}},n.eventPageY=function(e){var t=i.extractSingleTouch(e);return t?t.pageY:"undefined"!=typeof e.pageY?e.pageY:e.clientY+o.currentPageScrollTop},n.eventPageX=function(e){var t=i.extractSingleTouch(e);return t?t.pageX:"undefined"!=typeof e.pageX?e.pageX:e.clientX+o.currentPageScrollLeft},n.persistentCloneOf=function(e){return new n(e.type,e.abstractTargetID,e.originatingTopLevelEventType,e.nativeEvent,e.data,e.target)},t.exports=n},{"./BrowserEnv":46,"./PooledClass":37,"./TouchEventUtils":67,"./throwIf":31}],55:[function(e,t){"use strict";function n(e){return e===v.topMouseUp||e===v.topTouchEnd||e===v.topTouchCancel}function o(e){return e===v.topMouseMove||e===v.topTouchMove}function r(e){return e===v.topMouseDown||e===v.topTouchStart}function i(e,t){var n=f.eventPageX(t),o=f.eventPageY(t);e.pageX=n,e.pageY=o}function a(e,t){var n=f.eventPageX(t),o=f.eventPageY(t);return Math.pow(Math.pow(n-e.pageX,2)+Math.pow(o-e.pageY,2),.5)}function s(e,t){var n=e._dispatchListeners,o=e._dispatchIDs;if(Array.isArray(n)){var r;for(r=0;r=o.length?e.appendChild(t):e.insertBefore(t,o[n]),t)}t.exports=n},{}],66:[function(e,t){var n={listen:function(e,t,n){e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n)},capture:function(e,t,n){return e.addEventListener?(e.addEventListener(t,n,!0),void 0):(console.error("You are attempting to use addEventlistener in a browser that does not support it support it.This likely means that you will not receive events that your application relies on (such as scroll)."),void 0)}};t.exports=n},{}],67:[function(e,t){var n={extractSingleTouch:function(e){var t=e.touches,n=e.changedTouches,o=t&&t.length>0,r=n&&n.length>0;return!o&&r?n[0]:o?t[0]:e}};t.exports=n},{}],59:[function(e,t){"use strict";function n(e,t){return null===t||t===!1||t===!0||""===t?"":isNaN(t)?t?""+t:"":o.isNumber[e]?""+t:t+"px"}var o=e("./CSSProperty");t.exports=n},{"./CSSProperty":68}],62:[function(e,t){"use strict";function n(e){var t=e.tagName;return s[t]||(s[t]=document.createElement(t))}function o(e,t,n){return n?n.nextSibling?e.insertBefore(t,n.nextSibling):e.appendChild(t):e.insertBefore(t,e.firstChild)}function r(e,t,n){for(var r,i=t.length,a=0;i>a;a++)r=o(e,t[0],r||n)}function i(e,t,o){var i=n(e);i.innerHTML=t;var a=i.childNodes,s=o?e.childNodes[o-1]:null;r(e,a,s)}function a(e,t){var o=e.parentNode,r=n(o);r.innerHTML=t;var i=r.childNodes;o.replaceChild(i[0],e)}e("./ExecutionEnvironment"),e("./throwIf");var s={},u={dangerouslyInsertMarkupAt:i,dangerouslyReplaceNodeWithMarkup:a};t.exports=u},{"./ExecutionEnvironment":14,"./throwIf":31}],64:[function(e,t){"use strict";var n=e("./invariant"),o={isStandardName:{},getAttributeName:{},getPropertyName:{},getMutationMethod:{},mustUseAttribute:{},mustUseProperty:{},hasBooleanValue:{},hasSideEffects:{},isCustomAttribute:RegExp.prototype.test.bind(/^(data|aria)-[a-z_][a-z\d_.\-]*$/)},r=1,i=2,a=4,s=8,u={accept:null,action:null,ajaxify:r,allowFullScreen:r|a,alt:null,autoComplete:null,autoplay:a,cellPadding:null,cellSpacing:null,checked:i|a,className:i,colSpan:null,contentEditable:null,controls:i|a,data:null,dir:null,disabled:i|a,enctype:null,height:null,href:null,htmlFor:null,method:null,multiple:i|a,name:null,poster:null,preload:null,placeholder:null,rel:null,required:a,role:r,scrollLeft:i,scrollTop:i,selected:i|a,spellCheck:null,src:null,style:null,tabIndex:null,target:null,title:null,type:null,value:i|s,width:null,wmode:r,cx:i,cy:i,d:i,fill:i,fx:i,fy:i,points:i,r:i,stroke:i,strokeLinecap:i,strokeWidth:i,transform:i,x:i,x1:i,x2:i,version:i,viewBox:i,y:i,y1:i,y2:i,spreadMethod:i,offset:i,stopColor:i,stopOpacity:i,gradientUnits:i,gradientTransform:i},c={className:"class",htmlFor:"for",strokeLinecap:"stroke-linecap",strokeWidth:"stroke-width",stopColor:"stop-color",stopOpacity:"stop-opacity"},l={autoComplete:"autocomplete",spellCheck:"spellcheck"},p={className:function(e,t){e.className=t||""}};for(var d in u){o.isStandardName[d]=!0,o.getAttributeName[d]=c[d]||d.toLowerCase(),o.getPropertyName[d]=l[d]||d;var h=p[d];h&&(o.getMutationMethod[d]=h);var f=u[d];o.mustUseAttribute[d]=f&r,o.mustUseProperty[d]=f&i,o.hasBooleanValue[d]=f&a,o.hasSideEffects[d]=f&s,n(!o.mustUseAttribute[d]||!o.mustUseProperty[d],"DOMProperty: Cannot use require using both attribute and property: %s",d),n(o.mustUseProperty[d]||!o.hasSideEffects[d],"DOMProperty: Properties that have side effects must use property: %s",d)}t.exports=o},{"./invariant":10}],65:[function(e,t){"use strict";var n=e("./ReactComponent"),o=e("./escapeTextForBrowser"),r=e("./mixInto"),i=function(e){this.construct({text:e})};r(i,n.Mixin),r(i,{mountComponent:function(e){return n.Mixin.mountComponent.call(this,e),''+o(this.props.text)+""},receiveProps:function(e){e.text!==this.props.text&&(this.props.text=e.text,n.DOMIDOperations.updateTextContentByID(this._rootNodeID,e.text))}}),t.exports=i},{"./ReactComponent":3,"./escapeTextForBrowser":42,"./mixInto":13}],68:[function(e,t){"use strict";var n={fillOpacity:!0,fontWeight:!0,opacity:!0,orphans:!0,textDecoration:!0,zIndex:!0,zoom:!0},o={isNumber:n};t.exports=o},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/js/showdown.js b/js/showdown.js new file mode 100644 index 0000000000..43920d95c2 --- /dev/null +++ b/js/showdown.js @@ -0,0 +1,1302 @@ +// +// showdown.js -- A javascript port of Markdown. +// +// Copyright (c) 2007 John Fraser. +// +// Original Markdown Copyright (c) 2004-2005 John Gruber +// +// +// Redistributable under a BSD-style open source license. +// See license.txt for more information. +// +// The full source distribution is at: +// +// A A L +// T C A +// T K B +// +// +// + +// +// Wherever possible, Showdown is a straight, line-by-line port +// of the Perl version of Markdown. +// +// This is not a normal parser design; it's basically just a +// series of string substitutions. It's hard to read and +// maintain this way, but keeping Showdown close to the original +// design makes it easier to port new features. +// +// More importantly, Showdown behaves like markdown.pl in most +// edge cases. So web applications can do client-side preview +// in Javascript, and then build identical HTML on the server. +// +// This port needs the new RegExp functionality of ECMA 262, +// 3rd Edition (i.e. Javascript 1.5). Most modern web browsers +// should do fine. Even with the new regular expression features, +// We do a lot of work to emulate Perl's regex functionality. +// The tricky changes in this file mostly have the "attacklab:" +// label. Major or self-explanatory changes don't. +// +// Smart diff tools like Araxis Merge will be able to match up +// this file with markdown.pl in a useful way. A little tweaking +// helps: in a copy of markdown.pl, replace "#" with "//" and +// replace "$text" with "text". Be sure to ignore whitespace +// and line endings. +// + + +// +// Showdown usage: +// +// var text = "Markdown *rocks*."; +// +// var converter = new Showdown.converter(); +// var html = converter.makeHtml(text); +// +// alert(html); +// +// Note: move the sample code to the bottom of this +// file before uncommenting it. +// + + +// +// Showdown namespace +// +var Showdown = {}; + +// +// converter +// +// Wraps all "globals" so that the only thing +// exposed is makeHtml(). +// +Showdown.converter = function() { + +// +// Globals: +// + +// Global hashes, used by various utility routines +var g_urls; +var g_titles; +var g_html_blocks; + +// Used to track when we're inside an ordered or unordered list +// (see _ProcessListItems() for details): +var g_list_level = 0; + + +this.makeHtml = function(text) { +// +// Main function. The order in which other subs are called here is +// essential. Link and image substitutions need to happen before +// _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the +// and tags get encoded. +// + + // Clear the global hashes. If we don't clear these, you get conflicts + // from other articles when generating a page which contains more than + // one article (e.g. an index page that shows the N most recent + // articles): + g_urls = new Array(); + g_titles = new Array(); + g_html_blocks = new Array(); + + // attacklab: Replace ~ with ~T + // This lets us use tilde as an escape char to avoid md5 hashes + // The choice of character is arbitray; anything that isn't + // magic in Markdown will work. + text = text.replace(/~/g,"~T"); + + // attacklab: Replace $ with ~D + // RegExp interprets $ as a special character + // when it's in a replacement string + text = text.replace(/\$/g,"~D"); + + // Standardize line endings + text = text.replace(/\r\n/g,"\n"); // DOS to Unix + text = text.replace(/\r/g,"\n"); // Mac to Unix + + // Make sure text begins and ends with a couple of newlines: + text = "\n\n" + text + "\n\n"; + + // Convert all tabs to spaces. + text = _Detab(text); + + // Strip any lines consisting only of spaces and tabs. + // This makes subsequent regexen easier to write, because we can + // match consecutive blank lines with /\n+/ instead of something + // contorted like /[ \t]*\n+/ . + text = text.replace(/^[ \t]+$/mg,""); + + // Turn block-level HTML blocks into hash entries + text = _HashHTMLBlocks(text); + + // Strip link definitions, store in hashes. + text = _StripLinkDefinitions(text); + + text = _RunBlockGamut(text); + + text = _UnescapeSpecialChars(text); + + // attacklab: Restore dollar signs + text = text.replace(/~D/g,"$$"); + + // attacklab: Restore tildes + text = text.replace(/~T/g,"~"); + + return text; +} + + +var _StripLinkDefinitions = function(text) { +// +// Strips link definitions from text, stores the URLs and titles in +// hash references. +// + + // Link defs are in the form: ^[id]: url "optional title" + + /* + var text = text.replace(/ + ^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1 + [ \t]* + \n? // maybe *one* newline + [ \t]* + ? // url = $2 + [ \t]* + \n? // maybe one newline + [ \t]* + (?: + (\n*) // any lines skipped = $3 attacklab: lookbehind removed + ["(] + (.+?) // title = $4 + [")] + [ \t]* + )? // title is optional + (?:\n+|$) + /gm, + function(){...}); + */ + var text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm, + function (wholeMatch,m1,m2,m3,m4) { + m1 = m1.toLowerCase(); + g_urls[m1] = _EncodeAmpsAndAngles(m2); // Link IDs are case-insensitive + if (m3) { + // Oops, found blank lines, so it's not a title. + // Put back the parenthetical statement we stole. + return m3+m4; + } else if (m4) { + g_titles[m1] = m4.replace(/"/g,"""); + } + + // Completely remove the definition from the text + return ""; + } + ); + + return text; +} + + +var _HashHTMLBlocks = function(text) { + // attacklab: Double up blank lines to reduce lookaround + text = text.replace(/\n/g,"\n\n"); + + // Hashify HTML blocks: + // We only want to do this for block-level HTML tags, such as headers, + // lists, and tables. That's because we still want to wrap

    s around + // "paragraphs" that are wrapped in non-block-level tags, such as anchors, + // phrase emphasis, and spans. The list of tags we're looking for is + // hard-coded: + var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del" + var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math" + + // First, look for nested blocks, e.g.: + //

    + //
    + // tags for inner block must be indented. + //
    + //
    + // + // The outermost tags must start at the left margin for this to match, and + // the inner nested divs must be indented. + // We need to do this before the next, more liberal match, because the next + // match will start at the first `
    ` and stop at the first `
    `. + + // attacklab: This regex can be expensive when it fails. + /* + var text = text.replace(/ + ( // save in $1 + ^ // start of line (with /m) + <($block_tags_a) // start tag = $2 + \b // word break + // attacklab: hack around khtml/pcre bug... + [^\r]*?\n // any number of lines, minimally matching + // the matching end tag + [ \t]* // trailing spaces/tabs + (?=\n+) // followed by a newline + ) // attacklab: there are sentinel newlines at end of document + /gm,function(){...}}; + */ + text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,hashElement); + + // + // Now match more liberally, simply from `\n` to `\n` + // + + /* + var text = text.replace(/ + ( // save in $1 + ^ // start of line (with /m) + <($block_tags_b) // start tag = $2 + \b // word break + // attacklab: hack around khtml/pcre bug... + [^\r]*? // any number of lines, minimally matching + .* // the matching end tag + [ \t]* // trailing spaces/tabs + (?=\n+) // followed by a newline + ) // attacklab: there are sentinel newlines at end of document + /gm,function(){...}}; + */ + text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,hashElement); + + // Special case just for
    . It was easier to make a special case than + // to make the other regex more complicated. + + /* + text = text.replace(/ + ( // save in $1 + \n\n // Starting after a blank line + [ ]{0,3} + (<(hr) // start tag = $2 + \b // word break + ([^<>])*? // + \/?>) // the matching end tag + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,hashElement); + + // Special case for standalone HTML comments: + + /* + text = text.replace(/ + ( // save in $1 + \n\n // Starting after a blank line + [ ]{0,3} // attacklab: g_tab_width - 1 + + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(\n\n[ ]{0,3}[ \t]*(?=\n{2,}))/g,hashElement); + + // PHP and ASP-style processor instructions ( and <%...%>) + + /* + text = text.replace(/ + (?: + \n\n // Starting after a blank line + ) + ( // save in $1 + [ ]{0,3} // attacklab: g_tab_width - 1 + (?: + <([?%]) // $2 + [^\r]*? + \2> + ) + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,hashElement); + + // attacklab: Undo double lines (see comment at top of this function) + text = text.replace(/\n\n/g,"\n"); + return text; +} + +var hashElement = function(wholeMatch,m1) { + var blockText = m1; + + // Undo double lines + blockText = blockText.replace(/\n\n/g,"\n"); + blockText = blockText.replace(/^\n/,""); + + // strip trailing blank lines + blockText = blockText.replace(/\n+$/g,""); + + // Replace the element text with a marker ("~KxK" where x is its key) + blockText = "\n\n~K" + (g_html_blocks.push(blockText)-1) + "K\n\n"; + + return blockText; +}; + +var _RunBlockGamut = function(text) { +// +// These are all the transformations that form block-level +// tags like paragraphs, headers, and list items. +// + text = _DoHeaders(text); + + // Do Horizontal Rules: + var key = hashBlock("
    "); + text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key); + text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,key); + text = text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,key); + + text = _DoLists(text); + text = _DoCodeBlocks(text); + text = _DoBlockQuotes(text); + + // We already ran _HashHTMLBlocks() before, in Markdown(), but that + // was to escape raw HTML in the original Markdown source. This time, + // we're escaping the markup we've just created, so that we don't wrap + //

    tags around block-level tags. + text = _HashHTMLBlocks(text); + text = _FormParagraphs(text); + + return text; +} + + +var _RunSpanGamut = function(text) { +// +// These are all the transformations that occur *within* block-level +// tags like paragraphs, headers, and list items. +// + + text = _DoCodeSpans(text); + text = _EscapeSpecialCharsWithinTagAttributes(text); + text = _EncodeBackslashEscapes(text); + + // Process anchor and image tags. Images must come first, + // because ![foo][f] looks like an anchor. + text = _DoImages(text); + text = _DoAnchors(text); + + // Make links out of things like `` + // Must come after _DoAnchors(), because you can use < and > + // delimiters in inline links like [this](). + text = _DoAutoLinks(text); + text = _EncodeAmpsAndAngles(text); + text = _DoItalicsAndBold(text); + + // Do hard breaks: + text = text.replace(/ +\n/g,"
    \n"); + + return text; +} + +var _EscapeSpecialCharsWithinTagAttributes = function(text) { +// +// Within tags -- meaning between < and > -- encode [\ ` * _] so they +// don't conflict with their use in Markdown for code, italics and strong. +// + + // Build a regex to find HTML tags and comments. See Friedl's + // "Mastering Regular Expressions", 2nd Ed., pp. 200-201. + var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|)/gi; + + text = text.replace(regex, function(wholeMatch) { + var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g,"$1`"); + tag = escapeCharacters(tag,"\\`*_"); + return tag; + }); + + return text; +} + +var _DoAnchors = function(text) { +// +// Turn Markdown link shortcuts into XHTML
    tags. +// + // + // First, handle reference-style links: [link text] [id] + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ( + (?: + \[[^\]]*\] // allow brackets nested one level + | + [^\[] // or anything else + )* + ) + \] + + [ ]? // one optional space + (?:\n[ ]*)? // one optional newline followed by spaces + + \[ + (.*?) // id = $3 + \] + )()()()() // pad remaining backreferences + /g,_DoAnchors_callback); + */ + text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeAnchorTag); + + // + // Next, inline-style links: [link text](url "optional title") + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ( + (?: + \[[^\]]*\] // allow brackets nested one level + | + [^\[\]] // or anything else + ) + ) + \] + \( // literal paren + [ \t]* + () // no id, so leave $3 empty + ? // href = $4 + [ \t]* + ( // $5 + (['"]) // quote char = $6 + (.*?) // Title = $7 + \6 // matching quote + [ \t]* // ignore any spaces/tabs between closing quote and ) + )? // title is optional + \) + ) + /g,writeAnchorTag); + */ + text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeAnchorTag); + + // + // Last, handle reference-style shortcuts: [link text] + // These must come last in case you've also got [link test][1] + // or [link test](/foo) + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ([^\[\]]+) // link text = $2; can't contain '[' or ']' + \] + )()()()()() // pad rest of backreferences + /g, writeAnchorTag); + */ + text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag); + + return text; +} + +var writeAnchorTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) { + if (m7 == undefined) m7 = ""; + var whole_match = m1; + var link_text = m2; + var link_id = m3.toLowerCase(); + var url = m4; + var title = m7; + + if (url == "") { + if (link_id == "") { + // lower-case and turn embedded newlines into spaces + link_id = link_text.toLowerCase().replace(/ ?\n/g," "); + } + url = "#"+link_id; + + if (g_urls[link_id] != undefined) { + url = g_urls[link_id]; + if (g_titles[link_id] != undefined) { + title = g_titles[link_id]; + } + } + else { + if (whole_match.search(/\(\s*\)$/m)>-1) { + // Special case for explicit empty url + url = ""; + } else { + return whole_match; + } + } + } + + url = escapeCharacters(url,"*_"); + var result = ""; + + return result; +} + + +var _DoImages = function(text) { +// +// Turn Markdown image shortcuts into tags. +// + + // + // First, handle reference-style labeled images: ![alt text][id] + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + !\[ + (.*?) // alt text = $2 + \] + + [ ]? // one optional space + (?:\n[ ]*)? // one optional newline followed by spaces + + \[ + (.*?) // id = $3 + \] + )()()()() // pad rest of backreferences + /g,writeImageTag); + */ + text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeImageTag); + + // + // Next, handle inline images: ![alt text](url "optional title") + // Don't forget: encode * and _ + + /* + text = text.replace(/ + ( // wrap whole match in $1 + !\[ + (.*?) // alt text = $2 + \] + \s? // One optional whitespace character + \( // literal paren + [ \t]* + () // no id, so leave $3 empty + ? // src url = $4 + [ \t]* + ( // $5 + (['"]) // quote char = $6 + (.*?) // title = $7 + \6 // matching quote + [ \t]* + )? // title is optional + \) + ) + /g,writeImageTag); + */ + text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeImageTag); + + return text; +} + +var writeImageTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) { + var whole_match = m1; + var alt_text = m2; + var link_id = m3.toLowerCase(); + var url = m4; + var title = m7; + + if (!title) title = ""; + + if (url == "") { + if (link_id == "") { + // lower-case and turn embedded newlines into spaces + link_id = alt_text.toLowerCase().replace(/ ?\n/g," "); + } + url = "#"+link_id; + + if (g_urls[link_id] != undefined) { + url = g_urls[link_id]; + if (g_titles[link_id] != undefined) { + title = g_titles[link_id]; + } + } + else { + return whole_match; + } + } + + alt_text = alt_text.replace(/"/g,"""); + url = escapeCharacters(url,"*_"); + var result = "\""' + _RunSpanGamut(m1) + "");}); + + text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm, + function(matchFound,m1){return hashBlock('

    ' + _RunSpanGamut(m1) + "

    ");}); + + // atx-style headers: + // # Header 1 + // ## Header 2 + // ## Header 2 with closing hashes ## + // ... + // ###### Header 6 + // + + /* + text = text.replace(/ + ^(\#{1,6}) // $1 = string of #'s + [ \t]* + (.+?) // $2 = Header text + [ \t]* + \#* // optional closing #'s (not counted) + \n+ + /gm, function() {...}); + */ + + text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm, + function(wholeMatch,m1,m2) { + var h_level = m1.length; + return hashBlock("' + _RunSpanGamut(m2) + ""); + }); + + function headerId(m) { + return m.replace(/[^\w]/g, '').toLowerCase(); + } + return text; +} + +// This declaration keeps Dojo compressor from outputting garbage: +var _ProcessListItems; + +var _DoLists = function(text) { +// +// Form HTML ordered (numbered) and unordered (bulleted) lists. +// + + // attacklab: add sentinel to hack around khtml/safari bug: + // http://bugs.webkit.org/show_bug.cgi?id=11231 + text += "~0"; + + // Re-usable pattern to match any entirel ul or ol list: + + /* + var whole_list = / + ( // $1 = whole list + ( // $2 + [ ]{0,3} // attacklab: g_tab_width - 1 + ([*+-]|\d+[.]) // $3 = first list item marker + [ \t]+ + ) + [^\r]+? + ( // $4 + ~0 // sentinel for workaround; should be $ + | + \n{2,} + (?=\S) + (?! // Negative lookahead for another list item marker + [ \t]* + (?:[*+-]|\d+[.])[ \t]+ + ) + ) + )/g + */ + var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; + + if (g_list_level) { + text = text.replace(whole_list,function(wholeMatch,m1,m2) { + var list = m1; + var list_type = (m2.search(/[*+-]/g)>-1) ? "ul" : "ol"; + + // Turn double returns into triple returns, so that we can make a + // paragraph for the last item in a list, if necessary: + list = list.replace(/\n{2,}/g,"\n\n\n");; + var result = _ProcessListItems(list); + + // Trim any trailing whitespace, to put the closing `` + // up on the preceding line, to get it past the current stupid + // HTML block parser. This is a hack to work around the terrible + // hack that is the HTML block parser. + result = result.replace(/\s+$/,""); + result = "<"+list_type+">" + result + "\n"; + return result; + }); + } else { + whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g; + text = text.replace(whole_list,function(wholeMatch,m1,m2,m3) { + var runup = m1; + var list = m2; + + var list_type = (m3.search(/[*+-]/g)>-1) ? "ul" : "ol"; + // Turn double returns into triple returns, so that we can make a + // paragraph for the last item in a list, if necessary: + var list = list.replace(/\n{2,}/g,"\n\n\n");; + var result = _ProcessListItems(list); + result = runup + "<"+list_type+">\n" + result + "\n"; + return result; + }); + } + + // attacklab: strip sentinel + text = text.replace(/~0/,""); + + return text; +} + +_ProcessListItems = function(list_str) { +// +// Process the contents of a single ordered or unordered list, splitting it +// into individual list items. +// + // The $g_list_level global keeps track of when we're inside a list. + // Each time we enter a list, we increment it; when we leave a list, + // we decrement. If it's zero, we're not in a list anymore. + // + // We do this because when we're not inside a list, we want to treat + // something like this: + // + // I recommend upgrading to version + // 8. Oops, now this line is treated + // as a sub-list. + // + // As a single paragraph, despite the fact that the second line starts + // with a digit-period-space sequence. + // + // Whereas when we're inside a list (or sub-list), that line will be + // treated as the start of a sub-list. What a kludge, huh? This is + // an aspect of Markdown's syntax that's hard to parse perfectly + // without resorting to mind-reading. Perhaps the solution is to + // change the syntax rules such that sub-lists must start with a + // starting cardinal number; e.g. "1." or "a.". + + g_list_level++; + + // trim trailing blank lines: + list_str = list_str.replace(/\n{2,}$/,"\n"); + + // attacklab: add sentinel to emulate \z + list_str += "~0"; + + /* + list_str = list_str.replace(/ + (\n)? // leading line = $1 + (^[ \t]*) // leading whitespace = $2 + ([*+-]|\d+[.]) [ \t]+ // list marker = $3 + ([^\r]+? // list item text = $4 + (\n{1,2})) + (?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+)) + /gm, function(){...}); + */ + list_str = list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm, + function(wholeMatch,m1,m2,m3,m4){ + var item = m4; + var leading_line = m1; + var leading_space = m2; + + if (leading_line || (item.search(/\n{2,}/)>-1)) { + item = _RunBlockGamut(_Outdent(item)); + } + else { + // Recursion for sub-lists: + item = _DoLists(_Outdent(item)); + item = item.replace(/\n$/,""); // chomp(item) + item = _RunSpanGamut(item); + } + + return "
  • " + item + "
  • \n"; + } + ); + + // attacklab: strip sentinel + list_str = list_str.replace(/~0/g,""); + + g_list_level--; + return list_str; +} + + +var _DoCodeBlocks = function(text) { +// +// Process Markdown `
    ` blocks.
    +//  
    +
    +	/*
    +		text = text.replace(text,
    +			/(?:\n\n|^)
    +			(								// $1 = the code block -- one or more lines, starting with a space/tab
    +				(?:
    +					(?:[ ]{4}|\t)			// Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
    +					.*\n+
    +				)+
    +			)
    +			(\n*[ ]{0,3}[^ \t\n]|(?=~0))	// attacklab: g_tab_width
    +		/g,function(){...});
    +	*/
    +
    +	// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
    +	text += "~0";
    +	
    +	text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
    +		function(wholeMatch,m1,m2) {
    +			var codeblock = m1;
    +			var nextChar = m2;
    +		
    +			codeblock = _EncodeCode( _Outdent(codeblock));
    +			codeblock = _Detab(codeblock);
    +			codeblock = codeblock.replace(/^\n+/g,""); // trim leading newlines
    +			codeblock = codeblock.replace(/\n+$/g,""); // trim trailing whitespace
    +
    +			codeblock = "
    " + codeblock + "\n
    "; + + return hashBlock(codeblock) + nextChar; + } + ); + + // attacklab: strip sentinel + text = text.replace(/~0/,""); + + return text; +} + +var hashBlock = function(text) { + text = text.replace(/(^\n+|\n+$)/g,""); + return "\n\n~K" + (g_html_blocks.push(text)-1) + "K\n\n"; +} + + +var _DoCodeSpans = function(text) { +// +// * Backtick quotes are used for spans. +// +// * You can use multiple backticks as the delimiters if you want to +// include literal backticks in the code span. So, this input: +// +// Just type ``foo `bar` baz`` at the prompt. +// +// Will translate to: +// +//

    Just type foo `bar` baz at the prompt.

    +// +// There's no arbitrary limit to the number of backticks you +// can use as delimters. If you need three consecutive backticks +// in your code, use four for delimiters, etc. +// +// * You can use spaces to get literal backticks at the edges: +// +// ... type `` `bar` `` ... +// +// Turns to: +// +// ... type `bar` ... +// + + /* + text = text.replace(/ + (^|[^\\]) // Character before opening ` can't be a backslash + (`+) // $2 = Opening run of ` + ( // $3 = The code block + [^\r]*? + [^`] // attacklab: work around lack of lookbehind + ) + \2 // Matching closer + (?!`) + /gm, function(){...}); + */ + + text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, + function(wholeMatch,m1,m2,m3,m4) { + var c = m3; + c = c.replace(/^([ \t]*)/g,""); // leading whitespace + c = c.replace(/[ \t]*$/g,""); // trailing whitespace + c = _EncodeCode(c); + return m1+""+c+""; + }); + + return text; +} + + +var _EncodeCode = function(text) { +// +// Encode/escape certain characters inside Markdown code runs. +// The point is that in code, these characters are literals, +// and lose their special Markdown meanings. +// + // Encode all ampersands; HTML entities are not + // entities within a Markdown code span. + text = text.replace(/&/g,"&"); + + // Do the angle bracket song and dance: + text = text.replace(//g,">"); + + // Now, escape characters that are magic in Markdown: + text = escapeCharacters(text,"\*_{}[]\\",false); + +// jj the line above breaks this: +//--- + +//* Item + +// 1. Subitem + +// special char: * +//--- + + return text; +} + + +var _DoItalicsAndBold = function(text) { + + // must go first: + text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, + "$2"); + + text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, + "$2"); + + return text; +} + + +var _DoBlockQuotes = function(text) { + + /* + text = text.replace(/ + ( // Wrap whole match in $1 + ( + ^[ \t]*>[ \t]? // '>' at the start of a line + .+\n // rest of the first line + (.+\n)* // subsequent consecutive lines + \n* // blanks + )+ + ) + /gm, function(){...}); + */ + + text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm, + function(wholeMatch,m1) { + var bq = m1; + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + + bq = bq.replace(/^[ \t]*>[ \t]?/gm,"~0"); // trim one level of quoting + + // attacklab: clean up hack + bq = bq.replace(/~0/g,""); + + bq = bq.replace(/^[ \t]+$/gm,""); // trim whitespace-only lines + bq = _RunBlockGamut(bq); // recurse + + bq = bq.replace(/(^|\n)/g,"$1 "); + // These leading spaces screw with
     content, so we need to fix that:
    +			bq = bq.replace(
    +					/(\s*
    [^\r]+?<\/pre>)/gm,
    +				function(wholeMatch,m1) {
    +					var pre = m1;
    +					// attacklab: hack around Konqueror 3.5.4 bug:
    +					pre = pre.replace(/^  /mg,"~0");
    +					pre = pre.replace(/~0/g,"");
    +					return pre;
    +				});
    +			
    +			return hashBlock("
    \n" + bq + "\n
    "); + }); + return text; +} + + +var _FormParagraphs = function(text) { +// +// Params: +// $text - string to process with html

    tags +// + + // Strip leading and trailing lines: + text = text.replace(/^\n+/g,""); + text = text.replace(/\n+$/g,""); + + var grafs = text.split(/\n{2,}/g); + var grafsOut = new Array(); + + // + // Wrap

    tags. + // + var end = grafs.length; + for (var i=0; i= 0) { + grafsOut.push(str); + } + else if (str.search(/\S/) >= 0) { + str = _RunSpanGamut(str); + str = str.replace(/^([ \t]*)/g,"

    "); + str += "

    " + grafsOut.push(str); + } + + } + + // + // Unhashify HTML blocks + // + end = grafsOut.length; + for (var i=0; i= 0) { + var blockText = g_html_blocks[RegExp.$1]; + blockText = blockText.replace(/\$/g,"$$$$"); // Escape any dollar signs + grafsOut[i] = grafsOut[i].replace(/~K\d+K/,blockText); + } + } + + return grafsOut.join("\n\n"); +} + + +var _EncodeAmpsAndAngles = function(text) { +// Smart processing for ampersands and angle brackets that need to be encoded. + + // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: + // http://bumppo.net/projects/amputator/ + text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&"); + + // Encode naked <'s + text = text.replace(/<(?![a-z\/?\$!])/gi,"<"); + + return text; +} + + +var _EncodeBackslashEscapes = function(text) { +// +// Parameter: String. +// Returns: The string, with after processing the following backslash +// escape sequences. +// + + // attacklab: The polite way to do this is with the new + // escapeCharacters() function: + // + // text = escapeCharacters(text,"\\",true); + // text = escapeCharacters(text,"`*_{}[]()>#+-.!",true); + // + // ...but we're sidestepping its use of the (slow) RegExp constructor + // as an optimization for Firefox. This function gets called a LOT. + + text = text.replace(/\\(\\)/g,escapeCharacters_callback); + text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g,escapeCharacters_callback); + return text; +} + + +var _DoAutoLinks = function(text) { + + text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"
    $1"); + + // Email addresses: + + /* + text = text.replace(/ + < + (?:mailto:)? + ( + [-.\w]+ + \@ + [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+ + ) + > + /gi, _DoAutoLinks_callback()); + */ + text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi, + function(wholeMatch,m1) { + return _EncodeEmailAddress( _UnescapeSpecialChars(m1) ); + } + ); + + return text; +} + + +var _EncodeEmailAddress = function(addr) { +// +// Input: an email address, e.g. "foo@example.com" +// +// Output: the email address as a mailto link, with each character +// of the address encoded as either a decimal or hex entity, in +// the hopes of foiling most address harvesting spam bots. E.g.: +// +// foo +// @example.com +// +// Based on a filter by Matthew Wickline, posted to the BBEdit-Talk +// mailing list: +// + + // attacklab: why can't javascript speak hex? + function char2hex(ch) { + var hexDigits = '0123456789ABCDEF'; + var dec = ch.charCodeAt(0); + return(hexDigits.charAt(dec>>4) + hexDigits.charAt(dec&15)); + } + + var encode = [ + function(ch){return "&#"+ch.charCodeAt(0)+";";}, + function(ch){return "&#x"+char2hex(ch)+";";}, + function(ch){return ch;} + ]; + + addr = "mailto:" + addr; + + addr = addr.replace(/./g, function(ch) { + if (ch == "@") { + // this *must* be encoded. I insist. + ch = encode[Math.floor(Math.random()*2)](ch); + } else if (ch !=":") { + // leave ':' alone (to spot mailto: later) + var r = Math.random(); + // roughly 10% raw, 45% hex, 45% dec + ch = ( + r > .9 ? encode[2](ch) : + r > .45 ? encode[1](ch) : + encode[0](ch) + ); + } + return ch; + }); + + addr = "" + addr + ""; + addr = addr.replace(/">.+:/g,"\">"); // strip the mailto: from the visible part + + return addr; +} + + +var _UnescapeSpecialChars = function(text) { +// +// Swap back in all the special characters we've hidden. +// + text = text.replace(/~E(\d+)E/g, + function(wholeMatch,m1) { + var charCodeToReplace = parseInt(m1); + return String.fromCharCode(charCodeToReplace); + } + ); + return text; +} + + +var _Outdent = function(text) { +// +// Remove one level of line-leading tabs or spaces +// + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + + text = text.replace(/^(\t|[ ]{1,4})/gm,"~0"); // attacklab: g_tab_width + + // attacklab: clean up hack + text = text.replace(/~0/g,"") + + return text; +} + +var _Detab = function(text) { +// attacklab: Detab's completely rewritten for speed. +// In perl we could fix it by anchoring the regexp with \G. +// In javascript we're less fortunate. + + // expand first n-1 tabs + text = text.replace(/\t(?=\t)/g," "); // attacklab: g_tab_width + + // replace the nth with two sentinels + text = text.replace(/\t/g,"~A~B"); + + // use the sentinel to anchor our regex so it doesn't explode + text = text.replace(/~B(.+?)~A/g, + function(wholeMatch,m1,m2) { + var leadingText = m1; + var numSpaces = 4 - leadingText.length % 4; // attacklab: g_tab_width + + // there *must* be a better way to do this: + for (var i=0; i + + + + + React | Need help? + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + +
    +
    +

    Need help?

    +
    +

    React is worked on full-time by Facebook's product infrastructure and Instagram's user interface engineering teams. They're often around and available for questions.

    + +

    Google Groups mailing list

    + +

    The reactjs Google Group is the best place to ask questions and find answers.

    + +

    IRC

    + +

    Many developers and users idle on Freenode.net's IRC network in #reactjs on freenode.

    + + +
    + + +
    +
    +
    + + + +
    + + +