Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

fix: render style property in list #1344

Merged
merged 2 commits into from
Sep 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/jsx-compiler/src/modules/__tests__/jsx-plus.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ describe('Directives', () => {
<View x-for={val in array}>{val}</View>
`);
_transformList(ast, adapter);
expect(genExpression(ast)).toEqual('<View a:for={array} a:for-item="val">{val}</View>');
expect(genExpression(ast)).toEqual(`<View a:for={array.map((val, index) => {
return {
val: val,
index: index
};
})} a:for-item="val" a:for-index="index">{val}</View>`);
});
});

Expand Down
7 changes: 6 additions & 1 deletion packages/jsx-compiler/src/modules/code.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,12 @@ module.exports = {
];
const callUpdateProps = t.expressionStatement(t.callExpression(updateProps, updatePropsArgs));
if (propMaps.length > 0) {
(parentNode || fnBody).push(callUpdateProps);
const targetNode = parentNode || fnBody;
if (t.isReturnStatement(targetNode[targetNode.length - 1])) {
targetNode.splice(targetNode.length - 1, 0, callUpdateProps);
} else {
targetNode.push(callUpdateProps);
}
} else if ((parentNode || fnBody).length === 0) {
// Remove empty loop exp.
parentNode && parentNode.remove && parentNode.remove();
Expand Down
27 changes: 2 additions & 25 deletions packages/jsx-compiler/src/modules/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,8 @@ module.exports = {
componentsDependentProps[tagId].tagIdExpression = parentPath.node.__tagIdExpression;

if (parsed.renderFunctionPath) {
const { args, iterValue, loopFnBody } = parentJSXListEl.node.__jsxlist;
const __args = [
args[0] || t.identifier('item'),
args[1] || t.identifier('index'),
];
const callee = t.memberExpression(iterValue, t.identifier('forEach'));
const block = t.blockStatement([]);

const loopArgs = [t.arrowFunctionExpression(__args, block)];
const loopExp = t.expressionStatement(t.callExpression(callee, loopArgs));

const fnBody = parsed.renderFunctionPath.node.body.body;
const grandJSXListEl = parentJSXListEl.findParent(p => p.node.__jsxlist);
const body = grandJSXListEl && grandJSXListEl.node.__jsxlist.loopBlockStatement
? grandJSXListEl.node.__jsxlist.loopBlockStatement.body
: fnBody;

body.push(loopExp);
// Can be removed if not used.
block.body.remove = () => {
const index = body.indexOf(loopExp);
body.splice(index, 1);
};
componentsDependentProps[tagId].parentNode = block.body;
parentJSXListEl.node.__jsxlist.loopBlockStatement = block;
const { loopFnBody } = parentJSXListEl.node.__jsxlist;
componentsDependentProps[tagId].parentNode = loopFnBody.body;
}
}

Expand Down
55 changes: 34 additions & 21 deletions packages/jsx-compiler/src/modules/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,8 @@ function transformTemplate(ast, scope = null, adapter, sourceCode, componentDepe
if (innerPath.node.__transformed
|| innerPath.parentPath.isMemberExpression()
|| innerPath.parentPath.isObjectProperty()
|| innerPath.node.__xforArgs
|| innerPath.node.__mapArgs
&& !innerPath.node.__mapArgs.item) return;
|| innerPath.node.__listItem
&& !innerPath.node.__listItem.item) return;
const replaceNode = transformIdentifier(innerPath.node, dynamicValues, isDirective);
replaceNode.__transformed = true;
innerPath.replaceWith(replaceNode);
Expand All @@ -304,18 +303,7 @@ function transformTemplate(ast, scope = null, adapter, sourceCode, componentDepe
},
ObjectExpression(innerPath) {
if (innerPath.node.__transformed) return;
const { properties } = innerPath.node;
const replaceProperties = properties.map(property => {
const { key, value } = property;
let replaceNode;
if (t.isIdentifier(value)) {
replaceNode = transformIdentifier(value, dynamicValues, isDirective);
}
if (t.isMemberExpression(value)) {
replaceNode = transformMemberExpression(value, dynamicValues, isDirective);
}
return t.objectProperty(key, replaceNode);
});
const replaceProperties = transformObjectExpression(innerPath.node, dynamicValues, isDirective);
const replaceNode = t.objectExpression(replaceProperties);
replaceNode.__transformed = true;
innerPath.replaceWith(replaceNode);
Expand Down Expand Up @@ -414,7 +402,7 @@ function hasComplexExpression(path) {
const { properties } = innerPath.node;
const checkNested = properties.some(property => {
const { value } = property;
return !t.isIdentifier(value) && !t.isMemberExpression(value);
return !t.isIdentifier(value) && !t.isMemberExpression(value) && !t.isBinaryExpression(value);
});
if (checkNested) {
isComplex(innerPath);
Expand Down Expand Up @@ -452,7 +440,7 @@ function transformMemberExpression(expression, dynamicBinding, isDirective) {
replaceNode.__transformed = true;
return replaceNode;
}
if (t.isIdentifier(object) && !object.__xforArgs) {
if (t.isIdentifier(object)) {
objectReplaceNode = transformIdentifier(object, dynamicBinding, isDirective);
objectReplaceNode.__transformed = true;
}
Expand All @@ -475,13 +463,17 @@ function transformMemberExpression(expression, dynamicBinding, isDirective) {
* */
function transformIdentifier(expression, dynamicBinding, isDirective) {
let replaceNode;
if (expression.__xforArgs
|| expression.__mapArgs && !expression.__mapArgs.item
if (expression.__listItem
&& !expression.__listItem.item
|| expression.__templateVar) {
// The identifier is x-for args or template variable or map's index
replaceNode = expression;
} else if (expression.__mapArgs && expression.__mapArgs.item) {
replaceNode = t.memberExpression(t.identifier(expression.__mapArgs.item), expression);
} else if (expression.__listItem && expression.__listItem.item) {
const itemNode = t.identifier(expression.__listItem.item);
itemNode.__listItem = {
jsxplus: expression.__listItem.jsxplus
};
replaceNode = t.memberExpression(itemNode, expression);
} else {
const name = dynamicBinding.add({
expression,
Expand All @@ -492,6 +484,27 @@ function transformIdentifier(expression, dynamicBinding, isDirective) {
return replaceNode;
}

/**
* Transform ObjectExpression
* */
function transformObjectExpression(expression, dynamicBinding, isDirective) {
const { properties } = expression;
return properties.map(property => {
const { key, value } = property;
let replaceNode = value;
if (t.isIdentifier(value)) {
replaceNode = transformIdentifier(value, dynamicBinding, isDirective);
}
if (t.isMemberExpression(value)) {
replaceNode = transformMemberExpression(value, dynamicBinding, isDirective);
}
if (t.isObjectExpression(value)) {
replaceNode = transformObjectExpression(value, dynamicBinding, isDirective);
}
return t.objectProperty(key, replaceNode);
});
}

function checkMemberHasThis(expression) {
const { object, property } = expression;
let hasThisExpression = false;
Expand Down
4 changes: 2 additions & 2 deletions packages/jsx-compiler/src/modules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ module.exports = [
require('./style'),
// Handle Rax base components.
require('./components'),
// JSX+ Directives
require('./jsx-plus'),
// Directive a:for
require('./list'),
// Directive a:if
require('./condition'),
// JSX+ Directives
require('./jsx-plus'),
// Handle render function
require('./render-function'),
// Parse and generate template.
Expand Down
31 changes: 27 additions & 4 deletions packages/jsx-compiler/src/modules/jsx-plus.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,12 @@ function transformDirectiveList(ast, adapter) {
path.traverse({
Identifier(innerPath) {
const { node } = innerPath;
if (args.find(arg => arg.name === node.name)) {
node.__xforArgs = true;
if (args.find(arg => arg.name === node.name)
) {
node.__listItem = {
jsxplus: true,
item: args[0].name
};
}
}
});
Expand Down Expand Up @@ -147,17 +151,36 @@ function transformDirectiveList(ast, adapter) {
params = left.expressions;
} else if (t.isIdentifier(left)) {
// x-for={item in value}
params.push(left);
params = [left, t.identifier('index')];
} else {
// x-for={??? in value}
throw new Error('Stynax error of x-for.');
}
} else {
// x-for={value}, x-for={callExp()}, ...
iterValue = expression;
params = [t.identifier('item'), t.identifier('index')];
}
const parentJSXEl = path.findParent(p => p.isJSXElement());
parentJSXEl.node.__jsxlist = { args: params, iterValue, jsxplus: true };
// Transform x-for iterValue to map function
const loopFnBody = t.blockStatement([
t.returnStatement(
t.objectExpression([
t.objectProperty(params[0], params[0]),
t.objectProperty(params[1], params[1])
])
)
]);
parentJSXEl.node.__jsxlist = {
args: params,
iterValue: t.callExpression(
t.memberExpression(iterValue, t.identifier('map')),
[
t.arrowFunctionExpression(params, loopFnBody)
]),
loopFnBody,
jsxplus: true
};
path.remove();
}
}
Expand Down
31 changes: 18 additions & 13 deletions packages/jsx-compiler/src/modules/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const findIndex = require('../utils/findIndex');

function transformList(ast, renderItemFunctions, adapter) {
let fnScope;
let useCreateStyle = false;

function traverseFunction(path) {
fnScope = path.scope;
Expand Down Expand Up @@ -86,29 +87,27 @@ function transformList(ast, renderItemFunctions, adapter) {
returnElPath.traverse({
Identifier(innerPath) {
if (innerPath.findParent(p => p.node.__bindEvent)) return;
if (innerPath.node.name === forItem.name) {
innerPath.node.__mapArgs = {
item: forItem.name
};
}

if (innerPath.node.name === forIndex.name) {
innerPath.node.__mapArgs = {};
}

if (
innerPath.scope.hasBinding(innerPath.node.name)
|| innerPath.node.name === forItem.name
|| innerPath.node.name === forIndex.name
&& !(t.isMemberExpression(innerPath.parent) && innerPath.parent.property !== innerPath.node)
) {
innerPath.node.__mapArgs = {
console.log(t.isMemberExpression(innerPath.parent));
innerPath.node.__listItem = {
jsxplus: false,
item: forItem.name
};

// Skip duplicate keys.
if (!properties.some(
pty => pty.key.name === innerPath.node.name)) {
properties.push(t.objectProperty(innerPath.node, innerPath.node));
let value = innerPath.node;
if (innerPath.findParent(p => p.isJSXAttribute() && p.node.name.name === 'style')) {
value = t.callExpression(t.identifier('__create_style__'), [value]);
useCreateStyle = true;
}
properties.push(t.objectProperty(innerPath.node, value));
}
}
},
Expand Down Expand Up @@ -141,6 +140,7 @@ function transformList(ast, renderItemFunctions, adapter) {
iterValue: callee.object,
generated: true,
jsxplus: false,
loopFnBody: body
};

parentPath.replaceWith(listBlock);
Expand All @@ -154,11 +154,16 @@ function transformList(ast, renderItemFunctions, adapter) {
}
}
});
return useCreateStyle;
}

module.exports = {
parse(parsed, code, options) {
transformList(parsed.templateAST, parsed.renderItemFunctions, options.adapter);
const useCreateStyle = transformList(parsed.templateAST, parsed.renderItemFunctions, options.adapter);
// In list item maybe use __create_style__
if (!parsed.useCreateStyle) {
parsed.useCreateStyle = useCreateStyle;
}
},

// For test cases.
Expand Down
23 changes: 20 additions & 3 deletions packages/jsx-compiler/src/modules/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ const t = require('@babel/types');
const traverse = require('../utils/traverseNodePath');

const TEMPLATE_AST = 'templateAST';
const DYNAMIC_STYLES = 'dynamicStyles';
const DynamicBinding = require('../utils/DynamicBinding');

/**
Expand All @@ -12,13 +11,13 @@ const DynamicBinding = require('../utils/DynamicBinding');
* var _style0 = { width: 100 };
* return { _style0 };
*/
function transformStyle(ast, dynamicStyles) {
function transformStyle(ast) {
const dynamicValue = new DynamicBinding('_s');

traverse(ast, {
JSXAttribute(path) {
const { node } = path;
if (t.isJSXExpressionContainer(node.value) && node.name.name === 'style') {
if (shouldReplace(path)) {
const styleObjectExpression = node.value.expression;

// <tag style="{{ _s0 }}" />
Expand All @@ -32,6 +31,24 @@ function transformStyle(ast, dynamicStyles) {
return dynamicValue.getStore();
}

function shouldReplace(path) {
const { node } = path;
if (t.isJSXExpressionContainer(node.value) && node.name.name === 'style') {
let shouldReplace = true;
// List item has been replaced in list module
traverse(node.value.expression, {
Identifier(innerPath) {
if (innerPath.node.__listItem) {
shouldReplace = false;
innerPath.stop();
}
}
});
return shouldReplace;
}
return false;
}

module.exports = {
parse(parsed, code, options) {
const dynamicValues = transformStyle(parsed[TEMPLATE_AST]);
Expand Down