├── .coveragerc ├── .github ├── labels.yml ├── release-drafter.yml ├── renovate.json └── workflows │ ├── deploy.yml │ ├── labels.yml │ ├── lint.yml │ ├── release-drafter.yml │ ├── require-pr-label.yml │ └── test.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .yamlfmt.yaml ├── .zenodo.json ├── LICENSE.txt ├── README.md ├── RELEASING.md ├── codecov.yml ├── pyproject.toml ├── requirements-mypy.txt ├── requirements.txt ├── src └── tinytext │ ├── __init__.py │ ├── __main__.py │ └── cli.py ├── tests ├── __init__.py └── test_tinytext.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | # .coveragerc to control coverage.py 2 | 3 | [report] 4 | # Regexes for lines to exclude from consideration 5 | exclude_also = 6 | # Don't complain if non-runnable code isn't run: 7 | if __name__ == .__main__.: 8 | if TYPE_CHECKING: 9 | 10 | [run] 11 | disable_warnings = 12 | no-sysmon 13 | omit = 14 | **/tinytext/__main__.py 15 | **/tinytext/cli.py 16 | -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | # Keep a Changelog labels 2 | # https://keepachangelog.com/en/1.0.0/ 3 | - color: 0e8a16 4 | description: "For new features" 5 | name: "changelog: Added" 6 | - color: af99e5 7 | description: "For changes in existing functionality" 8 | name: "changelog: Changed" 9 | - color: FFA500 10 | description: "For soon-to-be removed features" 11 | name: "changelog: Deprecated" 12 | - color: 00A800 13 | description: "For any bug fixes" 14 | name: "changelog: Fixed" 15 | - color: ff0000 16 | description: "For now removed features" 17 | name: "changelog: Removed" 18 | - color: 045aa0 19 | description: "In case of vulnerabilities" 20 | name: "changelog: Security" 21 | - color: fbca04 22 | description: "Exclude PR from release draft" 23 | name: "changelog: skip" 24 | 25 | # Other labels 26 | - color: 0366d6 27 | description: "For dependencies" 28 | name: dependencies 29 | - color: f4660e 30 | description: "" 31 | name: Hacktoberfest 32 | - color: f4660e 33 | description: "To credit accepted Hacktoberfest PRs" 34 | name: hacktoberfest-accepted 35 | - color: d65e88 36 | description: "Deploy and release" 37 | name: release 38 | - color: fbca04 39 | description: "Unit tests, linting, CI, etc." 40 | name: testing 41 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: "Release $RESOLVED_VERSION" 2 | tag-template: "$RESOLVED_VERSION" 3 | 4 | categories: 5 | - title: "Added" 6 | labels: 7 | - "changelog: Added" 8 | - "enhancement" 9 | - title: "Changed" 10 | label: "changelog: Changed" 11 | - title: "Deprecated" 12 | label: "changelog: Deprecated" 13 | - title: "Removed" 14 | label: "changelog: Removed" 15 | - title: "Fixed" 16 | labels: 17 | - "changelog: Fixed" 18 | - "bug" 19 | - title: "Security" 20 | label: "changelog: Security" 21 | 22 | exclude-labels: 23 | - "changelog: skip" 24 | 25 | autolabeler: 26 | - label: "changelog: skip" 27 | branch: 28 | - "/pre-commit-ci-update-config/" 29 | 30 | template: | 31 | $CHANGES 32 | 33 | version-resolver: 34 | major: 35 | labels: 36 | - "changelog: Removed" 37 | minor: 38 | labels: 39 | - "changelog: Added" 40 | - "changelog: Changed" 41 | - "changelog: Deprecated" 42 | - "enhancement" 43 | 44 | patch: 45 | labels: 46 | - "changelog: Fixed" 47 | - "bug" 48 | default: minor 49 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base", ":semanticCommitsDisabled"], 4 | "labels": ["changelog: skip", "dependencies"], 5 | "packageRules": [ 6 | { 7 | "groupName": "github-actions", 8 | "matchManagers": ["github-actions"], 9 | "separateMajorMinor": "false" 10 | } 11 | ], 12 | "schedule": ["on the first day of the month"] 13 | } 14 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | tags: ["*"] 7 | pull_request: 8 | branches: [main] 9 | release: 10 | types: 11 | - published 12 | workflow_dispatch: 13 | 14 | permissions: {} 15 | 16 | env: 17 | FORCE_COLOR: 1 18 | 19 | jobs: 20 | # Always build & lint package. 21 | build-package: 22 | name: Build & verify package 23 | runs-on: ubuntu-latest 24 | 25 | steps: 26 | - uses: actions/checkout@v4 27 | with: 28 | fetch-depth: 0 29 | persist-credentials: false 30 | 31 | - uses: hynek/build-and-inspect-python-package@v2 32 | 33 | # Upload to Test PyPI on every commit on main. 34 | release-test-pypi: 35 | name: Publish in-dev package to test.pypi.org 36 | if: | 37 | github.event.repository.fork == false 38 | && github.event_name == 'push' 39 | && github.ref == 'refs/heads/main' 40 | runs-on: ubuntu-latest 41 | needs: build-package 42 | 43 | permissions: 44 | id-token: write 45 | 46 | steps: 47 | - name: Download packages built by build-and-inspect-python-package 48 | uses: actions/download-artifact@v4 49 | with: 50 | name: Packages 51 | path: dist 52 | 53 | - name: Upload package to Test PyPI 54 | uses: pypa/gh-action-pypi-publish@release/v1 55 | with: 56 | repository-url: https://test.pypi.org/legacy/ 57 | 58 | # Upload to real PyPI on GitHub Releases. 59 | release-pypi: 60 | name: Publish released package to pypi.org 61 | if: | 62 | github.event.repository.fork == false 63 | && github.event.action == 'published' 64 | runs-on: ubuntu-latest 65 | needs: build-package 66 | 67 | permissions: 68 | id-token: write 69 | 70 | steps: 71 | - name: Download packages built by build-and-inspect-python-package 72 | uses: actions/download-artifact@v4 73 | with: 74 | name: Packages 75 | path: dist 76 | 77 | - name: Upload package to PyPI 78 | uses: pypa/gh-action-pypi-publish@release/v1 79 | -------------------------------------------------------------------------------- /.github/workflows/labels.yml: -------------------------------------------------------------------------------- 1 | name: Sync labels 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - .github/labels.yml 9 | workflow_dispatch: 10 | 11 | jobs: 12 | sync: 13 | permissions: 14 | pull-requests: write 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | with: 19 | persist-credentials: false 20 | - uses: micnncim/action-label-syncer@v1 21 | with: 22 | prune: false 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | permissions: {} 6 | 7 | env: 8 | FORCE_COLOR: 1 9 | RUFF_OUTPUT_FORMAT: github 10 | 11 | jobs: 12 | lint: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | persist-credentials: false 19 | - uses: actions/setup-python@v5 20 | with: 21 | python-version: "3.x" 22 | - uses: tox-dev/action-pre-commit-uv@v1 23 | 24 | mypy: 25 | runs-on: ubuntu-latest 26 | 27 | steps: 28 | - uses: actions/checkout@v4 29 | with: 30 | persist-credentials: false 31 | - uses: actions/setup-python@v5 32 | with: 33 | python-version: "3.x" 34 | - name: Install uv 35 | uses: astral-sh/setup-uv@v6 36 | - name: Mypy 37 | run: uvx --with tox-uv tox -e mypy 38 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release drafter 2 | 3 | on: 4 | push: 5 | # branches to consider in the event; optional, defaults to all 6 | branches: 7 | - main 8 | # pull_request event is required only for autolabeler 9 | pull_request: 10 | # Only following types are handled by the action, but one can default to all as well 11 | types: [opened, reopened, synchronize] 12 | # pull_request_target event is required for autolabeler to support PRs from forks 13 | # pull_request_target: 14 | # types: [opened, reopened, synchronize] 15 | workflow_dispatch: 16 | 17 | jobs: 18 | update_release_draft: 19 | if: github.event.repository.fork == false 20 | permissions: 21 | # write permission is required to create a GitHub Release 22 | contents: write 23 | # write permission is required for autolabeler 24 | # otherwise, read permission is required at least 25 | pull-requests: write 26 | runs-on: ubuntu-latest 27 | steps: 28 | # Drafts your next release notes as pull requests are merged into "main" 29 | - uses: release-drafter/release-drafter@v6 30 | env: 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | -------------------------------------------------------------------------------- /.github/workflows/require-pr-label.yml: -------------------------------------------------------------------------------- 1 | name: Require PR label 2 | 3 | on: 4 | pull_request: 5 | types: [opened, reopened, labeled, unlabeled, synchronize] 6 | 7 | jobs: 8 | label: 9 | runs-on: ubuntu-latest 10 | 11 | permissions: 12 | issues: write 13 | pull-requests: write 14 | 15 | steps: 16 | - uses: mheap/github-action-required-labels@v5 17 | with: 18 | mode: minimum 19 | count: 1 20 | labels: | 21 | changelog: Added 22 | changelog: Changed 23 | changelog: Deprecated 24 | changelog: Fixed 25 | changelog: Removed 26 | changelog: Security 27 | changelog: skip 28 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | permissions: {} 6 | 7 | env: 8 | FORCE_COLOR: 1 9 | PIP_DISABLE_PIP_VERSION_CHECK: 1 10 | 11 | jobs: 12 | test: 13 | runs-on: ${{ matrix.os }} 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | python-version: 18 | - "pypy3.11" 19 | - "3.14t" 20 | - "3.14" 21 | - "3.13t" 22 | - "3.13" 23 | - "3.12" 24 | - "3.11" 25 | - "3.10" 26 | - "3.9" 27 | os: [windows-latest, macos-latest, ubuntu-latest] 28 | 29 | steps: 30 | - uses: actions/checkout@v4 31 | with: 32 | persist-credentials: false 33 | 34 | - name: Set up Python ${{ matrix.python-version }} 35 | uses: actions/setup-python@v5 36 | with: 37 | python-version: ${{ matrix.python-version }} 38 | allow-prereleases: true 39 | 40 | - name: Set PYTHON_GIL 41 | if: endsWith(matrix.python-version, 't') 42 | run: | 43 | echo "PYTHON_GIL=0" >> "$GITHUB_ENV" 44 | 45 | - name: Install uv 46 | uses: astral-sh/setup-uv@v6 47 | 48 | - name: Tox tests 49 | run: | 50 | uvx --python ${{ matrix.python-version }} --with tox-uv tox -e py 51 | 52 | - name: Test CLI 53 | run: | 54 | uvx --python ${{ matrix.python-version }} --with tox-uv tox -e cli 55 | 56 | - name: Upload coverage 57 | uses: codecov/codecov-action@v5 58 | with: 59 | flags: ${{ matrix.os }} 60 | name: ${{ matrix.os }} Python ${{ matrix.python-version }} 61 | 62 | success: 63 | needs: test 64 | runs-on: ubuntu-latest 65 | name: Test successful 66 | steps: 67 | - name: Success 68 | run: echo Test successful 69 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | .idea/ 161 | 162 | # hatch-vcs 163 | src/*/_version.py 164 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/astral-sh/ruff-pre-commit 3 | rev: v0.11.6 4 | hooks: 5 | - id: ruff 6 | args: [--exit-non-zero-on-fix] 7 | 8 | - repo: https://github.com/psf/black-pre-commit-mirror 9 | rev: 25.1.0 10 | hooks: 11 | - id: black 12 | 13 | - repo: https://github.com/pre-commit/pre-commit-hooks 14 | rev: v5.0.0 15 | hooks: 16 | - id: check-added-large-files 17 | - id: check-case-conflict 18 | - id: check-merge-conflict 19 | - id: check-json 20 | - id: check-toml 21 | - id: check-yaml 22 | - id: debug-statements 23 | - id: end-of-file-fixer 24 | - id: forbid-submodules 25 | - id: requirements-txt-fixer 26 | - id: trailing-whitespace 27 | 28 | - repo: https://github.com/python-jsonschema/check-jsonschema 29 | rev: 0.33.0 30 | hooks: 31 | - id: check-github-workflows 32 | - id: check-renovate 33 | 34 | - repo: https://github.com/rhysd/actionlint 35 | rev: v1.7.7 36 | hooks: 37 | - id: actionlint 38 | 39 | - repo: https://github.com/woodruffw/zizmor-pre-commit 40 | rev: v1.5.2 41 | hooks: 42 | - id: zizmor 43 | 44 | - repo: https://github.com/tox-dev/pyproject-fmt 45 | rev: v2.5.1 46 | hooks: 47 | - id: pyproject-fmt 48 | 49 | - repo: https://github.com/abravalheri/validate-pyproject 50 | rev: v0.24.1 51 | hooks: 52 | - id: validate-pyproject 53 | 54 | - repo: https://github.com/tox-dev/tox-ini-fmt 55 | rev: 1.5.0 56 | hooks: 57 | - id: tox-ini-fmt 58 | 59 | - repo: https://github.com/google/yamlfmt 60 | rev: v0.16.0 61 | hooks: 62 | - id: yamlfmt 63 | 64 | - repo: https://github.com/rbubley/mirrors-prettier 65 | rev: v3.5.3 66 | hooks: 67 | - id: prettier 68 | args: [--prose-wrap=always, --print-width=88] 69 | exclude_types: [yaml] 70 | 71 | - repo: meta 72 | hooks: 73 | - id: check-hooks-apply 74 | - id: check-useless-excludes 75 | 76 | ci: 77 | autoupdate_schedule: quarterly 78 | -------------------------------------------------------------------------------- /.yamlfmt.yaml: -------------------------------------------------------------------------------- 1 | formatter: 2 | retain_line_breaks_single: true 3 | -------------------------------------------------------------------------------- /.zenodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "tinytext", 3 | "description": "A helpful converter to change any normal text into cuter tinier text", 4 | "creators": [ 5 | { 6 | "affiliation": "Independent (Non-affiliated)", 7 | "name": "van Kemenade, Hugo", 8 | "orcid": "0000-0001-5715-8632" 9 | } 10 | ], 11 | "resource_type": { 12 | "type": "software" 13 | }, 14 | "license": { 15 | "id": "MIT" 16 | }, 17 | "access_right": "open", 18 | "keywords": [ 19 | "botally", 20 | "tiny type", 21 | "tiny type", 22 | "tiny text", 23 | "cute text", 24 | "generator" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2022 Hugo van Kemenade 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 | # tinytext 2 | 3 | [![PyPI version](https://img.shields.io/pypi/v/tinytext.svg?logo=pypi&logoColor=FFE873)](https://pypi.org/project/tinytext) 4 | [![Supported Python versions](https://img.shields.io/pypi/pyversions/tinytext.svg?logo=python&logoColor=FFE873)](https://pypi.org/project/tinytext) 5 | [![PyPI downloads](https://img.shields.io/pypi/dm/tinytext.svg)](https://pypistats.org/packages/tinytext) 6 | [![GitHub Actions status](https://github.com/hugovk/tinytext/workflows/Test/badge.svg)](https://github.com/hugovk/tinytext/actions) 7 | [![Codecov](https://codecov.io/gh/hugovk/tinytext/branch/main/graph/badge.svg)](https://codecov.io/gh/hugovk/tinytext) 8 | [![Licence](https://img.shields.io/github/license/hugovk/tinytext.svg)](LICENSE.txt) 9 | [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4071428.svg)](https://doi.org/10.5281/zenodo.4071428) 10 | [![Code style: Black](https://img.shields.io/badge/code%20style-Black-000000.svg)](https://github.com/psf/black) 11 | 12 | Convert your text ᶦᶰᵗᵒ ᵗᶦᶰᶦᵉʳ ᵗᵉˣᵗ 13 | 14 | Helpful for all your tiny cute needs. 15 | 16 | Especially helpful for cute bot needs. 17 | 18 | A Python port of 19 | [Rachel White's tiny-text for Node.js](https://github.com/rachelnicole/tiny-text). 20 | 21 | ## How to use 22 | 23 | Install the package into your lovely codebase. 24 | 25 | ```bash 26 | pip install tinytext 27 | ``` 28 | 29 | ```python 30 | from tinytext import tinytext 31 | 32 | print(tinytext("hello friend")) 33 | ``` 34 | 35 | Or on the command line: 36 | 37 | ```console 38 | $ tinytext "hello friend" 39 | ʰᵉᶫᶫᵒ ᶠʳᶦᵉᶰᵈ 40 | ``` 41 | 42 | And that's it! 43 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | # Release checklist 2 | 3 | - [ ] Get `main` to the appropriate code release state. 4 | [GitHub Actions](https://github.com/hugovk/tinytext/actions) should be running 5 | cleanly for all merges to `main`. 6 | [![GitHub Actions status](https://github.com/hugovk/tinytext/workflows/Test/badge.svg)](https://github.com/hugovk/tinytext/actions) 7 | 8 | - [ ] Edit release draft, adjust text if needed: 9 | https://github.com/hugovk/tinytext/releases 10 | 11 | - [ ] Check next tag is correct, amend if needed 12 | 13 | - [ ] Publish release 14 | 15 | - [ ] Check the tagged 16 | [GitHub Actions build](https://github.com/hugovk/tinytext/actions/workflows/deploy.yml) 17 | has deployed to [PyPI](https://pypi.org/project/tinytext/#history) 18 | 19 | - [ ] Check installation: 20 | 21 | ```bash 22 | pip3 uninstall -y tinytext && pip3 install -U tinytext && tinytext --version 23 | ``` 24 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "src/tinytext/cli.py" 3 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | build-backend = "hatchling.build" 3 | requires = [ 4 | "hatch-vcs", 5 | "hatchling>=1.27", 6 | ] 7 | 8 | [project] 9 | name = "tinytext" 10 | description = "A helpful converter to change any normal text into cuter tinier text" 11 | readme = "README.md" 12 | keywords = [ 13 | "botally", 14 | "cute text", 15 | "generator", 16 | "tiny text", 17 | "tiny type", 18 | ] 19 | license = "MIT" 20 | license-files = [ "LICENSE.txt" ] 21 | authors = [ { name = "Hugo van Kemenade" } ] 22 | requires-python = ">=3.9" 23 | classifiers = [ 24 | "Development Status :: 5 - Production/Stable", 25 | "Intended Audience :: Developers", 26 | "Natural Language :: English", 27 | "Programming Language :: Python :: 3 :: Only", 28 | "Programming Language :: Python :: 3.9", 29 | "Programming Language :: Python :: 3.10", 30 | "Programming Language :: Python :: 3.11", 31 | "Programming Language :: Python :: 3.12", 32 | "Programming Language :: Python :: 3.13", 33 | "Programming Language :: Python :: 3.14", 34 | "Programming Language :: Python :: Implementation :: CPython", 35 | "Programming Language :: Python :: Implementation :: PyPy", 36 | "Topic :: Artistic Software", 37 | "Topic :: Text Processing", 38 | ] 39 | dynamic = [ "version" ] 40 | optional-dependencies.tests = [ 41 | "pytest", 42 | "pytest-cov", 43 | ] 44 | urls.Changelog = "https://github.com/hugovk/tinytext/releases" 45 | urls.Homepage = "https://github.com/hugovk/tinytext" 46 | urls.Source = "https://github.com/hugovk/tinytext" 47 | scripts.tinytext = "tinytext.cli:main" 48 | 49 | [tool.hatch] 50 | version.source = "vcs" 51 | 52 | [tool.hatch.build.hooks.vcs] 53 | version-file = "src/tinytext/_version.py" 54 | 55 | [tool.hatch.version.raw-options] 56 | local_scheme = "no-local-version" 57 | 58 | [tool.ruff] 59 | fix = true 60 | 61 | lint.select = [ 62 | "C4", # flake8-comprehensions 63 | "E", # pycodestyle errors 64 | "EM", # flake8-errmsg 65 | "F", # pyflakes 66 | "I", # isort 67 | "ICN", # flake8-import-conventions 68 | "ISC", # flake8-implicit-str-concat 69 | "LOG", # flake8-logging 70 | "PGH", # pygrep-hooks 71 | "PIE", # flake8-pie 72 | "PT", # flake8-pytest-style 73 | "PYI", # flake8-pyi 74 | "RUF022", # unsorted-dunder-all 75 | "RUF100", # unused noqa (yesqa) 76 | "S", # flake8-bandit 77 | "UP", # pyupgrade 78 | "W", # pycodestyle warnings 79 | "YTT", # flake8-2020 80 | ] 81 | lint.ignore = [ 82 | "E203", # Whitespace before ':' 83 | "E221", # Multiple spaces before operator 84 | "E226", # Missing whitespace around arithmetic operator 85 | "E241", # Multiple spaces after ',' 86 | "PIE790", # flake8-pie: unnecessary-placeholder 87 | "UP038", # Makes code slower and more verbose 88 | ] 89 | lint.per-file-ignores."tests/**/*.py" = [ 90 | "S101", # Asserts allowed in tests 91 | ] 92 | lint.flake8-import-conventions.aliases.datetime = "dt" 93 | lint.flake8-import-conventions.banned-from = [ "datetime" ] 94 | lint.flake8-pytest-style.parametrize-names-type = "csv" 95 | lint.isort.known-first-party = [ "tinytext" ] 96 | lint.isort.required-imports = [ "from __future__ import annotations" ] 97 | 98 | [tool.pyproject-fmt] 99 | max_supported_python = "3.14" 100 | 101 | [tool.pytest.ini_options] 102 | testpaths = [ "tests" ] 103 | 104 | [tool.mypy] 105 | pretty = true 106 | strict = true 107 | show_error_codes = true 108 | -------------------------------------------------------------------------------- /requirements-mypy.txt: -------------------------------------------------------------------------------- 1 | mypy==1.16.0 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # Only for testing pinned versions on the CI 2 | pytest==8.3.5 3 | pytest-cov==6.1.1 4 | -------------------------------------------------------------------------------- /src/tinytext/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from ._version import __version__ 4 | 5 | __all__ = ["__version__"] 6 | 7 | tiny_characters: dict[int, str] = { 8 | ord("0"): "⁰", 9 | ord("1"): "¹", 10 | ord("2"): "²", 11 | ord("3"): "³", 12 | ord("4"): "⁴", 13 | ord("5"): "⁵", 14 | ord("6"): "⁶", 15 | ord("7"): "⁷", 16 | ord("8"): "⁸", 17 | ord("9"): "⁹", 18 | ord("a"): "ᵃ", 19 | ord("b"): "ᵇ", 20 | ord("c"): "ᶜ", 21 | ord("d"): "ᵈ", 22 | ord("e"): "ᵉ", 23 | ord("f"): "ᶠ", 24 | ord("g"): "ᵍ", 25 | ord("h"): "ʰ", 26 | ord("i"): "ᶦ", 27 | ord("j"): "ʲ", 28 | ord("k"): "ᵏ", 29 | ord("l"): "ᶫ", 30 | ord("m"): "ᵐ", 31 | ord("n"): "ᶰ", 32 | ord("o"): "ᵒ", 33 | ord("p"): "ᵖ", 34 | ord("q"): "ᑫ", 35 | ord("r"): "ʳ", 36 | ord("s"): "ˢ", 37 | ord("t"): "ᵗ", 38 | ord("u"): "ᵘ", 39 | ord("v"): "ᵛ", 40 | ord("w"): "ʷ", 41 | ord("x"): "ˣ", 42 | ord("y"): "ʸ", 43 | ord("z"): "ᶻ", 44 | ord("A"): "ᴬ", 45 | ord("B"): "ᴮ", 46 | ord("C"): "ᶜ", 47 | ord("D"): "ᴰ", 48 | ord("E"): "ᴱ", 49 | ord("F"): "ᶠ", 50 | ord("G"): "ᴳ", 51 | ord("H"): "ᴴ", 52 | ord("I"): "ᴵ", 53 | ord("J"): "ᴶ", 54 | ord("K"): "ᴷ", 55 | ord("L"): "ᴸ", 56 | ord("M"): "ᴹ", 57 | ord("N"): "ᴺ", 58 | ord("O"): "ᴼ", 59 | ord("P"): "ᴾ", 60 | ord("Q"): "ᑫ", 61 | ord("R"): "ᴿ", 62 | ord("S"): "ˢ", 63 | ord("T"): "ᵀ", 64 | ord("U"): "ᵁ", 65 | ord("V"): "ⱽ", 66 | ord("W"): "ᵂ", 67 | ord("X"): "ˣ", 68 | ord("Y"): "ʸ", 69 | ord("Z"): "ᶻ", 70 | ord("`"): "`", 71 | ord("~"): "~", 72 | ord("!"): "﹗", 73 | ord("@"): "@", 74 | ord("#"): "#", 75 | ord("$"): "﹩", 76 | ord("%"): "﹪", 77 | ord("^"): "^", 78 | ord("&"): "﹠", 79 | ord("*"): "﹡", 80 | ord("("): "⁽", 81 | ord(")"): "⁾", 82 | ord("_"): "⁻", 83 | ord("-"): "⁻", 84 | ord("="): "⁼", 85 | ord("+"): "+", 86 | ord("{"): "{", 87 | ord("["): "[", 88 | ord("}"): "}", 89 | ord("]"): "]", 90 | ord(":"): "﹕", 91 | ord(";"): "﹔", 92 | ord("?"): "﹖", 93 | } 94 | 95 | 96 | def tinytext(big: str) -> str: 97 | """convert your text ᶦᶰᵗᵒ ᵗᶦᶰᶦᵉʳ ᵗᵉˣᵗ""" 98 | tiny: str = big.translate(tiny_characters) 99 | return tiny 100 | -------------------------------------------------------------------------------- /src/tinytext/__main__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from tinytext import cli 4 | 5 | if __name__ == "__main__": 6 | cli.main() 7 | -------------------------------------------------------------------------------- /src/tinytext/cli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | CLI for tinytext 4 | """ 5 | from __future__ import annotations 6 | 7 | import argparse 8 | 9 | from . import __version__ as __version__ 10 | from . import tinytext 11 | 12 | 13 | def main() -> None: 14 | parser = argparse.ArgumentParser( 15 | description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter 16 | ) 17 | parser.color = True # type: ignore[attr-defined] 18 | parser.add_argument("text", help="Text to tinify") 19 | parser.add_argument( 20 | "-V", "--version", action="version", version=f"%(prog)s {__version__}" 21 | ) 22 | args = parser.parse_args() 23 | 24 | print(tinytext(args.text)) 25 | 26 | 27 | if __name__ == "__main__": 28 | main() 29 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugovk/tinytext/ba91665c4875d9a55e5688cbf5ee70a42033811f/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_tinytext.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import tinytext 4 | 5 | 6 | def test_something() -> None: 7 | # Arrange 8 | 9 | # Act 10 | tiny: str = tinytext.tinytext("into tinier text") 11 | 12 | # Assert 13 | assert tiny == "ᶦᶰᵗᵒ ᵗᶦᶰᶦᵉʳ ᵗᵉˣᵗ" 14 | 15 | 16 | def test_for_digits() -> None: 17 | # Arrange 18 | numbers = "9876543210" 19 | 20 | # Act 21 | tiny: str = tinytext.tinytext(numbers) 22 | 23 | # Assert 24 | assert tiny == "⁹⁸⁷⁶⁵⁴³²¹⁰" 25 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | requires = 3 | tox>=4.2 4 | env_list = 5 | cli 6 | lint 7 | mypy 8 | py{py3, 314, 313, 312, 311, 310, 39} 9 | 10 | [testenv] 11 | deps = 12 | -r requirements.txt 13 | pass_env = 14 | FORCE_COLOR 15 | set_env = 16 | COVERAGE_CORE = sysmon 17 | commands = 18 | {envpython} -m pytest \ 19 | --cov tinytext \ 20 | --cov tests \ 21 | --cov-report html \ 22 | --cov-report term \ 23 | --cov-report xml \ 24 | {posargs} 25 | 26 | [testenv:cli] 27 | commands = 28 | tinytext --version 29 | tinytext --help 30 | tinytext abcdef 31 | 32 | [testenv:lint] 33 | skip_install = true 34 | deps = 35 | pre-commit-uv 36 | pass_env = 37 | PRE_COMMIT_COLOR 38 | commands = 39 | pre-commit run --all-files --show-diff-on-failure 40 | 41 | [testenv:mypy] 42 | deps = 43 | -r requirements-mypy.txt 44 | commands = 45 | mypy . {posargs} 46 | --------------------------------------------------------------------------------