Squashed commit of the following:

commit 56582bc9eee5d81a01f42a28808b617b9c96873a
Author: Julian Lam <julian@designcreateplay.com>
Date:   Tue Oct 27 05:21:11 2015 -0400

    added missing template

commit 6462a1626e7d8d77210b6e10eace5c9214335f33
Author: Julian Lam <julian@designcreateplay.com>
Date:   Tue Oct 27 05:19:07 2015 -0400

    sitemap index

commit 3cfd56f1fbc8e03405dc394375bf5ff6eef21322
Author: Julian Lam <julian@designcreateplay.com>
Date:   Tue Oct 27 04:47:52 2015 -0400

    sitemap routes, controllers, and library methods for pages, categories, and topics

commit e58e07c0881bdbe16d503b4679b85f761b02163c
Author: Julian Lam <julian@designcreateplay.com>
Date:   Tue Oct 27 04:07:39 2015 -0400

    added groups to sitemap

commit 7ee584b632
Author: Julian Lam <julian@designcreateplay.com>
Date:   Tue Oct 27 01:43:06 2015 -0400

    If notification dropdown is double-clicked, all notifications are marked read

commit 488f147bef
Author: barisusakli <barisusakli@gmail.com>
Date:   Mon Oct 26 22:39:19 2015 -0400

    closes #3781

commit 5e1bd58a02
Author: barisusakli <barisusakli@gmail.com>
Date:   Mon Oct 26 22:28:30 2015 -0400

    closes #3782

commit 57d3980267
Author: barisusakli <barisusakli@gmail.com>
Date:   Mon Oct 26 22:16:08 2015 -0400

    closes #3790

commit 555c5b82da
Author: barisusakli <barisusakli@gmail.com>
Date:   Mon Oct 26 21:19:20 2015 -0400

    check user settings

commit 5454862c1c
Author: barisusakli <barisusakli@gmail.com>
Date:   Mon Oct 26 20:26:02 2015 -0400

    wait for all callbacks when creating tags

commit 051c5077eb
Merge: 839fd93 e0e04ef
Author: Barış Soner Uşaklı <barisusakli@gmail.com>
Date:   Mon Oct 26 09:54:12 2015 -0400

    Merge pull request #3792 from drlogout/master

    Fixed wrong method name in socket.io/groups.js from isAdmin to isAdmi…

commit e0e04ef892
Author: Christian Nolte <hello@noltech.net>
Date:   Mon Oct 26 14:50:32 2015 +0100

    Fixed wrong method name in socket.io/groups.js from isAdmin to isAdministrator

commit 839fd935ad
Author: barisusakli <barisusakli@gmail.com>
Date:   Sun Oct 25 21:54:35 2015 -0400

    add back thread tools filter

commit 37060bf1a3
Merge: 5820a19 bf918bd
Author: Barış Soner Uşaklı <barisusakli@gmail.com>
Date:   Sun Oct 25 18:13:06 2015 -0400

    Merge pull request #3787 from cubehouse/patch-1

    Upgrade script fails on some consoles

commit 5820a193f6
Author: barisusakli <barisusakli@gmail.com>
Date:   Sun Oct 25 17:04:46 2015 -0400

    closes #3789

commit 0d88d52557
Author: barisusakli <barisusakli@gmail.com>
Date:   Sun Oct 25 17:03:33 2015 -0400

    up theme

commit 9bc43ba5e1
Author: barisusakli <barisusakli@gmail.com>
Date:   Sun Oct 25 16:57:42 2015 -0400

    closes #3788

commit aafd4b6984
Author: barisusakli <barisusakli@gmail.com>
Date:   Sun Oct 25 15:56:17 2015 -0400

    closes #3786

commit bf918bd016
Author: James Holding <cubehouse@users.noreply.github.com>
Date:   Sun Oct 25 10:14:00 2015 +0000

    Upgrade script fails on some consoles

    The upgrade script errors/fails on some consoles if the stdout.columns isn't set (my console did this when upgrading a Docker instance of NodeBB).
    Checking for stdout.columns before using, falling back to a couple of spaces for slightly prettiness if we can't work out the console width.
v1.18.x
Julian Lam 9 years ago
parent f7f43de644
commit 68c3f9d849

@ -144,8 +144,10 @@ switch(process.argv[2]) {
if (err) {
process.stdout.write('\nError'.red + ': ' + err.message + '\n');
} else {
var message = 'NodeBB Upgrade Complete!',
spaces = new Array(Math.floor(process.stdout.columns / 2) - (message.length / 2) + 1).join(' ');
var message = 'NodeBB Upgrade Complete!';
// some consoles will return undefined/zero columns, so just use 2 spaces in upgrade script if we can't get our column count
var columns = process.stdout.columns;
var spaces = columns ? new Array(Math.floor(columns / 2) - (message.length / 2) + 1).join(' ') : " ";
process.stdout.write('OK\n'.green);
process.stdout.write('\n' + spaces + message.green.bold + '\n\n'.reset);

@ -49,8 +49,8 @@
"nodebb-plugin-spam-be-gone": "0.4.2",
"nodebb-rewards-essentials": "0.0.5",
"nodebb-theme-lavender": "2.0.10",
"nodebb-theme-persona": "3.0.61",
"nodebb-theme-vanilla": "4.0.28",
"nodebb-theme-persona": "3.0.62",
"nodebb-theme-vanilla": "4.0.29",
"nodebb-widget-essentials": "2.0.3",
"npm": "^2.1.4",
"passport": "^0.3.0",
@ -61,7 +61,7 @@
"rss": "^1.0.0",
"semver": "^5.0.1",
"serve-favicon": "^2.1.5",
"sitemap": "^1.0.0",
"sitemap": "^1.4.0",
"socket.io": "^1.2.1",
"socket.io-client": "^1.2.1",
"socket.io-redis": "^0.1.3",

@ -10,7 +10,7 @@ define('forum/topic/fork', ['components'], function(components) {
pids = [];
Fork.init = function() {
components.get('topic/fork').on('click', onForkThreadClicked);
$('.topic').on('click', '[component="topic/fork"]', onForkThreadClicked);
};
function disableClicks() {

@ -11,14 +11,21 @@ define('notifications', ['sounds', 'translator', 'components'], function(sound,
notifList = components.get('notifications/list'),
notifIcon = components.get('notifications/icon');
notifTrigger.on('click', function(e) {
e.preventDefault();
if (notifContainer.hasClass('open')) {
return;
}
notifTrigger
.on('click', function(e) {
e.preventDefault();
if (notifContainer.hasClass('open')) {
return;
}
Notifications.loadNotifications(notifList);
});
Notifications.loadNotifications(notifList);
})
.on('dblclick', function(e) {
e.preventDefault();
if (parseInt(notifIcon.attr('data-content'), 10) > 0) {
Notifications.markAllRead();
}
});
notifList.on('click', '[data-nid]', function() {
var unread = $(this).hasClass('unread');
@ -33,14 +40,7 @@ define('notifications', ['sounds', 'translator', 'components'], function(sound,
});
});
notifContainer.on('click', '.mark-all-read', function() {
socket.emit('notifications.markAllRead', function(err) {
if (err) {
app.alertError(err.message);
}
Notifications.updateNotifCount(0);
});
});
notifContainer.on('click', '.mark-all-read', Notifications.markAllRead);
notifList.on('click', '.mark-read', function(e) {
var liEl = $(this).parent(),
@ -125,5 +125,14 @@ define('notifications', ['sounds', 'translator', 'components'], function(sound,
Tinycon.setBubble(count);
};
Notifications.markAllRead = function() {
socket.emit('notifications.markAllRead', function(err) {
if (err) {
app.alertError(err.message);
}
Notifications.updateNotifCount(0);
});
};
return Notifications;
});

@ -10,6 +10,7 @@ var async = require('async'),
posts = require('../posts'),
topics = require('../topics'),
plugins = require('../plugins'),
sitemap = require('../sitemap'),
categories = require('../categories'),
privileges = require('../privileges'),
helpers = require('./helpers');
@ -161,14 +162,56 @@ Controllers.confirmEmail = function(req, res, next) {
});
};
Controllers.sitemap = function(req, res, next) {
Controllers.sitemap = {};
Controllers.sitemap.render = function(req, res, next) {
sitemap.render(function(err, tplData) {
Controllers.render('sitemap', tplData, function(err, xml) {
res.header('Content-Type', 'application/xml');
res.send(xml);
});
})
};
Controllers.sitemap.getPages = function(req, res, next) {
if (parseInt(meta.config['feeds:disableSitemap'], 10) === 1) {
return next();
}
sitemap.getPages(function(err, xml) {
if (err) {
return next(err);
}
res.header('Content-Type', 'application/xml');
res.send(xml);
});
};
Controllers.sitemap.getCategories = function(req, res, next) {
if (parseInt(meta.config['feeds:disableSitemap'], 10) === 1) {
return next();
}
var sitemap = require('../sitemap.js');
sitemap.getCategories(function(err, xml) {
if (err) {
return next(err);
}
res.header('Content-Type', 'application/xml');
res.send(xml);
});
};
Controllers.sitemap.getTopicPage = function(req, res, next) {
if (parseInt(meta.config['feeds:disableSitemap'], 10) === 1) {
return next();
}
sitemap.getTopicPage(parseInt(req.params[0], 10), function(err, xml) {
if (err) {
return next(err);
} else if (!xml) {
return next();
}
sitemap.render(function(xml) {
res.header('Content-Type', 'application/xml');
res.send(xml);
});

@ -374,12 +374,8 @@ var db = require('./database'),
};
Messaging.canMessage = function(fromUid, toUid, callback) {
if (parseInt(meta.config.disableChat) === 1) {
return callback(new Error('[[error:chat-disabled]]'));
} else if (toUid === fromUid) {
return callback(new Error('[[error:cant-chat-with-yourself]]'));
} else if (!fromUid) {
return callback(new Error('[[error:not-logged-in]]'));
if (parseInt(meta.config.disableChat) === 1 || !fromUid || toUid === fromUid) {
return callback(null, false);
}
async.waterfall([
@ -388,17 +384,17 @@ var db = require('./database'),
},
function (exists, next) {
if (!exists) {
return next(new Error('[[error:no-user]]'));
return callback(null, false);
}
user.getUserFields(fromUid, ['banned', 'email:confirmed'], next);
},
function (userData, next) {
if (parseInt(userData.banned, 10) === 1) {
return next(new Error('[[error:user-banned]]'));
return callback(null, false);
}
if (parseInt(meta.config.requireEmailConfirmation, 10) === 1 && parseInt(userData['email:confirmed'], 10) !== 1) {
return next(new Error('[[error:email-not-confirmed-chat]]'));
return callback(null, false);
}
user.getSettings(toUid, next);

@ -7,7 +7,7 @@ var admin = {},
db = require('../database'),
translator = require('../../public/src/modules/translator');
var navigationCache = null;
admin.cache = null;
admin.save = function(data, callback) {
var order = Object.keys(data),
@ -24,7 +24,7 @@ admin.save = function(data, callback) {
return JSON.stringify(data);
});
navigationCache = null;
admin.cache = null;
async.waterfall([
function(next) {
db.delete('navigation:enabled', next);
@ -43,19 +43,16 @@ admin.getAdmin = function(callback) {
};
admin.get = function(callback) {
if (navigationCache) {
return callback(null, navigationCache);
}
db.getSortedSetRange('navigation:enabled', 0, -1, function(err, data) {
if (err) {
return callback(err);
}
navigationCache = data.map(function(item, idx) {
data = data.map(function(item, idx) {
return JSON.parse(item)[idx];
});
callback(null, navigationCache);
callback(null, data);
});
};

@ -1,12 +1,15 @@
"use strict";
var navigation = {},
admin = require('./admin'),
translator = require('../../public/src/modules/translator');
var navigation = {};
var admin = require('./admin');
var translator = require('../../public/src/modules/translator');
navigation.get = function(callback) {
if (admin.cache) {
return callback(null, admin.cache);
}
admin.get(function(err, data) {
if (err) {
return callback(err);
@ -23,6 +26,8 @@ navigation.get = function(callback) {
return item;
});
admin.cache = data;
callback(null, data);
});
};

@ -43,7 +43,7 @@ module.exports = function(Posts) {
userTitle: group.userTitle
};
if (group.name === results.userSettings[i].groupTitle && group.userTitleEnabled) {
if (results.userSettings[i] && group.name === results.userSettings[i].groupTitle && group.userTitleEnabled) {
userData.selectedGroup = userData.groups[index];
}
});

@ -101,7 +101,12 @@ module.exports = function(privileges) {
});
groupNames = groups.getEphemeralGroups().concat(groupNames);
groupNames.splice(0, 0, groupNames.splice(groupNames.indexOf('registered-users'), 1)[0]);
var registeredUsersIndex = groupNames.indexOf('registered-users');
if (registeredUsersIndex !== -1) {
groupNames.splice(0, 0, groupNames.splice(registeredUsersIndex, 1)[0]);
} else {
groupNames = ['registered-users'].concat(groupNames);
}
var adminIndex = groupNames.indexOf('administrators');
if (adminIndex !== -1) {

@ -84,6 +84,9 @@ module.exports = function(app, middleware) {
pluginRouter.render = function() {
app.render.apply(app, arguments);
};
controllers.render = function() {
app.render.apply(app, arguments);
};
// Set-up for hotswapping (when NodeBB reloads)
pluginRouter.hotswapId = 'plugins';
@ -175,7 +178,7 @@ function handle404(app, middleware) {
}
function handleErrors(app, middleware) {
app.use(function(err, req, res) {
app.use(function(err, req, res, next) {
if (err.code === 'EBADCSRFTOKEN') {
winston.error(req.path + '\n', err.message);
return res.sendStatus(403);
@ -190,7 +193,7 @@ function handleErrors(app, middleware) {
res.status(err.status || 500);
if (res.locals.isAPI) {
return res.json({path: req.path, error: err.message});
res.json({path: req.path, error: err.message});
} else {
middleware.buildHeader(req, res, function() {
res.render('500', {path: req.path, error: err.message});

@ -31,7 +31,10 @@ module.exports = function(app, middleware, controllers) {
app.get('/admin.css', middleware.addExpiresHeaders, sendACPStylesheet);
app.get('/nodebb.min.js', middleware.addExpiresHeaders, sendMinifiedJS);
// app.get('/nodebb.min.js.map', middleware.addExpiresHeaders, sendJSSourceMap);
app.get('/sitemap.xml', controllers.sitemap);
app.get('/sitemap.xml', controllers.sitemap.render);
app.get('/sitemap/pages.xml', controllers.sitemap.getPages);
app.get('/sitemap/categories.xml', controllers.sitemap.getCategories);
app.get(/\/sitemap\/topics\.(\d+)\.xml/, controllers.sitemap.getTopicPage);
app.get('/robots.txt', controllers.robots);
app.get('/manifest.json', controllers.manifest);
app.get('/css/previews/:theme', controllers.admin.themes.get);

@ -12,30 +12,37 @@ var path = require('path'),
meta = require('./meta'),
utils = require('../public/src/utils');
var sitemap = {};
var sitemap = {
maps: {
topics: []
}
};
sitemap.render = function(callback) {
if (sitemap.obj && sitemap.obj.cache.length) {
return sitemap.obj.toXML(callback);
}
async.parallel([
sitemap.getStaticUrls,
sitemap.getDynamicUrls
], function(err, urls) {
var numTopics = parseInt(meta.config.sitemapTopics, 10) || 500;
var returnData = {
url: nconf.get('url'),
topics: []
};
var numPages;
async.waterfall([
async.apply(db.getSortedSetRange, 'topics:recent', 0, -1),
function(tids, next) {
privileges.topics.filterTids('read', tids, 0, next);
}
], function(err, tids) {
if (err) {
return callback(err);
numPages = 1;
} else {
numPages = Math.ceil(tids.length / numTopics);
}
urls = urls[0].concat(urls[1]);
sitemap.obj = sm.createSitemap({
hostname: nconf.get('url'),
cacheTime: 1000 * 60 * 60, // Cached for 1 hour
urls: urls
});
for(var x=1;x<=numPages;x++) {
returnData.topics.push(x);
}
sitemap.obj.toXML(callback);
callback(null, returnData);
});
};
@ -52,75 +59,127 @@ sitemap.getStaticUrls = function(callback) {
url: '/users',
changefreq: 'daily',
priority: '0.4'
}, {
url: '/groups',
changefreq: 'daily',
priority: '0.4'
}]);
};
sitemap.getDynamicUrls = function(callback) {
var returnUrls = [];
async.parallel({
categoryUrls: function(next) {
var categoryUrls = [];
categories.getCategoriesByPrivilege('categories:cid', 0, 'find', function(err, categoriesData) {
if (err) {
return next(err);
}
categoriesData.forEach(function(category) {
if (category) {
categoryUrls.push({
url: '/category/' + category.slug,
changefreq: 'weekly',
priority: '0.4'
});
}
});
sitemap.getPages = function(callback) {
if (sitemap.maps.pages && sitemap.maps.pages.cache.length) {
return sitemap.maps.pages.toXML(callback);
}
next(null, categoryUrls);
});
},
topicUrls: function(next) {
var topicUrls = [];
async.waterfall([
function(next) {
db.getSortedSetRevRange('topics:recent', 0, parseInt(meta.config.sitemapTopics, 10) || -1, next);
},
function(tids, next) {
privileges.topics.filterTids('read', tids, 0, next);
},
function(tids, next) {
topics.getTopicsFields(tids, ['tid', 'title', 'slug', 'lastposttime'], next);
}
], function(err, topics) {
if (err) {
return next(err);
}
topics.forEach(function(topic) {
if (topic) {
topicUrls.push({
url: '/topic/' + topic.slug,
lastmodISO: utils.toISOString(topic.lastposttime),
changefreq: 'daily',
priority: '0.6'
});
}
var urls = [{
url: '',
changefreq: 'weekly',
priority: '0.6'
}, {
url: '/recent',
changefreq: 'daily',
priority: '0.4'
}, {
url: '/users',
changefreq: 'daily',
priority: '0.4'
}, {
url: '/groups',
changefreq: 'daily',
priority: '0.4'
}];
sitemap.maps.pages = sm.createSitemap({
hostname: nconf.get('url'),
cacheTime: 1000 * 60 * 60 * 24, // Cached for 24 hours
urls: urls
});
sitemap.maps.pages.toXML(callback);
};
sitemap.getCategories = function(callback) {
if (sitemap.maps.categories && sitemap.maps.categories.cache.length) {
return sitemap.maps.categories.toXML(callback);
}
var categoryUrls = [];
categories.getCategoriesByPrivilege('categories:cid', 0, 'find', function(err, categoriesData) {
if (err) {
return callback(err);
}
categoriesData.forEach(function(category) {
if (category) {
categoryUrls.push({
url: '/category/' + category.slug,
changefreq: 'weekly',
priority: '0.4'
});
}
});
sitemap.maps.categories = sm.createSitemap({
hostname: nconf.get('url'),
cacheTime: 1000 * 60 * 60 * 24, // Cached for 24 hours
urls: categoryUrls
});
sitemap.maps.categories.toXML(callback);
});
};
sitemap.getTopicPage = function(page, callback) {
if (parseInt(page, 10) <= 0) {
return callback();
}
var numTopics = parseInt(meta.config.sitemapTopics, 10) || 500;
var min = (parseInt(page, 10) - 1) * numTopics;
var max = min + numTopics;
if (sitemap.maps.topics[page-1] && sitemap.maps.topics[page-1].cache.length) {
return sitemap.maps.topics[page-1].toXML(callback);
}
var topicUrls = [];
next(null, topicUrls);
});
async.waterfall([
function(next) {
db.getSortedSetRevRange('topics:recent', min, max, next);
},
function(tids, next) {
privileges.topics.filterTids('read', tids, 0, next);
},
function(tids, next) {
topics.getTopicsFields(tids, ['tid', 'title', 'slug', 'lastposttime'], next);
}
}, function(err, data) {
if (!err) {
returnUrls = data.categoryUrls.concat(data.topicUrls);
], function(err, topics) {
if (err) {
return callback(err);
}
callback(err, returnUrls);
topics.forEach(function(topic) {
if (topic) {
topicUrls.push({
url: '/topic/' + topic.slug,
lastmodISO: utils.toISOString(topic.lastposttime),
changefreq: 'daily',
priority: '0.6'
});
}
});
sitemap.maps.topics[page-1] = sm.createSitemap({
hostname: nconf.get('url'),
cacheTime: 1000 * 60 * 60, // Cached for 1 hour
urls: topicUrls
});
sitemap.maps.topics[page-1].toXML(callback);
});
};
sitemap.clearCache = function() {
if (sitemap.obj) {
sitemap.obj.clearCache();

@ -63,7 +63,7 @@ SocketGroups.leave = function(socket, data, callback) {
function isOwner(next) {
return function (socket, data, callback) {
async.parallel({
isAdmin: async.apply(user.isAdmin, socket.uid),
isAdmin: async.apply(user.isAdministrator, socket.uid),
isOwner: async.apply(groups.ownership.isOwner, socket.uid, data.groupName)
}, function(err, results) {
if (err || (!isOwner && !results.isAdmin)) {

@ -4,6 +4,7 @@ var async = require('async');
var topics = require('../../topics');
var events = require('../../events');
var privileges = require('../../privileges');
var plugins = require('../../plugins');
var socketHelpers = require('../helpers');
module.exports = function(SocketTopics) {
@ -13,28 +14,33 @@ module.exports = function(SocketTopics) {
return;
}
if (!data) {
return callback(new Error('[[error:invalid-data]]'))
return callback(new Error('[[error:invalid-data]]'));
}
async.parallel({
topic: function(next) {
topics.getTopicFields(data.tid, ['deleted', 'locked', 'pinned'], next);
var topic;
async.waterfall([
function (next) {
async.parallel({
topic: function(next) {
topics.getTopicData(data.tid, next);
},
privileges: function(next) {
privileges.topics.get(data.tid, socket.uid, next);
}
}, next);
},
privileges: function(next) {
privileges.topics.get(data.tid, socket.uid, next);
}
}, function(err, results) {
if (err) {
return callback(err);
function (results, next) {
topic = results.topic;
topic.privileges = results.privileges;
plugins.fireHook('filter:topic.thread_tools', {topic: results.topic, uid: socket.uid, tools: []}, next);
},
function (data, next) {
topic.deleted = parseInt(topic.deleted, 10) === 1;
topic.locked = parseInt(topic.locked, 10) === 1;
topic.pinned = parseInt(topic.pinned, 10) === 1;
topic.thread_tools = data.tools;
next(null, topic);
}
results.topic.deleted = parseInt(results.topic.deleted, 10) === 1;
results.topic.locked = parseInt(results.topic.locked, 10) === 1;
results.topic.pinned = parseInt(results.topic.pinned, 10) === 1;
results.topic.privileges = results.privileges;
callback(null, results.topic);
});
], callback);
};
SocketTopics.delete = function(socket, data, callback) {

@ -18,29 +18,31 @@ module.exports = function(Topics) {
return callback();
}
plugins.fireHook('filter:tags.filter', {tags: tags, tid: tid}, function(err, data) {
if (err) {
return callback(err);
}
tags = data.tags.slice(0, meta.config.maximumTagsPerTopic || 5);
async.each(tags, function(tag, next) {
tag = Topics.cleanUpTag(tag);
if (tag.length < (meta.config.minimumTagLength || 3)) {
return next();
}
db.setAdd('topic:' + tid + ':tags', tag);
async.waterfall([
function (next) {
plugins.fireHook('filter:tags.filter', {tags: tags, tid: tid}, next);
},
function (data, next) {
tags = data.tags.slice(0, meta.config.maximumTagsPerTopic || 5);
db.sortedSetAdd('tag:' + tag + ':topics', timestamp, tid, function(err) {
if (!err) {
updateTagCount(tag);
async.each(tags, function(tag, next) {
tag = Topics.cleanUpTag(tag);
if (tag.length < (meta.config.minimumTagLength || 3)) {
return next();
}
next(err);
});
}, callback);
});
async.parallel([
async.apply(db.setAdd, 'topic:' + tid + ':tags', tag),
async.apply(db.sortedSetAdd, 'tag:' + tag + ':topics', timestamp, tid)
], function(err) {
if (err) {
return next(err);
}
updateTagCount(tag, next);
});
}, next);
}
], callback);
};
Topics.cleanUpTag = function(tag) {

@ -98,7 +98,7 @@ var async = require('async'),
}
for(var i=0; i<notifications.length; ++i) {
if (notifications[i].image.indexOf('http') !== 0) {
if (notifications[i].image && notifications[i].image.indexOf('http') !== 0) {
notifications[i].image = nconf.get('url') + notifications[i].image;
}
}

@ -0,0 +1,9 @@
<script type="text/tpl" data-template="500">
<div class="alert alert-danger">
<strong>[[global:500.title]]</strong>
<p>[[global:500.message]]</p>
<p>{path}</p>
<!-- IF error --><p>{error}</p><!-- ENDIF error -->
</div>
</script>

@ -1,9 +1,6 @@
<script type="text/tpl" data-template="500">
<div class="alert alert-danger">
<strong>[[global:500.title]]</strong>
<p>[[global:500.message]]</p>
<p>{path}</p>
<!-- IF error --><p>{error}</p><!-- ENDIF error -->
</div>
</script>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>{url}/sitemap/pages.xml</loc>
</sitemap>
<sitemap>
<loc>{url}/sitemap/categories.xml</loc>
</sitemap>
<!-- BEGIN topics -->
<sitemap>
<loc>{url}/sitemap/topics.@value.xml</loc>
</sitemap>
<!-- END topics -->
</sitemapindex>
Loading…
Cancel
Save