From e8c2dafab8e821da2ffbf8ef3e403941ead477e2 Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Sat, 9 Mar 2024 19:30:09 -0500 Subject: [PATCH 01/24] feature/discussion 1117 Isolation Mode (v1) (#1206) * isolation mode for SSR pages and API routes for greenwood serve * documentation for isolation mode option and global config test case * misc refactoring * set isolation mode to true for Lit renderer plugin * set isolation mode to true for Lit renderer plugin --- packages/cli/src/lifecycles/serve.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cli/src/lifecycles/serve.js b/packages/cli/src/lifecycles/serve.js index 57a87f80f..44dc87151 100644 --- a/packages/cli/src/lifecycles/serve.js +++ b/packages/cli/src/lifecycles/serve.js @@ -372,6 +372,7 @@ async function getHybridServer(compilation) { } else if (isApiRoute) { const apiRoute = manifest.apis.get(url.pathname); const entryPointUrl = new URL(`.${apiRoute.path}`, outputDir); + let body, status, headers, statusText; if (apiRoute.isolation || isolationMode) { From a7b464fdd2ffffbf61117a4d3ded53ba74acc0af Mon Sep 17 00:00:00 2001 From: Paul Barry Date: Sun, 10 Mar 2024 11:22:26 -0400 Subject: [PATCH 02/24] enhancement/Issue-1118: Single File Bundles for SSR and API routes (#1186) * Issue-1118: Refactor rollup config generation for APIs * Issue-1118: Refactor rollup config generation for SSR * Issue-1118: Refactor forEach to use for-in for the ssr config generation * Issue-1118: Convert forEach to for..in * Issue-1118: Remove unused code * refactor away bundling work arounds and add comments * refactor SSR page bundling to avoid hacky entry point placeholder hack * patch custom element registry check from wcc * refactor SSR page output name from .entry to .route * document breaking changes for adapter plugins * refactor import meta relative asset path escaping * refactor API routes and adapters for mapped API bundles * misc refactoring and docs update * latest WCC patches * windows compatibility * update adapter docs example * remove patches --------- Co-authored-by: Owen Buckley --- packages/cli/src/lifecycles/serve.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cli/src/lifecycles/serve.js b/packages/cli/src/lifecycles/serve.js index 44dc87151..57a87f80f 100644 --- a/packages/cli/src/lifecycles/serve.js +++ b/packages/cli/src/lifecycles/serve.js @@ -372,7 +372,6 @@ async function getHybridServer(compilation) { } else if (isApiRoute) { const apiRoute = manifest.apis.get(url.pathname); const entryPointUrl = new URL(`.${apiRoute.path}`, outputDir); - let body, status, headers, statusText; if (apiRoute.isolation || isolationMode) { From 0a863c1ed26460604d3f7deb9779036f8d7ce43e Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Sat, 16 Mar 2024 19:31:28 -0400 Subject: [PATCH 03/24] v0.30.0-alpha.1 --- packages/plugin-import-json/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/plugin-import-json/package.json b/packages/plugin-import-json/package.json index e8017a121..e79e27cc5 100644 --- a/packages/plugin-import-json/package.json +++ b/packages/plugin-import-json/package.json @@ -1,7 +1,6 @@ { "name": "@greenwood/plugin-import-json", "version": "0.30.0-alpha.2", - "private": true, "description": "A Greenwood plugin to allow you to use ESM (import) syntax to load your JSON.", "repository": "https://github.com/ProjectEvergreen/greenwood", "homepage": "https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-json", From ae44511504b906f23dab6615f97129287cb619d9 Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Mon, 29 Apr 2024 15:33:39 -0400 Subject: [PATCH 04/24] feature/issue 923 native import attributes for CSS and JSON (#1215) * intial draft of import attributes support for CSS and JSON * all test cases passing * need patch package * wcc patches for import attributes and CSSStylesheet shim * bump min NodeJS version for exp specs * temp disable ESLint * develop based import assertion specs * serve based import attributes specs * add preIntercept resource plugin lifecycle and refactor PostCSS to use it * all test cases passing for import attributes support * refactor built in CSS and JSON intercepting * demo code * raw plugin docs and package.json updates * update latest documentation for custom loaders support in NodeJS * update custom import docs * upgrade wcc v0.13.0 * only need Node 18 for github actions * css imports and raw plugin interop with test cases * lit renderer import attribute test cases and documentation * refactor matchers support for raw plugin instead of patching and add test cases * disable describe.only * update usage for custom resource plugins to showcase usage of import attributes * document preIntercept lifecycle and convert Babel to use it * restore ESLint * enable debug logging for failing specs * refactor theme pack specs * fix linting * remove CSS and JSON packages from being publishable * clean up console logs and comments * rename exp test cases to loadersnaming prefix * fix command in github actions * remove plugin-import-css callout from plugin-postcss README * remove demo code from website * refine PostCSS plugin intercepting --- packages/plugin-import-json/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/plugin-import-json/package.json b/packages/plugin-import-json/package.json index e79e27cc5..e8017a121 100644 --- a/packages/plugin-import-json/package.json +++ b/packages/plugin-import-json/package.json @@ -1,6 +1,7 @@ { "name": "@greenwood/plugin-import-json", "version": "0.30.0-alpha.2", + "private": true, "description": "A Greenwood plugin to allow you to use ESM (import) syntax to load your JSON.", "repository": "https://github.com/ProjectEvergreen/greenwood", "homepage": "https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-json", From 8b9ed0cc1998b8a1710cb29d14bf31b70fe9e8fc Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Tue, 26 Dec 2023 18:34:03 -0500 Subject: [PATCH 05/24] first pass on resource tracking and bundling refactor with lit polyfills removal from CLI --- packages/cli/src/commands/build.js | 64 +------------------ packages/cli/src/lifecycles/bundle.js | 14 +++- packages/cli/src/lifecycles/prerender.js | 7 +- .../plugins/resource/plugin-standard-html.js | 4 -- .../serve.default.ssr-static-export.spec.js | 2 +- 5 files changed, 17 insertions(+), 74 deletions(-) diff --git a/packages/cli/src/commands/build.js b/packages/cli/src/commands/build.js index e2cc575fe..82937397c 100644 --- a/packages/cli/src/commands/build.js +++ b/packages/cli/src/commands/build.js @@ -1,70 +1,10 @@ import { bundleCompilation } from '../lifecycles/bundle.js'; -import { checkResourceExists, trackResourcesForRoute } from '../lib/resource-utils.js'; +import { checkResourceExists } from '../lib/resource-utils.js'; import { copyAssets } from '../lifecycles/copy.js'; import fs from 'fs/promises'; import { preRenderCompilationWorker, preRenderCompilationCustom, staticRenderCompilation } from '../lifecycles/prerender.js'; import { ServerInterface } from '../lib/server-interface.js'; -// TODO a lot of these are duplicated in the prerender lifecycle too -// would be good to refactor -async function servePage(url, request, plugins) { - let response = new Response(''); - - for (const plugin of plugins) { - if (plugin.shouldServe && await plugin.shouldServe(url, request)) { - response = await plugin.serve(url, request); - break; - } - } - - return response; -} - -async function interceptPage(url, request, plugins, body) { - let response = new Response(body, { - headers: new Headers({ 'Content-Type': 'text/html' }) - }); - - for (const plugin of plugins) { - if (plugin.shouldPreIntercept && await plugin.shouldPreIntercept(url, request, response)) { - response = await plugin.preIntercept(url, request, response); - } - - if (plugin.shouldIntercept && await plugin.shouldIntercept(url, request, response)) { - response = await plugin.intercept(url, request, response); - } - } - - return response; -} - -function getPluginInstances (compilation) { - return [...compilation.config.plugins] - .filter(plugin => plugin.type === 'resource' && plugin.name !== 'plugin-node-modules:resource') - .map((plugin) => { - return plugin.provider(compilation); - }); -} - -// TODO does this make more sense in bundle lifecycle? -// https://github.com/ProjectEvergreen/greenwood/issues/970 -// or could this be done sooner (like in appTemplate building in html resource plugin)? -// Or do we need to ensure userland code / plugins have gone first -async function trackResourcesForRoutes(compilation) { - const plugins = getPluginInstances(compilation); - - for (const page of compilation.graph) { - const { route } = page; - const url = new URL(`http://localhost:${compilation.config.port}${route}`); - const request = new Request(url); - - let body = await (await servePage(url, request, plugins)).text(); - body = await (await interceptPage(url, request, plugins, body)).text(); - - await trackResourcesForRoute(body, compilation, route); - } -} - const runProductionBuild = async (compilation) => { return new Promise(async (resolve, reject) => { @@ -106,13 +46,11 @@ const runProductionBuild = async (compilation) => { })); if (prerenderPlugin.executeModuleUrl) { - await trackResourcesForRoutes(compilation); await preRenderCompilationWorker(compilation, prerenderPlugin); } else { await preRenderCompilationCustom(compilation, prerenderPlugin); } } else { - await trackResourcesForRoutes(compilation); await staticRenderCompilation(compilation); } diff --git a/packages/cli/src/lifecycles/bundle.js b/packages/cli/src/lifecycles/bundle.js index 352fe485a..d787affda 100644 --- a/packages/cli/src/lifecycles/bundle.js +++ b/packages/cli/src/lifecycles/bundle.js @@ -3,7 +3,7 @@ import fs from 'fs/promises'; import { getRollupConfigForApis, getRollupConfigForScriptResources, getRollupConfigForSsr } from '../config/rollup.config.js'; import { getAppTemplate, getPageTemplate, getUserScripts } from '../lib/templating-utils.js'; import { hashString } from '../lib/hashing-utils.js'; -import { checkResourceExists, mergeResponse, normalizePathnameForWindows } from '../lib/resource-utils.js'; +import { checkResourceExists, mergeResponse, normalizePathnameForWindows, trackResourcesForRoute } from '../lib/resource-utils.js'; import path from 'path'; import { rollup } from 'rollup'; @@ -229,7 +229,6 @@ async function bundleSsrPages(compilation) { const input = []; if (!compilation.config.prerender && hasSSRPages) { - const htmlOptimizer = compilation.config.plugins.find(plugin => plugin.name === 'plugin-standard-html').provider(compilation); const { executeModuleUrl } = compilation.config.plugins.find(plugin => plugin.type === 'renderer').provider(); const { executeRouteModule } = await import(executeModuleUrl); const { pagesDir, scratchDir } = compilation.context; @@ -254,6 +253,16 @@ async function bundleSsrPages(compilation) { staticHtml = await getAppTemplate(staticHtml, compilation.context, imports, [], false, title); staticHtml = await getUserScripts(staticHtml, compilation); staticHtml = await (await interceptPage(new URL(`http://localhost:8080${route}`), new Request(new URL(`http://localhost:8080${route}`)), getPluginInstances(compilation), staticHtml)).text(); + + // track resources first before optimizing, so compilation is correctly set + await trackResourcesForRoute(staticHtml, compilation, route); + // TODO is there a way to avoid running this twice? + // first time we call this, we haven't tracked the resources for SSR pages yet + // so we have to do it again before optimizing + await bundleScriptResources(compilation); + + const htmlOptimizer = compilation.config.plugins.find(plugin => plugin.name === 'plugin-standard-html').provider(compilation); + staticHtml = await (await htmlOptimizer.optimize(new URL(`http://localhost:8080${route}`), new Response(staticHtml))).text(); staticHtml = staticHtml.replace(/[`\\$]/g, '\\$&'); // https://stackoverflow.com/a/75688937/417806 @@ -295,6 +304,7 @@ async function bundleSsrPages(compilation) { const ssrConfigs = await getRollupConfigForSsr(compilation, input); if (ssrConfigs.length > 0 && ssrConfigs[0].input !== '') { + console.info('bundling dynamic pages...'); for (const configIndex in ssrConfigs) { const rollupConfig = ssrConfigs[configIndex]; const bundle = await rollup(rollupConfig); diff --git a/packages/cli/src/lifecycles/prerender.js b/packages/cli/src/lifecycles/prerender.js index 804cfd4a1..a3f76cc8b 100644 --- a/packages/cli/src/lifecycles/prerender.js +++ b/packages/cli/src/lifecycles/prerender.js @@ -3,8 +3,6 @@ import { checkResourceExists, trackResourcesForRoute } from '../lib/resource-uti import os from 'os'; import { WorkerPool } from '../lib/threadpool.js'; -// TODO a lot of these are duplicated in the build lifecycle too -// would be good to refactor async function createOutputDirectory(route, outputDir) { if (!route.endsWith('/404/') && !await checkResourceExists(outputDir)) { await fs.mkdir(outputDir, { @@ -62,7 +60,7 @@ async function preRenderCompilationWorker(compilation, workerPrerender) { const pool = new WorkerPool(os.cpus().length, new URL('../lib/ssr-route-worker.js', import.meta.url)); for (const page of pages) { - const { route, outputPath, resources } = page; + const { route, outputPath } = page; const outputPathUrl = new URL(`.${outputPath}`, scratchDir); const url = new URL(`http://localhost:${compilation.config.port}${route}`); const request = new Request(url); @@ -70,10 +68,10 @@ async function preRenderCompilationWorker(compilation, workerPrerender) { let body = await (await servePage(url, request, plugins)).text(); body = await (await interceptPage(url, request, plugins, body)).text(); + const resources = await trackResourcesForRoute(body, compilation, route); await createOutputDirectory(route, new URL(outputPathUrl.href.replace('index.html', ''))); const scripts = resources - .map(resource => compilation.resources.get(resource)) .filter(resource => resource.type === 'script') .map(resource => resource.sourcePathURL.href); @@ -144,6 +142,7 @@ async function staticRenderCompilation(compilation) { let body = await (await servePage(url, request, plugins)).text(); body = await (await interceptPage(url, request, plugins, body)).text(); + await trackResourcesForRoute(body, compilation, route); await createOutputDirectory(route, new URL(outputPathUrl.href.replace('index.html', ''))); await fs.writeFile(outputPathUrl, body); diff --git a/packages/cli/src/plugins/resource/plugin-standard-html.js b/packages/cli/src/plugins/resource/plugin-standard-html.js index 000788cd0..a039f64b4 100644 --- a/packages/cli/src/plugins/resource/plugin-standard-html.js +++ b/packages/cli/src/plugins/resource/plugin-standard-html.js @@ -291,10 +291,6 @@ class StandardHtmlResource extends ResourceInterface { } } - // TODO clean up lit-polyfill - // https://github.com/ProjectEvergreen/greenwood/issues/728 - body = body.replace(/ + - + + + \ No newline at end of file From cc9211469cebf26e3b365b8bf4ed8fbf332071cc Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Wed, 27 Dec 2023 16:50:19 -0500 Subject: [PATCH 07/24] refactor frontmatter for graph and standard html plugin for SSR --- packages/cli/src/lifecycles/graph.js | 4 +-- .../plugins/resource/plugin-standard-html.js | 25 +++---------------- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/packages/cli/src/lifecycles/graph.js b/packages/cli/src/lifecycles/graph.js index 57b53b7bc..763ae46da 100644 --- a/packages/cli/src/lifecycles/graph.js +++ b/packages/cli/src/lifecycles/graph.js @@ -44,7 +44,7 @@ const generateGraph = async (compilation) => { const relativeWorkspacePath = directory.pathname.replace(projectDirectory.pathname, ''); let route = relativePagePath.replace(extension, ''); let id = filename.split('/')[filename.split('/').length - 1].replace(extension, ''); - let template = 'page'; + let template = extension === '.html' ? null : 'page'; let title = null; let imports = []; let customData = {}; @@ -76,7 +76,7 @@ const generateGraph = async (compilation) => { const fileContents = await fs.readFile(filenameUrl, 'utf8'); const { attributes } = fm(fileContents); - template = attributes.template || 'page'; + template = attributes.template || template; title = attributes.title || title; id = attributes.label || id; imports = attributes.imports || []; diff --git a/packages/cli/src/plugins/resource/plugin-standard-html.js b/packages/cli/src/plugins/resource/plugin-standard-html.js index bcb736f25..72e9d1a29 100644 --- a/packages/cli/src/plugins/resource/plugin-standard-html.js +++ b/packages/cli/src/plugins/resource/plugin-standard-html.js @@ -44,14 +44,13 @@ class StandardHtmlResource extends ResourceInterface { const filePath = !matchingRoute.external ? matchingRoute.path : ''; const isMarkdownContent = (matchingRoute?.filename || '').split('.').pop() === 'md'; - let customImports = []; let body = ''; - let title = null; - let template = null; - let frontMatter = {}; + let title = matchingRoute.title || null; + let template = matchingRoute.template || null; + let frontMatter = matchingRoute.data || {}; + let customImports = matchingRoute.imports || []; let ssrBody; let ssrTemplate; - let ssrFrontmatter; let processedMarkdown = null; if (matchingRoute.external) { @@ -119,22 +118,6 @@ class StandardHtmlResource extends ResourceInterface { if (result.body) { ssrBody = result.body; } - if (result.frontmatter) { - ssrFrontmatter = result.frontmatter; - - if (ssrFrontmatter.title) { - title = ssrFrontmatter.title; - frontMatter.title = ssrFrontmatter.title; - } - - if (ssrFrontmatter.template) { - template = ssrFrontmatter.template; - } - - if (ssrFrontmatter.imports) { - customImports = customImports.concat(ssrFrontmatter.imports); - } - } resolve(); }); worker.on('error', reject); From 50ce060ad04067428530018011494943bf8a7ff8 Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Fri, 29 Dec 2023 18:11:22 -0500 Subject: [PATCH 08/24] rename templates directory to layouts --- .github/CONTRIBUTING.md | 2 +- .../cli/src/{templates => layouts}/404.html | 0 .../cli/src/{templates => layouts}/app.html | 0 .../cli/src/{templates => layouts}/page.html | 0 packages/cli/src/lib/execute-route-module.js | 8 +- .../{templating-utils.js => layout-utils.js} | 112 +++++++++--------- packages/cli/src/lib/resource-utils.js | 7 +- packages/cli/src/lib/router.js | 6 +- packages/cli/src/lifecycles/bundle.js | 12 +- packages/cli/src/lifecycles/compile.js | 2 +- packages/cli/src/lifecycles/config.js | 12 +- packages/cli/src/lifecycles/context.js | 10 +- packages/cli/src/lifecycles/graph.js | 12 +- packages/cli/src/lifecycles/prerender.js | 4 +- .../plugins/resource/plugin-standard-html.js | 20 ++-- .../plugins/resource/plugin-static-router.js | 12 +- ...ld.config.error-layouts-directory.spec.js} | 10 +- .../greenwood.config.js | 3 + .../greenwood.config.js | 3 - ...ild.config.interpolate-frontmatter.spec.js | 2 +- .../src/{templates => layouts}/blog.html | 0 .../src/pages/blog/first-post.md | 2 +- .../build.config.layouts-directory.spec.js} | 8 +- .../greenwood.config.js | 3 + .../src/my-layouts}/page.html | 2 +- .../src/pages/index.md | 3 + .../build.config-optimization-inline.spec.js | 2 + .../src/{templates => layouts}/app.html | 0 .../build.config.static-router.spec.js | 6 +- .../src/pages/about.md | 2 +- .../src/pages/regex-test.html | 2 +- .../greenwood.config.js | 3 - .../src/pages/index.md | 3 - .../build.default.meta.spec.js | 4 +- .../src/{templates => layouts}/page.html | 0 .../build.default.ssr-prerender.spec.js | 4 +- .../src/{templates => layouts}/app.html | 0 .../build.default.ssr-static-export.spec.js | 2 +- .../src/{templates => layouts}/app.html | 0 .../src/pages/artists.js | 4 +- .../build.default.title.spec.js | 4 +- .../src/{templates => layouts}/page.html | 0 ...ild.default.workspace-404-markdown.spec.js | 22 ++-- .../src/{templates => layouts}/app.html | 0 .../build.default.workspace-404.spec.js | 22 ++-- .../src/{templates => layouts}/app.html | 0 ....default.workspace-getting-started.spec.js | 2 +- .../src/{templates => layouts}/blog.html | 0 .../src/{templates => layouts}/page.html | 0 .../src/pages/blog/first-post.md | 2 +- .../src/pages/blog/second-post.md | 2 +- ...ild.default.workspace-template-app.spec.js | 16 +-- .../src/{templates => layouts}/app.html | 2 +- ...lt.workspace-template-page-and-app.spec.js | 52 ++++---- .../src/{templates => layouts}/app.html | 12 +- .../src/layouts/page.html | 37 ++++++ .../src/scripts/app-layout-one.js | 1 + .../src/scripts/app-layout-two.js | 1 + .../src/scripts/app-template-one.js | 1 - .../src/scripts/app-template-two.js | 1 - .../src/scripts/page-layout-one.js | 1 + .../src/scripts/page-layout-two.js | 1 + .../src/scripts/page-template-one.js | 1 - .../src/scripts/page-template-two.js | 1 - ...pp-template-one.css => app-layout-one.css} | 0 ...pp-template-two.css => app-layout-two.css} | 0 ...e-template-one.css => page-layout-one.css} | 0 ...e-template-two.css => page-layout-two.css} | 0 .../src/templates/page.html | 37 ------ ...rkspace-template-page-bare-merging.spec.js | 6 +- .../src/{templates => layouts}/page.html | 2 +- ...ld.default.workspace-template-page.spec.js | 24 ++-- .../src/{templates => layouts}/page.html | 0 ....default.workspace-templates-empty.spec.js | 8 +- .../src/scripts/main.js | 2 +- ...workspace-templates-relative-paths.spec.js | 8 +- .../src/{templates => layouts}/app.html | 0 .../src/{templates => layouts}/page.html | 0 ...t.workspace-user-directory-mapping.spec.js | 2 +- .../src/{templates => layouts}/page.html | 0 .../build.plugins.context.spec.js | 36 +++--- .../fixtures/{layouts => my-layouts}/app.html | 2 +- .../{layouts => my-layouts}/page.html | 2 +- .../fixtures/my-layouts}/title.html | 2 +- .../src/pages/slides/index.md | 2 +- .../theme-pack-context-plugin.js | 10 +- .../build.plugins-source.spec.js | 8 +- .../build.plugins.source/greenwood.config.js | 2 +- .../src/{templates => layouts}/artist.html | 0 .../develop.plugins.context.spec.js | 12 +- .../fixtures/{layouts => my-layouts}/app.html | 2 +- .../{layouts => my-layouts}/page.html | 2 +- .../fixtures/my-layouts}/title.html | 2 +- .../src/pages/slides/index.md | 2 +- .../cases/develop.ssr/develop.ssr.spec.js | 4 +- .../src/{templates => layouts}/app.html | 0 .../cases/develop.ssr/src/pages/artists.js | 4 +- .../serve.config.base-path.spec.js | 6 +- .../serve.config.base-path/src/pages/about.md | 2 +- .../src/pages/about.md | 2 +- ...e.default.ssr-prerender-api-hybrid.spec.js | 2 +- .../src/{templates => layouts}/app.html | 0 .../serve.default.ssr-prerender.spec.js | 8 +- .../src/{templates => layouts}/app.html | 0 .../serve.default.ssr-static-export.spec.js | 2 +- .../src/{templates => layouts}/app.html | 0 .../src/pages/artists.js | 4 +- .../serve.default.ssr.spec.js | 6 +- .../src/{templates => layouts}/app.html | 0 .../serve.default.ssr/src/pages/artists.js | 4 +- .../serve.default/src/assets/router.js.map | 2 +- .../test/cases/theme-pack/my-theme-pack.js | 10 +- .../{layouts => my-layouts}/blog-post.html | 2 +- .../test/cases/theme-pack/src/pages/index.md | 2 +- .../cases/theme-pack/theme-pack.build.spec.js | 18 +-- .../theme-pack/theme-pack.develop.spec.js | 6 +- packages/plugin-graphql/README.md | 2 +- .../plugin-graphql/src/queries/children.gql | 2 +- packages/plugin-graphql/src/queries/graph.gql | 2 +- packages/plugin-graphql/src/schema/graph.js | 2 +- .../query-graph/src/pages/blog/first-post.md | 2 +- .../query-graph/src/pages/blog/second-post.md | 2 +- .../test/cases/query-menu/query-menu.spec.js | 2 +- .../src/{templates => layouts}/page.html | 0 .../plugin-graphql/test/unit/common.spec.js | 8 +- .../plugin-graphql/test/unit/mocks/graph.js | 90 +++++++------- .../test/unit/schema/graph.menu.spec.js | 12 +- .../test/unit/schema/graph.spec.js | 6 +- .../exp-build.prerender.spec.js | 2 +- .../src/{templates => layouts}/app.html | 0 .../exp-build.prerender.spec.js | 2 +- .../src/{templates => layouts}/app.html | 0 .../cases/default/default.prerender.spec.js | 2 +- .../src/{templates => layouts}/app.html | 0 .../loaders-build.prerender.spec.js | 2 +- .../src/{templates => layouts}/app.html | 0 packages/plugin-renderer-lit/README.md | 2 +- .../src/execute-route-module.js | 10 +- .../build.prerender.getting-started.spec.js | 4 +- .../src/{templates => layouts}/blog.html | 0 .../src/{templates => layouts}/page.html | 0 .../src/pages/blog/first-post.md | 2 +- .../src/pages/blog/second-post.md | 2 +- .../cases/serve.default/serve.default.spec.js | 5 +- .../src/{templates => layouts}/app.html | 0 .../cases/serve.default/src/pages/artists.js | 4 +- www/{templates => layouts}/app.html | 0 www/{templates => layouts}/blog.html | 0 www/{templates => layouts}/page.html | 0 www/pages/about/features.md | 2 +- www/pages/blog/index.md | 2 +- www/pages/blog/release/v0-15-0.md | 2 +- www/pages/blog/release/v0-18-0.md | 2 +- www/pages/blog/release/v0-19-0.md | 2 +- www/pages/blog/release/v0-20-0.md | 2 +- www/pages/blog/release/v0-21-0.md | 2 +- www/pages/blog/release/v0-23-0.md | 2 +- www/pages/blog/release/v0-24-0.md | 2 +- www/pages/blog/release/v0-26-0.md | 2 +- www/pages/blog/release/v0-27-0.md | 2 +- www/pages/blog/release/v0-28-0.md | 2 +- www/pages/blog/release/v0-29-0.md | 2 +- www/pages/blog/state-of-greenwood-2022.md | 2 +- www/pages/blog/state-of-greenwood-2023.md | 2 +- www/pages/docs/component-model.md | 4 +- www/pages/docs/configuration.md | 18 +-- www/pages/docs/css-and-images.md | 2 +- www/pages/docs/data.md | 18 +-- www/pages/docs/front-matter.md | 12 +- www/pages/docs/index.md | 2 +- www/pages/docs/layouts.md | 56 ++++----- www/pages/docs/markdown.md | 2 +- www/pages/docs/scripts.md | 2 +- www/pages/docs/server-rendering.md | 24 ++-- www/pages/getting-started/branding.md | 4 +- www/pages/getting-started/creating-content.md | 30 ++--- www/pages/getting-started/index.md | 2 +- www/pages/getting-started/key-concepts.md | 18 +-- www/pages/getting-started/quick-start.md | 2 +- www/pages/guides/netlify-cms.md | 6 +- www/pages/guides/theme-packs.md | 28 ++--- www/pages/plugins/context.md | 16 +-- www/pages/plugins/index.md | 4 +- www/pages/plugins/renderer.md | 2 +- 184 files changed, 586 insertions(+), 588 deletions(-) rename packages/cli/src/{templates => layouts}/404.html (100%) rename packages/cli/src/{templates => layouts}/app.html (100%) rename packages/cli/src/{templates => layouts}/page.html (100%) rename packages/cli/src/lib/{templating-utils.js => layout-utils.js} (56%) rename packages/cli/test/cases/{build.config.error-templates-directory/build.config.error-templates-directory.spec.js => build.config.error-layouts-directory/build.config.error-layouts-directory.spec.js} (63%) create mode 100644 packages/cli/test/cases/build.config.error-layouts-directory/greenwood.config.js delete mode 100644 packages/cli/test/cases/build.config.error-templates-directory/greenwood.config.js rename packages/cli/test/cases/build.config.interpolate-frontmatter/src/{templates => layouts}/blog.html (100%) rename packages/cli/test/cases/{build.config.templates-directory/build.config.templates-directory.spec.js => build.config.layouts-directory/build.config.layouts-directory.spec.js} (89%) create mode 100644 packages/cli/test/cases/build.config.layouts-directory/greenwood.config.js rename packages/cli/test/cases/{build.config.templates-directory/src/layouts => build.config.layouts-directory/src/my-layouts}/page.html (66%) create mode 100644 packages/cli/test/cases/build.config.layouts-directory/src/pages/index.md rename packages/cli/test/cases/build.config.optimization-inline/src/{templates => layouts}/app.html (100%) delete mode 100644 packages/cli/test/cases/build.config.templates-directory/greenwood.config.js delete mode 100644 packages/cli/test/cases/build.config.templates-directory/src/pages/index.md rename packages/cli/test/cases/build.default.meta/src/{templates => layouts}/page.html (100%) rename packages/cli/test/cases/build.default.ssr-prerender/src/{templates => layouts}/app.html (100%) rename packages/cli/test/cases/build.default.ssr-static-export/src/{templates => layouts}/app.html (100%) rename packages/cli/test/cases/build.default.title/src/{templates => layouts}/page.html (100%) rename packages/cli/test/cases/build.default.workspace-404-markdown/src/{templates => layouts}/app.html (100%) rename packages/cli/test/cases/build.default.workspace-404/src/{templates => layouts}/app.html (100%) rename packages/cli/test/cases/build.default.workspace-getting-started/src/{templates => layouts}/blog.html (100%) rename packages/cli/test/cases/build.default.workspace-getting-started/src/{templates => layouts}/page.html (100%) rename packages/cli/test/cases/build.default.workspace-template-app/src/{templates => layouts}/app.html (88%) rename packages/cli/test/cases/build.default.workspace-template-page-and-app/src/{templates => layouts}/app.html (61%) create mode 100644 packages/cli/test/cases/build.default.workspace-template-page-and-app/src/layouts/page.html create mode 100644 packages/cli/test/cases/build.default.workspace-template-page-and-app/src/scripts/app-layout-one.js create mode 100644 packages/cli/test/cases/build.default.workspace-template-page-and-app/src/scripts/app-layout-two.js delete mode 100644 packages/cli/test/cases/build.default.workspace-template-page-and-app/src/scripts/app-template-one.js delete mode 100644 packages/cli/test/cases/build.default.workspace-template-page-and-app/src/scripts/app-template-two.js create mode 100644 packages/cli/test/cases/build.default.workspace-template-page-and-app/src/scripts/page-layout-one.js create mode 100644 packages/cli/test/cases/build.default.workspace-template-page-and-app/src/scripts/page-layout-two.js delete mode 100644 packages/cli/test/cases/build.default.workspace-template-page-and-app/src/scripts/page-template-one.js delete mode 100644 packages/cli/test/cases/build.default.workspace-template-page-and-app/src/scripts/page-template-two.js rename packages/cli/test/cases/build.default.workspace-template-page-and-app/src/styles/{app-template-one.css => app-layout-one.css} (100%) rename packages/cli/test/cases/build.default.workspace-template-page-and-app/src/styles/{app-template-two.css => app-layout-two.css} (100%) rename packages/cli/test/cases/build.default.workspace-template-page-and-app/src/styles/{page-template-one.css => page-layout-one.css} (100%) rename packages/cli/test/cases/build.default.workspace-template-page-and-app/src/styles/{page-template-two.css => page-layout-two.css} (100%) delete mode 100644 packages/cli/test/cases/build.default.workspace-template-page-and-app/src/templates/page.html rename packages/cli/test/cases/build.default.workspace-template-page-bare-merging/src/{templates => layouts}/page.html (80%) rename packages/cli/test/cases/build.default.workspace-template-page/src/{templates => layouts}/page.html (100%) rename packages/cli/test/cases/build.default.workspace-templates-relative-paths/src/{templates => layouts}/app.html (100%) rename packages/cli/test/cases/build.default.workspace-templates-relative-paths/src/{templates => layouts}/page.html (100%) rename packages/cli/test/cases/build.default.workspace-user-directory-mapping/src/{templates => layouts}/page.html (100%) rename packages/cli/test/cases/build.plugins.context/fixtures/{layouts => my-layouts}/app.html (82%) rename packages/cli/test/cases/build.plugins.context/fixtures/{layouts => my-layouts}/page.html (55%) rename packages/cli/test/cases/{develop.plugins.context/fixtures/layouts => build.plugins.context/fixtures/my-layouts}/title.html (72%) rename packages/cli/test/cases/build.plugins.source/src/{templates => layouts}/artist.html (100%) rename packages/cli/test/cases/develop.plugins.context/fixtures/{layouts => my-layouts}/app.html (82%) rename packages/cli/test/cases/develop.plugins.context/fixtures/{layouts => my-layouts}/page.html (55%) rename packages/cli/test/cases/{build.plugins.context/fixtures/layouts => develop.plugins.context/fixtures/my-layouts}/title.html (72%) rename packages/cli/test/cases/develop.ssr/src/{templates => layouts}/app.html (100%) rename packages/cli/test/cases/serve.default.ssr-prerender-api-hybrid/src/{templates => layouts}/app.html (100%) rename packages/cli/test/cases/serve.default.ssr-prerender/src/{templates => layouts}/app.html (100%) rename packages/cli/test/cases/serve.default.ssr-static-export/src/{templates => layouts}/app.html (100%) rename packages/cli/test/cases/serve.default.ssr/src/{templates => layouts}/app.html (100%) rename packages/cli/test/cases/theme-pack/src/{layouts => my-layouts}/blog-post.html (79%) rename packages/plugin-graphql/test/cases/query-menu/src/{templates => layouts}/page.html (100%) rename packages/plugin-import-css/test/cases/exp-build.prerender/src/{templates => layouts}/app.html (100%) rename packages/plugin-import-json/test/cases/exp-build.prerender/src/{templates => layouts}/app.html (100%) rename packages/plugin-import-jsx/test/cases/default/src/{templates => layouts}/app.html (100%) rename packages/plugin-import-jsx/test/cases/loaders-build.prerender/src/{templates => layouts}/app.html (100%) rename packages/plugin-renderer-lit/test/cases/build.prerender.getting-started/src/{templates => layouts}/blog.html (100%) rename packages/plugin-renderer-lit/test/cases/build.prerender.getting-started/src/{templates => layouts}/page.html (100%) rename packages/plugin-renderer-lit/test/cases/serve.default/src/{templates => layouts}/app.html (100%) rename www/{templates => layouts}/app.html (100%) rename www/{templates => layouts}/blog.html (100%) rename www/{templates => layouts}/page.html (100%) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index d3e92b598..90ed23df3 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -57,7 +57,7 @@ The [layout](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/ - _lib/_ - Custom utility and client facing files - _lifecycles/_ - Tasks that can be composed by commands to support the full needs of that command - _plugins/_ - Custom default plugins maintained by the CLI project -- _templates/_ - Default templates and / or pages provided by Greenwood. +- _layouts/_ - Default layouts and / or pages provided by Greenwood. #### Lifecycles diff --git a/packages/cli/src/templates/404.html b/packages/cli/src/layouts/404.html similarity index 100% rename from packages/cli/src/templates/404.html rename to packages/cli/src/layouts/404.html diff --git a/packages/cli/src/templates/app.html b/packages/cli/src/layouts/app.html similarity index 100% rename from packages/cli/src/templates/app.html rename to packages/cli/src/layouts/app.html diff --git a/packages/cli/src/templates/page.html b/packages/cli/src/layouts/page.html similarity index 100% rename from packages/cli/src/templates/page.html rename to packages/cli/src/layouts/page.html diff --git a/packages/cli/src/lib/execute-route-module.js b/packages/cli/src/lib/execute-route-module.js index 1d3746ace..dec53e5e2 100644 --- a/packages/cli/src/lib/execute-route-module.js +++ b/packages/cli/src/lib/execute-route-module.js @@ -2,7 +2,7 @@ import { renderToString, renderFromHTML } from 'wc-compiler'; async function executeRouteModule({ moduleUrl, compilation, page = {}, prerender = false, htmlContents = null, scripts = [], request }) { const data = { - template: null, + layout: null, body: null, frontmatter: null, html: null @@ -15,7 +15,7 @@ async function executeRouteModule({ moduleUrl, compilation, page = {}, prerender data.html = html; } else { const module = await import(moduleUrl).then(module => module); - const { prerender = false, getTemplate = null, getBody = null, getFrontmatter = null, isolation } = module; + const { prerender = false, getLayout = null, getBody = null, getFrontmatter = null, isolation } = module; if (module.default) { const { html } = await renderToString(new URL(moduleUrl), false, request); @@ -27,8 +27,8 @@ async function executeRouteModule({ moduleUrl, compilation, page = {}, prerender } } - if (getTemplate) { - data.template = await getTemplate(compilation, page); + if (getLayout) { + data.layout = await getLayout(compilation, page); } if (getFrontmatter) { diff --git a/packages/cli/src/lib/templating-utils.js b/packages/cli/src/lib/layout-utils.js similarity index 56% rename from packages/cli/src/lib/templating-utils.js rename to packages/cli/src/lib/layout-utils.js index f9e83b771..6165350a8 100644 --- a/packages/cli/src/lib/templating-utils.js +++ b/packages/cli/src/lib/layout-utils.js @@ -2,93 +2,93 @@ import fs from 'fs/promises'; import htmlparser from 'node-html-parser'; import { checkResourceExists } from './resource-utils.js'; -async function getCustomPageTemplatesFromPlugins(contextPlugins, templateName) { - const customTemplateLocations = []; - const templateDir = contextPlugins - .map(plugin => plugin.templates) +async function getCustomPageLayoutsFromPlugins(contextPlugins, layoutName) { + const customLayoutLocations = []; + const layoutDir = contextPlugins + .map(plugin => plugin.layouts) .flat(); - for (const templateDirUrl of templateDir) { - if (templateName) { - const templateUrl = new URL(`./${templateName}.html`, templateDirUrl); + for (const layoutDirUrl of layoutDir) { + if (layoutName) { + const layoutUrl = new URL(`./${layoutName}.html`, layoutDirUrl); - if (await checkResourceExists(templateUrl)) { - customTemplateLocations.push(templateUrl); + if (await checkResourceExists(layoutUrl)) { + customLayoutLocations.push(layoutUrl); } } } - return customTemplateLocations; + return customLayoutLocations; } -async function getPageTemplate(filePath, context, template, contextPlugins = []) { - const { templatesDir, userTemplatesDir, pagesDir, projectDirectory } = context; - const customPluginDefaultPageTemplates = await getCustomPageTemplatesFromPlugins(contextPlugins, 'page'); - const customPluginPageTemplates = await getCustomPageTemplatesFromPlugins(contextPlugins, template); +async function getPageLayout(filePath, context, layout, contextPlugins = []) { + const { layoutsDir, userLayoutsDir, pagesDir, projectDirectory } = context; + const customPluginDefaultPageLayouts = await getCustomPageLayoutsFromPlugins(contextPlugins, 'page'); + const customPluginPageLayouts = await getCustomPageLayoutsFromPlugins(contextPlugins, layout); const extension = filePath.split('.').pop(); const is404Page = filePath.startsWith('404') && extension === 'html'; - const hasCustomTemplate = await checkResourceExists(new URL(`./${template}.html`, userTemplatesDir)); - const hasPageTemplate = await checkResourceExists(new URL('./page.html', userTemplatesDir)); + const hasCustomLayout = await checkResourceExists(new URL(`./${layout}.html`, userLayoutsDir)); + const hasPageLayout = await checkResourceExists(new URL('./page.html', userLayoutsDir)); const hasCustom404Page = await checkResourceExists(new URL('./404.html', pagesDir)); const isHtmlPage = extension === 'html' && await checkResourceExists(new URL(`./${filePath}`, projectDirectory)); let contents; - if (template && (customPluginPageTemplates.length > 0 || hasCustomTemplate)) { - // use a custom template, usually from markdown frontmatter - contents = customPluginPageTemplates.length > 0 - ? await fs.readFile(new URL(`./${template}.html`, customPluginPageTemplates[0]), 'utf-8') - : await fs.readFile(new URL(`./${template}.html`, userTemplatesDir), 'utf-8'); + if (layout && (customPluginPageLayouts.length > 0 || hasCustomLayout)) { + // use a custom layout, usually from markdown frontmatter + contents = customPluginPageLayouts.length > 0 + ? await fs.readFile(new URL(`./${layout}.html`, customPluginPageLayouts[0]), 'utf-8') + : await fs.readFile(new URL(`./${layout}.html`, userLayoutsDir), 'utf-8'); } else if (isHtmlPage) { - // if the page is already HTML, use that as the template, NOT accounting for 404 pages + // if the page is already HTML, use that as the layout, NOT accounting for 404 pages contents = await fs.readFile(new URL(`./${filePath}`, projectDirectory), 'utf-8'); - } else if (customPluginDefaultPageTemplates.length > 0 || (!is404Page && hasPageTemplate)) { - // else look for default page template from the user - // and 404 pages should be their own "top level" template - contents = customPluginDefaultPageTemplates.length > 0 - ? await fs.readFile(new URL('./page.html', customPluginDefaultPageTemplates[0]), 'utf-8') - : await fs.readFile(new URL('./page.html', userTemplatesDir), 'utf-8'); + } else if (customPluginDefaultPageLayouts.length > 0 || (!is404Page && hasPageLayout)) { + // else look for default page layout from the user + // and 404 pages should be their own "top level" layout + contents = customPluginDefaultPageLayouts.length > 0 + ? await fs.readFile(new URL('./page.html', customPluginDefaultPageLayouts[0]), 'utf-8') + : await fs.readFile(new URL('./page.html', userLayoutsDir), 'utf-8'); } else if (is404Page && !hasCustom404Page) { - contents = await fs.readFile(new URL('./404.html', templatesDir), 'utf-8'); + contents = await fs.readFile(new URL('./404.html', layoutsDir), 'utf-8'); } else { - // fallback to using Greenwood's stock page template - contents = await fs.readFile(new URL('./page.html', templatesDir), 'utf-8'); + // fallback to using Greenwood's stock page layout + contents = await fs.readFile(new URL('./page.html', layoutsDir), 'utf-8'); } return contents; } /* eslint-disable-next-line complexity */ -async function getAppTemplate(pageTemplateContents, context, customImports = [], contextPlugins, enableHud, frontmatterTitle) { - const { templatesDir, userTemplatesDir } = context; - const userAppTemplateUrl = new URL('./app.html', userTemplatesDir); - const customAppTemplatesFromPlugins = await getCustomPageTemplatesFromPlugins(contextPlugins, 'app'); - const hasCustomUserAppTemplate = await checkResourceExists(userAppTemplateUrl); - let appTemplateContents = customAppTemplatesFromPlugins.length > 0 - ? await fs.readFile(new URL('./app.html', customAppTemplatesFromPlugins[0])) - : hasCustomUserAppTemplate - ? await fs.readFile(userAppTemplateUrl, 'utf-8') - : await fs.readFile(new URL('./app.html', templatesDir), 'utf-8'); - let mergedTemplateContents = ''; - - const pageRoot = pageTemplateContents && htmlparser.parse(pageTemplateContents, { +async function getAppLayout(pageLayoutContents, context, customImports = [], contextPlugins, enableHud, frontmatterTitle) { + const { layoutsDir, userLayoutsDir } = context; + const userAppLayoutUrl = new URL('./app.html', userLayoutsDir); + const customAppLayoutsFromPlugins = await getCustomPageLayoutsFromPlugins(contextPlugins, 'app'); + const hasCustomUserAppLayout = await checkResourceExists(userAppLayoutUrl); + let appLayoutContents = customAppLayoutsFromPlugins.length > 0 + ? await fs.readFile(new URL('./app.html', customAppLayoutsFromPlugins[0])) + : hasCustomUserAppLayout + ? await fs.readFile(userAppLayoutUrl, 'utf-8') + : await fs.readFile(new URL('./app.html', layoutsDir), 'utf-8'); + let mergedLayoutContents = ''; + + const pageRoot = pageLayoutContents && htmlparser.parse(pageLayoutContents, { script: true, style: true, noscript: true, pre: true }); - const appRoot = htmlparser.parse(appTemplateContents, { + const appRoot = htmlparser.parse(appLayoutContents, { script: true, style: true }); - if ((pageTemplateContents && !pageRoot.valid) || !appRoot.valid) { + if ((pageLayoutContents && !pageRoot.valid) || !appRoot.valid) { console.debug('ERROR: Invalid HTML detected'); const invalidContents = !pageRoot.valid - ? pageTemplateContents - : appTemplateContents; + ? pageLayoutContents + : appLayoutContents; if (enableHud) { - appTemplateContents = appTemplateContents.replace('', ` + appLayoutContents = appLayoutContents.replace('', `

Malformed HTML detected, please check your closing tags or an HTML formatter.

@@ -101,7 +101,7 @@ async function getAppTemplate(pageTemplateContents, context, customImports = [], `); } - mergedTemplateContents = appTemplateContents.replace(/<\/page-outlet>/, ''); + mergedLayoutContents = appLayoutContents.replace(/<\/page-outlet>/, ''); } else { const appTitle = appRoot ? appRoot.querySelector('head title') : null; const appBody = appRoot.querySelector('body') ? appRoot.querySelector('body').innerHTML : ''; @@ -114,7 +114,7 @@ async function getAppTemplate(pageTemplateContents, context, customImports = [], ? pageTitle && pageTitle.rawText ? pageTitle.rawText : appTitle.rawText - : frontmatterTitle // otherwise, work in order of specificity from page -> page template -> app template + : frontmatterTitle // otherwise, work in order of specificity from page -> page layout -> app layout ? frontmatterTitle : pageTitle && pageTitle.rawText ? pageTitle.rawText @@ -152,11 +152,11 @@ async function getAppTemplate(pageTemplateContents, context, customImports = [], .map(resource => ``) ].join('\n'); - const finalBody = pageTemplateContents + const finalBody = pageLayoutContents ? appBody.replace(/<\/page-outlet>/, pageBody) : appBody; - mergedTemplateContents = ` + mergedLayoutContents = ` ${mergedHtml} ${title} @@ -172,7 +172,7 @@ async function getAppTemplate(pageTemplateContents, context, customImports = [], `; } - return mergedTemplateContents; + return mergedLayoutContents; } async function getUserScripts (contents, compilation) { @@ -189,7 +189,7 @@ async function getUserScripts (contents, compilation) { } export { - getAppTemplate, - getPageTemplate, + getAppLayout, + getPageLayout, getUserScripts }; \ No newline at end of file diff --git a/packages/cli/src/lib/resource-utils.js b/packages/cli/src/lib/resource-utils.js index a08cd9c57..6a78e4647 100644 --- a/packages/cli/src/lib/resource-utils.js +++ b/packages/cli/src/lib/resource-utils.js @@ -86,7 +86,7 @@ async function checkResourceExists(url) { // turn relative paths into relatively absolute based on a known root directory // * deep link route - /blog/releases/some-post -// * and a nested path in the template - ../../styles/theme.css +// * and a nested path in the layout - ../../styles/theme.css // so will get resolved as `${rootUrl}/styles/theme.css` async function resolveForRelativeUrl(url, rootUrl) { const search = url.search || ''; @@ -111,11 +111,6 @@ async function resolveForRelativeUrl(url, rootUrl) { return reducedUrl; } -// does this make more sense in bundle lifecycle? -// https://github.com/ProjectEvergreen/greenwood/issues/970 -// or could this be done sooner (like in appTemplate building in html resource plugin)? -// Or do we need to ensure userland code / plugins have gone first -// before we can curate the final list of `) diff --git a/packages/cli/test/cases/build.config.error-templates-directory/build.config.error-templates-directory.spec.js b/packages/cli/test/cases/build.config.error-layouts-directory/build.config.error-layouts-directory.spec.js similarity index 63% rename from packages/cli/test/cases/build.config.error-templates-directory/build.config.error-templates-directory.spec.js rename to packages/cli/test/cases/build.config.error-layouts-directory/build.config.error-layouts-directory.spec.js index 8b481fd00..e48c2130a 100644 --- a/packages/cli/test/cases/build.config.error-templates-directory/build.config.error-templates-directory.spec.js +++ b/packages/cli/test/cases/build.config.error-layouts-directory/build.config.error-layouts-directory.spec.js @@ -1,6 +1,6 @@ /* * Use Case - * Run Greenwood build command with a bad value for templatesDirectory in a custom config. + * Run Greenwood build command with a bad value for layoutsDirectory in a custom config. * * User Result * Should throw an error. @@ -10,7 +10,7 @@ * * User Config * { - * templatesDirectory: {} + * layoutsDirectory: {} * } * * User Workspace @@ -35,13 +35,13 @@ describe('Build Greenwood With: ', function() { runner = new Runner(); }); - describe('Custom Configuration with a bad value for templatesDirectory', function() { - it('should throw an error that templatesDirectory must be a string', function() { + describe('Custom Configuration with a bad value for layoutsDirectory', function() { + it('should throw an error that layoutsDirectory must be a string', async function() { try { runner.setup(outputPath); runner.runCommand(cliPath, 'build'); } catch (err) { - expect(err).to.contain('Error: provided templatesDirectory "[object Object]" is not supported. Please make sure to pass something like \'layouts/\''); + expect(err).to.contain('Error: provided layoutsDirectory "[object Object]" is not supported. Please make sure to pass something like \'layouts/\''); } }); }); diff --git a/packages/cli/test/cases/build.config.error-layouts-directory/greenwood.config.js b/packages/cli/test/cases/build.config.error-layouts-directory/greenwood.config.js new file mode 100644 index 000000000..376ab3249 --- /dev/null +++ b/packages/cli/test/cases/build.config.error-layouts-directory/greenwood.config.js @@ -0,0 +1,3 @@ +export default { + layoutsDirectory: {} +}; \ No newline at end of file diff --git a/packages/cli/test/cases/build.config.error-templates-directory/greenwood.config.js b/packages/cli/test/cases/build.config.error-templates-directory/greenwood.config.js deleted file mode 100644 index b8e6daaba..000000000 --- a/packages/cli/test/cases/build.config.error-templates-directory/greenwood.config.js +++ /dev/null @@ -1,3 +0,0 @@ -export default { - templatesDirectory: {} -}; \ No newline at end of file diff --git a/packages/cli/test/cases/build.config.interpolate-frontmatter/build.config.interpolate-frontmatter.spec.js b/packages/cli/test/cases/build.config.interpolate-frontmatter/build.config.interpolate-frontmatter.spec.js index 62b30ae9c..b39193067 100644 --- a/packages/cli/test/cases/build.config.interpolate-frontmatter/build.config.interpolate-frontmatter.spec.js +++ b/packages/cli/test/cases/build.config.interpolate-frontmatter/build.config.interpolate-frontmatter.spec.js @@ -19,7 +19,7 @@ * pages/ * blog/ * first-post.md - * templates/ + * layouts/ * blog.html */ import { JSDOM } from 'jsdom'; diff --git a/packages/cli/test/cases/build.config.interpolate-frontmatter/src/templates/blog.html b/packages/cli/test/cases/build.config.interpolate-frontmatter/src/layouts/blog.html similarity index 100% rename from packages/cli/test/cases/build.config.interpolate-frontmatter/src/templates/blog.html rename to packages/cli/test/cases/build.config.interpolate-frontmatter/src/layouts/blog.html diff --git a/packages/cli/test/cases/build.config.interpolate-frontmatter/src/pages/blog/first-post.md b/packages/cli/test/cases/build.config.interpolate-frontmatter/src/pages/blog/first-post.md index deae1bb80..fa488585c 100644 --- a/packages/cli/test/cases/build.config.interpolate-frontmatter/src/pages/blog/first-post.md +++ b/packages/cli/test/cases/build.config.interpolate-frontmatter/src/pages/blog/first-post.md @@ -1,6 +1,6 @@ --- title: Ny First Post -template: blog +layout: blog published: 11/11/2022 author: Owen Buckley --- diff --git a/packages/cli/test/cases/build.config.templates-directory/build.config.templates-directory.spec.js b/packages/cli/test/cases/build.config.layouts-directory/build.config.layouts-directory.spec.js similarity index 89% rename from packages/cli/test/cases/build.config.templates-directory/build.config.templates-directory.spec.js rename to packages/cli/test/cases/build.config.layouts-directory/build.config.layouts-directory.spec.js index baac1c79b..f206cf923 100644 --- a/packages/cli/test/cases/build.config.templates-directory/build.config.templates-directory.spec.js +++ b/packages/cli/test/cases/build.config.layouts-directory/build.config.layouts-directory.spec.js @@ -1,6 +1,6 @@ /* * Use Case - * Run Greenwood with a custom name for templates directory. + * Run Greenwood with a custom name for layouts directory. * * User Result * Should generate a bare bones Greenwood build. (same as build.default.spec.js) with custom title in header @@ -10,7 +10,7 @@ * * User Config * { - * templatesDirectory: 'layouts' + * layoutsDirectory: 'layouts' * } * * User Workspace @@ -68,7 +68,7 @@ describe('Build Greenwood With: ', function() { it('should have the correct page heading', function() { const heading = dom.window.document.querySelectorAll('head title')[0].textContent; - expect(heading).to.be.equal('Custom Layout Page Template'); + expect(heading).to.be.equal('Custom Layout Page Layout'); }); it('should have the correct page heading', function() { @@ -80,7 +80,7 @@ describe('Build Greenwood With: ', function() { it('should have the correct page heading', function() { const paragraph = dom.window.document.querySelectorAll('body p')[0].textContent; - expect(paragraph).to.be.equal('A page using a page template from a custom layout directory.'); + expect(paragraph).to.be.equal('A page using a page layout from a custom layout directory.'); }); }); }); diff --git a/packages/cli/test/cases/build.config.layouts-directory/greenwood.config.js b/packages/cli/test/cases/build.config.layouts-directory/greenwood.config.js new file mode 100644 index 000000000..04634f17c --- /dev/null +++ b/packages/cli/test/cases/build.config.layouts-directory/greenwood.config.js @@ -0,0 +1,3 @@ +export default { + layoutsDirectory: 'my-layouts' +}; \ No newline at end of file diff --git a/packages/cli/test/cases/build.config.templates-directory/src/layouts/page.html b/packages/cli/test/cases/build.config.layouts-directory/src/my-layouts/page.html similarity index 66% rename from packages/cli/test/cases/build.config.templates-directory/src/layouts/page.html rename to packages/cli/test/cases/build.config.layouts-directory/src/my-layouts/page.html index b7fe92d12..0fc6a16f9 100644 --- a/packages/cli/test/cases/build.config.templates-directory/src/layouts/page.html +++ b/packages/cli/test/cases/build.config.layouts-directory/src/my-layouts/page.html @@ -1,6 +1,6 @@ - Custom Layout Page Template + Custom Layout Page Layout diff --git a/packages/cli/test/cases/build.config.layouts-directory/src/pages/index.md b/packages/cli/test/cases/build.config.layouts-directory/src/pages/index.md new file mode 100644 index 000000000..3332d3216 --- /dev/null +++ b/packages/cli/test/cases/build.config.layouts-directory/src/pages/index.md @@ -0,0 +1,3 @@ +# Home Page + +A page using a page layout from a custom layout directory. \ No newline at end of file diff --git a/packages/cli/test/cases/build.config.optimization-inline/build.config-optimization-inline.spec.js b/packages/cli/test/cases/build.config.optimization-inline/build.config-optimization-inline.spec.js index 149ae06dd..f025f762b 100644 --- a/packages/cli/test/cases/build.config.optimization-inline/build.config-optimization-inline.spec.js +++ b/packages/cli/test/cases/build.config.optimization-inline/build.config-optimization-inline.spec.js @@ -18,6 +18,8 @@ * components/ * foobar.js * header.js + * layouts/ + * app.html * pages/ * index.html * styles/ diff --git a/packages/cli/test/cases/build.config.optimization-inline/src/templates/app.html b/packages/cli/test/cases/build.config.optimization-inline/src/layouts/app.html similarity index 100% rename from packages/cli/test/cases/build.config.optimization-inline/src/templates/app.html rename to packages/cli/test/cases/build.config.optimization-inline/src/layouts/app.html diff --git a/packages/cli/test/cases/build.config.static-router/build.config.static-router.spec.js b/packages/cli/test/cases/build.config.static-router/build.config.static-router.spec.js index 56a992c28..f90f340a3 100644 --- a/packages/cli/test/cases/build.config.static-router/build.config.static-router.spec.js +++ b/packages/cli/test/cases/build.config.static-router/build.config.static-router.spec.js @@ -95,7 +95,7 @@ describe('Build Greenwood With: ', function() { expect(inlineRouterTags.length).to.be.equal(1); expect(inlineRouterTags[0].textContent).to.contain('window.__greenwood = window.__greenwood || {};'); - expect(inlineRouterTags[0].textContent).to.contain('window.__greenwood.currentTemplate = "page"'); + expect(inlineRouterTags[0].textContent).to.contain('window.__greenwood.currentLayout = "page"'); }); it('should have one tag in the for the content', function() { @@ -117,7 +117,7 @@ describe('Build Greenwood With: ', function() { const dataset = aboutRouteTag[0].dataset; expect(aboutRouteTag.length).to.be.equal(1); - expect(dataset.template).to.be.equal('test'); + expect(dataset.layout).to.be.equal('test'); expect(dataset.key).to.be.equal('/_routes/about/index.html'); }); @@ -128,7 +128,7 @@ describe('Build Greenwood With: ', function() { const dataset = aboutRouteTag[0].dataset; expect(aboutRouteTag.length).to.be.equal(1); - expect(dataset.template).to.be.equal('page'); + expect(dataset.layout).to.be.equal('page'); expect(dataset.key).to.be.equal('/_routes/index.html'); }); diff --git a/packages/cli/test/cases/build.config.static-router/src/pages/about.md b/packages/cli/test/cases/build.config.static-router/src/pages/about.md index b90299ace..5618aaa66 100644 --- a/packages/cli/test/cases/build.config.static-router/src/pages/about.md +++ b/packages/cli/test/cases/build.config.static-router/src/pages/about.md @@ -1,5 +1,5 @@ --- -template: test +layout: test --- ### Greenwood diff --git a/packages/cli/test/cases/build.config.static-router/src/pages/regex-test.html b/packages/cli/test/cases/build.config.static-router/src/pages/regex-test.html index e25174ef9..70b2aba4e 100644 --- a/packages/cli/test/cases/build.config.static-router/src/pages/regex-test.html +++ b/packages/cli/test/cases/build.config.static-router/src/pages/regex-test.html @@ -176,7 +176,7 @@

The static site generator for your. . .
-
+

Greenwood is a modern and performant static site generator for Web Component based development.

diff --git a/packages/cli/test/cases/build.config.templates-directory/greenwood.config.js b/packages/cli/test/cases/build.config.templates-directory/greenwood.config.js deleted file mode 100644 index 4ea248e54..000000000 --- a/packages/cli/test/cases/build.config.templates-directory/greenwood.config.js +++ /dev/null @@ -1,3 +0,0 @@ -export default { - templatesDirectory: 'layouts' -}; \ No newline at end of file diff --git a/packages/cli/test/cases/build.config.templates-directory/src/pages/index.md b/packages/cli/test/cases/build.config.templates-directory/src/pages/index.md deleted file mode 100644 index a44ed2d17..000000000 --- a/packages/cli/test/cases/build.config.templates-directory/src/pages/index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Home Page - -A page using a page template from a custom layout directory. \ No newline at end of file diff --git a/packages/cli/test/cases/build.default.meta/build.default.meta.spec.js b/packages/cli/test/cases/build.default.meta/build.default.meta.spec.js index 23efa5a6d..5dae7737f 100644 --- a/packages/cli/test/cases/build.default.meta/build.default.meta.spec.js +++ b/packages/cli/test/cases/build.default.meta/build.default.meta.spec.js @@ -1,6 +1,6 @@ /* * Use Case - * Run Greenwood and tests for correct `` tag merging for pages and templates. + * Run Greenwood and tests for correct `` tag merging for pages and layouts. * * User Result * Should generate a bare bones Greenwood build with one nested About page with expected meta values. @@ -19,7 +19,7 @@ * index.md * hello.md * index.md - * template/ + * layout/ * app.html * page.html */ diff --git a/packages/cli/test/cases/build.default.meta/src/templates/page.html b/packages/cli/test/cases/build.default.meta/src/layouts/page.html similarity index 100% rename from packages/cli/test/cases/build.default.meta/src/templates/page.html rename to packages/cli/test/cases/build.default.meta/src/layouts/page.html diff --git a/packages/cli/test/cases/build.default.ssr-prerender/build.default.ssr-prerender.spec.js b/packages/cli/test/cases/build.default.ssr-prerender/build.default.ssr-prerender.spec.js index 862072886..c16a01c02 100644 --- a/packages/cli/test/cases/build.default.ssr-prerender/build.default.ssr-prerender.spec.js +++ b/packages/cli/test/cases/build.default.ssr-prerender/build.default.ssr-prerender.spec.js @@ -19,7 +19,7 @@ * footer.js * pages/ * index.js - * templates/ + * layouts/ * app.html */ import chai from 'chai'; @@ -68,7 +68,7 @@ describe('Build Greenwood With: ', function() { expect(headings[0].textContent).to.equal('This is the home page.'); }); - it('should have one top level tag with a