diff --git a/packages/cli/src/data/schema/graph.js b/packages/cli/src/data/schema/graph.js index 7840af4c5..f1c9f1797 100644 --- a/packages/cli/src/data/schema/graph.js +++ b/packages/cli/src/data/schema/graph.js @@ -22,16 +22,16 @@ const getPagesFromGraph = async (root, query, context) => { graph .forEach((page) => { - const { route, mdFile, fileName, template } = page; - const id = page.label; + const { route, mdFile, fileName, template, title } = page; const { label } = getDeriveMetaFromRoute(route); + const id = page.label; pages.push({ id, filePath: mdFile, fileName, template, - title: label, + title: title !== '' ? title : label, link: route }); }); @@ -69,11 +69,11 @@ const getChildrenFromParentRoute = async (root, query, context) => { graph .forEach((page) => { - const { route, mdFile, fileName, template } = page; + const { route, mdFile, fileName, template, title } = page; + const { label } = getDeriveMetaFromRoute(route); const root = route.split('/')[1]; if (root.indexOf(parent) >= 0) { - const { label } = getDeriveMetaFromRoute(route); const id = page.label; pages.push({ @@ -81,7 +81,7 @@ const getChildrenFromParentRoute = async (root, query, context) => { filePath: mdFile, fileName, template, - title: label, + title: title !== '' ? title : label, link: route }); } diff --git a/packages/cli/src/lifecycles/config.js b/packages/cli/src/lifecycles/config.js index 892d5a829..514453b64 100644 --- a/packages/cli/src/lifecycles/config.js +++ b/packages/cli/src/lifecycles/config.js @@ -9,7 +9,7 @@ let defaultConfig = { host: 'localhost' }, publicPath: '/', - title: 'Greenwood App', + title: 'My App', meta: [], plugins: [], themeFile: 'theme.css' diff --git a/packages/cli/src/lifecycles/graph.js b/packages/cli/src/lifecycles/graph.js index b457e5629..f9045ec0d 100644 --- a/packages/cli/src/lifecycles/graph.js +++ b/packages/cli/src/lifecycles/graph.js @@ -72,7 +72,7 @@ const createGraphFromPages = async (pagesDir, config) => { label = label || generateLabelHash(filePath); // set element text, override with markdown title - title = title || config.title; + title = title || ''; /* * Variable Definitions diff --git a/packages/cli/src/plugins/meta.js b/packages/cli/src/plugins/meta.js index 2e44ce269..b8c529a7b 100644 --- a/packages/cli/src/plugins/meta.js +++ b/packages/cli/src/plugins/meta.js @@ -56,14 +56,6 @@ class meta extends LitElement { header.appendChild(meta); } }); - - // handle tag - let title = document.createElement('title'); - - title.innerText = this.attributes.title; - const oldTitle = document.head.querySelector('title'); - - header.replaceChild(title, oldTitle); } } } diff --git a/packages/cli/src/templates/app-template.js b/packages/cli/src/templates/app-template.js index eee98601c..fc59bfc66 100644 --- a/packages/cli/src/templates/app-template.js +++ b/packages/cli/src/templates/app-template.js @@ -3,6 +3,9 @@ import { connectRouter } from 'lit-redux-router'; import { applyMiddleware, createStore, compose as origCompose, combineReducers } from 'redux'; import { lazyReducerEnhancer } from 'pwa-helpers/lazy-reducer-enhancer.js'; import thunk from 'redux-thunk'; +import client from '@greenwood/cli/data/client'; +import ConfigQuery from '@greenwood/cli/data/queries/config'; +import GraphQuery from '@greenwood/cli/data/queries/graph'; // eslint-disable-next-line no-underscore-dangle const compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || origCompose; @@ -17,6 +20,37 @@ import './list'; connectRouter(store); class AppComponent extends LitElement { + + async connectedCallback() { + super.connectedCallback(); + const route = window.location.pathname; + const response = await Promise.all([ + await client.query({ + query: ConfigQuery + }), + await client.query({ + query: GraphQuery + }) + ]); + const { config } = response[0].data; + const currentPage = response[1].data.graph.filter((page) => { + return route === page.link; + })[0]; + const currentPageTitleSuffix = currentPage.link === '/' + ? '' + : ` - ${currentPage.title}`; + const fullTitle = `${config.title}${currentPageTitleSuffix}`; + + this.setDocoumentTitle(fullTitle); + } + + setDocoumentTitle(title) { + const head = document.head; + const titleElement = head.getElementsByTagName('title')[0]; + + titleElement.innerHTML = title; + } + render() { return html` MYROUTES diff --git a/packages/cli/src/templates/index.html b/packages/cli/src/templates/index.html index b6ba9e499..fc7ca20f1 100644 --- a/packages/cli/src/templates/index.html +++ b/packages/cli/src/templates/index.html @@ -1,7 +1,7 @@ <!DOCTYPE html> <html lang="en" prefix="og:http://ogp.me/ns#"> <head> - <title>My App + @@ -20,6 +20,7 @@ + \ No newline at end of file diff --git a/packages/cli/test/cases/build.config.title/build.config.title.spec.js b/packages/cli/test/cases/build.config.title/build.config.title.spec.js index e60ad2c82..90f28767e 100644 --- a/packages/cli/test/cases/build.config.title/build.config.title.spec.js +++ b/packages/cli/test/cases/build.config.title/build.config.title.spec.js @@ -27,6 +27,7 @@ const expect = require('chai').expect; const runSmokeTest = require('../../../../../test/smoke-test'); const TestBed = require('../../../../../test/test-bed'); +const configTitle = require('./greenwood.config').title; const mainBundleScriptRegex = /index.*.bundle\.js/; describe('Build Greenwood With: ', function() { @@ -45,7 +46,6 @@ describe('Build Greenwood With: ', function() { runSmokeTest(['public', 'not-found', 'hello'], LABEL); describe('Custom Title', function() { - const indexPageTitle = 'My Custom Greenwood App'; const indexPageHeading = 'Greenwood'; const indexPageBody = 'This is the home page built by Greenwood. Make your own pages in src/pages/index.js!'; let dom; @@ -61,7 +61,7 @@ describe('Build Greenwood With: ', function() { it('should have our custom config meta tag in the <head>', function() { const title = dom.window.document.querySelector('head title').textContent; - expect(title).to.be.equal(indexPageTitle); + expect(title).to.be.equal(configTitle); }); // rest of index smoke-test because <title> is changed for this case @@ -116,7 +116,7 @@ describe('Build Greenwood With: ', function() { it('should have a overridden meta tag in the <head> using markdown front-matter', function() { const title = dom.window.document.querySelector('head title').textContent; - expect(title).to.be.equal(helloPageTitle); + expect(title).to.be.equal(`${configTitle} - ${helloPageTitle}`); }); }); }); diff --git a/packages/cli/test/cases/build.default.workspace-template-app/build.default.workspace-template-app.spec.js b/packages/cli/test/cases/build.default.workspace-template-app/build.default.workspace-template-app.spec.js index 57565a319..215e45bd5 100644 --- a/packages/cli/test/cases/build.default.workspace-template-app/build.default.workspace-template-app.spec.js +++ b/packages/cli/test/cases/build.default.workspace-template-app/build.default.workspace-template-app.spec.js @@ -51,10 +51,10 @@ describe('Build Greenwood With: ', function() { dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, 'index.html')); }); - it('should have a <title> tag in the <head>', function() { + it('should have the default config title in the <title> tag in the <head>', function() { const title = dom.window.document.querySelector('head title').textContent; - expect(title).to.be.equal('Greenwood App'); + expect(title).to.be.equal('My App'); }); it('should have one <script> tag in the <body> for the main bundle', function() { diff --git a/packages/cli/test/cases/build.default.workspace-template-app/src/templates/app-template.js b/packages/cli/test/cases/build.default.workspace-template-app/src/templates/app-template.js index 301b888e0..bfa938540 100644 --- a/packages/cli/test/cases/build.default.workspace-template-app/src/templates/app-template.js +++ b/packages/cli/test/cases/build.default.workspace-template-app/src/templates/app-template.js @@ -3,6 +3,8 @@ import { connectRouter } from 'lit-redux-router'; import { applyMiddleware, createStore, compose as origCompose, combineReducers } from 'redux'; import { lazyReducerEnhancer } from 'pwa-helpers/lazy-reducer-enhancer.js'; import thunk from 'redux-thunk'; +import client from '@greenwood/cli/data/client'; +import ConfigQuery from '@greenwood/cli/data/queries/config'; // eslint-disable-next-line no-underscore-dangle const compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || origCompose; @@ -18,6 +20,25 @@ import './list'; connectRouter(store); class AppComponent extends LitElement { + + async connectedCallback() { + super.connectedCallback(); + + const response = await client.query({ + query: ConfigQuery + }); + const { config } = response.data; + + this.setDocoumentTitle(config.title); + } + + setDocoumentTitle(title) { + const head = document.head; + const titleElement = head.getElementsByTagName('title')[0]; + + titleElement.innerHTML = title; + } + render() { return html` MYROUTES diff --git a/packages/cli/test/unit/data/mocks/graph.js b/packages/cli/test/unit/data/mocks/graph.js index ac3307345..3000c1dca 100644 --- a/packages/cli/test/unit/data/mocks/graph.js +++ b/packages/cli/test/unit/data/mocks/graph.js @@ -18,7 +18,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/about/community.md', fileName: 'community', relativeExpectedPath: '\'../about/community/community.js\'', - title: 'Greenwood', + title: 'About', meta: [Array] }, { mdFile: './about/features.md', label: '856848d74d8428b', @@ -28,7 +28,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/about/features.md', fileName: 'features', relativeExpectedPath: '\'../about/features/features.js\'', - title: 'Greenwood', + title: 'About', meta: [Array] }, { mdFile: './about/how-it-works.md', label: 'f7f7b27e3c27d0c', @@ -38,7 +38,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/about/how-it-works.md', fileName: 'how-it-works', relativeExpectedPath: '\'../about/how-it-works/how-it-works.js\'', - title: 'Greenwood', + title: 'About', meta: [Array] }, { mdFile: './about/goals.md', label: '9e1ec40126cbaa1', @@ -48,7 +48,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/about/goals.md', fileName: 'goals', relativeExpectedPath: '\'../about/goals/goals.js\'', - title: 'Greenwood', + title: 'About', meta: [Array] }, { mdFile: './about/index.md', label: 'about', @@ -58,7 +58,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/about/index.md', fileName: 'index', relativeExpectedPath: '\'../about/index/index.js\'', - title: 'Greenwood', + title: 'About', meta: [Array] }, { mdFile: './docs/component-model.md', label: '41d241788aba406', @@ -68,7 +68,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/docs/component-model.md', fileName: 'component-model', relativeExpectedPath: '\'../docs/component-model/component-model.js\'', - title: 'Greenwood', + title: 'Docs', meta: [Array] }, { mdFile: './docs/configuration.md', label: 'b8027b72fecbdf6', @@ -78,7 +78,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/docs/configuration.md', fileName: 'configuration', relativeExpectedPath: '\'../docs/configuration/configuration.js\'', - title: 'Greenwood', + title: 'Docs', meta: [Array] }, { mdFile: './docs/index.md', label: '4ed3ee4d104185e', @@ -88,7 +88,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/docs/index.md', fileName: 'index', relativeExpectedPath: '\'../docs/index/index.js\'', - title: 'Greenwood', + title: 'Docs', meta: [Array] }, { mdFile: './docs/front-matter.md', label: '0441281c8197941', @@ -98,7 +98,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/docs/front-matter.md', fileName: 'front-matter', relativeExpectedPath: '\'../docs/front-matter/front-matter.js\'', - title: 'Greenwood', + title: 'Docs', meta: [Array] }, { mdFile: './docs/layouts.md', label: 'ff00fdc5a5bb79e', @@ -108,7 +108,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/docs/layouts.md', fileName: 'layouts', relativeExpectedPath: '\'../docs/layouts/layouts.js\'', - title: 'Greenwood', + title: 'Docs', meta: [Array] }, { mdFile: './docs/css-and-images.md', label: '6ec677142cf4506', @@ -118,7 +118,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/docs/css-and-images.md', fileName: 'css-and-images', relativeExpectedPath: '\'../docs/css-and-images/css-and-images.js\'', - title: 'Greenwood', + title: 'Docs', meta: [Array] }, { mdFile: './docs/tech-stack.md', label: '5f2e96ac1d461f1', @@ -128,7 +128,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/docs/tech-stack.md', fileName: 'tech-stack', relativeExpectedPath: '\'../docs/tech-stack/tech-stack.js\'', - title: 'Greenwood', + title: 'Docs', meta: [Array] }, { mdFile: './getting-started/branding.md', label: '5436f1acd7a0297', @@ -138,7 +138,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/getting-started/branding.md', fileName: 'branding', relativeExpectedPath: '\'../getting-started/branding/branding.js\'', - title: 'Greenwood', + title: 'Getting Started', meta: [Array] }, { mdFile: './getting-started/creating-content.md', label: '878f45b3dea2a2e', @@ -149,7 +149,7 @@ const MOCK_GRAPH = { fileName: 'creating-content', relativeExpectedPath: '\'../getting-started/creating-content/creating-content.js\'', - title: 'Greenwood', + title: 'Getting Started', meta: [Array] }, { mdFile: './docs/markdown.md', label: 'd16333ec756763b', @@ -159,7 +159,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/docs/markdown.md', fileName: 'markdown', relativeExpectedPath: '\'../docs/markdown/markdown.js\'', - title: 'Greenwood', + title: 'Getting Started', meta: [Array] }, { mdFile: './getting-started/key-concepts.md', label: '7135cdf1062f91e', @@ -169,7 +169,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/getting-started/key-concepts.md', fileName: 'key-concepts', relativeExpectedPath: '\'../getting-started/key-concepts/key-concepts.js\'', - title: 'Greenwood', + title: 'Getting Started', meta: [Array] }, { mdFile: './getting-started/build-and-deploy.md', label: '1abbe13654a8651', @@ -180,7 +180,7 @@ const MOCK_GRAPH = { fileName: 'build-and-deploy', relativeExpectedPath: '\'../getting-started/build-and-deploy/build-and-deploy.js\'', - title: 'Greenwood', + title: 'Getting Started', meta: [Array] }, { mdFile: './getting-started/index.md', label: '0f09ddfde58fbc3', @@ -190,7 +190,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/getting-started/index.md', fileName: 'index', relativeExpectedPath: '\'../getting-started/index/index.js\'', - title: 'Greenwood', + title: 'Getting Started', meta: [Array] }, { mdFile: './getting-started/project-setup.md', label: 'd13f3b1a48b11ac', @@ -200,7 +200,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/getting-started/project-setup.md', fileName: 'project-setup', relativeExpectedPath: '\'../getting-started/project-setup/project-setup.js\'', - title: 'Greenwood', + title: 'Getting Started', meta: [Array] }, { mdFile: './getting-started/next-steps.md', label: 'e80510568562ced', @@ -210,7 +210,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/getting-started/next-steps.md', fileName: 'next-steps', relativeExpectedPath: '\'../getting-started/next-steps/next-steps.js\'', - title: 'Greenwood', + title: 'Getting Started', meta: [Array] }, { mdFile: './getting-started/quick-start.md', label: 'cf130a69289425d', @@ -220,7 +220,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/getting-started/quick-start.md', fileName: 'quick-start', relativeExpectedPath: '\'../getting-started/quick-start/quick-start.js\'', - title: 'Greenwood', + title: 'Getting Started', meta: [Array] }, { mdFile: './plugins/webpack.md', label: '9d2b98c69ab0867', @@ -230,7 +230,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/plugins/webpack.md', fileName: 'webpack', relativeExpectedPath: '\'../plugins/webpack/webpack.js\'', - title: 'Greenwood', + title: 'Plugins', meta: [Array] }, { mdFile: './plugins/composite-plugins.md', label: '8b231661fded283', @@ -240,7 +240,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/plugins/composite-plugins.md', fileName: 'composite-plugins', relativeExpectedPath: '\'../plugins/composite-plugins/composite-plugins.js\'', - title: 'Greenwood', + title: 'Plugins', meta: [Array] }, { mdFile: './plugins/index-hooks.md', label: '272e40c3703d4f2', @@ -250,7 +250,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/plugins/index-hooks.md', fileName: 'index-hooks', relativeExpectedPath: '\'../plugins/index-hooks/index-hooks.js\'', - title: 'Greenwood', + title: 'Plugins', meta: [Array] }, { mdFile: './docs/data.md', label: '5082835f0f7f7d7', @@ -260,7 +260,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/docs/data.md', fileName: 'data', relativeExpectedPath: '\'../docs/data/data.js\'', - title: 'Greenwood', + title: 'Docs', meta: [Array] }, { mdFile: './plugins/index.md', label: 'dd1ec2ef00cc386', @@ -270,7 +270,7 @@ const MOCK_GRAPH = { '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/pages/plugins/index.md', fileName: 'index', relativeExpectedPath: '\'../plugins/index/index.js\'', - title: 'Greenwood', + title: 'Plugins', meta: [Array] } ] diff --git a/test/smoke-test.js b/test/smoke-test.js index 7f041bb70..6e4dc513a 100644 --- a/test/smoke-test.js +++ b/test/smoke-test.js @@ -85,7 +85,7 @@ function defaultIndex(label) { it('should have a <title> tag in the <head>', function() { const title = dom.window.document.querySelector('head title').textContent; - expect(title).to.be.equal('Greenwood App'); + expect(title).to.be.equal('My App'); }); it('should have one <script> tag in the <body> for the main bundle', function() { diff --git a/www/components/shelf/shelf.js b/www/components/shelf/shelf.js index f6bdbbabf..64935914c 100644 --- a/www/components/shelf/shelf.js +++ b/www/components/shelf/shelf.js @@ -64,6 +64,7 @@ class Shelf extends LitElement { parent: page } }); + console.log('response from the shelf (data.children)', response.data.children); this.shelfList = list; diff --git a/www/pages/docs/data.md b/www/pages/docs/data.md index 4a2d7a861..70a99348a 100644 --- a/www/pages/docs/data.md +++ b/www/pages/docs/data.md @@ -34,7 +34,7 @@ Greenwood exposes a [GraphQL](https://graphql.org/) + [Apollo](https://www.apoll ![graphql-playground](/assets/graphql-playground.png) #### Schema -To kick things off, let's review what is availalble to you. Currently, the main "API" is just a list of all pages in your _pages/_ directory, represented as a `Page` [type definition](https://graphql.org/graphql-js/basic-types/). This is called Greenwood's `graph`. +To kick things off, let's review what is available to you. Currently, the main "API" is just a list of all pages in your _pages/_ directory, represented as a `Page` [type definition](https://graphql.org/graphql-js/basic-types/). This is called Greenwood's `graph`. This is what the schema looks like: @@ -44,7 +44,7 @@ graph { link, // (string) A URL link, typically derived from the filesystem path, e.g. /blog/2019/first-post/ - title, // (string) Useful for a page's <title> tag or the title attribute for an <a> tag, inferred from the filesystem path, e.g. "First Post" + title, // (string) Useful for a page's <title> tag or the title attribute for an <a> tag, inferred from the filesystem path, e.g. "First Post" or provided through front matter. filePath, // (string) path to file