mirror of
https://github.com/Xevion/exercism.git
synced 2025-12-06 09:14:59 -06:00
markdown exercise attempt
This commit is contained in:
1
python/markdown/.exercism/metadata.json
Normal file
1
python/markdown/.exercism/metadata.json
Normal 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
60
python/markdown/README.md
Normal 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.
|
||||
53
python/markdown/markdown.py
Normal file
53
python/markdown/markdown.py
Normal 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
|
||||
76
python/markdown/markdown_test.py
Normal file
76
python/markdown/markdown_test.py
Normal 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()
|
||||
1
python/markdown/tempCodeRunnerFile.py
Normal file
1
python/markdown/tempCodeRunnerFile.py
Normal file
@@ -0,0 +1 @@
|
||||
i
|
||||
Reference in New Issue
Block a user