packaton 0.0.15 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +1 -1
- package/src/plugins-prod/HtmlCompiler.js +27 -12
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Packaton WIP
|
|
2
2
|
|
|
3
|
-
Static
|
|
3
|
+
Static Site Generator (SSG). Inlines CSS and JS and
|
|
4
|
+
creates a header file with their corresponding CSP hashes.
|
|
4
5
|
|
|
5
6
|
## Limitations
|
|
6
7
|
- `src` and `href` URLs must be absolute
|
|
7
|
-
- can't write inline scripts or css (all must be in an external file, packaton inlines them)
|
|
8
8
|
- must have an index
|
|
9
9
|
- Ignored Documents start with `_`, so you can't have routes that begin with _
|
|
10
10
|
- Non-Documents and Files outside config.assetsDir are not automatically copied over,
|
package/package.json
CHANGED
|
@@ -69,22 +69,24 @@ export class HtmlCompiler {
|
|
|
69
69
|
.map(([, body]) => body)
|
|
70
70
|
.join('\n'))
|
|
71
71
|
|
|
72
|
-
this.scriptsModuleJs = await
|
|
72
|
+
this.scriptsModuleJs = await Promise.all(scripts
|
|
73
73
|
.filter(([type]) => type === 'module')
|
|
74
|
-
.map(([, body]) => body)
|
|
75
|
-
|
|
74
|
+
.map(([, body]) => this.#minifyJS(body)))
|
|
75
|
+
|
|
76
|
+
this.scriptsNonJs = scripts.filter(([type]) => type !== 'application/javascript' && type !== 'module')
|
|
76
77
|
|
|
77
78
|
this.scriptsNonJs = scripts
|
|
78
79
|
.filter(([type]) => type !== 'application/javascript' && type !== 'module')
|
|
79
80
|
|
|
80
81
|
if (this.scriptsJs)
|
|
81
82
|
this.html = this.html.replace('</body>', `\n<script>${this.scriptsJs}</script></body>`)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
this.html = this.html.replace('</body>', `\n<script type="module">${
|
|
83
|
+
|
|
84
|
+
for (const body of this.scriptsModuleJs)
|
|
85
|
+
this.html = this.html.replace('</body>', `\n<script type="module">${body}</script></body>`)
|
|
85
86
|
|
|
86
87
|
for (const [type, body] of this.scriptsNonJs)
|
|
87
88
|
this.html = this.html.replace('</body>', `\n<script type="${type}">${body}</script></body>`)
|
|
89
|
+
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
csp() {
|
|
@@ -94,17 +96,19 @@ export class HtmlCompiler {
|
|
|
94
96
|
const jsScriptHash = this.scriptsJs
|
|
95
97
|
? `'${this.hash256(this.scriptsJs)}'`
|
|
96
98
|
: '' // TODO maybe self?
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const nonJsScriptHashes = this.scriptsNonJs
|
|
101
|
-
|
|
99
|
+
|
|
100
|
+
const jsModulesHashes = this.scriptsModuleJs.map(body => `'${this.hash256(body)}'`).join(' ')
|
|
101
|
+
|
|
102
|
+
const nonJsScriptHashes = this.scriptsNonJs.map(([, body]) => `'${this.hash256(body)}'`).join(' ')
|
|
103
|
+
|
|
102
104
|
const externalScriptHashes = this.externalScripts.map(url => `${new URL(url).origin}`).join(' ')
|
|
105
|
+
|
|
106
|
+
const inlineScriptsHashes = this.extractInlineScripts().map(body => `'${this.hash256(body)}'`).join(' ')
|
|
103
107
|
return [
|
|
104
108
|
`default-src 'self'`,
|
|
105
109
|
`img-src 'self' data:`, // data: is for Safari's video player icons and for CSS bg images
|
|
106
110
|
`style-src ${cssHash}`,
|
|
107
|
-
`script-src-elem ${nonJsScriptHashes} ${jsScriptHash} ${
|
|
111
|
+
`script-src-elem ${nonJsScriptHashes} ${jsScriptHash} ${jsModulesHashes} ${externalScriptHashes} ${inlineScriptsHashes} 'self'`,
|
|
108
112
|
`frame-ancestors 'none'`
|
|
109
113
|
].join('; ')
|
|
110
114
|
}
|
|
@@ -144,4 +148,15 @@ export class HtmlCompiler {
|
|
|
144
148
|
]
|
|
145
149
|
})
|
|
146
150
|
}
|
|
151
|
+
|
|
152
|
+
extractInlineScripts() {
|
|
153
|
+
const reExtractInlineScripts = /<script\b([^>]*?)>([\s\S]*?)<\/script>/g
|
|
154
|
+
return Array.from(this.html.matchAll(reExtractInlineScripts), m => {
|
|
155
|
+
const attrs = m[1]
|
|
156
|
+
const body = m[2]
|
|
157
|
+
return attrs.includes('src=')
|
|
158
|
+
? null
|
|
159
|
+
: body
|
|
160
|
+
}).filter(Boolean)
|
|
161
|
+
}
|
|
147
162
|
}
|