Browse Source

Initial version

Marcos Dumay de Medeiros 6 years ago
commit
0ce38b9c5e

+ 45 - 0
.gitignore

@@ -0,0 +1,45 @@
+# Backup files
+*~
+
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+
+# C extensions
+*.so
+
+# Distribution / packaging
+bin/
+build/
+develop-eggs/
+dist/
+eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+.tox/
+.coverage
+.cache
+nosetests.xml
+coverage.xml
+
+# Translations
+*.mo
+
+# Sphinx documentation
+docs/_build/
+
+#Virtualenv dir
+ENV/

+ 1 - 0
MANIFEST.in

@@ -0,0 +1 @@
+include README.rst

+ 9 - 0
README.rst

@@ -0,0 +1,9 @@
+Django Articles
+============
+
+A simple CMS based on static file.
+
+
+How to Use
+==========
+

+ 0 - 0
__init__.py


+ 3 - 0
setup.cfg

@@ -0,0 +1,3 @@
+[bdist_wheel]
+universal=1
+

+ 101 - 0
setup.py

@@ -0,0 +1,101 @@
+__author__ = 'marcos.medeiros'
+
+"""Django Articles
+A simple CMS based on static files that hold data applied to a template.
+"""
+
+# Always prefer setuptools over distutils
+from setuptools import setup, find_packages
+# To use a consistent encoding
+from codecs import open
+from os import path
+
+here = path.abspath(path.dirname(__file__))
+
+# Get the long description from the relevant file
+with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
+    long_description = f.read()
+
+setup(
+    name='django-articles',
+
+    version='1.0.0',
+
+    description='A simple CMS based on static files that hold data applied to a template.',
+    long_description=long_description,
+
+    # The project's main homepage.
+    url='https://marcosdumay.com/django-articles',
+
+    # Author details
+    author='Marcos Dumay de Medeiros',
+    author_email='marcos@marcosdumay.com',
+
+    # Choose your license
+    license='MIT',
+
+    # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
+    classifiers=[
+#        'Development Status :: 2 - Pre-Alpha',
+#        'Environment :: Web Environment',
+#        'Framework :: Django :: 1.8',
+#        'Intended Audience :: Developers',
+#        'Topic :: Software Development :: Build Tools',
+#        'License :: OSI Approved :: MIT License',
+#        'Natural Language :: Portuguese (Brazilian)',
+#        'Operating System :: OS Independent',
+#        'Programming Language :: Python :: 2',
+#        'Programming Language :: Python :: 2.6',
+#        'Programming Language :: Python :: 2.7',
+        #'Programming Language :: Python :: 3',
+        #'Programming Language :: Python :: 3.2',
+        #'Programming Language :: Python :: 3.3',
+        #'Programming Language :: Python :: 3.4',
+    ],
+
+    # What does your project relate to?
+    keywords='',
+
+    # You can just specify the packages manually here if your project is
+    # simple. Or you can use find_packages().
+    packages=find_packages('src', exclude=['contrib', 'docs', 'tests*']),
+    package_dir = {'': 'src'},
+
+    zip_safe = False,
+
+    # List run-time dependencies here.  These will be installed by pip when
+    # your project is installed. For an analysis of "install_requires" vs pip's
+    # requirements files see:
+    # https://packaging.python.org/en/latest/requirements.html
+    install_requires=['django>=1.7'],
+
+    # List additional groups of dependencies here (e.g. development
+    # dependencies). You can install these using the following syntax,
+    # for example:
+    # $ pip install -e .[dev,test]
+    extras_require={},
+
+    # If there are data files included in your packages that need to be
+    # installed, specify them here.  If using Python 2.6 or less, then these
+    # have to be included in MANIFEST.in as well.
+
+    include_package_data=True,
+    # package_data={
+    #     'sample': ['package_data.dat'],
+    # },
+
+    # Although 'package_data' is the preferred approach, in some case you may
+    # need to place data files outside of your packages. See:
+    # http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files # noqa
+    # In this case, 'data_file' will be installed into '<sys.prefix>/my_data'
+    data_files=[],
+
+    # To provide executable scripts, use entry points in preference to the
+    # "scripts" keyword. Entry points provide cross-platform support and allow
+    # pip to create the appropriate form of executable for the target platform.
+    entry_points={
+        # 'console_scripts': [
+        #     'sample=sample:main',
+        # ],
+    },
+)

+ 19 - 0
src/articles/middleware.py

@@ -0,0 +1,19 @@
+from django.http import Http404
+from django.conf import settings
+
+from articles.views import showarticle
+
+__author__ = 'marcos'
+
+class ArticlesMiddleware:
+    def process_response(self, request, response):
+        if response.status_code != 404:
+            return response
+        try:
+            return showarticle(request, request.path_info)
+        except Http404:
+            return response
+        except Exception:
+            if settings.DEBUG:
+                raise
+            return response

+ 15 - 0
src/articles/templates/article.html

@@ -0,0 +1,15 @@
+{% extends 'basic.html' %}
+
+{% load markup %}
+
+{% block title %}{{ title }}{% endblock %}
+
+{% block body %}
+<h2><a href="{{ url }}">{{ title }}</a></h2>
+<p class="author"><span class="by">By:</span> <span class="name">Marcos</span></p>
+{{ article_text|restructuredtext }}
+<p class="history">
+  {% if previous_article %}<a href="{{ previous_url }}" class="previous">{{ previous_article }}</a>{% endif %}
+  {% if next_article %}<a href="{{ next_url }}" class="next">{{ next_article }}</a>{% endif %}
+</p>
+{% endblock %}

+ 0 - 0
src/articles/templatetags/__init__.py


+ 93 - 0
src/articles/templatetags/markup.py

@@ -0,0 +1,93 @@
+"""
+The tags of the django.contrib.markup package, because somebody decided
+it was just too good to be in Django...
+
+Set of "markup" template filters for Django. These filters transform plain text
+markup syntaxes to HTML; currently there is support for:
+
+* Textile, which requires the PyTextile library available at
+http://loopcore.com/python-textile/
+
+* Markdown, which requires the Python-markdown library from
+http://www.freewisdom.org/projects/python-markdown
+
+* reStructuredText, which requires docutils from http://docutils.sf.net/
+"""
+
+from django import template
+from django.conf import settings
+from django.utils.encoding import force_bytes, force_text
+from django.utils.safestring import mark_safe
+
+register = template.Library()
+
+@register.filter(is_safe=True)
+def textile(value):
+    try:
+        import textile
+    except ImportError:
+        if settings.DEBUG:
+            raise template.TemplateSyntaxError("Error in 'textile' filter: The Python textile library isn't installed.")
+        return force_text(value)
+    else:
+        return mark_safe(force_text(textile.textile(force_bytes(value), encoding='utf-8', output='utf-8')))
+
+@register.filter(is_safe=True)
+def markdown(value, arg=''):
+    """
+Runs Markdown over a given value, optionally using various
+extensions python-markdown supports.
+
+Syntax::
+
+{{ value|markdown:"extension1_name,extension2_name..." }}
+
+To enable safe mode, which strips raw HTML and only returns HTML
+generated by actual Markdown syntax, pass "safe" as the first
+extension in the list.
+
+If the version of Markdown in use does not support extensions,
+they will be silently ignored.
+
+"""
+    import warnings
+    warnings.warn('The markdown filter has been deprecated',
+                  category=DeprecationWarning)
+    try:
+        import markdown
+    except ImportError:
+        if settings.DEBUG:
+            raise template.TemplateSyntaxError("Error in 'markdown' filter: The Python markdown library isn't installed.")
+        return force_text(value)
+    else:
+        markdown_vers = getattr(markdown, "version_info", 0)
+        if markdown_vers < (2, 1):
+            if settings.DEBUG:
+                raise template.TemplateSyntaxError(
+                    "Error in 'markdown' filter: Django does not support versions of the Python markdown library < 2.1.")
+            return force_text(value)
+        else:
+            extensions = [e for e in arg.split(",") if e]
+            if extensions and extensions[0] == "safe":
+                extensions = extensions[1:]
+                return mark_safe(markdown.markdown(
+                    force_text(value), extensions, safe_mode=True, enable_attributes=False))
+            else:
+                return mark_safe(markdown.markdown(
+                    force_text(value), extensions, safe_mode=False))
+
+@register.filter(is_safe=True)
+def restructuredtext(value):
+    import warnings
+    warnings.warn('The restructuredtext filter has been deprecated',
+                  category=DeprecationWarning)
+    try:
+        from docutils.core import publish_parts
+    except ImportError:
+        if settings.DEBUG:
+            raise template.TemplateSyntaxError("Error in 'restructuredtext' filter: The Python docutils library isn't installed.")
+        return force_text(value)
+    else:
+        docutils_settings = getattr(settings, "RESTRUCTUREDTEXT_FILTER_SETTINGS", {})
+        parts = publish_parts(source=force_bytes(value), writer_name="html4css1", settings_overrides=docutils_settings)
+        return mark_safe(force_text(parts["fragment"]))

+ 3 - 0
src/articles/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 67 - 0
src/articles/views.py

@@ -0,0 +1,67 @@
+from django.template import Template, RequestContext
+from django.http import HttpResponse, Http404
+from django.conf import settings
+from django.shortcuts import render
+
+from os import path
+
+def articleVars(fn):
+    file, url = file_for_url(fn)
+    vars = {}
+    with open(file, 'r') as f:
+        l = f.readline().strip()
+        while l:
+            ll = l.split(':', 1)
+            h = ll[0].strip()
+            if len(ll) > 1:
+                v = ll[1].strip()
+            else:
+                v = ""
+            vars[h.lower()] = v
+            l = f.readline().strip()
+        return vars
+
+def loadArticle(request, url, f):
+    vars = {'url': url}
+    l = f.readline().strip()
+    while l:
+        ll = l.split(':', 1)
+        h = ll[0].strip()
+        if len(ll) > 1:
+            v = ll[1].strip()
+        else:
+            v = ""
+        if h.lower() == "display":
+            return showarticle(request, v)
+        vars[h.lower()] = v
+        l = f.readline().strip()
+    vars['article_text'] = f.read()
+    if vars.get('previousfile'):
+        f = vars['previousfile']
+        print(f)
+        vars['previous_url'] = '/' + f
+        prev = articleVars(f)
+        vars['previous_article'] = prev.get('title', '')
+    if vars.get('nextfile'):
+        f = vars['nextfile']
+        vars['next_url'] = '/' + f
+        nxt = articleVars(f)
+        vars['next_article'] = nxt.get('title', '')
+    return render(request, 'article.html', vars)
+
+def file_for_url(file):
+    if file.startswith('/'):
+        file = file[1:]
+    full_path = path.join(settings.DOC_ROOT, file)
+    if not path.exists(full_path):
+        raise Http404
+    if path.isdir(full_path):
+        full_path = path.join(full_path, 'index')
+    return full_path, '/' + file
+    
+
+def showarticle(request, file):
+    full_path, url = file_for_url(file)
+    with open(full_path, 'r') as f:
+        return loadArticle(request, url, f)
+