From 3bd85d070731e612075d8cd8549b6a55263008a8 Mon Sep 17 00:00:00 2001 From: Michael Rawlings Date: Mon, 23 Jan 2017 17:58:48 -0800 Subject: [PATCH] add support for class tag --- taglibs/core/class-tag.js | 7 +++ taglibs/core/marko.json | 3 ++ test/autotests/compiler/class-tag/expected.js | 13 ++++++ .../compiler/class-tag/template.marko | 7 +++ .../taglib-lookup/forEachTag/expected.json | 1 + .../taglib-lookup/getTagsSorted/expected.json | 1 + .../component-inline-class/expected.js | 24 ++++++++++ .../component-inline-class/index.marko | 11 +++++ .../taglib/TransformHelper/handleRootNodes.js | 44 +++++++++++++++++++ 9 files changed, 111 insertions(+) create mode 100644 taglibs/core/class-tag.js create mode 100644 test/autotests/compiler/class-tag/expected.js create mode 100644 test/autotests/compiler/class-tag/template.marko create mode 100644 test/autotests/widgets-compilation/component-inline-class/expected.js create mode 100644 test/autotests/widgets-compilation/component-inline-class/index.marko diff --git a/taglibs/core/class-tag.js b/taglibs/core/class-tag.js new file mode 100644 index 000000000..b434b01ee --- /dev/null +++ b/taglibs/core/class-tag.js @@ -0,0 +1,7 @@ +module.exports = function functionCodeGenerator(el, codegen) { + if(el.parentNode.type !== 'TemplateRoot') { + codegen.addError('class is a static tag and can only be declared at the template root'); + } + codegen.addStaticCode(codegen.builder.expression(el.tagString)); + return null; +}; \ No newline at end of file diff --git a/taglibs/core/marko.json b/taglibs/core/marko.json index 931480a3e..1c644cae2 100644 --- a/taglibs/core/marko.json +++ b/taglibs/core/marko.json @@ -9,6 +9,9 @@ } ] }, + "": { + "code-generator": "./class-tag" + }, "": { "node-factory": "./else-tag", "attributes": {}, diff --git a/test/autotests/compiler/class-tag/expected.js b/test/autotests/compiler/class-tag/expected.js new file mode 100644 index 000000000..94bc0adf9 --- /dev/null +++ b/test/autotests/compiler/class-tag/expected.js @@ -0,0 +1,13 @@ +var marko_template = module.exports = require("marko/html").t(__filename); + +class Foo { + constructor() { + + } +}; + +function render(data, out) { + var foo = new Foo(); +} + +marko_template._ = render; diff --git a/test/autotests/compiler/class-tag/template.marko b/test/autotests/compiler/class-tag/template.marko new file mode 100644 index 000000000..eae063ae6 --- /dev/null +++ b/test/autotests/compiler/class-tag/template.marko @@ -0,0 +1,7 @@ +class Foo { + constructor() { + + } +} + +var foo = new Foo(); \ No newline at end of file diff --git a/test/autotests/taglib-lookup/forEachTag/expected.json b/test/autotests/taglib-lookup/forEachTag/expected.json index d249222de..92a8515dd 100644 --- a/test/autotests/taglib-lookup/forEachTag/expected.json +++ b/test/autotests/taglib-lookup/forEachTag/expected.json @@ -11,6 +11,7 @@ "lasso-resource", "browser-refresh", "assign", + "class", "else", "else-if", "for", diff --git a/test/autotests/taglib-lookup/getTagsSorted/expected.json b/test/autotests/taglib-lookup/getTagsSorted/expected.json index 2dce99fee..4b53563d6 100644 --- a/test/autotests/taglib-lookup/getTagsSorted/expected.json +++ b/test/autotests/taglib-lookup/getTagsSorted/expected.json @@ -18,6 +18,7 @@ "body", "browser-refresh", "cached-fragment", + "class", "else", "else-if", "foo", diff --git a/test/autotests/widgets-compilation/component-inline-class/expected.js b/test/autotests/widgets-compilation/component-inline-class/expected.js new file mode 100644 index 000000000..5f61497ef --- /dev/null +++ b/test/autotests/widgets-compilation/component-inline-class/expected.js @@ -0,0 +1,24 @@ +var marko_template = module.exports = require("marko/html").t(__filename), + marko_component = { + foo: function() {}, + bar: function() {} + }, + marko_widgets = require("marko/widgets"), + marko_registerWidget = marko_widgets.rw, + marko_widgetType = marko_registerWidget("/marko-test$1.0.0/autotests/widgets-compilation/component-inline-class/index.marko", function() { + return module.exports; + }), + marko_helpers = require("marko/runtime/html/helpers"), + marko_attr = marko_helpers.a; + +function render(data, out, widget, state) { + out.w(""); +} + +marko_template._ = marko_widgets.r(render, { + type: marko_widgetType + }, marko_component); + +marko_template.Widget = marko_widgets.w(marko_component, marko_template._); diff --git a/test/autotests/widgets-compilation/component-inline-class/index.marko b/test/autotests/widgets-compilation/component-inline-class/index.marko new file mode 100644 index 000000000..23e4de14f --- /dev/null +++ b/test/autotests/widgets-compilation/component-inline-class/index.marko @@ -0,0 +1,11 @@ +class { + foo() { + + } + bar() { + + } +} + +
+
\ No newline at end of file diff --git a/widgets/taglib/TransformHelper/handleRootNodes.js b/widgets/taglib/TransformHelper/handleRootNodes.js index 270fafb5c..cf7f6aad4 100644 --- a/widgets/taglib/TransformHelper/handleRootNodes.js +++ b/widgets/taglib/TransformHelper/handleRootNodes.js @@ -114,6 +114,43 @@ function handleStyleElement(styleEl, transformHelper) { styleEl.detach(); } +function methodToProperty(method) { + return { + type: 'Property', + key: method.key, + computed: false, + value: method.value, + kind: 'init', + method: true, + shorthand: false + }; +} + +function classToObject(cls, transformHelper) { + return { + type: 'ObjectExpression', + properties: cls.body.body.map((method) => { + if(method.type != 'MethodDefinition') { + throw Error('Only methods are allowed on single file component class definitions.'); + } + return methodToProperty(method); + }) + }; +} + +function handleClassDeclaration(classEl, transformHelper) { + if(!/^class\s*\{/.test(classEl.tagString)) return; + + let tree = esprima.parse('('+classEl.tagString+')'); + let expression = tree.body[0].expression; + let object = classToObject(expression); + let componentVar = transformHelper.context.addStaticVar('marko_component', escodegen.generate(object)); + + transformHelper.setHasBoundWidgetForTemplate(); + transformHelper.setInlineComponent(componentVar); + classEl.detach() +} + module.exports = function handleRootNodes() { var context = this.context; var builder = this.builder; @@ -177,9 +214,16 @@ module.exports = function handleRootNodes() { return; } else if (node.type === 'CustomTag') { rootNodes.push(node); + walker.skip(); return; } else { + var tagName = node.tagName && node.tagName.toLowerCase(); + + if (tagName === 'class') { + handleClassDeclaration(node, transformHelper); + } + walker.skip(); return; }