Skip to content

Commit 25a6212

Browse files
feat: generate JS script hashes for CSP
Avoids the need to hard code the hashes when using a CSP. Depends on thuliteio/core#27 Signed-off-by: Daniel F. Dickinson <dfdpublic@wildtechgarden.ca>
1 parent 5e59abe commit 25a6212

File tree

5 files changed

+256
-193
lines changed

5 files changed

+256
-193
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{{- /* ESBUILD.HTML - Build javascript modules with esbuild
2+
* Simple Usage: {{ partial "esbuild" "js/file.js" }}
3+
* Simple Usage: {{ partial "esbuild" (dict "src" "js/file.js" "load" "defer/async" "babel" true ) }}
4+
* Parameters:
5+
* src - javascript file to build, relative to assets folder. Must include file extension can be .js or .ts
6+
* load - can set to "defer" or "async" defaults to null.
7+
* babel - set to true to transpile your js using babel. Note: all js is lowered to es6 by default.
8+
* for babel you must have the required babel dependencies installed , and configured
9+
* see hugo babel doc https://gohugo.io/hugo-pipes/babel
10+
* use the babel option if esbuild can't handle lowering your es6+ code, or you wish to go lower than es6
11+
* for unsupported es6+ syntax see
12+
* https://esbuild.github.io/content-types/#javascript
13+
*
14+
* example for checking hugo env from js file
15+
*
16+
* import * as params from '@params';
17+
*
18+
* if (params.env === 'development') {
19+
* console.log('hugo deveolopment environment')
20+
* } else {
21+
* console.log('hugo production environment')
22+
* }
23+
*
24+
* ----------------------------------------------------------------*/ -}}
25+
{{- /* get source from . or .src and fetch resource */ -}}
26+
{{- $src := . -}}
27+
{{- if not $src -}}
28+
{{- errorf `You must provide a source as the partial context, or (dict .src "path")` -}}
29+
{{- end -}}
30+
31+
{{- /* set .load only if valid option provided in dict */ -}}
32+
{{- $load := "" -}}
33+
34+
{{- /* set .babel only if provided in dict */ -}}
35+
{{- $babel := false -}}
36+
37+
{{- /* check for dict */ -}}
38+
{{- if reflect.IsMap . -}}
39+
{{- with .src -}}
40+
{{- $src = . -}}
41+
{{- else -}}
42+
{{- errorf "as you are providing params as a dict, you must provide the source file as .src" -}}
43+
{{- end -}}
44+
{{- with .load -}}
45+
{{- $loadOpts := slice "async" "defer" -}}
46+
{{- if not (in $loadOpts . ) -}}
47+
{{- errorf "Invalid .load %q for file /assets/%s - valid options are %s." . $src (delimit $loadOpts ", " " and " ) -}}
48+
{{- end -}}
49+
{{- $load = . }}
50+
{{- end -}}
51+
{{- with .babel -}}
52+
{{- if eq . true -}}
53+
{{- $babel = true -}}
54+
{{- else -}}
55+
{{- errorf "Invalid .babel option of %q. The only valid option is true" . -}}
56+
{{- end -}}
57+
{{- end -}}
58+
{{ end }}
59+
60+
{{- /* get the resource from .src path */ -}}
61+
{{- $resource := resources.Get $src -}}
62+
63+
{{- /* if resources.Get fails */ -}}
64+
{{- if not $resource }}
65+
{{- errorf "No js resource found at /assets/%s" $src -}}
66+
{{- end -}}
67+
68+
{{- /* pass hugo env to the js file as a param */ -}}
69+
{{- $paramsDefault := (dict "env" hugo.Environment) -}}
70+
{{- $params := "" -}}
71+
{{- with .params -}}
72+
{{- $params = merge $paramsDefault . -}}
73+
{{- else -}}
74+
{{- $params = $paramsDefault -}}
75+
{{- end -}}
76+
{{- $resource = $resource | resources.ExecuteAsTemplate $src . -}}
77+
78+
{{- /* standard production configuration for es build */ -}}
79+
{{- $jsConfig := (dict "target" "es2015" "minify" "true" "params" $params) }}
80+
81+
{{- /* is .babelEs6 is set to true - use babel to lower to es6 */ -}}
82+
{{- $js := $resource -}}
83+
{{- if $babel -}}
84+
{{- $babelConfig := (dict "noComments" true "minified" true "config" "config/babel.module.config.js") -}}
85+
{{- $js = $js | js.Build $jsConfig | babel $babelConfig | fingerprint -}}
86+
{{- else if eq (hugo.Environment) "development" -}}
87+
{{- $jsConfig = (dict "sourceMap" "inline" "target" "es2015" "params" $params) -}}
88+
{{- $js = $js | js.Build $jsConfig | fingerprint -}}
89+
{{- else -}}
90+
{{- $js = $js | js.Build $jsConfig | fingerprint -}}
91+
{{- end -}}
92+
{{- return (dict
93+
"src" $src
94+
"js" $js
95+
"load" $load
96+
"hash" $js.Data.Integrity
97+
) -}}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
{{- /* ESBUILD-HASH.HTML - Build javascript modules with esbuild
2+
* Simple Usage: {{ partial "esbuild" "js/file.js" }}
3+
* Simple Usage: {{ partial "esbuild" (dict "src" "js/file.js" "load" "defer/async" "babel" true ) }}
4+
* Parameters:
5+
* src - javascript file to build, relative to assets folder. Must include file extension can be .js or .ts
6+
* load - can set to "defer" or "async" defaults to null.
7+
* babel - set to true to transpile your js using babel. Note: all js is lowered to es6 by default.
8+
* for babel you must have the required babel dependencies installed , and configured
9+
* see hugo babel doc https://gohugo.io/hugo-pipes/babel
10+
* use the babel option if esbuild can't handle lowering your es6+ code, or you wish to go lower than es6
11+
* for unsupported es6+ syntax see
12+
* https://esbuild.github.io/content-types/#javascript
13+
*
14+
* example for checking hugo env from js file
15+
*
16+
* import * as params from '@params';
17+
*
18+
* if (params.env === 'development') {
19+
* console.log('hugo deveolopment environment')
20+
* } else {
21+
* console.log('hugo production environment')
22+
* }
23+
*
24+
* ----------------------------------------------------------------*/ -}}
25+
{{- /* get source from . or .src and fetch resource */ -}}
26+
{{- $src := . -}}
27+
{{- if not $src -}}
28+
{{- errorf `You must provide a source as the partial context, or (dict .src "path")` -}}
29+
{{- end -}}
30+
31+
{{- /* set .load only if valid option provided in dict */ -}}
32+
{{- $load := "" -}}
33+
34+
{{- /* set .babel only if provided in dict */ -}}
35+
{{- $babel := false -}}
36+
37+
{{- /* check for dict */ -}}
38+
{{- if reflect.IsMap . -}}
39+
{{- with .src -}}
40+
{{- $src = . -}}
41+
{{- else -}}
42+
{{- errorf "as you are providing params as a dict, you must provide the source file as .src" -}}
43+
{{- end -}}
44+
{{- with .load -}}
45+
{{- $loadOpts := slice "async" "defer" -}}
46+
{{- if not (in $loadOpts . ) -}}
47+
{{- errorf "Invalid .load %q for file /assets/%s - valid options are %s." . $src (delimit $loadOpts ", " " and " ) -}}
48+
{{- end -}}
49+
{{- $load = . }}
50+
{{- end -}}
51+
{{- with .babel -}}
52+
{{- if eq . true -}}
53+
{{- $babel = true -}}
54+
{{- else -}}
55+
{{- errorf "Invalid .babel option of %q. The only valid option is true" . -}}
56+
{{- end -}}
57+
{{- end -}}
58+
{{ end }}
59+
60+
{{- /* get the resource from .src path */ -}}
61+
{{- $resource := resources.Get $src -}}
62+
63+
{{- /* if resources.Get fails */ -}}
64+
{{- if not $resource }}
65+
{{- errorf "No js resource found at /assets/%s" $src -}}
66+
{{- end -}}
67+
68+
{{- /* pass hugo env to the js file as a param */ -}}
69+
{{- /* $params := (dict "env" hugo.Environment) */ -}}
70+
71+
{{- $paramsDefault := (dict "env" hugo.Environment) -}}
72+
{{- $params := "" -}}
73+
{{- with .params -}}
74+
{{- $params = merge $paramsDefault . -}}
75+
{{- else -}}
76+
{{- $params = $paramsDefault -}}
77+
{{- end -}}
78+
79+
{{- /* standard production configuration for es build */ -}}
80+
{{- $jsConfig := (dict "target" "es2015" "minify" "true" "params" $params) }}
81+
{{- $js := $resource -}}
82+
83+
{{- /* is .babelEs6 is set to true - use babel to lower to es6 */ -}}
84+
{{- if $babel -}}
85+
{{- $babelConfig := (dict "noComments" true "minified" true "config" "config/babel.module.config.js") -}}
86+
{{- $js = $js | js.Build $jsConfig | babel $babelConfig | fingerprint -}}
87+
{{- else if eq (hugo.Environment) "development" -}}
88+
{{- $jsConfig = (dict "sourceMap" "inline" "target" "es2015" "params" $params) -}}
89+
{{- $js = $js | js.Build $jsConfig | fingerprint -}}
90+
{{- else -}}
91+
{{- $js = $js | js.Build $jsConfig | fingerprint -}}
92+
{{- end -}}
93+
{{- return (dict
94+
"src" $src
95+
"js" $js
96+
"load" $load
97+
"hash" $js.Data.Integrity
98+
) -}}
Lines changed: 10 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,10 @@
1-
{{- /* ESBUILD.HTML - Build javascript modules with esbuild
2-
* Simple Usage: {{ partial "esbuild" "js/file.js" }}
3-
* Simple Usage: {{ partial "esbuild" (dict "src" "js/file.js" "load" "defer/async" "babel" true ) }}
4-
* Parameters:
5-
* src - javascript file to build, relative to assets folder. Must include file extension can be .js or .ts
6-
* load - can set to "defer" or "async" defaults to null.
7-
* babel - set to true to transpile your js using babel. Note: all js is lowered to es6 by default.
8-
* for babel you must have the required babel dependencies installed , and configured
9-
* see hugo babel doc https://gohugo.io/hugo-pipes/babel
10-
* use the babel option if esbuild can't handle lowering your es6+ code, or you wish to go lower than es6
11-
* for unsupported es6+ syntax see
12-
* https://esbuild.github.io/content-types/#javascript
13-
*
14-
* example for checking hugo env from js file
15-
*
16-
* import * as params from '@params';
17-
*
18-
* if (params.env === 'development') {
19-
* console.log('hugo deveolopment environment')
20-
* } else {
21-
* console.log('hugo production environment')
22-
* }
23-
*
24-
* ----------------------------------------------------------------*/ -}}
25-
{{- /* get source from . or .src and fetch resource */ -}}
26-
{{- $src := . -}}
27-
{{- if not $src -}}
28-
{{- errorf `You must provide a source as the partial context, or (dict .src "path")` -}}
29-
{{- end -}}
30-
31-
{{- /* set .load only if valid option provided in dict */ -}}
32-
{{- $load := "" -}}
33-
34-
{{- /* set .babel only if provided in dict */ -}}
35-
{{- $babel := false -}}
36-
37-
{{- /* check for dict */ -}}
38-
{{- if reflect.IsMap . -}}
39-
{{- with .src -}}
40-
{{- $src = . -}}
41-
{{- else -}}
42-
{{- errorf "as you are providing params as a dict, you must provide the source file as .src" -}}
43-
{{- end -}}
44-
{{- with .load -}}
45-
{{- $loadOpts := slice "async" "defer" -}}
46-
{{- if not (in $loadOpts . ) -}}
47-
{{- errorf "Invalid .load %q for file /assets/%s - valid options are %s." . $src (delimit $loadOpts ", " " and " ) -}}
48-
{{- end -}}
49-
{{- $load = . }}
50-
{{- end -}}
51-
{{- with .babel -}}
52-
{{- if eq . true -}}
53-
{{- $babel = true -}}
54-
{{- else -}}
55-
{{- errorf "Invalid .babel option of %q. The only valid option is true" . -}}
56-
{{- end -}}
57-
{{- end -}}
58-
{{ end }}
59-
60-
{{- /* get the resource from .src path */ -}}
61-
{{- $resource := resources.Get $src -}}
62-
63-
{{- /* if resources.Get fails */ -}}
64-
{{- if not $resource }}
65-
{{- errorf "No js resource found at /assets/%s" $src -}}
66-
{{- end -}}
67-
68-
{{- /* pass hugo env to the js file as a param */ -}}
69-
{{- $paramsDefault := (dict "env" hugo.Environment) -}}
70-
{{- $params := "" -}}
71-
{{- with .params -}}
72-
{{- $params = merge $paramsDefault . -}}
73-
{{- else -}}
74-
{{- $params = $paramsDefault -}}
75-
{{- end -}}
76-
{{- $resource = $resource | resources.ExecuteAsTemplate $src . -}}
77-
78-
{{- /* standard production configuration for es build */ -}}
79-
{{- $jsConfig := (dict "target" "es2015" "minify" "true" "params" $params) }}
80-
81-
{{- /* is .babelEs6 is set to true - use babel to lower to es6 */ -}}
82-
{{- $js := $resource -}}
83-
{{- if $babel -}}
84-
{{- $babelConfig := (dict "noComments" true "minified" true "config" "config/babel.module.config.js") -}}
85-
{{- $js = $js | js.Build $jsConfig | babel $babelConfig | fingerprint -}}
86-
{{- else if eq (hugo.Environment) "development" -}}
87-
{{- $jsConfig = (dict "sourceMap" "inline" "target" "es2015" "params" $params) -}}
88-
{{- $js = $js | js.Build $jsConfig | fingerprint -}}
89-
{{- else -}}
90-
{{- $js = $js | js.Build $jsConfig | fingerprint -}}
91-
{{- end -}}
92-
93-
<script {{ with $load }}{{ . | safeHTMLAttr }}{{ end }}
94-
src="{{- $js.RelPermalink -}}"
95-
integrity="{{- $js.Data.Integrity -}}">
96-
</script>
1+
{{- /* Call out to ESBILD-HASH-TEMPLATTE.HTML to generate JS and calculate hash
2+
* We do it this way so the hash can be available for adding to the
3+
* Content-Security-Policy headers
4+
*/ -}}
5+
{{- $scriptHash := partial "footer/esbuild-hash-template.html" . }}
6+
{{- with $scriptHash }}
7+
<script {{ with $scriptHash.load }}{{ . | safeHTMLAttr }}{{ end }}
8+
src="{{- $scriptHash.js.RelPermalink -}}"
9+
integrity="{{- $scriptHash.js.Data.Integrity -}}"></script>
10+
{{ end -}}

0 commit comments

Comments
 (0)