 Issue 29760699:
  Issue 6619 - Qualify CSS selectors in document style sheet correctly  (Closed) 
  Base URL: https://hg.adblockplus.org/adblockpluscore/
    
  
    Issue 29760699:
  Issue 6619 - Qualify CSS selectors in document style sheet correctly  (Closed) 
  Base URL: https://hg.adblockplus.org/adblockpluscore/| Left: | ||
| Right: | 
| OLD | NEW | 
|---|---|
| 1 /* | 1 /* | 
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 
| 3 * Copyright (C) 2006-present eyeo GmbH | 3 * Copyright (C) 2006-present eyeo GmbH | 
| 4 * | 4 * | 
| 5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify | 
| 6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as | 
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. | 
| 8 * | 8 * | 
| 9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, | 
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 start = i + 1; | 94 start = i + 1; | 
| 95 } | 95 } | 
| 96 } | 96 } | 
| 97 } | 97 } | 
| 98 | 98 | 
| 99 selectors.push(selector.substring(start)); | 99 selectors.push(selector.substring(start)); | 
| 100 return selectors; | 100 return selectors; | 
| 101 } | 101 } | 
| 102 | 102 | 
| 103 exports.splitSelector = splitSelector; | 103 exports.splitSelector = splitSelector; | 
| 104 | |
| 105 function findTargetSelectorIndex(selector) | |
| 106 { | |
| 107 let index = 0; | |
| 108 let whitespace = 0; | |
| 109 let scope = []; | |
| 110 | |
| 111 // Start from the end of the string and go character by character, where each | |
| 112 // character is a Unicode code point. | |
| 113 for (let character of [...selector].reverse()) | |
| 114 { | |
| 115 let currentScope = scope[scope.length - 1]; | |
| 116 | |
| 117 if (character == "'" || character == "\"") | |
| 118 { | |
| 119 // If we're already within the same type of quote, close the scope; | |
| 120 // otherwise open a new scope. | |
| 121 if (currentScope == character) | |
| 122 scope.pop(); | |
| 123 else | |
| 124 scope.push(character); | |
| 125 } | |
| 126 else if (character == "]" || character == ")") | |
| 127 { | |
| 128 // For closing brackets and parentheses, open a new scope only if we're | |
| 129 // not within a quote. Within quotes these characters should have no | |
| 130 // meaning. | |
| 131 if (currentScope != "'" && currentScope != "\"") | |
| 132 scope.push(character); | |
| 133 } | |
| 134 else if (character == "[") | |
| 135 { | |
| 136 // If we're already within a bracket, close the scope. | |
| 137 if (currentScope == "]") | |
| 138 scope.pop(); | |
| 139 } | |
| 140 else if (character == "(") | |
| 141 { | |
| 142 // If we're already within a parenthesis, close the scope. | |
| 143 if (currentScope == ")") | |
| 144 scope.pop(); | |
| 145 } | |
| 146 else if (!currentScope) | |
| 147 { | |
| 148 // At the top level (not within any scope), count the whitespace if we've | |
| 149 // encountered it. Otherwise if we've hit one of the combinators, | |
| 150 // terminate here; otherwise if we've hit a non-colon character, | |
| 151 // terminate here. | |
| 152 if (/\s/u.test(character)) | |
| 153 { | |
| 154 whitespace++; | |
| 155 } | |
| 156 else if ((character == ">" || character == "+" || character == "~") || | |
| 157 (whitespace > 0 && character != ":")) | |
| 158 { | |
| 159 break; | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 // Zero out the whitespace count if we've entered a scope. | |
| 164 if (scope.length > 0) | |
| 165 whitespace = 0; | |
| 166 | |
| 167 // Increment the index by the size of the character. Note that for Unicode | |
| 168 // composite characters (like emoji) this will be more than one. | |
| 169 index += character.length; | |
| 170 } | |
| 171 | |
| 172 return selector.length - index + whitespace; | |
| 173 } | |
| 174 | |
| 175 function qualifySelector(selector, qualifier) | |
| 
hub
2018/05/14 19:35:12
It would be nice to have a bit of documentation to
 
Manish Jethani
2018/05/15 12:03:58
Done.
 | |
| 176 { | |
| 177 let qualifiedSelector = ""; | |
| 178 | |
| 179 for (let sub of splitSelector(selector)) | |
| 180 { | |
| 181 sub = sub.trim(); | |
| 182 | |
| 183 qualifiedSelector += ", "; | |
| 184 | |
| 185 let index = findTargetSelectorIndex(sub); | |
| 186 let [, type = "", rest] = /^([a-z][a-z-]*)?(.*)/i.exec(sub.substr(index)); | |
| 187 | |
| 188 // Note that the first group in the regular expression is optional. If it | |
| 189 // doesn't match (e.g. "#foo::nth-child(1)"), type will be an empty string. | |
| 190 qualifiedSelector += sub.substr(0, index) + type + qualifier + rest; | |
| 191 } | |
| 192 | |
| 193 // Remove the initial comma and space. | |
| 194 return qualifiedSelector.substr(2); | |
| 195 } | |
| 196 | |
| 197 exports.qualifySelector = qualifySelector; | |
| OLD | NEW |