├── .gitattributes ├── .gitignore ├── .jscsrc ├── LICENSE.md ├── README.md ├── index.js ├── package-lock.json ├── package.json └── test ├── assets ├── compound.in.html ├── compound.out.html ├── ignore.in.html ├── ignore.out.html ├── special-chars.in.html ├── special-chars.out.html ├── standard.in.html └── standard.out.html └── index.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto eol=lf 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git 28 | node_modules 29 | 30 | # ========================= 31 | # Operating System Files 32 | # ========================= 33 | 34 | # OSX 35 | # ========================= 36 | 37 | .DS_Store 38 | .AppleDouble 39 | .LSOverride 40 | 41 | # Thumbnails 42 | ._* 43 | 44 | # Files that might appear in the root of a volume 45 | .DocumentRevisions-V100 46 | .fseventsd 47 | .Spotlight-V100 48 | .TemporaryItems 49 | .Trashes 50 | .VolumeIcon.icns 51 | 52 | # Directories potentially created on remote AFP share 53 | .AppleDB 54 | .AppleDesktop 55 | Network Trash Folder 56 | Temporary Items 57 | .apdisk 58 | 59 | # Windows 60 | # ========================= 61 | 62 | # Windows image file caches 63 | Thumbs.db 64 | ehthumbs.db 65 | 66 | # Folder config file 67 | Desktop.ini 68 | 69 | # Recycle Bin used on file shares 70 | $RECYCLE.BIN/ 71 | 72 | # Windows Installer files 73 | *.cab 74 | *.msi 75 | *.msm 76 | *.msp 77 | 78 | # Windows shortcuts 79 | *.lnk 80 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "disallowKeywords": ["with"], 3 | "disallowKeywordsOnNewLine": ["else"], 4 | "disallowMixedSpacesAndTabs": true, 5 | "disallowMultipleVarDecl": "exceptUndefined", 6 | "disallowNewlineBeforeBlockStatements": true, 7 | "disallowQuotedKeysInObjects": true, 8 | "disallowSpaceAfterObjectKeys": true, 9 | "disallowSpaceAfterPrefixUnaryOperators": true, 10 | "disallowSpacesInFunction": { 11 | "beforeOpeningRoundBrace": true 12 | }, 13 | "disallowSpacesInsideParentheses": true, 14 | "disallowTrailingWhitespace": true, 15 | "maximumLineLength": 80, 16 | "requireCamelCaseOrUpperCaseIdentifiers": true, 17 | "requireCapitalizedComments": true, 18 | "requireCapitalizedConstructors": true, 19 | "requireCurlyBraces": true, 20 | "requireSpaceAfterKeywords": [ 21 | "if", 22 | "else", 23 | "for", 24 | "while", 25 | "do", 26 | "switch", 27 | "case", 28 | "return", 29 | "try", 30 | "catch", 31 | "typeof" 32 | ], 33 | "requireSpaceAfterLineComment": true, 34 | "requireSpaceAfterBinaryOperators": true, 35 | "requireSpaceBeforeBinaryOperators": true, 36 | "requireSpaceBeforeBlockStatements": true, 37 | "requireSpaceBeforeObjectValues": true, 38 | "requireSpacesInFunction": { 39 | "beforeOpeningCurlyBrace": true 40 | }, 41 | "requireTrailingComma": { 42 | "ignoreSingleLine": true 43 | }, 44 | "requireEarlyReturn": true, 45 | "validateIndentation": 2, 46 | "validateLineBreaks": "LF", 47 | "validateQuoteMarks": "'" 48 | } 49 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Vokal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # declassify 2 | 3 | Remove any classes or IDs not found in CSS from HTML - modifies HTML, not CSS. 4 | 5 | This only considers CSS contained in the HTML document inside ` 25 | 26 | 27 |
28 |
29 | 30 | 31 | ``` 32 | 33 | Output: 34 | 35 | ```html 36 | 37 | 38 | 42 | 43 | // has removed class="unused" 44 |
// has removed unused-class 45 |
46 | 47 | 48 | ``` 49 | 50 | ### Options 51 | 52 | ```js 53 | var declassify = require('declassify'); 54 | var options = { 55 | ignore: [ 56 | 'ignored-class', 57 | /ignored-regex-class\-[0-9]+/, 58 | 'ignored-id', 59 | /ignored-regex-id\-[0-9]+/ 60 | ], 61 | attrs: ['id', 'class'] 62 | }; 63 | var result = declassify.process(html, options); 64 | ``` 65 | 66 | Input: 67 | 68 | ```html 69 | 70 | 71 | 74 | 75 | 76 |
77 |
78 |
79 |
80 | 81 | 82 | ``` 83 | 84 | Output: 85 | 86 | ```html 87 | 88 | 89 | 92 | 93 | 94 |
95 |
96 |
97 |
98 | 99 | 100 | ``` 101 | 102 | There are some other methods exposed by the module which can be considered public and will be considered for versioning, but please see `index.js` if you think you might need to use any of them. 103 | 104 | 105 | ## MIT Licensed 106 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var cssom = require('cssom'); 4 | var cheerio = require('cheerio'); 5 | 6 | var declassify = {}; 7 | 8 | module.exports = declassify; 9 | var idRuleRegex = /(\#)(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)\b/g; 10 | var classRuleRegex = /(\.)(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)\b/g; 11 | 12 | var getRuleName = function(rule, selector) { 13 | var ruleNames = []; 14 | var matches; 15 | var selectorText = rule.selectorText; 16 | var ruleRegex = selector === 'id' ? idRuleRegex : classRuleRegex; 17 | 18 | while ((matches = ruleRegex.exec(selectorText)) !== null) { 19 | var i = 2; 20 | while (matches[i]) { 21 | ruleNames.push(matches[i]); 22 | i++; 23 | } 24 | } 25 | 26 | return ruleNames; 27 | }; 28 | 29 | var getRules = function(cssomRules, selector) { 30 | var result = []; 31 | for (var i = 0, l = cssomRules.length; i < l; i++) { 32 | var rule = cssomRules[i]; 33 | if (rule.selectorText) { 34 | var ruleName = getRuleName(rule, selector); 35 | ruleName.forEach(function(name) { 36 | result.push(name); 37 | }); 38 | } else if (rule.media && rule.cssRules) { 39 | result = result.concat(getRules(rule.cssRules, selector)); 40 | } 41 | } 42 | return result; 43 | }; 44 | 45 | declassify.getInUseAttr = function(css, selector) { 46 | var rules = cssom.parse(css).cssRules; 47 | 48 | if (!rules) { 49 | return []; 50 | } 51 | 52 | return getRules(rules, selector); 53 | }; 54 | 55 | declassify.pruneAttr = function(attrName, $, ignore) { 56 | var $items = $('[' + attrName + ']'); 57 | var css = []; 58 | $('style').each(function() { 59 | css.push($(this).text()); 60 | }); 61 | css = css.join('\n'); 62 | 63 | var inUse = declassify.getInUseAttr(css, attrName); 64 | 65 | $items.each(function() { 66 | var $item = $(this); 67 | if (!$item.attr(attrName)) { 68 | return; 69 | } 70 | 71 | var tokens = $item.attr(attrName).split(' '); 72 | for (var tokenIndex = tokens.length; tokenIndex >= 0; tokenIndex--) { 73 | var isIgnored = false; 74 | for (var ignoreIndex = ignore.length; ignoreIndex >= 0; ignoreIndex--) { 75 | if (ignore[ignoreIndex] instanceof RegExp && ignore[ignoreIndex].test(tokens[tokenIndex])) { 76 | isIgnored = true; 77 | } else if (ignore[ignoreIndex] === tokens[tokenIndex]) { 78 | isIgnored = true; 79 | } 80 | } 81 | 82 | if (inUse.indexOf(tokens[tokenIndex]) === -1 && !isIgnored) { 83 | tokens.splice(tokenIndex, 1); 84 | } 85 | }; 86 | 87 | if (tokens.length) { 88 | $item.attr(attrName, tokens.join(' ')); 89 | } else { 90 | $item.removeAttr(attrName); 91 | } 92 | }); 93 | }; 94 | 95 | declassify.pruneAttrs = function(attrNames, $, ignore) { 96 | attrNames.forEach(function(attr) { 97 | declassify.pruneAttr(attr, $, ignore); 98 | }); 99 | }; 100 | 101 | declassify.process = function(htmlInput, options) { 102 | if (options === void 0) options = {}; 103 | 104 | var $ = cheerio.load(htmlInput, {decodeEntities: false}); 105 | var ignore = options.ignore || []; 106 | var attrs = options.attrs || ['id', 'class']; 107 | declassify.pruneAttrs(attrs, $, ignore); 108 | return $.html({decodeEntities: false}); 109 | }; 110 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "declassify", 3 | "version": "1.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "boolbase": { 8 | "version": "1.0.0", 9 | "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", 10 | "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" 11 | }, 12 | "cheerio": { 13 | "version": "0.22.0", 14 | "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", 15 | "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", 16 | "requires": { 17 | "css-select": "1.2.0", 18 | "dom-serializer": "0.1.0", 19 | "entities": "1.1.1", 20 | "htmlparser2": "3.9.2", 21 | "lodash.assignin": "4.2.0", 22 | "lodash.bind": "4.2.1", 23 | "lodash.defaults": "4.2.0", 24 | "lodash.filter": "4.6.0", 25 | "lodash.flatten": "4.4.0", 26 | "lodash.foreach": "4.5.0", 27 | "lodash.map": "4.6.0", 28 | "lodash.merge": "4.6.0", 29 | "lodash.pick": "4.4.0", 30 | "lodash.reduce": "4.6.0", 31 | "lodash.reject": "4.6.0", 32 | "lodash.some": "4.6.0" 33 | } 34 | }, 35 | "commander": { 36 | "version": "2.3.0", 37 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", 38 | "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", 39 | "dev": true 40 | }, 41 | "core-util-is": { 42 | "version": "1.0.2", 43 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 44 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 45 | }, 46 | "css-select": { 47 | "version": "1.2.0", 48 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", 49 | "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", 50 | "requires": { 51 | "boolbase": "1.0.0", 52 | "css-what": "2.1.0", 53 | "domutils": "1.5.1", 54 | "nth-check": "1.0.1" 55 | } 56 | }, 57 | "css-what": { 58 | "version": "2.1.0", 59 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", 60 | "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=" 61 | }, 62 | "cssom": { 63 | "version": "0.3.2", 64 | "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz", 65 | "integrity": "sha1-uANhcMefB6kP8vFuIihAJ6JDhIs=" 66 | }, 67 | "debug": { 68 | "version": "2.2.0", 69 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 70 | "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", 71 | "dev": true, 72 | "requires": { 73 | "ms": "0.7.1" 74 | } 75 | }, 76 | "diff": { 77 | "version": "1.4.0", 78 | "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", 79 | "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", 80 | "dev": true 81 | }, 82 | "dom-serializer": { 83 | "version": "0.1.0", 84 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", 85 | "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", 86 | "requires": { 87 | "domelementtype": "1.1.3", 88 | "entities": "1.1.1" 89 | }, 90 | "dependencies": { 91 | "domelementtype": { 92 | "version": "1.1.3", 93 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", 94 | "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" 95 | } 96 | } 97 | }, 98 | "domelementtype": { 99 | "version": "1.3.0", 100 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", 101 | "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" 102 | }, 103 | "domhandler": { 104 | "version": "2.4.1", 105 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", 106 | "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", 107 | "requires": { 108 | "domelementtype": "1.3.0" 109 | } 110 | }, 111 | "domutils": { 112 | "version": "1.5.1", 113 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", 114 | "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", 115 | "requires": { 116 | "dom-serializer": "0.1.0", 117 | "domelementtype": "1.3.0" 118 | } 119 | }, 120 | "entities": { 121 | "version": "1.1.1", 122 | "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", 123 | "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" 124 | }, 125 | "escape-string-regexp": { 126 | "version": "1.0.2", 127 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", 128 | "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", 129 | "dev": true 130 | }, 131 | "glob": { 132 | "version": "3.2.11", 133 | "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", 134 | "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", 135 | "dev": true, 136 | "requires": { 137 | "inherits": "2.0.3", 138 | "minimatch": "0.3.0" 139 | } 140 | }, 141 | "growl": { 142 | "version": "1.9.2", 143 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 144 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", 145 | "dev": true 146 | }, 147 | "htmlparser2": { 148 | "version": "3.9.2", 149 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", 150 | "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", 151 | "requires": { 152 | "domelementtype": "1.3.0", 153 | "domhandler": "2.4.1", 154 | "domutils": "1.5.1", 155 | "entities": "1.1.1", 156 | "inherits": "2.0.3", 157 | "readable-stream": "2.3.3" 158 | } 159 | }, 160 | "inherits": { 161 | "version": "2.0.3", 162 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 163 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 164 | }, 165 | "isarray": { 166 | "version": "1.0.0", 167 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 168 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 169 | }, 170 | "jade": { 171 | "version": "0.26.3", 172 | "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", 173 | "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", 174 | "dev": true, 175 | "requires": { 176 | "commander": "0.6.1", 177 | "mkdirp": "0.3.0" 178 | }, 179 | "dependencies": { 180 | "commander": { 181 | "version": "0.6.1", 182 | "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", 183 | "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", 184 | "dev": true 185 | }, 186 | "mkdirp": { 187 | "version": "0.3.0", 188 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", 189 | "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", 190 | "dev": true 191 | } 192 | } 193 | }, 194 | "lodash.assignin": { 195 | "version": "4.2.0", 196 | "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", 197 | "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" 198 | }, 199 | "lodash.bind": { 200 | "version": "4.2.1", 201 | "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", 202 | "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" 203 | }, 204 | "lodash.defaults": { 205 | "version": "4.2.0", 206 | "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", 207 | "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" 208 | }, 209 | "lodash.filter": { 210 | "version": "4.6.0", 211 | "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", 212 | "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" 213 | }, 214 | "lodash.flatten": { 215 | "version": "4.4.0", 216 | "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", 217 | "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" 218 | }, 219 | "lodash.foreach": { 220 | "version": "4.5.0", 221 | "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", 222 | "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" 223 | }, 224 | "lodash.map": { 225 | "version": "4.6.0", 226 | "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", 227 | "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" 228 | }, 229 | "lodash.merge": { 230 | "version": "4.6.0", 231 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.0.tgz", 232 | "integrity": "sha1-aYhLoUSsM/5plzemCG3v+t0PicU=" 233 | }, 234 | "lodash.pick": { 235 | "version": "4.4.0", 236 | "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", 237 | "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" 238 | }, 239 | "lodash.reduce": { 240 | "version": "4.6.0", 241 | "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", 242 | "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" 243 | }, 244 | "lodash.reject": { 245 | "version": "4.6.0", 246 | "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", 247 | "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" 248 | }, 249 | "lodash.some": { 250 | "version": "4.6.0", 251 | "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", 252 | "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" 253 | }, 254 | "lru-cache": { 255 | "version": "2.7.3", 256 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", 257 | "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", 258 | "dev": true 259 | }, 260 | "minimatch": { 261 | "version": "0.3.0", 262 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", 263 | "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", 264 | "dev": true, 265 | "requires": { 266 | "lru-cache": "2.7.3", 267 | "sigmund": "1.0.1" 268 | } 269 | }, 270 | "minimist": { 271 | "version": "0.0.8", 272 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 273 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 274 | "dev": true 275 | }, 276 | "mkdirp": { 277 | "version": "0.5.1", 278 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 279 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 280 | "dev": true, 281 | "requires": { 282 | "minimist": "0.0.8" 283 | } 284 | }, 285 | "mocha": { 286 | "version": "2.5.3", 287 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", 288 | "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", 289 | "dev": true, 290 | "requires": { 291 | "commander": "2.3.0", 292 | "debug": "2.2.0", 293 | "diff": "1.4.0", 294 | "escape-string-regexp": "1.0.2", 295 | "glob": "3.2.11", 296 | "growl": "1.9.2", 297 | "jade": "0.26.3", 298 | "mkdirp": "0.5.1", 299 | "supports-color": "1.2.0", 300 | "to-iso-string": "0.0.2" 301 | } 302 | }, 303 | "ms": { 304 | "version": "0.7.1", 305 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 306 | "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", 307 | "dev": true 308 | }, 309 | "nth-check": { 310 | "version": "1.0.1", 311 | "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", 312 | "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", 313 | "requires": { 314 | "boolbase": "1.0.0" 315 | } 316 | }, 317 | "process-nextick-args": { 318 | "version": "1.0.7", 319 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 320 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" 321 | }, 322 | "readable-stream": { 323 | "version": "2.3.3", 324 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", 325 | "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", 326 | "requires": { 327 | "core-util-is": "1.0.2", 328 | "inherits": "2.0.3", 329 | "isarray": "1.0.0", 330 | "process-nextick-args": "1.0.7", 331 | "safe-buffer": "5.1.1", 332 | "string_decoder": "1.0.3", 333 | "util-deprecate": "1.0.2" 334 | } 335 | }, 336 | "safe-buffer": { 337 | "version": "5.1.1", 338 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 339 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 340 | }, 341 | "sigmund": { 342 | "version": "1.0.1", 343 | "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", 344 | "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", 345 | "dev": true 346 | }, 347 | "string_decoder": { 348 | "version": "1.0.3", 349 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 350 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 351 | "requires": { 352 | "safe-buffer": "5.1.1" 353 | } 354 | }, 355 | "supports-color": { 356 | "version": "1.2.0", 357 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", 358 | "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", 359 | "dev": true 360 | }, 361 | "to-iso-string": { 362 | "version": "0.0.2", 363 | "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", 364 | "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", 365 | "dev": true 366 | }, 367 | "util-deprecate": { 368 | "version": "1.0.2", 369 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 370 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 371 | } 372 | } 373 | } 374 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "declassify", 3 | "version": "2.1.0", 4 | "description": "Remove any classes or IDs not found in CSS from HTML - modifies HTML, not CSS.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha --reporter spec", 8 | "testcover": "istanbul cover node_modules/mocha/bin/_mocha -- -R spec" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/jrit/declassify.git" 13 | }, 14 | "keywords": [ 15 | "HTML", 16 | "CSS", 17 | "clean", 18 | "process" 19 | ], 20 | "author": "Vokal", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/jrit/declassify/issues" 24 | }, 25 | "homepage": "https://github.com/jrit/declassify#readme", 26 | "dependencies": { 27 | "cheerio": "^0.22.0", 28 | "cssom": "^0.3.2" 29 | }, 30 | "devDependencies": { 31 | "mocha": "^2.3.4" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/assets/compound.in.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 |
Foo
21 |
bar
22 |
23 | 24 | Bar 25 | 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /test/assets/compound.out.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 |
Foo
21 |
bar
22 |
23 | 24 | Bar 25 | 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /test/assets/ignore.in.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 |
9 |
10 |
11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/assets/ignore.out.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 |
9 |
10 |
11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/assets/special-chars.in.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 |
15 |
16 | I should be red by default. 17 |
18 |
19 |
20 | Special Characters here: 21 |
22 | Declassify's a great tool. 23 |
24 |
25 | < Hey > & "'" 26 |
27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /test/assets/special-chars.out.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 |
15 |
16 | I should be red by default. 17 |
18 |
19 |
20 | Special Characters here: 21 |
22 | Declassify's a great tool. 23 |
24 |
25 | < Hey > & "'" 26 |
27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /test/assets/standard.in.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 |
15 |
16 |
17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /test/assets/standard.out.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 |
15 |
16 |
17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var declassify = require('../'); 4 | var assert = require('assert'); 5 | var fs = require('fs'); 6 | var path = require('path'); 7 | 8 | 9 | it('processes the HTML', function() { 10 | var input = fs.readFileSync( 11 | path.join(__dirname, 'assets', 'standard.in.html'), 'utf8'); 12 | 13 | var expected = fs.readFileSync( 14 | path.join(__dirname, 'assets', 'standard.out.html'), 'utf8'); 15 | 16 | var result = declassify.process(input); 17 | 18 | assert.equal(result, expected); 19 | }); 20 | 21 | it('processes the HTML with compound rules', function() { 22 | var input = fs.readFileSync( 23 | path.join(__dirname, 'assets', 'compound.in.html'), 'utf8'); 24 | 25 | var expected = fs.readFileSync( 26 | path.join(__dirname, 'assets', 'compound.out.html'), 'utf8'); 27 | 28 | var result = declassify.process(input); 29 | 30 | assert.equal(result, expected); 31 | }); 32 | 33 | it('processes the HTML and ignores given rules', function() { 34 | var input = fs.readFileSync( 35 | path.join(__dirname, 'assets', 'ignore.in.html'), 'utf8'); 36 | 37 | var expected = fs.readFileSync( 38 | path.join(__dirname, 'assets', 'ignore.out.html'), 'utf8'); 39 | 40 | var result = declassify.process(input, { 41 | ignore: [ 42 | 'ignored-class', 43 | /ignored-regex-class\-[0-9]+/, 44 | 'ignored-id', 45 | /ignored-regex-id\-[0-9]+/ 46 | ] 47 | }); 48 | }); 49 | 50 | it('processes the HTML with quote marks', function() { 51 | var input = fs.readFileSync( 52 | path.join(__dirname, 'assets', 'special-chars.in.html'), 'utf8'); 53 | 54 | var expected = fs.readFileSync( 55 | path.join(__dirname, 'assets', 'special-chars.out.html'), 'utf8'); 56 | 57 | var result = declassify.process(input); 58 | 59 | assert.equal(result, expected); 60 | }); 61 | --------------------------------------------------------------------------------