mirror of
https://github.com/bobwen-dev/react-templates
synced 2025-04-12 00:56:39 +02:00
no semi
This commit is contained in:
parent
8e149352a7
commit
ee4508aea3
@ -7,6 +7,7 @@ playground/**/*.rt.js
|
||||
playground/dist/**
|
||||
playground/libs/**
|
||||
|
||||
playground2/**
|
||||
playground3/**
|
||||
playground3/dist/**
|
||||
playground3/libs/**
|
||||
|
@ -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,
|
||||
|
44
Gruntfile.js
44
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'])
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
};
|
||||
});
|
||||
}
|
||||
})
|
||||
|
@ -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()
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
@ -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()
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
@ -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()
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
@ -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
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
@ -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'))
|
||||
})
|
||||
|
@ -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
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
@ -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'))
|
||||
})
|
||||
|
@ -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 = '<div></div>';
|
||||
var templateHTML = '<div></div>'
|
||||
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
|
||||
})
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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.<string>} 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
|
||||
};
|
||||
}
|
||||
|
50
src/api.js
50
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: {}
|
||||
};
|
||||
}
|
||||
|
86
src/cli.js
86
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
|
||||
};
|
||||
}
|
||||
|
@ -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.<MESSAGE>, options:Options, messages: Array.<MESSAGE>}} 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
|
||||
|
@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
'use strict'
|
||||
module.exports = function (results/*, config*/) {
|
||||
return JSON.stringify(results, undefined, 2);
|
||||
};
|
||||
return JSON.stringify(results, undefined, 2)
|
||||
}
|
@ -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 : ''
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -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 <filename|glob> [<filename|glob> ...] [<args>]`,
|
||||
default: 'false',
|
||||
description: 'Automatically bind event handlers to components'
|
||||
}]
|
||||
});
|
||||
})
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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: {}
|
||||
};
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -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, "<rt-virtual> may not contain attributes other than 'rt-scope', 'rt-if' and 'rt-repeat'");
|
||||
throw RTCodeError.build(context, node, "<rt-virtual> 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 = /<template>([^]*?)<\/template>/gm;
|
||||
const code = text.replace(templateMatcherJSRT, (template, html) => convertRT(html, reportContext, options).replace(/;$/, ''));
|
||||
options = getOptions(options)
|
||||
options.modules = 'jsrt'
|
||||
const templateMatcherJSRT = /<template>([^]*?)<\/template>/gm
|
||||
const code = text.replace(templateMatcherJSRT, (template, html) => convertRT(html, reportContext, options).replace(/;$/, ''))
|
||||
|
||||
return parseJS(code, options);
|
||||
return parseJS(code, options)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@ -726,4 +726,4 @@ module.exports = {
|
||||
convertJSRTToJS,
|
||||
RTCodeError,
|
||||
normalizeName: utils.normalizeName
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
'use strict'
|
||||
const map = {
|
||||
/*flex*/
|
||||
alignItems: 'string', // "enum('flex-start', 'flex-end', 'center', 'stretch')",
|
||||
@ -42,6 +42,6 @@ const map = {
|
||||
overflow: 'string', // enum('visible', 'hidden')
|
||||
tintColor: 'string',
|
||||
opacity: 'number'
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = map;
|
||||
module.exports = map
|
||||
|
@ -1,47 +1,47 @@
|
||||
'use strict';
|
||||
const css = require('css');
|
||||
const _ = require('lodash');
|
||||
const rtnData = require('./rt-style-support-data.js');
|
||||
'use strict'
|
||||
const css = require('css')
|
||||
const _ = require('lodash')
|
||||
const rtnData = require('./rt-style-support-data.js')
|
||||
|
||||
|
||||
const templateCommonJSTemplate = _.template(
|
||||
`'use strict';
|
||||
var style = <%= body %>;
|
||||
module.exports = style;
|
||||
`);
|
||||
`)
|
||||
|
||||
function convert(text) {
|
||||
return templateCommonJSTemplate({body: convertBody(text)});
|
||||
return templateCommonJSTemplate({body: convertBody(text)})
|
||||
}
|
||||
|
||||
function convertBody(text) {
|
||||
//source
|
||||
const obj = css.parse(text, {silent: false});
|
||||
const result = _.reduce(obj.stylesheet.rules, processRule2, {});
|
||||
return JSON.stringify(result, undefined, 2);
|
||||
const obj = css.parse(text, {silent: false})
|
||||
const result = _.reduce(obj.stylesheet.rules, processRule2, {})
|
||||
return JSON.stringify(result, undefined, 2)
|
||||
}
|
||||
|
||||
function processRule2(result, rule) {
|
||||
const name = rule.selectors[0].substring(1);
|
||||
result[name] = _.reduce(rule.declarations, processDeclaration, {});
|
||||
return result;
|
||||
const name = rule.selectors[0].substring(1)
|
||||
result[name] = _.reduce(rule.declarations, processDeclaration, {})
|
||||
return result
|
||||
}
|
||||
|
||||
function processDeclaration(result, dec) {
|
||||
const prop = _.camelCase(dec.property);
|
||||
result[prop] = convertValue(prop, dec.value);
|
||||
return result;
|
||||
const prop = _.camelCase(dec.property)
|
||||
result[prop] = convertValue(prop, dec.value)
|
||||
return result
|
||||
}
|
||||
|
||||
function convertValue(p, v) {
|
||||
if (rtnData[p] === 'string') {
|
||||
return v;
|
||||
return v
|
||||
}
|
||||
// TODO remove units
|
||||
return parseInt(v.match(/(\d+)/g)[0], 10);
|
||||
return parseInt(v.match(/(\d+)/g)[0], 10)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
convert,
|
||||
convertBody
|
||||
};
|
||||
}
|
||||
|
16
src/shell.js
16
src/shell.js
@ -1,16 +1,16 @@
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
'use strict'
|
||||
const _ = require('lodash')
|
||||
|
||||
/**
|
||||
* @param {CONTEXT} context
|
||||
* @return {number}
|
||||
*/
|
||||
function printResults(context) {
|
||||
const warnings = context.getMessages();
|
||||
const out = require(`./formatters/${context.options.format}`)(warnings);
|
||||
context.report(out);
|
||||
const grouped = _.groupBy(warnings, 'level');
|
||||
return grouped.ERROR ? grouped.ERROR.length : 0;
|
||||
const warnings = context.getMessages()
|
||||
const out = require(`./formatters/${context.options.format}`)(warnings)
|
||||
context.report(out)
|
||||
const grouped = _.groupBy(warnings, 'level')
|
||||
return grouped.ERROR ? grouped.ERROR.length : 0
|
||||
}
|
||||
|
||||
module.exports = {printResults};
|
||||
module.exports = {printResults}
|
||||
|
107
src/utils.js
107
src/utils.js
@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const esprima = require('esprima');
|
||||
const normalizeHtmlWhitespace = require('normalize-html-whitespace');
|
||||
const rtError = require('./RTCodeError');
|
||||
const RTCodeError = rtError.RTCodeError;
|
||||
'use strict'
|
||||
const _ = require('lodash')
|
||||
const esprima = require('esprima')
|
||||
const normalizeHtmlWhitespace = require('normalize-html-whitespace')
|
||||
const rtError = require('./RTCodeError')
|
||||
const RTCodeError = rtError.RTCodeError
|
||||
|
||||
/**
|
||||
* @param {string} code
|
||||
@ -12,9 +12,9 @@ const RTCodeError = rtError.RTCodeError;
|
||||
*/
|
||||
function validateJS(code, node, context) {
|
||||
try {
|
||||
esprima.parse(code);
|
||||
esprima.parse(code)
|
||||
} catch (e) {
|
||||
throw RTCodeError.build(context, node, e.description);
|
||||
throw RTCodeError.build(context, node, e.description)
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ function validateJS(code, node, context) {
|
||||
* @return {string}
|
||||
*/
|
||||
function normalizeName(name) {
|
||||
return name.replace(/-/g, '_');
|
||||
return name.replace(/-/g, '_')
|
||||
}
|
||||
|
||||
/**
|
||||
@ -31,7 +31,7 @@ function normalizeName(name) {
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isStringOnlyCode(txt) {
|
||||
return /^\s*\{.*}\s*$/g.test(txt);
|
||||
return /^\s*\{.*}\s*$/g.test(txt)
|
||||
//txt = txt.trim();
|
||||
//return txt.length && txt.charAt(0) === '{' && txt.charAt(txt.length - 1) === '}';
|
||||
}
|
||||
@ -42,7 +42,7 @@ function isStringOnlyCode(txt) {
|
||||
*/
|
||||
function addIfMissing(array, obj) {
|
||||
if (!_.includes(array, obj)) {
|
||||
array.push(obj);
|
||||
array.push(obj)
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,14 +51,14 @@ function addIfMissing(array, obj) {
|
||||
* @return {string}
|
||||
*/
|
||||
function concatChildren(children) {
|
||||
let res = '';
|
||||
let res = ''
|
||||
_.forEach(children, child => {
|
||||
if (child && !_.startsWith(child, ' /*')) {
|
||||
res += ',';
|
||||
res += ','
|
||||
}
|
||||
res += child;
|
||||
});
|
||||
return res;
|
||||
res += child
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,15 +70,16 @@ function concatChildren(children) {
|
||||
*/
|
||||
function validate(options, context, reportContext, node) {
|
||||
if (node.type === 'tag' && node.attribs['rt-if'] && !node.attribs.key) {
|
||||
const loc = rtError.getNodeLoc(context, node);
|
||||
reportContext.warn('rt-if without a key', options.fileName, loc.pos.line, loc.pos.col, loc.start, loc.end);
|
||||
const loc = rtError.getNodeLoc(context, node)
|
||||
reportContext.warn('rt-if without a key', options.fileName, loc.pos.line, loc.pos.col, loc.start, loc.end)
|
||||
}
|
||||
if (node.type === 'tag' && node.attribs['rt-require'] && (node.attribs.dependency || node.attribs.as)) {
|
||||
const loc = rtError.getNodeLoc(context, node);
|
||||
reportContext.warn("'rt-require' is obsolete, use 'rt-import' instead", options.fileName, loc.pos.line, loc.pos.col, loc.start, loc.end);
|
||||
const loc = rtError.getNodeLoc(context, node)
|
||||
reportContext.warn("'rt-require' is obsolete, use 'rt-import' instead", options.fileName, loc.pos.line, loc.pos.col, loc.start, loc.end)
|
||||
}
|
||||
// TODO check for duplicate import/require
|
||||
if (node.children) {
|
||||
node.children.forEach(validate.bind(this, options, context, reportContext));
|
||||
node.children.forEach(validate.bind(this, options, context, reportContext))
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,51 +90,51 @@ function validate(options, context, reportContext, node) {
|
||||
*/
|
||||
function usesScopeName(scopeNames, node) {
|
||||
function usesScope(root) {
|
||||
return usesScopeName(scopeNames, root);
|
||||
return usesScopeName(scopeNames, root)
|
||||
}
|
||||
if (_.isEmpty(scopeNames)) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
// rt-if="x"
|
||||
if (node.type === 'Identifier') {
|
||||
return _.includes(scopeNames, node.name);
|
||||
return _.includes(scopeNames, node.name)
|
||||
}
|
||||
// rt-if="e({key1: value1})"
|
||||
if (node.type === 'Property') {
|
||||
return usesScope(node.value);
|
||||
return usesScope(node.value)
|
||||
}
|
||||
// rt-if="e.x" or rt-if="e1[e2]"
|
||||
if (node.type === 'MemberExpression') {
|
||||
return node.computed ? usesScope(node.object) || usesScope(node.property) : usesScope(node.object);
|
||||
return node.computed ? usesScope(node.object) || usesScope(node.property) : usesScope(node.object)
|
||||
}
|
||||
// rt-if="!e"
|
||||
if (node.type === 'UnaryExpression') {
|
||||
return usesScope(node.argument);
|
||||
return usesScope(node.argument)
|
||||
}
|
||||
// rt-if="e1 || e2" or rt-if="e1 | e2"
|
||||
if (node.type === 'LogicalExpression' || node.type === 'BinaryExpression') {
|
||||
return usesScope(node.left) || usesScope(node.right);
|
||||
return usesScope(node.left) || usesScope(node.right)
|
||||
}
|
||||
// rt-if="e1(e2, ... eN)"
|
||||
if (node.type === 'CallExpression') {
|
||||
return usesScope(node.callee) || _.some(node.arguments, usesScope);
|
||||
return usesScope(node.callee) || _.some(node.arguments, usesScope)
|
||||
}
|
||||
// rt-if="f({e1: e2})"
|
||||
if (node.type === 'ObjectExpression') {
|
||||
return _.some(node.properties, usesScope);
|
||||
return _.some(node.properties, usesScope)
|
||||
}
|
||||
// rt-if="e1[e2]"
|
||||
if (node.type === 'ArrayExpression') {
|
||||
return _.some(node.elements, usesScope);
|
||||
return _.some(node.elements, usesScope)
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
const curlyMap = {'{': 1, '}': -1};
|
||||
const curlyMap = {'{': 1, '}': -1}
|
||||
|
||||
/**
|
||||
* @typedef {{boundParams: Array.<string>, injectedFunctions: Array.<string>, html: string, options: *}} Context
|
||||
@ -152,39 +153,39 @@ const curlyMap = {'{': 1, '}': -1};
|
||||
*/
|
||||
function convertText(node, context, txt, normalizeWhitespaces) {
|
||||
function jsonText(text) {
|
||||
return JSON.stringify(normalizeWhitespaces ? normalizeHtmlWhitespace(text) : text);
|
||||
return JSON.stringify(normalizeWhitespaces ? normalizeHtmlWhitespace(text) : text)
|
||||
}
|
||||
let res = '';
|
||||
let first = true;
|
||||
const concatChar = node.type === 'text' ? ',' : '+';
|
||||
let res = ''
|
||||
let first = true
|
||||
const concatChar = node.type === 'text' ? ',' : '+'
|
||||
while (_.includes(txt, '{')) {
|
||||
const start = txt.indexOf('{');
|
||||
const pre = txt.substr(0, start);
|
||||
const start = txt.indexOf('{')
|
||||
const pre = txt.substr(0, start)
|
||||
if (pre) {
|
||||
res += (first ? '' : concatChar) + jsonText(pre);
|
||||
first = false;
|
||||
res += (first ? '' : concatChar) + jsonText(pre)
|
||||
first = false
|
||||
}
|
||||
let curlyCounter = 1;
|
||||
let end = start;
|
||||
let curlyCounter = 1
|
||||
let end = start
|
||||
while (++end < txt.length && curlyCounter > 0) {
|
||||
curlyCounter += curlyMap[txt.charAt(end)] || 0;
|
||||
curlyCounter += curlyMap[txt.charAt(end)] || 0
|
||||
}
|
||||
if (curlyCounter === 0) {
|
||||
const needsParens = start !== 0 || end !== txt.length - 1;
|
||||
res += (first ? '' : concatChar) + (needsParens ? '(' : '') + txt.substr(start + 1, end - start - 2) + (needsParens ? ')' : '');
|
||||
first = false;
|
||||
txt = txt.substr(end);
|
||||
const needsParens = start !== 0 || end !== txt.length - 1
|
||||
res += (first ? '' : concatChar) + (needsParens ? '(' : '') + txt.substr(start + 1, end - start - 2) + (needsParens ? ')' : '')
|
||||
first = false
|
||||
txt = txt.substr(end)
|
||||
} else {
|
||||
throw RTCodeError.build(context, node, `Failed to parse text '${txt}'`);
|
||||
throw RTCodeError.build(context, node, `Failed to parse text '${txt}'`)
|
||||
}
|
||||
}
|
||||
if (txt) {
|
||||
res += (first ? '' : concatChar) + jsonText(txt);
|
||||
res += (first ? '' : concatChar) + jsonText(txt)
|
||||
}
|
||||
if (res === '') {
|
||||
res = 'true';
|
||||
res = 'true'
|
||||
}
|
||||
return res;
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
@ -197,4 +198,4 @@ module.exports = {
|
||||
validate,
|
||||
addIfMissing,
|
||||
convertText
|
||||
};
|
||||
}
|
||||
|
@ -1,31 +1,31 @@
|
||||
'use strict';
|
||||
const fs = require('fs');
|
||||
const fsUtil = require('../../src/fsUtil');
|
||||
const path = require('path');
|
||||
'use strict'
|
||||
const fs = require('fs')
|
||||
const fsUtil = require('../../src/fsUtil')
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
runTests(test, dataPath) {
|
||||
test('test isStale', t => {
|
||||
const a = path.join(dataPath, 'a.tmp');
|
||||
const b = path.join(dataPath, 'b.tmp');
|
||||
const a = path.join(dataPath, 'a.tmp')
|
||||
const b = path.join(dataPath, 'b.tmp')
|
||||
|
||||
fs.writeFileSync(a, 'actual');
|
||||
fs.writeFileSync(b, 'actual');
|
||||
fs.writeFileSync(a, 'actual')
|
||||
fs.writeFileSync(b, 'actual')
|
||||
|
||||
const mtime1 = new Date(1995, 11, 17, 3, 24, 0);
|
||||
fs.utimesSync(a, mtime1, mtime1);
|
||||
const mtime1 = new Date(1995, 11, 17, 3, 24, 0)
|
||||
fs.utimesSync(a, mtime1, mtime1)
|
||||
|
||||
const mtime2 = new Date(1995, 11, 17, 3, 24, 1);
|
||||
fs.utimesSync(b, mtime2, mtime2);
|
||||
const mtime2 = new Date(1995, 11, 17, 3, 24, 1)
|
||||
fs.utimesSync(b, mtime2, mtime2)
|
||||
|
||||
let actual = fsUtil.isStale(a, b);
|
||||
t.equal(actual, false);
|
||||
actual = fsUtil.isStale(b, a);
|
||||
t.equal(actual, true);
|
||||
let actual = fsUtil.isStale(a, b)
|
||||
t.equal(actual, false)
|
||||
actual = fsUtil.isStale(b, a)
|
||||
t.equal(actual, true)
|
||||
|
||||
fs.unlinkSync(a);
|
||||
fs.unlinkSync(b);
|
||||
t.end();
|
||||
});
|
||||
fs.unlinkSync(a)
|
||||
fs.unlinkSync(b)
|
||||
t.end()
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
const reactTemplates = require('../../src/reactTemplates');
|
||||
const testUtils = require('./testUtils');
|
||||
const readFileNormalized = testUtils.readFileNormalized;
|
||||
const path = require('path');
|
||||
const fsUtil = require('../../src/fsUtil');
|
||||
const fs = require('fs');
|
||||
'use strict'
|
||||
const reactTemplates = require('../../src/reactTemplates')
|
||||
const testUtils = require('./testUtils')
|
||||
const readFileNormalized = testUtils.readFileNormalized
|
||||
const path = require('path')
|
||||
const fsUtil = require('../../src/fsUtil')
|
||||
const fs = require('fs')
|
||||
|
||||
module.exports = {
|
||||
runTests(test, dataPath) {
|
||||
@ -32,31 +32,31 @@ module.exports = {
|
||||
'scope-reserved-tokens.rt',
|
||||
'repeat-literal-collection.rt',
|
||||
'include.rt'
|
||||
];
|
||||
]
|
||||
|
||||
files.forEach(testFile => {
|
||||
const filename = path.join(dataPath, testFile);
|
||||
const filename = path.join(dataPath, testFile)
|
||||
const options = {
|
||||
readFileSync: fsUtil.createRelativeReadFileSync(filename),
|
||||
modules: 'amd'
|
||||
};
|
||||
let actual = '';
|
||||
let equal = false;
|
||||
}
|
||||
let actual = ''
|
||||
let equal = false
|
||||
try {
|
||||
const html = fs.readFileSync(filename).toString();
|
||||
const expected = testUtils.normalizeHtml(readFileNormalized(filename + '.html'));
|
||||
const code = reactTemplates.convertTemplateToReact(html, options).replace(/\r/g, '');
|
||||
actual = testUtils.normalizeHtml(testUtils.codeToHtml(code));
|
||||
equal = t.equal(actual, expected, `${testFile}`);
|
||||
const html = fs.readFileSync(filename).toString()
|
||||
const expected = testUtils.normalizeHtml(readFileNormalized(filename + '.html'))
|
||||
const code = reactTemplates.convertTemplateToReact(html, options).replace(/\r/g, '')
|
||||
actual = testUtils.normalizeHtml(testUtils.codeToHtml(code))
|
||||
equal = t.equal(actual, expected, `${testFile}`)
|
||||
} catch (e) {
|
||||
console.log(testFile, e);
|
||||
t.fail(e);
|
||||
console.log(testFile, e)
|
||||
t.fail(e)
|
||||
}
|
||||
if (!equal) {
|
||||
fs.writeFileSync(filename + '.actual.html', actual);
|
||||
fs.writeFileSync(filename + '.actual.html', actual)
|
||||
}
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,60 +1,62 @@
|
||||
'use strict';
|
||||
const reactTemplates = require('../../src/reactTemplates');
|
||||
const testUtils = require('./testUtils');
|
||||
const _ = require('lodash');
|
||||
const path = require('path');
|
||||
const RTCodeError = reactTemplates.RTCodeError;
|
||||
'use strict'
|
||||
const reactTemplates = require('../../src/reactTemplates')
|
||||
const testUtils = require('./testUtils')
|
||||
const _ = require('lodash')
|
||||
const path = require('path')
|
||||
const RTCodeError = reactTemplates.RTCodeError
|
||||
|
||||
const omitStack = err => _.omit(err, 'stack', 'toIssue');
|
||||
const omitStack = err => _.omit(err, 'stack', 'toIssue')
|
||||
|
||||
module.exports = {
|
||||
runTests(test, basePath) {
|
||||
const dataPath = path.resolve(basePath, 'invalid');
|
||||
const dataPath = path.resolve(basePath, 'invalid')
|
||||
const invalidFiles = [
|
||||
{file: 'if-with-scope/invalid-if-scope-1.rt', issue: new RTCodeError("invalid scope mapping used in if part 'this.bar(activeUsers.length)'", 0, 160, 1, 1)},
|
||||
{file: 'if-with-scope/invalid-if-scope-2.rt', issue: new RTCodeError("invalid scope mapping used in if part 'this.bar[activeUsers || 0]'", 0, 158, 1, 1)},
|
||||
{file: 'if-with-scope/invalid-if-scope-3.rt', issue: new RTCodeError("invalid scope mapping used in if part 'this.foo + activeUsers.length > this.bar'", 0, 172, 1, 1)},
|
||||
{file: 'if-with-scope/invalid-if-scope-4.rt', issue: new RTCodeError("invalid scope mapping used in if part 'getCurrentActiveUsers().length'", 0, 170, 1, 1)},
|
||||
{file: 'if-with-scope/invalid-if-scope-5.rt', issue: new RTCodeError("invalid scope mapping used in if part 'this.bar({activeUsers})'", 0, 155, 1, 1)},
|
||||
{file: 'invalid-scope.rt', issue: new RTCodeError("invalid scope part 'a in a in a'", 0, 35, 1, 1)},
|
||||
{file: 'invalid-html.rt', issue: new RTCodeError('Document should have a root element', -1, -1, -1, -1)},
|
||||
{file: 'invalid-exp.rt', issue: new RTCodeError("Failed to parse text '\n {z\n'", 5, 13, 1, 6)},
|
||||
{file: 'invalid-lambda.rt', issue: new RTCodeError("when using 'on' events, use lambda '(p1,p2)=>body' notation or 'this.handler'; otherwise use {} to return a callback function. error: [onClick='']", 0, 23, 1, 1)},
|
||||
{file: 'invalid-autobind.rt', issue: new RTCodeError("'this.handler' syntax allowed only when the --autobind is on, use {} to return a callback function.", 0, 132, 1, 1)},
|
||||
// {file: 'invalid-js.rt', issue: new RTCodeError('Unexpected token ILLEGAL', 0, 32, 1, 1)}, bug interduced due to scope parsing
|
||||
{file: 'invalid-single-root.rt', issue: new RTCodeError('Document should have no more than a single root element', 12, 23, 2, 1)},
|
||||
{file: 'invalid-repeat-1.rt', issue: new RTCodeError("rt-repeat invalid 'in' expression 'a in b in c'", 9, 44, 2, 4)},
|
||||
{file: 'invalid-repeat-2.rt', issue: new RTCodeError("root element may not have a 'rt-repeat' attribute", 0, 39, 1, 1)},
|
||||
{file: 'invalid-rt-require-1.rt', issue: new RTCodeError("'rt-require' needs 'dependency' and 'as' attributes", 0, 14, 1, 1)},
|
||||
{file: 'invalid-rt-require-2.rt', issue: new RTCodeError("'rt-require' may have no children", 0, 32, 1, 1)},
|
||||
{file: 'invalid-rt-import-1.rt', issue: new RTCodeError("'*' imports must have an 'as' attribute", 0, 36, 1, 1)},
|
||||
{file: 'invalid-rt-import-2.rt', issue: new RTCodeError("default imports must have an 'as' attribute", 0, 42, 1, 1)},
|
||||
{file: 'invalid-rt-import-3.rt', issue: new RTCodeError("'rt-import' needs 'name' and 'from' attributes", 0, 13, 1, 1)},
|
||||
{file: 'invalid-rt-import-4.rt', issue: new RTCodeError("'rt-import' must be a toplevel node", 9, 54, 2, 4)},
|
||||
{file: 'invalid-rt-template-1.rt', issue: new RTCodeError("'rt-template' should have a single non-text element as direct child", 9, 88, 2, 4)},
|
||||
{file: 'invalid-rt-template-2.rt', issue: new RTCodeError("'rt-template' should have a single non-text element as direct child", 9, 90, 2, 4)},
|
||||
{file: 'invalid-brace.rt', issue: new RTCodeError('Unexpected end of input', 128, 163, 5, 11)},
|
||||
{file: 'invalid-style-1.rt', issue: new RTCodeError('Unexpected token ILLEGAL', 10, 39, 2, 5)},
|
||||
{file: 'invalid-style-2.rt', issue: new RTCodeError('style attribute keys cannot contain { } expressions', 35, 68, 2, 5)},
|
||||
{file: 'invalid-virtual-1.rt', issue: new RTCodeError('Document should not have <rt-virtual> as root element', 0, 60, 1, 1)},
|
||||
{file: 'invalid-virtual-2.rt', issue: new RTCodeError("<rt-virtual> may not contain attributes other than 'rt-scope', 'rt-if' and 'rt-repeat'", 9, 119, 2, 4)}
|
||||
];
|
||||
{file: 'sortByDragListItemRowExamples.rt', issue: new RTCodeError('x', 0, 160, 1, 1)}
|
||||
// {file: 'if-with-scope/invalid-if-scope-1.rt', issue: new RTCodeError("invalid scope mapping used in if part 'this.bar(activeUsers.length)'", 0, 160, 1, 1)},
|
||||
// {file: 'if-with-scope/invalid-if-scope-2.rt', issue: new RTCodeError("invalid scope mapping used in if part 'this.bar[activeUsers || 0]'", 0, 158, 1, 1)},
|
||||
// {file: 'if-with-scope/invalid-if-scope-3.rt', issue: new RTCodeError("invalid scope mapping used in if part 'this.foo + activeUsers.length > this.bar'", 0, 172, 1, 1)},
|
||||
// {file: 'if-with-scope/invalid-if-scope-4.rt', issue: new RTCodeError("invalid scope mapping used in if part 'getCurrentActiveUsers().length'", 0, 170, 1, 1)},
|
||||
// {file: 'if-with-scope/invalid-if-scope-5.rt', issue: new RTCodeError("invalid scope mapping used in if part 'this.bar({activeUsers})'", 0, 155, 1, 1)},
|
||||
// {file: 'invalid-scope.rt', issue: new RTCodeError("invalid scope part 'a in a in a'", 0, 35, 1, 1)},
|
||||
// {file: 'invalid-html.rt', issue: new RTCodeError('Document should have a root element', -1, -1, -1, -1)},
|
||||
// {file: 'invalid-exp.rt', issue: new RTCodeError("Failed to parse text '\n {z\n'", 5, 13, 1, 6)},
|
||||
// {file: 'invalid-lambda.rt', issue: new RTCodeError("when using 'on' events, use lambda '(p1,p2)=>body' notation or 'this.handler'; otherwise use {} to return a callback function. error: [onClick='']", 0, 23, 1, 1)},
|
||||
// {file: 'invalid-autobind.rt', issue: new RTCodeError("'this.handler' syntax allowed only when the --autobind is on, use {} to return a callback function.", 0, 132, 1, 1)},
|
||||
// // {file: 'invalid-js.rt', issue: new RTCodeError('Unexpected token ILLEGAL', 0, 32, 1, 1)}, bug interduced due to scope parsing
|
||||
// {file: 'invalid-single-root.rt', issue: new RTCodeError('Document should have no more than a single root element', 12, 23, 2, 1)},
|
||||
// {file: 'invalid-repeat-1.rt', issue: new RTCodeError("rt-repeat invalid 'in' expression 'a in b in c'", 9, 44, 2, 4)},
|
||||
// {file: 'invalid-repeat-2.rt', issue: new RTCodeError("root element may not have a 'rt-repeat' attribute", 0, 39, 1, 1)},
|
||||
// {file: 'invalid-rt-require-1.rt', issue: new RTCodeError("'rt-require' needs 'dependency' and 'as' attributes", 0, 14, 1, 1)},
|
||||
// {file: 'invalid-rt-require-2.rt', issue: new RTCodeError("'rt-require' may have no children", 0, 32, 1, 1)},
|
||||
// {file: 'invalid-rt-require-duplicate.rt', issue: new RTCodeError("'rt-import' must be a toplevel node", 9, 54, 2, 4), options: {modules: 'amd'}},
|
||||
// {file: 'invalid-rt-import-1.rt', issue: new RTCodeError("'*' imports must have an 'as' attribute", 0, 36, 1, 1)},
|
||||
// {file: 'invalid-rt-import-2.rt', issue: new RTCodeError("default imports must have an 'as' attribute", 0, 42, 1, 1)},
|
||||
// {file: 'invalid-rt-import-3.rt', issue: new RTCodeError("'rt-import' needs 'name' and 'from' attributes", 0, 13, 1, 1)},
|
||||
// {file: 'invalid-rt-import-4.rt', issue: new RTCodeError("'rt-import' must be a toplevel node", 9, 54, 2, 4)},
|
||||
// {file: 'invalid-rt-template-1.rt', issue: new RTCodeError("'rt-template' should have a single non-text element as direct child", 9, 88, 2, 4)},
|
||||
// {file: 'invalid-rt-template-2.rt', issue: new RTCodeError("'rt-template' should have a single non-text element as direct child", 9, 90, 2, 4)},
|
||||
// {file: 'invalid-brace.rt', issue: new RTCodeError('Unexpected end of input', 128, 163, 5, 11)},
|
||||
// {file: 'invalid-style-1.rt', issue: new RTCodeError('Unexpected token ILLEGAL', 10, 39, 2, 5)},
|
||||
// {file: 'invalid-style-2.rt', issue: new RTCodeError('style attribute keys cannot contain { } expressions', 35, 68, 2, 5)},
|
||||
// {file: 'invalid-virtual-1.rt', issue: new RTCodeError('Document should not have <rt-virtual> as root element', 0, 60, 1, 1)},
|
||||
// {file: 'invalid-virtual-2.rt', issue: new RTCodeError("<rt-virtual> may not contain attributes other than 'rt-scope', 'rt-if' and 'rt-repeat'", 9, 119, 2, 4)}
|
||||
]
|
||||
|
||||
test('invalid tests', t => {
|
||||
t.plan(invalidFiles.length);
|
||||
t.plan(invalidFiles.length)
|
||||
|
||||
invalidFiles.forEach(testFile => {
|
||||
const filename = path.join(dataPath, testFile.file);
|
||||
const html = testUtils.readFileNormalized(filename);
|
||||
let error = null;
|
||||
const filename = path.join(dataPath, testFile.file)
|
||||
const html = testUtils.readFileNormalized(filename)
|
||||
let error = null
|
||||
try {
|
||||
reactTemplates.convertTemplateToReact(html);
|
||||
reactTemplates.convertTemplateToReact(html)
|
||||
} catch (e) {
|
||||
error = e;
|
||||
error = e
|
||||
}
|
||||
t.deepEqual(omitStack(error), omitStack(testFile.issue), 'Expect convertTemplateToReact to throw an error');
|
||||
});
|
||||
});
|
||||
t.deepEqual(omitStack(error), omitStack(testFile.issue), 'Expect convertTemplateToReact to throw an error')
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* @param {ERR} err
|
||||
@ -62,26 +64,26 @@ module.exports = {
|
||||
*/
|
||||
function normalizeError(err) {
|
||||
if (err) {
|
||||
err.msg = err.msg.replace(/\r/g, '');
|
||||
err.msg = err.msg.replace(/\r/g, '')
|
||||
}
|
||||
return err;
|
||||
return err
|
||||
}
|
||||
|
||||
test('invalid tests json', t => {
|
||||
const cli = require('../../src/cli');
|
||||
const context = require('../../src/context');
|
||||
t.plan(invalidFiles.length);
|
||||
const cli = require('../../src/cli')
|
||||
const context = require('../../src/context')
|
||||
t.plan(invalidFiles.length)
|
||||
|
||||
invalidFiles.forEach(check);
|
||||
invalidFiles.forEach(check)
|
||||
|
||||
function check(testFile) {
|
||||
context.clear();
|
||||
const filename = path.join(dataPath, testFile.file);
|
||||
const options = {format: 'json', force: true};
|
||||
cli.handleSingleFile(options, filename);
|
||||
t.deepEqual(normalizeError(context.getMessages()[0]), errorEqualMessage(testFile.issue, filename), `Expect cli to produce valid output messages ${testFile.file}`);
|
||||
context.clear()
|
||||
const filename = path.join(dataPath, testFile.file)
|
||||
const options = {format: 'json', force: true}
|
||||
cli.handleSingleFile(_.assign(options, testFile.options), filename)
|
||||
t.deepEqual(normalizeError(context.getMessages()[0]), errorEqualMessage(testFile.issue, filename), `Expect cli to produce valid output messages ${testFile.file}`)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
/**
|
||||
* @typedef {{index: number, line: number, column: number, msg: string, level: string, file: string}} ERR
|
||||
@ -102,8 +104,8 @@ module.exports = {
|
||||
msg: err.message,
|
||||
level: 'ERROR',
|
||||
file
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,52 +1,53 @@
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const reactTemplates = require('../../src/reactTemplates');
|
||||
const testUtils = require('./testUtils');
|
||||
const readFileNormalized = testUtils.readFileNormalized;
|
||||
const compareAndWrite = testUtils.compareAndWrite;
|
||||
const path = require('path');
|
||||
const context = require('../../src/context');
|
||||
'use strict'
|
||||
const _ = require('lodash')
|
||||
const reactTemplates = require('../../src/reactTemplates')
|
||||
const testUtils = require('./testUtils')
|
||||
const readFileNormalized = testUtils.readFileNormalized
|
||||
const compareAndWrite = testUtils.compareAndWrite
|
||||
const path = require('path')
|
||||
const context = require('../../src/context')
|
||||
|
||||
module.exports = {
|
||||
runTests(test, dataPath) {
|
||||
function check(t, testData) {
|
||||
const filename = path.join(dataPath, testData.source);
|
||||
const html = readFileNormalized(filename);
|
||||
const expected = readFileNormalized(path.join(dataPath, testData.expected));
|
||||
const actual = reactTemplates.convertTemplateToReact(html, testData.options).replace(/\r/g, '').trim();
|
||||
compareAndWrite(t, actual, expected, filename);
|
||||
const filename = path.join(dataPath, testData.source)
|
||||
const html = readFileNormalized(filename)
|
||||
const expected = readFileNormalized(path.join(dataPath, testData.expected))
|
||||
const actual = reactTemplates.convertTemplateToReact(html, testData.options).replace(/\r/g, '').trim()
|
||||
compareAndWrite(t, actual, expected, filename)
|
||||
}
|
||||
|
||||
function testFiles(t, files, options) {
|
||||
t.plan(files.length);
|
||||
t.plan(files.length)
|
||||
files.forEach(testFile => {
|
||||
check(t, {
|
||||
source: testFile,
|
||||
expected: `${testFile}.js`,
|
||||
options
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
test('rt-if with rt-scope test', t => {
|
||||
const files = ['if-with-scope/valid-if-scope.rt'];
|
||||
const options = {modules: 'amd'};
|
||||
testFiles(t, files, options);
|
||||
});
|
||||
const files = ['if-with-scope/valid-if-scope.rt']
|
||||
const options = {modules: 'amd'}
|
||||
testFiles(t, files, options)
|
||||
})
|
||||
|
||||
test('conversion test', t => {
|
||||
const files = ['div.rt', 'test.rt', 'repeat.rt', 'repeat-with-index.rt', 'inputs.rt', 'virtual.rt', 'stateless.rt', 'style-vendor-prefix.rt', 'non-breaking-space.rt'];
|
||||
const options = {modules: 'amd'};
|
||||
testFiles(t, files, options);
|
||||
});
|
||||
const files = ['div.rt', 'test.rt', 'repeat.rt', 'repeat-with-index.rt', 'inputs.rt', 'virtual.rt', 'stateless.rt', 'style-vendor-prefix.rt', 'non-breaking-space.rt']
|
||||
const options = {modules: 'amd'}
|
||||
testFiles(t, files, options)
|
||||
})
|
||||
|
||||
test('autobinding conversion test', t => {
|
||||
const options = {
|
||||
modules: 'amd',
|
||||
autobind: true
|
||||
};
|
||||
const files = ['autobind.rt'];
|
||||
testFiles(t, files, options);
|
||||
});
|
||||
}
|
||||
const files = ['autobind.rt']
|
||||
testFiles(t, files, options)
|
||||
})
|
||||
|
||||
test('prop template conversion test', t => {
|
||||
const options = {
|
||||
@ -56,16 +57,16 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
modules: 'amd'
|
||||
};
|
||||
}
|
||||
const files = [
|
||||
'simpleTemplate.rt',
|
||||
'templateInScope.rt',
|
||||
'implicitTemplate.rt',
|
||||
'twoTemplates.rt',
|
||||
'siblingTemplates.rt'
|
||||
].map(file => path.join('propTemplates', file));
|
||||
testFiles(t, files, options);
|
||||
});
|
||||
].map(file => path.join('propTemplates', file))
|
||||
testFiles(t, files, options)
|
||||
})
|
||||
|
||||
test('conversion test - native', t => {
|
||||
const options = {
|
||||
@ -75,8 +76,8 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
native: true
|
||||
};
|
||||
const optionsNew = _.assign({nativeTargetVersion: '0.29.0'}, options);
|
||||
}
|
||||
const optionsNew = _.assign({nativeTargetVersion: '0.29.0'}, options)
|
||||
|
||||
const files = [
|
||||
{source: 'native/nativeView.rt', expected: 'native/nativeView.rt.js', options},
|
||||
@ -85,10 +86,10 @@ module.exports = {
|
||||
{source: 'native/nativeView.rt', expected: 'native/nativeView.rt.v029.js', options: optionsNew},
|
||||
{source: 'native/listViewTemplate.rt', expected: 'native/listViewTemplate.rt.v029.js', options: optionsNew},
|
||||
{source: 'native/listViewAndCustomTemplate.rt', expected: 'native/listViewAndCustomTemplate.rt.v029.js', options: optionsNew}
|
||||
];
|
||||
t.plan(files.length);
|
||||
files.forEach(file => check(t, file));
|
||||
});
|
||||
]
|
||||
t.plan(files.length)
|
||||
files.forEach(file => check(t, file))
|
||||
})
|
||||
|
||||
test('convert div with all module types', t => {
|
||||
const files = [
|
||||
@ -96,26 +97,27 @@ module.exports = {
|
||||
{source: 'div.rt', expected: 'div.rt.amd.js', options: {modules: 'amd', name: 'div'}},
|
||||
{source: 'div.rt', expected: 'div.rt.globals.js', options: {modules: 'none', name: 'div'}},
|
||||
{source: 'div.rt', expected: 'div.rt.es6.js', options: {modules: 'es6'}},
|
||||
{source: 'div.rt', expected: 'div.rt.typescript.ts', options: {modules: 'typescript'}}
|
||||
];
|
||||
t.plan(files.length);
|
||||
files.forEach(file => check(t, file));
|
||||
});
|
||||
{source: 'div.rt', expected: 'div.rt.typescript.ts', options: {modules: 'typescript'}},
|
||||
{source: 'div.rt', expected: 'div.rt.15.js', options: {targetVersion: '15.0.0', modules: 'amd'}}
|
||||
]
|
||||
t.plan(files.length)
|
||||
files.forEach(file => check(t, file))
|
||||
})
|
||||
|
||||
test('normalize whitespace', t => {
|
||||
const files = ['whitespace.rt'];
|
||||
const options = {normalizeHtmlWhitespace: true, modules: 'amd'};
|
||||
testFiles(t, files, options);
|
||||
});
|
||||
const files = ['whitespace.rt']
|
||||
const options = {normalizeHtmlWhitespace: true, modules: 'amd'}
|
||||
testFiles(t, files, options)
|
||||
})
|
||||
|
||||
test('convert comment with AMD and ES6 modules', t => {
|
||||
const files = [
|
||||
{source: 'comment.rt', expected: 'comment.rt.amd.js', options: {modules: 'amd'}},
|
||||
{source: 'comment.rt', expected: 'comment.rt.es6.js', options: {modules: 'es6'}}
|
||||
];
|
||||
t.plan(files.length);
|
||||
files.forEach(file => check(t, file));
|
||||
});
|
||||
]
|
||||
t.plan(files.length)
|
||||
files.forEach(file => check(t, file))
|
||||
})
|
||||
|
||||
test('rt-require with all module types', t => {
|
||||
const files = [
|
||||
@ -124,10 +126,10 @@ module.exports = {
|
||||
{source: 'require.rt', expected: 'require.rt.globals.js', options: {modules: 'none', name: 'div'}},
|
||||
{source: 'require.rt', expected: 'require.rt.es6.js', options: {modules: 'es6'}},
|
||||
{source: 'require.rt', expected: 'require.rt.typescript.ts', options: {modules: 'typescript'}}
|
||||
];
|
||||
t.plan(files.length);
|
||||
files.forEach(file => check(t, file));
|
||||
});
|
||||
]
|
||||
t.plan(files.length)
|
||||
files.forEach(file => check(t, file))
|
||||
})
|
||||
|
||||
test('rt-import with all module types', t => {
|
||||
const files = [
|
||||
@ -136,21 +138,21 @@ module.exports = {
|
||||
{source: 'import.rt', expected: 'import.rt.globals.js', options: {modules: 'none', name: 'div'}},
|
||||
{source: 'import.rt', expected: 'import.rt.es6.js', options: {modules: 'es6'}},
|
||||
{source: 'import.rt', expected: 'import.rt.typescript.ts', options: {modules: 'typescript'}}
|
||||
];
|
||||
t.plan(files.length);
|
||||
files.forEach(file => check(t, file));
|
||||
});
|
||||
]
|
||||
t.plan(files.length)
|
||||
files.forEach(file => check(t, file))
|
||||
})
|
||||
|
||||
test('convert jsrt and test source results', t => {
|
||||
const files = ['simple.jsrt'];
|
||||
t.plan(files.length);
|
||||
const files = ['simple.jsrt']
|
||||
t.plan(files.length)
|
||||
files.forEach(file => {
|
||||
const filename = path.join(dataPath, file);
|
||||
const js = readFileNormalized(filename);
|
||||
const expected = readFileNormalized(path.join(dataPath, file.replace('.jsrt', '.js')));
|
||||
const actual = reactTemplates.convertJSRTToJS(js, context).replace(/\r/g, '').trim();
|
||||
compareAndWrite(t, actual, expected, filename);
|
||||
});
|
||||
});
|
||||
const filename = path.join(dataPath, file)
|
||||
const js = readFileNormalized(filename)
|
||||
const expected = readFileNormalized(path.join(dataPath, file.replace('.jsrt', '.js')))
|
||||
const actual = reactTemplates.convertJSRTToJS(js, context).replace(/\r/g, '').trim()
|
||||
compareAndWrite(t, actual, expected, filename)
|
||||
})
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
'use strict';
|
||||
const rtStyle = require('../../src/rtStyle');
|
||||
'use strict'
|
||||
const rtStyle = require('../../src/rtStyle')
|
||||
|
||||
module.exports = {
|
||||
runTests(test) {
|
||||
test('test rtStyle', t => {
|
||||
const text = '.text { background-color: #00346E; padding: 3px; }';
|
||||
const expected = '{\n "text": {\n "backgroundColor": "#00346E",\n "padding": 3\n }\n}';
|
||||
const actual = rtStyle.convertBody(text);
|
||||
t.equal(actual, expected);
|
||||
t.end();
|
||||
});
|
||||
const text = '.text { background-color: #00346E; padding: 3px; }'
|
||||
const expected = '{\n "text": {\n "backgroundColor": "#00346E",\n "padding": 3\n }\n}'
|
||||
const actual = rtStyle.convertBody(text)
|
||||
t.equal(actual, expected)
|
||||
t.end()
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,33 +1,33 @@
|
||||
'use strict';
|
||||
const context = require('../../src/context');
|
||||
const _ = require('lodash');
|
||||
const path = require('path');
|
||||
'use strict'
|
||||
const context = require('../../src/context')
|
||||
const _ = require('lodash')
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
runTests(test, dataPath) {
|
||||
test('test context', t => {
|
||||
context.clear();
|
||||
t.equal(context.hasErrors(), false);
|
||||
context.error('hi', '', 1, 1);
|
||||
t.equal(context.hasErrors(), true);
|
||||
context.clear();
|
||||
t.equal(context.hasErrors(), false);
|
||||
context.clear()
|
||||
t.equal(context.hasErrors(), false)
|
||||
context.error('hi', '', 1, 1)
|
||||
t.equal(context.hasErrors(), true)
|
||||
context.clear()
|
||||
t.equal(context.hasErrors(), false)
|
||||
|
||||
t.end();
|
||||
});
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('test shell', t => {
|
||||
const shell = require('../../src/shell');
|
||||
const newContext = _.cloneDeep(context);
|
||||
let outputJSON = '';
|
||||
newContext.options.format = 'json';
|
||||
newContext.report = function (text) { outputJSON = text; };
|
||||
let r = shell.printResults(newContext);
|
||||
t.equal(r, 0);
|
||||
context.error('hi', '', 1, 1);
|
||||
r = shell.printResults(newContext);
|
||||
t.equal(r, 1);
|
||||
const output = JSON.parse(outputJSON);
|
||||
const shell = require('../../src/shell')
|
||||
const newContext = _.cloneDeep(context)
|
||||
let outputJSON = ''
|
||||
newContext.options.format = 'json'
|
||||
newContext.report = function (text) { outputJSON = text }
|
||||
let r = shell.printResults(newContext)
|
||||
t.equal(r, 0)
|
||||
context.error('hi', '', 1, 1)
|
||||
r = shell.printResults(newContext)
|
||||
t.equal(r, 1)
|
||||
const output = JSON.parse(outputJSON)
|
||||
t.deepEqual(output, [{
|
||||
column: 1,
|
||||
endOffset: -1,
|
||||
@ -37,17 +37,17 @@ module.exports = {
|
||||
line: 1,
|
||||
msg: 'hi',
|
||||
startOffset: -1
|
||||
}]);
|
||||
context.clear();
|
||||
t.end();
|
||||
});
|
||||
}])
|
||||
context.clear()
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('test shell', t => {
|
||||
const filename = path.join(dataPath, 'div.rt');
|
||||
const cli = require('../../src/cli');
|
||||
const r = cli.execute(`${filename} -r --dry-run`);
|
||||
t.equal(r, 0);
|
||||
t.end();
|
||||
});
|
||||
const filename = path.join(dataPath, 'div.rt')
|
||||
const cli = require('../../src/cli')
|
||||
const r = cli.execute(`${filename} -r --dry-run`)
|
||||
t.equal(r, 0)
|
||||
t.end()
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
'use strict';
|
||||
const test = require('tape');
|
||||
const path = require('path');
|
||||
const dataPath = path.resolve(__dirname, '..', 'data');
|
||||
'use strict'
|
||||
const test = require('tape')
|
||||
const path = require('path')
|
||||
const dataPath = path.resolve(__dirname, '..', 'data')
|
||||
|
||||
const specs = ['rt.invalid', 'rt.valid', 'rt-html-valid', 'utils', 'shell', 'rtStyle', 'fsUtil'];
|
||||
// const specs = ['rt.invalid', 'rt.valid', 'rt-html-valid', 'utils', 'shell', 'rtStyle', 'fsUtil'];
|
||||
const specs = ['rt.invalid']
|
||||
|
||||
specs
|
||||
.map(file => require(`./${file}.spec`))
|
||||
.forEach(spec => spec.runTests(test, dataPath));
|
||||
.forEach(spec => spec.runTests(test, dataPath))
|
||||
|
@ -1,11 +1,11 @@
|
||||
'use strict';
|
||||
const cheerio = require('cheerio');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const reactTemplates = require('../../src/reactTemplates');
|
||||
const React = require('react');
|
||||
const ReactDOMServer = require('react-dom/server');
|
||||
const _ = require('lodash');
|
||||
'use strict'
|
||||
const cheerio = require('cheerio')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const reactTemplates = require('../../src/reactTemplates')
|
||||
const React = require('react')
|
||||
const ReactDOMServer = require('react-dom/server')
|
||||
const _ = require('lodash')
|
||||
|
||||
/**
|
||||
* @param {string} html
|
||||
@ -15,7 +15,7 @@ function normalizeHtml(html) {
|
||||
return cheerio.load(html, {normalizeWhitespace: true}).html()
|
||||
.replace(/>\s+/mg, '>')
|
||||
.replace(/\s+</mg, '<')
|
||||
.replace(/>\s+</mg, '><');
|
||||
.replace(/>\s+</mg, '><')
|
||||
}
|
||||
|
||||
/**
|
||||
@ -26,28 +26,28 @@ function normalizeHtml(html) {
|
||||
* @return {boolean} whether actual is equal to expected
|
||||
*/
|
||||
function compareAndWrite(t, actual, expected, filename) {
|
||||
t.equal(actual, expected, filename);
|
||||
t.equal(actual, expected, filename)
|
||||
if (actual !== expected) {
|
||||
fs.writeFileSync(`${filename}.actual.js`, actual);
|
||||
return false;
|
||||
fs.writeFileSync(`${filename}.actual.js`, actual)
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
function compareNodes(t, a, b, filename) {
|
||||
_.forEach(a.attribs, (v, k) => {
|
||||
if (v !== b.attribs[k]) {
|
||||
console.log(`${v} is not ${b.attribs[k]}`);
|
||||
console.log(`${v} is not ${b.attribs[k]}`)
|
||||
}
|
||||
t.equal(v, b.attribs[k], filename);
|
||||
});
|
||||
compareNodesList(t, a.children, b.children);
|
||||
t.equal(v, b.attribs[k], filename)
|
||||
})
|
||||
compareNodesList(t, a.children, b.children)
|
||||
}
|
||||
|
||||
function compareNodesList(t, a, b, filename) {
|
||||
_.forEach(a, (v, i) => {
|
||||
compareNodes(t, v, b[i], filename);
|
||||
});
|
||||
compareNodes(t, v, b[i], filename)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,7 +55,7 @@ function compareNodesList(t, a, b, filename) {
|
||||
* @return {string}
|
||||
*/
|
||||
function readFileNormalized(filename) {
|
||||
return readFile(filename).replace(/\r/g, '').trim();
|
||||
return readFile(filename).replace(/\r/g, '').trim()
|
||||
}
|
||||
|
||||
//const dataPath = path.resolve(__dirname, '..', 'data');
|
||||
@ -64,31 +64,31 @@ function readFileNormalized(filename) {
|
||||
* @return {string}
|
||||
*/
|
||||
function readFile(filename) {
|
||||
return fs.readFileSync(filename).toString();
|
||||
return fs.readFileSync(filename).toString()
|
||||
}
|
||||
|
||||
function joinDataPath(fileName) {
|
||||
const dataPath = path.resolve(__dirname, '..', 'data');
|
||||
return path.join(dataPath, fileName);
|
||||
const dataPath = path.resolve(__dirname, '..', 'data')
|
||||
return path.join(dataPath, fileName)
|
||||
}
|
||||
|
||||
function rtToHtml(rt) {
|
||||
const code = reactTemplates.convertTemplateToReact(rt).replace(/\r/g, '');
|
||||
return codeToHtml(code);
|
||||
const code = reactTemplates.convertTemplateToReact(rt).replace(/\r/g, '')
|
||||
return codeToHtml(code)
|
||||
}
|
||||
|
||||
function codeToHtml(code) {
|
||||
const defineMap = {react: React, lodash: _};
|
||||
const defineMap = {react: React, lodash: _}
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
const define = function (requirementsNames, content) { //eslint-disable-line no-unused-vars,func-style
|
||||
const requirements = _.map(requirementsNames, reqName => defineMap[reqName]);
|
||||
return content.apply(this, requirements);
|
||||
};
|
||||
const requirements = _.map(requirementsNames, reqName => defineMap[reqName])
|
||||
return content.apply(this, requirements)
|
||||
}
|
||||
const comp = React.createFactory(React.createClass({
|
||||
displayName: 'testClass',
|
||||
render: eval(code) //eslint-disable-line no-eval
|
||||
}));
|
||||
return ReactDOMServer.renderToStaticMarkup(comp());
|
||||
}))
|
||||
return ReactDOMServer.renderToStaticMarkup(comp())
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@ -99,4 +99,4 @@ module.exports = {
|
||||
joinDataPath,
|
||||
rtToHtml,
|
||||
codeToHtml
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
'use strict'
|
||||
|
||||
const utils = require('../../src/utils');
|
||||
const utils = require('../../src/utils')
|
||||
|
||||
module.exports = {
|
||||
runTests(test) {
|
||||
@ -8,13 +8,13 @@ module.exports = {
|
||||
const texts = [
|
||||
{input: '{}', expected: '()'},
|
||||
{input: "a {'b'}", expected: '"a "+(\'b\')'}
|
||||
];
|
||||
t.plan(texts.length);
|
||||
texts.forEach(check);
|
||||
]
|
||||
t.plan(texts.length)
|
||||
texts.forEach(check)
|
||||
function check(testData) {
|
||||
const r = utils.convertText({}, {}, testData.input);
|
||||
t.equal(r, testData.expected);
|
||||
const r = utils.convertText({}, {}, testData.input)
|
||||
t.equal(r, testData.expected)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user