├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── AUTHORS
├── LICENSE
├── MANIFEST.in
├── README.md
├── dev-requirements.txt
├── docs
├── Makefile
├── _static
│ ├── logo.png
│ └── logo.svg
├── _themes
│ ├── .gitignore
│ ├── LICENSE
│ ├── README
│ ├── flask
│ │ ├── layout.html
│ │ ├── relations.html
│ │ ├── static
│ │ │ ├── flasky.css_t
│ │ │ └── small_flask.css
│ │ └── theme.conf
│ ├── flask_small
│ │ ├── layout.html
│ │ ├── static
│ │ │ └── flasky.css_t
│ │ └── theme.conf
│ └── flask_theme_support.py
├── conf.py
├── index.rst
└── make.bat
├── flask_misaka.py
├── requirements.txt
├── setup.py
└── tests.py
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 | on:
3 | pull_request:
4 | branches:
5 | - main
6 | push:
7 | branches:
8 | - main
9 |
10 | jobs:
11 | pytest:
12 | runs-on: ubuntu-latest
13 | strategy:
14 | matrix:
15 | python-version: ["3.x"]
16 | name: "pytest: Python ${{ matrix.python-version }}"
17 |
18 | steps:
19 | - uses: actions/checkout@v2
20 | - uses: actions/setup-python@v2
21 | with:
22 | python-version: ${{ matrix.python-version }}
23 |
24 | - name: Install setuptools
25 | run: pip install setuptools
26 |
27 | - name: Install dependencies
28 | run: >-
29 | pip install
30 | -r requirements.txt
31 | -r dev-requirements.txt
32 |
33 | - name: Run tests
34 | run: coverage run --source=flask_misaka setup.py test
35 |
36 | - name: Upload coverage to Codecov
37 | if: ${{ always() }}
38 | uses: codecov/codecov-action@v1
39 | with:
40 | fail_ci_if_error: false
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.DS_Store
3 | .Python
4 | *.egg
5 | *.eggs
6 | *.egg-info
7 | .coverage
8 | bin
9 | build
10 | dist
11 | docs/_build
12 | include
13 | lib
14 | man
15 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | David Baumgold
2 | Jesse Spangenberger
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012-2021 David Baumgold
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include LICENSE tests.py
2 | recursive-include docs *
3 | recursive-exclude docs *.pyc
4 | recursive-exclude docs *.pyo
5 | recursive-exclude docs *.DS_Store
6 | prune docs/_build
7 | prune docs/_themes/.git
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Flask-Misaka
2 |
3 |  [](http://codecov.io/github/singingwolfboy/flask-misaka?branch=master) [](http://flask-misaka.readthedocs.org/en/latest/?badge=latest)
4 |
5 | A simple Flask extension to integrate the [Misaka](http://misaka.61924.nl)
6 | module, which is a Python interface to the excellent
7 | [Hoedown](https://github.com/hoedown/hoedown) markdown-parsing library.
8 | Check the [Misaka changelog](http://misaka.61924.nl/changelog.html)
9 | to keep up with new features.
10 |
11 | The full documentation for this project is built using Sphinx; you can also
12 | check out [a pre-built version hosted on RTD](https://flask-misaka.readthedocs.org/en/latest/).
13 |
--------------------------------------------------------------------------------
/dev-requirements.txt:
--------------------------------------------------------------------------------
1 | Flask>=0.7
2 | coverage
3 | mock; python_version < '3.3'
4 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = _build
9 |
10 | # Internal variables.
11 | PAPEROPT_a4 = -D latex_paper_size=a4
12 | PAPEROPT_letter = -D latex_paper_size=letter
13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
14 | # the i18n builder cannot share the environment and doctrees with the others
15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
16 |
17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
18 |
19 | help:
20 | @echo "Please use \`make ' where is one of"
21 | @echo " html to make standalone HTML files"
22 | @echo " dirhtml to make HTML files named index.html in directories"
23 | @echo " singlehtml to make a single large HTML file"
24 | @echo " pickle to make pickle files"
25 | @echo " json to make JSON files"
26 | @echo " htmlhelp to make HTML files and a HTML help project"
27 | @echo " qthelp to make HTML files and a qthelp project"
28 | @echo " devhelp to make HTML files and a Devhelp project"
29 | @echo " epub to make an epub"
30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
31 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
32 | @echo " text to make text files"
33 | @echo " man to make manual pages"
34 | @echo " texinfo to make Texinfo files"
35 | @echo " info to make Texinfo files and run them through makeinfo"
36 | @echo " gettext to make PO message catalogs"
37 | @echo " changes to make an overview of all changed/added/deprecated items"
38 | @echo " linkcheck to check all external links for integrity"
39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
40 |
41 | clean:
42 | -rm -rf $(BUILDDIR)/*
43 |
44 | html:
45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
46 | @echo
47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
48 |
49 | dirhtml:
50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
51 | @echo
52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
53 |
54 | singlehtml:
55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
56 | @echo
57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
58 |
59 | pickle:
60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
61 | @echo
62 | @echo "Build finished; now you can process the pickle files."
63 |
64 | json:
65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
66 | @echo
67 | @echo "Build finished; now you can process the JSON files."
68 |
69 | htmlhelp:
70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
71 | @echo
72 | @echo "Build finished; now you can run HTML Help Workshop with the" \
73 | ".hhp project file in $(BUILDDIR)/htmlhelp."
74 |
75 | qthelp:
76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
77 | @echo
78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Flask-Misaka.qhcp"
81 | @echo "To view the help file:"
82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Flask-Misaka.qhc"
83 |
84 | devhelp:
85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
86 | @echo
87 | @echo "Build finished."
88 | @echo "To view the help file:"
89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Flask-Misaka"
90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Flask-Misaka"
91 | @echo "# devhelp"
92 |
93 | epub:
94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
95 | @echo
96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
97 |
98 | latex:
99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
100 | @echo
101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
103 | "(use \`make latexpdf' here to do that automatically)."
104 |
105 | latexpdf:
106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
107 | @echo "Running LaTeX files through pdflatex..."
108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
110 |
111 | text:
112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
113 | @echo
114 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
115 |
116 | man:
117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
118 | @echo
119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
120 |
121 | texinfo:
122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
123 | @echo
124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
125 | @echo "Run \`make' in that directory to run these through makeinfo" \
126 | "(use \`make info' here to do that automatically)."
127 |
128 | info:
129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
130 | @echo "Running Texinfo files through makeinfo..."
131 | make -C $(BUILDDIR)/texinfo info
132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
133 |
134 | gettext:
135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
136 | @echo
137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
138 |
139 | changes:
140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
141 | @echo
142 | @echo "The overview file is in $(BUILDDIR)/changes."
143 |
144 | linkcheck:
145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
146 | @echo
147 | @echo "Link check complete; look for any errors in the above output " \
148 | "or in $(BUILDDIR)/linkcheck/output.txt."
149 |
150 | doctest:
151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
152 | @echo "Testing of doctests in the sources finished, look at the " \
153 | "results in $(BUILDDIR)/doctest/output.txt."
154 |
--------------------------------------------------------------------------------
/docs/_static/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/singingwolfboy/flask-misaka/f804c05afb8633b9953faef788025377515c2553/docs/_static/logo.png
--------------------------------------------------------------------------------
/docs/_themes/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.pyo
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/docs/_themes/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010 by Armin Ronacher.
2 |
3 | Some rights reserved.
4 |
5 | Redistribution and use in source and binary forms of the theme, with or
6 | without modification, are permitted provided that the following conditions
7 | are met:
8 |
9 | * Redistributions of source code must retain the above copyright
10 | notice, this list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above
13 | copyright notice, this list of conditions and the following
14 | disclaimer in the documentation and/or other materials provided
15 | with the distribution.
16 |
17 | * The names of the contributors may not be used to endorse or
18 | promote products derived from this software without specific
19 | prior written permission.
20 |
21 | We kindly ask you to only use these themes in an unmodified manner just
22 | for Flask and Flask-related products, not for unrelated projects. If you
23 | like the visual style and want to use it for your own projects, please
24 | consider making some larger changes to the themes (such as changing
25 | font faces, sizes, colors or margins).
26 |
27 | THIS THEME IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 | ARISING IN ANY WAY OUT OF THE USE OF THIS THEME, EVEN IF ADVISED OF THE
37 | POSSIBILITY OF SUCH DAMAGE.
38 |
--------------------------------------------------------------------------------
/docs/_themes/README:
--------------------------------------------------------------------------------
1 | Flask Sphinx Styles
2 | ===================
3 |
4 | This repository contains sphinx styles for Flask and Flask related
5 | projects. To use this style in your Sphinx documentation, follow
6 | this guide:
7 |
8 | 1. put this folder as _themes into your docs folder. Alternatively
9 | you can also use git submodules to check out the contents there.
10 | 2. add this to your conf.py:
11 |
12 | sys.path.append(os.path.abspath('_themes'))
13 | html_theme_path = ['_themes']
14 | html_theme = 'flask'
15 |
16 | The following themes exist:
17 |
18 | - 'flask' - the standard flask documentation theme for large
19 | projects
20 | - 'flask_small' - small one-page theme. Intended to be used by
21 | very small addon libraries for flask.
22 |
23 | The following options exist for the flask_small theme:
24 |
25 | [options]
26 | index_logo = '' filename of a picture in _static
27 | to be used as replacement for the
28 | h1 in the index.rst file.
29 | index_logo_height = 120px height of the index logo
30 | github_fork = '' repository name on github for the
31 | "fork me" badge
32 |
--------------------------------------------------------------------------------
/docs/_themes/flask/layout.html:
--------------------------------------------------------------------------------
1 | {%- extends "basic/layout.html" %}
2 | {%- block extrahead %}
3 | {{ super() }}
4 | {% if theme_touch_icon %}
5 |
6 | {% endif %}
7 |
9 | {% endblock %}
10 | {%- block relbar2 %}{% endblock %}
11 | {% block header %}
12 | {{ super() }}
13 | {% if pagename == 'index' %}
14 |
15 | {% endif %}
16 | {% endblock %}
17 | {%- block footer %}
18 |
22 | {% if pagename == 'index' %}
23 |
24 | {% endif %}
25 | {%- endblock %}
26 |
--------------------------------------------------------------------------------
/docs/_themes/flask/relations.html:
--------------------------------------------------------------------------------
1 | Related Topics
2 |
20 |
--------------------------------------------------------------------------------
/docs/_themes/flask/static/flasky.css_t:
--------------------------------------------------------------------------------
1 | /*
2 | * flasky.css_t
3 | * ~~~~~~~~~~~~
4 | *
5 | * :copyright: Copyright 2010 by Armin Ronacher.
6 | * :license: Flask Design License, see LICENSE for details.
7 | */
8 |
9 | {% set page_width = '940px' %}
10 | {% set sidebar_width = '220px' %}
11 |
12 | @import url("basic.css");
13 |
14 | /* -- page layout ----------------------------------------------------------- */
15 |
16 | body {
17 | font-family: 'Georgia', serif;
18 | font-size: 17px;
19 | background-color: white;
20 | color: #000;
21 | margin: 0;
22 | padding: 0;
23 | }
24 |
25 | div.document {
26 | width: {{ page_width }};
27 | margin: 30px auto 0 auto;
28 | }
29 |
30 | div.documentwrapper {
31 | float: left;
32 | width: 100%;
33 | }
34 |
35 | div.bodywrapper {
36 | margin: 0 0 0 {{ sidebar_width }};
37 | }
38 |
39 | div.sphinxsidebar {
40 | width: {{ sidebar_width }};
41 | }
42 |
43 | hr {
44 | border: 1px solid #B1B4B6;
45 | }
46 |
47 | div.body {
48 | background-color: #ffffff;
49 | color: #3E4349;
50 | padding: 0 30px 0 30px;
51 | }
52 |
53 | img.floatingflask {
54 | padding: 0 0 10px 10px;
55 | float: right;
56 | }
57 |
58 | div.footer {
59 | width: {{ page_width }};
60 | margin: 20px auto 30px auto;
61 | font-size: 14px;
62 | color: #888;
63 | text-align: right;
64 | }
65 |
66 | div.footer a {
67 | color: #888;
68 | }
69 |
70 | div.related {
71 | display: none;
72 | }
73 |
74 | div.sphinxsidebar a {
75 | color: #444;
76 | text-decoration: none;
77 | border-bottom: 1px dotted #999;
78 | }
79 |
80 | div.sphinxsidebar a:hover {
81 | border-bottom: 1px solid #999;
82 | }
83 |
84 | div.sphinxsidebar {
85 | font-size: 14px;
86 | line-height: 1.5;
87 | }
88 |
89 | div.sphinxsidebarwrapper {
90 | padding: 18px 10px;
91 | }
92 |
93 | div.sphinxsidebarwrapper p.logo {
94 | padding: 0 0 20px 0;
95 | margin: 0;
96 | text-align: center;
97 | }
98 |
99 | div.sphinxsidebar h3,
100 | div.sphinxsidebar h4 {
101 | font-family: 'Garamond', 'Georgia', serif;
102 | color: #444;
103 | font-size: 24px;
104 | font-weight: normal;
105 | margin: 0 0 5px 0;
106 | padding: 0;
107 | }
108 |
109 | div.sphinxsidebar h4 {
110 | font-size: 20px;
111 | }
112 |
113 | div.sphinxsidebar h3 a {
114 | color: #444;
115 | }
116 |
117 | div.sphinxsidebar p.logo a,
118 | div.sphinxsidebar h3 a,
119 | div.sphinxsidebar p.logo a:hover,
120 | div.sphinxsidebar h3 a:hover {
121 | border: none;
122 | }
123 |
124 | div.sphinxsidebar p {
125 | color: #555;
126 | margin: 10px 0;
127 | }
128 |
129 | div.sphinxsidebar ul {
130 | margin: 10px 0;
131 | padding: 0;
132 | color: #000;
133 | }
134 |
135 | div.sphinxsidebar input {
136 | border: 1px solid #ccc;
137 | font-family: 'Georgia', serif;
138 | font-size: 1em;
139 | }
140 |
141 | /* -- body styles ----------------------------------------------------------- */
142 |
143 | a {
144 | color: #004B6B;
145 | text-decoration: underline;
146 | }
147 |
148 | a:hover {
149 | color: #6D4100;
150 | text-decoration: underline;
151 | }
152 |
153 | div.body h1,
154 | div.body h2,
155 | div.body h3,
156 | div.body h4,
157 | div.body h5,
158 | div.body h6 {
159 | font-family: 'Garamond', 'Georgia', serif;
160 | font-weight: normal;
161 | margin: 30px 0px 10px 0px;
162 | padding: 0;
163 | }
164 |
165 | {% if theme_index_logo %}
166 | div.indexwrapper h1 {
167 | text-indent: -999999px;
168 | background: url({{ theme_index_logo }}) no-repeat center center;
169 | height: {{ theme_index_logo_height }};
170 | }
171 | {% endif %}
172 |
173 | div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
174 | div.body h2 { font-size: 180%; }
175 | div.body h3 { font-size: 150%; }
176 | div.body h4 { font-size: 130%; }
177 | div.body h5 { font-size: 100%; }
178 | div.body h6 { font-size: 100%; }
179 |
180 | a.headerlink {
181 | color: #ddd;
182 | padding: 0 4px;
183 | text-decoration: none;
184 | }
185 |
186 | a.headerlink:hover {
187 | color: #444;
188 | background: #eaeaea;
189 | }
190 |
191 | div.body p, div.body dd, div.body li {
192 | line-height: 1.4em;
193 | }
194 |
195 | div.admonition {
196 | background: #fafafa;
197 | margin: 20px -30px;
198 | padding: 10px 30px;
199 | border-top: 1px solid #ccc;
200 | border-bottom: 1px solid #ccc;
201 | }
202 |
203 | div.admonition tt.xref, div.admonition a tt {
204 | border-bottom: 1px solid #fafafa;
205 | }
206 |
207 | dd div.admonition {
208 | margin-left: -60px;
209 | padding-left: 60px;
210 | }
211 |
212 | div.admonition p.admonition-title {
213 | font-family: 'Garamond', 'Georgia', serif;
214 | font-weight: normal;
215 | font-size: 24px;
216 | margin: 0 0 10px 0;
217 | padding: 0;
218 | line-height: 1;
219 | }
220 |
221 | div.admonition p.last {
222 | margin-bottom: 0;
223 | }
224 |
225 | div.highlight {
226 | background-color: white;
227 | }
228 |
229 | dt:target, .highlight {
230 | background: #FAF3E8;
231 | }
232 |
233 | div.note {
234 | background-color: #eee;
235 | border: 1px solid #ccc;
236 | }
237 |
238 | div.seealso {
239 | background-color: #ffc;
240 | border: 1px solid #ff6;
241 | }
242 |
243 | div.topic {
244 | background-color: #eee;
245 | }
246 |
247 | p.admonition-title {
248 | display: inline;
249 | }
250 |
251 | p.admonition-title:after {
252 | content: ":";
253 | }
254 |
255 | pre, tt {
256 | font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
257 | font-size: 0.9em;
258 | }
259 |
260 | img.screenshot {
261 | }
262 |
263 | tt.descname, tt.descclassname {
264 | font-size: 0.95em;
265 | }
266 |
267 | tt.descname {
268 | padding-right: 0.08em;
269 | }
270 |
271 | img.screenshot {
272 | -moz-box-shadow: 2px 2px 4px #eee;
273 | -webkit-box-shadow: 2px 2px 4px #eee;
274 | box-shadow: 2px 2px 4px #eee;
275 | }
276 |
277 | table.docutils {
278 | border: 1px solid #888;
279 | -moz-box-shadow: 2px 2px 4px #eee;
280 | -webkit-box-shadow: 2px 2px 4px #eee;
281 | box-shadow: 2px 2px 4px #eee;
282 | }
283 |
284 | table.docutils td, table.docutils th {
285 | border: 1px solid #888;
286 | padding: 0.25em 0.7em;
287 | }
288 |
289 | table.field-list, table.footnote {
290 | border: none;
291 | -moz-box-shadow: none;
292 | -webkit-box-shadow: none;
293 | box-shadow: none;
294 | }
295 |
296 | table.footnote {
297 | margin: 15px 0;
298 | width: 100%;
299 | border: 1px solid #eee;
300 | background: #fdfdfd;
301 | font-size: 0.9em;
302 | }
303 |
304 | table.footnote + table.footnote {
305 | margin-top: -15px;
306 | border-top: none;
307 | }
308 |
309 | table.field-list th {
310 | padding: 0 0.8em 0 0;
311 | }
312 |
313 | table.field-list td {
314 | padding: 0;
315 | }
316 |
317 | table.footnote td.label {
318 | width: 0px;
319 | padding: 0.3em 0 0.3em 0.5em;
320 | }
321 |
322 | table.footnote td {
323 | padding: 0.3em 0.5em;
324 | }
325 |
326 | dl {
327 | margin: 0;
328 | padding: 0;
329 | }
330 |
331 | dl dd {
332 | margin-left: 30px;
333 | }
334 |
335 | blockquote {
336 | margin: 0 0 0 30px;
337 | padding: 0;
338 | }
339 |
340 | ul, ol {
341 | margin: 10px 0 10px 30px;
342 | padding: 0;
343 | }
344 |
345 | pre {
346 | background: #eee;
347 | padding: 7px 30px;
348 | margin: 15px -30px;
349 | line-height: 1.3em;
350 | }
351 |
352 | dl pre, blockquote pre, li pre {
353 | margin-left: -60px;
354 | padding-left: 60px;
355 | }
356 |
357 | dl dl pre {
358 | margin-left: -90px;
359 | padding-left: 90px;
360 | }
361 |
362 | tt {
363 | background-color: #ecf0f3;
364 | color: #222;
365 | /* padding: 1px 2px; */
366 | }
367 |
368 | tt.xref, a tt {
369 | background-color: #FBFBFB;
370 | border-bottom: 1px solid white;
371 | }
372 |
373 | a.reference {
374 | text-decoration: none;
375 | border-bottom: 1px dotted #004B6B;
376 | }
377 |
378 | a.reference:hover {
379 | border-bottom: 1px solid #6D4100;
380 | }
381 |
382 | a.footnote-reference {
383 | text-decoration: none;
384 | font-size: 0.7em;
385 | vertical-align: top;
386 | border-bottom: 1px dotted #004B6B;
387 | }
388 |
389 | a.footnote-reference:hover {
390 | border-bottom: 1px solid #6D4100;
391 | }
392 |
393 | a:hover tt {
394 | background: #EEE;
395 | }
396 |
--------------------------------------------------------------------------------
/docs/_themes/flask/static/small_flask.css:
--------------------------------------------------------------------------------
1 | /*
2 | * small_flask.css_t
3 | * ~~~~~~~~~~~~~~~~~
4 | *
5 | * :copyright: Copyright 2010 by Armin Ronacher.
6 | * :license: Flask Design License, see LICENSE for details.
7 | */
8 |
9 | body {
10 | margin: 0;
11 | padding: 20px 30px;
12 | }
13 |
14 | div.documentwrapper {
15 | float: none;
16 | background: white;
17 | }
18 |
19 | div.sphinxsidebar {
20 | display: block;
21 | float: none;
22 | width: 102.5%;
23 | margin: 50px -30px -20px -30px;
24 | padding: 10px 20px;
25 | background: #333;
26 | color: white;
27 | }
28 |
29 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
30 | div.sphinxsidebar h3 a {
31 | color: white;
32 | }
33 |
34 | div.sphinxsidebar a {
35 | color: #aaa;
36 | }
37 |
38 | div.sphinxsidebar p.logo {
39 | display: none;
40 | }
41 |
42 | div.document {
43 | width: 100%;
44 | margin: 0;
45 | }
46 |
47 | div.related {
48 | display: block;
49 | margin: 0;
50 | padding: 10px 0 20px 0;
51 | }
52 |
53 | div.related ul,
54 | div.related ul li {
55 | margin: 0;
56 | padding: 0;
57 | }
58 |
59 | div.footer {
60 | display: none;
61 | }
62 |
63 | div.bodywrapper {
64 | margin: 0;
65 | }
66 |
67 | div.body {
68 | min-height: 0;
69 | padding: 0;
70 | }
71 |
--------------------------------------------------------------------------------
/docs/_themes/flask/theme.conf:
--------------------------------------------------------------------------------
1 | [theme]
2 | inherit = basic
3 | stylesheet = flasky.css
4 | pygments_style = flask_theme_support.FlaskyStyle
5 |
6 | [options]
7 | index_logo = ''
8 | index_logo_height = 120px
9 | touch_icon =
10 |
--------------------------------------------------------------------------------
/docs/_themes/flask_small/layout.html:
--------------------------------------------------------------------------------
1 | {% extends "basic/layout.html" %}
2 | {% block header %}
3 | {{ super() }}
4 | {% if pagename == 'index' %}
5 |
6 | {% endif %}
7 | {% endblock %}
8 | {% block footer %}
9 | {% if pagename == 'index' %}
10 |
11 | {% endif %}
12 | {% endblock %}
13 | {# do not display relbars #}
14 | {% block relbar1 %}{% endblock %}
15 | {% block relbar2 %}
16 | {% if theme_github_fork %}
17 |
19 | {% endif %}
20 | {% endblock %}
21 | {% block sidebar1 %}{% endblock %}
22 | {% block sidebar2 %}{% endblock %}
23 |
--------------------------------------------------------------------------------
/docs/_themes/flask_small/static/flasky.css_t:
--------------------------------------------------------------------------------
1 | /*
2 | * flasky.css_t
3 | * ~~~~~~~~~~~~
4 | *
5 | * Sphinx stylesheet -- flasky theme based on nature theme.
6 | *
7 | * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | @import url("basic.css");
13 |
14 | /* -- page layout ----------------------------------------------------------- */
15 |
16 | body {
17 | font-family: 'Georgia', serif;
18 | font-size: 17px;
19 | color: #000;
20 | background: white;
21 | margin: 0;
22 | padding: 0;
23 | }
24 |
25 | div.documentwrapper {
26 | float: left;
27 | width: 100%;
28 | }
29 |
30 | div.bodywrapper {
31 | margin: 40px auto 0 auto;
32 | width: 700px;
33 | }
34 |
35 | hr {
36 | border: 1px solid #B1B4B6;
37 | }
38 |
39 | div.body {
40 | background-color: #ffffff;
41 | color: #3E4349;
42 | padding: 0 30px 30px 30px;
43 | }
44 |
45 | img.floatingflask {
46 | padding: 0 0 10px 10px;
47 | float: right;
48 | }
49 |
50 | div.footer {
51 | text-align: right;
52 | color: #888;
53 | padding: 10px;
54 | font-size: 14px;
55 | width: 650px;
56 | margin: 0 auto 40px auto;
57 | }
58 |
59 | div.footer a {
60 | color: #888;
61 | text-decoration: underline;
62 | }
63 |
64 | div.related {
65 | line-height: 32px;
66 | color: #888;
67 | }
68 |
69 | div.related ul {
70 | padding: 0 0 0 10px;
71 | }
72 |
73 | div.related a {
74 | color: #444;
75 | }
76 |
77 | /* -- body styles ----------------------------------------------------------- */
78 |
79 | a {
80 | color: #004B6B;
81 | text-decoration: underline;
82 | }
83 |
84 | a:hover {
85 | color: #6D4100;
86 | text-decoration: underline;
87 | }
88 |
89 | div.body {
90 | padding-bottom: 40px; /* saved for footer */
91 | }
92 |
93 | div.body h1,
94 | div.body h2,
95 | div.body h3,
96 | div.body h4,
97 | div.body h5,
98 | div.body h6 {
99 | font-family: 'Garamond', 'Georgia', serif;
100 | font-weight: normal;
101 | margin: 30px 0px 10px 0px;
102 | padding: 0;
103 | }
104 |
105 | {% if theme_index_logo %}
106 | div.indexwrapper h1 {
107 | text-indent: -999999px;
108 | background: url({{ theme_index_logo }}) no-repeat center center;
109 | height: {{ theme_index_logo_height }};
110 | }
111 | {% endif %}
112 |
113 | div.body h2 { font-size: 180%; }
114 | div.body h3 { font-size: 150%; }
115 | div.body h4 { font-size: 130%; }
116 | div.body h5 { font-size: 100%; }
117 | div.body h6 { font-size: 100%; }
118 |
119 | a.headerlink {
120 | color: white;
121 | padding: 0 4px;
122 | text-decoration: none;
123 | }
124 |
125 | a.headerlink:hover {
126 | color: #444;
127 | background: #eaeaea;
128 | }
129 |
130 | div.body p, div.body dd, div.body li {
131 | line-height: 1.4em;
132 | }
133 |
134 | div.admonition {
135 | background: #fafafa;
136 | margin: 20px -30px;
137 | padding: 10px 30px;
138 | border-top: 1px solid #ccc;
139 | border-bottom: 1px solid #ccc;
140 | }
141 |
142 | div.admonition p.admonition-title {
143 | font-family: 'Garamond', 'Georgia', serif;
144 | font-weight: normal;
145 | font-size: 24px;
146 | margin: 0 0 10px 0;
147 | padding: 0;
148 | line-height: 1;
149 | }
150 |
151 | div.admonition p.last {
152 | margin-bottom: 0;
153 | }
154 |
155 | div.highlight{
156 | background-color: white;
157 | }
158 |
159 | dt:target, .highlight {
160 | background: #FAF3E8;
161 | }
162 |
163 | div.note {
164 | background-color: #eee;
165 | border: 1px solid #ccc;
166 | }
167 |
168 | div.seealso {
169 | background-color: #ffc;
170 | border: 1px solid #ff6;
171 | }
172 |
173 | div.topic {
174 | background-color: #eee;
175 | }
176 |
177 | div.warning {
178 | background-color: #ffe4e4;
179 | border: 1px solid #f66;
180 | }
181 |
182 | p.admonition-title {
183 | display: inline;
184 | }
185 |
186 | p.admonition-title:after {
187 | content: ":";
188 | }
189 |
190 | pre, tt {
191 | font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
192 | font-size: 0.85em;
193 | }
194 |
195 | img.screenshot {
196 | }
197 |
198 | tt.descname, tt.descclassname {
199 | font-size: 0.95em;
200 | }
201 |
202 | tt.descname {
203 | padding-right: 0.08em;
204 | }
205 |
206 | img.screenshot {
207 | -moz-box-shadow: 2px 2px 4px #eee;
208 | -webkit-box-shadow: 2px 2px 4px #eee;
209 | box-shadow: 2px 2px 4px #eee;
210 | }
211 |
212 | table.docutils {
213 | border: 1px solid #888;
214 | -moz-box-shadow: 2px 2px 4px #eee;
215 | -webkit-box-shadow: 2px 2px 4px #eee;
216 | box-shadow: 2px 2px 4px #eee;
217 | }
218 |
219 | table.docutils td, table.docutils th {
220 | border: 1px solid #888;
221 | padding: 0.25em 0.7em;
222 | }
223 |
224 | table.field-list, table.footnote {
225 | border: none;
226 | -moz-box-shadow: none;
227 | -webkit-box-shadow: none;
228 | box-shadow: none;
229 | }
230 |
231 | table.footnote {
232 | margin: 15px 0;
233 | width: 100%;
234 | border: 1px solid #eee;
235 | }
236 |
237 | table.field-list th {
238 | padding: 0 0.8em 0 0;
239 | }
240 |
241 | table.field-list td {
242 | padding: 0;
243 | }
244 |
245 | table.footnote td {
246 | padding: 0.5em;
247 | }
248 |
249 | dl {
250 | margin: 0;
251 | padding: 0;
252 | }
253 |
254 | dl dd {
255 | margin-left: 30px;
256 | }
257 |
258 | pre {
259 | padding: 0;
260 | margin: 15px -30px;
261 | padding: 8px;
262 | line-height: 1.3em;
263 | padding: 7px 30px;
264 | background: #eee;
265 | border-radius: 2px;
266 | -moz-border-radius: 2px;
267 | -webkit-border-radius: 2px;
268 | }
269 |
270 | dl pre {
271 | margin-left: -60px;
272 | padding-left: 60px;
273 | }
274 |
275 | tt {
276 | background-color: #ecf0f3;
277 | color: #222;
278 | /* padding: 1px 2px; */
279 | }
280 |
281 | tt.xref, a tt {
282 | background-color: #FBFBFB;
283 | }
284 |
285 | a:hover tt {
286 | background: #EEE;
287 | }
288 |
--------------------------------------------------------------------------------
/docs/_themes/flask_small/theme.conf:
--------------------------------------------------------------------------------
1 | [theme]
2 | inherit = basic
3 | stylesheet = flasky.css
4 | nosidebar = true
5 | pygments_style = flask_theme_support.FlaskyStyle
6 |
7 | [options]
8 | index_logo = ''
9 | index_logo_height = 120px
10 | github_fork = ''
11 |
--------------------------------------------------------------------------------
/docs/_themes/flask_theme_support.py:
--------------------------------------------------------------------------------
1 | # flasky extensions. flasky pygments style based on tango style
2 | from pygments.style import Style
3 | from pygments.token import Keyword, Name, Comment, String, Error, \
4 | Number, Operator, Generic, Whitespace, Punctuation, Other, Literal
5 |
6 |
7 | class FlaskyStyle(Style):
8 | background_color = "#f8f8f8"
9 | default_style = ""
10 |
11 | styles = {
12 | # No corresponding class for the following:
13 | #Text: "", # class: ''
14 | Whitespace: "underline #f8f8f8", # class: 'w'
15 | Error: "#a40000 border:#ef2929", # class: 'err'
16 | Other: "#000000", # class 'x'
17 |
18 | Comment: "italic #8f5902", # class: 'c'
19 | Comment.Preproc: "noitalic", # class: 'cp'
20 |
21 | Keyword: "bold #004461", # class: 'k'
22 | Keyword.Constant: "bold #004461", # class: 'kc'
23 | Keyword.Declaration: "bold #004461", # class: 'kd'
24 | Keyword.Namespace: "bold #004461", # class: 'kn'
25 | Keyword.Pseudo: "bold #004461", # class: 'kp'
26 | Keyword.Reserved: "bold #004461", # class: 'kr'
27 | Keyword.Type: "bold #004461", # class: 'kt'
28 |
29 | Operator: "#582800", # class: 'o'
30 | Operator.Word: "bold #004461", # class: 'ow' - like keywords
31 |
32 | Punctuation: "bold #000000", # class: 'p'
33 |
34 | # because special names such as Name.Class, Name.Function, etc.
35 | # are not recognized as such later in the parsing, we choose them
36 | # to look the same as ordinary variables.
37 | Name: "#000000", # class: 'n'
38 | Name.Attribute: "#c4a000", # class: 'na' - to be revised
39 | Name.Builtin: "#004461", # class: 'nb'
40 | Name.Builtin.Pseudo: "#3465a4", # class: 'bp'
41 | Name.Class: "#000000", # class: 'nc' - to be revised
42 | Name.Constant: "#000000", # class: 'no' - to be revised
43 | Name.Decorator: "#888", # class: 'nd' - to be revised
44 | Name.Entity: "#ce5c00", # class: 'ni'
45 | Name.Exception: "bold #cc0000", # class: 'ne'
46 | Name.Function: "#000000", # class: 'nf'
47 | Name.Property: "#000000", # class: 'py'
48 | Name.Label: "#f57900", # class: 'nl'
49 | Name.Namespace: "#000000", # class: 'nn' - to be revised
50 | Name.Other: "#000000", # class: 'nx'
51 | Name.Tag: "bold #004461", # class: 'nt' - like a keyword
52 | Name.Variable: "#000000", # class: 'nv' - to be revised
53 | Name.Variable.Class: "#000000", # class: 'vc' - to be revised
54 | Name.Variable.Global: "#000000", # class: 'vg' - to be revised
55 | Name.Variable.Instance: "#000000", # class: 'vi' - to be revised
56 |
57 | Number: "#990000", # class: 'm'
58 |
59 | Literal: "#000000", # class: 'l'
60 | Literal.Date: "#000000", # class: 'ld'
61 |
62 | String: "#4e9a06", # class: 's'
63 | String.Backtick: "#4e9a06", # class: 'sb'
64 | String.Char: "#4e9a06", # class: 'sc'
65 | String.Doc: "italic #8f5902", # class: 'sd' - like a comment
66 | String.Double: "#4e9a06", # class: 's2'
67 | String.Escape: "#4e9a06", # class: 'se'
68 | String.Heredoc: "#4e9a06", # class: 'sh'
69 | String.Interpol: "#4e9a06", # class: 'si'
70 | String.Other: "#4e9a06", # class: 'sx'
71 | String.Regex: "#4e9a06", # class: 'sr'
72 | String.Single: "#4e9a06", # class: 's1'
73 | String.Symbol: "#4e9a06", # class: 'ss'
74 |
75 | Generic: "#000000", # class: 'g'
76 | Generic.Deleted: "#a40000", # class: 'gd'
77 | Generic.Emph: "italic #000000", # class: 'ge'
78 | Generic.Error: "#ef2929", # class: 'gr'
79 | Generic.Heading: "bold #000080", # class: 'gh'
80 | Generic.Inserted: "#00A000", # class: 'gi'
81 | Generic.Output: "#888", # class: 'go'
82 | Generic.Prompt: "#745334", # class: 'gp'
83 | Generic.Strong: "bold #000000", # class: 'gs'
84 | Generic.Subheading: "bold #800080", # class: 'gu'
85 | Generic.Traceback: "bold #a40000", # class: 'gt'
86 | }
87 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Flask-Misaka documentation build configuration file, created by
4 | # sphinx-quickstart on Thu Nov 1 20:28:32 2012.
5 | #
6 | # This file is execfile()d with the current directory set to its containing dir.
7 | #
8 | # Note that not all possible configuration values are present in this
9 | # autogenerated file.
10 | #
11 | # All configuration values have a default; values that are commented out
12 | # serve to show the default.
13 |
14 | import sys, os
15 |
16 | # If extensions (or modules to document with autodoc) are in another directory,
17 | # add these directories to sys.path here. If the directory is relative to the
18 | # documentation root, use os.path.abspath to make it absolute, like shown here.
19 | sys.path.insert(0, os.path.abspath('..'))
20 | sys.path.append(os.path.abspath('_themes'))
21 | from flask_misaka import __version__
22 |
23 | # -- General configuration -----------------------------------------------------
24 |
25 | # If your documentation needs a minimal Sphinx version, state it here.
26 | #needs_sphinx = '1.0'
27 |
28 | # Add any Sphinx extension module names here, as strings. They can be extensions
29 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
30 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx']
31 |
32 | # Add any paths that contain templates here, relative to this directory.
33 | templates_path = ['_templates']
34 |
35 | # The suffix of source filenames.
36 | source_suffix = '.rst'
37 |
38 | # The encoding of source files.
39 | #source_encoding = 'utf-8-sig'
40 |
41 | # The master toctree document.
42 | master_doc = 'index'
43 |
44 | # General information about the project.
45 | project = u'Flask-Misaka'
46 | copyright = u'2012-2016, David Baumgold'
47 |
48 | # The version info for the project you're documenting, acts as replacement for
49 | # |version| and |release|, also used in various other places throughout the
50 | # built documents.
51 | #
52 | # The short X.Y version.
53 | version = __version__
54 | # The full version, including alpha/beta/rc tags.
55 | release = version
56 |
57 | # The language for content autogenerated by Sphinx. Refer to documentation
58 | # for a list of supported languages.
59 | #language = None
60 |
61 | # There are two options for replacing |today|: either, you set today to some
62 | # non-false value, then it is used:
63 | #today = ''
64 | # Else, today_fmt is used as the format for a strftime call.
65 | #today_fmt = '%B %d, %Y'
66 |
67 | # List of patterns, relative to source directory, that match files and
68 | # directories to ignore when looking for source files.
69 | exclude_patterns = ['_build']
70 |
71 | # The reST default role (used for this markup: `text`) to use for all documents.
72 | #default_role = None
73 |
74 | # If true, '()' will be appended to :func: etc. cross-reference text.
75 | #add_function_parentheses = True
76 |
77 | # If true, the current module name will be prepended to all description
78 | # unit titles (such as .. function::).
79 | #add_module_names = True
80 |
81 | # If true, sectionauthor and moduleauthor directives will be shown in the
82 | # output. They are ignored by default.
83 | #show_authors = False
84 |
85 | # The name of the Pygments (syntax highlighting) style to use.
86 | pygments_style = 'sphinx'
87 |
88 | # A list of ignored prefixes for module index sorting.
89 | #modindex_common_prefix = []
90 |
91 |
92 | # -- Options for HTML output ---------------------------------------------------
93 |
94 | # The theme to use for HTML and HTML Help pages. See the documentation for
95 | # a list of builtin themes.
96 | html_theme = 'flask_small'
97 |
98 | # Theme options are theme-specific and customize the look and feel of a theme
99 | # further. For a list of options available for each theme, see the
100 | # documentation.
101 | html_theme_options = {
102 | "github_fork": "singingwolfboy/flask-misaka",
103 | "index_logo": "logo.png",
104 | }
105 |
106 | # Add any paths that contain custom themes here, relative to this directory.
107 | html_theme_path = ['_themes']
108 |
109 | # The name for this set of Sphinx documents. If None, it defaults to
110 | # " v documentation".
111 | #html_title = None
112 |
113 | # A shorter title for the navigation bar. Default is the same as html_title.
114 | #html_short_title = None
115 |
116 | # The name of an image file (relative to this directory) to place at the top
117 | # of the sidebar.
118 | #html_logo = None
119 |
120 | # The name of an image file (within the static path) to use as favicon of the
121 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
122 | # pixels large.
123 | #html_favicon = None
124 |
125 | # Add any paths that contain custom static files (such as style sheets) here,
126 | # relative to this directory. They are copied after the builtin static files,
127 | # so a file named "default.css" will overwrite the builtin "default.css".
128 | html_static_path = ['_static']
129 |
130 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
131 | # using the given strftime format.
132 | #html_last_updated_fmt = '%b %d, %Y'
133 |
134 | # If true, SmartyPants will be used to convert quotes and dashes to
135 | # typographically correct entities.
136 | #html_use_smartypants = True
137 |
138 | # Custom sidebar templates, maps document names to template names.
139 | #html_sidebars = {}
140 |
141 | # Additional templates that should be rendered to pages, maps page names to
142 | # template names.
143 | #html_additional_pages = {}
144 |
145 | # If false, no module index is generated.
146 | #html_domain_indices = True
147 |
148 | # If false, no index is generated.
149 | #html_use_index = True
150 |
151 | # If true, the index is split into individual pages for each letter.
152 | #html_split_index = False
153 |
154 | # If true, links to the reST sources are added to the pages.
155 | #html_show_sourcelink = True
156 |
157 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
158 | #html_show_sphinx = True
159 |
160 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
161 | #html_show_copyright = True
162 |
163 | # If true, an OpenSearch description file will be output, and all pages will
164 | # contain a tag referring to it. The value of this option must be the
165 | # base URL from which the finished HTML is served.
166 | #html_use_opensearch = ''
167 |
168 | # This is the file name suffix for HTML files (e.g. ".xhtml").
169 | #html_file_suffix = None
170 |
171 | # Output file base name for HTML help builder.
172 | htmlhelp_basename = 'Flask-Misakadoc'
173 |
174 |
175 | # -- Options for LaTeX output --------------------------------------------------
176 |
177 | latex_elements = {
178 | # The paper size ('letterpaper' or 'a4paper').
179 | #'papersize': 'letterpaper',
180 |
181 | # The font size ('10pt', '11pt' or '12pt').
182 | #'pointsize': '10pt',
183 |
184 | # Additional stuff for the LaTeX preamble.
185 | #'preamble': '',
186 | }
187 |
188 | # Grouping the document tree into LaTeX files. List of tuples
189 | # (source start file, target name, title, author, documentclass [howto/manual]).
190 | latex_documents = [
191 | ('index', 'Flask-Misaka.tex', u'Flask-Misaka Documentation',
192 | u'David Baumgold', 'manual'),
193 | ]
194 |
195 | # The name of an image file (relative to this directory) to place at the top of
196 | # the title page.
197 | #latex_logo = None
198 |
199 | # For "manual" documents, if this is true, then toplevel headings are parts,
200 | # not chapters.
201 | #latex_use_parts = False
202 |
203 | # If true, show page references after internal links.
204 | #latex_show_pagerefs = False
205 |
206 | # If true, show URL addresses after external links.
207 | #latex_show_urls = False
208 |
209 | # Documents to append as an appendix to all manuals.
210 | #latex_appendices = []
211 |
212 | # If false, no module index is generated.
213 | #latex_domain_indices = True
214 |
215 |
216 | # -- Options for manual page output --------------------------------------------
217 |
218 | # One entry per manual page. List of tuples
219 | # (source start file, name, description, authors, manual section).
220 | man_pages = [
221 | ('index', 'flask-misaka', u'Flask-Misaka Documentation',
222 | [u'David Baumgold'], 1)
223 | ]
224 |
225 | # If true, show URL addresses after external links.
226 | #man_show_urls = False
227 |
228 |
229 | # -- Options for Texinfo output ------------------------------------------------
230 |
231 | # Grouping the document tree into Texinfo files. List of tuples
232 | # (source start file, target name, title, author,
233 | # dir menu entry, description, category)
234 | texinfo_documents = [
235 | ('index', 'Flask-Misaka', u'Flask-Misaka Documentation',
236 | u'David Baumgold', 'Flask-Misaka', 'One line description of project.',
237 | 'Miscellaneous'),
238 | ]
239 |
240 | # Documents to append as an appendix to all manuals.
241 | #texinfo_appendices = []
242 |
243 | # If false, no module index is generated.
244 | #texinfo_domain_indices = True
245 |
246 | # How to display URL addresses: 'footnote', 'no', or 'inline'.
247 | #texinfo_show_urls = 'footnote'
248 |
249 | intersphinx_mapping = {
250 | 'flask': ('http://flask.pocoo.org/docs/', None),
251 | 'misaka': ('http://misaka.61924.nl/', None),
252 | }
253 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | Flask-Misaka
2 | ============
3 |
4 | .. module:: flask_misaka
5 |
6 | Flask-Misaka provides a pleasant interface between the `Flask`_ web framework
7 | and the `Misaka`_ `Markdown`_ parser. [#technically]_
8 |
9 | Installation
10 | ------------
11 |
12 | Install the extension with:
13 |
14 | .. code-block:: sh
15 |
16 | $ pip install Flask-Misaka
17 |
18 | Usage
19 | ----------
20 | Just import the :func:`markdown` function and use it!
21 |
22 | .. code-block:: python
23 |
24 | >>> from flask_misaka import markdown
25 | >>> markdown("A *simple* example.")
26 | Markup(u'A simple example.
\n')
27 |
28 | To use Markdown in your templates, you just need to import the :class:`Misaka`
29 | class and wrap your Flask instance with it:
30 |
31 | .. code-block:: python
32 |
33 | from flask import Flask
34 | from flask_misaka import Misaka
35 |
36 | app = Flask(__name__)
37 | Misaka(app)
38 |
39 | or use the :ref:`application factory pattern `:
40 |
41 | .. code-block:: python
42 |
43 | md = Misaka()
44 | app = Flask(__name__)
45 | md.init_app(app)
46 |
47 | And then the ``markdown`` filter will be available in your `Jinja2`_ templates.
48 | You can pass variables in your template through it:
49 |
50 | .. code-block:: jinja
51 |
52 | {{ text|markdown }}
53 |
54 | Or, you can use the ``filter`` tag to write your template directly in Markdown
55 | and have Jinja dynamically interpret it for you!
56 |
57 | .. code-block:: jinja
58 |
59 | {% filter markdown %}
60 | I'm writing my templates in *Markdown!*
61 | {% endfilter %}
62 |
63 |
64 | API
65 | ---
66 | .. autofunction:: markdown
67 |
68 | .. autoclass:: Misaka
69 | :members: __init__, init_app, render
70 |
71 | Options
72 | -------
73 | Misaka is very customizable, and `supports many Markdown extensions
74 | `_. Flask-Misaka provides a nicer API for these
75 | extensions. All functions in the public API (except :py:meth:`Misaka.init_app`)
76 | accept the following boolean arguments, all of which default to False:
77 |
78 | .. list-table:: Flask-Misaka options
79 | :header-rows: 1
80 |
81 | * - Option Name
82 | - Description
83 |
84 | * - ``autolink``
85 | - Parse links even when they are not enclosed in ``<>`` characters.
86 | Autolinks for the http, https and ftp protocols will be automatically
87 | detected. Email addresses are also handled, and http links without
88 | protocol, but starting with ``www``.
89 |
90 | * - ``fenced_code``
91 | - Blocks delimited with 3 or more ``~`` or backticks will be considered
92 | as code, without the need to be indented. An optional language name
93 | may be added at the end of the opening fence for the code block.
94 |
95 | * - ``underline``
96 | - Treat text surrounded by underscores (like ``_this_``) as underlined,
97 | rather than emphasized.
98 |
99 | * - ``highlight``
100 | - Treat text surrounded by double equal signs (like ``==this==``)
101 | as highlighted.
102 |
103 | * - ``quote``
104 | - Parse inline quotes (like ``"this"``). This allows the renderer to
105 | control how they are rendered.
106 |
107 | * - ``math``
108 | - Parse inline LaTeX-style math blocks (like ``$$this$$``).
109 |
110 | * - ``math_explicit``
111 | - Parse inline LaTeX-style math blocks with a single dollar, e.g.
112 | ``$x + y = 3$``
113 |
114 | * - ``disable_indented_code`` or ``no_indented_code``
115 | - Ignore indented code blocks
116 |
117 | * - ``no_intra_emphasis``
118 | - Do not parse emphasis inside of words. Strings such as ``foo_bar_baz``
119 | will not generate ```` tags.
120 |
121 | * - ``space_headers``
122 | - A space is always required between the hash at the beginning of
123 | a header and its name, e.g. ``#this is my header`` would not be
124 | a valid header.
125 |
126 | * - ``strikethrough``
127 | - Two ``~`` characters mark the start of a strikethrough, e.g.
128 | ``this is ~~good~~ bad``.
129 |
130 | * - ``superscript``
131 | - Parse superscripts after the ``^`` character; contiguous superscripts
132 | are nested together, and complex values can be enclosed in parenthesis,
133 | e.g. ``this is the 2^(nd) time``.
134 |
135 | * - ``tables``
136 | - Parse `PHP-Markdown tables`_.
137 |
138 | * - ``hard_wrap`` *or* ``wrap``
139 | - Insert HTML `` `` tags inside on paragraphs where the origin
140 | Markdown document had newlines (by default, Markdown
141 | ignores these newlines).
142 |
143 | * - ``footnotes``
144 | - Parse Markdown footnotes.
145 |
146 | * - ``escape``
147 | - Escape all HTML tags, regardless of what they are.
148 |
149 | * - ``skip_html`` *or* ``no_html``
150 | - Do not allow any user-inputted HTML in the output.
151 |
152 | * - ``use_xhtml`` *or* ``xhtml``
153 | - Output XHTML-conformant tags.
154 |
155 | * - ``smartypants``
156 | - Post-process rendered markdown text with `SmartyPants`_.
157 |
158 |
159 | Any option that starts with ``no_`` can also be passed as its inverse set to
160 | False. For example, ``no_html=True`` and ``html=False`` have exactly the same
161 | effect, just as ``no_intra_emphasis=True`` and ``intra_emphasis=False`` have
162 | exactly the same effect.
163 |
164 | .. note::
165 | To override an option, you must use exactly the same option name as you used
166 | to originally set the option. If you set ``html=False`` as a default, you
167 | must override it with ``html=True``: using ``no_html=False`` or
168 | ``skip_html=False`` will not work, even though they all refer to the same
169 | thing.
170 |
171 | .. _Flask: http://flask.pocoo.org/
172 | .. _Jinja2: http://jinja.pocoo.org/
173 | .. _Misaka: http://misaka.61924.nl/
174 | .. _Markdown: http://en.wikipedia.org/wiki/Markdown
175 | .. _Hoedown: https://github.com/hoedown/hoedown
176 | .. _PHP-Markdown tables: http://michelf.com/projects/php-markdown/extra/#table
177 | .. _SmartyPants: http://daringfireball.net/projects/smartypants/
178 | .. _inline LaTex-style math: https://github.com/bhollis/maruku/blob/master/docs/math.md
179 |
180 | .. rubric:: Footnotes
181 | .. [#technically]
182 | (Technically, `Misaka`_ is just a Python binding to the `Hoedown`_ library,
183 | which is written in C.)
184 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | REM Command file for Sphinx documentation
4 |
5 | if "%SPHINXBUILD%" == "" (
6 | set SPHINXBUILD=sphinx-build
7 | )
8 | set BUILDDIR=_build
9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
10 | set I18NSPHINXOPTS=%SPHINXOPTS% .
11 | if NOT "%PAPER%" == "" (
12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
14 | )
15 |
16 | if "%1" == "" goto help
17 |
18 | if "%1" == "help" (
19 | :help
20 | echo.Please use `make ^` where ^ is one of
21 | echo. html to make standalone HTML files
22 | echo. dirhtml to make HTML files named index.html in directories
23 | echo. singlehtml to make a single large HTML file
24 | echo. pickle to make pickle files
25 | echo. json to make JSON files
26 | echo. htmlhelp to make HTML files and a HTML help project
27 | echo. qthelp to make HTML files and a qthelp project
28 | echo. devhelp to make HTML files and a Devhelp project
29 | echo. epub to make an epub
30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
31 | echo. text to make text files
32 | echo. man to make manual pages
33 | echo. texinfo to make Texinfo files
34 | echo. gettext to make PO message catalogs
35 | echo. changes to make an overview over all changed/added/deprecated items
36 | echo. linkcheck to check all external links for integrity
37 | echo. doctest to run all doctests embedded in the documentation if enabled
38 | goto end
39 | )
40 |
41 | if "%1" == "clean" (
42 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
43 | del /q /s %BUILDDIR%\*
44 | goto end
45 | )
46 |
47 | if "%1" == "html" (
48 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
49 | if errorlevel 1 exit /b 1
50 | echo.
51 | echo.Build finished. The HTML pages are in %BUILDDIR%/html.
52 | goto end
53 | )
54 |
55 | if "%1" == "dirhtml" (
56 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
57 | if errorlevel 1 exit /b 1
58 | echo.
59 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
60 | goto end
61 | )
62 |
63 | if "%1" == "singlehtml" (
64 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
65 | if errorlevel 1 exit /b 1
66 | echo.
67 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
68 | goto end
69 | )
70 |
71 | if "%1" == "pickle" (
72 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
73 | if errorlevel 1 exit /b 1
74 | echo.
75 | echo.Build finished; now you can process the pickle files.
76 | goto end
77 | )
78 |
79 | if "%1" == "json" (
80 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
81 | if errorlevel 1 exit /b 1
82 | echo.
83 | echo.Build finished; now you can process the JSON files.
84 | goto end
85 | )
86 |
87 | if "%1" == "htmlhelp" (
88 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
89 | if errorlevel 1 exit /b 1
90 | echo.
91 | echo.Build finished; now you can run HTML Help Workshop with the ^
92 | .hhp project file in %BUILDDIR%/htmlhelp.
93 | goto end
94 | )
95 |
96 | if "%1" == "qthelp" (
97 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
98 | if errorlevel 1 exit /b 1
99 | echo.
100 | echo.Build finished; now you can run "qcollectiongenerator" with the ^
101 | .qhcp project file in %BUILDDIR%/qthelp, like this:
102 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Flask-Misaka.qhcp
103 | echo.To view the help file:
104 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Flask-Misaka.ghc
105 | goto end
106 | )
107 |
108 | if "%1" == "devhelp" (
109 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
110 | if errorlevel 1 exit /b 1
111 | echo.
112 | echo.Build finished.
113 | goto end
114 | )
115 |
116 | if "%1" == "epub" (
117 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
118 | if errorlevel 1 exit /b 1
119 | echo.
120 | echo.Build finished. The epub file is in %BUILDDIR%/epub.
121 | goto end
122 | )
123 |
124 | if "%1" == "latex" (
125 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
126 | if errorlevel 1 exit /b 1
127 | echo.
128 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
129 | goto end
130 | )
131 |
132 | if "%1" == "text" (
133 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
134 | if errorlevel 1 exit /b 1
135 | echo.
136 | echo.Build finished. The text files are in %BUILDDIR%/text.
137 | goto end
138 | )
139 |
140 | if "%1" == "man" (
141 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
142 | if errorlevel 1 exit /b 1
143 | echo.
144 | echo.Build finished. The manual pages are in %BUILDDIR%/man.
145 | goto end
146 | )
147 |
148 | if "%1" == "texinfo" (
149 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
150 | if errorlevel 1 exit /b 1
151 | echo.
152 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
153 | goto end
154 | )
155 |
156 | if "%1" == "gettext" (
157 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
158 | if errorlevel 1 exit /b 1
159 | echo.
160 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
161 | goto end
162 | )
163 |
164 | if "%1" == "changes" (
165 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
166 | if errorlevel 1 exit /b 1
167 | echo.
168 | echo.The overview file is in %BUILDDIR%/changes.
169 | goto end
170 | )
171 |
172 | if "%1" == "linkcheck" (
173 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
174 | if errorlevel 1 exit /b 1
175 | echo.
176 | echo.Link check complete; look for any errors in the above output ^
177 | or in %BUILDDIR%/linkcheck/output.txt.
178 | goto end
179 | )
180 |
181 | if "%1" == "doctest" (
182 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
183 | if errorlevel 1 exit /b 1
184 | echo.
185 | echo.Testing of doctests in the sources finished, look at the ^
186 | results in %BUILDDIR%/doctest/output.txt.
187 | goto end
188 | )
189 |
190 | :end
191 |
--------------------------------------------------------------------------------
/flask_misaka.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, unicode_literals
2 |
3 | __version__ = '1.0.1'
4 |
5 | import misaka
6 | from markupsafe import Markup
7 | from copy import copy
8 |
9 | # import constants for compatibility
10 | from misaka import (EXT_AUTOLINK, EXT_FENCED_CODE, # pyflakes.ignore
11 | EXT_NO_INTRA_EMPHASIS, EXT_SPACE_HEADERS, EXT_STRIKETHROUGH,
12 | EXT_SUPERSCRIPT, EXT_TABLES, HTML_ESCAPE, HTML_HARD_WRAP, HTML_SKIP_HTML,
13 | HTML_USE_XHTML, TABLE_ALIGNMASK, TABLE_HEADER, TABLE_ALIGN_CENTER, TABLE_ALIGN_LEFT,
14 | TABLE_ALIGN_RIGHT, EXT_MATH, EXT_FOOTNOTES, EXT_UNDERLINE, EXT_MATH_EXPLICIT,
15 | EXT_DISABLE_INDENTED_CODE, EXT_HIGHLIGHT, EXT_QUOTE)
16 |
17 | ALIAS_EXT = {
18 | 'autolink': EXT_AUTOLINK,
19 | 'fenced_code': EXT_FENCED_CODE,
20 | 'no_intra_emphasis': EXT_NO_INTRA_EMPHASIS,
21 | 'space_headers': EXT_SPACE_HEADERS,
22 | 'strikethrough': EXT_STRIKETHROUGH,
23 | 'superscript': EXT_SUPERSCRIPT,
24 | 'tables': EXT_TABLES,
25 | 'math': EXT_MATH,
26 | 'footnotes': EXT_FOOTNOTES,
27 | 'underline': EXT_UNDERLINE,
28 | 'math_explicit': EXT_MATH_EXPLICIT,
29 | 'disable_indented_code': EXT_DISABLE_INDENTED_CODE,
30 | 'no_indented_code': EXT_DISABLE_INDENTED_CODE,
31 | 'highlight': EXT_HIGHLIGHT,
32 | 'quote': EXT_QUOTE
33 | }
34 |
35 | ALIAS_RENDER = {
36 | 'escape': HTML_ESCAPE,
37 | 'hard_wrap': HTML_HARD_WRAP,
38 | 'wrap': HTML_HARD_WRAP,
39 | 'skip_html': HTML_SKIP_HTML,
40 | 'no_html': HTML_SKIP_HTML,
41 | 'use_xhtml': HTML_USE_XHTML,
42 | 'xhtml': HTML_USE_XHTML,
43 | }
44 |
45 |
46 | def make_flags(**options):
47 | ext = 0
48 | for name, val in ALIAS_EXT.items():
49 | if options.get(name):
50 | ext = ext | val
51 | if name.startswith("no_"):
52 | if options.get(name[3:]) is False:
53 | ext = ext | val
54 |
55 | rndr = 0
56 | for name, val in ALIAS_RENDER.items():
57 | if options.get(name):
58 | rndr = rndr | val
59 | if name.startswith("no_"):
60 | if options.get(name[3:]) is False:
61 | rndr = rndr | val
62 |
63 | return ext, rndr
64 |
65 |
66 | def markdown(text, renderer=None, **options):
67 | """
68 | Parses the provided Markdown-formatted text into valid HTML, and returns
69 | it as a :class:`flask.Markup` instance.
70 |
71 | :param text: Markdown-formatted text to be rendered into HTML
72 | :param renderer: A custom misaka renderer to be used instead of the default one
73 | :param options: Additional options for customizing the default renderer
74 | :return: A :class:`flask.Markup` instance representing the rendered text
75 | """
76 | ext, rndr = make_flags(**options)
77 | if renderer:
78 | md = misaka.Markdown(renderer,ext)
79 | result = md(text)
80 | else:
81 | result = misaka.html(text, extensions=ext, render_flags=rndr)
82 | if options.get("smartypants"):
83 | result = misaka.smartypants(result)
84 | return Markup(result)
85 |
86 |
87 | class Misaka(object):
88 | def __init__(self, app=None, renderer=None, **defaults):
89 | """
90 | Set the default options for the :meth:`render` method. If you want
91 | the ``markdown`` template filter to use options, set them here.
92 |
93 | A custom misaka renderer can be specified to be used instead of the
94 | default one.
95 | """
96 | self.renderer = renderer
97 | self.defaults = defaults
98 | if app:
99 | self.init_app(app)
100 |
101 | def init_app(self, app):
102 | """
103 | Registers the rendering method as template filter.
104 |
105 | :param app: a :class:`flask.Flask` instance.
106 | """
107 | app.jinja_env.filters.setdefault('markdown', self.render)
108 |
109 | def render(self, text, **overrides):
110 | """
111 | It delegates to the :func:`markdown` function, passing any default
112 | options or renderer set in the :meth:`__init__` method.
113 |
114 | The ``markdown`` template filter calls this method.
115 |
116 | :param text: Markdown-formatted text to be rendered to HTML
117 | :param overrides: Additional options which may override the defaults
118 | :return: A :class:`flask.Markup` instance representing the rendered text
119 | """
120 | options = self.defaults
121 | if overrides:
122 | options = copy(options)
123 | options.update(overrides)
124 | return markdown(text, self.renderer, **options)
125 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | markupsafe
2 | misaka>=2.0,<3.0
3 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import re
3 | from setuptools import setup, find_packages
4 |
5 | tests_require = ['Flask']
6 | if sys.version_info[0] < 3:
7 | tests_require.append('mock')
8 |
9 | version = ''
10 | with open('flask_misaka.py', 'r') as fd:
11 | version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]',
12 | fd.read(), re.MULTILINE).group(1)
13 |
14 | if not version:
15 | raise RuntimeError('Cannot find version information')
16 |
17 | setup(
18 | name='Flask-Misaka',
19 | version=version,
20 | url='https://github.com/singingwolfboy/flask-misaka/',
21 | license='MIT',
22 | author='David Baumgold',
23 | author_email='david@davidbaumgold.com',
24 | description='A pleasant interface between the Flask web framework and the Misaka Markdown parser.',
25 | zip_safe=False,
26 | packages=find_packages(),
27 | py_modules=['flask_misaka'],
28 | install_requires=[
29 | 'markupsafe',
30 | 'misaka>=2.0,<3.0',
31 | ],
32 | test_suite='tests',
33 | tests_require=tests_require,
34 | classifiers=[
35 | 'Development Status :: 5 - Production/Stable',
36 | 'Programming Language :: Python',
37 | 'Programming Language :: Python :: 2',
38 | 'Programming Language :: Python :: 2.7',
39 | 'Programming Language :: Python :: 3',
40 | 'Programming Language :: Python :: 3.3',
41 | 'Environment :: Web Environment',
42 | 'Framework :: Flask',
43 | 'Intended Audience :: Developers',
44 | 'License :: OSI Approved :: MIT License',
45 | 'Topic :: Software Development :: Libraries :: Python Modules',
46 | ],
47 | )
48 |
--------------------------------------------------------------------------------
/tests.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 | from flask import Flask, render_template_string
3 | from markupsafe import Markup
4 | from unittest import TestCase
5 | from textwrap import dedent
6 | try:
7 | from unittest import mock
8 | except ImportError:
9 | import mock
10 |
11 | import misaka
12 | from misaka import (EXT_AUTOLINK, EXT_FENCED_CODE, # pyflakes.ignore
13 | EXT_NO_INTRA_EMPHASIS, EXT_SPACE_HEADERS, EXT_STRIKETHROUGH,
14 | EXT_SUPERSCRIPT, EXT_TABLES, HTML_ESCAPE, HTML_HARD_WRAP, HTML_SKIP_HTML,
15 | HTML_USE_XHTML, TABLE_ALIGNMASK, TABLE_HEADER, TABLE_ALIGN_CENTER, TABLE_ALIGN_LEFT,
16 | TABLE_ALIGN_RIGHT, EXT_MATH, EXT_FOOTNOTES, EXT_UNDERLINE, EXT_MATH_EXPLICIT,
17 | EXT_DISABLE_INDENTED_CODE, EXT_HIGHLIGHT, EXT_QUOTE)
18 |
19 | from flask_misaka import Misaka, markdown
20 |
21 | TEST_MD = "*This* ~~contains~~ ``some`` mark^(down) extensions: www.markdown.com foo_bar_baz it's"
22 |
23 | app = Flask(__name__)
24 | app.debug = True
25 | Misaka(app)
26 |
27 | # templating tests #
28 |
29 |
30 | @app.route('/a')
31 | def view_render_inline():
32 | s = "This is ~~restructuredtext~~ *markdown*"
33 | return render_template_string('{{s|markdown}}', s=s)
34 |
35 |
36 | def test_render_inline():
37 | client = app.test_client()
38 | resp = client.open('/a')
39 | assert resp.data == b'This is ~~restructuredtext~~ markdown
\n'
40 |
41 |
42 | @app.route('/b')
43 | def view_render_var_block():
44 | s = "This is a *markdown* block"
45 | tpl = '''{% filter markdown %}{{s}}{% endfilter %}'''
46 | return render_template_string(tpl, s=s)
47 |
48 |
49 | def test_render_var_block():
50 | client = app.test_client()
51 | resp = client.open('/b')
52 | assert resp.data == b'This is a markdown block
\n'
53 |
54 |
55 | @app.route('/c')
56 | def view_render_in_block():
57 | tpl = '''{% filter markdown %}This is a *markdown* block{% endfilter %}'''
58 | return render_template_string(tpl)
59 |
60 |
61 | def test_render_in_block():
62 | client = app.test_client()
63 | resp = client.open('/c')
64 | assert resp.data == b'This is a markdown block
\n'
65 |
66 | # markdown extensions in templates
67 |
68 | extapp = Flask(__name__)
69 | extapp.debug = True
70 | Misaka(extapp, strikethrough=True)
71 |
72 |
73 | @extapp.route('/d')
74 | def view_render_inline_ext():
75 | s = "This is ~~restructuredtext~~ *markdown*"
76 | return render_template_string('{{s|markdown}}', s=s)
77 |
78 |
79 | def test_render_inline_ext():
80 | client = extapp.test_client()
81 | resp = client.open('/d')
82 | assert resp.data == b'This is restructuredtext markdown
\n'
83 |
84 |
85 | # Note that the Markdown extension tests aren't actually testing that the
86 | # Markdown is rendered correctly; that should be covered by the test suite of
87 | # the misaka module. These tests should test that Flask-Misaka is calling
88 | # the misaka module correctly, and returning the result unmodified
89 | # (aside from being wrapped in a Markup class instance.)
90 |
91 | @mock.patch("flask_misaka.misaka.html", side_effect=misaka.html)
92 | class MarkdownExtensionTests(TestCase):
93 | def test_defaults(self, html):
94 | ext, flags = 0, 0
95 |
96 | result = markdown(TEST_MD)
97 |
98 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
99 | self.assertIsInstance(result, Markup)
100 | self.assertEqual(result, misaka.html(TEST_MD,
101 | extensions=ext, render_flags=flags))
102 |
103 | def test_one_ext(self, html):
104 | ext, flags = EXT_AUTOLINK, 0
105 |
106 | result = markdown(TEST_MD, autolink=True)
107 |
108 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
109 | self.assertIsInstance(result, Markup)
110 | self.assertEqual(result, misaka.html(TEST_MD,
111 | extensions=ext, render_flags=flags))
112 |
113 | def test_two_ext(self, html):
114 | ext, flags = EXT_FENCED_CODE | EXT_AUTOLINK, 0
115 |
116 | result = markdown(TEST_MD, fenced_code=True, autolink=True)
117 |
118 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
119 | self.assertIsInstance(result, Markup)
120 | self.assertEqual(result, misaka.html(TEST_MD,
121 | extensions=ext, render_flags=flags))
122 |
123 | def test_one_render(self, html):
124 | ext, flags = 0, HTML_ESCAPE
125 |
126 | result = markdown(TEST_MD, escape=True)
127 |
128 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
129 | self.assertIsInstance(result, Markup)
130 | self.assertEqual(result, misaka.html(TEST_MD,
131 | extensions=ext, render_flags=flags))
132 |
133 | def test_two_render(self, html):
134 | ext, flags = 0, HTML_HARD_WRAP | HTML_ESCAPE
135 |
136 | result = markdown(TEST_MD, wrap=True, escape=True)
137 |
138 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
139 | self.assertIsInstance(result, Markup)
140 | self.assertEqual(result, misaka.html(TEST_MD,
141 | extensions=ext, render_flags=flags))
142 |
143 | def test_one_ext_one_render(self, html):
144 | ext, flags = EXT_NO_INTRA_EMPHASIS, HTML_SKIP_HTML
145 |
146 | result = markdown(TEST_MD, no_intra_emphasis=True, no_html=True)
147 |
148 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
149 | self.assertIsInstance(result, Markup)
150 | self.assertEqual(result, misaka.html(TEST_MD,
151 | extensions=ext, render_flags=flags))
152 |
153 | def test_two_ext_two_render(self, html):
154 | ext = EXT_STRIKETHROUGH | EXT_SUPERSCRIPT
155 | flags = HTML_HARD_WRAP | HTML_USE_XHTML
156 |
157 | result = markdown(TEST_MD, strikethrough=True, superscript=True,
158 | hard_wrap=True, use_xhtml=True)
159 |
160 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
161 | self.assertIsInstance(result, Markup)
162 | self.assertEqual(result, misaka.html(TEST_MD,
163 | extensions=ext, render_flags=flags))
164 |
165 | def test_inverse_ext(self, html):
166 | ext, flags = EXT_NO_INTRA_EMPHASIS, 0
167 |
168 | result = markdown(TEST_MD, intra_emphasis=False)
169 |
170 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
171 | self.assertIsInstance(result, Markup)
172 | self.assertEqual(result, misaka.html(TEST_MD,
173 | extensions=ext, render_flags=flags))
174 |
175 | def test_inverse_render(self, html):
176 | ext, flags = 0, HTML_SKIP_HTML
177 |
178 | result = markdown(TEST_MD, no_html=True)
179 |
180 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
181 | self.assertIsInstance(result, Markup)
182 | self.assertEqual(result, misaka.html(TEST_MD,
183 | extensions=ext, render_flags=flags))
184 |
185 | def test_undefined_option(self, html):
186 | ext, flags = 0, 0
187 |
188 | result = markdown(TEST_MD, fireworks=True)
189 |
190 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
191 | self.assertIsInstance(result, Markup)
192 | self.assertEqual(result, misaka.html(TEST_MD,
193 | extensions=ext, render_flags=flags))
194 |
195 | def test_defined_and_undefined_options(self, html):
196 | ext, flags = 0, HTML_HARD_WRAP
197 |
198 | result = markdown(TEST_MD, hard_wrap=True, stupid_hard_wrap=False)
199 |
200 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
201 | self.assertIsInstance(result, Markup)
202 | self.assertEqual(result, misaka.html(TEST_MD,
203 | extensions=ext, render_flags=flags))
204 |
205 | def test_set_defaults(self, html):
206 | ext, flags = EXT_TABLES, HTML_HARD_WRAP
207 |
208 | md = Misaka(hard_wrap=True, tables=True)
209 | result = md.render(TEST_MD)
210 |
211 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
212 | self.assertIsInstance(result, Markup)
213 | self.assertEqual(result, misaka.html(TEST_MD,
214 | extensions=ext, render_flags=flags))
215 |
216 | def test_override_defaults(self, html):
217 | ext, flags = 0, 0
218 |
219 | md = Misaka(autolink=True)
220 | result = md.render(TEST_MD, autolink=False)
221 |
222 | html.assert_called_with(TEST_MD, extensions=ext, render_flags=flags)
223 | self.assertIsInstance(result, Markup)
224 | self.assertEqual(result, misaka.html(TEST_MD,
225 | extensions=ext, render_flags=flags))
226 |
227 | def test_custom_renderer(self, html):
228 |
229 | class CustomRenderer(misaka.HtmlRenderer):
230 | def image(self, link, title, alt_text):
231 | return '{1}
'.format(
232 | link, title, alt_text)
233 |
234 | test_md = ''
235 | expected_result = '
Title
\n'
236 |
237 | md = Misaka(None, CustomRenderer())
238 | result = md.render(test_md)
239 | self.assertFalse(html.called)
240 | self.assertEqual(str(result), expected_result)
241 |
242 | def test_smartypants(self, html):
243 | text = "Don't call me Shirley"
244 | expected_result = "Don’t call me Shirley
\n"
245 |
246 | md = Misaka(smartypants=True)
247 | result = md.render(text)
248 |
249 | self.assertIsInstance(result, Markup)
250 | self.assertEqual(result, expected_result)
251 |
252 | def test_smartypants_table(self, html):
253 | "smartypants should not interfere with processing tables"
254 |
255 | text = dedent("""
256 | | Left align | Right align | Center align |
257 | |:-----------|------------:|:------------:|
258 | | This | This | This |
259 | | column | column | column |
260 | | will | will | will |
261 | | be | be | be |
262 | | left | right | center |
263 | | aligned | aligned | aligned |
264 | """)
265 | expected_result = dedent("""
266 |
267 |
268 |
269 | Left align
270 | Right align
271 | Center align
272 |
273 |
274 |
275 |
276 |
277 | This
278 | This
279 | This
280 |
281 |
282 | column
283 | column
284 | column
285 |
286 |
287 | will
288 | will
289 | will
290 |
291 |
292 | be
293 | be
294 | be
295 |
296 |
297 | left
298 | right
299 | center
300 |
301 |
302 | aligned
303 | aligned
304 | aligned
305 |
306 |
307 |
308 | """)
309 |
310 | md = Misaka(tables=True, smartypants=True)
311 | result = md.render(text).strip()
312 |
313 | self.assertIsInstance(result, Markup)
314 | self.assertEqual(result.strip(), expected_result.strip())
315 |
316 |
317 | class FactoryPatternTests(TestCase):
318 | def test_init(self):
319 | md = Misaka()
320 | app2 = Flask(__name__)
321 | md.init_app(app2)
322 | self.assertIn("markdown", app2.jinja_env.filters)
323 |
--------------------------------------------------------------------------------