Skip to content

Instantly share code, notes, and snippets.

@khanfx
Last active September 8, 2016 23:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save khanfx/c0ffa60216ef6d152dca15bff91d8273 to your computer and use it in GitHub Desktop.
Save khanfx/c0ffa60216ef6d152dca15bff91d8273 to your computer and use it in GitHub Desktop.
Export a xenforo thread or conversation
<html>
<p>
Drag this bookmarklet link to your bookmarks toolbar:
<a href="javascript:void((function() {var element=document.createElement('script'); element.setAttribute('src', 'https://rawgit.com/khanfx/c0ffa60216ef6d152dca15bff91d8273/raw/d77f11daa7af1910dcde74e855301db8e61c36ef/xenforo-thread-export.js'); document.body.appendChild(element)})())">Save Xenforo Thread</a>
</p>
<p>Or check here for <a href='http://www.howtogeek.com/189358/beginner-geek-how-to-use-bookmarklets-on-any-device/'>How to Use a Bookmarklet</a></a></p>
</html>
var PAGE_LIMIT = 250;
function getResponseURL(jqXHR) {
var response = jqXHR.getAllResponseHeaders().match(/http(s?):\/\/(.*?)$/gim);
if (response)
return response[0];
}
// <abbr class="DateTime" data-time="1472242038" data-diff="334478" data-datestring="Aug 26, 2016" data-timestring="3:07 PM">Aug 26, 2016 at 3:07 PM</abbr>
var captureArticle = (ix,el) => {
var $a=$(el);
var $d = $a.find('.DateTime');
var article = {
//name: $a.find('[itemprop=creator]').text().trim(),
name: $a.data('author'),
//date: $a.find('time').attr('title'),
date: $d.attr('title'),
//date: $d.attr('data-')
//content: $a.find('[data-role=commentContent]').html()
content: $a.find('.messageText').html()
};
if (!article.date)
article.date = $d.attr('data-datestring') + $d.attr('data-timestring');
//if (!article.date) return null;
if (article.name && !article.date) debugger;
return article;
};
var parse = (path,onParse,notfound) => {
var jqXHR = $.ajax(path);
jqXHR.then(doc => {
var newUrl = getResponseURL(jqXHR);
if (newUrl)
console.log('Result page %s', newUrl)
if (newUrl &&
path.indexOf('page-1') == -1 &&
newUrl.indexOf(path) == -1) {
console.log('Done: page does not match')
notfound && notfound();
return;
}
//var articles = $(doc).find('article');
var articles = $(doc).find('.message');
var foundC = 0;
articles.each((ix,el) => {
if ($(el).hasClass('quickReply') ||
$(el).find('.quickReply').length)
return;
onParse(captureArticle(ix,el));
foundC++;
});
if (!foundC)
notfound && notfound();
});
return jqXHR;
}
var append = (article) => {
var $article = $('<div>').addClass('article').appendTo($output);
for(key in article) {
$('<div>').addClass(key).html(article[key]).appendTo($article);
}
};
var removePageRef = (url) => url.replace(/\/page-\d+$|\/$/,'')+'/';
var withEachPage = (callback) => {
var done = $.Deferred();
var path = removePageRef(location.pathname);
var pageC = 1;
var stop = false;
var runNext = () => callback(path + 'page-' + pageC++,() => stop = true).then(checkResult);
var checkResult = () => {
if (!stop && pageC <= PAGE_LIMIT)
runNext();
else
done.resolve();
}
runNext();
return done;
}
var selectDOM = (el) => {
var sel = window.getSelection();
var range = document.createRange();
range.selectNodeContents(el);
sel.removeAllRanges();
sel.addRange(range);
}
// https://thiscouldbebetter.wordpress.com/2012/12/18/loading-editing-and-saving-a-text-file-in-html5-using-javascrip/
function saveDOM($el)
{
var textToSave = $el.html();
var textToSaveAsBlob = new Blob([textToSave], {type:"text/html"});
var textToSaveAsURL = window.URL.createObjectURL(textToSaveAsBlob);
var fileNameToSaveAs = 'thread-export.html';
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
downloadLink.href = textToSaveAsURL;
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
downloadLink.click();
}
function destroyClickedElement(event)
{
document.body.removeChild(event.target);
}
console.clear();
var $output = $('<div>').addClass('dump-results').appendTo('body');
$output.append('<style type="text/css">.article{margin:10px} .name{font-size:200%;} .date{font-size:80%;}');
withEachPage((path,done) => {
console.log('Fetching %s', path);
return parse(path,append,done);
}).then(() => saveDOM($output));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment