Created
January 18, 2012 15:41
-
-
Save quietlynn/1633597 to your computer and use it in GitHub Desktop.
Google+ Post Censorship => Censor the words in your post.
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
/* | |
Google+ Post Censorship => Censor the words in your post. | |
Copyright (C) 2012 Jingqin Lynn | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
// ==UserScript== | |
// @name Google+ Post Censorship | |
// @namespace http://project.quietmusic.org/j/ | |
// @description Censor the words in your post. | |
// @match https://plus.google.com/* | |
// ==/UserScript== | |
function doClick(target) { | |
var e; | |
e = document.createEvent("MouseEvents"); | |
e.initEvent("mousedown", true, true); | |
target.dispatchEvent(e); | |
e = document.createEvent("MouseEvents"); | |
e.initEvent("click", true, true); | |
target.dispatchEvent(e); | |
e = document.createEvent("MouseEvents"); | |
e.initEvent("mouseup", true, true); | |
target.dispatchEvent(e); | |
return target; | |
}; | |
function doKeypress(target) { | |
var e = document.createEvent("KeyboardEvent"); | |
e.initEvent("keypress", true, true, window, 0, 0, 0, 0, 0, "e".charCodeAt(0)); | |
target.dispatchEvent(e); | |
return target; | |
}; | |
var urlPrefix = "http://sopastrike.com/#?/censor/"; | |
var censorChar = "█"; | |
var censorCharCode = censorChar.charCodeAt(0); | |
var censorWord = function (len) { | |
return Array(len + 1).join(censorChar); | |
} | |
var uncensorText = function(e) { | |
if(!e) e = event; | |
e.preventDefault(); | |
var span = e.target; | |
span.parentElement.replaceChild(document.createTextNode(span.title), span); | |
}; | |
var onCensorButtonClick = function (e) { | |
if(!e) e = event; | |
e.preventDefault(); | |
var sel = document.getSelection(); | |
if(sel.anchorNode == sel.focusNode && sel.anchorNode instanceof Text) { | |
var start = sel.anchorOffset; | |
var end = sel.focusOffset; | |
if(start == end) return; | |
if(start > end) { | |
var t = start; | |
start = end; | |
end = t; | |
} | |
var txt = sel.anchorNode; | |
var post = txt.textContent; | |
var beforeText = document.createTextNode(post.substr(0, start)); | |
var span = document.createElement("span"); | |
span.textContent = censorWord(end - start); | |
span.setAttribute("title", post.substring(start, end)); | |
span.setAttribute("contenteditable", "false"); | |
span.setAttribute("tabindex", "-1"); | |
span.setAttribute("censored", "true"); | |
span.addEventListener("contextmenu", uncensorText, false); | |
var p = txt.parentElement; | |
txt.nodeValue = post.substr(end); | |
p.insertBefore(beforeText, txt); | |
p.insertBefore(span, txt); | |
if(!p.getAttribute("censored")) { | |
p.setAttribute("censored", "true"); | |
var onShareButtonMousedown = function(e) { | |
if(!e) e = event; | |
e.preventDefault(); | |
e.target.removeEventListener("mousedown", onShareButtonMousedown, false); | |
p.removeAttribute("censored"); | |
var spans = p.querySelectorAll("span[censored='true']"); | |
var uncensored = new Array(); | |
for(var i = 0; i < spans.length; i++) { | |
uncensored.push(encodeURIComponent(spans[i].title)); | |
} | |
var uri = urlPrefix + uncensored.join("/"); | |
addUncensoredLink(uri); | |
}; | |
document.querySelector(".e-U-me-Qf").addEventListener("mousedown", onShareButtonMousedown, false); | |
} | |
} | |
}; | |
var addUncensoredLink = function (uri) { | |
var insertTo = document.querySelector(".k-Qf-e-fa"); | |
//This will fail for unknown reasons: | |
//insertTo.addEventListener('DOMNodeInserted', onMediaInserted, false); | |
doClick(document.querySelector(".e-ja-p.e-ja-p-C")); | |
var intMedia = setInterval(function() { | |
var urlBox = insertTo.querySelector(".Nf"); | |
if(urlBox) { | |
clearInterval(intMedia); | |
urlBox.value = uri; | |
doKeypress(urlBox); | |
var addButton = document.querySelector(".jhqR7"); | |
var i = setInterval(function() { | |
if(addButton.getAttribute("aria-disabled") == "false") { | |
clearInterval(i); | |
doClick(addButton); | |
} | |
}, 100); | |
} | |
}, 100); | |
}; | |
function checkElement(ele) { | |
if(!ele.classList) return; | |
var linkButton = ele; | |
if(!ele.classList.contains("e-ja-p") || !ele.classList.contains("e-ja-p-C")) { | |
linkButton = ele.querySelector(".e-ja-p.e-ja-p-C"); | |
if(!linkButton) return; | |
} | |
if(ele.querySelector(".ext-censor-button")) return; | |
var button = document.createElement("button"); | |
button.setAttribute("role", "button"); | |
button.setAttribute("class", "e-ja-p ext-censor-button"); | |
button.setAttribute("title", "Censor"); | |
button.textContent = censorChar + censorChar; | |
button.setAttribute("style", "border: none; top: -10px; position: relative; padding: 0; margin-right: 8px;"); | |
button.addEventListener("click", onCensorButtonClick, false); | |
linkButton.parentElement.appendChild(button); | |
} | |
//checkElement(document.body); | |
function uncensorPost(a) { | |
var content = a.parentElement.parentElement.parentElement.parentElement.querySelector(".rXnUBd"); | |
var uncensored = a.href.substr(urlPrefix.length).split("/"); | |
var uncensoredPos = 0; | |
var result = document.evaluate(".//text()", content, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); | |
for(var i = 0; i < result.snapshotLength; i++) { | |
var text = result.snapshotItem(i); | |
var match = null; | |
var pos = -1; | |
var str = null; | |
while((pos = (str = text.nodeValue).indexOf(censorChar)) >= 0) { | |
if(uncensoredPos > uncensored.length) return; | |
var end = pos + 1; | |
while(str.charCodeAt(end) == censorCharCode) end++; | |
var p = text.parentNode; | |
if(pos > 0) { | |
var beforeText = document.createTextNode(str.substr(0, pos)); | |
p.insertBefore(beforeText, text); | |
} | |
text.nodeValue = str.substr(end); | |
var span = document.createElement("span"); | |
span.textContent = decodeURIComponent(uncensored[uncensoredPos]); | |
span.setAttribute("style", "background: black;"); | |
p.insertBefore(span, text); | |
uncensoredPos++; | |
} | |
} | |
} | |
function checkPosts(ele) { | |
var censoredPosts = ele.querySelectorAll("a[href^='" + urlPrefix + "']"); | |
for(var i=0;i<censoredPosts.length;i++) uncensorPost(censoredPosts[i]); | |
} | |
document.body.addEventListener('DOMNodeInserted', function(e) { | |
if(!e) e = event; | |
if(!e.target.classList) return; | |
checkElement(e.target); | |
checkPosts(e.target); | |
}, false); | |
checkPosts(document.body); |
还原方法:
首先必须确认那个帖子包含一个到 SOPA Strike 的链接。
安装这个脚本后,选中被涂黑的文本,即可看到原来的文本。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
使用方法:
安装后 G+ 发贴框右下角会增加 『██』按钮。
先选中你想要涂黑的文字,然后点击『██』按钮,即可将这些文字涂黑。
鼠标悬停可以确认原文,右键点击则可以还原。
涂黑文字后,点击发贴按钮并不会立即发贴,而是会添加一个链接。
这个链接中包含了被涂黑的内容,所以不建议去除该链接。除非你不希望别人查看原始内容。
如果觉得链接的图片和说明很烦,可以去除,但链接本身不能移除。
当链接添加完成后,再次点击发贴按钮即可发送。