From 5785d45f663eddb006e1aefb807897e154cab3a4 Mon Sep 17 00:00:00 2001 From: Luke Westby Date: Tue, 7 Jan 2020 09:33:40 -0800 Subject: [PATCH 01/24] escape frontmatter content so it handles newlines --- generator/src/generate-raw-content.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generator/src/generate-raw-content.js b/generator/src/generate-raw-content.js index d7e6c716..8aa84438 100644 --- a/generator/src/generate-raw-content.js +++ b/generator/src/generate-raw-content.js @@ -19,8 +19,8 @@ function toEntry(entry, includeBody) { return ` ( [${fullPath.join(", ")}] - , { frontMatter = """${entry.metadata} -""" , body = ${body(entry, includeBody)} + , { frontMatter = ${JSON.stringify(entry.metadata)} + , body = ${body(entry, includeBody)} , extension = "${extension}" } ) `; From a4390b35de2afe52275f4113ee4f00b557633c73 Mon Sep 17 00:00:00 2001 From: Dillon Kearns Date: Sun, 12 Jan 2020 18:58:30 -0800 Subject: [PATCH 02/24] Update CHANGELOG-NPM.md --- CHANGELOG-NPM.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG-NPM.md b/CHANGELOG-NPM.md index 2840e4ea..e1eb1582 100644 --- a/CHANGELOG-NPM.md +++ b/CHANGELOG-NPM.md @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +## [1.1.7] - 2020-01-12 + +### Fixed +- Newlines and escaped double quotes (`"`s) are handled properly in content frontmatter now. See [#41](https://github.com/dillonkearns/elm-pages/pull/41). Thank you [Luke](https://github.com/lukewestby)! 🎉🙏 + ## [1.1.6] - 2020-01-04 ### Added From acbf63132b5e8121b4c330fc8723913df8d07c4f Mon Sep 17 00:00:00 2001 From: Dillon Kearns Date: Sun, 12 Jan 2020 18:59:12 -0800 Subject: [PATCH 03/24] 1.1.7 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ceffa007..9fe9efe4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "elm-pages", - "version": "1.1.6", + "version": "1.1.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index af75f3de..38b7a9c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "elm-pages", - "version": "1.1.6", + "version": "1.1.7", "homepage": "http://elm-pages.com", "description": "Type-safe static sites, written in pure elm with your own custom elm-markup syntax.", "main": "index.js", From fe6e04661038391bf4a9f52affbb49d8cdb4be45 Mon Sep 17 00:00:00 2001 From: Dillon Kearns Date: Mon, 20 Jan 2020 07:59:29 -0800 Subject: [PATCH 04/24] Add script defer tag. --- generator/src/develop.js | 5 +++++ package-lock.json | 8 ++++++++ package.json | 1 + 3 files changed, 14 insertions(+) diff --git a/generator/src/develop.js b/generator/src/develop.js index 4382e1d2..3b4b6eca 100644 --- a/generator/src/develop.js +++ b/generator/src/develop.js @@ -2,6 +2,7 @@ const webpack = require("webpack"); const middleware = require("webpack-dev-middleware"); const path = require("path"); const HTMLWebpackPlugin = require("html-webpack-plugin"); +const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin'); const CopyPlugin = require("copy-webpack-plugin"); const PrerenderSPAPlugin = require("prerender-spa-plugin"); const merge = require("webpack-merge"); @@ -159,6 +160,10 @@ function webpackOptions( inject: "head", template: path.resolve(__dirname, "template.html") }), + new ScriptExtHtmlWebpackPlugin({ + preload: /\.js$/, + defaultAttribute: 'defer' + }), new FaviconsWebpackPlugin({ logo: path.resolve(process.cwd(), `./${manifestConfig.sourceIcon}`), favicons: { diff --git a/package-lock.json b/package-lock.json index 9fe9efe4..e19b102c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9220,6 +9220,14 @@ "ajv-keywords": "^3.1.0" } }, + "script-ext-html-webpack-plugin": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/script-ext-html-webpack-plugin/-/script-ext-html-webpack-plugin-2.1.4.tgz", + "integrity": "sha512-7MAv3paAMfh9y2Rg+yQKp9jEGC5cEcmdge4EomRqri10qoczmliYEVPVNz0/5e9QQ202e05qDll9B8zZlY9N1g==", + "requires": { + "debug": "^4.1.1" + } + }, "scss-tokenizer": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", diff --git a/package.json b/package.json index 38b7a9c9..d51979ca 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "node-sass": "^4.12.0", "prerender-spa-plugin": "^3.4.0", "sass-loader": "^8.0.0", + "script-ext-html-webpack-plugin": "^2.1.4", "style-loader": "^1.0.0", "webpack": "^4.41.5", "webpack-dev-middleware": "^3.7.0", From defe0beb33796fb2e6fb679665c51cb3fedfb207 Mon Sep 17 00:00:00 2001 From: Dillon Kearns Date: Mon, 20 Jan 2020 08:02:46 -0800 Subject: [PATCH 05/24] Don't call user's init function during pre-rendering phase. --- index.js | 3 ++- src/Pages/Internal/Platform.elm | 34 ++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 6a9d6f79..f89b1338 100644 --- a/index.js +++ b/index.js @@ -9,7 +9,8 @@ module.exports = function pagesInit( document.addEventListener("DOMContentLoaded", function() { let app = mainElmModule.init({ flags: { - secrets: null + secrets: null, + isPrerendering: navigator.userAgent.indexOf("Headless") >= 0, } }); diff --git a/src/Pages/Internal/Platform.elm b/src/Pages/Internal/Platform.elm index 5876f213..575c6055 100644 --- a/src/Pages/Internal/Platform.elm +++ b/src/Pages/Internal/Platform.elm @@ -254,6 +254,17 @@ init pathKey canonicalSiteUrl document toJsPort viewFn content initUserModel fla case contentCache of Ok okCache -> let + phase = + case Decode.decodeValue (Decode.field "isPrerendering" Decode.bool) flags of + Ok True -> + Prerender + + Ok False -> + Client + + Err _ -> + Client + ( userModel, userCmd ) = initUserModel maybePagePath @@ -284,6 +295,7 @@ init pathKey canonicalSiteUrl document toJsPort viewFn content initUserModel fla , url = url , userModel = userModel , contentCache = contentCache + , phase = phase } , cmd ) @@ -297,6 +309,7 @@ init pathKey canonicalSiteUrl document toJsPort viewFn content initUserModel fla , url = url , userModel = userModel , contentCache = contentCache + , phase = Client } , Cmd.batch [ userCmd |> Cmd.map UserMsg @@ -333,9 +346,15 @@ type alias ModelDetails userModel metadata view = , url : Url.Url , contentCache : ContentCache metadata view , userModel : userModel + , phase : Phase } +type Phase + = Prerender + | Client + + update : String -> @@ -524,7 +543,20 @@ application config = \msg outerModel -> case outerModel of Model model -> - update config.canonicalSiteUrl config.view config.pathKey config.onPageChange config.toJsPort config.document config.update msg model + let + userUpdate = + case model.phase of + Prerender -> + noOpUpdate + + Client -> + config.update + + noOpUpdate = + \userMsg userModel -> + ( userModel, Cmd.none ) + in + update config.canonicalSiteUrl config.view config.pathKey config.onPageChange config.toJsPort config.document userUpdate msg model |> Tuple.mapFirst Model |> Tuple.mapSecond (Cmd.map AppMsg) From 07e445b2cc515255e92b8577d227920df002eb49 Mon Sep 17 00:00:00 2001 From: Dillon Kearns Date: Mon, 20 Jan 2020 08:03:42 -0800 Subject: [PATCH 06/24] Pass in content.json for current page to ensure there is no "Missing content" message flash. --- index.js | 17 +++++++ src/Pages/ContentCache.elm | 70 ++++++++++++++++------------- src/Pages/Internal/Platform.elm | 19 +++++++- src/Pages/Internal/Platform/Cli.elm | 2 +- 4 files changed, 74 insertions(+), 34 deletions(-) diff --git a/index.js b/index.js index f89b1338..67601391 100644 --- a/index.js +++ b/index.js @@ -7,10 +7,13 @@ module.exports = function pagesInit( let prefetchedPages = [window.location.pathname]; document.addEventListener("DOMContentLoaded", function() { + httpGet(`${window.location.origin}${window.location.pathname}/content.json`, function (/** @type JSON */ contentJson) { + let app = mainElmModule.init({ flags: { secrets: null, isPrerendering: navigator.userAgent.indexOf("Headless") >= 0, + contentJson } }); @@ -34,6 +37,9 @@ module.exports = function pagesInit( document.dispatchEvent(new Event("prerender-trigger")); }); + + }) + }); function setupLinkPrefetching() { @@ -131,3 +137,14 @@ module.exports = function pagesInit( document.getElementsByTagName("head")[0].appendChild(meta); } }; + +function httpGet(/** @type string */ theUrl, /** @type Function */ callback) +{ + var xmlHttp = new XMLHttpRequest(); + xmlHttp.onreadystatechange = function() { + if (xmlHttp.readyState == 4 && xmlHttp.status == 200) + callback(JSON.parse(xmlHttp.responseText)); + } + xmlHttp.open("GET", theUrl, true); // true for asynchronous + xmlHttp.send(null); +} diff --git a/src/Pages/ContentCache.elm b/src/Pages/ContentCache.elm index cfced161..826cb044 100644 --- a/src/Pages/ContentCache.elm +++ b/src/Pages/ContentCache.elm @@ -111,9 +111,10 @@ pagesWithErrors cache = init : Document metadata view -> Content + -> Maybe (ContentJson String) -> ContentCache metadata view -init document content = - parseMetadata document content +init document content maybeInitialPageContent = + parseMetadata maybeInitialPageContent document content |> List.map (\tuple -> Tuple.mapSecond @@ -149,39 +150,44 @@ createBuildError path decodeError = parseMetadata : - Document metadata view + Maybe (ContentJson String) + -> Document metadata view -> List ( List String, { extension : String, frontMatter : String, body : Maybe String } ) -> List ( List String, Result String (Entry metadata view) ) -parseMetadata document content = +parseMetadata maybeInitialPageContent document content = content |> List.map - (Tuple.mapSecond - (\{ frontMatter, extension, body } -> - let - maybeDocumentEntry = - Document.get extension document - in - case maybeDocumentEntry of - Just documentEntry -> - frontMatter - |> documentEntry.frontmatterParser - |> Result.map - (\metadata -> - -- TODO do I need to handle this case? - -- case body of - -- Just presentBody -> - -- Parsed metadata - -- { body = parseContent extension presentBody document - -- , staticData = "" - -- } - -- - -- Nothing -> - NeedContent extension metadata - ) + (\( path, { frontMatter, extension, body } ) -> + let + maybeDocumentEntry = + Document.get extension document + in + case maybeDocumentEntry of + Just documentEntry -> + frontMatter + |> documentEntry.frontmatterParser + |> Result.map + (\metadata -> + let + renderer = + \value -> + parseContent extension value document + in + case maybeInitialPageContent of + Just initialPageContent -> + Parsed metadata + { body = renderer initialPageContent.body + , staticData = initialPageContent.staticData + } - Nothing -> - Err ("Could not find extension '" ++ extension ++ "'") - ) + Nothing -> + NeedContent extension metadata + ) + |> Tuple.pair path + + Nothing -> + Err ("Could not find extension '" ++ extension ++ "'") + |> Tuple.pair path ) @@ -327,8 +333,8 @@ lazyLoad document url cacheResult = |> Task.map (\downloadedContent -> update cacheResult - (\thing -> - parseContent extension thing document + (\value -> + parseContent extension value document ) url downloadedContent diff --git a/src/Pages/Internal/Platform.elm b/src/Pages/Internal/Platform.elm index 575c6055..84672ec7 100644 --- a/src/Pages/Internal/Platform.elm +++ b/src/Pages/Internal/Platform.elm @@ -217,6 +217,12 @@ type alias Flags = Decode.Value +type alias ContentJson = + { body : String + , staticData : Dict String String + } + + init : pathKey -> String @@ -249,7 +255,18 @@ init : init pathKey canonicalSiteUrl document toJsPort viewFn content initUserModel flags url key = let contentCache = - ContentCache.init document content + ContentCache.init document content contentJson + + contentJson = + flags + |> Decode.decodeValue (Decode.field "contentJson" contentJsonDecoder) + |> Result.toMaybe + + contentJsonDecoder : Decode.Decoder ContentJson + contentJsonDecoder = + Decode.map2 ContentJson + (Decode.field "body" Decode.string) + (Decode.field "staticData" (Decode.dict Decode.string)) in case contentCache of Ok okCache -> diff --git a/src/Pages/Internal/Platform/Cli.elm b/src/Pages/Internal/Platform/Cli.elm index ba87f3fb..a0e74544 100644 --- a/src/Pages/Internal/Platform/Cli.elm +++ b/src/Pages/Internal/Platform/Cli.elm @@ -160,7 +160,7 @@ cliApplication : cliApplication cliMsgConstructor narrowMsg toModel fromModel config = let contentCache = - ContentCache.init config.document config.content + ContentCache.init config.document config.content Nothing siteMetadata = contentCache From 3a4881d002305e9fa49d1e23ec47fbc67bb8f3b2 Mon Sep 17 00:00:00 2001 From: Dillon Kearns Date: Mon, 20 Jan 2020 08:03:59 -0800 Subject: [PATCH 07/24] Change relative path reference for content.json preload tag. --- generator/src/template.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/src/template.html b/generator/src/template.html index 5859a472..08520225 100644 --- a/generator/src/template.html +++ b/generator/src/template.html @@ -1,7 +1,7 @@ - +