diff --git a/app.py b/app.py index 960e63a..0a8c01c 100644 --- a/app.py +++ b/app.py @@ -31,12 +31,8 @@ try: from slugify import slugify except ImportError: slugify = None -try: - import markdown_strikethrough -except Exception: - markdown_strikethrough = None -__version__ = '0.4' +__version__ = '0.5-dev' #### CONSTANTS #### @@ -93,6 +89,28 @@ def _makelist(l): else: return [] + +#### MARKDOWN EXTENSIONS #### + +class StrikethroughExtension(markdown.extensions.Extension): + def extendMarkdown(self, md, md_globals): + postprocessor = StrikethroughPostprocessor(md) + md.postprocessors.add('strikethrough', postprocessor, '>raw_html') + +class StrikethroughPostprocessor(markdown.postprocessors.Postprocessor): + pattern = re.compile(r"~~(((?!~~).)+)~~", re.DOTALL) + + def run(self, html): + return re.sub(self.pattern, self.convert, html) + + def convert(self, match): + return '' + match.group(1) + '' + +### XXX it currently only detects spoilers that are not at the beginning of the line. To be fixed. +class SpoilerExtension(markdown.extensions.Extension): + def extendMarkdown(self, md, md_globals): + md.inlinePatterns.register(markdown.inlinepatterns.SimpleTagInlineProcessor(r'()>!(.*?)!<', 'span class="spoiler"'), 'spoiler', 14) + #### DATABASE SCHEMA #### database = SqliteDatabase(_getconf("config", "database_dir") + '/data.sqlite') @@ -321,6 +339,9 @@ class PagePolicy(BaseModel): (('page', 'key'), True), ) +# DEPRECATED +# It will be possibly removed in v0.6. +# Use external image URL instead. class Upload(BaseModel): name = CharField(256) url_name = CharField(256, null=True) @@ -382,34 +403,11 @@ def init_db(): #### WIKI SYNTAX #### -magic_word_filters = {} - -def _replace_magic_word(match): - name = match.group(1) - if name not in magic_word_filters: - return match.group() - f = magic_word_filters[name] - try: - return f(*(x.strip() for x in match.group(2).split('|'))) - except Exception: - return '' - -def expand_magic_words(text): - ''' - Replace the special markups in double curly brackets. - - Unknown keywords are not replaced. Valid keywords with invalid arguments are replaced with nothing. - ''' - return re.sub(MAGIC_RE, _replace_magic_word, text) - def md(text, expand_magic=False, toc=True): if expand_magic: # DEPRECATED seeking for a better solution. warnings.warn('Magic words are no more supported.', DeprecationWarning) - text = expand_magic_words(text) - extensions = ['tables', 'footnotes', 'fenced_code', 'sane_lists'] - if markdown_strikethrough: - extensions.append("markdown_strikethrough.extension") + extensions = ['tables', 'footnotes', 'fenced_code', 'sane_lists', StrikethroughExtension(), SpoilerExtension()] if toc: extensions.append('toc') return markdown.Markdown(extensions=extensions).convert(text) @@ -418,59 +416,9 @@ def remove_tags(text, convert=True, headings=True): if headings: text = re.sub(r'\#[^\n]*', '', text) if convert: - text = md(text, expand_magic=False, toc=False) + text = md(text, toc=False) return re.sub(r'<.*?>|\{\{.*?\}\}', '', text) - -### Magic words (deprecated!) ### - -def expand_backto(pageid): - p = Page[pageid] - return '*« Main article: [{}]({}).*'.format(html.escape(p.title), p.get_url()) - -magic_word_filters['backto'] = expand_backto - -def expand_upload(id, *opt): - try: - upload = Upload[id] - except Upload.DoesNotExist: - return '' - if opt: - desc = opt[-1] - else: - desc = None - classname = 'fig-right' - return '
{1}{3}
'.format( - classname, html.escape(upload.name), upload.url, - '
{0}
'.format(md(desc, expand_magic=False)) if desc else '', - upload.id) - -magic_word_filters['media'] = expand_upload - -def make_gallery(items): - result = [] - for upload, desc in items: - result.append(''.format( - upload.id, html.escape(upload.name), upload.url, - '
{0}
'.format(md(desc, expand_magic=False)) if desc else '')) - return '' - -def expand_gallery(*ids): - items = [] - for i in ids: - if ' ' in i: - id, desc = i.split(' ', 1) - else: - id, desc = i, '' - try: - upload = Upload[id] - except Upload.DoesNotExist: - continue - items.append((upload, desc)) - return make_gallery(items) - -magic_word_filters['gallery'] = expand_gallery - #### I18N #### lang_poses = {'en': 1, 'en-US': 1, 'it': 2, 'it-IT': 2} @@ -549,8 +497,7 @@ def linebreaks(text): def homepage(): page_limit = _getconf("appearance","items_per_page",20,cast=int) return render_template('home.html', new_notes=Page.select() - .order_by(Page.touched.desc()).limit(page_limit), - gallery=make_gallery((x, '') for x in Upload.select().order_by(Upload.upload_date.desc()).limit(3))) + .order_by(Page.touched.desc()).limit(page_limit)) @app.route('/robots.txt') def robots(): @@ -795,28 +742,11 @@ def listtag(tag, page=1): def media(fp): return send_from_directory(UPLOAD_DIR, fp) -@app.route('/upload/', methods=['GET', 'POST']) +# symbolic route as of v0.5 +@app.route('/upload/', methods=['GET']) def upload(): - if request.method == 'POST': - name = request.form['name'] - file = request.files['file'] - filename = file.filename - ext = os.path.splitext(filename)[1] - content = file.read() - try: - upl = Upload.create_content(name, ext, content) - flash('File uploaded successfully') - return redirect('/upload-info/{}/'.format(upl.id)) - except Exception: - sys.excepthook(*sys.exc_info()) - flash('Unable to upload file. Try again later.') return render_template('upload.html') -@app.route('/upload-info//') -def upload_info(id): - upl = Upload[id] - return render_template('uploadinfo.html', upl=upl, type_list=upload_types_rev) - @app.route('/stats/') def stats(): return render_template('stats.html', @@ -881,7 +811,14 @@ def easter_y(y=None): #### EXTENSIONS #### -active_extensions = ['contactnova'] +active_extensions = [] + +_i = 1 +_extension_name = _getconf('extensions', 'ext.{}'.format(_i)) +while _extension_name: + active_extensions.append(_extension_name) + _i += 1 + _extension_name = _getconf('extensions', 'ext.{}'.format(_i)) for ext in active_extensions: try: diff --git a/static/content.js b/static/content.js new file mode 100644 index 0000000..53859c2 --- /dev/null +++ b/static/content.js @@ -0,0 +1,8 @@ +(function() { + + for (let i of document.getElementsByClassName('spoiler')) { + i.onclick = function() { + this.classList.toggle('revealed'); + } + }; +})(); diff --git a/static/style.css b/static/style.css index 4dd390e..04ec6d3 100644 --- a/static/style.css +++ b/static/style.css @@ -1,13 +1,14 @@ /* basic styles */ -body{font-family:sans-serif} +body{font-family:sans-serif;background-color:#faf5e9} .content{margin: 3em 1.3em} /* content styles */ -#firstHeading {font-family: 'Oswald','Anton','Impact',sans-serif; text-align: center;font-size:3em} +#firstHeading {font-family:sans-serif; text-align: center;font-size:3em; font-weight: normal} .inner-content{font-family:serif; margin: 1.7em auto; max-width: 1280px; line-height: 1.9; color: #1f2528} .inner-content em,.inner-content strong{color: black} .inner-content h1{color: #99081f} -.inner-content table, .inner-content h2, .inner-content h3, .inner-content h4, .inner-content h5, .inner-content h6{font-family:sans-serif; color: black} +.inner-content table {font-family: sans-serif} +.inner-content h2, .inner-content h3, .inner-content h4, .inner-content h5, .inner-content h6{font-family:sans-serif; color: black; font-weight: normal} .inner-content h3{margin:0.8em 0} .inner-content h4{margin:0.6em 0} .inner-content h5{margin:0.5em 0} @@ -19,6 +20,9 @@ body{font-family:sans-serif} .inner-content table > * > tr > th, .inner-content table > tr > th {background-color:#f9f9f9;border:#ccc 1px solid;padding:2px} .inner-content table > * > tr > td, .inner-content table > tr > td {border:#ccc 1px solid;padding:2px} +/* spoiler styles */ +.spoiler {color: black; background-color:black} +.spoiler.revealed {color: #1f2528; background-color: transparent} /* interface styles */ .nl-list{list-style:none} @@ -143,6 +147,8 @@ body.dark, .dark input, .dark textarea{background-color: #1f1f1f; color: white} a.dark-theme-toggle-off{display: none} .dark a.dark-theme-toggle-off{display: inline} .dark a.dark-theme-toggle-on{display: none} +.dark .spoiler {color: white; background-color: white} +.dark .spoiler.revealed {color: white; background-color: transparent} /* ?????? */ .wrap_responsive_cells { diff --git a/templates/edit.html b/templates/edit.html index eb24311..b7a6089 100644 --- a/templates/edit.html +++ b/templates/edit.html @@ -56,4 +56,5 @@ {% block scripts %} + {% endblock %} diff --git a/templates/home.html b/templates/home.html index f2643aa..c0d4691 100644 --- a/templates/home.html +++ b/templates/home.html @@ -7,7 +7,6 @@
-

{{ T('latest-notes') }}

@@ -31,8 +30,4 @@
  • {{ T('show-all') }}
  • -

    {{ T('latest-uploads') }}

    - -{# TODO security flaw; find a way to do this in a more safe manner! #} -{{ gallery|safe }} {% endblock %} diff --git a/templates/stats.html b/templates/stats.html index 34ca3ae..1e7ee93 100644 --- a/templates/stats.html +++ b/templates/stats.html @@ -8,7 +8,6 @@ diff --git a/templates/upload.html b/templates/upload.html index 153c6f8..e3f2266 100644 --- a/templates/upload.html +++ b/templates/upload.html @@ -3,41 +3,19 @@ {% block content %}

    Upload new file

    -

    Types supported: .jpeg, .jpg, .png.

    +

    Uploads are no more supported. Please use this syntax instead for external images: ![alt text](https://www.example.com/path/to/image.jpg).

    - +
    - +
    - +
    {% endblock %} - -{% block scripts %} - -{% endblock %} diff --git a/templates/view.html b/templates/view.html index eb15f68..cf10fc7 100644 --- a/templates/view.html +++ b/templates/view.html @@ -5,29 +5,32 @@ {% block json_info %}{% endblock %} {% block content %} -

    {{ p.title }}

    +
    +

    {{ p.title }}

    + +
    + {{ T('last-changed') }} {{ rev.human_pub_date() }} · + {{ T('jump-to-actions') }} +
    -
    - {{ T('last-changed') }} {{ rev.human_pub_date() }} · - {{ T('jump-to-actions') }} -
    + {% block history_nav %}{% endblock %} -{% block history_nav %}{% endblock %} +
    + {{ rev.html()|safe }} +
    -
    - {{ rev.html()|safe }} -
    + {% if p.tags %} +
    +

    {{ T('tags') }}:

    +
      + {% for tag in p.tags %} +
    • #{{ tag.name }} ({{ tag.popularity() }})
    • + {% endfor %} +
    +
    + {% endif %} +
    -{% if p.tags %} -
    -

    {{ T('tags') }}:

    - -
    -{% endif %} {% endblock %} {% block actions %} @@ -36,3 +39,7 @@ {{ T('last-changed') }} - {{ T('page-id') }}: {{ p.id }} {% endblock %} + +{% block scripts %} + +{% endblock %}