Skip to content

Commit

Permalink
Blog index pagination (mainmatter#690)
Browse files Browse the repository at this point in the history
* Allow ArrowLink to be reversed for pagination

* make blog components and template more generic

* split blog posts into pages

* make pagination links work

* make bundle split patterns more flexbile

* bundle blog posts with respective pages

* make blog page of each post its parent bundle

* drop blog.js bundle

* cache blog bundles in service worker

* format
  • Loading branch information
pichfl authored Aug 21, 2019
1 parent 94ef3c5 commit 9a065a1
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 71 deletions.
55 changes: 37 additions & 18 deletions config/routes-map.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,63 @@
'use strict';

const path = require('path');

const _ = require('lodash');

const collectPosts = require('../lib/generate-blog/lib/collect-posts');

module.exports = function() {
let { posts, authors } = collectPosts(path.join(__dirname, '..', '_posts'));
let blogPostRoutes = posts.reduce((acc, post) => {
acc[`/blog/${post.queryPath}`] = {
component: post.componentName,
bundle: {
asset: `/blog/${post.queryPath}.js`,
module: `__blog-${post.queryPath}__`,
},
parentBundle: {
asset: '/blog.js',
},
};
return acc;
}, {});

let blogAuthorsRoutes = authors.reduce((acc, author) => {
acc[`/blog/author/${author.twitter}`] = {
component: author.componentName,
bundle: {
asset: `/blog/author-${author.twitter}.js`,
module: `__blog-author-${author.twitter}__`,
},
parentBundle: {
asset: '/blog.js',
},
};
return acc;
}, {});

let blogPages = _.chunk(posts, 10);
let blogPostRoutes = {};
let blogPagesRoutes = {};
blogPages.forEach((pagePosts, i) => {
let page = i + 1;
let route;
if (page === 1) {
route = '/blog';
} else {
route = `/blog/page/${page}`;
}
blogPagesRoutes[route] = {
component: `PageBlogPage${page}`,
bundle: {
asset: `/blog/page/${page}.js`,
module: `__blog-page-${page}__`,
},
};

for (let post of pagePosts) {
blogPostRoutes[`/blog/${post.queryPath}`] = {
component: post.componentName,
bundle: {
asset: `/blog/${post.queryPath}.js`,
module: `__blog-${post.queryPath}__`,
},
parentBundle: {
asset: `/blog/page/${page}.js`,
},
};
}
});

let routes = {
...blogPagesRoutes,
...blogPostRoutes,
...blogAuthorsRoutes,
'/': { component: 'PageHomepage' },
'/404': { component: 'Page404' },
'/blog': { component: 'PageBlog', bundle: { asset: '/blog.js', module: '__blog__' } },
'/calendar': {
component: 'PageCalendar',
bundle: { asset: '/calendar.js', module: '__calendar__' },
Expand Down
39 changes: 27 additions & 12 deletions ember-cli-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,8 @@ class SimplabsApp extends GlimmerApp {
}

package(jsTree) {
let [blogTree, mainSiteTree] = this._splitBundle(jsTree, {
let mainSiteTree = this._dropBundle(jsTree, {
componentPrefix: 'PageBlog',
file: 'blog.js',
moduleName: '__blog__',
});

let { posts, authors } = collectPosts(path.join(__dirname, '_posts'));
Expand All @@ -84,6 +82,7 @@ class SimplabsApp extends GlimmerApp {
});
return blogPostTree;
});

let blogAuthorTrees = authors.map(author => {
let [blogAuthorTree] = this._splitBundle(jsTree, {
componentPrefix: author.componentName,
Expand All @@ -93,6 +92,18 @@ class SimplabsApp extends GlimmerApp {
return blogAuthorTree;
});

let blogPages = _.chunk(posts, 10);
let blogPageTrees = blogPages.map((posts, i) => {
let page = i + 1;
let postPrefixes = posts.map(post => post.componentName).join('|');
let [blogPageTree] = this._splitBundle(jsTree, {
componentPrefix: `PageBlogPage${page}|${postPrefixes}`,
file: `blog/page/${page}.js`,
moduleName: `__blog-page-${page}__`,
});
return blogPageTree;
});

let [calendarTree, mainSiteNonCalendarTree] = this._splitBundle(mainSiteTree, {
componentPrefix: 'PageCalendar',
file: 'calendar.js',
Expand Down Expand Up @@ -136,9 +147,9 @@ class SimplabsApp extends GlimmerApp {
playbookTree,
talksTree,
recentContentTree,
blogTree,
...blogPostTrees,
...blogAuthorTrees,
...blogPageTrees,
]);

if (process.env.PRERENDER) {
Expand Down Expand Up @@ -177,14 +188,7 @@ class SimplabsApp extends GlimmerApp {
}

_splitBundle(appTree, bundle) {
let mainBundleTree = new Funnel(appTree, {
exclude: [`src/ui/components/${bundle.componentPrefix}*`],
});
let mainBundleJsTree = new Funnel(mainBundleTree, {
include: ['**/*.js'],
});
let mainBundleModuleMap = this.buildResolutionMap(mainBundleJsTree);
mainBundleTree = new MergeTrees([mainBundleTree, mainBundleModuleMap], { overwrite: true });
let mainBundleTree = this._dropBundle(appTree, bundle);

let bundleTree = new Funnel(appTree, {
exclude: [`src/ui/components/!(${bundle.componentPrefix})*`],
Expand All @@ -199,6 +203,17 @@ class SimplabsApp extends GlimmerApp {
return [bundleTree, mainBundleTree];
}

_dropBundle(appTree, bundle) {
let mainBundleTree = new Funnel(appTree, {
exclude: [`src/ui/components/+(${bundle.componentPrefix})*`],
});
let mainBundleJsTree = new Funnel(mainBundleTree, {
include: ['**/*.js'],
});
let mainBundleModuleMap = this.buildResolutionMap(mainBundleJsTree);
return new MergeTrees([mainBundleTree, mainBundleModuleMap], { overwrite: true });
}

_packageSplitBundle(bundleTree, bundle) {
return new Rollup(bundleTree, {
rollup: {
Expand Down
6 changes: 4 additions & 2 deletions lib/generate-blog/lib/collect-posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ module.exports = function(folder) {
content,
};
});

let authors = _.chain(posts)
posts = _.chain(posts)
.sortBy('meta.date')
.reverse()
.value();

let authors = _.chain(posts)
.uniqBy('meta.twitter')
.map(post => {
let componentName = buildAuthorComponentName(post);
Expand Down
37 changes: 28 additions & 9 deletions lib/generate-blog/lib/components-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ module.exports = class ComponentsBuilder extends BaseComponentsBuilder {
}

writeComponentFiles() {
this._writeStartPageComponent();
let chunks = _.chunk(this.posts, 10);
chunks.forEach((chunk, i) => this._writeListPageComponent(chunk, i + 1, chunks.length));

for (let post of this.posts) {
let related = this._findRelatedPost(post);
Expand All @@ -58,17 +59,35 @@ module.exports = class ComponentsBuilder extends BaseComponentsBuilder {
}
}

_writeStartPageComponent() {
let [latest, ...rest] = this.posts;
let data = {
latest: this._preparePostTemplateData(latest),
rest: rest.map(post => this._preparePostTemplateData(post)),
_writeListPageComponent(chunk, page, totalPages) {
let componentName = `PageBlogPage${page}`;

let data = {};
let posts = chunk;
if (page === 1) {
let [latest, ...rest] = chunk;
posts = rest;
data.latest = this._preparePostTemplateData(latest);
}
posts = posts.map(post => this._preparePostTemplateData(post));

let previousPage = page > 1 ? (page > 2 ? `/blog/page/${page - 1}` : '/blog') : null;
let nextPage = page < totalPages ? `/blog/page/${page + 1}` : null;

data = {
...data,
posts,
previousPage,
nextPage,
};
let componentTemplate = this.templates['start-page'].template(data);
let componentTemplate = this.templates['list-page'].template(data);

let componentCssBlock = this.templates['start-page'].stylesheet();
data = {
componentName,
};
let componentCssBlock = this.templates['list-page'].stylesheet(data);

this.writeComponent('PageBlog', componentTemplate, componentCssBlock);
this.writeComponent(componentName, componentTemplate, componentCssBlock);
}

_writePostComponent(post, related) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
@block layout from "../../styles/blocks/layout.block.css";
@block offset from "../../styles/blocks/offset.block.css";
@block typography from "../../styles/blocks/typography.block.css";
@block pagination from '../../styles/blocks/pagination.block.css';

:scope {
block-name: PageBlog;
block-name: {{componentName}};
composes: 'layout';
}

.tweet {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,34 @@
>
<HeaderContent @headline="Blog" />
</Header>
<ShapeBlog>
<article>
<span class="typography.tag">
#
{{latest.topic}}
</span>
<h2 class="offset.before-none">
<a href="{{latest.path}}" data-internal>
{{latest.title}}
{{#if latest}}
<ShapeBlog>
<article>
<span class="typography.tag">
#{{latest.topic}}
</span>
<h2 class="offset.before-none">
<a href="{{latest.path}}" data-internal>
{{latest.title}}
</a>
</h2>
<div class="typography.lead offset.after-3">
{{{latest.excerpt}}}
</div>
<a href="/blog/author/{{latest.author.twitter}}/" data-internal>
{{latest.author.name}}
</a>
</h2>
<div class="typography.lead offset.after-3">
{{{latest.excerpt}}}
</div>
<a href="/blog/author/{{latest.author.twitter}}/" data-internal>
{{latest.author.name}}
</a>
<p class="typography.small">
{{latest.date}}
</p>
<ArrowLink @href="{{latest.path}}">
Read Post
</ArrowLink>
</article>
</ShapeBlog>
<p class="typography.small">
{{latest.date}}
</p>
<ArrowLink @href="{{latest.path}}">
Read Post
</ArrowLink>
</article>
</ShapeBlog>
{{/if}}
<section class="layout.main offset.after-21">
{{#each rest}}
{{#each posts}}
<article class="offset.after-12">
<span class="typography.tag">
#
Expand All @@ -84,6 +85,18 @@
</p>
</article>
{{/each}}
<nav aria-label="pagination" class="pagination">
{{#if nextPage}}
<ArrowLink @href="{{nextPage}}" @reverse="true">
Older
</ArrowLink>
{{/if}}
{{#if previousPage}}
<ArrowLink @href="{{previousPage}}">
Newer
</ArrowLink>
{{/if}}
</nav>
</section>
<aside class="layout.side offset.after-21">
<CardTalks />
Expand Down
2 changes: 1 addition & 1 deletion lib/service-workers/lib/worker-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module.exports = class WorkerBuilder extends BroccoliPlugin {

findAssets(assetsFolder) {
return walkSync(assetsFolder, {
globs: ['**/*.png', '**/*.jpg', '**/*.gif', '**/*.svg'],
globs: ['**/*.png', '**/*.jpg', '**/*.gif', '**/*.svg', '**/blog/page/*.js', '**/blog/author-*.js'],
});
}

Expand Down
1 change: 0 additions & 1 deletion lib/service-workers/workers/service-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import ASSETS from './assets/paths.js';
const PRE_CACHED_ASSETS = [
'/app.js',
'/app.css',
'/blog.js',
'/calendar.js',
'/legal.js',
'/playbook.js',
Expand Down
24 changes: 24 additions & 0 deletions src/ui/components/ArrowLink/stylesheet.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
pointer-events: none;
}

:scope + :scope {
margin-top: 0;
}

.link {
position: relative;
display: inline-block;
Expand Down Expand Up @@ -38,3 +42,23 @@
.arrow {
fill: var(--color-link);
}

:scope[state|reverse='true'] .link {
padding: 1.5rem 0 1.5rem 7rem;
}

@media (min-width: 888px) {
:scope[state|reverse='true'] .link {
margin-left: -7rem;
}
}

:scope[state|reverse='true'] .svg {
right: unset;
left: 0;
transform: translate(0) scaleX(-1);
}

:scope[state|reverse='true']:hover .svg {
transform: translate(-0.5rem) scaleX(-1);
}
2 changes: 1 addition & 1 deletion src/ui/components/ArrowLink/template.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<p>
<p state:reverse="{{@reverse}}">
<a class="link" href={{@href}} target={{this.target}} data-internal={{this.isInternal}} rel={{this.rel}}>
{{yield}}
<svg height="40" viewBox="0 0 40 40" width="40" xmlns="http://www.w3.org/2000/svg" class="svg">
Expand Down
6 changes: 6 additions & 0 deletions src/ui/styles/blocks/pagination.block.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
:scope {
block-name: pagination;

display: flex;
justify-content: space-between;
}

0 comments on commit 9a065a1

Please sign in to comment.