Skip to content

Commit

Permalink
Pretty much all the code, tests, and docs
Browse files Browse the repository at this point in the history
Co-authored-by: classabbyamp <[email protected]>
  • Loading branch information
0x5c and classabbyamp committed Sep 7, 2021
1 parent f46ecfe commit b7e8082
Show file tree
Hide file tree
Showing 31 changed files with 980 additions and 89 deletions.
4 changes: 4 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[flake8]
max-line-length = 120
per-file-ignores =
*/__init__.py:F401
6 changes: 3 additions & 3 deletions .github/workflows/pythonpublish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

jobs:
deploy:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
Expand All @@ -17,7 +17,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.8'
python-version: '3.6'
- name: Install dependencies
run: |
python -m pip install -U pip setuptools wheel
Expand All @@ -29,4 +29,4 @@ jobs:
run: |
python setup.py sdist bdist_wheel
twine check dist/*
twine upload dist/*
twine upload dist/*
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ name: Create Release
jobs:
release:
name: Create Release
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
Expand Down
92 changes: 92 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Lint and Test

on: [push,pull_request]

jobs:
precheck:
runs-on: ubuntu-20.04

outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@master
with:
# skip concurrent jobs if they are on the same thing
concurrent_skipping: 'same_content'
# never skip PR + manual/scheduled runs
do_not_skip: '["pull_request", "workflow_dispatch", "schedule"]'

flake8:
needs: precheck
if: ${{ needs.precheck.outputs.should_skip != 'true' }}
runs-on: ubuntu-latest

strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]

steps:
- uses: actions/checkout@v2
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Run flake8
uses: suo/flake8-github-action@releases/v1
with:
checkName: 'flake8' # NOTE: this needs to be the same as the job name
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

mypy:
needs: precheck
if: ${{ needs.precheck.outputs.should_skip != 'true' }}
runs-on: ubuntu-latest

strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]

steps:
- uses: actions/checkout@v2
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install mypy
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Run mypy
run: |
mypy -p discord_styler
pytest:
needs: precheck
if: ${{ needs.precheck.outputs.should_skip != 'true' }}
runs-on: ubuntu-latest

strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]

steps:
- uses: actions/checkout@v2
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Run pytest
run: |
python -m pytest
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ celerybeat.pid
# Environments
.env
.venv
env/
*env/
venv/
ENV/
env.bak/
Expand Down
1 change: 0 additions & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ formats: all

# Optionally set the version of Python and requirements required to build your docs
python:
version: 3.8
install:
- requirements: docs/requirements.txt
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Changelog for {{pkg_name}}
# Changelog for discord-styled-text
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
Expand All @@ -12,5 +12,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0


<!-- NOTE: Add these links to link the title of each section of the changelog to link to the release -->
<!-- [Unreleased]: {{pkg_repo}}/compare/{{version}}...HEAD -->
<!-- [{{version}}]: {{pkg_repo}}/releases/tag/{{version}} -->
<!-- [Unreleased]: https://github.com/miaowware/discord-styled-text/compare/{{version}}...HEAD -->
<!-- [{{version}}]: https://github.com/miaowware/discord-styled-text/releases/tag/{{version}} -->
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BSD 3-Clause License

Copyright (c) 2020, classabbyamp, 0x5c
Copyright (c) 2021, classabbyamp, 0x5c
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
67 changes: 43 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,58 @@
# {{pkg_name}}
# discord-styled-text

{{pkg_description}}
A small library to style text for Discord without having to remember any syntax

[![PyPI](https://img.shields.io/pypi/v/{{pkg_name}})](https://pypi.org/project/{{pkg_name}}/) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/{{pkg_name}}) ![PyPI - License](https://img.shields.io/pypi/l/{{pkg_name}}) [![Documentation Status](https://readthedocs.org/projects/{{pkg_name}}/badge/?version=latest)](https://{{pkg_name}}.readthedocs.io/en/latest/?badge=latest)

## Using This Template

1. Replace instances of ... with ...:
* `{{pkg_name}}` with the package name
* `{{pkg_description}}` with the package description
* `{{pkg_repo}}` with the package repository URL
* `{{pkg_site}}` with the package website
* `{{version}}` with the package version (probably something to do later)
* `{{authors}}` with the package authors (comma separated)
* `{{author_emails}}` with the package authors' emails (comma separated)
* `{{license}}` with the package license name
* `{{YYYY}}` with the package year of copyright
2. See comments with `NOTE` in them for more details.
3. If you want to use the Github action to publish releases, add the `PYPI_TOKEN` secret.
* More info: https://pypi.org/help/#apitoken
[![PyPI](https://img.shields.io/pypi/v/discord-styled-text)](https://pypi.org/project/discord-styled-text/) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/discord-styled-text) ![PyPI - License](https://img.shields.io/pypi/l/discord-styled-text) [![Documentation Status](https://readthedocs.org/projects/discord-styled-text/badge/?version=latest)](https://discord-styled-text.miaow.io/en/latest/?badge=latest)

## Installation

`{{pkg_name}}` requires Python 3.8 at minimum.
`discord-styled-text` requires Python 3.6 at minimum.

```none
$ pip install {{pkg_name}}
$ pip install discord-styled-text
```

## Documentation

Documentation is available on [ReadTheDocs](https://{{pkg_name}}.readthedocs.io/).
Documentation is available on [ReadTheDocs](https://discord-styled-text.miaow.io/).

## Example Usage

```py
>>> from discord_styler import *

>>> bold_text = Bold("Here's some bold text")
>>> italic_text = Italic("and here's some", Underline("italic text"), "with nested styles!")
>>> text = StyledText("We can combine them:", bold_text, italic_text)
>>> str(text)
"We can combine them: **Here's some bold text** *and here's some __italic text__ with nested styles!*"

>>> quoted = StyledText(BlockQuote(text), "and we can do quotes too")
>>> str(quoted)
"> We can combine them: **Here's some bold text** *and here's some __italic text__ with nested styles!*\n and we can do quotes too"

>>> question = StyledText(
... UserMention(200102491231092736),
... f"will you be free at {TimeStamp(1618953630, TimeStyle.LongDateTime)}?",
... f"I'll be doing code review in {ChannelMention(656893570711814145)} if you wanna join")
>>> str(question)
"<@200102491231092736> will you be free at <t:1618953630:F>? I'll be doing code review in <#656893570711814145> if you wanna join"

>>> link = NonEmbeddingURL("https://github.com/miaowware/discord-styled-text/pull/1")
>>> str(link)
'<https://github.com/miaowware/discord-styled-text/pull/1>'

>>> code = StyledText(
... "What do you think of this?\n",
... CodeBlock('def __str__(self) -> str:\n return "||" + super().__str__() + "||"', lang="py"))
>>> str(code)
'What do you think of this?\n ```py\ndef __str__(self) -> str:\n return "||" + super().__str__() + "||"\n```'
```

![The output of the example, rendered in Discord](/docs/discord_screenshot.png)

## Copyright

Copyright {{YYYY}} {{authors}}
Released under the {{license}} License.
Copyright 2021 classabbyamp, 0x5c
Released under the BSD 3-Clause License.
See [`LICENSE`](LICENSE) for the full license text.
4 changes: 2 additions & 2 deletions devrequirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
flake8
mypy
twine
sphinx
sphinx-autobuild
-r docs/requirements.txt
-r tests/requirements.txt
14 changes: 14 additions & 0 deletions discord_styler/__info__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"Package information file"
# Format and usage strongly inspired by AGProjects/python-application.


__project__ = "discord-styled-text"
__summary__ = "A small library to style text for Discord without having to remember any syntax"
__webpage__ = "https://discord-styled-text.miaow.io"

__version__ = "{{version}}"

__author__ = "classabbyamp, 0x5c"
__email__ = "[email protected], [email protected]"

__license__ = "BSD 3-Clause"
17 changes: 17 additions & 0 deletions discord_styler/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""
discord-styled-text
---
A small library to style text for Discord without having to remember any syntax
Copyright 2021 classabbyamp, 0x5c
Released under the terms of the BSD 3-Clause license.
"""


from .__info__ import __version__
from .styler import StyledText, Italic, Bold, Underline, Strikethrough, InlineCode, Spoiler, BlockQuote
from .styler import CodeBlock
from .styler import TitledURL, NonEmbeddingURL
from .styler import MentionABC, UserMention, RoleMention, ChannelMention
from .styler import TimeStyle, TimeStamp
from .escape import escape_markdown, escape_mentions, escape_everything
75 changes: 75 additions & 0 deletions discord_styler/escape.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""
discord-styled-text - escape.py
---
Copyright 2021 classabbyamp, 0x5c
Released under the terms of the BSD 3-Clause license.
"""

import re


__all__ = [
"escape_markdown",
"escape_mentions",
"escape_everything",
]


INLINE_MD_RE = re.compile(r"(?P<bs>(?<!\\)(?:\\\\)*)(?P<char>[_*~|`])")
INLINE_MD_SUB = r"\g<bs>\\\g<char>"

BLOCKQUOTE_RE = re.compile(r"^>(?=(>>)? )", flags=re.MULTILINE)
TIMESTAMP_RE = re.compile(r"<t:[0-9]+(?::[a-zA-Z])?>")
GENERIC_SUB = r"\\\g<0>"

USER_ROLE_CHANNEL_RE = re.compile(r"<(@[!&]?|#)([0-9]+)>")
USER_ROLE_RE = re.compile(r"<(@[!&]?)([0-9]+)>")
MENTION_SUB = "<\\g<1>\u200b\\g<2>>" # this cannot be a raw string because of the \u200b

EVERYONE_HERE_RE = re.compile(r"@(everyone|here)", flags=re.IGNORECASE)
EVERYONE_HERE_SUB = "@\u200b\\g<1>" # this cannot be a raw string because of the \u200b


def escape_markdown(text: str, *, esc_timestamps: bool = True) -> str:
"""Utility function to escape markdown-like formatting in a string
:param text: the text to escape
:param esc_timestamps: whether to escape timestamp formatting in the text
"""
text = re.sub(INLINE_MD_RE, INLINE_MD_SUB, text)
text = re.sub(BLOCKQUOTE_RE, GENERIC_SUB, text)
if esc_timestamps:
text = re.sub(TIMESTAMP_RE, GENERIC_SUB, text)
return text


def escape_mentions(text: str, *, esc_channels: bool = True) -> str:
"""Utility function to escape all mentions in the text
Escapes user, role, everyone/here, and optionally, channel mentions.
Escaping done by adding a non-breaking space (``\\u200b``) between the
mention symbol (``@``/``@!``/``@&``/``#``) and the identifier (ID/``everyone``/``here``).
:param text: the text to escape
:param esc_channels: whether to escape channel mentions in the text
"""
text = re.sub(EVERYONE_HERE_RE, EVERYONE_HERE_SUB, text)
if esc_channels:
text = re.sub(USER_ROLE_CHANNEL_RE, MENTION_SUB, text)
else:
text = re.sub(USER_ROLE_RE, MENTION_SUB, text)
return text


def escape_everything(text: str, *, esc_timestamps: bool = True, esc_channels: bool = True) -> str:
"""Utility function to escape all special formatting and mentions
Exactly the same as running both :func:`escape_markdown` and :func:`escape_mentions`.
Provided as a convenience shortcut.
:param text: the text to escape
:param esc_timestamps: whether to escape timestamp formatting in the text
:param esc_channels: whether to escape channel mentions in the text
"""
return escape_mentions(escape_markdown(text, esc_timestamps=esc_timestamps),
esc_channels=esc_channels)
Empty file added discord_styler/py.typed
Empty file.
Loading

0 comments on commit b7e8082

Please sign in to comment.