From 1d925ea17dea4e345dd9b6758cf844a1f0739683 Mon Sep 17 00:00:00 2001 From: Mikko Ahlroth Date: Sun, 16 Nov 2014 00:28:45 +0200 Subject: [PATCH] Implement disqus and config and page listing in menu --- gulpfile.js | 12 +- src/app/router.js | 1 + src/app/routes.js | 109 +++++++++--------- src/app/startup.js | 2 + .../address-service/address-service.js | 4 +- .../config-service/config-service.js | 22 ++++ src/components/nav-bar/nav-bar.html | 41 +++---- src/components/nav-bar/nav-bar.js | 14 ++- src/components/pagination/pagination.js | 6 +- src/components/single-post/single-post.html | 4 + src/components/single-post/single-post.js | 61 +++++++++- src/config.js.dist | 20 ++++ src/css/styles.css | 14 +++ src/index.html | 12 +- 14 files changed, 227 insertions(+), 95 deletions(-) create mode 100644 src/components/config-service/config-service.js create mode 100644 src/config.js.dist diff --git a/gulpfile.js b/gulpfile.js index 5b40cf2..5385147 100644 --- a/gulpfile.js +++ b/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')); diff --git a/src/app/router.js b/src/app/router.js index 461a971..5c16eda 100644 --- a/src/app/router.js +++ b/src/app/router.js @@ -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(); diff --git a/src/app/routes.js b/src/app/routes.js index f15e9a9..649c2e4 100644 --- a/src/app/routes.js +++ b/src/app/routes.js @@ -4,61 +4,62 @@ define([], function() { var PAGENUMBER_RE = /^\d*$/; return [ - // Page view - { - url: '{slug}', - params: { page: 'post-page', mode: 'page' } - }, - - // Single post view - { - url: '{year}/{month}/{day}/{slug}', - params: { page: 'post-page', mode: 'post' }, - rules: { - year: YEAR_RE, - month: MONTH_RE - } - }, - - // Year archive - { - url: 'archives/{year}/:pageNumber:', - params: { page: 'year-page', mode: 'year' }, - rules: { - year: YEAR_RE, - pageNumber: PAGENUMBER_RE - } - }, - - // Month archive - { - url: 'archives/{year}/{month}/:pageNumber:', - params: { page: 'month-page', mode: 'month' }, - rules: { - year: YEAR_RE, - month: MONTH_RE, - pageNumber: PAGENUMBER_RE - } - }, - - // Tag archive - { - url: 'tag/{slug}/:pageNumber:', - params: { page: 'tag-page', mode: 'tag' }, - rules: { - pageNumber: PAGENUMBER_RE - } - }, - - // Home view - { - url: ':pageNumber:', - params: { page: 'home-page', mode: 'home' }, - rules: { - pageNumber: PAGENUMBER_RE - } + // 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}', + params: { page: 'post-page', mode: 'page' } + }, + + // Single post view + { + url: '{year}/{month}/{day}/{slug}', + params: { page: 'post-page', mode: 'post' }, + rules: { + year: YEAR_RE, + month: MONTH_RE + } + }, + + // Year archive + { + url: 'archives/{year}/:pageNumber:', + params: { page: 'year-page', mode: 'year' }, + rules: { + year: YEAR_RE, + pageNumber: PAGENUMBER_RE + } + }, + + // Month archive + { + url: 'archives/{year}/{month}/:pageNumber:', + params: { page: 'month-page', mode: 'month' }, + rules: { + year: YEAR_RE, + month: MONTH_RE, + pageNumber: PAGENUMBER_RE + } + }, + + // Tag archive + { + url: 'tag/{slug}/:pageNumber:', + params: { page: 'tag-page', mode: 'tag' }, + rules: { + pageNumber: PAGENUMBER_RE + } + } + ]; }); diff --git a/src/app/startup.js b/src/app/startup.js index a0de4b3..b37bafc 100644 --- a/src/app/startup.js +++ b/src/app/startup.js @@ -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 diff --git a/src/components/address-service/address-service.js b/src/components/address-service/address-service.js index 5efbee3..deb62f1 100644 --- a/src/components/address-service/address-service.js +++ b/src/components/address-service/address-service.js @@ -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) { diff --git a/src/components/config-service/config-service.js b/src/components/config-service/config-service.js new file mode 100644 index 0000000..a3b452f --- /dev/null +++ b/src/components/config-service/config-service.js @@ -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(); + +}); diff --git a/src/components/nav-bar/nav-bar.html b/src/components/nav-bar/nav-bar.html index 3b2bff4..ec8a0dd 100644 --- a/src/components/nav-bar/nav-bar.html +++ b/src/components/nav-bar/nav-bar.html @@ -1,27 +1,20 @@ - + + +
+ diff --git a/src/components/single-post/single-post.js b/src/components/single-post/single-post.js index 39cf9d8..d063ba7 100644 --- a/src/components/single-post/single-post.js +++ b/src/components/single-post/single-post.js @@ -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 }; diff --git a/src/config.js.dist b/src/config.js.dist new file mode 100644 index 0000000..6515cf7 --- /dev/null +++ b/src/config.js.dist @@ -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; diff --git a/src/css/styles.css b/src/css/styles.css index 6a11c4c..88491f8 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -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; +} diff --git a/src/index.html b/src/index.html index 26f46d7..e741715 100644 --- a/src/index.html +++ b/src/index.html @@ -3,11 +3,14 @@ - Laine + Loading… + + + @@ -18,6 +21,13 @@

Loading…

+ +