ampproject / ampproject/amp-toolbox

SSR: Transforming of nodes with attribute 'heights' fails, if value contains multiple media queries

Open
#1,304 5 comments 1 reaction 0 assignees View on GitHub
Dominant language
HTML
Stars
459
Forks
242
PR merge metrics
No merged PRs in 30d

Description

# 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

```html

[...]

```

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:

```javascript
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.

https://github.com/ampproject/amp-toolbox/blob/b367a2db78e1934e5c3e72727777e7c29d6a3b35/packages/optimizer/lib/parseSizes.js#L61-L64

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.

https://github.com/ampproject/amp-toolbox/blob/b367a2db78e1934e5c3e72727777e7c29d6a3b35/packages/optimizer/lib/transformers/ApplyCommonAttributes.js#L206-L214

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.

https://github.com/ampproject/amp-toolbox/blob/b367a2db78e1934e5c3e72727777e7c29d6a3b35/packages/optimizer/lib/transformers/ApplyCommonAttributes.js#L246-L250

# 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:

```javascript
this.nodesToTransform = this.nodesToTransform.filter(
(nodeToTransform) => nodeToTransform !== node
);
```

In context it would look like that:

```javascript
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: https://github.com/ampproject/amp-toolbox/pull/1305

Contributor guide

Open the contributing guide

Research direction

Start with packages/optimizer/lib/parseSizes.js and the HeightsTransformer and ApplyCommonAttributes paths named in the stack trace. Reproduce the AMP carousel case with multiple media queries, then inspect the existing PR #1305 and verify that a failed transformation does not remove the original heights attribute while valid values still transform correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
backend, tooling
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.