{"id":23977965,"url":"https://github.com/ertgl/clsx-py","last_synced_at":"2026-06-14T08:33:35.068Z","repository":{"id":253053833,"uuid":"842291260","full_name":"ertgl/clsx-py","owner":"ertgl","description":"Easily define conditional class attributes for HTML elements.","archived":false,"fork":false,"pushed_at":"2024-08-14T16:30:10.000Z","size":17,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-23T05:08:05.025Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ertgl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-14T03:54:36.000Z","updated_at":"2024-12-23T22:59:42.000Z","dependencies_parsed_at":"2025-01-01T12:11:29.292Z","dependency_job_id":"05b126c1-781c-4fe6-b9d6-35d8647d71e2","html_url":"https://github.com/ertgl/clsx-py","commit_stats":null,"previous_names":["ertgl/clsx","ertgl/clsx-py"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Fclsx-py","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Fclsx-py/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Fclsx-py/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Fclsx-py/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ertgl","download_url":"https://codeload.github.com/ertgl/clsx-py/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240540554,"owners_count":19817791,"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":"2025-01-07T08:15:48.862Z","updated_at":"2026-06-14T08:33:35.019Z","avatar_url":"https://github.com/ertgl.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# clsx\n\nEasily define conditional class attributes for HTML elements.\n\n## Motivation\n\nDefining conditional class attributes based on a state can be cumbersome and\nerror-prone with string concatenation. `clsx` provides a utility function to\nhandle this logic efficiently, bringing the popular idea from the JavaScript\necosystem to the Python ecosystem.\n\n## Installation\n\nThe package is available on PyPI and can be installed using `pip`.\n\n```bash\npip install clsx\n```\n\n## Usage\n\nThe `clsx` function takes any number of arguments and returns a string that can\nbe used as the value of the `class` attribute of an HTML element.\n\n```python\nfrom clsx import clsx\n\nclsx()                                        # \"\"\nclsx(\"\")                                      # \"\"\nclsx(\"foo\")                                   # \"foo\"\nclsx(\"foo foo\")                               # \"foo\"\nclsx(\"foo \\n\\t foo\")                          # \"foo\"\n\nclsx(\"foo\", None)                             # \"foo\"\nclsx(\"foo\", None, \"bar\")                      # \"foo bar\"\n\nclsx(\"foo\", None, \"bar\", None)                # \"foo bar\"\nclsx(\"foo\", None, \"bar\", None, \"baz\")         # \"foo bar baz\"\n\nclsx(\"foo\", False)                            # \"\"\nclsx(\"foo\", True)                             # \"foo\"\n\nclsx(\"foo\", \"bar\")                            # \"foo bar\"\nclsx(\"foo\", \"bar\", \"baz\")                     # \"foo bar baz\"\nclsx(\"foo\", \"bar\", \"baz\", \"qux\")              # \"foo bar baz qux\"\n\nclsx([\"foo\", \"bar\"])                          # \"foo bar\"\nclsx([\"foo\", \"bar\"], [\"baz\", \"qux\"])          # \"foo bar baz qux\"\nclsx([(\"foo\", True), (\"foo\", \"bar\", \"baz\")])  # \"foo bar baz\"\n\nclsx([\"foo foo\"], \"foo\", \"bar\")               # \"foo bar\"\nclsx(\"foo\", [\"foo\", \"bar\", \"baz\"])            # \"foo bar baz\"\n\nclsx({\"foo\": True, \"bar\": False})             # \"foo\"\nclsx({\"foo\": True, \"bar\": True})              # \"foo bar\"\nclsx({(lambda: \"foo\"): True})                 # \"foo\"\n\nclsx(lambda: [lambda: (\"foo\", True)])         # \"foo\"\n```\n\n### Low-level API\n\nThe core of the implementation is the methods in the `ExpressionEvaluator`\nclass. For each type of input, there is a corresponding method that evaluates\nthe input and returns an iterator of class names. These methods are designed to\nbe chained together to form the final iterable.\n\nFor optimal performance and memory consumption, `ExpressionEvaluator` consists\nof several `generator` methods that yield the class names one by one, as they\nare consumed. This allows the evaluation process to be done lazily, which is\nespecially useful when dealing with large/infinite and/or nested inputs. Since\nthe evaluation is done lazily, the both the CPU and memory usage are kept to a\nminimum.\n\n```python\nfrom clsx.evaluation import ExpressionEvaluator\n\noutput_stream = ExpressionEvaluator.evaluate(input_stream)\n```\n\n#### Modularity\n\nThe implementation supports on-the-fly modifications of class names out of the\nbox by its nature. For more complex use cases similar to deduplication,\n[CSS Modules](https://github.com/css-modules/css-modules) resolution or\nanything else, the low-level API can be extended by chaining the output\niterable with other `generator` functions. This allows for a modular design\nwhere each step of the evaluation process can be customized and extended\nindependently, with zero extra overhead.\n\nFor an example of how to extend the low-level API, see the `deduplication`\nsection below.\n\n#### Deduplication\n\nThe deduplication is always enabled when using the high-level API. However, when\nusing the low-level API, the deduplication must be done manually. This can be\nachieved by using the `dedup` function from the `clsx.contrib.itertools`\nmodule, which is a generator function that deduplicates the input stream without\nahead of planning or buffering. See the example below.\n\n```python\nfrom clsx.contrib.itertools import dedup\nfrom clsx.evaluation import ExpressionEvaluator\n\noutput_stream = ExpressionEvaluator.evaluate(input_stream)\ndeduplicated_output_stream = dedup(output_stream)\n```\n\n#### CSS Modules\n\nThe `CSS Modules` resolution is not supported out of the box, but can be\nachieved by modifying the output stream by chaining it with a custom generator\nfunction that resolves the class names. See the example below.\n\n```python\nfrom clsx.abc import ClassNameIterable\nfrom clsx.evaluation import ExpressionEvaluator\n\nSTYLES = {\"foo\": \"Zm9v\"}\n\ndef resolve_css_module_class_names(\n    iterable: ClassNameIterable,\n) -\u003e ClassNameIterable:\n    for class_name in iterable:\n        yield STYLES.get(class_name, class_name)\n\noutput_stream = ExpressionEvaluator.evaluate(input_stream)\nresolved_output_stream = resolve_css_module_class_names(output_stream)\n```\n\n## Inspiration\n\nThis project is inspired by the popular idea implemented and widely used in the\nJavaScript ecosystem. The name `clsx` is a positive nod to the project\n[clsx](https://github.com/lukeed/clsx) by [@lukeed](https://github.com/lukeed),\nwhich provides a similar functionality for JavaScript.\n\nThe name `clsx` in this project is used as a shorthand for \"class expression\"\nand it might be pronounced as \"classics\".\n\n## License\n\nThis project is licensed under the\n[MIT License](https://spdx.org/licenses/MIT.html).\n\nSee the [LICENSE](https://github.com/ertgl/clsx/blob/main/LICENSE) file\nfor more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fertgl%2Fclsx-py","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fertgl%2Fclsx-py","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fertgl%2Fclsx-py/lists"}