From d6d417c7466482747f4756fabe4d2ef83e56c44c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Asiel=20Guevara=20Casta=C3=B1eda?= Date: Mon, 8 Oct 2018 08:44:29 -0400 Subject: [PATCH 1/9] Optimized dynamic tag code generation --- src/generators/components.ts | 7 +------ src/index.ts | 2 +- tools/index.ts | 3 +++ 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/generators/components.ts b/src/generators/components.ts index da3e139..065c30e 100644 --- a/src/generators/components.ts +++ b/src/generators/components.ts @@ -12,18 +12,13 @@ export function genTag(node: NodeElement, areas: BlockAreas, scope: string) { if (node.childNodes.length) node.dymTag = element; if (expression) { const setElement = `setTag${capitalize(element)}`; - const updateTag = `updateTag${capitalize(element)}`; areas.variables.push(setElement); const code = ctx(filterParser(expression), scope, areas.globals); let params = areas.globals && areas.globals.length > 0 ? `, ${areas.globals.join(', ')}` : ''; const setTag = `${setElement}(${scope}${params})`; areas.extras.push(`${setElement} = (${scope}${params}) => ${code};`); areas.create.push(`${element} = _$ce(${setTag});`); - areas.update.push(`let ${updateTag} = ${setTag}; - if (${updateTag}.toUpperCase() !== ${element}.tagName) { - ${element} = _$as(${element}, _$ce(${updateTag})); - } - ${updateTag} = void 0;`); + areas.update.push(`${element} = _$nu(${element}, ${setTag});`); } else { element = getVarName(areas.variables, node.tagName); } diff --git a/src/index.ts b/src/index.ts index 90c2233..7598a12 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,7 @@ import { basename, extname, dirname, join } from 'path'; import { genTemplate, CompilerOptions } from './generators'; import { kebabToCamelCases, capitalize, camelToKebabCase } from './utilities/tools'; -const dest = `{ _$CompCtr, _$, _$d, _$a, _$add, _$remove, _$as, _$r, _$ce, _$cse, _$ct, _$bu, _$tu, +const dest = `{ _$CompCtr, _$, _$d, _$a, _$add, _$remove, _$as, _$r, _$ce, _$cse, _$ct, _$bu, _$tu, _$nu, _$cm, _$sa, _$ga, _$al, _$ul, _$rl, _$bc, _$bs, _$f, _$e, _$is, _$ds, _$toStr, _$bindMultiSelect, _$gv, _$setRef, _$noop, _$isType, _$isKey, _$bindGroup, _$cu, _$emptyElse, _$extends, _$updateMultiSelect }`; const esDeps = `import ${dest} from 'trebor/tools';`; diff --git a/tools/index.ts b/tools/index.ts index af76cd2..6d655e5 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -580,6 +580,9 @@ export function _$bu(el: (HTMLInputElement | HTMLSelectElement | HTMLTextAreaEle export function _$tu(text: Text, value: string) { if (text.data !== (value = _$toStr(value))) text.data = value; } +export function _$nu(node: HTMLElement, tag: T) { + return tag.toUpperCase() !== node.tagName ? _$as(node, _$ce(tag)) : node; +} export function _$f(root: Component, obj: any[], loop: (...args: any[]) => ComponentTemplate) { let items: ObjectLike = {}, loopParent: Element, loopSibling: Element; let globs = _$toArgs(arguments, 3); From 39324fc2babb43373334e32c2cb8408df123c535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Asiel=20Guevara=20Casta=C3=B1eda?= Date: Mon, 8 Oct 2018 08:48:42 -0400 Subject: [PATCH 2/9] Fixed errors passing children in loops and conditions --- src/generators/commons.ts | 3 ++- tools/index.ts | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/generators/commons.ts b/src/generators/commons.ts index 016146f..e865a89 100644 --- a/src/generators/commons.ts +++ b/src/generators/commons.ts @@ -103,7 +103,8 @@ export function genBlockAreas(node: NodeElement, areas: BlockAreas, scope: strin export function genBody(funcName: string, scope: string, areas: BlockAreas, condType?: string) { return `${!areas.outer.length ? '' : `${areas.outer.join('\n')} - `}function ${funcName}(${scope}, children) { + `}function ${funcName}(${scope}) { + let { children } = ${scope.split(',')[0]}.$options; ${!areas.variables.length ? '' : `let ${areas.variables.join(', ')}`};${!areas.extras.length ? '' : ` ${areas.extras.join('\n')}`} return { diff --git a/tools/index.ts b/tools/index.ts index 6d655e5..57539e6 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -1,7 +1,7 @@ type AttrTypes = string | number | RegExp | null | boolean; type AttrParams = string[] | ObjectLike; type DirectiveDefinition = (inst: Component, options: DirectiveOptions, node: HTMLElement) => void | DirectiveDefObject; -type TemplateFn = (component: Component, children: ObjectLike) => ComponentTemplate; +type TemplateFn = (component: Component) => ComponentTemplate; type IterateKey = T extends any[] ? number : string; type IterateValue = T extends any[] ? T[number] : T[keyof T]; type PluginFn = (this: Component, ctor: ComponentConstructor, pluginOptions?: ObjectLike) => void; @@ -157,7 +157,7 @@ export function _$CompCtr(attrs: AttrParams, template: TemplateFn, options: Comp _$def(self, key, desc); } } - const tpl = template(self, opts.children); + const tpl = template(self); _$e(tpl, (value, key) => { _$def(self, key, { value: (function (key) { From 6e1be209f2471468aedbe42b5d0311e5bf7bc2c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Asiel=20Guevara=20Casta=C3=B1eda?= Date: Mon, 8 Oct 2018 08:49:32 -0400 Subject: [PATCH 3/9] Added Sequence expression to context generation --- src/types/recast.d.ts | 3 +- src/utilities/context.ts | 836 ++++++++++++++++++++------------------- 2 files changed, 427 insertions(+), 412 deletions(-) diff --git a/src/types/recast.d.ts b/src/types/recast.d.ts index 5439216..0d23b04 100644 --- a/src/types/recast.d.ts +++ b/src/types/recast.d.ts @@ -1,6 +1,6 @@ import { Node, BinaryExpression, Literal, CallExpression, - MemberExpression, Identifier, Expression, BinaryOperator, Program, Property, ExpressionStatement, TemplateLiteral, ArrayExpression, ConditionalExpression, SpreadElement, UnaryExpression, LogicalExpression, UpdateExpression, AssignmentExpression, ImportDeclaration, ExportDefaultDeclaration, VariableDeclaration, FunctionDeclaration, FunctionExpression, SwitchStatement, WhileStatement, IfStatement, TryStatement + MemberExpression, Identifier, Expression, BinaryOperator, Program, Property, ExpressionStatement, TemplateLiteral, ArrayExpression, ConditionalExpression, SpreadElement, UnaryExpression, LogicalExpression, UpdateExpression, AssignmentExpression, ImportDeclaration, ExportDefaultDeclaration, VariableDeclaration, FunctionDeclaration, FunctionExpression, SwitchStatement, WhileStatement, IfStatement, TryStatement, SequenceExpression } from 'estree'; interface NamedType { @@ -91,6 +91,7 @@ interface Types { visitUpdateExpression?(this: Visitor, path: Path, ...args: any[]): boolean | void; visitLogicalExpression?(this: Visitor, path: Path, ...args: any[]): boolean | void; visitImportDeclaration?(this: Visitor, path: Path, ...args: any[]): boolean | void; + visitSequenceExpression?(this: Visitor, path: Path, ...args: any[]): boolean | void; visitFunctionExpression?(this: Visitor, path: Path, ...args: any[]): boolean | void; visitFunctionDeclaration?(this: Visitor, path: Path, ...args: any[]): boolean | void; visitExpressionStatement?(this: Visitor, path: Path, ...args: any[]): boolean | void; diff --git a/src/utilities/context.ts b/src/utilities/context.ts index 729803e..92b6311 100644 --- a/src/utilities/context.ts +++ b/src/utilities/context.ts @@ -4,9 +4,9 @@ import { Recast, Path, RecastAST } from '../types/recast'; import { builtin, browser, node as nodejs, amd } from 'globals'; import { analyze, Scope, Variable, Reference } from 'eslint-scope'; import { - Node, Expression, Identifier, AssignmentExpression, UpdateExpression, - UnaryExpression, BinaryExpression, BinaryOperator, Literal, UnaryOperator, - ExportDefaultDeclaration, BlockStatement, VariableDeclaration, ImportDeclaration, FunctionExpression + Node, Expression, Identifier, AssignmentExpression, UpdateExpression, + UnaryExpression, BinaryExpression, BinaryOperator, Literal, UnaryOperator, + ExportDefaultDeclaration, BlockStatement, VariableDeclaration, ImportDeclaration, FunctionExpression } from 'estree'; const { print, types, parse } = recast; @@ -16,519 +16,533 @@ const { Identifier, BlockStatement, Literal, UnaryExpression } = types.namedType const { binaryExpression, literal, callExpression, memberExpression, identifier } = types.builders; export function ctx(src: string, context: string, globals: string[] = []) { - if (src[0] === '{') src = `let _$o = ${src}`; - let ast = toAst(src); - visitExpressions(ast, context, globals.concat([context])); - return toCode(ast).code.replace('let _$o = ', ''); + if (src[0] === '{') src = `let _$o = ${src}`; + let ast = toAst(src); + visitExpressions(ast, context, globals.concat([context])); + return toCode(ast).code.replace('let _$o = ', ''); } export function toOptions(src: string) { - let ast = toAst(src, 'module'); - return visitOptions(ast); + let ast = toAst(src, 'module'); + return visitOptions(ast); } export function optimize(src: string) { - let ast = toAst(src, 'module'); - visitOptimize(ast); - return toCode(ast).code; + let ast = toAst(src, 'module'); + visitOptimize(ast); + return toCode(ast).code; } function assignify(node: Node, ctx: string) { - if (isReplaceable(node)) { - if (types.namedTypes.AssignmentExpression.check(node)) { - let { operator, left, right } = node; - operator = operator.replace('=', '').trim(); - return settify(ctx, left, operator ? binaryExpression(operator, left, right) : right); - } else { - let { argument, operator } = node; - return settify(ctx, argument, binaryExpression(operator[0], argument, literal(1))); - } - } else { - return node; - } + if (isReplaceable(node)) { + if (types.namedTypes.AssignmentExpression.check(node)) { + let { operator, left, right } = node; + operator = operator.replace('=', '').trim(); + return settify(ctx, left, operator ? binaryExpression(operator, left, right) : right); + } else { + let { argument, operator } = node; + return settify(ctx, argument, binaryExpression(operator[0], argument, literal(1))); + } + } else { + return node; + } } function settify(ctx: string, left: Node, right: Expression) { - let callee = memberExpression(identifier(ctx), identifier('$set'), false); - let args = [literal(print(left).code), Identifier.check(right) ? toMember(right, ctx) : right]; - return callExpression(callee, args); + let callee = memberExpression(identifier(ctx), identifier('$set'), false); + let args = [literal(print(left).code), Identifier.check(right) ? toMember(right, ctx) : right]; + return callExpression(callee, args); } function visitExpressions(ast: RecastAST, ctx: string, globals: string[]) { - types.visit(ast, { - visitProperty(path) { - let { node } = path; - node.shorthand = false; - if (node.computed) { - if (canBeReplaced(node.key, path, globals)) { - replace('key', ctx, path); - } - this.traverse(path); - } - if (canBeReplaced(node.value, path, globals)) { - replace('value', ctx, path); - return false; - } - this.traverse(path); - }, - visitCallExpression(path) { - let { node } = path; - canBeReplaced(node.callee, path, globals) && replace('callee', ctx, path); - node.arguments.forEach((argument, i) => { - canBeReplaced(argument, path, globals) && replace('arguments', ctx, path, i); - }); - return this.traverse(path); - }, - visitMemberExpression(path) { - let { node } = path; - if (canBeReplaced(node.object, path, globals)) { - replace('object', ctx, path); - if (node.computed && canBeReplaced(node.property, path, globals)) { - replace('property', ctx, path); - return false; - } - } - this.traverse(path); - }, - visitExpressionStatement(path) { - let { node } = path; - if (canBeReplaced(node.expression, path, globals)) { - replace('expression', ctx, path); - } - this.traverse(path); - }, - visitTemplateLiteral(path) { - let { node } = path; - node.expressions.forEach((expression, i) => { - canBeReplaced(expression, path, globals) && replace('expressions', ctx, path, i); - }); - this.traverse(path); - }, - visitArrayExpression(path) { - let { node } = path; - node.elements.forEach((element, i) => { - canBeReplaced(element, path, globals) && replace('elements', ctx, path, i); - }); - this.traverse(path); - }, - visitConditionalExpression(path) { - let { node } = path; - canBeReplaced(node.test, path, globals) && replace('test', ctx, path); - canBeReplaced(node.alternate, path, globals) && replace('alternate', ctx, path); - canBeReplaced(node.consequent, path, globals) && replace('consequent', ctx, path); - this.traverse(path); - }, - visitSpreadElement(path) { - this.visitUnaryExpression(path); - }, - visitUnaryExpression(path) { - let { node } = path; - canBeReplaced(node.argument, path, globals) && replace('argument', ctx, path); - this.traverse(path); - }, - visitBinaryExpression(path) { - this.visitLogicalExpression(path); - }, - visitLogicalExpression(path) { - let { node } = path; - canBeReplaced(node.left, path, globals) && replace('left', ctx, path); - canBeReplaced(node.right, path, globals) && replace('right', ctx, path); - this.traverse(path); - }, - visitUpdateExpression(path) { - this.visitAssignmentExpression(path); - }, - visitAssignmentExpression(path) { - let { node, parent } = path; - let newNode = assignify(node, ctx); - node !== newNode && parent.get('expression').replace(newNode); - this.traverse(path); - } - }); - return ast; + types.visit(ast, { + visitProperty(path) { + let { node } = path; + node.shorthand = false; + if (node.computed) { + if (canBeReplaced(node.key, path, globals)) { + replace('key', ctx, path); + } + this.traverse(path); + } + if (canBeReplaced(node.value, path, globals)) { + replace('value', ctx, path); + return false; + } + this.traverse(path); + }, + visitCallExpression(path) { + let { node } = path; + canBeReplaced(node.callee, path, globals) && replace('callee', ctx, path); + node.arguments.forEach((argument, i) => { + canBeReplaced(argument, path, globals) && replace('arguments', ctx, path, i); + }); + return this.traverse(path); + }, + visitSequenceExpression(path) { + let { node } = path; + node.expressions.forEach((exp, i) => { + canBeReplaced(exp, path, globals) && replace('expressions', ctx, path, i); + }); + return this.traverse(path); + }, + visitMemberExpression(path) { + let { node } = path; + if (canBeReplaced(node.object, path, globals)) { + replace('object', ctx, path); + if (node.computed && canBeReplaced(node.property, path, globals)) { + replace('property', ctx, path); + return false; + } + } + this.traverse(path); + }, + visitExpressionStatement(path) { + let { node } = path; + if (canBeReplaced(node.expression, path, globals)) { + replace('expression', ctx, path); + } + this.traverse(path); + }, + visitTemplateLiteral(path) { + let { node } = path; + node.expressions.forEach((expression, i) => { + canBeReplaced(expression, path, globals) && replace('expressions', ctx, path, i); + }); + this.traverse(path); + }, + visitArrayExpression(path) { + let { node } = path; + node.elements.forEach((element, i) => { + canBeReplaced(element, path, globals) && replace('elements', ctx, path, i); + }); + this.traverse(path); + }, + visitConditionalExpression(path) { + let { node } = path; + canBeReplaced(node.test, path, globals) && replace('test', ctx, path); + canBeReplaced(node.alternate, path, globals) && replace('alternate', ctx, path); + canBeReplaced(node.consequent, path, globals) && replace('consequent', ctx, path); + this.traverse(path); + }, + visitSpreadElement(path) { + this.visitUnaryExpression(path); + }, + visitUnaryExpression(path) { + let { node } = path; + canBeReplaced(node.argument, path, globals) && replace('argument', ctx, path); + this.traverse(path); + }, + visitBinaryExpression(path) { + this.visitLogicalExpression(path); + }, + visitLogicalExpression(path) { + let { node } = path; + canBeReplaced(node.left, path, globals) && replace('left', ctx, path); + canBeReplaced(node.right, path, globals) && replace('right', ctx, path); + this.traverse(path); + }, + visitUpdateExpression(path) { + this.visitAssignmentExpression(path); + }, + visitAssignmentExpression(path) { + let { node, parent } = path; + if (canBeReplaced('argument' in node ? node['argument'] : node.left, path, globals)) { + let newNode = assignify(node, ctx); + if ('expressions' in parent.node) { + let i = parent.node.expressions.indexOf(node); + node !== newNode && parent.get('expressions', i).replace(newNode); + } else { + node !== newNode && parent.get('expression').replace(newNode); + } + } + this.traverse(path); + } + }); + return ast; } function visitOptions(ast) { - let options = ''; - const imports: string[] = []; - types.visit(ast, { - visitImportDeclaration(path) { - return this.extract(path, node => { imports.push(print(node).code); }); - }, - visitExportDefaultDeclaration(path) { - return this.extract(path, ({ declaration }: ExportDefaultDeclaration) => { - options = print(declaration).code; - }); - }, - extract(path, extractor: (node: Node) => boolean) { - extractor(path.node); - path.prune(); - return false; - } - }); - let extras = print(ast).code; - return { imports, extras, options }; + let options = ''; + const imports: string[] = []; + types.visit(ast, { + visitImportDeclaration(path) { + return this.extract(path, node => { imports.push(print(node).code); }); + }, + visitExportDefaultDeclaration(path) { + return this.extract(path, ({ declaration }: ExportDefaultDeclaration) => { + options = print(declaration).code; + }); + }, + extract(path, extractor: (node: Node) => boolean) { + extractor(path.node); + path.prune(); + return false; + } + }); + let extras = print(ast).code; + return { imports, extras, options }; } function visitOptimize(ast: RecastAST) { - let iterations = 0; - let unused = findUnused(ast); - let isUnused = (node: Identifier) => !!unused.find(id => isSameIdentifier(id, node)); - while (iterations < 5) { - types.visit(ast, { - // Remove unused declarations - visitImportDeclaration(path) { - this.declarations(path, 'specifiers', 'local'); - }, - visitVariableDeclaration(path) { - this.declarations(path, 'declarations', 'id'); - }, - visitFunctionExpression(path) { - let { params } = path.node; - for (let i = params.length - 1; i >= 0; i--) { - isUnused(params[i]) ? path.get('params', i).prune() : (i = -1); - } - this.traverse(path); - }, - visitFunctionDeclaration(path) { - let { id } = path.node; - if (isUnused(id)) { - path.prune(); - return false; - } - this.visitFunctionExpression(path); - }, - // Remove empty block statements - visitSwitchStatement(path) { - let { node } = path; - return this.emptyStatement(path, !node.cases.length); - }, - visitWhileStatement(path) { - let { body } = path.node; - return this.emptyStatement(path, BlockStatement.check(body) && !(body).body.length); - }, - visitIfStatement(path) { - let { node } = path; - if (BlockStatement.check(node.alternate)) { - !(node.alternate).body.length && path.get('alternate').prune(); - } else if (types.namedTypes.IfStatement.check(node.alternate)) { - this.traverse(path); - } - let condition = BlockStatement.check(node.consequent) - && !(node.consequent).body.length && !node.alternate; - return this.emptyStatement(path, condition); - }, - visitTryStatement(path) { - let { node } = path; - if (BlockStatement.check(node.finalizer) && !node.finalizer.body.length) { - path.get('finalizer').prune(); - } - let condition = BlockStatement.check(node.block) && !node.block.body.length - && BlockStatement.check(node.handler.body) && !node.handler.body.body.length; - return this.emptyStatement(path, condition); - }, - // reduce expressions - visitUnaryExpression(path) { - let { node } = path; - if (Literal.check(node.argument) && node.operator !== 'void') { - path.replace(toLiteral(node)); - } - this.traverse(path); - }, - visitLogicalExpression(path) { - this.visitBinaryExpression(path); - }, - visitBinaryExpression(path) { - this.traverse(path); - let { node } = path; - if (Literal.check(node.left) && Literal.check(node.right)) { - path.replace(toLiteral(node)); - } - }, - // utils - declarations(path, list: string, prop: string) { - let node = path.node; - let items = node[list]; - for (let i = items.length - 1; i >= 0; i--) { - isUnused(items[i][prop]) && path.get(list, i).prune(); - } - !items.length && prop === 'local' && path.prune(); - this.traverse(path); - }, - emptyStatement(path, condition: boolean) { - if (condition) { - path.prune(); - return false; - } - this.traverse(path); - } - }); - unused = findUnused(ast); - iterations++; - if (!unused.length) { - iterations = 5; - } - } + let iterations = 0; + let unused = findUnused(ast); + let isUnused = (node: Identifier) => !!unused.find(id => isSameIdentifier(id, node)); + while (iterations < 5) { + types.visit(ast, { + // Remove unused declarations + visitImportDeclaration(path) { + this.declarations(path, 'specifiers', 'local'); + }, + visitVariableDeclaration(path) { + this.declarations(path, 'declarations', 'id'); + }, + visitFunctionExpression(path) { + let { params } = path.node; + for (let i = params.length - 1; i >= 0; i--) { + isUnused(params[i]) ? path.get('params', i).prune() : (i = -1); + } + this.traverse(path); + }, + visitFunctionDeclaration(path) { + let { id } = path.node; + if (isUnused(id)) { + path.prune(); + return false; + } + this.visitFunctionExpression(path); + }, + // Remove empty block statements + visitSwitchStatement(path) { + let { node } = path; + return this.emptyStatement(path, !node.cases.length); + }, + visitWhileStatement(path) { + let { body } = path.node; + return this.emptyStatement(path, BlockStatement.check(body) && !(body).body.length); + }, + visitIfStatement(path) { + let { node } = path; + if (BlockStatement.check(node.alternate)) { + !(node.alternate).body.length && path.get('alternate').prune(); + } else if (types.namedTypes.IfStatement.check(node.alternate)) { + this.traverse(path); + } + let condition = BlockStatement.check(node.consequent) + && !(node.consequent).body.length && !node.alternate; + return this.emptyStatement(path, condition); + }, + visitTryStatement(path) { + let { node } = path; + if (BlockStatement.check(node.finalizer) && !node.finalizer.body.length) { + path.get('finalizer').prune(); + } + let condition = BlockStatement.check(node.block) && !node.block.body.length + && BlockStatement.check(node.handler.body) && !node.handler.body.body.length; + return this.emptyStatement(path, condition); + }, + // reduce expressions + visitUnaryExpression(path) { + let { node } = path; + if (Literal.check(node.argument) && node.operator !== 'void') { + path.replace(toLiteral(node)); + } + this.traverse(path); + }, + visitLogicalExpression(path) { + this.visitBinaryExpression(path); + }, + visitBinaryExpression(path) { + this.traverse(path); + let { node } = path; + if (Literal.check(node.left) && Literal.check(node.right)) { + path.replace(toLiteral(node)); + } + }, + // utils + declarations(path, list: string, prop: string) { + let node = path.node; + let items = node[list]; + for (let i = items.length - 1; i >= 0; i--) { + isUnused(items[i][prop]) && path.get(list, i).prune(); + } + !items.length && prop === 'local' && path.prune(); + this.traverse(path); + }, + emptyStatement(path, condition: boolean) { + if (condition) { + path.prune(); + return false; + } + this.traverse(path); + } + }); + unused = findUnused(ast); + iterations++; + if (!unused.length) { + iterations = 5; + } + } } function toLiteral(node: Node) { - if (UnaryExpression.check(node)) { - let { operator, argument } = node; - return literal(evalUnary(operator, (argument).value)); - } else { - let { operator, left, right } = node; - return literal(evalBinary(operator, (left).value, (right).value)); - } + if (UnaryExpression.check(node)) { + let { operator, argument } = node; + return literal(evalUnary(operator, (argument).value)); + } else { + let { operator, left, right } = node; + return literal(evalBinary(operator, (left).value, (right).value)); + } } function evalUnary(operator: UnaryOperator, argument: any) { - let evaluate = `${/typeof|delete/.test(operator) ? `${operator} ` : operator}${toValue(argument)}`; - return eval(evaluate); + let evaluate = `${/typeof|delete/.test(operator) ? `${operator} ` : operator}${toValue(argument)}`; + return eval(evaluate); } function evalBinary(operator: BinaryOperator, left: any, right: any) { - let evaluate = `${toValue(left)}${operator}${toValue(right)}`; - return eval(evaluate); + let evaluate = `${toValue(left)}${operator}${toValue(right)}`; + return eval(evaluate); } function toValue(value: any) { - return typeof value === 'string' ? `'${value}'` : value; + return typeof value === 'string' ? `'${value}'` : value; } function findUnused({ program }: RecastAST) { - types.visit(program, { - visitNode(path) { - if (path.node.type !== 'Program') path.node['parent'] = path.parent.node; - this.traverse(path); - } - }); - let scopeManager = analyze(program, { sourceType: 'module', ecmaVersion: 10 }); + types.visit(program, { + visitNode(path) { + if (path.node.type !== 'Program') path.node['parent'] = path.parent.node; + this.traverse(path); + } + }); + let scopeManager = analyze(program, { sourceType: 'module', ecmaVersion: 10 }); return collectUnuseds(scopeManager.acquire(program), []).reduce((result, variable) => { - if (variable.references.length) { - result.push(...variable.references.map(({ identifier: id, resolved }) => { - return id['parent'].type === 'CallExpression' ? resolved.defs[0].name : id; - })); - } else { - result.push(...variable.defs.map(d => d.name)); - } - return result; - }, []); + if (variable.references.length) { + result.push(...variable.references.map(({ identifier: id, resolved }) => { + return id['parent'].type === 'CallExpression' ? resolved.defs[0].name : id; + })); + } else { + result.push(...variable.defs.map(d => d.name)); + } + return result; + }, []); } function isInLoop(node: Node) { - while (node && !types.namedTypes.Function.check(node)) { - if (LOOP_STATEMENT.test(node.type)) return true; - node = node['parent']; - } - return false; + while (node && !types.namedTypes.Function.check(node)) { + if (LOOP_STATEMENT.test(node.type)) return true; + node = node['parent']; + } + return false; } function getUpperFunction(node: Node) { - while (node) { - if (types.namedTypes.Function.check(node)) return node; - node = node['parent']; - } - return null; + while (node) { + if (types.namedTypes.Function.check(node)) return node; + node = node['parent']; + } + return null; } function getRhsNode(ref: Reference, prevRhsNode: Node) { - const id = ref.identifier; - const parent = id['parent']; - const granpa = parent.parent; - const refScope = ref.from.variableScope; - const varScope = ref.resolved['scope'].variableScope; - const canBeUsedLater = refScope !== varScope || isInLoop(id); - - if (prevRhsNode && isInside(id, prevRhsNode)) { - return prevRhsNode; - } - if (parent.type === 'AssignmentExpression' && granpa.type === 'ExpressionStatement' && - id === parent.left && !canBeUsedLater - ) { - return parent.right; - } - return null; + const id = ref.identifier; + const parent = id['parent']; + const granpa = parent.parent; + const refScope = ref.from.variableScope; + const varScope = ref.resolved['scope'].variableScope; + const canBeUsedLater = refScope !== varScope || isInLoop(id); + + if (prevRhsNode && isInside(id, prevRhsNode)) { + return prevRhsNode; + } + if (parent.type === 'AssignmentExpression' && granpa.type === 'ExpressionStatement' && + id === parent.left && !canBeUsedLater + ) { + return parent.right; + } + return null; } function isStorableFunction(funcNode: Identifier, rhsNode: Node) { - let node = funcNode; - let parent: Node = funcNode['parent']; - - while (parent && isInside(parent, rhsNode)) { - switch (parent.type) { - case 'SequenceExpression': - if (parent.expressions[parent.expressions.length - 1] !== node) { - return false; - } - break; - case 'CallExpression': - case 'NewExpression': - return parent.callee !== node; - case 'AssignmentExpression': - case 'TaggedTemplateExpression': - case 'YieldExpression': - return true; - default: - if (STATEMENT_TYPE.test(parent.type)) { - return true; - } - } - node = parent; - parent = parent['parent']; - } - return false; + let node = funcNode; + let parent: Node = funcNode['parent']; + + while (parent && isInside(parent, rhsNode)) { + switch (parent.type) { + case 'SequenceExpression': + if (parent.expressions[parent.expressions.length - 1] !== node) { + return false; + } + break; + case 'CallExpression': + case 'NewExpression': + return parent.callee !== node; + case 'AssignmentExpression': + case 'TaggedTemplateExpression': + case 'YieldExpression': + return true; + default: + if (STATEMENT_TYPE.test(parent.type)) { + return true; + } + } + node = parent; + parent = parent['parent']; + } + return false; } function isExported(variable: Variable) { - const definition = variable.defs[0]; - if (definition) { - let node: Node = definition.node; - if (node.type === 'VariableDeclarator') { - node = node['parent']; - } else if (definition.type === 'Parameter') { - return false; - } - return node['parent'].type.indexOf('Export') === 0; - } - return false; + const definition = variable.defs[0]; + if (definition) { + let node: Node = definition.node; + if (node.type === 'VariableDeclarator') { + node = node['parent']; + } else if (definition.type === 'Parameter') { + return false; + } + return node['parent'].type.indexOf('Export') === 0; + } + return false; } function isReadRef(ref: Reference) { - return ref.isRead(); + return ref.isRead(); } function isSelfReference(ref: Reference, nodes: Node[]) { - let scope = ref.from; - while (scope) { - if (nodes.indexOf(scope.block) >= 0) { - return true; - } - scope = scope.upper; - } - return false; + let scope = ref.from; + while (scope) { + if (nodes.indexOf(scope.block) >= 0) { + return true; + } + scope = scope.upper; + } + return false; } function isInside(inner: Identifier, outer: Node) { - return (inner.range[0] >= outer.range[0] && inner.range[1] <= outer.range[1]); + return (inner.range[0] >= outer.range[0] && inner.range[1] <= outer.range[1]); } function isInsideOfStorableFunction(id, rhsNode) { const funcNode = getUpperFunction(id); - return (funcNode && isInside(funcNode, rhsNode) && isStorableFunction(funcNode, rhsNode)); + return (funcNode && isInside(funcNode, rhsNode) && isStorableFunction(funcNode, rhsNode)); } function isReadForItself(ref: Reference, rhsNode: Node) { - const id = ref.identifier; - const parent = id['parent']; - const isExpStmt = parent.parent.type === 'ExpressionStatement'; - return ref.isRead() && ( - (parent.type === 'AssignmentExpression' && isExpStmt && parent.left === id) || - (parent.type === 'UpdateExpression' && isExpStmt) || - (rhsNode && isInside(id, rhsNode) && !isInsideOfStorableFunction(id, rhsNode)) - ); + const id = ref.identifier; + const parent = id['parent']; + const isExpStmt = parent.parent.type === 'ExpressionStatement'; + return ref.isRead() && ( + (parent.type === 'AssignmentExpression' && isExpStmt && parent.left === id) || + (parent.type === 'UpdateExpression' && isExpStmt) || + (rhsNode && isInside(id, rhsNode) && !isInsideOfStorableFunction(id, rhsNode)) + ); } function isForInRef(ref: Reference) { - let target: Node = ref.identifier['parent']; - if (target.type === 'VariableDeclarator') target = target['parent'].parent; - if (target.type !== 'ForInStatement') return false; - target = target.body.type === 'BlockStatement' ? target.body.body[0] : target.body; - if (!target) return false; - return target.type === 'ReturnStatement'; + let target: Node = ref.identifier['parent']; + if (target.type === 'VariableDeclarator') target = target['parent'].parent; + if (target.type !== 'ForInStatement') return false; + target = target.body.type === 'BlockStatement' ? target.body.body[0] : target.body; + if (!target) return false; + return target.type === 'ReturnStatement'; } function isUsedVar({ defs, references }: Variable) { const fNodes = defs.filter(def => def.type === 'FunctionName') .map(def => def.node), isFuncDef = fNodes.length > 0; - let rhsNode: Node = null; + let rhsNode: Node = null; - return references.some(ref => { - if (isForInRef(ref)) return true; - const forItself = isReadForItself(ref, rhsNode); - rhsNode = getRhsNode(ref, rhsNode); - return (isReadRef(ref) && !forItself && - !(isFuncDef && isSelfReference(ref, fNodes))); - }); + return references.some(ref => { + if (isForInRef(ref)) return true; + const forItself = isReadForItself(ref, rhsNode); + rhsNode = getRhsNode(ref, rhsNode); + return (isReadRef(ref) && !forItself && + !(isFuncDef && isSelfReference(ref, fNodes))); + }); } function collectUnuseds(scope: Scope, unusedVars: Variable[]) { - let i, l; - const { variables, childScopes } = scope; - for (i = 0, l = variables.length; i < l; ++i) { - const variable = variables[i]; - if (scope.type === 'class' && (scope.block).id === variable.identifiers[0]) { - continue; - } - if (scope.functionExpressionScope || variable['eslintUsed']) { - continue; - } - if (scope.type === 'function' && variable.name === 'arguments' && variable.identifiers.length === 0) { - continue; - } - const def = variable.defs[0]; - if (def && def.type === 'Parameter') { - const { type, kind } = def.node['parent']; - if ((type === 'Property' || type === 'MethodDefinition') && kind === 'set') { - continue; - } - } - !isUsedVar(variable) && !isExported(variable) && unusedVars.push(variable); - } - for (i = 0, l = childScopes.length; i < l; ++i) { - collectUnuseds(childScopes[i], unusedVars); - } - return unusedVars; + let i, l; + const { variables, childScopes } = scope; + for (i = 0, l = variables.length; i < l; ++i) { + const variable = variables[i]; + if (scope.type === 'class' && (scope.block).id === variable.identifiers[0]) { + continue; + } + if (scope.functionExpressionScope || variable['eslintUsed']) { + continue; + } + if (scope.type === 'function' && variable.name === 'arguments' && variable.identifiers.length === 0) { + continue; + } + const def = variable.defs[0]; + if (def && def.type === 'Parameter') { + const { type, kind } = def.node['parent']; + if ((type === 'Property' || type === 'MethodDefinition') && kind === 'set') { + continue; + } + } + !isUsedVar(variable) && !isExported(variable) && unusedVars.push(variable); + } + for (i = 0, l = childScopes.length; i < l; ++i) { + collectUnuseds(childScopes[i], unusedVars); + } + return unusedVars; } function toAst(src: string, sourceType: string = 'script') { - return parse(src, { - parser: { - parse(source: string, options) { - return parser(source, { ...options, ...{ ecmaVersion: 10, sourceType, range: true, loc: true } }); - } - } - }); + return parse(src, { + parser: { + parse(source: string, options) { + return parser(source, { ...options, ...{ ecmaVersion: 10, sourceType, range: true, loc: true } }); + } + } + }); } function toMember(node: Expression, ctx: string) { - return memberExpression(identifier(ctx), node, false); + return memberExpression(identifier(ctx), node, false); } function toCode(ast: RecastAST) { - return print(ast, { tabWidth: 2, quote: 'single' }); + return print(ast, { tabWidth: 2, quote: 'single' }); } function canBeReplaced(node: Node, path, globals) { - return Identifier.check(node) && !isDeclared(node, path) && !isGlobal(node, globals); + return Identifier.check(node) && !isDeclared(node, path) && !isGlobal(node, globals); } function replace(name: string, ctx: string, path, position?: number) { - if (typeof position === 'number') { - let node = path.get(name, position).value; - path.get(name, position).replace(toMember(node, ctx)); - } else { - let node = path.get(name).value; - path.get(name).replace(toMember(node, ctx)); - } + if (typeof position === 'number') { + let node = path.get(name, position).value; + path.get(name, position).replace(toMember(node, ctx)); + } else { + let node = path.get(name).value; + path.get(name).replace(toMember(node, ctx)); + } } function isDeclared(node: Identifier, { scope }: Path) { - return scope.declares(node.name); + return scope.declares(node.name); } function isGlobal(node: Identifier, globals = []) { - let { name } = node; - let isGlob = name in builtin || name in browser || name in nodejs || name in amd; - return isGlob || !!~globals.indexOf(name); + let { name } = node; + let isGlob = name in builtin || name in browser || name in nodejs || name in amd; + return isGlob || !!~globals.indexOf(name); } function isReplaceable(node: Node) { - return Identifier.check(node) ? - true : types.namedTypes.AssignmentExpression.check(node) ? - isReplaceable((node).left) : types.namedTypes.UpdateExpression.check(node) ? - isReplaceable((node).argument) : isReplaceable((node).object); + return Identifier.check(node) ? + true : types.namedTypes.AssignmentExpression.check(node) ? + isReplaceable((node).left) : types.namedTypes.UpdateExpression.check(node) ? + isReplaceable((node).argument) : isReplaceable((node).object); } function isSameIdentifier(a: Identifier, b: Identifier) { - return a.name === b.name && JSON.stringify(a.loc) === JSON.stringify(b.loc); + return a.name === b.name && JSON.stringify(a.loc) === JSON.stringify(b.loc); } From 31827fcea8097aa649fb51ae2cd6b95a876e609e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Asiel=20Guevara=20Casta=C3=B1eda?= Date: Mon, 8 Oct 2018 08:50:56 -0400 Subject: [PATCH 4/9] Fixed bug generating code for component event attributes --- src/generators/components.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/generators/components.ts b/src/generators/components.ts index 065c30e..d5228ab 100644 --- a/src/generators/components.ts +++ b/src/generators/components.ts @@ -64,8 +64,8 @@ export function genComponent(node: NodeElement, areas: BlockAreas, scope: string if (name[0] === '@') { const eventVar = `event${capitalize(kebabToCamelCases(name.slice(1)))}${capitalize(variable)}`; areas.variables.push(eventVar); - extras.push(`${eventVar} = ${variable}.$on('${name.slice(1)}', ${ctx(value, scope, params)});`); - areas.destroy.push(`${eventVar}.off();`); + extras.push(`${eventVar} = ${variable}.$on('${name.slice(1)}', $data => { ${ctx(value, scope, params)}; });`); + areas.destroy.push(`${eventVar}.$off();`); } else if (name[0] === ':') { attrs += `${kebabToCamelCases(name.slice(1))}() { return ${ctx(value, scope, params)}; },`; } else if (name[0] === '$' && !/model|show/.test(name.slice(1))) { From a22569dd38bb1c8c62cc468700da57e7234ba328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Asiel=20Guevara=20Casta=C3=B1eda?= Date: Mon, 8 Oct 2018 08:52:17 -0400 Subject: [PATCH 5/9] Fixed missing attributes generating elements in slots --- src/generators/components.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/generators/components.ts b/src/generators/components.ts index d5228ab..958c8d3 100644 --- a/src/generators/components.ts +++ b/src/generators/components.ts @@ -1,5 +1,6 @@ import { genBlockAreas } from './commons'; import { ctx } from '../utilities/context'; +import { genSetAttrs } from './attributes'; import { genDirective } from './directives'; import { NodeElement, BlockAreas } from '../utilities/classes'; import { kebabToCamelCases, getVarName, capitalize, createElement, filterParser } from '../utilities/tools'; @@ -132,6 +133,10 @@ export function genComponent(node: NodeElement, areas: BlockAreas, scope: string areas.unmount.push(`_$a(${slot}, ${el});`); } }); + const attr = genSetAttrs(slot, n, scope, areas); + if (attr) { + areas.hydrate.push(attr); + } areas.unmount.push(`if (${slotDec}) { _$a(${slotDec}, ${slot}); }`); From 14d9213eb872ce2073f0632d70053aa3ea7f65e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Asiel=20Guevara=20Casta=C3=B1eda?= Date: Mon, 8 Oct 2018 12:19:10 -0400 Subject: [PATCH 6/9] Ignored spec folder --- .gitignore | 1 + spec/basic usage/initialize.spec.js | 69 -- spec/components/bind.umd.js | 640 ----------------- spec/components/condition.umd.js | 677 ------------------ spec/components/html.umd.js | 580 --------------- spec/components/init.umd.js | 516 -------------- spec/components/loop.umd.js | 786 --------------------- spec/helpers/setup.js | 19 - spec/special attributes/bind_value.spec.js | 45 -- spec/special attributes/condition.spec.js | 35 - spec/special attributes/html.spec.js | 29 - spec/special attributes/loop.spec.js | 55 -- spec/support/jasmine.json | 11 - 13 files changed, 1 insertion(+), 3462 deletions(-) delete mode 100644 spec/basic usage/initialize.spec.js delete mode 100644 spec/components/bind.umd.js delete mode 100644 spec/components/condition.umd.js delete mode 100644 spec/components/html.umd.js delete mode 100644 spec/components/init.umd.js delete mode 100644 spec/components/loop.umd.js delete mode 100644 spec/helpers/setup.js delete mode 100644 spec/special attributes/bind_value.spec.js delete mode 100644 spec/special attributes/condition.spec.js delete mode 100644 spec/special attributes/html.spec.js delete mode 100644 spec/special attributes/loop.spec.js delete mode 100644 spec/support/jasmine.json diff --git a/.gitignore b/.gitignore index 27c7774..424a545 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ node_modules/ build/ +spec/ tools/*.js tools/*.map test/index.js \ No newline at end of file diff --git a/spec/basic usage/initialize.spec.js b/spec/basic usage/initialize.spec.js deleted file mode 100644 index 4b6400d..0000000 --- a/spec/basic usage/initialize.spec.js +++ /dev/null @@ -1,69 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -require("../helpers/setup"); -const Component = require('../components/init.umd'); -describe('Component', () => { - it('should be a function constructor', () => { - expect(Component).not.toBeNull(); - expect(typeof Component).toBe('function'); - }); - it('should get an instance when is used with new', () => { - let instance = new Component(); - expect(typeof instance).toBe('object'); - expect(instance.constructor).toEqual(Component); - }); - it('instance should have prototype methods', () => { - let instance = new Component(); - expect('$refs' in instance).toBeTruthy(); - expect('$create' in instance).toBeTruthy(); - expect('$mount' in instance).toBeTruthy(); - expect('$update' in instance).toBeTruthy(); - expect('$unmount' in instance).toBeTruthy(); - expect('$destroy' in instance).toBeTruthy(); - expect('$watch' in instance).toBeTruthy(); - expect('$observe' in instance).toBeTruthy(); - }); - it('instance should have option properties', () => { - let instance = new Component(); - expect('text' in instance).toBeTruthy(); - expect(instance.text).toBe('World'); - }); -}); -describe('Component Instance', () => { - let instance, main; - beforeAll(done => { - instance = new Component(); - main = document.querySelector('main'); - done(); - }); - afterEach(done => { - instance.$unmount(); - done(); - }); - it('should be mounted in an element selector', () => { - instance.$mount('main'); - expect(instance.$parentEl).toEqual(main); - }); - it('should be mounted in an element', () => { - instance.$mount(main); - expect(instance.$parentEl).toEqual(main); - }); - it('should be mounted correctly', () => { - instance.$mount('main'); - let h1 = main.firstChild; - expect(h1.nodeName).toEqual('H1'); - expect(h1.textContent).toBe('Hello, World!!'); - }); - it('should update the view correctly', () => { - instance.$mount('main'); - let h1 = main.firstChild; - instance.$set('text', 'Somebody'); - expect(h1.textContent).toBe('Hello, Somebody!!'); - }); - it('should not update the view correctly if `$set` method is not used', () => { - instance.$mount('main'); - let h1 = main.firstChild; - instance.text = 'World'; - expect(h1.textContent).toBe('Hello, Somebody!!'); - }); -}); diff --git a/spec/components/bind.umd.js b/spec/components/bind.umd.js deleted file mode 100644 index 8d94acb..0000000 --- a/spec/components/bind.umd.js +++ /dev/null @@ -1,640 +0,0 @@ -!function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define('bind', factory) : - (global.Bind = factory()); - }(this, function () { - 'use strict'; -var PROP_MAP = { - p: '__TP__', - v: 'value', - _: '_value', - s: '_subscribers', - e: '_events', - w: '_watchers', - h: 'prototype' -}; -var PROPS = ['$slots', '$refs', '$filters', '$directives', '_events', '_watchers']; -var TPS = window[PROP_MAP.p] || (window[PROP_MAP.p] = []); -var _$assign = Object['assign'] || function(t) { - for (var s = void 0, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (_$hasProp(s, p)) - t[p] = s[p]; - } - return t; -}; -function _$CompCtr(attrs, template, options, parent) { - var self = this; - var _$set = function(prop, value) { - _$def(self, prop, { - value: value, - writable: true - }); - }; - if (!attrs) - attrs = {}; - _$e(PROPS, function(prop) { - _$def(self, prop, { - value: {} - }); - }); - _$set('$parent', parent || null); - _$set('$children', []); - _$set(PROP_MAP.s, {}); - _$set('$options', options); - var opts = self.$options; - if (!opts.attrs) - opts.attrs = {}; - if (!opts.children) - opts.children = {}; - _$e(TPS, function(plugin) { - plugin.fn.call(self, _$CompCtr, plugin.options); - }); - if (opts.filters) - _$assign(self.$filters, opts.filters); - if (opts.directives) _$e(opts.directives, function(drt, k) { - self.$directives[k] = _$drt(drt); - }); - _$e(opts.attrs, function(attrOps, key) { - _$def(self, _$isType(key, 'number') ? attrOps : key, { - get: function() { - if (_$isStr(attrOps)) { - var value = attrs[attrOps]; - return _$isFunction(value) ? value() : value; - } else { - if (!_$hasProp(attrs, key) && attrOps.required) { - return console.error('Attribute \'' + key + '\' is required.'); - } else { - var value = _$isFunction(attrs[key]) ? attrs[key]() : attrs[key]; - if (value === void 0 && _$hasProp(attrOps, 'default')) { - var def = attrOps.default; - value = _$isFunction(def) ? def() : def; - } - var typ = attrOps.type; - if (typ && !_$isType(value, typ) && attrOps.required) { - return console.error('Attribute \'' + key + '\' must be type \'' + typ + '\'.'); - } - value = _$toType(value, value === void 0 ? 'undefined' : typ, self, key); - if (value !== void 0 && _$hasProp(attrOps, 'validator')) { - var validator = attrOps.validator; - if (_$isFunction(validator) && !validator(value)) { - return console.error('Assigment \'' + key + '\'=\'' + JSON.stringify(value) + '\' invalid.'); - } - } - return value; - } - } - }, - - set: function() { - console.error('\'' + key + '\' is read only.'); - }, - - enumerable: true, - configurable: true - }); - }); - var data = opts.model || {}; - var _loop_1 = function(key) { - if (_$hasProp(data, key)) { - var desc = Object.getOwnPropertyDescriptor(data, key); - if (desc.value && _$isArray(desc.value)) { - desc.value = new _$List(desc.value, self, key); - } else { - if (desc.get) { - var getter_1 = desc.get; - desc.get = function() { - var value = getter_1.call(self); - if (_$isArray(value)) - value = new _$List(value, self, key); - return value; - }; - } - if (desc.set) { - var setter_1 = desc.set; - desc.set = function(v) { - if (_$isArray(v)) - v = new _$List(v, self, key); - setter_1.call(self, v); - }; - } - } - _$def(self, key, desc); - } - }; - for (var key in data) { - _loop_1(key); - } - var tpl = template(self, opts.children); - _$e(tpl, function(value, key) { - _$def(self, key, { - value: function(key) { - var hook = key[1].toUpperCase() + key.slice(2); - var bhook = opts['before' + hook]; - var ahook = opts['after' + hook]; - return function() { - bhook && bhook.call(this); - key.slice(1) === 'update' ? value.call(this, this) : value.apply(this, arguments); - ahook && ahook.call(this); - }; - }(key) - }); - }); - _$def(self, '$data', { - get: function() { - return _$toPlainObj(this); - } - }); -} -function _$isValueAttr(attr) { - return attr === 'value'; -} -function _$subs(dep, listener) { - if (!this[PROP_MAP.s][dep]) { - this[PROP_MAP.s][dep] = []; - } - return this[PROP_MAP.s][dep].push(listener.bind(this)) - 1; -} -function _$def(obj, key, desc) { - Object.defineProperty(obj, key, desc); -} -_$assign(_$CompCtr[PROP_MAP.h], { - $get: function(path) { - return _$accesor(this, path); - }, - - $set: function(path, value) { - _$accesor(this, path, value); - }, - - $on: function(event, handler) { - var _this = this; - if (!this[PROP_MAP.e][event]) { - this[PROP_MAP.e][event] = []; - } - var i = this[PROP_MAP.e][event].push(handler); - return { - $off: function() { - _this[PROP_MAP.e][event].splice(i - 1, 1); - } - }; - }, - - $once: function(event, handler) { - var e = this.$on(event, function(args) { - handler(args); - e.$off(); - }); - }, - - $fire: function(event, data) { - if (this[PROP_MAP.e][event]) { - _$e(this[PROP_MAP.e][event], function(handler) { - handler(data); - }); - } - }, - - $notify: function(key) { - if (this[PROP_MAP.s][key]) { - _$e(this[PROP_MAP.s][key], function(suscriber) { - suscriber(); - }); - } - }, - - $observe: function(deps, listener) { - var _this = this; - var subs = []; - if (_$isArray(deps)) { - _$e(deps, function(dep) { - subs.push({ - sub: dep, - i: _$subs.call(_this, dep, listener) - }); - }); - } else { - subs.push({ - sub: deps, - i: _$subs.call(this, deps, listener) - }); - } - return { - $unobserve: function() { - _$e(subs, function(sub) { - _this[PROP_MAP.s][sub.sub].splice(sub.i, 1); - }); - } - }; - }, - - $watch: function(key, watcher) { - var _this = this; - if (!this[PROP_MAP.w][key]) { - this[PROP_MAP.w][key] = []; - } - var i = this[PROP_MAP.w][key].push(watcher.bind(this)); - return { - $unwatch: function() { - _this[PROP_MAP.w][key].splice(i - 1, 1); - } - }; - } -}); -var array = Array[PROP_MAP.h]; -function _$toArgs(args, start) { - if (start === void 0) { - start = 0; - } - return array.slice.call(args, start); -} -function _$arrayValues(list, value, root, key) { - array.push.apply(list, value.map(function(v, i) { - if (list.length !== 0) - i += list.length; - return !_$isType(v, _$List) && _$isArray(v) ? new _$List(v, root, key + '.' + i) : v; - })); -} -function _$List(value, root, key) { - var self = this; - Array.apply(self, [value.length]); - var desc = { - writable: false, - configurable: false, - enumerable: false - }; - _$def(self, '_key', _$assign({ - value: key - }, desc)); - _$def(self, '_root', _$assign({ - value: root - }, desc)); - _$arrayValues(self, value, root, key); - desc.writable = true; - _$def(self, 'length', _$assign({ - value: self.length - }, desc)); -} -_$extends(_$List, Array); -['pop', 'push', 'reverse', 'shift', 'sort', 'fill', 'unshift', 'splice'].forEach(function(method) { - _$List[PROP_MAP.h][method] = function() { - var self = this; - var old = self.slice(); - var result; - if (method === 'push') { - _$arrayValues(self, _$toArgs(arguments), self._root, self._key); - result = self.length; - } else { - result = array[method].apply(self, arguments); - } - _$dispatch(self._root, self._key, old, self.slice()); - return result; - }; -}); -_$List[PROP_MAP.h].pull = function(index) { - var self = this; - var items = _$toArgs(arguments, 1); - var length = self.length; - if (index > length) { - length = index + 1; - var pull = new Array(index - self.length); - pull.push.apply(pull, items); - for (var i = 0; i < length; i++) { - if (i === index) { - self.push.apply(self, pull); - } - } - } else { - self.splice.apply(self, [index, 1].concat(items)); - } -}; -function _$dispatch(root, key, oldVal, value) { - root.$notify(key); - if (root[PROP_MAP.w][key]) { - _$e(root[PROP_MAP.w][key], function(watcher) { - watcher(oldVal, value); - }); - } - root.$update(); -} -function _$extends(ctor, exts) { - ctor['plugin'] = function(fn, options) { - TPS.push({ - options: options, - fn: fn - }); - }; - ctor[PROP_MAP.h] = Object.create(exts[PROP_MAP.h]); - ctor[PROP_MAP.h].constructor = ctor; -} -function _$isType(value, type) { - return _$type(type) === 'string' ? type.split('|').some(function(t) { - return t.trim() === _$type(value); - }) : value instanceof type; -} -function _$isObject(obj) { - return _$isType(obj, 'object'); -} -function _$isArray(obj) { - return Array.isArray ? Array.isArray(obj) : _$isType(obj, 'array'); -} -function _$isFunction(obj) { - return _$isType(obj, 'function'); -} -function _$isStr(obj) { - return _$isType(obj, 'string'); -} -function _$toType(value, type, root, key) { - switch (type) { - case 'date': - return new Date(value); - case 'string': - return _$toStr(value); - case 'number': - return +value; - case 'boolean': - return _$isStr(value) && !value ? true : !!value; - case 'array': - return _$isType(value, _$List) ? value : new _$List(value, root, key); - default: - return value; - } -} -function _$type(obj) { - return / (\w+)/.exec({}.toString.call(obj))[1].toLowerCase(); -} -function _$hasProp(obj, prop) { - return obj.hasOwnProperty(prop); -} -function _$drt(dd) { - var hasProp = function(prop, instance, options, element) { - return _$isObject(dd) && dd[prop] && dd[prop](instance, options, element); - }; - return { - $init: function(instance, options, element) { - hasProp('$init', instance, options, element); - }, - - $inserted: function(instance, options, element) { - hasProp('$inserted', instance, options, element); - }, - - $update: function(instance, options, element) { - if (_$isFunction(dd)) { - dd(instance, options, element); - } else { - hasProp('$update', instance, options, element); - } - }, - - $destroy: function(instance, options, element) { - hasProp('$destroy', instance, options, element); - } - }; -} -function _$toStr(obj) { - var str = _$type(obj); - return !/null|undefined/.test(str) ? obj.toString() : str; -} -function _$toPlainObj(obj) { - var data = {}; - _$e(_$isObject(obj) ? obj : {}, function(_v, k) { - if (k[0] !== '$' && !_$isFunction(obj[k])) { - if (_$isType(obj[k], _$List)) { - data[k] = obj[k].map(_$toPlainObj); - } else if (_$isObject(obj[k])) { - data[k] = _$toPlainObj(obj[k]); - } else { - data[k] = obj[k]; - } - } - }); - return _$isObject(obj) ? data : obj; -} -function _$accesor(object, path, value) { - return path.split('.').reduce(function(obj, key, i, arr) { - if (_$isType(value, 'undefined')) { - if (obj == null) { - arr.splice(0, arr.length); - return i > 0 && obj === null ? obj : undefined; - } - } else { - if (i === arr.length - 1) { - if (_$isType(obj, _$List) && _$toStr(+key) === key) { - obj.pull(+key, value); - } else { - var oldVal = obj[key]; - obj[key] = !_$isType(value, _$List) && _$isArray(value) ? new _$List(value, object, key) : value; - _$dispatch(object, path, oldVal, obj[key]); - } - } else if (!_$isObject(obj[key])) { - obj[key] = {}; - } - } - return obj ? obj[key] : null; - }, object); -} -function _$bindGroup(input, selection) { - var _value = _$gv(input); - var _$index = selection.indexOf(_value); - input.checked && !~_$index ? selection.push(_value) : selection.splice(_$index, 1); -} -function _$(selector, parent) { - return _$isStr(selector) ? (parent || document).querySelector(selector) : selector; -} -function _$d() { - return document.createDocumentFragment(); -} -function _$a(parent, child, sibling) { - if (_$isType(sibling, 'boolean') && sibling) - parent.parentElement.replaceChild(child, parent); - else if (!sibling) - parent.appendChild(child); - else - parent.insertBefore(child, sibling); -} -function _$ce(tagName) { - return document.createElement(tagName || 'div'); -} -function _$sa(el, attrOrBind) { - var attr = attrOrBind[0], value = attrOrBind[1]; - el.setAttribute(attr, _$toStr(value)); - if (_$isValueAttr(attr) && !_$isStr(value)) - el[PROP_MAP._] = value; -} -function _$ga(el, attr) { - return _$isValueAttr(attr) ? _$gv(el) : el.getAttribute(attr); -} -function _$gv(el) { - return _$hasProp(el, PROP_MAP._) ? el[PROP_MAP._] : el[PROP_MAP.v]; -} -function _$al(el, event, handler) { - el.addEventListener(event, handler, false); -} -function _$rl(el, event, handler) { - el.removeEventListener(event, handler, false); -} -function _$bu(el, binding) { - var attr = binding[0], value = binding[1]; - var _value = attr === 'checked' ? !!value : _$toStr(value); - if (/value|checked/.test(attr)) { - if (el[attr] !== _value) - el[attr] = _$isValueAttr(attr) ? _value : value; - el[PROP_MAP._] = _$isValueAttr(attr) ? value : el[PROP_MAP.v]; - } else if (_$ga(el, attr) !== _value) { - _$sa(el, [attr, _value]); - } -} -function _$e(obj, cb) { - for (var key in obj) { - if (_$hasProp(obj, key)) { - cb(obj[key], isNaN(+key) ? key : +key); - } - } -} -function _$tplBind(_$state) { - var _$frag, input_1, inputEvent_1, handlerInputEvent_1, bindValueInput_1, input_2, changeEvent_1, handlerChangeEvent_1, bindCheckedInput_2, input_3, changeEvent_2, handlerChangeEvent_2, bindCheckedInput_3, input_4, changeEvent_3, handlerChangeEvent_3, bindCheckedInput_4, input_5, changeEvent_4, handlerChangeEvent_4, bindCheckedInput_5, input_6, changeEvent_5, handlerChangeEvent_5, bindCheckedInput_6; - _$frag = _$d(); - inputEvent_1 = function(_$state, $event, $el) { - _$state.$set('textValue', $el.value); - }; - bindValueInput_1 = function(_$state) { - return ['value', _$state.textValue]; - }; - changeEvent_1 = function(_$state, $event, $el) { - _$bindGroup($el, _$state.checkboxes); - }; - bindCheckedInput_2 = function(_$state) { - return ['checked', !!~_$state.checkboxes.indexOf(_$ga(input_2, 'value'))]; - }; - changeEvent_2 = function(_$state, $event, $el) { - _$bindGroup($el, _$state.checkboxes); - }; - bindCheckedInput_3 = function(_$state) { - return ['checked', !!~_$state.checkboxes.indexOf(_$ga(input_3, 'value'))]; - }; - changeEvent_3 = function(_$state, $event, $el) { - _$state.$set('radios', $el.checked ? _$gv($el) : _$state.radios); - }; - bindCheckedInput_4 = function(_$state) { - return ['checked', _$state.radios === _$ga(input_4, 'value')]; - }; - changeEvent_4 = function(_$state, $event, $el) { - _$state.$set('radios', $el.checked ? _$gv($el) : _$state.radios); - }; - bindCheckedInput_5 = function(_$state) { - return ['checked', _$state.radios === _$ga(input_5, 'value')]; - }; - changeEvent_5 = function(_$state, $event, $el) { - _$state.$set('radios', $el.checked ? _$gv($el) : _$state.radios); - }; - bindCheckedInput_6 = function(_$state) { - return ['checked', _$state.radios === _$ga(input_6, 'value')]; - }; - return { - $create: function() { - input_1 = _$ce('input'); - input_2 = _$ce('input'); - input_3 = _$ce('input'); - input_4 = _$ce('input'); - input_5 = _$ce('input'); - input_6 = _$ce('input'); - _$al(input_1, 'input', handlerInputEvent_1 = function(event) { - inputEvent_1(_$state, event, input_1); - }); - input_1.value = _$toStr(bindValueInput_1(_$state)[1]); - _$sa(input_1, ['id', 'text']); - _$sa(input_1, ['type', 'text']); - _$al(input_2, 'change', handlerChangeEvent_1 = function(event) { - changeEvent_1(_$state, event, input_2); - }); - input_2.checked = !!bindCheckedInput_2(_$state)[1]; - _$sa(input_2, ['id', 'checkbox_1']); - _$sa(input_2, ['type', 'checkbox']); - _$sa(input_2, ['value', 'Yes']); - _$al(input_3, 'change', handlerChangeEvent_2 = function(event) { - changeEvent_2(_$state, event, input_3); - }); - input_3.checked = !!bindCheckedInput_3(_$state)[1]; - _$sa(input_3, ['id', 'checkbox_2']); - _$sa(input_3, ['type', 'checkbox']); - _$sa(input_3, ['value', 'No']); - _$al(input_4, 'change', handlerChangeEvent_3 = function(event) { - changeEvent_3(_$state, event, input_4); - }); - input_4.checked = !!bindCheckedInput_4(_$state)[1]; - _$sa(input_4, ['id', 'radio_1']); - _$sa(input_4, ['type', 'radio']); - _$sa(input_4, ['value', 'radio 1']); - _$al(input_5, 'change', handlerChangeEvent_4 = function(event) { - changeEvent_4(_$state, event, input_5); - }); - input_5.checked = !!bindCheckedInput_5(_$state)[1]; - _$sa(input_5, ['id', 'radio_2']); - _$sa(input_5, ['type', 'radio']); - _$sa(input_5, ['value', 'radio 2']); - _$al(input_6, 'change', handlerChangeEvent_5 = function(event) { - changeEvent_5(_$state, event, input_6); - }); - input_6.checked = !!bindCheckedInput_6(_$state)[1]; - _$sa(input_6, ['id', 'radio_3']); - _$sa(input_6, ['type', 'radio']); - _$sa(input_6, ['value', 'radio 3']); - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - this.$siblingEl = _$(sibling); - this.$parentEl = sibling && _$(sibling).parentElement || _$(parent); - }, - - $update: function(_$state) { - _$bu(input_1, bindValueInput_1(_$state)); - _$bu(input_2, bindCheckedInput_2(_$state)); - _$bu(input_3, bindCheckedInput_3(_$state)); - _$bu(input_4, bindCheckedInput_4(_$state)); - _$bu(input_5, bindCheckedInput_5(_$state)); - _$bu(input_6, bindCheckedInput_6(_$state)); - }, - - $unmount: function() { - _$a(_$frag, input_1); - _$a(_$frag, input_2); - _$a(_$frag, input_3); - _$a(_$frag, input_4); - _$a(_$frag, input_5); - _$a(_$frag, input_6); - }, - - $destroy: function() { - this.$unmount(); - this.$parent = null; - this.$parentEl = null; - this.$siblingEl = null; - this.$children.splice(0, this.$children.length); - _$rl(input_1, 'input', handlerInputEvent_1); - _$rl(input_2, 'change', handlerChangeEvent_1); - _$rl(input_3, 'change', handlerChangeEvent_2); - _$rl(input_4, 'change', handlerChangeEvent_3); - _$rl(input_5, 'change', handlerChangeEvent_4); - _$rl(input_6, 'change', handlerChangeEvent_5); - delete _$state.$root; - _$frag = input_1 = inputEvent_1 = handlerInputEvent_1 = bindValueInput_1 = input_2 = changeEvent_1 = handlerChangeEvent_1 = bindCheckedInput_2 = input_3 = changeEvent_2 = handlerChangeEvent_2 = bindCheckedInput_3 = input_4 = changeEvent_3 = handlerChangeEvent_3 = bindCheckedInput_4 = input_5 = changeEvent_4 = handlerChangeEvent_4 = bindCheckedInput_5 = input_6 = changeEvent_5 = handlerChangeEvent_5 = bindCheckedInput_6 = void 0; - } - }; -} -function Bind(_$attrs, _$parent) { - _$CompCtr.call(this, _$attrs, _$tplBind, { - model: { - radios: '', - textValue: '', - checkboxes: [] - } - }, _$parent); - !_$parent && this.$create(); -} -_$extends(Bind, _$CompCtr); -return Bind; - - }); \ No newline at end of file diff --git a/spec/components/condition.umd.js b/spec/components/condition.umd.js deleted file mode 100644 index 88a7dfc..0000000 --- a/spec/components/condition.umd.js +++ /dev/null @@ -1,677 +0,0 @@ -!function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define('condition', factory) : - (global.Condition = factory()); - }(this, function () { - 'use strict'; -var PROP_MAP = { - p: '__TP__', - v: 'value', - _: '_value', - s: '_subscribers', - e: '_events', - w: '_watchers', - h: 'prototype' -}; -var PROPS = ['$slots', '$refs', '$filters', '$directives', '_events', '_watchers']; -var TPS = window[PROP_MAP.p] || (window[PROP_MAP.p] = []); -var _$assign = Object['assign'] || function(t) { - for (var s = void 0, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (_$hasProp(s, p)) - t[p] = s[p]; - } - return t; -}; -function _$CompCtr(attrs, template, options, parent) { - var self = this; - var _$set = function(prop, value) { - _$def(self, prop, { - value: value, - writable: true - }); - }; - if (!attrs) - attrs = {}; - _$e(PROPS, function(prop) { - _$def(self, prop, { - value: {} - }); - }); - _$set('$parent', parent || null); - _$set('$children', []); - _$set(PROP_MAP.s, {}); - _$set('$options', options); - var opts = self.$options; - if (!opts.attrs) - opts.attrs = {}; - if (!opts.children) - opts.children = {}; - _$e(TPS, function(plugin) { - plugin.fn.call(self, _$CompCtr, plugin.options); - }); - if (opts.filters) - _$assign(self.$filters, opts.filters); - if (opts.directives) _$e(opts.directives, function(drt, k) { - self.$directives[k] = _$drt(drt); - }); - _$e(opts.attrs, function(attrOps, key) { - _$def(self, _$isType(key, 'number') ? attrOps : key, { - get: function() { - if (_$isStr(attrOps)) { - var value = attrs[attrOps]; - return _$isFunction(value) ? value() : value; - } else { - if (!_$hasProp(attrs, key) && attrOps.required) { - return console.error('Attribute \'' + key + '\' is required.'); - } else { - var value = _$isFunction(attrs[key]) ? attrs[key]() : attrs[key]; - if (value === void 0 && _$hasProp(attrOps, 'default')) { - var def = attrOps.default; - value = _$isFunction(def) ? def() : def; - } - var typ = attrOps.type; - if (typ && !_$isType(value, typ) && attrOps.required) { - return console.error('Attribute \'' + key + '\' must be type \'' + typ + '\'.'); - } - value = _$toType(value, value === void 0 ? 'undefined' : typ, self, key); - if (value !== void 0 && _$hasProp(attrOps, 'validator')) { - var validator = attrOps.validator; - if (_$isFunction(validator) && !validator(value)) { - return console.error('Assigment \'' + key + '\'=\'' + JSON.stringify(value) + '\' invalid.'); - } - } - return value; - } - } - }, - - set: function() { - console.error('\'' + key + '\' is read only.'); - }, - - enumerable: true, - configurable: true - }); - }); - var data = opts.model || {}; - var _loop_1 = function(key) { - if (_$hasProp(data, key)) { - var desc = Object.getOwnPropertyDescriptor(data, key); - if (desc.value && _$isArray(desc.value)) { - desc.value = new _$List(desc.value, self, key); - } else { - if (desc.get) { - var getter_1 = desc.get; - desc.get = function() { - var value = getter_1.call(self); - if (_$isArray(value)) - value = new _$List(value, self, key); - return value; - }; - } - if (desc.set) { - var setter_1 = desc.set; - desc.set = function(v) { - if (_$isArray(v)) - v = new _$List(v, self, key); - setter_1.call(self, v); - }; - } - } - _$def(self, key, desc); - } - }; - for (var key in data) { - _loop_1(key); - } - var tpl = template(self, opts.children); - _$e(tpl, function(value, key) { - _$def(self, key, { - value: function(key) { - var hook = key[1].toUpperCase() + key.slice(2); - var bhook = opts['before' + hook]; - var ahook = opts['after' + hook]; - return function() { - bhook && bhook.call(this); - key.slice(1) === 'update' ? value.call(this, this) : value.apply(this, arguments); - ahook && ahook.call(this); - }; - }(key) - }); - }); - _$def(self, '$data', { - get: function() { - return _$toPlainObj(this); - } - }); -} -function _$subs(dep, listener) { - if (!this[PROP_MAP.s][dep]) { - this[PROP_MAP.s][dep] = []; - } - return this[PROP_MAP.s][dep].push(listener.bind(this)) - 1; -} -function _$def(obj, key, desc) { - Object.defineProperty(obj, key, desc); -} -_$assign(_$CompCtr[PROP_MAP.h], { - $get: function(path) { - return _$accesor(this, path); - }, - - $set: function(path, value) { - _$accesor(this, path, value); - }, - - $on: function(event, handler) { - var _this = this; - if (!this[PROP_MAP.e][event]) { - this[PROP_MAP.e][event] = []; - } - var i = this[PROP_MAP.e][event].push(handler); - return { - $off: function() { - _this[PROP_MAP.e][event].splice(i - 1, 1); - } - }; - }, - - $once: function(event, handler) { - var e = this.$on(event, function(args) { - handler(args); - e.$off(); - }); - }, - - $fire: function(event, data) { - if (this[PROP_MAP.e][event]) { - _$e(this[PROP_MAP.e][event], function(handler) { - handler(data); - }); - } - }, - - $notify: function(key) { - if (this[PROP_MAP.s][key]) { - _$e(this[PROP_MAP.s][key], function(suscriber) { - suscriber(); - }); - } - }, - - $observe: function(deps, listener) { - var _this = this; - var subs = []; - if (_$isArray(deps)) { - _$e(deps, function(dep) { - subs.push({ - sub: dep, - i: _$subs.call(_this, dep, listener) - }); - }); - } else { - subs.push({ - sub: deps, - i: _$subs.call(this, deps, listener) - }); - } - return { - $unobserve: function() { - _$e(subs, function(sub) { - _this[PROP_MAP.s][sub.sub].splice(sub.i, 1); - }); - } - }; - }, - - $watch: function(key, watcher) { - var _this = this; - if (!this[PROP_MAP.w][key]) { - this[PROP_MAP.w][key] = []; - } - var i = this[PROP_MAP.w][key].push(watcher.bind(this)); - return { - $unwatch: function() { - _this[PROP_MAP.w][key].splice(i - 1, 1); - } - }; - } -}); -var array = Array[PROP_MAP.h]; -function _$toArgs(args, start) { - if (start === void 0) { - start = 0; - } - return array.slice.call(args, start); -} -function _$arrayValues(list, value, root, key) { - array.push.apply(list, value.map(function(v, i) { - if (list.length !== 0) - i += list.length; - return !_$isType(v, _$List) && _$isArray(v) ? new _$List(v, root, key + '.' + i) : v; - })); -} -function _$List(value, root, key) { - var self = this; - Array.apply(self, [value.length]); - var desc = { - writable: false, - configurable: false, - enumerable: false - }; - _$def(self, '_key', _$assign({ - value: key - }, desc)); - _$def(self, '_root', _$assign({ - value: root - }, desc)); - _$arrayValues(self, value, root, key); - desc.writable = true; - _$def(self, 'length', _$assign({ - value: self.length - }, desc)); -} -_$extends(_$List, Array); -['pop', 'push', 'reverse', 'shift', 'sort', 'fill', 'unshift', 'splice'].forEach(function(method) { - _$List[PROP_MAP.h][method] = function() { - var self = this; - var old = self.slice(); - var result; - if (method === 'push') { - _$arrayValues(self, _$toArgs(arguments), self._root, self._key); - result = self.length; - } else { - result = array[method].apply(self, arguments); - } - _$dispatch(self._root, self._key, old, self.slice()); - return result; - }; -}); -_$List[PROP_MAP.h].pull = function(index) { - var self = this; - var items = _$toArgs(arguments, 1); - var length = self.length; - if (index > length) { - length = index + 1; - var pull = new Array(index - self.length); - pull.push.apply(pull, items); - for (var i = 0; i < length; i++) { - if (i === index) { - self.push.apply(self, pull); - } - } - } else { - self.splice.apply(self, [index, 1].concat(items)); - } -}; -function _$dispatch(root, key, oldVal, value) { - root.$notify(key); - if (root[PROP_MAP.w][key]) { - _$e(root[PROP_MAP.w][key], function(watcher) { - watcher(oldVal, value); - }); - } - root.$update(); -} -function _$extends(ctor, exts) { - ctor['plugin'] = function(fn, options) { - TPS.push({ - options: options, - fn: fn - }); - }; - ctor[PROP_MAP.h] = Object.create(exts[PROP_MAP.h]); - ctor[PROP_MAP.h].constructor = ctor; -} -function _$isType(value, type) { - return _$type(type) === 'string' ? type.split('|').some(function(t) { - return t.trim() === _$type(value); - }) : value instanceof type; -} -function _$isObject(obj) { - return _$isType(obj, 'object'); -} -function _$isArray(obj) { - return Array.isArray ? Array.isArray(obj) : _$isType(obj, 'array'); -} -function _$isFunction(obj) { - return _$isType(obj, 'function'); -} -function _$isStr(obj) { - return _$isType(obj, 'string'); -} -function _$toType(value, type, root, key) { - switch (type) { - case 'date': - return new Date(value); - case 'string': - return _$toStr(value); - case 'number': - return +value; - case 'boolean': - return _$isStr(value) && !value ? true : !!value; - case 'array': - return _$isType(value, _$List) ? value : new _$List(value, root, key); - default: - return value; - } -} -function _$type(obj) { - return / (\w+)/.exec({}.toString.call(obj))[1].toLowerCase(); -} -function _$hasProp(obj, prop) { - return obj.hasOwnProperty(prop); -} -function _$drt(dd) { - var hasProp = function(prop, instance, options, element) { - return _$isObject(dd) && dd[prop] && dd[prop](instance, options, element); - }; - return { - $init: function(instance, options, element) { - hasProp('$init', instance, options, element); - }, - - $inserted: function(instance, options, element) { - hasProp('$inserted', instance, options, element); - }, - - $update: function(instance, options, element) { - if (_$isFunction(dd)) { - dd(instance, options, element); - } else { - hasProp('$update', instance, options, element); - } - }, - - $destroy: function(instance, options, element) { - hasProp('$destroy', instance, options, element); - } - }; -} -function _$noop() {} -function _$toStr(obj) { - var str = _$type(obj); - return !/null|undefined/.test(str) ? obj.toString() : str; -} -function _$toPlainObj(obj) { - var data = {}; - _$e(_$isObject(obj) ? obj : {}, function(_v, k) { - if (k[0] !== '$' && !_$isFunction(obj[k])) { - if (_$isType(obj[k], _$List)) { - data[k] = obj[k].map(_$toPlainObj); - } else if (_$isObject(obj[k])) { - data[k] = _$toPlainObj(obj[k]); - } else { - data[k] = obj[k]; - } - } - }); - return _$isObject(obj) ? data : obj; -} -function _$accesor(object, path, value) { - return path.split('.').reduce(function(obj, key, i, arr) { - if (_$isType(value, 'undefined')) { - if (obj == null) { - arr.splice(0, arr.length); - return i > 0 && obj === null ? obj : undefined; - } - } else { - if (i === arr.length - 1) { - if (_$isType(obj, _$List) && _$toStr(+key) === key) { - obj.pull(+key, value); - } else { - var oldVal = obj[key]; - obj[key] = !_$isType(value, _$List) && _$isArray(value) ? new _$List(value, object, key) : value; - _$dispatch(object, path, oldVal, obj[key]); - } - } else if (!_$isObject(obj[key])) { - obj[key] = {}; - } - } - return obj ? obj[key] : null; - }, object); -} -function _$emptyElse() { - return { - type: 'empty-else', - $create: _$noop, - $mount: _$noop, - $update: _$noop, - $destroy: _$noop - }; -} -function _$(selector, parent) { - return _$isStr(selector) ? (parent || document).querySelector(selector) : selector; -} -function _$d() { - return document.createDocumentFragment(); -} -function _$a(parent, child, sibling) { - if (_$isType(sibling, 'boolean') && sibling) - parent.parentElement.replaceChild(child, parent); - else if (!sibling) - parent.appendChild(child); - else - parent.insertBefore(child, sibling); -} -function _$ce(tagName) { - return document.createElement(tagName || 'div'); -} -function _$ct(content) { - return document.createTextNode(content || ''); -} -function _$cu(block, condition, inst, parent, anchor) { - if (block && block.type === condition(inst).type) { - block.$update(inst); - } else { - block && block.$destroy(); - block = condition(inst); - block.$create(); - block.$mount(parent, anchor); - } - return block; -} -function _$e(obj, cb) { - for (var key in obj) { - if (_$hasProp(obj, key)) { - cb(obj[key], isNaN(+key) ? key : +key); - } - } -} -function ifCondition_1() { - var _$frag, span_1; - _$frag = _$d(); - return { - type: 'if', - - $create: function() { - span_1 = _$ce('span'); - span_1.innerHTML = '1'; - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - }, - - $update: _$noop, - - $unmount: function() { - _$a(_$frag, span_1); - }, - - $destroy: function() { - this.$unmount(); - _$frag = span_1 = void 0; - } - }; -} -function elseIf_1_condition_1() { - var _$frag, span_1; - _$frag = _$d(); - return { - type: 'elseIf_1', - - $create: function() { - span_1 = _$ce('span'); - span_1.innerHTML = '2'; - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - }, - - $update: _$noop, - - $unmount: function() { - _$a(_$frag, span_1); - }, - - $destroy: function() { - this.$unmount(); - _$frag = span_1 = void 0; - } - }; -} -function elseCondition_1() { - var _$frag, span_1; - _$frag = _$d(); - return { - type: 'else', - - $create: function() { - span_1 = _$ce('span'); - span_1.innerHTML = 'other'; - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - }, - - $update: _$noop, - - $unmount: function() { - _$a(_$frag, span_1); - }, - - $destroy: function() { - this.$unmount(); - _$frag = span_1 = void 0; - } - }; -} -function condition_1(_$state) { - if (_$state.condition === 1) - return ifCondition_1(_$state); - else if (_$state.condition === 2) - return elseIf_1_condition_1(_$state); - else - return elseCondition_1(_$state); -} -function ifCondition_2() { - var _$frag, div_1; - _$frag = _$d(); - return { - type: 'if', - - $create: function() { - div_1 = _$ce(); - div_1.innerHTML = '1'; - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - }, - - $update: _$noop, - - $unmount: function() { - _$a(_$frag, div_1); - }, - - $destroy: function() { - this.$unmount(); - _$frag = div_1 = void 0; - } - }; -} -function condition_2(_$state) { - if (_$state.condition_1 === 1) - return ifCondition_2(_$state); - else - return _$emptyElse(); -} -function _$tplCondition(_$state) { - var _$frag, conditionAnchor_1, conditionBlock_1, conditionAnchor_2, conditionBlock_2; - _$frag = _$d(); - conditionAnchor_1 = _$ct(); - conditionAnchor_2 = _$ct(); - return { - $create: function() { - conditionBlock_1 = condition_1(_$state); - conditionBlock_1.$create(); - conditionBlock_2 = condition_2(_$state); - conditionBlock_2.$create(); - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - this.$siblingEl = _$(sibling); - this.$parentEl = sibling && _$(sibling).parentElement || _$(parent); - }, - - $update: function(_$state) { - conditionBlock_1 = _$cu( - conditionBlock_1, - condition_1, - _$state, - _$state.$parentEl, - conditionAnchor_1 - ); - conditionBlock_2 = _$cu( - conditionBlock_2, - condition_2, - _$state, - _$state.$parentEl, - conditionAnchor_2 - ); - }, - - $unmount: function() { - _$a(_$frag, conditionAnchor_1); - conditionBlock_1.$mount(_$frag, conditionAnchor_1); - _$a(_$frag, conditionAnchor_2); - conditionBlock_2.$mount(_$frag, conditionAnchor_2); - }, - - $destroy: function() { - this.$unmount(); - this.$parent = null; - this.$parentEl = null; - this.$siblingEl = null; - this.$children.splice(0, this.$children.length); - conditionBlock_1.$destroy(); - conditionBlock_2.$destroy(); - delete _$state.$root; - _$frag = conditionAnchor_1 = conditionBlock_1 = conditionAnchor_2 = conditionBlock_2 = void 0; - } - }; -} -function Condition(_$attrs, _$parent) { - _$CompCtr.call(this, _$attrs, _$tplCondition, { - model: { - condition: 1, - condition_1: 1 - } - }, _$parent); - !_$parent && this.$create(); -} -_$extends(Condition, _$CompCtr); -return Condition; - - }); \ No newline at end of file diff --git a/spec/components/html.umd.js b/spec/components/html.umd.js deleted file mode 100644 index b6d1885..0000000 --- a/spec/components/html.umd.js +++ /dev/null @@ -1,580 +0,0 @@ -!function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define('html', factory) : - (global.Html = factory()); - }(this, function () { - 'use strict'; -var PROP_MAP = { - p: '__TP__', - v: 'value', - _: '_value', - s: '_subscribers', - e: '_events', - w: '_watchers', - h: 'prototype' -}; -var PROPS = ['$slots', '$refs', '$filters', '$directives', '_events', '_watchers']; -var TPS = window[PROP_MAP.p] || (window[PROP_MAP.p] = []); -var _$assign = Object['assign'] || function(t) { - for (var s = void 0, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (_$hasProp(s, p)) - t[p] = s[p]; - } - return t; -}; -function _$CompCtr(attrs, template, options, parent) { - var self = this; - var _$set = function(prop, value) { - _$def(self, prop, { - value: value, - writable: true - }); - }; - if (!attrs) - attrs = {}; - _$e(PROPS, function(prop) { - _$def(self, prop, { - value: {} - }); - }); - _$set('$parent', parent || null); - _$set('$children', []); - _$set(PROP_MAP.s, {}); - _$set('$options', options); - var opts = self.$options; - if (!opts.attrs) - opts.attrs = {}; - if (!opts.children) - opts.children = {}; - _$e(TPS, function(plugin) { - plugin.fn.call(self, _$CompCtr, plugin.options); - }); - if (opts.filters) - _$assign(self.$filters, opts.filters); - if (opts.directives) _$e(opts.directives, function(drt, k) { - self.$directives[k] = _$drt(drt); - }); - _$e(opts.attrs, function(attrOps, key) { - _$def(self, _$isType(key, 'number') ? attrOps : key, { - get: function() { - if (_$isStr(attrOps)) { - var value = attrs[attrOps]; - return _$isFunction(value) ? value() : value; - } else { - if (!_$hasProp(attrs, key) && attrOps.required) { - return console.error('Attribute \'' + key + '\' is required.'); - } else { - var value = _$isFunction(attrs[key]) ? attrs[key]() : attrs[key]; - if (value === void 0 && _$hasProp(attrOps, 'default')) { - var def = attrOps.default; - value = _$isFunction(def) ? def() : def; - } - var typ = attrOps.type; - if (typ && !_$isType(value, typ) && attrOps.required) { - return console.error('Attribute \'' + key + '\' must be type \'' + typ + '\'.'); - } - value = _$toType(value, value === void 0 ? 'undefined' : typ, self, key); - if (value !== void 0 && _$hasProp(attrOps, 'validator')) { - var validator = attrOps.validator; - if (_$isFunction(validator) && !validator(value)) { - return console.error('Assigment \'' + key + '\'=\'' + JSON.stringify(value) + '\' invalid.'); - } - } - return value; - } - } - }, - - set: function() { - console.error('\'' + key + '\' is read only.'); - }, - - enumerable: true, - configurable: true - }); - }); - var data = opts.model || {}; - var _loop_1 = function(key) { - if (_$hasProp(data, key)) { - var desc = Object.getOwnPropertyDescriptor(data, key); - if (desc.value && _$isArray(desc.value)) { - desc.value = new _$List(desc.value, self, key); - } else { - if (desc.get) { - var getter_1 = desc.get; - desc.get = function() { - var value = getter_1.call(self); - if (_$isArray(value)) - value = new _$List(value, self, key); - return value; - }; - } - if (desc.set) { - var setter_1 = desc.set; - desc.set = function(v) { - if (_$isArray(v)) - v = new _$List(v, self, key); - setter_1.call(self, v); - }; - } - } - _$def(self, key, desc); - } - }; - for (var key in data) { - _loop_1(key); - } - var tpl = template(self, opts.children); - _$e(tpl, function(value, key) { - _$def(self, key, { - value: function(key) { - var hook = key[1].toUpperCase() + key.slice(2); - var bhook = opts['before' + hook]; - var ahook = opts['after' + hook]; - return function() { - bhook && bhook.call(this); - key.slice(1) === 'update' ? value.call(this, this) : value.apply(this, arguments); - ahook && ahook.call(this); - }; - }(key) - }); - }); - _$def(self, '$data', { - get: function() { - return _$toPlainObj(this); - } - }); -} -function _$isValueAttr(attr) { - return attr === 'value'; -} -function _$subs(dep, listener) { - if (!this[PROP_MAP.s][dep]) { - this[PROP_MAP.s][dep] = []; - } - return this[PROP_MAP.s][dep].push(listener.bind(this)) - 1; -} -function _$def(obj, key, desc) { - Object.defineProperty(obj, key, desc); -} -_$assign(_$CompCtr[PROP_MAP.h], { - $get: function(path) { - return _$accesor(this, path); - }, - - $set: function(path, value) { - _$accesor(this, path, value); - }, - - $on: function(event, handler) { - var _this = this; - if (!this[PROP_MAP.e][event]) { - this[PROP_MAP.e][event] = []; - } - var i = this[PROP_MAP.e][event].push(handler); - return { - $off: function() { - _this[PROP_MAP.e][event].splice(i - 1, 1); - } - }; - }, - - $once: function(event, handler) { - var e = this.$on(event, function(args) { - handler(args); - e.$off(); - }); - }, - - $fire: function(event, data) { - if (this[PROP_MAP.e][event]) { - _$e(this[PROP_MAP.e][event], function(handler) { - handler(data); - }); - } - }, - - $notify: function(key) { - if (this[PROP_MAP.s][key]) { - _$e(this[PROP_MAP.s][key], function(suscriber) { - suscriber(); - }); - } - }, - - $observe: function(deps, listener) { - var _this = this; - var subs = []; - if (_$isArray(deps)) { - _$e(deps, function(dep) { - subs.push({ - sub: dep, - i: _$subs.call(_this, dep, listener) - }); - }); - } else { - subs.push({ - sub: deps, - i: _$subs.call(this, deps, listener) - }); - } - return { - $unobserve: function() { - _$e(subs, function(sub) { - _this[PROP_MAP.s][sub.sub].splice(sub.i, 1); - }); - } - }; - }, - - $watch: function(key, watcher) { - var _this = this; - if (!this[PROP_MAP.w][key]) { - this[PROP_MAP.w][key] = []; - } - var i = this[PROP_MAP.w][key].push(watcher.bind(this)); - return { - $unwatch: function() { - _this[PROP_MAP.w][key].splice(i - 1, 1); - } - }; - } -}); -var array = Array[PROP_MAP.h]; -function _$toArgs(args, start) { - if (start === void 0) { - start = 0; - } - return array.slice.call(args, start); -} -function _$arrayValues(list, value, root, key) { - array.push.apply(list, value.map(function(v, i) { - if (list.length !== 0) - i += list.length; - return !_$isType(v, _$List) && _$isArray(v) ? new _$List(v, root, key + '.' + i) : v; - })); -} -function _$List(value, root, key) { - var self = this; - Array.apply(self, [value.length]); - var desc = { - writable: false, - configurable: false, - enumerable: false - }; - _$def(self, '_key', _$assign({ - value: key - }, desc)); - _$def(self, '_root', _$assign({ - value: root - }, desc)); - _$arrayValues(self, value, root, key); - desc.writable = true; - _$def(self, 'length', _$assign({ - value: self.length - }, desc)); -} -_$extends(_$List, Array); -['pop', 'push', 'reverse', 'shift', 'sort', 'fill', 'unshift', 'splice'].forEach(function(method) { - _$List[PROP_MAP.h][method] = function() { - var self = this; - var old = self.slice(); - var result; - if (method === 'push') { - _$arrayValues(self, _$toArgs(arguments), self._root, self._key); - result = self.length; - } else { - result = array[method].apply(self, arguments); - } - _$dispatch(self._root, self._key, old, self.slice()); - return result; - }; -}); -_$List[PROP_MAP.h].pull = function(index) { - var self = this; - var items = _$toArgs(arguments, 1); - var length = self.length; - if (index > length) { - length = index + 1; - var pull = new Array(index - self.length); - pull.push.apply(pull, items); - for (var i = 0; i < length; i++) { - if (i === index) { - self.push.apply(self, pull); - } - } - } else { - self.splice.apply(self, [index, 1].concat(items)); - } -}; -function _$dispatch(root, key, oldVal, value) { - root.$notify(key); - if (root[PROP_MAP.w][key]) { - _$e(root[PROP_MAP.w][key], function(watcher) { - watcher(oldVal, value); - }); - } - root.$update(); -} -function _$extends(ctor, exts) { - ctor['plugin'] = function(fn, options) { - TPS.push({ - options: options, - fn: fn - }); - }; - ctor[PROP_MAP.h] = Object.create(exts[PROP_MAP.h]); - ctor[PROP_MAP.h].constructor = ctor; -} -function _$isType(value, type) { - return _$type(type) === 'string' ? type.split('|').some(function(t) { - return t.trim() === _$type(value); - }) : value instanceof type; -} -function _$isObject(obj) { - return _$isType(obj, 'object'); -} -function _$isArray(obj) { - return Array.isArray ? Array.isArray(obj) : _$isType(obj, 'array'); -} -function _$isFunction(obj) { - return _$isType(obj, 'function'); -} -function _$isStr(obj) { - return _$isType(obj, 'string'); -} -function _$toType(value, type, root, key) { - switch (type) { - case 'date': - return new Date(value); - case 'string': - return _$toStr(value); - case 'number': - return +value; - case 'boolean': - return _$isStr(value) && !value ? true : !!value; - case 'array': - return _$isType(value, _$List) ? value : new _$List(value, root, key); - default: - return value; - } -} -function _$type(obj) { - return / (\w+)/.exec({}.toString.call(obj))[1].toLowerCase(); -} -function _$hasProp(obj, prop) { - return obj.hasOwnProperty(prop); -} -function _$drt(dd) { - var hasProp = function(prop, instance, options, element) { - return _$isObject(dd) && dd[prop] && dd[prop](instance, options, element); - }; - return { - $init: function(instance, options, element) { - hasProp('$init', instance, options, element); - }, - - $inserted: function(instance, options, element) { - hasProp('$inserted', instance, options, element); - }, - - $update: function(instance, options, element) { - if (_$isFunction(dd)) { - dd(instance, options, element); - } else { - hasProp('$update', instance, options, element); - } - }, - - $destroy: function(instance, options, element) { - hasProp('$destroy', instance, options, element); - } - }; -} -function _$toStr(obj) { - var str = _$type(obj); - return !/null|undefined/.test(str) ? obj.toString() : str; -} -function _$toPlainObj(obj) { - var data = {}; - _$e(_$isObject(obj) ? obj : {}, function(_v, k) { - if (k[0] !== '$' && !_$isFunction(obj[k])) { - if (_$isType(obj[k], _$List)) { - data[k] = obj[k].map(_$toPlainObj); - } else if (_$isObject(obj[k])) { - data[k] = _$toPlainObj(obj[k]); - } else { - data[k] = obj[k]; - } - } - }); - return _$isObject(obj) ? data : obj; -} -function _$setRef(obj, prop) { - var value = []; - _$def(obj, prop, { - get: function() { - return value.length <= 1 ? value[0] : value; - }, - - set: function(val) { - val && !~value.indexOf(val) && value.push(val); - }, - - enumerable: true, - configurable: true - }); -} -function _$accesor(object, path, value) { - return path.split('.').reduce(function(obj, key, i, arr) { - if (_$isType(value, 'undefined')) { - if (obj == null) { - arr.splice(0, arr.length); - return i > 0 && obj === null ? obj : undefined; - } - } else { - if (i === arr.length - 1) { - if (_$isType(obj, _$List) && _$toStr(+key) === key) { - obj.pull(+key, value); - } else { - var oldVal = obj[key]; - obj[key] = !_$isType(value, _$List) && _$isArray(value) ? new _$List(value, object, key) : value; - _$dispatch(object, path, oldVal, obj[key]); - } - } else if (!_$isObject(obj[key])) { - obj[key] = {}; - } - } - return obj ? obj[key] : null; - }, object); -} -function _$(selector, parent) { - return _$isStr(selector) ? (parent || document).querySelector(selector) : selector; -} -function _$d() { - return document.createDocumentFragment(); -} -function _$a(parent, child, sibling) { - if (_$isType(sibling, 'boolean') && sibling) - parent.parentElement.replaceChild(child, parent); - else if (!sibling) - parent.appendChild(child); - else - parent.insertBefore(child, sibling); -} -function _$ce(tagName) { - return document.createElement(tagName || 'div'); -} -function _$ct(content) { - return document.createTextNode(content || ''); -} -function _$sa(el, attrOrBind) { - var attr = attrOrBind[0], value = attrOrBind[1]; - el.setAttribute(attr, _$toStr(value)); - if (_$isValueAttr(attr) && !_$isStr(value)) - el[PROP_MAP._] = value; -} -function _$tu(text, value) { - if (text.data !== (value = _$toStr(value))) - text.data = value; -} -function _$e(obj, cb) { - for (var key in obj) { - if (_$hasProp(obj, key)) { - cb(obj[key], isNaN(+key) ? key : +key); - } - } -} -function _$tplHtml(_$state) { - var _$frag, div_1, div_2, p_1, txt_1, setTxt_1, div_3, p_2, txt_2, setTxt_2, _refs, div_4, div_5, contentDiv_5_1; - _$frag = _$d(); - setTxt_1 = function(_$state) { - return 'Some paragraph with text ' + _$state.expression; - }; - setTxt_2 = function(_$state) { - return 'Some paragraph with ' + _$state.text + ' and ' + _$state.attribute + ' expressions'; - }; - _refs = _$state.$refs; - contentDiv_5_1 = function(_$state) { - return _$state.html; - }; - return { - $create: function() { - div_1 = _$ce(); - div_1.innerHTML = '

Here\'s a very interesting note displayed in a lovely shadowed box.

Any kind of content here. Such as <p>, <table>. You name it!

'; - div_2 = _$ce(); - p_1 = _$ce('p'); - txt_1 = _$ct(); - txt_1.data = setTxt_1(_$state); - div_3 = _$ce(); - p_2 = _$ce('p'); - txt_2 = _$ct(); - txt_2.data = setTxt_2(_$state); - !_refs['someAttr'] && _$setRef(_refs, 'someAttr'); - _refs['someAttr'] = p_2; - div_4 = _$ce(); - div_4.innerHTML = '

Some paragraph with text intentional {{escaped}}

'; - div_5 = _$ce(); - div_5.innerHTML = contentDiv_5_1(_$state); - _$sa(div_1, ['class', 'shadowbox']); - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - this.$siblingEl = _$(sibling); - this.$parentEl = sibling && _$(sibling).parentElement || _$(parent); - }, - - $update: function(_$state) { - _$tu(txt_1, setTxt_1(_$state)); - _$tu(txt_2, setTxt_2(_$state)); - var updateContentDiv_5_1 = contentDiv_5_1(_$state); - if (div_5.innerHTML !== updateContentDiv_5_1) { - div_5.innerHTML = updateContentDiv_5_1; - } - updateContentDiv_5_1 = void 0; - }, - - $unmount: function() { - _$a(_$frag, div_1); - _$a(p_1, txt_1); - _$a(div_2, p_1); - _$a(_$frag, div_2); - _$a(p_2, txt_2); - _$a(div_3, p_2); - _$a(_$frag, div_3); - _$a(_$frag, div_4); - _$a(_$frag, div_5); - }, - - $destroy: function() { - this.$unmount(); - this.$parent = null; - this.$parentEl = null; - this.$siblingEl = null; - this.$children.splice(0, this.$children.length); - if (_$isType(_refs['someAttr'], 'array')) { - var indexP_2 = _refs['someAttr'].indexOf(p_2); - _refs['someAttr'].splice(indexP_2, 1); - } else { - delete _refs['someAttr']; - } - delete _$state.$root; - _$frag = div_1 = div_2 = p_1 = txt_1 = setTxt_1 = div_3 = p_2 = txt_2 = setTxt_2 = _refs = div_4 = div_5 = contentDiv_5_1 = void 0; - } - }; -} -function Html(_$attrs, _$parent) { - _$CompCtr.call(this, _$attrs, _$tplHtml, { - model: { - html: '

Some paragraph with text from {{model}}

' - } - }, _$parent); - !_$parent && this.$create(); -} -_$extends(Html, _$CompCtr); -return Html; - - }); \ No newline at end of file diff --git a/spec/components/init.umd.js b/spec/components/init.umd.js deleted file mode 100644 index 5f2fcad..0000000 --- a/spec/components/init.umd.js +++ /dev/null @@ -1,516 +0,0 @@ -!function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define('init', factory) : - (global.Init = factory()); - }(this, function () { - 'use strict'; -var PROP_MAP = { - p: '__TP__', - v: 'value', - _: '_value', - s: '_subscribers', - e: '_events', - w: '_watchers', - h: 'prototype' -}; -var PROPS = ['$slots', '$refs', '$filters', '$directives', '_events', '_watchers']; -var TPS = window[PROP_MAP.p] || (window[PROP_MAP.p] = []); -var _$assign = Object['assign'] || function(t) { - for (var s = void 0, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (_$hasProp(s, p)) - t[p] = s[p]; - } - return t; -}; -function _$CompCtr(attrs, template, options, parent) { - var self = this; - var _$set = function(prop, value) { - _$def(self, prop, { - value: value, - writable: true - }); - }; - if (!attrs) - attrs = {}; - _$e(PROPS, function(prop) { - _$def(self, prop, { - value: {} - }); - }); - _$set('$parent', parent || null); - _$set('$children', []); - _$set(PROP_MAP.s, {}); - _$set('$options', options); - var opts = self.$options; - if (!opts.attrs) - opts.attrs = {}; - if (!opts.children) - opts.children = {}; - _$e(TPS, function(plugin) { - plugin.fn.call(self, _$CompCtr, plugin.options); - }); - if (opts.filters) - _$assign(self.$filters, opts.filters); - if (opts.directives) _$e(opts.directives, function(drt, k) { - self.$directives[k] = _$drt(drt); - }); - _$e(opts.attrs, function(attrOps, key) { - _$def(self, _$isType(key, 'number') ? attrOps : key, { - get: function() { - if (_$isStr(attrOps)) { - var value = attrs[attrOps]; - return _$isFunction(value) ? value() : value; - } else { - if (!_$hasProp(attrs, key) && attrOps.required) { - return console.error('Attribute \'' + key + '\' is required.'); - } else { - var value = _$isFunction(attrs[key]) ? attrs[key]() : attrs[key]; - if (value === void 0 && _$hasProp(attrOps, 'default')) { - var def = attrOps.default; - value = _$isFunction(def) ? def() : def; - } - var typ = attrOps.type; - if (typ && !_$isType(value, typ) && attrOps.required) { - return console.error('Attribute \'' + key + '\' must be type \'' + typ + '\'.'); - } - value = _$toType(value, value === void 0 ? 'undefined' : typ, self, key); - if (value !== void 0 && _$hasProp(attrOps, 'validator')) { - var validator = attrOps.validator; - if (_$isFunction(validator) && !validator(value)) { - return console.error('Assigment \'' + key + '\'=\'' + JSON.stringify(value) + '\' invalid.'); - } - } - return value; - } - } - }, - - set: function() { - console.error('\'' + key + '\' is read only.'); - }, - - enumerable: true, - configurable: true - }); - }); - var data = opts.model || {}; - var _loop_1 = function(key) { - if (_$hasProp(data, key)) { - var desc = Object.getOwnPropertyDescriptor(data, key); - if (desc.value && _$isArray(desc.value)) { - desc.value = new _$List(desc.value, self, key); - } else { - if (desc.get) { - var getter_1 = desc.get; - desc.get = function() { - var value = getter_1.call(self); - if (_$isArray(value)) - value = new _$List(value, self, key); - return value; - }; - } - if (desc.set) { - var setter_1 = desc.set; - desc.set = function(v) { - if (_$isArray(v)) - v = new _$List(v, self, key); - setter_1.call(self, v); - }; - } - } - _$def(self, key, desc); - } - }; - for (var key in data) { - _loop_1(key); - } - var tpl = template(self, opts.children); - _$e(tpl, function(value, key) { - _$def(self, key, { - value: function(key) { - var hook = key[1].toUpperCase() + key.slice(2); - var bhook = opts['before' + hook]; - var ahook = opts['after' + hook]; - return function() { - bhook && bhook.call(this); - key.slice(1) === 'update' ? value.call(this, this) : value.apply(this, arguments); - ahook && ahook.call(this); - }; - }(key) - }); - }); - _$def(self, '$data', { - get: function() { - return _$toPlainObj(this); - } - }); -} -function _$subs(dep, listener) { - if (!this[PROP_MAP.s][dep]) { - this[PROP_MAP.s][dep] = []; - } - return this[PROP_MAP.s][dep].push(listener.bind(this)) - 1; -} -function _$def(obj, key, desc) { - Object.defineProperty(obj, key, desc); -} -_$assign(_$CompCtr[PROP_MAP.h], { - $get: function(path) { - return _$accesor(this, path); - }, - - $set: function(path, value) { - _$accesor(this, path, value); - }, - - $on: function(event, handler) { - var _this = this; - if (!this[PROP_MAP.e][event]) { - this[PROP_MAP.e][event] = []; - } - var i = this[PROP_MAP.e][event].push(handler); - return { - $off: function() { - _this[PROP_MAP.e][event].splice(i - 1, 1); - } - }; - }, - - $once: function(event, handler) { - var e = this.$on(event, function(args) { - handler(args); - e.$off(); - }); - }, - - $fire: function(event, data) { - if (this[PROP_MAP.e][event]) { - _$e(this[PROP_MAP.e][event], function(handler) { - handler(data); - }); - } - }, - - $notify: function(key) { - if (this[PROP_MAP.s][key]) { - _$e(this[PROP_MAP.s][key], function(suscriber) { - suscriber(); - }); - } - }, - - $observe: function(deps, listener) { - var _this = this; - var subs = []; - if (_$isArray(deps)) { - _$e(deps, function(dep) { - subs.push({ - sub: dep, - i: _$subs.call(_this, dep, listener) - }); - }); - } else { - subs.push({ - sub: deps, - i: _$subs.call(this, deps, listener) - }); - } - return { - $unobserve: function() { - _$e(subs, function(sub) { - _this[PROP_MAP.s][sub.sub].splice(sub.i, 1); - }); - } - }; - }, - - $watch: function(key, watcher) { - var _this = this; - if (!this[PROP_MAP.w][key]) { - this[PROP_MAP.w][key] = []; - } - var i = this[PROP_MAP.w][key].push(watcher.bind(this)); - return { - $unwatch: function() { - _this[PROP_MAP.w][key].splice(i - 1, 1); - } - }; - } -}); -var array = Array[PROP_MAP.h]; -function _$toArgs(args, start) { - if (start === void 0) { - start = 0; - } - return array.slice.call(args, start); -} -function _$arrayValues(list, value, root, key) { - array.push.apply(list, value.map(function(v, i) { - if (list.length !== 0) - i += list.length; - return !_$isType(v, _$List) && _$isArray(v) ? new _$List(v, root, key + '.' + i) : v; - })); -} -function _$List(value, root, key) { - var self = this; - Array.apply(self, [value.length]); - var desc = { - writable: false, - configurable: false, - enumerable: false - }; - _$def(self, '_key', _$assign({ - value: key - }, desc)); - _$def(self, '_root', _$assign({ - value: root - }, desc)); - _$arrayValues(self, value, root, key); - desc.writable = true; - _$def(self, 'length', _$assign({ - value: self.length - }, desc)); -} -_$extends(_$List, Array); -['pop', 'push', 'reverse', 'shift', 'sort', 'fill', 'unshift', 'splice'].forEach(function(method) { - _$List[PROP_MAP.h][method] = function() { - var self = this; - var old = self.slice(); - var result; - if (method === 'push') { - _$arrayValues(self, _$toArgs(arguments), self._root, self._key); - result = self.length; - } else { - result = array[method].apply(self, arguments); - } - _$dispatch(self._root, self._key, old, self.slice()); - return result; - }; -}); -_$List[PROP_MAP.h].pull = function(index) { - var self = this; - var items = _$toArgs(arguments, 1); - var length = self.length; - if (index > length) { - length = index + 1; - var pull = new Array(index - self.length); - pull.push.apply(pull, items); - for (var i = 0; i < length; i++) { - if (i === index) { - self.push.apply(self, pull); - } - } - } else { - self.splice.apply(self, [index, 1].concat(items)); - } -}; -function _$dispatch(root, key, oldVal, value) { - root.$notify(key); - if (root[PROP_MAP.w][key]) { - _$e(root[PROP_MAP.w][key], function(watcher) { - watcher(oldVal, value); - }); - } - root.$update(); -} -function _$extends(ctor, exts) { - ctor['plugin'] = function(fn, options) { - TPS.push({ - options: options, - fn: fn - }); - }; - ctor[PROP_MAP.h] = Object.create(exts[PROP_MAP.h]); - ctor[PROP_MAP.h].constructor = ctor; -} -function _$isType(value, type) { - return _$type(type) === 'string' ? type.split('|').some(function(t) { - return t.trim() === _$type(value); - }) : value instanceof type; -} -function _$isObject(obj) { - return _$isType(obj, 'object'); -} -function _$isArray(obj) { - return Array.isArray ? Array.isArray(obj) : _$isType(obj, 'array'); -} -function _$isFunction(obj) { - return _$isType(obj, 'function'); -} -function _$isStr(obj) { - return _$isType(obj, 'string'); -} -function _$toType(value, type, root, key) { - switch (type) { - case 'date': - return new Date(value); - case 'string': - return _$toStr(value); - case 'number': - return +value; - case 'boolean': - return _$isStr(value) && !value ? true : !!value; - case 'array': - return _$isType(value, _$List) ? value : new _$List(value, root, key); - default: - return value; - } -} -function _$type(obj) { - return / (\w+)/.exec({}.toString.call(obj))[1].toLowerCase(); -} -function _$hasProp(obj, prop) { - return obj.hasOwnProperty(prop); -} -function _$drt(dd) { - var hasProp = function(prop, instance, options, element) { - return _$isObject(dd) && dd[prop] && dd[prop](instance, options, element); - }; - return { - $init: function(instance, options, element) { - hasProp('$init', instance, options, element); - }, - - $inserted: function(instance, options, element) { - hasProp('$inserted', instance, options, element); - }, - - $update: function(instance, options, element) { - if (_$isFunction(dd)) { - dd(instance, options, element); - } else { - hasProp('$update', instance, options, element); - } - }, - - $destroy: function(instance, options, element) { - hasProp('$destroy', instance, options, element); - } - }; -} -function _$toStr(obj) { - var str = _$type(obj); - return !/null|undefined/.test(str) ? obj.toString() : str; -} -function _$toPlainObj(obj) { - var data = {}; - _$e(_$isObject(obj) ? obj : {}, function(_v, k) { - if (k[0] !== '$' && !_$isFunction(obj[k])) { - if (_$isType(obj[k], _$List)) { - data[k] = obj[k].map(_$toPlainObj); - } else if (_$isObject(obj[k])) { - data[k] = _$toPlainObj(obj[k]); - } else { - data[k] = obj[k]; - } - } - }); - return _$isObject(obj) ? data : obj; -} -function _$accesor(object, path, value) { - return path.split('.').reduce(function(obj, key, i, arr) { - if (_$isType(value, 'undefined')) { - if (obj == null) { - arr.splice(0, arr.length); - return i > 0 && obj === null ? obj : undefined; - } - } else { - if (i === arr.length - 1) { - if (_$isType(obj, _$List) && _$toStr(+key) === key) { - obj.pull(+key, value); - } else { - var oldVal = obj[key]; - obj[key] = !_$isType(value, _$List) && _$isArray(value) ? new _$List(value, object, key) : value; - _$dispatch(object, path, oldVal, obj[key]); - } - } else if (!_$isObject(obj[key])) { - obj[key] = {}; - } - } - return obj ? obj[key] : null; - }, object); -} -function _$(selector, parent) { - return _$isStr(selector) ? (parent || document).querySelector(selector) : selector; -} -function _$d() { - return document.createDocumentFragment(); -} -function _$a(parent, child, sibling) { - if (_$isType(sibling, 'boolean') && sibling) - parent.parentElement.replaceChild(child, parent); - else if (!sibling) - parent.appendChild(child); - else - parent.insertBefore(child, sibling); -} -function _$ce(tagName) { - return document.createElement(tagName || 'div'); -} -function _$ct(content) { - return document.createTextNode(content || ''); -} -function _$tu(text, value) { - if (text.data !== (value = _$toStr(value))) - text.data = value; -} -function _$e(obj, cb) { - for (var key in obj) { - if (_$hasProp(obj, key)) { - cb(obj[key], isNaN(+key) ? key : +key); - } - } -} -function _$tplInit(_$state) { - var _$frag, h1_1, txt_1, setTxt_1; - _$frag = _$d(); - setTxt_1 = function(_$state) { - return 'Hello, ' + _$state.text + '!!'; - }; - return { - $create: function() { - h1_1 = _$ce('h1'); - txt_1 = _$ct(); - txt_1.data = setTxt_1(_$state); - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - this.$siblingEl = _$(sibling); - this.$parentEl = sibling && _$(sibling).parentElement || _$(parent); - }, - - $update: function(_$state) { - _$tu(txt_1, setTxt_1(_$state)); - }, - - $unmount: function() { - _$a(h1_1, txt_1); - _$a(_$frag, h1_1); - }, - - $destroy: function() { - this.$unmount(); - this.$parent = null; - this.$parentEl = null; - this.$siblingEl = null; - this.$children.splice(0, this.$children.length); - delete _$state.$root; - _$frag = h1_1 = txt_1 = setTxt_1 = void 0; - } - }; -} -function Init(_$attrs, _$parent) { - _$CompCtr.call(this, _$attrs, _$tplInit, { - model: { - text: 'World' - } - }, _$parent); - !_$parent && this.$create(); -} -_$extends(Init, _$CompCtr); -return Init; - - }); \ No newline at end of file diff --git a/spec/components/loop.umd.js b/spec/components/loop.umd.js deleted file mode 100644 index 982710b..0000000 --- a/spec/components/loop.umd.js +++ /dev/null @@ -1,786 +0,0 @@ -!function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define('loop', factory) : - (global.Loop = factory()); - }(this, function () { - 'use strict'; -var PROP_MAP = { - p: '__TP__', - v: 'value', - _: '_value', - s: '_subscribers', - e: '_events', - w: '_watchers', - h: 'prototype' -}; -var PROPS = ['$slots', '$refs', '$filters', '$directives', '_events', '_watchers']; -var TPS = window[PROP_MAP.p] || (window[PROP_MAP.p] = []); -var _$assign = Object['assign'] || function(t) { - for (var s = void 0, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (_$hasProp(s, p)) - t[p] = s[p]; - } - return t; -}; -function _$CompCtr(attrs, template, options, parent) { - var self = this; - var _$set = function(prop, value) { - _$def(self, prop, { - value: value, - writable: true - }); - }; - if (!attrs) - attrs = {}; - _$e(PROPS, function(prop) { - _$def(self, prop, { - value: {} - }); - }); - _$set('$parent', parent || null); - _$set('$children', []); - _$set(PROP_MAP.s, {}); - _$set('$options', options); - var opts = self.$options; - if (!opts.attrs) - opts.attrs = {}; - if (!opts.children) - opts.children = {}; - _$e(TPS, function(plugin) { - plugin.fn.call(self, _$CompCtr, plugin.options); - }); - if (opts.filters) - _$assign(self.$filters, opts.filters); - if (opts.directives) _$e(opts.directives, function(drt, k) { - self.$directives[k] = _$drt(drt); - }); - _$e(opts.attrs, function(attrOps, key) { - _$def(self, _$isType(key, 'number') ? attrOps : key, { - get: function() { - if (_$isStr(attrOps)) { - var value = attrs[attrOps]; - return _$isFunction(value) ? value() : value; - } else { - if (!_$hasProp(attrs, key) && attrOps.required) { - return console.error('Attribute \'' + key + '\' is required.'); - } else { - var value = _$isFunction(attrs[key]) ? attrs[key]() : attrs[key]; - if (value === void 0 && _$hasProp(attrOps, 'default')) { - var def = attrOps.default; - value = _$isFunction(def) ? def() : def; - } - var typ = attrOps.type; - if (typ && !_$isType(value, typ) && attrOps.required) { - return console.error('Attribute \'' + key + '\' must be type \'' + typ + '\'.'); - } - value = _$toType(value, value === void 0 ? 'undefined' : typ, self, key); - if (value !== void 0 && _$hasProp(attrOps, 'validator')) { - var validator = attrOps.validator; - if (_$isFunction(validator) && !validator(value)) { - return console.error('Assigment \'' + key + '\'=\'' + JSON.stringify(value) + '\' invalid.'); - } - } - return value; - } - } - }, - - set: function() { - console.error('\'' + key + '\' is read only.'); - }, - - enumerable: true, - configurable: true - }); - }); - var data = opts.model || {}; - var _loop_1 = function(key) { - if (_$hasProp(data, key)) { - var desc = Object.getOwnPropertyDescriptor(data, key); - if (desc.value && _$isArray(desc.value)) { - desc.value = new _$List(desc.value, self, key); - } else { - if (desc.get) { - var getter_1 = desc.get; - desc.get = function() { - var value = getter_1.call(self); - if (_$isArray(value)) - value = new _$List(value, self, key); - return value; - }; - } - if (desc.set) { - var setter_1 = desc.set; - desc.set = function(v) { - if (_$isArray(v)) - v = new _$List(v, self, key); - setter_1.call(self, v); - }; - } - } - _$def(self, key, desc); - } - }; - for (var key in data) { - _loop_1(key); - } - var tpl = template(self, opts.children); - _$e(tpl, function(value, key) { - _$def(self, key, { - value: function(key) { - var hook = key[1].toUpperCase() + key.slice(2); - var bhook = opts['before' + hook]; - var ahook = opts['after' + hook]; - return function() { - bhook && bhook.call(this); - key.slice(1) === 'update' ? value.call(this, this) : value.apply(this, arguments); - ahook && ahook.call(this); - }; - }(key) - }); - }); - _$def(self, '$data', { - get: function() { - return _$toPlainObj(this); - } - }); -} -function _$isValueAttr(attr) { - return attr === 'value'; -} -function _$subs(dep, listener) { - if (!this[PROP_MAP.s][dep]) { - this[PROP_MAP.s][dep] = []; - } - return this[PROP_MAP.s][dep].push(listener.bind(this)) - 1; -} -function _$def(obj, key, desc) { - Object.defineProperty(obj, key, desc); -} -_$assign(_$CompCtr[PROP_MAP.h], { - $get: function(path) { - return _$accesor(this, path); - }, - - $set: function(path, value) { - _$accesor(this, path, value); - }, - - $on: function(event, handler) { - var _this = this; - if (!this[PROP_MAP.e][event]) { - this[PROP_MAP.e][event] = []; - } - var i = this[PROP_MAP.e][event].push(handler); - return { - $off: function() { - _this[PROP_MAP.e][event].splice(i - 1, 1); - } - }; - }, - - $once: function(event, handler) { - var e = this.$on(event, function(args) { - handler(args); - e.$off(); - }); - }, - - $fire: function(event, data) { - if (this[PROP_MAP.e][event]) { - _$e(this[PROP_MAP.e][event], function(handler) { - handler(data); - }); - } - }, - - $notify: function(key) { - if (this[PROP_MAP.s][key]) { - _$e(this[PROP_MAP.s][key], function(suscriber) { - suscriber(); - }); - } - }, - - $observe: function(deps, listener) { - var _this = this; - var subs = []; - if (_$isArray(deps)) { - _$e(deps, function(dep) { - subs.push({ - sub: dep, - i: _$subs.call(_this, dep, listener) - }); - }); - } else { - subs.push({ - sub: deps, - i: _$subs.call(this, deps, listener) - }); - } - return { - $unobserve: function() { - _$e(subs, function(sub) { - _this[PROP_MAP.s][sub.sub].splice(sub.i, 1); - }); - } - }; - }, - - $watch: function(key, watcher) { - var _this = this; - if (!this[PROP_MAP.w][key]) { - this[PROP_MAP.w][key] = []; - } - var i = this[PROP_MAP.w][key].push(watcher.bind(this)); - return { - $unwatch: function() { - _this[PROP_MAP.w][key].splice(i - 1, 1); - } - }; - } -}); -var array = Array[PROP_MAP.h]; -function _$toArgs(args, start) { - if (start === void 0) { - start = 0; - } - return array.slice.call(args, start); -} -function _$arrayValues(list, value, root, key) { - array.push.apply(list, value.map(function(v, i) { - if (list.length !== 0) - i += list.length; - return !_$isType(v, _$List) && _$isArray(v) ? new _$List(v, root, key + '.' + i) : v; - })); -} -function _$List(value, root, key) { - var self = this; - Array.apply(self, [value.length]); - var desc = { - writable: false, - configurable: false, - enumerable: false - }; - _$def(self, '_key', _$assign({ - value: key - }, desc)); - _$def(self, '_root', _$assign({ - value: root - }, desc)); - _$arrayValues(self, value, root, key); - desc.writable = true; - _$def(self, 'length', _$assign({ - value: self.length - }, desc)); -} -_$extends(_$List, Array); -['pop', 'push', 'reverse', 'shift', 'sort', 'fill', 'unshift', 'splice'].forEach(function(method) { - _$List[PROP_MAP.h][method] = function() { - var self = this; - var old = self.slice(); - var result; - if (method === 'push') { - _$arrayValues(self, _$toArgs(arguments), self._root, self._key); - result = self.length; - } else { - result = array[method].apply(self, arguments); - } - _$dispatch(self._root, self._key, old, self.slice()); - return result; - }; -}); -_$List[PROP_MAP.h].pull = function(index) { - var self = this; - var items = _$toArgs(arguments, 1); - var length = self.length; - if (index > length) { - length = index + 1; - var pull = new Array(index - self.length); - pull.push.apply(pull, items); - for (var i = 0; i < length; i++) { - if (i === index) { - self.push.apply(self, pull); - } - } - } else { - self.splice.apply(self, [index, 1].concat(items)); - } -}; -function _$dispatch(root, key, oldVal, value) { - root.$notify(key); - if (root[PROP_MAP.w][key]) { - _$e(root[PROP_MAP.w][key], function(watcher) { - watcher(oldVal, value); - }); - } - root.$update(); -} -function _$extends(ctor, exts) { - ctor['plugin'] = function(fn, options) { - TPS.push({ - options: options, - fn: fn - }); - }; - ctor[PROP_MAP.h] = Object.create(exts[PROP_MAP.h]); - ctor[PROP_MAP.h].constructor = ctor; -} -function _$isType(value, type) { - return _$type(type) === 'string' ? type.split('|').some(function(t) { - return t.trim() === _$type(value); - }) : value instanceof type; -} -function _$isObject(obj) { - return _$isType(obj, 'object'); -} -function _$isArray(obj) { - return Array.isArray ? Array.isArray(obj) : _$isType(obj, 'array'); -} -function _$isFunction(obj) { - return _$isType(obj, 'function'); -} -function _$isStr(obj) { - return _$isType(obj, 'string'); -} -function _$toType(value, type, root, key) { - switch (type) { - case 'date': - return new Date(value); - case 'string': - return _$toStr(value); - case 'number': - return +value; - case 'boolean': - return _$isStr(value) && !value ? true : !!value; - case 'array': - return _$isType(value, _$List) ? value : new _$List(value, root, key); - default: - return value; - } -} -function _$type(obj) { - return / (\w+)/.exec({}.toString.call(obj))[1].toLowerCase(); -} -function _$hasProp(obj, prop) { - return obj.hasOwnProperty(prop); -} -function _$drt(dd) { - var hasProp = function(prop, instance, options, element) { - return _$isObject(dd) && dd[prop] && dd[prop](instance, options, element); - }; - return { - $init: function(instance, options, element) { - hasProp('$init', instance, options, element); - }, - - $inserted: function(instance, options, element) { - hasProp('$inserted', instance, options, element); - }, - - $update: function(instance, options, element) { - if (_$isFunction(dd)) { - dd(instance, options, element); - } else { - hasProp('$update', instance, options, element); - } - }, - - $destroy: function(instance, options, element) { - hasProp('$destroy', instance, options, element); - } - }; -} -function _$toStr(obj) { - var str = _$type(obj); - return !/null|undefined/.test(str) ? obj.toString() : str; -} -function _$toPlainObj(obj) { - var data = {}; - _$e(_$isObject(obj) ? obj : {}, function(_v, k) { - if (k[0] !== '$' && !_$isFunction(obj[k])) { - if (_$isType(obj[k], _$List)) { - data[k] = obj[k].map(_$toPlainObj); - } else if (_$isObject(obj[k])) { - data[k] = _$toPlainObj(obj[k]); - } else { - data[k] = obj[k]; - } - } - }); - return _$isObject(obj) ? data : obj; -} -function _$accesor(object, path, value) { - return path.split('.').reduce(function(obj, key, i, arr) { - if (_$isType(value, 'undefined')) { - if (obj == null) { - arr.splice(0, arr.length); - return i > 0 && obj === null ? obj : undefined; - } - } else { - if (i === arr.length - 1) { - if (_$isType(obj, _$List) && _$toStr(+key) === key) { - obj.pull(+key, value); - } else { - var oldVal = obj[key]; - obj[key] = !_$isType(value, _$List) && _$isArray(value) ? new _$List(value, object, key) : value; - _$dispatch(object, path, oldVal, obj[key]); - } - } else if (!_$isObject(obj[key])) { - obj[key] = {}; - } - } - return obj ? obj[key] : null; - }, object); -} -function _$(selector, parent) { - return _$isStr(selector) ? (parent || document).querySelector(selector) : selector; -} -function _$d() { - return document.createDocumentFragment(); -} -function _$a(parent, child, sibling) { - if (_$isType(sibling, 'boolean') && sibling) - parent.parentElement.replaceChild(child, parent); - else if (!sibling) - parent.appendChild(child); - else - parent.insertBefore(child, sibling); -} -function _$ce(tagName) { - return document.createElement(tagName || 'div'); -} -function _$ct(content) { - return document.createTextNode(content || ''); -} -function _$sa(el, attrOrBind) { - var attr = attrOrBind[0], value = attrOrBind[1]; - el.setAttribute(attr, _$toStr(value)); - if (_$isValueAttr(attr) && !_$isStr(value)) - el[PROP_MAP._] = value; -} -function _$tu(text, value) { - if (text.data !== (value = _$toStr(value))) - text.data = value; -} -function _$f(root, obj, loop) { - var items = {}, loopParent, loopSibling; - var globs = _$toArgs(arguments, 3); - _$e(obj, function(item, i) { - items[i] = loop.apply(null, [root, item, i].concat(globs)); - }); - return { - $create: function() { - _$e(items, function(item) { - item.$create(); - }); - }, - - $mount: function(parent, sibling) { - loopParent = _$(parent); - loopSibling = _$(sibling); - _$e(items, function(item) { - item.$mount(loopParent, loopSibling); - }); - }, - - $update: function(root, obj) { - var globs = _$toArgs(arguments, 2); - _$e(items, function(item, i) { - if (obj[i]) { - item.$update.apply(item, [root, obj[i], i].concat(globs)); - } else { - item.$destroy(); - delete items[i]; - } - }); - _$e(obj, function(item, i) { - if (!items[i]) { - items[i] = loop.apply(null, [root, item, i].concat(globs)); - items[i].$create(); - items[i].$mount(loopParent, loopSibling); - } - }); - }, - - $destroy: function() { - _$e(items, function(item) { - item.$destroy(); - }); - } - }; -} -function _$e(obj, cb) { - for (var key in obj) { - if (_$hasProp(obj, key)) { - cb(obj[key], isNaN(+key) ? key : +key); - } - } -} -function itemLoop_1(_$state, item) { - var _$frag, li_1, txt_1, setTxt_1; - _$frag = _$d(); - setTxt_1 = function(_$state, item) { - return item; - }; - return { - $create: function() { - li_1 = _$ce('li'); - txt_1 = _$ct(); - txt_1.data = setTxt_1(_$state, item); - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - }, - - $update: function(_$state, item) { - _$tu(txt_1, setTxt_1(_$state, item)); - }, - - $unmount: function() { - _$a(li_1, txt_1); - _$a(_$frag, li_1); - }, - - $destroy: function() { - this.$unmount(); - _$frag = li_1 = txt_1 = setTxt_1 = void 0; - } - }; -} -function itemLoop_2(_$state, item) { - var _$frag, li_1, txt_1, setTxt_1; - _$frag = _$d(); - setTxt_1 = function(_$state, item) { - return item; - }; - return { - $create: function() { - li_1 = _$ce('li'); - txt_1 = _$ct(); - txt_1.data = setTxt_1(_$state, item); - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - }, - - $update: function(_$state, item) { - _$tu(txt_1, setTxt_1(_$state, item)); - }, - - $unmount: function() { - _$a(li_1, txt_1); - _$a(_$frag, li_1); - }, - - $destroy: function() { - this.$unmount(); - _$frag = li_1 = txt_1 = setTxt_1 = void 0; - } - }; -} -function itemLoop_3(_$state, item) { - var _$frag, li_1, txt_1, setTxt_1; - _$frag = _$d(); - setTxt_1 = function(_$state, item) { - return item; - }; - return { - $create: function() { - li_1 = _$ce('li'); - txt_1 = _$ct(); - txt_1.data = setTxt_1(_$state, item); - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - }, - - $update: function(_$state, item) { - _$tu(txt_1, setTxt_1(_$state, item)); - }, - - $unmount: function() { - _$a(li_1, txt_1); - _$a(_$frag, li_1); - }, - - $destroy: function() { - this.$unmount(); - _$frag = li_1 = txt_1 = setTxt_1 = void 0; - } - }; -} -function itemLoop_4(_$state, item) { - var _$frag, li_1, txt_1, setTxt_1; - _$frag = _$d(); - setTxt_1 = function(_$state, item) { - return item; - }; - return { - $create: function() { - li_1 = _$ce('li'); - txt_1 = _$ct(); - txt_1.data = setTxt_1(_$state, item); - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - }, - - $update: function(_$state, item) { - _$tu(txt_1, setTxt_1(_$state, item)); - }, - - $unmount: function() { - _$a(li_1, txt_1); - _$a(_$frag, li_1); - }, - - $destroy: function() { - this.$unmount(); - _$frag = li_1 = txt_1 = setTxt_1 = void 0; - } - }; -} -function itemLoop_5(_$state, item) { - var _$frag, li_1, txt_1, setTxt_1; - _$frag = _$d(); - setTxt_1 = function(_$state, item) { - return item; - }; - return { - $create: function() { - li_1 = _$ce('li'); - txt_1 = _$ct(); - txt_1.data = setTxt_1(_$state, item); - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - }, - - $update: function(_$state, item) { - _$tu(txt_1, setTxt_1(_$state, item)); - }, - - $unmount: function() { - _$a(li_1, txt_1); - _$a(_$frag, li_1); - }, - - $destroy: function() { - this.$unmount(); - _$frag = li_1 = txt_1 = setTxt_1 = void 0; - } - }; -} -function _$tplLoop(_$state) { - var _$frag, ul_1, loopAnchor_1_1, loopBlock_1, ul_2, loopAnchor_2_1, loopBlock_2, ul_3, loopAnchor_3_1, loopBlock_3, ul_4, loopAnchor_4_1, loopBlock_4, ul_5, loopAnchor_5_1, loopBlock_5; - _$frag = _$d(); - loopBlock_1 = _$f(_$state, _$state.items, itemLoop_1); - loopAnchor_1_1 = _$ct(); - loopBlock_2 = _$f(_$state, _$state.object, itemLoop_2); - loopAnchor_2_1 = _$ct(); - loopBlock_3 = _$f(_$state, [1, 2, 3, 4, 5], itemLoop_3); - loopAnchor_3_1 = _$ct(); - loopBlock_4 = _$f(_$state, [0, 1, 2, 3, 4], itemLoop_4); - loopAnchor_4_1 = _$ct(); - loopBlock_5 = _$f(_$state, [0, 1, 2, 3, 4], itemLoop_5); - loopAnchor_5_1 = _$ct(); - return { - $create: function() { - ul_1 = _$ce('ul'); - loopBlock_1.$create(); - ul_2 = _$ce('ul'); - loopBlock_2.$create(); - ul_3 = _$ce('ul'); - loopBlock_3.$create(); - ul_4 = _$ce('ul'); - loopBlock_4.$create(); - ul_5 = _$ce('ul'); - loopBlock_5.$create(); - _$sa(ul_1, ['id', 'loop_1']); - _$sa(ul_2, ['id', 'loop_2']); - _$sa(ul_3, ['id', 'loop_3']); - _$sa(ul_4, ['id', 'loop_4']); - _$sa(ul_5, ['id', 'loop_5']); - }, - - $mount: function(parent, sibling) { - this.$unmount(); - _$a(_$(parent), _$frag, _$(sibling)); - this.$siblingEl = _$(sibling); - this.$parentEl = sibling && _$(sibling).parentElement || _$(parent); - }, - - $update: function(_$state) { - loopBlock_1.$update(_$state, _$state.items); - loopBlock_2.$update(_$state, _$state.object); - loopBlock_3.$update(_$state, [1, 2, 3, 4, 5]); - loopBlock_4.$update(_$state, [0, 1, 2, 3, 4]); - loopBlock_5.$update(_$state, [0, 1, 2, 3, 4]); - }, - - $unmount: function() { - _$a(ul_1, loopAnchor_1_1); - loopBlock_1.$mount(ul_1, loopAnchor_1_1); - _$a(_$frag, ul_1); - _$a(ul_2, loopAnchor_2_1); - loopBlock_2.$mount(ul_2, loopAnchor_2_1); - _$a(_$frag, ul_2); - _$a(ul_3, loopAnchor_3_1); - loopBlock_3.$mount(ul_3, loopAnchor_3_1); - _$a(_$frag, ul_3); - _$a(ul_4, loopAnchor_4_1); - loopBlock_4.$mount(ul_4, loopAnchor_4_1); - _$a(_$frag, ul_4); - _$a(ul_5, loopAnchor_5_1); - loopBlock_5.$mount(ul_5, loopAnchor_5_1); - _$a(_$frag, ul_5); - }, - - $destroy: function() { - this.$unmount(); - this.$parent = null; - this.$parentEl = null; - this.$siblingEl = null; - this.$children.splice(0, this.$children.length); - loopBlock_1.$destroy(); - loopBlock_2.$destroy(); - loopBlock_3.$destroy(); - loopBlock_4.$destroy(); - loopBlock_5.$destroy(); - delete _$state.$root; - _$frag = ul_1 = loopAnchor_1_1 = loopBlock_1 = ul_2 = loopAnchor_2_1 = loopBlock_2 = ul_3 = loopAnchor_3_1 = loopBlock_3 = ul_4 = loopAnchor_4_1 = loopBlock_4 = ul_5 = loopAnchor_5_1 = loopBlock_5 = void 0; - } - }; -} -function Loop(_$attrs, _$parent) { - _$CompCtr.call(this, _$attrs, _$tplLoop, { - model: { - items: [1, 2, 3, 4, 5], - - object: { - a: 'a', - b: 'b', - c: 'c', - d: 'd', - e: 'e' - } - } - }, _$parent); - !_$parent && this.$create(); -} -_$extends(Loop, _$CompCtr); -return Loop; - - }); \ No newline at end of file diff --git a/spec/helpers/setup.js b/spec/helpers/setup.js deleted file mode 100644 index 7aa10e6..0000000 --- a/spec/helpers/setup.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const jsdom_1 = require("jsdom"); -function copyProps(src, target) { - const props = Object.getOwnPropertyNames(src) - .filter(prop => typeof target[prop] === 'undefined') - .reduce((result, prop) => ({ - ...result, - [prop]: Object.getOwnPropertyDescriptor(src, prop), - }), {}); - Object.defineProperties(target, props); -} -global['window'] = new jsdom_1.JSDOM('
').window; -global['document'] = global['window'].document; -global['navigator'] = { - userAgent: 'NodeJS', - language: 'en' -}; -copyProps(window, global); diff --git a/spec/special attributes/bind_value.spec.js b/spec/special attributes/bind_value.spec.js deleted file mode 100644 index 350e95a..0000000 --- a/spec/special attributes/bind_value.spec.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -require("../helpers/setup"); -const keysim_1 = require("keysim"); -const Component = require('../components/bind.umd'); -function fireClick(element) { - let event = new window['MouseEvent']('click', { bubbles: true, cancelable: true, view: window }); - element.dispatchEvent(event); -} -describe('Component Bind', () => { - let instance; - beforeAll(done => { - instance = new Component(); - instance.$mount('main'); - done(); - }); - it('`$name` in checkbox should add value to an array', () => { - let input = document.querySelector('#checkbox_1'); - fireClick(input); - expect(instance.checkboxes.length).toBe(1); - expect(instance.checkboxes[0]).toBe('Yes'); - }); - it('`$name` in a checked checkbox should remove value from the array', () => { - let input = document.querySelector('#checkbox_1'); - fireClick(input); - expect(instance.checkboxes.length).toBe(0); - }); - it('`$name` in a radio should change value of the property', () => { - let input = document.querySelector('#radio_1'); - fireClick(input); - expect(instance.radios).toBe('radio 1'); - }); - it('`$value` should change input value from model', () => { - instance.$set('textValue', 'some text'); - let input = document.querySelector('#text'); - expect(input.value).toBe('some text'); - }); - it('`input.value` should change input value in model', () => { - let input = document.querySelector('#text'); - let keyboard = keysim_1.Keyboard.US_ENGLISH; - input.value = input.value + ' to test'; - keyboard.dispatchEventsForInput(input.value, input); - expect(instance.textValue).toBe('some text to test'); - }); -}); diff --git a/spec/special attributes/condition.spec.js b/spec/special attributes/condition.spec.js deleted file mode 100644 index ddffb81..0000000 --- a/spec/special attributes/condition.spec.js +++ /dev/null @@ -1,35 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -require("../helpers/setup"); -const Component = require('../components/condition.umd'); -describe('Component Conditions', () => { - let instance, span, div; - beforeAll(done => { - instance = new Component(); - instance.$mount('main'); - done(); - }); - it('`$if` should be rendered', () => { - span = document.querySelector('span'); - expect(span.textContent).toBe('1'); - }); - it('`$else-if` should be rendered', () => { - instance.$set('condition', 2); - span = document.querySelector('span'); - expect(span.textContent).toBe('2'); - }); - it('`$else` should be rendered', () => { - instance.$set('condition', 3); - span = document.querySelector('span'); - expect(span.textContent).toBe('other'); - }); - it('`$if` only should be rendered', () => { - div = document.querySelector('div'); - expect(div.textContent).toBe('1'); - }); - it('`$if` only should be hidden', () => { - instance.$set('condition_1', 2); - div = document.querySelector('div'); - expect(div).toBeNull(); - }); -}); diff --git a/spec/special attributes/html.spec.js b/spec/special attributes/html.spec.js deleted file mode 100644 index 39d1ebe..0000000 --- a/spec/special attributes/html.spec.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -require("../helpers/setup"); -const Component = require('../components/html.umd'); -describe('Component Html', () => { - let instance, divs; - beforeAll(done => { - instance = new Component(); - instance.$mount('main'); - done(); - }); - it('nodes without expression should be normally rendered', () => { - divs = document.querySelectorAll('div'); - let div = divs.item(0); - expect(div.innerHTML).toBe('

Here\'s a very interesting note displayed in a lovely shadowed box.

Any kind of content here. Such as <p>, <table>. You name it!

'); - }); - it('nodes with expression should not escape expressions', () => { - divs = document.querySelectorAll('div'); - let div_1 = divs.item(1), div_2 = divs.item(2); - expect(div_1.innerHTML).toBe('

Some paragraph with text undefined

'); - expect(div_2.innerHTML).toBe('

Some paragraph with undefined and undefined expressions

'); - }); - it('`$html` should escape expressions', () => { - divs = document.querySelectorAll('div'); - let div_1 = divs.item(3), div_2 = divs.item(4); - expect(div_1.innerHTML).toBe('

Some paragraph with text intentional {{escaped}}

'); - expect(div_2.innerHTML).toBe('

Some paragraph with text from {{model}}

'); - }); -}); diff --git a/spec/special attributes/loop.spec.js b/spec/special attributes/loop.spec.js deleted file mode 100644 index 57ec189..0000000 --- a/spec/special attributes/loop.spec.js +++ /dev/null @@ -1,55 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -require("../helpers/setup"); -const Component = require('../components/loop.umd'); -describe('Component Loop', () => { - let instance, items; - beforeAll(done => { - instance = new Component(); - instance.$mount('main'); - done(); - }); - it('should loop over an array variable', () => { - items = document.querySelectorAll('#loop_1 li'); - expect(items.length).toBe(5); - for (let i = 0; i < items.length; i++) { - expect(items.item(i).textContent).toBe(`${i + 1}`); - } - }); - it('should loop over an object', () => { - items = document.querySelectorAll('#loop_2 li'); - expect(items.length).toBe(5); - expect(items.item(0).textContent).toBe('a'); - expect(items.item(4).textContent).toBe('e'); - }); - it('should loop over an array', () => { - items = document.querySelectorAll('#loop_3 li'); - expect(items.length).toBe(5); - for (let i = 0; i < items.length; i++) { - expect(items.item(i).textContent).toBe(`${i + 1}`); - } - }); - it('should loop over a number', () => { - items = document.querySelectorAll('#loop_4 li'); - expect(items.length).toBe(5); - for (let i = 0; i < items.length; i++) { - expect(items.item(i).textContent).toBe(`${i}`); - } - }); - it('should loop over a range of numbers', () => { - items = document.querySelectorAll('#loop_5 li'); - expect(items.length).toBe(5); - for (let i = 0; i < items.length; i++) { - expect(items.item(i).textContent).toBe(`${i}`); - } - }); - it('items should be modified', () => { - instance.items.splice(3, 1); - items = document.querySelectorAll('#loop_1 li'); - expect(items.length).toBe(4); - expect(items.item(0).textContent).toBe('1'); - expect(items.item(1).textContent).toBe('2'); - expect(items.item(2).textContent).toBe('3'); - expect(items.item(3).textContent).toBe('5'); - }); -}); diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json deleted file mode 100644 index 3ea3166..0000000 --- a/spec/support/jasmine.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "spec_dir": "spec", - "spec_files": [ - "**/*[sS]pec.js" - ], - "helpers": [ - "helpers/**/*.js" - ], - "stopSpecOnExpectationFailure": false, - "random": false -} From 27a68c087cf354f37f35fa9a42a4c8bba7faa2da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Asiel=20Guevara=20Casta=C3=B1eda?= Date: Mon, 8 Oct 2018 12:20:30 -0400 Subject: [PATCH 7/9] Ignored spec folder from package --- .npmignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.npmignore b/.npmignore index a02753d..be43b86 100644 --- a/.npmignore +++ b/.npmignore @@ -5,6 +5,7 @@ examples/ src/ test/ +spec/ tools/index.ts tools/tsconfig.json package-lock.json From 0f444e7c1054946d40281ff7088c9f0570beef42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Asiel=20Guevara=20Casta=C3=B1eda?= Date: Mon, 8 Oct 2018 14:52:23 -0400 Subject: [PATCH 8/9] Bump to version 0.2.2 --- CHANGELOG.md | 6 ++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bb10a1..c4401e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +0.2.2 +- Added Sequence expression to context generation. +- Fixed missing attributes generating elements in slots. +- Fixed bug generating code for component event attributes. +- Fixed internal errors passing children in loops and conditions. + 0.2.1 - Fixed issue analyzing slots. - Fixed bug mounting components. diff --git a/package-lock.json b/package-lock.json index bdde1b8..2928845 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "trebor", - "version": "0.2.1", + "version": "0.2.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ef15d9f..6efec12 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "trebor", - "version": "0.2.1", + "version": "0.2.2", "description": "A node js module to make standalone web components.", "main": "./build/index.js", "bin": { From c9adb675d3b0eb55a7cbd6cb4cfefd6b376c288d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Asiel=20Guevara=20Casta=C3=B1eda?= Date: Mon, 8 Oct 2018 12:19:10 -0400 Subject: [PATCH 9/9] Revert "Ignored spec folder" This reverts commit 14d9213eb872ce2073f0632d70053aa3ea7f65e1. --- .gitignore | 1 - spec/basic usage/initialize.spec.js | 69 ++ spec/components/bind.umd.js | 640 +++++++++++++++++ spec/components/condition.umd.js | 677 ++++++++++++++++++ spec/components/html.umd.js | 580 +++++++++++++++ spec/components/init.umd.js | 516 ++++++++++++++ spec/components/loop.umd.js | 786 +++++++++++++++++++++ spec/helpers/setup.js | 19 + spec/special attributes/bind_value.spec.js | 45 ++ spec/special attributes/condition.spec.js | 35 + spec/special attributes/html.spec.js | 29 + spec/special attributes/loop.spec.js | 55 ++ spec/support/jasmine.json | 11 + 13 files changed, 3462 insertions(+), 1 deletion(-) create mode 100644 spec/basic usage/initialize.spec.js create mode 100644 spec/components/bind.umd.js create mode 100644 spec/components/condition.umd.js create mode 100644 spec/components/html.umd.js create mode 100644 spec/components/init.umd.js create mode 100644 spec/components/loop.umd.js create mode 100644 spec/helpers/setup.js create mode 100644 spec/special attributes/bind_value.spec.js create mode 100644 spec/special attributes/condition.spec.js create mode 100644 spec/special attributes/html.spec.js create mode 100644 spec/special attributes/loop.spec.js create mode 100644 spec/support/jasmine.json diff --git a/.gitignore b/.gitignore index 424a545..27c7774 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ node_modules/ build/ -spec/ tools/*.js tools/*.map test/index.js \ No newline at end of file diff --git a/spec/basic usage/initialize.spec.js b/spec/basic usage/initialize.spec.js new file mode 100644 index 0000000..4b6400d --- /dev/null +++ b/spec/basic usage/initialize.spec.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("../helpers/setup"); +const Component = require('../components/init.umd'); +describe('Component', () => { + it('should be a function constructor', () => { + expect(Component).not.toBeNull(); + expect(typeof Component).toBe('function'); + }); + it('should get an instance when is used with new', () => { + let instance = new Component(); + expect(typeof instance).toBe('object'); + expect(instance.constructor).toEqual(Component); + }); + it('instance should have prototype methods', () => { + let instance = new Component(); + expect('$refs' in instance).toBeTruthy(); + expect('$create' in instance).toBeTruthy(); + expect('$mount' in instance).toBeTruthy(); + expect('$update' in instance).toBeTruthy(); + expect('$unmount' in instance).toBeTruthy(); + expect('$destroy' in instance).toBeTruthy(); + expect('$watch' in instance).toBeTruthy(); + expect('$observe' in instance).toBeTruthy(); + }); + it('instance should have option properties', () => { + let instance = new Component(); + expect('text' in instance).toBeTruthy(); + expect(instance.text).toBe('World'); + }); +}); +describe('Component Instance', () => { + let instance, main; + beforeAll(done => { + instance = new Component(); + main = document.querySelector('main'); + done(); + }); + afterEach(done => { + instance.$unmount(); + done(); + }); + it('should be mounted in an element selector', () => { + instance.$mount('main'); + expect(instance.$parentEl).toEqual(main); + }); + it('should be mounted in an element', () => { + instance.$mount(main); + expect(instance.$parentEl).toEqual(main); + }); + it('should be mounted correctly', () => { + instance.$mount('main'); + let h1 = main.firstChild; + expect(h1.nodeName).toEqual('H1'); + expect(h1.textContent).toBe('Hello, World!!'); + }); + it('should update the view correctly', () => { + instance.$mount('main'); + let h1 = main.firstChild; + instance.$set('text', 'Somebody'); + expect(h1.textContent).toBe('Hello, Somebody!!'); + }); + it('should not update the view correctly if `$set` method is not used', () => { + instance.$mount('main'); + let h1 = main.firstChild; + instance.text = 'World'; + expect(h1.textContent).toBe('Hello, Somebody!!'); + }); +}); diff --git a/spec/components/bind.umd.js b/spec/components/bind.umd.js new file mode 100644 index 0000000..8d94acb --- /dev/null +++ b/spec/components/bind.umd.js @@ -0,0 +1,640 @@ +!function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define('bind', factory) : + (global.Bind = factory()); + }(this, function () { + 'use strict'; +var PROP_MAP = { + p: '__TP__', + v: 'value', + _: '_value', + s: '_subscribers', + e: '_events', + w: '_watchers', + h: 'prototype' +}; +var PROPS = ['$slots', '$refs', '$filters', '$directives', '_events', '_watchers']; +var TPS = window[PROP_MAP.p] || (window[PROP_MAP.p] = []); +var _$assign = Object['assign'] || function(t) { + for (var s = void 0, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (_$hasProp(s, p)) + t[p] = s[p]; + } + return t; +}; +function _$CompCtr(attrs, template, options, parent) { + var self = this; + var _$set = function(prop, value) { + _$def(self, prop, { + value: value, + writable: true + }); + }; + if (!attrs) + attrs = {}; + _$e(PROPS, function(prop) { + _$def(self, prop, { + value: {} + }); + }); + _$set('$parent', parent || null); + _$set('$children', []); + _$set(PROP_MAP.s, {}); + _$set('$options', options); + var opts = self.$options; + if (!opts.attrs) + opts.attrs = {}; + if (!opts.children) + opts.children = {}; + _$e(TPS, function(plugin) { + plugin.fn.call(self, _$CompCtr, plugin.options); + }); + if (opts.filters) + _$assign(self.$filters, opts.filters); + if (opts.directives) _$e(opts.directives, function(drt, k) { + self.$directives[k] = _$drt(drt); + }); + _$e(opts.attrs, function(attrOps, key) { + _$def(self, _$isType(key, 'number') ? attrOps : key, { + get: function() { + if (_$isStr(attrOps)) { + var value = attrs[attrOps]; + return _$isFunction(value) ? value() : value; + } else { + if (!_$hasProp(attrs, key) && attrOps.required) { + return console.error('Attribute \'' + key + '\' is required.'); + } else { + var value = _$isFunction(attrs[key]) ? attrs[key]() : attrs[key]; + if (value === void 0 && _$hasProp(attrOps, 'default')) { + var def = attrOps.default; + value = _$isFunction(def) ? def() : def; + } + var typ = attrOps.type; + if (typ && !_$isType(value, typ) && attrOps.required) { + return console.error('Attribute \'' + key + '\' must be type \'' + typ + '\'.'); + } + value = _$toType(value, value === void 0 ? 'undefined' : typ, self, key); + if (value !== void 0 && _$hasProp(attrOps, 'validator')) { + var validator = attrOps.validator; + if (_$isFunction(validator) && !validator(value)) { + return console.error('Assigment \'' + key + '\'=\'' + JSON.stringify(value) + '\' invalid.'); + } + } + return value; + } + } + }, + + set: function() { + console.error('\'' + key + '\' is read only.'); + }, + + enumerable: true, + configurable: true + }); + }); + var data = opts.model || {}; + var _loop_1 = function(key) { + if (_$hasProp(data, key)) { + var desc = Object.getOwnPropertyDescriptor(data, key); + if (desc.value && _$isArray(desc.value)) { + desc.value = new _$List(desc.value, self, key); + } else { + if (desc.get) { + var getter_1 = desc.get; + desc.get = function() { + var value = getter_1.call(self); + if (_$isArray(value)) + value = new _$List(value, self, key); + return value; + }; + } + if (desc.set) { + var setter_1 = desc.set; + desc.set = function(v) { + if (_$isArray(v)) + v = new _$List(v, self, key); + setter_1.call(self, v); + }; + } + } + _$def(self, key, desc); + } + }; + for (var key in data) { + _loop_1(key); + } + var tpl = template(self, opts.children); + _$e(tpl, function(value, key) { + _$def(self, key, { + value: function(key) { + var hook = key[1].toUpperCase() + key.slice(2); + var bhook = opts['before' + hook]; + var ahook = opts['after' + hook]; + return function() { + bhook && bhook.call(this); + key.slice(1) === 'update' ? value.call(this, this) : value.apply(this, arguments); + ahook && ahook.call(this); + }; + }(key) + }); + }); + _$def(self, '$data', { + get: function() { + return _$toPlainObj(this); + } + }); +} +function _$isValueAttr(attr) { + return attr === 'value'; +} +function _$subs(dep, listener) { + if (!this[PROP_MAP.s][dep]) { + this[PROP_MAP.s][dep] = []; + } + return this[PROP_MAP.s][dep].push(listener.bind(this)) - 1; +} +function _$def(obj, key, desc) { + Object.defineProperty(obj, key, desc); +} +_$assign(_$CompCtr[PROP_MAP.h], { + $get: function(path) { + return _$accesor(this, path); + }, + + $set: function(path, value) { + _$accesor(this, path, value); + }, + + $on: function(event, handler) { + var _this = this; + if (!this[PROP_MAP.e][event]) { + this[PROP_MAP.e][event] = []; + } + var i = this[PROP_MAP.e][event].push(handler); + return { + $off: function() { + _this[PROP_MAP.e][event].splice(i - 1, 1); + } + }; + }, + + $once: function(event, handler) { + var e = this.$on(event, function(args) { + handler(args); + e.$off(); + }); + }, + + $fire: function(event, data) { + if (this[PROP_MAP.e][event]) { + _$e(this[PROP_MAP.e][event], function(handler) { + handler(data); + }); + } + }, + + $notify: function(key) { + if (this[PROP_MAP.s][key]) { + _$e(this[PROP_MAP.s][key], function(suscriber) { + suscriber(); + }); + } + }, + + $observe: function(deps, listener) { + var _this = this; + var subs = []; + if (_$isArray(deps)) { + _$e(deps, function(dep) { + subs.push({ + sub: dep, + i: _$subs.call(_this, dep, listener) + }); + }); + } else { + subs.push({ + sub: deps, + i: _$subs.call(this, deps, listener) + }); + } + return { + $unobserve: function() { + _$e(subs, function(sub) { + _this[PROP_MAP.s][sub.sub].splice(sub.i, 1); + }); + } + }; + }, + + $watch: function(key, watcher) { + var _this = this; + if (!this[PROP_MAP.w][key]) { + this[PROP_MAP.w][key] = []; + } + var i = this[PROP_MAP.w][key].push(watcher.bind(this)); + return { + $unwatch: function() { + _this[PROP_MAP.w][key].splice(i - 1, 1); + } + }; + } +}); +var array = Array[PROP_MAP.h]; +function _$toArgs(args, start) { + if (start === void 0) { + start = 0; + } + return array.slice.call(args, start); +} +function _$arrayValues(list, value, root, key) { + array.push.apply(list, value.map(function(v, i) { + if (list.length !== 0) + i += list.length; + return !_$isType(v, _$List) && _$isArray(v) ? new _$List(v, root, key + '.' + i) : v; + })); +} +function _$List(value, root, key) { + var self = this; + Array.apply(self, [value.length]); + var desc = { + writable: false, + configurable: false, + enumerable: false + }; + _$def(self, '_key', _$assign({ + value: key + }, desc)); + _$def(self, '_root', _$assign({ + value: root + }, desc)); + _$arrayValues(self, value, root, key); + desc.writable = true; + _$def(self, 'length', _$assign({ + value: self.length + }, desc)); +} +_$extends(_$List, Array); +['pop', 'push', 'reverse', 'shift', 'sort', 'fill', 'unshift', 'splice'].forEach(function(method) { + _$List[PROP_MAP.h][method] = function() { + var self = this; + var old = self.slice(); + var result; + if (method === 'push') { + _$arrayValues(self, _$toArgs(arguments), self._root, self._key); + result = self.length; + } else { + result = array[method].apply(self, arguments); + } + _$dispatch(self._root, self._key, old, self.slice()); + return result; + }; +}); +_$List[PROP_MAP.h].pull = function(index) { + var self = this; + var items = _$toArgs(arguments, 1); + var length = self.length; + if (index > length) { + length = index + 1; + var pull = new Array(index - self.length); + pull.push.apply(pull, items); + for (var i = 0; i < length; i++) { + if (i === index) { + self.push.apply(self, pull); + } + } + } else { + self.splice.apply(self, [index, 1].concat(items)); + } +}; +function _$dispatch(root, key, oldVal, value) { + root.$notify(key); + if (root[PROP_MAP.w][key]) { + _$e(root[PROP_MAP.w][key], function(watcher) { + watcher(oldVal, value); + }); + } + root.$update(); +} +function _$extends(ctor, exts) { + ctor['plugin'] = function(fn, options) { + TPS.push({ + options: options, + fn: fn + }); + }; + ctor[PROP_MAP.h] = Object.create(exts[PROP_MAP.h]); + ctor[PROP_MAP.h].constructor = ctor; +} +function _$isType(value, type) { + return _$type(type) === 'string' ? type.split('|').some(function(t) { + return t.trim() === _$type(value); + }) : value instanceof type; +} +function _$isObject(obj) { + return _$isType(obj, 'object'); +} +function _$isArray(obj) { + return Array.isArray ? Array.isArray(obj) : _$isType(obj, 'array'); +} +function _$isFunction(obj) { + return _$isType(obj, 'function'); +} +function _$isStr(obj) { + return _$isType(obj, 'string'); +} +function _$toType(value, type, root, key) { + switch (type) { + case 'date': + return new Date(value); + case 'string': + return _$toStr(value); + case 'number': + return +value; + case 'boolean': + return _$isStr(value) && !value ? true : !!value; + case 'array': + return _$isType(value, _$List) ? value : new _$List(value, root, key); + default: + return value; + } +} +function _$type(obj) { + return / (\w+)/.exec({}.toString.call(obj))[1].toLowerCase(); +} +function _$hasProp(obj, prop) { + return obj.hasOwnProperty(prop); +} +function _$drt(dd) { + var hasProp = function(prop, instance, options, element) { + return _$isObject(dd) && dd[prop] && dd[prop](instance, options, element); + }; + return { + $init: function(instance, options, element) { + hasProp('$init', instance, options, element); + }, + + $inserted: function(instance, options, element) { + hasProp('$inserted', instance, options, element); + }, + + $update: function(instance, options, element) { + if (_$isFunction(dd)) { + dd(instance, options, element); + } else { + hasProp('$update', instance, options, element); + } + }, + + $destroy: function(instance, options, element) { + hasProp('$destroy', instance, options, element); + } + }; +} +function _$toStr(obj) { + var str = _$type(obj); + return !/null|undefined/.test(str) ? obj.toString() : str; +} +function _$toPlainObj(obj) { + var data = {}; + _$e(_$isObject(obj) ? obj : {}, function(_v, k) { + if (k[0] !== '$' && !_$isFunction(obj[k])) { + if (_$isType(obj[k], _$List)) { + data[k] = obj[k].map(_$toPlainObj); + } else if (_$isObject(obj[k])) { + data[k] = _$toPlainObj(obj[k]); + } else { + data[k] = obj[k]; + } + } + }); + return _$isObject(obj) ? data : obj; +} +function _$accesor(object, path, value) { + return path.split('.').reduce(function(obj, key, i, arr) { + if (_$isType(value, 'undefined')) { + if (obj == null) { + arr.splice(0, arr.length); + return i > 0 && obj === null ? obj : undefined; + } + } else { + if (i === arr.length - 1) { + if (_$isType(obj, _$List) && _$toStr(+key) === key) { + obj.pull(+key, value); + } else { + var oldVal = obj[key]; + obj[key] = !_$isType(value, _$List) && _$isArray(value) ? new _$List(value, object, key) : value; + _$dispatch(object, path, oldVal, obj[key]); + } + } else if (!_$isObject(obj[key])) { + obj[key] = {}; + } + } + return obj ? obj[key] : null; + }, object); +} +function _$bindGroup(input, selection) { + var _value = _$gv(input); + var _$index = selection.indexOf(_value); + input.checked && !~_$index ? selection.push(_value) : selection.splice(_$index, 1); +} +function _$(selector, parent) { + return _$isStr(selector) ? (parent || document).querySelector(selector) : selector; +} +function _$d() { + return document.createDocumentFragment(); +} +function _$a(parent, child, sibling) { + if (_$isType(sibling, 'boolean') && sibling) + parent.parentElement.replaceChild(child, parent); + else if (!sibling) + parent.appendChild(child); + else + parent.insertBefore(child, sibling); +} +function _$ce(tagName) { + return document.createElement(tagName || 'div'); +} +function _$sa(el, attrOrBind) { + var attr = attrOrBind[0], value = attrOrBind[1]; + el.setAttribute(attr, _$toStr(value)); + if (_$isValueAttr(attr) && !_$isStr(value)) + el[PROP_MAP._] = value; +} +function _$ga(el, attr) { + return _$isValueAttr(attr) ? _$gv(el) : el.getAttribute(attr); +} +function _$gv(el) { + return _$hasProp(el, PROP_MAP._) ? el[PROP_MAP._] : el[PROP_MAP.v]; +} +function _$al(el, event, handler) { + el.addEventListener(event, handler, false); +} +function _$rl(el, event, handler) { + el.removeEventListener(event, handler, false); +} +function _$bu(el, binding) { + var attr = binding[0], value = binding[1]; + var _value = attr === 'checked' ? !!value : _$toStr(value); + if (/value|checked/.test(attr)) { + if (el[attr] !== _value) + el[attr] = _$isValueAttr(attr) ? _value : value; + el[PROP_MAP._] = _$isValueAttr(attr) ? value : el[PROP_MAP.v]; + } else if (_$ga(el, attr) !== _value) { + _$sa(el, [attr, _value]); + } +} +function _$e(obj, cb) { + for (var key in obj) { + if (_$hasProp(obj, key)) { + cb(obj[key], isNaN(+key) ? key : +key); + } + } +} +function _$tplBind(_$state) { + var _$frag, input_1, inputEvent_1, handlerInputEvent_1, bindValueInput_1, input_2, changeEvent_1, handlerChangeEvent_1, bindCheckedInput_2, input_3, changeEvent_2, handlerChangeEvent_2, bindCheckedInput_3, input_4, changeEvent_3, handlerChangeEvent_3, bindCheckedInput_4, input_5, changeEvent_4, handlerChangeEvent_4, bindCheckedInput_5, input_6, changeEvent_5, handlerChangeEvent_5, bindCheckedInput_6; + _$frag = _$d(); + inputEvent_1 = function(_$state, $event, $el) { + _$state.$set('textValue', $el.value); + }; + bindValueInput_1 = function(_$state) { + return ['value', _$state.textValue]; + }; + changeEvent_1 = function(_$state, $event, $el) { + _$bindGroup($el, _$state.checkboxes); + }; + bindCheckedInput_2 = function(_$state) { + return ['checked', !!~_$state.checkboxes.indexOf(_$ga(input_2, 'value'))]; + }; + changeEvent_2 = function(_$state, $event, $el) { + _$bindGroup($el, _$state.checkboxes); + }; + bindCheckedInput_3 = function(_$state) { + return ['checked', !!~_$state.checkboxes.indexOf(_$ga(input_3, 'value'))]; + }; + changeEvent_3 = function(_$state, $event, $el) { + _$state.$set('radios', $el.checked ? _$gv($el) : _$state.radios); + }; + bindCheckedInput_4 = function(_$state) { + return ['checked', _$state.radios === _$ga(input_4, 'value')]; + }; + changeEvent_4 = function(_$state, $event, $el) { + _$state.$set('radios', $el.checked ? _$gv($el) : _$state.radios); + }; + bindCheckedInput_5 = function(_$state) { + return ['checked', _$state.radios === _$ga(input_5, 'value')]; + }; + changeEvent_5 = function(_$state, $event, $el) { + _$state.$set('radios', $el.checked ? _$gv($el) : _$state.radios); + }; + bindCheckedInput_6 = function(_$state) { + return ['checked', _$state.radios === _$ga(input_6, 'value')]; + }; + return { + $create: function() { + input_1 = _$ce('input'); + input_2 = _$ce('input'); + input_3 = _$ce('input'); + input_4 = _$ce('input'); + input_5 = _$ce('input'); + input_6 = _$ce('input'); + _$al(input_1, 'input', handlerInputEvent_1 = function(event) { + inputEvent_1(_$state, event, input_1); + }); + input_1.value = _$toStr(bindValueInput_1(_$state)[1]); + _$sa(input_1, ['id', 'text']); + _$sa(input_1, ['type', 'text']); + _$al(input_2, 'change', handlerChangeEvent_1 = function(event) { + changeEvent_1(_$state, event, input_2); + }); + input_2.checked = !!bindCheckedInput_2(_$state)[1]; + _$sa(input_2, ['id', 'checkbox_1']); + _$sa(input_2, ['type', 'checkbox']); + _$sa(input_2, ['value', 'Yes']); + _$al(input_3, 'change', handlerChangeEvent_2 = function(event) { + changeEvent_2(_$state, event, input_3); + }); + input_3.checked = !!bindCheckedInput_3(_$state)[1]; + _$sa(input_3, ['id', 'checkbox_2']); + _$sa(input_3, ['type', 'checkbox']); + _$sa(input_3, ['value', 'No']); + _$al(input_4, 'change', handlerChangeEvent_3 = function(event) { + changeEvent_3(_$state, event, input_4); + }); + input_4.checked = !!bindCheckedInput_4(_$state)[1]; + _$sa(input_4, ['id', 'radio_1']); + _$sa(input_4, ['type', 'radio']); + _$sa(input_4, ['value', 'radio 1']); + _$al(input_5, 'change', handlerChangeEvent_4 = function(event) { + changeEvent_4(_$state, event, input_5); + }); + input_5.checked = !!bindCheckedInput_5(_$state)[1]; + _$sa(input_5, ['id', 'radio_2']); + _$sa(input_5, ['type', 'radio']); + _$sa(input_5, ['value', 'radio 2']); + _$al(input_6, 'change', handlerChangeEvent_5 = function(event) { + changeEvent_5(_$state, event, input_6); + }); + input_6.checked = !!bindCheckedInput_6(_$state)[1]; + _$sa(input_6, ['id', 'radio_3']); + _$sa(input_6, ['type', 'radio']); + _$sa(input_6, ['value', 'radio 3']); + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + this.$siblingEl = _$(sibling); + this.$parentEl = sibling && _$(sibling).parentElement || _$(parent); + }, + + $update: function(_$state) { + _$bu(input_1, bindValueInput_1(_$state)); + _$bu(input_2, bindCheckedInput_2(_$state)); + _$bu(input_3, bindCheckedInput_3(_$state)); + _$bu(input_4, bindCheckedInput_4(_$state)); + _$bu(input_5, bindCheckedInput_5(_$state)); + _$bu(input_6, bindCheckedInput_6(_$state)); + }, + + $unmount: function() { + _$a(_$frag, input_1); + _$a(_$frag, input_2); + _$a(_$frag, input_3); + _$a(_$frag, input_4); + _$a(_$frag, input_5); + _$a(_$frag, input_6); + }, + + $destroy: function() { + this.$unmount(); + this.$parent = null; + this.$parentEl = null; + this.$siblingEl = null; + this.$children.splice(0, this.$children.length); + _$rl(input_1, 'input', handlerInputEvent_1); + _$rl(input_2, 'change', handlerChangeEvent_1); + _$rl(input_3, 'change', handlerChangeEvent_2); + _$rl(input_4, 'change', handlerChangeEvent_3); + _$rl(input_5, 'change', handlerChangeEvent_4); + _$rl(input_6, 'change', handlerChangeEvent_5); + delete _$state.$root; + _$frag = input_1 = inputEvent_1 = handlerInputEvent_1 = bindValueInput_1 = input_2 = changeEvent_1 = handlerChangeEvent_1 = bindCheckedInput_2 = input_3 = changeEvent_2 = handlerChangeEvent_2 = bindCheckedInput_3 = input_4 = changeEvent_3 = handlerChangeEvent_3 = bindCheckedInput_4 = input_5 = changeEvent_4 = handlerChangeEvent_4 = bindCheckedInput_5 = input_6 = changeEvent_5 = handlerChangeEvent_5 = bindCheckedInput_6 = void 0; + } + }; +} +function Bind(_$attrs, _$parent) { + _$CompCtr.call(this, _$attrs, _$tplBind, { + model: { + radios: '', + textValue: '', + checkboxes: [] + } + }, _$parent); + !_$parent && this.$create(); +} +_$extends(Bind, _$CompCtr); +return Bind; + + }); \ No newline at end of file diff --git a/spec/components/condition.umd.js b/spec/components/condition.umd.js new file mode 100644 index 0000000..88a7dfc --- /dev/null +++ b/spec/components/condition.umd.js @@ -0,0 +1,677 @@ +!function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define('condition', factory) : + (global.Condition = factory()); + }(this, function () { + 'use strict'; +var PROP_MAP = { + p: '__TP__', + v: 'value', + _: '_value', + s: '_subscribers', + e: '_events', + w: '_watchers', + h: 'prototype' +}; +var PROPS = ['$slots', '$refs', '$filters', '$directives', '_events', '_watchers']; +var TPS = window[PROP_MAP.p] || (window[PROP_MAP.p] = []); +var _$assign = Object['assign'] || function(t) { + for (var s = void 0, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (_$hasProp(s, p)) + t[p] = s[p]; + } + return t; +}; +function _$CompCtr(attrs, template, options, parent) { + var self = this; + var _$set = function(prop, value) { + _$def(self, prop, { + value: value, + writable: true + }); + }; + if (!attrs) + attrs = {}; + _$e(PROPS, function(prop) { + _$def(self, prop, { + value: {} + }); + }); + _$set('$parent', parent || null); + _$set('$children', []); + _$set(PROP_MAP.s, {}); + _$set('$options', options); + var opts = self.$options; + if (!opts.attrs) + opts.attrs = {}; + if (!opts.children) + opts.children = {}; + _$e(TPS, function(plugin) { + plugin.fn.call(self, _$CompCtr, plugin.options); + }); + if (opts.filters) + _$assign(self.$filters, opts.filters); + if (opts.directives) _$e(opts.directives, function(drt, k) { + self.$directives[k] = _$drt(drt); + }); + _$e(opts.attrs, function(attrOps, key) { + _$def(self, _$isType(key, 'number') ? attrOps : key, { + get: function() { + if (_$isStr(attrOps)) { + var value = attrs[attrOps]; + return _$isFunction(value) ? value() : value; + } else { + if (!_$hasProp(attrs, key) && attrOps.required) { + return console.error('Attribute \'' + key + '\' is required.'); + } else { + var value = _$isFunction(attrs[key]) ? attrs[key]() : attrs[key]; + if (value === void 0 && _$hasProp(attrOps, 'default')) { + var def = attrOps.default; + value = _$isFunction(def) ? def() : def; + } + var typ = attrOps.type; + if (typ && !_$isType(value, typ) && attrOps.required) { + return console.error('Attribute \'' + key + '\' must be type \'' + typ + '\'.'); + } + value = _$toType(value, value === void 0 ? 'undefined' : typ, self, key); + if (value !== void 0 && _$hasProp(attrOps, 'validator')) { + var validator = attrOps.validator; + if (_$isFunction(validator) && !validator(value)) { + return console.error('Assigment \'' + key + '\'=\'' + JSON.stringify(value) + '\' invalid.'); + } + } + return value; + } + } + }, + + set: function() { + console.error('\'' + key + '\' is read only.'); + }, + + enumerable: true, + configurable: true + }); + }); + var data = opts.model || {}; + var _loop_1 = function(key) { + if (_$hasProp(data, key)) { + var desc = Object.getOwnPropertyDescriptor(data, key); + if (desc.value && _$isArray(desc.value)) { + desc.value = new _$List(desc.value, self, key); + } else { + if (desc.get) { + var getter_1 = desc.get; + desc.get = function() { + var value = getter_1.call(self); + if (_$isArray(value)) + value = new _$List(value, self, key); + return value; + }; + } + if (desc.set) { + var setter_1 = desc.set; + desc.set = function(v) { + if (_$isArray(v)) + v = new _$List(v, self, key); + setter_1.call(self, v); + }; + } + } + _$def(self, key, desc); + } + }; + for (var key in data) { + _loop_1(key); + } + var tpl = template(self, opts.children); + _$e(tpl, function(value, key) { + _$def(self, key, { + value: function(key) { + var hook = key[1].toUpperCase() + key.slice(2); + var bhook = opts['before' + hook]; + var ahook = opts['after' + hook]; + return function() { + bhook && bhook.call(this); + key.slice(1) === 'update' ? value.call(this, this) : value.apply(this, arguments); + ahook && ahook.call(this); + }; + }(key) + }); + }); + _$def(self, '$data', { + get: function() { + return _$toPlainObj(this); + } + }); +} +function _$subs(dep, listener) { + if (!this[PROP_MAP.s][dep]) { + this[PROP_MAP.s][dep] = []; + } + return this[PROP_MAP.s][dep].push(listener.bind(this)) - 1; +} +function _$def(obj, key, desc) { + Object.defineProperty(obj, key, desc); +} +_$assign(_$CompCtr[PROP_MAP.h], { + $get: function(path) { + return _$accesor(this, path); + }, + + $set: function(path, value) { + _$accesor(this, path, value); + }, + + $on: function(event, handler) { + var _this = this; + if (!this[PROP_MAP.e][event]) { + this[PROP_MAP.e][event] = []; + } + var i = this[PROP_MAP.e][event].push(handler); + return { + $off: function() { + _this[PROP_MAP.e][event].splice(i - 1, 1); + } + }; + }, + + $once: function(event, handler) { + var e = this.$on(event, function(args) { + handler(args); + e.$off(); + }); + }, + + $fire: function(event, data) { + if (this[PROP_MAP.e][event]) { + _$e(this[PROP_MAP.e][event], function(handler) { + handler(data); + }); + } + }, + + $notify: function(key) { + if (this[PROP_MAP.s][key]) { + _$e(this[PROP_MAP.s][key], function(suscriber) { + suscriber(); + }); + } + }, + + $observe: function(deps, listener) { + var _this = this; + var subs = []; + if (_$isArray(deps)) { + _$e(deps, function(dep) { + subs.push({ + sub: dep, + i: _$subs.call(_this, dep, listener) + }); + }); + } else { + subs.push({ + sub: deps, + i: _$subs.call(this, deps, listener) + }); + } + return { + $unobserve: function() { + _$e(subs, function(sub) { + _this[PROP_MAP.s][sub.sub].splice(sub.i, 1); + }); + } + }; + }, + + $watch: function(key, watcher) { + var _this = this; + if (!this[PROP_MAP.w][key]) { + this[PROP_MAP.w][key] = []; + } + var i = this[PROP_MAP.w][key].push(watcher.bind(this)); + return { + $unwatch: function() { + _this[PROP_MAP.w][key].splice(i - 1, 1); + } + }; + } +}); +var array = Array[PROP_MAP.h]; +function _$toArgs(args, start) { + if (start === void 0) { + start = 0; + } + return array.slice.call(args, start); +} +function _$arrayValues(list, value, root, key) { + array.push.apply(list, value.map(function(v, i) { + if (list.length !== 0) + i += list.length; + return !_$isType(v, _$List) && _$isArray(v) ? new _$List(v, root, key + '.' + i) : v; + })); +} +function _$List(value, root, key) { + var self = this; + Array.apply(self, [value.length]); + var desc = { + writable: false, + configurable: false, + enumerable: false + }; + _$def(self, '_key', _$assign({ + value: key + }, desc)); + _$def(self, '_root', _$assign({ + value: root + }, desc)); + _$arrayValues(self, value, root, key); + desc.writable = true; + _$def(self, 'length', _$assign({ + value: self.length + }, desc)); +} +_$extends(_$List, Array); +['pop', 'push', 'reverse', 'shift', 'sort', 'fill', 'unshift', 'splice'].forEach(function(method) { + _$List[PROP_MAP.h][method] = function() { + var self = this; + var old = self.slice(); + var result; + if (method === 'push') { + _$arrayValues(self, _$toArgs(arguments), self._root, self._key); + result = self.length; + } else { + result = array[method].apply(self, arguments); + } + _$dispatch(self._root, self._key, old, self.slice()); + return result; + }; +}); +_$List[PROP_MAP.h].pull = function(index) { + var self = this; + var items = _$toArgs(arguments, 1); + var length = self.length; + if (index > length) { + length = index + 1; + var pull = new Array(index - self.length); + pull.push.apply(pull, items); + for (var i = 0; i < length; i++) { + if (i === index) { + self.push.apply(self, pull); + } + } + } else { + self.splice.apply(self, [index, 1].concat(items)); + } +}; +function _$dispatch(root, key, oldVal, value) { + root.$notify(key); + if (root[PROP_MAP.w][key]) { + _$e(root[PROP_MAP.w][key], function(watcher) { + watcher(oldVal, value); + }); + } + root.$update(); +} +function _$extends(ctor, exts) { + ctor['plugin'] = function(fn, options) { + TPS.push({ + options: options, + fn: fn + }); + }; + ctor[PROP_MAP.h] = Object.create(exts[PROP_MAP.h]); + ctor[PROP_MAP.h].constructor = ctor; +} +function _$isType(value, type) { + return _$type(type) === 'string' ? type.split('|').some(function(t) { + return t.trim() === _$type(value); + }) : value instanceof type; +} +function _$isObject(obj) { + return _$isType(obj, 'object'); +} +function _$isArray(obj) { + return Array.isArray ? Array.isArray(obj) : _$isType(obj, 'array'); +} +function _$isFunction(obj) { + return _$isType(obj, 'function'); +} +function _$isStr(obj) { + return _$isType(obj, 'string'); +} +function _$toType(value, type, root, key) { + switch (type) { + case 'date': + return new Date(value); + case 'string': + return _$toStr(value); + case 'number': + return +value; + case 'boolean': + return _$isStr(value) && !value ? true : !!value; + case 'array': + return _$isType(value, _$List) ? value : new _$List(value, root, key); + default: + return value; + } +} +function _$type(obj) { + return / (\w+)/.exec({}.toString.call(obj))[1].toLowerCase(); +} +function _$hasProp(obj, prop) { + return obj.hasOwnProperty(prop); +} +function _$drt(dd) { + var hasProp = function(prop, instance, options, element) { + return _$isObject(dd) && dd[prop] && dd[prop](instance, options, element); + }; + return { + $init: function(instance, options, element) { + hasProp('$init', instance, options, element); + }, + + $inserted: function(instance, options, element) { + hasProp('$inserted', instance, options, element); + }, + + $update: function(instance, options, element) { + if (_$isFunction(dd)) { + dd(instance, options, element); + } else { + hasProp('$update', instance, options, element); + } + }, + + $destroy: function(instance, options, element) { + hasProp('$destroy', instance, options, element); + } + }; +} +function _$noop() {} +function _$toStr(obj) { + var str = _$type(obj); + return !/null|undefined/.test(str) ? obj.toString() : str; +} +function _$toPlainObj(obj) { + var data = {}; + _$e(_$isObject(obj) ? obj : {}, function(_v, k) { + if (k[0] !== '$' && !_$isFunction(obj[k])) { + if (_$isType(obj[k], _$List)) { + data[k] = obj[k].map(_$toPlainObj); + } else if (_$isObject(obj[k])) { + data[k] = _$toPlainObj(obj[k]); + } else { + data[k] = obj[k]; + } + } + }); + return _$isObject(obj) ? data : obj; +} +function _$accesor(object, path, value) { + return path.split('.').reduce(function(obj, key, i, arr) { + if (_$isType(value, 'undefined')) { + if (obj == null) { + arr.splice(0, arr.length); + return i > 0 && obj === null ? obj : undefined; + } + } else { + if (i === arr.length - 1) { + if (_$isType(obj, _$List) && _$toStr(+key) === key) { + obj.pull(+key, value); + } else { + var oldVal = obj[key]; + obj[key] = !_$isType(value, _$List) && _$isArray(value) ? new _$List(value, object, key) : value; + _$dispatch(object, path, oldVal, obj[key]); + } + } else if (!_$isObject(obj[key])) { + obj[key] = {}; + } + } + return obj ? obj[key] : null; + }, object); +} +function _$emptyElse() { + return { + type: 'empty-else', + $create: _$noop, + $mount: _$noop, + $update: _$noop, + $destroy: _$noop + }; +} +function _$(selector, parent) { + return _$isStr(selector) ? (parent || document).querySelector(selector) : selector; +} +function _$d() { + return document.createDocumentFragment(); +} +function _$a(parent, child, sibling) { + if (_$isType(sibling, 'boolean') && sibling) + parent.parentElement.replaceChild(child, parent); + else if (!sibling) + parent.appendChild(child); + else + parent.insertBefore(child, sibling); +} +function _$ce(tagName) { + return document.createElement(tagName || 'div'); +} +function _$ct(content) { + return document.createTextNode(content || ''); +} +function _$cu(block, condition, inst, parent, anchor) { + if (block && block.type === condition(inst).type) { + block.$update(inst); + } else { + block && block.$destroy(); + block = condition(inst); + block.$create(); + block.$mount(parent, anchor); + } + return block; +} +function _$e(obj, cb) { + for (var key in obj) { + if (_$hasProp(obj, key)) { + cb(obj[key], isNaN(+key) ? key : +key); + } + } +} +function ifCondition_1() { + var _$frag, span_1; + _$frag = _$d(); + return { + type: 'if', + + $create: function() { + span_1 = _$ce('span'); + span_1.innerHTML = '1'; + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + }, + + $update: _$noop, + + $unmount: function() { + _$a(_$frag, span_1); + }, + + $destroy: function() { + this.$unmount(); + _$frag = span_1 = void 0; + } + }; +} +function elseIf_1_condition_1() { + var _$frag, span_1; + _$frag = _$d(); + return { + type: 'elseIf_1', + + $create: function() { + span_1 = _$ce('span'); + span_1.innerHTML = '2'; + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + }, + + $update: _$noop, + + $unmount: function() { + _$a(_$frag, span_1); + }, + + $destroy: function() { + this.$unmount(); + _$frag = span_1 = void 0; + } + }; +} +function elseCondition_1() { + var _$frag, span_1; + _$frag = _$d(); + return { + type: 'else', + + $create: function() { + span_1 = _$ce('span'); + span_1.innerHTML = 'other'; + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + }, + + $update: _$noop, + + $unmount: function() { + _$a(_$frag, span_1); + }, + + $destroy: function() { + this.$unmount(); + _$frag = span_1 = void 0; + } + }; +} +function condition_1(_$state) { + if (_$state.condition === 1) + return ifCondition_1(_$state); + else if (_$state.condition === 2) + return elseIf_1_condition_1(_$state); + else + return elseCondition_1(_$state); +} +function ifCondition_2() { + var _$frag, div_1; + _$frag = _$d(); + return { + type: 'if', + + $create: function() { + div_1 = _$ce(); + div_1.innerHTML = '1'; + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + }, + + $update: _$noop, + + $unmount: function() { + _$a(_$frag, div_1); + }, + + $destroy: function() { + this.$unmount(); + _$frag = div_1 = void 0; + } + }; +} +function condition_2(_$state) { + if (_$state.condition_1 === 1) + return ifCondition_2(_$state); + else + return _$emptyElse(); +} +function _$tplCondition(_$state) { + var _$frag, conditionAnchor_1, conditionBlock_1, conditionAnchor_2, conditionBlock_2; + _$frag = _$d(); + conditionAnchor_1 = _$ct(); + conditionAnchor_2 = _$ct(); + return { + $create: function() { + conditionBlock_1 = condition_1(_$state); + conditionBlock_1.$create(); + conditionBlock_2 = condition_2(_$state); + conditionBlock_2.$create(); + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + this.$siblingEl = _$(sibling); + this.$parentEl = sibling && _$(sibling).parentElement || _$(parent); + }, + + $update: function(_$state) { + conditionBlock_1 = _$cu( + conditionBlock_1, + condition_1, + _$state, + _$state.$parentEl, + conditionAnchor_1 + ); + conditionBlock_2 = _$cu( + conditionBlock_2, + condition_2, + _$state, + _$state.$parentEl, + conditionAnchor_2 + ); + }, + + $unmount: function() { + _$a(_$frag, conditionAnchor_1); + conditionBlock_1.$mount(_$frag, conditionAnchor_1); + _$a(_$frag, conditionAnchor_2); + conditionBlock_2.$mount(_$frag, conditionAnchor_2); + }, + + $destroy: function() { + this.$unmount(); + this.$parent = null; + this.$parentEl = null; + this.$siblingEl = null; + this.$children.splice(0, this.$children.length); + conditionBlock_1.$destroy(); + conditionBlock_2.$destroy(); + delete _$state.$root; + _$frag = conditionAnchor_1 = conditionBlock_1 = conditionAnchor_2 = conditionBlock_2 = void 0; + } + }; +} +function Condition(_$attrs, _$parent) { + _$CompCtr.call(this, _$attrs, _$tplCondition, { + model: { + condition: 1, + condition_1: 1 + } + }, _$parent); + !_$parent && this.$create(); +} +_$extends(Condition, _$CompCtr); +return Condition; + + }); \ No newline at end of file diff --git a/spec/components/html.umd.js b/spec/components/html.umd.js new file mode 100644 index 0000000..b6d1885 --- /dev/null +++ b/spec/components/html.umd.js @@ -0,0 +1,580 @@ +!function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define('html', factory) : + (global.Html = factory()); + }(this, function () { + 'use strict'; +var PROP_MAP = { + p: '__TP__', + v: 'value', + _: '_value', + s: '_subscribers', + e: '_events', + w: '_watchers', + h: 'prototype' +}; +var PROPS = ['$slots', '$refs', '$filters', '$directives', '_events', '_watchers']; +var TPS = window[PROP_MAP.p] || (window[PROP_MAP.p] = []); +var _$assign = Object['assign'] || function(t) { + for (var s = void 0, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (_$hasProp(s, p)) + t[p] = s[p]; + } + return t; +}; +function _$CompCtr(attrs, template, options, parent) { + var self = this; + var _$set = function(prop, value) { + _$def(self, prop, { + value: value, + writable: true + }); + }; + if (!attrs) + attrs = {}; + _$e(PROPS, function(prop) { + _$def(self, prop, { + value: {} + }); + }); + _$set('$parent', parent || null); + _$set('$children', []); + _$set(PROP_MAP.s, {}); + _$set('$options', options); + var opts = self.$options; + if (!opts.attrs) + opts.attrs = {}; + if (!opts.children) + opts.children = {}; + _$e(TPS, function(plugin) { + plugin.fn.call(self, _$CompCtr, plugin.options); + }); + if (opts.filters) + _$assign(self.$filters, opts.filters); + if (opts.directives) _$e(opts.directives, function(drt, k) { + self.$directives[k] = _$drt(drt); + }); + _$e(opts.attrs, function(attrOps, key) { + _$def(self, _$isType(key, 'number') ? attrOps : key, { + get: function() { + if (_$isStr(attrOps)) { + var value = attrs[attrOps]; + return _$isFunction(value) ? value() : value; + } else { + if (!_$hasProp(attrs, key) && attrOps.required) { + return console.error('Attribute \'' + key + '\' is required.'); + } else { + var value = _$isFunction(attrs[key]) ? attrs[key]() : attrs[key]; + if (value === void 0 && _$hasProp(attrOps, 'default')) { + var def = attrOps.default; + value = _$isFunction(def) ? def() : def; + } + var typ = attrOps.type; + if (typ && !_$isType(value, typ) && attrOps.required) { + return console.error('Attribute \'' + key + '\' must be type \'' + typ + '\'.'); + } + value = _$toType(value, value === void 0 ? 'undefined' : typ, self, key); + if (value !== void 0 && _$hasProp(attrOps, 'validator')) { + var validator = attrOps.validator; + if (_$isFunction(validator) && !validator(value)) { + return console.error('Assigment \'' + key + '\'=\'' + JSON.stringify(value) + '\' invalid.'); + } + } + return value; + } + } + }, + + set: function() { + console.error('\'' + key + '\' is read only.'); + }, + + enumerable: true, + configurable: true + }); + }); + var data = opts.model || {}; + var _loop_1 = function(key) { + if (_$hasProp(data, key)) { + var desc = Object.getOwnPropertyDescriptor(data, key); + if (desc.value && _$isArray(desc.value)) { + desc.value = new _$List(desc.value, self, key); + } else { + if (desc.get) { + var getter_1 = desc.get; + desc.get = function() { + var value = getter_1.call(self); + if (_$isArray(value)) + value = new _$List(value, self, key); + return value; + }; + } + if (desc.set) { + var setter_1 = desc.set; + desc.set = function(v) { + if (_$isArray(v)) + v = new _$List(v, self, key); + setter_1.call(self, v); + }; + } + } + _$def(self, key, desc); + } + }; + for (var key in data) { + _loop_1(key); + } + var tpl = template(self, opts.children); + _$e(tpl, function(value, key) { + _$def(self, key, { + value: function(key) { + var hook = key[1].toUpperCase() + key.slice(2); + var bhook = opts['before' + hook]; + var ahook = opts['after' + hook]; + return function() { + bhook && bhook.call(this); + key.slice(1) === 'update' ? value.call(this, this) : value.apply(this, arguments); + ahook && ahook.call(this); + }; + }(key) + }); + }); + _$def(self, '$data', { + get: function() { + return _$toPlainObj(this); + } + }); +} +function _$isValueAttr(attr) { + return attr === 'value'; +} +function _$subs(dep, listener) { + if (!this[PROP_MAP.s][dep]) { + this[PROP_MAP.s][dep] = []; + } + return this[PROP_MAP.s][dep].push(listener.bind(this)) - 1; +} +function _$def(obj, key, desc) { + Object.defineProperty(obj, key, desc); +} +_$assign(_$CompCtr[PROP_MAP.h], { + $get: function(path) { + return _$accesor(this, path); + }, + + $set: function(path, value) { + _$accesor(this, path, value); + }, + + $on: function(event, handler) { + var _this = this; + if (!this[PROP_MAP.e][event]) { + this[PROP_MAP.e][event] = []; + } + var i = this[PROP_MAP.e][event].push(handler); + return { + $off: function() { + _this[PROP_MAP.e][event].splice(i - 1, 1); + } + }; + }, + + $once: function(event, handler) { + var e = this.$on(event, function(args) { + handler(args); + e.$off(); + }); + }, + + $fire: function(event, data) { + if (this[PROP_MAP.e][event]) { + _$e(this[PROP_MAP.e][event], function(handler) { + handler(data); + }); + } + }, + + $notify: function(key) { + if (this[PROP_MAP.s][key]) { + _$e(this[PROP_MAP.s][key], function(suscriber) { + suscriber(); + }); + } + }, + + $observe: function(deps, listener) { + var _this = this; + var subs = []; + if (_$isArray(deps)) { + _$e(deps, function(dep) { + subs.push({ + sub: dep, + i: _$subs.call(_this, dep, listener) + }); + }); + } else { + subs.push({ + sub: deps, + i: _$subs.call(this, deps, listener) + }); + } + return { + $unobserve: function() { + _$e(subs, function(sub) { + _this[PROP_MAP.s][sub.sub].splice(sub.i, 1); + }); + } + }; + }, + + $watch: function(key, watcher) { + var _this = this; + if (!this[PROP_MAP.w][key]) { + this[PROP_MAP.w][key] = []; + } + var i = this[PROP_MAP.w][key].push(watcher.bind(this)); + return { + $unwatch: function() { + _this[PROP_MAP.w][key].splice(i - 1, 1); + } + }; + } +}); +var array = Array[PROP_MAP.h]; +function _$toArgs(args, start) { + if (start === void 0) { + start = 0; + } + return array.slice.call(args, start); +} +function _$arrayValues(list, value, root, key) { + array.push.apply(list, value.map(function(v, i) { + if (list.length !== 0) + i += list.length; + return !_$isType(v, _$List) && _$isArray(v) ? new _$List(v, root, key + '.' + i) : v; + })); +} +function _$List(value, root, key) { + var self = this; + Array.apply(self, [value.length]); + var desc = { + writable: false, + configurable: false, + enumerable: false + }; + _$def(self, '_key', _$assign({ + value: key + }, desc)); + _$def(self, '_root', _$assign({ + value: root + }, desc)); + _$arrayValues(self, value, root, key); + desc.writable = true; + _$def(self, 'length', _$assign({ + value: self.length + }, desc)); +} +_$extends(_$List, Array); +['pop', 'push', 'reverse', 'shift', 'sort', 'fill', 'unshift', 'splice'].forEach(function(method) { + _$List[PROP_MAP.h][method] = function() { + var self = this; + var old = self.slice(); + var result; + if (method === 'push') { + _$arrayValues(self, _$toArgs(arguments), self._root, self._key); + result = self.length; + } else { + result = array[method].apply(self, arguments); + } + _$dispatch(self._root, self._key, old, self.slice()); + return result; + }; +}); +_$List[PROP_MAP.h].pull = function(index) { + var self = this; + var items = _$toArgs(arguments, 1); + var length = self.length; + if (index > length) { + length = index + 1; + var pull = new Array(index - self.length); + pull.push.apply(pull, items); + for (var i = 0; i < length; i++) { + if (i === index) { + self.push.apply(self, pull); + } + } + } else { + self.splice.apply(self, [index, 1].concat(items)); + } +}; +function _$dispatch(root, key, oldVal, value) { + root.$notify(key); + if (root[PROP_MAP.w][key]) { + _$e(root[PROP_MAP.w][key], function(watcher) { + watcher(oldVal, value); + }); + } + root.$update(); +} +function _$extends(ctor, exts) { + ctor['plugin'] = function(fn, options) { + TPS.push({ + options: options, + fn: fn + }); + }; + ctor[PROP_MAP.h] = Object.create(exts[PROP_MAP.h]); + ctor[PROP_MAP.h].constructor = ctor; +} +function _$isType(value, type) { + return _$type(type) === 'string' ? type.split('|').some(function(t) { + return t.trim() === _$type(value); + }) : value instanceof type; +} +function _$isObject(obj) { + return _$isType(obj, 'object'); +} +function _$isArray(obj) { + return Array.isArray ? Array.isArray(obj) : _$isType(obj, 'array'); +} +function _$isFunction(obj) { + return _$isType(obj, 'function'); +} +function _$isStr(obj) { + return _$isType(obj, 'string'); +} +function _$toType(value, type, root, key) { + switch (type) { + case 'date': + return new Date(value); + case 'string': + return _$toStr(value); + case 'number': + return +value; + case 'boolean': + return _$isStr(value) && !value ? true : !!value; + case 'array': + return _$isType(value, _$List) ? value : new _$List(value, root, key); + default: + return value; + } +} +function _$type(obj) { + return / (\w+)/.exec({}.toString.call(obj))[1].toLowerCase(); +} +function _$hasProp(obj, prop) { + return obj.hasOwnProperty(prop); +} +function _$drt(dd) { + var hasProp = function(prop, instance, options, element) { + return _$isObject(dd) && dd[prop] && dd[prop](instance, options, element); + }; + return { + $init: function(instance, options, element) { + hasProp('$init', instance, options, element); + }, + + $inserted: function(instance, options, element) { + hasProp('$inserted', instance, options, element); + }, + + $update: function(instance, options, element) { + if (_$isFunction(dd)) { + dd(instance, options, element); + } else { + hasProp('$update', instance, options, element); + } + }, + + $destroy: function(instance, options, element) { + hasProp('$destroy', instance, options, element); + } + }; +} +function _$toStr(obj) { + var str = _$type(obj); + return !/null|undefined/.test(str) ? obj.toString() : str; +} +function _$toPlainObj(obj) { + var data = {}; + _$e(_$isObject(obj) ? obj : {}, function(_v, k) { + if (k[0] !== '$' && !_$isFunction(obj[k])) { + if (_$isType(obj[k], _$List)) { + data[k] = obj[k].map(_$toPlainObj); + } else if (_$isObject(obj[k])) { + data[k] = _$toPlainObj(obj[k]); + } else { + data[k] = obj[k]; + } + } + }); + return _$isObject(obj) ? data : obj; +} +function _$setRef(obj, prop) { + var value = []; + _$def(obj, prop, { + get: function() { + return value.length <= 1 ? value[0] : value; + }, + + set: function(val) { + val && !~value.indexOf(val) && value.push(val); + }, + + enumerable: true, + configurable: true + }); +} +function _$accesor(object, path, value) { + return path.split('.').reduce(function(obj, key, i, arr) { + if (_$isType(value, 'undefined')) { + if (obj == null) { + arr.splice(0, arr.length); + return i > 0 && obj === null ? obj : undefined; + } + } else { + if (i === arr.length - 1) { + if (_$isType(obj, _$List) && _$toStr(+key) === key) { + obj.pull(+key, value); + } else { + var oldVal = obj[key]; + obj[key] = !_$isType(value, _$List) && _$isArray(value) ? new _$List(value, object, key) : value; + _$dispatch(object, path, oldVal, obj[key]); + } + } else if (!_$isObject(obj[key])) { + obj[key] = {}; + } + } + return obj ? obj[key] : null; + }, object); +} +function _$(selector, parent) { + return _$isStr(selector) ? (parent || document).querySelector(selector) : selector; +} +function _$d() { + return document.createDocumentFragment(); +} +function _$a(parent, child, sibling) { + if (_$isType(sibling, 'boolean') && sibling) + parent.parentElement.replaceChild(child, parent); + else if (!sibling) + parent.appendChild(child); + else + parent.insertBefore(child, sibling); +} +function _$ce(tagName) { + return document.createElement(tagName || 'div'); +} +function _$ct(content) { + return document.createTextNode(content || ''); +} +function _$sa(el, attrOrBind) { + var attr = attrOrBind[0], value = attrOrBind[1]; + el.setAttribute(attr, _$toStr(value)); + if (_$isValueAttr(attr) && !_$isStr(value)) + el[PROP_MAP._] = value; +} +function _$tu(text, value) { + if (text.data !== (value = _$toStr(value))) + text.data = value; +} +function _$e(obj, cb) { + for (var key in obj) { + if (_$hasProp(obj, key)) { + cb(obj[key], isNaN(+key) ? key : +key); + } + } +} +function _$tplHtml(_$state) { + var _$frag, div_1, div_2, p_1, txt_1, setTxt_1, div_3, p_2, txt_2, setTxt_2, _refs, div_4, div_5, contentDiv_5_1; + _$frag = _$d(); + setTxt_1 = function(_$state) { + return 'Some paragraph with text ' + _$state.expression; + }; + setTxt_2 = function(_$state) { + return 'Some paragraph with ' + _$state.text + ' and ' + _$state.attribute + ' expressions'; + }; + _refs = _$state.$refs; + contentDiv_5_1 = function(_$state) { + return _$state.html; + }; + return { + $create: function() { + div_1 = _$ce(); + div_1.innerHTML = '

Here\'s a very interesting note displayed in a lovely shadowed box.

Any kind of content here. Such as <p>, <table>. You name it!

'; + div_2 = _$ce(); + p_1 = _$ce('p'); + txt_1 = _$ct(); + txt_1.data = setTxt_1(_$state); + div_3 = _$ce(); + p_2 = _$ce('p'); + txt_2 = _$ct(); + txt_2.data = setTxt_2(_$state); + !_refs['someAttr'] && _$setRef(_refs, 'someAttr'); + _refs['someAttr'] = p_2; + div_4 = _$ce(); + div_4.innerHTML = '

Some paragraph with text intentional {{escaped}}

'; + div_5 = _$ce(); + div_5.innerHTML = contentDiv_5_1(_$state); + _$sa(div_1, ['class', 'shadowbox']); + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + this.$siblingEl = _$(sibling); + this.$parentEl = sibling && _$(sibling).parentElement || _$(parent); + }, + + $update: function(_$state) { + _$tu(txt_1, setTxt_1(_$state)); + _$tu(txt_2, setTxt_2(_$state)); + var updateContentDiv_5_1 = contentDiv_5_1(_$state); + if (div_5.innerHTML !== updateContentDiv_5_1) { + div_5.innerHTML = updateContentDiv_5_1; + } + updateContentDiv_5_1 = void 0; + }, + + $unmount: function() { + _$a(_$frag, div_1); + _$a(p_1, txt_1); + _$a(div_2, p_1); + _$a(_$frag, div_2); + _$a(p_2, txt_2); + _$a(div_3, p_2); + _$a(_$frag, div_3); + _$a(_$frag, div_4); + _$a(_$frag, div_5); + }, + + $destroy: function() { + this.$unmount(); + this.$parent = null; + this.$parentEl = null; + this.$siblingEl = null; + this.$children.splice(0, this.$children.length); + if (_$isType(_refs['someAttr'], 'array')) { + var indexP_2 = _refs['someAttr'].indexOf(p_2); + _refs['someAttr'].splice(indexP_2, 1); + } else { + delete _refs['someAttr']; + } + delete _$state.$root; + _$frag = div_1 = div_2 = p_1 = txt_1 = setTxt_1 = div_3 = p_2 = txt_2 = setTxt_2 = _refs = div_4 = div_5 = contentDiv_5_1 = void 0; + } + }; +} +function Html(_$attrs, _$parent) { + _$CompCtr.call(this, _$attrs, _$tplHtml, { + model: { + html: '

Some paragraph with text from {{model}}

' + } + }, _$parent); + !_$parent && this.$create(); +} +_$extends(Html, _$CompCtr); +return Html; + + }); \ No newline at end of file diff --git a/spec/components/init.umd.js b/spec/components/init.umd.js new file mode 100644 index 0000000..5f2fcad --- /dev/null +++ b/spec/components/init.umd.js @@ -0,0 +1,516 @@ +!function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define('init', factory) : + (global.Init = factory()); + }(this, function () { + 'use strict'; +var PROP_MAP = { + p: '__TP__', + v: 'value', + _: '_value', + s: '_subscribers', + e: '_events', + w: '_watchers', + h: 'prototype' +}; +var PROPS = ['$slots', '$refs', '$filters', '$directives', '_events', '_watchers']; +var TPS = window[PROP_MAP.p] || (window[PROP_MAP.p] = []); +var _$assign = Object['assign'] || function(t) { + for (var s = void 0, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (_$hasProp(s, p)) + t[p] = s[p]; + } + return t; +}; +function _$CompCtr(attrs, template, options, parent) { + var self = this; + var _$set = function(prop, value) { + _$def(self, prop, { + value: value, + writable: true + }); + }; + if (!attrs) + attrs = {}; + _$e(PROPS, function(prop) { + _$def(self, prop, { + value: {} + }); + }); + _$set('$parent', parent || null); + _$set('$children', []); + _$set(PROP_MAP.s, {}); + _$set('$options', options); + var opts = self.$options; + if (!opts.attrs) + opts.attrs = {}; + if (!opts.children) + opts.children = {}; + _$e(TPS, function(plugin) { + plugin.fn.call(self, _$CompCtr, plugin.options); + }); + if (opts.filters) + _$assign(self.$filters, opts.filters); + if (opts.directives) _$e(opts.directives, function(drt, k) { + self.$directives[k] = _$drt(drt); + }); + _$e(opts.attrs, function(attrOps, key) { + _$def(self, _$isType(key, 'number') ? attrOps : key, { + get: function() { + if (_$isStr(attrOps)) { + var value = attrs[attrOps]; + return _$isFunction(value) ? value() : value; + } else { + if (!_$hasProp(attrs, key) && attrOps.required) { + return console.error('Attribute \'' + key + '\' is required.'); + } else { + var value = _$isFunction(attrs[key]) ? attrs[key]() : attrs[key]; + if (value === void 0 && _$hasProp(attrOps, 'default')) { + var def = attrOps.default; + value = _$isFunction(def) ? def() : def; + } + var typ = attrOps.type; + if (typ && !_$isType(value, typ) && attrOps.required) { + return console.error('Attribute \'' + key + '\' must be type \'' + typ + '\'.'); + } + value = _$toType(value, value === void 0 ? 'undefined' : typ, self, key); + if (value !== void 0 && _$hasProp(attrOps, 'validator')) { + var validator = attrOps.validator; + if (_$isFunction(validator) && !validator(value)) { + return console.error('Assigment \'' + key + '\'=\'' + JSON.stringify(value) + '\' invalid.'); + } + } + return value; + } + } + }, + + set: function() { + console.error('\'' + key + '\' is read only.'); + }, + + enumerable: true, + configurable: true + }); + }); + var data = opts.model || {}; + var _loop_1 = function(key) { + if (_$hasProp(data, key)) { + var desc = Object.getOwnPropertyDescriptor(data, key); + if (desc.value && _$isArray(desc.value)) { + desc.value = new _$List(desc.value, self, key); + } else { + if (desc.get) { + var getter_1 = desc.get; + desc.get = function() { + var value = getter_1.call(self); + if (_$isArray(value)) + value = new _$List(value, self, key); + return value; + }; + } + if (desc.set) { + var setter_1 = desc.set; + desc.set = function(v) { + if (_$isArray(v)) + v = new _$List(v, self, key); + setter_1.call(self, v); + }; + } + } + _$def(self, key, desc); + } + }; + for (var key in data) { + _loop_1(key); + } + var tpl = template(self, opts.children); + _$e(tpl, function(value, key) { + _$def(self, key, { + value: function(key) { + var hook = key[1].toUpperCase() + key.slice(2); + var bhook = opts['before' + hook]; + var ahook = opts['after' + hook]; + return function() { + bhook && bhook.call(this); + key.slice(1) === 'update' ? value.call(this, this) : value.apply(this, arguments); + ahook && ahook.call(this); + }; + }(key) + }); + }); + _$def(self, '$data', { + get: function() { + return _$toPlainObj(this); + } + }); +} +function _$subs(dep, listener) { + if (!this[PROP_MAP.s][dep]) { + this[PROP_MAP.s][dep] = []; + } + return this[PROP_MAP.s][dep].push(listener.bind(this)) - 1; +} +function _$def(obj, key, desc) { + Object.defineProperty(obj, key, desc); +} +_$assign(_$CompCtr[PROP_MAP.h], { + $get: function(path) { + return _$accesor(this, path); + }, + + $set: function(path, value) { + _$accesor(this, path, value); + }, + + $on: function(event, handler) { + var _this = this; + if (!this[PROP_MAP.e][event]) { + this[PROP_MAP.e][event] = []; + } + var i = this[PROP_MAP.e][event].push(handler); + return { + $off: function() { + _this[PROP_MAP.e][event].splice(i - 1, 1); + } + }; + }, + + $once: function(event, handler) { + var e = this.$on(event, function(args) { + handler(args); + e.$off(); + }); + }, + + $fire: function(event, data) { + if (this[PROP_MAP.e][event]) { + _$e(this[PROP_MAP.e][event], function(handler) { + handler(data); + }); + } + }, + + $notify: function(key) { + if (this[PROP_MAP.s][key]) { + _$e(this[PROP_MAP.s][key], function(suscriber) { + suscriber(); + }); + } + }, + + $observe: function(deps, listener) { + var _this = this; + var subs = []; + if (_$isArray(deps)) { + _$e(deps, function(dep) { + subs.push({ + sub: dep, + i: _$subs.call(_this, dep, listener) + }); + }); + } else { + subs.push({ + sub: deps, + i: _$subs.call(this, deps, listener) + }); + } + return { + $unobserve: function() { + _$e(subs, function(sub) { + _this[PROP_MAP.s][sub.sub].splice(sub.i, 1); + }); + } + }; + }, + + $watch: function(key, watcher) { + var _this = this; + if (!this[PROP_MAP.w][key]) { + this[PROP_MAP.w][key] = []; + } + var i = this[PROP_MAP.w][key].push(watcher.bind(this)); + return { + $unwatch: function() { + _this[PROP_MAP.w][key].splice(i - 1, 1); + } + }; + } +}); +var array = Array[PROP_MAP.h]; +function _$toArgs(args, start) { + if (start === void 0) { + start = 0; + } + return array.slice.call(args, start); +} +function _$arrayValues(list, value, root, key) { + array.push.apply(list, value.map(function(v, i) { + if (list.length !== 0) + i += list.length; + return !_$isType(v, _$List) && _$isArray(v) ? new _$List(v, root, key + '.' + i) : v; + })); +} +function _$List(value, root, key) { + var self = this; + Array.apply(self, [value.length]); + var desc = { + writable: false, + configurable: false, + enumerable: false + }; + _$def(self, '_key', _$assign({ + value: key + }, desc)); + _$def(self, '_root', _$assign({ + value: root + }, desc)); + _$arrayValues(self, value, root, key); + desc.writable = true; + _$def(self, 'length', _$assign({ + value: self.length + }, desc)); +} +_$extends(_$List, Array); +['pop', 'push', 'reverse', 'shift', 'sort', 'fill', 'unshift', 'splice'].forEach(function(method) { + _$List[PROP_MAP.h][method] = function() { + var self = this; + var old = self.slice(); + var result; + if (method === 'push') { + _$arrayValues(self, _$toArgs(arguments), self._root, self._key); + result = self.length; + } else { + result = array[method].apply(self, arguments); + } + _$dispatch(self._root, self._key, old, self.slice()); + return result; + }; +}); +_$List[PROP_MAP.h].pull = function(index) { + var self = this; + var items = _$toArgs(arguments, 1); + var length = self.length; + if (index > length) { + length = index + 1; + var pull = new Array(index - self.length); + pull.push.apply(pull, items); + for (var i = 0; i < length; i++) { + if (i === index) { + self.push.apply(self, pull); + } + } + } else { + self.splice.apply(self, [index, 1].concat(items)); + } +}; +function _$dispatch(root, key, oldVal, value) { + root.$notify(key); + if (root[PROP_MAP.w][key]) { + _$e(root[PROP_MAP.w][key], function(watcher) { + watcher(oldVal, value); + }); + } + root.$update(); +} +function _$extends(ctor, exts) { + ctor['plugin'] = function(fn, options) { + TPS.push({ + options: options, + fn: fn + }); + }; + ctor[PROP_MAP.h] = Object.create(exts[PROP_MAP.h]); + ctor[PROP_MAP.h].constructor = ctor; +} +function _$isType(value, type) { + return _$type(type) === 'string' ? type.split('|').some(function(t) { + return t.trim() === _$type(value); + }) : value instanceof type; +} +function _$isObject(obj) { + return _$isType(obj, 'object'); +} +function _$isArray(obj) { + return Array.isArray ? Array.isArray(obj) : _$isType(obj, 'array'); +} +function _$isFunction(obj) { + return _$isType(obj, 'function'); +} +function _$isStr(obj) { + return _$isType(obj, 'string'); +} +function _$toType(value, type, root, key) { + switch (type) { + case 'date': + return new Date(value); + case 'string': + return _$toStr(value); + case 'number': + return +value; + case 'boolean': + return _$isStr(value) && !value ? true : !!value; + case 'array': + return _$isType(value, _$List) ? value : new _$List(value, root, key); + default: + return value; + } +} +function _$type(obj) { + return / (\w+)/.exec({}.toString.call(obj))[1].toLowerCase(); +} +function _$hasProp(obj, prop) { + return obj.hasOwnProperty(prop); +} +function _$drt(dd) { + var hasProp = function(prop, instance, options, element) { + return _$isObject(dd) && dd[prop] && dd[prop](instance, options, element); + }; + return { + $init: function(instance, options, element) { + hasProp('$init', instance, options, element); + }, + + $inserted: function(instance, options, element) { + hasProp('$inserted', instance, options, element); + }, + + $update: function(instance, options, element) { + if (_$isFunction(dd)) { + dd(instance, options, element); + } else { + hasProp('$update', instance, options, element); + } + }, + + $destroy: function(instance, options, element) { + hasProp('$destroy', instance, options, element); + } + }; +} +function _$toStr(obj) { + var str = _$type(obj); + return !/null|undefined/.test(str) ? obj.toString() : str; +} +function _$toPlainObj(obj) { + var data = {}; + _$e(_$isObject(obj) ? obj : {}, function(_v, k) { + if (k[0] !== '$' && !_$isFunction(obj[k])) { + if (_$isType(obj[k], _$List)) { + data[k] = obj[k].map(_$toPlainObj); + } else if (_$isObject(obj[k])) { + data[k] = _$toPlainObj(obj[k]); + } else { + data[k] = obj[k]; + } + } + }); + return _$isObject(obj) ? data : obj; +} +function _$accesor(object, path, value) { + return path.split('.').reduce(function(obj, key, i, arr) { + if (_$isType(value, 'undefined')) { + if (obj == null) { + arr.splice(0, arr.length); + return i > 0 && obj === null ? obj : undefined; + } + } else { + if (i === arr.length - 1) { + if (_$isType(obj, _$List) && _$toStr(+key) === key) { + obj.pull(+key, value); + } else { + var oldVal = obj[key]; + obj[key] = !_$isType(value, _$List) && _$isArray(value) ? new _$List(value, object, key) : value; + _$dispatch(object, path, oldVal, obj[key]); + } + } else if (!_$isObject(obj[key])) { + obj[key] = {}; + } + } + return obj ? obj[key] : null; + }, object); +} +function _$(selector, parent) { + return _$isStr(selector) ? (parent || document).querySelector(selector) : selector; +} +function _$d() { + return document.createDocumentFragment(); +} +function _$a(parent, child, sibling) { + if (_$isType(sibling, 'boolean') && sibling) + parent.parentElement.replaceChild(child, parent); + else if (!sibling) + parent.appendChild(child); + else + parent.insertBefore(child, sibling); +} +function _$ce(tagName) { + return document.createElement(tagName || 'div'); +} +function _$ct(content) { + return document.createTextNode(content || ''); +} +function _$tu(text, value) { + if (text.data !== (value = _$toStr(value))) + text.data = value; +} +function _$e(obj, cb) { + for (var key in obj) { + if (_$hasProp(obj, key)) { + cb(obj[key], isNaN(+key) ? key : +key); + } + } +} +function _$tplInit(_$state) { + var _$frag, h1_1, txt_1, setTxt_1; + _$frag = _$d(); + setTxt_1 = function(_$state) { + return 'Hello, ' + _$state.text + '!!'; + }; + return { + $create: function() { + h1_1 = _$ce('h1'); + txt_1 = _$ct(); + txt_1.data = setTxt_1(_$state); + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + this.$siblingEl = _$(sibling); + this.$parentEl = sibling && _$(sibling).parentElement || _$(parent); + }, + + $update: function(_$state) { + _$tu(txt_1, setTxt_1(_$state)); + }, + + $unmount: function() { + _$a(h1_1, txt_1); + _$a(_$frag, h1_1); + }, + + $destroy: function() { + this.$unmount(); + this.$parent = null; + this.$parentEl = null; + this.$siblingEl = null; + this.$children.splice(0, this.$children.length); + delete _$state.$root; + _$frag = h1_1 = txt_1 = setTxt_1 = void 0; + } + }; +} +function Init(_$attrs, _$parent) { + _$CompCtr.call(this, _$attrs, _$tplInit, { + model: { + text: 'World' + } + }, _$parent); + !_$parent && this.$create(); +} +_$extends(Init, _$CompCtr); +return Init; + + }); \ No newline at end of file diff --git a/spec/components/loop.umd.js b/spec/components/loop.umd.js new file mode 100644 index 0000000..982710b --- /dev/null +++ b/spec/components/loop.umd.js @@ -0,0 +1,786 @@ +!function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define('loop', factory) : + (global.Loop = factory()); + }(this, function () { + 'use strict'; +var PROP_MAP = { + p: '__TP__', + v: 'value', + _: '_value', + s: '_subscribers', + e: '_events', + w: '_watchers', + h: 'prototype' +}; +var PROPS = ['$slots', '$refs', '$filters', '$directives', '_events', '_watchers']; +var TPS = window[PROP_MAP.p] || (window[PROP_MAP.p] = []); +var _$assign = Object['assign'] || function(t) { + for (var s = void 0, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (_$hasProp(s, p)) + t[p] = s[p]; + } + return t; +}; +function _$CompCtr(attrs, template, options, parent) { + var self = this; + var _$set = function(prop, value) { + _$def(self, prop, { + value: value, + writable: true + }); + }; + if (!attrs) + attrs = {}; + _$e(PROPS, function(prop) { + _$def(self, prop, { + value: {} + }); + }); + _$set('$parent', parent || null); + _$set('$children', []); + _$set(PROP_MAP.s, {}); + _$set('$options', options); + var opts = self.$options; + if (!opts.attrs) + opts.attrs = {}; + if (!opts.children) + opts.children = {}; + _$e(TPS, function(plugin) { + plugin.fn.call(self, _$CompCtr, plugin.options); + }); + if (opts.filters) + _$assign(self.$filters, opts.filters); + if (opts.directives) _$e(opts.directives, function(drt, k) { + self.$directives[k] = _$drt(drt); + }); + _$e(opts.attrs, function(attrOps, key) { + _$def(self, _$isType(key, 'number') ? attrOps : key, { + get: function() { + if (_$isStr(attrOps)) { + var value = attrs[attrOps]; + return _$isFunction(value) ? value() : value; + } else { + if (!_$hasProp(attrs, key) && attrOps.required) { + return console.error('Attribute \'' + key + '\' is required.'); + } else { + var value = _$isFunction(attrs[key]) ? attrs[key]() : attrs[key]; + if (value === void 0 && _$hasProp(attrOps, 'default')) { + var def = attrOps.default; + value = _$isFunction(def) ? def() : def; + } + var typ = attrOps.type; + if (typ && !_$isType(value, typ) && attrOps.required) { + return console.error('Attribute \'' + key + '\' must be type \'' + typ + '\'.'); + } + value = _$toType(value, value === void 0 ? 'undefined' : typ, self, key); + if (value !== void 0 && _$hasProp(attrOps, 'validator')) { + var validator = attrOps.validator; + if (_$isFunction(validator) && !validator(value)) { + return console.error('Assigment \'' + key + '\'=\'' + JSON.stringify(value) + '\' invalid.'); + } + } + return value; + } + } + }, + + set: function() { + console.error('\'' + key + '\' is read only.'); + }, + + enumerable: true, + configurable: true + }); + }); + var data = opts.model || {}; + var _loop_1 = function(key) { + if (_$hasProp(data, key)) { + var desc = Object.getOwnPropertyDescriptor(data, key); + if (desc.value && _$isArray(desc.value)) { + desc.value = new _$List(desc.value, self, key); + } else { + if (desc.get) { + var getter_1 = desc.get; + desc.get = function() { + var value = getter_1.call(self); + if (_$isArray(value)) + value = new _$List(value, self, key); + return value; + }; + } + if (desc.set) { + var setter_1 = desc.set; + desc.set = function(v) { + if (_$isArray(v)) + v = new _$List(v, self, key); + setter_1.call(self, v); + }; + } + } + _$def(self, key, desc); + } + }; + for (var key in data) { + _loop_1(key); + } + var tpl = template(self, opts.children); + _$e(tpl, function(value, key) { + _$def(self, key, { + value: function(key) { + var hook = key[1].toUpperCase() + key.slice(2); + var bhook = opts['before' + hook]; + var ahook = opts['after' + hook]; + return function() { + bhook && bhook.call(this); + key.slice(1) === 'update' ? value.call(this, this) : value.apply(this, arguments); + ahook && ahook.call(this); + }; + }(key) + }); + }); + _$def(self, '$data', { + get: function() { + return _$toPlainObj(this); + } + }); +} +function _$isValueAttr(attr) { + return attr === 'value'; +} +function _$subs(dep, listener) { + if (!this[PROP_MAP.s][dep]) { + this[PROP_MAP.s][dep] = []; + } + return this[PROP_MAP.s][dep].push(listener.bind(this)) - 1; +} +function _$def(obj, key, desc) { + Object.defineProperty(obj, key, desc); +} +_$assign(_$CompCtr[PROP_MAP.h], { + $get: function(path) { + return _$accesor(this, path); + }, + + $set: function(path, value) { + _$accesor(this, path, value); + }, + + $on: function(event, handler) { + var _this = this; + if (!this[PROP_MAP.e][event]) { + this[PROP_MAP.e][event] = []; + } + var i = this[PROP_MAP.e][event].push(handler); + return { + $off: function() { + _this[PROP_MAP.e][event].splice(i - 1, 1); + } + }; + }, + + $once: function(event, handler) { + var e = this.$on(event, function(args) { + handler(args); + e.$off(); + }); + }, + + $fire: function(event, data) { + if (this[PROP_MAP.e][event]) { + _$e(this[PROP_MAP.e][event], function(handler) { + handler(data); + }); + } + }, + + $notify: function(key) { + if (this[PROP_MAP.s][key]) { + _$e(this[PROP_MAP.s][key], function(suscriber) { + suscriber(); + }); + } + }, + + $observe: function(deps, listener) { + var _this = this; + var subs = []; + if (_$isArray(deps)) { + _$e(deps, function(dep) { + subs.push({ + sub: dep, + i: _$subs.call(_this, dep, listener) + }); + }); + } else { + subs.push({ + sub: deps, + i: _$subs.call(this, deps, listener) + }); + } + return { + $unobserve: function() { + _$e(subs, function(sub) { + _this[PROP_MAP.s][sub.sub].splice(sub.i, 1); + }); + } + }; + }, + + $watch: function(key, watcher) { + var _this = this; + if (!this[PROP_MAP.w][key]) { + this[PROP_MAP.w][key] = []; + } + var i = this[PROP_MAP.w][key].push(watcher.bind(this)); + return { + $unwatch: function() { + _this[PROP_MAP.w][key].splice(i - 1, 1); + } + }; + } +}); +var array = Array[PROP_MAP.h]; +function _$toArgs(args, start) { + if (start === void 0) { + start = 0; + } + return array.slice.call(args, start); +} +function _$arrayValues(list, value, root, key) { + array.push.apply(list, value.map(function(v, i) { + if (list.length !== 0) + i += list.length; + return !_$isType(v, _$List) && _$isArray(v) ? new _$List(v, root, key + '.' + i) : v; + })); +} +function _$List(value, root, key) { + var self = this; + Array.apply(self, [value.length]); + var desc = { + writable: false, + configurable: false, + enumerable: false + }; + _$def(self, '_key', _$assign({ + value: key + }, desc)); + _$def(self, '_root', _$assign({ + value: root + }, desc)); + _$arrayValues(self, value, root, key); + desc.writable = true; + _$def(self, 'length', _$assign({ + value: self.length + }, desc)); +} +_$extends(_$List, Array); +['pop', 'push', 'reverse', 'shift', 'sort', 'fill', 'unshift', 'splice'].forEach(function(method) { + _$List[PROP_MAP.h][method] = function() { + var self = this; + var old = self.slice(); + var result; + if (method === 'push') { + _$arrayValues(self, _$toArgs(arguments), self._root, self._key); + result = self.length; + } else { + result = array[method].apply(self, arguments); + } + _$dispatch(self._root, self._key, old, self.slice()); + return result; + }; +}); +_$List[PROP_MAP.h].pull = function(index) { + var self = this; + var items = _$toArgs(arguments, 1); + var length = self.length; + if (index > length) { + length = index + 1; + var pull = new Array(index - self.length); + pull.push.apply(pull, items); + for (var i = 0; i < length; i++) { + if (i === index) { + self.push.apply(self, pull); + } + } + } else { + self.splice.apply(self, [index, 1].concat(items)); + } +}; +function _$dispatch(root, key, oldVal, value) { + root.$notify(key); + if (root[PROP_MAP.w][key]) { + _$e(root[PROP_MAP.w][key], function(watcher) { + watcher(oldVal, value); + }); + } + root.$update(); +} +function _$extends(ctor, exts) { + ctor['plugin'] = function(fn, options) { + TPS.push({ + options: options, + fn: fn + }); + }; + ctor[PROP_MAP.h] = Object.create(exts[PROP_MAP.h]); + ctor[PROP_MAP.h].constructor = ctor; +} +function _$isType(value, type) { + return _$type(type) === 'string' ? type.split('|').some(function(t) { + return t.trim() === _$type(value); + }) : value instanceof type; +} +function _$isObject(obj) { + return _$isType(obj, 'object'); +} +function _$isArray(obj) { + return Array.isArray ? Array.isArray(obj) : _$isType(obj, 'array'); +} +function _$isFunction(obj) { + return _$isType(obj, 'function'); +} +function _$isStr(obj) { + return _$isType(obj, 'string'); +} +function _$toType(value, type, root, key) { + switch (type) { + case 'date': + return new Date(value); + case 'string': + return _$toStr(value); + case 'number': + return +value; + case 'boolean': + return _$isStr(value) && !value ? true : !!value; + case 'array': + return _$isType(value, _$List) ? value : new _$List(value, root, key); + default: + return value; + } +} +function _$type(obj) { + return / (\w+)/.exec({}.toString.call(obj))[1].toLowerCase(); +} +function _$hasProp(obj, prop) { + return obj.hasOwnProperty(prop); +} +function _$drt(dd) { + var hasProp = function(prop, instance, options, element) { + return _$isObject(dd) && dd[prop] && dd[prop](instance, options, element); + }; + return { + $init: function(instance, options, element) { + hasProp('$init', instance, options, element); + }, + + $inserted: function(instance, options, element) { + hasProp('$inserted', instance, options, element); + }, + + $update: function(instance, options, element) { + if (_$isFunction(dd)) { + dd(instance, options, element); + } else { + hasProp('$update', instance, options, element); + } + }, + + $destroy: function(instance, options, element) { + hasProp('$destroy', instance, options, element); + } + }; +} +function _$toStr(obj) { + var str = _$type(obj); + return !/null|undefined/.test(str) ? obj.toString() : str; +} +function _$toPlainObj(obj) { + var data = {}; + _$e(_$isObject(obj) ? obj : {}, function(_v, k) { + if (k[0] !== '$' && !_$isFunction(obj[k])) { + if (_$isType(obj[k], _$List)) { + data[k] = obj[k].map(_$toPlainObj); + } else if (_$isObject(obj[k])) { + data[k] = _$toPlainObj(obj[k]); + } else { + data[k] = obj[k]; + } + } + }); + return _$isObject(obj) ? data : obj; +} +function _$accesor(object, path, value) { + return path.split('.').reduce(function(obj, key, i, arr) { + if (_$isType(value, 'undefined')) { + if (obj == null) { + arr.splice(0, arr.length); + return i > 0 && obj === null ? obj : undefined; + } + } else { + if (i === arr.length - 1) { + if (_$isType(obj, _$List) && _$toStr(+key) === key) { + obj.pull(+key, value); + } else { + var oldVal = obj[key]; + obj[key] = !_$isType(value, _$List) && _$isArray(value) ? new _$List(value, object, key) : value; + _$dispatch(object, path, oldVal, obj[key]); + } + } else if (!_$isObject(obj[key])) { + obj[key] = {}; + } + } + return obj ? obj[key] : null; + }, object); +} +function _$(selector, parent) { + return _$isStr(selector) ? (parent || document).querySelector(selector) : selector; +} +function _$d() { + return document.createDocumentFragment(); +} +function _$a(parent, child, sibling) { + if (_$isType(sibling, 'boolean') && sibling) + parent.parentElement.replaceChild(child, parent); + else if (!sibling) + parent.appendChild(child); + else + parent.insertBefore(child, sibling); +} +function _$ce(tagName) { + return document.createElement(tagName || 'div'); +} +function _$ct(content) { + return document.createTextNode(content || ''); +} +function _$sa(el, attrOrBind) { + var attr = attrOrBind[0], value = attrOrBind[1]; + el.setAttribute(attr, _$toStr(value)); + if (_$isValueAttr(attr) && !_$isStr(value)) + el[PROP_MAP._] = value; +} +function _$tu(text, value) { + if (text.data !== (value = _$toStr(value))) + text.data = value; +} +function _$f(root, obj, loop) { + var items = {}, loopParent, loopSibling; + var globs = _$toArgs(arguments, 3); + _$e(obj, function(item, i) { + items[i] = loop.apply(null, [root, item, i].concat(globs)); + }); + return { + $create: function() { + _$e(items, function(item) { + item.$create(); + }); + }, + + $mount: function(parent, sibling) { + loopParent = _$(parent); + loopSibling = _$(sibling); + _$e(items, function(item) { + item.$mount(loopParent, loopSibling); + }); + }, + + $update: function(root, obj) { + var globs = _$toArgs(arguments, 2); + _$e(items, function(item, i) { + if (obj[i]) { + item.$update.apply(item, [root, obj[i], i].concat(globs)); + } else { + item.$destroy(); + delete items[i]; + } + }); + _$e(obj, function(item, i) { + if (!items[i]) { + items[i] = loop.apply(null, [root, item, i].concat(globs)); + items[i].$create(); + items[i].$mount(loopParent, loopSibling); + } + }); + }, + + $destroy: function() { + _$e(items, function(item) { + item.$destroy(); + }); + } + }; +} +function _$e(obj, cb) { + for (var key in obj) { + if (_$hasProp(obj, key)) { + cb(obj[key], isNaN(+key) ? key : +key); + } + } +} +function itemLoop_1(_$state, item) { + var _$frag, li_1, txt_1, setTxt_1; + _$frag = _$d(); + setTxt_1 = function(_$state, item) { + return item; + }; + return { + $create: function() { + li_1 = _$ce('li'); + txt_1 = _$ct(); + txt_1.data = setTxt_1(_$state, item); + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + }, + + $update: function(_$state, item) { + _$tu(txt_1, setTxt_1(_$state, item)); + }, + + $unmount: function() { + _$a(li_1, txt_1); + _$a(_$frag, li_1); + }, + + $destroy: function() { + this.$unmount(); + _$frag = li_1 = txt_1 = setTxt_1 = void 0; + } + }; +} +function itemLoop_2(_$state, item) { + var _$frag, li_1, txt_1, setTxt_1; + _$frag = _$d(); + setTxt_1 = function(_$state, item) { + return item; + }; + return { + $create: function() { + li_1 = _$ce('li'); + txt_1 = _$ct(); + txt_1.data = setTxt_1(_$state, item); + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + }, + + $update: function(_$state, item) { + _$tu(txt_1, setTxt_1(_$state, item)); + }, + + $unmount: function() { + _$a(li_1, txt_1); + _$a(_$frag, li_1); + }, + + $destroy: function() { + this.$unmount(); + _$frag = li_1 = txt_1 = setTxt_1 = void 0; + } + }; +} +function itemLoop_3(_$state, item) { + var _$frag, li_1, txt_1, setTxt_1; + _$frag = _$d(); + setTxt_1 = function(_$state, item) { + return item; + }; + return { + $create: function() { + li_1 = _$ce('li'); + txt_1 = _$ct(); + txt_1.data = setTxt_1(_$state, item); + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + }, + + $update: function(_$state, item) { + _$tu(txt_1, setTxt_1(_$state, item)); + }, + + $unmount: function() { + _$a(li_1, txt_1); + _$a(_$frag, li_1); + }, + + $destroy: function() { + this.$unmount(); + _$frag = li_1 = txt_1 = setTxt_1 = void 0; + } + }; +} +function itemLoop_4(_$state, item) { + var _$frag, li_1, txt_1, setTxt_1; + _$frag = _$d(); + setTxt_1 = function(_$state, item) { + return item; + }; + return { + $create: function() { + li_1 = _$ce('li'); + txt_1 = _$ct(); + txt_1.data = setTxt_1(_$state, item); + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + }, + + $update: function(_$state, item) { + _$tu(txt_1, setTxt_1(_$state, item)); + }, + + $unmount: function() { + _$a(li_1, txt_1); + _$a(_$frag, li_1); + }, + + $destroy: function() { + this.$unmount(); + _$frag = li_1 = txt_1 = setTxt_1 = void 0; + } + }; +} +function itemLoop_5(_$state, item) { + var _$frag, li_1, txt_1, setTxt_1; + _$frag = _$d(); + setTxt_1 = function(_$state, item) { + return item; + }; + return { + $create: function() { + li_1 = _$ce('li'); + txt_1 = _$ct(); + txt_1.data = setTxt_1(_$state, item); + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + }, + + $update: function(_$state, item) { + _$tu(txt_1, setTxt_1(_$state, item)); + }, + + $unmount: function() { + _$a(li_1, txt_1); + _$a(_$frag, li_1); + }, + + $destroy: function() { + this.$unmount(); + _$frag = li_1 = txt_1 = setTxt_1 = void 0; + } + }; +} +function _$tplLoop(_$state) { + var _$frag, ul_1, loopAnchor_1_1, loopBlock_1, ul_2, loopAnchor_2_1, loopBlock_2, ul_3, loopAnchor_3_1, loopBlock_3, ul_4, loopAnchor_4_1, loopBlock_4, ul_5, loopAnchor_5_1, loopBlock_5; + _$frag = _$d(); + loopBlock_1 = _$f(_$state, _$state.items, itemLoop_1); + loopAnchor_1_1 = _$ct(); + loopBlock_2 = _$f(_$state, _$state.object, itemLoop_2); + loopAnchor_2_1 = _$ct(); + loopBlock_3 = _$f(_$state, [1, 2, 3, 4, 5], itemLoop_3); + loopAnchor_3_1 = _$ct(); + loopBlock_4 = _$f(_$state, [0, 1, 2, 3, 4], itemLoop_4); + loopAnchor_4_1 = _$ct(); + loopBlock_5 = _$f(_$state, [0, 1, 2, 3, 4], itemLoop_5); + loopAnchor_5_1 = _$ct(); + return { + $create: function() { + ul_1 = _$ce('ul'); + loopBlock_1.$create(); + ul_2 = _$ce('ul'); + loopBlock_2.$create(); + ul_3 = _$ce('ul'); + loopBlock_3.$create(); + ul_4 = _$ce('ul'); + loopBlock_4.$create(); + ul_5 = _$ce('ul'); + loopBlock_5.$create(); + _$sa(ul_1, ['id', 'loop_1']); + _$sa(ul_2, ['id', 'loop_2']); + _$sa(ul_3, ['id', 'loop_3']); + _$sa(ul_4, ['id', 'loop_4']); + _$sa(ul_5, ['id', 'loop_5']); + }, + + $mount: function(parent, sibling) { + this.$unmount(); + _$a(_$(parent), _$frag, _$(sibling)); + this.$siblingEl = _$(sibling); + this.$parentEl = sibling && _$(sibling).parentElement || _$(parent); + }, + + $update: function(_$state) { + loopBlock_1.$update(_$state, _$state.items); + loopBlock_2.$update(_$state, _$state.object); + loopBlock_3.$update(_$state, [1, 2, 3, 4, 5]); + loopBlock_4.$update(_$state, [0, 1, 2, 3, 4]); + loopBlock_5.$update(_$state, [0, 1, 2, 3, 4]); + }, + + $unmount: function() { + _$a(ul_1, loopAnchor_1_1); + loopBlock_1.$mount(ul_1, loopAnchor_1_1); + _$a(_$frag, ul_1); + _$a(ul_2, loopAnchor_2_1); + loopBlock_2.$mount(ul_2, loopAnchor_2_1); + _$a(_$frag, ul_2); + _$a(ul_3, loopAnchor_3_1); + loopBlock_3.$mount(ul_3, loopAnchor_3_1); + _$a(_$frag, ul_3); + _$a(ul_4, loopAnchor_4_1); + loopBlock_4.$mount(ul_4, loopAnchor_4_1); + _$a(_$frag, ul_4); + _$a(ul_5, loopAnchor_5_1); + loopBlock_5.$mount(ul_5, loopAnchor_5_1); + _$a(_$frag, ul_5); + }, + + $destroy: function() { + this.$unmount(); + this.$parent = null; + this.$parentEl = null; + this.$siblingEl = null; + this.$children.splice(0, this.$children.length); + loopBlock_1.$destroy(); + loopBlock_2.$destroy(); + loopBlock_3.$destroy(); + loopBlock_4.$destroy(); + loopBlock_5.$destroy(); + delete _$state.$root; + _$frag = ul_1 = loopAnchor_1_1 = loopBlock_1 = ul_2 = loopAnchor_2_1 = loopBlock_2 = ul_3 = loopAnchor_3_1 = loopBlock_3 = ul_4 = loopAnchor_4_1 = loopBlock_4 = ul_5 = loopAnchor_5_1 = loopBlock_5 = void 0; + } + }; +} +function Loop(_$attrs, _$parent) { + _$CompCtr.call(this, _$attrs, _$tplLoop, { + model: { + items: [1, 2, 3, 4, 5], + + object: { + a: 'a', + b: 'b', + c: 'c', + d: 'd', + e: 'e' + } + } + }, _$parent); + !_$parent && this.$create(); +} +_$extends(Loop, _$CompCtr); +return Loop; + + }); \ No newline at end of file diff --git a/spec/helpers/setup.js b/spec/helpers/setup.js new file mode 100644 index 0000000..7aa10e6 --- /dev/null +++ b/spec/helpers/setup.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const jsdom_1 = require("jsdom"); +function copyProps(src, target) { + const props = Object.getOwnPropertyNames(src) + .filter(prop => typeof target[prop] === 'undefined') + .reduce((result, prop) => ({ + ...result, + [prop]: Object.getOwnPropertyDescriptor(src, prop), + }), {}); + Object.defineProperties(target, props); +} +global['window'] = new jsdom_1.JSDOM('
').window; +global['document'] = global['window'].document; +global['navigator'] = { + userAgent: 'NodeJS', + language: 'en' +}; +copyProps(window, global); diff --git a/spec/special attributes/bind_value.spec.js b/spec/special attributes/bind_value.spec.js new file mode 100644 index 0000000..350e95a --- /dev/null +++ b/spec/special attributes/bind_value.spec.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("../helpers/setup"); +const keysim_1 = require("keysim"); +const Component = require('../components/bind.umd'); +function fireClick(element) { + let event = new window['MouseEvent']('click', { bubbles: true, cancelable: true, view: window }); + element.dispatchEvent(event); +} +describe('Component Bind', () => { + let instance; + beforeAll(done => { + instance = new Component(); + instance.$mount('main'); + done(); + }); + it('`$name` in checkbox should add value to an array', () => { + let input = document.querySelector('#checkbox_1'); + fireClick(input); + expect(instance.checkboxes.length).toBe(1); + expect(instance.checkboxes[0]).toBe('Yes'); + }); + it('`$name` in a checked checkbox should remove value from the array', () => { + let input = document.querySelector('#checkbox_1'); + fireClick(input); + expect(instance.checkboxes.length).toBe(0); + }); + it('`$name` in a radio should change value of the property', () => { + let input = document.querySelector('#radio_1'); + fireClick(input); + expect(instance.radios).toBe('radio 1'); + }); + it('`$value` should change input value from model', () => { + instance.$set('textValue', 'some text'); + let input = document.querySelector('#text'); + expect(input.value).toBe('some text'); + }); + it('`input.value` should change input value in model', () => { + let input = document.querySelector('#text'); + let keyboard = keysim_1.Keyboard.US_ENGLISH; + input.value = input.value + ' to test'; + keyboard.dispatchEventsForInput(input.value, input); + expect(instance.textValue).toBe('some text to test'); + }); +}); diff --git a/spec/special attributes/condition.spec.js b/spec/special attributes/condition.spec.js new file mode 100644 index 0000000..ddffb81 --- /dev/null +++ b/spec/special attributes/condition.spec.js @@ -0,0 +1,35 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("../helpers/setup"); +const Component = require('../components/condition.umd'); +describe('Component Conditions', () => { + let instance, span, div; + beforeAll(done => { + instance = new Component(); + instance.$mount('main'); + done(); + }); + it('`$if` should be rendered', () => { + span = document.querySelector('span'); + expect(span.textContent).toBe('1'); + }); + it('`$else-if` should be rendered', () => { + instance.$set('condition', 2); + span = document.querySelector('span'); + expect(span.textContent).toBe('2'); + }); + it('`$else` should be rendered', () => { + instance.$set('condition', 3); + span = document.querySelector('span'); + expect(span.textContent).toBe('other'); + }); + it('`$if` only should be rendered', () => { + div = document.querySelector('div'); + expect(div.textContent).toBe('1'); + }); + it('`$if` only should be hidden', () => { + instance.$set('condition_1', 2); + div = document.querySelector('div'); + expect(div).toBeNull(); + }); +}); diff --git a/spec/special attributes/html.spec.js b/spec/special attributes/html.spec.js new file mode 100644 index 0000000..39d1ebe --- /dev/null +++ b/spec/special attributes/html.spec.js @@ -0,0 +1,29 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("../helpers/setup"); +const Component = require('../components/html.umd'); +describe('Component Html', () => { + let instance, divs; + beforeAll(done => { + instance = new Component(); + instance.$mount('main'); + done(); + }); + it('nodes without expression should be normally rendered', () => { + divs = document.querySelectorAll('div'); + let div = divs.item(0); + expect(div.innerHTML).toBe('

Here\'s a very interesting note displayed in a lovely shadowed box.

Any kind of content here. Such as <p>, <table>. You name it!

'); + }); + it('nodes with expression should not escape expressions', () => { + divs = document.querySelectorAll('div'); + let div_1 = divs.item(1), div_2 = divs.item(2); + expect(div_1.innerHTML).toBe('

Some paragraph with text undefined

'); + expect(div_2.innerHTML).toBe('

Some paragraph with undefined and undefined expressions

'); + }); + it('`$html` should escape expressions', () => { + divs = document.querySelectorAll('div'); + let div_1 = divs.item(3), div_2 = divs.item(4); + expect(div_1.innerHTML).toBe('

Some paragraph with text intentional {{escaped}}

'); + expect(div_2.innerHTML).toBe('

Some paragraph with text from {{model}}

'); + }); +}); diff --git a/spec/special attributes/loop.spec.js b/spec/special attributes/loop.spec.js new file mode 100644 index 0000000..57ec189 --- /dev/null +++ b/spec/special attributes/loop.spec.js @@ -0,0 +1,55 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("../helpers/setup"); +const Component = require('../components/loop.umd'); +describe('Component Loop', () => { + let instance, items; + beforeAll(done => { + instance = new Component(); + instance.$mount('main'); + done(); + }); + it('should loop over an array variable', () => { + items = document.querySelectorAll('#loop_1 li'); + expect(items.length).toBe(5); + for (let i = 0; i < items.length; i++) { + expect(items.item(i).textContent).toBe(`${i + 1}`); + } + }); + it('should loop over an object', () => { + items = document.querySelectorAll('#loop_2 li'); + expect(items.length).toBe(5); + expect(items.item(0).textContent).toBe('a'); + expect(items.item(4).textContent).toBe('e'); + }); + it('should loop over an array', () => { + items = document.querySelectorAll('#loop_3 li'); + expect(items.length).toBe(5); + for (let i = 0; i < items.length; i++) { + expect(items.item(i).textContent).toBe(`${i + 1}`); + } + }); + it('should loop over a number', () => { + items = document.querySelectorAll('#loop_4 li'); + expect(items.length).toBe(5); + for (let i = 0; i < items.length; i++) { + expect(items.item(i).textContent).toBe(`${i}`); + } + }); + it('should loop over a range of numbers', () => { + items = document.querySelectorAll('#loop_5 li'); + expect(items.length).toBe(5); + for (let i = 0; i < items.length; i++) { + expect(items.item(i).textContent).toBe(`${i}`); + } + }); + it('items should be modified', () => { + instance.items.splice(3, 1); + items = document.querySelectorAll('#loop_1 li'); + expect(items.length).toBe(4); + expect(items.item(0).textContent).toBe('1'); + expect(items.item(1).textContent).toBe('2'); + expect(items.item(2).textContent).toBe('3'); + expect(items.item(3).textContent).toBe('5'); + }); +}); diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json new file mode 100644 index 0000000..3ea3166 --- /dev/null +++ b/spec/support/jasmine.json @@ -0,0 +1,11 @@ +{ + "spec_dir": "spec", + "spec_files": [ + "**/*[sS]pec.js" + ], + "helpers": [ + "helpers/**/*.js" + ], + "stopSpecOnExpectationFailure": false, + "random": false +}