From 20656daa0bde7fca1e4a320b1f5df9e14359b977 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sat, 24 Sep 2011 22:06:53 +0200 Subject: [PATCH 1/9] Start Filter work --- 4chan_x.user.js | 19 ++++++++++++++++--- script.coffee | 13 +++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index c33e9a5a9..cfa44e7bd 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -61,13 +61,12 @@ */ (function() { - var $, $$, DAY, Favicon, HOUR, MINUTE, Main, NAMESPACE, QR, SECOND, Time, anonymize, conf, config, d, expandComment, expandThread, firstRun, g, getTitle, imgExpand, imgGif, imgHover, imgPreloading, key, keybinds, log, nav, nodeInserted, options, pathname, quoteBacklink, quoteInline, quoteOP, quotePreview, redirect, replyHiding, reportButton, revealSpoilers, sauce, temp, threadHiding, threadStats, threading, titlePost, ui, unread, updater, val, watcher; + var $, $$, DAY, Favicon, HOUR, MINUTE, Main, NAMESPACE, QR, SECOND, Time, anonymize, conf, config, d, expandComment, expandThread, filter, firstRun, g, getTitle, imgExpand, imgGif, imgHover, imgPreloading, key, keybinds, log, nav, nodeInserted, options, pathname, quoteBacklink, quoteInline, quoteOP, quotePreview, redirect, replyHiding, reportButton, revealSpoilers, sauce, temp, threadHiding, threadStats, threading, titlePost, ui, unread, updater, val, watcher; var __slice = Array.prototype.slice; config = { main: { Enhancing: { '404 Redirect': [true, 'Redirect dead threads'], - 'Anonymize': [false, 'Make everybody anonymous'], 'Keybinds': [true, 'Binds actions to keys'], 'Time Formatting': [true, 'Arbitrarily formatted timestamps, using your local time'], 'Report Button': [true, 'Add report buttons'], @@ -76,7 +75,9 @@ 'Index Navigation': [true, 'Navigate to previous / next thread'], 'Reply Navigation': [false, 'Navigate to top / bottom of thread'] }, - Hiding: { + Filtering: { + 'Anonymize': [false, 'Make everybody anonymous'], + 'Filter': [false, 'Self-moderation placebo'], 'Reply Hiding': [true, 'Hide single replies'], 'Thread Hiding': [true, 'Hide entire threads'], 'Show Stubs': [true, 'Of hidden threads / replies'] @@ -516,6 +517,15 @@ } return Array.prototype.slice.call(root.querySelectorAll(selector)); }; + filter = { + init: function() { + return HTMLBlockquoteElement.prototype.toString = function() { + return ($.el('span', { + innerHTML: this.innerHTML.replace(/
/g, '\n') + })).textContent; + }; + } + }; expandComment = { init: function() { var a, _i, _len, _ref, _results; @@ -2846,6 +2856,9 @@ if (g.REPLY && (id = location.hash.slice(1)) && /\d/.test(id[0]) && !$.id(id)) { scrollTo(0, d.body.scrollHeight); } + if (conf['Filter']) { + filter.init(); + } if (conf['Image Expansion']) { imgExpand.init(); } diff --git a/script.coffee b/script.coffee index fd975629e..8dcf594dd 100644 --- a/script.coffee +++ b/script.coffee @@ -2,7 +2,6 @@ config = main: Enhancing: '404 Redirect': [true, 'Redirect dead threads'] - 'Anonymize': [false, 'Make everybody anonymous'] 'Keybinds': [true, 'Binds actions to keys'] 'Time Formatting': [true, 'Arbitrarily formatted timestamps, using your local time'] 'Report Button': [true, 'Add report buttons'] @@ -10,7 +9,9 @@ config = 'Thread Expansion': [true, 'View all replies'] 'Index Navigation': [true, 'Navigate to previous / next thread'] 'Reply Navigation': [false, 'Navigate to top / bottom of thread'] - Hiding: + Filtering: + 'Anonymize': [false, 'Make everybody anonymous'] + 'Filter': [false, 'Self-moderation placebo'] 'Reply Hiding': [true, 'Hide single replies'] 'Thread Hiding': [true, 'Hide entire threads'] 'Show Stubs': [true, 'Of hidden threads / replies'] @@ -374,6 +375,11 @@ else $$ = (selector, root=d.body) -> Array::slice.call root.querySelectorAll selector +filter = + init: -> + HTMLBlockquoteElement.prototype.toString = -> + return ($.el 'span', innerHTML: @innerHTML.replace /
/g, '\n').textContent + expandComment = init: -> for a in $$ 'span.abbr a' @@ -2183,6 +2189,9 @@ Main = if g.REPLY and (id = location.hash[1..]) and /\d/.test(id[0]) and !$.id(id) scrollTo 0, d.body.scrollHeight + if conf['Filter'] + filter.init() + if conf['Image Expansion'] imgExpand.init() From 33d650b530656bca5eedd6491380e52cf57adfd5 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 25 Sep 2011 05:24:25 +0200 Subject: [PATCH 2/9] Set up options --- 4chan_x.user.js | 40 ++++++++++++++++++++++++++++++++++------ script.coffee | 30 +++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 02b2a40f8..1a78e95e4 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -116,6 +116,15 @@ 'Indicate OP quote': [true, 'Add \'(OP)\' to OP quotes'] } }, + filter: { + name: '', + trip: '', + mail: '', + sub: '', + com: '', + file: '', + md5: '' + }, flavors: ['http://iqdb.org/?url=', 'http://google.com/searchbyimage?image_url=', '#http://regex.info/exif.cgi?url=', '#http://tineye.com/search?url=', '#http://saucenao.com/search.php?db=999&url=', '#http://imgur.com/upload?url='].join('\n'), time: '%m/%d/%y(%a)%H:%M', backlink: '>>%id', @@ -1127,7 +1136,7 @@ return $.replace(home, a); }, dialog: function() { - var arr, back, checked, description, dialog, flavors, hiddenNum, hiddenThreads, input, key, li, obj, overlay, time, ul, _i, _len, _ref, _ref2; + var arr, back, checked, description, dialog, hiddenNum, hiddenThreads, input, key, li, obj, overlay, ta, time, ul, _i, _j, _len, _len2, _ref, _ref2, _ref3; dialog = $.el('div', { id: 'options', innerHTML: '\ @@ -1141,6 +1150,7 @@ \
\ \ + | \ | \ | \ | \ @@ -1152,6 +1162,18 @@
\ \ \ + \ +
\ + Filters are case-insensitive. One filter per line.
\ + You can use regular expressions, without opening and ending `/`, and without flags.\ +

Name:

\ +

Tripcode:

\ +

E-mail:

\ +

Subject:

\ +

Comment:

\ +

Filename:

\ +

Image MD5:

\ +
\ \
\
    \ @@ -1224,15 +1246,19 @@ }); $.bind($('button', li), 'click', options.clearHidden); $.add($('ul:nth-child(2)', dialog), li); - (flavors = $('#flavors', dialog)).textContent = conf['flavors']; - $.bind(flavors, 'change', $.cb.value); + _ref2 = $$('textarea', dialog); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + ta = _ref2[_i]; + ta.textContent = conf[ta.name]; + $.bind(ta, 'change', $.cb.value); + } (back = $('[name=backlink]', dialog)).value = conf['backlink']; (time = $('[name=time]', dialog)).value = conf['time']; $.bind(back, 'keyup', options.backlink); $.bind(time, 'keyup', options.time); - _ref2 = $$('#keybinds input', dialog); - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - input = _ref2[_i]; + _ref3 = $$('#keybinds input', dialog); + for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) { + input = _ref3[_j]; input.type = 'text'; input.value = conf[input.name]; $.bind(input, 'keydown', options.keybind); @@ -3134,6 +3160,8 @@ }\ #content textarea {\ margin: 0;\ + min-height: 100px;\ + resize: vertical;\ width: 100%;\ }\ \ diff --git a/script.coffee b/script.coffee index 6b30170de..43cf7be14 100644 --- a/script.coffee +++ b/script.coffee @@ -44,6 +44,14 @@ config = 'Quote Inline': [true, 'Show quoted post inline on quote click'] 'Quote Preview': [true, 'Show quote content on hover'] 'Indicate OP quote': [true, 'Add \'(OP)\' to OP quotes'] + filter: + name: '' + trip: '' + mail: '' + sub: '' + com: '' + file: '' + md5: '' flavors: [ 'http://iqdb.org/?url=' 'http://google.com/searchbyimage?image_url=' @@ -813,6 +821,7 @@ options =
+ | | | | @@ -824,6 +833,18 @@ options =
+ +
+ Filters are case-insensitive. One filter per line.
+ You can use regular expressions, without opening and ending `/`, and without flags. +

Name:

+

Tripcode:

+

E-mail:

+

Subject:

+

Comment:

+

Filename:

+

Image MD5:

+
    @@ -891,9 +912,10 @@ options = $.bind $('button', li), 'click', options.clearHidden $.add $('ul:nth-child(2)', dialog), li - #sauce - (flavors = $ '#flavors', dialog).textContent = conf['flavors'] - $.bind flavors, 'change', $.cb.value + #filter & sauce + for ta in $$ 'textarea', dialog + ta.textContent = conf[ta.name] + $.bind ta, 'change', $.cb.value #rice (back = $ '[name=backlink]', dialog).value = conf['backlink'] @@ -2389,6 +2411,8 @@ Main = } #content textarea { margin: 0; + min-height: 100px; + resize: vertical; width: 100%; } From 60b5494f916127280056d272bdd6874a000c19dc Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 25 Sep 2011 18:56:45 +0200 Subject: [PATCH 3/9] Read & store RegExps --- 4chan_x.user.js | 23 ++++++++++++++++++++--- script.coffee | 15 +++++++++++++-- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 1a78e95e4..b5c7ed548 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -528,11 +528,28 @@ }; filter = { init: function() { - return HTMLBlockquoteElement.prototype.toString = function() { + var filter, filters, key, m, regx, _i, _len; + HTMLBlockquoteElement.prototype.toString = function() { return ($.el('span', { innerHTML: this.innerHTML.replace(/
    /g, '\n') })).textContent; }; + filters = {}; + for (key in config.filter) { + filters[key] = []; + if (!(m = conf[key].match(/(.+)/g))) { + continue; + } + for (_i = 0, _len = m.length; _i < _len; _i++) { + filter = m[_i]; + try { + if ((regx = eval(filter)).constructor === RegExp) { + filters[key].push(regx); + } + } catch (_e) {} + } + } + return log(filters); } }; expandComment = { @@ -1164,8 +1181,8 @@ \ \
    \ - Filters are case-insensitive. One filter per line.
    \ - You can use regular expressions, without opening and ending `/`, and without flags.\ + Use regular expressions, one per line.
    \ + For example, /weeaboo/i will filter posts containing `weeaboo` case-insensitive.\

    Name:

    \

    Tripcode:

    \

    E-mail:

    \ diff --git a/script.coffee b/script.coffee index 43cf7be14..3af106d67 100644 --- a/script.coffee +++ b/script.coffee @@ -388,6 +388,17 @@ filter = HTMLBlockquoteElement.prototype.toString = -> return ($.el 'span', innerHTML: @innerHTML.replace /
    /g, '\n').textContent + filters = {} + for key of config.filter + filters[key] = [] + unless m = conf[key].match /(.+)/g + continue + for filter in m + try if (regx = eval filter).constructor is RegExp + filters[key].push regx + + log filters + expandComment = init: -> for a in $$ 'span.abbr a' @@ -835,8 +846,8 @@ options =
    - Filters are case-insensitive. One filter per line.
    - You can use regular expressions, without opening and ending `/`, and without flags. + Use regular expressions, one per line.
    + For example, /weeaboo/i will filter posts containing `weeaboo` case-insensitive.

    Name:

    Tripcode:

    E-mail:

    From f9f620c3d03640813b77fea48cd9c9a89da18e78 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 25 Sep 2011 19:55:56 +0200 Subject: [PATCH 4/9] =?UTF-8?q?im=CB=88pro=CD=9Eovm=C9=99nt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 4chan_x.user.js | 4 ++-- script.coffee | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index b5c7ed548..155db3dff 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -530,16 +530,16 @@ init: function() { var filter, filters, key, m, regx, _i, _len; HTMLBlockquoteElement.prototype.toString = function() { - return ($.el('span', { + return ($.el('a', { innerHTML: this.innerHTML.replace(/
    /g, '\n') })).textContent; }; filters = {}; for (key in config.filter) { - filters[key] = []; if (!(m = conf[key].match(/(.+)/g))) { continue; } + filters[key] = []; for (_i = 0, _len = m.length; _i < _len; _i++) { filter = m[_i]; try { diff --git a/script.coffee b/script.coffee index 3af106d67..57fd1d2c3 100644 --- a/script.coffee +++ b/script.coffee @@ -386,13 +386,13 @@ $$ = (selector, root=d.body) -> filter = init: -> HTMLBlockquoteElement.prototype.toString = -> - return ($.el 'span', innerHTML: @innerHTML.replace /
    /g, '\n').textContent + return ($.el 'a', innerHTML: @innerHTML.replace /
    /g, '\n').textContent filters = {} for key of config.filter - filters[key] = [] unless m = conf[key].match /(.+)/g continue + filters[key] = [] for filter in m try if (regx = eval filter).constructor is RegExp filters[key].push regx From c0ceefcfad35d93f0b2766a2cb83818f581e779a Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 26 Sep 2011 01:40:22 +0200 Subject: [PATCH 5/9] Cache regular expressions, set up functions and selectors, only fire required functions. --- 4chan_x.user.js | 71 +++++++++++++++++++++++++++++++++++++++++++++---- script.coffee | 41 +++++++++++++++++++++++++--- 2 files changed, 103 insertions(+), 9 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 155db3dff..1a590ea26 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -527,29 +527,90 @@ return Array.prototype.slice.call(root.querySelectorAll(selector)); }; filter = { + regexps: {}, init: function() { - var filter, filters, key, m, regx, _i, _len; + var filter, key, m, regx, _i, _len, _results; HTMLBlockquoteElement.prototype.toString = function() { return ($.el('a', { innerHTML: this.innerHTML.replace(/
    /g, '\n') })).textContent; }; - filters = {}; + _results = []; for (key in config.filter) { if (!(m = conf[key].match(/(.+)/g))) { continue; } - filters[key] = []; + this.regexps[key] = []; for (_i = 0, _len = m.length; _i < _len; _i++) { filter = m[_i]; try { if ((regx = eval(filter)).constructor === RegExp) { - filters[key].push(regx); + this.regexps[key].push(regx); } } catch (_e) {} } + _results.push(this.regexps[key].length ? g.callbacks.push(this[key]) : void 0); } - return log(filters); + return _results; + }, + test: function(key, value) { + var regexp, _i, _len, _ref; + _ref = filter.regexps[key]; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + regexp = _ref[_i]; + if (regexp.test(value)) { + return true; + } + } + }, + name: function(root) { + var name; + if (!(name = root.className === 'op' ? $('.postername', root).textContent : $('.commentpostername', root).textContent)) { + return; + } + return filter.test('name', name); + }, + trip: function(root) { + var trip; + if (!(trip = $('.postertrip', root))) { + return; + } + return filter.test('trip', trip.textContent); + }, + mail: function(root) { + var mail; + if (!(mail = $('.linkmail', root))) { + return; + } + return filter.test('mail', mail.href); + }, + sub: function(root) { + var sub; + if (!(sub = root.className === 'op' ? $('.filetitle', root).textContent : $('.replytitle', root).textContent)) { + return; + } + return filter.test('sub', sub); + }, + com: function(root) { + var com; + if (!(com = $('blockquote', root).toString())) { + return; + } + return filter.test('com', com); + }, + file: function(root) { + var file; + if (!(file = $('.filesize span', root))) { + return; + } + return filter.test('file', file.title); + }, + md5: function(root) { + var img; + if (!(img = $('img[md5]', root))) { + return; + } + return filter.test('md5', img.getAttribute('md5')); } }; expandComment = { diff --git a/script.coffee b/script.coffee index 57fd1d2c3..a01f9e74d 100644 --- a/script.coffee +++ b/script.coffee @@ -384,20 +384,53 @@ $$ = (selector, root=d.body) -> Array::slice.call root.querySelectorAll selector filter = + regexps: {} init: -> HTMLBlockquoteElement.prototype.toString = -> return ($.el 'a', innerHTML: @innerHTML.replace /
    /g, '\n').textContent - filters = {} for key of config.filter unless m = conf[key].match /(.+)/g continue - filters[key] = [] + @regexps[key] = [] for filter in m try if (regx = eval filter).constructor is RegExp - filters[key].push regx + @regexps[key].push regx + #only execute what's filterable + g.callbacks.push @[key] if @regexps[key].length - log filters + test: (key, value) -> + for regexp in filter.regexps[key] + return true if regexp.test value + + name: (root) -> + unless (name = if root.className is 'op' then $('.postername', root).textContent else $('.commentpostername', root).textContent) + return + filter.test 'name', name + trip: (root) -> + unless trip = $('.postertrip', root) + return + filter.test 'trip', trip.textContent + mail: (root) -> + unless mail = $('.linkmail', root) + return + filter.test 'mail', mail.href + sub: (root) -> + unless(sub = if root.className is 'op' then $('.filetitle', root).textContent else $('.replytitle', root).textContent) + return + filter.test 'sub', sub + com: (root) -> + unless com = $('blockquote', root).toString() + return + filter.test 'com', com + file: (root) -> + unless file = $ '.filesize span', root + return + filter.test 'file', file.title + md5: (root) -> + unless img = $ 'img[md5]', root + return + filter.test 'md5', img.getAttribute('md5') expandComment = init: -> From d3276057290a7a293e456e5a460712ac58d99699 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 26 Sep 2011 03:29:01 +0200 Subject: [PATCH 6/9] And done! --- 4chan_x.user.js | 84 +++++++++++++++++++++++++++++++------------------ script.coffee | 64 ++++++++++++++++++++++--------------- 2 files changed, 92 insertions(+), 56 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 1a590ea26..6901d407c 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -78,6 +78,7 @@ Filtering: { 'Anonymize': [false, 'Make everybody anonymous'], 'Filter': [false, 'Self-moderation placebo'], + 'Filter OPs': [false, 'Filter OPs along with their threads'], 'Reply Hiding': [true, 'Hide single replies'], 'Thread Hiding': [true, 'Hide entire threads'], 'Show Stubs': [true, 'Of hidden threads / replies'] @@ -528,14 +529,14 @@ }; filter = { regexps: {}, + callbacks: [], init: function() { - var filter, key, m, regx, _i, _len, _results; + var filter, key, m, regx, _i, _len; HTMLBlockquoteElement.prototype.toString = function() { return ($.el('a', { innerHTML: this.innerHTML.replace(/
    /g, '\n') })).textContent; }; - _results = []; for (key in config.filter) { if (!(m = conf[key].match(/(.+)/g))) { continue; @@ -549,9 +550,35 @@ } } catch (_e) {} } - _results.push(this.regexps[key].length ? g.callbacks.push(this[key]) : void 0); + if (this.regexps[key].length) { + this.callbacks.push(this[key]); + } + } + return g.callbacks.push(this.node); + }, + node: function(root) { + var callback, _i, _j, _len, _len2, _ref, _ref2; + if (root.className === 'op') { + if (!g.REPLY && conf['Filter OPs']) { + _ref = filter.callbacks; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + callback = _ref[_i]; + if (callback(root)) { + threadHiding.hideHide(root.parentNode); + return; + } + } + } + } else if (!root.classList.contains('inline')) { + _ref2 = filter.callbacks; + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + callback = _ref2[_j]; + if (callback(root)) { + replyHiding.hideHide($('td:not([nowrap])', root)); + return; + } + } } - return _results; }, test: function(key, value) { var regexp, _i, _len, _ref; @@ -565,52 +592,45 @@ }, name: function(root) { var name; - if (!(name = root.className === 'op' ? $('.postername', root).textContent : $('.commentpostername', root).textContent)) { - return; + if ((name = root.className === 'op' ? $('.postername', root).textContent : $('.commentpostername', root).textContent)) { + return filter.test('name', name); } - return filter.test('name', name); }, trip: function(root) { var trip; - if (!(trip = $('.postertrip', root))) { - return; + if (trip = $('.postertrip', root)) { + return filter.test('trip', trip.textContent); } - return filter.test('trip', trip.textContent); }, mail: function(root) { var mail; - if (!(mail = $('.linkmail', root))) { - return; + if (mail = $('.linkmail', root)) { + return filter.test('mail', mail.href); } - return filter.test('mail', mail.href); }, sub: function(root) { var sub; - if (!(sub = root.className === 'op' ? $('.filetitle', root).textContent : $('.replytitle', root).textContent)) { - return; + if ((sub = root.className === 'op' ? $('.filetitle', root).textContent : $('.replytitle', root).textContent)) { + return filter.test('sub', sub); } - return filter.test('sub', sub); }, com: function(root) { var com; - if (!(com = $('blockquote', root).toString())) { - return; + if (com = $('blockquote', root).toString()) { + return filter.test('com', com); } - return filter.test('com', com); }, file: function(root) { var file; - if (!(file = $('.filesize span', root))) { - return; + if (file = $('.filesize span', root)) { + return filter.test('file', file.title); } - return filter.test('file', file.title); }, md5: function(root) { var img; - if (!(img = $('img[md5]', root))) { - return; + if (img = $('img[md5]', root)) { + return filter.test('md5', img.getAttribute('md5')); } - return filter.test('md5', img.getAttribute('md5')); } }; expandComment = { @@ -818,7 +838,14 @@ } }, hide: function(reply) { - var a, div, id, name, table, trip, _ref; + var id; + replyHiding.hideHide(reply); + id = reply.id; + g.hiddenReplies[id] = Date.now(); + return $.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies); + }, + hideHide: function(reply) { + var a, div, name, table, trip, _ref; table = reply.parentNode.parentNode.parentNode; table.hidden = true; if (conf['Show Stubs']) { @@ -832,11 +859,8 @@ className: 'stub' }); $.add(div, a); - $.before(table, div); + return $.before(table, div); } - id = reply.id; - g.hiddenReplies[id] = Date.now(); - return $.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies); }, show: function(table) { var id; diff --git a/script.coffee b/script.coffee index a01f9e74d..7db6ee694 100644 --- a/script.coffee +++ b/script.coffee @@ -12,6 +12,7 @@ config = Filtering: 'Anonymize': [false, 'Make everybody anonymous'] 'Filter': [false, 'Self-moderation placebo'] + 'Filter OPs': [false, 'Filter OPs along with their threads'] 'Reply Hiding': [true, 'Hide single replies'] 'Thread Hiding': [true, 'Hide entire threads'] 'Show Stubs': [true, 'Of hidden threads / replies'] @@ -385,6 +386,7 @@ $$ = (selector, root=d.body) -> filter = regexps: {} + callbacks: [] init: -> HTMLBlockquoteElement.prototype.toString = -> return ($.el 'a', innerHTML: @innerHTML.replace /
    /g, '\n').textContent @@ -397,40 +399,47 @@ filter = try if (regx = eval filter).constructor is RegExp @regexps[key].push regx #only execute what's filterable - g.callbacks.push @[key] if @regexps[key].length + @callbacks.push @[key] if @regexps[key].length + g.callbacks.push @node + + node: (root) -> + if root.className is 'op' + if !g.REPLY and conf['Filter OPs'] + for callback in filter.callbacks + if callback root + threadHiding.hideHide root.parentNode + return + else unless root.classList.contains('inline') + for callback in filter.callbacks + if callback root + replyHiding.hideHide $('td:not([nowrap])', root) + return test: (key, value) -> for regexp in filter.regexps[key] return true if regexp.test value name: (root) -> - unless (name = if root.className is 'op' then $('.postername', root).textContent else $('.commentpostername', root).textContent) - return - filter.test 'name', name + if (name = if root.className is 'op' then $('.postername', root).textContent else $('.commentpostername', root).textContent) + filter.test 'name', name trip: (root) -> - unless trip = $('.postertrip', root) - return - filter.test 'trip', trip.textContent + if trip = $('.postertrip', root) + filter.test 'trip', trip.textContent mail: (root) -> - unless mail = $('.linkmail', root) - return - filter.test 'mail', mail.href + if mail = $('.linkmail', root) + filter.test 'mail', mail.href sub: (root) -> - unless(sub = if root.className is 'op' then $('.filetitle', root).textContent else $('.replytitle', root).textContent) - return - filter.test 'sub', sub + if (sub = if root.className is 'op' then $('.filetitle', root).textContent else $('.replytitle', root).textContent) + filter.test 'sub', sub com: (root) -> - unless com = $('blockquote', root).toString() - return - filter.test 'com', com + if com = $('blockquote', root).toString() + filter.test 'com', com file: (root) -> - unless file = $ '.filesize span', root - return - filter.test 'file', file.title + if file = $ '.filesize span', root + filter.test 'file', file.title md5: (root) -> - unless img = $ 'img[md5]', root - return - filter.test 'md5', img.getAttribute('md5') + if img = $ 'img[md5]', root + filter.test 'md5', img.getAttribute('md5') expandComment = init: -> @@ -575,6 +584,13 @@ replyHiding = $.rm div hide: (reply) -> + replyHiding.hideHide reply + + id = reply.id + g.hiddenReplies[id] = Date.now() + $.set "hiddenReplies/#{g.BOARD}/", g.hiddenReplies + + hideHide: (reply) -> table = reply.parentNode.parentNode.parentNode table.hidden = true @@ -590,10 +606,6 @@ replyHiding = $.add div, a $.before table, div - id = reply.id - g.hiddenReplies[id] = Date.now() - $.set "hiddenReplies/#{g.BOARD}/", g.hiddenReplies - show: (table) -> table.hidden = false From 3066be24af73d37ee2b9ca5973eb680b52b0841b Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 26 Sep 2011 03:43:34 +0200 Subject: [PATCH 7/9] Changelog, less parentheses. --- changelog | 1 + script.coffee | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/changelog b/changelog index f6a862e9a..a22a7ac8c 100644 --- a/changelog +++ b/changelog @@ -3,6 +3,7 @@ master initiate 4chan X earlier automatically reload expanded pictures on error update /sci/ archive redirection + Regular expressions based filter 2.20.1 - mayhem diff --git a/script.coffee b/script.coffee index 7db6ee694..762a3c28a 100644 --- a/script.coffee +++ b/script.coffee @@ -410,10 +410,10 @@ filter = if callback root threadHiding.hideHide root.parentNode return - else unless root.classList.contains('inline') + else unless root.classList.contains 'inline' for callback in filter.callbacks if callback root - replyHiding.hideHide $('td:not([nowrap])', root) + replyHiding.hideHide $ 'td:not([nowrap])', root return test: (key, value) -> for regexp in filter.regexps[key] @@ -423,10 +423,10 @@ filter = if (name = if root.className is 'op' then $('.postername', root).textContent else $('.commentpostername', root).textContent) filter.test 'name', name trip: (root) -> - if trip = $('.postertrip', root) + if trip = $ '.postertrip', root filter.test 'trip', trip.textContent mail: (root) -> - if mail = $('.linkmail', root) + if mail = $ '.linkmail', root filter.test 'mail', mail.href sub: (root) -> if (sub = if root.className is 'op' then $('.filetitle', root).textContent else $('.replytitle', root).textContent) From baf5a4ec139a9eb616671b18959396c2a941efee Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 26 Sep 2011 12:29:47 +0200 Subject: [PATCH 8/9] Blockquotes are HTMLQuoteElements in the latest HTML5 specs. --- script.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/script.coffee b/script.coffee index 762a3c28a..28f9592e6 100644 --- a/script.coffee +++ b/script.coffee @@ -388,8 +388,12 @@ filter = regexps: {} callbacks: [] init: -> - HTMLBlockquoteElement.prototype.toString = -> + HTMLQuoteElement.prototype.toString = -> return ($.el 'a', innerHTML: @innerHTML.replace /
    /g, '\n').textContent + #to remove when both chrom, ff and oprah will define blockquotes as HTMLQuoteElement + if HTMLBlockquoteElement + HTMLBlockquoteElement.prototype.toString = -> + return ($.el 'a', innerHTML: @innerHTML.replace /
    /g, '\n').textContent for key of config.filter unless m = conf[key].match /(.+)/g From 5dcff904a8ac516b73c610b711f534a6e41bf4af Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Mon, 26 Sep 2011 22:03:56 +0200 Subject: [PATCH 9/9] Don't depend on prototype.toString() --- 4chan_x.user.js | 9 +++------ script.coffee | 9 +-------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 6901d407c..5736f1009 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -532,11 +532,6 @@ callbacks: [], init: function() { var filter, key, m, regx, _i, _len; - HTMLBlockquoteElement.prototype.toString = function() { - return ($.el('a', { - innerHTML: this.innerHTML.replace(/
    /g, '\n') - })).textContent; - }; for (key in config.filter) { if (!(m = conf[key].match(/(.+)/g))) { continue; @@ -616,7 +611,9 @@ }, com: function(root) { var com; - if (com = $('blockquote', root).toString()) { + if (com = ($.el('a', { + innerHTML: $('blockquote', root).innerHTML.replace(/
    /g, '\n') + })).textContent) { return filter.test('com', com); } }, diff --git a/script.coffee b/script.coffee index 28f9592e6..4e8427239 100644 --- a/script.coffee +++ b/script.coffee @@ -388,13 +388,6 @@ filter = regexps: {} callbacks: [] init: -> - HTMLQuoteElement.prototype.toString = -> - return ($.el 'a', innerHTML: @innerHTML.replace /
    /g, '\n').textContent - #to remove when both chrom, ff and oprah will define blockquotes as HTMLQuoteElement - if HTMLBlockquoteElement - HTMLBlockquoteElement.prototype.toString = -> - return ($.el 'a', innerHTML: @innerHTML.replace /
    /g, '\n').textContent - for key of config.filter unless m = conf[key].match /(.+)/g continue @@ -436,7 +429,7 @@ filter = if (sub = if root.className is 'op' then $('.filetitle', root).textContent else $('.replytitle', root).textContent) filter.test 'sub', sub com: (root) -> - if com = $('blockquote', root).toString() + if com = ($.el 'a', innerHTML: $('blockquote', root).innerHTML.replace /
    /g, '\n').textContent filter.test 'com', com file: (root) -> if file = $ '.filesize span', root