DEV: Upgrade our widget handlebars compiler

DEV: Upgrade our widget handlebars compiler

Now supports subexpressions such as i18n and concat, plus automatic attaching of widgets similar to ember.

diff --git a/app/assets/javascripts/discourse/lib/transform-post.js.es6 b/app/assets/javascripts/discourse/lib/transform-post.js.es6
index 43aa804..1aa662a 100644
--- a/app/assets/javascripts/discourse/lib/transform-post.js.es6
+++ b/app/assets/javascripts/discourse/lib/transform-post.js.es6
@@ -222,7 +222,7 @@ export default function transformPost(
           acted,
           count,
           canUndo: a.can_undo,
-          canDeferFlags: a.can_defer_flags,
+          canIgnoreFlags: a.can_defer_flags,
           description: actionDescription(action, acted, count)
         };
       });
diff --git a/app/assets/javascripts/discourse/widgets/actions-summary.js.es6 b/app/assets/javascripts/discourse/widgets/actions-summary.js.es6
index 50c6d8a..d15a3d7 100644
--- a/app/assets/javascripts/discourse/widgets/actions-summary.js.es6
+++ b/app/assets/javascripts/discourse/widgets/actions-summary.js.es6
@@ -63,15 +63,12 @@ createWidget("small-user-list", {
 
 createWidget("action-link", {
   tagName: "span.action-link",
+  template: hbs`<a>{{attrs.text}}. </a>`,
 
   buildClasses(attrs) {
     return attrs.className;
   },
 
-  html(attrs) {
-    return h("a", [attrs.text, ". "]);
-  },
-
   click() {
     this.sendWidgetAction(this.attrs.action);
   }
@@ -82,56 +79,24 @@ createWidget("actions-summary-item", {
   buildKey: attrs => `actions-summary-item-${attrs.id}`,
 
   defaultState() {
-    return { users: [] };
+    return { users: null };
   },
 
-  html(attrs, state) {
-    const users = state.users;
-
-    const result = [];
-    const action = attrs.action;
-
-    if (users.length === 0) {
-      result.push(
-        this.attach("action-link", {
-          action: "whoActed",
-          text: attrs.description
-        })
-      );
-    } else {
-      result.push(
-        this.attach("small-user-list", {
-          users,
-          description: `post.actions.people.${action}`
-        })
-      );
-    }
-
-    if (attrs.canUndo) {
-      result.push(
-        this.attach("action-link", {
-          action: "undo",
-          className: "undo",
-          text: I18n.t(`post.actions.undo.${action}`)
-        })
-      );
-    }
+  template: hbs`
+    {{#if state.users}}
+      {{small-user-list users=state.users description=(concat "post.actions.people." attrs.action)}}
+    {{else}}
+      {{action-link action="whoActed" text=attrs.description}}
+    {{/if}}
 
-    if (attrs.canDeferFlags) {
-      const flagsDesc = I18n.t(`post.actions.defer_flags`, {
-        count: attrs.count
-      });
-      result.push(
-        this.attach("action-link", {
-          action: "deferFlags",
-          className: "defer-flags",
-          text: flagsDesc
-        })
-      );
-    }
+    {{#if attrs.canUndo}}
+      {{action-link action="undo" className="undo" text=(i18n (concat "post.actions.undo." attrs.action))}}
+    {{/if}}
 
-    return result;
-  },
+    {{#if attrs.canIgnoreFlags}}
+      {{action-link action="deferFlags" className="defer-flags" text=(i18n "post.actions.defer_flags" count=attrs.count)}}
+    {{/if}}
+  `,
 
   whoActed() {
     const attrs = this.attrs;
@@ -159,7 +124,7 @@ export default createWidget("actions-summary", {
   tagName: "section.post-actions",
   template: hbs`
     {{#each attrs.actionsSummary as |as|}}
-      {{attach widget="actions-summary-item" attrs=as}}
+      {{actions-summary-item attrs=as}}
       <div class='clearfix'></div>
     {{/each}}
     {{#if attrs.deleted_at}}
diff --git a/app/assets/javascripts/discourse/widgets/header-contents.js.es6 b/app/assets/javascripts/discourse/widgets/header-contents.js.es6
index 82bae85..6f4c708 100644
--- a/app/assets/javascripts/discourse/widgets/header-contents.js.es6
+++ b/app/assets/javascripts/discourse/widgets/header-contents.js.es6
@@ -4,9 +4,9 @@ import hbs from "discourse/widgets/hbs-compiler";
 createWidget("header-contents", {
   tagName: "div.contents.clearfix",
   template: hbs`
-    {{attach widget="home-logo" attrs=attrs}}
+    {{home-logo attrs=attrs}}
     {{#if attrs.topic}}
-      {{attach widget="header-topic-info" attrs=attrs}}
+      {{header-topic-info attrs=attrs}}
     {{/if}}
     <div class="panel clearfix">{{yield}}</div>
   `
diff --git a/app/assets/javascripts/discourse/widgets/private-message-map.js.es6 b/app/assets/javascripts/discourse/widgets/private-message-map.js.es6
index 64274c4..faf7ebe 100644
--- a/app/assets/javascripts/discourse/widgets/private-message-map.js.es6
+++ b/app/assets/javascripts/discourse/widgets/private-message-map.js.es6
@@ -34,9 +34,9 @@ createWidget("pm-map-user-group", {
       <span class="group-name">{{attrs.group.name}}</span>
     </a>
     {{#if attrs.isEditing}}
-    {{#if attrs.canRemoveAllowedUsers}}
-      {{attach widget="pm-remove-group-link" attrs=attrs.group}}
-    {{/if}}
+      {{#if attrs.canRemoveAllowedUsers}}
+        {{pm-remove-group-link attrs=attrs.group}}
+      {{/if}}
     {{/if}}
   `
 });
diff --git a/app/assets/javascripts/discourse/widgets/user-menu.js.es6 b/app/assets/javascripts/discourse/widgets/user-menu.js.es6
index d1a37e4..efd94ba 100644
--- a/app/assets/javascripts/discourse/widgets/user-menu.js.es6
+++ b/app/assets/javascripts/discourse/widgets/user-menu.js.es6
@@ -109,15 +109,12 @@ createWidget("user-menu-dismiss-link", {
   template: hbs`
     <ul class='menu-links'>
       <li>
-        {{attach
-          widget="link"
-          attrs=(hash
-            action="dismissNotifications"
-            className="dismiss"
-            tabindex="0"
-            icon="check"
-            label="user.dismiss"
-            title="user.dismiss_notifications_tooltip")}}
+        {{link action="dismissNotifications"
+          className="dismiss"
+          tabindex="0"
+          icon="check"
+          label="user.dismiss"
+          title="user.dismiss_notifications_tooltip"}}
       </li>
     </ul>
   `
diff --git a/lib/javascripts/widget-hbs-compiler.js.es6 b/lib/javascripts/widget-hbs-compiler.js.es6
index a55dfae..fc2280a 100644
--- a/lib/javascripts/widget-hbs-compiler.js.es6
+++ b/lib/javascripts/widget-hbs-compiler.js.es6
@@ -5,27 +5,62 @@ function resolve(path) {
   return path;
 }
 
+function sexpValue(value) {
+  if (!value) {
+    return;
+  }
+
+  let pValue = value.original;
+  if (value.type === "StringLiteral") {
+    return JSON.stringify(pValue);
+  } else if (value.type === "SubExpression") {
+    return sexp(value);
+  }
+  return pValue;
+}
+
+function pairsToObj(pairs) {
+  let result = [];
+
+  pairs.forEach(p => {
+    result.push(`"${p.key}": ${sexpValue(p.value)}`);
+  });
+
+  return `{ ${result.join(", ")} }`;
+}
+
+function i18n(node) {
+  let key = sexpValue(node.params[0]);
+
+  let hash = node.hash;
+  if (hash.pairs.length) {
+    return `I18n.t(${key}, ${pairsToObj(hash.pairs)})`;
+  }
+
+  return `I18n.t(${key})`;
+}
+
 function sexp(value) {
   if (value.path.original === "hash") {
-    let result = [];
-
-    value.hash.pairs.forEach(p => {
-      let pValue = p.value.original;
-      if (p.value.type === "StringLiteral") {
-        pValue = JSON.stringify(pValue);
-      }
+    return pairsToObj(value.hash.pairs);
+  }
 
-      result.push(`"${p.key}": ${pValue}`);
+  if (value.path.original === "concat") {
+    let result = [];
+    value.params.forEach(p => {
+      result.push(sexpValue(p));
     });
+    return result.join(" + ");
+  }
 
-    return `{ ${result.join(", ")} }`;
+  if (value.path.original === "i18n") {
+    return i18n(value);
   }
 }
 
-function argValue(arg) {
-  let value = arg.value;
+function valueOf(value) {
   if (value.type === "SubExpression") {
-    return sexp(arg.value);
+    return sexp(value);
   } else if (value.type === "PathExpression") {
     return value.original;
   } else if (value.type === "StringLiteral") {
@@ -33,6 +68,10 @@ function argValue(arg) {
   }
 }
 
+function argValue(arg) {
+  return valueOf(arg.value);
+}
+
 function useHelper(state, name) {
   let id = state.helpersUsed[name];
   if (!id) {

[... diff too long, it was truncated ...]

GitHub sha: 3cb0d27d

1 Like