Skip to content

Commit

Permalink
✨ Introduce new Hawkejs template syntax for better readability
Browse files Browse the repository at this point in the history
- Add new syntax using prop:, on:, var: prefixes
- Preserve existing #, :, + syntax for backwards compatibility
- Deprecate old syntax, which will be removed in a future release
  • Loading branch information
skerit committed May 6, 2024
1 parent e0fd20c commit f293906
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 25 deletions.
42 changes: 23 additions & 19 deletions lib/core/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2584,9 +2584,10 @@ Renderer.setMethod(function applyElementOptions(element, options, for_sync_rende
let event_handlers = [];

for (let hook of options.hooks) {
const name = hook.name;
const name = hook.name,
domain = hook.domain;

if (name === 'ref') {
if (domain == 'hook' && name === 'ref') {
let value = this.parseRuntimeExpression(hook.value);

if (value) {
Expand All @@ -2596,23 +2597,26 @@ Renderer.setMethod(function applyElementOptions(element, options, for_sync_rende
continue;
}

switch (name) {
case 'click':
case 'focus':
case 'hover':
case 'blur':
case 'change':
case 'input':
case 'keydown':
case 'keyup':
case 'keypress':
if (hook.value?.$expression) {
event_handlers.push({
type : name,
expression: hook.value?.$expression,
});
}
break;
if (domain == 'on') {

switch (name) {
case 'click':
case 'focus':
case 'hover':
case 'blur':
case 'change':
case 'input':
case 'keydown':
case 'keyup':
case 'keypress':
if (hook.value?.$expression) {
event_handlers.push({
type : name,
expression: hook.value?.$expression,
});
}
break;
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions lib/parser/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,10 @@ Builder.setMethod(function _compileDirectiveValues(values, unwrap_optionals = tr
value : this._compileAttributeValue(value.value, unwrap_optionals),
};

if (value.domain) {
entry.domain = value.domain;
}

result.push(entry);
}

Expand Down
43 changes: 37 additions & 6 deletions lib/parser/directives_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,8 @@ Dparser.setMethod(function parseCurrent() {
*/
Dparser.setMethod(function parseAttributes(result) {

var next = this.next(),
let next = this.next(),
domain,
entry,
temp,
char,
Expand Down Expand Up @@ -434,11 +435,39 @@ Dparser.setMethod(function parseAttributes(result) {
continue;
}

domain = null;
char = next.value[0];
name = next.value;

if (char === '!' || char === '#' || char === '+' || char === ':') {
if (char === '!' || char === '#' || char === '+' || char === ':' || char === '@') {
name = next.value.slice(1);

switch (char) {
case '!':
domain = 'directive';
break;

case '#':
domain = 'prop';
break;

case '+':
domain = 'var';
break;

case ':':
domain = 'hook';
break;

case '@':
domain = 'on';
break;
}
} else if (name.includes(':')) {
let parts = Bound.String.splitOnce(name, ':');

domain = parts[0];
name = parts[1];
}

entry = {
Expand All @@ -460,7 +489,7 @@ Dparser.setMethod(function parseAttributes(result) {
this.index--;
}

if (char === '!') {
if (domain == 'directive') {
if (!result.directives) {
result.directives = [];
}
Expand All @@ -476,25 +505,27 @@ Dparser.setMethod(function parseAttributes(result) {
}

result.directives.push(entry);
} else if (char === '#') {
} else if (domain == 'prop') {
if (!result.properties) {
result.properties = [];
}

result.properties.push(entry);
} else if (char === '+') {
} else if (domain == 'var') {

if (!result.variables) {
result.variables = [];
}

result.variables.push(entry);
} else if (char === ':') {
} else if (domain && domain != 'attr') {

if (!result.hooks) {
result.hooks = [];
}

entry.domain = domain;

result.hooks.push(entry);
} else {
result.attributes[entry.name] = entry;
Expand Down
24 changes: 24 additions & 0 deletions test/50-directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,21 @@ describe('Directives', function() {
createTests(tests);
});

describe('Set properties using the `prop` domain', function() {
let tests = [
[
`<i prop:testing="ok"><%= $0.testing %></i>`,
`<i>ok</i>`
],
[
`<input prop:disabled={% true %}>`,
`<input disabled="true">`
]
];

createTests(tests);
});

describe('Apply directives using the ! syntax', function() {

var tests = [
Expand Down Expand Up @@ -236,6 +251,11 @@ describe('Directives', function() {
`<element-specific-variables +my_specific_variable={% 1 + 1 %}></element-specific-variables>`,
`<element-specific-variables he-rendered="1">my_specific_variable: 2</element-specific-variables>`
],

[
`<element-specific-variables var:my_specific_variable={% 1 + 1 %}></element-specific-variables>`,
`<element-specific-variables he-rendered="1">my_specific_variable: 2</element-specific-variables>`
],
];

createTests(tests);
Expand All @@ -247,6 +267,10 @@ describe('Directives', function() {
`<div +new_variable="NEW">{{new_variable}}</div>`,
`<div>NEW</div>`
],
[
`<div var:new_variable="NEW2">{{new_variable}}</div>`,
`<div>NEW2</div>`
],
[
`<div>{{def_string}}</div>`,
`<div>default</div>`
Expand Down

0 comments on commit f293906

Please sign in to comment.