django-markdown-view 0.0.6b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_markdown_view-0.0.6b2.dist-info/METADATA +312 -0
- django_markdown_view-0.0.6b2.dist-info/RECORD +37 -0
- django_markdown_view-0.0.6b2.dist-info/WHEEL +5 -0
- django_markdown_view-0.0.6b2.dist-info/licenses/LICENSE +27 -0
- django_markdown_view-0.0.6b2.dist-info/top_level.txt +1 -0
- markdown_view/__init__.py +1 -0
- markdown_view/apps.py +12 -0
- markdown_view/checks.py +42 -0
- markdown_view/constants.py +11 -0
- markdown_view/loaders.py +61 -0
- markdown_view/markdown_extensions.py +19 -0
- markdown_view/models.py +0 -0
- markdown_view/registry.py +343 -0
- markdown_view/templates/markdown_view/markdown.html +28 -0
- markdown_view/tests/__init__.py +0 -0
- markdown_view/tests/fixtures/loaders_a/readme.md +4 -0
- markdown_view/tests/fixtures/loaders_b/readme.md +4 -0
- markdown_view/tests/settings/__init__.py +0 -0
- markdown_view/tests/settings/coveralls_settings.py +74 -0
- markdown_view/tests/test_checks.py +38 -0
- markdown_view/tests/test_loaders.py +68 -0
- markdown_view/tests/test_markdown_extensions.py +36 -0
- markdown_view/tests/test_registry.py +337 -0
- markdown_view/tests/test_settings_validation.py +55 -0
- markdown_view/tests/test_views.py +169 -0
- markdown_view/tests/testapp/CONTEXT_TEST.md +3 -0
- markdown_view/tests/testapp/LOGGED_IN.md +3 -0
- markdown_view/tests/testapp/NESTED.md +5 -0
- markdown_view/tests/testapp/NO_HEADERS.md +4 -0
- markdown_view/tests/testapp/README.md +35 -0
- markdown_view/tests/testapp/STAFF.md +3 -0
- markdown_view/tests/testapp/UNROUTED.md +4 -0
- markdown_view/tests/testapp/__init__.py +0 -0
- markdown_view/tests/testapp/apps.py +6 -0
- markdown_view/tests/testapp/docs/OTHER.md +8 -0
- markdown_view/tests/urls.py +109 -0
- markdown_view/views.py +109 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-markdown-view
|
|
3
|
+
Version: 0.0.6b2
|
|
4
|
+
Summary: Serve .md pages as Django views.
|
|
5
|
+
Author-email: "Ryan J. Sullivan" <ryanj@ryanjsullivan.com>
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, http://github.com/rgs258/django-markdown-view
|
|
8
|
+
Keywords: django,markdown,markdown view,md
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Framework :: Django :: 5.2
|
|
11
|
+
Classifier: Framework :: Django :: 6.0
|
|
12
|
+
Classifier: Framework :: Django
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python
|
|
16
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/x-rst
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: django>=5.2
|
|
26
|
+
Requires-Dist: markdown>=3.2
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
Django Markdown View
|
|
30
|
+
====================
|
|
31
|
+
|
|
32
|
+
.. image:: https://github.com/rgs258/django-markdown-view/actions/workflows/test.yml/badge.svg
|
|
33
|
+
:target: https://github.com/rgs258/django-markdown-view/actions/workflows/test.yml
|
|
34
|
+
|
|
35
|
+
.. image:: https://coveralls.io/repos/github/rgs258/django-markdown-view/badge.svg?branch=master
|
|
36
|
+
:target: https://coveralls.io/github/rgs258/django-markdown-view?branch=master
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
**Serve .md pages as Django views.**
|
|
40
|
+
|
|
41
|
+
This package aims to make it easy to serve .md files on Django sites.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
.. contents:: Contents
|
|
45
|
+
:depth: 5
|
|
46
|
+
|
|
47
|
+
Installation
|
|
48
|
+
------------
|
|
49
|
+
|
|
50
|
+
#. Install with ``pip install django-markdown-view``.
|
|
51
|
+
|
|
52
|
+
#. Add ``'markdown_view'`` to your ``INSTALLED_APPS`` settings.
|
|
53
|
+
|
|
54
|
+
.. code-block:: python
|
|
55
|
+
|
|
56
|
+
INSTALLED_APPS = [
|
|
57
|
+
...,
|
|
58
|
+
'markdown_view',
|
|
59
|
+
...
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
#. (OPTIONAL) Add ``MARKDOWN_VIEW_BASE_DIR`` or ``BASE_DIR`` to settings
|
|
63
|
+
The dictionary of the application's base. See Settings_ below
|
|
64
|
+
|
|
65
|
+
For example, if settings are in config/settings/base.py, then:
|
|
66
|
+
|
|
67
|
+
.. code-block:: python
|
|
68
|
+
|
|
69
|
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
Usage
|
|
73
|
+
-----
|
|
74
|
+
|
|
75
|
+
Views
|
|
76
|
+
~~~~~
|
|
77
|
+
|
|
78
|
+
Use one of ``MarkdownView``, ``LoggedInMarkdownView``, or ``StaffMarkdownView``
|
|
79
|
+
from ``markdown_view.views`` to serve a .md file
|
|
80
|
+
|
|
81
|
+
.. code-block:: python
|
|
82
|
+
|
|
83
|
+
from markdown_view.views import StaffMarkdownView
|
|
84
|
+
|
|
85
|
+
path('readme/',
|
|
86
|
+
StaffMarkdownView.as_view(file_name='my_app/README.md'),
|
|
87
|
+
name="readme"),
|
|
88
|
+
|
|
89
|
+
Settings
|
|
90
|
+
~~~~~~~~
|
|
91
|
+
|
|
92
|
+
All settings are optional. See `<markdown_view/constants.py>`_ for the defaults.
|
|
93
|
+
|
|
94
|
+
* `MARKDOWN_VIEW_BASE_DIR` and `BASE_DIR`
|
|
95
|
+
|
|
96
|
+
When present, the value is taken as a location to append to the list of dirs that
|
|
97
|
+
Django's `django.template.utils.get_app_template_dirs` will return when passed
|
|
98
|
+
`dirname=""`. This is used to locate .md files in the root of the project, e.g.,
|
|
99
|
+
a README.md file. Looks for `BASE_DIR` if `MARKDOWN_VIEW_BASE_DIR` is not found.
|
|
100
|
+
|
|
101
|
+
* `MARKDOWN_VIEW_LOADERS`
|
|
102
|
+
|
|
103
|
+
A list of loaders that locate .md files. The default list includes only
|
|
104
|
+
`markdown_view.loaders.MarkdownLoader` which will by default try to load .md files
|
|
105
|
+
from root directories in INSTALLED_APPS packages much the same as Django's
|
|
106
|
+
`django.template.loaders.app_directories.Loader` looks to load from "templates".
|
|
107
|
+
|
|
108
|
+
* `MARKDOWN_VIEW_LOADER_TEMPLATES_DIR`
|
|
109
|
+
|
|
110
|
+
The name of the directories in INSTALLED_APPS packages in which to locate .md
|
|
111
|
+
files. Defaults to "" in order to locate .md filed in the root directories.
|
|
112
|
+
|
|
113
|
+
* `MARKDOWN_VIEW_EXTENSIONS`
|
|
114
|
+
|
|
115
|
+
The extensions to enable. These extensions are enabled be default:
|
|
116
|
+
|
|
117
|
+
* `toc`:
|
|
118
|
+
generates a Table of Contents. If `toc` is removed from extensions, then
|
|
119
|
+
`MARKDOWN_VIEW_TEMPLATE_USE_TOC` must be set to False.
|
|
120
|
+
|
|
121
|
+
* `tables`:
|
|
122
|
+
enables tables.
|
|
123
|
+
|
|
124
|
+
* `fenced_code`:
|
|
125
|
+
enables code blocks. If `fenced_code` is removed from extensions, then
|
|
126
|
+
`MARKDOWN_VIEW_TEMPLATE_USE_HIGHLIGHT_JS`, which provides the highlighting for
|
|
127
|
+
code blocks, can be disabled.
|
|
128
|
+
|
|
129
|
+
* `markdown_view.markdown_extensions.ImageExtension`:
|
|
130
|
+
makes images responsive in bootstrap4.
|
|
131
|
+
|
|
132
|
+
See https://python-markdown.github.io/extensions/ and
|
|
133
|
+
https://github.com/Python-Markdown/markdown/wiki/Third-Party-Extensions for more
|
|
134
|
+
extensions.
|
|
135
|
+
|
|
136
|
+
You can create your own extensions by following
|
|
137
|
+
https://github.com/Python-Markdown/markdown/wiki/Tutorial-1---Writing-Extensions-for-Python-Markdown
|
|
138
|
+
|
|
139
|
+
* `MARKDOWN_VIEW_TEMPLATE`
|
|
140
|
+
|
|
141
|
+
The Django template that'll be used to render the HTML that is generated from the
|
|
142
|
+
Markdown. Set your own template to style your pages. Context includes:
|
|
143
|
+
|
|
144
|
+
* `markdown_content`:
|
|
145
|
+
The HTML produced from the Markdown.
|
|
146
|
+
|
|
147
|
+
* `use_highlight_js`:
|
|
148
|
+
If highlight.js is enabled.
|
|
149
|
+
|
|
150
|
+
* `use_toc`:
|
|
151
|
+
If the table of contents should be rendered.
|
|
152
|
+
|
|
153
|
+
* `markdown_toc`:
|
|
154
|
+
A table of contents from the headers of the Markdown. Not set when `use_toc`
|
|
155
|
+
is False.
|
|
156
|
+
|
|
157
|
+
* `page_title`:
|
|
158
|
+
A guess at a page title, for now it's the first row of the TOC. Not set when
|
|
159
|
+
`use_toc` is False, or when the Markdown has no headers for the TOC to be
|
|
160
|
+
built from.
|
|
161
|
+
|
|
162
|
+
* `MARKDOWN_VIEW_TEMPLATE_USE_TOC`
|
|
163
|
+
|
|
164
|
+
Whether to render the TOC. If false, in the template context, `use_toc` is False
|
|
165
|
+
and `markdown_toc` and `page_title` are not present.
|
|
166
|
+
|
|
167
|
+
* `MARKDOWN_VIEW_TEMPLATE_USE_HIGHLIGHT_JS`
|
|
168
|
+
|
|
169
|
+
Whether to load and activate the highlight.js library in the template.
|
|
170
|
+
|
|
171
|
+
* `MARKDOWN_VIEW_REWRITE_INTERNAL_LINKS`
|
|
172
|
+
|
|
173
|
+
Defaults to `True`. Markdown source files commonly link to other `.md`
|
|
174
|
+
files using plain, filesystem-relative links (e.g.
|
|
175
|
+
``[See also](../README-cron.md)``), exactly as they'd resolve on GitHub
|
|
176
|
+
or in a local editor. Since a rendered page is served at its *view's*
|
|
177
|
+
URL rather than at the source file's location on disk, such a link
|
|
178
|
+
would otherwise 404 in the browser.
|
|
179
|
+
|
|
180
|
+
When enabled, `MarkdownView` looks up whether any URL pattern in the
|
|
181
|
+
project serves the linked `.md` file via a `MarkdownView` (or
|
|
182
|
+
subclass), and if so, rewrites the link to that view's actual URL
|
|
183
|
+
instead of leaving the raw relative file path in place. See
|
|
184
|
+
`markdown_view/registry.py <markdown_view/registry.py>`_ for the
|
|
185
|
+
resolution logic. This is best-effort: links to files that aren't
|
|
186
|
+
routed anywhere, or whose route is behind a required URL argument, are
|
|
187
|
+
left exactly as Markdown would otherwise have rendered them -- nothing
|
|
188
|
+
breaks if a linked file simply isn't routed. Set to `False` to disable
|
|
189
|
+
this rewriting entirely.
|
|
190
|
+
|
|
191
|
+
Experimental Settings
|
|
192
|
+
~~~~~~~~~~~~~~~~~~~~~
|
|
193
|
+
|
|
194
|
+
* `MARKDOWN_VIEW_USE_REQUEST_CONTEXT`
|
|
195
|
+
|
|
196
|
+
If the request context should be used as a base when creating the context with
|
|
197
|
+
which to render the Markdown internally. This is because the Markdown is rendered
|
|
198
|
+
once first in order to prepend it with `{% load static %}`.
|
|
199
|
+
This is not well tested; YMMV.
|
|
200
|
+
|
|
201
|
+
* `MARKDOWN_VIEW_EXTRA_CONTEXT`
|
|
202
|
+
|
|
203
|
+
Any extra context to send to the internal render of the Markdown. Can be used
|
|
204
|
+
to expose context to template tags embedded in the Markdown.
|
|
205
|
+
This is not well tested; YMMV.
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
Implementation
|
|
209
|
+
--------------
|
|
210
|
+
|
|
211
|
+
At a high level, `MarkdownView` will:
|
|
212
|
+
|
|
213
|
+
#. Use a template loader to locate `.md` given as `file_name`
|
|
214
|
+
|
|
215
|
+
#. Convert the Markdown to HTML
|
|
216
|
+
|
|
217
|
+
#. If `MARKDOWN_VIEW_REWRITE_INTERNAL_LINKS` is enabled, rewrite any
|
|
218
|
+
relative links to other `.md` files that resolve to a file served by a
|
|
219
|
+
registered `MarkdownView` route, to that route's actual URL
|
|
220
|
+
|
|
221
|
+
#. Render as a template, the resulting HTML prepended with
|
|
222
|
+
`{% load static %}`, into several context variables
|
|
223
|
+
|
|
224
|
+
#. Serve the `MARKDOWN_VIEW_TEMPLATE` with the context variables
|
|
225
|
+
|
|
226
|
+
Release Notes and Contributors
|
|
227
|
+
------------------------------
|
|
228
|
+
|
|
229
|
+
* `Release notes <https://github.com/rgs258/django-markdown-view/releases>`_
|
|
230
|
+
* `Our wonderful contributors <https://github.com/rgs258/django-markdown-view/graphs/contributors>`_
|
|
231
|
+
|
|
232
|
+
Releasing
|
|
233
|
+
---------
|
|
234
|
+
|
|
235
|
+
Versions are derived from git tags via `setuptools_scm`_, so there is no
|
|
236
|
+
hardcoded ``version`` to bump.
|
|
237
|
+
|
|
238
|
+
To publish a new release to PyPI:
|
|
239
|
+
|
|
240
|
+
#. Merge the changes for the release into ``master``.
|
|
241
|
+
|
|
242
|
+
#. `Create a GitHub Release`_ with a tag matching the desired version
|
|
243
|
+
(e.g. ``0.0.6``).
|
|
244
|
+
|
|
245
|
+
#. Publishing the release triggers the `Publish to PyPI`_ GitHub Actions
|
|
246
|
+
workflow, which builds the sdist/wheel and uploads them to PyPI using
|
|
247
|
+
`PyPI Trusted Publishing`_ (no stored token required).
|
|
248
|
+
|
|
249
|
+
Publishing beta / pre-releases
|
|
250
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
251
|
+
|
|
252
|
+
Beta and other pre-releases can be published to PyPI the same way as a
|
|
253
|
+
regular release, and this is standard practice: PyPI understands
|
|
254
|
+
`PEP 440`_ pre-release version identifiers and will not let a plain
|
|
255
|
+
``pip install django-markdown-view`` pick them up by default, so betas are
|
|
256
|
+
safe to publish without risking accidental adoption.
|
|
257
|
+
|
|
258
|
+
#. Tag the release commit with an explicit PEP 440 pre-release suffix
|
|
259
|
+
instead of a plain version, e.g. ``0.0.6b1`` for a beta, or ``0.0.6rc1``
|
|
260
|
+
for a release candidate. ``setuptools_scm`` will pick up the tag as-is.
|
|
261
|
+
|
|
262
|
+
#. `Create a GitHub Release`_ for that tag and check the **"Set as a
|
|
263
|
+
pre-release"** box. This only affects how the release is labeled on
|
|
264
|
+
GitHub; PyPI determines pre-release status purely from the version
|
|
265
|
+
string.
|
|
266
|
+
|
|
267
|
+
#. Publishing the release triggers the same `Publish to PyPI`_ workflow,
|
|
268
|
+
which uploads the pre-release to PyPI. It will appear in the release
|
|
269
|
+
history but will not be installed by ``pip install
|
|
270
|
+
django-markdown-view``.
|
|
271
|
+
|
|
272
|
+
#. Users who want to try it must opt in, e.g. ``pip install --pre
|
|
273
|
+
django-markdown-view`` or by pinning the exact version, such as
|
|
274
|
+
``pip install django-markdown-view==0.0.6b1``.
|
|
275
|
+
|
|
276
|
+
#. If further fixes are needed, bump the pre-release number (``0.0.6b2``,
|
|
277
|
+
``0.0.6b3``, ...) rather than reusing one, since PyPI does not allow
|
|
278
|
+
re-uploading files for a version that has already been published.
|
|
279
|
+
Once the release is stable, tag and publish the final version without
|
|
280
|
+
a suffix (e.g. ``0.0.6``), which then becomes installable by default.
|
|
281
|
+
|
|
282
|
+
.. _setuptools_scm: https://github.com/pypa/setuptools_scm
|
|
283
|
+
.. _`Create a GitHub Release`: https://github.com/rgs258/django-markdown-view/releases/new
|
|
284
|
+
.. _`Publish to PyPI`: https://github.com/rgs258/django-markdown-view/actions/workflows/publish.yml
|
|
285
|
+
.. _`PyPI Trusted Publishing`: https://docs.pypi.org/trusted-publishers/
|
|
286
|
+
.. _`PEP 440`: https://peps.python.org/pep-0440/#pre-releases
|
|
287
|
+
|
|
288
|
+
Contributing
|
|
289
|
+
------------
|
|
290
|
+
|
|
291
|
+
All contributions are very welcomed. Propositions, problems, bugs, and
|
|
292
|
+
enhancement are tracked with `GitHub issues`_ and patches are submitted
|
|
293
|
+
via `pull requests`_.
|
|
294
|
+
|
|
295
|
+
We use `GitHub Actions`_ coupled with `Coveralls`_ as continuous integration tools.
|
|
296
|
+
|
|
297
|
+
.. _`GitHub issues`: https://github.com/rgs258/django-markdown-view/issues
|
|
298
|
+
.. _`pull requests`: https://github.com/rgs258/django-markdown-view/pulls
|
|
299
|
+
.. _`GitHub Actions`: https://github.com/rgs258/django-markdown-view/actions
|
|
300
|
+
.. _Coveralls: https://coveralls.io/github/rgs258/django-markdown-view
|
|
301
|
+
|
|
302
|
+
Requirements
|
|
303
|
+
------------
|
|
304
|
+
|
|
305
|
+
We aspire to support the currently supported versions of Django.
|
|
306
|
+
|
|
307
|
+
**The Tested With section describes aspirational goals.**
|
|
308
|
+
|
|
309
|
+
Tested with:
|
|
310
|
+
|
|
311
|
+
* Python: 3.10, 3.11, 3.12, 3.13
|
|
312
|
+
* Django: 5.2, 6.0
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
django_markdown_view-0.0.6b2.dist-info/licenses/LICENSE,sha256=Xun9tu6GoUnr8qy5C3MBQeqJZeuzkw67SQiFzexknls,1542
|
|
2
|
+
markdown_view/__init__.py,sha256=EXOCt-R6NOvU0yLhQcmwQT_U-DVK0TPZYpErkJ6tbko,61
|
|
3
|
+
markdown_view/apps.py,sha256=QwgUCdY8AupkXpT7AOqqigSaPY45bpp7KHeAYvDlMds,332
|
|
4
|
+
markdown_view/checks.py,sha256=ojtG0-R_I1XGc9Bik7C0ZLyM0TB__cIzRKFOWDnEDxk,1537
|
|
5
|
+
markdown_view/constants.py,sha256=BlDRKrMOJ20Pmby40r4FCSiHZ6Hexs2e1janwxkpsPA,580
|
|
6
|
+
markdown_view/loaders.py,sha256=dtZ2X01MGfW5cnGMH78jSQ08SATqsv_amPmBM9jOA14,2221
|
|
7
|
+
markdown_view/markdown_extensions.py,sha256=T_9cRg99vnXyhBA-evqVRRE0kHITx1YitRGJV9IghX8,635
|
|
8
|
+
markdown_view/models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
markdown_view/registry.py,sha256=bCuPqe3T_iwEpWApeRIwwLqHx5tXwQUJ8heInJ_n9gQ,15919
|
|
10
|
+
markdown_view/views.py,sha256=TMVLbBQ23xTD1NXGrJe0LuMgeFbcYX4HrjkKrdST6_M,4162
|
|
11
|
+
markdown_view/templates/markdown_view/markdown.html,sha256=QyddBcicEe0CnGQFN66BRCNcUr3SUVXBEqwzLm9NCWQ,1232
|
|
12
|
+
markdown_view/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
markdown_view/tests/test_checks.py,sha256=dh4LYFj6kD_r7rEoPtsqfbqpJ5sOQmpnoQEi2-zkaq4,1584
|
|
14
|
+
markdown_view/tests/test_loaders.py,sha256=w1-WBFcRjTnYjZWFRFcJVWqbT5B8CYvU0oCwJiz7sZY,2583
|
|
15
|
+
markdown_view/tests/test_markdown_extensions.py,sha256=GHgcI3zeUFi-BisdrHJ8gx_NOXOv10q-vAKjuDuQ_kk,1271
|
|
16
|
+
markdown_view/tests/test_registry.py,sha256=b1Fy6JKVoiCQHQQDyJMyd0Vmbp8taoRf9JUcaQ0tO8M,14339
|
|
17
|
+
markdown_view/tests/test_settings_validation.py,sha256=bWlsbZxvGOlOtJUBtwD8dcBqjJhjx7HJTfDPZdgYLqY,2534
|
|
18
|
+
markdown_view/tests/test_views.py,sha256=aYpujitgvguMwK12t2S5XOEOfT6_tZ7S7_twZzohmVU,7112
|
|
19
|
+
markdown_view/tests/urls.py,sha256=xfj1o_k3iZvd8kox7hzYFn47H67_82M5KVA-KlrUPro,3630
|
|
20
|
+
markdown_view/tests/fixtures/loaders_a/readme.md,sha256=3ZLpASU8bfOp6GY2ExZPrzlnHfCb3LR8qGNpVC_9iLU,227
|
|
21
|
+
markdown_view/tests/fixtures/loaders_b/readme.md,sha256=NwuNR4ZsdXlmp2wE5GvfVNrkYoRzXcHwtqdvU_t72sA,227
|
|
22
|
+
markdown_view/tests/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
+
markdown_view/tests/settings/coveralls_settings.py,sha256=JG-heiLhtoiGwxKL0sb77yIFqPeZGMAKaM4FcDxMgTs,2263
|
|
24
|
+
markdown_view/tests/testapp/CONTEXT_TEST.md,sha256=25kLvqZC8pHZ2DUuEUVABV28to3aMzUKsN-e5rDZPGY,72
|
|
25
|
+
markdown_view/tests/testapp/LOGGED_IN.md,sha256=_ycP4KN2-LCpdapSnskA-6VLs6f7nG3WTdmAGn3VDsw,73
|
|
26
|
+
markdown_view/tests/testapp/NESTED.md,sha256=hXAcDFiEwtG0aZatjSKRzoDiZIOOH3voYMZqfFGBYjc,192
|
|
27
|
+
markdown_view/tests/testapp/NO_HEADERS.md,sha256=YbL0KxChybEQauZ46zltWsQbzKRcvfGxTHzIZ174vkg,237
|
|
28
|
+
markdown_view/tests/testapp/README.md,sha256=xk_cwqo8kS6qNHCMTmmFsgohoMvzrs_tgIpC8e010S4,896
|
|
29
|
+
markdown_view/tests/testapp/STAFF.md,sha256=kJyaIF4JFSjc4QBcX_jAmlJ32_HHzpmWaygPbLeYqGw,68
|
|
30
|
+
markdown_view/tests/testapp/UNROUTED.md,sha256=6xbM35PNQ2e1FJWmihJ8_aTXSN96vYG_6RUrQIibl0A,157
|
|
31
|
+
markdown_view/tests/testapp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
|
+
markdown_view/tests/testapp/apps.py,sha256=my2snU00q5vjhr0BK_fs9tPVnDTLnk6PM8ezS3lV-ZY,173
|
|
33
|
+
markdown_view/tests/testapp/docs/OTHER.md,sha256=xRf-5jaJCnJiaz_bQaVMI5OVpVcuhWlNVejSedyY57k,231
|
|
34
|
+
django_markdown_view-0.0.6b2.dist-info/METADATA,sha256=zEBuEqrnCqVqmdQ1MzW_KVfiU370_HYV1MQnn7moqzw,11366
|
|
35
|
+
django_markdown_view-0.0.6b2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
36
|
+
django_markdown_view-0.0.6b2.dist-info/top_level.txt,sha256=MqRRE0ldzEe17rDjvoESYz22dyeBcPAG9ELXUR5FD7w,14
|
|
37
|
+
django_markdown_view-0.0.6b2.dist-info/RECORD,,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Copyright (c) Ryan J. Sullivan and individual contributors.
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
5
|
+
are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
this list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
notice, this list of conditions and the following disclaimer in the
|
|
12
|
+
documentation and/or other materials provided with the distribution.
|
|
13
|
+
|
|
14
|
+
3. Neither the name of Django nor the names of its contributors may be used
|
|
15
|
+
to endorse or promote products derived from this software without
|
|
16
|
+
specific prior written permission.
|
|
17
|
+
|
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
19
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
20
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
22
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
23
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
24
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
25
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
26
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
27
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
markdown_view
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
default_app_config = "markdown_view.apps.MarkdownViewConfig"
|
markdown_view/apps.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from django.apps import AppConfig
|
|
2
|
+
from django.core.checks import register, Tags
|
|
3
|
+
|
|
4
|
+
from markdown_view.checks import markdown_view_check
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MarkdownViewConfig(AppConfig):
|
|
8
|
+
name = "markdown_view"
|
|
9
|
+
verbose_name = "Serve .md pages as Django templates"
|
|
10
|
+
|
|
11
|
+
def ready(self):
|
|
12
|
+
register(markdown_view_check, Tags.security)
|
markdown_view/checks.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from django.conf import settings
|
|
2
|
+
from django.core import checks
|
|
3
|
+
|
|
4
|
+
# Expected type for each optional markdown_view setting. Validated by
|
|
5
|
+
# `markdown_view_check()` below (registered as a Django system check in
|
|
6
|
+
# `apps.py`), rather than at import time, so `manage.py check` -- and
|
|
7
|
+
# `override_settings` in tests -- can exercise this validation directly.
|
|
8
|
+
SETTINGS_TYPES = {
|
|
9
|
+
"MARKDOWN_VIEW_LOADERS": list,
|
|
10
|
+
"MARKDOWN_VIEW_LOADER_TEMPLATES_DIR": str,
|
|
11
|
+
"MARKDOWN_VIEW_EXTENSIONS": list,
|
|
12
|
+
"MARKDOWN_VIEW_BASE_DIR": str,
|
|
13
|
+
"MARKDOWN_VIEW_TEMPLATE": str,
|
|
14
|
+
"MARKDOWN_VIEW_TEMPLATE_USE_TOC": bool,
|
|
15
|
+
"MARKDOWN_VIEW_TEMPLATE_USE_HIGHLIGHT_JS": bool,
|
|
16
|
+
"MARKDOWN_VIEW_USE_REQUEST_CONTEXT": bool,
|
|
17
|
+
"MARKDOWN_VIEW_EXTRA_CONTEXT": dict,
|
|
18
|
+
"MARKDOWN_VIEW_REWRITE_INTERNAL_LINKS": bool,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def markdown_view_check(app_configs, **kwargs):
|
|
23
|
+
"""
|
|
24
|
+
Validate that any of markdown_view's optional settings the project has
|
|
25
|
+
defined are of the expected type.
|
|
26
|
+
"""
|
|
27
|
+
errors = []
|
|
28
|
+
|
|
29
|
+
for variable, instance_type in SETTINGS_TYPES.items():
|
|
30
|
+
if hasattr(settings, variable) and not isinstance(
|
|
31
|
+
getattr(settings, variable), instance_type
|
|
32
|
+
):
|
|
33
|
+
errors.append(
|
|
34
|
+
checks.Error(
|
|
35
|
+
"Setting %s is not of type %s" % (variable, instance_type),
|
|
36
|
+
hint="Update %s in your settings module to be of type %s."
|
|
37
|
+
% (variable, instance_type),
|
|
38
|
+
id="markdown_view.E001",
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
return errors
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from markdown_view.markdown_extensions import ImageExtension
|
|
2
|
+
|
|
3
|
+
DEFAULT_MARKDOWN_VIEW_LOADERS = ["markdown_view.loaders.MarkdownLoader", ]
|
|
4
|
+
DEFAULT_MARKDOWN_VIEW_LOADER_TEMPLATES_DIR = ""
|
|
5
|
+
DEFAULT_MARKDOWN_VIEW_EXTENSIONS = ["tables", "fenced_code", "toc", ImageExtension(), ]
|
|
6
|
+
DEFAULT_MARKDOWN_VIEW_TEMPLATE = "markdown_view/markdown.html"
|
|
7
|
+
DEFAULT_MARKDOWN_VIEW_TEMPLATE_USE_TOC = True
|
|
8
|
+
DEFAULT_MARKDOWN_VIEW_TEMPLATE_USE_HIGHLIGHT_JS = True
|
|
9
|
+
DEFAULT_MARKDOWN_VIEW_USE_REQUEST_CONTEXT = False
|
|
10
|
+
DEFAULT_MARKDOWN_VIEW_EXTRA_CONTEXT = {}
|
|
11
|
+
DEFAULT_MARKDOWN_VIEW_REWRITE_INTERNAL_LINKS = True
|
markdown_view/loaders.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from django.conf import settings
|
|
2
|
+
from django.core.exceptions import SuspiciousFileOperation
|
|
3
|
+
from django.template import Origin
|
|
4
|
+
from django.template.loaders.filesystem import Loader as FilesystemLoader
|
|
5
|
+
from django.template.utils import get_app_template_dirs
|
|
6
|
+
from django.utils._os import safe_join
|
|
7
|
+
|
|
8
|
+
from markdown_view.constants import DEFAULT_MARKDOWN_VIEW_LOADER_TEMPLATES_DIR
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class MarkdownLoader(FilesystemLoader):
|
|
12
|
+
"""
|
|
13
|
+
A loader that will find a .md file in the context of any installed app or
|
|
14
|
+
application root.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def get_dirs(self):
|
|
18
|
+
base_dir = getattr(
|
|
19
|
+
settings,
|
|
20
|
+
"MARKDOWN_VIEW_BASE_DIR",
|
|
21
|
+
getattr(
|
|
22
|
+
settings,
|
|
23
|
+
"BASE_DIR",
|
|
24
|
+
None)
|
|
25
|
+
)
|
|
26
|
+
dirs = [*get_app_template_dirs(
|
|
27
|
+
getattr(
|
|
28
|
+
settings,
|
|
29
|
+
"MARKDOWN_VIEW_LOADER_TEMPLATES_DIR",
|
|
30
|
+
DEFAULT_MARKDOWN_VIEW_LOADER_TEMPLATES_DIR
|
|
31
|
+
)
|
|
32
|
+
)]
|
|
33
|
+
if base_dir:
|
|
34
|
+
dirs.extend([base_dir])
|
|
35
|
+
return dirs
|
|
36
|
+
|
|
37
|
+
def get_template_sources(self, template_name):
|
|
38
|
+
"""
|
|
39
|
+
Return an Origin object pointing to an absolute path in each directory
|
|
40
|
+
in template_dirs. For security reasons, if a path doesn't lie inside
|
|
41
|
+
one of the template_dirs it is excluded from the result set.
|
|
42
|
+
"""
|
|
43
|
+
if template_name.endswith('.md'):
|
|
44
|
+
template_split = template_name.split("/")
|
|
45
|
+
template_split.reverse()
|
|
46
|
+
template_app_dir = template_split.pop()
|
|
47
|
+
template_split.reverse()
|
|
48
|
+
for template_dir in self.get_dirs():
|
|
49
|
+
if str(template_dir).endswith(template_app_dir):
|
|
50
|
+
try:
|
|
51
|
+
name = safe_join(template_dir, *template_split)
|
|
52
|
+
except SuspiciousFileOperation:
|
|
53
|
+
# The joined path was located outside of this template_dir
|
|
54
|
+
# (it might be inside another one, so this isn't fatal).
|
|
55
|
+
continue
|
|
56
|
+
|
|
57
|
+
yield Origin(
|
|
58
|
+
name=name,
|
|
59
|
+
template_name=template_name,
|
|
60
|
+
loader=self,
|
|
61
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
from markdown.treeprocessors import Treeprocessor
|
|
4
|
+
from markdown.extensions import Extension
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class InlineImageProcessor(Treeprocessor):
|
|
8
|
+
def run(self, root):
|
|
9
|
+
for element in root.iter("img"):
|
|
10
|
+
src_orig = element.attrib.get('src', '')
|
|
11
|
+
src_re = re.sub(r"[/\\]*static[/\\]*", "", src_orig)
|
|
12
|
+
src = "{{% static '{}' %}}".format(src_re)
|
|
13
|
+
element.attrib["src"] = src
|
|
14
|
+
element.attrib["class"] = "img-fluid"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ImageExtension(Extension):
|
|
18
|
+
def extendMarkdown(self, md):
|
|
19
|
+
md.treeprocessors.register(InlineImageProcessor(md), 'inlineimageprocessor', 15)
|
markdown_view/models.py
ADDED
|
File without changes
|