refreshcss


Namerefreshcss JSON
Version 0.5.1 PyPI version JSON
download
home_pagehttps://github.com/adamghill/refreshcss/
SummaryRemoves unused classes, ids, and element selectors from CSS.
upload_time2024-09-01 01:42:55
maintainerNone
docs_urlNone
authoradamghill
requires_python<4.0,>=3.10
licenseMIT
keywords django python css html
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # RefreshCSS 🫧

[![All Contributors](https://img.shields.io/github/all-contributors/adamghill/refreshcss?color=ee8449&style=flat-square)](#contributors)

`RefreshCSS` is a Python library that removes unused classes, ids, and element selectors from CSS.

> Make your CSS so fresh, so clean.

## πŸ”§ Installation

### To use the `refreshcss` library or use the `django-compressor` integration

`pip install refreshcss`

### To run `refreshcss` on the command-line

`pip install refreshcss[cli]`

## ⭐️ Features

- Pure Python (no extra NodeJS build process needed)
- Filters out unused classes, ids, elements from CSS based on HTML templates
- Handles Django/Jinja styles HTML templates
- Can be used as a filter with `django-compressor` to minify CSS as part of the `compress` management command
- Can be used via command-line interface in CI/CD

### ⌨️ Command-line interface

> Make sure that the `cli` extra is installed first: `pip install refreshcss[cli]`.

```sh
Usage: refreshcss [OPTIONS] CSS HTML...

  Remove classes, ids, and element selectors not used in HTML from CSS.

Options:
  -o, --output FILENAME  Write to file instead of stdout.
  -R, -r, --recursive    Recursively search subdirectories listed.
  --encoding TEXT        Character encoding to use when reading files. If not
                         specified, the encoding will be guessed.
  --version              Show the version and exit.
  --help                 Show this message and exit.
```

### πŸ—œοΈ Integrate with django-compressor

Add `"refreshcss.filters.RefreshCSSFilter"` to `COMPRESS_FILTERS` in the Django settings file.

```python
COMPRESS_FILTERS = {
    "css": [
        "refreshcss.filters.RefreshCSSFilter",
        ...
    ],
    "js": [...],
}
```

### βš™οΈ Library

```python
from refreshcss import RefreshCSS, PathSite

def clean_css(css_path: Path):
    # Parse the HTML files
    site = PathSite(paths=["templates"], recursive=True)
    site.parse()

    # Get clean CSS based on the parsed HTML
    css_text = css_path.read_text()
    cleaned_css = RefreshCSS(site).clean(css_text)

    return cleaned_css
```

## πŸ€“ How does it work?

1. Catalogue classes, ids, and elements that are currently being used in found HTML templates
1. Catalogue classes, ids, elements, and at-rules in a particular CSS stylesheet
1. Return new CSS stylesheet that only contains rules that are actively being used by the HTML

## 🧐 Why?

I wanted to have a filter for `django-compressor` that would purge unused CSS as part of the `compress` step when deploying for [`coltrane`](https://coltrane.readthedocs.io) apps. After dealing with a manual process and attempting to integrate https://purgecss.com and https://github.com/uncss/uncss I thought "this couldn't be that hard to do in Python".

Which is always the thought at the beginning of every side project... πŸ˜…

## πŸ™‹ FAQ

### Will this work with SPAs?

Probably not. `RefreshCSS` only inspects HTML templates, so if CSS classes are being changed client-side then `refreshcss` will not know about it.

### Does this work by crawling a website URL?

Currently no, although that is a possibility in the future. PRs appreciated. πŸ˜‰

### Does this support HTML written in the Django Template Language?

Yes! That was a primary reason I built my own solution. πŸ˜… Jinja might also be possible to support with some small tweaks, although it is currently untested.

### Is this what people mean when they say "treeshaking"?

Maybe. 🀷

### I found a bug!

Thanks for trying `RefreshCSS` out! Please make a PR (pull request) with a small test that replicates the bug or, if that is not possible, create a [new discussion](https://github.com/adamghill/refreshcss/discussions/new?category=ideas).

## 🀘 Related libraries

### Node

- [uncss](https://github.com/uncss/uncss)
- [PurgeCSS](https://purgecss.com/)

### Python

- [treeshake](https://pypi.org/project/treeshake/): I unfortunately could not get this to work on my local environment.
- [cssutils](https://pypi.org/project/cssutils/): This unfortunately seemed to choke on more modern CSS when I tested on Bulma 1.0.
- [css-optomizer](https://github.com/hamzaehsan97/CSS-optomizer)

## πŸ™ Thanks

- [Django](https://www.djangoproject.com)
- [django-compressor](https://django-compressor.readthedocs.io/)
- [CSS standards](https://www.w3.org/Style/CSS/)

## ❀️ Support

This project is supported by GitHub [Sponsors](https://github.com/sponsors/adamghill) and [Digital Ocean](https://m.do.co/c/617d629f56c0).

<p>
  <a href="https://m.do.co/c/617d629f56c0">
    <img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" width="201px">
  </a>
</p>

## πŸ₯³ Contributors

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tbody>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://git.boelz.eu/tmb/"><img src="https://avatars.githubusercontent.com/u/641522?v=4?s=100" width="100px;" alt="Tobias BΓΆlz"/><br /><sub><b>Tobias BΓΆlz</b></sub></a><br /><a href="#code-tobiasmboelz" title="Code">πŸ’»</a> <a href="#doc-tobiasmboelz" title="Documentation">πŸ“–</a> <a href="#test-tobiasmboelz" title="Tests">⚠️</a></td>
    </tr>
  </tbody>
</table>

<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/adamghill/refreshcss/",
    "name": "refreshcss",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.10",
    "maintainer_email": null,
    "keywords": "django, python, css, html",
    "author": "adamghill",
    "author_email": "adamghill@yahoo.com",
    "download_url": "https://files.pythonhosted.org/packages/b0/41/c3b701cce178cc01121351df5975faa29b37e6818127764b4990b21f504b/refreshcss-0.5.1.tar.gz",
    "platform": null,
    "description": "# RefreshCSS \ud83e\udee7\n\n[![All Contributors](https://img.shields.io/github/all-contributors/adamghill/refreshcss?color=ee8449&style=flat-square)](#contributors)\n\n`RefreshCSS` is a Python library that removes unused classes, ids, and element selectors from CSS.\n\n> Make your CSS so fresh, so clean.\n\n## \ud83d\udd27 Installation\n\n### To use the `refreshcss` library or use the `django-compressor` integration\n\n`pip install refreshcss`\n\n### To run `refreshcss` on the command-line\n\n`pip install refreshcss[cli]`\n\n## \u2b50\ufe0f Features\n\n- Pure Python (no extra NodeJS build process needed)\n- Filters out unused classes, ids, elements from CSS based on HTML templates\n- Handles Django/Jinja styles HTML templates\n- Can be used as a filter with `django-compressor` to minify CSS as part of the `compress` management command\n- Can be used via command-line interface in CI/CD\n\n### \u2328\ufe0f Command-line interface\n\n> Make sure that the `cli` extra is installed first: `pip install refreshcss[cli]`.\n\n```sh\nUsage: refreshcss [OPTIONS] CSS HTML...\n\n  Remove classes, ids, and element selectors not used in HTML from CSS.\n\nOptions:\n  -o, --output FILENAME  Write to file instead of stdout.\n  -R, -r, --recursive    Recursively search subdirectories listed.\n  --encoding TEXT        Character encoding to use when reading files. If not\n                         specified, the encoding will be guessed.\n  --version              Show the version and exit.\n  --help                 Show this message and exit.\n```\n\n### \ud83d\udddc\ufe0f Integrate with django-compressor\n\nAdd `\"refreshcss.filters.RefreshCSSFilter\"` to `COMPRESS_FILTERS` in the Django settings file.\n\n```python\nCOMPRESS_FILTERS = {\n    \"css\": [\n        \"refreshcss.filters.RefreshCSSFilter\",\n        ...\n    ],\n    \"js\": [...],\n}\n```\n\n### \u2699\ufe0f Library\n\n```python\nfrom refreshcss import RefreshCSS, PathSite\n\ndef clean_css(css_path: Path):\n    # Parse the HTML files\n    site = PathSite(paths=[\"templates\"], recursive=True)\n    site.parse()\n\n    # Get clean CSS based on the parsed HTML\n    css_text = css_path.read_text()\n    cleaned_css = RefreshCSS(site).clean(css_text)\n\n    return cleaned_css\n```\n\n## \ud83e\udd13 How does it work?\n\n1. Catalogue classes, ids, and elements that are currently being used in found HTML templates\n1. Catalogue classes, ids, elements, and at-rules in a particular CSS stylesheet\n1. Return new CSS stylesheet that only contains rules that are actively being used by the HTML\n\n## \ud83e\uddd0 Why?\n\nI wanted to have a filter for `django-compressor` that would purge unused CSS as part of the `compress` step when deploying for [`coltrane`](https://coltrane.readthedocs.io) apps. After dealing with a manual process and attempting to integrate https://purgecss.com and https://github.com/uncss/uncss I thought \"this couldn't be that hard to do in Python\".\n\nWhich is always the thought at the beginning of every side project... \ud83d\ude05\n\n## \ud83d\ude4b FAQ\n\n### Will this work with SPAs?\n\nProbably not. `RefreshCSS` only inspects HTML templates, so if CSS classes are being changed client-side then `refreshcss` will not know about it.\n\n### Does this work by crawling a website URL?\n\nCurrently no, although that is a possibility in the future. PRs appreciated. \ud83d\ude09\n\n### Does this support HTML written in the Django Template Language?\n\nYes! That was a primary reason I built my own solution. \ud83d\ude05 Jinja might also be possible to support with some small tweaks, although it is currently untested.\n\n### Is this what people mean when they say \"treeshaking\"?\n\nMaybe. \ud83e\udd37\n\n### I found a bug!\n\nThanks for trying `RefreshCSS` out! Please make a PR (pull request) with a small test that replicates the bug or, if that is not possible, create a [new discussion](https://github.com/adamghill/refreshcss/discussions/new?category=ideas).\n\n## \ud83e\udd18 Related libraries\n\n### Node\n\n- [uncss](https://github.com/uncss/uncss)\n- [PurgeCSS](https://purgecss.com/)\n\n### Python\n\n- [treeshake](https://pypi.org/project/treeshake/): I unfortunately could not get this to work on my local environment.\n- [cssutils](https://pypi.org/project/cssutils/): This unfortunately seemed to choke on more modern CSS when I tested on Bulma 1.0.\n- [css-optomizer](https://github.com/hamzaehsan97/CSS-optomizer)\n\n## \ud83d\ude4f Thanks\n\n- [Django](https://www.djangoproject.com)\n- [django-compressor](https://django-compressor.readthedocs.io/)\n- [CSS standards](https://www.w3.org/Style/CSS/)\n\n## \u2764\ufe0f Support\n\nThis project is supported by GitHub [Sponsors](https://github.com/sponsors/adamghill) and [Digital Ocean](https://m.do.co/c/617d629f56c0).\n\n<p>\n  <a href=\"https://m.do.co/c/617d629f56c0\">\n    <img src=\"https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg\" width=\"201px\">\n  </a>\n</p>\n\n## \ud83e\udd73 Contributors\n\n<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->\n<!-- prettier-ignore-start -->\n<!-- markdownlint-disable -->\n<table>\n  <tbody>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://git.boelz.eu/tmb/\"><img src=\"https://avatars.githubusercontent.com/u/641522?v=4?s=100\" width=\"100px;\" alt=\"Tobias B\u00f6lz\"/><br /><sub><b>Tobias B\u00f6lz</b></sub></a><br /><a href=\"#code-tobiasmboelz\" title=\"Code\">\ud83d\udcbb</a> <a href=\"#doc-tobiasmboelz\" title=\"Documentation\">\ud83d\udcd6</a> <a href=\"#test-tobiasmboelz\" title=\"Tests\">\u26a0\ufe0f</a></td>\n    </tr>\n  </tbody>\n</table>\n\n<!-- markdownlint-restore -->\n<!-- prettier-ignore-end -->\n\n<!-- ALL-CONTRIBUTORS-LIST:END -->\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Removes unused classes, ids, and element selectors from CSS.",
    "version": "0.5.1",
    "project_urls": {
        "Documentation": "https://github.com/adamghill/refreshcss/",
        "Funding": "https://github.com/sponsors/adamghill",
        "Homepage": "https://github.com/adamghill/refreshcss/",
        "Repository": "https://github.com/adamghill/refreshcss/"
    },
    "split_keywords": [
        "django",
        " python",
        " css",
        " html"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "56a432a5177f5d69362b7060d1b3a5e6cba1338503cca4b95f42c566a0c96030",
                "md5": "47d354173cf56a0eca7fc5db5228ba21",
                "sha256": "6048c156ab2f1cbd429eb273e158ebae41f32a5696eab7ee19efe6d9ce1c3de0"
            },
            "downloads": -1,
            "filename": "refreshcss-0.5.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "47d354173cf56a0eca7fc5db5228ba21",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.10",
            "size": 14389,
            "upload_time": "2024-09-01T01:42:54",
            "upload_time_iso_8601": "2024-09-01T01:42:54.657227Z",
            "url": "https://files.pythonhosted.org/packages/56/a4/32a5177f5d69362b7060d1b3a5e6cba1338503cca4b95f42c566a0c96030/refreshcss-0.5.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b041c3b701cce178cc01121351df5975faa29b37e6818127764b4990b21f504b",
                "md5": "80aa9c0a4a509a27b751503758cf9d4d",
                "sha256": "b81b2ce6b675f238ca89b0e946d5e0366a55f41535b5ae3d7691961d5e002b88"
            },
            "downloads": -1,
            "filename": "refreshcss-0.5.1.tar.gz",
            "has_sig": false,
            "md5_digest": "80aa9c0a4a509a27b751503758cf9d4d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.10",
            "size": 13895,
            "upload_time": "2024-09-01T01:42:55",
            "upload_time_iso_8601": "2024-09-01T01:42:55.646501Z",
            "url": "https://files.pythonhosted.org/packages/b0/41/c3b701cce178cc01121351df5975faa29b37e6818127764b4990b21f504b/refreshcss-0.5.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-01 01:42:55",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "adamghill",
    "github_project": "refreshcss",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "refreshcss"
}
        
Elapsed time: 1.92592s