// ==UserScript==
// @name FZ-E1のようなもの
// @description もう「バールのようなもの」は古い
// @include http*
// @version 1.0
// @namespace https://gf.qytechs.cn/users/3157
// ==/UserScript==
const filters = [
{
name: "バール",
regexp: /バール/g,
txt: function(match) { return "FZ-E1"; }
},
];
/***********************************
* Helper functions for filters *
***********************************/
function digits(s)
{
return s.replace(/[^0-9]/g, "");
}
function alphanumerics(s)
{
return s.replace(/[^0-9a-z]/ig, "");
}
/***********************************
* Link styling *
***********************************/
/*
You can make links generated by AutoLink look different from normal links
by editing styleLink below and/or by setting up user style sheet rules.
Example: on squarefree.com, make autolinked plain text links orange. (Firefox trunk only.)
@-moz-document domain(squarefree.com) {
.autolink-plain-text-link { color: orange ! important; }
}
*/
function styleLink(a, filter)
{
a.style.borderBottom = "0px solid";
}
/***********************************
* Fix filters *
***********************************/
function fixFilters()
{
var i, r;
for (i = 0; r = filters[i]; ++i) {
// lowercase, and replace each run of non-alphanumerics with a single hyphen
r.classNamePart = r.name.toLowerCase().replace(/[^0-9a-z]+/ig, "-");
if(!r.regexp.global)
alert("AutoLink filter " + r.name + " is not global! This will break stuff!");
}
}
fixFilters();
/***********************************
* When and where to run *
***********************************/
var moddingDOM = false;
window.addEventListener("load", init, false);
function init()
{
document.addEventListener("DOMNodeInserted", nodeInserted, false);
setTimeout(go, 50, document.body);
}
// This makes it work at Gmail.
// 20% performance penalty on a plain text file with a link on almost every line.
// Tiny performance penalty on pages with few automatically added links.
function nodeInserted(e)
{
// our own modifications should not trigger this.
// (we don't want our regular expression objects getting confused)
// (we want better control over when we recurse)
//GM_log("Inserted: " + e.target);
if (!moddingDOM)
go(e.target);
}
/***********************************
* DOM traversal *
***********************************/
/*
This script uses manual DOM traversal, in an iterative way without a stack!
Advantages of snapshot XPath:
* Much less code
* 20-40% faster
* May be possible to get another speed boost by including the regexp in the XPath expression - http://www.developer.com/xml/article.php/10929_3344421_3
* All the cool people are using it
Advantages of manual DOM traversal:
* Lets us stop+continue (snapshot xpath doesn't let us)
* Lets us modify DOM in strange ways without worrying.
* Easier to control which elements we recurse into.
*/
// Ignore all children of these elements.
const skippedElements = {
trans: true, // keeps us from screwing with existing links. keeps us from recursing to death :)
noscript: true, // noscript has uninterpreted, unshown text children; don't waste time+sanity there.
head: true,
script: true,
style: true,
textarea: true,
label: true,
select: true,
button: true
}
const gmail = (location.host == "gmail.google.com");
function skipChildren(node)
{
if (node.tagName) // !
{
if (skippedElements[node.tagName.toLowerCase()]) {
return true;
}
if (gmail) {
if (node.className == "ac") // gmail autocomplete (fake dropdown)
return true;
if (node.className == "ilc sxs") // invite foo to gmail (fake link/button)
return true;
}
}
return false;
}
function go(traversalRoot)
{
var m;
// Ensure we're not already in a forbidden element.
for (m = traversalRoot; m != undefined; m = m.parentNode) {
if (skipChildren(m)) {
return;
}
}
// work around bug, or in case previous user scripts did crazy stuff
traversalRoot.normalize();
function cont(n, didChildren)
{
var k = 0; // split work into chunks so Firefox doesn't freeze
var q;
while (n && k < 100)
{
++k;
// Do stuff at this node
if (!didChildren && n.nodeType == 3) {
if((q = runFiltersOnTextNode(n))) {
n = q[0];
// if there were changes, run filters again on the new text node that's here
if (q[1])
continue;
}
}
// Traverse to the "next" node in depth-first order
if (!n.firstChild)
didChildren = true;
if (didChildren && n == traversalRoot)
break;
else if (!didChildren && n.firstChild && !skipChildren(n)) {
n = n.firstChild;
// didChildren is already false and should stay false
}
else {
if (n.nextSibling) {
n = n.nextSibling;
didChildren = false;
}
else {
n = n.parentNode;
didChildren = true;
}
}
} // end while
if (!n) {
//GM_log("Odd. traversalRoot was " + traversalRoot);
}
else if (n == traversalRoot) {
//GM_log("Done");
//alert("AutoLink time: " + (new Date() - timeBefore))
}
else {
// Continue after 10ms.
//GM_log("will have to continue");
setTimeout(cont, 10, n, didChildren);
}
} // end function cont
cont(traversalRoot, false);
}
/***********************************
* Running filters *
***********************************/
// runFiltersOnTextNode
// Return: node at which to continue traversal, or |null| to mean no changes were made.
function runFiltersOnTextNode(node)
{
// Too many variables. Good hint that I need to split this function up :P
var source, j, regexp, match, lastLastIndex, k, filter, href, anyChanges; // things
var used, unused, firstUnused, lastUnused, a, parent, nextSibling; // nodes
source = node.data;
anyChanges = false;
// runFiltersOnTextNode has its own do-too-much-at-once avoider thingie.
// assumption: if there is one text node with a lot of matches,
// it's more important to finish quickly than be transparent.
// (e.g. plain text file FULL of links)
// assumption: 40 * 100 = 140.
k=0;
for (j = 0; filter = filters[j]; ++j) {
regexp = filter.regexp;
if (regexp.test(source)) {
parent = node.parentNode;
nextSibling = node.nextSibling;
regexp.lastIndex = 0;
firstUnused = null;
// Optimization from the linkify that came with Greasemonkey(?):
// instead of splitting a text node multiple times, take advantage
// of global regexps and substring.
for (match = null, lastLastIndex = 0; k < 40 && (match = regexp.exec(source)); ) {
// this should happen first, so RegExp.foo is still good :)
txt = genLink(filter, match);
if (txt != null && txt != location.href) {
++k;
unused = document.createTextNode(source.substring(lastLastIndex, match.index));
if (!anyChanges) {
anyChanges = true;
parent.removeChild(node);
firstUnused = unused;
moddingDOM = true;
}
parent.insertBefore(unused, nextSibling);
used = document.createTextNode(match[0])
trans = document.createElement("trans");
//a.href = href;
trans.title = "translated by filter: " + filter.name;
//a.className = "autolink autolink-" + filter.classNamePart;
trans.innerHTML = txt;
styleLink(trans, filter);
// trans.appendChild(used);
parent.insertBefore(trans, nextSibling);
lastLastIndex = regexp.lastIndex;
}
}
if (anyChanges) {
lastUnused = document.createTextNode(source.substring(lastLastIndex));
parent.insertBefore(lastUnused, nextSibling);
moddingDOM = false;
return [firstUnused, true]
}
return [node, false];
}
}
return null;
}
function genLink(filter, match)
{
try {
return filter.txt(match);
}
catch(er) {
return "data:text/plain,Error running AutoLink function for filter: " + encodeURIComponent(filter.name) + "%0A%0A" + encodeURIComponent(er);
}
}