Issue
A node fails transforming, if it has 'heights'-attribute which contains more than one media query.
Also the attribute got removed on rendering, if it had failed on transforming.
For example
<amp-carousel
width="1"
height="1"
heights="(min-width:768px) 56.25%, (min-width:576px) and (max-width:767px) 100%, 133%"
layout="responsive"
type="slides"
role="region"
>
[...]
</amp-carousel>
Will be rendered by amp framework, without any validation errors and with correct media queries. But on SSR with amp optimizer i get following error and the 'heights'-attribute will be removed on rendered amp page:
AMP Optimizer ServerSideRendering Cannot remove boilerplate. Failed transforming heights="(min-width:768px) 56.25%, (min-width:576px) and (max-width:767px) 100%, 133%". Error: Invalid sizes definition '(min-width:768px) 56.25%, (min-width:576px) and (max-width:767px) 100%, 133%'
at parseSizes (/.../node_modules/@ampproject/toolbox-optimizer/lib/parseSizes.js:63:15)
at HeightsTransformer.transform (/.../node_modules/@ampproject/toolbox-optimizer/lib/transformers/ApplyCommonAttributes.js:127:21)
at ApplyCommonAttributes.apply (/.../node_modules/@ampproject/toolbox-optimizer/lib/transformers/ApplyCommonAttributes.js:207:76)
at ServerSideRendering.transform (/.../node_modules/@ampproject/toolbox-optimizer/lib/transformers/ServerSideRendering.js:105:27)
at /.../node_modules/@ampproject/toolbox-optimizer/lib/DomTransformer.js:208:61
at DomTransformer.doProfile (/.../node_modules/@ampproject/toolbox-optimizer/lib/DomTransformer.js:188:14)
at DomTransformer.transformTree (/.../node_modules/@ampproject/toolbox-optimizer/lib/DomTransformer.js:208:18)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async DomTransformer.transform (/.../node_modules/@ampproject/toolbox-optimizer/lib/DomTransformer.js:178:7)
at async DomTransformer.transformHtml (/.../node_modules/@ampproject/toolbox-optimizer/lib/DomTransformer.js:183:12)
Reason
parseSizes(string) throws an error for strings which has more than one ')' and trailing characters.
|
const size = sizeString.split(/\)\s+/); |
|
if (size.length !== 2) { |
|
throw new Error(`Invalid sizes definition '${string}'`); |
|
} |
When function transform(node, id) of HeightsTransformer gets called on nodes with 'height'-attributes, which contain a value with multiple media queries, parseSizes(string) will throw an error and ApplyCommonAttributes will catch that error and logs them.
|
try { |
|
nodeHasBeenTransformed = nodeHasBeenTransformed || transformer.transform(node, id); |
|
} catch (e) { |
|
this.log.debug( |
|
`Cannot remove boilerplate. Failed transforming ${attribute}="${node.attribs[attribute]}".`, |
|
e |
|
); |
|
this.canRemoveBoilerplate = false; |
|
} |
In function applyToCustomStyles(head, customStyles) of ApplyCommonAttributes the attributes 'heights', 'media' and 'sizes' will be removed on nodes which are in array nodesToTransform and my own value in 'heights'-attribute (which could not be transformed) will be removed. So the result is, the rendered amp component has no 'heights' attribute at all.
|
for (const node of this.nodesToTransform) { |
|
for (const attribute of Object.keys(this.attributeTransformations)) { |
|
delete node.attribs[attribute]; |
|
} |
|
} |
Solutions
First possible solution
One possible solution would be, that nodes which could not be transformed should be removed from array nodesToTransform, so the values could stay if transformation fails.
This could be done with following code:
this.nodesToTransform = this.nodesToTransform.filter(
(nodeToTransform) => nodeToTransform !== node
);
In context it would look like that:
try {
nodeHasBeenTransformed = nodeHasBeenTransformed || transformer.transform(node, id);
} catch (e) {
this.log.debug(
`Cannot remove boilerplate. Failed transforming ${attribute}="${node.attribs[attribute]}".`,
e
);
this.nodesToTransform = this.nodesToTransform.filter(
(nodeToTransform) => nodeToTransform !== node
);
this.canRemoveBoilerplate = false;
}
Second possible solution
An other solution would be, that function parseSize(string) would accept all values which amp framework does.
Maybe for the second solution it would make sense, to ignore all nodes where parseSizes(string) could not parse values, too.
PR
I've created a PR with a fix described in first solution: #1305
Issue
A node fails transforming, if it has 'heights'-attribute which contains more than one media query.
Also the attribute got removed on rendering, if it had failed on transforming.
For example
Will be rendered by amp framework, without any validation errors and with correct media queries. But on SSR with amp optimizer i get following error and the 'heights'-attribute will be removed on rendered amp page:
Reason
parseSizes(string)throws an error for strings which has more than one ')' and trailing characters.amp-toolbox/packages/optimizer/lib/parseSizes.js
Lines 61 to 64 in b367a2d
When function
transform(node, id)ofHeightsTransformergets called on nodes with 'height'-attributes, which contain a value with multiple media queries,parseSizes(string)will throw an error andApplyCommonAttributeswill catch that error and logs them.amp-toolbox/packages/optimizer/lib/transformers/ApplyCommonAttributes.js
Lines 206 to 214 in b367a2d
In function
applyToCustomStyles(head, customStyles)ofApplyCommonAttributesthe attributes 'heights', 'media' and 'sizes' will be removed on nodes which are in arraynodesToTransformand my own value in 'heights'-attribute (which could not be transformed) will be removed. So the result is, the rendered amp component has no 'heights' attribute at all.amp-toolbox/packages/optimizer/lib/transformers/ApplyCommonAttributes.js
Lines 246 to 250 in b367a2d
Solutions
First possible solution
One possible solution would be, that nodes which could not be transformed should be removed from array
nodesToTransform, so the values could stay if transformation fails.This could be done with following code:
In context it would look like that:
Second possible solution
An other solution would be, that function
parseSize(string)would accept all values which amp framework does.Maybe for the second solution it would make sense, to ignore all nodes where parseSizes(string) could not parse values, too.
PR
I've created a PR with a fix described in first solution: #1305