{"id":13611150,"url":"https://github.com/oyvindeh/ucss","last_synced_at":"2025-05-15T12:04:02.190Z","repository":{"id":4167731,"uuid":"5283216","full_name":"oyvindeh/ucss","owner":"oyvindeh","description":"Find unused and duplicate CSS","archived":false,"fork":false,"pushed_at":"2017-01-26T10:08:08.000Z","size":331,"stargazers_count":1619,"open_issues_count":3,"forks_count":63,"subscribers_count":76,"default_branch":"master","last_synced_at":"2025-04-14T19:59:36.962Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"apache/cloudstack","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oyvindeh.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-08-03T08:53:05.000Z","updated_at":"2025-03-04T11:10:22.000Z","dependencies_parsed_at":"2022-09-05T06:30:13.534Z","dependency_job_id":null,"html_url":"https://github.com/oyvindeh/ucss","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oyvindeh%2Fucss","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oyvindeh%2Fucss/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oyvindeh%2Fucss/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oyvindeh%2Fucss/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oyvindeh","download_url":"https://codeload.github.com/oyvindeh/ucss/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254248998,"owners_count":22039019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T19:01:52.261Z","updated_at":"2025-05-15T12:03:57.174Z","avatar_url":"https://github.com/oyvindeh.png","language":"JavaScript","readme":"## uCSS (beta)\nuCSS is made for crawling (large) websites to find unused CSS selectors.\n\n### Features\nFeatures of uCSS include:\n* Find unused CSS selectors, given a HTML code base.\n* Find duplicate CSS selectors (also when no HTML is given).\n* Count matches for each rule.\n* Follows links (crawl), within the given domain.\n* Give information about server responses, redirects, etc. while crawling, allowing you to find e.g. dead links.\n\nBy setting up a config file, uCSS can also:\n* Do login, and visit pages both as a logged in and logged out user.\n* Exclude specific pages and/or subfolders.\n* Visit specific pages instead of, or in addition to, crawling.\n* White list CSS rules to be ignored (e.g. those toggled by JavaScript).\n* Customizable output.\n\nuCSS is written for [Node](http://www.nodejs.org/). It can be used both as a\nlibrary and as a command line tool.\n\nWant to contribute? Please see at the bottom.\n\nPlease note: uCSS is currently in beta. There will be bugs, docs may be\noutdated, and functionality may change.\n\n#### What uCSS can't do\nuCSS does NOT:\n* Capture rules that are switched on using JavaScript after page load.\n* Look for style sheet URLs, internal style sheets, or inline styles in HTML\n  code.\n* Remove unused CSS. If you need to automatically strip away unused CSS from your favourite CSS library, you may find [UnCSS](https://github.com/giakki/uncss) helpful.\n\nThese features may, or may not, be added in the future.\n\n### Installation\n\n`npm install ucss -g`\n\nIf you use [Grunt](http://gruntjs.com/), check out [grunt-ucss](https://github.com/ullmark/grunt-ucss).\n\n### Usage (command line)\n\nFor basic usage, you can use the command line options:\n```\n$ ucss --help\nUsage: ucss [OPTION]...\n\nOptions:\n  --help            This help text.\n  --html, -h        HTML to load (local file or URL).\n  --css, -c         CSS to load (local file or URL).\n  --config, -g      Config file to use.\n  --full, -f        Show full report, with details for each rule.\n  --silent, -s      Only output list of rules. Nice if you need to pipe the output somewhere.\n  --duplicates, -d  Show duplicates. If only CSS is given, this is enabled by default.\n\nEither a config file or a CSS file is required. If no HTML is given, uCSS will only look for duplicate CSS.\nIf no arguments are specified, uCSS will assume there is a config_ucss.js file in the current directory.\n```\nSo, to check a web page you could write\n```\n$ ucss -h http://example.com/foo.html -c http://example.com/foo.css\n\nNote that if you use a selector both inside and outside a media query, it will\nbe counted as a duplicate.\n```\nTo output a full report, with all found selectors and an overview of duplicates\nand ignored ones, you can do:\n```\n$ ucss -f -h foo.html -c foo.css\n```\nAs you can see in the examples above, files can be stored locally as well as on\nthe web.\n\nTo use a config file (\"config_ucss.js\") that you have created in the current\nfolder, simply run\n```\n$ ucss\n```\nor specify another file name using the -g option. For more info on the config\nfile, see below.\n\nFor advanced usage, please see the sections about config files.\n\n### Usage (as library)\n\n```\n// css can be an array of strings, file paths, or URLs\nvar css = [\".foo {} .bar {} .baz {}\"];\n\n// html can be an array of strings, file paths, or URLs\nvar html = [\"\u003chtml\u003e\u003chead\u003e\u003c/head\u003e\u003cbody class='foo'\u003e\u003c/body\u003e\u003c/html\u003e\"];\n\nvar context = {\n    whitelist: [\".baz\"], // CSS selectors to ignore\n    auth: null, // For login (please se example elsewhere)\n    timeout: 400 // Request timeout (defaults to 400ms)\n};\nvar logger = null; // Function for logging HTTP requests\n\n// Do the magic\nucss.analyze(html, css, context, logger, function(result) {\n    // Do something to the result object\n    console.log(result);\n});\n```\n\n### Setting up a config file\nThere are several things you can do with a config file, that you cannot do with\ncommand line arguments.\n\nuCSS follows links by default. But there may be specific files, or whole\nsubfolders, that you don't want to check. These can be listed inside\npages.exclude. If you want to exclude a whole subfolder, use a wildcard (\"*\")\nat the end of the url (please see [example config\nfile](https://github.com/operasoftware/ucss/blob/master/examples/config_ucss.js)).\nYou may also use regular expressions.\n\nIn other cases, you may want to visit just a single file, or there are files that\nthe crawler cannot reach (e.g. because they are not linked to). Those can be\nadded to pages.include. Also, if you want to visit certain pages under an\nexcluded subfolder, you can add those to pages.include. Note that pages.include\ndoes not support wildcards, nor regular expressions.\n\nIn addition to managing what pages to visit (and not to visit), you can check\npages both as a regular visitor and as a logged in user. This is done by\nspecifying a function that performs a log in, and then returns a session cookie\nfor uCSS to use for identifying itself to the server. You can also set headers\nto send to the server.\n\nFurthermore, you can create a white list of selectors to be ignored. This is\nuseful if you e.g. have classes toggled by JavaScript, or if you have special\nstyling for various error situations that is tricky to trigger.\n\nAs well as checking several html files, uCSS can also combine CSS from several\nfiles. You can specify a list of CSS files in your config file.\n\nIf you name your config file \"config_ucss.js\", it will automatically be picked\nup by ucss. You can also name your config file something else, and use the -g\noption to point to it.\n\nAgain, please see the [example config\nfile](https://github.com/operasoftware/ucss/blob/master/examples/config_ucss.js).\nIf you want to write a custom login function, please see below.\n\n#### Logging in\nLogin requires you to set up a config file. In the config file, you can specify\nyour own login function:\n\n```\nmodule.exports = {\n    ...,\n    auth: {\n        \"username\": \"foo\",\n        \"password\": \"bar\",\n        \"loginUrl\": \"http://example.com/login/\",\n        \"loginFunc\": function(url, username, password, callback) {\n            // Do login, get cookie\n            var cookie = \"sessionid:1234\"\n            callback(cookie);\n        }\n    },\n   ...\n}\n\n```\nIf you use Django, you can use the supplied Django login helper (see [example\nconfig file](https://github.com/operasoftware/ucss/blob/master/examples/config_ucss.js)).\n\n### Understanding the output\nWhile crawling, uCSS will output all URLs it visits, with response status code.\nIf logged in, it will say so. It will also output a hash of the response body,\nwhich may be useful if you want to make sure that uCSS was successfully logged\nin (compare the hash of the logged in and the logged out visit).\n\nWhen the crawling is done, you will get a list of all unused selectors. If\nyou've asked for a list of duplicates, that will be printed as well.\n\nLastly, a summary will be printed. This contains the total amount of CSS\nselectors found, and how many used, unused and duplicates there were.\n\nUsing the --full option, you will get a more detailed and colorful output, with\nall rules being listed with number of matches, in addition to number of\nduplicates in CSS and details about ignored and whitelisted rules.\n\nIf the output doesn't suit your needs, and you know some JavaScript, you may\ncustomize it.\n\n### Customizable output\nYou can configure uCSS to do logging and handle the result differently from\nwhat's default. Do this by adding an \"output\" property in the config, which can\ncontain two functions, named \"logger\" and \"result\".\n\n```\nmodule.exports = {\n    ...,\n    \"output\": {\n        \"logger\": function(response, originalUrl, loggedIn) {\n            // Do some logging here, e.g. using console.log.\n        },\n        \"result\": function(result) {\n            // Do something with the result object, e.g. print every rule\n            // found, together with positions in CSS file:\n            for (var s in result.selectors) {\n                // Only unused rules:\n                if (result.selectors[s].matches_html === 0) {\n                    // Print position(s), given it's only one CSS file:\n                    var pos_css = result.selectors[s].pos_css;\n                    var key = Object.keys(pos_css)[0];\n                    console.log(s + \": \" + pos_css[key]);\n                }\n            }\n        }\n   },\n   ...\n}\n\n```\n\n#### Logging\nThe \"logger\" function is called every time there is a response to a HTTP\nrequest. It takes three parameters: \"res\" is a response object, as returned by\n[request](https://github.com/mikeal/request). \"originalUrl\" is a string that\npoints to the HTML instance being visited. \"loggedIn\" is a boolean that is true\nif uCSS has sent an authentication cookie in the request header.\n\nThis function is normally used for logging, but you can make it do whatever you\nwant. Just note that it is triggered by an event, so uCSS will not wait for it\nto return.\n\nSetting \"logger\" to null will silence logging.\n\n#### Result\nThe \"result\" function is called when uCSS is done. It recieves an object with\nthree properties: \"used\", \"duplicates\" and \"ignored\". \"used\" shows all CSS\nrules that has been matched in the HTML (including how many times).\n\"duplicates\" shows all duplicate CSS rules, including how many times they've\nbeen found. \"ignored\" shows all ignored rules.\n\nThis function can also whatever you want, e.g. write the result to a file.\n\n### Nice to know\n\n#### Some pages are not reachable by crawler\nSome pages are not accessible when crawling:\n* Pages that are only accessible by posting a form will not be checked. You may\nadd them to pages.include if they are reachable without posting data.\n* All parameters in links are normally stripped away when crawling, which may\nhave side effects for the rendering of some pages. If you want an URL to be\nvisited with specific parameters, you have to include it in pages.include.\n* When crawling, pages that are not linked to in other pages will not be\nchecked. You may add them to pages.include.\n* Style sheets are only fetched as a non-logged in user.\n\n\n#### At-rules\nAll at-rules are ignored, except @media: All the content inside media queries\nis read as if there were no media query.\n\n### I want to contribute!\n\nGreat! Feel free to pick one of the issues, or submit a bug/feature you would\nwant to work on.\n\nPlease be tidy in your commits. Also, try to touch as small parts of the code\nas possible. This makes it easier to review and manage pull requests. Make sure\nyour code is covered by tests, and write new ones if needed.\n\nIf you plan to do big changes or refactoring, please notify me first, so that\nwe can discuss this in advance.\n","funding_links":[],"categories":["JavaScript","Miscellaneous"],"sub_categories":["Meetups"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foyvindeh%2Fucss","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foyvindeh%2Fucss","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foyvindeh%2Fucss/lists"}