-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Markdown #51
Markdown #51
Changes from all commits
4661701
477fb1a
9075696
a2146e3
278d3f5
bb91f67
0c19023
fac5ef3
264dbfd
b44841b
a453383
1f80f19
199096a
0fd19b1
9481730
0dd7f3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Copyright 2017 Julien Palard | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
from __future__ import absolute_import, division, print_function | ||
|
||
import mdorrst | ||
|
||
from .rst import render as rst_renderer | ||
from .markdown import render as md_renderer | ||
from .txt import render as txt_renderer | ||
|
||
RENDERERS = {'rst': rst_renderer, | ||
'md': md_renderer, | ||
'txt': txt_renderer} | ||
|
||
|
||
def render(raw): | ||
sniffed_format = mdorrst.sniff(raw) | ||
return RENDERERS[sniffed_format](raw) or txt_renderer(raw) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Copyright 2014 Donald Stufft | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
from __future__ import absolute_import, division, print_function | ||
|
||
import markdown | ||
|
||
from .clean import clean | ||
|
||
|
||
def render(raw): | ||
try: | ||
rendered = markdown.markdown( | ||
raw, | ||
extensions=[ | ||
'markdown.extensions.codehilite', | ||
'markdown.extensions.fenced_code', | ||
'markdown.extensions.smart_strong', | ||
]) | ||
except ValueError: | ||
# Markdown failed to strip top-level tags. | ||
return None | ||
else: | ||
return clean(rendered) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<p>Here is some Python:</p> | ||
<div><pre><span></span><span class="kn">import</span> <span class="nn">os</span> | ||
|
||
<span class="k">def</span> <span class="nf">read</span><span class="p">(</span><span class="n">fn</span><span class="p">):</span> | ||
<span class="k">return</span> <span class="nb">open</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> | ||
</pre></div> | ||
|
||
|
||
<p>And some more with the commonly used short <em>py</em> mark:</p> | ||
<div><pre><span></span><span class="ch">#!/usr/bin/env python3</span> | ||
|
||
<span class="kn">import</span> <span class="nn">os</span> | ||
<span class="kn">import</span> <span class="nn">setuptools</span> | ||
|
||
<span class="n">base_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span> | ||
</pre></div> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Here is some Python: | ||
|
||
```python | ||
import os | ||
|
||
def read(fn): | ||
return open(fn).read() | ||
``` | ||
|
||
And some more with the commonly used short *py* mark: | ||
|
||
```py | ||
#!/usr/bin/env python3 | ||
|
||
import os | ||
import setuptools | ||
|
||
base_dir = os.path.dirname(__file__) | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<h1>Required packages</h1> | ||
<p>To run the PyPI software, you need Python 2.5+ and PostgreSQL</p> | ||
<h1>Quick development setup</h1> | ||
<p>Make sure you ...</p> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Required packages | ||
|
||
To run the PyPI software, you need Python 2.5+ and PostgreSQL | ||
|
||
# Quick development setup | ||
Make sure you ... |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<p>Then, you can create a <em>development environment</em> like this, | ||
if you have <strong>virtualenv</strong> installed:</p> | ||
<div><pre><span></span>$ virtualenv --no-site-packages . | ||
$ pip install -r requirements.txt | ||
</pre></div> | ||
|
||
|
||
<p>Then you can launch the server using the <code>pypi.wsgi</code> script:</p> | ||
<div><pre><span></span>$ python pypi.wsgi | ||
Serving on port <span class="m">8000</span>... | ||
</pre></div> | ||
|
||
|
||
<p>PyPI will be available in your browser at http://localhost:8000</p> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
Then, you can create a *development environment* like this, | ||
if you have **virtualenv** installed: | ||
|
||
$ virtualenv --no-site-packages . | ||
$ pip install -r requirements.txt | ||
|
||
Then you can launch the server using the `pypi.wsgi` script: | ||
|
||
$ python pypi.wsgi | ||
Serving on port 8000... | ||
|
||
PyPI will be available in your browser at http://localhost:8000 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import io | ||
import glob | ||
import os.path | ||
|
||
import pytest | ||
|
||
from readme_renderer.base import render | ||
|
||
|
||
@pytest.mark.parametrize( | ||
("src_filename", "html_filename"), | ||
[ | ||
(fn, os.path.splitext(fn)[0] + ".html") | ||
for fn in glob.glob( | ||
os.path.join(os.path.dirname(__file__), | ||
"fixtures", "test_*.rst") | ||
) + glob.glob( | ||
os.path.join(os.path.dirname(__file__), | ||
"fixtures", "markdown", "*.md") | ||
) | ||
], | ||
) | ||
def test_base_fixtures(src_filename, html_filename): | ||
too_short = { | ||
'misc.md', | ||
'test_rst_004.rst', | ||
'test_rst_005.rst', | ||
'test_rst_006.rst', | ||
'test_rst_007.rst'} | ||
if os.path.basename(src_filename) in too_short: | ||
"""sniff won't match in any cases for those files being too short | ||
tests to be sniffed correctly (like just an "<a href", or just | ||
a <script>alert("Hello")</script>) """ | ||
return | ||
# Get our Markup | ||
with io.open(src_filename, encoding='utf-8') as f: | ||
markup = f.read() | ||
|
||
# Get our expected | ||
with io.open(html_filename, encoding="utf-8") as f: | ||
expected = f.read() | ||
|
||
out = render(markup) | ||
|
||
assert out.rstrip() == expected.rstrip() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import io | ||
import os | ||
import textwrap | ||
|
||
from readme_renderer.markdown import render | ||
|
||
|
||
def test_simple(): | ||
markdown_markup = 'Hello' | ||
out = render(markdown_markup) | ||
assert out == '<p>Hello</p>' | ||
|
||
|
||
def test_url_no_link(): | ||
markdown_markup = 'http://mymalicioussite.com/' | ||
out = render(markdown_markup) | ||
expected_html = '<p>http://mymalicioussite.com/</p>' | ||
assert out == expected_html | ||
|
||
|
||
def test_iframe(): | ||
markdown_markup = """\ | ||
<iframe src="http://mymalicioussite.com/">Click here</iframe> | ||
""".strip() | ||
out = render(markdown_markup) | ||
expected_html = ''.join([ | ||
'<iframe src="http://mymalicioussite.com/">' | ||
'Click here</iframe>']) | ||
assert out == expected_html | ||
|
||
|
||
def test_script(): | ||
markdown_markup = textwrap.dedent("""\ | ||
<script> | ||
alert("Hello"); | ||
</script>""") | ||
out = render(markdown_markup) | ||
expected_html = textwrap.dedent("""\ | ||
<script> | ||
alert("Hello"); | ||
</script>""") | ||
assert out == expected_html | ||
|
||
|
||
def test_a_tag_gets_nofollow(): | ||
markdown_markup = '<a href="http://mymalicioussite.com/">Click here</a>' | ||
out = render(markdown_markup) | ||
expected_htmls = [ | ||
''.join(['<p><a rel="nofollow" href="http://mymalicioussite.com/">', | ||
'Click here</a></p>']), | ||
''.join(['<p><a href="http://mymalicioussite.com/" rel="nofollow">', | ||
'Click here</a></p>']), | ||
] | ||
assert out in expected_htmls | ||
|
||
|
||
def test_smart_strong(): | ||
markdown_markup = 'Text with double__underscore__words.' | ||
out = render(markdown_markup) | ||
expected_html = '<p>Text with double__underscore__words.</p>' | ||
assert out == expected_html | ||
|
||
|
||
def test_github_backtick_syntax_for_code(): | ||
_do_test_with_files('code') | ||
|
||
|
||
def test_headings_and_paragraphs(): | ||
_do_test_with_files('headings_and_paragraphs') | ||
|
||
|
||
def test_misc(): | ||
_do_test_with_files('misc') | ||
|
||
|
||
def _do_test_with_files(test_name): | ||
md_markup = read('{0}.md'.format(test_name)) | ||
expected_html = read('{0}.html'.format(test_name)) | ||
out = render(md_markup) | ||
assert out == expected_html.rstrip() | ||
|
||
|
||
def read(fn): | ||
path = os.path.join(os.path.dirname(__file__), 'fixtures', 'markdown', fn) | ||
with io.open(path, encoding='utf-8') as f: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for using io here either. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same, Python 2 compatibility, to give the encoding. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright, so we can change it later when python 2 is decided to be fully dropped? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I'm OK to change it later when python2 compat is dropped. Look like pypi-legacy has an indeterminate lifespan, but if we pin a legacy version of readme_renderer in pypi-lecacy requirements, we'll be able to drop python2 compatibility. For the moment, I think it's better to keep with python2 compatibility so pypi-legacy can at least get markdown. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, or port python 2's open function to accept `encoding`` as an paramiter like how python 3 does. I would have to figure out a patch for python 2 then to allow such. (because I only use python 3 now) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure backporting the Also, it will be easier to port Python 2 using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A comment here might be useful, mentioning that this a Py2 compatibility thing. |
||
return f.read() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change this to ```py. This is a shortcut for ```python.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As it's a test fixture I really don't see the point of changing this. If I touch it, maybe I can add a new block with py so the test ensure both are working?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, many people use py for shorthand anyway as it saves them some typing so I think adding that block anyway would be great.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's probably not really the responsibility of the readme_renderer tests to validate this, but it may not hurt to add it so we're also ensuring that this particular tag, probably the most used in this context, still work, so I added it.