{"id":15294043,"url":"https://github.com/tktech/flask-themer","last_synced_at":"2025-04-13T13:56:56.606Z","repository":{"id":57430794,"uuid":"231855476","full_name":"TkTech/flask-themer","owner":"TkTech","description":"Simple flask theme support.","archived":false,"fork":false,"pushed_at":"2023-06-06T05:02:57.000Z","size":79,"stargazers_count":11,"open_issues_count":0,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-13T13:56:51.381Z","etag":null,"topics":["flask","themes"],"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/TkTech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"TkTech","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":"TkTech","issuehunt":null,"otechie":null,"custom":null}},"created_at":"2020-01-05T02:09:13.000Z","updated_at":"2024-08-06T14:28:38.000Z","dependencies_parsed_at":"2024-10-14T22:40:41.562Z","dependency_job_id":"c19a36bb-bcd6-426f-862d-d1f162ea1148","html_url":"https://github.com/TkTech/flask-themer","commit_stats":{"total_commits":34,"total_committers":1,"mean_commits":34.0,"dds":0.0,"last_synced_commit":"a35cc7ed2fd0ba4ea483028a49d9eca9b9ac8fab"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TkTech%2Fflask-themer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TkTech%2Fflask-themer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TkTech%2Fflask-themer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TkTech%2Fflask-themer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TkTech","download_url":"https://codeload.github.com/TkTech/flask-themer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248724587,"owners_count":21151559,"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":["flask","themes"],"created_at":"2024-09-30T16:56:04.652Z","updated_at":"2025-04-13T13:56:56.582Z","avatar_url":"https://github.com/TkTech.png","language":"Python","funding_links":["https://github.com/sponsors/TkTech","https://liberapay.com/TkTech"],"categories":[],"sub_categories":[],"readme":"![PyPI](https://img.shields.io/pypi/v/flask-themer?style=flat-square)\n![PyPI - License](https://img.shields.io/pypi/l/flask-themer?style=flat-square)\n![GitHub Workflow Status](https://img.shields.io/github/workflow/status/TkTech/flask-themer/Run%20tests?style=flat-square)\n\n\n# Flask-Themer\n\nSimple theme support for flask apps.\n\nFlask-Themer is inspired by the (seemingly) abandoned [flask-themes][] project,\nbut has been written from scratch for Python 3.8+. However, it is _not_ immediately\ncompatible with flask-themes and does not seek to be. Flask-Themer tries to have\nlittle opinion on how you actually structure your project and its themes and does\nnot require a particular metadata format/file.\n\nFlask-Themer releases follow [Semantic Versioning][semver].\nFlask-Themer has 100% test coverage and considers it an error to fall below\n100%.\n\n## Installation\n\nInstall the latest release from [PyPi][]:\n\n```\npip install flask-themer\n```\n\nor get the latest development version from GitHub:\n\n```\ngit clone https://github.com/TkTech/flask-themer.git\ncd flask-themer\npython setup.py develop\n```\n\n## Quickstart\n\n\nFlask-Themer usage is usually very basic, and once setup you likely won't need\nto touch it again. Let's do a quickstart. Notice how we import `render_template`\nfrom `flask_themer` instead of `flask`.\n\n\nOur `app.py` looks like this:\n\n```python\nfrom flask import Flask\nfrom flask_themer import Themer, render_template\n\napp = Flask(__name__)\nthemer = Themer(app)\n\n\n@themer.current_theme_loader\ndef get_current_theme():\n    # This is where you would look up the current user's theme if one was\n    # logged in, for example.\n    return 'default'\n\n@app.route('/')\ndef hello_world():\n    return render_template('hello.html')\n```\n\nAnd next to it we have a directory called `themes` with a directory called\n`default` inside of it. Our `themes/default/hello.html` looks like this:\n\n\n```jinja2\nHello world!\n```\n\nThat's it! By default Flask-Themer will look for a `themes` directory next to\nyour project and assume all the directories inside of it are themes. You can\nchange what directory it looks for with `THEMER_DEFAULT_DIRECTORY`, or specify\nthe template loaders explicitly to overwrite the default:\n\n```python\nfrom flask_themer import Themer, FileSystemThemeLoader\n\napp = Flask(__name__)\nthemer = Themer(app, loaders=[\n    FileSystemThemeLoader(app, os.path.join(\n        app.root_path,\n        'also_themes'\n    ))\n])\n```\n\n## Using Themes From Templates\n\nTwo template globals are added once Flask-Themer is setup, `theme()` and\n`theme_static()` (just like flask-themes). These methods look up the currently\nactive theme and look for the given path in that theme, returning a special\npath that Jinja can use to load it.\n\n```jinja2\n{% extends theme(\"base.html\") %}\n\n{% block header %}\n    {{ super() }}\n    \u003clink rel=\"stylesheet\" href=\"{{ theme_static(\"bootstrap.css\") }}\"\u003e\n{% endblock %}\n```\n\nThemes can also extend other themes using the `theme` argument:\n\n```jinja2\n{% extends theme(\"base.html\", theme=\"my_parent_theme\") %}\n```\n\n\n## Theme Loaders\n\n_Theme_ loaders are the mechanism by which Flask-Themer discovers what themes\nare available. You can create a custom loader to get themes from a ZIP file, or\na database for example. Usually if you create a new `ThemeLoader` you'll also\nneed to create a new Jinja [_template_ loader][loader] so Jinja knows how to\nread individual templates. Lets do a very minimal example that loads just a\nsingle theme from a ZIP file.\n\n\n```python\nfrom zipfile import ZipFile\nfrom flask_themer import ThemeLoader, Theme\nfrom jinja2.loaders import BaseLoader, TemplateNotFound\n\nclass ZipFileTemplateLoader(BaseLoader):\n    def __init__(self, *args, archive, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.archive = archive\n\n    def get_source(self, environment, template):\n        try:\n            return (self.archive.read(template), None, False)\n        except KeyError:\n            raise TemplateNotFound(template)\n\n\nclass ZipFileThemeLoader(ThemeLoader):\n    def __init__(self, path_to_zip):\n        self.archive = ZipFile(path_to_zip)\n\n    @property\n    def themes(self):\n        yield Theme(\n            name='my_dumb_theme',\n            theme_loader=self,\n            jinja_loader=ZipFileTemplateLoader(archive=self.archive),\n        )\n\n    def get_static(self, theme, path):\n        return self.archive.read(path)\n```\n\nAnd then to use our new loaders we update our previous example:\n\n```python\n...\nthemer = Themer(app, loaders=[\n    ZipFileThemeLoader('my_dumb_theme.zip')\n])\n...\n```\n\nPretty simple right? You can see how we could easily create a loader to load\nmultiple themes from an archive, or load a user's customized theme from a\ndatabase.\n\n[flask-themes]: https://github.com/maxcountryman/flask-themes\n[pypi]: https://pypi.org/\n[semver]: https://semver.org/\n[loader]: https://jinja.palletsprojects.com/en/latest/api/#loaders\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftktech%2Fflask-themer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftktech%2Fflask-themer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftktech%2Fflask-themer/lists"}