Last active
July 25, 2018 10:41
-
-
Save A-312/fa7ac99f1336b8ff06cc9013f2e59681 to your computer and use it in GitHub Desktop.
Userscript pour citer la selection sur Zeste de savoir - Version 1.41
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name ZDS - Citer la selection | |
// @description Citer la selection. | |
// @namespace zds_citer_selection_a-312 | |
// @author A-312 | |
// @version 1.41 | |
// @include https://zestedesavoir.com/forums/sujet/* | |
// @include https://zestedesavoir.com/tutoriels/* | |
// @include https://zestedesavoir.com/billets/* | |
// @require http://code.jquery.com/jquery-3.3.1.min.js | |
// ==/UserScript==zds | |
(function($, undefined) { | |
//$(".message-actions").off("click", "[data-ajax-input='cite-message']").on("click", "[data-ajax-input='cite-message']", function(e) { | |
$(".message-actions").off("click", "[data-ajax-input='cite-message']"); | |
$(".message-actions .cite[data-ajax-input='cite-message']") | |
.parent().on("click", "[data-ajax-input='cite-message']", function(e) { | |
var $act = $(this), | |
$editor = $(".md-editor"); | |
// quote the selection | |
var doAjax = !(function() { | |
var $message = $act.closest(".message"), | |
$msgcontent = $message.find("[itemprop=text]"), | |
username = $message.find("[itemprop=name]").text(), | |
href = $message.find("> .message-metadata > a.date")[0].href; | |
if (window.getSelection && window.getSelection() && window.getSelection().rangeCount > 0) { | |
var selection = window.getSelection(), | |
range = selection.getRangeAt(0); | |
console.log("dddddddd", selection, range); | |
if (selection.isCollapsed) | |
return false; | |
if (!$(range.startContainer).closest($msgcontent)[0]) | |
return false; | |
if (!$(range.endContainer).closest($msgcontent)[0]) { | |
var node = $msgcontent[0].childNodes; | |
node = node[node.length - 1]; | |
range.setEnd(node, node.nodeValue.length); | |
} | |
var content = html2MD_rangeToVirtualDOM(range); | |
var markdown = window.html2markdown(content); | |
markdown = markdown.replace(/(^|\n)/g, "$1> "); | |
markdown += "\nSource:[" + username + "](" + href + ")"; | |
$editor.val($editor.val() + markdown + "\n\n"); | |
return true; | |
} | |
return false; | |
})(); | |
if (doAjax) { | |
$.ajax({ | |
url: $act.attr("href"), | |
dataType: "json", | |
success: function(data) { | |
$editor.val($editor.val() + data.text + "\n\n"); | |
} | |
}); | |
} | |
// scroll to the textarea and focus the textarea | |
$("html, body").animate({ | |
scrollTop: $editor.offset().top | |
}, 500); | |
$editor.focus(); | |
e.stopPropagation(); | |
e.preventDefault(); | |
}); | |
})(jQuery); | |
/* ===== Zeste de Savoir ==================================================== | |
Parse HTML to Markdown | |
--------------------------------- | |
Author: A-312 | |
========================================================================== */ | |
(function(window, $, undefined) { | |
"use strict"; | |
window.html2markdown = function(aParam) { | |
var abbr = {}, | |
footer = ""; | |
var $message = (aParam instanceof $) ? aParam : $("<div></div>").append(aParam), | |
element, text, | |
boolstisP = !!($message.children(":first").is("p")); | |
$message.find("p").prepend("\n"); | |
while ($message[0].children.length > 0 && $message[0].children[0]) { | |
element = $message[0].children[0]; | |
if (!html2Text(element)) { | |
if ($(element).children()[0]) { | |
recursiveWalk(element); | |
} | |
element.parentNode.replaceChild(document.createTextNode($(element).text()), element); | |
} | |
} | |
$.each(abbr, function(word, title) { | |
footer += "\n\n*[" + word + "]: " + title; | |
}); | |
text = $message.text(); | |
if (boolstisP) //remove first new line | |
text = text.replace(/^\n/, ""); | |
text = text.replace(/\n( +)\n/g, "\n\n"); | |
return text + footer; | |
}; | |
var makePathOfHTMLElements = function(parents) { | |
return parents.map(function() { | |
var innerTag = "", | |
$el = $(this); | |
["id", "class"].map(function(key) { | |
if ($el.attr(key)) | |
innerTag += " " + key + '="' + $el.attr(key) + '"'; | |
}); | |
return "<" + $el[0].tagName + innerTag + "></" + $el[0].tagName + ">"; | |
}).get(); | |
}; | |
/* | |
* Cette fonction ajoute le bon niveau HTML à la selection. Pour éviter un bug | |
* lorsque l'utilisateur selectionne uniquement l'intérieur d'une balise code, | |
* ou s'il selectionne uniquement l'auteur de la citation. | |
* | |
* Fonctionnement : La fonction va ajouter les parents manquants aux éléments, | |
* pour obtenir le même niveau HTML à chaque éxecution. | |
*/ | |
window.html2MD_rangeToVirtualDOM = function(range) { | |
var content = range.cloneContents(), | |
slice = (content.childNodes[0].nodeType === Node.ELEMENT_NODE) ? 1 : 0, | |
parents = $(range.startContainer).parents().slice(slice); | |
// .slice(1) car startContainer renvoit le node et non l'element | |
parents = makePathOfHTMLElements(parents); | |
var index = parents.indexOf('<DIV class="message-content"></DIV>'); | |
if (index === -1) { // On anticipe un bug : provoqué en cas de changement du template/html. | |
console.error("ligne 68: citerlaselection !"); | |
return content; | |
} | |
parents = parents.slice(0, index - 1); // -1 pour DIV car .message-content > DIV > [contenuMSG] | |
if (parents && parents.length > 0) { | |
var $virtualDOM = $(parents[0]); | |
for (var i = 1, $child = $virtualDOM; i < parents.length; i++) | |
$child = $(parents[i]).append($child); | |
$virtualDOM.append(content).append("\n"); | |
return (parents.length > 1) ? $virtualDOM.parents().last() : $virtualDOM; | |
} | |
return content; | |
}; | |
var recursiveWalk = function(element) { | |
if ($(element).children()[0]) { | |
$(element).children().each(function() { | |
if (html2Text(this)) | |
return; | |
else | |
recursiveWalk(this); | |
}); | |
} | |
return element; | |
}; | |
var html2Text = function(element) { | |
var text = $(element).text(); | |
var repaceWithTextNode = function(string, oldChild) { | |
var child = (oldChild || element); | |
child.parentNode.replaceChild(document.createTextNode(string), child); | |
}; | |
var html2MD = function(obj) { | |
return $(recursiveWalk(obj)).text(); | |
}; | |
//console.log("-->", element.nodeName, $(element).html()); | |
if (element.nodeName === "BR") { | |
repaceWithTextNode(" "); | |
} | |
//bold | |
else if (element.nodeName === "STRONG") { | |
repaceWithTextNode("**" + html2MD(element) + "**"); | |
} | |
//italic | |
else if (element.nodeName === "EM") { | |
repaceWithTextNode("*" + html2MD(element) + "*"); | |
} | |
//strike | |
else if (element.nodeName === "DEL") { | |
repaceWithTextNode("~~" + html2MD(element) + "~~"); | |
} | |
//sup | |
else if (element.nodeName === "SUP") { | |
repaceWithTextNode("^" + html2MD(element) + "^"); | |
} | |
//sub | |
else if (element.nodeName === "SUB") { | |
repaceWithTextNode("~" + html2MD(element) + "~"); | |
} | |
//abbr & footnote | |
else if (element.nodeName === "ABBR") { | |
repaceWithTextNode(text); | |
abbr[text] = element.title; | |
} | |
//key | |
else if (element.nodeName === "KBD") { | |
repaceWithTextNode("||" + text + "||"); | |
} | |
//titles h1, h2, h3, h4 | |
else if (element.nodeName[0] === "H" && /^H[3-6]$/.test(element.nodeName)) { | |
repaceWithTextNode("\n" + new Array(element.nodeName[1] - 1).join("#") + " " + html2MD(element)); | |
} | |
//ul & ol | |
else if (element.nodeName === "LI") { | |
if (!$(this).data("num") && $(element).parent()[0].nodeName === "OL") { | |
$(element).parent().children().each(function() { | |
$(this).data("num", ($(this).index() + 1) + ". "); | |
}); | |
} | |
repaceWithTextNode(($(element).data("num") || "- ") + html2MD(element)); | |
} | |
//center & right | |
else if (element.nodeName === "DIV" && $(element).attr("align")) { | |
text = html2MD(element); | |
text = text.replace(/^\s*(.*?)\s*$/, "$1") || text; | |
if ($(element).attr("align") === "center") { | |
repaceWithTextNode("\n-> " + text + " <-"); | |
} else if ($(element).attr("align") === "right") { | |
repaceWithTextNode("\n-> " + text + " ->"); | |
} else { | |
return false; | |
} | |
} | |
//quote | |
else if (element.nodeName === "FIGURE" && $(element).children("blockquote")[0]) { | |
var $blockquote = $(element).children("blockquote"); | |
recursiveWalk($blockquote); | |
text = $blockquote.children("p").text().replace(/( {2})?\n/g, " \n> "); | |
text += "\nSource:" + html2MD($(element).children("figcaption")).replace(/^\n/, ""); | |
repaceWithTextNode(text); | |
} | |
//image | |
else if (element.nodeName === "FIGURE" && $(element).children("img")[0]) { | |
var src = $(element).children("img").attr("src"), | |
title = $(element).children("figcaption").text(); | |
repaceWithTextNode(""); | |
} | |
//inline image & smiley | |
else if (element.nodeName === "IMG") { | |
if ($(element).attr("src").indexOf("/static/smileys") === 0) | |
repaceWithTextNode(element.alt); | |
else | |
repaceWithTextNode(".attr("src") + ")"); | |
} | |
//link | |
else if (element.nodeName === "A") { | |
text = html2MD(element); | |
if ($(element).hasClass("spoiler-title")) { | |
repaceWithTextNode(""); // remove "Afficher/Masquer le contenu masqué" | |
} else if (text.indexOf("http") === 0) { | |
repaceWithTextNode($(element).attr("href")); | |
} else { | |
repaceWithTextNode("[" + text + "](" + $(element).attr("href") + ")"); | |
} | |
} | |
//table | |
/* | |
*/ | |
/* ... */ | |
else if (element.nodeName === "DIV" && $(element).is(".information, .question, .warning, .error, .spoiler")) { | |
var makeBlock = function(type) { | |
var text = html2MD($(element)); | |
text = text | |
.replace(/( {2})?\n/g, " \n| ") | |
.replace(/^ \n\|\s+\n/, "") | |
.replace(/(\n\|\s+)+$/, ""); | |
repaceWithTextNode("\n[[" + type + "]]\n" + text); | |
}; | |
//information | |
if ($(element).hasClass("information")) { | |
makeBlock("information"); | |
} | |
//question | |
else if ($(element).hasClass("question")) { | |
makeBlock("question"); | |
} | |
//attention | |
else if ($(element).hasClass("warning")) { | |
makeBlock("attention"); | |
} | |
//error | |
else if ($(element).hasClass("error")) { | |
makeBlock("erreur"); | |
} | |
//secret | |
else if ($(element).hasClass("spoiler")) { | |
makeBlock("secret"); // see A (remove "Afficher/Masquer le contenu masqué") | |
} else { | |
return false; | |
} | |
} | |
//monospace | |
else if (element.nodeName === "CODE") { | |
repaceWithTextNode("`" + text + "`"); | |
} | |
//blockcode | |
else if (element.nodeName === "TABLE" && $(element).hasClass("codehilitetable")) { | |
text = $(element).find("td.code pre").text(); | |
if (text.split("\n").length <= 2) | |
repaceWithTextNode("\n " + text.replace(/\n$/, "")); | |
else | |
repaceWithTextNode(" \n```\n" + text + "```"); | |
} | |
//math | |
else if (element.nodeName === "MATHJAX") { | |
text = $(element).children("script[type='math/tex']").text(); | |
repaceWithTextNode("$" + text + "$"); | |
} | |
//iframe | |
else if (element.nodeName === "FIGURE" && $(element).children("iframe")[0]) { | |
text = html2MD($("<div></div>").append($(element).children("iframe"))); | |
text += "\nVideo:" + html2MD($(element).children("figcaption")).replace(/^\n/, ""); | |
repaceWithTextNode(text); | |
} | |
//inline iframe | |
else if (element.nodeName === "IFRAME") { | |
var embeds = [ | |
/^https?:\/\/www\.dailymotion\.com\/embed\/video\/(.+)$/, | |
/^https?:\/\/www\.metacafe\.com\/embed\/(.+)\/$/, | |
/^https?:\/\/www\.veoh\.com\/videodetails2\.swf\?.*permalinkId\=(.+)$/, | |
/^https?:\/\/player\.vimeo\.com\/video\/(.+)$/, | |
/^https?:\/\/screen\.yahoo\.com\/(.+)\/?/, // don't add $ | |
/^https?:\/\/www\.youtube\.com\/embed\/(.+)$/, | |
/^https?:\/\/jsfiddle\.net\/(.*)\/(.*)\// // don't add $ | |
]; | |
var urls = [ | |
"http://www.dailymotion.com/video/$1", | |
"http://www.metacafe.com/watch/$1/", | |
"http://www.veoh.com/watch/$1", | |
"http://vimeo.com/$1", | |
"http://screen.yahoo.com/$1", | |
"http://youtu.be/$1", | |
"http://jsfiddle.net/$1/$2/" | |
]; | |
text = $(element).attr("src"); | |
for (var i = 0; i < embeds.length; i++) { | |
if (embeds[i].test(text)) { | |
repaceWithTextNode("\n!(" + text.replace(embeds[i], urls[i]) + ")"); | |
break; | |
} | |
} | |
} | |
//hr | |
else if (element.nodeName === "HR") { | |
repaceWithTextNode("\n\n------\n\n"); | |
} | |
//other | |
else { | |
return false; | |
} | |
return true; | |
}; | |
})(window, jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment