<commit_before># AMP cache modifications best practices

These are guidelines for what AMP cache implementations should look like. Some items are required for overall security of the platform while others are suggestions for performance improvements. All modifications are made to both AMP and AMP4ADS documents except where noted.

For example, given a [recent version](https://github.com/ampproject/amphtml/tree/master/spec/amp-cache-modifications.everything.original.html) of [everything.amp.html](https://github.com/ampproject/amphtml/blob/master/examples/everything.amp.html), the output after modifications will be [this version](https://github.com/ampproject/amphtml/tree/master/spec/amp-cache-modifications.everything.out.html).


### HTML Sanitization

The AMP Cache parses and re-serializes all documents to remove any ambiguities in parsing the document which might result in subtly different parses in different browsers.

#### All HTML comments are stripped

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<foo><!-- comment --></foo>` | `<foo></foo>` |

</details>

#### Tag and attribute names are lowercased

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<P DATA-FOO=BAR>` | `<p data-foo=BAR>` |

</details>

#### Attribute values are consistently quoted and escaped

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<p data-foo=’< >’>` | `<p data-foo="&lt; &gt">` |

</details>

#### All tags are closed, except for HTML5 void elements

[Void elements](https://www.w3.org/TR/html5/syntax.html#void-elements)  are tags that have no end tag and also no contents. All other tags are closed.

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<foo><bar></foo>`<br>`<br/>` | `<foo><bar></bar></foo>`<br>`<br>` |

</details>

#### Whitespace inside tags is stripped

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<p    data-foo=bar    >` | `<p data-foo=bar>` |

</details>

#### Text is escaped

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `3 < 4` | `3 &lt; 4` |

</details>

#### Encoded text characters are simplified, using UTF-8 equivalent characters

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `&nbsp;` | `"\u00A0"` |
| `&#x61;` | `a` |
| `&#00000000000039;` | ` &#39;` |

</details>

#### Move elements after `<body>`, which are only allowed in `<body>`, into the `<body>`. This includes text.

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<body></body><div>foo</div>text` | `<body><div>foo</div>text</body>` |

</details>


### URL Rewrites

The AMP Cache rewrites URLs found in the AMP HTML for two purposes. One is to rebase relative URLs found in the document so that the URL remains the same when loaded from the AMP Cache. The other reason is to improve performance by selecting a different equivalent resource. This includes rewriting image and font URLs to use a cached copy and rewriting AMP javascript URLs to use a copy with longer cache lifetimes.

#### All relative `href` , `src` and `data-iframe-src` URLs are rewritten as absolute URLs

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<a href=foo.html target=_top>Lorem ipsum</a>` | `<a href=https://example.com/foo.html target=_top>Lorem ipsum</a>` |
| `<amp-list src="list.json" ...>...</amp-list>` | `<amp-list src="https://example.com/list.json" ...>...</amp-list>` |
| `<amp-install-serviceworker data-iframe-src="sw.html"...></amp-install-serviceworker>` | `<amp-install-serviceworker data-iframe-src="https://example.com/sw.html"...></amp-install-serviceworker>` |

</details>

#### All relative `form[action]` and `form[action-xhr]` URLs are rewritten as absolute URLs

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<form action=/subscribe>...</form>` | `<form action=https://example.com/subscribe>...</form>` |

</details>

#### All relative `@font-face` CSS URLs are rewritten as absolute URLs

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `@font-face {`<br>`font-family: Foo;`<br>`src: url(font.woff);`<br>`}` | `@font-face {`<br>`font-family: Foo;`<br>`src: url(https://example.com/font.woff);`<br>`}` |

</details>

#### All image URLs are rewritten as AMP cache URLs

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<amp-img src=https://example.com/foo.png>`<br>`<amp-video poster=bar.png>` | `<amp-img src=/i/s/foo.png>`<br>`<amp-video poster=/i/s/bar.png>` |

</details>

#### Anchor tags must have a target of `_blank` or `_top`

*Condition*:
If `<a>` tag does not have attribute `target=_blank` or `target=_top` then add `target=_top`. All other `target` values are rewritten to `_top`.

<details>
<summary>example</summary>

| before | after |<commit_msg>AMP cache modification document update (#7611)<commit_after># AMP cache modifications best practices

These are guidelines for what AMP cache implementations should look like. Some items are required for overall security of the platform while others are suggestions for performance improvements. All modifications are made to both AMP and AMP4ADS documents except where noted.

For example, given a [recent version](https://github.com/ampproject/amphtml/tree/master/spec/amp-cache-modifications.everything.original.html) of [everything.amp.html](https://github.com/ampproject/amphtml/blob/master/examples/everything.amp.html), the output after modifications will be [this version](https://github.com/ampproject/amphtml/tree/master/spec/amp-cache-modifications.everything.out.html).


### HTML Sanitization

The AMP Cache parses and re-serializes all documents to remove any ambiguities in parsing the document which might result in subtly different parses in different browsers.

#### All HTML comments are stripped

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<foo><!-- comment --></foo>` | `<foo></foo>` |

</details>

#### Tag and attribute names are lowercased

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<P DATA-FOO=BAR>` | `<p data-foo=BAR>` |

</details>

#### Attribute values are consistently quoted and escaped

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<p data-foo=’< >’>` | `<p data-foo="&lt; &gt">` |

</details>

#### All tags are closed, except for HTML5 void elements

[Void elements](https://www.w3.org/TR/html5/syntax.html#void-elements)  are tags that have no end tag and also no contents. All other tags are closed.

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<foo><bar></foo>`<br>`<br/>` | `<foo><bar></bar></foo>`<br>`<br>` |

</details>

#### Whitespace inside tags is stripped

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<p    data-foo=bar    >` | `<p data-foo=bar>` |

</details>

#### Text is escaped

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `3 < 4` | `3 &lt; 4` |

</details>

#### Encoded text characters are simplified, using UTF-8 equivalent characters

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `&nbsp;` | `"\u00A0"` |
| `&#x61;` | `a` |
| `&#00000000000039;` | ` &#39;` |

</details>

#### Move elements after `<body>`, which are only allowed in `<body>`, into the `<body>`. This includes text.

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<body></body><div>foo</div>text` | `<body><div>foo</div>text</body>` |

</details>


### URL Rewrites

The AMP Cache rewrites URLs found in the AMP HTML for two purposes. One is to rebase relative URLs found in the document so that the URL remains the same when loaded from the AMP Cache. The other reason is to improve performance by selecting a different equivalent resource. This includes rewriting image and font URLs to use a cached copy and rewriting AMP javascript URLs to use a copy with longer cache lifetimes.

#### All relative `href` , `src` and `data-iframe-src` URLs are rewritten as absolute URLs

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<a href=foo.html target=_top>Lorem ipsum</a>` | `<a href=https://example.com/foo.html target=_top>Lorem ipsum</a>` |
| `<amp-list src="list.json" ...>...</amp-list>` | `<amp-list src="https://example.com/list.json" ...>...</amp-list>` |
| `<amp-install-serviceworker data-iframe-src="sw.html"...></amp-install-serviceworker>` | `<amp-install-serviceworker data-iframe-src="https://example.com/sw.html"...></amp-install-serviceworker>` |

</details>

#### All relative `form[action]` and `form[action-xhr]` URLs are rewritten as absolute URLs

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<form action=/subscribe>...</form>` | `<form action=https://example.com/subscribe>...</form>` |

</details>

#### All relative `@font-face` CSS URLs are rewritten as absolute URLs

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `@font-face {`<br>`font-family: Foo;`<br>`src: url(font.woff);`<br>`}` | `@font-face {`<br>`font-family: Foo;`<br>`src: url(https://example.com/font.woff);`<br>`}` |

</details>

#### All image URLs are rewritten as AMP cache URLs except those in `amp-mustache` `template`

<details>
<summary>example</summary>

| before | after |
| --- | --- |
| `<amp-img src=https://example.com/foo.png></amp-img>` | `<amp-img src=/i/s/foo.png></amp-img>` |
| `<amp-img srcset="https://example.com/bar.png 1080w, https://example.com/bar-400.png 400w">`| `<amp-img src="/i/s/bar.png 1080w, /i/s/bar-400.png 400w">` |
| `<amp-anim src=foo.gif></amp-anim>` | `<amp-anim src=/i/s/foo.gif></amp-anim>` |
| `<amp-video poster=bar.png>` | `<amp-video poster=/i/s/bar.png>` |

</details>

#### Anchor tags must have a target of `_blank` or `_top`

*Condition*:
If `<a>` tag does not have attribute `target=_blank` or `target=_top` then add `target=_top`. All other `target` values are rewritten to `_top`.

<details>
<summary>example</summary>

| before | after |
{'fraction_non_alphanumeric': 0.19338875692794932, 'fraction_numerical': 0.00831353919239905, 'mean_word_length': 4.004952947003467, 'pattern_counts': {'":': 0, '<': 239, '<?xml version=': 0, '>': 237, 'https://': 22, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4099543', 'n_tokens_mistral': 3519, 'n_tokens_neox': 3297, 'n_words': 928}