Skip to content
This repository was archived by the owner on Sep 10, 2022. It is now read-only.

Commit 3efe29e

Browse files
committed
Merge pull request #11 from addyosmani/sw-app-shell
Sw app shell
2 parents 0c8e6c7 + cebc4a4 commit 3efe29e

28 files changed

+561
-947
lines changed

.eslintrc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,12 @@
3939
"space-before-function-paren": [2, "never"],
4040
"spaced-comment": 2,
4141
"valid-typeof": 2,
42-
"no-unused-vars": [2, {"args": "none"}]
42+
"no-unused-vars": [2, {"args": "none"}],
43+
"no-empty-class": 0,
44+
"no-extra-strict": 0,
45+
"no-reserved-keys": 0,
46+
"no-space-before-semi": 0,
47+
"no-wrap-func": 0
4348
},
4449
"env": {
4550
"es6": true,

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "app-shell",
3-
"version": "0.1.150",
3+
"version": "0.1.159",
44
"private": true,
55
"license": "Apache",
66
"engines": {

server/app.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,9 @@
1313

1414
var serverController = require('./controllers/server-controller');
1515
var StaticPageController = require('./controllers/static-page-controller');
16+
var PartialsController = require('./controllers/partials-controller');
1617

18+
// PartialsController serves up the HTML without any HTML body or head
19+
serverController.addEndpoint('/partials*', new PartialsController());
20+
// The static page controller serves the basic form of the pages
1721
serverController.addEndpoint('/*', new StaticPageController());
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
3+
var pathConfigs = require('../models/path-config.js');
4+
5+
function PartialsController() {
6+
7+
}
8+
9+
// This method looks at the request path and renders the appropriate handlebars
10+
// template
11+
PartialsController.prototype.onRequest = function(req, res) {
12+
var urlSections = req.path.split('/');
13+
urlSections = urlSections.filter(function(sectionString) {
14+
return sectionString.length > 0;
15+
});
16+
17+
var urlPath = null;
18+
if (urlSections.length === 1) {
19+
urlPath = '/';
20+
} else {
21+
urlPath = '/' + urlSections[1];
22+
}
23+
24+
var pathConfig = pathConfigs.getConfig(urlPath);
25+
if (!pathConfig) {
26+
res.status(404).send();
27+
return;
28+
}
29+
30+
pathConfig.layout = 'partial';
31+
res.render(pathConfig.view, pathConfig);
32+
};
33+
34+
module.exports = PartialsController;

server/controllers/static-page-controller.js

Lines changed: 16 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,31 @@
11
'use strict';
22

3-
var fs = require('fs');
4-
var path = require('path');
3+
var pathConfigs = require('../models/path-config.js');
54

65
function StaticPageController() {
76

87
}
98

10-
function prepareData(config) {
11-
// Concat inline styles for document <head>
12-
var flattenedStyles = '';
13-
var pathPrefix = '/../../dist/';
14-
config.inlineStyles.forEach(function(file) {
15-
flattenedStyles += fs.readFileSync(path.resolve(__dirname) +
16-
pathPrefix + file);
17-
});
18-
19-
// Replace array with flattened string of content
20-
config.inlineStyles = flattenedStyles;
21-
return config;
22-
}
23-
249
// This method looks at the request path and renders the appropriate handlebars
2510
// template
2611
StaticPageController.prototype.onRequest = function(req, res) {
12+
var pathConfig = pathConfigs.getConfig(req.path);
13+
if (!pathConfig) {
14+
res.status(404).send();
15+
return;
16+
}
17+
18+
2719
switch (req.path) {
28-
case '/':
29-
res.render('index', prepareData({
30-
inlineStyles: ['/styles/core.css'],
31-
remoteStyles: [],
32-
inlineScripts: [],
33-
remoteScripts: ['/scripts/static-page.js']
34-
}));
35-
break;
36-
case '/url-1':
37-
res.render('url-1', prepareData({
38-
inlineStyles: ['/styles/core.css'],
39-
remoteStyles: [],
40-
inlineScripts: [],
41-
remoteScripts: ['/scripts/static-page.js']
42-
}));
43-
break;
44-
case '/url-2':
45-
res.render('url-2', prepareData({
46-
inlineStyles: ['/styles/core.css'],
47-
remoteStyles: [],
48-
inlineScripts: [],
49-
remoteScripts: ['/scripts/static-page.js']
50-
}));
51-
break;
20+
case '/app-shell':
21+
// Render with app-shell layout and include no initial content
22+
pathConfig.layout = 'app-shell';
23+
res.render('', pathConfig);
24+
return;
5225
default:
53-
res.status(404).send();
54-
break;
26+
// Use default layout
27+
res.render(pathConfig.view, pathConfig);
28+
return;
5529
}
5630
};
5731

server/layouts/app-shell.handlebars

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<!--
2+
3+
Copyright 2015 Google Inc. All rights reserved.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
17+
-->
18+
19+
<!DOCTYPE html>
20+
<html>
21+
<head>
22+
<meta charset="utf-8">
23+
<title>App Shell</title>
24+
25+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
26+
<meta name="viewport" content="width=device-width, initial-scale=1">
27+
<meta id="theme-color" name="theme-color" content="#4527A0">
28+
29+
<link rel="manifest" href="/manifest.json">
30+
<link rel="icon" href="/images/chrome-touch-icon-192x192.png" sizes="192x192" type="image/png">
31+
32+
<style type="text/css">{{{inlineStyles}}}</style>
33+
</head>
34+
<body class="{{ deeplink_class }}">
35+
36+
<!-- Header element -->
37+
<header class="header">
38+
<button role="tab" class="header__menu js-toggle-menu">
39+
Toggle nav menu
40+
</button>
41+
42+
<h1 class="header__title">App Shell</h1>
43+
</header>
44+
45+
<!-- Main Content goes here -->
46+
<main class="main js-global-main" aria-role="main"></main>
47+
48+
<!-- Navigation Drawer -->
49+
<section class="side-nav js-side-nav">
50+
<div class="side-nav__content js-side-nav-content">
51+
<div class="side-nav__header">
52+
<h1 class="side-nav__title">App shell</h1>
53+
</div>
54+
55+
<div class="side-nav__body" tabindex="0">
56+
<a role="tab" tabindex="0" class="side-nav__blog-post" href="/">Index</a>
57+
<a role="tab" tabindex="0" class="side-nav__blog-post" href="/url-1">URL 1</a>
58+
<a role="tab" tabindex="0" class="side-nav__blog-post" href="/url-2">URL 2</a>
59+
</div>
60+
61+
<div class="side-nav__version">Version @VERSION@</div>
62+
</div>
63+
</section>
64+
65+
<!-- Loading Dialog For use by Activities -->
66+
<div class="loader js-global-loader is-hidden">
67+
<svg viewBox="0 0 32 32" width="32" height="32">
68+
<style>
69+
#spinner {
70+
box-sizing: border-box;
71+
stroke: #673AB7;
72+
stroke-width: 3px;
73+
transform-origin: 50%;
74+
75+
-webkit-animation: line 1.6s cubic-bezier(0.4, 0.0, 0.2, 1) infinite, rotate 1.6s linear infinite;
76+
}
77+
78+
@-webkit-keyframes rotate {
79+
80+
from {
81+
transform: rotate(0)
82+
}
83+
84+
to {
85+
transform: rotate(450deg);
86+
}
87+
}
88+
89+
@-webkit-keyframes line {
90+
0% {
91+
stroke-dasharray: 2, 85.964;
92+
transform: rotate(0);
93+
}
94+
95+
50% {
96+
stroke-dasharray: 65.973, 21.9911;
97+
stroke-dashoffset: 0;
98+
}
99+
100+
100% {
101+
stroke-dasharray: 2, 85.964;
102+
stroke-dashoffset: -65.973;
103+
transform: rotate(90deg);
104+
}
105+
}
106+
</style>
107+
<circle id="spinner" cx="16" cy="16" r="14" fill="none"></circle>
108+
</svg>
109+
</div>
110+
111+
{{#each remoteScripts}}
112+
<script src="{{this}}" async></script>
113+
{{~/each}}
114+
</body>
115+
</html>

server/layouts/default.handlebars

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,26 @@
1+
<!--
2+
3+
Copyright 2015 Google Inc. All rights reserved.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
17+
-->
18+
119
<!DOCTYPE html>
220
<html>
321
<head>
422
<meta charset="utf-8">
5-
<title>App Shell</title>
23+
<title>Static Page</title>
624

725
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
826
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -16,11 +34,11 @@
1634
<body>
1735

1836
<header class="header">
19-
<button tabindex="-1" class="header__menu js-toggle-menu">
37+
<button role="tab" class="header__menu js-toggle-menu">
2038
Toggle nav menu
2139
</button>
2240

23-
<h1 class="header__title">App shell</h1>
41+
<h1 class="header__title">Static Page</h1>
2442
</header>
2543

2644
<main class="main js-main" aria-role="main">
@@ -34,9 +52,9 @@
3452
</div>
3553

3654
<div class="side-nav__body">
37-
<a tabindex="-1" class="side-nav__blog-post" href="/">Index</a>
38-
<a tabindex="-1" class="side-nav__blog-post" href="/url-1">URL 1</a>
39-
<a tabindex="-1" class="side-nav__blog-post" href="/url-2">URL 2</a>
55+
<a role="tab" tabindex="0" class="side-nav__blog-post" href="/">Index</a>
56+
<a role="tab" tabindex="0" class="side-nav__blog-post" href="/url-1">URL 1</a>
57+
<a role="tab" tabindex="0" class="side-nav__blog-post" href="/url-2">URL 2</a>
4058
</div>
4159

4260
<div class="side-nav__version">Version @VERSION@</div>

server/layouts/partial.handlebars

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<style type="text/css">{{{inlineStyles}}}</style>
2+
3+
<div class="card">
4+
{{{ body }}}
5+
<div>
6+
7+
{{#each remoteScripts}}
8+
<script src="{{this}}" async></script>
9+
{{~/each}}

server/models/path-config.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
var fs = require('fs');
2+
var path = require('path');
3+
4+
var pathConfigs = {
5+
'/': {
6+
view: 'index',
7+
inlineStyles: getFileContents(['/styles/core.css']),
8+
remoteScripts: ['/scripts/static-page.js']
9+
},
10+
'/url-1': {
11+
view: 'url-1',
12+
inlineStyles: getFileContents(['/styles/core.css']),
13+
remoteScripts: ['/scripts/static-page.js']
14+
},
15+
'/url-2': {
16+
view: 'url-2',
17+
inlineStyles: getFileContents(['/styles/core.css']),
18+
remoteScripts: ['/scripts/static-page.js']
19+
},
20+
'/app-shell': {
21+
view: '',
22+
inlineStyles: getFileContents(['/styles/core.css']),
23+
remoteScripts: ['/scripts/core.js']
24+
}
25+
};
26+
27+
function getFileContents(files) {
28+
// Concat inline styles for document <head>
29+
var flattenedContents = '';
30+
var pathPrefix = '/../../dist/';
31+
files.forEach(function(file) {
32+
flattenedContents += fs.readFileSync(path.resolve(__dirname) +
33+
pathPrefix + file);
34+
});
35+
36+
return flattenedContents;
37+
}
38+
39+
module.exports = {
40+
getConfig: function(urlPath) {
41+
// This needed to ensure changes made to the objects dont stick / alter
42+
// the original object
43+
return Object.create(pathConfigs[urlPath]);
44+
}
45+
};

0 commit comments

Comments
 (0)