Gracefully handle errors coming from the QGL server
Fix parsing plain email and markdown links

Currently [email@sr.ht](https://sr.ht) is parsed as both an email and a
url, leading to nested urls and incorrect behavior after sanitization.

This was previously fixed in the context of double urls:

That fix works because the regex of PlainLink matches part of the
markdown url (it matches through the `](<url>)` parts) and therefore the
precedence of mistletoe kicks in.

However that fix doesn't work for email addresses. The inner node is
PlainLink (in the case of email) and RawText (in the case of a url).

The only solution I see is to turn `Link` child `PlainLink` nodes into
`RawText` ones. Alternatively the regex of `PlainLink` could be changed
to also match part of the markdown in the case of email (and let the
precedence kick in), but this feels like big hack to me.

Fixes: https://todo.sr.ht/~sircmpwn/sr.ht/271
Fix excessively green dark mode syntax highlighting
Improve GraphQL explorer on dark theme
highlight-dark: override .gh
56dd1b73 — Alexey Yerin 12 days ago
Extract styles from pygments
Clean up cls checks in Validation::optional()
Remove allow_none parameter from Validation::optional()

The parameter isn't used by any sr.ht service and is functionally
redundant as there is Validation::required().

The if block which sets default values is also fixed. Prior to this
commit, it would only set default values for keys that did not exist in
the incoming request. For things like logging in, this was incorrect
Properly check empty/missing optional form parameters

Some request forms contain keys with empty values. For instance, logging
in from https://meta.sr.ht will generate a request containing the
"return_to" key with a value of "". Similarly, registering without
providing a PGP key generates a request containing the "pgp-key" key
with a value of "".

In such cases, calls to Validation::optional() do not behave as
expected. Since "" != None, the first two top-level if blocks are
immediately skipped in Validation::optional(), even though the second
block is where any default values are set.

In the case of logging in, this results in users being redirected to ""
instead of the specified "/".  Luckily, redirecting to "" is apparently
the same as redirecting to "/", so nothing catastrophic happens.
However, this clearly is an unintended side-effect, and not desired
Make werkzeug.wsgi middleware imports the fallback option

This change swaps the attempted import order around so that the
newer imports are tried first.
debug: Fix old SharedDataMiddleware import

In werkzeug 1.0, SharedDataMiddleware lives at
werkzeug.middleware.shared_data, not werkzeug.wsgi.
Many tweaks & improvements to the dark theme
Add alembic to package dependencies
fda5790d — Alexey Yerin a month ago
Don't color buttons in alerts in dark theme

Signed-off-by: Alexey Yerin <yerinalexey98fd@gmail.com>
b0a261c9 — Alexey Yerin a month ago 0.66.1
Fix color for :focus-ed links in dark mode

Signed-off-by: Alexey Yerin <yerinalexey98fd@gmail.com>
Add dark theme support code
Allow id attribute on sanitized anchor tags

Previously the sanitizer attributes dictionary was created by updating
the desired whitelist with `bleach.sanitizer.ALLOWED_ATTRIBUTES` which
is (at the time of this writing):

    {'a': ['href', 'title'], 'abbr': ['title'], 'acronym': ['title']}

By updating the whitelist dictionary with a duplicated key (`a`), the
whitelist value is overwritten.

Instead, build a new dictionary by merging the two dictionaries with a
preference for the whitelisted values. To accommodate the overwrite
behavior the whitelist is expanded to include those default values.
Add id to list of permitted anchor attributes
Work around pygments GraphQL issue
Allow gemini and gopher URIs on profile
pagination: escape search keys

Fix for paging through, for instance, hashtag searches.