forked from angular/angular-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnonce.ts
65 lines (52 loc) · 1.79 KB
/
nonce.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { htmlRewritingStream } from './html-rewriting-stream';
/**
* Pattern matching the name of the Angular nonce attribute. Note that this is
* case-insensitive, because HTML attribute names are case-insensitive as well.
*/
const NONCE_ATTR_PATTERN = /ngCspNonce/i;
/**
* Finds the `ngCspNonce` value and copies it to all inline `<style>` and `<script> `tags.
* @param html Markup that should be processed.
*/
export async function addNonce(html: string): Promise<string> {
const nonce = await findNonce(html);
if (!nonce) {
return html;
}
const { rewriter, transformedContent } = await htmlRewritingStream(html);
rewriter.on('startTag', (tag) => {
if (
(tag.tagName === 'style' || tag.tagName === 'script') &&
!tag.attrs.some((attr) => attr.name === 'nonce')
) {
tag.attrs.push({ name: 'nonce', value: nonce });
}
rewriter.emitStartTag(tag);
});
return transformedContent();
}
/** Finds the Angular nonce in an HTML string. */
async function findNonce(html: string): Promise<string | null> {
// Inexpensive check to avoid parsing the HTML when we're sure there's no nonce.
if (!NONCE_ATTR_PATTERN.test(html)) {
return null;
}
const { rewriter, transformedContent } = await htmlRewritingStream(html);
let nonce: string | null = null;
rewriter.on('startTag', (tag) => {
const nonceAttr = tag.attrs.find((attr) => NONCE_ATTR_PATTERN.test(attr.name));
if (nonceAttr?.value) {
nonce = nonceAttr.value;
rewriter.stop(); // Stop parsing since we've found the nonce.
}
});
await transformedContent();
return nonce;
}