move back to master

This commit is contained in:
ido 2017-06-29 10:47:09 +03:00
parent 9a475475ca
commit 87ed2032fe
270 changed files with 81065 additions and 3 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

27
.eslintignore Normal file
View File

@ -0,0 +1,27 @@
node_modules/**
bower_components/**
**/*.rt.js
**/*.json.js
playground/**/*.rt.js
playground/dist/**
playground/libs/**
playground2/**
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

30
.eslintrc Normal file
View File

@ -0,0 +1,30 @@
{
"extends": ["wix-editor", "wix-editor/node", "plugin:lodash/recommended"],
"plugins": ["lodash", "wix-editor"],
"rules": {
"semi": [2, "never"],
"func-style": [2, "declaration", {"allowArrowFunctions": true}],
"prefer-spread": 0,
"prefer-template": 0,
"consistent-return": 0,
"no-restricted-syntax": [2, "WithStatement", "ContinueStatement", "ForStatement"],
"no-negated-condition": 1,
"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,
"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
}
}

9
.gitignore vendored
View File

@ -16,7 +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

25
.npmignore Normal file
View File

@ -0,0 +1,25 @@
### Operating systems ###
.DS_Store
.AppleDouble
.LSOverride
._*
.Spotlight-V100
.Trashes
### Regular dev ###
node_modules
npm-debug.log
.idea
*.iml
### bower ###
/bower_components/*
### 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'])
}

22
LICENSE Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2014 Wix.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

674
README.md
View File

@ -1,5 +1,673 @@
# react-templates
[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[![Coverage Status][coveralls-image]][coveralls-url]
Branch `master` is not in use - do not use it!
# React Templates
Moved to the default [gh-pages branch](https://github.com/wix/react-templates).
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 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.
## 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
* 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)
* [rt-virtual](#rt-virtual)
* [styles](#styles)
* [event handlers](#event-handlers)
## 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
```shell
rt [file.rt|dir]* [options]
```
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
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 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
<a href="{this.state.linkRef}">{this.state.linkText}</a>
```
###### Compiled:
```javascript
define([
'react',
'lodash'
], function (React, _) {
'use strict';
return function () {
return React.DOM.a({ 'href': this.state.linkRef }, this.state.linkText);
};
});
```
## rt-if
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:
```html
<div rt-if="this.state.resultCode === 200">Success!</div>
```
###### Compiled:
```javascript
define([
'react',
'lodash'
], function (React, _) {
'use strict';
return function () {
return this.state.resultCode === 200 ? React.DOM.div({}, 'Success!') : null;
};
});
```
## rt-repeat
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>
```
###### Compiled:
```javascript
define([
'react',
'lodash'
], function (React, _) {
'use strict';
function repeatMyNum1(myNum, myNumIndex) {
return React.DOM.div({}, myNumIndex + '. ' + myNum);
}
return function () {
return _.map(this.getMyNumbers(), repeatMyNum1.bind(this));
};
});
```
## 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>
</rt-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 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
<div rt-repeat="rpt in array">
<div rt-scope="')' as separator; rpt.val as val">{rptIndex}{separator} {val}</div>
<div>'rpt' exists here, but not 'separator' and 'val'</div>
</div>
```
###### Compiled:
```javascript
define([
'react',
'lodash'
], function (React, _) {
'use strict';
function scopeSeparatorVal1(rpt, rptIndex, separator, val) {
return React.DOM.div({}, rptIndex + separator + ' ' + val);
}
function repeatRpt2(rpt, rptIndex) {
return React.DOM.div({}, scopeSeparatorVal1.apply(this, [
rpt,
rptIndex,
')',
rpt.val
]), React.DOM.div({}, '\'rpt\' exists here, but not \'separator\' and \'val\''));
}
return function () {
return _.map(array, repeatRpt2.bind(this));
};
});
```
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
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
<div rt-scope="{blue: true, selected: this.isSelected()} as classes">
These are logically equivalent
<div rt-class="classes">Reference</div>
<div rt-class="{blue: true, selected: this.isSelected()}">Inline</div>
<div class="blue{this.isSelected() ? ' selected' : ''}">Using the class attribute</div>
</div>
```
###### Compiled:
```javascript
define([
'react',
'lodash'
], function (React, _) {
'use strict';
function scopeClasses1(classes) {
return React.DOM.div({}, 'These are logically equivalent', React.DOM.div({ 'className': React.addons.classSet(classes) }, 'Reference'), React.DOM.div({
'className': React.addons.classSet({
blue: true,
selected: this.isSelected()
})
}, 'Inline'), React.DOM.div({ 'className': 'blue' + this.isSelected() ? ' selected' : '' }, 'Using the class attribute'));
}
return function () {
return scopeClasses1.apply(this, [{
blue: true,
selected: this.isSelected()
}]);
};
});
```
## 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
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
<div>
These are really equivalent
<div style="color:white; line-height:{this.state.lineHeight}px">Inline</div>
<div style="{{'color': 'white', 'lineHeight': this.state.lineHeight + 'px'}}">Inline</div>
</div>
```
###### Compiled:
```javascript
define([
'react',
'lodash'
], function (React, _) {
'use strict';
return function () {
return React.DOM.div({}, 'These are really equivalent', React.DOM.div({
'style': {
color: 'white',
lineHeight: this.state.lineHeight + 'px'
}
}, 'Inline'), React.DOM.div({
'style': {
'color': 'white',
'lineHeight': this.state.lineHeight + 'px'
}
}, 'Inline'));
};
});
```
## 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 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
<div rt-repeat="item in items">
<div onClick="()=>this.itemSelected(item)" onMouseDown="{this.mouseDownHandler}">
</div>
```
###### Compiled:
```javascript
define([
'react',
'lodash'
], function (React, _) {
'use strict';
function onClick1(item, itemIndex) {
this.itemSelected(item);
}
function repeatItem2(item, itemIndex) {
return React.DOM.div({}, React.DOM.div({
'onClick': onClick1.bind(this, item, itemIndex),
'onMouseDown': this.mouseDownHandler
}));
}
return function () {
return _.map(items, repeatItem2.bind(this));
};
});
```
## 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"/>
```
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
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',
'module-name',
'module-name',
'module-name',
'module-name'
], function (React, _, $2, $3, alias3, $5) {
'use strict';
var member = $2.member;
var alias2 = $3.member;
var alias4 = $5.default;
return function () {
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

7
bin/rt.js Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env node
'use strict'
const cli = require('../dist/cli') //src
// console.log(process.argv);
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

97
index.html Normal file
View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<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 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="//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>

82
package.json Normal file
View File

@ -0,0 +1,82 @@
{
"name": "react-templates",
"version": "0.6.1",
"description": "Light weight templates for react -> write html get valid react code",
"main": "./dist/cli.js",
"bin": {
"rt": "./bin/rt.js"
},
"scripts": {
"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",
"url": "git://github.com/wix/react-templates.git"
},
"author": "Avi Marcus",
"license": "MIT",
"bugs": {
"url": "https://github.com/wix/react-templates/issues"
},
"homepage": "https://github.com/wix/react-templates",
"dependencies": {
"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": {
"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

@ -0,0 +1,318 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
}
.CodeMirror-scroll {
/* Set scrolling behaviour here */
overflow: auto;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror div.CodeMirror-cursor {
border-left: 1px solid black;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-animate-fat-cursor {
width: auto;
border: 0;
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
}
@-moz-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
@-webkit-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
@keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
/* Can style cursor different in overwrite (non-insert) mode */
div.CodeMirror-overwrite div.CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-ruler {
border-left: 1px solid #ccc;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
line-height: 1;
position: relative;
overflow: hidden;
background: white;
color: black;
}
.CodeMirror-scroll {
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-sizer {
position: relative;
border-right: 30px solid transparent;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
padding-bottom: 30px;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
-moz-box-sizing: content-box;
box-sizing: content-box;
padding-bottom: 30px;
margin-bottom: -32px;
display: inline-block;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
height: 100%;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
overflow: auto;
}
.CodeMirror-widget {}
.CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor {
position: absolute;
border-right: none;
width: 0;
}
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* 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

@ -0,0 +1,165 @@
/*
Solarized theme for code-mirror
http://ethanschoonover.com/solarized
*/
/*
Solarized color pallet
http://ethanschoonover.com/solarized/img/solarized-palette.png
*/
.solarized.base03 { color: #002b36; }
.solarized.base02 { color: #073642; }
.solarized.base01 { color: #586e75; }
.solarized.base00 { color: #657b83; }
.solarized.base0 { color: #839496; }
.solarized.base1 { color: #93a1a1; }
.solarized.base2 { color: #eee8d5; }
.solarized.base3 { color: #fdf6e3; }
.solarized.solar-yellow { color: #b58900; }
.solarized.solar-orange { color: #cb4b16; }
.solarized.solar-red { color: #dc322f; }
.solarized.solar-magenta { color: #d33682; }
.solarized.solar-violet { color: #6c71c4; }
.solarized.solar-blue { color: #268bd2; }
.solarized.solar-cyan { color: #2aa198; }
.solarized.solar-green { color: #859900; }
/* Color scheme for code-mirror */
.cm-s-solarized {
line-height: 1.45em;
color-profile: sRGB;
rendering-intent: auto;
}
.cm-s-solarized.cm-s-dark {
color: #839496;
background-color: #002b36;
text-shadow: #002b36 0 1px;
}
.cm-s-solarized.cm-s-light {
background-color: #fdf6e3;
color: #657b83;
text-shadow: #eee8d5 0 1px;
}
.cm-s-solarized .CodeMirror-widget {
text-shadow: none;
}
.cm-s-solarized .cm-keyword { color: #cb4b16 }
.cm-s-solarized .cm-atom { color: #d33682; }
.cm-s-solarized .cm-number { color: #d33682; }
.cm-s-solarized .cm-def { color: #2aa198; }
.cm-s-solarized .cm-variable { color: #268bd2; }
.cm-s-solarized .cm-variable-2 { color: #b58900; }
.cm-s-solarized .cm-variable-3 { color: #6c71c4; }
.cm-s-solarized .cm-property { color: #2aa198; }
.cm-s-solarized .cm-operator {color: #6c71c4;}
.cm-s-solarized .cm-comment { color: #586e75; font-style:italic; }
.cm-s-solarized .cm-string { color: #859900; }
.cm-s-solarized .cm-string-2 { color: #b58900; }
.cm-s-solarized .cm-meta { color: #859900; }
.cm-s-solarized .cm-qualifier { color: #b58900; }
.cm-s-solarized .cm-builtin { color: #d33682; }
.cm-s-solarized .cm-bracket { color: #cb4b16; }
.cm-s-solarized .CodeMirror-matchingbracket { color: #859900; }
.cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; }
.cm-s-solarized .cm-tag { color: #93a1a1 }
.cm-s-solarized .cm-attribute { color: #2aa198; }
.cm-s-solarized .cm-header { color: #586e75; }
.cm-s-solarized .cm-quote { color: #93a1a1; }
.cm-s-solarized .cm-hr {
color: transparent;
border-top: 1px solid #586e75;
display: block;
}
.cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; }
.cm-s-solarized .cm-special { color: #6c71c4; }
.cm-s-solarized .cm-em {
color: #999;
text-decoration: underline;
text-decoration-style: dotted;
}
.cm-s-solarized .cm-strong { color: #eee; }
.cm-s-solarized .cm-error,
.cm-s-solarized .cm-invalidchar {
color: #586e75;
border-bottom: 1px dotted #dc322f;
}
.cm-s-solarized.cm-s-dark .CodeMirror-selected {
background: #073642;
}
.cm-s-solarized.cm-s-light .CodeMirror-selected {
background: #eee8d5;
}
/* Editor styling */
/* Little shadow on the view-port of the buffer view */
.cm-s-solarized.CodeMirror {
-moz-box-shadow: inset 7px 0 12px -6px #000;
-webkit-box-shadow: inset 7px 0 12px -6px #000;
box-shadow: inset 7px 0 12px -6px #000;
}
/* Gutter border and some shadow from it */
.cm-s-solarized .CodeMirror-gutters {
border-right: 1px solid;
}
/* Gutter colors and line number styling based of color scheme (dark / light) */
/* Dark */
.cm-s-solarized.cm-s-dark .CodeMirror-gutters {
background-color: #002b36;
border-color: #00232c;
}
.cm-s-solarized.cm-s-dark .CodeMirror-linenumber {
text-shadow: #021014 0 -1px;
}
/* Light */
.cm-s-solarized.cm-s-light .CodeMirror-gutters {
background-color: #fdf6e3;
border-color: #eee8d5;
}
/* Common */
.cm-s-solarized .CodeMirror-linenumber {
color: #586e75;
padding: 0 5px;
}
.cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; }
.cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; }
.cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; }
.cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text {
color: #586e75;
}
.cm-s-solarized .CodeMirror-lines .CodeMirror-cursor {
border-left: 1px solid #819090;
}
/*
Active line. Negative margin compensates left padding of the text in the
view-port
*/
.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background {
background: rgba(255, 255, 255, 0.10);
}
.cm-s-solarized.cm-s-light .CodeMirror-activeline-background {
background: rgba(0, 0, 0, 0.10);
}

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});

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> */)))));
};
});

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
})

45
playground/playground.rt Normal file
View File

@ -0,0 +1,45 @@
<!--<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

@ -0,0 +1,81 @@
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>

16
sample/.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
}
}

94
sample/ImageSearch.js Normal file
View File

@ -0,0 +1,94 @@
define([
'lodash',
'jquery',
'react',
'ImageSearch.rt'
], function (_, $, React, template) {
'use strict'
var ImageSearch = React.createClass({
displayName: 'ImageSearch',
mixins: [React.addons.LinkedStateMixin],
seq: 0,
total: 0,
hasMore: true,
heights: [0, 0, 0],
realTerm: 'cats',
getInitialState: function () {
setTimeout(this.search, 0)
return {
searchTerm: this.realTerm,
items: [[], [], []]
}
},
search: function () {
this.state.items = [[], [], []]
this.total = 0
this.heights = [0, 0, 0]
this.hasMore = true
this.realTerm = this.state.searchTerm
this.loadMore()
},
indexOfMin: function (array) {
var indexAndMin = _.reduce(array, function (accum, height, index) {
/*eslint no-extra-parens:0*/
return (height < accum.min) ? {i: index, min: height} : accum
}, {i: -1, min: Number.MAX_VALUE})
return indexAndMin.i
},
loadMore: function (done) {
done = done || _.noop
if (!this.hasMore) {
done()
return
}
var url = 'https://ajax.googleapis.com/ajax/services/search/images?v=1.0&rsz=8&start=' + this.total + '&q=' + this.realTerm + '&callback=?'
var self = this
$.ajax({url: url, dataType: 'jsonp'})
.done(function (data) {
if (!data.responseData) {
self.hasMore = false
done()
return
}
var results = data.responseData.results
var items = _.cloneDeep(self.state.items)
results.forEach(function (result) {
var minHeightIndex = self.indexOfMin(self.heights)
items[minHeightIndex].push({
id: self.seq + 1,
title: result.titleNoFormatting,
url: result.url,
ratio: result.width / result.height,
originalContext: result.originalContextUrl
})
self.heights[minHeightIndex] += result.height / result.width
self.total++
self.seq++
})
self.setState({items: items})
done()
})
},
shouldComponentUpdate: function (nextProps, nextState) {
return !_.isEqual(this.state, nextState)
},
render: function () {
return template.apply(this)
}
})
return ImageSearch
})

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