Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 "use strict"; | 1 "use strict"; |
2 | 2 |
3 let readline = require("readline"); | 3 let readline = require("readline"); |
4 let punycode = require("punycode"); | 4 let punycode = require("punycode"); |
5 let tldjs = require("tldjs"); | 5 let tldjs = require("tldjs"); |
6 let filterClasses = require("./adblockplus.js"); | 6 let filterClasses = require("./adblockplus.js"); |
7 | 7 |
8 let typeMap = filterClasses.RegExpFilter.typeMap; | 8 let typeMap = filterClasses.RegExpFilter.typeMap; |
9 | 9 |
10 const selectorLimit = 5000; | 10 const selectorLimit = 5000; |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 return true; | 247 return true; |
248 | 248 |
249 for (let name of Object.getOwnPropertyNames(obj)) | 249 for (let name of Object.getOwnPropertyNames(obj)) |
250 if (hasNonASCI(obj[name])) | 250 if (hasNonASCI(obj[name])) |
251 return true; | 251 return true; |
252 } | 252 } |
253 | 253 |
254 return false; | 254 return false; |
255 } | 255 } |
256 | 256 |
257 function convertIDSelectorsToAttributeSelectors(selector) | |
258 { | |
259 // First we figure out where all the IDs are | |
260 let sep = ""; | |
261 let start = null; | |
262 let positions = []; | |
263 for (let i = 0; i < selector.length; i++) | |
264 { | |
265 let chr = selector[i]; | |
266 | |
267 if (chr == "\\") // ignore escaped characters | |
268 i++; | |
269 else if (chr == sep) // don't match IDs within quoted text | |
270 sep = ""; // e.g. [attr="#Hello"] | |
271 else if (sep == "") | |
272 { | |
273 if (chr == '"' || chr == "'") | |
274 sep = chr; | |
275 else if (start == null) // look for the start of an ID | |
276 { | |
277 if (chr == "#") | |
278 start = i; | |
279 } | |
280 else if (chr != "-" && chr != "_" && | |
281 (chr < "0" || | |
282 chr > "9" && chr < "A" || | |
283 chr > "Z" && chr < "a" || | |
284 chr > "z" && chr < "\x80")) // look for the end of the ID | |
285 { | |
286 positions.push({start: start, end: i}); | |
287 start = null; | |
288 } | |
289 } | |
290 } | |
291 if (start != null) | |
292 positions.push({start: start, end: selector.length}); | |
293 | |
294 // Now replace them all with the [id="someID"] form | |
295 let newSelector = []; | |
296 let i = 0; | |
297 for (let pos of positions) | |
298 { | |
299 newSelector.push(selector.substring(i, pos.start)); | |
300 newSelector.push('[id=' + selector.substring(pos.start + 1, pos.end) + ']'); | |
301 i = pos.end; | |
302 } | |
303 newSelector.push(selector.substring(i)); | |
304 | |
305 return newSelector.join(""); | |
306 } | |
307 | |
257 function logRules() | 308 function logRules() |
258 { | 309 { |
259 let rules = []; | 310 let rules = []; |
260 | 311 |
261 function addRule(rule) | 312 function addRule(rule) |
262 { | 313 { |
263 if (!hasNonASCI(rule)) | 314 if (!hasNonASCI(rule)) |
264 rules.push(rule); | 315 rules.push(rule); |
265 } | 316 } |
266 | 317 |
(...skipping 13 matching lines...) Expand all Loading... | |
280 group.push(result.selector); | 331 group.push(result.selector); |
281 groupedElemhideFilters.set(matchDomain, group); | 332 groupedElemhideFilters.set(matchDomain, group); |
282 } | 333 } |
283 } | 334 } |
284 | 335 |
285 groupedElemhideFilters.forEach((selectors, matchDomain) => | 336 groupedElemhideFilters.forEach((selectors, matchDomain) => |
286 { | 337 { |
287 while (selectors.length) | 338 while (selectors.length) |
288 { | 339 { |
289 let selector = selectors.splice(0, selectorLimit).join(", "); | 340 let selector = selectors.splice(0, selectorLimit).join(", "); |
341 | |
342 // As of Safari 9.0 element IDs are matched as lowercase. We work around | |
343 // this by converting to the attribute format [id="elementID"] | |
344 selector = convertIDSelectorsToAttributeSelectors(selector); | |
345 | |
290 addRule({ | 346 addRule({ |
291 trigger: {"url-filter": matchDomain}, | 347 trigger: {"url-filter": matchDomain}, |
292 action: {type: "css-display-none", | 348 action: {type: "css-display-none", |
293 selector: selector} | 349 selector: selector} |
294 }); | 350 }); |
295 | |
296 // FIXME - Hack to work around WebKit bug whereby element IDs are | |
Sebastian Noack
2016/02/17 08:04:28
I feel that this won't be just a temporary workaro
kzar
2016/02/17 13:45:26
Done.
| |
297 // converted to lowercase before being matched. | |
298 let lowercaseSelector = selector.replace( | |
299 /#[\w-]+/g, match => match.toLowerCase() | |
Sebastian Noack
2016/02/17 08:04:28
ID selectors can have escaped special chars, e.g #
kzar
2016/02/17 13:45:26
Acknowledged.
| |
300 ); | |
301 if (lowercaseSelector != selector) | |
302 addRule({ | |
Sebastian Noack
2016/02/17 08:04:28
Ideally, we merge the lowercase variants with the
kzar
2016/02/17 13:45:26
Acknowledged.
| |
303 trigger: {"url-filter": matchDomain}, | |
304 action: {type: "css-display-none", | |
305 selector: lowercaseSelector} | |
306 }); | |
307 } | 351 } |
308 }); | 352 }); |
309 | 353 |
310 for (let filter of elemhideExceptions) | 354 for (let filter of elemhideExceptions) |
311 addRule(convertFilter(filter, "ignore-previous-rules", false)); | 355 addRule(convertFilter(filter, "ignore-previous-rules", false)); |
312 | 356 |
313 for (let filter of requestFilters) | 357 for (let filter of requestFilters) |
314 addRule(convertFilter(filter, "block", true)); | 358 addRule(convertFilter(filter, "block", true)); |
315 for (let filter of requestExceptions) | 359 for (let filter of requestExceptions) |
316 addRule(convertFilter(filter, "ignore-previous-rules", true)); | 360 addRule(convertFilter(filter, "ignore-previous-rules", true)); |
317 | 361 |
318 console.log(JSON.stringify(rules, null, "\t")); | 362 console.log(JSON.stringify(rules, null, "\t")); |
319 } | 363 } |
320 | 364 |
321 let rl = readline.createInterface({input: process.stdin, terminal: false}); | 365 let rl = readline.createInterface({input: process.stdin, terminal: false}); |
322 rl.on("line", parseFilter); | 366 rl.on("line", parseFilter); |
323 rl.on("close", logRules); | 367 rl.on("close", logRules); |
LEFT | RIGHT |