diff --git a/lib/elemHide.js b/lib/elemHide.js
a
|
b
|
|
142 | 142 | |
143 | 143 | /** |
144 | 144 | * Returns the list of selectors that apply on a given domain from the subset |
145 | 145 | * of filters that do not apply unconditionally on all domains. |
146 | 146 | * |
147 | 147 | * @param {string} domain The domain. |
148 | 148 | * @param {boolean} specificOnly Whether selectors from generic filters should |
149 | 149 | * be included. |
| 150 | * @param {boolean} [withExceptions=false] Whether exceptions should be |
| 151 | * included. |
150 | 152 | * |
151 | 153 | * @returns {Array.<string>} The list of selectors. |
152 | 154 | */ |
153 | | function getConditionalSelectors(domain, specificOnly) |
| 155 | function getConditionalSelectors(domain, specificOnly, withExceptions = false) |
154 | 156 | { |
155 | 157 | let selectors = []; |
| 158 | let exceptions = []; |
156 | 159 | |
157 | 160 | let excluded = new Set(); |
158 | 161 | let currentDomain = domain; |
159 | 162 | |
160 | 163 | // This code is a performance hot-spot, which is why we've made certain |
161 | 164 | // micro-optimisations. Please be careful before making changes. |
162 | 165 | while (true) |
163 | 166 | { |
… |
… |
|
171 | 174 | { |
172 | 175 | if (!isIncluded) |
173 | 176 | { |
174 | 177 | excluded.add(filter); |
175 | 178 | } |
176 | 179 | else |
177 | 180 | { |
178 | 181 | let {selector} = filter; |
179 | | if ((excluded.size == 0 || !excluded.has(filter)) && |
180 | | !ElemHideExceptions.getException(selector, domain)) |
| 182 | if (excluded.size == 0 || !excluded.has(filter)) |
181 | 183 | { |
182 | | selectors.push(selector); |
| 184 | let exception = ElemHideExceptions.getException(selector, domain); |
| 185 | if (!exception) |
| 186 | selectors.push(selector); |
| 187 | else if (withExceptions) |
| 188 | exceptions.push(exception); |
183 | 189 | } |
184 | 190 | } |
185 | 191 | } |
186 | 192 | } |
187 | 193 | |
188 | 194 | if (currentDomain == "") |
189 | 195 | break; |
190 | 196 | |
191 | 197 | let nextDot = currentDomain.indexOf("."); |
192 | 198 | currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1); |
193 | 199 | } |
194 | 200 | |
| 201 | if (withExceptions) |
| 202 | selectors.exceptions = exceptions; |
| 203 | |
195 | 204 | return selectors; |
196 | 205 | } |
197 | 206 | |
198 | 207 | /** |
199 | 208 | * Returns the default style sheet that applies on all domains. |
200 | 209 | * @returns {string} |
201 | 210 | */ |
202 | 211 | function getDefaultStyleSheet() |
… |
… |
|
355 | 364 | * Generates a style sheet for a given domain based on the current set of |
356 | 365 | * filters. |
357 | 366 | * |
358 | 367 | * @param {string} domain The domain. |
359 | 368 | * @param {boolean} [specificOnly=false] Whether selectors from generic |
360 | 369 | * filters should be included. |
361 | 370 | * @param {boolean} [includeSelectors=false] Whether the return value should |
362 | 371 | * include a separate list of selectors. |
| 372 | * @param {boolean} [withExceptions=false] Whether the selectors should |
| 373 | * include exceptions. Ignored if <code>includeSelectors</code> is |
| 374 | * <code>false</code>. |
363 | 375 | * |
364 | 376 | * @returns {ElemHideStyleSheet} An object containing the CSS code and the |
365 | 377 | * list of selectors. |
366 | 378 | */ |
367 | 379 | generateStyleSheetForDomain(domain, specificOnly = false, |
368 | | includeSelectors = false) |
| 380 | includeSelectors = false, withExceptions = false) |
369 | 381 | { |
370 | 382 | let code = null; |
371 | 383 | let selectors = null; |
372 | 384 | |
373 | 385 | if (domain[domain.length - 1] == ".") |
374 | 386 | domain = domain.replace(/\.+$/, ""); |
375 | 387 | |
376 | 388 | domain = domain.toLowerCase(); |
377 | 389 | |
378 | 390 | if (specificOnly) |
379 | 391 | { |
380 | | selectors = getConditionalSelectors(domain, true); |
| 392 | selectors = getConditionalSelectors(domain, true, |
| 393 | includeSelectors && withExceptions); |
381 | 394 | code = createStyleSheet(selectors); |
382 | 395 | } |
383 | 396 | else |
384 | 397 | { |
385 | 398 | let knownSuffix = getKnownSuffix(domain); |
386 | 399 | |
387 | 400 | if (includeSelectors) |
388 | 401 | { |
389 | | selectors = getConditionalSelectors(knownSuffix, false); |
| 402 | selectors = getConditionalSelectors(knownSuffix, false, withExceptions); |
390 | 403 | code = knownSuffix == "" ? getCommonStyleSheet() : |
391 | 404 | (getDefaultStyleSheet() + createStyleSheet(selectors)); |
392 | 405 | |
393 | 406 | selectors = getUnconditionalSelectors().concat(selectors); |
394 | 407 | } |
395 | 408 | else |
396 | 409 | { |
397 | 410 | code = knownSuffix == "" ? getCommonStyleSheet() : |