Implement disqus and config and page listing in menu
This commit is contained in:
parent
b8f0b373a1
commit
1d925ea17d
14 changed files with 227 additions and 95 deletions
12
gulpfile.js
12
gulpfile.js
|
@ -37,7 +37,8 @@ var requireJsRuntimeConfig = vm.runInNewContext(fs.readFileSync('src/app/require
|
|||
'components/tag-page/tag-page',
|
||||
'components/year-page/year-page',
|
||||
'components/month-page/month-page',
|
||||
'components/post-page/post-page'
|
||||
'components/post-page/post-page',
|
||||
'components/config-service/config-service'
|
||||
],
|
||||
insertRequire: ['app/startup'],
|
||||
bundles: {
|
||||
|
@ -91,13 +92,20 @@ gulp.task('html', function() {
|
|||
.pipe(gulp.dest('./dev/'));
|
||||
});
|
||||
|
||||
// Copies misc files
|
||||
gulp.task('misc', function() {
|
||||
return gulp.src('./src/config.js.dist')
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
.pipe(gulp.dest('./dev/'));
|
||||
});
|
||||
|
||||
// Removes all files from ./dist/
|
||||
gulp.task('clean', function() {
|
||||
return gulp.src('./dist/**/*', { read: false })
|
||||
.pipe(clean());
|
||||
});
|
||||
|
||||
gulp.task('default', ['html', 'js', 'css', 'fonts'], function(callback) {
|
||||
gulp.task('default', ['html', 'js', 'css', 'fonts', 'misc'], function(callback) {
|
||||
callback();
|
||||
console.log('\nPlaced optimized files in ' + chalk.magenta('dist/')
|
||||
+ ' and dev files in ' + chalk.magenta('dev/\n'));
|
||||
|
|
|
@ -31,6 +31,7 @@ define(["knockout", "crossroads", "hasher", "./routes"], function(ko, crossroads
|
|||
function activateCrossroads() {
|
||||
function parseHash(newHash, oldHash) { crossroads.parse(newHash); }
|
||||
crossroads.normalizeFn = crossroads.NORM_AS_OBJECT;
|
||||
hasher.prependHash = '!';
|
||||
hasher.initialized.add(parseHash);
|
||||
hasher.changed.add(parseHash);
|
||||
hasher.init();
|
||||
|
|
|
@ -4,6 +4,16 @@ define([], function() {
|
|||
var PAGENUMBER_RE = /^\d*$/;
|
||||
|
||||
return [
|
||||
// Home view
|
||||
// This is above page view because page view will catch the rest
|
||||
{
|
||||
url: ':pageNumber:',
|
||||
params: { page: 'home-page', mode: 'home' },
|
||||
rules: {
|
||||
pageNumber: PAGENUMBER_RE
|
||||
}
|
||||
},
|
||||
|
||||
// Page view
|
||||
{
|
||||
url: '{slug}',
|
||||
|
@ -48,15 +58,6 @@ define([], function() {
|
|||
rules: {
|
||||
pageNumber: PAGENUMBER_RE
|
||||
}
|
||||
},
|
||||
|
||||
// Home view
|
||||
{
|
||||
url: ':pageNumber:',
|
||||
params: { page: 'home-page', mode: 'home' },
|
||||
rules: {
|
||||
pageNumber: PAGENUMBER_RE
|
||||
}
|
||||
}
|
||||
];
|
||||
});
|
||||
|
|
|
@ -30,6 +30,8 @@ define(['jquery', 'knockout', './router', 'marked', 'bootstrap', 'knockout-proje
|
|||
|
||||
ko.components.register('generic-route', { require: 'components/generic-route/generic-route' });
|
||||
|
||||
ko.components.register('config-service', { require: 'components/config-service/config-service' });
|
||||
|
||||
// [Scaffolded component registrations will be inserted here. To retain this feature, don't remove this comment.]
|
||||
|
||||
// Set Markdown parser options
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
define(['knockout', '../../app/routes', '../../app/router', 'hasher'],
|
||||
function(ko, routes, router, hasher) {
|
||||
|
||||
function AddressService(params) {
|
||||
function AddressService() {
|
||||
var self = this;
|
||||
|
||||
self.getCurrentRoute = function() {
|
||||
|
@ -34,7 +34,7 @@ define(['knockout', '../../app/routes', '../../app/router', 'hasher'],
|
|||
};
|
||||
|
||||
self.prefixUrlTo = function(arguments, mode) {
|
||||
return '/#/' + self.urlTo(arguments, mode);
|
||||
return '/#!/' + self.urlTo(arguments, mode);
|
||||
};
|
||||
|
||||
self.goTo = function(arguments, mode) {
|
||||
|
|
22
src/components/config-service/config-service.js
Normal file
22
src/components/config-service/config-service.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
define(['knockout', '../../app/routes', '../../app/router', 'hasher'],
|
||||
function(ko, routes, router, hasher) {
|
||||
|
||||
function ConfigService() {
|
||||
var self = this;
|
||||
|
||||
// Load configs from variables defined in config.js
|
||||
self.blogName = CONF_BLOG_NAME;
|
||||
self.authorName = CONF_AUTHOR_NAME;
|
||||
self.useDisqus = CONF_USE_DISQUS;
|
||||
self.disqusShortname = CONF_DISQUS_SHORTNAME;
|
||||
self.pageCommenting = CONF_PAGE_COMMENTING;
|
||||
self.postsPerPage = CONF_POSTS_PER_PAGE;
|
||||
}
|
||||
|
||||
// This runs when the component is torn down. Put here any logic necessary to clean up,
|
||||
// for example cancelling setTimeouts or disposing Knockout subscriptions/computeds.
|
||||
ConfigService.prototype.dispose = function() {};
|
||||
|
||||
return new ConfigService();
|
||||
|
||||
});
|
|
@ -1,8 +1,3 @@
|
|||
<!--
|
||||
The navigation UI that is docked to the top of the window. Most of this markup simply
|
||||
follows Bootstrap conventions. The only Knockout-specific parts are the data-bind
|
||||
attributes on the <li> elements.
|
||||
-->
|
||||
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
|
@ -12,16 +7,14 @@
|
|||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Laine</a>
|
||||
<a class="navbar-brand" href="#!">Laine</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse">
|
||||
|
||||
<ul class="nav navbar-nav">
|
||||
<li data-bind="css: { active: route().page === 'home-page' }">
|
||||
<a href="#">Home</a>
|
||||
<ul class="nav navbar-nav" data-bind="foreach: { data: pages, as: 'page' }">
|
||||
<li data-bind="css: { active: $parent.route().slug === page.slug() }">
|
||||
<a href="/" data-bind="attr: { href: $parent.AS.prefixUrlTo({ slug: page.slug() }, 'page') }, text: page.linkText()"></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
define(['knockout', 'text!./nav-bar.html'], function(ko, template) {
|
||||
define(['knockout', 'text!./nav-bar.html', '../db/db', '../address-service/address-service'],
|
||||
function(ko, template, DB, addressService) {
|
||||
|
||||
function NavBarViewModel(params) {
|
||||
var self = this;
|
||||
|
||||
// This viewmodel doesn't do anything except pass through the 'route' parameter to the view.
|
||||
// You could remove this viewmodel entirely, and define 'nav-bar' as a template-only component.
|
||||
// But in most apps, you'll want some viewmodel logic to determine what navigation options appear.
|
||||
|
||||
this.route = params.route;
|
||||
self.AS = addressService;
|
||||
self.route = params.route;
|
||||
self.pages = ko.pureComputed(function() {
|
||||
return DB.pages();
|
||||
});
|
||||
}
|
||||
|
||||
return { viewModel: NavBarViewModel, template: template };
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
define(['knockout', 'text!./pagination.html', '../address-service/address-service'],
|
||||
function(ko, templateMarkup, addressService) {
|
||||
define(['knockout', 'text!./pagination.html', '../address-service/address-service', '../config-service/config-service'],
|
||||
function(ko, templateMarkup, addressService, configService) {
|
||||
|
||||
function Pagination(params) {
|
||||
var self = this;
|
||||
self.posts = params.posts;
|
||||
self.page = params.page;
|
||||
|
||||
self.postsPerPage = 3;
|
||||
self.postsPerPage = configService.postsPerPage;
|
||||
|
||||
self.pageCount = ko.pureComputed(function() {
|
||||
return Math.ceil(self.posts().length / self.postsPerPage);
|
||||
|
|
|
@ -34,4 +34,8 @@
|
|||
</a>
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
|
||||
<!-- ko if: useDisqus -->
|
||||
<div id="disqus_thread" class="post-comments-container"></div>
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,39 @@
|
|||
define(['knockout', 'text!./single-post.html', '../db/db', 'marked', '../address-service/address-service'],
|
||||
function(ko, templateMarkup, DB, marked, addressService) {
|
||||
define(['knockout', 'text!./single-post.html', '../db/db', 'marked', '../address-service/address-service', '../config-service/config-service', 'hasher'],
|
||||
function(ko, templateMarkup, DB, marked, addressService, configService, hasher) {
|
||||
|
||||
var disqusSub = null;
|
||||
|
||||
function disqusIdentifier(post) {
|
||||
return (post.isPage()? 'page-' : 'post-') + post.slug();
|
||||
}
|
||||
|
||||
function insertDisqus(post) {
|
||||
if (!_.isUndefined(window.DISQUS)) {
|
||||
resetDisqus(post);
|
||||
}
|
||||
else {
|
||||
var disqus_shortname = configService.disqusShortname;
|
||||
var disqus_title = post.title();
|
||||
var disqus_url = hasher.getURL();
|
||||
var disqus_identifier = disqusIdentifier(post);
|
||||
|
||||
var dsq = document.createElement('script');
|
||||
dsq.type = 'text/javascript';
|
||||
dsq.async = true;
|
||||
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
|
||||
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
||||
}
|
||||
}
|
||||
|
||||
function resetDisqus(post) {
|
||||
DISQUS.reset({
|
||||
reload: true,
|
||||
config: function() {
|
||||
this.page.identifier = disqusIdentifier(post);
|
||||
this.page.url = hasher.getURL();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function SinglePost(params) {
|
||||
var self = this;
|
||||
|
@ -38,11 +72,32 @@ define(['knockout', 'text!./single-post.html', '../db/db', 'marked', '../address
|
|||
DB.loadPage(self.post.slug());
|
||||
}
|
||||
}
|
||||
|
||||
// Load disqus comments if they are in use on this page
|
||||
self.useDisqus = !self.short && configService.useDisqus && (configService.pageComments || !self.post.isPage());
|
||||
|
||||
if (self.useDisqus) {
|
||||
// Wait until the post title is available
|
||||
if (!self.post.synced()) {
|
||||
disqusSub = self.post.synced.subscribe(function (newVal) {
|
||||
if (newVal === true) {
|
||||
insertDisqus(self.post);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
insertDisqus(self.post);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This runs when the component is torn down. Put here any logic necessary to clean up,
|
||||
// for example cancelling setTimeouts or disposing Knockout subscriptions/computeds.
|
||||
SinglePost.prototype.dispose = function() {};
|
||||
SinglePost.prototype.dispose = function() {
|
||||
if (!_.isNull(disqusSub)) {
|
||||
disqusSub.dispose();
|
||||
}
|
||||
};
|
||||
|
||||
return { viewModel: SinglePost, template: templateMarkup };
|
||||
|
||||
|
|
20
src/config.js.dist
Normal file
20
src/config.js.dist
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Example configuration for Laine
|
||||
// Don't edit the names of the variables or the configuration won't work.
|
||||
|
||||
// Blog name
|
||||
CONF_BLOG_NAME = 'Laine';
|
||||
|
||||
// Author name
|
||||
CONF_AUTHOR_NAME = 'Nicd';
|
||||
|
||||
// Set to false to disable Disqus comments
|
||||
CONF_USE_DISQUS = true;
|
||||
|
||||
// Disqus shortname for your site
|
||||
CONF_DISQUS_SHORTNAME = 'lainedemoblog';
|
||||
|
||||
// Set to true to show comments on pages in addition to posts
|
||||
CONF_PAGE_COMMENTING = false;
|
||||
|
||||
// Posts shown per page
|
||||
CONF_POSTS_PER_PAGE = 5;
|
|
@ -1,3 +1,17 @@
|
|||
#page {
|
||||
margin-top: 80px;
|
||||
}
|
||||
|
||||
.single-post {
|
||||
margin: 20px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.single-post>h2 {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.post-content-container {
|
||||
padding-top: 20px;
|
||||
border-top: 1px dashed #aaa;
|
||||
}
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Laine</title>
|
||||
<title>Loading…</title>
|
||||
<!-- build:css -->
|
||||
<link href="bower_modules/components-bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="css/styles.css" rel="stylesheet">
|
||||
<!-- endbuild -->
|
||||
|
||||
<script src="config.js"></script>
|
||||
|
||||
<!-- build:js -->
|
||||
<script src="app/require.config.js"></script>
|
||||
<script data-main="app/startup" src="bower_modules/requirejs/require.js"></script>
|
||||
|
@ -18,6 +21,13 @@
|
|||
<div id="page" class="container" data-bind="component: { name: route().page, params: route }">
|
||||
<div class="loading">
|
||||
<h1>Loading…</h1>
|
||||
|
||||
<noscript>
|
||||
<p>
|
||||
To read this blog, you need to turn JavaScript on in
|
||||
your browser.
|
||||
</p>
|
||||
</noscript>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
Reference in a new issue