Compare commits

...

486 Commits

Author SHA1 Message Date
ido 696aa2b4be 0.6.1 2017-01-04 14:25:13 +02:00
ido 6c5ea9e3a1 fixed issue with globing pattern, allow glob pattern 2017-01-04 14:24:06 +02:00
ido 3eb8df60b3 0.6.0 2017-01-02 16:46:26 +02:00
ido b78c3cae3e use babel-node to fix node 4 issues 2017-01-02 16:13:43 +02:00
ido 07547fdb68 fix eslint issue and lock versions 2017-01-01 17:19:35 +02:00
ido b125af0440 fix eslint error 2017-01-01 16:56:20 +02:00
Antonino Porcino d853510890 trim some trailing spaces 2016-12-29 16:11:59 +02:00
Antonino Porcino 12998d1022 fix broken --react-import-path when path is different from "react" 2016-12-29 16:09:49 +02:00
Antonino Porcino 5ccbfec25a removed some trainling spaces in docs/cli.md 2016-12-29 15:01:42 +02:00
ido b2525009b6 fix tests 2016-12-29 15:01:07 +02:00
Antonino Porcino 9dbff140cf do not use _() in rt-class, fixes #179 2016-12-29 14:33:24 +02:00
Antonino Porcino 5c730e8b95 updated comment explaining the regex 2016-12-29 13:03:04 +02:00
Antonino Porcino f3fc45f119 fixed broken html tests
Fixed html tests that were not running due to changed file name.
Failing html tests now dump "actual" html instead of the code that
generates it (.actual.html)
Fixed title for rtStyle tests
Removed compareAndWriteHtml() that is no longer needed
2016-12-29 12:56:27 +02:00
Antonino Porcino 8623963796 implements #175, better rt-scope syntax parser 2016-12-29 12:52:58 +02:00
Antonino Porcino dd2fbae5ec fix #190: allow kebab-case names containing more than one '-' 2016-12-29 12:50:40 +02:00
Antonino Porcino 079f5da0d1 fix #191, allow use of 'class' in custom-elements 2016-12-29 12:34:58 +02:00
ido a4962c5946 0.5.4 2016-09-28 18:25:11 +03:00
ido b657cb70d9 remove console.log 2016-09-28 18:24:53 +03:00
ido 364a3e300d 0.5.3 2016-09-28 18:20:11 +03:00
ido 7d69fd08e3 ignore temp playground web site 2016-09-28 18:19:33 +03:00
ido a993f8b172 update dependencies
minor fixes
2016-09-28 18:16:17 +03:00
ido f086cd63ea fix test 2016-07-21 10:55:39 +03:00
Marcus R. Brown 4a403dffbf Fix code generation for rt-template siblings. (#164)
* Clean up the list of propTemplates fixtures.

* Subtract the child index of a rt-template tag by the number of rt-template tags seen.

Fixes wix/react-templates#163.
2016-07-21 10:26:18 +03:00
ido fb3afc9a5b update dependencies 2016-07-21 10:20:20 +03:00
ido 556633d977 compare html with cheerio 2016-07-21 10:20:01 +03:00
Antonino Porcino b3cc40e297 Moved function "jsonText" to be local to "convertText" 2016-07-09 11:56:26 +02:00
Antonino Porcino 854293c589 code formatting 2016-07-09 10:19:44 +02:00
Antonino Porcino 6af5715ea1 Do not normalize whitespaces within { } expressions 2016-07-09 10:19:19 +02:00
Antonino Porcino a6be6ffc9c Type in README.md 2016-07-08 14:11:15 +02:00
Antonino Porcino 36d69bdcb3 Added rt-pre attribute to README.md 2016-07-08 14:09:48 +02:00
Antonino Porcino 6c7d032e15 Updated CLI doc file 2016-07-08 14:09:20 +02:00
Antonino Porcino 720db6c121 Test for --normalize-html-whitespace CLI option 2016-07-08 14:07:27 +02:00
Antonino Porcino 6348e53306 Added --normalize-html-whitespace CLI option 2016-07-08 14:06:47 +02:00
Antonino Porcino d80de30f62 Forbid rt-repeat in root nodes (fix #171) 2016-07-08 12:19:35 +02:00
Antonino Porcino 9b8d15a530 Restrict attributes on rt-virtual (fix #152) 2016-07-08 11:45:16 +02:00
Antonino Porcino 4559fdf744 refactored test code eliminating repeating functions 2016-07-08 09:50:18 +02:00
Antonino Porcino c801cb6acf Do not discard non breaking space (fix #151) 2016-07-08 08:58:55 +02:00
Antonino Porcino fb8d4028dd Test for react-native 0.29.0 2016-07-07 13:52:23 +02:00
Antonino Porcino bde2f67e01 Support for react native 0.29.0 2016-07-07 13:52:06 +02:00
Antonino Porcino 305d132a48 Emit code with different react-native versions 2016-07-07 13:51:44 +02:00
Antonino Porcino 5dcc94deb5 Multiple --native-target-version in command line argument 2016-07-07 10:38:09 +02:00
Antonino Porcino a993ebffde Fix #167 --native CLI behaviour 2016-07-06 19:53:42 +02:00
nino-porcino 46caeea387 Fix #138, #139, #134, #144, #145, #147, #157, #158, #161, #162 (#142)
* Single child for rt-template (fixes #138)

* Nested scope functions (fixes #139)

* Forbid nested rt-import (fixes #134)

* Vendor prefixes style keys (#144)

* Renamed test file

* Forbid expressions in style keys (#145)

* fixed rt-import and AMD (#147)

* Updated documentation

* Fixed links in README.md

* Sanitize comments (fix #158)

* Disable comments when es6 (fix#157)

* Added test case for comments

* Simplified TypeScript output

* Test cases for simplified TypeScript output

* Fixed wrong TypeScript output (#161)

* fix repeat with custom index (#162)
2016-07-06 11:25:08 +03:00
nino-porcino c3a6e46220 Updated to React v15.1.0 (#143) 2016-07-06 10:33:48 +03:00
Omer Ganim ff5bccdd93 0.5.2 2016-05-15 18:16:04 +03:00
Omer Ganim 2a9bd2b4c9 add context parameter to stateless components (fixes #130) 2016-05-15 18:14:42 +03:00
Omer Ganim 042c73882f 0.5.1 2016-05-15 16:58:05 +03:00
Omer Ganim 1094fa8215 0.5.0 2016-05-15 16:53:55 +03:00
Omer Ganim 66f709592c regenerate playground 2016-05-15 16:48:39 +03:00
Omer Ganim 43019f987e stop transpiling test files 2016-05-15 16:46:09 +03:00
Omer Ganim dc9e84e99b add option for custom index variable in react templates (fixes #88) 2016-05-15 16:44:55 +03:00
Omer Ganim 5b6eb7222c add rt-stateless option for stateless functional components (fixes #75) 2016-05-15 16:44:55 +03:00
Omer Ganim 63be2c9968 make default options be contingent on actual other options 2016-05-15 16:44:55 +03:00
Omer Ganim 7a117400be remove console.log from rtStyle 2016-05-15 16:44:55 +03:00
Omer Ganim 8103d35585 Change docs to rt-import instead of rt-require 2016-05-15 16:44:55 +03:00
Omer Ganim 3913453642 refactor import cases in reactSupport to use _.cond pattern matching 2016-05-15 16:44:55 +03:00
Omer Ganim 245c388a1b remove commented out code in RTCodeError 2016-05-15 16:44:55 +03:00
Brian Vella 68b088fe2e basic support for react 15 (#128) 2016-05-15 16:44:28 +03:00
nino-porcino c495a02452 New syntax for rt-require: "import" "from" (#125)
* New syntaxt for rt-require import="" from=""

* Added warning message for obsolete syntax

* Allow to import multiple names from the same module

* Added tests for rt-require new import syntax

* Removed unneded comment

* Separated rt-require into rt-require and rt-import

* Tests for rt-require and rt-import
2016-05-15 13:58:24 +03:00
nino-porcino b2483bd2de Automatically add key to "rt-if" if missing (fixes #99) 2016-05-02 17:05:54 +03:00
Omer Ganim 731296b27a rebuild playground using dist folder (#96) 2016-05-02 15:59:45 +03:00
Omer Ganim cef886ac7d Use React Templates from dist folder in playground's rt-main (fixes #96) 2016-05-02 15:59:26 +03:00
Omer Ganim 12f94ae357 remove unnecessary ESLint comment 2016-05-02 15:48:16 +03:00
Omer Ganim a64f22e0c8 add node 6 version to travis.yml 2016-05-02 14:52:28 +03:00
Omer Ganim 1a04bdcdf9 add prepublish script 2016-05-02 14:52:15 +03:00
Omer Ganim c138b919be 0.4.4 2016-05-02 14:30:22 +03:00
Omer Ganim 65635f89ef provide a key to virtual node children (#86) 2016-05-02 14:06:23 +03:00
Omer Ganim 3a1fcf6d33 replace util.format with ES6 template strings 2016-05-02 13:53:48 +03:00
Omer Ganim 232e0de5cf move reactTemplates internals to utils and refactor tests 2016-05-02 13:47:04 +03:00
Omer Ganim bcf9fa866b allow arrow functions outside callbacks in ESLint 2016-05-01 17:36:48 +03:00
Omer Ganim a97dff52f4 add coverage to .eslintignore 2016-05-01 17:36:23 +03:00
Omer Ganim 45af9f0eca add docs for rt-virtual 2016-05-01 13:27:21 +03:00
Omer Ganim 44d91b4149 remove node version 0.12 from travis build until issue can be resolved 2016-04-27 16:59:49 +03:00
Omer Ganim 4bbbfec3e8 enable rule prefer-arrow-callback and fix errors 2016-04-27 14:05:42 +03:00
Omer Ganim 5b664b9904 enable rule object-shorthand and fix errors 2016-04-27 14:04:35 +03:00
Omer Ganim 4cb8c4524c enable rules no-var and prefer-const and fix errors 2016-04-27 14:04:02 +03:00
Omer Ganim 4c385d5525 add eslint config wix-editor and fix errors 2016-04-27 14:01:18 +03:00
Omer Ganim 3cd56fe7ef add .babelrc file 2016-04-27 13:58:45 +03:00
Omer Ganim 4f67fee3b5 update eslint-plugin-lodash to use the plugin recommended settings and fix errors 2016-04-27 13:56:24 +03:00
Omer Ganim 6a11cb7f69 delete redundant eslint-plugin-lodash settings 2016-04-26 17:14:14 +03:00
ido 6e8012b620 Merge branch 'gh-pages' of github.com:wix/react-templates into gh-pages 2016-04-20 11:16:15 +03:00
ido 090ed7b81f 0.4.3 2016-04-20 11:14:53 +03:00
Joe Critchley dfddda8315 "surpported" > "supported" typo fix (#118) 2016-04-20 11:08:37 +03:00
ido bbdf5a6409 update lodash to 4 in eslint 2016-04-17 11:09:04 +03:00
ido e3fa8a7784 0.4.2 2016-04-17 10:59:54 +03:00
ido 500b6df9dc update lodash to 4
update dependencies
2016-04-17 10:57:57 +03:00
ido 6353e88bdb fixed #116 2016-04-17 10:20:13 +03:00
maria e56cd6d06a Change class set template for compatibility with lodash 4 2016-04-06 16:48:40 +03:00
ido 2bcfcc738e update dependencies 2016-03-02 19:04:44 +02:00
ido 58b8093090 upgrade eslint and plugins 2016-03-02 18:53:49 +02:00
ido 12040961f8 babel tests 2016-03-02 17:35:33 +02:00
ido f30ca08076 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2016-03-02 17:09:26 +02:00
Eitan Rousso 67f3431409 Update README.md 2016-02-19 20:54:43 +02:00
Eitan Rousso d79ab84bb0 Update README.md 2016-02-19 20:54:14 +02:00
Eitan Rousso 28da7538d3 Update README.md
added documentation for rt-include
2016-02-05 10:16:02 +02:00
Avi Marcus 6bc41f0113 made rt-include self closing to prevent future bugs 2016-02-04 16:30:50 +02:00
Avi Marcus 9d38cbb828 added rt-include, not in playground as the only interesting use case for playground is with url support and that requires changing the entire code to be async 2016-02-04 16:21:34 +02:00
ido 12578a06a2 Merge branch 'gh-pages' of github.com:wix/react-templates into gh-pages 2016-02-01 11:48:45 +02:00
Avi Marcus 63ef4541ae merge of nippur72 changes regarding rt-virtual 2016-01-13 13:40:28 +02:00
Avi Marcus ea4729dafe Merge branch 'nippur72-virtual-node' into gh-pages 2016-01-13 13:21:13 +02:00
Avi Marcus b67efbf278 Merge pull request #89 from nippur72/safe-parsing
Correctly parse rt-repeat object literal collection
2016-01-13 12:10:43 +02:00
Avi Marcus 7457826e38 Merge pull request #90 from nippur72/back-to-esprima
esprima-fb deprecated, back to upstream/esprima
2016-01-13 12:10:03 +02:00
Antonino Porcino 510d394e2b Updated escodegen, fixed es6 test 2016-01-03 10:59:35 +01:00
Antonino Porcino 9375b8e2d1 Added test for rt-repeat over object literal collection 2016-01-01 19:22:35 +01:00
Antonino Porcino f35bb9312a Fixed rt-repeat collection JS parsing 2016-01-01 19:05:23 +01:00
Antonino Porcino 27ad9e1cc0 Deprecated esprima-fb, back to upstream esprima 2016-01-01 18:20:35 +01:00
Antonino Porcino a3c1dc1dfb Changed to rt-virtual, added tests 2015-12-31 17:47:44 +01:00
Antonino Porcino e8baaaec01 Fix typo 2015-12-31 15:49:12 +01:00
Antonino Porcino fff28fd4b3 Support for <virtual> tag 2015-12-31 15:47:09 +01:00
ido cde47b1b50 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2015-12-30 15:33:36 +02:00
ido 0eb45a549b remove eslint ignores 2015-12-30 15:33:02 +02:00
Ido 486c093b51 Merge pull request #83 from nippur72/windows-build
Fix package.json to allow build under Windows
2015-12-30 15:29:43 +02:00
ido a7de93bd09 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2015-12-30 15:21:50 +02:00
Dany Shaanan da6864f28d 0.4.1 2015-12-30 11:14:21 +02:00
Antonino Porcino 6621a564da Fix package.json to allow build under Windows 2015-12-29 14:09:47 +01:00
ido b20f455fbe Merge remote-tracking branch 'origin/gh-pages' into gh-pages
# Conflicts:
#	package.json
2015-12-29 13:00:20 +02:00
Dany Shaanan c22228fe95 0.4.0 2015-12-29 12:25:21 +02:00
ido 6a37c19eb7 make react 14 the default 2015-12-29 12:24:37 +02:00
ido 80a188f131 0.5.0 2015-12-29 12:22:08 +02:00
ido 62f67b81bb make react 14 the default 2015-12-29 12:21:52 +02:00
ido cc8625faa3 0.4.0 2015-12-29 12:10:28 +02:00
ido 2ad0578e9e update dependencies 2015-12-29 12:07:14 +02:00
ido f79cb7632b use babel to support es6/node4 2015-12-29 12:00:41 +02:00
maria 178f1dfd0e fix eslint error 2015-11-29 17:36:20 +02:00
ido 09b8b3ec51 fix tape 2015-11-29 17:32:57 +02:00
maria 3fff4db2ae check scope in rt-if and fix eslint warnings 2015-11-29 14:50:09 +02:00
ido e65e81eefd clean dependencies 2015-11-22 12:33:21 +02:00
ido 041506d896 0.3.2 2015-11-22 12:23:01 +02:00
ido 0d35afe4cf fixed #72 2015-11-22 12:22:01 +02:00
ido 8169e057ea update hot reload sample 2015-11-17 13:05:41 +02:00
ido e73e15b186 add svg to test 2015-11-12 12:29:55 +02:00
ido cd10ee8b70 update react to 14
cleanups
2015-11-12 12:26:48 +02:00
ido 98af0f40ce fixed #73 2015-11-12 12:26:27 +02:00
ido 2d98822e5d cleanup 2015-11-12 10:26:22 +02:00
ido 0720e7f56a add styles support for react native 2015-11-09 15:07:05 +02:00
ido 6b6df898eb use eslint shared config 2015-11-09 14:39:27 +02:00
ido 8649ecb7be add style support 2015-11-09 14:33:04 +02:00
ido 3989f7893c 0.3.1 2015-11-08 12:40:35 +02:00
ido c72e272c70 expose convert style 2015-11-08 12:40:14 +02:00
ido ba5b489d29 0.3.0 2015-11-08 12:18:40 +02:00
ido ae8f04596e support for css for react native 2015-11-08 12:15:34 +02:00
ido 5e564afb3a fix eslint 2015-10-26 10:38:28 +02:00
ido 217992a666 0.2.1 2015-10-25 16:35:29 +02:00
ido 0a4bf6a18b support react 14 2015-10-25 16:31:29 +02:00
ido 2a8ee0a49a eslint fixes 2015-10-25 13:14:13 +02:00
ido 3619b7a22a add eslint ignore 2015-10-25 13:07:35 +02:00
ido 007073255b update dependencies 2015-10-25 13:04:38 +02:00
ido bd7be16aeb minor fix 2015-10-25 12:55:35 +02:00
ido dbf3dbf21e minor fix 2015-10-25 12:55:01 +02:00
ido 88ce4a3326 remove redundant files 2015-10-25 10:01:36 +02:00
ido ff6b99d925 add wix eslint plugin 2015-10-20 18:35:17 +03:00
ido 3d35790cd3 add editor config 2015-10-20 18:33:35 +03:00
ido 8717f33107 refactor 2015-10-06 17:20:16 +03:00
ido ce7163cc0a update dependencies
eslint rules
2015-10-06 17:18:50 +03:00
ido ed30c3a6a1 replace iojs with node 4 2015-10-06 17:17:08 +03:00
ido a7e1085559 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2015-09-30 10:17:19 +03:00
ido 9bf1532982 eslint fixes 2015-09-30 10:16:49 +03:00
Ido b21311a735 Update README.md 2015-09-10 13:50:19 +03:00
ido 008d370fe0 extract code from test 2015-09-10 13:48:29 +03:00
ido 56b8f58bb7 more lodash eslint rules 2015-09-07 11:55:21 +03:00
ido 4b57b3195a 0.2.0 2015-09-03 15:49:21 +03:00
ido 7b86b2a11d refactoring code out 2015-09-03 15:44:37 +03:00
ido 1269ecb071 update doc with rt-scope changes 2015-09-03 11:11:43 +03:00
ido e9376d990b test fix for #63 2015-09-03 11:01:01 +03:00
ido 205546eb3c fixed #63 2015-09-03 10:53:48 +03:00
ido b3fd044344 close #62 2015-09-03 10:14:51 +03:00
ido 6db983e7cc fix bad merge 2015-08-30 16:45:14 +03:00
ido 3001676e0b eslint fixes 2015-08-30 11:45:35 +03:00
Ido 5995959d77 Merge pull request #58 from frontrowed/flow
add an option to add a flow header
2015-08-30 09:44:20 +03:00
ido 558bb73474 lodash eslint rules
dependencies up to date
2015-08-25 17:15:02 +03:00
Greg Weber dc421097f0 add an option to add a flow header 2015-08-20 16:07:59 -07:00
Ido 24db05797a Merge pull request #57 from nirnatan/patch-1
replace the json notation with javascript
2015-08-20 17:22:12 +03:00
Nir Natan 197efe42ba replace the json notation with javascript 2015-08-20 11:50:19 +03:00
Ido e60d366279 Merge pull request #56 from nirnatan/gh-pages
Add support for React Native
2015-08-20 10:50:27 +03:00
Nir Natan 27dc925bf3 update native.md to explain both 'modules' and 'react-import-path' default options values. 2015-08-20 10:15:53 +03:00
Nir Natan 08aa36a2f1 Add support for React Native 2015-08-19 20:20:31 +03:00
ido a0f39e3435 add lodash3 rules 2015-08-19 13:45:00 +03:00
ido 020d66126b Merge branch 'nirnatan-gh-pages' into gh-pages 2015-08-19 12:56:03 +03:00
ido 295f2f41f0 Merge branch 'gh-pages' of https://github.com/nirnatan/react-templates into nirnatan-gh-pages 2015-08-19 12:55:39 +03:00
ido 46a60fb91e fix legacy build on travis 2015-08-18 14:30:47 +03:00
Omer Ganim e30545facf update README.md to document inline templates 2015-08-18 10:32:43 +03:00
Nir Natan 4ee34d21ae convert 'template' tag to 'rt-template' 2015-08-17 17:39:09 +03:00
Nir Natan 78d653a538 typo fix 2015-08-10 00:07:52 +03:00
Nir Natan ddb0a7f208 fix the new "properties template functions" section 2015-08-10 00:05:19 +03:00
Nir Natan a0bedecc0d update README.md with the new "properties template functions" section 2015-08-09 23:59:43 +03:00
Nir Natan 78799bfca7 add support for function templates props 2015-08-09 23:37:33 +03:00
ido d565f5380f 0.1.22 2015-08-02 17:46:26 +03:00
ido 473283ffd5 publish script 2015-08-02 17:46:11 +03:00
ido 1e32a7c222 eslint 1.0.0 2015-08-02 17:45:01 +03:00
ido 0e744736ce fixed #52 2015-08-02 17:16:55 +03:00
Dany Shaanan 731f8d8b1f Set the 'fork-me' ribbon link to open in a new tab 2015-07-30 17:51:44 +03:00
Dany Shaanan 4ab5d0f44d Update markdown files 2015-07-30 17:49:11 +03:00
ido 2cafda386d update dependencies 2015-07-30 17:18:52 +03:00
ido cb3ca7aa20 0.1.21 2015-07-30 16:07:51 +03:00
ido 2fc585df4d upgrade lodash to 3.10 2015-07-30 16:05:53 +03:00
ido 28d75c9945 Merge branch 'anchann-scope-variable-references' into gh-pages 2015-07-30 13:43:23 +03:00
ido accef5fb0f merge #45 2015-07-30 13:41:55 +03:00
ido 3415de3661 Merge branch 'scope-variable-references' of https://github.com/anchann/react-templates into anchann-scope-variable-references 2015-07-30 13:40:39 +03:00
Dany Shaanan d1783b11f5 Enabled site to work on HTTPS 2015-07-29 18:01:52 +03:00
ido d5ab5b1f39 Merge branch 'anchann-better-class-support' into gh-pages 2015-07-29 17:48:07 +03:00
ido 02f4c08bd3 close #43 2015-07-29 17:47:13 +03:00
ido ed23d1022f playground changes: update dependencies, minor fixes in samples and code 2015-07-29 17:16:37 +03:00
ido 36ad80b4a1 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2015-07-29 17:16:06 +03:00
ido 707b5d8fd2 eslint fixes 2015-07-29 17:15:42 +03:00
Ido 70231ea493 Merge pull request #41 from subyraman/gh-pages
Add CLI options to specify lodash/react import paths
2015-07-29 16:57:05 +03:00
Avi Marcus b79ed7a040 Merge pull request #44 from anchann/rt-scope-trailing-semicolon
Allow trailing semicolon in rt-scope
2015-07-29 08:34:46 +03:00
anchann 0c5fee07a7 In rt-scope subsequent aliases should be able to reference preceding ones
Rationale: It is typical to want to alias multiple subtrees of a nested
structure in a single rt-scope statement, like so:

<div rt-scope="this.props.user as user; user.profile as profile;
user.friends as friends">

This was not possible because of the function parameter based
implementation of rt-scope. I tweaked it a bit to use var declaration
instead, while preserving the parameter-based passing for all child
scopes.
2015-07-27 15:56:10 +09:00
anchann 88dc5544e8 Allow trailing semicolon in rt-scope
Rationale: it is natural for many developers to place a trailing
semicolon after the last scope alias pair, just as they do after every
preceding pair in the list. Since it is possible to save them time (and
perhaps frustration) at no cost in terms of semantics and safety, we
should do so.

On tests. Wasn't sure if this should be broken out into a separate test,
or bundled together with the existing one.
2015-07-27 13:57:16 +09:00
Suby Raman 0fd6ea5045 Set objects to be imported 2015-07-08 10:22:07 -04:00
Suby Raman 691e008c3e Add cli options for react/lodash import paths
Add in options if user wants to specify different paths to lodash or react in their application.
2015-07-08 10:12:44 -04:00
ido cee215c081 fix error not clearing in playground 2015-07-07 11:54:59 +03:00
ido faf90d186b 0.1.20 2015-05-19 12:12:01 +03:00
ido e3a23fb1fb move file up to date message to verbose 2015-05-19 11:09:50 +03:00
ido b2956ac812 0.1.19 2015-05-14 14:57:58 +03:00
ido 3b98c97cd2 update dependencies 2015-05-14 14:56:47 +03:00
Ido cfb339845d Merge pull request #39 from liady/gh-pages-es6
convert es6 imports without brackets
2015-05-14 14:39:19 +03:00
Ido 9491b36847 Merge pull request #37 from artemkaint/gh-pages
Fix spoiled option 'defines'
2015-05-14 14:32:04 +03:00
Liad Yosef e8d95c1a47 convert es6 imports without brackets 2015-05-10 17:23:25 +03:00
artemkaint e9af1eea52 Fix spoiled option 'defines' 2015-05-06 15:52:55 +03:00
Ido 8ca28b2f70 Merge pull request #35 from liady/gh-pages
Add the webpack react-templates-loader to README
2015-04-29 16:47:16 +03:00
Ido dbec6dc6b1 Merge pull request #36 from liady/gh-pages-htmlfor
support "for" attribute in react templates
2015-04-29 16:47:06 +03:00
Liad Yosef 2114f5705e support "for" attribute in react templates
Add support for using "for" attribute and converting it to DOM API supported "htmlFor"
2015-04-28 12:47:11 +03:00
Liad Yosef c43690bf79 Add the webpack react-templates-loader to README 2015-04-27 16:32:33 +03:00
ido a0e30d5441 0.1.18 2015-04-26 16:50:01 +03:00
ido 3e9d622453 update dependencies 2015-04-26 16:48:14 +03:00
ido fd9245c6df fix api 2015-04-26 16:44:51 +03:00
ido d12b61ca0b fixed #34 api breaks 2015-04-26 16:37:25 +03:00
ido 9d868f7466 add class test 2015-04-21 18:24:19 +03:00
ido bfe56bbda4 0.1.17 2015-04-21 17:44:30 +03:00
ido 70cf3dae90 update rt 2015-04-21 17:43:12 +03:00
ido 52412d99b0 fix info print outs 2015-04-21 17:42:49 +03:00
ido 8e4af67439 eslint fixes 2015-04-21 17:32:12 +03:00
ido 1c3bafbfab 0.1.16 2015-04-21 17:22:30 +03:00
ido 2ab86644f0 add context where missing 2015-04-21 17:21:12 +03:00
ido 307084e11d support react 13,
rename string utils method,
warn on rt-if without key
2015-04-21 17:15:03 +03:00
ido e4bbd93844 cleanups 2015-04-16 17:41:52 +03:00
ido 68407b6dc5 0.1.15 2015-04-16 16:51:29 +03:00
ido b6b5707fa3 update dependencies + eslint 2015-04-16 16:45:22 +03:00
ido a90e88582c eslint fixes 2015-04-05 17:17:10 +03:00
avim 08f6a601f2 Merge branch 'gh-pages' of github.com:wix/react-templates into gh-pages 2015-04-02 16:01:00 +03:00
avim 737272f7c3 finished support for jsrt 2015-04-02 16:00:38 +03:00
ido e451c9b4a1 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2015-03-30 11:20:30 +03:00
ido 1082f8f244 update dependencies + eslint react and prop types 2015-03-30 11:18:59 +03:00
ido bf2dde25e6 update dependencies + eslint 2015-03-29 15:59:08 +03:00
avim 084a44b402 added jsrt support 2015-03-29 15:55:40 +03:00
ido 92e8ca38cd fix test 2015-03-18 13:18:53 +02:00
ido ee604b6a3a fixed #15 2015-03-18 12:13:40 +02:00
ido 30b581a552 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2015-03-17 14:11:33 +02:00
ido 067ad07986 fixed #12, thanks! 2015-03-17 14:11:28 +02:00
ido b407e8b849 update dependencies + eslint 2015-03-17 14:10:44 +02:00
Ido f1754c3dc3 Merge pull request #19 from kraftwer1/patch-1
Removed newline
2015-03-17 13:50:26 +02:00
ido e0f3501db7 eslint fixes 2015-03-08 16:11:19 +02:00
ido 2a815ab72e update dependencies 2015-03-08 14:52:05 +02:00
ido c37028256b 0.1.14 2015-02-26 11:29:53 +02:00
avim faa6b1adf2 added better rt-props support use assign instead of merge and merge correctly style and className 2015-02-26 10:48:44 +02:00
ido 6826a880ef update dependencies + eslint 2015-02-24 10:07:55 +02:00
Ido 0fa3404d81 Merge pull request #20 from kraftwer1/patch-2
Added link to Broccoli plugin
2015-02-23 11:53:56 +02:00
ido 09a46dd543 added jsdoc 2015-02-22 11:16:44 +02:00
kraftwer1 dc960a1a1f Added link to Broccoli plugin 2015-02-19 15:44:33 +01:00
ido 17d8eec7f3 0.1.13 2015-02-19 16:00:24 +02:00
kraftwer1 18067e5f92 Removed newline 2015-02-19 14:34:20 +01:00
ido 1394f9d02f add es6 sample 2015-02-19 14:50:46 +02:00
ido 7358cea9f6 add es6 sample 2015-02-19 14:49:11 +02:00
ido 4d00e92772 close #pr-14 es6 modules support 2015-02-19 14:45:41 +02:00
Ido b1e17e6bd9 Merge pull request #18 from wix/pr/16
Pr/16
2015-02-19 13:48:09 +02:00
ido cd12a3a4bf fix eslint issues 2015-02-19 13:07:30 +02:00
Bruno Grieder 4788d3d5f8 Updated cli.md 2015-02-17 02:26:00 +01:00
Bruno Grieder 49b5034f3e Added TypeScript support via the `--modules typescript` flag 2015-02-17 02:23:08 +01:00
ido f18bbbb113 update lodash 2015-02-16 15:39:13 +02:00
ido 87ca187fa6 0.1.12 2015-02-12 10:08:31 +02:00
ido 913e4d99fa fix eslint 2015-02-12 10:08:05 +02:00
Ido 65c80c1c3e Merge pull request #11 from drewlesueur/patch-1
fix bug with multiple rt files
2015-02-12 10:05:22 +02:00
ido 7ae3e11262 eslint 14 and fixes 2015-02-12 10:04:36 +02:00
ido 4d52b03be1 fix tests 2015-02-11 16:42:03 +02:00
avim d1e6d41740 fixed js execution context outside of string nodes needs to concat as string 2015-02-09 10:43:55 +02:00
avim 0af424dd7e change string concat to separate children in the function call, so you don't get [Object object] 2015-02-08 17:26:29 +02:00
Drew LeSueur d3871194a6 added semicolons 2015-02-06 07:52:08 -07:00
Drew LeSueur d60d1737cc fix bug with multiple rt files
calling `rt *.rt` will cause the variable names of all the final template functions to be the same. This fixes that issue.
2015-02-06 07:16:01 -07:00
ido 5a43e9f28a 0.1.11 2015-02-01 11:51:37 +02:00
ido 2c79edf519 better error reporting, added column and enfOffset, deprecated index 2015-02-01 11:50:05 +02:00
ido f187062ed1 increase coverage 2015-01-27 15:10:54 +02:00
ido 3c755779ee remove coverall.yaml 2015-01-27 13:13:30 +02:00
ido d4e65bb491 fix coverage to travis 2015-01-27 12:46:46 +02:00
ido decbff8698 fix coverage to travis 2015-01-27 12:36:08 +02:00
ido 05facc549d fix coverage to travis 2015-01-27 12:34:25 +02:00
ido cc3faa4187 fix coverage to travis 2015-01-27 12:27:11 +02:00
ido 4ed1244110 add coverage to travis 2015-01-27 12:23:16 +02:00
ido f63fa8e366 add coverage and update dependencies 2015-01-25 11:18:35 +02:00
ido 3b9d8579fa increase test coverage 2015-01-22 18:02:18 +02:00
ido d26c8ed759 0.1.10 2015-01-22 16:57:57 +02:00
ido d5f975bfbd fix release task 2015-01-22 16:57:48 +02:00
ido 47a4b3216a remove release task 2015-01-22 16:54:00 +02:00
ido eb2a958ddb add release task 2015-01-22 16:52:45 +02:00
ido 65759e1d5c add release task 2015-01-22 16:51:56 +02:00
ido 4de1f45ea0 support named amd module 2015-01-22 16:50:50 +02:00
ido 866df02d0e support named amd module 2015-01-22 16:50:00 +02:00
barak igal bd47783a0c added module id to the compiled output of templateAMDTemplate 2015-01-22 13:01:04 +02:00
ido c06efc1fdd add test src to eslint 2015-01-20 09:43:59 +02:00
ido b010a488ac ignore tests 2015-01-19 17:49:17 +02:00
ido 3fe459baf2 0.1.9 2015-01-19 16:54:20 +02:00
ido cc8c83fa71 add tests to eslint 2015-01-19 16:53:14 +02:00
avim 36f1edfc1f support style tags - cheerio parses them as special section in the html 2015-01-19 16:22:42 +02:00
avim 5015222f45 support custom-elements 2015-01-19 15:29:42 +02:00
avim 268ac0a419 fixed tests on windows 2015-01-19 15:29:11 +02:00
ido dbcd1f2cbe fix eslint 2015-01-19 13:51:05 +02:00
ido 1d82e5faf5 0.1.8 2015-01-19 10:39:16 +02:00
ido 21271eefa4 list version and expose convertTemplate 2015-01-19 10:38:39 +02:00
ido 6662bda1e6 bump and publish 2015-01-13 10:25:51 +02:00
Avi Marcus 3ba52d1653 replace htmlMode with hard wired list of self closing tags... caused weird problems with rt-require... 2015-01-12 20:08:30 +02:00
ido f515c17a67 add tests for json output 2015-01-12 15:29:21 +02:00
ido 5ab047cbed fix bug with json output 2015-01-12 15:02:10 +02:00
ido a9536edce6 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2015-01-12 15:01:36 +02:00
ido f807a487ba update escodegen 2015-01-12 15:01:16 +02:00
avim 491a3e6125 html mode instead of xml, fix problem with inputs and br tags caused by html which is not valid xml 2015-01-11 12:13:01 +02:00
Ido 88005a399b Update README.md 2015-01-08 17:40:27 +02:00
Dany Shaanan 3978843047 added target to gitignore 2015-01-05 14:11:04 +02:00
Dany Shaanan 93e8c59e37 added eslint rules: no-new-require, block-scoped-var and fixed errors 2015-01-05 14:10:33 +02:00
ido be588db1ab fix legacy react render 2015-01-05 12:07:20 +02:00
ido 8327c5c5c5 merge project to one grunt and npm 2015-01-05 10:49:35 +02:00
ido 823b149f5e anchor links fix 2015-01-05 10:26:06 +02:00
ido 14a199929e anchor links 2015-01-05 10:25:13 +02:00
ido c5c7ced976 fix JS to JSX as it should be 2015-01-05 10:20:17 +02:00
ido d1543d0fd6 build editorial changes by Marlowe and David (thanks) 2015-01-05 10:15:11 +02:00
ido 27f01fc267 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2015-01-05 10:07:44 +02:00
ido d44559a5e8 remove console logs 2015-01-05 10:07:27 +02:00
Marlowe Shaeffer deb86f99e1 Minor editorial tweaks. 2015-01-04 14:42:30 -08:00
Marlowe Shaeffer dc67587b3e Matches new bulleted descriptions in README 2015-01-04 14:28:21 -08:00
David Zuckerman 5263574ebb Update README.md
editorial work
2015-01-05 00:15:28 +02:00
Marlowe Shaeffer 303c2c279e Clarified the "style" section. 2015-01-04 13:38:01 -08:00
Marlowe Shaeffer 137a402a69 Additional editorial changes for consistency. 2015-01-04 12:19:38 -08:00
Marlowe Shaeffer 2a13fd1661 Provided "Improved todo list" a new description.
Used Avi's suggested description.
2015-01-04 12:11:52 -08:00
Marlowe Shaeffer 3dfe6e0e12 Updated list items to match README file. 2015-01-04 12:08:56 -08:00
Marlowe Shaeffer ad24b3fc4f Additional changes. Please review. 2015-01-04 12:04:02 -08:00
Marlowe Shaeffer 4f378c3ea3 With editorial changes—please review. 2015-01-04 11:59:30 -08:00
Marlowe Shaeffer 71a75e41d8 Made editorial changes.
Note that two descriptions match, and it seems that the one for "Improved todo list" should be changed.
2015-01-04 09:47:51 -08:00
ido 8ec25ad8cd fix "Blocked loading mixed active content" issue in Firefox
https://github.com/wix/react-templates/pull/3
2015-01-04 17:09:26 +02:00
Ido 465cfa93cd Merge pull request #3 from martintietz/gh-pages
Fixes "Blocked loading mixed active content" issue in Firefox
2015-01-04 17:02:14 +02:00
Martin Tietz d06720fe6c Fixes "Blocked loading mixed active content" issue in Firefox 2015-01-04 14:32:46 +01:00
ido fed280150a remove old index, update integrations 2015-01-04 12:21:07 +02:00
Ido 91fc599f30 Update README.md 2015-01-04 12:17:31 +02:00
Ido eb92b37fa2 Update README.md 2015-01-04 12:16:28 +02:00
Ido 34a4816425 Update README.md 2015-01-04 12:16:06 +02:00
Ido d7e12a9b65 Update cli.md 2015-01-04 12:15:14 +02:00
Dany Shaanan 0f86ec65c1 added GA 2015-01-02 18:45:37 +02:00
Tom Bigelajzen eab0467158 Update README.md 2015-01-02 11:40:19 +02:00
ido 0166106c06 add yeoman and hello project 2015-01-01 17:00:22 +02:00
ido cc7cb8ea44 remove redundant code 2015-01-01 10:33:57 +02:00
ido 2f9824be85 cleanup css, remove hr, update dependecies 2015-01-01 10:19:50 +02:00
Omer Ganim 0acb98b7ce changed loading bar to not use jquery 2014-12-31 19:05:59 +02:00
Omer Ganim 6583528e94 merged correct scripts 2014-12-31 18:40:59 +02:00
ido 94dd567a78 optimized version 2014-12-31 18:34:48 +02:00
Omer Ganim b9b1816133 Merge branch 'gh-pages' of github.com:wix/react-templates into gh-pages 2014-12-31 18:32:28 +02:00
Omer Ganim f7df9a82b5 added "fork me on github" ribbon 2014-12-31 18:32:23 +02:00
ido 2f3a91d8da default task runs eslint:all only 2014-12-31 18:31:57 +02:00
ido ca42fbff6f fix docs 2014-12-31 17:29:21 +02:00
ido cd3e690e57 fix travis branch 2014-12-31 17:27:59 +02:00
ido 42c19432d0 add tests 2014-12-31 17:24:08 +02:00
ido 13729c9910 fix eslint issues 2 2014-12-31 16:43:58 +02:00
ido 5d55e210b7 fix eslint issues 2014-12-31 16:41:11 +02:00
ido f8586b1298 fix travis 2014-12-31 16:25:20 +02:00
ido e80653b445 add grunt eslint 2014-12-31 16:15:46 +02:00
ido 8c280b8cef travis fix branch 2014-12-31 16:06:19 +02:00
ido b07d4bb1af travis url 2014-12-31 14:58:58 +02:00
ido 87d348b819 fix urls 2014-12-31 14:57:52 +02:00
ido dc853e0e6e npm package 2014-12-31 13:41:56 +02:00
ido d29859f5a4 trying travis 2014-12-31 13:34:48 +02:00
ido 513ee92255 add keywords 2014-12-31 11:03:07 +02:00
ido 0de46e9378 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2014-12-31 09:55:17 +02:00
ido 5d906b3d6a add support for react 0.12.2 2014-12-31 09:55:06 +02:00
amitk d87b86b960 Added rt-require example to show amd and commonjs support 2014-12-30 21:19:49 +02:00
ido 8ef5be16bf publish to npm 2014-12-30 18:13:52 +02:00
ido 2b20484bf0 publish to npm 2014-12-30 18:10:18 +02:00
ido 71af8eb7ad minified requirejs 2014-12-30 17:56:10 +02:00
ido 881bdc0dfc minified 2014-12-30 17:54:32 +02:00
ido efb8db022e minified 2014-12-30 17:53:42 +02:00
ido 14af6aacb0 cleanup 2014-12-30 17:49:13 +02:00
ido 33b5443e25 add amd, minor ui fixes 2014-12-30 17:33:28 +02:00
ido e258d88a2b fix update sample issue 2014-12-30 11:35:24 +02:00
ido 6bdd57cec2 fix samples in playground 2014-12-30 11:05:27 +02:00
ido bf3c5d550a improved UI, better samples 2014-12-30 10:42:31 +02:00
amitk d2f459c505 Added image for sample 2014-12-30 01:54:48 +02:00
avim 54e6abc482 removed bootstrap.js and implemented tabs in react 2014-12-28 17:36:39 +02:00
ido f3da1f73fe move generated files to dist 2014-12-28 11:52:06 +02:00
ido 2abd385739 removed eslint ignores 2014-12-28 11:48:50 +02:00
ido 349057188a allow generation of globals + ui fixes 2014-12-28 11:47:34 +02:00
ido 133f2645d2 fix error in editor 2014-12-25 12:13:07 +02:00
ido 07c3952a2f react minimized 2014-12-24 12:36:32 +02:00
ido adda4e3877 lodash minimized 2014-12-24 12:33:54 +02:00
ido 990256d2d1 add react attributes 2014-12-24 12:33:23 +02:00
ido a05574bd1e optimize script loading 2014-12-24 12:31:07 +02:00
ido 339494759d Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2014-12-24 12:29:46 +02:00
ido bc4a3d9ae0 add minified versions 2014-12-24 12:28:24 +02:00
Tom Bigelajzen c14fc36e36 logo one last time 2014-12-24 11:22:51 +02:00
Tom Bigelajzen 7c35179f67 logo again 2014-12-24 11:17:35 +02:00
Tom Bigelajzen 2801c39392 logo in fiddle 2014-12-24 11:11:17 +02:00
Tom Bigelajzen 799e55692e logo in fiddle 2014-12-24 11:10:37 +02:00
Tom Bigelajzen 1d001d4967 logo in fiddle 2014-12-24 11:07:29 +02:00
Tom Bigelajzen 2b19343071 logo 2014-12-24 10:31:05 +02:00
Tom Bigelajzen 63305e0698 Update index.html 2014-12-23 18:47:42 +02:00
Tom Bigelajzen 714c2a9e0f logo 2014-12-23 18:43:18 +02:00
Tom Bigelajzen 7bcbd9c222 Update index.html 2014-12-23 18:28:39 +02:00
Tom Bigelajzen 3e7982b0e6 Update index.html 2014-12-23 18:26:49 +02:00
Tom Bigelajzen 98ba82e7a8 added logo 2014-12-23 18:08:47 +02:00
Lieron Schalew c46163d0da Better usage message 2014-12-15 15:11:53 +01:00
amitk 57f2b77911 Added rt-require documentation and fixed commonJS option 2014-12-14 13:03:22 +02:00
Avi Marcus 8fb5fb3674 moved require to rt-require tag instead of inside of doctype and removed doctype completely 2014-12-11 09:30:27 +02:00
ido d60af285c3 add panel with errors 2014-12-10 14:14:22 +02:00
ido a65eff45c4 add dry run option 2014-12-10 14:13:16 +02:00
ido 48cb50143d fix image url 2014-12-10 10:05:04 +02:00
ido 9a9e06033e docs 2014-12-10 10:02:54 +02:00
ido 898edf585b sample fix 2014-12-10 09:46:59 +02:00
ido de9c1b090c doc fix 2014-12-10 09:46:35 +02:00
ido 2fc0e6df41 remove console, cleanup htmls 2014-12-09 17:20:56 +02:00
ido 3066de38b7 invalid input tests 2014-12-09 17:20:09 +02:00
ido 83ef37633a update docs 2014-12-09 16:29:38 +02:00
ido 2ebafe4580 replace ace with code mirror 2014-12-09 15:32:31 +02:00
ido 4f3dcc3a87 replace ace with code mirror 2014-12-09 15:31:25 +02:00
ido 85f3ef4a95 add toolbar + samples 2014-12-08 14:48:12 +02:00
ido fa51a3ea5c css layout I love you 2014-12-08 12:45:32 +02:00
ido 99e3a49543 fix format issue 2014-12-07 17:40:25 +02:00
ido dda7477582 add theme 2014-12-07 15:33:24 +02:00
ido 77014dc1d8 fix case 2014-12-07 15:32:05 +02:00
ido ec0a854ab9 ace url fix 2014-12-07 15:30:35 +02:00
ido 4fb76cca99 add ace 2014-12-07 15:15:38 +02:00
ido 638548a852 add samples 2014-12-07 15:13:35 +02:00
ido 7c1ccff8ab changed playground to work with requirejs instead of browserify 2014-12-07 15:12:50 +02:00
ido 01a46e506c eslint fixes 2014-12-04 18:09:27 +02:00
ido e97275b760 add optionator 2014-12-04 18:04:33 +02:00
avim 13fffaa55d support React 0.12 & React 0.10/0.11 syntax and dom elements 2014-12-04 14:40:54 +02:00
ido 39051d8c46 replace index with home 2014-12-04 11:23:48 +02:00
ido 2ed1428131 add fiddle layout 2014-12-04 11:15:19 +02:00
ido ec1eef1cc0 fix eslint issues 2014-12-03 18:45:29 +02:00
ido 9bf4042fb3 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2014-12-03 18:45:10 +02:00
ido 5c65f8192e fix examples 2014-12-03 18:44:57 +02:00
Avi Marcus 6b70d9b342 Revert "changed back to react instead of react/addons"
This reverts commit 8059810f54.
2014-12-03 12:54:12 +02:00
Avi Marcus 8059810f54 changed back to react instead of react/addons 2014-12-03 12:44:44 +02:00
ido 4654770a10 react/addons generation change 2014-12-03 11:45:31 +02:00
ido 84c4864602 eslint fixes 2014-12-03 11:36:34 +02:00
avim b32bba381c intro and samples 2014-12-02 18:59:03 +02:00
ido 42b8741beb Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2014-12-02 17:32:40 +02:00
ido c5d3ef203c edit texts and links for home 2014-12-02 17:32:26 +02:00
Ido 062d29e126 Update README.md 2014-12-02 17:09:45 +02:00
ido 659ebc8d7c separate playground from home page 2014-12-02 16:57:18 +02:00
ido 82ac637683 add rt 2014-12-02 14:35:20 +02:00
ido a317b0df1a error handling + test 2014-12-02 14:30:06 +02:00
ido 0c58bbf1dd Merge branch 'gh-pages' of github.com:wix/react-templates into gh-pages 2014-12-02 14:27:33 +02:00
Avi Marcus 580889fb23 Merge pull request #2 from wix/grunt-tap
Adding grunt task to run node-tap tests
2014-12-02 09:04:45 +02:00
Lior Shefer c537974865 Adding grunt task to run node-tap tests 2014-12-01 22:39:59 +02:00
ido 2f2a97d20a Merge branch 'gh-pages' of github.com:wix/react-templates into gh-pages 2014-11-30 18:51:39 +02:00
ido 1c0db6f722 update version to 0.1.2 2014-11-30 18:51:15 +02:00
avim cbd1384e6b vertical 2014-11-30 17:34:43 +02:00
ido 41b9a7d5dc theme fix 2014-11-30 14:01:55 +02:00
ido 5ae74e47f0 change theme, remove selection 2014-11-30 13:59:44 +02:00
ido 3a1a1840df add direction to code sample 2014-11-30 13:12:03 +02:00
amitk 229f046167 Packed the sample again 2014-11-30 11:02:51 +02:00
amitk 68b6015bfd Don't ignore whitespace in html text 2014-11-30 10:55:38 +02:00
Avi Marcus dddc3770a4 Merge pull request #1 from wix/rtProps
Added rt-props directive
2014-11-30 10:31:18 +02:00
amitk edbc8fac9b Added rt-props 2014-11-29 23:32:00 +02:00
amitk 444d21334a Fixed the files to show the editor again
Fixed the package.json to export api.js instead of reactTemplate.js so that the grunt task will work
2014-11-29 22:50:49 +02:00
ido a62b54c520 add tabs to playground 2014-11-27 18:53:37 +02:00
ido e646677554 fix clone issue 2014-11-27 18:52:12 +02:00
ido b087470cdc Merge branch 'gh-pages' of github.com:wix/react-templates into gh-pages 2014-11-27 18:23:35 +02:00
ido a3a5099d29 improve cli, json output, improve error handling 2014-11-27 18:21:46 +02:00
avim 43113f7a4d Merge branch 'gh-pages' of github.com:wix/react-templates into gh-pages 2014-11-27 11:58:02 +02:00
avim 7504b09a12 fixed tests
Fixed problem with wrapping of injected code if concatted with strings.
2014-11-27 11:57:45 +02:00
Ido 9aaf7b9c99 Update README.md 2014-11-25 18:02:13 +02:00
avim 51061370d6 Merge branch 'gh-pages' of github.com:wix/react-templates into gh-pages 2014-11-25 17:25:09 +02:00
avim 951d0a0bf3 switched to ace editor... better ipad support 2014-11-25 17:24:54 +02:00
amitk b676086914 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2014-11-25 17:07:01 +02:00
amitk 5b4a5aa2b3 Replaced className with class in the sample 2014-11-25 17:06:54 +02:00
Amit Kaufman 99a52cf935 Fixed rt-repeat sample to include execution context 2014-11-25 17:03:25 +02:00
amitk 8952d19789 Changed doctype 2014-11-19 21:26:39 +02:00
ido 388e3e9444 fix missing options issue 2014-11-19 11:53:47 +02:00
ido 0437813804 Merge remote-tracking branch 'origin/gh-pages' into gh-pages 2014-11-19 10:28:29 +02:00
ido 39b00fa27e publish to local repo 2014-11-19 10:28:17 +02:00
Dan Shappir 14931d319a Update README.md 2014-11-18 18:25:28 +02:00
Dan Shappir 3464a80e72 Update README.md 2014-11-18 18:20:16 +02:00
ido 18137686c7 eslint fixes 2014-11-18 16:06:25 +02:00
ido 80fdb2aa01 add grunt 2014-11-18 15:54:52 +02:00
ido 44cb755bd8 add grunt 2014-11-18 15:54:34 +02:00
ido 027787ce69 add force option 2014-11-18 15:54:20 +02:00
ido 75323d07d7 add code mirror and grunt 2014-11-18 15:53:46 +02:00
avim b9825aea40 added codemirror and playground 2014-11-18 15:00:28 +02:00
ido 9b9a12b48d ignore eslint in generated code 2014-11-17 18:12:50 +02:00
amitk f7ab580849 Fixed todo sample to work nicer with style 2014-11-17 16:05:32 +02:00
Dany Shaanan b000bdf524 added gh-pages content to npmignore 2014-11-17 15:33:30 +02:00
267 changed files with 79822 additions and 59017 deletions

4
.babelrc Normal file
View File

@ -0,0 +1,4 @@
{
"presets": ["es2015"],
"ignore": "test/data"
}

20
.editorconfig Normal file
View File

@ -0,0 +1,20 @@
# http://EditorConfig.org
# top-most EditorConfig file
root = true
# [*.{js,json}]
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true # doesn't work yet
insert_final_newline = true # doesn't work yet
[{package.json,*.yml}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false

26
.eslintignore Normal file
View File

@ -0,0 +1,26 @@
node_modules/**
bower_components/**
**/*.rt.js
**/*.json.js
playground/**/*.rt.js
playground/dist/**
playground/libs/**
playground3/**
playground3/dist/**
playground3/libs/**
playground3/**/*.rt.js
playground4
web/**
playground/sample/**
test/data/**
dist-test
dist
internalTasks/release.js
playground.config.js
sample/InfiniteScroll.js
/coverage

169
.eslintrc
View File

@ -1,155 +1,30 @@
{
"extends": ["wix-editor", "wix-editor/node", "plugin:lodash/recommended"],
"plugins": ["lodash", "wix-editor"],
"rules": {
"no-array-constructor": 2,
"no-catch-shadow": 2,
"no-comma-dangle": 2,
"no-cond-assign": 2,
"no-constant-condition": 2,
"no-control-regex": 2,
"no-div-regex": 1,
"no-else-return": 2,
"no-empty-class": 2,
"no-empty-label": 2,
"no-eq-null": 2,
"no-extend-native": 2,
"no-extra-boolean-cast": 2,
"no-extra-strict": 2,
"global-strict": [2, "always"],
"no-inner-declarations": [2, "functions"],
"no-iterator": 2,
"no-labels": 2,
"no-lone-blocks": 2,
"no-lonely-if": 2,
"no-loop-func": 2,
"no-mixed-requires": [0, false],
"no-negated-in-lhs": 2,
"no-nested-ternary": 2,
"no-new-require": 0,
"no-octal-escape": 2,
"no-path-concat": 1,
"no-process-exit": 2,
"no-proto": 2,
"no-redeclare": 2,
"no-regex-spaces": 2,
"no-restricted-modules": 1,
"no-script-url": 2,
"no-sequences": 2,
"no-shadow": 1,
"no-shadow-restricted-names": 2,
"no-spaced-func": 2,
"no-space-before-semi": 2,
"no-sparse-arrays": 2,
"no-sync": 0,
"no-undef": 2,
"no-unused-expressions": 2,
"no-unused-vars": [2, {"vars": "all", "args": "after-used"}],
"no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],
"no-wrap-func": 2,
"yoda": 2,
"semi": [2, "always"],
"func-style": [2, "declaration", {"allowArrowFunctions": true}],
"prefer-spread": 0,
"prefer-template": 0,
"consistent-return": 0,
"block-scoped-var": 0,
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
"consistent-return": 2,
"consistent-this": [0, "self", "TODO: add this options, remove this value in array"],
"curly": [2, "all"],
"default-case": 0,
"func-names": 0,
"func-style": [0, "declaration"],
"max-depth": [0, 4],
"max-len": [0, 80, 4],
"max-nested-callbacks": [0, 2],
"handle-callback-err": 0,
"one-var": 0,
"sort-vars": 0,
"space-after-keywords": [2, "always"],
"space-in-brackets": [0, "never"],
"space-infix-ops": 2,
"space-return-throw-case": 2,
"space-unary-word-ops": 2,
"strict": 2,
"valid-typeof": 2,
"wrap-regex": 0,
"no-restricted-syntax": [2, "WithStatement", "ContinueStatement", "ForStatement"],
"no-negated-condition": 1,
"no-alert": 2,
"no-caller": 2,
"no-bitwise": 0,
"no-console": 0,
"no-underscore-dangle": 0,
"no-debugger": 2,
"no-dupe-keys": 2,
"no-empty": 2,
"no-eval": 2,
"no-ex-assign": 2,
"no-extra-parens": 0,
"no-extra-semi": 2,
"no-floating-decimal": 1,
"no-func-assign": 2,
"no-invalid-regexp": 2,
"no-implied-eval": 2,
"no-with": 2,
"no-fallthrough": 2,
"no-unreachable": 2,
"no-undef-init": 2,
"no-octal": 2,
"no-obj-calls": 2,
"no-new-wrappers": 2,
"no-new": 2,
"no-new-func": 2,
"no-native-reassign": 2,
"no-plusplus": 0,
"no-delete-var": 2,
"no-return-assign": 2,
"no-new-object": 2,
"no-label-var": 2,
"no-ternary": 0,
"no-self-compare": 2,
"no-use-before-define": 0,
"valid-jsdoc": 0,
"eol-last": 0,
"no-trailing-spaces": 0,
"no-extra-bind": 2,
"camelcase": 0,
"dot-notation": 2,
"eqeqeq": 2,
"new-parens": 2,
"guard-for-in": 2,
"radix": 0,
"new-cap": 2,
"semi": 2,
"use-isnan": 2,
"quotes": [1, "single", "avoid-escape"],
"max-params": [0, 3],
"max-statements": [0, 10],
"complexity": [0, 11],
"wrap-iife": 2,
"no-multi-str": 2,
"lodash/prefer-filter": 0,
"lodash/chaining": [2, "always"],
"lodash/prefer-map": 0,
"lodash/path-style": 0,
"lodash/no-extra-args": 2,
"lodash/prefer-lodash-method": 0,
"quote-props": [1, "as-needed"],
"no-multi-spaces": 1,
"key-spacing": [1, { "beforeColon": false, "afterColon": true }],
"comma-spacing": 1
},
"env": {
"browser": false,
"node": true,
"amd": true
},
"globals": {
"requirejs": true,
"xdescribe": false,
"describe": false,
"it": false,
"xit": false,
"beforeEach": false,
"afterEach": false,
"jasmine": false,
"expect": false,
"waitsFor": false,
"waits": false,
"runs": false,
"any": false,
"spyOn": false,
"createSpy": false
"wix-editor/augmented-assignment": 1,
"wix-editor/no-not-not": 1,
"wix-editor/no-unneeded-match": 1,
"wix-editor/prefer-filter": 1,
"wix-editor/prefer-ternary": 1,
"wix-editor/return-boolean": 1,
"wix-editor/simplify-boolean-expression": 1
}
}

13
.gitignore vendored
View File

@ -16,3 +16,16 @@ npm-debug.log
### bower ###
/bower_components/*
### babel ###
/dist
/dist-test
/web
/target
/coverage
### Test Output ###
test/data/**/*.rt.actual.js
test/data/**/*.code.js
test/data/**/*.actual.html

View File

@ -19,3 +19,7 @@ npm-debug.log
### tests ###
/test
### gh-pages content ###
/index.html
/playground
/web

26
.travis.yml Normal file
View File

@ -0,0 +1,26 @@
language: node_js
node_js:
- 4
- 5
- 6
sudo: false
#before_script:
# - npm install -g grunt-cli
install:
- npm install
script:
- npm run lint
- npm run test-cov
branches:
only:
- gh-pages
#after_success:
# - npm run coveralls
#after_success:
# - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js

33
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,33 @@
# Contributing to React-Templates
Thanks for coming! Contributions of any kind are welcome.
## Setup
* Fork [React-Templates](https://github.com/wix/react-templates)
* Clone your fork
* In your `react-templates` directory, run `npm i && grunt all`
## Submitting an issue
You can submit an issue [here](https://github.com/wix/react-templates/issues).
Please make sure that there isn't already an issue regarding the same matter,
and include as many details as possible about the issue and on how to reproduce it,
if relevant.
## Creating a pull request
* Please adhere to the style and formatting of the code
* Write tests for new functionality
* Create purposeful and complete commits
### Before committing
* Make sure that `grunt all` passes.
* Pick a concise commit message
When working on [wix.github.io/react-templates](http://wix.github.io/react-templates),
run `grunt pgall` to create the minified files,
but do not include their updated version in your commit.
Describe in your PR what you did to the site and we'll update them after the merge.
(This is important for preventing merge conflicts in the minified files).

120
Gruntfile.js Normal file
View File

@ -0,0 +1,120 @@
'use strict';
module.exports = function (grunt) {
grunt.initConfig({
clean: {
main: {
src: ['coverage', 'playground/**/*.rt.js']
}
},
eslint: {
all: {
src: [
'src/**/*.js', 'playground/**/*.js',
'test/src/**/*.js',
'!playground/libs/**/*.js',
'!playground/dist/**/*.js',
'!playground/**/*.rt.js'
]
}
},
jasmine_node: {
options: {
forceExit: true,
match: '.',
matchall: false,
specNameMatcher: 'spec',
extensions: 'js'
},
all: ['server/test'],
grunt: ['conf/tasks/test']
},
browserify: {
rt: {
files: {
'playground/dist/rt-main.browser.js': ['playground/rt-main.js']
},
options: {
transform: ['brfs'],
alias: ['react:react/addons']
}
}
},
tape: {
options: {
pretty: true,
output: 'console'
},
files: ['test/src/*.js']
},
watch: {
rt: {
files: [
'playground/*.rt'
],
tasks: ['rt'],
options: {
spawn: false
}
},
test: {
files: [
'src/**/*.*', 'test/**/*.*'
],
tasks: ['test'],
options: {
spawn: false
}
}
},
uglify: {
my_target: {
//options: {
// sourceMap: true,
// sourceMapIncludeSources: true,
// sourceMapIn: 'example/coffeescript-sourcemap.js', // input sourcemap from a previous compilation
//},
files: {
'playground/dist/rt-main.browser.min.js': ['playground/dist/rt-main.browser.js'],
'playground/libs/requirejs-plugins/text.min.js': ['playground/libs/requirejs-plugins/text.js'],
'playground/libs/requirejs-plugins/json.min.js': ['playground/libs/requirejs-plugins/json.js']
}
}
},
requirejs: {
compile: {
options: readConfig('./home.config.js')
},
playground: {
options: readConfig('./playground.config.js')
}
}
});
function readConfig(file) {
return eval(require('fs').readFileSync(file).toString()); // eslint-disable-line no-eval
}
grunt.loadNpmTasks('grunt-tape');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.loadNpmTasks('grunt-eslint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['eslint:all']);
grunt.registerTask('lint', ['eslint:all']);
grunt.registerTask('test', ['tape']);
grunt.registerTask('rt', () => {
const reactTemplates = require('./src/cli');
const files = grunt.file.expand('playground/*.rt');
const ret = reactTemplates.execute({modules: 'amd', force: true, _: files});
return ret === 0;
});
grunt.registerTask('build', ['rt', 'browserify:pg']);
grunt.registerTask('home', ['rt', 'browserify:home']);
grunt.registerTask('pgall', ['rt', 'browserify', 'uglify', 'requirejs']);
grunt.registerTask('all', ['default', 'test']);
};

513
README.md
View File

@ -1,44 +1,92 @@
# react-templates
[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[![Coverage Status][coveralls-image]][coveralls-url]
Light weight templates for react. Reasons that we love it:
# React Templates
* No runtime libraries. No magic. Just simple pre-compilation to a clear code
* Super easy to write panels. By panels we mean components that have a lot of HTML code and non-reusable logic
* Very good separation of presentation and logic. Almost no HTML within the component file
* Declerative coding for presentation. HTML that you write and inspect look similar
* Easy syntax. Similar to HTML. All IDEs recognize this format
Lightweight templates for [React](http://facebook.github.io/react/index.html).
* No runtime libraries. No magic. Simply precompile your way to clear React code.
* Easy syntax that's similar to HTML, supported by most IDEs.
* Clear separation of presentation and logic - almost zero HTML in component files.
* Declarative coding ensures that the HTML that you write and the HTML you inspect look nearly identical.
* Supports AMD, CommonJS, ES6, Typescript and globals.
## How does it work
React templates compiles a *.rt file (react template file - extended HTML format) into a javascript file. Currently, this file supports requirejs format, that will return a function. This function, when applied, will return a virtual react DOM (based on React.DOM elements and user custom components). A common use case would be that a React component would require a JS file generated by a template, and then call `func.apply(this)`, causing the template to have the component as its context.
React Templates compiles an *.rt file (react template file - an extended HTML format) into a JavaScript file.
This file, which uses AMD syntax, returns a function. When invoked, this function returns a virtual React DOM based on React.DOM elements and custom user components.
<p>A common use case would be that a regular React component would require a JavaScript file generated from a template,
and then perform `func.apply(this)`, causing the template to have that component as its context.
###### Basic concepts for react templates
* Any valid HTML is a template (and comments)
## Playground
http://wix.github.io/react-templates/
## Yeoman generator
https://github.com/wix/generator-react-templates
## Hello react-templates
Here's a sample Hello project:<br/>
https://github.com/wix/hello-react-templates
Here's a sample Hello project with webpack, es6 and hot reload:<br/>
https://github.com/wix/react-templates-transform-boilerplate
## IntelliJ / WebStorm plugin
http://plugins.jetbrains.com/plugin/7648
## Basic concepts for React templates
* Any valid HTML (including comments) is a template
* {} to identify JS expression
* rt-if
* rt-repeat
* rt-scope
* rt-class
* style
* event handlers
* doctype rt, require dependencies, and calling other components
* Built-in directives:
* [rt-if](#rt-if)
* [rt-repeat](#rt-repeat)
* [rt-scope](#rt-scope)
* [rt-props](#rt-props)
* [rt-class](#rt-class)
* [rt-import](#rt-import)
* ~~rt-require~~ (deprecated, use rt-import)
* [rt-template](#rt-template)
* [rt-include](#rt-include)
* [rt-pre](#rt-pre)
* [styles](#styles)
* [event handlers](#event-handlers)
###### Why not use JSX?
Some love jsx, some don't. We don't. Well, not that we don't like it, but it seems to fit only components with very little html inside, which could be done by creating elements in code. Also, we like to separate code and html. It just feels right.
## Why not use JSX?
Some love JSX, some don't. We don't. More specifically, it seems to us that JSX is only a good fit for components with very little HTML inside.
And this can be accomplished by creating DOM elements in code. Also, we like to separate code and HTML because it just feels right.
## Installation
You can install react-templates using npm:
```shell
npm install react-templates -g
```
## Usage
**src/cli.js < filename.rt >**
*(you might need to provide execution permission to the file)*
```shell
rt [file.rt|dir]* [options]
```
Note that in most cases, this package will be wrapped in a grunt task, so the cli will not be used directly
TODO: pointer to the grunt repository
See more on CLI usage [here](https://github.com/wix/react-templates/blob/gh-pages/docs/cli.md).
In most cases, this package will be wrapped in a build task, so CLI will not be used explicitly:
* Grunt: [grunt-react-templates](https://github.com/wix/grunt-react-templates)
* Gulp: [gulp-react-templates](https://github.com/wix/gulp-react-templates)
* Broccoli: [broccoli-react-templates](https://github.com/kraftwer1/broccoli-react-templates)
* Browserify plugin: [react-templatify](https://www.npmjs.com/package/react-templatify)
* Webpack loader : [react-templates-loader](https://github.com/AlexanderPavlenko/react-templates-loader)
### Use React Templates for Native Apps?
You can get all the react templates functionality and more. [Click here for more info](https://github.com/wix/react-templates/blob/gh-pages/docs/native.md)
# Template directives and syntax
## Any valid HTML is a template
Writing any html is a valid template. This does not apply to event handlers ("on" methods). See the section about event handlers
Any HTML that you write is a valid template, except for inline event handlers ("on" attributes). See the "event handlers" section below for more information.
## {} to identify JS expression
In html attributes and text, you can replace context by a javascript expression. You do this by wrapping it in {}. If this is inside an attribute, it still needs to be wrapped by quotes. In text, you can just use it.
## {} to identify JavaScript expressions
To embed JavaScript expressions in both attribute values and tag content, encapsulate them in {}.
If this is done inside an attribute value, the value still needs to be wrapped in quotes. For directives (see below), {} are not used.
###### Sample:
```html
@ -56,10 +104,9 @@ define([
};
});
```
*Note: within the special **"rt-"** directives, simple strings don't make sense, as all those directives apply on some execution context. Therefore, in these directives, there won't be a need to add the {} to identify execution context*
## rt-if
This gives you the ability to add conditions to a sub-tree of html. If the condition is evaluated to true, the subree will be returned, otherwise, it will not be calculated. It is implemented by a trinary expression
This lets you add conditions to a subtree of HTML. If the condition evaluates to true, the subtree will be returned; otherwise, it will not be calculated. It is implemented as a ternary expression.
###### Sample:
@ -80,11 +127,13 @@ define([
```
## rt-repeat
Repeats a node with its subtree for each item in an array. This is implemented by creating a method that is passed to a map call as a callback. It creates a real context for the iterated variable. The syntax is `rt-repeat="itemVar in arrayExpr"`. Within the scope of the element, `itemVar` will be available in javascript context, and also an `itemVarIndex` will be created to represent the index of the item. If the definition is `myNum in this.getMyNumbers()`, than there will be 2 variables in the scope: `myNum` and `myNumIndex`. This naming is used to allow nesting of repeat expression with access to all levels.
Repeats a DOM node with its subtree for each item in an array. The syntax is `rt-repeat="itemVar, indexVar in arrayExpr"`, where the element, `itemVar`, will be available in JavaScript context,
and an `itemVarIndex` will be created to represent the index of the item. By using this naming scheme, repeated expressions have access to all levels of nesting.
It is also possible to declare a custom index variable using the syntax `rt-repeat="itemVar, indexVar in arrayExpr"`, in which case the index variable will be `indexVar`.
###### Sample:
```html
<div rt-repeat="myNum in this.getMyNumbers()">{myNumIndex}. myNum</div>
<div rt-repeat="myNum in this.getMyNumbers()">{myNumIndex}. {myNum}</div>
```
###### Compiled:
```javascript
@ -94,7 +143,7 @@ define([
], function (React, _) {
'use strict';
function repeatMyNum1(myNum, myNumIndex) {
return React.DOM.div({}, myNumIndex + '. myNum');
return React.DOM.div({}, myNumIndex + '. ' + myNum);
}
return function () {
return _.map(this.getMyNumbers(), repeatMyNum1.bind(this));
@ -102,8 +151,49 @@ define([
});
```
## rt-virtual
This directive creates as a virtual node, which will not be rendered to the DOM, but can still be used as a root for directives, e.g. `rt-if` and `rt-repeat`.
###### Sample:
For instance, to repeat several nodes at once without a shared root for each instance:
```html
<ul>
<rt-virtual rt-repeat="n in [1,2,3]">
<li>{n}</li>
<li>{n*2}</li>
</virtual>
</ul>
```
##### Compiled:
```javascript
define([
'react/addons',
'lodash'
], function (React, _) {
'use strict';
function repeatN1(n, nIndex) {
return [
React.createElement('li', {}, n),
React.createElement('li', {}, n * 2)
];
}
return function () {
return React.createElement.apply(this, [
'ul',
{},
_.map([
1,
2,
3
], repeatN1.bind(this))
]);
};
});
```
## rt-scope
This directive creates a new javascript scope. It actually creates a new method for this scope, and calls it with its current context. The syntax is `rt-scope="expr1 as var1; expr2 as var2`. This gives a convenience method to shorten stuff up in a scope and make the code more readable. It also helps to execute an expression only once in a scope instead of every chunk that needs it.
This directive creates a new JavaScript scope by creating a new method and invoking it with its current context. The syntax is `rt-scope="expr1 as var1; expr2 as var2`.
This allows for a convenient shorthand to make the code more readable. It also helps to execute an expression only once per scope.
###### Sample:
```html
@ -136,10 +226,59 @@ define([
});
```
Subsequent expressions may reference preceding variables, since generated code declares each alias as a `var` (as opposed to a function parameter, which get bound to formal parameter names only after evaluation),
so you can do stuff like
```html
<div rt-scope="users[userId] as user; user.profile as profile; profile.avatar as avatar;">
```
When used with `rt-if`, the `rt-if` condition is evaluated first, and only if it is truthy, the `rt-scope` mappings are processed. This means you can write things like
```html
<div rt-if="user.profile" rt-scope="user.profile.image as image">
```
without risking accessing a field on an `undefined`, or doing something ugly like `user.profile && user.profile.image as image`.
When used with `rt-repeat`, the `rt-scope` is evaluated for every iteration, so that iteration's `item` and `itemIndex` are in scope.
## rt-props
rt-props is used to inject properties into an element programmatically. It will merge the properties with the properties received in the template.
This option allows you to build properties based on external logic and pass them to the template. It is also useful when passing properties set on the component to an element within the template.
The expected value of this attribute is an expression returning an object. The keys will be the property name, and the values will be the property values.
###### Sample:
```html
<input style="height:10px;width:3px;" rt-props="{style:{width:'5px'},type:'text'}"/>
```
###### Compiled:
```javascript
define([
'react',
'lodash'
], function (React, _) {
'use strict';
return function () {
return React.DOM.input(_.merge({}, {
'style': {
height: '10px',
width: '3px'
}
}, {
style: { width: '5px' },
type: 'text'
}));
};
});
```
## rt-class
In order to reduce the boiler-plate code when programatically setting class names, you can use the rt-class directive. It expectes to get a JSON object with keys as class names, and a value of true or false as the value. If the value is true, the class name will be included. Please note the following:
1. In react templates, you can use the "class" attribute the same as you'd do in html. If you like, you can even have execution context within
2. You cannot use class and rt-class on the same html element
To reduce the boilerplate code when setting class names programatically, you can use the rt-class directive. It expects a JSON object with keys as class names, and a Boolean as the value.
If the value is true, the class name will be included.
<p>Note the following:<br/>
1. In React templates, you can use the "class" attribute as you would in HTML. <br/>
2. If you use both class and rt-class on the same HTML element, they get merged.
###### Sample:
```html
@ -174,8 +313,66 @@ define([
});
```
## rt-include
Optionally choose to extract static contents out of rt files.<br>
rt-include is a "macro" that takes a text file (e.g svg/html/xml) and injects it into the file as if it was part of the original markup.
###### Sample:
given `main.rt`:
```html
<div>
<rt-include src="./my-icon.svg" />
</div>
```
and `my-icon.svg`:
```html
<svg xmlns="http://www.w3.org/2000/svg">
<rect height="50" width="50" style="fill: #00f"/>
</svg>
```
is equivalent to:
```html
<div>
<svg xmlns="http://www.w3.org/2000/svg">
<rect height="50" width="50" style="fill: #00f"/>
</svg>
</div>
```
## rt-pre
When using the option `--normalize-html-whitespace` it allows to override the whitespace removal behaviour on a specific tag.
###### Sample:
given `main.rt`:
```html
<span rt-pre>
here repeating whitespaces are preserved
even if --normalize-html-whitespace is on
</span>
<span>
here repeating whitespaces are removed
if --normalize-html-whitespace is on
</span>
```
`rt-pre` is applied automatically on `<pre>` and `<textarea>` tags:
###### Sample:
given `main.rt`:
```html
<pre>
here repeating whitespaces are preserved
even if --normalize-html-whitespace is on
</pre>
```
## style
In order to make it closer to html, we allow the settings of inline styles. In addition, this will take care of changing the styles from hyphen-style to camelCase style. If you'd like, you can still return an object from evaluation context. Please note that if you do it inline, you'll need to open single curly braces for the js context, and another for the object. Also, you'll need to use camelCase if using it that way
React templates allow the settings of styles inline in HTML, optionally returning an object from the evaluation context. By default, style names will be converted from hyphen-style to camelCase-style naming.
To embed JavaScript inside a style attribute, single curly braces are used. To embed an entire object, double curly braces are used. *Note*: When embedding objects, styles must conform to camelCase-style naming.
###### Sample:
```html
@ -208,8 +405,36 @@ define([
});
```
## stateless components
Since React v0.14, [React allows defining a component as a pure function of its props](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions).
To enable creating a stateless component using react templates, add the `rt-stateless` attribute to the template's root element.
Using `rt-stateless` generates a stateless functional component instead of a render function.
The resulting function receives `props` and `context` parameters to be used in the template instead of `this.props`.
###### Sample:
```html
<div rt-stateless>Hello {props.person}</div>
```
###### Compiled:
```html
define([
'react',
'lodash'
], function (React, _) {
'use strict';
return function (props, context) {
return React.createElement('div', {}, 'Hello ', props.person);
};
});
```
## event handlers
React event handlers accept function pointers. Therefore, when using event, you can just open an execution context and provide a pointer to a method. This would look like `onClick="{this.myClickHandler}"`. However, sometimes there's very little to do on click, or we just want to call a method with bound parameters. In that case, you can use a lambda notation, which will result in creating a react template creating a method for the handler. It does not have a performance impact, as the method is created once, and just bound to the context instead of created again. The lambda notation will look like this `onClick="(evt) => console.log(evt)"`. In this example, **evt** was the name you choose for the first argument that will be passed into your inline method. With browser events, this will most likely be the react synthetic event. However, if you expect a property that starts with **on**Something, then react-templates will treat it as an event handler. So if you have an event handler called **onBoxSelected** that will trigger an event with a row and column params, you can write `onBoxSelected="(row, col)=>this.doSomething(row,col)"`. You can use a no-param version as well `onClick="()=>console.log('just wanted to know it clicked')"`
React event handlers accept function references inside of {}, such as `onClick="{this.myClickHandler}"`. When functions are not needed, lambda notation can be used,
which will create a React template that creates a function for the included code. There is no performance impact, as the function created is bound to the context instead of being recreated.
<p>The lambda notation has the form: `onClick="(evt) => console.log(evt)"`. In this example, **evt** is the name of the first argument passed into the inline function.
With browser events, this will most likely be the React synthetic event. However, if you expect a property that starts with **on**Something, then React templates will treat it as an event handler.
If you have an event handler called **onBoxSelected** that triggers an event with row and column params, you can write `onBoxSelected="(row, col)=>this.doSomething(row,col)"`.
A no-param version is supported as well: `onClick="()=>console.log('just wanted to know it clicked')"`.
###### Sample:
```html
@ -239,31 +464,209 @@ define([
});
```
## doctype rt, require dependencies, and calling other components
In many cases, you'd like to use either library code, or other components within your template. In order to do so, you can define a doctype and indicate dependencies. You do so by `<!doctype rt depVarName="depVarPath">`. After that, you will have **depVarName** in your scope. You can import react components and use them afterwords in the template as tag names. For example `<MySlider prop1="val1" onMyChange="{this.onSliderMoved}">`. This will also support nesting `<MyContainer><div>child</div><div>another</div></MyContainer>`. You will then be able to find the children in **this.props.children**.
###### Sample:
```html
<!doctype rt MyComp="comps/myComp" utils="utils/utils">
<MyComp rt-repeat="item in items">
<div>{utils.toLower(item.name)}</div>
</MyComp>
## rt-import and using other components in the template
In many cases, you'd like to use either external code or other components within your template.
To do so, you can use an `rt-import` tag that lets you include dependencies in a syntax similar to ES6 imports:
```xml
<rt-import name="*" as="depVarName" from="depName"/>
```
###### Compiled:
Once included, **depVarName** will be in scope.
You can only use rt-import tags at the beginning of your template. When including React components, they can be referred to by their tag name inside a template.
For example, `<MySlider prop1="val1" onMyChange="{this.onSliderMoved}">`. Nesting is also supported: `<MyContainer><div>child</div><div>another</div></MyContainer>`.
Children are accessible from **this.props.children**.
###### Sample:
```xml
<rt-import name="member" from="module-name"/>
<rt-import name="member" as="alias2" from="module-name"/>
<rt-import name="*" as="alias3" from="module-name"/>
<rt-import name="default" as="alias4" from="module-name"/>
<div>
</div>
```
###### Compiled (ES6 flag):
```javascript
define([
import * as React from 'react/addons';
import * as _ from 'lodash';
import { member } from 'module-name';
import { member as alias2 } from 'module-name';
import * as alias3 from 'module-name';
import alias4 from 'module-name';
export default function () {
return React.createElement('div', {});
}
```
###### Compiled (AMD):
```javascript
define('div', [
'react',
'lodash',
'comps/myComp',
'utils/utils'
], function (React, _, MyComp, utils) {
'module-name',
'module-name',
'module-name',
'module-name'
], function (React, _, $2, $3, alias3, $5) {
'use strict';
function repeatItem1(item, itemIndex) {
return MyComp({}, React.DOM.div({}, utils.toLower(item.name)));
}
var member = $2.member;
var alias2 = $3.member;
var alias4 = $5.default;
return function () {
return _.map(items, repeatItem1.bind(this));
return React.createElement('div', {});
};
});
```
###### Compiled (with CommonJS flag):
```javascript
'use strict';
var React = require('react/addons');
var _ = require('lodash');
var member = require('module-name').member;
var alias2 = require('module-name').member;
var alias3 = require('module-name');
var alias4 = require('module-name').default;
module.exports = function () {
return React.createElement('div', {});
};
```
#### deprecated: rt-require
The tag `rt-require` is deprecated and replaced with `rt-import`.
Its syntax is similar to `rt-import` but does not allow default imports:
```html
<rt-require dependency="comps/myComp" as="MyComp"/>
<rt-require dependency="utils/utils" as="utils"/>
<MyComp rt-repeat="item in items">
<div>{utils.toLower(item.name)}</div>
</MyComp>
```
## Inline Templates
Although we recommend separating the templates to a separate `.rt` file, there's an option to use a template inline as the render method (à la JSX).
To do that, write your code in a `.jsrt` file, and send it to react-templates with the `modules` flag set to `jsrt`.
###### Sample:
```javascript
define(['react','lodash'], function (React, _) {
var comp = React.createClass({
render:
<template>
<div>hello world</div>
</template>
});
return comp;
});
```
###### Compiled (with jsrt flag):
```javascript
define([
'react',
'lodash'
], function (React, _) {
var comp = React.createClass({
render: function () {
return function () {
return React.createElement('div', {}, 'hello world');
};
}()
});
return comp;
});
```
## rt-template, and defining properties template functions
In cases you'd like to use a property that accepts a function and return renderable React component.
You should use a **rt-template** tag that will let you do exactly that: `<rt-template prop="propName" arguments="arg1, arg2"/>`.
Templates can be used only as an immediate child of the component that it will be used in. All scope variable will be available in the template function.
###### Sample:
```html
<MyComp data="{[1,2,3]}">
<rt-template prop="renderItem" arguments="item">
<div>{item}</div>
</rt-template>
</MyComp>
```
###### Compiled (AMD):
```javascript
define([
'react/addons',
'lodash'
], function (React, _) {
'use strict';
function renderItem1(item) {
return React.createElement('div', {}, item);
}
return function () {
return React.createElement(MyComp, {
'data': [
1,
2,
3
],
'renderItem': renderItem1.bind(this)
});
};
});
```
###### Compiled (with CommonJS flag):
```javascript
'use strict';
var React = require('react/addons');
var _ = require('lodash');
function renderItem1(item) {
return React.createElement('div', {}, item);
}
module.exports = function () {
return React.createElement(MyComp, {
'data': [
1,
2,
3
],
'renderItem': renderItem1.bind(this)
});
};
```
###### Compiled (with ES6 flag):
```javascript
import React from 'react/addons';
import _ from 'lodash';
function renderItem1(item) {
return React.createElement('div', {}, item);
}
export default function () {
return React.createElement(MyComp, {
'data': [
1,
2,
3
],
'renderItem': renderItem1.bind(this)
});
};
```
## Contributing
See the [Contributing page](CONTRIBUTING.md).
## License
Copyright (c) 2015 Wix. Licensed under the MIT license.
[npm-image]: https://img.shields.io/npm/v/react-templates.svg?style=flat-square
[npm-url]: https://npmjs.org/package/react-templates
[travis-image]: https://img.shields.io/travis/wix/react-templates/gh-pages.svg?style=flat-square
[travis-url]: https://travis-ci.org/wix/react-templates
[coveralls-image]: https://img.shields.io/coveralls/wix/react-templates/gh-pages.svg?style=flat-square
[coveralls-url]: https://coveralls.io/r/wix/react-templates?branch=gh-pages
[downloads-image]: http://img.shields.io/npm/dm/react-templates.svg?style=flat-square
[downloads-url]: https://npmjs.org/package/react-templates

6
bin/rt.js Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env node
'use strict';
const cli = require('../dist/cli');
const exitCode = cli.execute(process.argv);
/*eslint no-process-exit:0*/
process.exit(exitCode);

127
docs/cli.md Normal file
View File

@ -0,0 +1,127 @@
# Command line Interface
## Installation
```shell
npm install react-templates -g
```
## Usage
```shell
rt [file.rt|glob]* [options]
```
Such as:
```shell
rt dir/file.rt
```
Please note that when passing a glob as a parameter, it will be expanded by your shell.
The results of the expansion can vary depending on your shell, and its configuration.
If you want to use node glob syntax, you have to quote your parameter (using double quotes if you need it to run in Windows), as follows:
```shell
rt 'src/**/*.rt'
```
## Options
The command line utility has several options. You can view the options by running `rt -h`.
```
Usage:
$ rt <filename> [<filename> ...] [<args>]
Options:
-h, --help Show help.
-c, --color Use colors in output. - default: true
-m, --modules String Use output modules. (amd|commonjs|none|es6|typescript|jsrt) - either: amd, commonjs, none, es6, typescript, or jsrt
-n, --name String When using globals, the name for the variable. The default is the [file name]RT, when using amd, the name of the module
-d, --dry-run Run compilation without creating an output file, used to check if the file is valid - default: false
-r, --force Force creation of output. skip file check. - default: false
-f, --format String Use a specific output format. (stylish|json) - default: stylish
-t, --target-version String 'React version to generate code for (15.0.1, 15.0.0, 0.14.0, 0.13.1, 0.12.2, 0.12.1, 0.12.0, 0.11.2, 0.11.1, 0.11.0, 0.10.0, default)' - default: 0.14.0
--list-target-version Show list of target versions - default: false
-v, --version Outputs the version number.
-k, --stack Show stack trace on errors.
--react-import-path String Dependency path for importing React.
--lodash-import-path String Dependency path for importing lodash. - default: lodash
--native, --rn Renders react native templates.
--flow Add /* @flow */ to the top of the generated file
--native-target-version, --rnv String React native version to generate code for (0.9.0, 0.29.0, default) - either: 0.9.0, 0.29.0, or default - default: 0.9.0
--normalize-html-whitespace Remove repeating whitespace from HTML text. - default: false
```
### `-h`, `--help`
This option outputs the help menu, displaying all of the available options. All other flags are ignored when this is present.
### `-c`, `--color`
The option enable or disable color in the output.
### `-m`, `--modules`
Use output modules. Valid targets are: `amd`, `commonjs`, `none`, `es6`, `typescript`, or `jsrt`.
### `-n`, `--name`
When using globals, the name for the variable. The default is the [file name]RT, when using amd, the name of the module.
### `-d`, `--dry-run`
Run compilation without creating an output file, used to check if the file is valid - default: false
### `-r`, `--force`
This option allows to override the output file even if there are no changes.
### `-f`, `--format`
Use a specific output format (`stylish` or `json`).
### `-t`, `--target-version`
React version to generate code for (15.0.1, 15.0.0, 0.14.0, 0.13.1, 0.12.2, 0.12.1, 0.12.0, 0.11.2, 0.11.1, 0.11.0, 0.10.0, default). default: 0.14.0
### `--list-target-version`
Show list of target versions.
### `-v`, `--version`
Outputs the version number.
### `-k`, `--stack`
Show stack trace on errors.
### `--react-import-path`
Dependency path for importing React.
### `--lodash-import-path`
Dependency path for importing lodash.
### `--native`, `--rn`
Renders react native templates.
### `--native-target-version`, `--rnv`
React native version to generate code for (0.9.0, 0.29.0, default) - either: 0.9.0, 0.29.0, or default - default: 0.9.0
### `--flow`
Add /* @flow */ to the top of the generated file
### `--normalize-html-whitespace`
Remove repeating whitespace from HTML text.
Repeating whitespaces normally are not displayed and thus can be removed in order to reduce
the size of the generated JavaScript file.
Whitespace removal is not applied on `<pre>` and `<textarea>` tags, or when the special attribute `rt-pre` is specified on a tag.

23
docs/integrations.md Normal file
View File

@ -0,0 +1,23 @@
# Integrations
## Intellij / WebStorm
### Install intellij react templates plugin
1. From intellij/WebStorm open preferences
2. Go to plugins
3. Press browse repositories
4. Press manage repositories
5. Add repository: http://intellij.wixpress.com/
6. Select react-templates from the repository.
7. Press ok and restart the IDEA.
8. Open preferences
9. Go to react-packages plugin
10. Enable the plugin.
11. Configure node
12. Configure react template executable
### enable es6
react templates uses es6 syntax for lambda expressions in event handlers, enable this in the IDE:
![ES6 in intellij](https://raw.githubusercontent.com/wix/react-templates/gh-pages/docs/intellij-es6.png "ES6 in intellij")

BIN
docs/intellij-es6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

123
docs/native.md Normal file
View File

@ -0,0 +1,123 @@
# React Templates for Native Apps
In order to use React Templates for [React Native](https://facebook.github.io/react-native/) you should set the `native` option to true.
In native mode the default `modules` option is set to `commonjs` and the default `react-import-path` is set to `react-native`.
## Default properties templates configuration
In native mode we define a default properties template configuration in order to easily write native templates.
```javascript
{
ListView: {
Row: {prop: 'renderRow', arguments: ['rowData', 'sectionID', 'rowID', 'highlightRow']},
Footer: {prop: 'renderFooter', arguments: []},
Header: {prop: 'renderHeader', arguments: []},
ScrollComponent: {prop: 'renderScrollComponent', arguments: ['props']},
SectionHeader: {prop: 'renderSectionHeader', arguments: ['sectionData', 'sectionID']},
Separator: {prop: 'renderSeparator', arguments: ['sectionID', 'rowID', 'adjacentRowHighlighted']}
}
}
```
With this configuration you can write your ListView component as follow:
##### With default arguments:
```html
<View>
<ListView dataSource="{this.state.dataSource}">
<Row>
<Text>{rowData}</Text>
</Row>
</ListView>
</View>
```
###### Compiled:
```javascript
'use strict';
var React = require('react-native');
var _ = require('lodash');
function renderRow1(rowData) {
return React.createElement(React.Text, {}, rowData);
}
module.exports = function () {
return React.createElement(React.View, {}, React.createElement(React.ListView, {
'dataSource': this.state.dataSource,
'renderRow': renderRow1.bind(this)
}));
};
```
##### With custom arguments:
```html
<View>
<ListView dataSource="{this.state.dataSource}">
<Row arguments="item">
<Text>{item}</Text>
</Row>
</ListView>
</View>
```
###### Compiled:
```javascript
'use strict';
var React = require('react-native');
var _ = require('lodash');
function renderRow1(item) {
return React.createElement(React.Text, {}, item);
}
module.exports = function () {
return React.createElement(React.View, {}, React.createElement(React.ListView, {
'dataSource': this.state.dataSource,
'renderRow': renderRow1.bind(this)
}));
};
```
## Native style support
This feature is **Experimental** and is subject to change.
You can use rt to compile a style file similar to css:
```
.text {
background-color: #00346E;
padding: 3px;
}
.fonts {
background-color: #000099;
height: 30px;
}
```
will result in:
```javascript
'use strict';
var style = {
"text": {
"backgroundColor": "#00346E",
"padding": 3
},
"fonts": {
"backgroundColor": "#000099",
"height": 30
}
};
module.exports = style;
```
Which later you can import in your react native component:
```javascript
var styles = StyleSheet.create(require('./style.rts'))
```

49
fiddle.html Normal file
View File

@ -0,0 +1,49 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>React templates | RTFiddle</title>
<meta name="viewport" content="width=device-width">
<meta name="description" content="Light weight templates for React.">
<link rel="shortcut icon" href="https://facebook.github.io/react/favicon.ico">
<link href='//fonts.googleapis.com/css?family=Lato:100,300,400,700' rel='stylesheet' type='text/css'>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<!-- Latest compiled and minified JavaScript -->
<link rel="stylesheet" href="playground/libs/codemirror-4.8/lib/codemirror.css" />
<link rel="stylesheet" href="playground/libs/codemirror-4.8/theme/solarized.css" />
<link rel="stylesheet" href="playground/libs/codemirror-4.8/addon/hint/show-hint.css">
<link rel="stylesheet" href="playground/libs/codemirror-4.8/addon/lint/lint.css">
<link rel="stylesheet" href="playground/css/playground.css"/>
<link rel="stylesheet" href="playground/css/fiddle.css"/>
</head>
<body>
<div id="container">
</div>
<!--<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>-->
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<!--<script src="playground/libs/ace-builds-1.1.8/src-min-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>-->
<!--<script src="https://cdn.firebase.com/js/client/2.0.5/firebase.js"></script>-->
<!--<script src="playground/libs.browser.js"></script>-->
<script src="playground/dist/rt-main.browser.js"></script>
<!--<script data-main="playground/fiddle-main.js" src="http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.20/require.js"></script>-->
<script data-main="playground/dist/fiddle.min.js" src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.20/require.min.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-58169705-1', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

30
home.config.js Normal file
View File

@ -0,0 +1,30 @@
/*eslint semi:0,no-unused-expressions:0,no-extra-parens:0,strict:0*/
({
baseUrl: 'playground',
//name: 'node_modules/almond/almond.js', // assumes a production build using almond
out: 'playground/dist/home.min.js',
include: ['home-main.js'],
paths: {
lodash: '//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash',
jquery: '//code.jquery.com/jquery-1.11.0.min',
firebase: '//cdn.firebase.com/js/client/2.0.5/firebase',
react: '//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-with-addons',
'react-dom': '//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom',
//ace: '../ace-builds-1.1.8/src-min/ace',
fiddle: './fiddle',
text: 'libs/requirejs-plugins/text',
json: 'libs/requirejs-plugins/json'
},
shim: {
lodash: {exports: '_'},
firebase: {exports: 'Firebase'},
jquery: {exports: '$'},
react: {exports: 'React'},
'react-dom': {exports: 'ReactDOM'}
},
map: {
'*': {
'react/addons': 'react'
}
}
})

BIN
img/github-fork-me.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

20
img/logo-rt.svg Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="902px" height="392px" viewBox="-4 72 902 392" enable-background="new -4 72 902 392" xml:space="preserve">
<circle fill="#00D8FF" cx="353.3" cy="269.3" r="37.1"/>
<path fill="none" stroke="#00D8FF" stroke-width="25" stroke-miterlimit="10" d="M353.4,196.2c48.3,0,92.9,7,126.7,18.6
c40.7,13.9,65.7,35.2,65.7,54.4c0,20.1-26.6,42.6-70.2,57.1c-33,10.8-76.5,16.6-122.2,16.6c-46.9,0-91.3-5.3-124.8-16.8
c-42.2-14.5-67.7-37.2-67.7-56.9c0-19,23.9-40.1,64.1-54C258.9,203.2,304.7,196.2,353.4,196.2z"/>
<path fill="none" stroke="#00D8FF" stroke-width="25" stroke-miterlimit="10" d="M290,232.9c24.2-41.8,52.4-77.2,79.4-100.5
c32.5-28.2,63.4-39.3,80-29.7c17.4,10,23.7,44.2,14.3,89.2c-7,34.2-23.7,74.5-46.7,114.2c-23.5,40.7-50.3,76.5-77,99.7
c-33.6,29.5-66.1,40.1-83.1,30.3c-16.6-9.6-22.9-40.7-14.9-82.5C248.8,318.4,265.6,275,290,232.9z"/>
<path fill="none" stroke="#00D8FF" stroke-width="25" stroke-miterlimit="10" d="M290,306.3c-24.2-41.8-40.7-83.9-47.5-119.1
c-8.2-42.2-2.5-74.5,14.1-84.1c17.4-10,50.1,1.6,84.5,32.1c26,23.1,52.8,57.9,75.7,97.4c23.5,40.5,41.1,81.7,47.9,116.5
c8.6,43.8,1.6,77.4-15.3,87.2c-16.6,9.6-46.7-0.6-79-28.2C343.4,384.5,314.3,348.5,290,306.3z"/>
<polyline fill="none" stroke="#00D8FF" stroke-width="32" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
163.4,423.5 28.9,270.3 28.9,268.9 163.4,115.5 "/>
<polyline fill="none" stroke="#00D8FF" stroke-width="32" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
734.2,423.5 868.7,270.3 868.7,268.9 734.2,115.5 "/>
<line fill="none" stroke="#00D8FF" stroke-width="32" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="680.8" y1="101.3" x2="560.4" y2="437.7"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
img/samples/delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

View File

@ -1,16 +1,97 @@
<!doctype html>
<html lang="en">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>React templates - Image Search Sample</title>
<link rel="stylesheet" href="playground/playground.css"/>
<link rel="stylesheet" href="playground/codemirror.css">
<link rel="stylesheet" href="playground/solarized.css">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>React Templates</title>
<meta name="viewport" content="width=device-width">
<meta name="description" content="Light weight templates for React.">
<link rel="shortcut icon" href="https://facebook.github.io/react/favicon.ico">
<link href='//fonts.googleapis.com/css?family=Lato:100,300,700' rel='stylesheet' type='text/css'>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<!-- Optional theme -->
<!--<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css">-->
<link rel="stylesheet" href="playground/libs/codemirror-4.8/lib/codemirror.css"/>
<link rel="stylesheet" href="playground/libs/codemirror-4.8/theme/solarized.css"/>
<link rel="stylesheet" href="playground/libs/codemirror-4.8/addon/hint/show-hint.css">
<link rel="stylesheet" href="playground/libs/codemirror-4.8/addon/lint/lint.css">
<link rel="stylesheet" href="playground/css/playground.css"/>
<link rel="stylesheet" href="playground/css/home.css"/>
<!--<link rel="stylesheet" href="playground/dist/css/tidy.css"/>-->
</head>
<body>
<div id="playground">
<div class="container">
<div class="nav-main">
<div class="wrap">
<a class="nav-home" href="index.html">
<img class="nav-logo" src="https://wix.github.io/react-templates/img/logo-rt.svg" width="56" height="24" />
<span>React Templates</span>
</a>
<ul class="nav-site">
<li><a href="fiddle.html">Playground</a></li>
<li><a href="https://github.com/wix/react-templates#template-directives-and-syntax">docs</a></li>
<li><a href="https://github.com/wix/react-templates#installation">download</a></li>
<li><a href="https://github.com/wix/react-templates">github</a>
</ul>
</div>
</div>
<a href="https://github.com/wix/react-templates" target="_blank">
<img class="img-fork-github" src="img/github-fork-me.png" alt="Fork me on GitHub" />
</a>
<div class="hero">
<div class="wrap">
<div class="text">React Templates</div>
<div class="minitext">
Lightweight Templates for React
</div>
<div class="buttons-unit">
<a href="fiddle.html" class="button">Check Out the Playground</a>
</div>
</div>
</div>
<section class="content wrap">
<section class="love-list">
<ul>
<li>No runtime libraries. No magic. Simply precompile your way to clear React code.</li>
<li>Easy syntax that's similar to HTML, supported by most IDEs.</li>
<li>Clear separation of presentation and logic - almost zero HTML in component files.</li>
<li>Declarative coding ensures that the HTML that you write and the HTML you inspect look nearly identical.</li>
<li>Supports <a href="#amd">AMD</a>, <a href="#commonjs">CommonJS</a>, <a href="#es6">ES6</a>, Typescript and globals.</li>
</ul>
</section>
<section id="home-section" class="home-section">
<div id="loading">
Loading...
</div>
</section>
</section>
<footer class="footer">
<span>Sponsored by </span> <a href="//wix.com" class="wf-white-logo"></a>
</footer>
</div>
<script src="playground/main.browser.js"></script>
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="playground/dist/rt-main.browser.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.20/require.min.js"></script>
<!--<script src="playground/home-main.js"></script>-->
<script src="playground/dist/home.min.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-58169705-1', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

View File

@ -1,13 +1,23 @@
{
"name": "react-templates",
"version": "0.0.1",
"version": "0.6.1",
"description": "Light weight templates for react -> write html get valid react code",
"main": "./src/reactTemplates.js",
"main": "./dist/cli.js",
"bin": {
"rt": "./src/cli.js"
"rt": "./bin/rt.js"
},
"scripts": {
"test": "node test/src/test.js"
"build": "npm run lint && npm run test",
"lint": "eslint .",
"test": "babel-node test/src/test.js",
"test-cov": "istanbul cover test/src/test.js -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/",
"patch": "npm version patch -m\"update version to %s\" && git push && git push --tags",
"minor": "npm version minor -m\"update version to %s\" && git push && git push --tags",
"major": "npm version major -m\"update version to %s\" && git push && git push --tags",
"buildwp": "webpack --config webpack-production.config.js --progress --profile --colors",
"babel": "rm -rf dist && babel src/ --out-dir dist",
"all": "npm run lint && npm run test",
"prepublish": "npm run babel"
},
"repository": {
"type": "git",
@ -20,14 +30,53 @@
},
"homepage": "https://github.com/wix/react-templates",
"dependencies": {
"chalk": "^0.5.1",
"cheerio": "^0.18.0",
"escodegen": "^1.4.1",
"esprima": "^1.2.2",
"lodash": "^2.4.1",
"react": "^0.12.0"
"chalk": "1.1.3",
"cheerio": "0.22.0",
"css": "2.2.1",
"escodegen": "1.8.1",
"esprima": "3.1.3",
"glob": "7.1.1",
"lodash": "4.17.4",
"normalize-html-whitespace": "0.2.0",
"optionator": "0.8.2",
"text-table": "0.2.0"
},
"devDependencies": {
"tape": "^3.0.2"
}
"babel-cli": "6.18.0",
"babel-core": "6.21.0",
"babel-loader": "6.2.10",
"babel-preset-es2015": "6.18.0",
"brace": "0.9.1",
"brfs": "1.4.3",
"coveralls": "2.11.15",
"eslint": "3.12.2",
"eslint-config-wix-editor": "0.2.3",
"eslint-plugin-lodash": "2.2.5",
"eslint-plugin-react": "6.8.0",
"eslint-plugin-wix-editor": "1.1.1",
"grunt": "1.0.1",
"grunt-babel": "6.0.0",
"grunt-browserify": "5.0.0",
"grunt-contrib-requirejs": "1.0.0",
"grunt-contrib-uglify": "2.0.0",
"grunt-contrib-watch": "1.0.0",
"grunt-eslint": "19.0.0",
"grunt-tape": "0.1.0",
"istanbul": "0.4.5",
"json-loader": "0.5.4",
"react": "15.3.2",
"react-dom": "15.3.2",
"react-native": "0.39.2",
"tape": "4.6.3",
"webpack": "1.14.0"
},
"keywords": [
"templates",
"react-templates",
"react",
"reactjs",
"react.js",
"react-component",
"react component"
]
}

30
playground.config.js Normal file
View File

@ -0,0 +1,30 @@
({
baseUrl: 'playground',
//name: 'node_modules/almond/almond.js', // assumes a production build using almond
out: 'playground/dist/fiddle.min.js',
include: ['fiddle-main.js'],
paths: {
lodash: '//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash',
jquery: '//code.jquery.com/jquery-2.1.4.min',
firebase: '//cdn.firebase.com/js/client/2.0.5/firebase',
react: '//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-with-addons',
'react-dom': '//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom',
//ace: '../ace-builds-1.1.8/src-min/ace',
fiddle: './fiddle',
text: 'libs/requirejs-plugins/text',
json: 'libs/requirejs-plugins/json',
bootstrap: 'libs/bootstrap/bootstrap.min'
},
shim: {
lodash: {exports: '_'},
firebase: {exports: 'Firebase'},
jquery: {exports: '$'},
react: {exports: 'React'},
'react-dom': {exports: 'ReactDOM'}
},
map: {
'*': {
'react/addons': 'react'
}
}
})

16
playground/.eslintrc Normal file
View File

@ -0,0 +1,16 @@
{
"rules": {
"strict": [2, "function"],
"no-var": 0,
"object-shorthand": 0,
"prefer-arrow-callback": 0
},
"env": {
"browser": true,
"node": true,
"amd": true
},
"globals": {
"requirejs": true
}
}

118
playground/CMLint.js Normal file
View File

@ -0,0 +1,118 @@
define(['react', 'lodash', 'jquery', './libs/codemirror-4.8/lib/codemirror'], function (React, _, $, CodeMirror) {
'use strict';
function annotationTooltip(ann) {
var severity = ann.severity;
if (!severity) {
severity = 'error';
}
var tip = document.createElement('div');
tip.className = 'CodeMirror-lint-message-' + severity;
tip.appendChild(document.createTextNode(ann.message));
return tip;
}
var GUTTER_ID = 'rt-annotations';
function annotate(editor, annot) {
//if (annot.index) {
// //posFromIndex
// var pos = editor.findPosH({line: 0, ch: 0}, 25, 'char');
// var range = editor.findWordAt(pos);
// editor.markText(range.anchor, range.head, {className: 'editor-error'});
//}
var tipLabel = document.createDocumentFragment(); /*state.hasGutter &&*/
var ann = {severity: 'error', message: annot.message};
tipLabel.appendChild(annotationTooltip(ann));
editor.setGutterMarker(Math.max(annot.line, 0), GUTTER_ID, makeMarker(tipLabel, 'error', false, 'state.options.tooltips'));
}
function clearMarks(cm) {
//var state = cm.state.lint;
//if (state.hasGutter) cm.clearGutter(GUTTER_ID);
//for (var i = 0; i < state.marked.length; ++i)
// state.marked[i].clear();
//state.marked.length = 0;
cm.clearGutter(GUTTER_ID);
}
function makeMarker(labels, severity, multiple, tooltips) {
var marker = document.createElement('div');
var inner = marker;
marker.className = 'CodeMirror-lint-marker-' + severity;
if (multiple) {
inner = marker.appendChild(document.createElement('div'));
inner.className = 'CodeMirror-lint-marker-multiple';
}
if (tooltips !== false) {
CodeMirror.on(inner, 'mouseover', function (e) {
showTooltipFor(e, labels, inner);
});
}
return marker;
}
function showTooltip(e, content) {
var tt = document.createElement('div');
tt.className = 'CodeMirror-lint-tooltip';
tt.appendChild(content.cloneNode(true));
document.body.appendChild(tt);
function position(ev) {
if (!tt.parentNode) {
return CodeMirror.off(document, 'mousemove', position);
}
tt.style.top = Math.max(0, ev.clientY - tt.offsetHeight - 5) + 'px';
tt.style.left = (ev.clientX + 5) + 'px'; //eslint-disable-line no-extra-parens
}
CodeMirror.on(document, 'mousemove', position);
position(e);
if (tt.style.opacity !== null) {
tt.style.opacity = 1;
}
return tt;
}
function rm(elt) {
if (elt.parentNode) {
elt.parentNode.removeChild(elt);
}
}
function hideTooltip(tt) {
if (!tt.parentNode) {
return;
}
if (tt.style.opacity === null) {
rm(tt);
}
tt.style.opacity = 0;
setTimeout(function () { rm(tt); }, 600);
}
function showTooltipFor(e, content, node) {
var tooltip = showTooltip(e, content);
function hide() {
CodeMirror.off(node, 'mouseout', hide);
if (tooltip) { hideTooltip(tooltip); tooltip = null; }
}
var poll = setInterval(function () {
if (tooltip) {
for (var n = node; ; n = n.parentNode) { //eslint-disable-line no-restricted-syntax
if (n === document.body) {
return undefined;
}
if (!n) { hide(); break; }
}
}
if (!tooltip) {
return clearInterval(poll);
}
}, 400);
CodeMirror.on(node, 'mouseout', hide);
}
return {
GUTTER_ID: GUTTER_ID,
annotate: annotate,
clearMarks: clearMarks
};
});

View File

@ -0,0 +1,175 @@
define([
'react', 'react-dom', 'lodash', 'jquery', './libs/codemirror-4.8/lib/codemirror',
'./CMLint',
'./libs/codemirror-4.8/mode/javascript/javascript',
'./libs/codemirror-4.8/addon/hint/html-hint',
'./libs/codemirror-4.8/addon/hint/show-hint',
'./libs/codemirror-4.8/addon/hint/xml-hint',
'./libs/codemirror-4.8/addon/hint/html-hint',
//'./libs/codemirror-4.8/addon/display/panel',
'./libs/codemirror-4.8/mode/xml/xml',
//'./libs/codemirror-4.8/mode/css/css',
'./libs/codemirror-4.8/addon/runmode/runmode'
//'./libs/codemirror-4.8/addon/display/placeholder'
], function (React, ReactDOM, _, $, CodeMirror, CMLint) {
'use strict';
//codeMirror: 'libs/codemirror-4.8/lib/codemirror',
//htmlmixed: 'libs/codemirror-4.8/mode/htmlmixed/htmlmixed',
//javascript: 'libs/codemirror-4.8/mode/javascript/javascript'
var rtSchema = {
div: {
attrs: {
'rt-props': null,
'rt-if': null,
'rt-repeat': null,
'rt-class': null,
'rt-scope': null,
valueLink: null,
key: null,
ref: null,
dangerouslySetInnerHTML: null
}
}
};
var tags = CodeMirror.htmlSchema;
Object.keys(CodeMirror.htmlSchema).forEach(function (i) {
tags[i].attrs = _.defaults(rtSchema.div.attrs, tags[i].attrs);
});
function completeAfter(cm, pred) {
//var cur = cm.getCursor();
if (!pred || pred()) {
setTimeout(function () {
if (!cm.state.completionActive) {
cm.showHint({completeSingle: false});
}
}, 100);
}
return CodeMirror.Pass;
}
function completeIfAfterLt(cm) {
return completeAfter(cm, function () {
var cur = cm.getCursor();
return cm.getRange(CodeMirror.Pos(cur.line, cur.ch - 1), cur) === '<'; //eslint-disable-line new-cap
});
}
function completeIfInTag(cm) {
return completeAfter(cm, function () {
var tok = cm.getTokenAt(cm.getCursor());
if (tok.type === 'string' && (!/['"]/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length === 1)) {
return false;
}
var inner = CodeMirror.innerMode(cm.getMode(), tok.state).state;
return inner.tagName;
});
}
return React.createClass({
displayName: 'CodeMirrorEditor',
propTypes: {
id: React.PropTypes.string,
readOnly: React.PropTypes.bool,
runMode: React.PropTypes.bool,
mode: React.PropTypes.string,
value: React.PropTypes.string,
valueLink: React.PropTypes.string,
onChange: React.PropTypes.func
},
getDefaultProps: function () {
return {
readOnly: false,
mode: 'html'
};
},
getInitialState: function () {
return {
editorId: _.uniqueId()
};
},
//componentWillMount: function () {
//},
render: function () {
var props = _.omit(this.props, ['ref', 'key', 'value', 'valueLink', 'onChange']);
props.id = this.props.id || this.state.editorId;
props.defaultValue = this.props.valueLink ? this.props.valueLink() : this.props.value;
return React.DOM.textarea(props);
},
componentWillUpdate: function (nextProps/*, nextState*/) {
var value = nextProps.valueLink ? nextProps.valueLink() : nextProps.value;
if (this.editor && this.editor.getValue() !== value) {
this.editor.setValue(value || '');
}
},
componentDidMount: function () {
var value = this.props.valueLink ? this.props.valueLink() : this.props.value;
var options = {
readOnly: this.props.readOnly,
lineWrapping: true,
smartIndent: true,
matchBrackets: true,
value: value,
lineNumbers: true,
mode: 'javascript',
gutters: ['CodeMirror-linenumbers', 'rt-annotations'],
theme: 'solarized' //solarized_light solarized-light
};
if (this.props.mode === 'html') {
options.mode = 'text/html';
options.extraKeys = {
"'<'": completeAfter,
"'/'": completeIfAfterLt,
"' '": completeIfInTag,
"'='": completeIfInTag,
'Ctrl-Space': 'autocomplete'
};
options.hintOptions = {schemaInfo: tags};
//options.gutters = ['CodeMirror-lint-markers'];
//options.lint = true;
} else {
options.mode = 'javascript';
//options.gutters = ['CodeMirror-lint-markers'];
//options.lint = true;
}
this.editor = CodeMirror.fromTextArea(ReactDOM.findDOMNode(this), options);
if (!this.props.readOnly) {
this.editor.on('change', function (/*e*/) {
if (this.props.valueLink) {
this.props.valueLink(this.editor.getValue());
} else if (this.props.onChange) {
this.props.onChange({target: {value: this.editor.getValue()}});
}
}.bind(this));
}
},
//showMessage: function (msg) {
// //var anOption = document.createElement('div');
// //anOption.innerText = msg;
// //anOption.setAttribute('class', 'error-panel');
// //if (this.panel) {
// // this.panel.clear();
// //}
// //this.panel = this.editor.addPanel(anOption, {height: 22}); // {position: 'bottom'}
//},
//clearMessage: function () {
// if (this.panel) {
// this.panel.clear();
// this.panel = null;
// }
//},
annotate: function (annot) {
CMLint.annotate(this.editor, annot);
},
clearAnnotations: function () {
CMLint.clearMarks(this.editor);
},
componentWillUnmount: function () {
this.editor.toTextArea();
}
});
});

View File

@ -0,0 +1,46 @@
define(['react', 'react-dom', 'lodash', 'jquery', './libs/codemirror-4.8/lib/codemirror',
'./libs/codemirror-4.8/mode/javascript/javascript',
'./libs/codemirror-4.8/mode/xml/xml',
'./libs/codemirror-4.8/addon/runmode/runmode'
], function (React, ReactDOM, _, $, CodeMirror) {
'use strict';
return React.createClass({
displayName: 'CodeMirrorViewer',
propTypes: {
id: React.PropTypes.string,
mode: React.PropTypes.string,
value: React.PropTypes.string,
valueLink: React.PropTypes.string
},
getDefaultProps: function () {
return {mode: 'html'};
},
getInitialState: function () {
return {editorId: _.uniqueId()};
},
render: function () {
var props = _.omit(this.props, ['ref', 'key', 'value', 'valueLink', 'onChange']);
props.id = this.props.id || this.state.editorId;
props.className = 'cm-s-default';
var value = this.props.valueLink ? this.props.valueLink() : this.props.value;
return React.DOM.pre(props, value);
},
componentWillUpdate: function (nextProps/*, nextState*/) {
var value = nextProps.valueLink ? nextProps.valueLink() : nextProps.value;
if (this.editor && this.editor.getValue() !== value) {
this.editor.setValue(value || '');
}
},
componentDidMount: function () {
var value = this.props.valueLink ? this.props.valueLink() : this.props.value;
var mode = this.props.mode;
if (this.props.mode === 'html') {
mode = 'text/html';
}
this.editor = CodeMirror.runMode(value, mode, ReactDOM.findDOMNode(this));
},
componentWillUnmount: function () {
this.editor.toTextArea();
}
});
});

65
playground/aceEditor.js Normal file
View File

@ -0,0 +1,65 @@
/**
* Created by avim on 11/25/2014.
*/
/*global ace:true*/
define(['react', 'lodash']/*, 'ace'*/, function (React, _/*, ace*/) {
'use strict';
return React.createClass({
displayName: 'BraceEditor',
propTypes: {
id: React.PropTypes.string,
mode: React.PropTypes.string,
readOnly: React.PropTypes.bool,
value: React.PropTypes.string,
valueLink: React.PropTypes.string,
onChange: React.PropTypes.function
},
getInitialState: function () {
return {
editorId: _.uniqueId()
};
},
componentWillMount: _.noop,
render: function () {
var props = _.omit(this.props, ['ref', 'key', 'value', 'valueLink', 'onChange']);
props.id = this.props.id || this.state.editorId;
return React.DOM.div(props);
},
componentWillUpdate: function (nextProps/*, nextState*/) {
var value = nextProps.valueLink ? nextProps.valueLink() : nextProps.value;
if (this.editor && this.editor.getValue() !== value) {
this.editor.setValue(value, 0);
}
},
componentDidMount: function () {
this.editor = ace.edit(this.props.id || this.state.editorId);
// this.editor.setTheme('ace/theme/monokai');
this.editor.setTheme('ace/theme/solarized_light');
if (this.props.mode === 'html') {
this.editor.getSession().setMode('ace/mode/html');
} else {
this.editor.getSession().setMode('ace/mode/javascript');
}
this.editor.getSession().setUseWorker(false);
var value = this.props.valueLink ? this.props.valueLink() : this.props.value;
this.editor.setValue(value, 0);
if (this.props.readOnly) {
this.editor.setReadOnly(true);
} else {
this.editor.setReadOnly(false);
this.editor.on('change', function (/*e*/) {
if (this.props.valueLink) {
this.props.valueLink(this.editor.getValue());
} else if (this.props.onChange) {
this.props.onChange({target: {value: this.editor.getValue()}});
}
}.bind(this));
}
this.editor.clearSelection();
},
componentWillUnmount: function () {
this.editor.destroy();
}
});
});

231
playground/css/fiddle.css Normal file
View File

@ -0,0 +1,231 @@
html {
height: 100%;
}
body {
font-family: 'Lato', sans-serif;
font-weight: 300;
overflow: hidden;
padding: 0;
margin: 0;
/*position: relative;*/
font-size: 14px;
/*height: 100%;*/
display: block;
}
#container {
height: 100%;
}
.playground-container {
position: absolute;
top: 48px;
bottom: 0;
left: 0;
right: 0;
/*background: #DFDFD5;*/
}
#header {
height: 48px;
/*background: #4679bd;*/
background: #222;
}
#header-title {
color: #00d8ff;
font-size: 24px;
line-height: 48px;
/*height: 50px;*/
padding-left: 10px;
vertical-align: middle;
display: inline-block;
}
.title-link {
float: left;
margin-top: -3px;
margin-right: 5px;
}
.title-link, .title-link:hover, .title-link:visited {
text-decoration: none;
color: #00d8ff;
}
#buttons-bar {
padding-left: 40px;
display: inline-block;
}
#buttons-bar button {
font-weight: 400;
}
#buttons-bar button, #buttons-bar div {
margin-right: 10px;
}
.toolbar-dropdown {
display: inline-block;
}
.button-icon {
margin-right: 5px;
}
.nav-site {
position: absolute;
top: 0;
right: 0;
}
.nav-site li {
margin: 0;
display: inline-block;
}
.nav-site a {
padding: 0 8px;
text-transform: uppercase;
letter-spacing: 1px;
line-height: 50px;
display: inline-block;
height: 50px;
color: #aaa
}
.nav-site a:hover {
color: #fafafa
}
.nav-site a.active {
color: #fafafa;
border-bottom: 3px solid #cc7a6f;
background: #333
}
.fiddle {
height: 100%;
}
.CodeMirror {
height: 100%;
/*border: 1px solid black;*/
}
.large-text-area {
width: 100%;
height: 100%;
/*height: 300px;*/
/*display: block;*/
/*margin: 10px;*/
border: 1px solid #ddd;
border-radius: 4px 4px 4px 4px;
/*height: 400px;*/
/*min-height: 100px;*/
/*height: 100%;*/
/*margin: 10px;*/
}
.sample-view {
height: 100%;
border: 1px solid #ddd;
background-color: #f8f8f5;
}
.sample-view button {
margin: 5px;
}
.sample-view input[type=checkbox] {
margin-right: 5px;
}
.playground {
height: 100%;
width: 100%;
}
.CodeMirror-wrap {
border: 1px solid #ddd;
/*border-radius: 4px 4px 4px 4px;*/
/*height: 400px;*/
/*min-height: 100px;*/
/*height: 100%;*/
/*margin: 10px;*/
}
.fiddle-row {
overflow: hidden;
}
.code-area {
width: 50%;
float: left;
position: relative;
padding: 5px;
}
.result-area-form {
padding: 5px;
margin: 10px 20px;
}
.error-panel {
/*padding: 4px; */
padding-left: 20px;
/* position: static; */
color: red;
background: #f7f7f7;
border-bottom: 1px solid #000;
}
.message {
position: absolute;
bottom: 500px;
left: 200px;
z-index: 30;
background-color: aliceblue;
opacity: 0.9;
}
/*position: relative; min-height: 100%;*/
.code-area::after {
content: '';
position: absolute;
top: 5px;
right: 5px;
font-size: 11px;
padding: 2px 5px;
border: 1px solid #ddd;
color: #b4b4b4;
background: rgba(255, 255, 255, 0.5);
pointer-events: none;
transition: opacity 0.2s;
-webkit-transition: opacity 0.2s;
}
/*.code-area:hover::after{
opacity:0.2;
}*/
#area-rt::after {
content: 'Template';
}
#area-code::after {
content: 'Class';
}
#area-generated::after {
content: 'Generated Code';
}
#area-result::after {
content: 'Result';
}

1218
playground/css/home.css Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
/* uncss:ignore */
.playground-error {
color: red;
font-weight: 500;
}
/* uncss:ignore */
.cm-s-solarized .editor-error {
background-color: #F0F079;
}

15
playground/dist/fiddle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

10
playground/dist/home.min.js vendored Normal file

File diff suppressed because one or more lines are too long

60517
playground/dist/rt-main.browser.js vendored Normal file

File diff suppressed because one or more lines are too long

20
playground/dist/rt-main.browser.min.js vendored Normal file

File diff suppressed because one or more lines are too long

38
playground/examples.js Normal file
View File

@ -0,0 +1,38 @@
define(['lodash', 'react', './examples.rt',
'text!./samples/hello.code', 'text!./samples/hello.rt',
'text!./samples/todo.code', 'text!./samples/todo.rt',
'text!./samples/rt-if.code', 'text!./samples/rt-if.rt',
'text!./samples/rt-props.code', 'text!./samples/rt-props.rt',
'text!./samples/rt-repeat.code', 'text!./samples/rt-repeat.rt',
'text!./samples/weather.code', 'text!./samples/weather.rt',
'text!./samples/rt-import.rt'
], function (_, React, examplesTemplate, helloCode, helloRT, todoCode, todoRT, rtIfCode, rtIfRT, rtPropsCode, rtPropsRT, rtRepeatCode, rtRepeatRT, weatherCode, weatherRT, rtImportRT) {
'use strict';
var samples = {
hello: [helloCode, helloRT],
todo: [todoCode, todoRT],
props: [rtPropsCode, rtPropsRT],
rtIf: [rtIfCode, rtIfRT],
repeat: [rtRepeatCode, rtRepeatRT],
weather: [weatherCode, weatherRT]
};
samples = _.mapValues(samples, function (v, k) { return {name: k, templateProps: _.template(v[0])({name: k}), templateHTML: v[1]}; });
return React.createClass({
displayName: 'Examples',
mixins: [React.addons.LinkedStateMixin],
getInitialState: function () {
var codeAmd = window.reactTemplates.convertTemplateToReact(rtImportRT, {modules: 'amd', name: 'template'});
var codeCJS = window.reactTemplates.convertTemplateToReact(rtImportRT, {modules: 'commonjs', name: 'template'});
var codeES6 = window.reactTemplates.convertTemplateToReact(rtImportRT, {modules: 'es6', name: 'template'});
return {
rtImport: {value: rtImportRT},
amd: {value: codeAmd},
cjs: {value: codeCJS},
es6: {value: codeES6},
samples: samples
};
},
render: examplesTemplate
});
});

75
playground/examples.rt Normal file
View File

@ -0,0 +1,75 @@
<!--suppress CheckEmptyScriptTag -->
<rt-require dependency="./playground" as="playground"/>
<rt-require dependency="./CodeMirrorViewer" as="viewer"/>
<div id="examples">
<div class="example">
<h3>Hello world in React Templates</h3>
<p>
Simple "Hello world" HTML transformed into React JavaScript code.
</p>
<playground id="helloExample" rt-props="this.state.samples.hello" direction="horizontal"></playground>
</div>
<div class="example">
<h3>rt-if</h3>
<p>
This shows the use of rt-if.
</p>
<playground id="ifExample" rt-props="this.state.samples.rtIf" direction="horizontal"></playground>
</div>
<div class="example">
<h3>rt-repeat</h3>
<p>
This uses rt-repeat to show multiple items and rt-scope to create a reusable name for multiple calculations.
</p>
<playground id="repeatExample" rt-props="this.state.samples.repeat" direction="horizontal"></playground>
</div>
<div class="example">
<h3>rt-props</h3>
<p>
rt-props is used to pass all the original properties set on this component (except the ones used for the component logic: onClick and eventId) to the element that will actually represent this component.
</p>
<playground id="propsExample" rt-props="this.state.samples.props" direction="horizontal"></playground>
</div>
<div class="example">
<h3>Improved todo list</h3>
<p>
Every project needs a todo list example, so here is ours.
</p>
<playground id="todoExample" rt-props="this.state.samples.todo" direction="horizontal"></playground>
</div>
<div class="example">
<h3>Weather</h3>
<p>
This example shows working with async events, the usage of regular event handler function pointers instead of lambda expression, and working with two-way binding.
</p>
<playground id="weatherExample" rt-props="this.state.samples.weather" direction="horizontal"></playground>
</div>
<div id="rt-import" class="example">
<h3>rt-import</h3>
<p>
This example shows how to load other React components and libraries into a React template and then use them within the template.
</p>
<viewer rt-props="this.state.rtImport" mode="javascript" />
</div>
<div id="amd" class="example">
<h3>AMD</h3>
<p>
This example shows the rt-require sample output with AMD support.
</p>
<viewer rt-props="this.state.amd" mode="javascript" />
</div>
<div id="commonjs" class="example">
<h3>CommonJS</h3>
<p>
This example shows the rt-require sample output with CommonJS support.
</p>
<viewer rt-props="this.state.cjs" mode="javascript" />
</div>
<div id="es6" class="example">
<h3>ES6</h3>
<p>
This example shows the rt-require sample output with ES6 support.
</p>
<viewer rt-props="this.state.es6" mode="javascript" />
</div>
</div>

41
playground/examples.rt.js Normal file
View File

@ -0,0 +1,41 @@
define([
'react/addons',
'lodash',
'./playground',
'./CodeMirrorViewer'
], function (React, _, playground, viewer) {
'use strict';
return function () {
return React.createElement('div', { 'id': 'examples' }, React.createElement('div', { 'className': 'example' }, React.createElement('h3', {}, 'Hello world in React Templates'), React.createElement('p', {}, '\n Simple "Hello world" HTML transformed into React JavaScript code.\n '), React.createElement(playground, _.assign({}, {
'id': 'helloExample',
'direction': 'horizontal'
}, this.state.samples.hello))), React.createElement('div', { 'className': 'example' }, React.createElement('h3', {}, 'rt-if'), React.createElement('p', {}, '\n This shows the use of rt-if.\n '), React.createElement(playground, _.assign({}, {
'id': 'ifExample',
'direction': 'horizontal'
}, this.state.samples.rtIf))), React.createElement('div', { 'className': 'example' }, React.createElement('h3', {}, 'rt-repeat'), React.createElement('p', {}, '\n This uses rt-repeat to show multiple items and rt-scope to create a reusable name for multiple calculations.\n '), React.createElement(playground, _.assign({}, {
'id': 'repeatExample',
'direction': 'horizontal'
}, this.state.samples.repeat))), React.createElement('div', { 'className': 'example' }, React.createElement('h3', {}, 'rt-props'), React.createElement('p', {}, '\n rt-props is used to pass all the original properties set on this component (except the ones used for the component logic: onClick and eventId) to the element that will actually represent this component.\n '), React.createElement(playground, _.assign({}, {
'id': 'propsExample',
'direction': 'horizontal'
}, this.state.samples.props))), React.createElement('div', { 'className': 'example' }, React.createElement('h3', {}, 'Improved todo list'), React.createElement('p', {}, '\n Every project needs a todo list example, so here is ours.\n '), React.createElement(playground, _.assign({}, {
'id': 'todoExample',
'direction': 'horizontal'
}, this.state.samples.todo))), React.createElement('div', { 'className': 'example' }, React.createElement('h3', {}, 'Weather'), React.createElement('p', {}, '\n This example shows working with async events, the usage of regular event handler function pointers instead of lambda expression, and working with two-way binding.\n '), React.createElement(playground, _.assign({}, {
'id': 'weatherExample',
'direction': 'horizontal'
}, this.state.samples.weather))), React.createElement('div', {
'id': 'rt-import',
'className': 'example'
}, React.createElement('h3', {}, 'rt-import'), React.createElement('p', {}, '\n This example shows how to load other React components and libraries into a React template and then use them within the template.\n '), React.createElement(viewer, _.assign({}, { 'mode': 'javascript' }, this.state.rtImport))), React.createElement('div', {
'id': 'amd',
'className': 'example'
}, React.createElement('h3', {}, 'AMD'), React.createElement('p', {}, '\n This example shows the rt-require sample output with AMD support.\n '), React.createElement(viewer, _.assign({}, { 'mode': 'javascript' }, this.state.amd))), React.createElement('div', {
'id': 'commonjs',
'className': 'example'
}, React.createElement('h3', {}, 'CommonJS'), React.createElement('p', {}, '\n This example shows the rt-require sample output with CommonJS support.\n '), React.createElement(viewer, _.assign({}, { 'mode': 'javascript' }, this.state.cjs))), React.createElement('div', {
'id': 'es6',
'className': 'example'
}, React.createElement('h3', {}, 'ES6'), React.createElement('p', {}, '\n This example shows the rt-require sample output with ES6 support.\n '), React.createElement(viewer, _.assign({}, { 'mode': 'javascript' }, this.state.es6))));
};
});

29
playground/fiddle-main.js Normal file
View File

@ -0,0 +1,29 @@
requirejs.config({
paths: {
lodash: '//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min',
jquery: '//code.jquery.com/jquery-2.1.4.min',
firebase: '//cdn.firebase.com/js/client/2.0.5/firebase',
react: '//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-with-addons',
'react-dom': '//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom',
fiddle: './fiddle',
text: 'libs/requirejs-plugins/text',
json: 'libs/requirejs-plugins/json',
bootstrap: 'libs/bootstrap/bootstrap.min'
},
shim: {
lodash: {exports: '_'},
firebase: {exports: 'Firebase'},
jquery: {exports: '$'},
react: {exports: 'React'},
'react-dom': {exports: 'ReactDOM'}
},
map: {
'*': {'react/addons': 'react'}
}
});
requirejs(['fiddle', 'react', 'react-dom', 'jquery', 'bootstrap'], function (fiddle, React, ReactDOM) {
'use strict';
var elem = React.createElement(fiddle);
window.fiddle = ReactDOM.render(elem, document.getElementById('container'));
});

76
playground/fiddle.js Normal file
View File

@ -0,0 +1,76 @@
/**
* Created by avim on 12/2/2014.
*/
define(['react', 'firebase', 'lodash', './fiddle.rt', 'jquery'], function (React, Firebase, _, fiddleTemplate, $) {
'use strict';
function generateRandomId() {
var uuid = 'xxxxxxxx'.replace(/[xy]/g, function (c) {
var r = _.random(0, 15);
return (c === 'x' ? r : r & 0x3 | 0x8).toString(16);
});
return uuid;
}
var Fiddle = React.createClass({
displayName: 'Fiddle',
componentDidMount: function () {
if (window.location.hash) {
var newHash = window.location.hash.replace('#', '');
var firebase = new Firebase('https://reacttemplates.firebaseio-demo.com/');
firebase.child('fiddles').child(newHash).on('value', function (snapshot) {
this.refs.playground.setState(snapshot.val());
Firebase.goOffline();
}.bind(this));
} else {
Firebase.goOffline();
}
},
save: function () {
var newHash = generateRandomId();
window.location.hash = newHash;
Firebase.goOnline();
var playgroundState = this.refs.playground.state;
var firebase = new Firebase('https://reacttemplates.firebaseio-demo.com/');
firebase.child('fiddles').child(newHash).set(playgroundState, function () {
Firebase.goOffline();
alert('Saved the fiddle, you can share your url'); //eslint-disable-line no-alert
});
},
clear: function () {
this.refs.playground.clear();
},
loadSample: function (name) {
//require(['text!./samples/' + name + '.rt', 'text!./samples/' + name + '.code'], function (rt, code) {
// var currentState = {
// templateHTML: rt,
// templateProps: code
// };
// //this.updateSample(currentState);
// this.refs.playground.setState(currentState);
//});
var playground = this.refs.playground;
$.get('playground/samples/' + name + '.rt', null, function (data/*, textStatus, jqXHR*/) {
var rt = data;
$.get('playground/samples/' + name + '.code', null, function (data2/*, textStatus2, jqXHR2*/) {
var currentState = {
templateHTML: rt,
templateProps: _.template(data2)({name: 'template'})
};
//this.updateSample(currentState);
playground.setState(currentState);
});
});
//this.refs.playground.clear();
},
render: fiddleTemplate
});
return Fiddle;
});

43
playground/fiddle.rt Normal file
View File

@ -0,0 +1,43 @@
<!--suppress CheckEmptyScriptTag -->
<rt-require dependency="./playground" as="playground"/>
<div class="fiddle">
<div id="header">
<div id="header-title">
<a href="index.html" class="title-link">
<img class="nav-logo" src="https://wix.github.io/react-templates/img/logo-rt.svg" width="56" height="24" />
</a>
RT Playground
</div>
<div id="buttons-bar">
<button type="button" class="btn btn-default" onClick="(evt)=>evt.preventDefault();this.save()">
<span class="glyphicon glyphicon-star button-icon" aria-hidden="true"></span>Save fiddle
</button>
<button type="button" class="btn btn-default" onClick="(evt)=>evt.preventDefault();this.clear()">
<span class="glyphicon glyphicon-trash button-icon" aria-hidden="true"></span>Clear
</button>
<div class="dropdown toolbar-dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-expanded="true">
Load Sample
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
<li role="presentation"><a role="menuitem" tabindex="-1" href="#" onClick="(evt)=>evt.preventDefault();this.loadSample('rt-if')">rt-if</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="#" onClick="(evt)=>evt.preventDefault();this.loadSample('rt-repeat')">rt-repeat</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="#" onClick="(evt)=>evt.preventDefault();this.loadSample('rt-props')">rt-props</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="#" onClick="(evt)=>evt.preventDefault();this.loadSample('todo')">Todo</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="#" onClick="(evt)=>evt.preventDefault();this.loadSample('weather')">Weather</a></li>
</ul>
</div>
</div>
<ul class="nav-site">
<li><a href="index.html">HOME</a></li>
<li><a href="https://github.com/wix/react-templates#template-directives-and-syntax">docs</a></li>
<li><a href="https://github.com/wix/react-templates#installation">download</a></li>
<li><a href="https://github.com/wix/react-templates">github</a>
</ul>
</div>
<div class="playground-container">
<playground ref="playground" direction="vertical" fiddle="{true}" />
</div>
</div>

99
playground/fiddle.rt.js Normal file
View File

@ -0,0 +1,99 @@
define([
'react/addons',
'lodash',
'./playground'
], function (React, _, playground) {
'use strict';
function onClick1(evt) {
evt.preventDefault();
this.save();
}
function onClick2(evt) {
evt.preventDefault();
this.clear();
}
function onClick3(evt) {
evt.preventDefault();
this.loadSample('rt-if');
}
function onClick4(evt) {
evt.preventDefault();
this.loadSample('rt-repeat');
}
function onClick5(evt) {
evt.preventDefault();
this.loadSample('rt-props');
}
function onClick6(evt) {
evt.preventDefault();
this.loadSample('todo');
}
function onClick7(evt) {
evt.preventDefault();
this.loadSample('weather');
}
return function () {
return React.createElement('div', { 'className': 'fiddle' }, React.createElement('div', { 'id': 'header' }, React.createElement('div', { 'id': 'header-title' }, React.createElement('a', {
'href': 'index.html',
'className': 'title-link'
}, React.createElement('img', {
'className': 'nav-logo',
'src': 'https://wix.github.io/react-templates/img/logo-rt.svg',
'width': '56',
'height': '24'
})), '\n RT Playground\n '), React.createElement('div', { 'id': 'buttons-bar' }, React.createElement('button', {
'type': 'button',
'className': 'btn btn-default',
'onClick': onClick1.bind(this)
}, React.createElement('span', {
'className': 'glyphicon glyphicon-star button-icon',
'aria-hidden': 'true'
}), 'Save fiddle\n '), React.createElement('button', {
'type': 'button',
'className': 'btn btn-default',
'onClick': onClick2.bind(this)
}, React.createElement('span', {
'className': 'glyphicon glyphicon-trash button-icon',
'aria-hidden': 'true'
}), 'Clear\n '), React.createElement('div', { 'className': 'dropdown toolbar-dropdown' }, React.createElement('button', {
'className': 'btn btn-default dropdown-toggle',
'type': 'button',
'id': 'dropdownMenu1',
'data-toggle': 'dropdown',
'aria-expanded': 'true'
}, '\n Load Sample\n ', React.createElement('span', { 'className': 'caret' })), React.createElement('ul', {
'className': 'dropdown-menu',
'role': 'menu',
'aria-labelledby': 'dropdownMenu1'
}, React.createElement('li', { 'role': 'presentation' }, React.createElement('a', {
'role': 'menuitem',
'tabIndex': '-1',
'href': '#',
'onClick': onClick3.bind(this)
}, 'rt-if')), React.createElement('li', { 'role': 'presentation' }, React.createElement('a', {
'role': 'menuitem',
'tabIndex': '-1',
'href': '#',
'onClick': onClick4.bind(this)
}, 'rt-repeat')), React.createElement('li', { 'role': 'presentation' }, React.createElement('a', {
'role': 'menuitem',
'tabIndex': '-1',
'href': '#',
'onClick': onClick5.bind(this)
}, 'rt-props')), React.createElement('li', { 'role': 'presentation' }, React.createElement('a', {
'role': 'menuitem',
'tabIndex': '-1',
'href': '#',
'onClick': onClick6.bind(this)
}, 'Todo')), React.createElement('li', { 'role': 'presentation' }, React.createElement('a', {
'role': 'menuitem',
'tabIndex': '-1',
'href': '#',
'onClick': onClick7.bind(this)
}, 'Weather'))))), React.createElement('ul', { 'className': 'nav-site' }, React.createElement('li', {}, React.createElement('a', { 'href': 'index.html' }, 'HOME')), React.createElement('li', {}, React.createElement('a', { 'href': 'https://github.com/wix/react-templates#template-directives-and-syntax' }, 'docs')), React.createElement('li', {}, React.createElement('a', { 'href': 'https://github.com/wix/react-templates#installation' }, 'download')), React.createElement('li', {}, React.createElement('a', { 'href': 'https://github.com/wix/react-templates' }, 'github')))), React.createElement('div', { 'className': 'playground-container' }, React.createElement(playground, {
'ref': 'playground',
'direction': 'vertical',
'fiddle': true
})));
};
});

30
playground/home-main.js Normal file
View File

@ -0,0 +1,30 @@
requirejs.config({
//baseUrl: '.',
baseUrl: './playground',
paths: {
lodash: '//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min',
jquery: '//code.jquery.com/jquery-2.1.4.min',
firebase: 'https://cdn.firebase.com/js/client/2.0.5/firebase',
react: '//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-with-addons',
'react-dom': '//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom',
text: 'libs/requirejs-plugins/text',
json: 'libs/requirejs-plugins/json'
//examples: './examples'
},
shim: {
lodash: {exports: '_'},
firebase: {exports: 'Firebase'},
jquery: {exports: '$'},
react: {exports: 'React'},
'react-dom': {exports: 'ReactDOM'}
},
map: {
'*': {'react/addons': 'react'}
}
});
requirejs(['./examples', 'react', 'react-dom', 'jquery'], function (Examples, React, ReactDOM) {
'use strict';
var elem = React.createElement(Examples);
ReactDOM.render(elem, document.getElementById('home-section'));
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
ace.define("ace/theme/solarized_light",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-solarized-light",t.cssText=".ace-solarized-light .ace_gutter {background: #fbf1d3;color: #333}.ace-solarized-light .ace_print-margin {width: 1px;background: #e8e8e8}.ace-solarized-light {background-color: #FDF6E3;color: #586E75}.ace-solarized-light .ace_cursor {color: #000000}.ace-solarized-light .ace_marker-layer .ace_selection {background: rgba(7, 54, 67, 0.09)}.ace-solarized-light.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #FDF6E3;border-radius: 2px}.ace-solarized-light .ace_marker-layer .ace_step {background: rgb(255, 255, 0)}.ace-solarized-light .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(147, 161, 161, 0.50)}.ace-solarized-light .ace_marker-layer .ace_active-line {background: #EEE8D5}.ace-solarized-light .ace_gutter-active-line {background-color : #EDE5C1}.ace-solarized-light .ace_marker-layer .ace_selected-word {border: 1px solid #073642}.ace-solarized-light .ace_invisible {color: rgba(147, 161, 161, 0.50)}.ace-solarized-light .ace_keyword,.ace-solarized-light .ace_meta,.ace-solarized-light .ace_support.ace_class,.ace-solarized-light .ace_support.ace_type {color: #859900}.ace-solarized-light .ace_constant.ace_character,.ace-solarized-light .ace_constant.ace_other {color: #CB4B16}.ace-solarized-light .ace_constant.ace_language {color: #B58900}.ace-solarized-light .ace_constant.ace_numeric {color: #D33682}.ace-solarized-light .ace_fold {background-color: #268BD2;border-color: #586E75}.ace-solarized-light .ace_entity.ace_name.ace_function,.ace-solarized-light .ace_entity.ace_name.ace_tag,.ace-solarized-light .ace_support.ace_function,.ace-solarized-light .ace_variable,.ace-solarized-light .ace_variable.ace_language {color: #268BD2}.ace-solarized-light .ace_storage {color: #073642}.ace-solarized-light .ace_string {color: #2AA198}.ace-solarized-light .ace_string.ace_regexp {color: #D30102}.ace-solarized-light .ace_comment,.ace-solarized-light .ace_entity.ace_other.ace_attribute-name {color: #93A1A1}.ace-solarized-light .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHjy8NJ/AAjgA5fzQUmBAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)})

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

181
playground/libs/bootstrap/bootstrap.js vendored Executable file
View File

@ -0,0 +1,181 @@
/*!
* Bootstrap v3.3.1 (http://getbootstrap.com)
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
/*!
* Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=b3a553f0244f7a115bca)
* Config saved to config.json and https://gist.github.com/b3a553f0244f7a115bca
*/
if (typeof jQuery === 'undefined') {
throw new Error('Bootstrap\'s JavaScript requires jQuery')
}
+function ($) {
var version = $.fn.jquery.split(' ')[0].split('.')
if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
}
}(jQuery);
/* ========================================================================
* Bootstrap: dropdown.js v3.3.1
* http://getbootstrap.com/javascript/#dropdowns
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// DROPDOWN CLASS DEFINITION
// =========================
var backdrop = '.dropdown-backdrop'
var toggle = '[data-toggle="dropdown"]'
var Dropdown = function (element) {
$(element).on('click.bs.dropdown', this.toggle)
}
Dropdown.VERSION = '3.3.1'
Dropdown.prototype.toggle = function (e) {
var $this = $(this)
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
clearMenus()
if (!isActive) {
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
// if mobile we use a backdrop because click events don't delegate
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
}
var relatedTarget = { relatedTarget: this }
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this
.trigger('focus')
.attr('aria-expanded', 'true')
$parent
.toggleClass('open')
.trigger('shown.bs.dropdown', relatedTarget)
}
return false
}
Dropdown.prototype.keydown = function (e) {
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
var $this = $(this)
e.preventDefault()
e.stopPropagation()
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
var desc = ' li:not(.divider):visible a'
var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
if (!$items.length) return
var index = $items.index(e.target)
if (e.which == 38 && index > 0) index-- // up
if (e.which == 40 && index < $items.length - 1) index++ // down
if (!~index) index = 0
$items.eq(index).trigger('focus')
}
function clearMenus(e) {
if (e && e.which === 3) return
$(backdrop).remove()
$(toggle).each(function () {
var $this = $(this)
var $parent = getParent($this)
var relatedTarget = { relatedTarget: this }
if (!$parent.hasClass('open')) return
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this.attr('aria-expanded', 'false')
$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
})
}
function getParent($this) {
var selector = $this.attr('data-target')
if (!selector) {
selector = $this.attr('href')
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
}
var $parent = selector && $(selector)
return $parent && $parent.length ? $parent : $this.parent()
}
// DROPDOWN PLUGIN DEFINITION
// ==========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.dropdown')
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
if (typeof option == 'string') data[option].call($this)
})
}
var old = $.fn.dropdown
$.fn.dropdown = Plugin
$.fn.dropdown.Constructor = Dropdown
// DROPDOWN NO CONFLICT
// ====================
$.fn.dropdown.noConflict = function () {
$.fn.dropdown = old
return this
}
// APPLY TO STANDARD DROPDOWN ELEMENTS
// ===================================
$(document)
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
.on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
.on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
}(jQuery);

11
playground/libs/bootstrap/bootstrap.min.js vendored Executable file
View File

@ -0,0 +1,11 @@
/*!
* Bootstrap v3.3.1 (http://getbootstrap.com)
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
/*!
* Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=b3a553f0244f7a115bca)
* Config saved to config.json and https://gist.github.com/b3a553f0244f7a115bca
*/
if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(t){var o=t.fn.jquery.split(" ")[0].split(".");if(o[0]<2&&o[1]<9||1==o[0]&&9==o[1]&&o[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(t){"use strict";function o(o){o&&3===o.which||(t(n).remove(),t(a).each(function(){var e=t(this),n=r(e),a={relatedTarget:this};n.hasClass("open")&&(n.trigger(o=t.Event("hide.bs.dropdown",a)),o.isDefaultPrevented()||(e.attr("aria-expanded","false"),n.removeClass("open").trigger("hidden.bs.dropdown",a)))}))}function r(o){var r=o.attr("data-target");r||(r=o.attr("href"),r=r&&/#[A-Za-z]/.test(r)&&r.replace(/.*(?=#[^\s]*$)/,""));var e=r&&t(r);return e&&e.length?e:o.parent()}function e(o){return this.each(function(){var r=t(this),e=r.data("bs.dropdown");e||r.data("bs.dropdown",e=new i(this)),"string"==typeof o&&e[o].call(r)})}var n=".dropdown-backdrop",a='[data-toggle="dropdown"]',i=function(o){t(o).on("click.bs.dropdown",this.toggle)};i.VERSION="3.3.1",i.prototype.toggle=function(e){var n=t(this);if(!n.is(".disabled, :disabled")){var a=r(n),i=a.hasClass("open");if(o(),!i){"ontouchstart"in document.documentElement&&!a.closest(".navbar-nav").length&&t('<div class="dropdown-backdrop"/>').insertAfter(t(this)).on("click",o);var d={relatedTarget:this};if(a.trigger(e=t.Event("show.bs.dropdown",d)),e.isDefaultPrevented())return;n.trigger("focus").attr("aria-expanded","true"),a.toggleClass("open").trigger("shown.bs.dropdown",d)}return!1}},i.prototype.keydown=function(o){if(/(38|40|27|32)/.test(o.which)&&!/input|textarea/i.test(o.target.tagName)){var e=t(this);if(o.preventDefault(),o.stopPropagation(),!e.is(".disabled, :disabled")){var n=r(e),i=n.hasClass("open");if(!i&&27!=o.which||i&&27==o.which)return 27==o.which&&n.find(a).trigger("focus"),e.trigger("click");var d=" li:not(.divider):visible a",s=n.find('[role="menu"]'+d+', [role="listbox"]'+d);if(s.length){var p=s.index(o.target);38==o.which&&p>0&&p--,40==o.which&&p<s.length-1&&p++,~p||(p=0),s.eq(p).trigger("focus")}}}};var d=t.fn.dropdown;t.fn.dropdown=e,t.fn.dropdown.Constructor=i,t.fn.dropdown.noConflict=function(){return t.fn.dropdown=d,this},t(document).on("click.bs.dropdown.data-api",o).on("click.bs.dropdown.data-api",".dropdown form",function(t){t.stopPropagation()}).on("click.bs.dropdown.data-api",a,i.prototype.toggle).on("keydown.bs.dropdown.data-api",a,i.prototype.keydown).on("keydown.bs.dropdown.data-api",'[role="menu"]',i.prototype.keydown).on("keydown.bs.dropdown.data-api",'[role="listbox"]',i.prototype.keydown)}(jQuery);

View File

@ -0,0 +1,94 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
CodeMirror.defineExtension("addPanel", function(node, options) {
if (!this.state.panels) initPanels(this);
var info = this.state.panels;
if (options && options.position == "bottom")
info.wrapper.appendChild(node);
else
info.wrapper.insertBefore(node, info.wrapper.firstChild);
var height = (options && options.height) || node.offsetHeight;
this._setSize(null, info.heightLeft -= height);
info.panels++;
return new Panel(this, node, options, height);
});
function Panel(cm, node, options, height) {
this.cm = cm;
this.node = node;
this.options = options;
this.height = height;
this.cleared = false;
}
Panel.prototype.clear = function() {
if (this.cleared) return;
this.cleared = true;
var info = this.cm.state.panels;
this.cm._setSize(null, info.heightLeft += this.height);
info.wrapper.removeChild(this.node);
if (--info.panels == 0) removePanels(this.cm);
};
Panel.prototype.changed = function(height) {
var newHeight = height == null ? this.node.offsetHeight : height;
var info = this.cm.state.panels;
this.cm._setSize(null, info.height += (newHeight - this.height));
this.height = newHeight;
};
function initPanels(cm) {
var wrap = cm.getWrapperElement();
var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle;
var height = parseInt(style.height);
var info = cm.state.panels = {
setHeight: wrap.style.height,
heightLeft: height,
panels: 0,
wrapper: document.createElement("div")
};
wrap.parentNode.insertBefore(info.wrapper, wrap);
var hasFocus = cm.hasFocus();
info.wrapper.appendChild(wrap);
if (hasFocus) cm.focus();
cm._setSize = cm.setSize;
if (height != null) cm.setSize = function(width, newHeight) {
if (newHeight == null) return this._setSize(width, newHeight);
info.setHeight = newHeight;
if (typeof newHeight != "number") {
var px = /^(\d+\.?\d*)px$/.exec(newHeight);
if (px) {
newHeight = Number(px[1]);
} else {
info.wrapper.style.height = newHeight;
newHeight = info.wrapper.offsetHeight;
info.wrapper.style.height = "";
}
}
cm._setSize(width, info.heightLeft += (newHeight - height));
height = newHeight;
};
}
function removePanels(cm) {
var info = cm.state.panels;
cm.state.panels = null;
var wrap = cm.getWrapperElement();
info.wrapper.parentNode.replaceChild(wrap, info.wrapper);
wrap.style.height = info.setHeight;
cm.setSize = cm._setSize;
cm.setSize();
}
});

View File

@ -0,0 +1,56 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../../mode/css/css"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../../mode/css/css"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1,
"first-letter": 1, "first-line": 1, "first-child": 1,
before: 1, after: 1, lang: 1};
CodeMirror.registerHelper("hint", "css", function(cm) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
if (inner.mode.name != "css") return;
var word = token.string, start = token.start, end = token.end;
if (/[^\w$_-]/.test(word)) {
word = ""; start = end = cur.ch;
}
var spec = CodeMirror.resolveMode("text/css");
var result = [];
function add(keywords) {
for (var name in keywords)
if (!word || name.lastIndexOf(word, 0) == 0)
result.push(name);
}
var st = inner.state.state;
if (st == "pseudo" || token.type == "variable-3") {
add(pseudoClasses);
} else if (st == "block" || st == "maybeprop") {
add(spec.propertyKeywords);
} else if (st == "prop" || st == "parens" || st == "at" || st == "params") {
add(spec.valueKeywords);
add(spec.colorKeywords);
} else if (st == "media" || st == "media_parens") {
add(spec.mediaTypes);
add(spec.mediaFeatures);
}
if (result.length) return {
list: result,
from: CodeMirror.Pos(cur.line, start),
to: CodeMirror.Pos(cur.line, end)
};
});
});

View File

@ -0,0 +1,348 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror", "./xml-hint"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "./xml-hint"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var langs = "ab aa af ak sq am ar an hy as av ae ay az bm ba eu be bn bh bi bs br bg my ca ch ce ny zh cv kw co cr hr cs da dv nl dz en eo et ee fo fj fi fr ff gl ka de el gn gu ht ha he hz hi ho hu ia id ie ga ig ik io is it iu ja jv kl kn kr ks kk km ki rw ky kv kg ko ku kj la lb lg li ln lo lt lu lv gv mk mg ms ml mt mi mr mh mn na nv nb nd ne ng nn no ii nr oc oj cu om or os pa pi fa pl ps pt qu rm rn ro ru sa sc sd se sm sg sr gd sn si sk sl so st es su sw ss sv ta te tg th ti bo tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa cy wo fy xh yi yo za zu".split(" ");
var targets = ["_blank", "_self", "_top", "_parent"];
var charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"];
var methods = ["get", "post", "put", "delete"];
var encs = ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"];
var media = ["all", "screen", "print", "embossed", "braille", "handheld", "print", "projection", "screen", "tty", "tv", "speech",
"3d-glasses", "resolution [>][<][=] [X]", "device-aspect-ratio: X/Y", "orientation:portrait",
"orientation:landscape", "device-height: [X]", "device-width: [X]"];
var s = { attrs: {} }; // Simple tag, reused for a whole lot of tags
var data = {
a: {
attrs: {
href: null, ping: null, type: null,
media: media,
target: targets,
hreflang: langs
}
},
abbr: s,
acronym: s,
address: s,
applet: s,
area: {
attrs: {
alt: null, coords: null, href: null, target: null, ping: null,
media: media, hreflang: langs, type: null,
shape: ["default", "rect", "circle", "poly"]
}
},
article: s,
aside: s,
audio: {
attrs: {
src: null, mediagroup: null,
crossorigin: ["anonymous", "use-credentials"],
preload: ["none", "metadata", "auto"],
autoplay: ["", "autoplay"],
loop: ["", "loop"],
controls: ["", "controls"]
}
},
b: s,
base: { attrs: { href: null, target: targets } },
basefont: s,
bdi: s,
bdo: s,
big: s,
blockquote: { attrs: { cite: null } },
body: s,
br: s,
button: {
attrs: {
form: null, formaction: null, name: null, value: null,
autofocus: ["", "autofocus"],
disabled: ["", "autofocus"],
formenctype: encs,
formmethod: methods,
formnovalidate: ["", "novalidate"],
formtarget: targets,
type: ["submit", "reset", "button"]
}
},
canvas: { attrs: { width: null, height: null } },
caption: s,
center: s,
cite: s,
code: s,
col: { attrs: { span: null } },
colgroup: { attrs: { span: null } },
command: {
attrs: {
type: ["command", "checkbox", "radio"],
label: null, icon: null, radiogroup: null, command: null, title: null,
disabled: ["", "disabled"],
checked: ["", "checked"]
}
},
data: { attrs: { value: null } },
datagrid: { attrs: { disabled: ["", "disabled"], multiple: ["", "multiple"] } },
datalist: { attrs: { data: null } },
dd: s,
del: { attrs: { cite: null, datetime: null } },
details: { attrs: { open: ["", "open"] } },
dfn: s,
dir: s,
div: s,
dl: s,
dt: s,
em: s,
embed: { attrs: { src: null, type: null, width: null, height: null } },
eventsource: { attrs: { src: null } },
fieldset: { attrs: { disabled: ["", "disabled"], form: null, name: null } },
figcaption: s,
figure: s,
font: s,
footer: s,
form: {
attrs: {
action: null, name: null,
"accept-charset": charsets,
autocomplete: ["on", "off"],
enctype: encs,
method: methods,
novalidate: ["", "novalidate"],
target: targets
}
},
frame: s,
frameset: s,
h1: s, h2: s, h3: s, h4: s, h5: s, h6: s,
head: {
attrs: {},
children: ["title", "base", "link", "style", "meta", "script", "noscript", "command"]
},
header: s,
hgroup: s,
hr: s,
html: {
attrs: { manifest: null },
children: ["head", "body"]
},
i: s,
iframe: {
attrs: {
src: null, srcdoc: null, name: null, width: null, height: null,
sandbox: ["allow-top-navigation", "allow-same-origin", "allow-forms", "allow-scripts"],
seamless: ["", "seamless"]
}
},
img: {
attrs: {
alt: null, src: null, ismap: null, usemap: null, width: null, height: null,
crossorigin: ["anonymous", "use-credentials"]
}
},
input: {
attrs: {
alt: null, dirname: null, form: null, formaction: null,
height: null, list: null, max: null, maxlength: null, min: null,
name: null, pattern: null, placeholder: null, size: null, src: null,
step: null, value: null, width: null,
accept: ["audio/*", "video/*", "image/*"],
autocomplete: ["on", "off"],
autofocus: ["", "autofocus"],
checked: ["", "checked"],
disabled: ["", "disabled"],
formenctype: encs,
formmethod: methods,
formnovalidate: ["", "novalidate"],
formtarget: targets,
multiple: ["", "multiple"],
readonly: ["", "readonly"],
required: ["", "required"],
type: ["hidden", "text", "search", "tel", "url", "email", "password", "datetime", "date", "month",
"week", "time", "datetime-local", "number", "range", "color", "checkbox", "radio",
"file", "submit", "image", "reset", "button"]
}
},
ins: { attrs: { cite: null, datetime: null } },
kbd: s,
keygen: {
attrs: {
challenge: null, form: null, name: null,
autofocus: ["", "autofocus"],
disabled: ["", "disabled"],
keytype: ["RSA"]
}
},
label: { attrs: { "for": null, form: null } },
legend: s,
li: { attrs: { value: null } },
link: {
attrs: {
href: null, type: null,
hreflang: langs,
media: media,
sizes: ["all", "16x16", "16x16 32x32", "16x16 32x32 64x64"]
}
},
map: { attrs: { name: null } },
mark: s,
menu: { attrs: { label: null, type: ["list", "context", "toolbar"] } },
meta: {
attrs: {
content: null,
charset: charsets,
name: ["viewport", "application-name", "author", "description", "generator", "keywords"],
"http-equiv": ["content-language", "content-type", "default-style", "refresh"]
}
},
meter: { attrs: { value: null, min: null, low: null, high: null, max: null, optimum: null } },
nav: s,
noframes: s,
noscript: s,
object: {
attrs: {
data: null, type: null, name: null, usemap: null, form: null, width: null, height: null,
typemustmatch: ["", "typemustmatch"]
}
},
ol: { attrs: { reversed: ["", "reversed"], start: null, type: ["1", "a", "A", "i", "I"] } },
optgroup: { attrs: { disabled: ["", "disabled"], label: null } },
option: { attrs: { disabled: ["", "disabled"], label: null, selected: ["", "selected"], value: null } },
output: { attrs: { "for": null, form: null, name: null } },
p: s,
param: { attrs: { name: null, value: null } },
pre: s,
progress: { attrs: { value: null, max: null } },
q: { attrs: { cite: null } },
rp: s,
rt: s,
ruby: s,
s: s,
samp: s,
script: {
attrs: {
type: ["text/javascript"],
src: null,
async: ["", "async"],
defer: ["", "defer"],
charset: charsets
}
},
section: s,
select: {
attrs: {
form: null, name: null, size: null,
autofocus: ["", "autofocus"],
disabled: ["", "disabled"],
multiple: ["", "multiple"]
}
},
small: s,
source: { attrs: { src: null, type: null, media: null } },
span: s,
strike: s,
strong: s,
style: {
attrs: {
type: ["text/css"],
media: media,
scoped: null
}
},
sub: s,
summary: s,
sup: s,
table: s,
tbody: s,
td: { attrs: { colspan: null, rowspan: null, headers: null } },
textarea: {
attrs: {
dirname: null, form: null, maxlength: null, name: null, placeholder: null,
rows: null, cols: null,
autofocus: ["", "autofocus"],
disabled: ["", "disabled"],
readonly: ["", "readonly"],
required: ["", "required"],
wrap: ["soft", "hard"]
}
},
tfoot: s,
th: { attrs: { colspan: null, rowspan: null, headers: null, scope: ["row", "col", "rowgroup", "colgroup"] } },
thead: s,
time: { attrs: { datetime: null } },
title: s,
tr: s,
track: {
attrs: {
src: null, label: null, "default": null,
kind: ["subtitles", "captions", "descriptions", "chapters", "metadata"],
srclang: langs
}
},
tt: s,
u: s,
ul: s,
"var": s,
video: {
attrs: {
src: null, poster: null, width: null, height: null,
crossorigin: ["anonymous", "use-credentials"],
preload: ["auto", "metadata", "none"],
autoplay: ["", "autoplay"],
mediagroup: ["movie"],
muted: ["", "muted"],
controls: ["", "controls"]
}
},
wbr: s
};
var globalAttrs = {
accesskey: ["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", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
"class": null,
contenteditable: ["true", "false"],
contextmenu: null,
dir: ["ltr", "rtl", "auto"],
draggable: ["true", "false", "auto"],
dropzone: ["copy", "move", "link", "string:", "file:"],
hidden: ["hidden"],
id: null,
inert: ["inert"],
itemid: null,
itemprop: null,
itemref: null,
itemscope: ["itemscope"],
itemtype: null,
lang: ["en", "es"],
spellcheck: ["true", "false"],
style: null,
tabindex: ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
title: null,
translate: ["yes", "no"],
onclick: null,
rel: ["stylesheet", "alternate", "author", "bookmark", "help", "license", "next", "nofollow", "noreferrer", "prefetch", "prev", "search", "tag"]
};
function populate(obj) {
for (var attr in globalAttrs) if (globalAttrs.hasOwnProperty(attr))
obj.attrs[attr] = globalAttrs[attr];
}
populate(s);
for (var tag in data) if (data.hasOwnProperty(tag) && data[tag] != s)
populate(data[tag]);
CodeMirror.htmlSchema = data;
function htmlHint(cm, options) {
var local = {schemaInfo: data};
if (options) for (var opt in options) local[opt] = options[opt];
return CodeMirror.hint.xml(cm, local);
}
CodeMirror.registerHelper("hint", "html", htmlHint);
});

View File

@ -0,0 +1,141 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
var Pos = CodeMirror.Pos;
function forEach(arr, f) {
for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
}
function arrayContains(arr, item) {
if (!Array.prototype.indexOf) {
var i = arr.length;
while (i--) {
if (arr[i] === item) {
return true;
}
}
return false;
}
return arr.indexOf(item) != -1;
}
function scriptHint(editor, keywords, getToken, options) {
// Find the token at the cursor
var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
if (/\b(?:string|comment)\b/.test(token.type)) return;
token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;
// If it's not a 'word-style' token, ignore the token.
if (!/^[\w$_]*$/.test(token.string)) {
token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
type: token.string == "." ? "property" : null};
}
// If it is a property, find out what it is a property of.
while (tprop.type == "property") {
tprop = getToken(editor, Pos(cur.line, tprop.start));
if (tprop.string != ".") return;
tprop = getToken(editor, Pos(cur.line, tprop.start));
if (!context) var context = [];
context.push(tprop);
}
return {list: getCompletions(token, context, keywords, options),
from: Pos(cur.line, token.start),
to: Pos(cur.line, token.end)};
}
function javascriptHint(editor, options) {
return scriptHint(editor, javascriptKeywords,
function (e, cur) {return e.getTokenAt(cur);},
options);
};
CodeMirror.registerHelper("hint", "javascript", javascriptHint);
function getCoffeeScriptToken(editor, cur) {
// This getToken, it is for coffeescript, imitates the behavior of
// getTokenAt method in javascript.js, that is, returning "property"
// type and treat "." as indepenent token.
var token = editor.getTokenAt(cur);
if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
token.end = token.start;
token.string = '.';
token.type = "property";
}
else if (/^\.[\w$_]*$/.test(token.string)) {
token.type = "property";
token.start++;
token.string = token.string.replace(/\./, '');
}
return token;
}
function coffeescriptHint(editor, options) {
return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
}
CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint);
var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
"toUpperCase toLowerCase split concat match replace search").split(" ");
var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
"lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
var funcProps = "prototype apply call bind".split(" ");
var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " +
"if in instanceof new null return switch throw true try typeof var void while with").split(" ");
var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
"if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
function getCompletions(token, context, keywords, options) {
var found = [], start = token.string, global = options && options.globalScope || window;
function maybeAdd(str) {
if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
}
function gatherCompletions(obj) {
if (typeof obj == "string") forEach(stringProps, maybeAdd);
else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
else if (obj instanceof Function) forEach(funcProps, maybeAdd);
for (var name in obj) maybeAdd(name);
}
if (context && context.length) {
// If this is a property, see if it belongs to some object we can
// find in the current environment.
var obj = context.pop(), base;
if (obj.type && obj.type.indexOf("variable") === 0) {
if (options && options.additionalContext)
base = options.additionalContext[obj.string];
if (!options || options.useGlobalScope !== false)
base = base || global[obj.string];
} else if (obj.type == "string") {
base = "";
} else if (obj.type == "atom") {
base = 1;
} else if (obj.type == "function") {
if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
(typeof global.jQuery == 'function'))
base = global.jQuery();
else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function'))
base = global._();
}
while (base != null && context.length)
base = base[context.pop().string];
if (base != null) gatherCompletions(base);
} else {
// If not, just look in the global object and any local scope
// (reading into JS mode internals to get at the local and global variables)
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
if (!options || options.useGlobalScope !== false)
gatherCompletions(global);
forEach(keywords, maybeAdd);
}
return found;
}
});

View File

@ -0,0 +1,38 @@
.CodeMirror-hints {
position: absolute;
z-index: 10;
overflow: hidden;
list-style: none;
margin: 0;
padding: 2px;
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
border-radius: 3px;
border: 1px solid silver;
background: white;
font-size: 90%;
font-family: monospace;
max-height: 20em;
overflow-y: auto;
}
.CodeMirror-hint {
margin: 0;
padding: 0 4px;
border-radius: 2px;
max-width: 19em;
overflow: hidden;
white-space: pre;
color: black;
cursor: pointer;
}
li.CodeMirror-hint-active {
background: #08f;
color: white;
}

View File

@ -0,0 +1,389 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var HINT_ELEMENT_CLASS = "CodeMirror-hint";
var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
// This is the old interface, kept around for now to stay
// backwards-compatible.
CodeMirror.showHint = function(cm, getHints, options) {
if (!getHints) return cm.showHint(options);
if (options && options.async) getHints.async = true;
var newOpts = {hint: getHints};
if (options) for (var prop in options) newOpts[prop] = options[prop];
return cm.showHint(newOpts);
};
CodeMirror.defineExtension("showHint", function(options) {
// We want a single cursor position.
if (this.listSelections().length > 1 || this.somethingSelected()) return;
if (this.state.completionActive) this.state.completionActive.close();
var completion = this.state.completionActive = new Completion(this, options);
var getHints = completion.options.hint;
if (!getHints) return;
CodeMirror.signal(this, "startCompletion", this);
if (getHints.async)
getHints(this, function(hints) { completion.showHints(hints); }, completion.options);
else
return completion.showHints(getHints(this, completion.options));
});
function Completion(cm, options) {
this.cm = cm;
this.options = this.buildOptions(options);
this.widget = this.onClose = null;
}
Completion.prototype = {
close: function() {
if (!this.active()) return;
this.cm.state.completionActive = null;
if (this.widget) this.widget.close();
if (this.onClose) this.onClose();
CodeMirror.signal(this.cm, "endCompletion", this.cm);
},
active: function() {
return this.cm.state.completionActive == this;
},
pick: function(data, i) {
var completion = data.list[i];
if (completion.hint) completion.hint(this.cm, data, completion);
else this.cm.replaceRange(getText(completion), completion.from || data.from,
completion.to || data.to, "complete");
CodeMirror.signal(data, "pick", completion);
this.close();
},
showHints: function(data) {
if (!data || !data.list.length || !this.active()) return this.close();
if (this.options.completeSingle && data.list.length == 1)
this.pick(data, 0);
else
this.showWidget(data);
},
showWidget: function(data) {
this.widget = new Widget(this, data);
CodeMirror.signal(data, "shown");
var debounce = 0, completion = this, finished;
var closeOn = this.options.closeCharacters;
var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
return setTimeout(fn, 1000/60);
};
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
function done() {
if (finished) return;
finished = true;
completion.close();
completion.cm.off("cursorActivity", activity);
if (data) CodeMirror.signal(data, "close");
}
function update() {
if (finished) return;
CodeMirror.signal(data, "update");
var getHints = completion.options.hint;
if (getHints.async)
getHints(completion.cm, finishUpdate, completion.options);
else
finishUpdate(getHints(completion.cm, completion.options));
}
function finishUpdate(data_) {
data = data_;
if (finished) return;
if (!data || !data.list.length) return done();
if (completion.widget) completion.widget.close();
completion.widget = new Widget(completion, data);
}
function clearDebounce() {
if (debounce) {
cancelAnimationFrame(debounce);
debounce = 0;
}
}
function activity() {
clearDebounce();
var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
pos.ch < startPos.ch || completion.cm.somethingSelected() ||
(pos.ch && closeOn.test(line.charAt(pos.ch - 1)))) {
completion.close();
} else {
debounce = requestAnimationFrame(update);
if (completion.widget) completion.widget.close();
}
}
this.cm.on("cursorActivity", activity);
this.onClose = done;
},
buildOptions: function(options) {
var editor = this.cm.options.hintOptions;
var out = {};
for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
if (editor) for (var prop in editor)
if (editor[prop] !== undefined) out[prop] = editor[prop];
if (options) for (var prop in options)
if (options[prop] !== undefined) out[prop] = options[prop];
return out;
}
};
function getText(completion) {
if (typeof completion == "string") return completion;
else return completion.text;
}
function buildKeyMap(completion, handle) {
var baseMap = {
Up: function() {handle.moveFocus(-1);},
Down: function() {handle.moveFocus(1);},
PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
Home: function() {handle.setFocus(0);},
End: function() {handle.setFocus(handle.length - 1);},
Enter: handle.pick,
Tab: handle.pick,
Esc: handle.close
};
var custom = completion.options.customKeys;
var ourMap = custom ? {} : baseMap;
function addBinding(key, val) {
var bound;
if (typeof val != "string")
bound = function(cm) { return val(cm, handle); };
// This mechanism is deprecated
else if (baseMap.hasOwnProperty(val))
bound = baseMap[val];
else
bound = val;
ourMap[key] = bound;
}
if (custom)
for (var key in custom) if (custom.hasOwnProperty(key))
addBinding(key, custom[key]);
var extra = completion.options.extraKeys;
if (extra)
for (var key in extra) if (extra.hasOwnProperty(key))
addBinding(key, extra[key]);
return ourMap;
}
function getHintElement(hintsElement, el) {
while (el && el != hintsElement) {
if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
el = el.parentNode;
}
}
function Widget(completion, data) {
this.completion = completion;
this.data = data;
var widget = this, cm = completion.cm;
var hints = this.hints = document.createElement("ul");
hints.className = "CodeMirror-hints";
this.selectedHint = data.selectedHint || 0;
var completions = data.list;
for (var i = 0; i < completions.length; ++i) {
var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
if (cur.className != null) className = cur.className + " " + className;
elt.className = className;
if (cur.render) cur.render(elt, data, cur);
else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
elt.hintId = i;
}
var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
var left = pos.left, top = pos.bottom, below = true;
hints.style.left = left + "px";
hints.style.top = top + "px";
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
(completion.options.container || document.body).appendChild(hints);
var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
if (overlapY > 0) {
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
if (curTop - height > 0) { // Fits above cursor
hints.style.top = (top = pos.top - height) + "px";
below = false;
} else if (height > winH) {
hints.style.height = (winH - 5) + "px";
hints.style.top = (top = pos.bottom - box.top) + "px";
var cursor = cm.getCursor();
if (data.from.ch != cursor.ch) {
pos = cm.cursorCoords(cursor);
hints.style.left = (left = pos.left) + "px";
box = hints.getBoundingClientRect();
}
}
}
var overlapX = box.left - winW;
if (overlapX > 0) {
if (box.right - box.left > winW) {
hints.style.width = (winW - 5) + "px";
overlapX -= (box.right - box.left) - winW;
}
hints.style.left = (left = pos.left - overlapX) + "px";
}
cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
setFocus: function(n) { widget.changeActive(n); },
menuSize: function() { return widget.screenAmount(); },
length: completions.length,
close: function() { completion.close(); },
pick: function() { widget.pick(); },
data: data
}));
if (completion.options.closeOnUnfocus) {
var closingOnBlur;
cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
}
var startScroll = cm.getScrollInfo();
cm.on("scroll", this.onScroll = function() {
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
var newTop = top + startScroll.top - curScroll.top;
var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
if (!below) point += hints.offsetHeight;
if (point <= editor.top || point >= editor.bottom) return completion.close();
hints.style.top = newTop + "px";
hints.style.left = (left + startScroll.left - curScroll.left) + "px";
});
CodeMirror.on(hints, "dblclick", function(e) {
var t = getHintElement(hints, e.target || e.srcElement);
if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
});
CodeMirror.on(hints, "click", function(e) {
var t = getHintElement(hints, e.target || e.srcElement);
if (t && t.hintId != null) {
widget.changeActive(t.hintId);
if (completion.options.completeOnSingleClick) widget.pick();
}
});
CodeMirror.on(hints, "mousedown", function() {
setTimeout(function(){cm.focus();}, 20);
});
CodeMirror.signal(data, "select", completions[0], hints.firstChild);
return true;
}
Widget.prototype = {
close: function() {
if (this.completion.widget != this) return;
this.completion.widget = null;
this.hints.parentNode.removeChild(this.hints);
this.completion.cm.removeKeyMap(this.keyMap);
var cm = this.completion.cm;
if (this.completion.options.closeOnUnfocus) {
cm.off("blur", this.onBlur);
cm.off("focus", this.onFocus);
}
cm.off("scroll", this.onScroll);
},
pick: function() {
this.completion.pick(this.data, this.selectedHint);
},
changeActive: function(i, avoidWrap) {
if (i >= this.data.list.length)
i = avoidWrap ? this.data.list.length - 1 : 0;
else if (i < 0)
i = avoidWrap ? 0 : this.data.list.length - 1;
if (this.selectedHint == i) return;
var node = this.hints.childNodes[this.selectedHint];
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
node = this.hints.childNodes[this.selectedHint = i];
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
if (node.offsetTop < this.hints.scrollTop)
this.hints.scrollTop = node.offsetTop - 3;
else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
},
screenAmount: function() {
return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
}
};
CodeMirror.registerHelper("hint", "auto", function(cm, options) {
var helpers = cm.getHelpers(cm.getCursor(), "hint"), words;
if (helpers.length) {
for (var i = 0; i < helpers.length; i++) {
var cur = helpers[i](cm, options);
if (cur && cur.list.length) return cur;
}
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
if (words) return CodeMirror.hint.fromList(cm, {words: words});
} else if (CodeMirror.hint.anyword) {
return CodeMirror.hint.anyword(cm, options);
}
});
CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
var found = [];
for (var i = 0; i < options.words.length; i++) {
var word = options.words[i];
if (word.slice(0, token.string.length) == token.string)
found.push(word);
}
if (found.length) return {
list: found,
from: CodeMirror.Pos(cur.line, token.start),
to: CodeMirror.Pos(cur.line, token.end)
};
});
CodeMirror.commands.autocomplete = CodeMirror.showHint;
var defaultOptions = {
hint: CodeMirror.hint.auto,
completeSingle: true,
alignWithWord: true,
closeCharacters: /[\s()\[\]{};:>,]/,
closeOnUnfocus: true,
completeOnSingleClick: false,
container: null,
customKeys: null,
extraKeys: null
};
CodeMirror.defineOption("hintOptions", null);
});

View File

@ -0,0 +1,111 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var Pos = CodeMirror.Pos;
function getHints(cm, options) {
var tags = options && options.schemaInfo;
var quote = (options && options.quoteChar) || '"';
if (!tags) return;
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
if (/^<\/?$/.test(token.string) && token.end == cur.ch) {
var nextToken = cm.getTokenAt(Pos(cur.line, cur.ch + 1));
if (nextToken.start == cur.ch && /\btag\b/.test(nextToken.type))
token = nextToken;
}
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
if (inner.mode.name != "xml") return;
var result = [], replaceToken = false, prefix;
var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
var tagName = tag && /^\w/.test(token.string), tagStart;
if (tagName) {
var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
} else if (tag && token.string == "<") {
tagType = "open";
} else if (tag && token.string == "</") {
tagType = "close";
}
if (!tag && !inner.state.tagName || tagType) {
if (tagName)
prefix = token.string;
replaceToken = tagType;
var cx = inner.state.context, curTag = cx && tags[cx.tagName];
var childList = cx ? curTag && curTag.children : tags["!top"];
if (childList && tagType != "close") {
for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0)
result.push("<" + childList[i]);
} else if (tagType != "close") {
for (var name in tags)
if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || name.lastIndexOf(prefix, 0) == 0))
result.push("<" + name);
}
if (cx && (!prefix || tagType == "close" && cx.tagName.lastIndexOf(prefix, 0) == 0))
result.push("</" + cx.tagName + ">");
} else {
// Attribute completion
var curTag = tags[inner.state.tagName], attrs = curTag && curTag.attrs;
var globalAttrs = tags["!attrs"];
if (!attrs && !globalAttrs) return;
if (!attrs) {
attrs = globalAttrs;
} else if (globalAttrs) { // Combine tag-local and global attributes
var set = {};
for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
attrs = set;
}
if (token.type == "string" || token.string == "=") { // A value
var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
Pos(cur.line, token.type == "string" ? token.start : token.end));
var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
if (token.type == "string") {
prefix = token.string;
var n = 0;
if (/['"]/.test(token.string.charAt(0))) {
quote = token.string.charAt(0);
prefix = token.string.slice(1);
n++;
}
var len = token.string.length;
if (/['"]/.test(token.string.charAt(len - 1))) {
quote = token.string.charAt(len - 1);
prefix = token.string.substr(n, len - 2);
}
replaceToken = true;
}
for (var i = 0; i < atValues.length; ++i) if (!prefix || atValues[i].lastIndexOf(prefix, 0) == 0)
result.push(quote + atValues[i] + quote);
} else { // An attribute name
if (token.type == "attribute") {
prefix = token.string;
replaceToken = true;
}
for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || attr.lastIndexOf(prefix, 0) == 0))
result.push(attr);
}
}
return {
list: result,
from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
to: replaceToken ? Pos(cur.line, token.end) : cur
};
}
CodeMirror.registerHelper("hint", "xml", getHints);
});

View File

@ -0,0 +1,73 @@
/* The lint marker gutter */
.CodeMirror-lint-markers {
width: 16px;
}
.CodeMirror-lint-tooltip {
background-color: infobackground;
border: 1px solid black;
border-radius: 4px 4px 4px 4px;
color: infotext;
font-family: monospace;
font-size: 10pt;
overflow: hidden;
padding: 2px 5px;
position: fixed;
white-space: pre;
white-space: pre-wrap;
z-index: 100;
max-width: 600px;
opacity: 0;
transition: opacity .4s;
-moz-transition: opacity .4s;
-webkit-transition: opacity .4s;
-o-transition: opacity .4s;
-ms-transition: opacity .4s;
}
.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning {
background-position: left bottom;
background-repeat: repeat-x;
}
.CodeMirror-lint-mark-error {
background-image:
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==")
;
}
.CodeMirror-lint-mark-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning {
background-position: center center;
background-repeat: no-repeat;
cursor: pointer;
display: inline-block;
height: 16px;
width: 16px;
vertical-align: middle;
position: relative;
}
.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning {
padding-left: 18px;
background-position: top left;
background-repeat: no-repeat;
}
.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-multiple {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");
background-repeat: no-repeat;
background-position: right bottom;
width: 100%; height: 100%;
}

View File

@ -0,0 +1,72 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.runMode = function(string, modespec, callback, options) {
var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
var ie = /MSIE \d/.test(navigator.userAgent);
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
if (callback.nodeType == 1) {
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
var node = callback, col = 0;
node.innerHTML = "";
callback = function(text, style) {
if (text == "\n") {
// Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
// Emitting a carriage return makes everything ok.
node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
col = 0;
return;
}
var content = "";
// replace tabs
for (var pos = 0;;) {
var idx = text.indexOf("\t", pos);
if (idx == -1) {
content += text.slice(pos);
col += text.length - pos;
break;
} else {
col += idx - pos;
content += text.slice(pos, idx);
var size = tabSize - col % tabSize;
col += size;
for (var i = 0; i < size; ++i) content += " ";
pos = idx + 1;
}
}
if (style) {
var sp = node.appendChild(document.createElement("span"));
sp.className = "cm-" + style.replace(/ +/g, " cm-");
sp.appendChild(document.createTextNode(content));
} else {
node.appendChild(document.createTextNode(content));
}
};
}
var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n");
var stream = new CodeMirror.StringStream(lines[i]);
if (!stream.string && mode.blankLine) mode.blankLine(state);
while (!stream.eol()) {
var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start, state);
stream.start = stream.pos;
}
}
};
});

View File

@ -52,12 +52,12 @@
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
}
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursors {
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
@ -125,6 +125,7 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
@ -209,6 +210,11 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
height: 100%;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
@ -305,5 +311,8 @@ div.CodeMirror-cursors {
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,717 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("css", function(config, parserConfig) {
if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
var indentUnit = config.indentUnit,
tokenHooks = parserConfig.tokenHooks,
mediaTypes = parserConfig.mediaTypes || {},
mediaFeatures = parserConfig.mediaFeatures || {},
propertyKeywords = parserConfig.propertyKeywords || {},
nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
colorKeywords = parserConfig.colorKeywords || {},
valueKeywords = parserConfig.valueKeywords || {},
fontProperties = parserConfig.fontProperties || {},
allowNested = parserConfig.allowNested;
var type, override;
function ret(style, tp) { type = tp; return style; }
// Tokenizers
function tokenBase(stream, state) {
var ch = stream.next();
if (tokenHooks[ch]) {
var result = tokenHooks[ch](stream, state);
if (result !== false) return result;
}
if (ch == "@") {
stream.eatWhile(/[\w\\\-]/);
return ret("def", stream.current());
} else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
return ret(null, "compare");
} else if (ch == "\"" || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
} else if (ch == "#") {
stream.eatWhile(/[\w\\\-]/);
return ret("atom", "hash");
} else if (ch == "!") {
stream.match(/^\s*\w*/);
return ret("keyword", "important");
} else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
stream.eatWhile(/[\w.%]/);
return ret("number", "unit");
} else if (ch === "-") {
if (/[\d.]/.test(stream.peek())) {
stream.eatWhile(/[\w.%]/);
return ret("number", "unit");
} else if (stream.match(/^\w+-/)) {
return ret("meta", "meta");
}
} else if (/[,+>*\/]/.test(ch)) {
return ret(null, "select-op");
} else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
return ret("qualifier", "qualifier");
} else if (/[:;{}\[\]\(\)]/.test(ch)) {
return ret(null, ch);
} else if (ch == "u" && stream.match("rl(")) {
stream.backUp(1);
state.tokenize = tokenParenthesized;
return ret("property", "word");
} else if (/[\w\\\-]/.test(ch)) {
stream.eatWhile(/[\w\\\-]/);
return ret("property", "word");
} else {
return ret(null, null);
}
}
function tokenString(quote) {
return function(stream, state) {
var escaped = false, ch;
while ((ch = stream.next()) != null) {
if (ch == quote && !escaped) {
if (quote == ")") stream.backUp(1);
break;
}
escaped = !escaped && ch == "\\";
}
if (ch == quote || !escaped && quote != ")") state.tokenize = null;
return ret("string", "string");
};
}
function tokenParenthesized(stream, state) {
stream.next(); // Must be '('
if (!stream.match(/\s*[\"\')]/, false))
state.tokenize = tokenString(")");
else
state.tokenize = null;
return ret(null, "(");
}
// Context management
function Context(type, indent, prev) {
this.type = type;
this.indent = indent;
this.prev = prev;
}
function pushContext(state, stream, type) {
state.context = new Context(type, stream.indentation() + indentUnit, state.context);
return type;
}
function popContext(state) {
state.context = state.context.prev;
return state.context.type;
}
function pass(type, stream, state) {
return states[state.context.type](type, stream, state);
}
function popAndPass(type, stream, state, n) {
for (var i = n || 1; i > 0; i--)
state.context = state.context.prev;
return pass(type, stream, state);
}
// Parser
function wordAsValue(stream) {
var word = stream.current().toLowerCase();
if (valueKeywords.hasOwnProperty(word))
override = "atom";
else if (colorKeywords.hasOwnProperty(word))
override = "keyword";
else
override = "variable";
}
var states = {};
states.top = function(type, stream, state) {
if (type == "{") {
return pushContext(state, stream, "block");
} else if (type == "}" && state.context.prev) {
return popContext(state);
} else if (type == "@media") {
return pushContext(state, stream, "media");
} else if (type == "@font-face") {
return "font_face_before";
} else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
return "keyframes";
} else if (type && type.charAt(0) == "@") {
return pushContext(state, stream, "at");
} else if (type == "hash") {
override = "builtin";
} else if (type == "word") {
override = "tag";
} else if (type == "variable-definition") {
return "maybeprop";
} else if (type == "interpolation") {
return pushContext(state, stream, "interpolation");
} else if (type == ":") {
return "pseudo";
} else if (allowNested && type == "(") {
return pushContext(state, stream, "parens");
}
return state.context.type;
};
states.block = function(type, stream, state) {
if (type == "word") {
var word = stream.current().toLowerCase();
if (propertyKeywords.hasOwnProperty(word)) {
override = "property";
return "maybeprop";
} else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
override = "string-2";
return "maybeprop";
} else if (allowNested) {
override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
return "block";
} else {
override += " error";
return "maybeprop";
}
} else if (type == "meta") {
return "block";
} else if (!allowNested && (type == "hash" || type == "qualifier")) {
override = "error";
return "block";
} else {
return states.top(type, stream, state);
}
};
states.maybeprop = function(type, stream, state) {
if (type == ":") return pushContext(state, stream, "prop");
return pass(type, stream, state);
};
states.prop = function(type, stream, state) {
if (type == ";") return popContext(state);
if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
if (type == "}" || type == "{") return popAndPass(type, stream, state);
if (type == "(") return pushContext(state, stream, "parens");
if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
override += " error";
} else if (type == "word") {
wordAsValue(stream);
} else if (type == "interpolation") {
return pushContext(state, stream, "interpolation");
}
return "prop";
};
states.propBlock = function(type, _stream, state) {
if (type == "}") return popContext(state);
if (type == "word") { override = "property"; return "maybeprop"; }
return state.context.type;
};
states.parens = function(type, stream, state) {
if (type == "{" || type == "}") return popAndPass(type, stream, state);
if (type == ")") return popContext(state);
if (type == "(") return pushContext(state, stream, "parens");
if (type == "word") wordAsValue(stream);
return "parens";
};
states.pseudo = function(type, stream, state) {
if (type == "word") {
override = "variable-3";
return state.context.type;
}
return pass(type, stream, state);
};
states.media = function(type, stream, state) {
if (type == "(") return pushContext(state, stream, "media_parens");
if (type == "}") return popAndPass(type, stream, state);
if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
if (type == "word") {
var word = stream.current().toLowerCase();
if (word == "only" || word == "not" || word == "and")
override = "keyword";
else if (mediaTypes.hasOwnProperty(word))
override = "attribute";
else if (mediaFeatures.hasOwnProperty(word))
override = "property";
else
override = "error";
}
return state.context.type;
};
states.media_parens = function(type, stream, state) {
if (type == ")") return popContext(state);
if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
return states.media(type, stream, state);
};
states.font_face_before = function(type, stream, state) {
if (type == "{")
return pushContext(state, stream, "font_face");
return pass(type, stream, state);
};
states.font_face = function(type, stream, state) {
if (type == "}") return popContext(state);
if (type == "word") {
if (!fontProperties.hasOwnProperty(stream.current().toLowerCase()))
override = "error";
else
override = "property";
return "maybeprop";
}
return "font_face";
};
states.keyframes = function(type, stream, state) {
if (type == "word") { override = "variable"; return "keyframes"; }
if (type == "{") return pushContext(state, stream, "top");
return pass(type, stream, state);
};
states.at = function(type, stream, state) {
if (type == ";") return popContext(state);
if (type == "{" || type == "}") return popAndPass(type, stream, state);
if (type == "word") override = "tag";
else if (type == "hash") override = "builtin";
return "at";
};
states.interpolation = function(type, stream, state) {
if (type == "}") return popContext(state);
if (type == "{" || type == ";") return popAndPass(type, stream, state);
if (type != "variable") override = "error";
return "interpolation";
};
return {
startState: function(base) {
return {tokenize: null,
state: "top",
context: new Context("top", base || 0, null)};
},
token: function(stream, state) {
if (!state.tokenize && stream.eatSpace()) return null;
var style = (state.tokenize || tokenBase)(stream, state);
if (style && typeof style == "object") {
type = style[1];
style = style[0];
}
override = style;
state.state = states[state.state](type, stream, state);
return override;
},
indent: function(state, textAfter) {
var cx = state.context, ch = textAfter && textAfter.charAt(0);
var indent = cx.indent;
if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
if (cx.prev &&
(ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") ||
ch == ")" && (cx.type == "parens" || cx.type == "media_parens") ||
ch == "{" && (cx.type == "at" || cx.type == "media"))) {
indent = cx.indent - indentUnit;
cx = cx.prev;
}
return indent;
},
electricChars: "}",
blockCommentStart: "/*",
blockCommentEnd: "*/",
fold: "brace"
};
});
function keySet(array) {
var keys = {};
for (var i = 0; i < array.length; ++i) {
keys[array[i]] = true;
}
return keys;
}
var mediaTypes_ = [
"all", "aural", "braille", "handheld", "print", "projection", "screen",
"tty", "tv", "embossed"
], mediaTypes = keySet(mediaTypes_);
var mediaFeatures_ = [
"width", "min-width", "max-width", "height", "min-height", "max-height",
"device-width", "min-device-width", "max-device-width", "device-height",
"min-device-height", "max-device-height", "aspect-ratio",
"min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
"min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
"max-color", "color-index", "min-color-index", "max-color-index",
"monochrome", "min-monochrome", "max-monochrome", "resolution",
"min-resolution", "max-resolution", "scan", "grid"
], mediaFeatures = keySet(mediaFeatures_);
var propertyKeywords_ = [
"align-content", "align-items", "align-self", "alignment-adjust",
"alignment-baseline", "anchor-point", "animation", "animation-delay",
"animation-direction", "animation-duration", "animation-fill-mode",
"animation-iteration-count", "animation-name", "animation-play-state",
"animation-timing-function", "appearance", "azimuth", "backface-visibility",
"background", "background-attachment", "background-clip", "background-color",
"background-image", "background-origin", "background-position",
"background-repeat", "background-size", "baseline-shift", "binding",
"bleed", "bookmark-label", "bookmark-level", "bookmark-state",
"bookmark-target", "border", "border-bottom", "border-bottom-color",
"border-bottom-left-radius", "border-bottom-right-radius",
"border-bottom-style", "border-bottom-width", "border-collapse",
"border-color", "border-image", "border-image-outset",
"border-image-repeat", "border-image-slice", "border-image-source",
"border-image-width", "border-left", "border-left-color",
"border-left-style", "border-left-width", "border-radius", "border-right",
"border-right-color", "border-right-style", "border-right-width",
"border-spacing", "border-style", "border-top", "border-top-color",
"border-top-left-radius", "border-top-right-radius", "border-top-style",
"border-top-width", "border-width", "bottom", "box-decoration-break",
"box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
"caption-side", "clear", "clip", "color", "color-profile", "column-count",
"column-fill", "column-gap", "column-rule", "column-rule-color",
"column-rule-style", "column-rule-width", "column-span", "column-width",
"columns", "content", "counter-increment", "counter-reset", "crop", "cue",
"cue-after", "cue-before", "cursor", "direction", "display",
"dominant-baseline", "drop-initial-after-adjust",
"drop-initial-after-align", "drop-initial-before-adjust",
"drop-initial-before-align", "drop-initial-size", "drop-initial-value",
"elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
"flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
"float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
"font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
"font-stretch", "font-style", "font-synthesis", "font-variant",
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
"font-variant-ligatures", "font-variant-numeric", "font-variant-position",
"font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
"grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end",
"grid-column-start", "grid-row", "grid-row-end", "grid-row-start",
"grid-template", "grid-template-areas", "grid-template-columns",
"grid-template-rows", "hanging-punctuation", "height", "hyphens",
"icon", "image-orientation", "image-rendering", "image-resolution",
"inline-box-align", "justify-content", "left", "letter-spacing",
"line-break", "line-height", "line-stacking", "line-stacking-ruby",
"line-stacking-shift", "line-stacking-strategy", "list-style",
"list-style-image", "list-style-position", "list-style-type", "margin",
"margin-bottom", "margin-left", "margin-right", "margin-top",
"marker-offset", "marks", "marquee-direction", "marquee-loop",
"marquee-play-count", "marquee-speed", "marquee-style", "max-height",
"max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
"nav-left", "nav-right", "nav-up", "object-fit", "object-position",
"opacity", "order", "orphans", "outline",
"outline-color", "outline-offset", "outline-style", "outline-width",
"overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
"page", "page-break-after", "page-break-before", "page-break-inside",
"page-policy", "pause", "pause-after", "pause-before", "perspective",
"perspective-origin", "pitch", "pitch-range", "play-during", "position",
"presentation-level", "punctuation-trim", "quotes", "region-break-after",
"region-break-before", "region-break-inside", "region-fragment",
"rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
"right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
"ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
"shape-outside", "size", "speak", "speak-as", "speak-header",
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
"tab-size", "table-layout", "target", "target-name", "target-new",
"target-position", "text-align", "text-align-last", "text-decoration",
"text-decoration-color", "text-decoration-line", "text-decoration-skip",
"text-decoration-style", "text-emphasis", "text-emphasis-color",
"text-emphasis-position", "text-emphasis-style", "text-height",
"text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
"text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
"text-wrap", "top", "transform", "transform-origin", "transform-style",
"transition", "transition-delay", "transition-duration",
"transition-property", "transition-timing-function", "unicode-bidi",
"vertical-align", "visibility", "voice-balance", "voice-duration",
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
"voice-volume", "volume", "white-space", "widows", "width", "word-break",
"word-spacing", "word-wrap", "z-index",
// SVG-specific
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
"color-interpolation", "color-interpolation-filters",
"color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
"marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
"stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
"stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
"baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
"glyph-orientation-vertical", "text-anchor", "writing-mode"
], propertyKeywords = keySet(propertyKeywords_);
var nonStandardPropertyKeywords_ = [
"scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
"scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
"scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
"searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
"searchfield-results-decoration", "zoom"
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
var colorKeywords_ = [
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
"darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
"deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
"gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
"lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
"purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
"salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
"slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
"whitesmoke", "yellow", "yellowgreen"
], colorKeywords = keySet(colorKeywords_);
var valueKeywords_ = [
"above", "absolute", "activeborder", "activecaption", "afar",
"after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
"arabic-indic", "armenian", "asterisks", "auto", "avoid", "avoid-column", "avoid-page",
"avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
"bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
"both", "bottom", "break", "break-all", "break-word", "button", "button-bevel",
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian",
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
"cell", "center", "checkbox", "circle", "cjk-earthly-branch",
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
"col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
"content-box", "context-menu", "continuous", "copy", "cover", "crop",
"cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal",
"decimal-leading-zero", "default", "default-button", "destination-atop",
"destination-in", "destination-out", "destination-over", "devanagari",
"disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted",
"double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
"element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
"ethiopic-halehame-gez", "ethiopic-halehame-om-et",
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et",
"ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed",
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes",
"forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
"help", "hidden", "hide", "higher", "highlight", "highlighttext",
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
"inline-block", "inline-table", "inset", "inside", "intrinsic", "invert",
"italic", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer",
"landscape", "lao", "large", "larger", "left", "level", "lighter",
"line-through", "linear", "lines", "list-item", "listbox", "listitem",
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
"lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
"lower-roman", "lowercase", "ltr", "malayalam", "match",
"media-controls-background", "media-current-time-display",
"media-fullscreen-button", "media-mute-button", "media-play-button",
"media-return-to-realtime-button", "media-rewind-button",
"media-seek-back-button", "media-seek-forward-button", "media-slider",
"media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
"media-volume-slider-container", "media-volume-sliderthumb", "medium",
"menu", "menulist", "menulist-button", "menulist-text",
"menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
"mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
"narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
"ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
"outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
"painted", "page", "paused", "persian", "plus-darker", "plus-lighter", "pointer",
"polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
"radio", "read-only", "read-write", "read-write-plaintext-only", "rectangle", "region",
"relative", "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
"ridge", "right", "round", "row-resize", "rtl", "run-in", "running",
"s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield",
"searchfield-cancel-button", "searchfield-decoration",
"searchfield-results-button", "searchfield-results-decoration",
"semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
"single", "skip-white-space", "slide", "slider-horizontal",
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
"small", "small-caps", "small-caption", "smaller", "solid", "somali",
"source-atop", "source-in", "source-out", "source-over", "space", "square",
"square-button", "start", "static", "status-bar", "stretch", "stroke",
"sub", "subpixel-antialiased", "super", "sw-resize", "table",
"table-caption", "table-cell", "table-column", "table-column-group",
"table-footer-group", "table-header-group", "table-row", "table-row-group",
"telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
"thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
"threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
"transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
"vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
"visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
"window", "windowframe", "windowtext", "x-large", "x-small", "xor",
"xx-large", "xx-small"
], valueKeywords = keySet(valueKeywords_);
var fontProperties_ = [
"font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
"font-stretch", "font-weight", "font-style"
], fontProperties = keySet(fontProperties_);
var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_)
.concat(nonStandardPropertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);
CodeMirror.registerHelper("hintWords", "css", allWords);
function tokenCComment(stream, state) {
var maybeEnd = false, ch;
while ((ch = stream.next()) != null) {
if (maybeEnd && ch == "/") {
state.tokenize = null;
break;
}
maybeEnd = (ch == "*");
}
return ["comment", "comment"];
}
function tokenSGMLComment(stream, state) {
if (stream.skipTo("-->")) {
stream.match("-->");
state.tokenize = null;
} else {
stream.skipToEnd();
}
return ["comment", "comment"];
}
CodeMirror.defineMIME("text/css", {
mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures,
propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
fontProperties: fontProperties,
tokenHooks: {
"<": function(stream, state) {
if (!stream.match("!--")) return false;
state.tokenize = tokenSGMLComment;
return tokenSGMLComment(stream, state);
},
"/": function(stream, state) {
if (!stream.eat("*")) return false;
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
}
},
name: "css"
});
CodeMirror.defineMIME("text/x-scss", {
mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures,
propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
fontProperties: fontProperties,
allowNested: true,
tokenHooks: {
"/": function(stream, state) {
if (stream.eat("/")) {
stream.skipToEnd();
return ["comment", "comment"];
} else if (stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
} else {
return ["operator", "operator"];
}
},
":": function(stream) {
if (stream.match(/\s*\{/))
return [null, "{"];
return false;
},
"$": function(stream) {
stream.match(/^[\w-]+/);
if (stream.match(/^\s*:/, false))
return ["variable-2", "variable-definition"];
return ["variable-2", "variable"];
},
"#": function(stream) {
if (!stream.eat("{")) return false;
return [null, "interpolation"];
}
},
name: "css",
helperType: "scss"
});
CodeMirror.defineMIME("text/x-less", {
mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures,
propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
fontProperties: fontProperties,
allowNested: true,
tokenHooks: {
"/": function(stream, state) {
if (stream.eat("/")) {
stream.skipToEnd();
return ["comment", "comment"];
} else if (stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
} else {
return ["operator", "operator"];
}
},
"@": function(stream) {
if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
stream.eatWhile(/[\w\\\-]/);
if (stream.match(/^\s*:/, false))
return ["variable-2", "variable-definition"];
return ["variable-2", "variable"];
},
"&": function() {
return ["atom", "atom"];
}
},
name: "css",
helperType: "less"
});
});

View File

@ -0,0 +1,121 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
var htmlMode = CodeMirror.getMode(config, {name: "xml",
htmlMode: true,
multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
var cssMode = CodeMirror.getMode(config, "css");
var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
mode: CodeMirror.getMode(config, "javascript")});
if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
var conf = scriptTypesConf[i];
scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
}
scriptTypes.push({matches: /./,
mode: CodeMirror.getMode(config, "text/plain")});
function html(stream, state) {
var tagName = state.htmlState.tagName;
if (tagName) tagName = tagName.toLowerCase();
var style = htmlMode.token(stream, state.htmlState);
if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
// Script block: mode to change to depends on type attribute
var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
scriptType = scriptType ? scriptType[1] : "";
if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
for (var i = 0; i < scriptTypes.length; ++i) {
var tp = scriptTypes[i];
if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
if (tp.mode) {
state.token = script;
state.localMode = tp.mode;
state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
}
break;
}
}
} else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
state.token = css;
state.localMode = cssMode;
state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
}
return style;
}
function maybeBackup(stream, pat, style) {
var cur = stream.current();
var close = cur.search(pat), m;
if (close > -1) stream.backUp(cur.length - close);
else if (m = cur.match(/<\/?$/)) {
stream.backUp(cur.length);
if (!stream.match(pat, false)) stream.match(cur);
}
return style;
}
function script(stream, state) {
if (stream.match(/^<\/\s*script\s*>/i, false)) {
state.token = html;
state.localState = state.localMode = null;
return null;
}
return maybeBackup(stream, /<\/\s*script\s*>/,
state.localMode.token(stream, state.localState));
}
function css(stream, state) {
if (stream.match(/^<\/\s*style\s*>/i, false)) {
state.token = html;
state.localState = state.localMode = null;
return null;
}
return maybeBackup(stream, /<\/\s*style\s*>/,
cssMode.token(stream, state.localState));
}
return {
startState: function() {
var state = htmlMode.startState();
return {token: html, localMode: null, localState: null, htmlState: state};
},
copyState: function(state) {
if (state.localState)
var local = CodeMirror.copyState(state.localMode, state.localState);
return {token: state.token, localMode: state.localMode, localState: local,
htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
},
token: function(stream, state) {
return state.token(stream, state);
},
indent: function(state, textAfter) {
if (!state.localMode || /^\s*<\//.test(textAfter))
return htmlMode.indent(state.htmlState, textAfter);
else if (state.localMode.indent)
return state.localMode.indent(state.localState, textAfter);
else
return CodeMirror.Pass;
},
innerMode: function(state) {
return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
}
};
}, "xml", "javascript", "css");
CodeMirror.defineMIME("text/html", "htmlmixed");
});

View File

@ -0,0 +1,684 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// TODO actually recognize syntax of TypeScript constructs
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("javascript", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var statementIndent = parserConfig.statementIndent;
var jsonldMode = parserConfig.jsonld;
var jsonMode = parserConfig.json || jsonldMode;
var isTS = parserConfig.typescript;
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
// 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": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": 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,
"this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C
};
// 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"),
"extends": kw("extends"),
"constructor": kw("constructor"),
// scope modifiers
"public": kw("public"),
"private": kw("private"),
"protected": kw("protected"),
"static": kw("static"),
// types
"string": type, "number": type, "bool": type, "any": type
};
for (var attr in tsKeywords) {
jsKeywords[attr] = tsKeywords[attr];
}
}
return jsKeywords;
}();
var isOperatorChar = /[+\-*&%=<>!?|~^]/;
var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
function readRegexp(stream) {
var escaped = false, next, inSet = false;
while ((next = stream.next()) != null) {
if (!escaped) {
if (next == "/" && !inSet) return;
if (next == "[") inSet = true;
else if (inSet && next == "]") inSet = false;
}
escaped = !escaped && next == "\\";
}
}
// 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 tokenBase(stream, state) {
var ch = stream.next();
if (ch == '"' || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
} else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
return ret("number", "number");
} else if (ch == "." && stream.match("..")) {
return ret("spread", "meta");
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
return ret(ch);
} else if (ch == "=" && stream.eat(">")) {
return ret("=>", "operator");
} else if (ch == "0" && stream.eat(/x/i)) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
} else if (/\d/.test(ch)) {
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
return ret("number", "number");
} else if (ch == "/") {
if (stream.eat("*")) {
state.tokenize = tokenComment;
return tokenComment(stream, state);
} else if (stream.eat("/")) {
stream.skipToEnd();
return ret("comment", "comment");
} else if (state.lastType == "operator" || state.lastType == "keyword c" ||
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
readRegexp(stream);
stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
return ret("regexp", "string-2");
} else {
stream.eatWhile(isOperatorChar);
return ret("operator", "operator", stream.current());
}
} else if (ch == "`") {
state.tokenize = tokenQuasi;
return tokenQuasi(stream, state);
} else if (ch == "#") {
stream.skipToEnd();
return ret("error", "error");
} else if (isOperatorChar.test(ch)) {
stream.eatWhile(isOperatorChar);
return ret("operator", "operator", stream.current());
} else if (wordRE.test(ch)) {
stream.eatWhile(wordRE);
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 tokenString(quote) {
return function(stream, state) {
var escaped = false, next;
if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
state.tokenize = tokenBase;
return ret("jsonld-keyword", "meta");
}
while ((next = stream.next()) != null) {
if (next == quote && !escaped) break;
escaped = !escaped && next == "\\";
}
if (!escaped) state.tokenize = tokenBase;
return ret("string", "string");
};
}
function tokenComment(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "*");
}
return ret("comment", "comment");
}
function tokenQuasi(stream, state) {
var escaped = false, next;
while ((next = stream.next()) != null) {
if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
state.tokenize = tokenBase;
break;
}
escaped = !escaped && next == "\\";
}
return ret("quasi", "string-2", stream.current());
}
var brackets = "([{}])";
// This is a crude lookahead trick to try and notice that we're
// parsing the argument patterns for a fat-arrow function before we
// actually hit the arrow token. It only works if the arrow is on
// the same line as the arguments and there's no strange noise
// (comments) in between. Fallback is to only notice when we hit the
// arrow, and not declare the arguments as locals for the arrow
// body.
function findFatArrow(stream, state) {
if (state.fatArrowAt) state.fatArrowAt = null;
var arrow = stream.string.indexOf("=>", stream.start);
if (arrow < 0) return;
var depth = 0, sawSomething = false;
for (var pos = arrow - 1; pos >= 0; --pos) {
var ch = stream.string.charAt(pos);
var bracket = brackets.indexOf(ch);
if (bracket >= 0 && bracket < 3) {
if (!depth) { ++pos; break; }
if (--depth == 0) break;
} else if (bracket >= 3 && bracket < 6) {
++depth;
} else if (wordRE.test(ch)) {
sawSomething = true;
} else if (sawSomething && !depth) {
++pos;
break;
}
}
if (sawSomething && !depth) state.fatArrowAt = pos;
}
// Parser
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": 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;
for (var cx = state.context; cx; cx = cx.prev) {
for (var v = cx.vars; 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; cx.style = style;
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;
if (parserConfig.globalVars)
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, indent = state.indented;
if (state.lexical.type == "stat") indent = state.lexical.indented;
else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
indent = outer.indented;
state.lexical = new JSLexical(indent, 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) {
function exp(type) {
if (type == wanted) return cont();
else if (wanted == ";") return pass();
else return cont(exp);
};
return exp;
}
function statement(type, value) {
if (type == "var") return cont(pushlex("vardef", value.length), vardef, 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 == "if") {
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
cx.state.cc.pop()();
return cont(pushlex("form"), expression, statement, poplex, maybeelse);
}
if (type == "function") return cont(functiondef);
if (type == "for") return cont(pushlex("form"), forspec, 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);
if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
if (type == "class") return cont(pushlex("form"), className, poplex);
if (type == "export") return cont(pushlex("form"), afterExport, poplex);
if (type == "import") return cont(pushlex("form"), afterImport, poplex);
return pass(pushlex("stat"), expression, expect(";"), poplex);
}
function expression(type) {
return expressionInner(type, false);
}
function expressionNoComma(type) {
return expressionInner(type, true);
}
function expressionInner(type, noComma) {
if (cx.state.fatArrowAt == cx.stream.start) {
var body = noComma ? arrowBodyNoComma : arrowBody;
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
}
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
if (type == "function") return cont(functiondef, maybeop);
if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
if (type == "quasi") { return pass(quasi, maybeop); }
return cont();
}
function maybeexpression(type) {
if (type.match(/[;\}\)\],]/)) return pass();
return pass(expression);
}
function maybeexpressionNoComma(type) {
if (type.match(/[;\}\)\],]/)) return pass();
return pass(expressionNoComma);
}
function maybeoperatorComma(type, value) {
if (type == ",") return cont(expression);
return maybeoperatorNoComma(type, value, false);
}
function maybeoperatorNoComma(type, value, noComma) {
var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
var expr = noComma == false ? expression : expressionNoComma;
if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
if (type == "operator") {
if (/\+\+|--/.test(value)) return cont(me);
if (value == "?") return cont(expression, expect(":"), expr);
return cont(expr);
}
if (type == "quasi") { return pass(quasi, me); }
if (type == ";") return;
if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
if (type == ".") return cont(property, me);
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
}
function quasi(type, value) {
if (type != "quasi") return pass();
if (value.slice(value.length - 2) != "${") return cont(quasi);
return cont(expression, continueQuasi);
}
function continueQuasi(type) {
if (type == "}") {
cx.marked = "string-2";
cx.state.tokenize = tokenQuasi;
return cont(quasi);
}
}
function arrowBody(type) {
findFatArrow(cx.stream, cx.state);
return pass(type == "{" ? statement : expression);
}
function arrowBodyNoComma(type) {
findFatArrow(cx.stream, cx.state);
return pass(type == "{" ? statement : expressionNoComma);
}
function maybelabel(type) {
if (type == ":") return cont(poplex, statement);
return pass(maybeoperatorComma, expect(";"), poplex);
}
function property(type) {
if (type == "variable") {cx.marked = "property"; return cont();}
}
function objprop(type, value) {
if (type == "variable" || cx.style == "keyword") {
cx.marked = "property";
if (value == "get" || value == "set") return cont(getterSetter);
return cont(afterprop);
} else if (type == "number" || type == "string") {
cx.marked = jsonldMode ? "property" : (cx.style + " property");
return cont(afterprop);
} else if (type == "jsonld-keyword") {
return cont(afterprop);
} else if (type == "[") {
return cont(expression, expect("]"), afterprop);
}
}
function getterSetter(type) {
if (type != "variable") return pass(afterprop);
cx.marked = "property";
return cont(functiondef);
}
function afterprop(type) {
if (type == ":") return cont(expressionNoComma);
if (type == "(") return pass(functiondef);
}
function commasep(what, end) {
function proceed(type) {
if (type == ",") {
var lex = cx.state.lexical;
if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
return cont(what, proceed);
}
if (type == end) return cont();
return cont(expect(end));
}
return function(type) {
if (type == end) return cont();
return pass(what, proceed);
};
}
function contCommasep(what, end, info) {
for (var i = 3; i < arguments.length; i++)
cx.cc.push(arguments[i]);
return cont(pushlex(end, info), commasep(what, end), poplex);
}
function block(type) {
if (type == "}") return cont();
return pass(statement, block);
}
function maybetype(type) {
if (isTS && type == ":") return cont(typedef);
}
function typedef(type) {
if (type == "variable"){cx.marked = "variable-3"; return cont();}
}
function vardef() {
return pass(pattern, maybetype, maybeAssign, vardefCont);
}
function pattern(type, value) {
if (type == "variable") { register(value); return cont(); }
if (type == "[") return contCommasep(pattern, "]");
if (type == "{") return contCommasep(proppattern, "}");
}
function proppattern(type, value) {
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
register(value);
return cont(maybeAssign);
}
if (type == "variable") cx.marked = "property";
return cont(expect(":"), pattern, maybeAssign);
}
function maybeAssign(_type, value) {
if (value == "=") return cont(expressionNoComma);
}
function vardefCont(type) {
if (type == ",") return cont(vardef);
}
function maybeelse(type, value) {
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
}
function forspec(type) {
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
}
function forspec1(type) {
if (type == "var") return cont(vardef, expect(";"), forspec2);
if (type == ";") return cont(forspec2);
if (type == "variable") return cont(formaybeinof);
return pass(expression, expect(";"), forspec2);
}
function formaybeinof(_type, value) {
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
return cont(maybeoperatorComma, forspec2);
}
function forspec2(type, value) {
if (type == ";") return cont(forspec3);
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
return pass(expression, expect(";"), forspec3);
}
function forspec3(type) {
if (type != ")") cont(expression);
}
function functiondef(type, value) {
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
if (type == "variable") {register(value); return cont(functiondef);}
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
}
function funarg(type) {
if (type == "spread") return cont(funarg);
return pass(pattern, maybetype);
}
function className(type, value) {
if (type == "variable") {register(value); return cont(classNameAfter);}
}
function classNameAfter(type, value) {
if (value == "extends") return cont(expression, classNameAfter);
if (type == "{") return cont(pushlex("}"), classBody, poplex);
}
function classBody(type, value) {
if (type == "variable" || cx.style == "keyword") {
cx.marked = "property";
if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
return cont(functiondef, classBody);
}
if (value == "*") {
cx.marked = "keyword";
return cont(classBody);
}
if (type == ";") return cont(classBody);
if (type == "}") return cont();
}
function classGetterSetter(type) {
if (type != "variable") return pass();
cx.marked = "property";
return cont();
}
function afterModule(type, value) {
if (type == "string") return cont(statement);
if (type == "variable") { register(value); return cont(maybeFrom); }
}
function afterExport(_type, value) {
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
return pass(statement);
}
function afterImport(type) {
if (type == "string") return cont();
return pass(importSpec, maybeFrom);
}
function importSpec(type, value) {
if (type == "{") return contCommasep(importSpec, "}");
if (type == "variable") register(value);
return cont();
}
function maybeFrom(_type, value) {
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
}
function arrayLiteral(type) {
if (type == "]") return cont();
return pass(expressionNoComma, maybeArrayComprehension);
}
function maybeArrayComprehension(type) {
if (type == "for") return pass(comprehension, expect("]"));
if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
return pass(commasep(expressionNoComma, "]"));
}
function comprehension(type) {
if (type == "for") return cont(forspec, comprehension);
if (type == "if") return cont(expression, comprehension);
}
// Interface
return {
startState: function(basecolumn) {
var state = {
tokenize: tokenBase,
lastType: "sof",
cc: [],
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
localVars: parserConfig.localVars,
context: parserConfig.localVars && {vars: parserConfig.localVars},
indented: 0
};
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
state.globalVars = parserConfig.globalVars;
return state;
},
token: function(stream, state) {
if (stream.sol()) {
if (!state.lexical.hasOwnProperty("align"))
state.lexical.align = false;
state.indented = stream.indentation();
findFatArrow(stream, state);
}
if (state.tokenize != tokenComment && stream.eatSpace()) return null;
var style = state.tokenize(stream, state);
if (type == "comment") return style;
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
return parseJS(state, style, type, content, stream);
},
indent: function(state, textAfter) {
if (state.tokenize == tokenComment) return CodeMirror.Pass;
if (state.tokenize != tokenBase) return 0;
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
// Kludge to prevent 'maybelse' from blocking lexical scope pops
if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
var c = state.cc[i];
if (c == poplex) lexical = lexical.prev;
else if (c != maybeelse) break;
}
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
lexical = lexical.prev;
var type = lexical.type, closing = firstChar == type;
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 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 == "," ? statementIndent || indentUnit : 0);
else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
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);
},
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
blockCommentStart: jsonMode ? null : "/*",
blockCommentEnd: jsonMode ? null : "*/",
lineComment: jsonMode ? null : "//",
fold: "brace",
helperType: jsonMode ? "json" : "javascript",
jsonldMode: jsonldMode,
jsonMode: jsonMode
};
});
CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
CodeMirror.defineMIME("text/javascript", "javascript");
CodeMirror.defineMIME("text/ecmascript", "javascript");
CodeMirror.defineMIME("application/javascript", "javascript");
CodeMirror.defineMIME("application/x-javascript", "javascript");
CodeMirror.defineMIME("application/ecmascript", "javascript");
CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
});

View File

@ -0,0 +1,384 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("xml", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
var Kludges = parserConfig.htmlMode ? {
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
'track': true, 'wbr': true, 'menuitem': true},
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
'th': true, 'tr': true},
contextGrabbers: {
'dd': {'dd': true, 'dt': true},
'dt': {'dd': true, 'dt': true},
'li': {'li': true},
'option': {'option': true, 'optgroup': true},
'optgroup': {'optgroup': true},
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
'rp': {'rp': true, 'rt': true},
'rt': {'rp': true, 'rt': true},
'tbody': {'tbody': true, 'tfoot': true},
'td': {'td': true, 'th': true},
'tfoot': {'tbody': true},
'th': {'td': true, 'th': true},
'thead': {'tbody': true, 'tfoot': true},
'tr': {'tr': true}
},
doNotIndent: {"pre": true},
allowUnquoted: true,
allowMissing: true,
caseFold: true
} : {
autoSelfClosers: {},
implicitlyClosed: {},
contextGrabbers: {},
doNotIndent: {},
allowUnquoted: false,
allowMissing: false,
caseFold: false
};
var alignCDATA = parserConfig.alignCDATA;
// Return variables for tokenizers
var type, setStyle;
function inText(stream, state) {
function chain(parser) {
state.tokenize = parser;
return parser(stream, state);
}
var ch = stream.next();
if (ch == "<") {
if (stream.eat("!")) {
if (stream.eat("[")) {
if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
else return null;
} else if (stream.match("--")) {
return chain(inBlock("comment", "-->"));
} else if (stream.match("DOCTYPE", true, true)) {
stream.eatWhile(/[\w\._\-]/);
return chain(doctype(1));
} else {
return null;
}
} else if (stream.eat("?")) {
stream.eatWhile(/[\w\._\-]/);
state.tokenize = inBlock("meta", "?>");
return "meta";
} else {
type = stream.eat("/") ? "closeTag" : "openTag";
state.tokenize = inTag;
return "tag bracket";
}
} else if (ch == "&") {
var ok;
if (stream.eat("#")) {
if (stream.eat("x")) {
ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
} else {
ok = stream.eatWhile(/[\d]/) && stream.eat(";");
}
} else {
ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
}
return ok ? "atom" : "error";
} else {
stream.eatWhile(/[^&<]/);
return null;
}
}
function inTag(stream, state) {
var ch = stream.next();
if (ch == ">" || (ch == "/" && stream.eat(">"))) {
state.tokenize = inText;
type = ch == ">" ? "endTag" : "selfcloseTag";
return "tag bracket";
} else if (ch == "=") {
type = "equals";
return null;
} else if (ch == "<") {
state.tokenize = inText;
state.state = baseState;
state.tagName = state.tagStart = null;
var next = state.tokenize(stream, state);
return next ? next + " tag error" : "tag error";
} else if (/[\'\"]/.test(ch)) {
state.tokenize = inAttribute(ch);
state.stringStartCol = stream.column();
return state.tokenize(stream, state);
} else {
stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
return "word";
}
}
function inAttribute(quote) {
var closure = function(stream, state) {
while (!stream.eol()) {
if (stream.next() == quote) {
state.tokenize = inTag;
break;
}
}
return "string";
};
closure.isInAttribute = true;
return closure;
}
function inBlock(style, terminator) {
return function(stream, state) {
while (!stream.eol()) {
if (stream.match(terminator)) {
state.tokenize = inText;
break;
}
stream.next();
}
return style;
};
}
function doctype(depth) {
return function(stream, state) {
var ch;
while ((ch = stream.next()) != null) {
if (ch == "<") {
state.tokenize = doctype(depth + 1);
return state.tokenize(stream, state);
} else if (ch == ">") {
if (depth == 1) {
state.tokenize = inText;
break;
} else {
state.tokenize = doctype(depth - 1);
return state.tokenize(stream, state);
}
}
}
return "meta";
};
}
function Context(state, tagName, startOfLine) {
this.prev = state.context;
this.tagName = tagName;
this.indent = state.indented;
this.startOfLine = startOfLine;
if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
this.noIndent = true;
}
function popContext(state) {
if (state.context) state.context = state.context.prev;
}
function maybePopContext(state, nextTagName) {
var parentTagName;
while (true) {
if (!state.context) {
return;
}
parentTagName = state.context.tagName;
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
return;
}
popContext(state);
}
}
function baseState(type, stream, state) {
if (type == "openTag") {
state.tagStart = stream.column();
return tagNameState;
} else if (type == "closeTag") {
return closeTagNameState;
} else {
return baseState;
}
}
function tagNameState(type, stream, state) {
if (type == "word") {
state.tagName = stream.current();
setStyle = "tag";
return attrState;
} else {
setStyle = "error";
return tagNameState;
}
}
function closeTagNameState(type, stream, state) {
if (type == "word") {
var tagName = stream.current();
if (state.context && state.context.tagName != tagName &&
Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
popContext(state);
if (state.context && state.context.tagName == tagName) {
setStyle = "tag";
return closeState;
} else {
setStyle = "tag error";
return closeStateErr;
}
} else {
setStyle = "error";
return closeStateErr;
}
}
function closeState(type, _stream, state) {
if (type != "endTag") {
setStyle = "error";
return closeState;
}
popContext(state);
return baseState;
}
function closeStateErr(type, stream, state) {
setStyle = "error";
return closeState(type, stream, state);
}
function attrState(type, _stream, state) {
if (type == "word") {
setStyle = "attribute";
return attrEqState;
} else if (type == "endTag" || type == "selfcloseTag") {
var tagName = state.tagName, tagStart = state.tagStart;
state.tagName = state.tagStart = null;
if (type == "selfcloseTag" ||
Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
maybePopContext(state, tagName);
} else {
maybePopContext(state, tagName);
state.context = new Context(state, tagName, tagStart == state.indented);
}
return baseState;
}
setStyle = "error";
return attrState;
}
function attrEqState(type, stream, state) {
if (type == "equals") return attrValueState;
if (!Kludges.allowMissing) setStyle = "error";
return attrState(type, stream, state);
}
function attrValueState(type, stream, state) {
if (type == "string") return attrContinuedState;
if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
setStyle = "error";
return attrState(type, stream, state);
}
function attrContinuedState(type, stream, state) {
if (type == "string") return attrContinuedState;
return attrState(type, stream, state);
}
return {
startState: function() {
return {tokenize: inText,
state: baseState,
indented: 0,
tagName: null, tagStart: null,
context: null};
},
token: function(stream, state) {
if (!state.tagName && stream.sol())
state.indented = stream.indentation();
if (stream.eatSpace()) return null;
type = null;
var style = state.tokenize(stream, state);
if ((style || type) && style != "comment") {
setStyle = null;
state.state = state.state(type || style, stream, state);
if (setStyle)
style = setStyle == "error" ? style + " error" : setStyle;
}
return style;
},
indent: function(state, textAfter, fullLine) {
var context = state.context;
// Indent multi-line strings (e.g. css).
if (state.tokenize.isInAttribute) {
if (state.tagStart == state.indented)
return state.stringStartCol + 1;
else
return state.indented + indentUnit;
}
if (context && context.noIndent) return CodeMirror.Pass;
if (state.tokenize != inTag && state.tokenize != inText)
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
// Indent the starts of attribute names.
if (state.tagName) {
if (multilineTagIndentPastTag)
return state.tagStart + state.tagName.length + 2;
else
return state.tagStart + indentUnit * multilineTagIndentFactor;
}
if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
if (tagAfter && tagAfter[1]) { // Closing tag spotted
while (context) {
if (context.tagName == tagAfter[2]) {
context = context.prev;
break;
} else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
context = context.prev;
} else {
break;
}
}
} else if (tagAfter) { // Opening tag spotted
while (context) {
var grabbers = Kludges.contextGrabbers[context.tagName];
if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
context = context.prev;
else
break;
}
}
while (context && !context.startOfLine)
context = context.prev;
if (context) return context.indent + indentUnit;
else return 0;
},
electricInput: /<\/[\s\w:]+>$/,
blockCommentStart: "<!--",
blockCommentEnd: "-->",
configuration: parserConfig.htmlMode ? "html" : "xml",
helperType: parserConfig.htmlMode ? "html" : "xml"
};
});
CodeMirror.defineMIME("text/xml", "xml");
CodeMirror.defineMIME("application/xml", "xml");
if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
});

View File

@ -88,11 +88,6 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png
text-decoration-style: dotted;
}
.cm-s-solarized .cm-strong { color: #eee; }
.cm-s-solarized .cm-tab:before {
content: "➤"; /*visualize tab character*/
color: #586e75;
position:absolute;
}
.cm-s-solarized .cm-error,
.cm-s-solarized .cm-invalidchar {
color: #586e75;

View File

@ -0,0 +1,61 @@
/** @license
* RequireJS plugin for loading JSON files
* - depends on Text plugin and it was HEAVILY "inspired" by it as well.
* Author: Miller Medeiros
* Version: 0.3.1 (2013/02/04)
* Released under the MIT license
*/
define(['text'], function(text){
var CACHE_BUST_QUERY_PARAM = 'bust',
CACHE_BUST_FLAG = '!bust',
jsonParse = (typeof JSON !== 'undefined' && typeof JSON.parse === 'function')? JSON.parse : function(val){
return eval('('+ val +')'); //quick and dirty
},
buildMap = {};
function cacheBust(url){
url = url.replace(CACHE_BUST_FLAG, '');
url += (url.indexOf('?') < 0)? '?' : '&';
return url + CACHE_BUST_QUERY_PARAM +'='+ Math.round(2147483647 * Math.random());
}
//API
return {
load : function(name, req, onLoad, config) {
if ( config.isBuild && (config.inlineJSON === false || name.indexOf(CACHE_BUST_QUERY_PARAM +'=') !== -1) ) {
//avoid inlining cache busted JSON or if inlineJSON:false
onLoad(null);
} else {
text.get(req.toUrl(name), function(data){
if (config.isBuild) {
buildMap[name] = data;
onLoad(data);
} else {
onLoad(jsonParse(data));
}
},
onLoad.error, {
accept: 'application/json'
}
);
}
},
normalize : function (name, normalize) {
//used normalize to avoid caching references to a "cache busted" request
return (name.indexOf(CACHE_BUST_FLAG) === -1)? name : cacheBust(name);
},
//write method based on RequireJS official text plugin by James Burke
//https://github.com/jrburke/requirejs/blob/master/text.js
write : function(pluginName, moduleName, write){
if(moduleName in buildMap){
var content = buildMap[moduleName];
write('define("'+ pluginName +'!'+ moduleName +'", function(){ return '+ content +';});\n');
}
}
};
});

View File

@ -0,0 +1 @@
define(["text"],function(text){function cacheBust(a){return a=a.replace(CACHE_BUST_FLAG,""),a+=a.indexOf("?")<0?"?":"&",a+CACHE_BUST_QUERY_PARAM+"="+Math.round(2147483647*Math.random())}var CACHE_BUST_QUERY_PARAM="bust",CACHE_BUST_FLAG="!bust",jsonParse="undefined"!=typeof JSON&&"function"==typeof JSON.parse?JSON.parse:function(val){return eval("("+val+")")},buildMap={};return{load:function(a,b,c,d){!d.isBuild||d.inlineJSON!==!1&&-1===a.indexOf(CACHE_BUST_QUERY_PARAM+"=")?text.get(b.toUrl(a),function(b){d.isBuild?(buildMap[a]=b,c(b)):c(jsonParse(b))},c.error,{accept:"application/json"}):c(null)},normalize:function(a,b){return-1===a.indexOf(CACHE_BUST_FLAG)?a:cacheBust(a)},write:function(a,b,c){if(b in buildMap){var d=buildMap[b];c('define("'+a+"!"+b+'", function(){ return '+d+";});\n")}}}});

View File

@ -0,0 +1,332 @@
/**
* @license RequireJS text 2.0.5 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/requirejs/text for details
*/
/*jslint regexp: true */
/*global require: false, XMLHttpRequest: false, ActiveXObject: false,
define: false, window: false, process: false, Packages: false,
java: false, location: false */
define(['module'], function (module) {
'use strict';
var text, fs,
progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
hasLocation = typeof location !== 'undefined' && location.href,
defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''),
defaultHostName = hasLocation && location.hostname,
defaultPort = hasLocation && (location.port || undefined),
buildMap = [],
masterConfig = (module.config && module.config()) || {};
text = {
version: '2.0.5',
strip: function (content) {
//Strips <?xml ...?> declarations so that external SVG and XML
//documents can be added to a document without worry. Also, if the string
//is an HTML document, only the part inside the body tag is returned.
if (content) {
content = content.replace(xmlRegExp, "");
var matches = content.match(bodyRegExp);
if (matches) {
content = matches[1];
}
} else {
content = "";
}
return content;
},
jsEscape: function (content) {
return content.replace(/(['\\])/g, '\\$1')
.replace(/[\f]/g, "\\f")
.replace(/[\b]/g, "\\b")
.replace(/[\n]/g, "\\n")
.replace(/[\t]/g, "\\t")
.replace(/[\r]/g, "\\r")
.replace(/[\u2028]/g, "\\u2028")
.replace(/[\u2029]/g, "\\u2029");
},
createXhr: masterConfig.createXhr || function () {
//Would love to dump the ActiveX crap in here. Need IE 6 to die first.
var xhr, i, progId;
if (typeof XMLHttpRequest !== "undefined") {
return new XMLHttpRequest();
} else if (typeof ActiveXObject !== "undefined") {
for (i = 0; i < 3; i += 1) {
progId = progIds[i];
try {
xhr = new ActiveXObject(progId);
} catch (e) {}
if (xhr) {
progIds = [progId]; // so faster next time
break;
}
}
}
return xhr;
},
/**
* Parses a resource name into its component parts. Resource names
* look like: module/name.ext!strip, where the !strip part is
* optional.
* @param {String} name the resource name
* @returns {Object} with properties "moduleName", "ext" and "strip"
* where strip is a boolean.
*/
parseName: function (name) {
var modName, ext, temp,
strip = false,
index = name.indexOf("."),
isRelative = name.indexOf('./') === 0 ||
name.indexOf('../') === 0;
if (index !== -1 && (!isRelative || index > 1)) {
modName = name.substring(0, index);
ext = name.substring(index + 1, name.length);
} else {
modName = name;
}
temp = ext || modName;
index = temp.indexOf("!");
if (index !== -1) {
//Pull off the strip arg.
strip = temp.substring(index + 1) === "strip";
temp = temp.substring(0, index);
if (ext) {
ext = temp;
} else {
modName = temp;
}
}
return {
moduleName: modName,
ext: ext,
strip: strip
};
},
xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/,
/**
* Is an URL on another domain. Only works for browser use, returns
* false in non-browser environments. Only used to know if an
* optimized .js version of a text resource should be loaded
* instead.
* @param {String} url
* @returns Boolean
*/
useXhr: function (url, protocol, hostname, port) {
var uProtocol, uHostName, uPort,
match = text.xdRegExp.exec(url);
if (!match) {
return true;
}
uProtocol = match[2];
uHostName = match[3];
uHostName = uHostName.split(':');
uPort = uHostName[1];
uHostName = uHostName[0];
return (!uProtocol || uProtocol === protocol) &&
(!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&
((!uPort && !uHostName) || uPort === port);
},
finishLoad: function (name, strip, content, onLoad) {
content = strip ? text.strip(content) : content;
if (masterConfig.isBuild) {
buildMap[name] = content;
}
onLoad(content);
},
load: function (name, req, onLoad, config) {
//Name has format: some.module.filext!strip
//The strip part is optional.
//if strip is present, then that means only get the string contents
//inside a body tag in an HTML string. For XML/SVG content it means
//removing the <?xml ...?> declarations so the content can be inserted
//into the current doc without problems.
// Do not bother with the work if a build and text will
// not be inlined.
if (config.isBuild && !config.inlineText) {
onLoad();
return;
}
masterConfig.isBuild = config.isBuild;
var parsed = text.parseName(name),
nonStripName = parsed.moduleName +
(parsed.ext ? '.' + parsed.ext : ''),
url = req.toUrl(nonStripName),
useXhr = (masterConfig.useXhr) ||
text.useXhr;
//Load the text. Use XHR if possible and in a browser.
if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {
text.get(url, function (content) {
text.finishLoad(name, parsed.strip, content, onLoad);
}, function (err) {
if (onLoad.error) {
onLoad.error(err);
}
});
} else {
//Need to fetch the resource across domains. Assume
//the resource has been optimized into a JS module. Fetch
//by the module name + extension, but do not include the
//!strip part to avoid file system issues.
req([nonStripName], function (content) {
text.finishLoad(parsed.moduleName + '.' + parsed.ext,
parsed.strip, content, onLoad);
});
}
},
write: function (pluginName, moduleName, write, config) {
if (buildMap.hasOwnProperty(moduleName)) {
var content = text.jsEscape(buildMap[moduleName]);
write.asModule(pluginName + "!" + moduleName,
"define(function () { return '" +
content +
"';});\n");
}
},
writeFile: function (pluginName, moduleName, req, write, config) {
var parsed = text.parseName(moduleName),
extPart = parsed.ext ? '.' + parsed.ext : '',
nonStripName = parsed.moduleName + extPart,
//Use a '.js' file name so that it indicates it is a
//script that can be loaded across domains.
fileName = req.toUrl(parsed.moduleName + extPart) + '.js';
//Leverage own load() method to load plugin value, but only
//write out values that do not have the strip argument,
//to avoid any potential issues with ! in file names.
text.load(nonStripName, req, function (value) {
//Use own write() method to construct full module value.
//But need to create shell that translates writeFile's
//write() to the right interface.
var textWrite = function (contents) {
return write(fileName, contents);
};
textWrite.asModule = function (moduleName, contents) {
return write.asModule(moduleName, fileName, contents);
};
text.write(pluginName, nonStripName, textWrite, config);
}, config);
}
};
if (masterConfig.env === 'node' || (!masterConfig.env &&
typeof process !== "undefined" &&
process.versions &&
!!process.versions.node)) {
//Using special require.nodeRequire, something added by r.js.
fs = require.nodeRequire('fs');
text.get = function (url, callback) {
var file = fs.readFileSync(url, 'utf8');
//Remove BOM (Byte Mark Order) from utf8 files if it is there.
if (file.indexOf('\uFEFF') === 0) {
file = file.substring(1);
}
callback(file);
};
} else if (masterConfig.env === 'xhr' || (!masterConfig.env &&
text.createXhr())) {
text.get = function (url, callback, errback, headers) {
var xhr = text.createXhr(), header;
xhr.open('GET', url, true);
//Allow plugins direct access to xhr headers
if (headers) {
for (header in headers) {
if (headers.hasOwnProperty(header)) {
xhr.setRequestHeader(header.toLowerCase(), headers[header]);
}
}
}
//Allow overrides specified in config
if (masterConfig.onXhr) {
masterConfig.onXhr(xhr, url);
}
xhr.onreadystatechange = function (evt) {
var status, err;
//Do not explicitly handle errors, those should be
//visible via console output in the browser.
if (xhr.readyState === 4) {
status = xhr.status;
if (status > 399 && status < 600) {
//An http 4xx or 5xx error. Signal an error.
err = new Error(url + ' HTTP status: ' + status);
err.xhr = xhr;
errback(err);
} else {
callback(xhr.responseText);
}
}
};
xhr.send(null);
};
} else if (masterConfig.env === 'rhino' || (!masterConfig.env &&
typeof Packages !== 'undefined' && typeof java !== 'undefined')) {
//Why Java, why is this so awkward?
text.get = function (url, callback) {
var stringBuffer, line,
encoding = "utf-8",
file = new java.io.File(url),
lineSeparator = java.lang.System.getProperty("line.separator"),
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
content = '';
try {
stringBuffer = new java.lang.StringBuffer();
line = input.readLine();
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
// http://www.unicode.org/faq/utf_bom.html
// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
if (line && line.length() && line.charAt(0) === 0xfeff) {
// Eat the BOM, since we've already found the encoding on this file,
// and we plan to concatenating this buffer with others; the BOM should
// only appear at the top of a file.
line = line.substring(1);
}
stringBuffer.append(line);
while ((line = input.readLine()) !== null) {
stringBuffer.append(lineSeparator);
stringBuffer.append(line);
}
//Make sure we return a JavaScript string and not a Java string.
content = String(stringBuffer.toString()); //String
} finally {
input.close();
}
callback(content);
};
}
return text;
});

View File

@ -0,0 +1 @@
define(["module"],function(a){"use strict";var b,c,d=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"],e=/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,f=/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,g="undefined"!=typeof location&&location.href,h=g&&location.protocol&&location.protocol.replace(/\:/,""),i=g&&location.hostname,j=g&&(location.port||void 0),k=[],l=a.config&&a.config()||{};return b={version:"2.0.5",strip:function(a){if(a){a=a.replace(e,"");var b=a.match(f);b&&(a=b[1])}else a="";return a},jsEscape:function(a){return a.replace(/(['\\])/g,"\\$1").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r").replace(/[\u2028]/g,"\\u2028").replace(/[\u2029]/g,"\\u2029")},createXhr:l.createXhr||function(){var a,b,c;if("undefined"!=typeof XMLHttpRequest)return new XMLHttpRequest;if("undefined"!=typeof ActiveXObject)for(b=0;3>b;b+=1){c=d[b];try{a=new ActiveXObject(c)}catch(e){}if(a){d=[c];break}}return a},parseName:function(a){var b,c,d,e=!1,f=a.indexOf("."),g=0===a.indexOf("./")||0===a.indexOf("../");return-1!==f&&(!g||f>1)?(b=a.substring(0,f),c=a.substring(f+1,a.length)):b=a,d=c||b,f=d.indexOf("!"),-1!==f&&(e="strip"===d.substring(f+1),d=d.substring(0,f),c?c=d:b=d),{moduleName:b,ext:c,strip:e}},xdRegExp:/^((\w+)\:)?\/\/([^\/\\]+)/,useXhr:function(a,c,d,e){var f,g,h,i=b.xdRegExp.exec(a);return i?(f=i[2],g=i[3],g=g.split(":"),h=g[1],g=g[0],!(f&&f!==c||g&&g.toLowerCase()!==d.toLowerCase()||(h||g)&&h!==e)):!0},finishLoad:function(a,c,d,e){d=c?b.strip(d):d,l.isBuild&&(k[a]=d),e(d)},load:function(a,c,d,e){if(e.isBuild&&!e.inlineText)return void d();l.isBuild=e.isBuild;var f=b.parseName(a),k=f.moduleName+(f.ext?"."+f.ext:""),m=c.toUrl(k),n=l.useXhr||b.useXhr;!g||n(m,h,i,j)?b.get(m,function(c){b.finishLoad(a,f.strip,c,d)},function(a){d.error&&d.error(a)}):c([k],function(a){b.finishLoad(f.moduleName+"."+f.ext,f.strip,a,d)})},write:function(a,c,d,e){if(k.hasOwnProperty(c)){var f=b.jsEscape(k[c]);d.asModule(a+"!"+c,"define(function () { return '"+f+"';});\n")}},writeFile:function(a,c,d,e,f){var g=b.parseName(c),h=g.ext?"."+g.ext:"",i=g.moduleName+h,j=d.toUrl(g.moduleName+h)+".js";b.load(i,d,function(c){var d=function(a){return e(j,a)};d.asModule=function(a,b){return e.asModule(a,j,b)},b.write(a,i,d,f)},f)}},"node"===l.env||!l.env&&"undefined"!=typeof process&&process.versions&&process.versions.node?(c=require.nodeRequire("fs"),b.get=function(a,b){var d=c.readFileSync(a,"utf8");0===d.indexOf("\ufeff")&&(d=d.substring(1)),b(d)}):"xhr"===l.env||!l.env&&b.createXhr()?b.get=function(a,c,d,e){var f,g=b.createXhr();if(g.open("GET",a,!0),e)for(f in e)e.hasOwnProperty(f)&&g.setRequestHeader(f.toLowerCase(),e[f]);l.onXhr&&l.onXhr(g,a),g.onreadystatechange=function(b){var e,f;4===g.readyState&&(e=g.status,e>399&&600>e?(f=new Error(a+" HTTP status: "+e),f.xhr=g,d(f)):c(g.responseText))},g.send(null)}:("rhino"===l.env||!l.env&&"undefined"!=typeof Packages&&"undefined"!=typeof java)&&(b.get=function(a,b){var c,d,e="utf-8",f=new java.io.File(a),g=java.lang.System.getProperty("line.separator"),h=new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(f),e)),i="";try{for(c=new java.lang.StringBuffer,d=h.readLine(),d&&d.length()&&65279===d.charAt(0)&&(d=d.substring(1)),c.append(d);null!==(d=h.readLine());)c.append(g),c.append(d);i=String(c.toString())}finally{h.close()}b(i)}),b});

File diff suppressed because one or more lines are too long

View File

@ -1,103 +0,0 @@
var reactTemplates = require('../src/reactTemplates');
var playgroundTemplate = require('./playground.rt.js');
var htmlMode = require('codemirror/mode/htmlmixed/htmlmixed');
var javascriptMode = require('codemirror/mode/javascript/javascript');
var xmlMode = require('codemirror/mode/xml/xml');
var cssMode = require('codemirror/mode/css/css');
var vbScriptMode = require('codemirror/mode/vbscript/vbscript');
var React = require('react/addons');
var _ = require('lodash');
var html = "<div>hello</div>";
var res = reactTemplates.convertTemplateToReact(html.trim());
console.log(res);
function emptyFunc() {
return null;
}
function generateTemplateFunction(html) {
try {
var code = reactTemplates.convertTemplateToReact(html.trim().replace(/\r/g,""));
var defineMap = {"react":React,"lodash":_};
var define = function (requirementsNames,content) {
var requirements = _.map(requirementsNames,function (reqName) {
return defineMap[reqName];
});
return content.apply(this,requirements);
};
var res = eval(code);
return res;
} catch (e) {
return emptyFunc
}
}
function generateRenderFunc(renderFunc) {
return function() {
var res = null;
try {
res = renderFunc.apply(this)
} catch (e) {
res = React.DOM.div.apply(this,[{style:{color:"red"}},"Exception:"+e.message]);
}
return React.DOM.div.apply(this, _.flatten([
{key:"result"},
res
]));
}
}
var z = {getInitialState: function() {return {name:"reactTemplates"}}};
var templateHTML = "<div>\n Have {_.filter(this.state.todos, {done:true}).length} todos done,\n and {_.filter(this.state.todos, {done:false}).length} not done\n <br/>\n <div rt-repeat=\"todo in this.state.todos\" key=\"{todo.key}\">\n <button onClick=\"(e)=>e.preventDefault(); this.remove(todo)\">x</button>\n <input type=\"checkbox\" checked=\"{todo.done}\" onChange=\"()=>this.toggleChecked(todoIndex)\"/>\n <span style=\"{todo.done ? {'text-decoration':'line-through'} : {} }\">{todo.value}</span>\n </div>\n <input key=\"myinput\" type=\"text\" onKeyDown=\"(e) => if (e.keyCode == 13) { this.add(); }\" valueLink=\"{this.linkState('edited')}\"/>\n <button onClick=\"(e)=>e.preventDefault(); this.add()\" >Add</button><br/>\n <button onClick=\"(e)=>e.preventDefault(); this.clearDone()\">Clear done</button>\n</div>";
var templateProps = "{\n mixins: [React.addons.LinkedStateMixin],\n getInitialState: function () {\n return {edited: '', todos: [], counter: 0};\n },\n add: function () {\n if (this.state.edited.trim().length === 0) {\n return;\n }\n var newTodo = {value: this.state.edited, done: false, key: this.state.counter};\n this.setState({todos: this.state.todos.concat(newTodo), edited: '', counter: this.state.counter + 1});\n },\n remove: function (todo) {\n this.setState({todos: _.reject(this.state.todos, todo)});\n },\n toggleChecked: function (index) {\n var todos = _.cloneDeep(this.state.todos);\n todos[index].done = !todos[index].done;\n this.setState({todos: todos});\n },\n clearDone: function () {\n this.setState({todos: _.filter(this.state.todos, {done: false})});\n }\n}";
var Playground = React.createClass({
displayName: 'Playground',
mixins: [React.addons.LinkedStateMixin],
updateSample: function (state) {
this.sampleFunc = generateTemplateFunction(state.templateHTML);
this.validHTML = this.sampleFunc !== emptyFunc;
this.sampleRender = generateRenderFunc(this.sampleFunc);
var classBase = {};
try {
this.validProps = true;
console.log(state.templateProps);
classBase = eval("("+state.templateProps+")");
if (!_.isObject(classBase)) {
throw "failed to eval";
}
} catch (e) {
classBase = {};
this.validProps = false;
}
classBase.render = this.sampleRender;
console.log(classBase);
this.sample = React.createFactory(React.createClass(classBase));
},
getInitialState: function () {
var currentState = {
templateHTML:templateHTML,
templateProps: templateProps
};
this.updateSample(currentState);
return currentState;
},
componentWillUpdate: function (nextProps,nextState) {
if (nextState.templateHTML !== this.state.templateHTML || nextState.templateProps !== this.state.templateProps) {
this.updateSample(nextState);
}
},
render: function () {
return playgroundTemplate.apply(this);
}
});
React.render(Playground(),document.getElementById('playground'));

View File

@ -0,0 +1,36 @@
<!--suppress CheckEmptyScriptTag -->
<rt-require dependency="./CodeMirrorEditor" as="CodeEditor"/>
<div class="playground">
<div class="fiddle-row">
<div class="code-area" id="area-rt">
<CodeEditor ref="editorRT" id="editor-rt" class="large-text-area"
value="{this.state.templateHTML}"
mode="html"
onChange="(e)=>this.setState({templateHTML:e.target.value})" />
</div>
<div class="code-area" id="area-code">
<CodeEditor ref="editorCode" id="editor-code" class="large-text-area"
value="{this.state.templateProps}"
mode="javascript"
onChange="(e)=>this.setState({templateProps:e.target.value})" />
</div>
</div>
<div class="fiddle-row">
<div class="code-area" id="area-generated">
<CodeEditor id="editor-generated" class="large-text-area"
ref="editorGenerated"
value="{this.templateSource}"
mode="javascript"
readOnly="{true}" />
</div>
<div class="code-area" id="area-result">
<!--<div id="result-container" class="result-area">-->
<div id="result-area" key="result-area" class="sample-view">
<form class="result-area-form" ref="mount" onSubmit="(e)=>e.preventDefault();">
<!--<this.sample key="sample">-->
<!--</this.sample>-->
</form>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,61 @@
define([
'react/addons',
'lodash',
'./CodeMirrorEditor'
], function (React, _, CodeEditor) {
'use strict';
function onChange1(e) {
this.setState({ templateHTML: e.target.value });
}
function onChange2(e) {
this.setState({ templateProps: e.target.value });
}
function onSubmit3(e) {
e.preventDefault();
}
return function () {
return React.createElement('div', { 'className': 'playground' }, React.createElement('div', { 'className': 'fiddle-row' }, React.createElement('div', {
'className': 'code-area',
'id': 'area-rt'
}, React.createElement(CodeEditor, {
'ref': 'editorRT',
'id': 'editor-rt',
'className': 'large-text-area',
'value': this.state.templateHTML,
'mode': 'html',
'onChange': onChange1.bind(this)
})), React.createElement('div', {
'className': 'code-area',
'id': 'area-code'
}, React.createElement(CodeEditor, {
'ref': 'editorCode',
'id': 'editor-code',
'className': 'large-text-area',
'value': this.state.templateProps,
'mode': 'javascript',
'onChange': onChange2.bind(this)
}))), React.createElement('div', { 'className': 'fiddle-row' }, React.createElement('div', {
'className': 'code-area',
'id': 'area-generated'
}, React.createElement(CodeEditor, {
'id': 'editor-generated',
'className': 'large-text-area',
'ref': 'editorGenerated',
'value': this.templateSource,
'mode': 'javascript',
'readOnly': true
})), React.createElement('div', {
'className': 'code-area',
'id': 'area-result'
} /* <div id="result-container" class="result-area"> */, React.createElement('div', {
'id': 'result-area',
'key': 'result-area',
'className': 'sample-view'
}, React.createElement('form', {
'className': 'result-area-form',
'ref': 'mount',
'onSubmit': onSubmit3.bind(this)
} /* <this.sample key="sample"> */
/* </this.sample> */)))));
};
});

View File

@ -1,20 +0,0 @@
.hidden {
display:none;
}
.large-text-area {
width:600px;
height:300px;
}
.code-area {
width:620px;
height:620px;
float:left;
}
.result-area {
width: 400px;
height: 600px;
float:left;
}

272
playground/playground.js Normal file
View File

@ -0,0 +1,272 @@
/*eslint-env browser*/
define(['react', 'react-dom', 'jquery', 'lodash', './playground-fiddle.rt', './playground.rt'], function (React, ReactDOM, $, _, pgFiddleTemplate, playgroundTemplate) {
'use strict';
//function emptyFunc() {
// return null;
//}
//function generateTemplateSource(html, editor, name) {
// var code = null;
// try {
// code = window.reactTemplates.convertTemplateToReact(html.trim().replace(/\r/g, ''), {modules: 'none', name: name});
// clearMessage(editor);
// } catch (e) {
// if (e.name === 'RTCodeError') {
// //index: -1 line: -1 message: "Document should have a root element" name: "RTCodeError"
// editor.annotate({line: e.line, message: e.message, index: e.index});
// } else {
// editor.annotate({line: 1, message: e.message});
// }
// //showMessage(editor, msg);
// console.log(e);
// }
// return code;
//}
function showMessage(editor, msg) {
if (editor && editor.showMessage) {
editor.annotate({line: 1, message: msg});
}
}
function clearMessage(editor) {
if (editor && editor.clearAnnotations) {
editor.clearAnnotations();
}
}
//function generateTemplateFunction(code) {
// try {
// var defineMap = {'react/addons': React, lodash: _};
// var define = function (requirementsNames, content) {
// var requirements = _.map(requirementsNames, function (reqName) {
// return defineMap[reqName];
// });
// return content.apply(this, requirements);
// };
// /*eslint no-eval:0*/
// var res = eval(code);
// return res;
// } catch (e) {
// console.log(e);
// return emptyFunc;
// }
//}
function generateRenderFunc(renderFunc) {
return function () {
var res = null;
try {
res = renderFunc.apply(this);
} catch (e) {
res = React.DOM.div.apply(this, [{style: {color: 'red'}}, 'Exception:' + e.message]);
}
return React.DOM.div.apply(this, _.flatten([
{key: 'result'},
res
]));
};
}
var templateHTML = '<div></div>';
var templateProps = 'var template = React.createClass({\n' +
' render: templateRT\n' +
'});';
//var selfCleaningTimeout = {
// componentDidUpdate: function() {
// clearTimeout(this.timeoutID);
// },
// setTimeout: function() {
// console.log('setTimeout');
// clearTimeout(this.timeoutID);
// this.timeoutID = setTimeout.apply(null, arguments);
// }
//};
var Playground = React.createClass({
displayName: 'Playground',
mixins: [React.addons.LinkedStateMixin],
propTypes: {
direction: React.PropTypes.oneOf(['horizontal', 'vertical']),
codeVisible: React.PropTypes.bool,
fiddle: React.PropTypes.bool,
templateHTML: React.PropTypes.string,
templateProps: React.PropTypes.string,
name: React.PropTypes.string
},
templateSource: '',
validHTML: true,
validProps: true,
setTimeout: function () {
//console.log('setTimeout');
clearTimeout(this.timeoutID);
this.timeoutID = setTimeout.apply(null, arguments);
},
getDefaultProps: function () {
return {
direction: 'horizontal', //vertical
codeVisible: true,
fiddle: false
};
},
getLayoutClass: function () {
return (this.props.direction === 'horizontal' && 'horizontal') || 'vertical'; //eslint-disable-line no-extra-parens
},
//executeCode: function() {
// var mountNode = this.refs.mount.getDOMNode();
//
// try {
// React.unmountComponentAtNode(mountNode);
// } catch (e) { }
//
// try {
// var compiledCode = this.compileCode();
// if (this.props.renderCode) {
// React.render(
// React.createElement(CodeMirrorEditor, {codeText: compiledCode, readOnly: true}),
// mountNode
// );
// } else {
// eval(compiledCode);
// }
// } catch (err) {
// this.setTimeout(function() {
// React.render(
// React.createElement('div', {className: 'playgroundError'}, err.toString()),
// mountNode
// );
// }, 500);
// }
//},
getTabs: function () {
if (this.props.codeVisible) {
return [['templateHTML', 'Template'], ['templateProps', 'Class'], ['templateSource', 'Generated code']];
}
return [['templateHTML', 'Template'], ['templateSource', 'Generated code']];
},
updateSample: function (state) {
//try {
// React.unmountComponentAtNode(mountNode);
//} catch (e) { }
this.generateCode(state);
//this.sampleFunc = generateTemplateFunction(this.templateSource);
//this.validHTML = this.sampleFunc !== emptyFunc;
this.validHTML = true;
this.sampleRender = generateRenderFunc(this.sampleFunc);
var editor;
try {
this.validProps = true;
//console.log(state.templateProps);
this.sample = eval('(function () {' + this.templateSource + '\n' + state.templateProps + '\n return React.createElement(' + state.name + ');})()'); //eslint-disable-line no-eval
clearMessage(this.refs.editorCode);
} catch (e) {
this.validProps = false;
this.sample = null;
editor = this.refs.editorCode;
this.showError(e, editor);
}
//classBase.render = this.sampleRender;
//this.sample = React.createFactory(React.createClass(classBase));
},
showError: function (e, editor) {
var mountNode = this.refs.mount;
this.setTimeout(function () {
showMessage(editor, e.message);
ReactDOM.render(
React.createElement('div', {className: 'playground-error'}, e.toString()),
mountNode
);
}, 500);
},
showErrorAnnotation: function (annot, editor) {
var mountNode = this.refs.mount;
this.setTimeout(function () {
editor.annotate(annot);
ReactDOM.render(
React.createElement('div', {className: 'playground-error'}, annot.message),
mountNode
);
}, 500);
},
clear: function () {
var currentState = {
templateHTML: templateHTML,
templateProps: templateProps
};
//this.updateSample(currentState);
this.setState(currentState);
},
generateCode: function (state) {
var html = state.templateHTML;
var editor = this.refs.editorRT;
var name = window.reactTemplates.normalizeName(state.name) + 'RT';
var code = null;
try {
code = window.reactTemplates.convertTemplateToReact(html.trim().replace(/\r/g, ''), {modules: 'none', name: name});
clearMessage(editor);
} catch (e) {
var annot = e.name === 'RTCodeError' ? {line: e.line, message: e.message, index: e.index} : {line: 1, message: e.message};
this.showErrorAnnotation(annot, editor);
//showMessage(editor, msg);
console.log(e);
}
this.templateSource = code;
},
getInitialState: function () {
var currentState = {
templateHTML: this.props.templateHTML || templateHTML,
templateProps: this.props.templateProps || templateProps,
name: this.props.name || 'template',
currentTab: 'templateHTML'
};
//this.updateSample(currentState);
return currentState;
},
componentDidMount: function () {
if (this.props.fiddle) {
window.addEventListener('resize', this.calcSize);
this.calcSize();
}
this.updateSample(this.state);
this.renderSample();
},
renderSample: function () {
var mountNode = this.refs.mount;
if (this.sample) {
ReactDOM.render(this.sample, mountNode);
}
},
componentDidUpdate: function () {
this.renderSample();
},
componentWillUnmount: function () {
window.removeEventListener('resize', this.calcSize);
},
calcSize: function () {
var contentHeight = $(window).height() - $('#header').height();
var height = contentHeight / 2 - 10;
$('.code-area').each(function (/*i, k*/) {
$(this).height(height);
//console.log($(this).height());
});
this.refs.editorCode.editor.refresh();
this.refs.editorRT.editor.refresh();
this.refs.editorGenerated.editor.refresh();
},
componentWillUpdate: function (nextProps, nextState) {
if (nextState.templateHTML !== this.state.templateHTML || nextState.templateProps !== this.state.templateProps) {
this.updateSample(nextState);
}
},
render: function () {
this.generateCode(this.state);
var template = this.props.fiddle ? pgFiddleTemplate : playgroundTemplate;
return template.apply(this);
}
});
return Playground;
});

View File

@ -1,30 +1,45 @@
<!DOCTYPE rt CodeEditor="react-code-mirror">
<div>
<div class="code-area">
<form>
<CodeEditor class="large-text-area" style="border: {this.validHTML? '1px solid black':'2px solid red'};"
value="{this.state.templateHTML}"
mode="htmlmixed"
smartIndent="{true}"
lineNumbers="{true}"
onChange="(evt) => this.setState({'templateHTML':evt.target.value})"
/>
<br/>
<CodeEditor class="large-text-area" style="border: {this.validProps? '1px solid black':'2px solid red'};"
value="{this.state.templateProps}"
mode="javascript"
theme="solarized"
smartIndent="{true}"
lineNumbers="{true}"
onChange="(evt) => this.setState({'templateProps':evt.target.value})"
/>
</form>
</div>
<div class="result-area">
<this.sample>
</this.sample>
<!--<rt-require dependency="./aceEditor" as="CodeEditor"/>-->
<!--suppress CheckEmptyScriptTag -->
<rt-require dependency="./CodeMirrorEditor" as="CodeEditor"/>
<div class="playground">
<div id="{this.props.id}-myTab" class="code-area {this.getLayoutClass()}">
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li rt-repeat="tab in this.getTabs()" role="presentation" key="tab{tabIndex}"
rt-class="{active:this.state.currentTab === tab[0]}"
onClick="(evt)=> evt.preventDefault();this.setState({'currentTab':tab[0]});">
<a aria-controls="{tab[1]}">{tab[1]}</a>
</li>
</ul>
<!-- Tab panes -->
<div>
<div rt-if="this.state.currentTab === 'templateHTML'" key="editorRT" class="tab-pane active" >
<CodeEditor ref="editorRT" class="large-text-area" style="border: {this.validHTML? '':'2px solid red'};"
value="{this.state.templateHTML}"
mode="html"
onChange="(evt) => this.setState({templateHTML:evt.target.value})" />
</div>
<div rt-if="this.state.currentTab === 'templateProps'" key="editorCode" class="tab-pane active">
<CodeEditor ref="editorCode" class="large-text-area" style="border: {this.validProps? '':'2px solid red'};"
value="{this.state.templateProps}"
mode="javascript"
onChange="(evt) => this.setState({templateProps:evt.target.value})" />
</div>
<div rt-if="this.state.currentTab === 'templateSource'" key="templateSource" class="tab-pane active">
<CodeEditor class="large-text-area"
value="{this.templateSource}"
mode="javascript"
readOnly="{true}" />
</div>
</div>
</div>
<div key="result-area" class="result-area {this.getLayoutClass()}">
<span class="preview-title">{'\u00A0'}</span>
<form ref="mount" class="sample-view" onSubmit="(e) => e.preventDefault();">
<!--<this.sample key="sample">-->
<!--</this.sample>-->
</form>
</div>
<br style="clear:both">
</div>

View File

@ -1,30 +1,81 @@
var React = require('react');
var _ = require('lodash');
var CodeEditor = require('react-code-mirror');
'use strict';
function onChange1(evt) {
this.setState({ 'templateHTML': evt.target.value });
}
function onChange2(evt) {
this.setState({ 'templateProps': evt.target.value });
}
module.exports = function () {
return React.DOM.div({}, React.DOM.div({ 'className': 'code-area' }, React.DOM.form({}, CodeEditor({
'className': 'large-text-area',
'style': { border: this.validHTML ? '1px solid black' : '2px solid red' },
'value': this.state.templateHTML,
'mode': 'htmlmixed',
'smartIndent': true,
'lineNumbers': true,
'onChange': onChange1.bind(this)
}), React.DOM.br({}), CodeEditor({
'className': 'large-text-area',
'style': { border: this.validProps ? '1px solid black' : '2px solid red' },
'value': this.state.templateProps,
'mode': 'javascript',
'theme': 'solarized',
'smartIndent': true,
'lineNumbers': true,
'onChange': onChange2.bind(this)
}))), React.DOM.div({ 'className': 'result-area' }, this.sample({})));
};
define([
'react/addons',
'lodash',
'./CodeMirrorEditor'
], function (React, _, CodeEditor) {
'use strict';
function onClick1(tab, tabIndex, evt) {
evt.preventDefault();
this.setState({ 'currentTab': tab[0] });
}
function repeatTab2(tab, tabIndex) {
return React.createElement('li', {
'role': 'presentation',
'key': 'tab' + tabIndex,
'className': _({ active: this.state.currentTab === tab[0] }).transform(function (res, value, key) {
if (value) {
res.push(key);
}
}, []).join(' '),
'onClick': onClick1.bind(this, tab, tabIndex)
}, React.createElement('a', { 'aria-controls': tab[1] }, tab[1]));
}
function onChange3(evt) {
this.setState({ templateHTML: evt.target.value });
}
function onChange4(evt) {
this.setState({ templateProps: evt.target.value });
}
function onSubmit5(e) {
e.preventDefault();
}
return function () {
return React.createElement('div', { 'className': 'playground' }, React.createElement('div', {
'id': this.props.id + '-myTab',
'className': 'code-area ' + this.getLayoutClass()
} /* Nav tabs */, React.createElement.apply(this, [
'ul',
{
'className': 'nav nav-tabs',
'role': 'tablist'
},
_.map(this.getTabs(), repeatTab2.bind(this))
]) /* Tab panes */, React.createElement('div', {}, this.state.currentTab === 'templateHTML' ? React.createElement('div', {
'key': 'editorRT',
'className': 'tab-pane active'
}, React.createElement(CodeEditor, {
'ref': 'editorRT',
'className': 'large-text-area',
'style': { border: this.validHTML ? '' : '2px solid red' },
'value': this.state.templateHTML,
'mode': 'html',
'onChange': onChange3.bind(this)
})) : null, this.state.currentTab === 'templateProps' ? React.createElement('div', {
'key': 'editorCode',
'className': 'tab-pane active'
}, React.createElement(CodeEditor, {
'ref': 'editorCode',
'className': 'large-text-area',
'style': { border: this.validProps ? '' : '2px solid red' },
'value': this.state.templateProps,
'mode': 'javascript',
'onChange': onChange4.bind(this)
})) : null, this.state.currentTab === 'templateSource' ? React.createElement('div', {
'key': 'templateSource',
'className': 'tab-pane active'
}, React.createElement(CodeEditor, {
'className': 'large-text-area',
'value': this.templateSource,
'mode': 'javascript',
'readOnly': true
})) : null)), React.createElement('div', {
'key': 'result-area',
'className': 'result-area ' + this.getLayoutClass()
}, React.createElement('span', { 'className': 'preview-title' }, '\xA0'), React.createElement('form', {
'ref': 'mount',
'className': 'sample-view',
'onSubmit': onSubmit5.bind(this)
} /* <this.sample key="sample"> */
/* </this.sample> */)), React.createElement('br', { 'style': { clear: 'both' } }));
};
});

10
playground/rt-main.js Normal file
View File

@ -0,0 +1,10 @@
/*eslint strict:0*/
'use strict';
/*eslint-env browser*/
/*var _ = */require('lodash');
var reactTemplates = require('../dist/reactTemplates');
window.reactTemplates = reactTemplates;

View File

@ -0,0 +1,3 @@
var <%= name %> = React.createClass({
render: <%= name %>RT
});

View File

@ -0,0 +1 @@
<h2>Hello world</h2>

View File

@ -0,0 +1,9 @@
var <%= name %> = React.createClass({
getInitialState: function () {
return {open: false};
},
toggle: function() {
this.setState({open: !this.state.open});
},
render: <%= name %>RT
});

View File

@ -0,0 +1,7 @@
<div>
<h4 style="cursor:pointer" onClick="()=>this.toggle()">
Click to {this.state.open ? 'close' : 'open'}
</h4>
<p rt-if="this.state.open">This is my paragraph. It opens and
closes</p>
</div>

View File

@ -0,0 +1,5 @@
<rt-import name="myComp" from="comps" />
<rt-import name="*" as="utils" from="utils/utils" />
<div>
<myComp customProp="{utils.doSomething()}">myComp is just a regular tag</myComp>
</div>

View File

@ -0,0 +1,16 @@
var <%= name %> = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return { key: 'color', val: 'blue' };
},
getProps: function() {
var ret = { style: {
color: 'black',
backgroundColor: 'white',
borderColor: 'black'
}};
ret.style[this.state.key] = this.state.val;
return ret;
},
render: <%= name %>RT
});

View File

@ -0,0 +1,16 @@
<div>
Style:
<select valueLink="{this.linkState('key')}">
<option value="color">Color</option>
<option value="backgroundColor">Background color</option>
<option value="borderColor">Border color</option>
</select><br/>
Value:
<select valueLink="{this.linkState('val')}">
<option value="blue">Blue</option>
<option value="red">Red</option>
<option value="yellow">Yellow</option>
</select><br/><br/>
<div style="padding:5px;text-align:center;border:1px solid"
rt-props="this.getProps()">Sample</div>
</div>

View File

@ -0,0 +1,8 @@
var <%= name %> = React.createClass({
getInitialState: function () {
return {
items: ['One', 'Two', 'Three']
};
},
render: <%= name %>RT
});

View File

@ -0,0 +1,5 @@
<div>
<ul>
<li rt-repeat="item in this.state.items">{item}</li>
</ul>
</div>

View File

@ -0,0 +1,5 @@
<rt-require dependency="comps/myComp" as="myComp"/>
<rt-require dependency="utils/utils" as="utils"/>
<div>
<myComp customProp="{utils.doSomething()}">myComp is just a regular tag</myComp>
</div>

View File

@ -0,0 +1,31 @@
var <%= name %> = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function () {
return {edited: '', todos: [], counter: 0};
},
add: function () {
if (this.state.edited.trim().length === 0) {
return;
}
var newTodo = {value: this.state.edited, done: false, key: this.state.counter};
this.setState({todos: this.state.todos.concat(newTodo), edited: '', counter: this.state.counter + 1});
},
remove: function (todo) {
this.setState({todos: _.reject(this.state.todos, todo)});
},
toggleChecked: function (index) {
var todos = _.cloneDeep(this.state.todos);
todos[index].done = !todos[index].done;
this.setState({todos: todos});
},
clearDone: function () {
this.setState({todos: this.getPending()});
},
getDone: function () {
return _.filter(this.state.todos, {done: true});
},
getPending: function () {
return _.filter(this.state.todos, {done: false});
},
render: <%= name %>RT
});

View File

@ -0,0 +1,21 @@
<div>
<strong>{this.getDone().length}</strong>
done,
<strong>{this.getPending().length}</strong>
pending
<br/>
<div rt-repeat="todo in this.state.todos" key="{todo.key}">
<img src="img/samples/delete.png"
onClick="()=>this.remove(todo)"
title="Remove Todo"
style="cursor:pointer"/>
<input type="checkbox" checked="{todo.done}"
onChange="()=>this.toggleChecked(todoIndex)"/>
<span style="text-decoration: {todo.done ? 'line-through': 'none'}">{todo.value}</span>
</div>
<input key="myinput" style="width:130px" type="text"
onKeyDown="(e) => if (e.keyCode == 13) { e.preventDefault(); this.add(); }"
valueLink="{this.linkState('edited')}"/>
<button onClick="()=>this.add()">Add</button><br/>
<button onClick="()=>this.clearDone()">Clear done</button>
</div>

View File

@ -0,0 +1,24 @@
{
mixins: [React.addons.LinkedStateMixin],
getInitialState: function () {
return {edited: '', todos: [], counter: 0};
},
add: function () {
if (this.state.edited.trim().length === 0) {
return;
}
var newTodo = {value: this.state.edited, done: false, key: this.state.counter};
this.setState({todos: this.state.todos.concat(newTodo), edited: '', counter: this.state.counter + 1});
},
remove: function (todo) {
this.setState({todos: _.reject(this.state.todos, todo)});
},
toggleChecked: function (index) {
var todos = _.cloneDeep(this.state.todos);
todos[index].done = !todos[index].done;
this.setState({todos: todos});
},
clearDone: function () {
this.setState({todos: _.filter(this.state.todos, {done: false})});
}
}

View File

@ -0,0 +1,13 @@
<div>
Have {_.filter(this.state.todos, {done:true}).length} todos done,
and {_.filter(this.state.todos, {done:false}).length} not done
<br/>
<div rt-repeat="todo in this.state.todos" key="{todo.key}">
<button onClick="()=>this.remove(todo)">x</button>
<input type="checkbox" checked="{todo.done}" onChange="()=>this.toggleChecked(todoIndex)"/>
<span style="text-decoration: {todo.done ? 'line-through': 'none'}">{todo.value}</span>
</div>
<input key="myinput" type="text" onKeyDown="(e) => if (e.keyCode == 13) { e.preventDefault(); this.add(); }" valueLink="{this.linkState('edited')}"/>
<button onClick="()=>this.add()">Add</button><br/>
<button onClick="()=>this.clearDone()">Clear done</button>
</div>

View File

@ -0,0 +1,34 @@
var <%= name %> = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
this.cityIds = [5391959,293397,2643743];
this.fetchWeather();
return { loading: true, cityToAdd: '', info: [] };
},
addCity: function() {
if (this.state.cityToAdd.trim() == '') {
return;
}
this.setState({ loading: true, cityToAdd: '' });
$.get('http://api.openweathermap.org/data/2.5/weather?q=' + this.state.cityToAdd, this.findCityCallback);
},
findCityCallback: function(result) {
if (result.id && !_.contains(this.cityIds, result.id)) {
this.cityIds.unshift(result.id);
this.fetchWeather();
} else {
this.setState({ loading: false });
}
},
refresh: function() {
this.setState({ loading:true });
this.fetchWeather();
},
fetchWeather: function() {
$.get('http://api.openweathermap.org/data/2.5/group?id=' + this.cityIds.join(',') + '&units=metric', this.fetchWeatherCallback);
},
fetchWeatherCallback: function(result) {
this.setState({ loading:false, info: result.list });
},
render: <%= name %>RT
});

View File

@ -0,0 +1,19 @@
<div>
<h4>Cities weather report</h4>
<input placeholder="Type a city to add"
style="width:130px"
valueLink="{this.linkState('cityToAdd')}"
onKeyDown="(e)=>if (e.keyCode === 13) { e.preventDefault(); this.addCity(); }"/>
<button onClick="{this.addCity}">Add</button>
<div key="preloader" rt-if="this.state.loading">
-- Loading --
</div>
<div rt-repeat="city in this.state.info" key="{city.id}">
{cityIndex+1})
<img rt-repeat="weather in city.weather"
src="http://openweathermap.org/img/w/{weather.icon}.png"
title="{weather.description}"/>
<span style="white-space:nowrap">{city.name}, {city.sys.country}</span>
</div>
<button onClick="{this.refresh}">Refresh</button>
</div>

Some files were not shown because too many files have changed in this diff Show More