@@ -51,9 +51,11 @@ class Result {
5151 return insertIntoIndexHTML (
5252 this . _html ,
5353 this . _htmlAttributes ,
54+ this . _htmlClass ,
5455 this . _head ,
5556 this . _body ,
56- this . _bodyAttributes
57+ this . _bodyAttributes ,
58+ this . _bodyClass
5759 ) ;
5860 }
5961
@@ -72,9 +74,11 @@ class Result {
7274 return insertIntoIndexHTML (
7375 this . _html ,
7476 this . _htmlAttributes ,
77+ this . _htmlClass ,
7578 this . _head ,
7679 this . _body ,
77- this . _bodyAttributes
80+ this . _bodyAttributes ,
81+ this . _bodyClass
7882 ) . then ( html => {
7983 let docParts = html . match ( HTML_HEAD_REGEX ) ;
8084 if ( ! docParts || docParts . length === 1 ) {
@@ -173,17 +177,13 @@ class Result {
173177 let head = this . _doc . head ;
174178 let body = this . _doc . body ;
175179
176- if ( htmlElement . attributes . length > 0 ) {
177- this . _htmlAttributes = HTMLSerializer . attributes ( htmlElement . attributes ) ;
178- } else {
179- this . _htmlAttributes = null ;
180- }
180+ let { klass : htmlClass , attributes : htmlAttributes } = extractExtraAttributes ( htmlElement ) ;
181+ this . _htmlClass = htmlClass ;
182+ this . _htmlAttributes = htmlAttributes ;
181183
182- if ( body . attributes . length > 0 ) {
183- this . _bodyAttributes = HTMLSerializer . attributes ( body . attributes ) ;
184- } else {
185- this . _bodyAttributes = null ;
186- }
184+ let { klass : bodyClass , attributes : bodyAttributes } = extractExtraAttributes ( body ) ;
185+ this . _bodyClass = bodyClass ;
186+ this . _bodyAttributes = bodyAttributes ;
187187
188188 if ( head ) {
189189 head = HTMLSerializer . serializeChildren ( head ) ;
@@ -198,13 +198,44 @@ class Result {
198198 }
199199}
200200
201+ function extractExtraAttributes ( element ) {
202+ let klass ;
203+ let attributes ;
204+ if ( element . attributes . length > 0 ) {
205+ let elementClass = element . attributes . find ( attr => attr . name === 'class' ) ;
206+ if ( elementClass ) {
207+ klass = elementClass ;
208+ let otherAttrs = element . attributes . filter ( attr => attr . name !== 'class' ) ;
209+ if ( otherAttrs . length > 0 ) {
210+ attributes = HTMLSerializer . attributes ( otherAttrs ) ;
211+ } else {
212+ attributes = null ;
213+ }
214+ } else {
215+ attributes = HTMLSerializer . attributes ( element . attributes ) ;
216+ klass = null ;
217+ }
218+ } else {
219+ klass = attributes = null ;
220+ }
221+ return { klass, attributes } ;
222+ }
223+
201224function missingTag ( tag ) {
202225 throw new Error (
203226 `Fastboot was not able to find ${ tag } in base HTML. It could not replace the contents.`
204227 ) ;
205228}
206229
207- async function insertIntoIndexHTML ( html , htmlAttributes , head , body , bodyAttributes ) {
230+ async function insertIntoIndexHTML (
231+ html ,
232+ htmlAttributes ,
233+ htmlClass ,
234+ head ,
235+ body ,
236+ bodyAttributes ,
237+ bodyClass
238+ ) {
208239 if ( ! html ) {
209240 return Promise . resolve ( html ) ;
210241 }
@@ -222,12 +253,22 @@ async function insertIntoIndexHTML(html, htmlAttributes, head, body, bodyAttribu
222253 return '' ;
223254 } ) ;
224255
256+ if ( htmlClass ) {
257+ html = html . replace ( / ( < h t m l .* ) c l a s s = \" ( [ ^ " ] * ) \" ( [ ^ > ] * ) / i, function ( _ , prefix , klass , suffix ) {
258+ return prefix + `class="${ klass + ' ' + htmlClass . value } "` + suffix ;
259+ } ) ;
260+ }
225261 if ( htmlAttributes ) {
226262 html = html . replace ( / < h t m l [ ^ > ] * / i, function ( match ) {
227263 return match + ' ' + htmlAttributes ;
228264 } ) ;
229265 }
230266
267+ if ( bodyClass ) {
268+ html = html . replace ( / ( < b o d y .* ) c l a s s = \" ( [ ^ " ] * ) \" ( [ ^ > ] * ) / i, function ( _ , prefix , klass , suffix ) {
269+ return prefix + `class="${ klass + ' ' + bodyClass . value } "` + suffix ;
270+ } ) ;
271+ }
231272 if ( bodyAttributes ) {
232273 html = html . replace ( / < b o d y [ ^ > ] * / i, function ( match ) {
233274 return match + ' ' + bodyAttributes ;
0 commit comments