From 0f400c195666ebeeabcb656c1260e55790bf7856 Mon Sep 17 00:00:00 2001
From: Dennis Burke notelist({0})(?:\:([\w|{1}]))?([\^!]?)(\+?)'
- r'\.?[\s]*
', match.group(3))
return '<{0}{1}>{2}{3}'.format(match.group(1), match.group(2), content,
- match.group(4))
+ match.group(4))
def block(self, text):
if not self.lite:
@@ -450,8 +449,8 @@ def block(self, text):
eat_whitespace = False
pattern = (r'^(?P
text\nmoretext\n\nevenmoretext\n\nmoremoretext
\n\n\ttest
' @@ -54,6 +57,7 @@ def test_blockcode_extended(): result = t.parse(input) assert result == expect + def test_blockcode_in_README(): with open('README.textile') as f: readme = ''.join(f.readlines()) @@ -62,6 +66,7 @@ def test_blockcode_in_README(): expect = ''.join(f.readlines()) assert result == expect + def test_blockcode_comment(): input = '###.. block comment\nanother line\n\np. New line' expect = '\tNew line
' From 73adb81c5cf614b80aebe4121a94648770e10909 Mon Sep 17 00:00:00 2001 From: Dennis BurkeYACC1
', html) is not None + def test_Footnote(): html = textile.textile('This is covered elsewhere[1].\n\nfn1. Down here, in fact.\n\nfn2. Here is another footnote.') assert re.search(r'^\tThis is covered elsewhere1.
\n\n\t1 Down here, in fact.
\n\n\t2 Here is another footnote.
$', html) is not None @@ -24,6 +26,7 @@ def test_Footnote(): html = textile.textile('''See[4!] for details.\n\nfn4^. Here are the details.''') assert re.search(r'^\tSee4 for details.
\n\n\t4 Here are the details.
$', html) is not None + def test_issue_35(): result = textile.textile('"z"') expect = '\t“z”
' @@ -33,8 +36,9 @@ def test_issue_35(): expect = '\t“ z”
' assert result == expect + def test_restricted(): - #Note that the HTML is escaped, thus rendering the " result = textile.textile_restricted(test) expect = "\tHere is some text.
\n<script>alert(‘hello world’)</script>
текст1
$', re.U).search(html) is not None + def test_autolinking(): test = """some text "test":http://www.google.com http://www.google.com "$":http://www.google.com""" result = """\tsome text test http://www.google.com www.google.com
""" @@ -104,6 +110,7 @@ def test_autolinking(): assert result == expect + def test_sanitize(): test = "a paragraph of benign text" result = "\ta paragraph of benign text
" @@ -120,14 +127,16 @@ def test_sanitize(): expect = textile.Textile(html_type='html5').parse(test, sanitize=True) assert result == expect + def test_imagesize(): - PIL = pytest.importorskip('PIL') # noqa: F841 + PIL = pytest.importorskip('PIL') # noqa: F841 test = "!http://www.google.com/intl/en_ALL/images/srpr/logo1w.png!" result = '\t' expect = textile.Textile(get_sizes=True).parse(test) assert result == expect + def test_endnotes_simple(): test = """Scientists say the moon is slowly shrinking[#my_first_label].\n\nnotelist!.\n\nnote#my_first_label Over the past billion years, about a quarter of the moon's 4.5 billion-year lifespan, it has shrunk about 200 meters (700 feet) in diameter.""" html = textile.textile(test) @@ -135,6 +144,7 @@ def test_endnotes_simple(): result_re = re.compile(result_pattern) assert result_re.search(html) is not None + def test_endnotes_complex(): test = """Tim Berners-Lee is one of the pioneer voices in favour of Net Neutrality[#netneutral] and has expressed the view that ISPs should supply "connectivity with no strings attached"[#netneutral!] [#tbl_quote]\n\nBerners-Lee admitted that the forward slashes ("//") in a web address were actually unnecessary. He told the newspaper that he could easily have designed URLs not to have the forward slashes. "... it seemed like a good idea at the time,"[#slashes]\n\nnote#netneutral. "Web creator rejects net tracking":http://news.bbc.co.uk/2/hi/technology/7613201.stm. BBC. 15 September 2008\n\nnote#tbl_quote. "Web inventor's warning on spy software":http://www.telegraph.co.uk/news/uknews/1581938/Web-inventor%27s-warning-on-spy-software.html. The Daily Telegraph (London). 25 May 2008\n\nnote#slashes. "Berners-Lee 'sorry' for slashes":http://news.bbc.co.uk/1/hi/technology/8306631.stm. BBC. 14 October 2009\n\nnotelist.""" html = textile.textile(test) @@ -142,6 +152,7 @@ def test_endnotes_complex(): result_re = re.compile(result_pattern) assert result_re.search(html) is not None + def test_endnotes_unreferenced_note(): test = """Scientists say[#lavader] the moon is quite small. But I, for one, don't believe them. Others claim it to be made of cheese[#aardman]. If this proves true I suspect we are in for troubled times[#apollo13] as people argue over their "share" of the moon's cheese. In the end, its limited size[#lavader] may prove problematic.\n\nnote#lavader(noteclass). "Proof of the small moon hypothesis":http://antwrp.gsfc.nasa.gov/apod/ap080801.html. Copyright(c) Laurent Laveder\n\nnote#aardman(#noteid). "Proof of a cheese moon":http://www.imdb.com/title/tt0104361\n\nnote#apollo13. After all, things do go "wrong":http://en.wikipedia.org/wiki/Apollo_13#The_oxygen_tank_incident.\n\nnotelist{padding:1em; margin:1em; border-bottom:1px solid gray}.\n\nnotelist{padding:1em; margin:1em; border-bottom:1px solid gray}:§^.\n\nnotelist{padding:1em; margin:1em; border-bottom:1px solid gray}:‡""" html = textile.textile(test) @@ -149,6 +160,7 @@ def test_endnotes_unreferenced_note(): result_re = re.compile(result_pattern, re.U) assert result_re.search(html) is not None + def test_endnotes_malformed(): test = """Scientists say[#lavader] the moon is quite small. But I, for one, don't believe them. Others claim it to be made of cheese[#aardman]. If this proves true I suspect we are in for troubled times[#apollo13!] as people argue over their "share" of the moon's cheese. In the end, its limited size[#lavader] may prove problematic.\n\nnote#unused An unreferenced note.\n\nnote#lavader^ "Proof of the small moon hypothesis":http://antwrp.gsfc.nasa.gov/apod/ap080801.html. Copyright(c) Laurent Laveder\n\nnote#aardman^ "Proof of a cheese moon":http://www.imdb.com/title/tt0104361\n\nnote#apollo13^ After all, things do go "wrong":http://en.wikipedia.org/wiki/Apollo_13#The_oxygen_tank_incident.\n\nnotelist{padding:1em; margin:1em; border-bottom:1px solid gray}:α!+""" html = textile.textile(test) @@ -156,6 +168,7 @@ def test_endnotes_malformed(): result_re = re.compile(result_pattern, re.U) assert result_re.search(html) is not None + def test_endnotes_undefined_note(): test = """Scientists say the moon is slowly shrinking[#my_first_label].\n\nnotelist!.""" html = textile.textile(test) @@ -163,6 +176,7 @@ def test_endnotes_undefined_note(): result_re = re.compile(result_pattern) assert result_re.search(html) is not None + def test_encode_url(): # I tried adding these as doctests, but the unicode tests weren't # returning the correct results. @@ -198,21 +212,25 @@ def test_encode_url(): eurl = t.encode_url(url) assert eurl == result + def test_footnote_crosslink(): html = textile.textile('''See[2] for details, and later, reference it again[2].\n\nfn2^(footy#otherid)[en]. Here are the details.''') searchstring = r'\tSee2 for details, and later, reference it again2.
\n\n\t2 Here are the details.
$' assert re.compile(searchstring).search(html) is not None + def test_footnote_without_reflink(): html = textile.textile('''See[3!] for details.\n\nfn3. Here are the details.''') searchstring = r'^\tSee3 for details.
\n\n\t3 Here are the details.
$' assert re.compile(searchstring).search(html) is not None + def testSquareBrackets(): html = textile.textile("""1[^st^], 2[^nd^], 3[^rd^]. 2 log[~n~]\n\nA close[!http://textpattern.com/favicon.ico!]image.\nA tight["text":http://textpattern.com/]link.\nA ["footnoted link":http://textpattern.com/][182].""") searchstring = r'^\t1st, 2nd, 3rd. 2 logn
\n\n\tA closeimage.
\nA tighttextlink.
\nA footnoted link182.
A link that contains a\nnewline raises an exception.
' assert result == expect + def test_rel_attribute(): t = Textile(rel='nofollow') result = t.parse('"$":http://domain.tld') expect = '\t' assert result == expect + def test_quotes_in_link_text(): """quotes in link text are tricky.""" test = '""this is a quote in link text"":url' From d0b90435eb3f7f4bc17925544f962d14d92b908a Mon Sep 17 00:00:00 2001 From: Dennis Burkegoogle.com google.com blackhole@sun.comet
' assert result == expect + def test_github_issue_17(): result = textile.textile('!http://www.ox.ac.uk/favicon.ico!') expect = '\t' assert result == expect + def test_github_issue_20(): text = 'This is a link to a ["Wikipedia article about Textile":http://en.wikipedia.org/wiki/Textile_(markup_language)].' result = textile.textile(text) expect = '\tThis is a link to a Wikipedia article about Textile.
' assert result == expect + def test_github_issue_21(): - text = '''h1. xml example + text = ('''h1. xml example -bc. +bc. ''' + '''\n<foo>\n bar\n</foo>
'
assert result == expect
+
def test_github_issue_22():
text = '''_(artist-name)Ty Segall_’s'''
result = textile.textile(text)
expect = '\tTy Segall’s
' assert result == expect + def test_github_issue_26(): text = '' result = textile.textile(text) expect = '' assert result == expect + def test_github_issue_27(): test = """* Folders with ":" in their names are displayed with a forward slash "/" instead. (Filed as "#4581709":/test/link, which was considered "normal behaviour" - quote: "Please note that Finder presents the 'Carbon filesystem' view, regardless of the underlying filesystem.")""" result = textile.textile(test) expect = """\tOf course there’s a lot more error handling to do (and useful data to glean off the XML), but being able to cut through all the usual parsing crap is immensely gratifying.
""") assert result == expect + def test_github_issue_30(): - text ='"Tëxtíle (Tëxtíle)":http://lala.com' + text = '"Tëxtíle (Tëxtíle)":http://lala.com' result = textile.textile(text) expect = '\t' assert result == expect - text ='!http://lala.com/lol.gif(♡ imáges)!' + text = '!http://lala.com/lol.gif(♡ imáges)!' result = textile.textile(text) expect = '\t' assert result == expect + def test_github_issue_36(): text = '"Chögyam Trungpa":https://www.google.com/search?q=Chögyam+Trungpa' result = textile.textile(text) expect = '\t' assert result == expect + def test_github_issue_37(): text = '# xxx\n# yyy\n*blah*' result = textile.textile(text) @@ -118,24 +130,28 @@ def test_github_issue_37(): \t''' assert result == expect + def test_github_issue_40(): text = '\r\n' result = textile.textile(text) expect = '\r\n' assert result == expect + def test_github_issue_42(): text = '!./image.png!' result = textile.textile(text) expect = '\t' assert result == expect + def test_github_issue_43(): text = 'pre. smart ‘quotes’ are not smart!' result = textile.textile(text) expect = 'smart ‘quotes’ are not smart!' assert result == expect + def test_github_issue_45(): """Incorrect transform unicode url""" text = '"test":https://myabstractwiki.ru/index.php/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0' @@ -143,6 +159,7 @@ def test_github_issue_45(): expect = '\t' assert result == expect + def test_github_issue_46(): """Key error on mal-formed numbered lists. CAUTION: both the input and the ouput are ugly.""" @@ -153,6 +170,7 @@ def test_github_issue_46(): result = textile.textile(text) assert result == expect + def test_github_issue_47(): """Incorrect wrap pre-formatted value""" text = '''pre.. word @@ -172,6 +190,7 @@ def test_github_issue_47(): yet anothe word''' assert result == expect + def test_github_issue_49(): """Key error on russian hash-route link""" s = '"link":https://ru.vuejs.org/v2/guide/components.html#Входные-параметры' @@ -179,6 +198,7 @@ def test_github_issue_49(): expect = '\t' assert result == expect + def test_github_issue_50(): """Incorrect wrap code with Java generics in pre""" test = ('pre.. public class Tynopet
This is some TEXT inside a "Code BLOCK"
@@ -299,6 +325,7 @@ def test_github_pull_61():
result = t.parse(test)
assert result == expect
+
def test_github_pull_62():
"""Fix for paragraph multiline, only last paragraph is rendered
correctly"""
@@ -341,6 +368,7 @@ def test_github_pull_62():
result = t.parse(test)
assert result == expect
+
def test_github_pull_63():
"""Forgot to set multiline_para to False"""
test = '''p.. First one 'is'
From ed17a4f0fd10acbb51a8a6c8af47efa7fa0fa6d4 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:36:35 -0500
Subject: [PATCH 045/228] flake8: whitespace cleanup
---
tests/test_cli.py | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 5f6e501..57b2d5f 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -3,28 +3,30 @@
import textile
+
def test_console_script():
command = [sys.executable, '-m', 'textile', 'README.textile']
try:
result = subprocess.check_output(command)
except AttributeError:
command[2] = 'textile.__main__'
- result = subprocess.Popen(command,
- stdout=subprocess.PIPE).communicate()[0]
+ result = subprocess.Popen(
+ command, stdout=subprocess.PIPE).communicate()[0]
with open('tests/fixtures/README.txt') as f:
expect = ''.join(f.readlines())
if type(result) == bytes:
result = result.decode('utf-8')
assert result == expect
+
def test_version_string():
command = [sys.executable, '-m', 'textile', '-v']
try:
result = subprocess.check_output(command)
except AttributeError:
command[2] = 'textile.__main__'
- result = subprocess.Popen(command,
- stdout=subprocess.PIPE).communicate()[0]
+ result = subprocess.Popen(
+ command, stdout=subprocess.PIPE).communicate()[0]
if type(result) == bytes:
result = result.decode('utf-8')
assert result.strip() == textile.__version__
From b010a31482fceeb0fb228c959b18ce48be68aed1 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:52:50 -0500
Subject: [PATCH 046/228] flake8: whitespace cleanup
---
tests/test_attributes.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_attributes.py b/tests/test_attributes.py
index 0f5d019..b07712f 100644
--- a/tests/test_attributes.py
+++ b/tests/test_attributes.py
@@ -1,5 +1,6 @@
from textile.utils import parse_attributes
+
def test_parse_attributes():
assert parse_attributes('\\1', element='td') == {'colspan': '1'}
assert parse_attributes('/1', element='td') == {'rowspan': '1'}
From ba71882313124d17d9d6deb87fd10a8cc250dbee Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:53:42 -0500
Subject: [PATCH 047/228] flake8: whitespace cleanup
---
tests/test_getimagesize.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_getimagesize.py b/tests/test_getimagesize.py
index 43f85e3..3a3c0a9 100644
--- a/tests/test_getimagesize.py
+++ b/tests/test_getimagesize.py
@@ -3,6 +3,7 @@
PIL = pytest.importorskip('PIL')
+
def test_imagesize():
assert getimagesize("http://www.google.com/intl/en_ALL/images/logo.gif") == (276, 110)
assert getimagesize("http://bad.domain/") == ''
From 00ac6423fcecc6d164a2cde1bb547dca8c0c59f8 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:55:41 -0500
Subject: [PATCH 048/228] flake8: whitespace cleanup
---
tests/test_glyphs.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_glyphs.py b/tests/test_glyphs.py
index 56b0d27..ed50ad5 100644
--- a/tests/test_glyphs.py
+++ b/tests/test_glyphs.py
@@ -1,5 +1,6 @@
from textile import Textile
+
def test_glyphs():
t = Textile()
From 19936d813275f19465fbb695559961f72a983cab Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:57:52 -0500
Subject: [PATCH 049/228] flake8: whitespace cleanup
---
tests/test_subclassing.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/test_subclassing.py b/tests/test_subclassing.py
index 9235e03..a7db99a 100644
--- a/tests/test_subclassing.py
+++ b/tests/test_subclassing.py
@@ -1,10 +1,10 @@
import textile
+
def test_change_glyphs():
class TextilePL(textile.Textile):
glyph_definitions = dict(textile.Textile.glyph_definitions,
- quote_double_open = '„'
- )
+ quote_double_open='„')
test = 'Test "quotes".'
expect = '\tTest „quotes”.
'
From 5c61671087751271a37c8283c02e84a4f0f505df Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:58:40 -0500
Subject: [PATCH 050/228] flake8: whitespace cleanup
---
tests/test_imagesize.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tests/test_imagesize.py b/tests/test_imagesize.py
index 0a89b43..e7d9d88 100644
--- a/tests/test_imagesize.py
+++ b/tests/test_imagesize.py
@@ -1,10 +1,11 @@
import textile
+
def test_imagesize():
imgurl = 'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png'
result = textile.tools.imagesize.getimagesize(imgurl)
try:
- import PIL # noqa: F401
+ import PIL # noqa: F401
expect = (275, 95)
assert result == expect
From 8db86d6149017837e1ad7d91d09303b70e2cfb75 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:17:17 -0500
Subject: [PATCH 051/228] flake8: whitespace cleanup
---
tests/test_textilefactory.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_textilefactory.py b/tests/test_textilefactory.py
index 846b927..e9fc027 100644
--- a/tests/test_textilefactory.py
+++ b/tests/test_textilefactory.py
@@ -1,6 +1,7 @@
from textile import textilefactory
import pytest
+
def test_TextileFactory():
f = textilefactory.TextileFactory()
result = f.process("some text here")
From db0626b36f14a85b715d00f19b51ef43eece419f Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:18:01 -0500
Subject: [PATCH 052/228] flake8: whitespace cleanup
---
tests/test_getRefs.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_getRefs.py b/tests/test_getRefs.py
index d3cfcd7..8a22d4f 100644
--- a/tests/test_getRefs.py
+++ b/tests/test_getRefs.py
@@ -1,5 +1,6 @@
from textile import Textile
+
def test_getRefs():
t = Textile()
result = t.getRefs("some text [Google]http://www.google.com")
From d6d7f995aa35187215bea5a83ce5b7dab8305f9d Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:18:34 -0500
Subject: [PATCH 053/228] flake8: whitespace cleanup
---
tests/test_footnoteRef.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_footnoteRef.py b/tests/test_footnoteRef.py
index c973ee7..5ac2ea4 100644
--- a/tests/test_footnoteRef.py
+++ b/tests/test_footnoteRef.py
@@ -1,5 +1,6 @@
from textile import Textile
+
def test_footnoteRef():
t = Textile()
result = t.footnoteRef('foo[1]')
From 325014da65763d42dc86c50a99f17512ec143373 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:19:14 -0500
Subject: [PATCH 054/228] flake8: whitespace cleanup
---
tests/test_table.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_table.py b/tests/test_table.py
index 0a3cb0d..1ea34e9 100644
--- a/tests/test_table.py
+++ b/tests/test_table.py
@@ -1,5 +1,6 @@
from textile import Textile
+
def test_table():
t = Textile()
result = t.table('(rowclass). |one|two|three|\n|a|b|c|')
From cbb6bb71cf7c6165aadd1b29c59331542039e233 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:21:12 -0500
Subject: [PATCH 055/228] flake8: whitespace cleanup
---
tests/test_values.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/test_values.py b/tests/test_values.py
index 063ed3e..5b2b7e3 100644
--- a/tests/test_values.py
+++ b/tests/test_values.py
@@ -309,12 +309,14 @@
('Hello ["(Mum) & dad"]', '\tHello [“(Mum) & dad”]
'),
)
+
@pytest.mark.parametrize("input, expected_output", xhtml_known_values)
def test_KnownValuesXHTML(input, expected_output):
# XHTML
output = textile.textile(input, html_type='xhtml')
assert output == expected_output
+
@pytest.mark.parametrize("input, expected_output", html_known_values)
def test_KnownValuesHTML(input, expected_output):
# HTML5
From 8cb3bf7b95f49af518a4a3231043f35be9788835 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:21:42 -0500
Subject: [PATCH 056/228] flake8: whitespace cleanup
---
tests/test_values.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tests/test_values.py b/tests/test_values.py
index 5b2b7e3..12dae55 100644
--- a/tests/test_values.py
+++ b/tests/test_values.py
@@ -35,7 +35,7 @@
('h3. Header 3', '\tHeader 3
'),
('An old text\n\nbq. A block quotation.\n\nAny old text''',
- '\tAn old text
\n\n\t\n\t\tA block quotation.
\n\t
\n\n\tAny old text
'),
+ '\tAn old text
\n\n\t\n\t\tA block quotation.
\n\t
\n\n\tAny old text
'),
('I _believe_ every word.', '\tI believe every word.
'),
@@ -70,8 +70,8 @@
('p[fr]. rouge', '\trouge
'),
('I seriously *{color:red}blushed*\nwhen I _(big)sprouted_ that\ncorn stalk from my\n%[es]cabeza%.',
- '\tI seriously blushed
\nwhen I sprouted'
- ' that
\ncorn stalk from my
\ncabeza.
'),
+ '\tI seriously blushed
\nwhen I sprouted'
+ ' that
\ncorn stalk from my
\ncabeza.
'),
('p<. align left', '\talign left
'),
@@ -226,7 +226,7 @@
("""table(#dvds){border-collapse:collapse}. Great films on DVD employing Textile summary, caption, thead, tfoot, two tbody elements and colgroups\n|={font-size:140%;margin-bottom:15px}. DVDs with two Textiled tbody elements\n|:\\3. 100 |{background:#ddd}|250||50|300|\n|^(header).\n|_. Title |_. Starring |_. Director |_. Writer |_. Notes |\n|~(footer).\n|\\5=. This is the tfoot, centred |\n|-(toplist){background:#c5f7f6}.\n| _The Usual Suspects_ | Benicio Del Toro, Gabriel Byrne, Stephen Baldwin, Kevin Spacey | Bryan Singer | Chris McQaurrie | One of the finest films ever made |\n| _Se7en_ | Morgan Freeman, Brad Pitt, Kevin Spacey | David Fincher | Andrew Kevin Walker | Great psychological thriller |\n| _Primer_ | David Sullivan, Shane Carruth | Shane Carruth | Shane Carruth | Amazing insight into trust and human psychology
rather than science fiction. Terrific! |\n| _District 9_ | Sharlto Copley, Jason Cope | Neill Blomkamp | Neill Blomkamp, Terri Tatchell | Social commentary layered on thick,\nbut boy is it done well |\n|-(medlist){background:#e7e895;}.\n| _Arlington Road_ | Tim Robbins, Jeff Bridges | Mark Pellington | Ehren Kruger | Awesome study in neighbourly relations |\n| _Phone Booth_ | Colin Farrell, Kiefer Sutherland, Forest Whitaker | Joel Schumacher | Larry Cohen | Edge-of-the-seat stuff in this\nshort but brilliantly executed thriller |""",
"""\t\n\tDVDs with two Textiled tbody elements \n\t\n\t \n\t \n\t \n\t \n\t \n\t \n\t\n\t\t\n\t\t\tTitle \n\t\t\tStarring \n\t\t\tDirector \n\t\t\tWriter \n\t\t\tNotes \n\t\t \n\t\n\t\n\t\t\n\t\t\tThis is the tfoot, centred \n\t\t \n\t\n\t\n\t\t\n\t\t\t The Usual Suspects \n\t\t\t Benicio Del Toro, Gabriel Byrne, Stephen Baldwin, Kevin Spacey \n\t\t\t Bryan Singer \n\t\t\t Chris McQaurrie \n\t\t\t One of the finest films ever made \n\t\t \n\t\t\n\t\t\t Se7en \n\t\t\t Morgan Freeman, Brad Pitt, Kevin Spacey \n\t\t\t David Fincher \n\t\t\t Andrew Kevin Walker \n\t\t\t Great psychological thriller \n\t\t \n\t\t\n\t\t\t Primer \n\t\t\t David Sullivan, Shane Carruth \n\t\t\t Shane Carruth \n\t\t\t Shane Carruth \n\t\t\t Amazing insight into trust and human psychology
\nrather than science fiction. Terrific! \n\t\t \n\t\t\n\t\t\t District 9 \n\t\t\t Sharlto Copley, Jason Cope \n\t\t\t Neill Blomkamp \n\t\t\t Neill Blomkamp, Terri Tatchell \n\t\t\t Social commentary layered on thick,
\nbut boy is it done well \n\t\t \n\t\n\t\n\t\t\n\t\t\t Arlington Road \n\t\t\t Tim Robbins, Jeff Bridges \n\t\t\t Mark Pellington \n\t\t\t Ehren Kruger \n\t\t\t Awesome study in neighbourly relations \n\t\t \n\t\t\n\t\t\t Phone Booth \n\t\t\t Colin Farrell, Kiefer Sutherland, Forest Whitaker \n\t\t\t Joel Schumacher \n\t\t\t Larry Cohen \n\t\t\t Edge-of-the-seat stuff in this
\nshort but brilliantly executed thriller \n\t\t \n\t\n\t
"""),
("""-(hot) *coffee* := Hot _and_ black\n-(hot#tea) tea := Also hot, but a little less black\n-(cold) milk := Nourishing beverage for baby cows.\nCold drink that goes great with cookies. =:\n\n-(hot) coffee := Hot and black\n-(hot#tea) tea := Also hot, but a little less black\n-(cold) milk :=\nNourishing beverage for baby cows.\nCold drink that goes great with cookies. =:""",
- """\n\t- coffee
\n\t- Hot and black
\n\t- tea
\n\t- Also hot, but a little less black
\n\t- milk
\n\t- Nourishing beverage for baby cows.
\nCold drink that goes great with cookies. \n
\n\n\n\t- coffee
\n\t- Hot and black
\n\t- tea
\n\t- Also hot, but a little less black
\n\t- milk
\n\tNourishing beverage for baby cows.
\nCold drink that goes great with cookies.
\n
"""),
+ """\n\t- coffee
\n\t- Hot and black
\n\t- tea
\n\t- Also hot, but a little less black
\n\t- milk
\n\t- Nourishing beverage for baby cows.
\nCold drink that goes great with cookies. \n
\n\n\n\t- coffee
\n\t- Hot and black
\n\t- tea
\n\t- Also hot, but a little less black
\n\t- milk
\n\tNourishing beverage for baby cows.
\nCold drink that goes great with cookies.
\n
"""),
(""";(class#id) Term 1\n: Def 1\n: Def 2\n: Def 3""",
"""\t\n\t\t- Term 1
\n\t\t- Def 1
\n\t\t- Def 2
\n\t\t- Def 3
\n\t
"""),
("""*Here is a comment*\n\nHere is *(class)a comment*\n\n*(class)Here is a class* that is a little extended and is\n*followed* by a strong word!\n\nbc. ; Content-type: text/javascript\n; Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\n; Expires: Sat, 24 Jul 2003 05:00:00 GMT\n; Last-Modified: Wed, 1 Jan 2025 05:00:00 GMT\n; Pragma: no-cache\n\n*123 test*\n\n*test 123*\n\n**123 test**\n\n**test 123**""",
@@ -258,8 +258,8 @@
('I __know__.\nI **really** __know__.', '\tI know.
\nI really know.
'),
("I'm %{color:red}unaware%\nof most soft drinks.", '\tI’m unaware
\nof most soft drinks.
'),
('I seriously *{color:red}blushed*\nwhen I _(big)sprouted_ that\ncorn stalk from my\n%[es]cabeza%.',
- '\tI seriously blushed
\nwhen I sprouted'
- ' that
\ncorn stalk from my
\ncabeza.
'),
+ '\tI seriously blushed
\nwhen I sprouted'
+ ' that
\ncorn stalk from my
\ncabeza.
'),
('\n\na.gsub!( /, "" )\n
\n
',
'\n\na.gsub!( /</, "" )\n
\n
'),
('\n\nh3. Sidebar\n\n"Hobix":http://hobix.com/\n"Ruby":http://ruby-lang.org/\n\n\n\n'
From 1b65dc74c51493f6167d661338112b5506c11f33 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:22:50 -0500
Subject: [PATCH 057/228] flake8: whitespace cleanup
---
tests/test_utils.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 7f386a9..a6e88f8 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -3,21 +3,25 @@
from textile import utils
+
def test_encode_html():
result = utils.encode_html('''this is a "test" of text that's safe to '''
- 'put in an attribute.')
+ 'put in an attribute.')
expect = ('this is a "test" of text that's safe to put in '
- 'an <html> attribute.')
+ 'an <html> attribute.')
assert result == expect
+
def test_has_raw_text():
assert utils.has_raw_text('foo bar biz baz
') is False
assert utils.has_raw_text(' why yes, yes it does') is True
+
def test_is_rel_url():
assert utils.is_rel_url("http://www.google.com/") is False
assert utils.is_rel_url("/foo") is True
+
def test_generate_tag():
result = utils.generate_tag('span', 'inner text', {'class': 'test'})
expect = 'inner text'
From 30c4eef40b5a5391802287a49f34e73914a5425e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:25:27 -0500
Subject: [PATCH 058/228] turn flake8 warnings and errors back on
---
.flake8 | 3 ---
1 file changed, 3 deletions(-)
diff --git a/.flake8 b/.flake8
index 07c24d1..9f8ccc3 100644
--- a/.flake8
+++ b/.flake8
@@ -2,8 +2,5 @@
ignore =
# line too long
E501
- # temporarily ignore warnings and errors
- W
- E
exclude =
build/
From 157ff1edac900c1135ca0b6f2d6f5830ffa60894 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:35:36 -0500
Subject: [PATCH 059/228] use environment vars as intended
maybe this will fix a warning about unexpected inputs ???
---
.github/workflows/lint_and_test.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 437820d..f82f4c2 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -20,9 +20,10 @@ jobs:
- name: Python flake8 Lint
uses: py-actions/flake8@v1.2.0
- name: Install dependencies
+ env:
+ IMAGESIZE: ${{ matrix.image-size }}
run: |
imagesize=''
- IMAGESIZE=${{ matrix.image-size }}
pip install -U pytest pytest-cov coverage codecov
if [[ $IMAGESIZE == true ]] ; then imagesize='[imagesize]' ; fi
pip install -e ".${imagesize}"
From a4b09ab08ec36087ac66c694f185545a76e31ca0 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:42:24 -0500
Subject: [PATCH 060/228] further testing of environment variables
---
.github/workflows/lint_and_test.yml | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index f82f4c2..5ba1e86 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -9,7 +9,7 @@ jobs:
strategy:
matrix:
python-version: [3.5, 3.6, 3.7, 3.8, 3.9]
- image-size: ['true', 'false']
+ image_size: ['true', 'false']
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
@@ -20,12 +20,10 @@ jobs:
- name: Python flake8 Lint
uses: py-actions/flake8@v1.2.0
- name: Install dependencies
- env:
- IMAGESIZE: ${{ matrix.image-size }}
run: |
imagesize=''
pip install -U pytest pytest-cov coverage codecov
- if [[ $IMAGESIZE == true ]] ; then imagesize='[imagesize]' ; fi
+ if [[ $INPUT_IMAGE_SIZE == true ]] ; then imagesize='[imagesize]' ; fi
pip install -e ".${imagesize}"
- name: run tests
run: |
From 674ed26891970f213a0e692cab1e21da502348a3 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:44:45 -0500
Subject: [PATCH 061/228] This is probably the source of the `unexpected
inputs` warning
---
.github/workflows/lint_and_test.yml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 5ba1e86..47ce8cf 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -16,7 +16,6 @@ jobs:
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- image-size: ${{ matrix.image-size }}
- name: Python flake8 Lint
uses: py-actions/flake8@v1.2.0
- name: Install dependencies
From 16b70594b23947ccc3c4154369727215e0a7e4b6 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:49:10 -0500
Subject: [PATCH 062/228] add pypy3 to github actions
---
.github/workflows/lint_and_test.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 47ce8cf..0db7ea8 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: [3.5, 3.6, 3.7, 3.8, 3.9]
+ python-version: [3.5, 3.6, 3.7, 3.8, 3.9, pypy3]
image_size: ['true', 'false']
steps:
- uses: actions/checkout@v2
From cdfa9490bea32b33bde09dac83ff3b219fafd4d8 Mon Sep 17 00:00:00 2001
From: Kirill Mavreshko
Date: Wed, 31 Aug 2022 12:56:49 +0500
Subject: [PATCH 063/228] Fix wrong output when "bc.." is the last block #81
---
tests/fixtures/README.txt | 2 +-
tests/test_values.py | 8 ++++++++
textile/core.py | 9 ++++-----
3 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/tests/fixtures/README.txt b/tests/fixtures/README.txt
index 61dc0f0..949db70 100644
--- a/tests/fixtures/README.txt
+++ b/tests/fixtures/README.txt
@@ -60,4 +60,4 @@
When textile is not installed locally:
-PYTHONPATH=. pytest\ No newline at end of file +
PYTHONPATH=. pytest
\ No newline at end of file
diff --git a/tests/test_values.py b/tests/test_values.py
index 063ed3e..9792881 100644
--- a/tests/test_values.py
+++ b/tests/test_values.py
@@ -254,6 +254,14 @@
# A few extra cases for HTML4
html_known_values = (
+ ("pre.. The beginning\n\nbc.. This code\n\nis the last\n\nblock in the document\n",
+ "The beginning\n\n
This code\n\nis the last\n\nblock in the document
"),
+ ("bc.. This code\n\nis not\n\nsurrounded by anything\n",
+ "This code\n\nis not\n\nsurrounded by anything
"),
+ ("bc.. Paragraph 1\n\nParagraph 2\n\nParagraph 3\n\np.. post-code paragraph",
+ "Paragraph 1\n\nParagraph 2\n\nParagraph 3
\n\npost-code paragraph
"), + ("bc.. Paragraph 1\n\nParagraph 2\n\nParagraph 3\n\npre.. post-code non-p block", + "Paragraph 1\n\nParagraph 2\n\nParagraph 3
\n\npost-code non-p block"), ('I spoke.\nAnd none replied.', '\t
I spoke.
\nAnd none replied.
I know.
\nI really know.
I’m unaware
\nof most soft drinks.
\n\t\t'), ('Hello ["(Mum) & dad"]', '\tText…
\n\t
Hello [“(Mum) & dad”]
'), + # Dimensions + ( + ('[1/2] x [1/4] and (1/2)" x [1/4]" and (1/2)\' x (1/4)\'\n\n' + '(2 x 10) X (3 / 4) x (200 + 64)\n\n' + '1 x 1 = 1\n\n' + '1 x1 = 1\n\n' + '1x 1 = 1\n\n' + '1x1 = 1\n\n' + '1 X 1 = 1\n\n' + '1 X1 = 1\n\n' + '1X 1 = 1\n\n' + '1X1 = 1\n\n' + 'What is 1 x 1?\n\n' + 'What is 1x1?\n\n' + 'What is 1 X 1?\n\n' + 'What is 1X1?\n\n' + '1 x 2 x 3 = 6\n\n' + '1x2x3=6\n\n' + '1x2 x 1x3 = 6\n\n' + '2\' x 2\' = 4 sqft.\n\n' + '2\'x 2\' = 4 sqft.\n\n' + '2\' x2\' = 4 sqft.\n\n' + '2\'x2\' = 4 sqft.\n\n' + '2\' X 2\' = 4 sqft.\n\n' + '2\'X 2\' = 4 sqft.\n\n' + '2\' X2\' = 4 sqft.\n\n' + '2\'X2\' = 4 sqft.\n\n' + '2" x 2" = 4 sqin.\n\n' + '2"x 2" = 4 sqin.\n\n' + '2" x2" = 4 sqin.\n\n' + '2"x2" = 4 sqin.\n\n' + '2" X 2" = 4 sqin.\n\n' + '2"X 2" = 4 sqin.\n\n' + '2" X2" = 4 sqin.\n\n' + '2"X2" = 4in[^2^].\n\n' + 'What is 1.2 x 3.5?\n\n' + 'What is .2 x .5?\n\n' + 'What is 1.2x3.5?\n\n' + 'What is .2x.5?\n\n' + 'What is 1.2\' x3.5\'?\n\n' + 'What is .2"x .5"?\n\n' + '1 x $10.00 x -£ 1.23 x ¥20,000 x -¤120.00 x ฿1,000,000 x -€110,00\n\n'), + + ('\t½ × ¼ and ½” × ¼” and ½’ × ¼’
\n\n' + '\t(2 × 10) × (3 / 4) × (200 + 64)
\n\n' + '\t1 × 1 = 1
\n\n' + '\t1 ×1 = 1
\n\n' + '\t1× 1 = 1
\n\n' + '\t1×1 = 1
\n\n' + '\t1 × 1 = 1
\n\n' + '\t1 ×1 = 1
\n\n' + '\t1× 1 = 1
\n\n' + '\t1×1 = 1
\n\n' + '\tWhat is 1 × 1?
\n\n' + '\tWhat is 1×1?
\n\n' + '\tWhat is 1 × 1?
\n\n' + '\tWhat is 1×1?
\n\n' + '\t1 × 2 × 3 = 6
\n\n' + '\t1×2×3=6
\n\n' + '\t1×2 × 1×3 = 6
\n\n' + '\t2’ × 2’ = 4 sqft.
\n\n' + '\t2’× 2’ = 4 sqft.
\n\n' + '\t2’ ×2’ = 4 sqft.
\n\n' + '\t2’×2’ = 4 sqft.
\n\n' + '\t2’ × 2’ = 4 sqft.
\n\n' + '\t2’× 2’ = 4 sqft.
\n\n' + '\t2’ ×2’ = 4 sqft.
\n\n' + '\t2’×2’ = 4 sqft.
\n\n' + '\t2” × 2” = 4 sqin.
\n\n' + '\t2”× 2” = 4 sqin.
\n\n' + '\t2” ×2” = 4 sqin.
\n\n' + '\t2”×2” = 4 sqin.
\n\n' + '\t2” × 2” = 4 sqin.
\n\n' + '\t2”× 2” = 4 sqin.
\n\n' + '\t2” ×2” = 4 sqin.
\n\n' + '\t2”×2” = 4in2.
\n\n' + '\tWhat is 1.2 × 3.5?
\n\n' + '\tWhat is .2 × .5?
\n\n' + '\tWhat is 1.2×3.5?
\n\n' + '\tWhat is .2×.5?
\n\n' + '\tWhat is 1.2’ ×3.5’?
\n\n' + '\tWhat is .2”× .5”?
\n\n' + '\t1 × $10.00 × -£ 1.23 × ¥20,000 × -¤120.00 × ฿1,000,000 × -€110,00
') + ), ) @pytest.mark.parametrize("input, expected_output", xhtml_known_values) diff --git a/textile/core.py b/textile/core.py index 5e74b42..39daa1a 100644 --- a/textile/core.py +++ b/textile/core.py @@ -47,6 +47,12 @@ def make_glyph_replacers(html_type, uid, glyph_defs, is_initial): if regex_snippets['cur'] else r'') pre_result = [ + # dimension sign (before apostrophes/quotes are replaced) + (re.compile( + r'([0-9]+[\])]?[\'"]? ?)[x]( ?[\[(]?)' + r'(?=[+-]?{0}[0-9]*\.?[0-9]+)'.format(cur), + flags=re.I | re.U), + r'\1{dimension}\2'), # apostrophe's (re.compile( (r"(^|{0}|\))'({0})" if not is_initial @@ -97,12 +103,6 @@ def make_glyph_replacers(html_type, uid, glyph_defs, is_initial): (re.compile(r'(\s?)--(\s?)'), r'\1{emdash}\2'), # en dash (re.compile(r' - '), r' {endash} '), - # dimension sign - (re.compile( - r'([0-9]+[\])]?[\'"]? ?)[x]( ?[\[(]?)' - r'(?=[+-]?{0}[0-9]*\.?[0-9]+)'.format(cur), - flags=re.I | re.U), - r'\1{dimension}\2'), # trademark (re.compile( r'(\b ?|{0}|^)[([]TM[])]'.format(regex_snippets['space']), diff --git a/textile/regex_strings.py b/textile/regex_strings.py index 470203c..deb4a4a 100644 --- a/textile/regex_strings.py +++ b/textile/regex_strings.py @@ -26,7 +26,10 @@ 'abr': r'{0}'.format(upper_re_s), 'nab': r'a-z', 'wrd': r'\w', - 'cur': r'', + # All codepoints identified as currency symbols + # by the [mrab-regex library](https://pypi.org/project/regex/) + # and the UNICODE standard. + 'cur': r'$¢-¥֏؋৲৳৻૱௹฿៛\u20a0-\u20cf\ua838﷼﹩$¢£¥₩', 'digit': r'\d', 'space': r'(?:\s|\v)', 'char': r'\S', From 6286b805039880d68ce6442b866ca759c6679496 Mon Sep 17 00:00:00 2001 From: Kirill Mavreshko“z”
' + expect = '\t“z”
' assert result == expect result = textile.textile('" z"') - expect = '\t“ z”
' + expect = '\t“ z”
' assert result == expect def test_restricted(): diff --git a/tests/test_values.py b/tests/test_values.py index 48e8006..b1d8ec9 100644 --- a/tests/test_values.py +++ b/tests/test_values.py @@ -14,7 +14,7 @@ ('I spoke.\nAnd none replied.', '\tI spoke.
\nAnd none replied.
“Observe!”
'), + ('"Observe!"', '\t“Observe!”
'), ('Observe -- very nice!', '\tObserve — very nice!
'), @@ -201,13 +201,13 @@ """\tThe Prisoner
"""), ("""p=. "An emphasised _word._" & "*A spanned phrase.*" """, - """\t“An emphasised word.” & “A spanned phrase.”
"""), + """\t“An emphasised word.” & “A spanned phrase.”
"""), ("""p=. "*Here*'s a word!" """, - """\t“Here’s a word!”
"""), + """\t“Here’s a word!”
"""), ("""p=. "Please visit our "Textile Test Page":http://textile.sitemonks.com" """, - """\t“Please visit our Textile Test Page”
"""), + """\t“Please visit our Textile Test Page”
"""), ("""| Foreign EXPÓŅÉNTIAL |""", """\tForeign EXPÓŅÉNTIAL | \n\t\t
What is .2”× .5”?
\n\n' '\t1 × $10.00 × -£ 1.23 × ¥20,000 × -¤120.00 × ฿1,000,000 × -€110,00
') ), + # Empty note lists + ('There should be nothing below.\n\nnotelist.', '\tThere should be nothing below.
\n\n\t'), ) @pytest.mark.parametrize("input, expected_output", xhtml_known_values) diff --git a/textile/core.py b/textile/core.py index 39daa1a..221890d 100644 --- a/textile/core.py +++ b/textile/core.py @@ -1304,8 +1304,9 @@ def fNoteLists(self, match): o.append(li) self.notelist_cache[index] = "\n".join(o) result = self.notelist_cache[index] - list_atts = pba(att, restricted=self.restricted) - result = 'There should be nothing below.
\n\n\t'), + # Empty things + (('\'\'\n\n""\n\n%%\n\n^^\n\n&&\n\n**\n\n__\n\n--\n\n++\n\n~~\n\n{}\n\n' + '[]\n\n()\n\n<>\n\n\\\\\n\n//\n\n??\n\n==\n\n@@\n\n##\n\n$$\n\n!!\n\n' + '::\n\n;;\n\n..\n\n,,\n\n||\n\n` `\n\n\' \'\n\n" "\n\n% %\n\n^ ^\n\n' + '& &\n\n* *\n\n_ _\n\n- -\n\n+ +\n\n~ ~\n\n{ }\n\n[ ]\n\n( )\n\n< >\n\n' + '\\ \\\n\n/ /\n\n? ?\n\n= =\n\n@ @\n\n# #\n\n$ $\n\n! !\n\n: :\n\n; ;\n\n' + '. .\n\n, ,'), + ("\t‘’
\n\n\t“”
\n\n\t%%
\n\n\t^^
\n\n\t" + "&&
\n\n\t**
\n\n\t__
\n\n\t—
\n\n\t++
\n\n\t" + "~~
\n\n\t{}
\n\n\t[]
\n\n\t()
\n\n\t<>
\n\n\t\\\\
\n\n\t" + "//
\n\n\t??
\n\n\t==
\n\n\t##
\n\n\t$$
\n\n\t" + "!!
\n\n\t::
\n\n\t;;
\n\n\t..
\n\n\t,,
\n\n\t" + "\n\t\t |
` `
\n\n\t‘ ‘
\n\n\t" + "“ “
\n\n\t% %
\n\n\t^ ^
\n\n\t& &
\n\n\t" + "_ _
\n\n\t- -
\n\n\t+ +
\n\n\t~ ~
\n\n\t" + "{ }
\n\n\t[ ]
\n\n\t( )
\n\n\t< >
\n\n\t\\ \\
\n\n\t" + "/ /
\n\n\t? ?
\n\n\t= =
\n\n\t
$ $
\n\n\t! !
\n\n\t. .
\n\n\t, ,
")) ) @pytest.mark.parametrize("input, expected_output", xhtml_known_values) diff --git a/textile/core.py b/textile/core.py index 221890d..f321809 100644 --- a/textile/core.py +++ b/textile/core.py @@ -97,8 +97,6 @@ def make_glyph_replacers(html_type, uid, glyph_defs, is_initial): (re.compile(r'"'), r'{quote_double_open}'), # ellipsis (re.compile(r'([^.]?)\.{3}'), r'\1{ellipsis}'), - # ampersand - (re.compile(r'(\s?)&(\s)', re.U), r'\1{ampersand}\2'), # em dash (re.compile(r'(\s?)--(\s?)'), r'\1{emdash}\2'), # en dash @@ -622,10 +620,20 @@ def glyphs(self, text): text = text.rstrip('\n') result = [] replacers = self.initial_glyph_replacers + standalone_amp_re = re.compile(r'&(?!#?[a-z0-9]+;)', flags=re.I) + html_amp_symbol = self.glyph_definitions['ampersand'] # split the text by any angle-bracketed tags for i, line in enumerate(re.compile(r'(<[\w\/!?].*?>)', re.U).split( text)): if not i % 2: + if not self.restricted: + # Raw < > & chars have already been encoded + # when in restricted mode + line = ( + standalone_amp_re + .sub(html_amp_symbol, line) + .replace('<', '<') + .replace('>', '>')) for s, r in replacers: line = s.sub(r, line) result.append(line) From b8061b505e9359e90efc82b07d4e234208aefada Mon Sep 17 00:00:00 2001 From: Kirill MavreshkoTxStyle is a documentation project of Textile 2.4 for Textpattern CMS.
'), (""""Übermensch":http://de.wikipedia.org/wiki/Übermensch""", """\t"""), ("""Here is some text with a block.\n\n\n\n\n\nbc. """, - """\tHere is some text with a block.
\n\n\t\n\n\t\n\n<!-- Here is a comment block in a code block. -->
"""),
+ """\tHere is some text with a block.
\n\n\n\n\n\n<!-- Here is a comment block in a code block. -->
"""),
(""""Textile(c)" is a registered(r) 'trademark' of Textpattern(tm) -- or TXP(That's textpattern!) -- at least it was - back in '88 when 2x4 was (+/-)5(o)C ... QED!\n\np{font-size: 200%;}. 2(1/4) 3(1/2) 4(3/4)""",
"""\t“Textile©” is a registered® ‘trademark’ of Textpattern™ — or TXP — at least it was – back in ’88 when 2×4 was ±5°C … QED!
\n\n\t2¼ 3½ 4¾
"""), ("""|=. Testing colgroup and col syntax\n|:\\5. 80\n|a|b|c|d|e|\n\n|=. Testing colgroup and col syntax|\n|:\\5. 80|\n|a|b|c|d|e|""", """\ta | \n\t\t\tb | \n\t\t\tc | \n\t\t\td | \n\t\t\te | \n\t\t
a | \n\t\t\tb | \n\t\t\tc | \n\t\t\td | \n\t\t\te | \n\t\t
{ }
\n\n\t[ ]
\n\n\t( )
\n\n\t< >
\n\n\t\\ \\
\n\n\t" "/ /
\n\n\t? ?
\n\n\t= =
\n\n\t
$ $
\n\n\t! !
\n\n\t. .
\n\n\t, ,
")) + ". .
\n\n\t, ,
")), + # A lone standing comment must be preserved as is: + # withouth wrapping it into a paragraph + (('An ordinary block.\n\n' + '\n'), + '\tAn ordinary block.
\n\n'), ) @pytest.mark.parametrize("input, expected_output", xhtml_known_values) diff --git a/textile/utils.py b/textile/utils.py index cd619ed..06a51e7 100644 --- a/textile/utils.py +++ b/textile/utils.py @@ -14,6 +14,18 @@ from textile.regex_strings import valign_re_s, halign_re_s +# Regular expressions for stripping chunks of HTML, +# leaving only content not wrapped in a tag or a comment +RAW_TEXT_REVEALERS = ( + # The php version has orders the below list of tags differently. The + # important thing to note here is that the pre must occur before the p or + # else the regex module doesn't properly match pre-s. It only matches the + # p in pre. + re.compile(r'<(pre|p|blockquote|div|form|table|ul|ol|dl|h[1-6])[^>]*?>.*\1>', + re.S), + re.compile(r'<(hr|br)[^>]*?/>'), + re.compile(r''), +) def decode_high(text): """Decode encoded HTML entities.""" @@ -66,14 +78,10 @@ def generate_tag(tag, content, attributes=None): def has_raw_text(text): """checks whether the text has text not already enclosed by a block tag""" - # The php version has orders the below list of tags differently. The - # important thing to note here is that the pre must occur before the p or - # else the regex module doesn't properly match pre-s. It only matches the - # p in pre. - r = re.compile(r'<(pre|p|blockquote|div|form|table|ul|ol|dl|h[1-6])[^>]*?>.*\1>', - re.S).sub('', text.strip()).strip() - r = re.compile(r'<(hr|br)[^>]*?/>').sub('', r) - return '' != r + r = text.strip() + for pattern in RAW_TEXT_REVEALERS: + r = pattern.sub('', r).strip() + return r != '' def is_rel_url(url): """Identify relative urls.""" From b4c02b8c0c6e176c1dfe4a0dfb7b0ae2eaf7dae6 Mon Sep 17 00:00:00 2001 From: Kirill MavreshkoAn ordinary block.
\n\n'), + # Headers must be "breakable", just like paragraphs. + ('h1. Two line with *strong*\nheading\n', + '\t“test”
\n\n" + "\t“test”
\n\n" + "\ttest
")), ) @pytest.mark.parametrize("input, expected_output", xhtml_known_values) diff --git a/textile/core.py b/textile/core.py index 2c89eb9..f8e478e 100644 --- a/textile/core.py +++ b/textile/core.py @@ -621,7 +621,9 @@ def glyphs(self, text): text = text.rstrip('\n') result = [] replacers = self.initial_glyph_replacers - standalone_amp_re = re.compile(r'&(?!#?[a-z0-9]+;)', flags=re.I) + standalone_amp_re = re.compile( + r"&(?!#[0-9]+;|#x[a-f0-9]+;|[a-z][a-z0-9]*;)", + flags=re.I) html_amp_symbol = self.glyph_definitions['ampersand'] # split the text by any angle-bracketed tags for i, line in enumerate(re.compile(r'(<[\w\/!?].*?>)', re.U).split( From a047b3b6ec7cae8ddd706a22f0aa958187b9fd1d Mon Sep 17 00:00:00 2001 From: Kirill MavreshkoThe Prisoner
"""), ("""p=. "An emphasised _word._" & "*A spanned phrase.*" """, - """\t“An emphasised word.” & “A spanned phrase.”
"""), + """\t“An emphasised word.” & “A spanned phrase.”
"""), ("""p=. "*Here*'s a word!" """, - """\t“Here’s a word!”
"""), + """\t“Here’s a word!”
"""), ("""p=. "Please visit our "Textile Test Page":http://textile.sitemonks.com" """, - """\t“Please visit our Textile Test Page”
"""), + """\t“Please visit our Textile Test Page”
"""), ("""| Foreign EXPÓŅÉNTIAL |""", """\tForeign EXPÓŅÉNTIAL | \n\t\t
“test”
\n\n" "\t“test”
\n\n" "\ttest
")), + # Nested and mixed multi-level ordered and unordered lists + (("* bullet\n" + "*# number\n" + "*# number\n" + "*#* bullet\n" + "*# number\n" + "*# number with\n" + "a break\n" + "* bullet\n" + "** okay"), + ("\ttest
\n\n\ttest
\n\n\t\t
| \n\t\t
\t
| \n\t\t
\n | \n\t\t
\t
| \n\t\t
\t
| \n\t\t
| \n\t\t
table | \n\t\t\tmore | \n\t\t\tbadass | \n\t\t
---|---|---|
Horizontal span of 3 | \n\t\t||
first | \n\t\t\tHAL | \n\t\t\t1 | \n\t\t
some | \n\t\t\tstyled | \n\t\t\tcontent | \n\t\t
spans 2 rows | \n\t\t\tthis is | \n\t\t\tquite a | \n\t\t
deep test | \n\t\t\tdon’t you think? | \n\t\t|
fifth | \n\t\t\tI’m a lumberjack | \n\t\t\t5 | \n\t\t
sixth | \n\t\t\tbold italics | \n\t\t\t6 | \n\t\t
| \n"
+ "\t\t
Nourishing beverage for baby cows.
Here is a ‘spanned’ word.
'), ) @pytest.mark.parametrize("input, expected_output", xhtml_known_values) diff --git a/textile/core.py b/textile/core.py index 07fdf74..8214fc8 100644 --- a/textile/core.py +++ b/textile/core.py @@ -35,7 +35,7 @@ import re -def make_glyph_replacers(html_type, uid, glyph_defs, is_initial): +def make_glyph_replacers(html_type, uid, glyph_defs): """ Generates a list of "replacers" (each is a pair consiting of a regular expression and a replacing pattern) that, @@ -55,8 +55,7 @@ def make_glyph_replacers(html_type, uid, glyph_defs, is_initial): r'\1{dimension}\2'), # apostrophe's (re.compile( - (r"(^|{0}|\))'({0})" if not is_initial - else r"({0}|\))'({0})") + r"({0}|\))'({0})" .format(regex_snippets['wrd']), flags=re.U), r'\1{apostrophe}\2'), @@ -71,11 +70,7 @@ def make_glyph_replacers(html_type, uid, glyph_defs, is_initial): r'\1{quote_single_open}'), # single closing (re.compile( - (r"(^|\S)'(?={0}|{1}|<|$)".format( - regex_snippets['space'], pnct_re_s) - if not is_initial - else r"(\S)'(?={0}|{1}|$)".format( - regex_snippets['space'], pnct_re_s)), + r"(\S)'(?={0}|{1}|<|$)".format(regex_snippets['space'], pnct_re_s), flags=re.U), r'\1{quote_single_close}'), # single opening @@ -86,11 +81,7 @@ def make_glyph_replacers(html_type, uid, glyph_defs, is_initial): r'\1{quote_double_open}'), # double closing (re.compile( - (r'(^|\S)"(?={0}|{1}|<|$)'.format( - regex_snippets['space'], pnct_re_s) - if not is_initial - else r'(\S)"(?={0}|{1}|<|$)'.format( - regex_snippets['space'], pnct_re_s)), + r'(\S)"(?={0}|{1}|<|$)'.format(regex_snippets['space'], pnct_re_s), flags=re.U), r'\1{quote_double_close}'), # double opening @@ -184,6 +175,10 @@ class Textile(object): 'plusminus': '±', } + spanWrappers = ( + ('[', ']'), + ) + def __init__(self, restricted=False, lite=False, noimage=False, get_sizes=False, html_type='xhtml', rel='', block_tags=True): """Textile properties that are common to regular textile and @@ -213,11 +208,7 @@ def __init__(self, restricted=False, lite=False, noimage=False, regex_snippets['space']) self.glyph_replacers = make_glyph_replacers( - html_type, self.uid, self.glyph_definitions, is_initial=False) - # Replacements that need to be made at the beginning - # of the string - self.initial_glyph_replacers = make_glyph_replacers( - html_type, self.uid, self.glyph_definitions, is_initial=True) + html_type, self.uid, self.glyph_definitions) if self.restricted is True: self.url_schemes = self.restricted_url_schemes @@ -279,6 +270,7 @@ def parse(self, text, rel=None, sanitize=False): if sanitize: text = sanitizer.sanitize(text) + text = self.retrieveTags(text) text = self.retrieveURLs(text) # if the text contains a break tag ({0}
'.format(text)), after])
@@ -1174,6 +1193,7 @@ def fPre(self, match):
before, text, after = match.groups()
if after is None:
after = ''
+ before, after = self.getSpecialOptions(before, after)
# text needs to be escaped
text = encode_html(text)
return ''.join([before, '', self.shelve(text), '', after]) @@ -1192,6 +1212,7 @@ def fTextile(self, match): before, notextile, after = match.groups() if after is None: # pragma: no branch after = '' + before, after = self.getSpecialOptions(before, after) return ''.join([before, self.shelve(notextile), after]) def getHTMLComments(self, text): From 155e2b32ab955072940f085d591227a75d056bd9 Mon Sep 17 00:00:00 2001 From: Kirill Mavreshko
Goodbye.
"""), - ("""h2. A Definition list which covers the instance where a new definition list is created with a term without a definition\n\n- term :=\n- term2 := def""", """\t& test
'), diff --git a/textile/core.py b/textile/core.py index 8214fc8..c68f344 100644 --- a/textile/core.py +++ b/textile/core.py @@ -1246,7 +1246,7 @@ def fRCList(self, match): text = re.split(r'\n(?=[-])', match.group(), flags=re.M) for line in text: # parse the attributes and content - m = re.match(r'^[-]+({0})[ .](.*)$'.format(cls_re_s), line, + m = re.match(r'^[-]+({0})\.? (.*)$'.format(cls_re_s), line, flags=re.M | re.S) if not m: continue @@ -1257,9 +1257,15 @@ def fRCList(self, match): atts = pba(atts, restricted=self.restricted) # split the content into the term and definition - xm = re.match(r'^(.*?)[\s]*:=(.*?)[\s]*(=:|:=)?[\s]*$', content, - re.S) - term, definition, ending = xm.groups() + xm = re.match( + r'^(.*?){0}*:=(.*?){0}*(=:|:=)?{0}*$' + .format(regex_snippets['space']), + content, + re.S) + if xm: + term, definition, _ = xm.groups() + else: + term, definition = content, '' # cleanup term = term.strip() definition = definition.strip(' ') @@ -1272,16 +1278,23 @@ def fRCList(self, match): dltag = "{0}
'.format(definition.lstrip()) - definition = definition.replace('\n', '{0}
'.format(definition) + term = term.replace('\n', 'Here is a ‘spanned’ word.
'), + # Using $-links with link aliases + ("\"$\":test\n[test]https://textpattern.com/start\n", + "\t"), + ('Please check on "$":test for any updates.\n[test]https://de.wikipedia.org/wiki/Übermensch', + '\tPlease check on de.wikipedia.org/wiki/Übermensch for any updates.
'), ) @pytest.mark.parametrize("input, expected_output", xhtml_known_values) diff --git a/textile/core.py b/textile/core.py index c68f344..bf0b01b 100644 --- a/textile/core.py +++ b/textile/core.py @@ -139,6 +139,13 @@ def make_glyph_replacers(html_type, uid, glyph_defs): for (regex_obj, replacement) in pre_result] +def human_readable_url(url): + if "://" in url: + url = url.split("://")[1] + elif ":" in url: + url = url.split(":")[1] + return url + class Textile(object): restricted_url_schemes = ('http', 'https', 'ftp', 'mailto') @@ -957,11 +964,14 @@ def _casesdefault(c, pop, popped, url_chars, counts, pre): return in_.replace('{0}linkStartMarker:'.format(self.uid), '') if text == '$': - text = url - if "://" in text: - text = text.split("://")[1] - elif ":" in text: - text = text.split(":")[1] + if valid_scheme: + text = human_readable_url(url) + else: + ref_url = self.urlrefs.get(url) + if ref_url is not None: + text = human_readable_url(ref_url) + else: + text = url text = text.strip() title = encode_html(title) From 05c59a787bb719304c74861cc4450d9cf51636e5 Mon Sep 17 00:00:00 2001 From: Kirill MavreshkoPlease check on de.wikipedia.org/wiki/Übermensch for any updates.
'), + # Make sure smileys don't get recognised as a definition list. + (":(\n\n:)\n\n:( \n:( \n:( \n:) \n\nPinocchio!\n:^)\n\nBaboon!\n:=)\n\nWink!\n;)\n\n:[ \n:]\n\n;(\nsomething\ndark side\n:) \n\n;(c)[de] Item", + '\t:(
\n\n\t:)
\n\n\t:(
\n:(
\n:(
\n:)
Pinocchio!
\n:^)
Baboon!
\n:=)
Wink!
\n;)
:[
\n:]
;(
\nsomething
\ndark side
\n:)
:(
\n\n\t:)
\n\n\t:(
\n:(
\n:(
\n:)
Pinocchio!
\n:^)
Baboon!
\n:=)
Wink!
\n;)
:[
\n:]
;(
\nsomething
\ndark side
\n:)
text1 text2
A footer | diff --git a/tests/test_values.py b/tests/test_values.py index e14b23d..298502f 100644 --- a/tests/test_values.py +++ b/tests/test_values.py @@ -489,6 +489,17 @@ # Checking proper parsing of classes and IDs ("_(class1 class2#id1)text1_ -(foobarbaz#boom bang)text2-\n", '\t
\n\t\t\t | \n\t\t |
a | \n\t\t\tb | \n\t\t\tc | \n\t\t\td | \n\t\t\te | \n\t\t
touch this! | \n\t\t\ttouch this! | \n\t\t
Scientists say the moon is slowly shrinking1.
\n\n\tScientists say the moon is slowly shrinking1.
\n\n\tnotelist({0})(?:\:([\w|{1}]))?([\^!]?)(\+?)' - r'\.?[\s]*
'.format(cls_re_s, syms_re_s), re.U) + r'\.?[\s]*'.format(cls_re_s, syms_re_s), re.U) text = text_re.sub(self.fNoteLists, text) return text @@ -1363,8 +1358,8 @@ def fNoteLists(self, match): atts = info['def']['atts'] content = info['def']['content'] li = ('\t\ttext\nmoretext\n\nevenmoretext\n\nmoremoretext
\n\n\ttest
' @@ -54,6 +57,7 @@ def test_blockcode_extended(): result = t.parse(input) assert result == expect + def test_blockcode_in_README(): with open('README.textile') as f: readme = ''.join(f.readlines()) @@ -62,6 +66,7 @@ def test_blockcode_in_README(): expect = ''.join(f.readlines()) assert result == expect + def test_blockcode_comment(): input = '###.. block comment\nanother line\n\np. New line' expect = '\tNew line
' From 1ee596229be05950a1e1addcfb3226d4e4e4e794 Mon Sep 17 00:00:00 2001 From: Dennis BurkeYACC1
', html) is not None + def test_Footnote(): html = textile.textile('This is covered elsewhere[1].\n\nfn1. Down here, in fact.\n\nfn2. Here is another footnote.') assert re.search(r'^\tThis is covered elsewhere1.
\n\n\t1 Down here, in fact.
\n\n\t2 Here is another footnote.
$', html) is not None @@ -24,6 +26,7 @@ def test_Footnote(): html = textile.textile('''See[4!] for details.\n\nfn4^. Here are the details.''') assert re.search(r'^\tSee4 for details.
\n\n\t4 Here are the details.
$', html) is not None + def test_issue_35(): result = textile.textile('"z"') expect = '\t“z”
' @@ -33,8 +36,9 @@ def test_issue_35(): expect = '\t“ z”
' assert result == expect + def test_restricted(): - #Note that the HTML is escaped, thus rendering the " result = textile.textile_restricted(test) expect = "\tHere is some text.
\n<script>alert(‘hello world’)</script>
текст1
$', re.U).search(html) is not None + def test_autolinking(): test = """some text "test":http://www.google.com http://www.google.com "$":http://www.google.com""" result = """\tsome text test http://www.google.com www.google.com
""" @@ -104,6 +110,7 @@ def test_autolinking(): assert result == expect + def test_sanitize(): test = "a paragraph of benign text" result = "\ta paragraph of benign text
" @@ -120,14 +127,16 @@ def test_sanitize(): expect = textile.Textile(html_type='html5').parse(test, sanitize=True) assert result == expect + def test_imagesize(): - PIL = pytest.importorskip('PIL') # noqa: F841 + PIL = pytest.importorskip('PIL') # noqa: F841 test = "!http://www.google.com/intl/en_ALL/images/srpr/logo1w.png!" result = '\t' expect = textile.Textile(get_sizes=True).parse(test) assert result == expect + def test_endnotes_simple(): test = """Scientists say the moon is slowly shrinking[#my_first_label].\n\nnotelist!.\n\nnote#my_first_label Over the past billion years, about a quarter of the moon's 4.5 billion-year lifespan, it has shrunk about 200 meters (700 feet) in diameter.""" html = textile.textile(test) @@ -135,6 +144,7 @@ def test_endnotes_simple(): result_re = re.compile(result_pattern) assert result_re.search(html) is not None + def test_endnotes_complex(): test = """Tim Berners-Lee is one of the pioneer voices in favour of Net Neutrality[#netneutral] and has expressed the view that ISPs should supply "connectivity with no strings attached"[#netneutral!] [#tbl_quote]\n\nBerners-Lee admitted that the forward slashes ("//") in a web address were actually unnecessary. He told the newspaper that he could easily have designed URLs not to have the forward slashes. "... it seemed like a good idea at the time,"[#slashes]\n\nnote#netneutral. "Web creator rejects net tracking":http://news.bbc.co.uk/2/hi/technology/7613201.stm. BBC. 15 September 2008\n\nnote#tbl_quote. "Web inventor's warning on spy software":http://www.telegraph.co.uk/news/uknews/1581938/Web-inventor%27s-warning-on-spy-software.html. The Daily Telegraph (London). 25 May 2008\n\nnote#slashes. "Berners-Lee 'sorry' for slashes":http://news.bbc.co.uk/1/hi/technology/8306631.stm. BBC. 14 October 2009\n\nnotelist.""" html = textile.textile(test) @@ -142,6 +152,7 @@ def test_endnotes_complex(): result_re = re.compile(result_pattern) assert result_re.search(html) is not None + def test_endnotes_unreferenced_note(): test = """Scientists say[#lavader] the moon is quite small. But I, for one, don't believe them. Others claim it to be made of cheese[#aardman]. If this proves true I suspect we are in for troubled times[#apollo13] as people argue over their "share" of the moon's cheese. In the end, its limited size[#lavader] may prove problematic.\n\nnote#lavader(noteclass). "Proof of the small moon hypothesis":http://antwrp.gsfc.nasa.gov/apod/ap080801.html. Copyright(c) Laurent Laveder\n\nnote#aardman(#noteid). "Proof of a cheese moon":http://www.imdb.com/title/tt0104361\n\nnote#apollo13. After all, things do go "wrong":http://en.wikipedia.org/wiki/Apollo_13#The_oxygen_tank_incident.\n\nnotelist{padding:1em; margin:1em; border-bottom:1px solid gray}.\n\nnotelist{padding:1em; margin:1em; border-bottom:1px solid gray}:§^.\n\nnotelist{padding:1em; margin:1em; border-bottom:1px solid gray}:‡""" html = textile.textile(test) @@ -149,6 +160,7 @@ def test_endnotes_unreferenced_note(): result_re = re.compile(result_pattern, re.U) assert result_re.search(html) is not None + def test_endnotes_malformed(): test = """Scientists say[#lavader] the moon is quite small. But I, for one, don't believe them. Others claim it to be made of cheese[#aardman]. If this proves true I suspect we are in for troubled times[#apollo13!] as people argue over their "share" of the moon's cheese. In the end, its limited size[#lavader] may prove problematic.\n\nnote#unused An unreferenced note.\n\nnote#lavader^ "Proof of the small moon hypothesis":http://antwrp.gsfc.nasa.gov/apod/ap080801.html. Copyright(c) Laurent Laveder\n\nnote#aardman^ "Proof of a cheese moon":http://www.imdb.com/title/tt0104361\n\nnote#apollo13^ After all, things do go "wrong":http://en.wikipedia.org/wiki/Apollo_13#The_oxygen_tank_incident.\n\nnotelist{padding:1em; margin:1em; border-bottom:1px solid gray}:α!+""" html = textile.textile(test) @@ -156,6 +168,7 @@ def test_endnotes_malformed(): result_re = re.compile(result_pattern, re.U) assert result_re.search(html) is not None + def test_endnotes_undefined_note(): test = """Scientists say the moon is slowly shrinking[#my_first_label].\n\nnotelist!.""" html = textile.textile(test) @@ -163,6 +176,7 @@ def test_endnotes_undefined_note(): result_re = re.compile(result_pattern) assert result_re.search(html) is not None + def test_encode_url(): # I tried adding these as doctests, but the unicode tests weren't # returning the correct results. @@ -198,21 +212,25 @@ def test_encode_url(): eurl = t.encode_url(url) assert eurl == result + def test_footnote_crosslink(): html = textile.textile('''See[2] for details, and later, reference it again[2].\n\nfn2^(footy#otherid)[en]. Here are the details.''') searchstring = r'\tSee2 for details, and later, reference it again2.
\n\n\t2 Here are the details.
$' assert re.compile(searchstring).search(html) is not None + def test_footnote_without_reflink(): html = textile.textile('''See[3!] for details.\n\nfn3. Here are the details.''') searchstring = r'^\tSee3 for details.
\n\n\t3 Here are the details.
$' assert re.compile(searchstring).search(html) is not None + def testSquareBrackets(): html = textile.textile("""1[^st^], 2[^nd^], 3[^rd^]. 2 log[~n~]\n\nA close[!http://textpattern.com/favicon.ico!]image.\nA tight["text":http://textpattern.com/]link.\nA ["footnoted link":http://textpattern.com/][182].""") searchstring = r'^\t1st, 2nd, 3rd. 2 logn
\n\n\tA closeimage.
\nA tighttextlink.
\nA footnoted link182.
A link that contains a\nnewline raises an exception.
' assert result == expect + def test_rel_attribute(): t = Textile(rel='nofollow') result = t.parse('"$":http://domain.tld') expect = '\t' assert result == expect + def test_quotes_in_link_text(): """quotes in link text are tricky.""" test = '""this is a quote in link text"":url' From ae01636248e974b2cc9b5028d570d9a7e7d03ab3 Mon Sep 17 00:00:00 2001 From: Dennis Burkegoogle.com google.com blackhole@sun.comet
' assert result == expect + def test_github_issue_17(): result = textile.textile('!http://www.ox.ac.uk/favicon.ico!') expect = '\t' assert result == expect + def test_github_issue_20(): text = 'This is a link to a ["Wikipedia article about Textile":http://en.wikipedia.org/wiki/Textile_(markup_language)].' result = textile.textile(text) expect = '\tThis is a link to a Wikipedia article about Textile.
' assert result == expect + def test_github_issue_21(): - text = '''h1. xml example + text = ('''h1. xml example -bc. +bc. ''' + '''\n<foo>\n bar\n</foo>
'
assert result == expect
+
def test_github_issue_22():
text = '''_(artist-name)Ty Segall_’s'''
result = textile.textile(text)
expect = '\tTy Segall’s
' assert result == expect + def test_github_issue_26(): text = '' result = textile.textile(text) expect = '' assert result == expect + def test_github_issue_27(): test = """* Folders with ":" in their names are displayed with a forward slash "/" instead. (Filed as "#4581709":/test/link, which was considered "normal behaviour" - quote: "Please note that Finder presents the 'Carbon filesystem' view, regardless of the underlying filesystem.")""" result = textile.textile(test) expect = """\tOf course there’s a lot more error handling to do (and useful data to glean off the XML), but being able to cut through all the usual parsing crap is immensely gratifying.
""") assert result == expect + def test_github_issue_30(): - text ='"Tëxtíle (Tëxtíle)":http://lala.com' + text = '"Tëxtíle (Tëxtíle)":http://lala.com' result = textile.textile(text) expect = '\t' assert result == expect - text ='!http://lala.com/lol.gif(♡ imáges)!' + text = '!http://lala.com/lol.gif(♡ imáges)!' result = textile.textile(text) expect = '\t' assert result == expect + def test_github_issue_36(): text = '"Chögyam Trungpa":https://www.google.com/search?q=Chögyam+Trungpa' result = textile.textile(text) expect = '\t' assert result == expect + def test_github_issue_37(): text = '# xxx\n# yyy\n*blah*' result = textile.textile(text) @@ -118,24 +130,28 @@ def test_github_issue_37(): \t''' assert result == expect + def test_github_issue_40(): text = '\r\n' result = textile.textile(text) expect = '\r\n' assert result == expect + def test_github_issue_42(): text = '!./image.png!' result = textile.textile(text) expect = '\t' assert result == expect + def test_github_issue_43(): text = 'pre. smart ‘quotes’ are not smart!' result = textile.textile(text) expect = 'smart ‘quotes’ are not smart!' assert result == expect + def test_github_issue_45(): """Incorrect transform unicode url""" text = '"test":https://myabstractwiki.ru/index.php/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0' @@ -143,6 +159,7 @@ def test_github_issue_45(): expect = '\t' assert result == expect + def test_github_issue_46(): """Key error on mal-formed numbered lists. CAUTION: both the input and the ouput are ugly.""" @@ -153,6 +170,7 @@ def test_github_issue_46(): result = textile.textile(text) assert result == expect + def test_github_issue_47(): """Incorrect wrap pre-formatted value""" text = '''pre.. word @@ -172,6 +190,7 @@ def test_github_issue_47(): yet anothe word''' assert result == expect + def test_github_issue_49(): """Key error on russian hash-route link""" s = '"link":https://ru.vuejs.org/v2/guide/components.html#Входные-параметры' @@ -179,6 +198,7 @@ def test_github_issue_49(): expect = '\t' assert result == expect + def test_github_issue_50(): """Incorrect wrap code with Java generics in pre""" test = ('pre.. public class Tynopet
This is some TEXT inside a "Code BLOCK"
@@ -299,6 +325,7 @@ def test_github_pull_61():
result = t.parse(test)
assert result == expect
+
def test_github_pull_62():
"""Fix for paragraph multiline, only last paragraph is rendered
correctly"""
@@ -341,6 +368,7 @@ def test_github_pull_62():
result = t.parse(test)
assert result == expect
+
def test_github_pull_63():
"""Forgot to set multiline_para to False"""
test = '''p.. First one 'is'
From f15dc31edef29df3b140070be1d64f3e6205272e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:36:35 -0500
Subject: [PATCH 148/228] flake8: whitespace cleanup
---
tests/test_cli.py | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 5f6e501..57b2d5f 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -3,28 +3,30 @@
import textile
+
def test_console_script():
command = [sys.executable, '-m', 'textile', 'README.textile']
try:
result = subprocess.check_output(command)
except AttributeError:
command[2] = 'textile.__main__'
- result = subprocess.Popen(command,
- stdout=subprocess.PIPE).communicate()[0]
+ result = subprocess.Popen(
+ command, stdout=subprocess.PIPE).communicate()[0]
with open('tests/fixtures/README.txt') as f:
expect = ''.join(f.readlines())
if type(result) == bytes:
result = result.decode('utf-8')
assert result == expect
+
def test_version_string():
command = [sys.executable, '-m', 'textile', '-v']
try:
result = subprocess.check_output(command)
except AttributeError:
command[2] = 'textile.__main__'
- result = subprocess.Popen(command,
- stdout=subprocess.PIPE).communicate()[0]
+ result = subprocess.Popen(
+ command, stdout=subprocess.PIPE).communicate()[0]
if type(result) == bytes:
result = result.decode('utf-8')
assert result.strip() == textile.__version__
From 8abe7f4e7b8acbf0efd3b25123221e6c16ff5aa0 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:52:50 -0500
Subject: [PATCH 149/228] flake8: whitespace cleanup
---
tests/test_attributes.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_attributes.py b/tests/test_attributes.py
index 0f5d019..b07712f 100644
--- a/tests/test_attributes.py
+++ b/tests/test_attributes.py
@@ -1,5 +1,6 @@
from textile.utils import parse_attributes
+
def test_parse_attributes():
assert parse_attributes('\\1', element='td') == {'colspan': '1'}
assert parse_attributes('/1', element='td') == {'rowspan': '1'}
From ed28e7155fc48b13aeccf6d5160bec9d1553e91e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:53:42 -0500
Subject: [PATCH 150/228] flake8: whitespace cleanup
---
tests/test_getimagesize.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_getimagesize.py b/tests/test_getimagesize.py
index 43f85e3..3a3c0a9 100644
--- a/tests/test_getimagesize.py
+++ b/tests/test_getimagesize.py
@@ -3,6 +3,7 @@
PIL = pytest.importorskip('PIL')
+
def test_imagesize():
assert getimagesize("http://www.google.com/intl/en_ALL/images/logo.gif") == (276, 110)
assert getimagesize("http://bad.domain/") == ''
From 3c222b214ff9392623c2b4be856eeccb7eee5f1b Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:55:41 -0500
Subject: [PATCH 151/228] flake8: whitespace cleanup
---
tests/test_glyphs.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_glyphs.py b/tests/test_glyphs.py
index 56b0d27..ed50ad5 100644
--- a/tests/test_glyphs.py
+++ b/tests/test_glyphs.py
@@ -1,5 +1,6 @@
from textile import Textile
+
def test_glyphs():
t = Textile()
From 4304da9394c5d33f7724692797364b1172ea2082 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:57:52 -0500
Subject: [PATCH 152/228] flake8: whitespace cleanup
---
tests/test_subclassing.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/test_subclassing.py b/tests/test_subclassing.py
index 9235e03..a7db99a 100644
--- a/tests/test_subclassing.py
+++ b/tests/test_subclassing.py
@@ -1,10 +1,10 @@
import textile
+
def test_change_glyphs():
class TextilePL(textile.Textile):
glyph_definitions = dict(textile.Textile.glyph_definitions,
- quote_double_open = '„'
- )
+ quote_double_open='„')
test = 'Test "quotes".'
expect = '\tTest „quotes”.
'
From 5c663e39ca1f7551f8e5304245abf9d5ea2e5d53 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 19:58:40 -0500
Subject: [PATCH 153/228] flake8: whitespace cleanup
---
tests/test_imagesize.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tests/test_imagesize.py b/tests/test_imagesize.py
index 0a89b43..e7d9d88 100644
--- a/tests/test_imagesize.py
+++ b/tests/test_imagesize.py
@@ -1,10 +1,11 @@
import textile
+
def test_imagesize():
imgurl = 'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png'
result = textile.tools.imagesize.getimagesize(imgurl)
try:
- import PIL # noqa: F401
+ import PIL # noqa: F401
expect = (275, 95)
assert result == expect
From 0b66de8799a06a38068ea8c418d28d7bec080eb3 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:17:17 -0500
Subject: [PATCH 154/228] flake8: whitespace cleanup
---
tests/test_textilefactory.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_textilefactory.py b/tests/test_textilefactory.py
index 846b927..e9fc027 100644
--- a/tests/test_textilefactory.py
+++ b/tests/test_textilefactory.py
@@ -1,6 +1,7 @@
from textile import textilefactory
import pytest
+
def test_TextileFactory():
f = textilefactory.TextileFactory()
result = f.process("some text here")
From 343e26d8a00e61a510b380145a213828ee4bae96 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:18:01 -0500
Subject: [PATCH 155/228] flake8: whitespace cleanup
---
tests/test_getRefs.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_getRefs.py b/tests/test_getRefs.py
index d3cfcd7..8a22d4f 100644
--- a/tests/test_getRefs.py
+++ b/tests/test_getRefs.py
@@ -1,5 +1,6 @@
from textile import Textile
+
def test_getRefs():
t = Textile()
result = t.getRefs("some text [Google]http://www.google.com")
From fddda0ca1e73f73c588c2889b0a465a91f9d5f19 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:18:34 -0500
Subject: [PATCH 156/228] flake8: whitespace cleanup
---
tests/test_footnoteRef.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_footnoteRef.py b/tests/test_footnoteRef.py
index c973ee7..5ac2ea4 100644
--- a/tests/test_footnoteRef.py
+++ b/tests/test_footnoteRef.py
@@ -1,5 +1,6 @@
from textile import Textile
+
def test_footnoteRef():
t = Textile()
result = t.footnoteRef('foo[1]')
From 739ee86698c6bf4357c9211365410c4f55f12569 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:19:14 -0500
Subject: [PATCH 157/228] flake8: whitespace cleanup
---
tests/test_table.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_table.py b/tests/test_table.py
index 0a3cb0d..1ea34e9 100644
--- a/tests/test_table.py
+++ b/tests/test_table.py
@@ -1,5 +1,6 @@
from textile import Textile
+
def test_table():
t = Textile()
result = t.table('(rowclass). |one|two|three|\n|a|b|c|')
From 0def35bc88b2b8c0f0385106787dd254bf6da838 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:21:12 -0500
Subject: [PATCH 158/228] flake8: whitespace cleanup
---
tests/test_values.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/test_values.py b/tests/test_values.py
index 5d15950..7ebd2c7 100644
--- a/tests/test_values.py
+++ b/tests/test_values.py
@@ -506,12 +506,14 @@
)
+
@pytest.mark.parametrize("input, expected_output", xhtml_known_values)
def test_KnownValuesXHTML(input, expected_output):
# XHTML
output = textile.textile(input, html_type='xhtml')
assert output == expected_output
+
@pytest.mark.parametrize("input, expected_output", html_known_values)
def test_KnownValuesHTML(input, expected_output):
# HTML5
From 5eea5a77cbdab22fd3c381410b75c5a2077d82ae Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:21:42 -0500
Subject: [PATCH 159/228] flake8: whitespace cleanup
---
tests/test_values.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tests/test_values.py b/tests/test_values.py
index 7ebd2c7..f08ac6f 100644
--- a/tests/test_values.py
+++ b/tests/test_values.py
@@ -35,7 +35,7 @@
('h3. Header 3', '\tHeader 3
'),
('An old text\n\nbq. A block quotation.\n\nAny old text''',
- '\tAn old text
\n\n\t\n\t\tA block quotation.
\n\t
\n\n\tAny old text
'),
+ '\tAn old text
\n\n\t\n\t\tA block quotation.
\n\t
\n\n\tAny old text
'),
('I _believe_ every word.', '\tI believe every word.
'),
@@ -70,8 +70,8 @@
('p[fr]. rouge', '\trouge
'),
('I seriously *{color:red}blushed*\nwhen I _(big)sprouted_ that\ncorn stalk from my\n%[es]cabeza%.',
- '\tI seriously blushed
\nwhen I sprouted'
- ' that
\ncorn stalk from my
\ncabeza.
'),
+ '\tI seriously blushed
\nwhen I sprouted'
+ ' that
\ncorn stalk from my
\ncabeza.
'),
('p<. align left', '\talign left
'),
@@ -226,7 +226,7 @@
("""table(#dvds){border-collapse:collapse}. Great films on DVD employing Textile summary, caption, thead, tfoot, two tbody elements and colgroups\n|={font-size:140%;margin-bottom:15px}. DVDs with two Textiled tbody elements\n|:\\3. 100 |{background:#ddd}|250||50|300|\n|^(header).\n|_. Title |_. Starring |_. Director |_. Writer |_. Notes |\n|~(footer).\n|\\5=. This is the tfoot, centred |\n|-(toplist){background:#c5f7f6}.\n| _The Usual Suspects_ | Benicio Del Toro, Gabriel Byrne, Stephen Baldwin, Kevin Spacey | Bryan Singer | Chris McQaurrie | One of the finest films ever made |\n| _Se7en_ | Morgan Freeman, Brad Pitt, Kevin Spacey | David Fincher | Andrew Kevin Walker | Great psychological thriller |\n| _Primer_ | David Sullivan, Shane Carruth | Shane Carruth | Shane Carruth | Amazing insight into trust and human psychology
rather than science fiction. Terrific! |\n| _District 9_ | Sharlto Copley, Jason Cope | Neill Blomkamp | Neill Blomkamp, Terri Tatchell | Social commentary layered on thick,\nbut boy is it done well |\n|-(medlist){background:#e7e895;}.\n| _Arlington Road_ | Tim Robbins, Jeff Bridges | Mark Pellington | Ehren Kruger | Awesome study in neighbourly relations |\n| _Phone Booth_ | Colin Farrell, Kiefer Sutherland, Forest Whitaker | Joel Schumacher | Larry Cohen | Edge-of-the-seat stuff in this\nshort but brilliantly executed thriller |""",
"""\t\n\tDVDs with two Textiled tbody elements \n\t\n\t \n\t \n\t \n\t \n\t \n\t \n\t\n\t\t\n\t\t\tTitle \n\t\t\tStarring \n\t\t\tDirector \n\t\t\tWriter \n\t\t\tNotes \n\t\t \n\t\n\t\n\t\t\n\t\t\tThis is the tfoot, centred \n\t\t \n\t\n\t\n\t\t\n\t\t\t The Usual Suspects \n\t\t\t Benicio Del Toro, Gabriel Byrne, Stephen Baldwin, Kevin Spacey \n\t\t\t Bryan Singer \n\t\t\t Chris McQaurrie \n\t\t\t One of the finest films ever made \n\t\t \n\t\t\n\t\t\t Se7en \n\t\t\t Morgan Freeman, Brad Pitt, Kevin Spacey \n\t\t\t David Fincher \n\t\t\t Andrew Kevin Walker \n\t\t\t Great psychological thriller \n\t\t \n\t\t\n\t\t\t Primer \n\t\t\t David Sullivan, Shane Carruth \n\t\t\t Shane Carruth \n\t\t\t Shane Carruth \n\t\t\t Amazing insight into trust and human psychology
\nrather than science fiction. Terrific! \n\t\t \n\t\t\n\t\t\t District 9 \n\t\t\t Sharlto Copley, Jason Cope \n\t\t\t Neill Blomkamp \n\t\t\t Neill Blomkamp, Terri Tatchell \n\t\t\t Social commentary layered on thick,
\nbut boy is it done well \n\t\t \n\t\n\t\n\t\t\n\t\t\t Arlington Road \n\t\t\t Tim Robbins, Jeff Bridges \n\t\t\t Mark Pellington \n\t\t\t Ehren Kruger \n\t\t\t Awesome study in neighbourly relations \n\t\t \n\t\t\n\t\t\t Phone Booth \n\t\t\t Colin Farrell, Kiefer Sutherland, Forest Whitaker \n\t\t\t Joel Schumacher \n\t\t\t Larry Cohen \n\t\t\t Edge-of-the-seat stuff in this
\nshort but brilliantly executed thriller \n\t\t \n\t\n\t
"""),
("""-(hot) *coffee* := Hot _and_ black\n-(hot#tea) tea := Also hot, but a little less black\n-(cold) milk := Nourishing beverage for baby cows.\nCold drink that goes great with cookies. =:\n\n-(hot) coffee := Hot and black\n-(hot#tea) tea := Also hot, but a little less black\n-(cold) milk :=\nNourishing beverage for baby cows.\nCold drink that goes great with cookies. =:""",
- """\n\t- coffee
\n\t- Hot and black
\n\t- tea
\n\t- Also hot, but a little less black
\n\t- milk
\n\t- Nourishing beverage for baby cows.
\nCold drink that goes great with cookies. \n
\n\n\n\t- coffee
\n\t- Hot and black
\n\t- tea
\n\t- Also hot, but a little less black
\n\t- milk
\n\tNourishing beverage for baby cows.
\nCold drink that goes great with cookies.
\n
"""),
+ """\n\t- coffee
\n\t- Hot and black
\n\t- tea
\n\t- Also hot, but a little less black
\n\t- milk
\n\t- Nourishing beverage for baby cows.
\nCold drink that goes great with cookies. \n
\n\n\n\t- coffee
\n\t- Hot and black
\n\t- tea
\n\t- Also hot, but a little less black
\n\t- milk
\n\tNourishing beverage for baby cows.
\nCold drink that goes great with cookies.
\n
"""),
(""";(class#id) Term 1\n: Def 1\n: Def 2\n: Def 3""",
"""\t\n\t\t- Term 1
\n\t\t- Def 1
\n\t\t- Def 2
\n\t\t- Def 3
\n\t
"""),
("""*Here is a comment*\n\nHere is *(class)a comment*\n\n*(class)Here is a class* that is a little extended and is\n*followed* by a strong word!\n\nbc. ; Content-type: text/javascript\n; Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\n; Expires: Sat, 24 Jul 2003 05:00:00 GMT\n; Last-Modified: Wed, 1 Jan 2025 05:00:00 GMT\n; Pragma: no-cache\n\n*123 test*\n\n*test 123*\n\n**123 test**\n\n**test 123**""",
@@ -266,8 +266,8 @@
('I __know__.\nI **really** __know__.', '\tI know.
\nI really know.
'),
("I'm %{color:red}unaware%\nof most soft drinks.", '\tI’m unaware
\nof most soft drinks.
'),
('I seriously *{color:red}blushed*\nwhen I _(big)sprouted_ that\ncorn stalk from my\n%[es]cabeza%.',
- '\tI seriously blushed
\nwhen I sprouted'
- ' that
\ncorn stalk from my
\ncabeza.
'),
+ '\tI seriously blushed
\nwhen I sprouted'
+ ' that
\ncorn stalk from my
\ncabeza.
'),
('\n\na.gsub!( /, "" )\n
\n
',
'\n\na.gsub!( /</, "" )\n
\n
'),
('\n\nh3. Sidebar\n\n"Hobix":http://hobix.com/\n"Ruby":http://ruby-lang.org/\n\n\n\n'
From e0e488916e007595806364bb49eb175f53ce9243 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:22:50 -0500
Subject: [PATCH 160/228] flake8: whitespace cleanup
---
tests/test_utils.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 7f386a9..a6e88f8 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -3,21 +3,25 @@
from textile import utils
+
def test_encode_html():
result = utils.encode_html('''this is a "test" of text that's safe to '''
- 'put in an attribute.')
+ 'put in an attribute.')
expect = ('this is a "test" of text that's safe to put in '
- 'an <html> attribute.')
+ 'an <html> attribute.')
assert result == expect
+
def test_has_raw_text():
assert utils.has_raw_text('foo bar biz baz
') is False
assert utils.has_raw_text(' why yes, yes it does') is True
+
def test_is_rel_url():
assert utils.is_rel_url("http://www.google.com/") is False
assert utils.is_rel_url("/foo") is True
+
def test_generate_tag():
result = utils.generate_tag('span', 'inner text', {'class': 'test'})
expect = 'inner text'
From 1281ede405ae71b365c8c20ea02480006b7d543e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:25:27 -0500
Subject: [PATCH 161/228] turn flake8 warnings and errors back on
---
.flake8 | 3 ---
1 file changed, 3 deletions(-)
diff --git a/.flake8 b/.flake8
index 07c24d1..9f8ccc3 100644
--- a/.flake8
+++ b/.flake8
@@ -2,8 +2,5 @@
ignore =
# line too long
E501
- # temporarily ignore warnings and errors
- W
- E
exclude =
build/
From e60b72fe625a71289c731d8363a335e5c5fc7be2 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:35:36 -0500
Subject: [PATCH 162/228] use environment vars as intended
maybe this will fix a warning about unexpected inputs ???
---
.github/workflows/lint_and_test.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 437820d..f82f4c2 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -20,9 +20,10 @@ jobs:
- name: Python flake8 Lint
uses: py-actions/flake8@v1.2.0
- name: Install dependencies
+ env:
+ IMAGESIZE: ${{ matrix.image-size }}
run: |
imagesize=''
- IMAGESIZE=${{ matrix.image-size }}
pip install -U pytest pytest-cov coverage codecov
if [[ $IMAGESIZE == true ]] ; then imagesize='[imagesize]' ; fi
pip install -e ".${imagesize}"
From bda9a67d44011734bf66ebd6b8a9599963b2ac2b Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:42:24 -0500
Subject: [PATCH 163/228] further testing of environment variables
---
.github/workflows/lint_and_test.yml | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index f82f4c2..5ba1e86 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -9,7 +9,7 @@ jobs:
strategy:
matrix:
python-version: [3.5, 3.6, 3.7, 3.8, 3.9]
- image-size: ['true', 'false']
+ image_size: ['true', 'false']
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
@@ -20,12 +20,10 @@ jobs:
- name: Python flake8 Lint
uses: py-actions/flake8@v1.2.0
- name: Install dependencies
- env:
- IMAGESIZE: ${{ matrix.image-size }}
run: |
imagesize=''
pip install -U pytest pytest-cov coverage codecov
- if [[ $IMAGESIZE == true ]] ; then imagesize='[imagesize]' ; fi
+ if [[ $INPUT_IMAGE_SIZE == true ]] ; then imagesize='[imagesize]' ; fi
pip install -e ".${imagesize}"
- name: run tests
run: |
From 45257b6d8ddae53c281490c95b9d3a3ecb83cf7d Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:44:45 -0500
Subject: [PATCH 164/228] This is probably the source of the `unexpected
inputs` warning
---
.github/workflows/lint_and_test.yml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 5ba1e86..47ce8cf 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -16,7 +16,6 @@ jobs:
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- image-size: ${{ matrix.image-size }}
- name: Python flake8 Lint
uses: py-actions/flake8@v1.2.0
- name: Install dependencies
From dd5982ee3345a638fb6db15547f1feb132b4b064 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 28 Nov 2021 20:49:10 -0500
Subject: [PATCH 165/228] add pypy3 to github actions
---
.github/workflows/lint_and_test.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 47ce8cf..0db7ea8 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: [3.5, 3.6, 3.7, 3.8, 3.9]
+ python-version: [3.5, 3.6, 3.7, 3.8, 3.9, pypy3]
image_size: ['true', 'false']
steps:
- uses: actions/checkout@v2
From 060e7f46846d427e6674af9ddcb7ced8e1f2f7f3 Mon Sep 17 00:00:00 2001
From: Brad Schoening <5796692+bschoening@users.noreply.github.com>
Date: Mon, 22 Jul 2024 22:23:50 -0400
Subject: [PATCH 166/228] Update setup.py to support Python 3.8..3.12
---
setup.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/setup.py b/setup.py
index b405f28..cbbb774 100644
--- a/setup.py
+++ b/setup.py
@@ -28,11 +28,11 @@ def get_version():
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3 :: Only',
- 'Programming Language :: Python :: 3.5',
- 'Programming Language :: Python :: 3.6',
- 'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: 3.11',
+ 'Programming Language :: Python :: 3.12',
'Topic :: Software Development :: Libraries :: Python Modules',
],
keywords='textile,text,html markup',
From 3eb20497fec2bc31ee6184d2e64a2abab3568ab6 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 11:18:12 -0400
Subject: [PATCH 167/228] update versions to test against
---
.github/workflows/lint_and_test.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 0db7ea8..f488521 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: [3.5, 3.6, 3.7, 3.8, 3.9, pypy3]
+ python-version: [3.8, 3.9, 3.10, 3.11, 3.12, pypy3]
image_size: ['true', 'false']
steps:
- uses: actions/checkout@v2
From 3fc933a17814adf94a46f0fc651f1eb388ad2f77 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 11:22:46 -0400
Subject: [PATCH 168/228] make sure versions are interpreted as strings
3.10 was being interpreted as 3.1 with a trailing 0
---
.github/workflows/lint_and_test.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index f488521..935d688 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: [3.8, 3.9, 3.10, 3.11, 3.12, pypy3]
+ python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy3"]
image_size: ['true', 'false']
steps:
- uses: actions/checkout@v2
From fe144a8ae0947cf941197eb0804984a4b4812cdc Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 11:26:09 -0400
Subject: [PATCH 169/228] use isinstance for type comparison
fixes a flake8 failure
---
tests/test_cli.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 57b2d5f..5e6ab79 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -14,7 +14,7 @@ def test_console_script():
command, stdout=subprocess.PIPE).communicate()[0]
with open('tests/fixtures/README.txt') as f:
expect = ''.join(f.readlines())
- if type(result) == bytes:
+ if isinstance(result, bytes):
result = result.decode('utf-8')
assert result == expect
@@ -27,6 +27,6 @@ def test_version_string():
command[2] = 'textile.__main__'
result = subprocess.Popen(
command, stdout=subprocess.PIPE).communicate()[0]
- if type(result) == bytes:
+ if isinstance(result, bytes):
result = result.decode('utf-8')
assert result.strip() == textile.__version__
From dd353101a7116acd96594afac624d52d1c310b76 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 11:36:54 -0400
Subject: [PATCH 170/228] try the latest version of the github action
---
.github/workflows/lint_and_test.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 935d688..96bfd6d 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -17,7 +17,7 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Python flake8 Lint
- uses: py-actions/flake8@v1.2.0
+ uses: py-actions/flake8@v2.3.0
- name: Install dependencies
run: |
imagesize=''
From 5b44180a58def4527c29750cde59e2a8a482687e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 11:41:42 -0400
Subject: [PATCH 171/228] update other actions as well
---
.github/workflows/lint_and_test.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 96bfd6d..c4d4aab 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -11,9 +11,9 @@ jobs:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy3"]
image_size: ['true', 'false']
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Python flake8 Lint
From 9bb449a97e149428951d122156346cebbd7501a3 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 11:54:17 -0400
Subject: [PATCH 172/228] fix version spec for pypy
---
.github/workflows/lint_and_test.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index c4d4aab..cc2690b 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy3"]
+ python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy3.10"]
image_size: ['true', 'false']
steps:
- uses: actions/checkout@v4
From 56c912b568ce24404f1291ddb068904b87bd7631 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 11:59:57 -0400
Subject: [PATCH 173/228] update to the latest version of the codecov action
---
.github/workflows/lint_and_test.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index cc2690b..8cfec1f 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -28,4 +28,4 @@ jobs:
run: |
pytest
- name: Codecov
- uses: codecov/codecov-action@v2.1.0
+ uses: codecov/codecov-action@v4
From dac1716210fe6d9b4c631ce3b8b861c75b381149 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 12:07:53 -0400
Subject: [PATCH 174/228] add codecov token which is stored as a secret
---
.github/workflows/lint_and_test.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 8cfec1f..44a7c91 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -29,3 +29,5 @@ jobs:
pytest
- name: Codecov
uses: codecov/codecov-action@v4
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
From 07782366f00bcc723033a9aa42b72eb16de6ff0e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 12:58:55 -0400
Subject: [PATCH 175/228] update badge to github actions
---
README.textile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.textile b/README.textile
index 98f4fbd..797516c 100644
--- a/README.textile
+++ b/README.textile
@@ -1,4 +1,4 @@
-!https://travis-ci.org/textile/python-textile.svg!:https://travis-ci.org/textile/python-textile !https://codecov.io/github/textile/python-textile/coverage.svg!:https://codecov.io/github/textile/python-textile !https://img.shields.io/pypi/pyversions/textile! !https://img.shields.io/pypi/wheel/textile!
+!https://github.com/textile/python-textile/actions/workflows/lint_and_test.yml/badge.svg(python-textile)!:https://github.com/textile/python-textile/actions/workflows/lint_and_test.yml !https://codecov.io/github/textile/python-textile/coverage.svg!:https://codecov.io/github/textile/python-textile !https://img.shields.io/pypi/pyversions/textile! !https://img.shields.io/pypi/wheel/textile!
h1. python-textile
From 47a03ebbec92576fcdef1b681884b2cf3d16079f Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 13:01:08 -0400
Subject: [PATCH 176/228] update fixture to reflect README changes
---
tests/fixtures/README.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/fixtures/README.txt b/tests/fixtures/README.txt
index 949db70..a485943 100644
--- a/tests/fixtures/README.txt
+++ b/tests/fixtures/README.txt
@@ -1,4 +1,4 @@
-
+
python-textile
From c4308890fecc070622b963557507f98509e69460 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 13:59:53 -0400
Subject: [PATCH 177/228] update minimum supported python version
---
setup.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/setup.py b/setup.py
index cbbb774..b14b9a6 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,5 @@
-from setuptools import setup, find_packages
import os
+from setuptools import setup, find_packages
def get_version():
@@ -48,5 +48,5 @@ def get_version():
tests_require=['pytest', 'pytest-cov'],
include_package_data=True,
zip_safe=False,
- python_requires='>=3.5',
+ python_requires='>=3.8',
)
From f8533fae9964f744105a01769213ca00dd9d1ffb Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 14:15:18 -0400
Subject: [PATCH 178/228] codecov is reporting missing coverage in this file
testing to see if moving this import will have any affect
---
textile/tools/imagesize.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/textile/tools/imagesize.py b/textile/tools/imagesize.py
index 6fba73e..ec724a2 100644
--- a/textile/tools/imagesize.py
+++ b/textile/tools/imagesize.py
@@ -1,3 +1,5 @@
+from urllib.request import urlopen
+
def getimagesize(url):
"""
Attempts to determine an image's width and height, and returns a tuple,
@@ -11,8 +13,6 @@ def getimagesize(url):
except ImportError:
return ''
- from urllib.request import urlopen
-
try:
p = ImageFile.Parser()
f = urlopen(url)
From 1f32b74d233a3e3f6bfe134ea251ba5c4ab608ab Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 14:17:00 -0400
Subject: [PATCH 179/228] flake8 insists on two new lines
---
textile/tools/imagesize.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/textile/tools/imagesize.py b/textile/tools/imagesize.py
index ec724a2..1d758cc 100644
--- a/textile/tools/imagesize.py
+++ b/textile/tools/imagesize.py
@@ -1,5 +1,6 @@
from urllib.request import urlopen
+
def getimagesize(url):
"""
Attempts to determine an image's width and height, and returns a tuple,
From db58e41ab37a3f0a158d4ace15a51dbbbfcf665e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 14:23:05 -0400
Subject: [PATCH 180/228] setting this back to what it was
---
textile/tools/imagesize.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/textile/tools/imagesize.py b/textile/tools/imagesize.py
index 1d758cc..6fba73e 100644
--- a/textile/tools/imagesize.py
+++ b/textile/tools/imagesize.py
@@ -1,6 +1,3 @@
-from urllib.request import urlopen
-
-
def getimagesize(url):
"""
Attempts to determine an image's width and height, and returns a tuple,
@@ -14,6 +11,8 @@ def getimagesize(url):
except ImportError:
return ''
+ from urllib.request import urlopen
+
try:
p = ImageFile.Parser()
f = urlopen(url)
From 88042c5591818d4e4a6acf810029e7038e0aca5e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 14:23:21 -0400
Subject: [PATCH 181/228] debugging the value of imagesize
---
.github/workflows/lint_and_test.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 44a7c91..e932372 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -24,6 +24,8 @@ jobs:
pip install -U pytest pytest-cov coverage codecov
if [[ $INPUT_IMAGE_SIZE == true ]] ; then imagesize='[imagesize]' ; fi
pip install -e ".${imagesize}"
+ echo "INPUT_IMAGE_SIZE: ${INPUT_IMAGE_SIZE}"
+ echo "imagesize: ${imagesize}"
- name: run tests
run: |
pytest
From 9c23fdff323c62430f8633bbd90201895f338d0b Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 14:25:23 -0400
Subject: [PATCH 182/228] more debugging
---
.github/workflows/lint_and_test.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index e932372..f4795b2 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -24,6 +24,7 @@ jobs:
pip install -U pytest pytest-cov coverage codecov
if [[ $INPUT_IMAGE_SIZE == true ]] ; then imagesize='[imagesize]' ; fi
pip install -e ".${imagesize}"
+ echo "image_size: ${image_size}"
echo "INPUT_IMAGE_SIZE: ${INPUT_IMAGE_SIZE}"
echo "imagesize: ${imagesize}"
- name: run tests
From 889432773d7a53dc23ffdfcbae43156bdca24b28 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 14:30:29 -0400
Subject: [PATCH 183/228] maybe this is the right way to reference matrix
values???
---
.github/workflows/lint_and_test.yml | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index f4795b2..047e6d8 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -24,9 +24,7 @@ jobs:
pip install -U pytest pytest-cov coverage codecov
if [[ $INPUT_IMAGE_SIZE == true ]] ; then imagesize='[imagesize]' ; fi
pip install -e ".${imagesize}"
- echo "image_size: ${image_size}"
- echo "INPUT_IMAGE_SIZE: ${INPUT_IMAGE_SIZE}"
- echo "imagesize: ${imagesize}"
+ echo "image_size: ${{ matrix.image_size }}"
- name: run tests
run: |
pytest
From c55d83b16203cd75047b0acc57cad0a892b73250 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 5 Aug 2024 14:32:17 -0400
Subject: [PATCH 184/228] correct way to look up matrix value
---
.github/workflows/lint_and_test.yml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 047e6d8..14ced37 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -22,9 +22,8 @@ jobs:
run: |
imagesize=''
pip install -U pytest pytest-cov coverage codecov
- if [[ $INPUT_IMAGE_SIZE == true ]] ; then imagesize='[imagesize]' ; fi
+ if [[ ${{ matrix.image_size }} == true ]] ; then imagesize='[imagesize]' ; fi
pip install -e ".${imagesize}"
- echo "image_size: ${{ matrix.image_size }}"
- name: run tests
run: |
pytest
From abb0581805cb05301a5c6d06e2f604aec7f923b2 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Tue, 6 Aug 2024 14:55:42 -0400
Subject: [PATCH 185/228] flake8 cleanup
---
tests/test_values.py | 4 ++--
textile/core.py | 14 ++++----------
textile/objects/table.py | 2 +-
textile/utils.py | 4 ++--
4 files changed, 9 insertions(+), 15 deletions(-)
diff --git a/tests/test_values.py b/tests/test_values.py
index f08ac6f..62c797d 100644
--- a/tests/test_values.py
+++ b/tests/test_values.py
@@ -430,8 +430,8 @@
'\tTwo line with strong
\nheading
'),
# Non-standalone ampersands should not be escaped
(("“test”\n\n"
- "“test”\n\n"
- " test \n"),
+ "“test”\n\n"
+ " test \n"),
("\t“test”
\n\n"
"\t“test”
\n\n"
"\t test
")),
diff --git a/textile/core.py b/textile/core.py
index 1457c64..9c93ad7 100644
--- a/textile/core.py
+++ b/textile/core.py
@@ -209,11 +209,6 @@ def __init__(self, restricted=False, lite=False, noimage=False,
self.refIndex = 0
self.block_tags = block_tags
- cur = r''
- if regex_snippets['cur']: # pragma: no branch
- cur = r'(?:[{0}]{1}*)?'.format(regex_snippets['cur'],
- regex_snippets['space'])
-
self.glyph_replacers = make_glyph_replacers(
html_type, self.uid, self.glyph_definitions)
@@ -424,7 +419,7 @@ def fPBr(self, m):
re.compile(r"
{0}*\n(?![{0}|])".format(regex_snippets['space']),
re.I)
.sub("\n", content))
- content = re.compile(r"\n(?![\s|])").sub('
',content)
+ content = re.compile(r"\n(?![\s|])").sub('
', content)
return '<{0}{1}>{2}{3}'.format(m.group(1), m.group(2), content, m.group(4))
def doBr(self, match):
@@ -1122,11 +1117,11 @@ def storeTags(self, opentag, closetag=''):
tags = {}
self.refIndex += 1
self.refCache[self.refIndex] = opentag
- tags['open'] = self.uid + str(self.refIndex) + ':ospan ';
+ tags['open'] = self.uid + str(self.refIndex) + ':ospan '
self.refIndex += 1
self.refCache[self.refIndex] = closetag
- tags['close'] = ' ' + self.uid + str(self.refIndex) + ':cspan';
+ tags['close'] = ' ' + self.uid + str(self.refIndex) + ':cspan'
return tags
def retrieveTags(self, text):
@@ -1139,7 +1134,6 @@ def retrieveTags(self, text):
def fRetrieveTags(self, match):
return self.refCache[int(match.group('token'))]
-
def image(self, text):
pattern = re.compile(r"""
(?:[\[{{])? # pre
@@ -1363,7 +1357,7 @@ def fNoteLists(self, match):
content)
else:
li = ('\t\t{1} Undefined Note [#{2}]. '
- ).format(atts, links, info['seq'])
+ ).format(atts, links, info['seq'])
o.append(li)
if '+' == extras and self.unreferencedNotes:
for seq, info in self.unreferencedNotes.items():
diff --git a/textile/objects/table.py b/textile/objects/table.py
index 7a3d0ce..ba034f2 100644
--- a/textile/objects/table.py
+++ b/textile/objects/table.py
@@ -5,7 +5,7 @@
from textile.regex_strings import (align_re_s, cls_re_s, regex_snippets,
table_span_re_s, valign_re_s, pnct_re_s)
-from textile.utils import generate_tag, parse_attributes
+from textile.utils import generate_tag, parse_attributes, pba
try:
import regex as re
diff --git a/textile/utils.py b/textile/utils.py
index 9a459a9..1a04182 100644
--- a/textile/utils.py
+++ b/textile/utils.py
@@ -22,11 +22,12 @@
# else the regex module doesn't properly match pre-s. It only matches the
# p in pre.
re.compile(r'<(pre|p|blockquote|div|form|table|ul|ol|dl|h[1-6])[^>]*?>.*\1>',
- re.S),
+ re.S),
re.compile(r'<(hr|br)[^>]*?/>'),
re.compile(r''),
)
+
def decode_high(text):
"""Decode encoded HTML entities."""
text = '{0};'.format(text)
@@ -88,7 +89,6 @@ def has_raw_text(text):
return r != ''
-
def is_rel_url(url):
"""Identify relative urls."""
(scheme, netloc) = urlparse(url)[0:2]
From 82fe31acdd6333ca6b5f732e798190b504e55fcb Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Tue, 6 Aug 2024 15:02:52 -0400
Subject: [PATCH 186/228] fix colgroup handling
---
textile/objects/table.py | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/textile/objects/table.py b/textile/objects/table.py
index ba034f2..2471d3c 100644
--- a/textile/objects/table.py
+++ b/textile/objects/table.py
@@ -57,19 +57,17 @@ def process(self):
# Colgroup -- A colgroup row will not necessarily end with a |.
# Hence it may include the next row of actual table data.
-
- gmtch = self.colgroup_re.match(row)
- if gmtch:
- cols = gmtch.group(1).replace('.', "")
- for idx, col in enumerate(cols.split("|")):
- gatts = pba(col.strip(), 'col', restricted=self.textile.restricted)
- self.colgroup += '\t ') if idx == 0 else (gatts + ' />'))
- self.colgroup += '\t'
- nl_index = row.find('\n')
- if nl_index >= 0:
- row = row[nl_index:].lstrip()
+ if row[:2] == '|:':
+ if '\n' in row:
+ colgroup_data, row = row[2:].split('\n')
else:
+ colgroup_data, row = row[2:], ''
+ colgroup_atts, cols = colgroup_data, None
+ if '|' in colgroup_data:
+ colgroup_atts, cols = colgroup_data.split('|', 1)
+ colgrp = Colgroup(cols, colgroup_atts, restricted=self.textile.restricted)
+ self.colgroup = colgrp.process()
+ if row == '':
continue
# search the row for a table group - thead, tfoot, or tbody
From 57e01fcfc89e1ff5dc6d04a86660f24567fe44b4 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Tue, 6 Aug 2024 15:04:27 -0400
Subject: [PATCH 187/228] remove unused import
---
textile/objects/table.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/textile/objects/table.py b/textile/objects/table.py
index 2471d3c..96adaed 100644
--- a/textile/objects/table.py
+++ b/textile/objects/table.py
@@ -5,7 +5,7 @@
from textile.regex_strings import (align_re_s, cls_re_s, regex_snippets,
table_span_re_s, valign_re_s, pnct_re_s)
-from textile.utils import generate_tag, parse_attributes, pba
+from textile.utils import generate_tag, parse_attributes
try:
import regex as re
From 063aaab3fa8ba039557db658aa9297d100ce6841 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Tue, 6 Aug 2024 15:22:02 -0400
Subject: [PATCH 188/228] fix formatting of captions and colgroups
---
textile/objects/table.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/textile/objects/table.py b/textile/objects/table.py
index 96adaed..fcecb06 100644
--- a/textile/objects/table.py
+++ b/textile/objects/table.py
@@ -152,7 +152,7 @@ def __init__(self, capts, cap, row, restricted):
def process(self, cap):
tag = generate_tag('caption', cap.strip(), self.attributes)
- return '\t{0}\n\t'.format(tag)
+ return '\t{0}\n'.format(tag)
class Colgroup(object):
@@ -181,7 +181,7 @@ def process(self):
# tab between cols and a newline at the end
xml_declaration = "\n"
colgrp = colgrp.replace(xml_declaration, '')
- return colgrp.replace('><', '>\n\t<')
+ return f'\t{colgrp.replace('><', '>\n\t<')}'
class Row(object):
From 036f4ba34f6466b12d166735932db5ce00f53d37 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Tue, 6 Aug 2024 15:25:01 -0400
Subject: [PATCH 189/228] fix f-string formatting
---
textile/objects/table.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/textile/objects/table.py b/textile/objects/table.py
index fcecb06..ac1da76 100644
--- a/textile/objects/table.py
+++ b/textile/objects/table.py
@@ -181,7 +181,7 @@ def process(self):
# tab between cols and a newline at the end
xml_declaration = "\n"
colgrp = colgrp.replace(xml_declaration, '')
- return f'\t{colgrp.replace('><', '>\n\t<')}'
+ return f"\t{colgrp.replace('><', '>\n\t<')}"
class Row(object):
From 6e041ab237b2536e23f65cf3c87ede1aa3ffd19f Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Tue, 6 Aug 2024 15:26:57 -0400
Subject: [PATCH 190/228] further f-string formatting fix
---
textile/objects/table.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/textile/objects/table.py b/textile/objects/table.py
index ac1da76..42644b5 100644
--- a/textile/objects/table.py
+++ b/textile/objects/table.py
@@ -181,7 +181,8 @@ def process(self):
# tab between cols and a newline at the end
xml_declaration = "\n"
colgrp = colgrp.replace(xml_declaration, '')
- return f"\t{colgrp.replace('><', '>\n\t<')}"
+ colgrp = colgrp.replace('><', '>\n\t<')
+ return f"\t{colgrp}"
class Row(object):
From a10ace1feccf1296f53ae39234bf8e5c73dac772 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Wed, 7 Aug 2024 15:01:30 -0400
Subject: [PATCH 191/228] add a test for a table which has a colgroup but no
caption
---
tests/test_values.py | 8 +++++++-
textile/objects/table.py | 4 ++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/tests/test_values.py b/tests/test_values.py
index 62c797d..957a42e 100644
--- a/tests/test_values.py
+++ b/tests/test_values.py
@@ -503,7 +503,13 @@
# Table column with an emphasis should not be confused with a heading
('|_touch_ this!| _touch_ this! |',
'\t\n\t\t\n\t\t\ttouch this! \n\t\t\t touch this! \n\t\t \n\t
'),
-
+ # Table with colgroup but no caption
+ (("|:\\5. 80 |\x20\n"
+ "|a|b|c|d|e|\x20\n"),
+ ('\t\n'
+ '\t\n\t \n'
+ '\t\t\n\t\t\ta \n\t\t\tb \n\t\t\tc \n\t\t\td \n\t\t\te \n\t\t \n'
+ '\t
')),
)
diff --git a/textile/objects/table.py b/textile/objects/table.py
index 42644b5..a257bd0 100644
--- a/textile/objects/table.py
+++ b/textile/objects/table.py
@@ -152,7 +152,7 @@ def __init__(self, capts, cap, row, restricted):
def process(self, cap):
tag = generate_tag('caption', cap.strip(), self.attributes)
- return '\t{0}\n'.format(tag)
+ return '\t{0}'.format(tag)
class Colgroup(object):
@@ -182,7 +182,7 @@ def process(self):
xml_declaration = "\n"
colgrp = colgrp.replace(xml_declaration, '')
colgrp = colgrp.replace('><', '>\n\t<')
- return f"\t{colgrp}"
+ return f"\n\t{colgrp}"
class Row(object):
From 0c2c0fa376faa0f457c7da4a09da83e978b1dc2b Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Wed, 7 Aug 2024 15:40:31 -0400
Subject: [PATCH 192/228] confirm that the extra newline from captions without
colgroups is fixed
---
tests/test_textile.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/tests/test_textile.py b/tests/test_textile.py
index 0b2abca..8a5e4f8 100644
--- a/tests/test_textile.py
+++ b/tests/test_textile.py
@@ -76,7 +76,6 @@ def test_restricted():
expect = '''\
\t
\tYour caption goes here
-
\t
\t\t
\t\t\tA footer
From 9c4013c22993219771bdc88a47d1652850a08b8c Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Wed, 7 Aug 2024 16:17:27 -0400
Subject: [PATCH 193/228] hopefully this will cover a missing line in codecov
---
tests/test_values.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_values.py b/tests/test_values.py
index 957a42e..8b6d36b 100644
--- a/tests/test_values.py
+++ b/tests/test_values.py
@@ -247,6 +247,7 @@
"""\tA definition list
\n\n\t\n\t\t- Term 1
\n\t\t- Def 1
\n\t\t- Def 2
\n\t\t- Def 3\n\t\t
\n\t\t\t- Center
\n\t\t\t- NATO
\n\t\t\t- Subdef 1
\n\t\t\t- Subdef 2\n\t\t\t
\n\t\t\t\t- SubSub Term
\n\t\t\t\t- SubSub Def 1
\n\t\t\t\t- SubSub Def 2
\n\t\t\t\t- Subsub Def 3
\nWith newline \n\t\t\t\t- Subsub Def 4
\n\t\t\t
\n\t\t\t- Subdef 3
\n\t\t
\n\t\t- DEF 4
\n\t\t- Term 2
\n\t\t- Another def
\n\t\t- And another
\n\t\t- One more\n\t\t
\n\t\t\t- A def without a term
\n\t\t\t- More defness
\n\t\t
\n\t\t- Third term for good measure
\n\t\t- My definition of a boombastic jazz
\n\t
"""),
("""###. Here's a comment.\n\nh3. Hello\n\n###. And\nanother\none.\n\nGoodbye.""", """\tHello
\n\n\tGoodbye.
"""),
("""h2. A Definition list which covers the instance where a new definition list is created with a term without a definition\n\n- term :=\n- term2 := def""", """\tA Definition list which covers the instance where a new definition list is created with a term without a definition
\n\n\n\t- term
\n\t- term2
\n\t- def
\n
"""),
+ ("""h2. A definition list where one item in the list is missing a definition for the term\n\n- Markdown := a perfectly cromulent plaintext markup system\n- Textile :=""", """\tA definition list where one item in the list is missing a definition for the term
\n\n\n\t- Markdown
\n\t- a perfectly cromulent plaintext markup system
\n\t- Textile
\n
"""),
('!{height:20px;width:20px;}https://1.gravatar.com/avatar/!',
'\t'),
('& test', '\t& test
'),
From a169a7c508b978e82c0816a8f9ffe30a0938f43e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Wed, 7 Aug 2024 16:36:23 -0400
Subject: [PATCH 194/228] I don't think we have to worry about a possibly
malformed term
---
textile/core.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/textile/core.py b/textile/core.py
index 9c93ad7..6454187 100644
--- a/textile/core.py
+++ b/textile/core.py
@@ -1276,10 +1276,7 @@ def fRCList(self, match):
.format(regex_snippets['space']),
content,
re.S)
- if xm:
- term, definition, _ = xm.groups()
- else:
- term, definition = content, ''
+ term, definition, _ = xm.groups()
# cleanup
term = term.strip()
definition = definition.strip(' ')
From 52c1b8a4be6eb2e0df294c0b4c1ea0c751e8722e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Wed, 7 Aug 2024 16:40:52 -0400
Subject: [PATCH 195/228] If only I had read the test on the line immediately
above this
---
tests/test_values.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/tests/test_values.py b/tests/test_values.py
index 8b6d36b..957a42e 100644
--- a/tests/test_values.py
+++ b/tests/test_values.py
@@ -247,7 +247,6 @@
"""\tA definition list
\n\n\t\n\t\t- Term 1
\n\t\t- Def 1
\n\t\t- Def 2
\n\t\t- Def 3\n\t\t
\n\t\t\t- Center
\n\t\t\t- NATO
\n\t\t\t- Subdef 1
\n\t\t\t- Subdef 2\n\t\t\t
\n\t\t\t\t- SubSub Term
\n\t\t\t\t- SubSub Def 1
\n\t\t\t\t- SubSub Def 2
\n\t\t\t\t- Subsub Def 3
\nWith newline \n\t\t\t\t- Subsub Def 4
\n\t\t\t
\n\t\t\t- Subdef 3
\n\t\t
\n\t\t- DEF 4
\n\t\t- Term 2
\n\t\t- Another def
\n\t\t- And another
\n\t\t- One more\n\t\t
\n\t\t\t- A def without a term
\n\t\t\t- More defness
\n\t\t
\n\t\t- Third term for good measure
\n\t\t- My definition of a boombastic jazz
\n\t
"""),
("""###. Here's a comment.\n\nh3. Hello\n\n###. And\nanother\none.\n\nGoodbye.""", """\tHello
\n\n\tGoodbye.
"""),
("""h2. A Definition list which covers the instance where a new definition list is created with a term without a definition\n\n- term :=\n- term2 := def""", """\tA Definition list which covers the instance where a new definition list is created with a term without a definition
\n\n\n\t- term
\n\t- term2
\n\t- def
\n
"""),
- ("""h2. A definition list where one item in the list is missing a definition for the term\n\n- Markdown := a perfectly cromulent plaintext markup system\n- Textile :=""", """\tA definition list where one item in the list is missing a definition for the term
\n\n\n\t- Markdown
\n\t- a perfectly cromulent plaintext markup system
\n\t- Textile
\n
"""),
('!{height:20px;width:20px;}https://1.gravatar.com/avatar/!',
'\t'),
('& test', '\t& test
'),
From 164c09e572b37dddb5bb4e724fa2f3c4fb320c5d Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Wed, 7 Aug 2024 18:37:37 -0400
Subject: [PATCH 196/228] add test cases to increase code coverage for
parse_attributes
---
tests/test_attributes.py | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/tests/test_attributes.py b/tests/test_attributes.py
index b07712f..fed235d 100644
--- a/tests/test_attributes.py
+++ b/tests/test_attributes.py
@@ -1,3 +1,4 @@
+from typing import OrderedDict
from textile.utils import parse_attributes
@@ -13,3 +14,11 @@ def test_parse_attributes():
assert parse_attributes('<') == {'style': 'text-align:left;'}
assert parse_attributes('(c#i)') == {'class': 'c', 'id': 'i'}
assert parse_attributes('\\2 100', element='col') == {'span': '2', 'width': '100'}
+
+
+def test_parse_attributes_edge_cases():
+ result = parse_attributes('(:c#i)')
+ expect = OrderedDict({'id': 'i'})
+ assert result == expect
+
+ assert parse_attributes('(<)') == OrderedDict()
From d3cc63cfc07782ea2a8fd4a0b06c1e7ddc1c4fc9 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Wed, 7 Aug 2024 18:47:50 -0400
Subject: [PATCH 197/228] move human_readable_url function into utils
---
textile/core.py | 13 +++----------
textile/utils.py | 8 ++++++++
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/textile/core.py b/textile/core.py
index 6454187..ea94ac1 100644
--- a/textile/core.py
+++ b/textile/core.py
@@ -25,8 +25,9 @@
from textile.regex_strings import (align_re_s, cls_re_s, pnct_re_s,
regex_snippets, syms_re_s, table_span_re_s)
from textile.utils import (decode_high, encode_high, encode_html, generate_tag,
- has_raw_text, is_rel_url, is_valid_url, list_type,
- normalize_newlines, parse_attributes, pba)
+ has_raw_text, human_readable_url, is_rel_url,
+ is_valid_url, list_type, normalize_newlines,
+ parse_attributes, pba)
from textile.objects import Block, Table
try:
@@ -139,14 +140,6 @@ def make_glyph_replacers(html_type, uid, glyph_defs):
for (regex_obj, replacement) in pre_result]
-def human_readable_url(url):
- if "://" in url:
- url = url.split("://")[1]
- elif ":" in url:
- url = url.split(":")[1]
- return url
-
-
class Textile(object):
restricted_url_schemes = ('http', 'https', 'ftp', 'mailto')
unrestricted_url_schemes = restricted_url_schemes + (
diff --git a/textile/utils.py b/textile/utils.py
index 1a04182..7045bcb 100644
--- a/textile/utils.py
+++ b/textile/utils.py
@@ -89,6 +89,14 @@ def has_raw_text(text):
return r != ''
+def human_readable_url(url):
+ if "://" in url:
+ url = url.split("://")[1]
+ elif ":" in url:
+ url = url.split(":")[1]
+ return url
+
+
def is_rel_url(url):
"""Identify relative urls."""
(scheme, netloc) = urlparse(url)[0:2]
From f10d0aea01ff915876a012ba17b801ae35a15aa2 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Wed, 7 Aug 2024 18:59:53 -0400
Subject: [PATCH 198/228] add human_readable_url edge case test to increase
coverage
---
tests/test_utils.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tests/test_utils.py b/tests/test_utils.py
index a6e88f8..6ddb93f 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -32,3 +32,7 @@ def test_generate_tag():
expect = 'Übermensch'
result = utils.generate_tag('a', text, attributes)
assert result == expect
+
+
+def test_human_readable_url_edge_case():
+ assert utils.human_readable_url('tel:1-800-555-1212') == '1-800-555-1212'
From 4d6fd237f2a06e860e931a9ace9c48b575ca2cb4 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Wed, 7 Aug 2024 19:25:04 -0400
Subject: [PATCH 199/228] closing the final edge case for complete coverage of
human_readable_url
---
tests/test_utils.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 6ddb93f..b2e455b 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -35,4 +35,5 @@ def test_generate_tag():
def test_human_readable_url_edge_case():
+ assert utils.human_readable_url('google.com') == 'google.com'
assert utils.human_readable_url('tel:1-800-555-1212') == '1-800-555-1212'
From 08dc3dc9ca0ddfae0072d395141b474a3672c8ec Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Thu, 8 Aug 2024 12:57:57 -0400
Subject: [PATCH 200/228] update README regarding Python version support
---
README.textile | 2 +-
tests/fixtures/README.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.textile b/README.textile
index 797516c..7362c73 100644
--- a/README.textile
+++ b/README.textile
@@ -42,7 +42,7 @@ bc.. import textile
h3. Notes:
-* Active development supports Python 3.5 or later.
+* Active development supports Python 3.8 or later.
h3. Running Tests
diff --git a/tests/fixtures/README.txt b/tests/fixtures/README.txt
index a485943..fd5ce43 100644
--- a/tests/fixtures/README.txt
+++ b/tests/fixtures/README.txt
@@ -47,7 +47,7 @@
Notes:
- - Active development supports Python 3.5 or later.
+ - Active development supports Python 3.8 or later.
Running Tests
From dbdf43031b0c237b5117767356f78eeeab31ac12 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Thu, 8 Aug 2024 12:59:26 -0400
Subject: [PATCH 201/228] update CHANGELOG in preparation for next release
---
CHANGELOG.textile | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/CHANGELOG.textile b/CHANGELOG.textile
index 43beedc..e13f6f5 100644
--- a/CHANGELOG.textile
+++ b/CHANGELOG.textile
@@ -1,5 +1,12 @@
h1. Textile Changelog
+h2. Version 4.0.3
+* Update supported Python versions to 3.8 - 3.12 ("#83":https://github.com/textile/python-textile/issues/83)
+* Bugfixes:
+** Wrong HTML output when "bc.." is the very last in the document ("#81":https://github.com/textile/python-textile/issues/81)
+* Other:
+** Use github actions instead of travis for automated testing
+
h2. Version 4.0.2
* Bugfixes:
** Support non-http schemas in url refs ("#75":https://github.com/textile/python-textile/pull/75)
From 247dbfad5909da3579367619242990b036213377 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Thu, 8 Aug 2024 13:05:28 -0400
Subject: [PATCH 202/228] update url for textile-lang
---
README.textile | 2 +-
tests/fixtures/README.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.textile b/README.textile
index 7362c73..1bb9087 100644
--- a/README.textile
+++ b/README.textile
@@ -2,7 +2,7 @@
h1. python-textile
-python-textile is a Python port of "Textile":http://txstyle.org/, Dean Allen's humane web text generator.
+python-textile is a Python port of "Textile":https://textile-lang.com/, Dean Allen's humane web text generator.
h2. Installation
diff --git a/tests/fixtures/README.txt b/tests/fixtures/README.txt
index fd5ce43..01d0209 100644
--- a/tests/fixtures/README.txt
+++ b/tests/fixtures/README.txt
@@ -2,7 +2,7 @@
python-textile
- python-textile is a Python port of Textile, Dean Allen’s humane web text generator.
+ python-textile is a Python port of Textile, Dean Allen’s humane web text generator.
Installation
From 8b26327ad665cd48e990d92a41f044d711d062e8 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Thu, 8 Aug 2024 13:30:10 -0400
Subject: [PATCH 203/228] update contributors list
---
CONTRIBUTORS.txt | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index 5624ae6..90d949a 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -7,4 +7,6 @@ Alex Shiels
Jason Samsa
Kurt Raschke
Dave Brondsema
-Dmitry Shachnev
\ No newline at end of file
+Dmitry Shachnev
+Kirill Mavreshko
+Brad Schoening
\ No newline at end of file
From 739f758befd3fe349f179c37a435ecaf2ebb2e7e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Thu, 8 Aug 2024 15:46:51 -0400
Subject: [PATCH 204/228] replace old setup.py config with pyproject.toml
---
MANIFEST.in | 2 --
pyproject.toml | 43 +++++++++++++++++++++++++++++++++++++++++
setup.py | 52 --------------------------------------------------
3 files changed, 43 insertions(+), 54 deletions(-)
delete mode 100644 MANIFEST.in
create mode 100644 pyproject.toml
delete mode 100644 setup.py
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index 5ca56e8..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,2 +0,0 @@
-include MANIFEST.in
-include tests/fixtures/README.txt
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..fdb4bd7
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,43 @@
+[build-system]
+requires = ["setuptools", "setuptools-scm"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "textile"
+authors = [
+ { name = "Dennis Burke", email = "ikirudennis@gmail.com"}
+]
+description = 'Textile processing for python.'
+classifiers = [
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3 :: Only',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: 3.11',
+ 'Programming Language :: Python :: 3.12',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+]
+dynamic = ["version",]
+dependencies = [
+ 'html5lib>=1.0.1',
+ 'regex>1.0; implementation_name != "pypy"',
+]
+requires-python = '>=3.8'
+keywords = ['textile', 'text', 'html', 'markup']
+
+[project.optional-dependencies]
+develop = ['pytest', 'pytest-cov']
+imagesize = ['Pillow>=3.0.0',]
+
+[python.scripts]
+pytextile = "textile.__main__:main"
+
+[tool.setuptools.dynamic]
+version = {attr = "textile.__version__"}
diff --git a/setup.py b/setup.py
deleted file mode 100644
index b14b9a6..0000000
--- a/setup.py
+++ /dev/null
@@ -1,52 +0,0 @@
-import os
-from setuptools import setup, find_packages
-
-
-def get_version():
- basedir = os.path.dirname(__file__)
- with open(os.path.join(basedir, 'textile/version.py')) as f:
- variables = {}
- exec(f.read(), variables)
- return variables.get('VERSION')
- raise RuntimeError('No version info found.')
-
-
-setup(
- name='textile',
- version=get_version(),
- author='Dennis Burke',
- author_email='ikirudennis@gmail.com',
- description='Textile processing for python.',
- url='http://github.com/textile/python-textile',
- packages=find_packages(),
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Environment :: Web Environment',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: BSD License',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3 :: Only',
- 'Programming Language :: Python :: 3.8',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: 3.11',
- 'Programming Language :: Python :: 3.12',
- 'Topic :: Software Development :: Libraries :: Python Modules',
- ],
- keywords='textile,text,html markup',
- install_requires=[
- 'html5lib>=1.0.1',
- 'regex>1.0; implementation_name != "pypy"',
- ],
- extras_require={
- 'develop': ['pytest', 'pytest-cov'],
- 'imagesize': ['Pillow>=3.0.0'],
- },
- entry_points={'console_scripts': ['pytextile=textile.__main__:main']},
- tests_require=['pytest', 'pytest-cov'],
- include_package_data=True,
- zip_safe=False,
- python_requires='>=3.8',
-)
From 8a5053e45c82e68299c2451f79fb0ac8e7b43532 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Thu, 8 Aug 2024 19:17:53 -0400
Subject: [PATCH 205/228] define the urls for the pypi project
---
pyproject.toml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/pyproject.toml b/pyproject.toml
index fdb4bd7..f8e13ef 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -36,6 +36,11 @@ keywords = ['textile', 'text', 'html', 'markup']
develop = ['pytest', 'pytest-cov']
imagesize = ['Pillow>=3.0.0',]
+[project.urls]
+Homepage = "https://github.com/textile/python-textile"
+Repository = "https://github.com/textile/python-textile.git"
+Issues = "https://github.com/textile/python-textile/issues"
+
[python.scripts]
pytextile = "textile.__main__:main"
From c758c633f56271ea58c27d3c09736996fa0dab61 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Fri, 9 Aug 2024 11:27:55 -0400
Subject: [PATCH 206/228] replace html5lib with nh3
We're only using the santizer part of html5lib, and it's being
deprecated. It seems nh3 is the recommended replacement at this time.
This change eliminates a series of Deprecation Warnings.
---
pyproject.toml | 2 +-
tests/test_textile.py | 2 +-
textile/core.py | 11 ++++++-----
textile/tools/sanitizer.py | 11 -----------
4 files changed, 8 insertions(+), 18 deletions(-)
delete mode 100644 textile/tools/sanitizer.py
diff --git a/pyproject.toml b/pyproject.toml
index f8e13ef..5ef4a96 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -26,7 +26,7 @@ classifiers = [
]
dynamic = ["version",]
dependencies = [
- 'html5lib>=1.0.1',
+ 'nh3',
'regex>1.0; implementation_name != "pypy"',
]
requires-python = '>=3.8'
diff --git a/tests/test_textile.py b/tests/test_textile.py
index 8a5e4f8..a4ec90b 100644
--- a/tests/test_textile.py
+++ b/tests/test_textile.py
@@ -117,7 +117,7 @@ def test_sanitize():
assert result == expect
test = """a paragraph of evil text
"""
- result = 'a paragraph of evil text
'
+ result = 'a paragraph of evil text
'
expect = textile.Textile().parse(test, sanitize=True)
assert result == expect
diff --git a/textile/core.py b/textile/core.py
index ea94ac1..e9d2955 100644
--- a/textile/core.py
+++ b/textile/core.py
@@ -20,8 +20,9 @@
import uuid
from urllib.parse import urlparse, urlsplit, urlunsplit, quote, unquote
from collections import OrderedDict
+from nh3 import clean
-from textile.tools import sanitizer, imagesize
+from textile.tools import imagesize
from textile.regex_strings import (align_re_s, cls_re_s, pnct_re_s,
regex_snippets, syms_re_s, table_span_re_s)
from textile.utils import (decode_high, encode_high, encode_html, generate_tag,
@@ -236,12 +237,12 @@ def parse(self, text, rel=None, sanitize=False):
if self.block_tags:
if self.lite:
- self.blocktag_whitelist = ['bq', 'p']
+ self.blocktag_allowlist = set(['bq', 'p', 'br'])
text = self.block(text)
else:
- self.blocktag_whitelist = ['bq', 'p', 'bc', 'notextile',
+ self.blocktag_allowlist = set(['bq', 'p', 'br', 'bc', 'notextile',
'pre', 'h[1-6]', 'fn{0}+'.format(
- regex_snippets['digit']), '###']
+ regex_snippets['digit']), '###'])
text = self.block(text)
text = self.placeNoteLists(text)
else:
@@ -263,7 +264,7 @@ def parse(self, text, rel=None, sanitize=False):
text = text.replace('{0}:glyph:'.format(self.uid), '')
if sanitize:
- text = sanitizer.sanitize(text)
+ text = clean(text, tags=self.blocktag_allowlist)
text = self.retrieveTags(text)
text = self.retrieveURLs(text)
diff --git a/textile/tools/sanitizer.py b/textile/tools/sanitizer.py
deleted file mode 100644
index 3c7209c..0000000
--- a/textile/tools/sanitizer.py
+++ /dev/null
@@ -1,11 +0,0 @@
-def sanitize(string):
- """
- Ensure that the text does not contain any malicious HTML code which might
- break the page.
- """
- from html5lib import parseFragment, serialize
-
- parsed = parseFragment(string)
- clean = serialize(parsed, sanitize=True, omit_optional_tags=False,
- quote_attr_values='always')
- return clean
From f6fbd530384d131be15eee73c88b4fa60c4de112 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Fri, 9 Aug 2024 11:33:00 -0400
Subject: [PATCH 207/228] replace str.format with f-string
---
textile/core.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/textile/core.py b/textile/core.py
index e9d2955..1b8cd66 100644
--- a/textile/core.py
+++ b/textile/core.py
@@ -241,8 +241,8 @@ def parse(self, text, rel=None, sanitize=False):
text = self.block(text)
else:
self.blocktag_allowlist = set(['bq', 'p', 'br', 'bc', 'notextile',
- 'pre', 'h[1-6]', 'fn{0}+'.format(
- regex_snippets['digit']), '###'])
+ 'pre', 'h[1-6]',
+ f'fn{regex_snippets['digit']}+', '###'])
text = self.block(text)
text = self.placeNoteLists(text)
else:
From 01b3e73a2fc97eecf774adeda3a9004b706fe181 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Fri, 9 Aug 2024 11:34:37 -0400
Subject: [PATCH 208/228] fix formatting
---
textile/core.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/textile/core.py b/textile/core.py
index 1b8cd66..711d08c 100644
--- a/textile/core.py
+++ b/textile/core.py
@@ -242,7 +242,7 @@ def parse(self, text, rel=None, sanitize=False):
else:
self.blocktag_allowlist = set(['bq', 'p', 'br', 'bc', 'notextile',
'pre', 'h[1-6]',
- f'fn{regex_snippets['digit']}+', '###'])
+ f"fn{regex_snippets['digit']}+", '###'])
text = self.block(text)
text = self.placeNoteLists(text)
else:
From a716dfaece13f5f77c57d02afd79fe973a2744e2 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Fri, 9 Aug 2024 12:21:01 -0400
Subject: [PATCH 209/228] add nh3 to build requirements
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 5ef4a96..08ded12 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,5 +1,5 @@
[build-system]
-requires = ["setuptools", "setuptools-scm"]
+requires = ["setuptools", "setuptools-scm", "nh3"]
build-backend = "setuptools.build_meta"
[project]
From a47bd97e7244c4881fe25f50e414616a9a7ac4a3 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Fri, 9 Aug 2024 12:39:29 -0400
Subject: [PATCH 210/228] update README to reflect change of dependencies
---
README.textile | 2 +-
tests/fixtures/README.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.textile b/README.textile
index 1bb9087..49df25e 100644
--- a/README.textile
+++ b/README.textile
@@ -9,7 +9,7 @@ h2. Installation
@pip install textile@
Dependencies:
-* "html5lib":https://pypi.org/project/html5lib/
+* "nh3":https://pypi.org/project/nh3/
* "regex":https://pypi.org/project/regex/ (The regex package causes problems with PyPy, and is not installed as a dependency in such environments. If you are upgrading a textile install on PyPy which had regex previously included, you may need to uninstall it.)
Optional dependencies include:
diff --git a/tests/fixtures/README.txt b/tests/fixtures/README.txt
index 01d0209..bb0ad30 100644
--- a/tests/fixtures/README.txt
+++ b/tests/fixtures/README.txt
@@ -10,7 +10,7 @@
Dependencies:
- - html5lib
+ - nh3
- regex (The regex package causes problems with PyPy, and is not installed as a dependency in such environments. If you are upgrading a textile install on PyPy which had regex previously included, you may need to uninstall it.)
From 9f2b9352de20db5e7ab73f474829a989cffb2b15 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Fri, 9 Aug 2024 14:30:44 -0400
Subject: [PATCH 211/228] remove `from __future__ import unicode_literals`
This is effectively a no-op in all supported python versions
---
tests/test_block.py | 2 --
tests/test_github_issues.py | 2 --
tests/test_textile.py | 1 -
tests/test_utils.py | 2 --
tests/test_values.py | 1 -
textile/__init__.py | 2 --
textile/core.py | 2 --
textile/objects/block.py | 2 --
textile/objects/table.py | 2 --
textile/regex_strings.py | 2 --
textile/textilefactory.py | 1 -
textile/utils.py | 2 --
12 files changed, 21 deletions(-)
diff --git a/tests/test_block.py b/tests/test_block.py
index 691d21a..eed5441 100644
--- a/tests/test_block.py
+++ b/tests/test_block.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
import textile
from textile.objects import Block
diff --git a/tests/test_github_issues.py b/tests/test_github_issues.py
index c08d067..6808054 100644
--- a/tests/test_github_issues.py
+++ b/tests/test_github_issues.py
@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
import textile
diff --git a/tests/test_textile.py b/tests/test_textile.py
index a4ec90b..84e9ddf 100644
--- a/tests/test_textile.py
+++ b/tests/test_textile.py
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
import pytest
import re
import textile
diff --git a/tests/test_utils.py b/tests/test_utils.py
index b2e455b..952c7b4 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
from textile import utils
diff --git a/tests/test_values.py b/tests/test_values.py
index 957a42e..7c19e11 100644
--- a/tests/test_values.py
+++ b/tests/test_values.py
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
import textile
import pytest
diff --git a/textile/__init__.py b/textile/__init__.py
index 08a242f..1641873 100644
--- a/textile/__init__.py
+++ b/textile/__init__.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
from .core import textile, textile_restricted, Textile # noqa: F401
from .version import VERSION
diff --git a/textile/core.py b/textile/core.py
index 711d08c..6d2c1e7 100644
--- a/textile/core.py
+++ b/textile/core.py
@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
__copyright__ = """
Copyright (c) 2009, Jason Samsa, http://jsamsa.com/
Copyright (c) 2010, Kurt Raschke
diff --git a/textile/objects/block.py b/textile/objects/block.py
index 8f44ad1..6d611ed 100644
--- a/textile/objects/block.py
+++ b/textile/objects/block.py
@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
from collections import OrderedDict
try:
import regex as re
diff --git a/textile/objects/table.py b/textile/objects/table.py
index a257bd0..72781ad 100644
--- a/textile/objects/table.py
+++ b/textile/objects/table.py
@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
from xml.etree import ElementTree
from textile.regex_strings import (align_re_s, cls_re_s, regex_snippets,
diff --git a/textile/regex_strings.py b/textile/regex_strings.py
index 2e096fb..c3691bb 100644
--- a/textile/regex_strings.py
+++ b/textile/regex_strings.py
@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
try:
# Use regex module for matching uppercase characters if installed,
# otherwise fall back to finding all the uppercase chars in a loop.
diff --git a/textile/textilefactory.py b/textile/textilefactory.py
index e5e2458..3892988 100644
--- a/textile/textilefactory.py
+++ b/textile/textilefactory.py
@@ -1,4 +1,3 @@
-from __future__ import unicode_literals
from .core import Textile
diff --git a/textile/utils.py b/textile/utils.py
index 7045bcb..b4516ea 100644
--- a/textile/utils.py
+++ b/textile/utils.py
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
try:
import regex as re
except ImportError:
From 6544c68dcf96b93d353f906e60cdd8e76aa2ff13 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Fri, 9 Aug 2024 14:35:17 -0400
Subject: [PATCH 212/228] remove unused variable
---
textile/core.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/textile/core.py b/textile/core.py
index 6d2c1e7..8efdbea 100644
--- a/textile/core.py
+++ b/textile/core.py
@@ -149,8 +149,6 @@ class Textile(object):
note_index = 1
- doctype_whitelist = ['xhtml', 'html5']
-
glyph_definitions = {
'quote_single_open': '‘', # noqa: E241
'quote_single_close': '’', # noqa: E241
From 8b262811853a6ce2c71d05fcc40dd3a9a3d0eab5 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Fri, 9 Aug 2024 14:58:22 -0400
Subject: [PATCH 213/228] move getimagesize into utils
And now the tools directory is no longer needed.
---
tests/test_getimagesize.py | 2 +-
tests/test_imagesize.py | 2 +-
textile/core.py | 9 ++++-----
textile/textilefactory.py | 5 +----
textile/tools/__init__.py | 0
textile/tools/imagesize.py | 27 ---------------------------
textile/utils.py | 29 +++++++++++++++++++++++++++++
7 files changed, 36 insertions(+), 38 deletions(-)
delete mode 100644 textile/tools/__init__.py
delete mode 100644 textile/tools/imagesize.py
diff --git a/tests/test_getimagesize.py b/tests/test_getimagesize.py
index 3a3c0a9..4cafc9d 100644
--- a/tests/test_getimagesize.py
+++ b/tests/test_getimagesize.py
@@ -1,4 +1,4 @@
-from textile.tools.imagesize import getimagesize
+from textile.utils import getimagesize
import pytest
PIL = pytest.importorskip('PIL')
diff --git a/tests/test_imagesize.py b/tests/test_imagesize.py
index e7d9d88..cb3ad68 100644
--- a/tests/test_imagesize.py
+++ b/tests/test_imagesize.py
@@ -3,7 +3,7 @@
def test_imagesize():
imgurl = 'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png'
- result = textile.tools.imagesize.getimagesize(imgurl)
+ result = textile.utils.getimagesize(imgurl)
try:
import PIL # noqa: F401
diff --git a/textile/core.py b/textile/core.py
index 8efdbea..4a2594f 100644
--- a/textile/core.py
+++ b/textile/core.py
@@ -20,13 +20,12 @@
from collections import OrderedDict
from nh3 import clean
-from textile.tools import imagesize
from textile.regex_strings import (align_re_s, cls_re_s, pnct_re_s,
regex_snippets, syms_re_s, table_span_re_s)
from textile.utils import (decode_high, encode_high, encode_html, generate_tag,
- has_raw_text, human_readable_url, is_rel_url,
- is_valid_url, list_type, normalize_newlines,
- parse_attributes, pba)
+ getimagesize, has_raw_text, human_readable_url,
+ is_rel_url, is_valid_url, list_type,
+ normalize_newlines, parse_attributes, pba)
from textile.objects import Block, Table
try:
@@ -1152,7 +1151,7 @@ def fImage(self, match):
title = ''
if not is_rel_url(url) and self.get_sizes:
- size = imagesize.getimagesize(url)
+ size = getimagesize(url)
if href:
href = self.shelveURL(href)
diff --git a/textile/textilefactory.py b/textile/textilefactory.py
index 3892988..402bf86 100644
--- a/textile/textilefactory.py
+++ b/textile/textilefactory.py
@@ -20,10 +20,7 @@ def __init__(self, restricted=False, lite=False, sanitize=False,
self.method_parms['rel'] = 'nofollow'
if noimage is None:
- if restricted:
- noimage = True
- else:
- noimage = False
+ noimage = bool(restricted)
self.class_parms['noimage'] = noimage
self.method_parms['sanitize'] = sanitize
diff --git a/textile/tools/__init__.py b/textile/tools/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/textile/tools/imagesize.py b/textile/tools/imagesize.py
deleted file mode 100644
index 6fba73e..0000000
--- a/textile/tools/imagesize.py
+++ /dev/null
@@ -1,27 +0,0 @@
-def getimagesize(url):
- """
- Attempts to determine an image's width and height, and returns a tuple,
- (width, height), in pixels or an empty string in case of failure.
- Requires that PIL is installed.
-
- """
-
- try:
- from PIL import ImageFile
- except ImportError:
- return ''
-
- from urllib.request import urlopen
-
- try:
- p = ImageFile.Parser()
- f = urlopen(url)
- while True:
- s = f.read(1024)
- if not s:
- break
- p.feed(s)
- if p.image:
- return p.image.size
- except (IOError, ValueError):
- return ''
diff --git a/textile/utils.py b/textile/utils.py
index b4516ea..578af4e 100644
--- a/textile/utils.py
+++ b/textile/utils.py
@@ -79,6 +79,35 @@ def generate_tag(tag, content, attributes=None):
return element_text
+def getimagesize(url):
+ """
+ Attempts to determine an image's width and height, and returns a tuple,
+ (width, height), in pixels or an empty string in case of failure.
+ Requires that PIL is installed.
+
+ """
+
+ try:
+ from PIL import ImageFile
+ except ImportError:
+ return ''
+
+ from urllib.request import urlopen
+
+ try:
+ p = ImageFile.Parser()
+ f = urlopen(url)
+ while True:
+ s = f.read(1024)
+ if not s:
+ break
+ p.feed(s)
+ if p.image:
+ return p.image.size
+ except (IOError, ValueError):
+ return ''
+
+
def has_raw_text(text):
"""checks whether the text has text not already enclosed by a block tag"""
r = text.strip()
From 05ec535ea96c4a5ac4fa41ea59b49933e5d6718b Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Fri, 9 Aug 2024 15:31:49 -0400
Subject: [PATCH 214/228] update CHANGELOG
---
CHANGELOG.textile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGELOG.textile b/CHANGELOG.textile
index e13f6f5..a3ff742 100644
--- a/CHANGELOG.textile
+++ b/CHANGELOG.textile
@@ -2,6 +2,8 @@ h1. Textile Changelog
h2. Version 4.0.3
* Update supported Python versions to 3.8 - 3.12 ("#83":https://github.com/textile/python-textile/issues/83)
+* Replace html5lib with nh3 for html sanitization
+* General code cleanup
* Bugfixes:
** Wrong HTML output when "bc.." is the very last in the document ("#81":https://github.com/textile/python-textile/issues/81)
* Other:
From 8498638d1d550131d4676f602443f5d128b40f92 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sat, 17 Aug 2024 15:56:40 -0400
Subject: [PATCH 215/228] typo fix to allow pytextile cli tool installation
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 08ded12..15f27c2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -41,7 +41,7 @@ Homepage = "https://github.com/textile/python-textile"
Repository = "https://github.com/textile/python-textile.git"
Issues = "https://github.com/textile/python-textile/issues"
-[python.scripts]
+[project.scripts]
pytextile = "textile.__main__:main"
[tool.setuptools.dynamic]
From e1de4a6e75c4533ac8786ba0620c7fd0b7b4851e Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 18 Aug 2024 15:00:31 -0400
Subject: [PATCH 216/228] set project keywords to current values on pypi
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 15f27c2..5e7c2db 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -30,7 +30,7 @@ dependencies = [
'regex>1.0; implementation_name != "pypy"',
]
requires-python = '>=3.8'
-keywords = ['textile', 'text', 'html', 'markup']
+keywords = ['textile', 'text', 'html markup']
[project.optional-dependencies]
develop = ['pytest', 'pytest-cov']
From a3709a07bfeec29958d8059ea2d882157436bf00 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 18 Aug 2024 15:04:53 -0400
Subject: [PATCH 217/228] attempt adding rendered README to pypi project page
---
pyproject.toml | 1 +
1 file changed, 1 insertion(+)
diff --git a/pyproject.toml b/pyproject.toml
index 5e7c2db..a2774e7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -31,6 +31,7 @@ dependencies = [
]
requires-python = '>=3.8'
keywords = ['textile', 'text', 'html markup']
+readme = {file = 'tests/fixtures/README.txt', content-type = 'text/plain'}
[project.optional-dependencies]
develop = ['pytest', 'pytest-cov']
From 51fa5c9e29a96bb2ce851d4358f204479471b61a Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 18 Aug 2024 18:52:15 -0400
Subject: [PATCH 218/228] fix formatting in README
---
README.textile | 4 ++--
tests/fixtures/README.txt | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.textile b/README.textile
index 49df25e..958ea63 100644
--- a/README.textile
+++ b/README.textile
@@ -50,8 +50,8 @@ To run the test suite, use pytest. `pytest-cov` is required as well.
When textile is installed locally:
-bc.. pytest
+bc. pytest
When textile is not installed locally:
-bc.. PYTHONPATH=. pytest
+bc. PYTHONPATH=. pytest
diff --git a/tests/fixtures/README.txt b/tests/fixtures/README.txt
index bb0ad30..515cf86 100644
--- a/tests/fixtures/README.txt
+++ b/tests/fixtures/README.txt
@@ -56,8 +56,8 @@
When textile is installed locally:
-pytest
+pytest
-When textile is not installed locally:
+ When textile is not installed locally:
PYTHONPATH=. pytest
\ No newline at end of file
From 8aa13cb6389d7f2e3806c6cf97b11fad68357359 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 18 Aug 2024 18:52:50 -0400
Subject: [PATCH 219/228] upload a pandoc-converted version of the README to
pypi
---
pyproject.toml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index a2774e7..50e2a57 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -31,7 +31,10 @@ dependencies = [
]
requires-python = '>=3.8'
keywords = ['textile', 'text', 'html markup']
-readme = {file = 'tests/fixtures/README.txt', content-type = 'text/plain'}
+# use pandoc to generate a markdown version of the README before uploading:
+# pandoc README.textile -o README.md
+# this kinda hurts to have to do this.
+readme = {file = 'README.md', content-type = 'text/markdown'}
[project.optional-dependencies]
develop = ['pytest', 'pytest-cov']
From 2f6f4de49d017a8aebef23a42768d3d1e487c894 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sun, 18 Aug 2024 19:11:41 -0400
Subject: [PATCH 220/228] ignore converted README.md
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 2ea0352..9cc80d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,4 @@ develop-eggs
.DS_Store
*.swp
.tox
+README.md
From 37225e1091197d37b373390b933548979cfd3502 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 19 Aug 2024 14:57:41 -0400
Subject: [PATCH 221/228] a better way to upload the README to pypi
---
pyproject.toml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/pyproject.toml b/pyproject.toml
index 50e2a57..caa03da 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -31,10 +31,10 @@ dependencies = [
]
requires-python = '>=3.8'
keywords = ['textile', 'text', 'html markup']
-# use pandoc to generate a markdown version of the README before uploading:
-# pandoc README.textile -o README.md
-# this kinda hurts to have to do this.
-readme = {file = 'README.md', content-type = 'text/markdown'}
+# Use the following command to generate a README.txt which is compatible with
+# pypi's readme rendering:
+# pytextile README.textile | sed -e 's/^\t//' > README.txt
+readme = {file = 'README.txt', content-type = 'text/markdown'}
[project.optional-dependencies]
develop = ['pytest', 'pytest-cov']
From 53fb39ee2a08af904be1e069e04574e11b8016c0 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 19 Aug 2024 14:58:36 -0400
Subject: [PATCH 222/228] create a Makefile to ease building a release
---
Makefile | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 Makefile
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..fff9565
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,18 @@
+clean:
+ rm README.txt
+ rm -rf ./dist ./build
+
+generate_pypi_README:
+ ${VIRTUAL_ENV}/bin/pytextile README.textile | sed -e 's/^\t//' > README.txt
+
+build: generate_pypi_README
+ python -m build
+
+upload_to_test: build
+ twine check ./dist/*
+ twine upload --repository test_textile ./dist/*
+
+upload_to_prod: build
+ twine check ./dist/*
+ # for now, don't actually upload to prod PyPI, just output the command to do so.
+ @echo "twine upload --repository textile ./dist/*"
From 0abea01888582c899202da6e5deceee50c60c797 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 19 Aug 2024 16:29:43 -0400
Subject: [PATCH 223/228] update which pypi README file to ignore
---
.gitignore | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index 9cc80d7..7f97eb6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,4 +21,4 @@ develop-eggs
.DS_Store
*.swp
.tox
-README.md
+README.txt
From f24f52fdd4410a382a96276a11f5b4e235d3438b Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Mon, 19 Aug 2024 18:07:36 -0400
Subject: [PATCH 224/228] better name for the github action
we're not building, we're linting and testing
---
.github/workflows/lint_and_test.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml
index 14ced37..d6e13da 100644
--- a/.github/workflows/lint_and_test.yml
+++ b/.github/workflows/lint_and_test.yml
@@ -4,7 +4,7 @@ name: python-textile
on: [push]
jobs:
- build:
+ lint_and_test:
runs-on: ubuntu-latest
strategy:
matrix:
From e596255998c0a46bae29ad48733ccf8f735adc7d Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Thu, 19 Sep 2024 16:58:53 -0400
Subject: [PATCH 225/228] add an __init__.py to the tests directory
Without this, when running tests locally, I get a warning from coverage
about `no data collected.`
It's not happening with the automated tests in github actions, and
googling the error seems to indicate that some people need this while
others don't. Not sure what's up, but at least, it shouldn't hurt
anything
---
tests/__init__.py | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 tests/__init__.py
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
From a5cef1b554aea531f96e8bada992878b39d3ac11 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sat, 21 Sep 2024 15:30:28 -0400
Subject: [PATCH 226/228] bumping the version number for test.pypi upload
testing
---
textile/version.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/textile/version.py b/textile/version.py
index f3c42a7..0374ae8 100644
--- a/textile/version.py
+++ b/textile/version.py
@@ -1 +1 @@
-VERSION = '4.0.2'
+VERSION = '4.0.3rc1'
From e876ddd5a470b6899dd955e1ff505fac8ca7c917 Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sat, 21 Sep 2024 16:06:00 -0400
Subject: [PATCH 227/228] a better way to handle the `make clean` task
Previously, make clean would fail if README.txt did not exist. This is
the recommended way to get around this and it just continues on silently
if there's nothing to be done
---
Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index fff9565..7570eac 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
clean:
- rm README.txt
- rm -rf ./dist ./build
+ $(RM) README.txt
+ $(RM) -r ./dist ./build
generate_pypi_README:
${VIRTUAL_ENV}/bin/pytextile README.textile | sed -e 's/^\t//' > README.txt
From 64ab026e8a5f9cfd06186fe8a19bb64cd0218a1f Mon Sep 17 00:00:00 2001
From: Dennis Burke
Date: Sat, 21 Sep 2024 16:09:01 -0400
Subject: [PATCH 228/228] prepare the final version number for release
---
textile/version.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/textile/version.py b/textile/version.py
index 0374ae8..ad53acb 100644
--- a/textile/version.py
+++ b/textile/version.py
@@ -1 +1 @@
-VERSION = '4.0.3rc1'
+VERSION = '4.0.3'