2
0
Fork 0

Added inline mode.

This commit is contained in:
Thomas Touhey 2018-07-29 20:34:56 +02:00
parent 5acbc428cd
commit 64c49b0ace
No known key found for this signature in database
GPG Key ID: 2ECEB0517AD947FB
6 changed files with 111 additions and 21 deletions

View File

@ -25,8 +25,6 @@ What is left to do
* Make a clean interface to transmit them;
- Check why exceptions on raw tags effectively escape the content, as it
shouldn't…?
- Implement the ``inline`` tweak in order not to read blocks in the
translator.
- Look for security flaws (we really don't want stored XSS flaws!).
- Manage keywords with tags such as ``[tag key=value other="something else"]``.

View File

@ -29,6 +29,8 @@ equivalent.
The following tweaks are read by the translator and built-in tags:
- ``inline``: if ``True``, only use inline tags, not blocks (for inline
contexts such as instant messaging or one-line comments).
- ``label_prefix`` (HTML): prefix to be used by the ``[label]`` and
``[target]`` tags, e.g. ``msg45529-``. Defaults to `""` for PCv42
compatibility;

View File

@ -7,8 +7,10 @@
Uses the builtin `unittest` module.
"""
import unittest
import textoutpc
import unittest as _unittest
import textoutpc as _textoutpc
__all__ = ["TextoutHTMLTest"]
# Define the tests.
@ -187,7 +189,7 @@ _cnt = 0
_len = len(str(len(__test_cases)))
_templ = """\
def test_html{n:0>{l}}(self):
self.assertEqual(textoutpc.tohtml({i}), {r}, \\
self.assertEqual(_textoutpc.tohtml({i}), {r}, \\
"for the following text: " + {i})
"""
@ -197,13 +199,13 @@ def _wrap_test(inp, res):
_cnt += 1
return _templ.format(n = _cnt, l = _len, i = repr(inp), r = repr(res))
exec("class TextoutHTMLTest(unittest.TestCase):\n maxDiff = None\n" + \
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()
çunittest.main()
# End of file.

55
test/htmli.py Executable file
View File

@ -0,0 +1,55 @@
#!/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
import textoutpc as _textoutpc
__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):
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

@ -7,8 +7,10 @@
Uses the builtin `unittest` module.
"""
import unittest
import textoutpc
import unittest as _unittest
import textoutpc as _textoutpc
__all__ = ["TextoutLSTest"]
# Define the tests.
@ -23,7 +25,7 @@ _cnt = 0
_len = len(str(len(__test_cases)))
_templ = """\
def test_lgsp{n:0>{l}}(self):
self.assertEqual(textoutpc.tolightscript({i}), {r}, {i})
self.assertEqual(_textoutpc.tolightscript({i}), {r}, {i})
"""
def _wrap_test(inp, res):
@ -32,13 +34,13 @@ def _wrap_test(inp, res):
_cnt += 1
return _templ.format(n = _cnt, l = _len, i = repr(inp), r = repr(res))
exec("class TextoutLSTest(unittest.TestCase):\n maxDiff = None\n" + \
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()
_unittest.main()
# End of file.

View File

@ -178,6 +178,20 @@ class Translator:
self.raw_mode = False
self.raw_deg = 0
# `inline_mode` is whether the inline mode is on or not.
# Actually, for now, this mode is only global and cannot be enabled
# by tags.
self.inline_mode = bool(self.tweak("inline", False))
def tweak(self, key, default = None):
""" Get a tweak from the tweaks dictionary. """
try:
return self.tweaks[key]
except KeyError:
return default
# ---
# Text outputting utilities.
# ---
@ -240,7 +254,8 @@ class Translator:
# ---
def add_text(self, text, process_func = lambda x: x, start_tags = True,
superblocks_only = False, next_block_is_super = False):
superblocks_only = False, next_block_is_super = False,
skip_first = False):
""" Add text to the higher blocks if available. """
# The last queue is composed of booleans (does the group contain
@ -264,6 +279,12 @@ class Translator:
else:
continue
# Check if it is the first tag we want to skip.
if skip_first:
skip_first = False
continue
# Contribute to it, either by or-ing the content if it is
# a boolean (but anything or True == True), or by contributing
# to the buffer otherwise.
@ -305,7 +326,8 @@ class Translator:
self.outp.write(message)
def put_code(self, code, start_tags = True, flush_text = True,
superblocks_only = True, next_block_is_super = False):
superblocks_only = True, next_block_is_super = False,
skip_first = False):
""" Put some code. """
# We don't want to mix text and code, so we'll flush to be sure that
@ -323,7 +345,8 @@ class Translator:
self.add_text(code, start_tags = start_tags,
superblocks_only = superblocks_only,
next_block_is_super = next_block_is_super)
next_block_is_super = next_block_is_super,
skip_first = skip_first)
def put_newline(self):
""" Put a newline. """
@ -575,7 +598,7 @@ class Translator:
if hasattr(dat.tag, 'begin'):
self.put_code(dat.tag.begin(), start_tags = False,
flush_text = False)
flush_text = False, skip_first = dat == self.queue[0])
dat.started = True
def close_inline_tags(self):
@ -603,8 +626,9 @@ class Translator:
# By default, everything is in a paragraph.
# Other blocks will supplant this by being further in the queue.
self.push_tag(_TagData(_TextoutParagraphTag(None, None,
self.output_type, self.tweaks), None, ''))
if not self.inline_mode:
self.push_tag(_TagData(_TextoutParagraphTag(None, None,
self.output_type, self.tweaks), None, ''))
# We want to get our elements out of the element stream (Lephe
# told me that the `TextoutStream` class was actually a lexer,
@ -721,9 +745,15 @@ class Translator:
self.put_text(tagdata.full)
continue
# And don't forget to push the tag.
# Check if it is a block tag.
dat = _TagData(tag, tagdata.name, tagdata.full)
if self.inline_mode and dat.type == dat.BLOCK:
self.put_text(tagdata.full)
continue
# And don't forget to push the tag (through its data).
self.push_tag(dat)
# Push a paragraph tag if the block is a superblock.
@ -733,11 +763,12 @@ class Translator:
self.push_tag(_TagData(_TextoutParagraphTag(None, None,
self.output_type, self.tweaks), None, ''))
# End of file, it seems! Let's close the tags and just resume our
# lives from there.
# End of file, it seems! Let's close the tags, flush the text
# and just resume our lives from there.
while self.queue:
self.pop_tag()
self.flush_text()
# And don't forget to return the output for the user to chain
# stuff easily ;)