diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0e5ca2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,107 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +.static_storage/ +.media/ +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# IDE +.idea diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0a12095 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +language: python +python: +- '3.5' +sudo: true +dist: trusty +install: +- wget https://github.com/jgm/pandoc/releases/download/2.1.1/pandoc-2.1.1-1-amd64.deb +- sudo dpkg -i pandoc-2.1.1-1-amd64.deb +- pip install -r bin/requirements.txt +script: +- python bin/dw_deploy.py tutorials +branches: + only: + - master +env: + global: + - DW_URL: https://edux.fit.cvut.cz/courses/MI-AFP + - DW_NAMESPACE: tutorials:master + - DW_USERNAME: suchama4 + - secure: kfeUcNiJ/wCzae4fSgi6m4dze44izWh3g9Yx/jpkwOeoAvEd1K7wf20dUs1dLclBCDechD2x5zjyomSJhg8zkpqDn0/6y/0Q2qtuLHcIihUybnaBg1y0OzvynPfhb9tm6ZxifvwfHPt3KmJ8QZP7EgWzXWoUpu2grrOEDVHza/K5PIyCq+TiK2NGfko/FQmpUKHYeLtcFt/gkX1KfZAJYWbcjWVkt1hhQmFH4w4eh5I4NQk+yvI8LoDzYm/b0XHtd5CCQZ+VOGoM8eKmNfDgmlIKQn6bPQHZUh57iJ7P2HEO5xfXn64fNPshEkqLgXdjRbYIo8kljRBHBkjsu0jfy3w9jCDpJR9FFAJS5ZmMfIiMrrFvbPPjmwXOAMt+ExF/lkJpp1idJoET/JLlz/GSgKdvFQGX3tDG9cNKbvNbUOd03g+FdL9Nh03HhYyFpxat94vZDK8tvm9ctTcF7dg2cW49qSa4OKp+YdBkhFvNPx3M7S5fQ+ODRFoeFhlJt2YMgW1iw8o5o77mPWTN2cGkeXeM6W4+PkN3R10nTOe2H7ZN6N+5u1NBXWCqtzit2Cq9lDSuDjRZwMhwA1znuoBtM4n1Qtz9qFov+48sZIPTk/pqHLVTF6wGpHpT5Hi65XHWqKQsjVM1+2W9dWIB+jhidKi0TlSkwBKQhQlygh7E7sQ= diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 0000000..39d4636 --- /dev/null +++ b/bin/.gitignore @@ -0,0 +1 @@ +set_env.sh diff --git a/bin/dw_deploy.py b/bin/dw_deploy.py new file mode 100644 index 0000000..b3af4a9 --- /dev/null +++ b/bin/dw_deploy.py @@ -0,0 +1,151 @@ +# Markdown to DW deployment script +# inspired by https://github.com/cvut/MI-PYT +import os +import re + +import click +import pypandoc +import requests + +from lxml import etree + + +def prefilter_haskellcode(input_md): + """Make use of pascal to enable haskell code highlighting (in md)""" + return input_md.replace('```haskell', '```pascal') + + +def postfilter_haskellcode(output_dw): + """Make use of pascal to enable haskell code highlighting (in dw)""" + return output_dw.replace('', '') + + +def prefilter_interlinking(input_md): + """Removed md from local interlinked documents in the same directory""" + return re.sub(r'\[([^\]]*)]\(([^\)\/]*)\.md\)', r'[\1](\2)', input_md) + + +class DW: + PREFILTERS = [ + prefilter_haskellcode, + prefilter_interlinking + ] + POSTFILTERS = [ + postfilter_haskellcode + ] + + def __init__(self, url, username, password): + self.url = url + '/doku.php' + self.session = self._init_session(username, password) + + @staticmethod + def _find_elem(content, type, attr, value): + tree = etree.HTML(content) + for elem in tree.findall('.//' + type): + if elem.attrib.get(attr) == value: + return elem + return None + + def _init_session(self, username, password): + session = requests.Session() + + params = {'id': 'start', 'do': 'login'} + r = session.get(self.url, params=params) + sectok_input = self._find_elem(r.text, 'input', 'name', 'sectok') + if sectok_input is None: + raise ValueError('Could not find sectok on login page') + + sectok = sectok_input.attrib.get('value', '') + login_data = { + 'sectok': sectok, + 'id': 'start', + 'do': 'login', + 'authnProvider': '2', + 'u': username, + 'p': password, + 'r': '1', + } + params['sectok'] = sectok + r = session.post(self.url, params=params, data=login_data) + if 'logout' not in r.text: + raise ValueError('Could not login') + + return session + + def put_page(self, dw_page, content): + params = {'id': dw_page, 'do': 'edit'} + r = self.session.get(self.url, params=params) + + edit_form = self._find_elem(r.text, 'form', 'id', 'dw__editform') + if edit_form is None: + raise ValueError('Could not find edit form on parsed page') + + data = {} + for inp in edit_form.findall('.//input'): + name = inp.attrib.get('name') + if not name.startswith('do['): + data[name] = inp.attrib.get('value', '') + + data['wikitext'] = content + data['do[save]'] = 'Yes, please!' + + self.session.post(r.url, data=data) + + def put_md(self, dw_page, file): + self.put_page(dw_page, self._transform_md2dw(file)) + + @classmethod + def _transform_md2dw(cls, file): + with open(file, mode='r') as f: + content = f.read() + content = cls._apply_filters(cls.PREFILTERS, content) + content = pypandoc.convert_text(content, 'dokuwiki', format='md') + content = cls._apply_filters(cls.POSTFILTERS, content) + return content + + @staticmethod + def _apply_filters(filters, text): + for flt in filters: + text = flt(text) + return text + + @staticmethod + def join(*args): + return ':'.join(args) + + +def get_files(root, extension): + files = dict() + ext_mlen = -len(extension) + for file in os.listdir(root): + path = os.path.join(root, file) + if os.path.isfile(path) and file.endswith(extension): + files[file[0:ext_mlen]] = path + return files + + +@click.command() +@click.argument('root', type=click.Path(exists=True)) +@click.option('-d', '--dw-url', help='DokuWiki URL', + envvar='DW_URL', required=True) +@click.option('-u', '--dw-username', help='DokuWiki username', + envvar='DW_USERNAME', required=True) +@click.option('-p', '--dw-password', help='DokuWiki password', + envvar='DW_PASSWORD', required=True) +@click.option('-n', '--dw-namespace', help='Target DokuWiki namespace', + envvar='DW_NAMESPACE', required=True) +def cli(root, dw_url, dw_username, dw_password, dw_namespace): + dw = DW(dw_url, dw_username, dw_password) + markdowns = get_files(root, '.md') + print('Deploying {} markdown file(s) to {}'.format( + len(markdowns), dw_url + )) + for name, file in markdowns.items(): + qname = dw.join(dw_namespace, name) + print('| ', file, '-->', qname) + dw.put_md(qname, file) + print('Done!') + + +if __name__ == '__main__': + cli() diff --git a/bin/requirements.txt b/bin/requirements.txt new file mode 100644 index 0000000..1e762ed --- /dev/null +++ b/bin/requirements.txt @@ -0,0 +1,4 @@ +click +lxml +pypandoc +requests diff --git a/bin/test.md b/bin/test.md new file mode 100644 index 0000000..2386c4c --- /dev/null +++ b/bin/test.md @@ -0,0 +1,134 @@ +# H1 + +## H2 + +### H3 + +#### H4 + +##### H5 + +###### H6 + +Emphasis, aka italics, with *asterisks* or _underscores_. + +Strong emphasis, aka bold, with **asterisks** or __underscores__. + +Combined emphasis with **asterisks and _underscores_**. + +Strikethrough uses two tildes. ~~Scratch this.~~ + +## Lists + +1. First ordered list item +2. Another item +3. Unordered sub-list. + + You can have properly indented paragraphs within list items. Notice the blank line above, and the leading spaces (at least one, but we'll use three here to also align the raw Markdown). + + To have a line break without a paragraph, you will need to use two trailing spaces. + Note that this line is separate, but within the same paragraph. + (This is contrary to the typical GFM line break behaviour, where trailing spaces are not required.) + ++ Unordered list can use asterisks ++ Or minuses ++ Or pluses + + x + + y + +## Links + +[Link to local markdown](other.md) + +[I'm an inline-style link](https://www.google.com) + +[I'm an inline-style link with title](https://www.google.com "Google's Homepage") + +[I'm a reference-style link][Arbitrary case-insensitive reference text] + +[I'm a relative reference to a repository file](../blob/master/LICENSE) + +[You can use numbers for reference-style link definitions][1] + +Or leave it empty and use the [link text itself]. + +URLs and URLs in angle brackets will automatically get turned into links. +http://www.example.com or and sometimes +example.com (but not on Github, for example). + +Some text to show that the reference links can follow later. + +[arbitrary case-insensitive reference text]: https://www.mozilla.org +[1]: http://slashdot.org +[link text itself]: http://www.reddit.com + +## Code + +Inline `code` has `back-ticks around` it. + +```javascript +var s = "JavaScript syntax highlighting"; +alert(s); +``` + +```python +s = "Python syntax highlighting" +print s +``` + +``` +No language indicated, so no syntax highlighting. +But let's throw in a tag. +``` + +```pascal +test :: Num a => a -> String +test = undefined +``` + +## Tables + +| Tables | Are | Cool | +| ------------- |:-------------:| -----:| +| col 3 is | right-aligned | $1600 | +| col 2 is | centered | $12 | +| zebra stripes | are neat | $1 | + +## Blockquote + +> Blockquotes are very handy in email to emulate reply text. +> This line is part of the same quote. + +Quote break. + +> This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote. + +## Inline HTML + +
+
Definition list
+
Is something people use sometimes.
+ +
Markdown in HTML
+
Does *not* work **very** well. Use HTML tags.
+
+ +## Horizontal Rule + +Three or more... + +--- + +Hyphens + +*** + +Asterisks + +___ + +Underscores + +## Images (TODO) + +## GitHub & DokuWiki specialties (TODO)