markdown exercise attempt

This commit is contained in:
Xevion
2019-07-13 23:15:06 -05:00
parent c87391f5e8
commit 42b5529dff
5 changed files with 191 additions and 0 deletions

View File

@@ -0,0 +1 @@
{"track":"python","exercise":"markdown","id":"75a6c2148fe940eb841a8ebc24e8b6ad","url":"https://exercism.io/my/solutions/75a6c2148fe940eb841a8ebc24e8b6ad","handle":"Xevion","is_requester":true,"auto_approve":false}

60
python/markdown/README.md Normal file
View File

@@ -0,0 +1,60 @@
# Markdown
Refactor a Markdown parser.
The markdown exercise is a refactoring exercise. There is code that parses a
given string with [Markdown
syntax](https://guides.github.com/features/mastering-markdown/) and returns the
associated HTML for that string. Even though this code is confusingly written
and hard to follow, somehow it works and all the tests are passing! Your
challenge is to re-write this code to make it easier to read and maintain
while still making sure that all the tests keep passing.
It would be helpful if you made notes of what you did in your refactoring in
comments so reviewers can see that, but it isn't strictly necessary. The most
important thing is to make the code better!
## Exception messages
Sometimes it is necessary to raise an exception. When you do this, you should include a meaningful error message to
indicate what the source of the error is. This makes your code more readable and helps significantly with debugging. Not
every exercise will require you to raise an exception, but for those that do, the tests will only pass if you include
a message.
To raise a message with an exception, just write it as an argument to the exception type. For example, instead of
`raise Exception`, you should write:
```python
raise Exception("Meaningful message indicating the source of the error")
```
## Running the tests
To run the tests, run the appropriate command below ([why they are different](https://github.com/pytest-dev/pytest/issues/1629#issue-161422224)):
- Python 2.7: `py.test markdown_test.py`
- Python 3.4+: `pytest markdown_test.py`
Alternatively, you can tell Python to run the pytest module (allowing the same command to be used regardless of Python version):
`python -m pytest markdown_test.py`
### Common `pytest` options
- `-v` : enable verbose output
- `-x` : stop running tests on first failure
- `--ff` : run failures from previous test before running other test cases
For other options, see `python -m pytest -h`
## Submitting Exercises
Note that, when trying to submit an exercise, make sure the solution is in the `$EXERCISM_WORKSPACE/python/markdown` directory.
You can find your Exercism workspace by running `exercism debug` and looking for the line that starts with `Workspace`.
For more detailed information about running tests, code style and linting,
please see [Running the Tests](http://exercism.io/tracks/python/tests).
## Submitting Incomplete Solutions
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

View File

@@ -0,0 +1,53 @@
import re
def parse(markdown):
lines = markdown.split('\n')
res = ''
in_list = False
in_list_append = False
for line in lines:
if re.match('###### (.*)', line) is not None:
line = '<h6>' + line[7:] + '</h6>'
elif re.match('## (.*)', line) is not None:
line = '<h2>' + line[3:] + '</h2>'
elif re.match('# (.*)', line) is not None:
line = '<h1>' + line[2:] + '</h1>'
m = re.match(r'\* (.*)', line)
if m:
in_list, is_bold, is_italic = not in_list, False, False
current_line = m.group(1)
# Bold
strongmatch = re.match('(.*)__(.*)__(.*)', current_line)
if strongmatch:
current_line = strongmatch.group(1) + '<strong>' + \
strongmatch.group(2) + '</strong>' + strongmatch.group(3)
is_bold = True
# Italics
italicmatch = re.match('(.*)_(.*)_(.*)', current_line)
if italicmatch:
current_line = italicmatch.group(1) + '<em>' + italicmatch.group(2) + \
'</em>' + italicmatch.group(3)
is_italic = True
line = '<ul><li>' + current_line + '</li>' if not in_list else '<li>' + current_line + '</li>'
else:
if in_list:
in_list_append = True
in_list = False
m = re.match('<h|<ul|<p|<li', line)
if not m:
line = '<p>' + line + '</p>'
m = re.match('(.*)__(.*)__(.*)', line)
if m:
line = m.group(1) + '<strong>' + m.group(2) + '</strong>' + m.group(3)
m = re.match('(.*)_(.*)_(.*)', line)
if m:
line = m.group(1) + '<em>' + m.group(2) + '</em>' + m.group(3)
if in_list_append:
line = '</ul>' + line
in_list_append = False
res += line
if in_list:
res += '</ul>'
return res

View File

@@ -0,0 +1,76 @@
import unittest
from markdown import parse
# Tests adapted from `problem-specifications//canonical-data.json` @ v1.4.0
class MarkdownTest(unittest.TestCase):
def test_paragraph(self):
self.assertEqual(parse('This will be a paragraph'),
'<p>This will be a paragraph</p>')
def test_italics(self):
self.assertEqual(parse('_This will be italic_'),
'<p><em>This will be italic</em></p>')
def test_bold(self):
self.assertEqual(parse('__This will be bold__'),
'<p><strong>This will be bold</strong></p>')
def test_mixed_normal_italics_and_bold(self):
self.assertEqual(parse('This will _be_ __mixed__'),
'<p>This will <em>be</em> <strong>mixed</strong></p>')
def test_h1(self):
self.assertEqual(parse('# This will be an h1'),
'<h1>This will be an h1</h1>')
def test_h2(self):
self.assertEqual(parse('## This will be an h2'),
'<h2>This will be an h2</h2>')
def test_h6(self):
self.assertEqual(parse(
'###### This will be an h6'), '<h6>This will be an h6</h6>')
def test_unordered_lists(self):
self.assertEqual(parse('* Item 1\n* Item 2'),
'<ul><li>Item 1</li>'
'<li>Item 2</li></ul>')
def test_little_bit_of_everything(self):
self.assertEqual(parse(
'# Header!\n* __Bold Item__\n* _Italic Item_'),
'<h1>Header!</h1><ul><li><strong>Bold Item</strong></li>'
'<li><em>Italic Item</em></li></ul>')
def test_symbols_in_the_header_text_that_should_not_be_interpreted(self):
self.assertEqual(
parse('# This is a header with # and * in the text'),
'<h1>This is a header with # and * in the text</h1>')
def test_symbols_in_the_list_item_text_that_should_not_be_interpreted(
self):
self.assertEqual(
parse(
'* Item 1 with a # in the text\n* Item 2 with * in the text'),
'<ul><li>Item 1 with a # in the text</li>'
'<li>Item 2 with * in the text</li></ul>')
def test_symbols_in_the_paragraph_text_that_should_not_be_interpreted(
self):
self.assertEqual(
parse('This is a paragraph with # and * in the text'),
'<p>This is a paragraph with # and * in the text</p>')
def test_unordered_lists_close_properly_with_preceding_and_following_lines(
self):
self.assertEqual(
parse('# Start a list\n* Item 1\n* Item 2\nEnd a list'),
'<h1>Start a list</h1><ul><li>Item 1</li>'
'<li>Item 2</li></ul><p>End a list</p>')
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1 @@
i