mirror of
https://github.com/discourse/discourse.git
synced 2025-05-23 08:07:19 +08:00
FEATURE: Use Glimmer compiler for widget templates
Widgets can now specify a template which is precompiled using Glimmer's AST and then converted into our virtual dom code. Example: ```javascript createWidget('post-link-arrow', { template: hbs` {{#if attrs.above}} <a class="post-info arrow" title={{i18n "topic.jump_reply_up"}}> {{fa-icon "arrow-up"}} </a> {{else}} <a class="post-info arrow" title={{i18n "topic.jump_reply_down"}}> {{fa-icon "arrow-down"}} </a> {{/if}} `, click() { DiscourseURL.routeTo(this.attrs.shareUrl); } }); ```
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
import { moduleForWidget, widgetTest } from 'helpers/widget-test';
|
||||
import { createWidget } from 'discourse/widgets/widget';
|
||||
import { withPluginApi } from 'discourse/lib/plugin-api';
|
||||
import hbs from 'discourse/widgets/hbs-compiler';
|
||||
|
||||
moduleForWidget('base');
|
||||
|
||||
@ -10,10 +11,7 @@ widgetTest('widget attributes are passed in via args', {
|
||||
beforeEach() {
|
||||
createWidget('hello-test', {
|
||||
tagName: 'div.test',
|
||||
|
||||
html(attrs) {
|
||||
return `Hello ${attrs.name}`;
|
||||
},
|
||||
template: hbs`Hello {{attrs.name}}`
|
||||
});
|
||||
|
||||
this.set('args', { name: 'Robin' });
|
||||
@ -24,6 +22,39 @@ widgetTest('widget attributes are passed in via args', {
|
||||
}
|
||||
});
|
||||
|
||||
widgetTest("hbs template - no tagName", {
|
||||
template: `{{mount-widget widget="hbs-test" args=args}}`,
|
||||
|
||||
beforeEach() {
|
||||
createWidget('hbs-test', {
|
||||
template: hbs`<div class='test'>Hello {{attrs.name}}</div>`
|
||||
});
|
||||
|
||||
this.set('args', { name: 'Robin' });
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
assert.equal(this.$('div.test').text(), "Hello Robin");
|
||||
}
|
||||
});
|
||||
|
||||
widgetTest("hbs template - with tagName", {
|
||||
template: `{{mount-widget widget="hbs-test" args=args}}`,
|
||||
|
||||
beforeEach() {
|
||||
createWidget('hbs-test', {
|
||||
tagName: 'div.test',
|
||||
template: hbs`Hello {{attrs.name}}`
|
||||
});
|
||||
|
||||
this.set('args', { name: 'Robin' });
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
assert.equal(this.$('div.test').text(), "Hello Robin");
|
||||
}
|
||||
});
|
||||
|
||||
widgetTest('buildClasses', {
|
||||
template: `{{mount-widget widget="classname-test" args=args}}`,
|
||||
|
||||
@ -90,15 +121,12 @@ widgetTest('widget state', {
|
||||
createWidget('state-test', {
|
||||
tagName: 'button.test',
|
||||
buildKey: () => `button-test`,
|
||||
template: hbs`{{state.clicks}} clicks`,
|
||||
|
||||
defaultState() {
|
||||
return { clicks: 0 };
|
||||
},
|
||||
|
||||
html(attrs, state) {
|
||||
return `${state.clicks} clicks`;
|
||||
},
|
||||
|
||||
click() {
|
||||
this.state.clicks++;
|
||||
}
|
||||
@ -123,10 +151,13 @@ widgetTest('widget update with promise', {
|
||||
createWidget('promise-test', {
|
||||
tagName: 'button.test',
|
||||
buildKey: () => 'promise-test',
|
||||
|
||||
html(attrs, state) {
|
||||
return state.name || "No name";
|
||||
},
|
||||
template: hbs`
|
||||
{{#if state.name}}
|
||||
{{state.name}}
|
||||
{{else}}
|
||||
No name
|
||||
{{/if}}
|
||||
`,
|
||||
|
||||
click() {
|
||||
return new Ember.RSVP.Promise(resolve => {
|
||||
@ -140,11 +171,11 @@ widgetTest('widget update with promise', {
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
assert.equal(this.$('button.test').text(), "No name");
|
||||
assert.equal(this.$('button.test').text().trim(), "No name");
|
||||
|
||||
click(this.$('button'));
|
||||
andThen(() => {
|
||||
assert.equal(this.$('button.test').text(), "Robin");
|
||||
assert.equal(this.$('button.test').text().trim(), "Robin");
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -157,9 +188,7 @@ widgetTest('widget attaching', {
|
||||
|
||||
createWidget('attach-test', {
|
||||
tagName: 'div.container',
|
||||
html() {
|
||||
return this.attach('test-embedded');
|
||||
},
|
||||
template: hbs`{{attach widget="test-embedded"}}`
|
||||
});
|
||||
},
|
||||
|
||||
@ -169,15 +198,78 @@ widgetTest('widget attaching', {
|
||||
}
|
||||
});
|
||||
|
||||
widgetTest("handlebars fa-icon", {
|
||||
template: `{{mount-widget widget="hbs-icon-test" args=args}}`,
|
||||
|
||||
beforeEach() {
|
||||
createWidget('hbs-icon-test', {
|
||||
template: hbs`{{fa-icon "arrow-down"}}`
|
||||
});
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
assert.equal(this.$('i.fa.fa-arrow-down').length, 1);
|
||||
}
|
||||
});
|
||||
|
||||
widgetTest("handlebars i18n", {
|
||||
template: `{{mount-widget widget="hbs-i18n-test" args=args}}`,
|
||||
|
||||
beforeEach() {
|
||||
createWidget('hbs-i18n-test', {
|
||||
template: hbs`
|
||||
<span class='string'>{{i18n "hbs_test0"}}</span>
|
||||
<span class='var'>{{i18n attrs.key}}</span>
|
||||
<a href title={{i18n "hbs_test0"}}>test</a>
|
||||
`
|
||||
});
|
||||
I18n.extras = [ {
|
||||
"hbs_test0": "evil",
|
||||
"hbs_test1": "trout"
|
||||
} ];
|
||||
this.set('args', { key: 'hbs_test1' });
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
// comin up
|
||||
assert.equal(this.$('span.string').text(), 'evil');
|
||||
assert.equal(this.$('span.var').text(), 'trout');
|
||||
assert.equal(this.$('a').prop('title'), 'evil');
|
||||
}
|
||||
});
|
||||
|
||||
widgetTest('handlebars #each', {
|
||||
template: `{{mount-widget widget="hbs-each-test" args=args}}`,
|
||||
|
||||
beforeEach() {
|
||||
createWidget('hbs-each-test', {
|
||||
tagName: 'ul',
|
||||
template: hbs`
|
||||
{{#each attrs.items as |item|}}
|
||||
<li>{{item}}</li>
|
||||
{{/each}}
|
||||
`
|
||||
});
|
||||
|
||||
this.set('args', {
|
||||
items: ['one', 'two', 'three']
|
||||
});
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
assert.equal(this.$('ul li').length, 3);
|
||||
assert.equal(this.$('ul li:eq(0)').text(), "one");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
widgetTest('widget decorating', {
|
||||
template: `{{mount-widget widget="decorate-test"}}`,
|
||||
|
||||
beforeEach() {
|
||||
createWidget('decorate-test', {
|
||||
tagName: 'div.decorate',
|
||||
html() {
|
||||
return "main content";
|
||||
},
|
||||
template: hbs`main content`
|
||||
});
|
||||
|
||||
withPluginApi('0.1', api => {
|
||||
@ -204,14 +296,8 @@ widgetTest('widget settings', {
|
||||
beforeEach() {
|
||||
createWidget('settings-test', {
|
||||
tagName: 'div.settings',
|
||||
|
||||
settings: {
|
||||
age: 36
|
||||
},
|
||||
|
||||
html() {
|
||||
return `age is ${this.settings.age}`;
|
||||
},
|
||||
template: hbs`age is {{settings.age}}`,
|
||||
settings: { age: 36 }
|
||||
});
|
||||
},
|
||||
|
||||
@ -226,14 +312,8 @@ widgetTest('override settings', {
|
||||
beforeEach() {
|
||||
createWidget('ov-settings-test', {
|
||||
tagName: 'div.settings',
|
||||
|
||||
settings: {
|
||||
age: 36
|
||||
},
|
||||
|
||||
html() {
|
||||
return `age is ${this.settings.age}`;
|
||||
},
|
||||
template: hbs`age is {{settings.age}}`,
|
||||
settings: { age: 36 },
|
||||
});
|
||||
|
||||
withPluginApi('0.1', api => {
|
||||
|
Reference in New Issue
Block a user