diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 5cf650703a..77b91d5d25 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -102,26 +102,29 @@ var ajaxify = {}; // Enhancing all anchors to ajaxify... $(document.body).on('click', 'a', function(e) { - function hrefEmpty(href) { return href == 'javascript:;' || href == window.location.href + "#" || href.slice(-1) === "#"; } if (hrefEmpty(this.href)) return; - - var url = this.href.replace(rootUrl + '/', ''); - if (this.target !== '') return; + if (this.protocol === 'javascript:') return; if (!e.ctrlKey && e.which === 1) { - if (ajaxify.go(url)) { + if (this.host === window.location.host) { + var url = this.href.replace(rootUrl + '/', ''); + + if (ajaxify.go(url)) { + e.preventDefault(); + } + } else { + ajaxify.go('outgoing?url=' + encodeURIComponent(this.href)); e.preventDefault(); } } }); }); - function exec_body_scripts(body_el) { // modified from http://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml diff --git a/public/src/app.js b/public/src/app.js index b7dd3a8e20..53d102c81f 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -4,14 +4,14 @@ var socket, API_URL = null; -(function() { +(function () { var showWelcomeMessage = false; function loadConfig() { $.ajax({ url: RELATIVE_PATH + '/api/config', - success: function(data) { + success: function (data) { API_URL = data.api_url; config = data; @@ -20,19 +20,18 @@ var socket, var reconnecting = false; var reconnectTries = 0; - socket.on('event:connect', function(data) { - console.log('connected to nodebb socket: ', data); + socket.on('event:connect', function (data) { app.username = data.username; app.showLoginMessage(); }); - socket.on('event:alert', function(data) { + socket.on('event:alert', function (data) { app.alert(data); }); - socket.on('connect', function(data) { + socket.on('connect', function (data) { if (reconnecting) { - setTimeout(function() { + setTimeout(function () { app.alert({ alert_id: 'connection_alert', title: 'Connected', @@ -49,14 +48,14 @@ var socket, } }); - socket.on('reconnecting', function(data) { + socket.on('reconnecting', function (data) { function showDisconnectModal() { $('#disconnect-modal').modal({ backdrop: 'static', show: true }); - $('#reload-button').on('click', function() { + $('#reload-button').on('click', function () { $('#disconnect-modal').modal('hide'); window.location.reload(); }); @@ -79,8 +78,8 @@ var socket, }); }); - socket.on('api:user.get_online_users', function(users) { - jQuery('a.username-field').each(function() { + socket.on('api:user.get_online_users', function (users) { + jQuery('a.username-field').each(function () { if (this.processed === true) return; @@ -97,7 +96,7 @@ var socket, el.processed = true; }); - jQuery('button .username-field').each(function() { + jQuery('button .username-field').each(function () { //DRY FAIL if (this.processed === true) return; @@ -124,17 +123,17 @@ var socket, } // takes a string like 1000 and returns 1,000 - app.addCommas = function(text) { + app.addCommas = function (text) { return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"); } // Willingly stolen from: http://phpjs.org/functions/strip_tags/ - app.strip_tags = function(input, allowed) { + app.strip_tags = function (input, allowed) { allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase () var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, commentsAndPhpTags = /|<\?(?:php)?[\s\S]*?\?>/gi; - return input.replace(commentsAndPhpTags, '').replace(tags, function($0, $1) { + return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) { return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : ''; }); } @@ -145,14 +144,14 @@ var socket, // message = alert message content // timeout default = permanent // location : alert_window (default) or content - app.alert = function(params) { + app.alert = function (params) { var alert_id = 'alert_button_' + ((params.alert_id) ? params.alert_id : new Date().getTime()); var alert = $('#' + alert_id); function startTimeout(div, timeout) { - var timeoutId = setTimeout(function() { - $(div).fadeOut(1000, function() { + var timeoutId = setTimeout(function () { + $(div).fadeOut(1000, function () { $(this).remove(); }); }, timeout); @@ -185,7 +184,7 @@ var socket, button.className = 'close'; button.innerHTML = '×'; - button.onclick = function(ev) { + button.onclick = function (ev) { div.parentNode.removeChild(div); } @@ -199,9 +198,9 @@ var socket, } if (params.clickfn) { - div.onclick = function() { + div.onclick = function () { params.clickfn(); - jQuery(div).fadeOut(500, function() { + jQuery(div).fadeOut(500, function () { this.remove(); }); } @@ -209,7 +208,7 @@ var socket, } } - app.alertSuccess = function(message, timeout) { + app.alertSuccess = function (message, timeout) { if (!timeout) timeout = 2000; @@ -221,7 +220,7 @@ var socket, }); } - app.alertError = function(message, timeout) { + app.alertError = function (message, timeout) { if (!timeout) timeout = 2000; @@ -234,7 +233,7 @@ var socket, } app.current_room = null; - app.enter_room = function(room) { + app.enter_room = function (room) { if (socket) { if (app.current_room === room) return; @@ -248,20 +247,20 @@ var socket, } }; - app.populate_online_users = function() { + app.populate_online_users = function () { var uids = []; - jQuery('.post-row').each(function() { + jQuery('.post-row').each(function () { uids.push(this.getAttribute('data-uid')); }); socket.emit('api:user.get_online_users', uids); } - app.process_page = function() { + app.process_page = function () { // here is where all modules' onNavigate should be called, I think. - require(['mobileMenu'], function(mobileMenu) { + require(['mobileMenu'], function (mobileMenu) { mobileMenu.onNavigate(); }); @@ -273,7 +272,7 @@ var socket, jQuery('#main-nav li').removeClass('active'); if (active) { - jQuery('#main-nav li a').each(function() { + jQuery('#main-nav li a').each(function () { var href = this.getAttribute('href'); if (active == "sort-posts" || active == "sort-reputation" || active == "search" || active == "latest" || active == "online") active = 'users'; @@ -287,12 +286,12 @@ var socket, $('span.timeago').timeago(); - setTimeout(function() { + setTimeout(function () { window.scrollTo(0, 1); // rehide address bar on mobile after page load completes. }, 100); } - app.showLoginMessage = function() { + app.showLoginMessage = function () { function showAlert() { app.alert({ type: 'success', @@ -312,14 +311,14 @@ var socket, } } - app.addCommasToNumbers = function() { - $('.formatted-number').each(function(index, element) { + app.addCommasToNumbers = function () { + $('.formatted-number').each(function (index, element) { $(element).html(app.addCommas($(element).html())); }); } - app.openChat = function(username, touid) { - require(['chat'], function(chat) { + app.openChat = function (username, touid) { + require(['chat'], function (chat) { var chatModal; if (!chat.modalExists(touid)) { chatModal = chat.createModal(username, touid); @@ -330,7 +329,7 @@ var socket, }); } - app.createNewPosts = function(data) { + app.createNewPosts = function (data) { data.posts[0].display_moderator_tools = 'none'; var html = templates.prepare(templates['topic'].blocks['posts']).parse(data), uniqueid = new Date().getTime(), @@ -354,7 +353,7 @@ var socket, app.infiniteLoaderActive = false; - app.loadMorePosts = function(tid, callback) { + app.loadMorePosts = function (tid, callback) { if (app.infiniteLoaderActive) return; app.infiniteLoaderActive = true; @@ -365,7 +364,7 @@ var socket, socket.emit('api:topic.loadMore', { tid: tid, after: document.querySelectorAll('#post-container li[data-pid]').length - }, function(data) { + }, function (data) { app.infiniteLoaderActive = false; if (data.posts.length) { $('#loading-indicator').attr('done', '0'); @@ -379,19 +378,19 @@ var socket, }); } - app.scrollToTop = function() { + app.scrollToTop = function () { $('body,html').animate({ scrollTop: 0 }); }; - app.scrollToBottom = function() { + app.scrollToBottom = function () { $('body,html').animate({ scrollTop: $('html').height() - 100 }); } - app.scrollToPost = function(pid) { + app.scrollToPost = function (pid) { if (!pid) return; @@ -408,8 +407,8 @@ var socket, if (!scrollTo.length && tid) { - var intervalID = setInterval(function() { - app.loadMorePosts(tid, function(posts) { + var intervalID = setInterval(function () { + app.loadMorePosts(tid, function (posts) { scrollTo = $('#post_anchor_' + pid); if (tid && scrollTo.length) { @@ -427,8 +426,8 @@ var socket, } - jQuery('document').ready(function() { - $('#search-form').on('submit', function() { + jQuery('document').ready(function () { + $('#search-form').on('submit', function () { var input = $(this).find('input'); ajaxify.go("search/" + input.val(), null, "search"); input.val(''); diff --git a/src/postTools.js b/src/postTools.js index 5917d8c83b..8913a1e787 100644 --- a/src/postTools.js +++ b/src/postTools.js @@ -87,7 +87,7 @@ var RDB = require('./redis.js'), }); }, function(next) { - PostTools.toHTML(content, next); + PostTools.parse(content, next); } ], function(err, results) { io.sockets.in('topic_' + results[0].tid).emit('event:post_edited', { @@ -128,7 +128,7 @@ var RDB = require('./redis.js'), }); // Delete the thread if it is the last undeleted post - threadTools.get_latest_undeleted_pid(postData.tid, function(err, pid) { + threadTools.getLatestUndeletedPid(postData.tid, function(err, pid) { if (err && err.message === 'no-undeleted-pids-found') { threadTools.delete(postData.tid, -1, function(err) { if (err) winston.error('Could not delete topic (tid: ' + postData.tid + ')', err.stack); @@ -164,7 +164,7 @@ var RDB = require('./redis.js'), pid: pid }); - threadTools.get_latest_undeleted_pid(postData.tid, function(err, pid) { + threadTools.getLatestUndeletedPid(postData.tid, function(err, pid) { posts.getPostField(pid, 'timestamp', function(timestamp) { topics.updateTimestamp(postData.tid, timestamp); }); @@ -190,28 +190,11 @@ var RDB = require('./redis.js'), }); } - PostTools.toHTML = function(raw, callback) { + PostTools.parse = function(raw, callback) { raw = raw || ''; + plugins.fireHook('filter:post.parse', raw, function(parsed) { - var cheerio = require('cheerio'); - - if (parsed && parsed.length > 0) { - var parsedContentDOM = cheerio.load(parsed); - var domain = nconf.get('url'); - - parsedContentDOM('a').each(function() { - this.attr('rel', 'nofollow'); - var href = this.attr('href'); - - if (href && !href.match(domain) && !utils.isRelativeUrl(href)) { - this.attr('href', domain + 'outgoing?url=' + encodeURIComponent(href)); - } - }); - - callback(null, parsedContentDOM.html()); - } else { - callback(null, '

'); - } + callback(null, parsed); }); } diff --git a/src/posts.js b/src/posts.js index e2ab4fc69c..07c20371d8 100644 --- a/src/posts.js +++ b/src/posts.js @@ -36,7 +36,7 @@ var RDB = require('./redis.js'), user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(err, userData) { if (err) return callback(); - postTools.toHTML(userData.signature, function(err, signature) { + postTools.parse(userData.signature, function(err, signature) { post.username = userData.username || 'anonymous'; post.userslug = userData.userslug || ''; post.user_rep = userData.reputation || 0; @@ -91,7 +91,7 @@ var RDB = require('./redis.js'), }, function(postData, next) { if (postData.content) { - postTools.toHTML(postData.content, function(err, content) { + postTools.parse(postData.content, function(err, content) { if (!err) postData.content = utils.strip_tags(content); next(err, postData); }); @@ -164,7 +164,7 @@ var RDB = require('./redis.js'), postData['edited-class'] = postData.editor !== '' ? '' : 'none'; postData['relativeEditTime'] = postData.edited !== '0' ? (new Date(parseInt(postData.edited,10)).toISOString()) : ''; - postTools.toHTML(postData.content, function(err, content) { + postTools.parse(postData.content, function(err, content) { postData.content = content; posts.push(postData); callback(null); @@ -321,7 +321,7 @@ var RDB = require('./redis.js'), async.parallel({ content: function(next) { plugins.fireHook('filter:post.get', postData, function(postData) { - postTools.toHTML(postData.content, function(err, content) { + postTools.parse(postData.content, function(err, content) { next(null, content); }); }); diff --git a/src/routes/user.js b/src/routes/user.js index e6870823b8..29b8fcacae 100644 --- a/src/routes/user.js +++ b/src/routes/user.js @@ -426,7 +426,7 @@ var user = require('./../user.js'), if (callerUID !== userData.uid) user.incrementUserFieldBy(userData.uid, 'profileviews', 1); - postTools.toHTML(userData.signature, function(err, signature) { + postTools.parse(userData.signature, function(err, signature) { userData.signature = signature; res.json(userData); }); diff --git a/src/threadTools.js b/src/threadTools.js index d4c9ab682b..23b641f0d2 100644 --- a/src/threadTools.js +++ b/src/threadTools.js @@ -297,22 +297,20 @@ var RDB = require('./redis.js'), }); } - ThreadTools.get_latest_undeleted_pid = function(tid, callback) { + ThreadTools.getLatestUndeletedPid = function(tid, callback) { + RDB.lrange('tid:' + tid + ':posts', 0, -1, function(err, pids) { + if (pids.length === 0) return callback(new Error('no-undeleted-pids-found')); - posts.getPostsByTid(tid, 0, -1, function(posts) { - - var numPosts = posts.length; - if (!numPosts) - return callback(new Error('no-undeleted-pids-found')); - - while (numPosts--) { - if (posts[numPosts].deleted !== '1') { - callback(null, posts[numPosts].pid); - return; - } - } - - callback(new Error('no-undeleted-pids-found')); + pids.reverse(); + async.detectSeries(pids, function(pid, next) { + RDB.hget('post:' + pid, 'deleted', function(err, deleted) { + if (deleted === '0') next(true); + else next(false); + }); + }, function(pid) { + if (pid) callback(null, pid); + else callback(new Error('no-undeleted-pids-found')); + }); }); } }(exports)); \ No newline at end of file diff --git a/src/topics.js b/src/topics.js index ae5e8c1911..e6380882a5 100644 --- a/src/topics.js +++ b/src/topics.js @@ -573,7 +573,7 @@ schema = require('./schema.js'), } Topics.getTeaser = function(tid, callback) { - threadTools.get_latest_undeleted_pid(tid, function(err, pid) { + threadTools.getLatestUndeletedPid(tid, function(err, pid) { if (!err) { posts.getPostFields(pid, ['content', 'uid', 'timestamp'], function(postData) { @@ -591,7 +591,7 @@ schema = require('./schema.js'), if (postData.content) { stripped = postData.content.replace(/>.+\n\n/, ''); - postTools.toHTML(stripped, function(err, stripped) { + postTools.parse(stripped, function(err, stripped) { returnObj.text = utils.strip_tags(stripped); callback(null, returnObj); }); diff --git a/src/webserver.js b/src/webserver.js index 0f9f5c8bc7..25a255f7c7 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -428,7 +428,6 @@ var express = require('express'), app.get('/robots.txt', function (req, res) { res.set('Content-Type', 'text/plain'); res.send("User-agent: *\n" + - "Disallow: \n" + "Disallow: /admin/\n" + "Sitemap: " + nconf.get('url') + "sitemap.xml"); });