Skip to content

Commit 1df77df

Browse files
committed
Allow body attributes
The SimpleDOM document that gets created during fastboot rendering has a body tag, and it's possible to set attributes on it. For example, assuming `getDOM` from [ember-wormhole](https://github.com/yapplabs/ember-wormhole/blob/6992bb2a9fced9183cdb426a931722fb1fefba8a/addon/utils/dom.js#L45-L63): ```js Component.extend({ init() { this._super(..arguments); getDOM(this).body.setAttribute('data-foo', 'hello') } }) ``` But this doesn't actually cause any output in fastboot, because the user's own `<body>` tag from index.html is always used instead. This PR allows attributes set on the simpledom body to be copied into the output. Given that the user's `index.html` is treated as a string and handled with string substitution, I'm forced to do a Regexp-based replaced that is less elegant than we would be able to do if we parsed the `index.html` file. But that seems like a pretty big change that would need more thought. So I think the string substitute is good enough here. add test
1 parent e981f63 commit 1df77df

6 files changed

Lines changed: 88065 additions & 2 deletions

File tree

src/result.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class Result {
4242
}
4343
}
4444

45-
return insertIntoIndexHTML(this._html, this._head, this._body);
45+
return insertIntoIndexHTML(this._html, this._head, this._body, this._bodyAttributes);
4646
}
4747

4848
/**
@@ -109,6 +109,12 @@ class Result {
109109
let head = this._doc.head;
110110
let body = this._doc.body;
111111

112+
if (body.attributes.length > 0) {
113+
this._bodyAttributes = HTMLSerializer.attributes(body.attributes);
114+
} else {
115+
this._bodyAttributes = null;
116+
}
117+
112118
if (head) {
113119
head = HTMLSerializer.serializeChildren(head);
114120
}
@@ -124,7 +130,7 @@ function missingTag(tag) {
124130
return Promise.reject(new Error(`Fastboot was not able to find ${tag} in base HTML. It could not replace the contents.`));
125131
}
126132

127-
function insertIntoIndexHTML(html, head, body) {
133+
function insertIntoIndexHTML(html, head, body, bodyAttributes) {
128134
if (!html) { return Promise.resolve(html); }
129135
let isBodyReplaced = false;
130136
let isHeadReplaced = false;
@@ -140,6 +146,12 @@ function insertIntoIndexHTML(html, head, body) {
140146
return '';
141147
});
142148

149+
if (bodyAttributes) {
150+
html = html.replace(/<body[^>]*/i, function(match) {
151+
return match + ' ' + bodyAttributes;
152+
});
153+
}
154+
143155
if (head && !isHeadReplaced) {
144156
return missingTag('<!--EMBER_CLI_FASTBOOT_HEAD-->');
145157
}

test/fastboot-test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,18 @@ describe("FastBoot", function() {
8787
});
8888
});
8989

90+
it("outputs body attributes from the fastboot app", function() {
91+
var fastboot = new FastBoot({
92+
distPath: fixture('custom-body-attrs')
93+
});
94+
95+
return fastboot.visit('/')
96+
.then(r => r.html())
97+
.then(html => {
98+
expect(html).to.match(/<body data-foo=1 +class="it-works"/);
99+
});
100+
});
101+
90102
it("can serialize the head and body", function() {
91103
var fastboot = new FastBoot({
92104
distPath: fixture('basic-app')

0 commit comments

Comments
 (0)