2
0
Fork 0

Latest changes (and mirror testing)

This commit is contained in:
Thomas Touhey 2019-06-25 14:49:22 +02:00
parent 0df1699c27
commit f1f1be481a
No known key found for this signature in database
GPG Key ID: 2ECEB0517AD947FB
16 changed files with 409 additions and 373 deletions

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (C) 2018 Thomas Touhey <thomas@touhey.fr>
Copyright (C) 2018-2019 Thomas Touhey <thomas@touhey.fr>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal

View File

@ -4,7 +4,7 @@
DNAME := dist/$(shell $(ST) --name)-$(shell $(ST) --version).tar.gz
test tests:
@$(ST) test
@$(PE) pytest -s -q
prepare:
@pipenv install --dev

View File

@ -8,9 +8,10 @@ python_version = '3.7'
[packages]
regex = '*'
thcolor = { git = 'https://forge.touhey.org/thcolor.git' }
thcolor = '*'
[dev-packages]
sphinx = '*'
"collective.checkdocs" = '*'
pudb = '*'
pytest = '*'

66
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "6505cb754ffede68e416ce5cf702dddf8f956a3181a4d58924aff57847b29ee9"
"sha256": "f2cea3a09ae48de290ab5aa3af45cedaf158f9586a8f84c50c1825de25732522"
},
"pipfile-spec": 6,
"requires": {
@ -32,8 +32,11 @@
"version": "==2019.4.14"
},
"thcolor": {
"git": "https://forge.touhey.org/thcolor.git",
"ref": "be32e9875ea503dd80bc00abaff12727fdb6c645"
"hashes": [
"sha256:a93a535f7f81b5e38460531b5731f0fa8c4b30b2a63d1fe763c2ac15e37df8b7"
],
"index": "pypi",
"version": "==0.3.1"
}
},
"develop": {
@ -44,6 +47,20 @@
],
"version": "==0.7.12"
},
"atomicwrites": {
"hashes": [
"sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4",
"sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"
],
"version": "==1.3.0"
},
"attrs": {
"hashes": [
"sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79",
"sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"
],
"version": "==19.1.0"
},
"babel": {
"hashes": [
"sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669",
@ -134,6 +151,14 @@
],
"version": "==1.1.1"
},
"more-itertools": {
"hashes": [
"sha256:2112d2ca570bb7c3e53ea1a35cd5df42bb0fd10c45f0fb97178679c3c03d64c7",
"sha256:c3e4748ba1aad8dba30a4886b0b1a2004f9a863837b8654e7059eebf727afa5a"
],
"markers": "python_version > '2.7'",
"version": "==7.0.0"
},
"packaging": {
"hashes": [
"sha256:0c98a5d0be38ed775798ece1b9727178c4469d9c3b4ada66e8e6b7849f8732af",
@ -141,6 +166,13 @@
],
"version": "==19.0"
},
"pluggy": {
"hashes": [
"sha256:25a1bc1d148c9a640211872b4ff859878d422bccb59c9965e04eed468a0aa180",
"sha256:964cedd2b27c492fbf0b7f58b3284a09cf7f99b0f715941fb24a439b3af1bd1a"
],
"version": "==0.11.0"
},
"pudb": {
"hashes": [
"sha256:ac30cfc64580958ab7265decb4cabb9141f08781ff072e9a336d5a7942ce35a6"
@ -148,12 +180,19 @@
"index": "pypi",
"version": "==2019.1"
},
"py": {
"hashes": [
"sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa",
"sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"
],
"version": "==1.8.0"
},
"pygments": {
"hashes": [
"sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a",
"sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d"
"sha256:31cba6ffb739f099a85e243eff8cb717089fdd3c7300767d9fc34cb8e1b065f5",
"sha256:5ad302949b3c98dd73f8d9fcdc7e9cb592f120e32a18e23efd7f3dc51194472b"
],
"version": "==2.3.1"
"version": "==2.4.0"
},
"pyparsing": {
"hashes": [
@ -162,6 +201,14 @@
],
"version": "==2.4.0"
},
"pytest": {
"hashes": [
"sha256:1a8aa4fa958f8f451ac5441f3ac130d9fc86ea38780dd2715e6d5c5882700b24",
"sha256:b8bf138592384bd4e87338cb0f256bf5f615398a649d4bd83915f0e4047a5ca6"
],
"index": "pypi",
"version": "==4.5.0"
},
"pytz": {
"hashes": [
"sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda",
@ -252,6 +299,13 @@
"sha256:644d3e3900867161a2fc9287a9762753d66bd194754679adb26aede559bcccbc"
],
"version": "==2.0.1"
},
"wcwidth": {
"hashes": [
"sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
"sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
],
"version": "==0.1.7"
}
}
}

View File

@ -7,27 +7,28 @@ documentation accessible on `the official website`_.
.. warning::
If you are accessing this repository from `Planète Casio's forge`_,
If you are accessing this repository from another forge (such as
`Planète Casio's forge <https://gitea.planet-casio.com/>`_),
keep in mind that it is only a mirror and that the real repository
is located `in my forge <Thomas' forge_>`_ for now.
What is left to do
------------------
For example, if we want to translate some basic multi-block text to HTML:
- Add an ``[imgurl]`` tag?
- Manage lightscript (or even markdown?) as output languages;
- Check where the errors are to display them to the user:
.. code-block:: python
* Count character offset, line number and column number in the lexer;
* Produce readable exceptions;
* Make a clean interface to transmit them;
- Check why exceptions on raw tags effectively escape the content, as it
shouldn't…?
- Look for security flaws (we really don't want stored XSS flaws!).
- Implement match names (such as ``\[\*+\]`` for lists).
- Manage keywords with tags such as ``[tag key=value other="something else"]``.
from textoutpc import tohtml
text = """[img=center]https://www.planet-casio.com/skins/bootstrap/img/default/logo.png[/img]
Hello [color=R10]world[/color]!
[ul]
[*]This module is made by [url=https://thomas.touhey.fr/]Thomas Touhey[/url]!
[*]Use `.tohtml()` to translate magically to HTML!
[/]
"""
print(tohtml(text))
.. _Planète Casio: https://www.planet-casio.com/
.. _Planète Casio's forge: https://gitea.planet-casio.com/
.. _Thomas' forge: https://forge.touhey.fr/pc/textout.git
.. _the official website: https://textout.touhey.fr/
.. _the official website: https://textout.touhey.pro/

15
TODO.rst Normal file
View File

@ -0,0 +1,15 @@
What is left to do
==================
- Add an ``[imgurl]`` tag?
- Manage lightscript (or even markdown?) as output languages;
- Check where the errors are to display them to the user:
* Count character offset, line number and column number in the lexer;
* Produce readable exceptions;
* Make a clean interface to transmit them;
- Check why exceptions on raw tags effectively escape the content, as it
shouldn't…?
- Look for security flaws (we really don't want stored XSS flaws!).
- Implement match names (such as ``\[\*+\]`` for lists).
- Manage keywords with tags such as ``[tag key=value other="something else"]``.

View File

@ -11,22 +11,33 @@
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
def _add_paths():
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
_add_paths()
# -- Project information -----------------------------------------------------
project = 'textoutpc'
copyright = '2018, Thomas Touhey'
copyright = '2019, Thomas Touhey'
author = 'Thomas Touhey'
# The short X.Y version
version = ''
# The full version, including alpha/beta/rc tags
release = ''
def _get_release():
from os.path import dirname, join
from pkg_resources import find_distributions as find_dist
module_path = join(dirname(__file__), '..')
dist = next(find_dist(module_path, True))
return dist.version
release = _get_release()
# -- General configuration ---------------------------------------------------
@ -39,10 +50,11 @@ release = ''
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = []
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
@ -63,7 +75,7 @@ language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path .
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.goutput*']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
@ -74,7 +86,7 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@ -85,7 +97,7 @@ html_theme = 'alabaster'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = []
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
@ -152,4 +164,4 @@ texinfo_documents = [
(master_doc, 'textoutpc', 'textoutpc Documentation',
author, 'textoutpc', 'One line description of project.',
'Miscellaneous'),
]
]

View File

@ -2,6 +2,8 @@
name = textoutpc
version = attr: textoutpc.version
url = https://textout.touhey.pro/
project_urls =
Documentation = https://textout.touhey.pro/docs/
author = Thomas Touhey
author_email = thomas@touhey.fr
description = textout() equivalent from Planète Casio
@ -42,3 +44,7 @@ universal = True
[flake8]
ignore = F401, F403, E128, E131, E241, E261, E265, E271, W191
exclude = .git, __pycache__, build, dist, docs/conf.py, test.py, test
[tool:pytest]
python_files = tests.py test_*.py *_tests.py
testpaths = tests

View File

@ -1,232 +0,0 @@
#!/usr/bin/env python3
#******************************************************************************
# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
# This file is part of the textoutpc project, which is MIT-licensed.
#******************************************************************************
""" Unit tests for the Python version of textout.
Uses the builtin `unittest` module.
"""
import unittest as _unittest
__all__ = ["TextoutHTMLTest"]
# Define the tests.
__test_cases = {
# Basic text.
'': '',
'lol': '<p>lol</p>',
'<script>alert(1);</script>': \
'<p>&lt;script&gt;alert(1);&lt;/script&gt;</p>',
# Other tests. (?)
'[a][c][/a]': '<p>[a][c][/a]</p>',
'[a][a]': '<p>[a][a]</p>',
"[<>]><[/<>]": "<p>[&lt;&gt;]&gt;&lt;[/&lt;&gt;]</p>",
# Autolinking.
'(http://www.example.org/some-[damn-url]-(youknow))': \
'<p>(<a href="http://www.example.org/some-[damn-url]-(youknow)">' \
'http://www.example.org/some-[damn-url]-(youknow)</a>)</p>',
'https://thomas.touhey.fr/, tu vois ?': \
'<p><a href="https://thomas.touhey.fr/">https://thomas.touhey.fr/' \
'</a>, tu vois ?</p>',
# Basic text styling.
'[u][b][a][i][/b]': "<p><u><b>[a]</b></u></p>",
'[u][b]a[/]mdr': '<p><u><b>a</b>mdr</u></p>',
# Blocks, alignment.
'[left]': '',
'[left]lol[/]hi': '<div class="align-left"><p>lol</p></div><p>hi</p>',
'a[justify]b': '<p>a</p><div class="align-justify"><p>b</p></div>',
'a[i]': '<p>a</p>',
'a[i][justify]b': '<p>a</p>' \
'<div class="align-justify"><p><i>b</i></p></div>',
'a[i]k[center]b': '<p>a<i>k</i></p>' \
'<div class="align-center"><p><i>b</i></p></div>',
'a[i]k[center][b]b[justify]c[/center]d[/]wouhou': \
'<p>a<i>k</i></p>' \
'<div class="align-center"><p><i><b>b</b></i></p>' \
'<div class="align-justify"><p><i><b>c</b></i></p></div></div>' \
'<p><i>d</i>wouhou</p>',
# Show tag for super preprocessing blocks.
'[show]lol': '<p><span class="inline-code">lol</span></p>',
'[quote][show][justify]hehe': \
'<div class="citation"><p><span class="inline-code">' \
'&lt;div class=&quot;align-justify&quot;&gt;' \
'&lt;p&gt;hehe&lt;/p&gt;&lt;/div&gt;' \
'</span></p></div>',
# Titles.
'lolk[title]smth': '<p>lolk</p>' '<h1 class="title">smth</h1>',
'[subtitle]<>': '<h2 class="subtitle">&lt;&gt;</h2>',
# Fonts.
'[arial]test': '<p><span style="font-family: arial">test</span></p>',
'[font=mono]stereo': \
'<p><span style="font-family: monospace">stereo</span></p>',
'[haettenschweiler]': '',
'[font=hello]yea': '<p>[font=hello]yea</p>',
# Color.
'yea[color=blue]dabadee': \
'<p>yea<span style="color: #0000FF">dabadee</span></p>',
'[color=#12345F]a': '<p><span style="color: #12345F">a</span></p>',
'[color=#123]a': '<p><span style="color: #112233">a</span></p>',
'[color=123]a': '<p><span style="color: #010203">a</span></p>',
'[color=chucknorris]a': '<p><span style="color: #C00000">a</span></p>',
'[color=rgb(1, 22,242)]a': '<p><span style="color: #0116F2">a</span></p>',
'[color= rgb (1,22, 242 , 50.0% )]a': '<p><span style="color: #0116F2; ' \
'color: rgba(1, 22, 242, 0.5)">a</span></p>',
'[color=rgba(1,22,242,0.500)]a': '<p><span style="color: #0116F2; ' \
'color: rgba(1, 22, 242, 0.5)">a</span></p>',
'[color=rbga(5, 7)]b': '<p><span style="color: #050007">b</span></p>',
'[color=hsl(0, 1,50.0%)]r': '<p><span style="color: #FF0000">r</span></p>',
# TODO: hls, hwb
# Links.
'[url]': '<p>[url]</p>',
'[url=https://thomas.touhey.fr/]mon profil est le meilleur[/url]':
'<p><a href="https://thomas.touhey.fr/">mon profil est le meilleur' \
'</a></p>',
'[url=https://thomas.touhey.fr/]': \
'<p><a href="https://thomas.touhey.fr/">https://thomas.touhey.fr/' \
'</a></p>',
'[url=http://hey.org/lol[]>"a]': '<p><a href="http://hey.org/lol[]&gt;' \
'&quot;a">' \
'http://hey.org/lol[]&gt;&quot;a</a></p>',
'[url]javascript:alert(1)[/url]': '<p>[url]javascript:alert(1)[/url]</p>',
'[url]<script>alert(1);</script>[/url]': \
'<p>[url]&lt;script&gt;alert(1);&lt;/script&gt;[/url]</p>',
'[profil]cake[/profil]': \
'<p><a href="https://www.planet-casio.com/Fr/compte/voir_profil.php' \
'?membre=cake">cake</a></p>',
'[profile]ekac': \
'<p><a href="https://www.planet-casio.com/Fr/compte/voir_profil.php' \
'?membre=ekac">ekac</a></p>',
# Quotes.
'[quote]': '',
'[quote]a': \
'<div class="citation"><p>a</p></div>',
'[quote=Test 1 :)]lel[/quote]': \
'<div class="citation"><p><b>Test 1 ' \
'<img src="/images/smileys/smile.gif"> a écrit:</b></p><p>' \
'lel</p></div>',
# Spoilers.
'[spoiler]': '',
'[spoiler=Hello|world> :D]Close this, quick![/spoiler]': \
'<div class="spoiler"><div class="title on" ' \
'onclick="toggleSpoiler(this.parentNode, ' "'open'" ');"><p>Hello' \
'</p></div><div class="title off" ' \
'onclick="toggleSpoiler(this.parentNode, ' "'close'" ');"><p>world' \
'&gt; <img src="/images/smileys/grin.gif"></p></div>' \
'<div class="off"><p>Close this, quick!</p></div></div>',
# Code.
'[code]': '',
"`[code]`": '<p><span class="inline-code">[code]</span></p>',
'[inlinecode]': '',
"[inlinecode]`[/inlinecode]": '<p><span class="inline-code">`</span></p>',
"[b]a[noeval]b[/b]c[/noeval]d": "<p><b>ab[/b]cd</b></p>",
"a[noeval]b[noeval]c[/noeval]d[/noeval]e": "<p>ab[noeval]c[/noeval]de</p>",
"[noeval]``[/noeval]": "<p>``</p>",
'[noeval]<>[/noeval]': '<p>&lt;&gt;</p>',
# Pictures.
'[img]': '<p>[img]</p>',
'[img]"incroyable<>"[/img]': \
'<p>[img]&quot;incroyable&lt;&gt;&quot;[/img]</p>',
'[img=right|float|12x345]https://example.org/image.png': \
'<img src="https://example.org/image.png" class="img-float-right" ' \
'style="width: 12px; height: 345px" />',
# Videos.
'[video]"><script>alert(1)</script>[/video]': \
'<p>[video]&quot;&gt;&lt;script&gt;alert(1)&lt;/script&gt;' \
'[/video]</p>',
'[video]<script>alert(document.cookie)</script>[/video]': \
'<p>[video]&lt;script&gt;alert(document.cookie)&lt;/script&gt;' \
'[/video]</p>',
'[video]https://www.youtube.com/watch?v=6odDOOyUawY[/video]': \
'<div class="video-wrapper" style="padding-bottom: 56.25%"><iframe ' \
'src="https://www.youtube.com/embed/6odDOOyUawY" ' \
'frameborder="0" allowfullscreen></iframe></div>',
'[video]https://www.youtube.com/watch?v=<script>alert(1)</script>': \
'<p><a href="https://www.youtube.com/watch?v=&lt;script&gt;alert(1)' \
'&lt;/script&gt;">' \
'https://www.youtube.com/watch?v=&lt;script&gt;alert(1)' \
'&lt;/script&gt;</a></p>',
'[video=left|float|4:3]https://www.youtube.com/watch?v=XEjLoHdbVeE': \
'<div class="video-wrapper img-float-left" ' \
'style="padding-bottom: 75%"><iframe ' \
'src="https://www.youtube.com/embed/XEjLoHdbVeE" frameborder="0" ' \
'allowfullscreen></iframe></div>',
'lol[youtube]h4WLX8hfpJw': '<p>lol</p><div class="video-wrapper" ' \
'style="padding-bottom: 56.25%"><iframe ' \
'src="https://www.youtube.com/embed/h4WLX8hfpJw" frameborder="0" ' \
'allowfullscreen></iframe></div>',
'[color=blue][youtube]h4WLX8hfpJw': \
'<div class="video-wrapper" style="padding-bottom: 56.25%">' \
'<iframe src="https://www.youtube.com/embed/h4WLX8hfpJw" ' \
'frameborder="0" allowfullscreen></iframe></div>',
'[color=blue]oh[youtube]h4WLX8hfpJw': \
'<p><span style="color: #0000FF">oh</span></p>' \
'<div class="video-wrapper" style="padding-bottom: 56.25%"><iframe ' \
'src="https://www.youtube.com/embed/h4WLX8hfpJw" frameborder="0" ' \
'allowfullscreen></iframe></div>',
# Progress bars.
'[progress=lol]mdr[/progress]': '<p>[progress=lol]mdr[/progress]</p>',
# Text rotation obfuscation.
'[rot13]obawbhe[/rot13]': '<p>bonjour</p>',
# Lists.
'[list]haha[b][*]wow[*]incredible[/b][/*]wow[*]yuy[/list]': \
'<ul><li><p>wow</p></li><li><p>incredible[/b]</p></li>' \
'<li><p>yuy</p></li></ul>',
'[list]\n[*]bonjour': '<ul><li><p>bonjour</p></li></ul>',
# Smileys.
':)': '<p><img src="/images/smileys/smile.gif"></p>',
':):)': '<p>:):)</p>',
':) :D': '<p><img src="/images/smileys/smile.gif"> ' \
'<img src="/images/smileys/grin.gif"></p>',
}
# Define the tests wrapper, and define the classes.
_cnt = 0
_len = len(str(len(__test_cases)))
_templ = """\
def test_html{n:0>{l}}(self):
import textoutpc as _textoutpc
self.assertEqual(_textoutpc.tohtml({i}), {r}, \\
"for the following text: " + {i})
"""
def _wrap_test(inp, res):
global _cnt
_cnt += 1
return _templ.format(n = _cnt, l = _len, i = repr(inp), r = repr(res))
exec("class TextoutHTMLTest(_unittest.TestCase):\n maxDiff = None\n" + \
'\n'.join(map(lambda args: _wrap_test(*args), __test_cases.items())),
globals())
# If run as main script, run the test function.
if __name__ == '__main__':
_unittest.main()
# End of file.

View File

@ -1,55 +0,0 @@
#!/usr/bin/env python3
#******************************************************************************
# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
# This file is part of the textoutpc project, which is MIT-licensed.
#******************************************************************************
""" Unit tests for the Python version of textout.
Uses the builtin `unittest` module.
"""
import unittest as _unittest
__all__ = ["TextoutHTMLiTest"]
# Define the tests.
__test_cases = {
# Basic text.
'': '',
'lol': 'lol',
# Basic text styling.
'[u][b]a[/]mdr': '<u><b>a</b>mdr</u>',
# Links.
'[url=https://thomas.touhey.fr/]': '<a href="https://thomas.touhey.fr/">' \
'https://thomas.touhey.fr/</a>',
}
# Define the tests wrapper, and define the classes.
_cnt = 0
_len = len(str(len(__test_cases)))
_templ = """\
def test_htmli{n:0>{l}}(self):
import textoutpc as _textoutpc
self.assertEqual(_textoutpc.tohtml({i}, inline = True), {r}, \\
"for the following text: " + {i})
"""
def _wrap_test(inp, res):
global _cnt
_cnt += 1
return _templ.format(n = _cnt, l = _len, i = repr(inp), r = repr(res))
exec("class _TextoutHTMLiTest(_unittest.TestCase):\n maxDiff = None\n" + \
'\n'.join(map(lambda args: _wrap_test(*args), __test_cases.items())),
globals())
# If run as main script, run the test function.
if __name__ == '__main__':
_unittest.main()
# End of file.

View File

@ -1,47 +0,0 @@
#!/usr/bin/env python3
#******************************************************************************
# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
# This file is part of the textoutpc project, which is MIT-licensed.
#******************************************************************************
""" Unit tests for the Python version of textout, lightscript-related funcs.
Uses the builtin `unittest` module.
"""
import unittest as _unittest
__all__ = ["TextoutLSTest"]
# Define the tests.
__test_cases = {
# Basic text.
'': '',
}
# Define the tests wrapper, and define the classes.
_cnt = 0
_len = len(str(len(__test_cases)))
_templ = """\
def test_lgsp{n:0>{l}}(self):
import textoutpc as _textoutpc
self.assertEqual(_textoutpc.tolightscript({i}), {r}, {i})
"""
def _wrap_test(inp, res):
global _cnt
_cnt += 1
return _templ.format(n = _cnt, l = _len, i = repr(inp), r = repr(res))
exec("class TextoutLSTest(_unittest.TestCase):\n maxDiff = None\n" + \
'\n'.join(map(lambda args: _wrap_test(*args), __test_cases.items())),
globals())
# If run as main script, run the test function.
if __name__ == '__main__':
_unittest.main()
# End of file.

230
tests/test_html.py Executable file
View File

@ -0,0 +1,230 @@
#!/usr/bin/env python3
#******************************************************************************
# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
# This file is part of the textoutpc project, which is MIT-licensed.
#******************************************************************************
""" Unit tests for the Python version of textout. """
import pytest
from textoutpc import tohtml as _tohtml
# Define the tests.
@pytest.mark.parametrize('test_input,expected', (
# Basic text.
('', ''),
('lol', '<p>lol</p>'),
('<script>alert(1);</script>',
'<p>&lt;script&gt;alert(1);&lt;/script&gt;</p>'),
# Other tests. (?)
('[a][c][/a]', '<p>[a][c][/a]</p>'),
('[a][a]', '<p>[a][a]</p>'),
("[<>]><[/<>]", "<p>[&lt;&gt;]&gt;&lt;[/&lt;&gt;]</p>"),
# Autolinking.
('(http://www.example.org/some-[damn-url]-(youknow))',
'<p>(<a href="http://www.example.org/some-[damn-url]-(youknow)">' \
'http://www.example.org/some-[damn-url]-(youknow)</a>)</p>'),
('https://thomas.touhey.fr/, tu vois ?',
'<p><a href="https://thomas.touhey.fr/">https://thomas.touhey.fr/' \
'</a>, tu vois ?</p>'),
# Basic text styling.
('[u][b][a][i][/b]', "<p><u><b>[a]</b></u></p>"),
('[u][b]a[/]mdr', '<p><u><b>a</b>mdr</u></p>'),
# Blocks, alignment.
('[left]', ''),
('[left]lol[/]hi', '<div class="align-left"><p>lol</p></div><p>hi</p>'),
('a[justify]b', '<p>a</p><div class="align-justify"><p>b</p></div>'),
('a[i]', '<p>a</p>'),
('a[i][justify]b', '<p>a</p>' \
'<div class="align-justify"><p><i>b</i></p></div>'),
('a[i]k[center]b', '<p>a<i>k</i></p>' \
'<div class="align-center"><p><i>b</i></p></div>'),
('a[i]k[center][b]b[justify]c[/center]d[/]wouhou',
'<p>a<i>k</i></p>' \
'<div class="align-center"><p><i><b>b</b></i></p>' \
'<div class="align-justify"><p><i><b>c</b></i></p></div></div>' \
'<p><i>d</i>wouhou</p>'),
# Show tag for super preprocessing blocks.
('[show]lol', '<p><span class="inline-code">lol</span></p>'),
('[quote][show][justify]hehe',
'<div class="citation"><p><span class="inline-code">' \
'&lt;div class=&quot;align-justify&quot;&gt;' \
'&lt;p&gt;hehe&lt;/p&gt;&lt;/div&gt;' \
'</span></p></div>'),
# Titles.
('lolk[title]smth', '<p>lolk</p>' '<h1 class="title">smth</h1>'),
('[subtitle]<>', '<h2 class="subtitle">&lt;&gt;</h2>'),
# Fonts.
('[arial]test', '<p><span style="font-family: arial">test</span></p>'),
('[font=mono]stereo',
'<p><span style="font-family: monospace">stereo</span></p>'),
('[haettenschweiler]', ''),
('[font=hello]yea', '<p>[font=hello]yea</p>'),
# Color.
('yea[color=blue]dabadee', \
'<p>yea<span style="color: #0000FF">dabadee</span></p>'),
('[color=#12345F]a', '<p><span style="color: #12345F">a</span></p>'),
('[color=#123]a', '<p><span style="color: #112233">a</span></p>'),
('[color=123]a', '<p><span style="color: #010203">a</span></p>'),
('[color=chucknorris]a', '<p><span style="color: #C00000">a</span></p>'),
('[color=rgb(1, 22,242)]a',
'<p><span style="color: #0116F2">a</span></p>'),
('[color= rgb (1,22, 242 , 50.0% )]a',
'<p><span style="color: #0116F2; ' \
'color: rgba(1, 22, 242, 0.5)">a</span></p>'),
('[color=rgba(1,22,242,0.500)]a', '<p><span style="color: #0116F2; ' \
'color: rgba(1, 22, 242, 0.5)">a</span></p>'),
('[color=rbga(5, 7)]b', '<p><span style="color: #050007">b</span></p>'),
('[color=hsl(0, 1,50.0%)]r',
'<p><span style="color: #FF0000">r</span></p>'),
# TODO: hls, hwb
# Links.
('[url]', '<p>[url]</p>'),
('[url=https://thomas.touhey.fr/]mon profil est le meilleur[/url]',
'<p><a href="https://thomas.touhey.fr/">mon profil est le meilleur' \
'</a></p>'),
('[url=https://thomas.touhey.fr/]',
'<p><a href="https://thomas.touhey.fr/">https://thomas.touhey.fr/' \
'</a></p>'),
('[url=http://hey.org/lol[]>"a]', '<p><a href="http://hey.org/lol[]&gt;' \
'&quot;a">' 'http://hey.org/lol[]&gt;&quot;a</a></p>'),
('[url]javascript:alert(1)[/url]',
'<p>[url]javascript:alert(1)[/url]</p>'),
('[url]<script>alert(1);</script>[/url]',
'<p>[url]&lt;script&gt;alert(1);&lt;/script&gt;[/url]</p>'),
('[profil]cake[/profil]',
'<p><a href="https://www.planet-casio.com/Fr/compte/voir_profil.php' \
'?membre=cake">cake</a></p>'),
('[profile]ekac',
'<p><a href="https://www.planet-casio.com/Fr/compte/voir_profil.php' \
'?membre=ekac">ekac</a></p>'),
# Quotes.
('[quote]', ''),
('[quote]a',
'<div class="citation"><p>a</p></div>'),
('[quote=Test 1 :)]lel[/quote]',
'<div class="citation"><p><b>Test 1 ' \
'<img src="/images/smileys/smile.gif"> a écrit:</b></p><p>' \
'lel</p></div>'),
# Spoilers.
('[spoiler]', ''),
('[spoiler=Hello|world> :D]Close this, quick![/spoiler]',
'<div class="spoiler"><div class="title on" ' \
'onclick="toggleSpoiler(this.parentNode, ' "'open'" ');"><p>Hello' \
'</p></div><div class="title off" ' \
'onclick="toggleSpoiler(this.parentNode, ' "'close'" ');"><p>world' \
'&gt; <img src="/images/smileys/grin.gif"></p></div>' \
'<div class="off"><p>Close this, quick!</p></div></div>'),
# Code.
('[code]', ''),
("`[code]`", '<p><span class="inline-code">[code]</span></p>'),
('[inlinecode]', ''),
("[inlinecode]`[/inlinecode]",
'<p><span class="inline-code">`</span></p>'),
("[b]a[noeval]b[/b]c[/noeval]d", "<p><b>ab[/b]cd</b></p>"),
("a[noeval]b[noeval]c[/noeval]d[/noeval]e",
"<p>ab[noeval]c[/noeval]de</p>"),
("[noeval]``[/noeval]", "<p>``</p>"),
('[noeval]<>[/noeval]', '<p>&lt;&gt;</p>'),
# Pictures.
('[img]', '<p>[img]</p>'),
('[img]"incroyable<>"[/img]',
'<p>[img]&quot;incroyable&lt;&gt;&quot;[/img]</p>'),
('[img=right|float|12x345]https://example.org/image.png',
'<img src="https://example.org/image.png" class="img-float-right" ' \
'style="width: 12px; height: 345px" />'),
# Videos.
('[video]"><script>alert(1)</script>[/video]',
'<p>[video]&quot;&gt;&lt;script&gt;alert(1)&lt;/script&gt;' \
'[/video]</p>'),
('[video]<script>alert(document.cookie)</script>[/video]',
'<p>[video]&lt;script&gt;alert(document.cookie)&lt;/script&gt;' \
'[/video]</p>'),
('[video]https://www.youtube.com/watch?v=6odDOOyUawY[/video]',
'<div class="video-wrapper" style="padding-bottom: 56.25%"><iframe ' \
'src="https://www.youtube.com/embed/6odDOOyUawY" ' \
'frameborder="0" allowfullscreen></iframe></div>'),
('[video]https://www.youtube.com/watch?v=<script>alert(1)</script>',
'<p><a href="https://www.youtube.com/watch?v=&lt;script&gt;alert(1)' \
'&lt;/script&gt;">' \
'https://www.youtube.com/watch?v=&lt;script&gt;alert(1)' \
'&lt;/script&gt;</a></p>'),
('[video=left|float|4:3]https://www.youtube.com/watch?v=XEjLoHdbVeE',
'<div class="video-wrapper img-float-left" ' \
'style="padding-bottom: 75%"><iframe ' \
'src="https://www.youtube.com/embed/XEjLoHdbVeE" frameborder="0" ' \
'allowfullscreen></iframe></div>'),
('lol[youtube]h4WLX8hfpJw', '<p>lol</p><div class="video-wrapper" ' \
'style="padding-bottom: 56.25%"><iframe ' \
'src="https://www.youtube.com/embed/h4WLX8hfpJw" frameborder="0" ' \
'allowfullscreen></iframe></div>'),
('[color=blue][youtube]h4WLX8hfpJw',
'<div class="video-wrapper" style="padding-bottom: 56.25%">' \
'<iframe src="https://www.youtube.com/embed/h4WLX8hfpJw" ' \
'frameborder="0" allowfullscreen></iframe></div>'),
('[color=blue]oh[youtube]h4WLX8hfpJw',
'<p><span style="color: #0000FF">oh</span></p>' \
'<div class="video-wrapper" style="padding-bottom: 56.25%"><iframe ' \
'src="https://www.youtube.com/embed/h4WLX8hfpJw" frameborder="0" ' \
'allowfullscreen></iframe></div>'),
# Progress bars.
('[progress=lol]mdr[/progress]', '<p>[progress=lol]mdr[/progress]</p>'),
# Text rotation obfuscation.
('[rot13]obawbhe[/rot13]', '<p>bonjour</p>'),
# Lists.
('[list]haha[b][*]wow[*]incredible[/b][/*]wow[*]yuy[/list]',
'<ul><li><p>wow</p></li><li><p>incredible[/b]</p></li>' \
'<li><p>yuy</p></li></ul>'),
('[list]\n[*]bonjour', '<ul><li><p>bonjour</p></li></ul>'),
# Smileys.
(':)', '<p><img src="/images/smileys/smile.gif"></p>'),
(':):)', '<p>:):)</p>'),
(':) :D', '<p><img src="/images/smileys/smile.gif"> ' \
'<img src="/images/smileys/grin.gif"></p>'),
))
def test_html(test_input, expected):
assert _tohtml(test_input) == expected
# End of file.

30
tests/test_htmli.py Executable file
View File

@ -0,0 +1,30 @@
#!/usr/bin/env python3
#******************************************************************************
# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
# This file is part of the textoutpc project, which is MIT-licensed.
#******************************************************************************
""" Unit tests for the Python version of textout. """
import pytest
from textoutpc import tohtml as _tohtml
@pytest.mark.parametrize('test_input,expected', (
# Basic text.
('', ''),
('lol', 'lol'),
# Basic text styling.
('[u][b]a[/]mdr', '<u><b>a</b>mdr</u>'),
# Links.
('[url=https://thomas.touhey.fr/]',
'<a href="https://thomas.touhey.fr/">https://thomas.touhey.fr/</a>'),
))
def test_htmli(test_input, expected):
assert _tohtml(test_input, inline = True) == expected
# End of file.

21
tests/test_ls.py Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
#******************************************************************************
# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
# This file is part of the textoutpc project, which is MIT-licensed.
#******************************************************************************
""" Unit tests for the Python version of textout, lightscript-related
functions. """
import pytest
from textoutpc import tolightscript as _tolightscript
@pytest.mark.parametrize('test_input,expected', (
# Basic text.
('', ''),
))
def test_lightscript(test_input, expected):
assert _tolightscript(test_input) == expected
# End of file.

View File

@ -101,7 +101,7 @@ class TextoutStream:
#
# FIXME: check the sizes? it seems that it stopped working…
_Tag = _re.compile("""\
_Tag = _re.compile(r"""
\[\s?
(?P<bname>
(?P<bname_e>[^\/\[\]\=][^\[\]\=]* (\[(?&bname_e)\]?)*)*