add support for function templates props
This commit is contained in:
parent
d565f5380f
commit
78799bfca7
|
@ -179,6 +179,51 @@ function generateInjectedFunc(context, namePrefix, body, params) {
|
|||
return generatedFuncName;
|
||||
}
|
||||
|
||||
function generateTemplateProps(node, context) {
|
||||
var propTemplateDefinition = context.options.templates && context.options.templates[node.name];
|
||||
var propertiesTemplates = _(node.children)
|
||||
.map(function (child, index) {
|
||||
var templateProp = null;
|
||||
if (child.name === 'template' && child.attribs.prop) { // Generic explicit template tag
|
||||
var childTemplate = _.find(context.options.templates, {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, content: _.find(child.children, {type: 'tag'})});
|
||||
}
|
||||
|
||||
return templateProp;
|
||||
})
|
||||
.compact()
|
||||
.value();
|
||||
|
||||
return _.transform(propertiesTemplates, function (props, templateProp) {
|
||||
var functionParams = _.values(context.boundParams).concat(templateProp.arguments);
|
||||
|
||||
var oldBoundParams = context.boundParams;
|
||||
context.boundParams = context.boundParams.concat(templateProp.arguments);
|
||||
|
||||
var functionBody = 'return ' + convertHtmlToReact(templateProp.content, context);
|
||||
context.boundParams = oldBoundParams;
|
||||
|
||||
var generatedFuncName = generateInjectedFunc(context, templateProp.prop, functionBody, functionParams);
|
||||
var boundArguments = _.values(context.boundParams).join(',');
|
||||
props[templateProp.prop] = generatedFuncName + '.bind(this' + (boundArguments.length ? ', ' + boundArguments : '') + ')';
|
||||
|
||||
// Remove the template child from the children definition.
|
||||
node.children.splice(templateProp.childIndex, 1);
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node
|
||||
* @param {Context} context
|
||||
|
@ -237,6 +282,8 @@ function generateProps(node, context) {
|
|||
}
|
||||
});
|
||||
|
||||
_.assign(props, generateTemplateProps(node, context));
|
||||
|
||||
return '{' + _.map(props, function (val, key) {
|
||||
return JSON.stringify(key) + ' : ' + val;
|
||||
}).join(',') + '}';
|
||||
|
@ -304,7 +351,7 @@ function convertHtmlToReact(node, context) {
|
|||
_.each(context.boundParams, function (boundParam) {
|
||||
data.outerScopeMapping[boundParam] = boundParam;
|
||||
});
|
||||
|
||||
|
||||
// these are variables declared in the rt-scope attribute
|
||||
data.innerScopeMapping = {};
|
||||
_.each(node.attribs[scopeAttr].split(';'), function (scopePart) {
|
||||
|
@ -457,7 +504,7 @@ function convertTemplateToReact(html, options) {
|
|||
function convertRT(html, reportContext, options) {
|
||||
var rootNode = cheerio.load(html, {lowerCaseTags: false, lowerCaseAttributeNames: false, xmlMode: true, withStartIndices: true});
|
||||
options = _.defaults({}, options, defaultOptions);
|
||||
|
||||
|
||||
var defaultDefines = {};
|
||||
defaultDefines[options.reactImportPath] = 'React';
|
||||
defaultDefines[options.lodashImportPath] = '_';
|
||||
|
@ -490,15 +537,23 @@ function convertRT(html, reportContext, options) {
|
|||
throw RTCodeError.build('Document should have a single root element', context, rootNode.root()[0]);
|
||||
}
|
||||
var body = convertHtmlToReact(firstTag, context);
|
||||
var requirePaths = _(defines).keys().map(function (reqName) { return '"' + reqName + '"'; }).value().join(',');
|
||||
var requirePaths = _(defines).keys().map(function (reqName) {
|
||||
return '"' + reqName + '"';
|
||||
}).value().join(',');
|
||||
var requireVars = _(defines).values().value().join(',');
|
||||
var vars;
|
||||
if (options.modules === 'typescript') {
|
||||
vars = _(defines).map(function (reqVar, reqPath) { return 'import ' + reqVar + " = require('" + reqPath + "');"; }).join('\n');
|
||||
vars = _(defines).map(function (reqVar, reqPath) {
|
||||
return 'import ' + reqVar + " = require('" + reqPath + "');";
|
||||
}).join('\n');
|
||||
} else if (options.modules === 'es6') {
|
||||
vars = _(defines).map(function (reqVar, reqPath) { return 'import ' + reqVar + " from '" + reqPath + "';"; }).join('\n');
|
||||
vars = _(defines).map(function (reqVar, reqPath) {
|
||||
return 'import ' + reqVar + " from '" + reqPath + "';";
|
||||
}).join('\n');
|
||||
} else {
|
||||
vars = _(defines).map(function (reqVar, reqPath) { return 'var ' + reqVar + " = require('" + reqPath + "');"; }).join('\n');
|
||||
vars = _(defines).map(function (reqVar, reqPath) {
|
||||
return 'var ' + reqVar + " = require('" + reqPath + "');";
|
||||
}).join('\n');
|
||||
}
|
||||
var data = {body: body, injectedFunctions: '', requireNames: requireVars, requirePaths: requirePaths, vars: vars, name: options.name};
|
||||
data.injectedFunctions = context.injectedFunctions.join('\n');
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<div>
|
||||
<List data="{[1,2,3]}">
|
||||
<Row>
|
||||
<div>{rowData}</div>
|
||||
</Row>
|
||||
</List>
|
||||
</div>
|
|
@ -0,0 +1,19 @@
|
|||
define([
|
||||
'react/addons',
|
||||
'lodash'
|
||||
], function (React, _) {
|
||||
'use strict';
|
||||
function renderRow1(rowData) {
|
||||
return React.createElement('div', {}, rowData);
|
||||
}
|
||||
return function () {
|
||||
return React.createElement('div', {}, React.createElement(List, {
|
||||
'data': [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
'renderRow': renderRow1.bind(this)
|
||||
}));
|
||||
};
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
<div>
|
||||
<template prop="templateProp" arguments="arg1">
|
||||
<div>{arg1}</div>
|
||||
</template>
|
||||
</div>
|
|
@ -0,0 +1,12 @@
|
|||
define([
|
||||
'react/addons',
|
||||
'lodash'
|
||||
], function (React, _) {
|
||||
'use strict';
|
||||
function templateProp1(arg1) {
|
||||
return React.createElement('div', {}, arg1);
|
||||
}
|
||||
return function () {
|
||||
return React.createElement('div', { 'templateProp': templateProp1.bind(this) });
|
||||
};
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
<div rt-scope="'boten' as name">
|
||||
<template prop="templateProp" arguments="arg1">
|
||||
<div>Name: {name} {arg1}</div>
|
||||
</template>
|
||||
</div>
|
|
@ -0,0 +1,16 @@
|
|||
define([
|
||||
'react/addons',
|
||||
'lodash'
|
||||
], function (React, _) {
|
||||
'use strict';
|
||||
function templateProp1(name, arg1) {
|
||||
return React.createElement('div', {}, 'Name: ', name, ' ', arg1);
|
||||
}
|
||||
function scopeName2() {
|
||||
var name = 'boten';
|
||||
return React.createElement('div', { 'templateProp': templateProp1.bind(this, name) });
|
||||
}
|
||||
return function () {
|
||||
return scopeName2.apply(this, []);
|
||||
};
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
<div>
|
||||
<template prop="templateProp" arguments="arg1">
|
||||
<div>
|
||||
<template prop="templateProp2" arguments="inner1, inner2">
|
||||
<div>{arg1 + inner1 + inner2}</div>
|
||||
</template>
|
||||
<div>{arg1}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
|
@ -0,0 +1,15 @@
|
|||
define([
|
||||
'react/addons',
|
||||
'lodash'
|
||||
], function (React, _) {
|
||||
'use strict';
|
||||
function templateProp21(arg1, inner1, inner2) {
|
||||
return React.createElement('div', {}, arg1 + inner1 + inner2);
|
||||
}
|
||||
function templateProp2(arg1) {
|
||||
return React.createElement('div', { 'templateProp2': templateProp21.bind(this, arg1) }, React.createElement('div', {}, arg1));
|
||||
}
|
||||
return function () {
|
||||
return React.createElement('div', { 'templateProp': templateProp2.bind(this) });
|
||||
};
|
||||
});
|
|
@ -114,6 +114,28 @@ test('conversion test', function (t) {
|
|||
}
|
||||
});
|
||||
|
||||
test('prop template conversion test', function (t) {
|
||||
var options = {
|
||||
templates: {
|
||||
List: {
|
||||
Row: {prop: 'renderRow', arguments: ['rowData']}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var files = ['propTemplates/simpleTemplate.rt', 'propTemplates/templateInScope.rt', 'propTemplates/implicitTemplate.rt', 'propTemplates/twoTemplates.rt'];
|
||||
t.plan(files.length);
|
||||
files.forEach(check);
|
||||
|
||||
function check(testFile) {
|
||||
var filename = path.join(dataPath, testFile);
|
||||
var html = readFileNormalized(filename);
|
||||
var expected = readFileNormalized(filename + '.js');
|
||||
var actual = reactTemplates.convertTemplateToReact(html, options).replace(/\r/g, '').trim();
|
||||
compareAndWrite(t, actual, expected, filename);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {*} t
|
||||
* @param {string} actual
|
||||
|
|
Loading…
Reference in New Issue