diff --git a/.eleventy.js b/.eleventy.js
index ed8bad0..f68f173 100644
--- a/.eleventy.js
+++ b/.eleventy.js
@@ -70,7 +70,7 @@ module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(require("./_11ty/img-dim.js"));
eleventyConfig.addPlugin(require("./_11ty/json-ld.js"));
eleventyConfig.addPlugin(require("./_11ty/optimize-html.js"));
- eleventyConfig.addPlugin(require("./_11ty/csp.js"));
+ eleventyConfig.addPlugin(require("./_11ty/apply-csp.js"));
eleventyConfig.setDataDeepMerge(true);
eleventyConfig.addLayoutAlias("post", "layouts/post.njk");
eleventyConfig.addNunjucksAsyncFilter("addHash", function (
@@ -113,6 +113,14 @@ module.exports = function (eleventyConfig) {
return DateTime.fromJSDate(dateObj, { zone: "utc" }).toFormat("yyyy-LL-dd");
});
+ eleventyConfig.addFilter("sitemapDateTimeString", (dateObj) => {
+ const dt = DateTime.fromJSDate(dateObj, { zone: "utc" });
+ if (!dt.isValid) {
+ return "";
+ }
+ return dt.toISO();
+ });
+
// Get the first `n` elements of a collection.
eleventyConfig.addFilter("head", (array, n) => {
if (n < 0) {
diff --git a/.eleventyignore b/.eleventyignore
index 6b552c2..9fa95ac 100644
--- a/.eleventyignore
+++ b/.eleventyignore
@@ -9,3 +9,4 @@ third_party
functions
test
src
+.oryx_prod_node_modules/
diff --git a/README.md b/README.md
index 36f25ed..24edfac 100644
--- a/README.md
+++ b/README.md
@@ -139,6 +139,7 @@ Generates a strong CSP for the base template.
- Default-src is self.
- Disallows plugins.
- Generates hash based CSP for the JS used on the site.
+- To extend the CSP with new rules, see [CSP.js](https://github.com/google/eleventy-high-performance-blog/blob/main/_data/csp.js#L22)
### Build performance
diff --git a/_11ty/csp.js b/_11ty/apply-csp.js
similarity index 100%
rename from _11ty/csp.js
rename to _11ty/apply-csp.js
diff --git a/_data/csp.js b/_data/csp.js
index 7d667c0..a0a93c9 100644
--- a/_data/csp.js
+++ b/_data/csp.js
@@ -20,18 +20,13 @@
*/
/**
- * Provides the default CSP.
+ * Provides the default CSP (Content Security Policy).
* Inline scripts must have the `csp-hash` attribute to be allowed.
+ * Example: ``
+ * For more info see https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
+ * or the comments at the end of the `CSP` const below.
*/
-function quote(str) {
- return `'${str}'`;
-}
-
-function serialize(csp) {
- return csp.map((src) => src.join(" ")).join(";");
-}
-
const SELF = quote("self");
const CSP = {
@@ -46,7 +41,22 @@ const CSP = {
["style-src", quote("unsafe-inline")],
// Images may also come from data-URIs.
["img-src", SELF, "data:"],
+
+ // To add new rules, add new array literals here or extend those above with
+ // additional allowed elements.
+ // Example for allowing YouTube iframe embeds
+ // ['frame-src', 'https://www.youtube.com/embed/']
]),
};
+// Quotes CSP "keywords" like `none` or `self`. This function does very little
+// but reads better than the inlined contents because of the nested quotes.
+function quote(str) {
+ return `'${str}'`;
+}
+
+function serialize(csp) {
+ return csp.map((src) => src.join(" ")).join(";");
+}
+
module.exports = () => CSP;
diff --git a/sitemap.xml.njk b/sitemap.xml.njk
index da996da..5a746ee 100644
--- a/sitemap.xml.njk
+++ b/sitemap.xml.njk
@@ -7,12 +7,16 @@ siteWideUpdate: 2020-07-12
{%- for page in collections.all %}
{% set absoluteUrl %}{{ page.url | url | absoluteUrl(metadata.url) }}{% endset %}
- {% set pageDate = page.date | htmlDateString %}
- {% set siteWide = siteWideUpdate| htmlDateString %}
+ {% set pageDate = page.date | sitemapDateTimeString %}
+ {% set lastModifiedDate = page.inputPath | lastModifiedDate | sitemapDateTimeString %}
+ {% set siteWide = siteWideUpdate| sitemapDateTimeString %}
{% set lastmod = siteWide %}
{% if pageDate > lastmod %}
{% set lastmod = pageDate %}
{% endif %}
+ {% if lastModifiedDate > lastmod %}
+ {% set lastmod = lastModifiedDate %}
+ {% endif %}
{{ absoluteUrl }}
{{ lastmod }}