diff --git a/.eslintignore b/.eslintignore index 52d19ae..9e898bb 100644 --- a/.eslintignore +++ b/.eslintignore @@ -7,6 +7,7 @@ playground/**/*.rt.js playground/dist/** playground/libs/** +playground2/** playground3/** playground3/dist/** playground3/libs/** diff --git a/.eslintrc b/.eslintrc index 9278e45..b554368 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,7 +2,7 @@ "extends": ["wix-editor", "wix-editor/node", "plugin:lodash/recommended"], "plugins": ["lodash", "wix-editor"], "rules": { - "semi": [2, "always"], + "semi": [2, "never"], "func-style": [2, "declaration", {"allowArrowFunctions": true}], "prefer-spread": 0, "prefer-template": 0, diff --git a/Gruntfile.js b/Gruntfile.js index 521d98b..ddf4deb 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' module.exports = function (grunt) { grunt.initConfig({ clean: { @@ -88,33 +88,33 @@ module.exports = function (grunt) { options: readConfig('./playground.config.js') } } - }); + }) function readConfig(file) { - return eval(require('fs').readFileSync(file).toString()); // eslint-disable-line no-eval + 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.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('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; - }); + 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('build', ['rt', 'browserify:pg']) + grunt.registerTask('home', ['rt', 'browserify:home']) + grunt.registerTask('pgall', ['rt', 'browserify', 'uglify', 'requirejs']) - grunt.registerTask('all', ['default', 'test']); -}; + grunt.registerTask('all', ['default', 'test']) +} diff --git a/bin/rt.js b/bin/rt.js index d7a0cd8..9070df7 100755 --- a/bin/rt.js +++ b/bin/rt.js @@ -1,6 +1,7 @@ #!/usr/bin/env node -'use strict'; -const cli = require('../dist/cli'); -const exitCode = cli.execute(process.argv); +'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); +process.exit(exitCode) diff --git a/playground/CMLint.js b/playground/CMLint.js index 1b751a1..f730335 100644 --- a/playground/CMLint.js +++ b/playground/CMLint.js @@ -1,18 +1,18 @@ define(['react', 'lodash', 'jquery', './libs/codemirror-4.8/lib/codemirror'], function (React, _, $, CodeMirror) { - 'use strict'; + 'use strict' function annotationTooltip(ann) { - var severity = ann.severity; + var severity = ann.severity if (!severity) { - severity = 'error'; + severity = 'error' } - var tip = document.createElement('div'); - tip.className = 'CodeMirror-lint-message-' + severity; - tip.appendChild(document.createTextNode(ann.message)); - return tip; + var tip = document.createElement('div') + tip.className = 'CodeMirror-lint-message-' + severity + tip.appendChild(document.createTextNode(ann.message)) + return tip } - var GUTTER_ID = 'rt-annotations'; + var GUTTER_ID = 'rt-annotations' function annotate(editor, annot) { //if (annot.index) { @@ -21,10 +21,10 @@ define(['react', 'lodash', 'jquery', './libs/codemirror-4.8/lib/codemirror'], fu // 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')); + 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) { @@ -33,86 +33,86 @@ define(['react', 'lodash', 'jquery', './libs/codemirror-4.8/lib/codemirror'], fu //for (var i = 0; i < state.marked.length; ++i) // state.marked[i].clear(); //state.marked.length = 0; - cm.clearGutter(GUTTER_ID); + cm.clearGutter(GUTTER_ID) } function makeMarker(labels, severity, multiple, tooltips) { - var marker = document.createElement('div'); - var inner = marker; - marker.className = 'CodeMirror-lint-marker-' + severity; + 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'; + 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); - }); + showTooltipFor(e, labels, inner) + }) } - return marker; + 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); + 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); + 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 + 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); + CodeMirror.on(document, 'mousemove', position) + position(e) if (tt.style.opacity !== null) { - tt.style.opacity = 1; + tt.style.opacity = 1 } - return tt; + return tt } function rm(elt) { if (elt.parentNode) { - elt.parentNode.removeChild(elt); + elt.parentNode.removeChild(elt) } } function hideTooltip(tt) { if (!tt.parentNode) { - return; + return } if (tt.style.opacity === null) { - rm(tt); + rm(tt) } - tt.style.opacity = 0; - setTimeout(function () { rm(tt); }, 600); + tt.style.opacity = 0 + setTimeout(function () { rm(tt) }, 600) } function showTooltipFor(e, content, node) { - var tooltip = showTooltip(e, content); + var tooltip = showTooltip(e, content) function hide() { - CodeMirror.off(node, 'mouseout', hide); - if (tooltip) { hideTooltip(tooltip); tooltip = null; } + 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; + return undefined } - if (!n) { hide(); break; } + if (!n) { hide(); break } } } if (!tooltip) { - return clearInterval(poll); + return clearInterval(poll) } - }, 400); - CodeMirror.on(node, 'mouseout', hide); + }, 400) + CodeMirror.on(node, 'mouseout', hide) } return { GUTTER_ID: GUTTER_ID, annotate: annotate, clearMarks: clearMarks - }; -}); + } +}) diff --git a/playground/CodeMirrorEditor.js b/playground/CodeMirrorEditor.js index 4190609..0af7e6f 100644 --- a/playground/CodeMirrorEditor.js +++ b/playground/CodeMirrorEditor.js @@ -12,7 +12,7 @@ define([ './libs/codemirror-4.8/addon/runmode/runmode' //'./libs/codemirror-4.8/addon/display/placeholder' ], function (React, ReactDOM, _, $, CodeMirror, CMLint) { - 'use strict'; + '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' @@ -31,40 +31,40 @@ define([ dangerouslySetInnerHTML: null } } - }; - var tags = CodeMirror.htmlSchema; + } + var tags = CodeMirror.htmlSchema Object.keys(CodeMirror.htmlSchema).forEach(function (i) { - tags[i].attrs = _.defaults(rtSchema.div.attrs, tags[i].attrs); - }); + 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}); + cm.showHint({completeSingle: false}) } - }, 100); + }, 100) } - return CodeMirror.Pass; + 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 - }); + 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()); + var tok = cm.getTokenAt(cm.getCursor()) if (tok.type === 'string' && (!/['"]/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length === 1)) { - return false; + return false } - var inner = CodeMirror.innerMode(cm.getMode(), tok.state).state; - return inner.tagName; - }); + var inner = CodeMirror.innerMode(cm.getMode(), tok.state).state + return inner.tagName + }) } return React.createClass({ @@ -82,29 +82,29 @@ define([ 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); + 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; + var value = nextProps.valueLink ? nextProps.valueLink() : nextProps.value if (this.editor && this.editor.getValue() !== value) { - this.editor.setValue(value || ''); + this.editor.setValue(value || '') } }, componentDidMount: function () { - var value = this.props.valueLink ? this.props.valueLink() : this.props.value; + var value = this.props.valueLink ? this.props.valueLink() : this.props.value var options = { readOnly: this.props.readOnly, lineWrapping: true, @@ -115,36 +115,36 @@ define([ mode: 'javascript', gutters: ['CodeMirror-linenumbers', 'rt-annotations'], theme: 'solarized' //solarized_light solarized-light - }; + } if (this.props.mode === 'html') { - options.mode = 'text/html'; + options.mode = 'text/html' options.extraKeys = { "'<'": completeAfter, "'/'": completeIfAfterLt, "' '": completeIfInTag, "'='": completeIfInTag, 'Ctrl-Space': 'autocomplete' - }; - options.hintOptions = {schemaInfo: tags}; + } + options.hintOptions = {schemaInfo: tags} //options.gutters = ['CodeMirror-lint-markers']; //options.lint = true; } else { - options.mode = 'javascript'; + options.mode = 'javascript' //options.gutters = ['CodeMirror-lint-markers']; //options.lint = true; } - this.editor = CodeMirror.fromTextArea(ReactDOM.findDOMNode(this), options); + 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()); + this.props.valueLink(this.editor.getValue()) } else if (this.props.onChange) { - this.props.onChange({target: {value: this.editor.getValue()}}); + this.props.onChange({target: {value: this.editor.getValue()}}) } - }.bind(this)); + }.bind(this)) } }, //showMessage: function (msg) { @@ -163,13 +163,13 @@ define([ // } //}, annotate: function (annot) { - CMLint.annotate(this.editor, annot); + CMLint.annotate(this.editor, annot) }, clearAnnotations: function () { - CMLint.clearMarks(this.editor); + CMLint.clearMarks(this.editor) }, componentWillUnmount: function () { - this.editor.toTextArea(); + this.editor.toTextArea() } - }); -}); + }) +}) diff --git a/playground/CodeMirrorViewer.js b/playground/CodeMirrorViewer.js index 2356590..4b0fc5e 100644 --- a/playground/CodeMirrorViewer.js +++ b/playground/CodeMirrorViewer.js @@ -3,7 +3,7 @@ define(['react', 'react-dom', 'lodash', 'jquery', './libs/codemirror-4.8/lib/cod './libs/codemirror-4.8/mode/xml/xml', './libs/codemirror-4.8/addon/runmode/runmode' ], function (React, ReactDOM, _, $, CodeMirror) { - 'use strict'; + 'use strict' return React.createClass({ displayName: 'CodeMirrorViewer', propTypes: { @@ -13,34 +13,34 @@ define(['react', 'react-dom', 'lodash', 'jquery', './libs/codemirror-4.8/lib/cod valueLink: React.PropTypes.string }, getDefaultProps: function () { - return {mode: 'html'}; + return {mode: 'html'} }, getInitialState: function () { - return {editorId: _.uniqueId()}; + 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); + 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; + var value = nextProps.valueLink ? nextProps.valueLink() : nextProps.value if (this.editor && this.editor.getValue() !== value) { - this.editor.setValue(value || ''); + this.editor.setValue(value || '') } }, componentDidMount: function () { - var value = this.props.valueLink ? this.props.valueLink() : this.props.value; - var mode = this.props.mode; + var value = this.props.valueLink ? this.props.valueLink() : this.props.value + var mode = this.props.mode if (this.props.mode === 'html') { - mode = 'text/html'; + mode = 'text/html' } - this.editor = CodeMirror.runMode(value, mode, ReactDOM.findDOMNode(this)); + this.editor = CodeMirror.runMode(value, mode, ReactDOM.findDOMNode(this)) }, componentWillUnmount: function () { - this.editor.toTextArea(); + this.editor.toTextArea() } - }); -}); + }) +}) diff --git a/playground/aceEditor.js b/playground/aceEditor.js index c1186b5..c5f3284 100644 --- a/playground/aceEditor.js +++ b/playground/aceEditor.js @@ -3,7 +3,7 @@ */ /*global ace:true*/ define(['react', 'lodash']/*, 'ace'*/, function (React, _/*, ace*/) { - 'use strict'; + 'use strict' return React.createClass({ displayName: 'BraceEditor', propTypes: { @@ -17,49 +17,49 @@ define(['react', 'lodash']/*, 'ace'*/, function (React, _/*, ace*/) { 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); + 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; + var value = nextProps.valueLink ? nextProps.valueLink() : nextProps.value if (this.editor && this.editor.getValue() !== value) { - this.editor.setValue(value, 0); + this.editor.setValue(value, 0) } }, componentDidMount: function () { - this.editor = ace.edit(this.props.id || this.state.editorId); + this.editor = ace.edit(this.props.id || this.state.editorId) // this.editor.setTheme('ace/theme/monokai'); - this.editor.setTheme('ace/theme/solarized_light'); + this.editor.setTheme('ace/theme/solarized_light') if (this.props.mode === 'html') { - this.editor.getSession().setMode('ace/mode/html'); + this.editor.getSession().setMode('ace/mode/html') } else { - this.editor.getSession().setMode('ace/mode/javascript'); + this.editor.getSession().setMode('ace/mode/javascript') } - this.editor.getSession().setUseWorker(false); + this.editor.getSession().setUseWorker(false) - var value = this.props.valueLink ? this.props.valueLink() : this.props.value; - this.editor.setValue(value, 0); + var value = this.props.valueLink ? this.props.valueLink() : this.props.value + this.editor.setValue(value, 0) if (this.props.readOnly) { - this.editor.setReadOnly(true); + this.editor.setReadOnly(true) } else { - this.editor.setReadOnly(false); + this.editor.setReadOnly(false) this.editor.on('change', function (/*e*/) { if (this.props.valueLink) { - this.props.valueLink(this.editor.getValue()); + this.props.valueLink(this.editor.getValue()) } else if (this.props.onChange) { - this.props.onChange({target: {value: this.editor.getValue()}}); + this.props.onChange({target: {value: this.editor.getValue()}}) } - }.bind(this)); + }.bind(this)) } - this.editor.clearSelection(); + this.editor.clearSelection() }, componentWillUnmount: function () { - this.editor.destroy(); + this.editor.destroy() } - }); -}); + }) +}) diff --git a/playground/examples.js b/playground/examples.js index a2d3a8e..b277ec0 100644 --- a/playground/examples.js +++ b/playground/examples.js @@ -7,7 +7,7 @@ define(['lodash', 'react', './examples.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'; + 'use strict' var samples = { hello: [helloCode, helloRT], todo: [todoCode, todoRT], @@ -15,24 +15,24 @@ define(['lodash', 'react', './examples.rt', 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]}; }); + } + 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'}); + 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 - }); -}); + }) +}) diff --git a/playground/fiddle-main.js b/playground/fiddle-main.js index a2cee1a..1f0c418 100644 --- a/playground/fiddle-main.js +++ b/playground/fiddle-main.js @@ -20,10 +20,10 @@ requirejs.config({ 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')); -}); + 'use strict' + var elem = React.createElement(fiddle) + window.fiddle = ReactDOM.render(elem, document.getElementById('container')) +}) diff --git a/playground/fiddle.js b/playground/fiddle.js index e5982df..d46e6f9 100644 --- a/playground/fiddle.js +++ b/playground/fiddle.js @@ -2,44 +2,44 @@ * Created by avim on 12/2/2014. */ define(['react', 'firebase', 'lodash', './fiddle.rt', 'jquery'], function (React, Firebase, _, fiddleTemplate, $) { - 'use strict'; + '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 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/'); + 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)); + this.refs.playground.setState(snapshot.val()) + Firebase.goOffline() + }.bind(this)) } else { - Firebase.goOffline(); + Firebase.goOffline() } }, save: function () { - var newHash = generateRandomId(); - window.location.hash = newHash; - Firebase.goOnline(); + var newHash = generateRandomId() + window.location.hash = newHash + Firebase.goOnline() - var playgroundState = this.refs.playground.state; - var firebase = new Firebase('https://reacttemplates.firebaseio-demo.com/'); + 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 - }); + Firebase.goOffline() + alert('Saved the fiddle, you can share your url') //eslint-disable-line no-alert + }) }, clear: function () { - this.refs.playground.clear(); + this.refs.playground.clear() }, loadSample: function (name) { //require(['text!./samples/' + name + '.rt', 'text!./samples/' + name + '.code'], function (rt, code) { @@ -51,25 +51,25 @@ define(['react', 'firebase', 'lodash', './fiddle.rt', 'jquery'], function (React // this.refs.playground.setState(currentState); //}); - var playground = this.refs.playground; + var playground = this.refs.playground $.get('playground/samples/' + name + '.rt', null, function (data/*, textStatus, jqXHR*/) { - var rt = data; + 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); - }); - }); + playground.setState(currentState) + }) + }) //this.refs.playground.clear(); }, render: fiddleTemplate - }); + }) - return Fiddle; -}); + return Fiddle +}) diff --git a/playground/home-main.js b/playground/home-main.js index 25a8a47..9059168 100644 --- a/playground/home-main.js +++ b/playground/home-main.js @@ -21,10 +21,10 @@ requirejs.config({ 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')); -}); + 'use strict' + var elem = React.createElement(Examples) + ReactDOM.render(elem, document.getElementById('home-section')) +}) diff --git a/playground/playground.js b/playground/playground.js index 9c04875..922a219 100644 --- a/playground/playground.js +++ b/playground/playground.js @@ -1,6 +1,6 @@ /*eslint-env browser*/ define(['react', 'react-dom', 'jquery', 'lodash', './playground-fiddle.rt', './playground.rt'], function (React, ReactDOM, $, _, pgFiddleTemplate, playgroundTemplate) { - 'use strict'; + 'use strict' //function emptyFunc() { // return null; //} @@ -25,13 +25,13 @@ define(['react', 'react-dom', 'jquery', 'lodash', './playground-fiddle.rt', './p function showMessage(editor, msg) { if (editor && editor.showMessage) { - editor.annotate({line: 1, message: msg}); + editor.annotate({line: 1, message: msg}) } } function clearMessage(editor) { if (editor && editor.clearAnnotations) { - editor.clearAnnotations(); + editor.clearAnnotations() } } @@ -55,23 +55,23 @@ define(['react', 'react-dom', 'jquery', 'lodash', './playground-fiddle.rt', './p function generateRenderFunc(renderFunc) { return function () { - var res = null; + var res = null try { - res = renderFunc.apply(this); + res = renderFunc.apply(this) } catch (e) { - res = React.DOM.div.apply(this, [{style: {color: 'red'}}, 'Exception:' + e.message]); + res = React.DOM.div.apply(this, [{style: {color: 'red'}}, 'Exception:' + e.message]) } return React.DOM.div.apply(this, _.flatten([ {key: 'result'}, res - ])); - }; + ])) + } } - var templateHTML = '
'; + var templateHTML = '
' var templateProps = 'var template = React.createClass({\n' + ' render: templateRT\n' + - '});'; + '});' //var selfCleaningTimeout = { // componentDidUpdate: function() { @@ -100,18 +100,18 @@ define(['react', 'react-dom', 'jquery', 'lodash', './playground-fiddle.rt', './p validProps: true, setTimeout: function () { //console.log('setTimeout'); - clearTimeout(this.timeoutID); - this.timeoutID = setTimeout.apply(null, arguments); + 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 + return (this.props.direction === 'horizontal' && 'horizontal') || 'vertical' //eslint-disable-line no-extra-parens }, //executeCode: function() { // var mountNode = this.refs.mount.getDOMNode(); @@ -141,78 +141,78 @@ define(['react', 'react-dom', 'jquery', 'lodash', './playground-fiddle.rt', './p //}, getTabs: function () { if (this.props.codeVisible) { - return [['templateHTML', 'Template'], ['templateProps', 'Class'], ['templateSource', 'Generated code']]; + return [['templateHTML', 'Template'], ['templateProps', 'Class'], ['templateSource', 'Generated code']] } - return [['templateHTML', 'Template'], ['templateSource', 'Generated code']]; + return [['templateHTML', 'Template'], ['templateSource', 'Generated code']] }, updateSample: function (state) { //try { // React.unmountComponentAtNode(mountNode); //} catch (e) { } - this.generateCode(state); + this.generateCode(state) //this.sampleFunc = generateTemplateFunction(this.templateSource); //this.validHTML = this.sampleFunc !== emptyFunc; - this.validHTML = true; - this.sampleRender = generateRenderFunc(this.sampleFunc); - var editor; + this.validHTML = true + this.sampleRender = generateRenderFunc(this.sampleFunc) + var editor try { - this.validProps = true; + 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); + 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); + 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; + var mountNode = this.refs.mount this.setTimeout(function () { - showMessage(editor, e.message); + showMessage(editor, e.message) ReactDOM.render( React.createElement('div', {className: 'playground-error'}, e.toString()), mountNode - ); - }, 500); + ) + }, 500) }, showErrorAnnotation: function (annot, editor) { - var mountNode = this.refs.mount; + var mountNode = this.refs.mount this.setTimeout(function () { - editor.annotate(annot); + editor.annotate(annot) ReactDOM.render( React.createElement('div', {className: 'playground-error'}, annot.message), mountNode - ); - }, 500); + ) + }, 500) }, clear: function () { var currentState = { templateHTML: templateHTML, templateProps: templateProps - }; + } //this.updateSample(currentState); - this.setState(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; + 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); + 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); + 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); + console.log(e) } - this.templateSource = code; + this.templateSource = code }, getInitialState: function () { var currentState = { @@ -220,53 +220,53 @@ define(['react', 'react-dom', 'jquery', 'lodash', './playground-fiddle.rt', './p templateProps: this.props.templateProps || templateProps, name: this.props.name || 'template', currentTab: 'templateHTML' - }; + } //this.updateSample(currentState); - return currentState; + return currentState }, componentDidMount: function () { if (this.props.fiddle) { - window.addEventListener('resize', this.calcSize); - this.calcSize(); + window.addEventListener('resize', this.calcSize) + this.calcSize() } - this.updateSample(this.state); - this.renderSample(); + this.updateSample(this.state) + this.renderSample() }, renderSample: function () { - var mountNode = this.refs.mount; + var mountNode = this.refs.mount if (this.sample) { - ReactDOM.render(this.sample, mountNode); + ReactDOM.render(this.sample, mountNode) } }, componentDidUpdate: function () { - this.renderSample(); + this.renderSample() }, componentWillUnmount: function () { - window.removeEventListener('resize', this.calcSize); + window.removeEventListener('resize', this.calcSize) }, calcSize: function () { - var contentHeight = $(window).height() - $('#header').height(); - var height = contentHeight / 2 - 10; + var contentHeight = $(window).height() - $('#header').height() + var height = contentHeight / 2 - 10 $('.code-area').each(function (/*i, k*/) { - $(this).height(height); + $(this).height(height) //console.log($(this).height()); - }); - this.refs.editorCode.editor.refresh(); - this.refs.editorRT.editor.refresh(); - this.refs.editorGenerated.editor.refresh(); + }) + 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); + this.updateSample(nextState) } }, render: function () { - this.generateCode(this.state); - var template = this.props.fiddle ? pgFiddleTemplate : playgroundTemplate; - return template.apply(this); + this.generateCode(this.state) + var template = this.props.fiddle ? pgFiddleTemplate : playgroundTemplate + return template.apply(this) } - }); + }) - return Playground; -}); + return Playground +}) diff --git a/playground/rt-main.js b/playground/rt-main.js index 05571c4..17999b5 100644 --- a/playground/rt-main.js +++ b/playground/rt-main.js @@ -1,9 +1,9 @@ /*eslint strict:0*/ -'use strict'; +'use strict' /*eslint-env browser*/ -/*var _ = */require('lodash'); -var reactTemplates = require('../dist/reactTemplates'); -window.reactTemplates = reactTemplates; +/*var _ = */require('lodash') +var reactTemplates = require('../dist/reactTemplates') +window.reactTemplates = reactTemplates diff --git a/sample/ImageSearch.js b/sample/ImageSearch.js index a7264b6..3fe47f4 100644 --- a/sample/ImageSearch.js +++ b/sample/ImageSearch.js @@ -4,7 +4,7 @@ define([ 'react', 'ImageSearch.rt' ], function (_, $, React, template) { - 'use strict'; + 'use strict' var ImageSearch = React.createClass({ @@ -18,50 +18,50 @@ define([ realTerm: 'cats', getInitialState: function () { - setTimeout(this.search, 0); + 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(); + 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; + return (height < accum.min) ? {i: index, min: height} : accum + }, {i: -1, min: Number.MAX_VALUE}) + return indexAndMin.i }, loadMore: function (done) { - done = done || _.noop; + done = done || _.noop if (!this.hasMore) { - done(); - return; + 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 url = 'https://ajax.googleapis.com/ajax/services/search/images?v=1.0&rsz=8&start=' + this.total + '&q=' + this.realTerm + '&callback=?' - var self = this; + var self = this $.ajax({url: url, dataType: 'jsonp'}) .done(function (data) { if (!data.responseData) { - self.hasMore = false; - done(); - return; + self.hasMore = false + done() + return } - var results = data.responseData.results; - var items = _.cloneDeep(self.state.items); + var results = data.responseData.results + var items = _.cloneDeep(self.state.items) results.forEach(function (result) { - var minHeightIndex = self.indexOfMin(self.heights); + var minHeightIndex = self.indexOfMin(self.heights) items[minHeightIndex].push({ id: self.seq + 1, @@ -69,26 +69,26 @@ define([ url: result.url, ratio: result.width / result.height, originalContext: result.originalContextUrl - }); + }) - self.heights[minHeightIndex] += result.height / result.width; - self.total++; - self.seq++; - }); + self.heights[minHeightIndex] += result.height / result.width + self.total++ + self.seq++ + }) - self.setState({items: items}); - done(); - }); + self.setState({items: items}) + done() + }) }, shouldComponentUpdate: function (nextProps, nextState) { - return !_.isEqual(this.state, nextState); + return !_.isEqual(this.state, nextState) }, render: function () { - return template.apply(this); + return template.apply(this) } - }); + }) - return ImageSearch; -}); + return ImageSearch +}) diff --git a/sample/main.js b/sample/main.js index 8a81773..fb67d1e 100644 --- a/sample/main.js +++ b/sample/main.js @@ -10,9 +10,9 @@ requirejs.config({ jquery: {exports: '$'}, react: {exports: 'React'} } -}); +}) requirejs(['jquery', 'react', 'ImageSearch'], function ($, React, ImageSearch) { - 'use strict'; - React.renderComponent(ImageSearch(), $('#main').get(0)); //eslint-disable-line new-cap -}); + 'use strict' + React.renderComponent(ImageSearch(), $('#main').get(0)) //eslint-disable-line new-cap +}) diff --git a/src/RTCodeError.js b/src/RTCodeError.js index be6d09c..5db057d 100644 --- a/src/RTCodeError.js +++ b/src/RTCodeError.js @@ -1,6 +1,6 @@ -'use strict'; -const util = require('util'); -const _ = require('lodash'); +'use strict' +const util = require('util') +const _ = require('lodash') /** @@ -14,14 +14,14 @@ const _ = require('lodash'); */ function getLine(html, node) { if (!node) { - return {line: 1, col: 1}; + return {line: 1, col: 1} } - const linesUntil = html.substring(0, node.startIndex).split('\n'); - return {line: linesUntil.length, col: linesUntil[linesUntil.length - 1].length + 1}; + const linesUntil = html.substring(0, node.startIndex).split('\n') + return {line: linesUntil.length, col: linesUntil[linesUntil.length - 1].length + 1} } function norm(n) { - return n === undefined ? -1 : n; + return n === undefined ? -1 : n } /** @@ -34,23 +34,23 @@ function norm(n) { */ class RTCodeError extends Error { constructor(message, startOffset, endOffset, line, column) { - super(); - Error.captureStackTrace(this, RTCodeError); - this.name = 'RTCodeError'; - this.message = message || ''; - this.index = norm(startOffset); - this.startOffset = norm(startOffset); - this.endOffset = norm(endOffset); - this.line = norm(line); - this.column = norm(column); + super() + Error.captureStackTrace(this, RTCodeError) + this.name = 'RTCodeError' + this.message = message || '' + this.index = norm(startOffset) + this.startOffset = norm(startOffset) + this.endOffset = norm(endOffset) + this.line = norm(line) + this.column = norm(column) } } /** * @type {buildError} */ -RTCodeError.build = buildError; -RTCodeError.norm = norm; +RTCodeError.build = buildError +RTCodeError.norm = norm /** * @param {*} context @@ -60,7 +60,7 @@ RTCodeError.norm = norm; * @return {RTCodeError} */ function buildFormat(context, node, msg, args) { - return buildError(context, node, util.format.apply(this, [msg].concat(args))); + return buildError(context, node, util.format.apply(this, [msg].concat(args))) } /** @@ -70,7 +70,7 @@ function buildFormat(context, node, msg, args) { * @param {Array.} args * @return {RTCodeError} */ -RTCodeError.buildFormat = _.rest(buildFormat, 3); +RTCodeError.buildFormat = _.rest(buildFormat, 3) /** * @param {*} context @@ -79,8 +79,8 @@ RTCodeError.buildFormat = _.rest(buildFormat, 3); * @return {RTCodeError} */ function buildError(context, node, msg) { - const loc = getNodeLoc(context, node); - return new RTCodeError(msg, loc.start, loc.end, loc.pos.line, loc.pos.col); + const loc = getNodeLoc(context, node) + return new RTCodeError(msg, loc.start, loc.end, loc.pos.line, loc.pos.col) } /** @@ -89,24 +89,24 @@ function buildError(context, node, msg) { * @return {{pos:Pos, start:number, end:number}} */ function getNodeLoc(context, node) { - const start = node.startIndex; - const pos = getLine(context.html, node); - let end; + const start = node.startIndex + const pos = getLine(context.html, node) + let end if (node.data) { - end = start + node.data.length; + end = start + node.data.length } else if (node.next) { // eslint-disable-line - end = node.next.startIndex; + end = node.next.startIndex } else { - end = context.html.length; + end = context.html.length } return { pos, start, end - }; + } } module.exports = { RTCodeError, getNodeLoc -}; +} diff --git a/src/api.js b/src/api.js index f10df78..3c4ab60 100644 --- a/src/api.js +++ b/src/api.js @@ -1,12 +1,12 @@ -'use strict'; +'use strict' -const fs = require('fs'); -const path = require('path'); -const chalk = require('chalk'); -const reactTemplates = require('./reactTemplates'); -const fsUtil = require('./fsUtil'); -const convertRT = reactTemplates.convertRT; -const convertJSRTToJS = reactTemplates.convertJSRTToJS; +const fs = require('fs') +const path = require('path') +const chalk = require('chalk') +const reactTemplates = require('./reactTemplates') +const fsUtil = require('./fsUtil') +const convertRT = reactTemplates.convertRT +const convertJSRTToJS = reactTemplates.convertJSRTToJS /** * @param {string} source @@ -15,35 +15,35 @@ const convertJSRTToJS = reactTemplates.convertJSRTToJS; * @param {CONTEXT} context */ function convertFile(source, target, options, context) { - options = options || {}; - options.fileName = source; + options = options || {} + options.fileName = source if (!options.force && !fsUtil.isStale(source, target)) { - context.verbose(`target file ${chalk.cyan(target)} is up to date, skipping`); - return; + context.verbose(`target file ${chalk.cyan(target)} is up to date, skipping`) + return } - const html = fs.readFileSync(source).toString(); + const html = fs.readFileSync(source).toString() if (path.extname(source) === '.rts') { - const rtStyle = require('./rtStyle'); - const out = rtStyle.convert(html); + const rtStyle = require('./rtStyle') + const out = rtStyle.convert(html) if (!options.dryRun) { - fs.writeFileSync(target, out); + fs.writeFileSync(target, out) } - return; + return } - const modules = options.modules || 'none'; - const shouldAddName = modules === 'none' && !options.name; + const modules = options.modules || 'none' + const shouldAddName = modules === 'none' && !options.name if (shouldAddName) { - options.name = reactTemplates.normalizeName(path.basename(source, path.extname(source))) + 'RT'; + options.name = reactTemplates.normalizeName(path.basename(source, path.extname(source))) + 'RT' } - options.readFileSync = fsUtil.createRelativeReadFileSync(source); - const js = modules === 'jsrt' ? convertJSRTToJS(html, context, options) : convertRT(html, context, options); + options.readFileSync = fsUtil.createRelativeReadFileSync(source) + const js = modules === 'jsrt' ? convertJSRTToJS(html, context, options) : convertRT(html, context, options) if (!options.dryRun) { - fs.writeFileSync(target, js); + fs.writeFileSync(target, js) } if (shouldAddName) { - delete options.name; + delete options.name } } @@ -51,4 +51,4 @@ module.exports = { convertFile, context: require('./context'), _test: {} -}; +} diff --git a/src/cli.js b/src/cli.js index b2f4592..61f773a 100755 --- a/src/cli.js +++ b/src/cli.js @@ -1,36 +1,36 @@ -'use strict'; -const _ = require('lodash'); -const path = require('path'); +'use strict' +const _ = require('lodash') +const path = require('path') // const fs = require('fs'); -const api = require('./api'); -const context = require('./context'); -const shell = require('./shell'); -const pkg = require('../package.json'); -const options = require('./options'); -const reactDOMSupport = require('./reactDOMSupport'); -const reactTemplates = require('./reactTemplates'); -const rtStyle = require('./rtStyle'); -const glob = require('glob'); +const api = require('./api') +const context = require('./context') +const shell = require('./shell') +const pkg = require('../package.json') +const options = require('./options') +const reactDOMSupport = require('./reactDOMSupport') +const reactTemplates = require('./reactTemplates') +const rtStyle = require('./rtStyle') +const glob = require('glob') /** * @param {Options} currentOptions * @return {number} */ function executeOptions(currentOptions) { - let ret = 0; - const files = currentOptions._; - context.options.format = currentOptions.format || 'stylish'; + let ret = 0 + const files = currentOptions._ + context.options.format = currentOptions.format || 'stylish' if (currentOptions.version) { - console.log(`v${pkg.version}`); + console.log(`v${pkg.version}`) } else if (currentOptions.help) { if (files.length) { - console.log(options.generateHelpForOption(files[0])); + console.log(options.generateHelpForOption(files[0])) } else { - console.log(options.generateHelp()); + console.log(options.generateHelp()) } } else if (currentOptions.listTargetVersion) { - printVersions(currentOptions); + printVersions(currentOptions) } else if (files.length) { // console.log(files); // console.log(files.length); @@ -42,22 +42,22 @@ function executeOptions(currentOptions) { // } // return fp; // }); - const allFiles = _.flatMap(files, f => glob.sync(f, {cwd: context.cwd})); + const allFiles = _.flatMap(files, f => glob.sync(f, {cwd: context.cwd})) // console.log(allFiles.length); - _.forEach(allFiles, handleSingleFile.bind(this, currentOptions)); - ret = shell.printResults(context); + _.forEach(allFiles, handleSingleFile.bind(this, currentOptions)) + ret = shell.printResults(context) } else { - console.log(options.generateHelp()); + console.log(options.generateHelp()) } - return ret; + return ret } function printVersions(currentOptions) { - const ret = Object.keys(reactDOMSupport); + const ret = Object.keys(reactDOMSupport) if (currentOptions.format === 'json') { - console.log(JSON.stringify(ret, undefined, 2)); + console.log(JSON.stringify(ret, undefined, 2)) } else { - console.log(ret.join(', ')); + console.log(ret.join(', ')) } } @@ -67,23 +67,23 @@ function printVersions(currentOptions) { */ function handleSingleFile(currentOptions, filename) { try { - const sourceExt = path.extname(filename); - let outputFilename; + const sourceExt = path.extname(filename) + let outputFilename if (sourceExt === '.rt') { - outputFilename = filename + (currentOptions.modules === 'typescript' ? '.ts' : '.js'); + outputFilename = filename + (currentOptions.modules === 'typescript' ? '.ts' : '.js') } else if (sourceExt === '.jsrt') { - outputFilename = filename.replace(/\.jsrt$/, '.js'); - currentOptions = _.assign({}, currentOptions, {modules: 'jsrt'}); + outputFilename = filename.replace(/\.jsrt$/, '.js') + currentOptions = _.assign({}, currentOptions, {modules: 'jsrt'}) } else if (sourceExt === '.rts') { - outputFilename = filename + '.js'; - currentOptions = _.assign({}, currentOptions, {modules: 'rts'}); + outputFilename = filename + '.js' + currentOptions = _.assign({}, currentOptions, {modules: 'rts'}) } else { - context.error('invalid file, only handle rt/jsrt files', filename); - return; + context.error('invalid file, only handle rt/jsrt files', filename) + return } - api.convertFile(filename, outputFilename, currentOptions, context); + api.convertFile(filename, outputFilename, currentOptions, context) } catch (e) { - context.error(e.message, filename, e.line, e.column, e.startOffset, e.endOffset); + context.error(e.message, filename, e.line, e.column, e.startOffset, e.endOffset) } } @@ -94,11 +94,11 @@ function handleSingleFile(currentOptions, filename) { */ function execute(args) { try { - const currentOptions = options.parse(args); - return executeOptions(currentOptions); + const currentOptions = options.parse(args) + return executeOptions(currentOptions) } catch (error) { - console.error(error.message); - return 1; + console.error(error.message) + return 1 } } @@ -109,4 +109,4 @@ module.exports = { handleSingleFile, convertTemplateToReact: reactTemplates.convertTemplateToReact, convertStyle: rtStyle.convert -}; +} diff --git a/src/context.js b/src/context.js index e9b6712..3dc892f 100644 --- a/src/context.js +++ b/src/context.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' /** * @typedef {{color: boolean, cwd: string, report: function(string), issue: function(string, string,string,number,number,number=,number=), warn: function(string), verbose: function(string), getMessages: function():Array., options:Options, messages: Array.}} CONTEXT */ @@ -14,11 +14,11 @@ const MESSAGE_LEVEL = { ERROR: 'ERROR', WARN: 'WARN', INFO: 'INFO' -}; +} -const _ = require('lodash'); -const err = require('./RTCodeError'); -const norm = err.RTCodeError.norm; +const _ = require('lodash') +const err = require('./RTCodeError') +const norm = err.RTCodeError.norm /** @@ -32,21 +32,21 @@ const context = { /** @type {string} */ cwd: process.cwd(), report(msg) { - console.log(msg); + console.log(msg) }, verbose(msg) { if (context.options.verbose) { - console.log(msg); + console.log(msg) } }, info(msg, file, line, column) { - context.issue(MESSAGE_LEVEL.INFO, msg, file, line, column); + context.issue(MESSAGE_LEVEL.INFO, msg, file, line, column) }, warn(msg, file, line, column, startOffset, endOffset) { - context.issue(MESSAGE_LEVEL.WARN, msg, file, line, column, startOffset, endOffset); + context.issue(MESSAGE_LEVEL.WARN, msg, file, line, column, startOffset, endOffset) }, error(msg, file, line, column, startOffset, endOffset) { - context.issue(MESSAGE_LEVEL.ERROR, msg, file, line, column, startOffset, endOffset); + context.issue(MESSAGE_LEVEL.ERROR, msg, file, line, column, startOffset, endOffset) }, /** * @param {MESSAGE_LEVEL} level @@ -58,16 +58,16 @@ const context = { * @param {number=} endOffset */ issue(level, msg, file, line, column, startOffset, endOffset) { - context.messages.push({level, msg, file: file || null, line: norm(line), column: norm(column), index: norm(startOffset), startOffset: norm(startOffset), endOffset: norm(endOffset)}); + context.messages.push({level, msg, file: file || null, line: norm(line), column: norm(column), index: norm(startOffset), startOffset: norm(startOffset), endOffset: norm(endOffset)}) }, getMessages() { - return context.messages; + return context.messages }, clear() { - context.messages = []; + context.messages = [] }, hasErrors() { - return _.some(context.messages, {level: MESSAGE_LEVEL.ERROR}); + return _.some(context.messages, {level: MESSAGE_LEVEL.ERROR}) }, options: { verbose: false, @@ -75,6 +75,6 @@ const context = { format: 'stylish' }, MESSAGE_LEVEL -}; +} -module.exports = context; +module.exports = context diff --git a/src/formatters/json.js b/src/formatters/json.js index d22be95..1b75505 100644 --- a/src/formatters/json.js +++ b/src/formatters/json.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' module.exports = function (results/*, config*/) { - return JSON.stringify(results, undefined, 2); -}; \ No newline at end of file + return JSON.stringify(results, undefined, 2) +} \ No newline at end of file diff --git a/src/formatters/stylish.js b/src/formatters/stylish.js index deb04e4..c3b1aaa 100644 --- a/src/formatters/stylish.js +++ b/src/formatters/stylish.js @@ -1,10 +1,10 @@ -'use strict'; +'use strict' /** * @type {Chalk.ChalkModule} */ -const chalk = require('chalk'); -const _ = require('lodash'); -const table = require('text-table'); +const chalk = require('chalk') +const _ = require('lodash') +const table = require('text-table') /** * Given a word and a count, append an s if count is not one. @@ -13,51 +13,51 @@ const table = require('text-table'); * @returns {string} The original word with an s on the end if count is not one. */ function pluralize(word, count) { - return count === 1 ? word : word + 's'; + return count === 1 ? word : word + 's' } /** * @param {number} line * @return {string} */ function lineText(line) { - return line < 1 ? '' : line; + return line < 1 ? '' : line } module.exports = function (results) { - results = _.groupBy(results, 'file'); + results = _.groupBy(results, 'file') - let output = '\n'; - let total = 0; - let errors = 0; - let warnings = 0; - let infos = 0; - let summaryColor = 'cyan'; + let output = '\n' + let total = 0 + let errors = 0 + let warnings = 0 + let infos = 0 + let summaryColor = 'cyan' _.forEach(results, (result, k) => { - const messages = result; + const messages = result if (messages.length === 0) { - return; + return } - total += messages.length; - output += chalk.underline(k) + '\n'; + total += messages.length + output += chalk.underline(k) + '\n' output += table( messages.map(message => { - let messageType; + let messageType if (message.level === 'ERROR') { - messageType = chalk.red('error'); - summaryColor = 'red'; - errors++; + messageType = chalk.red('error') + summaryColor = 'red' + errors++ } else if (message.level === 'WARN') { - messageType = chalk.yellow('warning'); - summaryColor = 'yellow'; - warnings++; + messageType = chalk.yellow('warning') + summaryColor = 'yellow' + warnings++ } else { - messageType = chalk.cyan('info'); - infos++; + messageType = chalk.cyan('info') + infos++ } return [ @@ -67,14 +67,14 @@ module.exports = function (results) { messageType, message.msg.replace(/\.$/, ''), chalk.gray(message.ruleId || '') - ]; + ] }), { align: ['', 'r', 'l'], stringLength: str => chalk.stripColor(str).length } - ).split('\n').map(el => el.replace(/(\d+)\s+(\d+)/, (m, p1, p2) => chalk.gray(p1 + ':' + p2))).join('\n') + '\n\n'; - }); + ).split('\n').map(el => el.replace(/(\d+)\s+(\d+)/, (m, p1, p2) => chalk.gray(p1 + ':' + p2))).join('\n') + '\n\n' + }) if (total > 0) { output += chalk[summaryColor].bold([ @@ -82,8 +82,8 @@ module.exports = function (results) { ' (', errors, pluralize(' error', errors), ', ', warnings, pluralize(' warning', warnings), ', ', infos, pluralize(' info', infos), ')\n' - ].join('')); + ].join('')) } - return total > 0 ? output : ''; -}; + return total > 0 ? output : '' +} diff --git a/src/fsUtil.js b/src/fsUtil.js index 0bb5baa..0956248 100644 --- a/src/fsUtil.js +++ b/src/fsUtil.js @@ -1,6 +1,6 @@ -'use strict'; -const fs = require('fs'); -const path = require('path'); +'use strict' +const fs = require('fs') +const path = require('path') /** * @param {string} source @@ -9,19 +9,19 @@ const path = require('path'); */ function isStale(source, target) { if (!fs.existsSync(target)) { - return true; + return true } - const sourceTime = fs.statSync(source).mtime; - const targetTime = fs.statSync(target).mtime; - return sourceTime.getTime() > targetTime.getTime(); + const sourceTime = fs.statSync(source).mtime + const targetTime = fs.statSync(target).mtime + return sourceTime.getTime() > targetTime.getTime() } function createRelativeReadFileSync(baseFile) { - const basePath = path.dirname(baseFile); - return filename => fs.readFileSync(path.resolve(basePath, filename)); + const basePath = path.dirname(baseFile) + return filename => fs.readFileSync(path.resolve(basePath, filename)) } module.exports = { isStale, createRelativeReadFileSync -}; +} diff --git a/src/options.js b/src/options.js index 4c03624..e96125d 100644 --- a/src/options.js +++ b/src/options.js @@ -2,16 +2,16 @@ * @fileoverview Options configuration for optionator. * @author idok */ -'use strict'; +'use strict' //------------------------------------------------------------------------------ // Requirements //------------------------------------------------------------------------------ -const optionator = require('optionator'); -const pkg = require('../package.json'); -const reactDOMSupport = require('./reactDOMSupport'); -const reactNativeSupport = require('./reactNativeSupport'); +const optionator = require('optionator') +const pkg = require('../package.json') +const reactDOMSupport = require('./reactDOMSupport') +const reactNativeSupport = require('./reactNativeSupport') //------------------------------------------------------------------------------ // Initialization and Public Interface @@ -127,4 +127,4 @@ $ rt [ ...] []`, default: 'false', description: 'Automatically bind event handlers to components' }] -}); +}) diff --git a/src/reactDOMSupport.js b/src/reactDOMSupport.js index 6131ba4..9a87c09 100644 --- a/src/reactDOMSupport.js +++ b/src/reactDOMSupport.js @@ -1,12 +1,12 @@ -'use strict'; +'use strict' const ver0_12_0 = ['a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', - 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'menuitem', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr', 'circle', 'defs', 'ellipse', 'g', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'tspan']; -const ver0_11_2 = ['a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'menuitem', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr', 'circle', 'defs', 'ellipse', 'g', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'tspan', 'injection']; -const ver0_11_0 = ['a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'menuitem', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr', 'circle', 'defs', 'ellipse', 'g', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'tspan', 'injection']; -const ver0_10_0 = ['a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'menuitem', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr', 'circle', 'defs', 'g', 'line', 'linearGradient', 'path', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'injection']; + 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'menuitem', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr', 'circle', 'defs', 'ellipse', 'g', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'tspan'] +const ver0_11_2 = ['a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'menuitem', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr', 'circle', 'defs', 'ellipse', 'g', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'tspan', 'injection'] +const ver0_11_0 = ['a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'menuitem', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr', 'circle', 'defs', 'ellipse', 'g', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'tspan', 'injection'] +const ver0_10_0 = ['a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'menuitem', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr', 'circle', 'defs', 'g', 'line', 'linearGradient', 'path', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'injection'] const svg = ['a', 'altGlyph', 'altGlyphDef', 'altGlyphItem', 'animate', 'animateMotion', 'animateTransform', 'circle', 'clipPath', 'color-profile', 'cursor', 'defs', 'desc', 'ellipse', 'feBlend', 'g', 'image', 'line', - 'linearGradient', 'marker', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'tref', 'tspan', 'use']; -const v12_svg = ver0_12_0.concat(svg); + 'linearGradient', 'marker', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'tref', 'tspan', 'use'] +const v12_svg = ver0_12_0.concat(svg) const versions = { '15.0.1': v12_svg, @@ -21,5 +21,5 @@ const versions = { '0.11.0': ver0_11_0, '0.10.0': ver0_10_0, default: '0.14.0' -}; -module.exports = versions; +} +module.exports = versions diff --git a/src/reactNativeSupport.js b/src/reactNativeSupport.js index 8c347ca..add8954 100644 --- a/src/reactNativeSupport.js +++ b/src/reactNativeSupport.js @@ -1,6 +1,6 @@ -'use strict'; +'use strict' -const ver0_9_0 = ['ActivityIndicatorIOS', 'DatePickerIOS', 'Image', 'ListView', 'MapView', 'Navigator', 'NavigatorIOS', 'PickerIOS', 'ScrollView', 'SliderIOS', 'SwitchIOS', 'TabBarIOS', 'Text', 'TextInput', 'TouchableHighlight', 'TouchableOpacity', 'TouchableWithoutFeedback', 'View', 'WebView']; +const ver0_9_0 = ['ActivityIndicatorIOS', 'DatePickerIOS', 'Image', 'ListView', 'MapView', 'Navigator', 'NavigatorIOS', 'PickerIOS', 'ScrollView', 'SliderIOS', 'SwitchIOS', 'TabBarIOS', 'Text', 'TextInput', 'TouchableHighlight', 'TouchableOpacity', 'TouchableWithoutFeedback', 'View', 'WebView'] const versions = { '0.9.0': { @@ -14,6 +14,6 @@ const versions = { components: ver0_9_0 }, default: '0.9.0' -}; +} -module.exports = versions; +module.exports = versions diff --git a/src/reactPropTemplates.js b/src/reactPropTemplates.js index 1974af8..448e7d2 100644 --- a/src/reactPropTemplates.js +++ b/src/reactPropTemplates.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' const native = { '0.9.0': { @@ -21,9 +21,9 @@ const native = { Separator: {prop: 'renderSeparator', arguments: ['sectionID', 'rowID', 'adjacentRowHighlighted']} } } -}; +} module.exports = { native, dom: {} -}; +} diff --git a/src/reactSupport.js b/src/reactSupport.js index a3a95a6..fb6abb3 100644 --- a/src/reactSupport.js +++ b/src/reactSupport.js @@ -1,5 +1,5 @@ -'use strict'; -const _ = require('lodash'); +'use strict' +const _ = require('lodash') /** * @param {Context} context @@ -11,9 +11,9 @@ function shouldUseCreateElement(context) { case '0.11.1': case '0.11.0': case '0.10.0': - return false; + return false default: - return true; + return true } } @@ -22,24 +22,24 @@ const reactSupportedAttributes = ['accept', 'acceptCharset', 'accessKey', 'actio 'draggable', 'encType', 'form', 'formNoValidate', 'frameBorder', 'height', 'hidden', 'href', 'hrefLang', 'htmlFor', 'httpEquiv', 'icon', 'id', 'label', 'lang', 'list', 'loop', 'manifest', 'max', 'maxLength', 'media', 'mediaGroup', 'method', 'min', 'multiple', 'muted', 'name', 'noValidate', 'open', 'pattern', 'placeholder', 'poster', 'preload', 'radioGroup', 'readOnly', 'rel', 'required', 'role', 'rows', 'rowSpan', 'sandbox', 'scope', 'scrolling', 'seamless', 'selected', 'shape', 'size', 'sizes', 'span', 'spellCheck', 'src', 'srcDoc', 'srcSet', 'start', 'step', - 'style', 'tabIndex', 'target', 'title', 'type', 'useMap', 'value', 'width', 'wmode']; -const classNameProp = 'className'; -const attributesMapping = {'class': classNameProp, 'rt-class': classNameProp, 'for': 'htmlFor'}; //eslint-disable-line quote-props + 'style', 'tabIndex', 'target', 'title', 'type', 'useMap', 'value', 'width', 'wmode'] +const classNameProp = 'className' +const attributesMapping = {'class': classNameProp, 'rt-class': classNameProp, 'for': 'htmlFor'} //eslint-disable-line quote-props _.forEach(reactSupportedAttributes, attributeReactName => { if (attributeReactName !== attributeReactName.toLowerCase()) { - attributesMapping[attributeReactName.toLowerCase()] = attributeReactName; + attributesMapping[attributeReactName.toLowerCase()] = attributeReactName } -}); +}) -const htmlSelfClosingTags = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']; +const htmlSelfClosingTags = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'] -const templateAMDTemplate = _.template("define(<%= name ? '\"'+name + '\", ' : '' %>[<%= requirePaths %>], function (<%= AMDArguments %>) {\n'use strict';\n<%= AMDSubstitutions %>return <%= renderFunction %>;\n});"); -const templateCommonJSTemplate = _.template("'use strict';\n<%= vars %>\nmodule.exports = <%= renderFunction %>;\n"); -const templateES6Template = _.template('<%= vars %>\nexport default <%= renderFunction %>\n'); -const templatePJSTemplate = _.template('var <%= name %> = <%= renderFunction %>'); -const templateTypescriptTemplate = _.template('<%= vars %>\nexport = <%= renderFunction %>;\n'); -const templateJSRTTemplate = _.template('<%= renderFunction %>'); +const templateAMDTemplate = _.template("define(<%= name ? '\"'+name + '\", ' : '' %>[<%= requirePaths %>], function (<%= AMDArguments %>) {\n'use strict';\n<%= AMDSubstitutions %>return <%= renderFunction %>;\n});") +const templateCommonJSTemplate = _.template("'use strict';\n<%= vars %>\nmodule.exports = <%= renderFunction %>;\n") +const templateES6Template = _.template('<%= vars %>\nexport default <%= renderFunction %>\n') +const templatePJSTemplate = _.template('var <%= name %> = <%= renderFunction %>') +const templateTypescriptTemplate = _.template('<%= vars %>\nexport = <%= renderFunction %>;\n') +const templateJSRTTemplate = _.template('<%= renderFunction %>') const templates = { amd: templateAMDTemplate, @@ -48,27 +48,27 @@ const templates = { es6: templateES6Template, none: templatePJSTemplate, jsrt: templateJSRTTemplate -}; +} -const isImportAsterisk = _.matches({member: '*'}); -const defaultCase = _.constant(true); +const isImportAsterisk = _.matches({member: '*'}) +const defaultCase = _.constant(true) const buildImportTypeScript = _.cond([ [isImportAsterisk, d => `import ${d.alias} = require('${d.moduleName}');`], [_.matches({member: 'default'}), d => `import ${d.alias} from '${d.moduleName}';`], [defaultCase, d => `import { ${d.member} as ${d.alias} } from '${d.moduleName}';`] -]); +]) const buildImportES6 = _.cond([ [isImportAsterisk, d => `import * as ${d.alias} from '${d.moduleName}';`], [_.matches({member: 'default'}), d => `import ${d.alias} from '${d.moduleName}';`], [defaultCase, d => `import { ${d.member} as ${d.alias} } from '${d.moduleName}';`] -]); +]) const buildImportCommonJS = _.cond([ [isImportAsterisk, d => `var ${d.alias} = require('${d.moduleName}');`], [defaultCase, d => `var ${d.alias} = require('${d.moduleName}').${d.member};`] -]); +]) const buildImport = { typescript: buildImportTypeScript, @@ -77,7 +77,7 @@ const buildImport = { amd: buildImportCommonJS, none: buildImportCommonJS, jsrt: buildImportCommonJS -}; +} module.exports = { htmlSelfClosingTags, @@ -86,4 +86,4 @@ module.exports = { shouldUseCreateElement, templates, buildImport -}; +} diff --git a/src/reactTemplates.js b/src/reactTemplates.js index 06bff01..4d07415 100644 --- a/src/reactTemplates.js +++ b/src/reactTemplates.js @@ -1,22 +1,22 @@ -'use strict'; -const cheerio = require('cheerio'); -const _ = require('lodash'); -const esprima = require('esprima'); -const escodegen = require('escodegen'); -const reactDOMSupport = require('./reactDOMSupport'); -const reactNativeSupport = require('./reactNativeSupport'); -const reactPropTemplates = require('./reactPropTemplates'); -const rtError = require('./RTCodeError'); -const reactSupport = require('./reactSupport'); -const templates = reactSupport.templates; -const utils = require('./utils'); -const validateJS = utils.validateJS; -const RTCodeError = rtError.RTCodeError; +'use strict' +const cheerio = require('cheerio') +const _ = require('lodash') +const esprima = require('esprima') +const escodegen = require('escodegen') +const reactDOMSupport = require('./reactDOMSupport') +const reactNativeSupport = require('./reactNativeSupport') +const reactPropTemplates = require('./reactPropTemplates') +const rtError = require('./RTCodeError') +const reactSupport = require('./reactSupport') +const templates = reactSupport.templates +const utils = require('./utils') +const validateJS = utils.validateJS +const RTCodeError = rtError.RTCodeError -const repeatTemplate = _.template('_.map(<%= collection %>,<%= repeatFunction %>.bind(<%= repeatBinds %>))'); -const ifTemplate = _.template('((<%= condition %>)?(<%= body %>):null)'); -const propsTemplateSimple = _.template('_.assign({}, <%= generatedProps %>, <%= rtProps %>)'); -const propsTemplate = _.template('mergeProps( <%= generatedProps %>, <%= rtProps %>)'); +const repeatTemplate = _.template('_.map(<%= collection %>,<%= repeatFunction %>.bind(<%= repeatBinds %>))') +const ifTemplate = _.template('((<%= condition %>)?(<%= body %>):null)') +const propsTemplateSimple = _.template('_.assign({}, <%= generatedProps %>, <%= rtProps %>)') +const propsTemplate = _.template('mergeProps( <%= generatedProps %>, <%= rtProps %>)') const propsMergeFunction = `function mergeProps(inline,external) { var res = _.assign({},inline,external) @@ -28,43 +28,43 @@ const propsMergeFunction = `function mergeProps(inline,external) { } return res; } -`; +` -const classSetTemplate = _.template('_.transform(<%= classSet %>, function(res, value, key){ if(value){ res.push(key); } }, []).join(" ")'); +const classSetTemplate = _.template('_.transform(<%= classSet %>, function(res, value, key){ if(value){ res.push(key); } }, []).join(" ")') function getTagTemplateString(simpleTagTemplate, shouldCreateElement) { if (simpleTagTemplate) { - return shouldCreateElement ? 'React.createElement(<%= name %>,<%= props %><%= children %>)' : '<%= name %>(<%= props %><%= children %>)'; + return shouldCreateElement ? 'React.createElement(<%= name %>,<%= props %><%= children %>)' : '<%= name %>(<%= props %><%= children %>)' } - return shouldCreateElement ? 'React.createElement.apply(this, [<%= name %>,<%= props %><%= children %>])' : '<%= name %>.apply(this, [<%= props %><%= children %>])'; + return shouldCreateElement ? 'React.createElement.apply(this, [<%= name %>,<%= props %><%= children %>])' : '<%= name %>.apply(this, [<%= props %><%= children %>])' } -const commentTemplate = _.template(' /* <%= data %> */ '); +const commentTemplate = _.template(' /* <%= data %> */ ') -const repeatAttr = 'rt-repeat'; -const ifAttr = 'rt-if'; -const classSetAttr = 'rt-class'; -const classAttr = 'class'; -const scopeAttr = 'rt-scope'; -const propsAttr = 'rt-props'; -const templateNode = 'rt-template'; -const virtualNode = 'rt-virtual'; -const includeNode = 'rt-include'; -const includeSrcAttr = 'src'; -const requireAttr = 'rt-require'; -const importAttr = 'rt-import'; -const statelessAttr = 'rt-stateless'; -const preAttr = 'rt-pre'; +const repeatAttr = 'rt-repeat' +const ifAttr = 'rt-if' +const classSetAttr = 'rt-class' +const classAttr = 'class' +const scopeAttr = 'rt-scope' +const propsAttr = 'rt-props' +const templateNode = 'rt-template' +const virtualNode = 'rt-virtual' +const includeNode = 'rt-include' +const includeSrcAttr = 'src' +const requireAttr = 'rt-require' +const importAttr = 'rt-import' +const statelessAttr = 'rt-stateless' +const preAttr = 'rt-pre' -const reactTemplatesSelfClosingTags = [includeNode]; +const reactTemplatesSelfClosingTags = [includeNode] /** * @param {Options} options * @return {Options} */ function getOptions(options) { - options = options || {}; + options = options || {} const defaultOptions = { version: false, force: false, @@ -73,29 +73,29 @@ function getOptions(options) { lodashImportPath: 'lodash', native: false, nativeTargetVersion: reactNativeSupport.default - }; + } - const finalOptions = _.defaults({}, options, defaultOptions); - finalOptions.reactImportPath = reactImport(finalOptions); - finalOptions.modules = finalOptions.modules || (finalOptions.native ? 'commonjs' : 'none'); + const finalOptions = _.defaults({}, options, defaultOptions) + finalOptions.reactImportPath = reactImport(finalOptions) + finalOptions.modules = finalOptions.modules || (finalOptions.native ? 'commonjs' : 'none') const defaultPropTemplates = finalOptions.native ? reactPropTemplates.native[finalOptions.nativeTargetVersion] : - reactPropTemplates.dom[finalOptions.targetVersion]; + reactPropTemplates.dom[finalOptions.targetVersion] - finalOptions.propTemplates = _.defaults({}, options.propTemplates, defaultPropTemplates); - return finalOptions; + finalOptions.propTemplates = _.defaults({}, options.propTemplates, defaultPropTemplates) + return finalOptions } function reactImport(options) { if (options.native) { - return reactNativeSupport[options.nativeTargetVersion].react.module; + return reactNativeSupport[options.nativeTargetVersion].react.module } if (!options.reactImportPath) { - const isNewReact = _.includes(['0.14.0', '0.15.0', '15.0.0', '15.0.1'], options.targetVersion); - return isNewReact ? 'react' : 'react/addons'; + const isNewReact = _.includes(['0.14.0', '0.15.0', '15.0.0', '15.0.1'], options.targetVersion) + return isNewReact ? 'react' : 'react/addons' } - return options.reactImportPath; + return options.reactImportPath } /** @@ -106,66 +106,66 @@ function reactImport(options) { * @return {string} */ function generateInjectedFunc(context, namePrefix, body, params) { - params = params || context.boundParams; - const funcName = namePrefix.replace(',', '') + (context.injectedFunctions.length + 1); + params = params || context.boundParams + const funcName = namePrefix.replace(',', '') + (context.injectedFunctions.length + 1) const funcText = `function ${funcName}(${params.join(',')}) { ${body} } - `; - context.injectedFunctions.push(funcText); - return funcName; + ` + context.injectedFunctions.push(funcText) + return funcName } function generateTemplateProps(node, context) { - let templatePropCount = 0; - const propTemplateDefinition = context.options.propTemplates[node.name]; + let templatePropCount = 0 + const propTemplateDefinition = context.options.propTemplates[node.name] const propertiesTemplates = _(node.children) .map((child, index) => { - let templateProp = null; + let templateProp = null if (child.name === templateNode) { // Generic explicit template tag if (!_.has(child.attribs, 'prop')) { - throw RTCodeError.build(context, child, 'rt-template must have a prop attribute'); + throw RTCodeError.build(context, child, 'rt-template must have a prop attribute') } if (_.filter(child.children, {type: 'tag'}).length !== 1) { - throw RTCodeError.build(context, child, "'rt-template' should have a single non-text element as direct child"); + throw RTCodeError.build(context, child, "'rt-template' should have a single non-text element as direct child") } - const childTemplate = _.find(context.options.propTemplates, {prop: child.attribs.prop}) || {arguments: []}; + const childTemplate = _.find(context.options.propTemplates, {prop: child.attribs.prop}) || {arguments: []} templateProp = { prop: child.attribs.prop, arguments: (child.attribs.arguments ? child.attribs.arguments.split(',') : childTemplate.arguments) || [] - }; + } } else if (propTemplateDefinition && propTemplateDefinition[child.name]) { // Implicit child template from configuration templateProp = { prop: propTemplateDefinition[child.name].prop, arguments: child.attribs.arguments ? child.attribs.arguments.split(',') : propTemplateDefinition[child.name].arguments - }; + } } if (templateProp) { - _.assign(templateProp, {childIndex: index - templatePropCount++, content: _.find(child.children, {type: 'tag'})}); + _.assign(templateProp, {childIndex: index - templatePropCount++, content: _.find(child.children, {type: 'tag'})}) } - return templateProp; + return templateProp }) .compact() - .value(); + .value() return _.transform(propertiesTemplates, (props, templateProp) => { - const functionParams = _.values(context.boundParams).concat(templateProp.arguments); + const functionParams = _.values(context.boundParams).concat(templateProp.arguments) - const oldBoundParams = context.boundParams; - context.boundParams = context.boundParams.concat(templateProp.arguments); + const oldBoundParams = context.boundParams + context.boundParams = context.boundParams.concat(templateProp.arguments) - const functionBody = 'return ' + convertHtmlToReact(templateProp.content, context); - context.boundParams = oldBoundParams; + const functionBody = 'return ' + convertHtmlToReact(templateProp.content, context) + context.boundParams = oldBoundParams - const generatedFuncName = generateInjectedFunc(context, templateProp.prop, functionBody, functionParams); - props[templateProp.prop] = genBind(generatedFuncName, _.values(context.boundParams)); + const generatedFuncName = generateInjectedFunc(context, templateProp.prop, functionBody, functionParams) + props[templateProp.prop] = genBind(generatedFuncName, _.values(context.boundParams)) // Remove the template child from the children definition. - node.children.splice(templateProp.childIndex, 1); - }, {}); + node.children.splice(templateProp.childIndex, 1) + }, {}) } /** @@ -174,70 +174,70 @@ function generateTemplateProps(node, context) { * @return {string} */ function generateProps(node, context) { - const props = {}; + const props = {} _.forOwn(node.attribs, (val, key) => { - const propKey = reactSupport.attributesMapping[key.toLowerCase()] || key; + const propKey = reactSupport.attributesMapping[key.toLowerCase()] || key if (props.hasOwnProperty(propKey) && propKey !== reactSupport.classNameProp) { - throw RTCodeError.build(context, node, `duplicate definition of ${propKey} ${JSON.stringify(node.attribs)}`); + throw RTCodeError.build(context, node, `duplicate definition of ${propKey} ${JSON.stringify(node.attribs)}`) } if (_.startsWith(key, 'on') && !utils.isStringOnlyCode(val)) { - props[propKey] = handleEventHandler(val, context, node, key); + props[propKey] = handleEventHandler(val, context, node, key) } else if (key === 'style' && !utils.isStringOnlyCode(val)) { - props[propKey] = handleStyleProp(val, node, context); + props[propKey] = handleStyleProp(val, node, context) } else if (propKey === reactSupport.classNameProp) { // Processing for both class and rt-class conveniently return strings that // represent JS expressions, each evaluating to a space-separated set of class names. // We can just join them with another space here. - const existing = props[propKey] ? `${props[propKey]} + " " + ` : ''; + const existing = props[propKey] ? `${props[propKey]} + " " + ` : '' if (key === classSetAttr) { - props[propKey] = existing + classSetTemplate({classSet: val}); + props[propKey] = existing + classSetTemplate({classSet: val}) } else if (key === classAttr || key === reactSupport.classNameProp) { - props[propKey] = existing + utils.convertText(node, context, val.trim()); + props[propKey] = existing + utils.convertText(node, context, val.trim()) } } else if (!_.startsWith(key, 'rt-')) { - props[propKey] = utils.convertText(node, context, val.trim()); + props[propKey] = utils.convertText(node, context, val.trim()) } - }); - _.assign(props, generateTemplateProps(node, context)); + }) + _.assign(props, generateTemplateProps(node, context)) // map 'className' back into 'class' for custom elements if (props[reactSupport.classNameProp] && isCustomElement(node.name)) { - props[classAttr] = props[reactSupport.classNameProp]; - delete props[reactSupport.classNameProp]; + props[classAttr] = props[reactSupport.classNameProp] + delete props[reactSupport.classNameProp] } - const propStr = _.map(props, (v, k) => `${JSON.stringify(k)} : ${v}`).join(','); - return `{${propStr}}`; + const propStr = _.map(props, (v, k) => `${JSON.stringify(k)} : ${v}`).join(',') + return `{${propStr}}` } function handleEventHandler(val, context, node, key) { - let handlerString; + let handlerString if (_.startsWith(val, 'this.')) { if (context.options.autobind) { - handlerString = `${val}.bind(this)`; + handlerString = `${val}.bind(this)` } else { - throw RTCodeError.build(context, node, "'this.handler' syntax allowed only when the --autobind is on, use {} to return a callback function."); + throw RTCodeError.build(context, node, "'this.handler' syntax allowed only when the --autobind is on, use {} to return a callback function.") } } else { - const funcParts = val.split('=>'); + const funcParts = val.split('=>') if (funcParts.length !== 2) { - throw RTCodeError.build(context, node, `when using 'on' events, use lambda '(p1,p2)=>body' notation or 'this.handler'; otherwise use {} to return a callback function. error: [${key}='${val}']`); + throw RTCodeError.build(context, node, `when using 'on' events, use lambda '(p1,p2)=>body' notation or 'this.handler'; otherwise use {} to return a callback function. error: [${key}='${val}']`) } - const evtParams = funcParts[0].replace('(', '').replace(')', '').trim(); - const funcBody = funcParts[1].trim(); - let params = context.boundParams; + const evtParams = funcParts[0].replace('(', '').replace(')', '').trim() + const funcBody = funcParts[1].trim() + let params = context.boundParams if (evtParams.trim() !== '') { - params = params.concat([evtParams.trim()]); + params = params.concat([evtParams.trim()]) } - const generatedFuncName = generateInjectedFunc(context, key, funcBody, params); - handlerString = genBind(generatedFuncName, context.boundParams); + const generatedFuncName = generateInjectedFunc(context, key, funcBody, params) + handlerString = genBind(generatedFuncName, context.boundParams) } - return handlerString; + return handlerString } function genBind(func, args) { - const bindArgs = ['this'].concat(args); - return `${func}.bind(${bindArgs.join(',')})`; + const bindArgs = ['this'].concat(args) + return `${func}.bind(${bindArgs.join(',')})` } function handleStyleProp(val, node, context) { @@ -246,17 +246,17 @@ function handleStyleProp(val, node, context) { .map(_.trim) .filter(i => _.includes(i, ':')) .map(i => { - const pair = i.split(':'); - const key = pair[0].trim(); + const pair = i.split(':') + const key = pair[0].trim() if (/\{|}/g.test(key)) { - throw RTCodeError.build(context, node, 'style attribute keys cannot contain { } expressions'); + throw RTCodeError.build(context, node, 'style attribute keys cannot contain { } expressions') } - const value = pair.slice(1).join(':').trim(); - const parsedKey = /(^-moz-)|(^-o-)|(^-webkit-)/ig.test(key) ? _.upperFirst(_.camelCase(key)) : _.camelCase(key); - return parsedKey + ' : ' + utils.convertText(node, context, value.trim()); + const value = pair.slice(1).join(':').trim() + const parsedKey = /(^-moz-)|(^-o-)|(^-webkit-)/ig.test(key) ? _.upperFirst(_.camelCase(key)) : _.camelCase(key) + return parsedKey + ' : ' + utils.convertText(node, context, value.trim()) }) - .join(','); - return `{${styleStr}}`; + .join(',') + return `{${styleStr}}` } /** @@ -266,19 +266,19 @@ function handleStyleProp(val, node, context) { */ function convertTagNameToConstructor(tagName, context) { if (context.options.native) { - const targetSupport = reactNativeSupport[context.options.nativeTargetVersion]; - return _.includes(targetSupport.components, tagName) ? `${targetSupport.reactNative.name}.${tagName}` : tagName; + const targetSupport = reactNativeSupport[context.options.nativeTargetVersion] + return _.includes(targetSupport.components, tagName) ? `${targetSupport.reactNative.name}.${tagName}` : tagName } - let isHtmlTag = _.includes(reactDOMSupport[context.options.targetVersion], tagName) || isCustomElement(tagName); + let isHtmlTag = _.includes(reactDOMSupport[context.options.targetVersion], tagName) || isCustomElement(tagName) if (reactSupport.shouldUseCreateElement(context)) { - isHtmlTag = isHtmlTag || tagName.match(/^\w+(-\w+)+$/); - return isHtmlTag ? `'${tagName}'` : tagName; + isHtmlTag = isHtmlTag || tagName.match(/^\w+(-\w+)+$/) + return isHtmlTag ? `'${tagName}'` : tagName } - return isHtmlTag ? `React.DOM.${tagName}` : tagName; + return isHtmlTag ? `React.DOM.${tagName}` : tagName } function isCustomElement(tagName) { - return tagName.match(/^\w+(-\w+)+$/); + return tagName.match(/^\w+(-\w+)+$/) } /** @@ -291,11 +291,11 @@ function defaultContext(html, options, reportContext) { const defaultDefines = [ {moduleName: options.reactImportPath, alias: 'React', member: '*'}, {moduleName: options.lodashImportPath, alias: '_', member: '*'} - ]; + ] if (options.native) { - const targetSupport = reactNativeSupport[options.nativeTargetVersion]; + const targetSupport = reactNativeSupport[options.nativeTargetVersion] if (targetSupport.reactNative.module !== targetSupport.react.module) { - defaultDefines.splice(0, 0, {moduleName: targetSupport.reactNative.module, alias: targetSupport.reactNative.name, member: '*'}); + defaultDefines.splice(0, 0, {moduleName: targetSupport.reactNative.module, alias: targetSupport.reactNative.name, member: '*'}) } } return { @@ -305,7 +305,7 @@ function defaultContext(html, options, reportContext) { options, defines: options.defines ? _.clone(options.defines) : defaultDefines, reportContext - }; + } } /** @@ -313,7 +313,7 @@ function defaultContext(html, options, reportContext) { * @return {boolean} */ function hasNonSimpleChildren(node) { - return _.some(node.children, child => child.type === 'tag' && child.attribs[repeatAttr]); + return _.some(node.children, child => child.type === 'tag' && child.attribs[repeatAttr]) } /** @@ -322,7 +322,7 @@ function hasNonSimpleChildren(node) { * @return {string} */ function trimHtmlText(text) { - return text.replace(/^[ \f\n\r\t\v\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+|[ \f\n\r\t\v\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+$/g, ''); + return text.replace(/^[ \f\n\r\t\v\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+|[ \f\n\r\t\v\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+$/g, '') } /** @@ -334,84 +334,84 @@ function convertHtmlToReact(node, context) { if (node.type === 'tag' || node.type === 'style') { context = _.defaults({ boundParams: _.clone(context.boundParams) - }, context); + }, context) if (node.type === 'tag' && node.name === importAttr) { - throw RTCodeError.build(context, node, "'rt-import' must be a toplevel node"); + throw RTCodeError.build(context, node, "'rt-import' must be a toplevel node") } if (node.type === 'tag' && node.name === includeNode) { - const srcFile = node.attribs[includeSrcAttr]; + const srcFile = node.attribs[includeSrcAttr] if (!srcFile) { - throw RTCodeError.build(context, node, 'rt-include must supply a source attribute'); + throw RTCodeError.build(context, node, 'rt-include must supply a source attribute') } if (!context.options.readFileSync) { - throw RTCodeError.build(context, node, 'rt-include needs a readFileSync polyfill on options'); + throw RTCodeError.build(context, node, 'rt-include needs a readFileSync polyfill on options') } try { - context.html = context.options.readFileSync(srcFile); + context.html = context.options.readFileSync(srcFile) } catch (e) { - console.error(e); - throw RTCodeError.build(context, node, `rt-include failed to read file '${srcFile}'`); + console.error(e) + throw RTCodeError.build(context, node, `rt-include failed to read file '${srcFile}'`) } - return parseAndConvertHtmlToReact(context.html, context); + return parseAndConvertHtmlToReact(context.html, context) } - const data = {name: convertTagNameToConstructor(node.name, context)}; + const data = {name: convertTagNameToConstructor(node.name, context)} // Order matters. We need to add the item and itemIndex to context.boundParams before // the rt-scope directive is processed, lest they are not passed to the child scopes if (node.attribs[repeatAttr]) { - const arr = node.attribs[repeatAttr].split(' in '); + const arr = node.attribs[repeatAttr].split(' in ') if (arr.length !== 2) { - throw RTCodeError.build(context, node, `rt-repeat invalid 'in' expression '${node.attribs[repeatAttr]}'`); + throw RTCodeError.build(context, node, `rt-repeat invalid 'in' expression '${node.attribs[repeatAttr]}'`) } - const repeaterParams = arr[0].split(',').map(s => s.trim()); - data.item = repeaterParams[0]; - data.index = repeaterParams[1] || `${data.item}Index`; - data.collection = arr[1].trim(); - const bindParams = [data.item, data.index]; + const repeaterParams = arr[0].split(',').map(s => s.trim()) + data.item = repeaterParams[0] + data.index = repeaterParams[1] || `${data.item}Index` + data.collection = arr[1].trim() + const bindParams = [data.item, data.index] _.forEach(bindParams, param => { - validateJS(param, node, context); - }); - validateJS(`(${data.collection})`, node, context); + validateJS(param, node, context) + }) + validateJS(`(${data.collection})`, node, context) _.forEach(bindParams, param => { if (!_.includes(context.boundParams, param)) { - context.boundParams.push(param); + context.boundParams.push(param) } - }); + }) } if (node.attribs[scopeAttr]) { - handleScopeAttribute(node, context, data); + handleScopeAttribute(node, context, data) } if (node.attribs[ifAttr]) { - validateIfAttribute(node, context, data); - data.condition = node.attribs[ifAttr].trim(); + validateIfAttribute(node, context, data) + data.condition = node.attribs[ifAttr].trim() if (!node.attribs.key && node.name !== virtualNode) { - _.set(node, ['attribs', 'key'], `${node.startIndex}`); + _.set(node, ['attribs', 'key'], `${node.startIndex}`) } } - data.props = generateProps(node, context); + data.props = generateProps(node, context) if (node.attribs[propsAttr]) { if (data.props === '{}') { - data.props = node.attribs[propsAttr]; + data.props = node.attribs[propsAttr] } else if (!node.attribs.style && !node.attribs.class) { - data.props = propsTemplateSimple({generatedProps: data.props, rtProps: node.attribs[propsAttr]}); + data.props = propsTemplateSimple({generatedProps: data.props, rtProps: node.attribs[propsAttr]}) } else { - data.props = propsTemplate({generatedProps: data.props, rtProps: node.attribs[propsAttr]}); + data.props = propsTemplate({generatedProps: data.props, rtProps: node.attribs[propsAttr]}) if (!_.includes(context.injectedFunctions, propsMergeFunction)) { - context.injectedFunctions.push(propsMergeFunction); + context.injectedFunctions.push(propsMergeFunction) } } } if (node.name === virtualNode) { - const invalidAttributes = _.without(_.keys(node.attribs), scopeAttr, ifAttr, repeatAttr); + const invalidAttributes = _.without(_.keys(node.attribs), scopeAttr, ifAttr, repeatAttr) if (invalidAttributes.length > 0) { - throw RTCodeError.build(context, node, " may not contain attributes other than 'rt-scope', 'rt-if' and 'rt-repeat'"); + throw RTCodeError.build(context, node, " may not contain attributes other than 'rt-scope', 'rt-if' and 'rt-repeat'") } // provide a key to virtual node children if missing @@ -420,52 +420,52 @@ function convertHtmlToReact(node, context) { .reject('attribs.key') .forEach((child, i) => { if (child.type === 'tag' && child.name !== virtualNode) { - _.set(child, ['attribs', 'key'], `${node.startIndex}${i}`); + _.set(child, ['attribs', 'key'], `${node.startIndex}${i}`) } - }); + }) } } const children = _.map(node.children, child => { - const code = convertHtmlToReact(child, context); - validateJS(code, child, context); - return code; - }); + const code = convertHtmlToReact(child, context) + validateJS(code, child, context) + return code + }) - data.children = utils.concatChildren(children); + data.children = utils.concatChildren(children) if (node.name === virtualNode) { //eslint-disable-line wix-editor/prefer-ternary - data.body = `[${_.compact(children).join(',')}]`; + data.body = `[${_.compact(children).join(',')}]` } else { - data.body = _.template(getTagTemplateString(!hasNonSimpleChildren(node), reactSupport.shouldUseCreateElement(context)))(data); + data.body = _.template(getTagTemplateString(!hasNonSimpleChildren(node), reactSupport.shouldUseCreateElement(context)))(data) } if (node.attribs[scopeAttr]) { - const functionBody = _.values(data.innerScope.innerMapping).join('\n') + `return ${data.body}`; - const generatedFuncName = generateInjectedFunc(context, 'scope' + data.innerScope.scopeName, functionBody, _.keys(data.innerScope.outerMapping)); - data.body = `${generatedFuncName}.apply(this, [${_.values(data.innerScope.outerMapping).join(',')}])`; + const functionBody = _.values(data.innerScope.innerMapping).join('\n') + `return ${data.body}` + const generatedFuncName = generateInjectedFunc(context, 'scope' + data.innerScope.scopeName, functionBody, _.keys(data.innerScope.outerMapping)) + data.body = `${generatedFuncName}.apply(this, [${_.values(data.innerScope.outerMapping).join(',')}])` } // Order matters here. Each rt-repeat iteration wraps over the rt-scope, so // the scope variables are evaluated in context of the current iteration. if (node.attribs[repeatAttr]) { - data.repeatFunction = generateInjectedFunc(context, 'repeat' + _.upperFirst(data.item), 'return ' + data.body); - data.repeatBinds = ['this'].concat(_.reject(context.boundParams, p => p === data.item || p === data.index || data.innerScope && p in data.innerScope.innerMapping)); - data.body = repeatTemplate(data); + data.repeatFunction = generateInjectedFunc(context, 'repeat' + _.upperFirst(data.item), 'return ' + data.body) + data.repeatBinds = ['this'].concat(_.reject(context.boundParams, p => p === data.item || p === data.index || data.innerScope && p in data.innerScope.innerMapping)) + data.body = repeatTemplate(data) } if (node.attribs[ifAttr]) { - data.body = ifTemplate(data); + data.body = ifTemplate(data) } - return data.body; + return data.body } else if (node.type === 'comment') { - const sanitizedComment = node.data.split('*/').join('* /'); - return commentTemplate({data: sanitizedComment}); + const sanitizedComment = node.data.split('*/').join('* /') + return commentTemplate({data: sanitizedComment}) } else if (node.type === 'text') { - const parentNode = node.parent; - const overrideNormalize = parentNode !== undefined && (parentNode.name === 'pre' || parentNode.name === 'textarea' || _.has(parentNode.attribs, preAttr)); - const normalizeWhitespaces = context.options.normalizeHtmlWhitespace && !overrideNormalize; - const text = node.data; - return trimHtmlText(text) ? utils.convertText(node, context, text, normalizeWhitespaces) : ''; + const parentNode = node.parent + const overrideNormalize = parentNode !== undefined && (parentNode.name === 'pre' || parentNode.name === 'textarea' || _.has(parentNode.attribs, preAttr)) + const normalizeWhitespaces = context.options.normalizeHtmlWhitespace && !overrideNormalize + const text = node.data + return trimHtmlText(text) ? utils.convertText(node, context, text, normalizeWhitespaces) : '' } } @@ -490,21 +490,21 @@ function parseScopeSyntax(text) { // // regex = capture(expression) + as + capture(id) + optional_spaces + semicolon + optional_spaces - const regex = RegExp("((?:(?:\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"|'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'|[^\"']*?))*?) as(?: )+([$_a-zA-Z]+[$_a-zA-Z0-9]*)(?: )*(?:;|$)(?: )*", 'g'); - const res = []; + const regex = RegExp("((?:(?:\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"|'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'|[^\"']*?))*?) as(?: )+([$_a-zA-Z]+[$_a-zA-Z0-9]*)(?: )*(?:;|$)(?: )*", 'g') + const res = [] do { - const idx = regex.lastIndex; - const match = regex.exec(text); + const idx = regex.lastIndex + const match = regex.exec(text) if (regex.lastIndex === idx || match === null) { - throw text.substr(idx); + throw text.substr(idx) } if (match.index === regex.lastIndex) { - regex.lastIndex++; + regex.lastIndex++ } - res.push({expression: match[1].trim(), identifier: match[2]}); - } while (regex.lastIndex < text.length); + res.push({expression: match[1].trim(), identifier: match[2]}) + } while (regex.lastIndex < text.length) - return res; + return res } function handleScopeAttribute(node, context, data) { @@ -512,110 +512,110 @@ function handleScopeAttribute(node, context, data) { scopeName: '', innerMapping: {}, outerMapping: {} - }; + } - data.innerScope.outerMapping = _.zipObject(context.boundParams, context.boundParams); + data.innerScope.outerMapping = _.zipObject(context.boundParams, context.boundParams) - let scopes; + let scopes try { - scopes = parseScopeSyntax(node.attribs[scopeAttr]); + scopes = parseScopeSyntax(node.attribs[scopeAttr]) } catch (scopePart) { - throw RTCodeError.build(context, node, `invalid scope part '${scopePart}'`); + throw RTCodeError.build(context, node, `invalid scope part '${scopePart}'`) } scopes.forEach(({expression, identifier}) => { - validateJS(identifier, node, context); + validateJS(identifier, node, context) // this adds both parameters to the list of parameters passed further down // the scope chain, as well as variables that are locally bound before any // function call, as with the ones we generate for rt-scope. if (!_.includes(context.boundParams, identifier)) { - context.boundParams.push(identifier); + context.boundParams.push(identifier) } - data.innerScope.scopeName += _.upperFirst(identifier); - data.innerScope.innerMapping[identifier] = `var ${identifier} = ${expression};`; - validateJS(data.innerScope.innerMapping[identifier], node, context); - }); + data.innerScope.scopeName += _.upperFirst(identifier) + data.innerScope.innerMapping[identifier] = `var ${identifier} = ${expression};` + validateJS(data.innerScope.innerMapping[identifier], node, context) + }) } function validateIfAttribute(node, context, data) { - const innerMappingKeys = _.keys(data.innerScope && data.innerScope.innerMapping || {}); - let ifAttributeTree = null; + const innerMappingKeys = _.keys(data.innerScope && data.innerScope.innerMapping || {}) + let ifAttributeTree = null try { - ifAttributeTree = esprima.parse(node.attribs[ifAttr]); + ifAttributeTree = esprima.parse(node.attribs[ifAttr]) } catch (e) { - throw new RTCodeError(e.message, e.index, -1); + throw new RTCodeError(e.message, e.index, -1) } if (ifAttributeTree && ifAttributeTree.body && ifAttributeTree.body.length === 1 && ifAttributeTree.body[0].type === 'ExpressionStatement') { // make sure that rt-if does not use an inner mapping if (ifAttributeTree.body[0].expression && utils.usesScopeName(innerMappingKeys, ifAttributeTree.body[0].expression)) { - throw RTCodeError.buildFormat(context, node, "invalid scope mapping used in if part '%s'", node.attribs[ifAttr]); + throw RTCodeError.buildFormat(context, node, "invalid scope mapping used in if part '%s'", node.attribs[ifAttr]) } } else { - throw RTCodeError.buildFormat(context, node, "invalid if part '%s'", node.attribs[ifAttr]); + throw RTCodeError.buildFormat(context, node, "invalid if part '%s'", node.attribs[ifAttr]) } } function handleSelfClosingHtmlTags(nodes) { return _.flatMap(nodes, node => { - let externalNodes = []; - node.children = handleSelfClosingHtmlTags(node.children); + let externalNodes = [] + node.children = handleSelfClosingHtmlTags(node.children) if (node.type === 'tag' && (_.includes(reactSupport.htmlSelfClosingTags, node.name) || _.includes(reactTemplatesSelfClosingTags, node.name))) { - externalNodes = _.filter(node.children, {type: 'tag'}); - _.forEach(externalNodes, i => {i.parent = node;}); - node.children = _.reject(node.children, {type: 'tag'}); + externalNodes = _.filter(node.children, {type: 'tag'}) + _.forEach(externalNodes, i => {i.parent = node}) + node.children = _.reject(node.children, {type: 'tag'}) } - return [node].concat(externalNodes); - }); + return [node].concat(externalNodes) + }) } function handleRequire(tag, context) { - let moduleName; - let alias; - let member; + let moduleName + let alias + let member if (tag.children.length) { - throw RTCodeError.build(context, tag, `'${requireAttr}' may have no children`); + throw RTCodeError.build(context, tag, `'${requireAttr}' may have no children`) } else if (tag.attribs.dependency && tag.attribs.as) { - moduleName = tag.attribs.dependency; - member = '*'; - alias = tag.attribs.as; + moduleName = tag.attribs.dependency + member = '*' + alias = tag.attribs.as } if (!moduleName) { - throw RTCodeError.build(context, tag, `'${requireAttr}' needs 'dependency' and 'as' attributes`); + throw RTCodeError.build(context, tag, `'${requireAttr}' needs 'dependency' and 'as' attributes`) } - context.defines.push({moduleName, member, alias}); + context.defines.push({moduleName, member, alias}) } function handleImport(tag, context) { - let moduleName; - let alias; - let member; + let moduleName + let alias + let member if (tag.children.length) { - throw RTCodeError.build(context, tag, `'${importAttr}' may have no children`); + throw RTCodeError.build(context, tag, `'${importAttr}' may have no children`) } else if (tag.attribs.name && tag.attribs.from) { - moduleName = tag.attribs.from; - member = tag.attribs.name; - alias = tag.attribs.as; + moduleName = tag.attribs.from + member = tag.attribs.name + alias = tag.attribs.as if (!alias) { if (member === '*') { - throw RTCodeError.build(context, tag, "'*' imports must have an 'as' attribute"); + throw RTCodeError.build(context, tag, "'*' imports must have an 'as' attribute") } else if (member === 'default') { - throw RTCodeError.build(context, tag, "default imports must have an 'as' attribute"); + throw RTCodeError.build(context, tag, "default imports must have an 'as' attribute") } - alias = member; + alias = member } } if (!moduleName) { - throw RTCodeError.build(context, tag, `'${importAttr}' needs 'name' and 'from' attributes`); + throw RTCodeError.build(context, tag, `'${importAttr}' needs 'name' and 'from' attributes`) } - context.defines.push({moduleName, member, alias}); + context.defines.push({moduleName, member, alias}) } function convertTemplateToReact(html, options) { - const context = require('./context'); - return convertRT(html, context, options); + const context = require('./context') + return convertRT(html, context, options) } function parseAndConvertHtmlToReact(html, context) { @@ -624,36 +624,36 @@ function parseAndConvertHtmlToReact(html, context) { lowerCaseAttributeNames: false, xmlMode: true, withStartIndices: true - }); - utils.validate(context.options, context, context.reportContext, rootNode.root()[0]); - let rootTags = _.filter(rootNode.root()[0].children, {type: 'tag'}); - rootTags = handleSelfClosingHtmlTags(rootTags); + }) + utils.validate(context.options, context, context.reportContext, rootNode.root()[0]) + let rootTags = _.filter(rootNode.root()[0].children, {type: 'tag'}) + rootTags = handleSelfClosingHtmlTags(rootTags) if (!rootTags || rootTags.length === 0) { - throw new RTCodeError('Document should have a root element'); + throw new RTCodeError('Document should have a root element') } - let firstTag = null; + let firstTag = null _.forEach(rootTags, tag => { if (tag.name === requireAttr) { - handleRequire(tag, context); + handleRequire(tag, context) } else if (tag.name === importAttr) { - handleImport(tag, context); + handleImport(tag, context) } else if (firstTag === null) { - firstTag = tag; + firstTag = tag if (_.hasIn(tag, ['attribs', statelessAttr])) { - context.stateless = true; + context.stateless = true } } else { - throw RTCodeError.build(context, tag, 'Document should have no more than a single root element'); + throw RTCodeError.build(context, tag, 'Document should have no more than a single root element') } - }); + }) if (firstTag === null) { - throw RTCodeError.build(context, rootNode.root()[0], 'Document should have a single root element'); + throw RTCodeError.build(context, rootNode.root()[0], 'Document should have a single root element') } else if (firstTag.name === virtualNode) { - throw RTCodeError.build(context, firstTag, `Document should not have <${virtualNode}> as root element`); + throw RTCodeError.build(context, firstTag, `Document should not have <${virtualNode}> as root element`) } else if (_.includes(_.keys(firstTag.attribs), repeatAttr)) { - throw RTCodeError.build(context, firstTag, "root element may not have a 'rt-repeat' attribute"); + throw RTCodeError.build(context, firstTag, "root element may not have a 'rt-repeat' attribute") } - return convertHtmlToReact(firstTag, context); + return convertHtmlToReact(firstTag, context) } /** @@ -663,22 +663,22 @@ function parseAndConvertHtmlToReact(html, context) { * @return {string} */ function convertRT(html, reportContext, options) { - options = getOptions(options); + options = getOptions(options) - const context = defaultContext(html, options, reportContext); - const body = parseAndConvertHtmlToReact(html, context); - const injectedFunctions = context.injectedFunctions.join('\n'); - const statelessParams = context.stateless ? 'props, context' : ''; - const renderFunction = `function(${statelessParams}) { ${injectedFunctions}return ${body} }`; + const context = defaultContext(html, options, reportContext) + const body = parseAndConvertHtmlToReact(html, context) + const injectedFunctions = context.injectedFunctions.join('\n') + const statelessParams = context.stateless ? 'props, context' : '' + const renderFunction = `function(${statelessParams}) { ${injectedFunctions}return ${body} }` - const requirePaths = _.map(context.defines, d => `"${d.moduleName}"`).join(','); - const requireNames = _.map(context.defines, d => `${d.alias}`).join(','); - const AMDArguments = _.map(context.defines, (d, i) => (d.member === '*' ? `${d.alias}` : `$${i}`)).join(','); //eslint-disable-line - const AMDSubstitutions = _.map(context.defines, (d, i) => (d.member === '*' ? null : `var ${d.alias} = $${i}.${d.member};`)).join('\n'); //eslint-disable-line - const buildImport = reactSupport.buildImport[options.modules] || reactSupport.buildImport.commonjs; - const requires = _.map(context.defines, buildImport).join('\n'); - const header = options.flow ? '/* @flow */\n' : ''; - const vars = header + requires; + const requirePaths = _.map(context.defines, d => `"${d.moduleName}"`).join(',') + const requireNames = _.map(context.defines, d => `${d.alias}`).join(',') + const AMDArguments = _.map(context.defines, (d, i) => d.member === '*' ? `${d.alias}` : `$${i}`).join(',') + const AMDSubstitutions = _.map(context.defines, (d, i) => d.member === '*' ? null : `var ${d.alias} = $${i}.${d.member};`).join('\n') + const buildImport = reactSupport.buildImport[options.modules] || reactSupport.buildImport.commonjs + const requires = _.map(context.defines, buildImport).join('\n') + const header = options.flow ? '/* @flow */\n' : '' + const vars = header + requires const data = { renderFunction, requireNames, @@ -687,37 +687,37 @@ function convertRT(html, reportContext, options) { AMDSubstitutions, vars, name: options.name - }; - let code = templates[options.modules](data); - if (options.modules !== 'typescript' && options.modules !== 'jsrt') { - code = parseJS(code, options); } - return code; + let code = templates[options.modules](data) + if (options.modules !== 'typescript' && options.modules !== 'jsrt') { + code = parseJS(code, options) + } + return code } function parseJS(code, options) { try { - let tree = esprima.parse(code, {range: true, tokens: true, comment: true, sourceType: 'module'}); + let tree = esprima.parse(code, {range: true, tokens: true, comment: true, sourceType: 'module'}) // fix for https://github.com/wix/react-templates/issues/157 // do not include comments for es6 modules due to bug in dependency "escodegen" // to be removed when https://github.com/estools/escodegen/issues/263 will be fixed // remove also its test case "test/data/comment.rt.es6.js" if (options.modules !== 'es6') { - tree = escodegen.attachComments(tree, tree.comments, tree.tokens); + tree = escodegen.attachComments(tree, tree.comments, tree.tokens) } - return escodegen.generate(tree, {comment: true}); + return escodegen.generate(tree, {comment: true}) } catch (e) { - throw new RTCodeError(e.message, e.index, -1); + throw new RTCodeError(e.message, e.index, -1) } } function convertJSRTToJS(text, reportContext, options) { - options = getOptions(options); - options.modules = 'jsrt'; - const templateMatcherJSRT = /