let transform = require('./transform')
let html_escape = require('html-escape')
-let html_body = (node, st, c) => {
- let tag, arguments
- if (node.tag.type === 'CallExpression') {
- tag = node.tag.callee
- arguments = node.tag.arguments
+let expr_to_tag = (node, context, html_allowed, call_allowed) => {
+ if (node.type === 'Identifier')
+ context.name.push(node.name)
+ else if (node.type === 'Literal')
+ context.name.push(node.value.toString())
+ else if (node.type === 'BinaryExpression' && node.operator === '-') {
+ if (!expr_to_tag(node.left, context, false, false))
+ return false;
+ if (!expr_to_tag(node.right, context, html_allowed, call_allowed))
+ return false;
}
- else {
- tag = node.tag
- arguments = []
+ else if (node.type === 'MemberExpression') {
+ if (!expr_to_tag(node.object, context, false, false))
+ return false;
+ context.tag[context.tag_type].push(context.name.join('-'))
+ context.name = []
+ context.tag_type = 1
+ if (!expr_to_tag(node.property, context, html_allowed, call_allowed))
+ return false;
}
- assert(tag.type === 'Identifier')
+ else if (html_allowed && node.type === 'HTMLExpression') {
+ if (!expr_to_tag(node.tag, context, false, true))
+ return false;
+ context.tag[context.tag_type].push(context.name.join('-'))
+ context.body = node.body
+ }
+ else if (call_allowed && node.type === 'CallExpression') {
+ if (!expr_to_tag(node.callee, context, false, false))
+ return false;
+ context.arguments = node.arguments
+ }
+ else
+ return false;
+ return true;
+}
+
+let expr_to_name = (node, name) => {
+ if (node.type === 'Identifier')
+ name.push(node.name)
+ else if (node.type === 'Literal')
+ name.push(node.value.toString())
+ else if (node.type === 'BinaryExpression' && node.operator === '-') {
+ expr_to_name(node.left, name)
+ expr_to_name(node.right, name)
+ }
+ else
+ assert(false)
+}
+
+let html_body = (context, st, c) => {
+ assert(context.tag[0].length == 1)
+ let tag = context.tag[0][0]
+ let prefix = '<' + tag
+
+ if (context.tag[1].length)
+ prefix += ' class="' + context.tag[1].join(' ') + '"'
+
+ let expr = undefined
+ for (var i = 0; i < context.arguments.length; ++i) {
+ let argument = context.arguments[i]
- let prefix = '<' + tag.name, expr = undefined, expr1;
- for (var i = 0; i < arguments.length; ++i) {
let name_expr, value_expr
- if (arguments[i].type === 'AssignmentExpression') {
- name_expr = arguments[i].left
- value_expr = arguments[i].right
+ if (
+ argument.type === 'AssignmentExpression' &&
+ argument.operator === '='
+ ) {
+ name_expr = argument.left
+ value_expr = c(argument.right, st, 'Expression')
}
else {
- name_expr = arguments[i]
+ name_expr = argument
value_expr = undefined
}
- let name = ''
- while (
- name_expr.type === 'BinaryExpression' &&
- name_expr.operator === '-' &&
- name_expr.right.type === 'Identifier'
- ) {
- name = '-' + name_expr.right.name + name
- name_expr = name_expr.left
- }
- assert(name_expr.type === 'Identifier')
- name = name_expr.name + name
- prefix += ' ' + name
-
+ name = []
+ expr_to_name(name_expr, name)
+ prefix += ' ' + name.join('-')
+
if (value_expr !== undefined) {
prefix += '="'
if (value_expr.type === 'Literal')
prefix += html_escape(value_expr.value)
else {
- expr1 = {
+ let expr1 = {
type: 'Literal',
value: prefix
}
type: 'BinaryExpression',
left: expr,
operator: '+',
- right: expr1,
- start: node.start,
- end: node.end
+ right: expr1
},
operator: '+',
right: {
prefix += '"'
}
}
- expr1 = {
+
+ let expr1 = {
type: 'Literal',
value: prefix + '>',
}
operator: '+',
right: expr1,
}
+
let result = [
{
type: 'ExpressionStatement',
]
}
}
- ].concat(c(node.body, st, 'Statement').body)
+ ].concat(c(context.body, st, 'Statement').body)
if (
- tag.name !== 'br' &&
- tag.name !== 'img' &&
- tag.name !== 'input' &&
- tag.name !== 'link' &&
- tag.name !== 'meta'
+ tag !== 'br' &&
+ tag !== 'img' &&
+ tag !== 'input' &&
+ tag !== 'link' &&
+ tag !== 'meta'
)
result.push(
{
arguments: [
{
type: 'Literal',
- value: '</' + tag.name + '>'
+ value: '</' + tag + '>'
}
]
}
let visitors = Object.assign({}, transform.visitors)
let visitors_ExpressionStatement = visitors.ExpressionStatement
-visitors.ExpressionStatement = (node, st, c) =>
- node.expression.type === 'Literal' ||
- node.expression.type === 'TemplateLiteral' ||
- node.expression.type === 'TaggedTemplateLiteral' ?
- {
- type: 'ExpressionStatement',
- expression: {
- type: 'CallExpression',
- callee: {
- type: 'MemberExpression',
- object: {
- type: 'Identifier',
- name: '_out'
- },
- property: {
- type: 'Identifier',
- name: 'push'
- },
- computed: false
- },
- arguments: [
- {
- type: 'CallExpression',
- callee: {
+visitors.ExpressionStatement = (node, st, c) => {
+ if (
+ node.expression.type === 'Literal' ||
+ node.expression.type === 'TemplateLiteral' ||
+ node.expression.type === 'TaggedTemplateLiteral'
+ )
+ return {
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'CallExpression',
+ callee: {
+ type: 'MemberExpression',
+ object: {
type: 'Identifier',
- name: '_esc'
+ name: '_out'
},
- arguments: [
- c(node.expression, st, 'Expression')
- ]
- }
- ]
- }
- } :
- node.expression.type === 'HTMLExpression' ?
- {
- type: 'BlockStatement',
- body: html_body(node.expression, st, c)
- } :
- visitors_ExpressionStatement(node, st, c)
-visitors.HTMLExpression = (node, st, c) => {
- return {
- type: 'CallExpression',
- callee: {
- type: 'ArrowFunctionExpression',
- id: null,
- expression: false,
- generator: false,
- async: false,
- params: [],
- body: {
- type: 'BlockStatement',
- body: [
+ property: {
+ type: 'Identifier',
+ name: 'push'
+ },
+ computed: false
+ },
+ arguments: [
{
- type: 'VariableDeclaration',
- declarations: [
- {
- type: 'VariableDeclarator',
- id: {
- type: 'Identifier',
- name: '_out'
- },
- init: {
- type: 'ArrayExpression',
- elements: []
- }
- }
- ],
- kind: 'let'
+ type: 'CallExpression',
+ callee: {
+ type: 'Identifier',
+ name: '_esc'
+ },
+ arguments: [
+ c(node.expression, st, 'Expression')
+ ]
}
]
- .concat(html_body(node, st, c))
- .concat(
- [
- {
- type: 'ReturnStatement',
- argument: {
- type: 'CallExpression',
- callee: {
- type: 'MemberExpression',
- object: {
- type: 'Identifier',
- name: '_out'
- },
- property: {
- type: 'Identifier',
- name: 'join'
- },
- computed: false
- },
- arguments: [
+ }
+ }
+ if (
+ node.expression.type === 'BinaryExpression' ||
+ node.expression.type === 'MemberExpression' ||
+ node.expression.type === 'HTMLExpression'
+ ) {
+ context = {name: [], tag: [[], []], tag_type: 0, arguments: []}
+ if (
+ expr_to_tag(node.expression, context, true, false) &&
+ context.body !== undefined
+ )
+ return {
+ type: 'BlockStatement',
+ body: html_body(context, st, c)
+ }
+ }
+ return visitors_ExpressionStatement(node, st, c)
+}
+let visitors_Expression = visitors.Expression
+visitors.Expression = (node, st, c) => {
+ if (
+ node.type === 'BinaryExpression' ||
+ node.type === 'MemberExpression' ||
+ node.type === 'HTMLExpression'
+ ) {
+ context = {name: [], tag: [[], []], tag_type: 0, arguments: []}
+ if (
+ expr_to_tag(node, context, true, false) &&
+ context.body !== undefined
+ )
+ return {
+ type: 'CallExpression',
+ callee: {
+ type: 'ArrowFunctionExpression',
+ id: null,
+ expression: false,
+ generator: false,
+ async: false,
+ params: [],
+ body: {
+ type: 'BlockStatement',
+ body: [
+ {
+ type: 'VariableDeclaration',
+ declarations: [
{
- type: 'Literal',
- value: '',
- raw: '\'\''
+ type: 'VariableDeclarator',
+ id: {
+ type: 'Identifier',
+ name: '_out'
+ },
+ init: {
+ type: 'ArrayExpression',
+ elements: []
+ }
}
- ]
+ ],
+ kind: 'let'
}
- }
- ]
- )
+ ]
+ .concat(html_body(context, st, c))
+ .concat(
+ [
+ {
+ type: 'ReturnStatement',
+ argument: {
+ type: 'CallExpression',
+ callee: {
+ type: 'MemberExpression',
+ object: {
+ type: 'Identifier',
+ name: '_out'
+ },
+ property: {
+ type: 'Identifier',
+ name: 'join'
+ },
+ computed: false
+ },
+ arguments: [
+ {
+ type: 'Literal',
+ value: '',
+ raw: '\'\''
+ }
+ ]
+ }
+ }
+ ]
+ )
+ }
+ },
+ arguments: []
}
- },
- arguments: []
}
+ return visitors_Expression(node, st, c)
}
module.exports = visitors