diff --git a/async_fixtures/components-advanced-props-compat/compiled.js b/async_fixtures/components-advanced-props-compat/compiled.js index b65da31..8a3fc85 100644 --- a/async_fixtures/components-advanced-props-compat/compiled.js +++ b/async_fixtures/components-advanced-props-compat/compiled.js @@ -2,7 +2,11 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += await template.compileComponent("components-advanced-props-compat/button")(template, template.getComponentState({ class: 'mb-4 px-4', id: 'foo-bar', title: 'Click me' }, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); +out += await template.compileComponent("components-advanced-props-compat/button")(template, template.getComponentState({ + class: 'mb-4 px-4', + id: 'foo-bar', + title: 'Click me' +}, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); } catch (error) { template.reThrow(error, $filename, $lineNumber); } diff --git a/async_fixtures/components-advanced-props/button.edge b/async_fixtures/components-advanced-props/button.edge index 2bbce78..fa6fed0 100644 --- a/async_fixtures/components-advanced-props/button.edge +++ b/async_fixtures/components-advanced-props/button.edge @@ -1,3 +1,3 @@ - \ No newline at end of file diff --git a/async_fixtures/components-advanced-props/compiled.js b/async_fixtures/components-advanced-props/compiled.js index 714ce2f..e6b438e 100644 --- a/async_fixtures/components-advanced-props/compiled.js +++ b/async_fixtures/components-advanced-props/compiled.js @@ -2,7 +2,11 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += await template.compileComponent("components-advanced-props/button")(template, template.getComponentState({ class: 'mb-4 px-4', id: 'foo-bar', title: 'Click me' }, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); +out += await template.compileComponent("components-advanced-props/button")(template, template.getComponentState({ + class: 'mb-4 px-4', + id: 'foo-bar', + title: 'Click me' +}, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); } catch (error) { template.reThrow(error, $filename, $lineNumber); } diff --git a/async_fixtures/components-falsy-args/compiled.js b/async_fixtures/components-falsy-args/compiled.js index 88de088..4186d87 100644 --- a/async_fixtures/components-falsy-args/compiled.js +++ b/async_fixtures/components-falsy-args/compiled.js @@ -2,7 +2,9 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += await template.compileComponent("components-falsy-args/alert")(template, template.getComponentState({ index: 0 }, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); +out += await template.compileComponent("components-falsy-args/alert")(template, template.getComponentState({ + index: 0 +}, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); } catch (error) { template.reThrow(error, $filename, $lineNumber); } diff --git a/async_fixtures/components-falsy-args/index.edge b/async_fixtures/components-falsy-args/index.edge index a20e150..93dbe7d 100644 --- a/async_fixtures/components-falsy-args/index.edge +++ b/async_fixtures/components-falsy-args/index.edge @@ -1 +1 @@ -@!component("components-falsy-args/alert", index = 0) \ No newline at end of file +@!component("components-falsy-args/alert", { index: 0 }) \ No newline at end of file diff --git a/async_fixtures/components-partials/compiled.js b/async_fixtures/components-partials/compiled.js index db401d5..416846a 100644 --- a/async_fixtures/components-partials/compiled.js +++ b/async_fixtures/components-partials/compiled.js @@ -2,7 +2,9 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += await template.compileComponent("components-partials/alert")(template, template.getComponentState({ username: "virk" }, { $context: Object.assign({}, $context), main: async function () { const $context = this.$context; +out += await template.compileComponent("components-partials/alert")(template, template.getComponentState({ + username: 'virk' +}, { $context: Object.assign({}, $context), main: async function () { const $context = this.$context; let slot_main = ""; try { slot_main += " Hello "; diff --git a/async_fixtures/components-partials/index.edge b/async_fixtures/components-partials/index.edge index c185bff..6e11f8b 100644 --- a/async_fixtures/components-partials/index.edge +++ b/async_fixtures/components-partials/index.edge @@ -1,3 +1,3 @@ -@component("components-partials/alert", username = "virk") +@component("components-partials/alert", { username: 'virk' }) Hello {{ username || "Guest" }} @endcomponent \ No newline at end of file diff --git a/async_fixtures/components-props/compiled.js b/async_fixtures/components-props/compiled.js index 4e796f4..efbbb7a 100644 --- a/async_fixtures/components-props/compiled.js +++ b/async_fixtures/components-props/compiled.js @@ -2,7 +2,9 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += await template.compileComponent("components-props/alert")(template, template.getComponentState({ "title": "H1" }, { $context: Object.assign({}, $context), main: async function () { const $context = this.$context; +out += await template.compileComponent("components-props/alert")(template, template.getComponentState({ + "title": "H1" +}, { $context: Object.assign({}, $context), main: async function () { const $context = this.$context; let slot_main = ""; try { slot_main += "Hello world"; diff --git a/async_fixtures/components-spread-and-literal/compiled.js b/async_fixtures/components-spread-and-literal/compiled.js index bcfa95a..d093bb0 100644 --- a/async_fixtures/components-spread-and-literal/compiled.js +++ b/async_fixtures/components-spread-and-literal/compiled.js @@ -2,7 +2,10 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += await template.compileComponent("components-spread-and-literal/alert")(template, template.getComponentState({ ...state.data, name: 'virk' }, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); +out += await template.compileComponent("components-spread-and-literal/alert")(template, template.getComponentState({ + ...state.data, + name: 'virk' +}, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); } catch (error) { template.reThrow(error, $filename, $lineNumber); } diff --git a/async_fixtures/components-spread/compiled.js b/async_fixtures/components-spread/compiled.js index c2d54ee..030811d 100644 --- a/async_fixtures/components-spread/compiled.js +++ b/async_fixtures/components-spread/compiled.js @@ -2,7 +2,9 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += await template.compileComponent("components-spread/alert")(template, template.getComponentState({ ...state.data }, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); +out += await template.compileComponent("components-spread/alert")(template, template.getComponentState({ + ...state.data +}, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); } catch (error) { template.reThrow(error, $filename, $lineNumber); } diff --git a/fixtures/components-advanced-props-compat/compiled.js b/fixtures/components-advanced-props-compat/compiled.js index c9cb090..66656bc 100644 --- a/fixtures/components-advanced-props-compat/compiled.js +++ b/fixtures/components-advanced-props-compat/compiled.js @@ -2,7 +2,11 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += template.compileComponent("components-advanced-props-compat/button")(template, template.getComponentState({ class: 'mb-4 px-4', id: 'foo-bar', title: 'Click me' }, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); +out += template.compileComponent("components-advanced-props-compat/button")(template, template.getComponentState({ + class: 'mb-4 px-4', + id: 'foo-bar', + title: 'Click me' +}, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); } catch (error) { template.reThrow(error, $filename, $lineNumber); } diff --git a/fixtures/components-advanced-props/button.edge b/fixtures/components-advanced-props/button.edge index 2bbce78..fa6fed0 100644 --- a/fixtures/components-advanced-props/button.edge +++ b/fixtures/components-advanced-props/button.edge @@ -1,3 +1,3 @@ - \ No newline at end of file diff --git a/fixtures/components-advanced-props/compiled.js b/fixtures/components-advanced-props/compiled.js index 6a767a6..6940a28 100644 --- a/fixtures/components-advanced-props/compiled.js +++ b/fixtures/components-advanced-props/compiled.js @@ -2,7 +2,11 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += template.compileComponent("components-advanced-props/button")(template, template.getComponentState({ class: 'mb-4 px-4', id: 'foo-bar', title: 'Click me' }, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); +out += template.compileComponent("components-advanced-props/button")(template, template.getComponentState({ + class: 'mb-4 px-4', + id: 'foo-bar', + title: 'Click me' +}, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); } catch (error) { template.reThrow(error, $filename, $lineNumber); } diff --git a/fixtures/components-falsy-args/compiled.js b/fixtures/components-falsy-args/compiled.js index 8af28a4..84f45df 100644 --- a/fixtures/components-falsy-args/compiled.js +++ b/fixtures/components-falsy-args/compiled.js @@ -2,7 +2,9 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += template.compileComponent("components-falsy-args/alert")(template, template.getComponentState({ index: 0 }, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); +out += template.compileComponent("components-falsy-args/alert")(template, template.getComponentState({ + index: 0 +}, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); } catch (error) { template.reThrow(error, $filename, $lineNumber); } diff --git a/fixtures/components-falsy-args/index.edge b/fixtures/components-falsy-args/index.edge index a20e150..93dbe7d 100644 --- a/fixtures/components-falsy-args/index.edge +++ b/fixtures/components-falsy-args/index.edge @@ -1 +1 @@ -@!component("components-falsy-args/alert", index = 0) \ No newline at end of file +@!component("components-falsy-args/alert", { index: 0 }) \ No newline at end of file diff --git a/fixtures/components-partials/compiled.js b/fixtures/components-partials/compiled.js index 0b9253f..6e95014 100644 --- a/fixtures/components-partials/compiled.js +++ b/fixtures/components-partials/compiled.js @@ -2,7 +2,9 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += template.compileComponent("components-partials/alert")(template, template.getComponentState({ username: "virk" }, { $context: Object.assign({}, $context), main: function () { const $context = this.$context; +out += template.compileComponent("components-partials/alert")(template, template.getComponentState({ + username: 'virk' +}, { $context: Object.assign({}, $context), main: function () { const $context = this.$context; let slot_main = ""; try { slot_main += " Hello "; diff --git a/fixtures/components-partials/index.edge b/fixtures/components-partials/index.edge index c185bff..6e11f8b 100644 --- a/fixtures/components-partials/index.edge +++ b/fixtures/components-partials/index.edge @@ -1,3 +1,3 @@ -@component("components-partials/alert", username = "virk") +@component("components-partials/alert", { username: 'virk' }) Hello {{ username || "Guest" }} @endcomponent \ No newline at end of file diff --git a/fixtures/components-props/compiled.js b/fixtures/components-props/compiled.js index 5836071..4dc8930 100644 --- a/fixtures/components-props/compiled.js +++ b/fixtures/components-props/compiled.js @@ -2,7 +2,9 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += template.compileComponent("components-props/alert")(template, template.getComponentState({ "title": "H1" }, { $context: Object.assign({}, $context), main: function () { const $context = this.$context; +out += template.compileComponent("components-props/alert")(template, template.getComponentState({ + "title": "H1" +}, { $context: Object.assign({}, $context), main: function () { const $context = this.$context; let slot_main = ""; try { slot_main += "Hello world"; diff --git a/fixtures/components-spread-and-literal/compiled.js b/fixtures/components-spread-and-literal/compiled.js index 809a3c0..8863737 100644 --- a/fixtures/components-spread-and-literal/compiled.js +++ b/fixtures/components-spread-and-literal/compiled.js @@ -2,7 +2,10 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += template.compileComponent("components-spread-and-literal/alert")(template, template.getComponentState({ ...state.data, name: 'virk' }, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); +out += template.compileComponent("components-spread-and-literal/alert")(template, template.getComponentState({ + ...state.data, + name: 'virk' +}, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); } catch (error) { template.reThrow(error, $filename, $lineNumber); } diff --git a/fixtures/components-spread/compiled.js b/fixtures/components-spread/compiled.js index ec99c8a..3cad914 100644 --- a/fixtures/components-spread/compiled.js +++ b/fixtures/components-spread/compiled.js @@ -2,7 +2,9 @@ let out = ""; let $lineNumber = 1; let $filename = "{{__dirname}}index.edge"; try { -out += template.compileComponent("components-spread/alert")(template, template.getComponentState({ ...state.data }, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); +out += template.compileComponent("components-spread/alert")(template, template.getComponentState({ + ...state.data +}, { $context: Object.assign({}, $context), main: function () { return "" } }, { filename: $filename, line: $lineNumber, col: 0 }), $context); } catch (error) { template.reThrow(error, $filename, $lineNumber); } diff --git a/fixtures/eval-tag/compiled.js b/fixtures/eval-tag/compiled.js new file mode 100644 index 0000000..1ec0f29 --- /dev/null +++ b/fixtures/eval-tag/compiled.js @@ -0,0 +1,12 @@ +let out = ""; +let $lineNumber = 1; +let $filename = "{{__dirname}}index.edge"; +try { +state.user.username = state.user.username.toUpperCase(); +out += "Hello "; +$lineNumber = 2; +out += `${template.escape(state.user.username)}`; +} catch (error) { +template.reThrow(error, $filename, $lineNumber); +} +return out; \ No newline at end of file diff --git a/fixtures/eval-tag/index.edge b/fixtures/eval-tag/index.edge new file mode 100644 index 0000000..09f67d2 --- /dev/null +++ b/fixtures/eval-tag/index.edge @@ -0,0 +1,2 @@ +@eval(user.username = user.username.toUpperCase()) +Hello {{ user.username }} \ No newline at end of file diff --git a/fixtures/eval-tag/index.json b/fixtures/eval-tag/index.json new file mode 100644 index 0000000..9c47b3a --- /dev/null +++ b/fixtures/eval-tag/index.json @@ -0,0 +1,5 @@ +{ + "user": { + "username": "virk" + } +} \ No newline at end of file diff --git a/fixtures/eval-tag/index.txt b/fixtures/eval-tag/index.txt new file mode 100644 index 0000000..14edf7f --- /dev/null +++ b/fixtures/eval-tag/index.txt @@ -0,0 +1 @@ +Hello VIRK \ No newline at end of file diff --git a/newline_fixtures/yaml-components-with-slots/index.edge b/newline_fixtures/yaml-components-with-slots/index.edge index 3e3a66e..fd7cf21 100644 --- a/newline_fixtures/yaml-components-with-slots/index.edge +++ b/newline_fixtures/yaml-components-with-slots/index.edge @@ -4,7 +4,7 @@ name: {{ user.name }} job: {{ user.job }} skills: - @component('yaml-components/skills', skills = user.skills) + @component('yaml-components/skills', { skills: user.skills }) @slot('skill', skill) - {{ skill }} @endslot diff --git a/newline_fixtures/yaml-components/index.edge b/newline_fixtures/yaml-components/index.edge index 2f36626..3e0dda9 100644 --- a/newline_fixtures/yaml-components/index.edge +++ b/newline_fixtures/yaml-components/index.edge @@ -4,6 +4,6 @@ name: {{ user.name }} job: {{ user.job }} skills: - @component('yaml-components/skills', skills = user.skills) + @component('yaml-components/skills', { skills: user.skills }) @endcomponent @endeach \ No newline at end of file diff --git a/package.json b/package.json index a63e4a5..4f6069a 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "classnames": "^2.3.2", "edge-error": "^4.0.0-0", "edge-lexer": "^6.0.0-4", - "edge-parser": "^9.0.0-2", + "edge-parser": "^9.0.0-3", "he": "^1.2.0", "js-stringify": "^1.0.2", "property-information": "^6.2.0", diff --git a/src/compiler.ts b/src/compiler.ts index 9b14703..60ad433 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -209,7 +209,6 @@ export class Compiler { async: this.async, statePropertyName: 'state', escapeCallPath: ['template', 'escape'], - toAttributesCallPath: ['template', 'toAttributes'], localVariables: this.#inlineVariables, onTag: (tag) => this.#processor.executeTag({ tag, path: templatePath }), }) diff --git a/src/component/props.ts b/src/component/props.ts index d04c62e..9510d18 100644 --- a/src/component/props.ts +++ b/src/component/props.ts @@ -75,7 +75,7 @@ export class ComponentProps { /** * Converts props to HTML attributes */ - toAttributes() { + toAttrs() { return htmlSafe(stringifyAttributes(this.#values)) } } diff --git a/src/edge/globals.ts b/src/edge/globals.ts index 9f3a113..f91d24f 100644 --- a/src/edge/globals.ts +++ b/src/edge/globals.ts @@ -76,7 +76,9 @@ export const edgeGlobals = { escape: escape, safe: htmlSafe, classNames: classNames, - toAttributes: stringifyAttributes, + attrs: (values: Record) => { + return htmlSafe(stringifyAttributes(values)) + }, }, /** diff --git a/src/tags/component.ts b/src/tags/component.ts index 29c82a3..11fa990 100644 --- a/src/tags/component.ts +++ b/src/tags/component.ts @@ -80,19 +80,6 @@ function getComponentNameAndProps( * expression, as components allows a max of two arguments */ const firstSequenceExpression = expression.expressions[0] - - if ( - firstSequenceExpression && - [expressions.ObjectExpression, expressions.AssignmentExpression].includes( - firstSequenceExpression.type - ) - ) { - return [ - parser.utils.stringify(name), - StringifiedObject.fromAcornExpressions([firstSequenceExpression], parser), - ] - } - return [parser.utils.stringify(name), parser.utils.stringify(firstSequenceExpression)] } diff --git a/src/tags/eval.ts b/src/tags/eval.ts new file mode 100644 index 0000000..4109355 --- /dev/null +++ b/src/tags/eval.ts @@ -0,0 +1,31 @@ +/* + * edge.js + * + * (c) EdgeJS + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { parseJsArg } from '../utils.js' +import type { TagContract } from '../types.js' + +/** + * The eval tag accepts expressions similar to double curly + * braces. However, it does not write anything to the + * output. + */ +export const evalTag: TagContract = { + block: false, + seekable: true, + tagName: 'eval', + noNewLine: true, + + /** + * Compiles the tag AST + */ + compile(parser, buffer, token) { + const parsed = parseJsArg(parser, token) + buffer.writeExpression(parser.utils.stringify(parsed), token.filename, token.loc.start.line) + }, +} diff --git a/src/tags/main.ts b/src/tags/main.ts index be2dd4e..01bd425 100644 --- a/src/tags/main.ts +++ b/src/tags/main.ts @@ -11,6 +11,7 @@ export { ifTag as if } from './if.js' export { eachTag as each } from './each.js' export { slotTag as slot } from './slot.js' export { elseTag as else } from './else.js' +export { evalTag as eval } from './eval.js' export { injectTag as inject } from './inject.js' export { unlessTag as unless } from './unless.js' export { elseIfTag as elseif } from './else_if.js' diff --git a/src/template.ts b/src/template.ts index a22072a..850ac98 100644 --- a/src/template.ts +++ b/src/template.ts @@ -15,7 +15,6 @@ import Macroable from '@poppinss/macroable' import { Compiler } from './compiler.js' import { Processor } from './processor.js' import { Props } from './migrate/props.js' -import { stringifyAttributes } from './utils.js' import type { CompiledTemplate } from './types.js' import { ComponentProps } from './component/props.js' @@ -171,13 +170,6 @@ export class Template extends Macroable { return escape(input) } - /** - * Converts an object to HTML attributes - */ - toAttributes(attributes: Record) { - return stringifyAttributes(attributes) - } - /** * Raise an error */ diff --git a/src/utils.ts b/src/utils.ts index 7cf276d..c87d180 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -243,49 +243,6 @@ export class StringifiedObject { this.#obj = '' return obj } - - /** - * Parses an array of expressions to form an object. Each expression inside the array must - * be `ObjectExpression` or an `AssignmentExpression`, otherwise it will be ignored. - * - * ```js - * (title = 'hello') - * // returns { title: 'hello' } - * - * ({ title: 'hello' }) - * // returns { title: 'hello' } - * - * ({ title: 'hello' }, username = 'virk') - * // returns { title: 'hello', username: 'virk' } - * ``` - */ - static fromAcornExpressions(expressions: any[], parser: Parser): string { - if (!Array.isArray(expressions)) { - throw new Error('"fromAcornExpressions" expects an array of acorn ast expressions') - } - - const objectifyString = new this() - - expressions.forEach((arg) => { - if (arg.type === 'ObjectExpression') { - arg.properties.forEach((prop: any) => { - if (prop.type === 'SpreadElement') { - objectifyString.addSpread(parser.utils.stringify(prop)) - } else { - const key = parser.utils.stringify(prop.key) - const value = parser.utils.stringify(prop.value) - objectifyString.add(key, value, prop.computed) - } - }) - } - - if (arg.type === 'AssignmentExpression') { - objectifyString.add(arg.left.name, parser.utils.stringify(arg.right)) - } - }) - - return objectifyString.flush() - } } /** diff --git a/tests/component.spec.ts b/tests/component.spec.ts index 53579f7..60654bf 100644 --- a/tests/component.spec.ts +++ b/tests/component.spec.ts @@ -421,7 +421,7 @@ test.group('Component | context API', (group) => { dedent`

Some content

- @component('modal', needsHandler = true) + @component('modal', { needsHandler: true })

{{ $context.closeHandler }}

@endcomponent ` @@ -455,7 +455,7 @@ test.group('Component | context API', (group) => { dedent`

Some content

- @component('modal', needsHandler = true) + @component('modal', { needsHandler: true })

{{ $context.closeHandler }}

@endcomponent @@ -493,7 +493,7 @@ test.group('Component | context API', (group) => { dedent`

Some content

- @component('modal', needsHandler = true) + @component('modal', { needsHandler: true })

{{ $context.closeHandler }}

@endcomponent @@ -543,7 +543,7 @@ test.group('Component | context API', (group) => {

Some content

@component('wrapper') - @component('modal', needsHandler = true) + @component('modal', { needsHandler: true })

{{ $context.closeHandler }}

@endcomponent diff --git a/tests/edge.spec.ts b/tests/edge.spec.ts index 7d6fb27..0590c87 100644 --- a/tests/edge.spec.ts +++ b/tests/edge.spec.ts @@ -16,7 +16,6 @@ import { test } from '@japa/runner' import { Edge } from '../src/edge/main.js' import { migrate } from '../src/migrate/plugin.js' import { edgeGlobals } from '../src/edge/globals.js' -import { PerformanceObserver } from 'node:perf_hooks' test.group('Edge', () => { test('mount default disk', async ({ assert, fs }) => { diff --git a/tests/globals/attrs.spec.ts b/tests/globals/attrs.spec.ts new file mode 100644 index 0000000..8274549 --- /dev/null +++ b/tests/globals/attrs.spec.ts @@ -0,0 +1,299 @@ +/* + * edge-js + * + * (c) Edge + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import '../assert_extend.js' +import dedent from 'dedent-js' +import { test } from '@japa/runner' +import path, { join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { Filesystem } from '@poppinss/dev-utils' + +import { Loader } from '../../src/loader.js' +import { Template } from '../../src/template.js' +import { Compiler } from '../../src/compiler.js' +import { slotTag } from '../../src/tags/slot.js' +import { Processor } from '../../src/processor.js' +import { includeTag } from '../../src/tags/include.js' +import { edgeGlobals } from '../../src/edge/globals.js' +import { componentTag } from '../../src/tags/component.js' + +const tags = { slot: slotTag, component: componentTag, include: includeTag } +const fs = new Filesystem(join(path.dirname(fileURLToPath(import.meta.url)), 'views')) + +const loader = new Loader() +loader.mount('default', fs.basePath) + +test.group('Template | toAttributes', () => { + test('serialize object to HTML attributes', async ({ assert }) => { + const processor = new Processor() + const compiler = new Compiler(loader, tags, processor, { cache: false }) + const template = new Template(compiler, edgeGlobals, {}, processor) + + const html = await template.renderRaw( + dedent` + + `, + { + hasError: false, + } + ) + + assert.equal( + html, + dedent` + + ` + ) + }) + + test('allow properties with no values', async ({ assert }) => { + const processor = new Processor() + const compiler = new Compiler(loader, tags, processor, { cache: false }) + const template = new Template(compiler, edgeGlobals, {}, processor) + + const html = await template.renderRaw( + dedent` + + `, + {} + ) + + assert.equal( + html, + dedent` + + ` + ) + }) + + test('allow non-standard attributes', async ({ assert }) => { + const processor = new Processor() + const compiler = new Compiler(loader, tags, processor, { cache: false }) + const template = new Template(compiler, edgeGlobals, {}, processor) + + const html = await template.renderRaw( + dedent` + + `, + { + hasError: false, + } + ) + + assert.equal( + html, + dedent` + + ` + ) + }) + + test('define comma separated values', async ({ assert }) => { + const processor = new Processor() + const compiler = new Compiler(loader, tags, processor, { cache: false }) + const template = new Template(compiler, edgeGlobals, {}, processor) + + const html = await template.renderRaw( + dedent` + + `, + {} + ) + + assert.equal( + html, + dedent` + + ` + ) + }) + + test('define alpine js attributes', async ({ assert }) => { + const processor = new Processor() + const compiler = new Compiler(loader, tags, processor, { cache: false }) + const template = new Template(compiler, edgeGlobals, {}, processor) + + const html = await template.renderRaw( + dedent` +
+
+ `, + {} + ) + + assert.equal( + html, + dedent` +
+
+ ` + ) + }) + + test('define alpine js boolean attributes', async ({ assert }) => { + const processor = new Processor() + const compiler = new Compiler(loader, tags, processor, { cache: false }) + const template = new Template(compiler, edgeGlobals, {}, processor) + + const html = await template.renderRaw( + dedent` +
+
+ `, + {} + ) + + assert.equal( + html, + dedent` +
+
+ ` + ) + }) + + test('define alpine js event listeners', async ({ assert }) => { + const processor = new Processor() + const compiler = new Compiler(loader, tags, processor, { cache: false }) + const template = new Template(compiler, edgeGlobals, {}, processor) + + const html = await template.renderRaw( + dedent` +
+
+ `, + {} + ) + + assert.equal( + html, + dedent` +
+
+ ` + ) + }) + + test('define alpinejs x-bind properties', async ({ assert }) => { + const processor = new Processor() + const compiler = new Compiler(loader, tags, processor, { cache: false }) + const template = new Template(compiler, edgeGlobals, {}, processor) + + const html = await template.renderRaw( + dedent` +
+
+ `, + {} + ) + + assert.equal( + html, + dedent` +
+
+ ` + ) + }) + + test('define alpinejs transition properties', async ({ assert }) => { + const processor = new Processor() + const compiler = new Compiler(loader, tags, processor, { cache: false }) + const template = new Template(compiler, edgeGlobals, {}, processor) + + const html = await template.renderRaw( + dedent` +
+
+ `, + {} + ) + + assert.equal( + html, + dedent` +
+
+ ` + ) + }) +}) diff --git a/tests/stringified_object.spec.ts b/tests/stringified_object.spec.ts index b9c9e5c..279489e 100644 --- a/tests/stringified_object.spec.ts +++ b/tests/stringified_object.spec.ts @@ -8,23 +8,8 @@ */ import { test } from '@japa/runner' -import { Parser, Stack } from 'edge-parser' import { StringifiedObject } from '../src/utils.js' -/** - * Sample loc - */ -const LOC = { - start: { - line: 1, - col: 0, - }, - end: { - line: 1, - col: 0, - }, -} - test.group('StringifiedObject', () => { test('add string as a key-value pair to object', ({ assert }) => { const stringified = new StringifiedObject() @@ -56,125 +41,3 @@ test.group('StringifiedObject', () => { assert.equal(stringified.flush(), '{ username: [10, 20] }') }) }) - -test.group('StringifiedObject | fromAcornAst', () => { - test('stringify object expression', ({ assert }) => { - const parser = new Parser({}, new Stack(), { - async: false, - statePropertyName: 'state', - escapeCallPath: 'escape', - toAttributesCallPath: 'toAttributes', - }) - const expression = parser.utils.transformAst( - parser.utils.generateAST("({ username: 'virk' })", LOC, 'eval.edge'), - 'eval.edge', - parser - ) - - const props = StringifiedObject.fromAcornExpressions([expression], parser) - assert.equal(props, "{ username: 'virk' }") - }) - - test('parse props with shorthand obj', ({ assert }) => { - const parser = new Parser({}, new Stack(), { - async: false, - statePropertyName: 'state', - escapeCallPath: 'escape', - toAttributesCallPath: 'toAttributes', - }) - const expression = parser.utils.transformAst( - parser.utils.generateAST('({ username })', LOC, 'eval.edge'), - 'eval.edge', - parser - ) - - const props = StringifiedObject.fromAcornExpressions([expression], parser) - assert.equal(props, '{ username: state.username }') - }) - - test('parse props with computed obj', ({ assert }) => { - const parser = new Parser({}, new Stack(), { - async: false, - statePropertyName: 'state', - escapeCallPath: 'escape', - toAttributesCallPath: 'toAttributes', - }) - const expression = parser.utils.transformAst( - parser.utils.generateAST('({ [username]: username })', LOC, 'eval.edge'), - 'eval.edge', - parser - ) - - const props = StringifiedObject.fromAcornExpressions([expression], parser) - assert.equal(props, '{ [state.username]: state.username }') - }) - - test('parse props with multiple obj properties', ({ assert }) => { - const parser = new Parser({}, new Stack(), { - async: false, - statePropertyName: 'state', - escapeCallPath: 'escape', - toAttributesCallPath: 'toAttributes', - }) - const expression = parser.utils.transformAst( - parser.utils.generateAST("({ username: 'virk', age: 22 })", LOC, 'eval.edge'), - 'eval.edge', - parser - ) - - const props = StringifiedObject.fromAcornExpressions([expression], parser) - - assert.equal(props, "{ username: 'virk', age: 22 }") - }) - - test('parse props with shorthand and full properties', ({ assert }) => { - const parser = new Parser({}, new Stack(), { - async: false, - statePropertyName: 'state', - escapeCallPath: 'escape', - toAttributesCallPath: 'toAttributes', - }) - const expression = parser.utils.transformAst( - parser.utils.generateAST('({ username, age: 22 })', LOC, 'eval.edge'), - 'eval.edge', - parser - ) - - const props = StringifiedObject.fromAcornExpressions([expression], parser) - assert.equal(props, '{ username: state.username, age: 22 }') - }) - - test('parse props with assignment expression', ({ assert }) => { - const parser = new Parser({}, new Stack(), { - async: false, - statePropertyName: 'state', - escapeCallPath: 'escape', - toAttributesCallPath: 'toAttributes', - }) - const expression = parser.utils.transformAst( - parser.utils.generateAST("(title = 'Hello')", LOC, 'eval.edge'), - 'eval.edge', - parser - ) - - const props = StringifiedObject.fromAcornExpressions([expression], parser) - assert.equal(props, "{ title: 'Hello' }") - }) - - test('parse props with more than one assignment expression', ({ assert }) => { - const parser = new Parser({}, new Stack(), { - async: false, - statePropertyName: 'state', - escapeCallPath: 'escape', - toAttributesCallPath: 'toAttributes', - }) - const expression = parser.utils.transformAst( - parser.utils.generateAST("(title = 'Hello', body = 'Some content')", LOC, 'eval.edge'), - 'eval.edge', - parser - ) - - const props = StringifiedObject.fromAcornExpressions(expression.expressions, parser) - assert.equal(props, "{ title: 'Hello', body: 'Some content' }") - }) -}) diff --git a/tests/template.spec.ts b/tests/template.spec.ts index 00a755e..98b7610 100644 --- a/tests/template.spec.ts +++ b/tests/template.spec.ts @@ -8,7 +8,6 @@ */ import './assert_extend.js' -import dedent from 'dedent-js' import { test } from '@japa/runner' import path, { join } from 'node:path' import { fileURLToPath } from 'node:url' @@ -250,272 +249,3 @@ test.group('Template', (group) => { assert.equal(partailWithInlineVariables(template, {}, {}, 'virk').trim(), 'Hello virk') }) }) - -test.group('Template | toAttributes', () => { - test('serialize object to HTML attributes', async ({ assert }) => { - const processor = new Processor() - const compiler = new Compiler(loader, tags, processor, { cache: false }) - const template = new Template(compiler, {}, {}, processor) - - const html = await template.renderRaw( - dedent` - - `, - { - hasError: false, - } - ) - - assert.equal( - html, - dedent` - - ` - ) - }) - - test('allow properties with no values', async ({ assert }) => { - const processor = new Processor() - const compiler = new Compiler(loader, tags, processor, { cache: false }) - const template = new Template(compiler, {}, {}, processor) - - const html = await template.renderRaw( - dedent` - - `, - {} - ) - - assert.equal( - html, - dedent` - - ` - ) - }) - - test('allow non-standard attributes', async ({ assert }) => { - const processor = new Processor() - const compiler = new Compiler(loader, tags, processor, { cache: false }) - const template = new Template(compiler, {}, {}, processor) - - const html = await template.renderRaw( - dedent` - - `, - { - hasError: false, - } - ) - - assert.equal( - html, - dedent` - - ` - ) - }) - - test('define comma separated values', async ({ assert }) => { - const processor = new Processor() - const compiler = new Compiler(loader, tags, processor, { cache: false }) - const template = new Template(compiler, {}, {}, processor) - - const html = await template.renderRaw( - dedent` - - `, - {} - ) - - assert.equal( - html, - dedent` - - ` - ) - }) - - test('define alpine js attributes', async ({ assert }) => { - const processor = new Processor() - const compiler = new Compiler(loader, tags, processor, { cache: false }) - const template = new Template(compiler, {}, {}, processor) - - const html = await template.renderRaw( - dedent` -
-
- `, - {} - ) - - assert.equal( - html, - dedent` -
-
- ` - ) - }) - - test('define alpine js boolean attributes', async ({ assert }) => { - const processor = new Processor() - const compiler = new Compiler(loader, tags, processor, { cache: false }) - const template = new Template(compiler, {}, {}, processor) - - const html = await template.renderRaw( - dedent` -
-
- `, - {} - ) - - assert.equal( - html, - dedent` -
-
- ` - ) - }) - - test('define alpine js event listeners', async ({ assert }) => { - const processor = new Processor() - const compiler = new Compiler(loader, tags, processor, { cache: false }) - const template = new Template(compiler, {}, {}, processor) - - const html = await template.renderRaw( - dedent` -
-
- `, - {} - ) - - assert.equal( - html, - dedent` -
-
- ` - ) - }) - - test('define alpinejs x-bind properties', async ({ assert }) => { - const processor = new Processor() - const compiler = new Compiler(loader, tags, processor, { cache: false }) - const template = new Template(compiler, {}, {}, processor) - - const html = await template.renderRaw( - dedent` -
-
- `, - {} - ) - - assert.equal( - html, - dedent` -
-
- ` - ) - }) - - test('define alpinejs transition properties', async ({ assert }) => { - const processor = new Processor() - const compiler = new Compiler(loader, tags, processor, { cache: false }) - const template = new Template(compiler, {}, {}, processor) - - const html = await template.renderRaw( - dedent` -
-
- `, - {} - ) - - assert.equal( - html, - dedent` -
-
- ` - ) - }) -})