Skip to content

Commit f6b25ae

Browse files
marcoowpichfl
authored andcommitted
Better handling of title tag and related meta tags (mainmatter#662)
* rename Header @title to @Headline * write title tags from page components' header * rename pageTitle arg to documentTitle * fix tests * fix formatting * restore blog index page title
1 parent b70f70f commit f6b25ae

File tree

32 files changed

+212
-84
lines changed

32 files changed

+212
-84
lines changed

config/routes-map.js

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ module.exports = function() {
88
let blogPostRoutes = posts.reduce((acc, post) => {
99
acc[`/blog/${post.queryPath}`] = {
1010
component: post.componentName,
11-
title: `${post.meta.title} | Blog`,
1211
bundle: {
1312
asset: `/blog/${post.queryPath}.js`,
1413
module: `__blog-${post.queryPath}__`,
@@ -23,7 +22,6 @@ module.exports = function() {
2322
let blogAuthorsRoutes = authors.reduce((acc, author) => {
2423
acc[`/blog/author/${author.twitter}`] = {
2524
component: author.componentName,
26-
title: `Posts by ${author.name} | Blog`,
2725
bundle: {
2826
asset: `/blog/author-${author.twitter}.js`,
2927
module: `__blog-author-${author.twitter}__`,
@@ -39,46 +37,41 @@ module.exports = function() {
3937
...blogPostRoutes,
4038
...blogAuthorsRoutes,
4139
'/': { component: 'PageHomepage' },
42-
'/404': { component: 'Page404', title: 'Not found' },
43-
'/blog': { component: 'PageBlog', title: 'Blog', bundle: { asset: '/blog.js', module: '__blog__' } },
40+
'/404': { component: 'Page404' },
41+
'/blog': { component: 'PageBlog', bundle: { asset: '/blog.js', module: '__blog__' } },
4442
'/calendar': {
4543
component: 'PageCalendar',
46-
title: 'Calendar',
4744
bundle: { asset: '/calendar.js', module: '__calendar__' },
4845
},
49-
'/cases/ddwrt': { component: 'PageCaseDdWrt', title: 'DD-WRT NXT | Work' },
50-
'/cases/expedition': { component: 'PageCaseStudyExpedition', title: 'Expedition | Work' },
51-
'/cases/timify': { component: 'PageCaseStudyTimify', title: 'Timify | Work' },
52-
'/cases/trainline': { component: 'PageCaseStudyTrainline', title: 'Trainline | Work' },
53-
'/contact': { component: 'PageContact', title: 'Contact' },
54-
'/expertise/ember': { component: 'PageEmberExpertise', title: 'Europe’s leading Ember experts' },
55-
'/expertise/elixir-phoenix': { component: 'PageElixirExpertise', title: 'Elixir & Phoenix' },
46+
'/cases/ddwrt': { component: 'PageCaseDdWrt' },
47+
'/cases/expedition': { component: 'PageCaseStudyExpedition' },
48+
'/cases/timify': { component: 'PageCaseStudyTimify' },
49+
'/cases/trainline': { component: 'PageCaseStudyTrainline' },
50+
'/contact': { component: 'PageContact' },
51+
'/expertise/ember': { component: 'PageEmberExpertise' },
52+
'/expertise/elixir-phoenix': { component: 'PageElixirExpertise' },
5653
'/imprint': {
5754
component: 'PageLegalImprint',
58-
title: 'Imprint',
5955
bundle: { asset: '/legal.js', module: '__legal__' },
6056
},
6157
'/playbook': {
6258
component: 'PagePlaybook',
63-
title: 'Playbook',
6459
bundle: { asset: '/playbook.js', module: '__playbook__' },
6560
},
6661
'/privacy': {
6762
component: 'PageLegalPrivacy',
68-
title: 'Privacy Policy',
6963
bundle: { asset: '/legal.js', module: '__legal__' },
7064
},
71-
'/services': { component: 'PageServices', title: 'Services' },
65+
'/services': { component: 'PageServices' },
7266
'/services/full-stack-engineering': {
7367
component: 'PageFullStackEngineering',
74-
title: 'Full Stack Engineering | Services',
7568
},
76-
'/services/team-augmentation': { component: 'PageTeamAugmentation', title: 'Team Augmentation | Services' },
77-
'/services/tutoring': { component: 'PageTutoring', title: 'Tutoring | Services' },
78-
'/talks': { component: 'PageTalks', title: 'Talks', bundle: { asset: '/talks.js', module: '__talks__' } },
79-
'/why-simplabs': { component: 'PageWhySimplabs', title: 'Why simplabs' },
80-
'/work': { component: 'PageWork', title: 'Work' },
81-
'/webinars/modern-web': { component: 'PageLandingPwaWebinar', title: 'Webinar: Modern Web Applications' },
69+
'/services/team-augmentation': { component: 'PageTeamAugmentation' },
70+
'/services/tutoring': { component: 'PageTutoring' },
71+
'/talks': { component: 'PageTalks', bundle: { asset: '/talks.js', module: '__talks__' } },
72+
'/why-simplabs': { component: 'PageWhySimplabs' },
73+
'/work': { component: 'PageWork' },
74+
'/webinars/modern-web': { component: 'PageLandingPwaWebinar' },
8275
};
8376

8477
return routes;

lib/generate-blog/lib/templates/author/template.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div>
2-
<Header @active="blog" @flex-content="true">
2+
<Header @active="blog" @flex-content="true" @title="Posts by {{name}}" @documentTitle="Posts by {{name}} | Blog">
33
<div class="blog-post.badge">
44
<div class="blog-post.badge-image">
55
<img class="fluid-image.image" src="/assets/images/authors/{{twitter}}.jpg" alt="photo of {{name}}" />

lib/generate-blog/lib/templates/post/template.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
"@context": "http://schema.org"
6565
}
6666
</script>
67-
<Header @active="blog" @flex-content="true">
67+
<Header @active="blog" @flex-content="true" @title="{{title}}" @documentTitle="{{title}} | Blog">
6868
<div class="blog-post.badge">
6969
<div class="blog-post.badge-image">
7070
<img

lib/generate-blog/lib/templates/start-page/template.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"@context": "http://schema.org"
2929
}
3030
</script>
31-
<Header @active="blog" @title="Blog" />
31+
<Header @active="blog" @headline="Blog" @title="Blog" />
3232
<ShapeBlog>
3333
<article>
3434
<span class="typography.tag">

lib/generate-calendar/lib/templates/page/template.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div>
2-
<Header @title="Calendar">
2+
<Header @headline="Calendar" @title="Calendar">
33
<p class="typography.lead">
44
Find out about upcoming events, conferences and meetups we will be attending or organizing.
55
</p>

lib/generate-talks-archive/lib/templates/page/template.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div>
2-
<Header @title="Talks">
2+
<Header @headline="Talks" @title="Talks">
33
<p class="typography.lead">
44
We strongly believe in the value of sharing our expertise and experience with others. Here are a collection of talks that members of our team have given at various conferences all over the world in the past years.
55
</p>

src/index.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ function register(registry, key: string, object: any) {
2020
}
2121
}
2222

23+
function readRoutesMap() {
24+
let script: HTMLElement | null = document.querySelector('[data-shoebox-routes]');
25+
if (script) {
26+
return JSON.parse(script.innerText);
27+
} else {
28+
return {};
29+
}
30+
}
31+
2332
app.registerInitializer({
2433
initialize(registry) {
2534
function registerBundle(module) {
@@ -37,6 +46,25 @@ app.registerInitializer({
3746
public registerBundle(module) {
3847
registerBundle(module);
3948
}
49+
50+
// tslint:disable-next-line:max-classes-per-file
51+
class AppState {
52+
53+
public static create() {
54+
return new AppState();
55+
}
56+
57+
public isSSR: boolean;
58+
public route: string;
59+
public origin: string;
60+
public routesMap: IRoutesMap;
61+
62+
constructor() {
63+
this.isSSR = false;
64+
this.route = window.location.pathname;
65+
this.origin = window.location.origin;
66+
this.routesMap = readRoutesMap();
67+
}
4068
}
4169

4270
document.querySelectorAll('[data-shoebox]').forEach((shoebox: HTMLElement) => {
@@ -65,6 +93,16 @@ app.registerInitializer({
6593
'headTags',
6694
`utils:/${app.appName}/head-tags/main`,
6795
);
96+
97+
registry.register(
98+
`app-state:/${app.appName}/main/main`,
99+
AppState
100+
);
101+
registry.registerInjection(
102+
`component`,
103+
'appState',
104+
`app-state:/${app.appName}/main/main`
105+
);
68106
}
69107
});
70108

src/ui/components/HeadTag/component.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
import Component from '@glimmer/component';
22

33
export default class HeadTag extends Component {
4+
private appState: IAppState;
5+
46
constructor(options) {
57
super(options);
68

7-
this.setMetaTags();
9+
if (this.appState.isSSR) {
10+
this.setMetaTags();
11+
} else {
12+
// when changing routes, the willDestroy of a component previously in the DOM
13+
// will be called *after* the constructor of one rendered *after* the route
14+
// change, so we have to delay writing the tag…
15+
window.setTimeout(() => this.setMetaTags());
16+
}
817
}
918

1019
public willDestroy() {

src/ui/components/Header/component.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Component from '@glimmer/component';
2+
3+
export default class Header extends Component {
4+
constructor(options) {
5+
super(options);
6+
7+
let documentTitle = this.args.documentTitle === undefined ? this.args.title : this.args.documentTitle;
8+
this.documentTitle = formatformatDocumentTitle(documentTitle);
9+
}
10+
}
11+
12+
function formatformatDocumentTitle(title) {
13+
return `${title ? `${title} | ` : ''}simplabs`;
14+
}

src/ui/components/Header/template.hbs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<header>
2+
<HeadTag @name="title" @content={{this.documentTitle}} />
3+
<HeadTag @name="meta" @keys={{hash property="og:title" name="twitter:title"}} @values={{hash content=@title}} />
24
<input id="toggle" type="checkbox" hidden="true" />
35
<div class="navbar" data-menu>
46
<div class="wrapper">
@@ -48,14 +50,14 @@
4850
</div>
4951
</div>
5052
<div class="content" state:flex-content={{@flex-content}}>
51-
{{#if @title}}
53+
{{#if @headline}}
5254
<h1 class="typography.display">
5355
{{#if @label}}
5456
<small class="typography.small">
5557
{{@label}}<span class="typography.hidden">:</span>
5658
</small>
5759
{{/if}}
58-
{{@title}}
60+
{{@headline}}
5961
</h1>
6062
{{/if}}
6163
{{yield}}

0 commit comments

Comments
 (0)