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 }}