mirror of
https://github.com/marko-js/marko.git
synced 2026-02-01 16:07:13 +00:00
Tag params (#1076)
This commit is contained in:
parent
63b0aeb58a
commit
f5ebda8f2a
@ -52,6 +52,7 @@ var CustomTag = require("./ast/CustomTag");
|
||||
var parseExpression = require("./util/parseExpression");
|
||||
var parseStatement = require("./util/parseStatement");
|
||||
var parseJavaScriptArgs = require("./util/parseJavaScriptArgs");
|
||||
var parseJavaScriptParams = require("./util/parseJavaScriptParams");
|
||||
var replacePlaceholderEscapeFuncs = require("./util/replacePlaceholderEscapeFuncs");
|
||||
var isValidJavaScriptIdentifier = require("./util/isValidJavaScriptIdentifier");
|
||||
|
||||
@ -475,6 +476,11 @@ class Builder {
|
||||
return parseJavaScriptArgs(args, DEFAULT_BUILDER);
|
||||
}
|
||||
|
||||
parseJavaScriptParams(params) {
|
||||
ok(typeof params === "string", '"params" should be a string');
|
||||
return parseJavaScriptParams(params, DEFAULT_BUILDER);
|
||||
}
|
||||
|
||||
parseStatement(str) {
|
||||
ok(typeof str === "string", '"str" should be a string expression');
|
||||
var parsed = parseStatement(str, DEFAULT_BUILDER);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
"use strict";
|
||||
var ok = require("assert").ok;
|
||||
var replacePlaceholderEscapeFuncs = require("./util/replacePlaceholderEscapeFuncs");
|
||||
var enableTagParams = require("./util/enableTagParams");
|
||||
var extend = require("raptor-util/extend");
|
||||
|
||||
var COMPILER_ATTRIBUTE_HANDLERS = {
|
||||
@ -400,7 +401,13 @@ class Parser {
|
||||
}
|
||||
|
||||
this.prevTextNode = null;
|
||||
this.stack.pop();
|
||||
var { node } = this.stack.pop();
|
||||
var tagDef = node.tagDef;
|
||||
if (tagDef && tagDef.featureFlags) {
|
||||
if (tagDef.featureFlags.includes("params")) {
|
||||
enableTagParams(node, this.context.builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleComment(comment) {
|
||||
|
||||
@ -77,8 +77,11 @@ function getNestedVariables(elNode, tagDef, codegen) {
|
||||
}
|
||||
|
||||
if (elNode.additionalNestedVars.length) {
|
||||
elNode.additionalNestedVars.forEach(varName => {
|
||||
variableNames.push(codegen.builder.identifier(varName));
|
||||
elNode.additionalNestedVars.forEach(variable => {
|
||||
if (typeof variable === "string") {
|
||||
variable = codegen.builder.identifier(variable);
|
||||
}
|
||||
variableNames.push(variable);
|
||||
});
|
||||
}
|
||||
|
||||
@ -811,8 +814,12 @@ class CustomTag extends HtmlElement {
|
||||
if (
|
||||
checkIfNestedTagCanBeAddedDirectlyToInput(this, parentCustomTag)
|
||||
) {
|
||||
let params = getNestedVariables(this, this.tagDef, codegen);
|
||||
let renderBody = hasBody
|
||||
? builder.renderBodyFunction(body)
|
||||
? builder.renderBodyFunction(
|
||||
body,
|
||||
[builder.identifier("out")].concat(params)
|
||||
)
|
||||
: null;
|
||||
let additionalAttrs = renderBody ? { renderBody } : null;
|
||||
let inputProps = this.buildInputProps(codegen, additionalAttrs);
|
||||
|
||||
@ -45,21 +45,8 @@ class FunctionDeclaration extends Node {
|
||||
if (i !== 0) {
|
||||
writer.write(", ");
|
||||
}
|
||||
var param = params[i];
|
||||
|
||||
if (typeof param === "string") {
|
||||
writer.write(param);
|
||||
} else {
|
||||
if (param.type !== "Identifier") {
|
||||
throw new Error(
|
||||
"Illegal param " +
|
||||
JSON.stringify(param) +
|
||||
" for FunctionDeclaration: " +
|
||||
JSON.stringify(this)
|
||||
);
|
||||
}
|
||||
writer.write(param);
|
||||
}
|
||||
writer.write(params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -686,6 +686,10 @@ class TagLoader {
|
||||
htmlType(value) {
|
||||
this.tag.htmlType = value;
|
||||
}
|
||||
|
||||
featureFlags(value) {
|
||||
this.tag.featureFlags = value;
|
||||
}
|
||||
}
|
||||
|
||||
function isSupportedProperty(name) {
|
||||
|
||||
16
src/compiler/util/enableTagParams.js
Normal file
16
src/compiler/util/enableTagParams.js
Normal file
@ -0,0 +1,16 @@
|
||||
module.exports = function enableTagParams(el, builder) {
|
||||
if (el.argument) {
|
||||
el.params = builder.parseJavaScriptParams(el.argument);
|
||||
el.params.forEach(param => el.addNestedVariable(param));
|
||||
delete el.argument;
|
||||
}
|
||||
el.forEachChild(childNode => {
|
||||
if (isNestedTag(childNode)) {
|
||||
enableTagParams(childNode, builder);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function isNestedTag(node) {
|
||||
return node.tagName && node.tagName[0] === "@";
|
||||
}
|
||||
19
src/compiler/util/parseJavaScriptParams.js
Normal file
19
src/compiler/util/parseJavaScriptParams.js
Normal file
@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
var ok = require("assert").ok;
|
||||
var esprima = require("esprima");
|
||||
|
||||
function parseJavaScriptParams(params, builder) {
|
||||
ok(typeof params === "string", '"params" should be a string');
|
||||
ok(builder, '"builder" is required');
|
||||
|
||||
var src = "(" + params + ") => {}";
|
||||
var jsAST = esprima.parseScript(src, { range: true });
|
||||
var paramNodes = jsAST.body[0].expression.params;
|
||||
return paramNodes.map(node => {
|
||||
var nodeSrc = src.slice(node.range[0], node.range[1]);
|
||||
return builder.expression(nodeSrc);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = parseJavaScriptParams;
|
||||
@ -0,0 +1,17 @@
|
||||
class {
|
||||
onCreate() {
|
||||
this.state = {
|
||||
name:'Anna'
|
||||
}
|
||||
}
|
||||
changeName() {
|
||||
this.state.name = 'Vickie';
|
||||
}
|
||||
}
|
||||
|
||||
<div>
|
||||
<${input.first} name=state.name/>
|
||||
<button on-click('changeName')>
|
||||
Change
|
||||
</button>
|
||||
</div>
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"featureFlags": ["params"]
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
class {}
|
||||
|
||||
<name key="name">
|
||||
<@first({ name })>
|
||||
Hello, ${name}!
|
||||
</@first>
|
||||
</name>
|
||||
@ -0,0 +1,10 @@
|
||||
var expect = require("chai").expect;
|
||||
|
||||
module.exports = function(helpers) {
|
||||
var component = helpers.mount(require.resolve("./index"), {});
|
||||
expect(helpers.targetEl.innerHTML).to.contain("Hello, Anna!");
|
||||
var nameComponent = component.getComponent("name");
|
||||
nameComponent.changeName();
|
||||
nameComponent.update();
|
||||
expect(helpers.targetEl.innerHTML).to.contain("Hello, Vickie!");
|
||||
};
|
||||
@ -0,0 +1,17 @@
|
||||
class {
|
||||
onCreate() {
|
||||
this.state = {
|
||||
name:'Anna'
|
||||
}
|
||||
}
|
||||
changeName() {
|
||||
this.state.name = 'Vickie';
|
||||
}
|
||||
}
|
||||
|
||||
<div>
|
||||
<${input} name=state.name/>
|
||||
<button on-click('changeName')>
|
||||
Change
|
||||
</button>
|
||||
</div>
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"featureFlags": ["params"]
|
||||
}
|
||||
5
test/components-browser/fixtures/tag-params/index.marko
Normal file
5
test/components-browser/fixtures/tag-params/index.marko
Normal file
@ -0,0 +1,5 @@
|
||||
class {}
|
||||
|
||||
<name({ name }) key="name">
|
||||
Hello, ${name}!
|
||||
</name>
|
||||
10
test/components-browser/fixtures/tag-params/test.js
Normal file
10
test/components-browser/fixtures/tag-params/test.js
Normal file
@ -0,0 +1,10 @@
|
||||
var expect = require("chai").expect;
|
||||
|
||||
module.exports = function(helpers) {
|
||||
var component = helpers.mount(require.resolve("./index"), {});
|
||||
expect(helpers.targetEl.innerHTML).to.contain("Hello, Anna!");
|
||||
var nameComponent = component.getComponent("name");
|
||||
nameComponent.changeName();
|
||||
nameComponent.update();
|
||||
expect(helpers.targetEl.innerHTML).to.contain("Hello, Vickie!");
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user