diff --git a/CHANGELOG.md b/CHANGELOG.md index 696ed1d..8311294 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## v1.1 2021.03.28 + +### Added + +- **owl** switched to `markdown` module. +- `markdown_alerts` extension. Short admonition syntax. +- `markdown_del_ins` extension. Deleted and inserted text support. + +### Changed + +- Fixed `PASSWORD_FILE` detecting. +- Fixed path resolving. Now uses `os.path.join()`. + +### Removed + +- `markdown2`. Replaced by `markdown` module. + ## v1.0 2021.03.23 ### Added @@ -27,4 +44,4 @@ ## v0.1 2020.08.15 -First version released. +First version released. \ No newline at end of file diff --git a/README.md b/README.md index def1b19..fd2ee5c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # owl -![](https://img.shields.io/badge/owl-v1.0-%2300f) +![](https://img.shields.io/badge/owl-v1.1-blueviolet) **owl** — is the minimalistic kn**owl**edge base web app written in Python. @@ -22,13 +22,11 @@ App is now available at [http://localhost:5000/](http://localhost:5000/). This solution is suitable for creating documentation or maintaining a personal knowledge base. -New in `v1.0`: -- This is brand new owl! -- New frontend and refactored backend. -- Bootstrap 5 -- Optional authentication. +New in `v1.1`: +- Switched to [Python-Markdown](https://github.com/Python-Markdown/markdown). +- Added some new Markdown extensions. -See [CHANGELOG.md](CHANGELOG.md) +See [CHANGELOG.md](CHANGELOG.md). # License diff --git a/config.py b/config.py index e564299..bc1aa78 100644 --- a/config.py +++ b/config.py @@ -1,16 +1,32 @@ class Config(object): DEBUG = False - SECRET_KEY = 'top_secret' + SECRET_KEY = None PASSWORD_FILE = '.pw' SIGN_IN = False # Enable or disable authentication MARKDOWN_ROOT = 'docs/' # Path to your .md files MARKDOWN_DOWLOADS = True - # See https://github.com/trentm/python-markdown2/wiki/Extras - MARKDOWN2_EXTRAS = [ - 'fenced-code-blocks', - 'markdown-in-html', - 'code-friendly', - 'header-ids', - 'strike', - 'tables' - ] \ No newline at end of file + MARKDOWN_EXTRAS = [ + 'admonition', + 'attr_list', + 'codehilite', + 'def_list', + 'fenced_code', + 'md_in_html', + 'markdown_alerts', + 'markdown_del_ins', + 'tables', + 'toc' + ] + MARKDOWN_EXTRAS_CONFIGS = { + 'markdown_alerts': { + 'info': 'alert alert-info', + 'note': 'alert alert-primary', + 'tip': 'alert alert-success', + 'success': 'alert alert-success', + 'warning': 'alert alert-warning', + 'danger': 'alert alert-danger' + }, + 'toc': { + 'toc_depth': '2-5' + } + } \ No newline at end of file diff --git a/docs/CONTENTS.md b/docs/CONTENTS.md index 5587640..73d0295 100644 --- a/docs/CONTENTS.md +++ b/docs/CONTENTS.md @@ -1,3 +1,3 @@ -### Contents +# @v@ -- [Home](/) +- [Home](/) \ No newline at end of file diff --git a/docs/HOME.md b/docs/HOME.md index 9de7ccf..e6e6df8 100644 --- a/docs/HOME.md +++ b/docs/HOME.md @@ -1,6 +1,16 @@ -# @v@ owl took off! +# owl took off! -Read the [Docs](https://owl.gch.icu/docs/) to get started. +
+ , , + /\ /\ +((@v@)) +((;;; (\ + \ ;;; \' + ,V.V ` + `` `` +-Also there is project's [git repository](https://gitea.gch.icu/gd/owl) ([mirror](https://github.com/gechandesu/owl)). +Read the [Docs](https://owl.gch.icu/docs/){target="_blank"} to get started. + +Also there is project's [git repository](https://gitea.gch.icu/gd/owl) ([mirror on GitHub](https://github.com/gechandesu/owl)). diff --git a/owl.py b/owl.py index 2c244df..ec36d61 100644 --- a/owl.py +++ b/owl.py @@ -1,10 +1,12 @@ +__version__ = '1.1' + import os import re from functools import wraps from datetime import timedelta import pygments -from markdown2 import Markdown +from markdown import Markdown from flask import Flask from flask import request @@ -30,31 +32,35 @@ def read_file(filepath: str) -> str: except IOError: return 'Error: Cannot read file: {}'.format(filepath) +def get_path(path: str) -> str: + return os.path.join(app.config['MARKDOWN_ROOT'], path) + def render_html(filepath: str) -> str: - markdown = Markdown(extras=app.config['MARKDOWN2_EXTRAS']) - return markdown.convert( - read_file( - app.config['MARKDOWN_ROOT'] + filepath - ) - ) + html = Markdown( + extensions = app.config['MARKDOWN_EXTRAS'], + extension_configs = app.config['MARKDOWN_EXTRAS_CONFIGS'] + ) + return html.convert( + read_file(get_path(filepath)) + ) def parse_title_from_markdown(filepath: str) -> str: # This function parses article title from first level heading. # It returns the occurrence of the first heading, and there # can be nothing before it except empty lines and spaces. - article = read_file(app.config['MARKDOWN_ROOT'] + filepath) + article = read_file(get_path(filepath)) pattern = re.compile(r'^\s*#\s.*') if pattern.search(article): return pattern.search(article).group().strip()[2:] else: - return 'Error: Cannot parse title from file:'.format(filepath) + return 'Error: Cannot parse title from file: {}'.format(filepath) def parse_content_links(filepath: str) -> list: # This function returns a list of links from a Markdown file. # Only links contained in the list (ul ol li) are parsed. r = re.compile(r'(.*(-|\+|\*|\d).?\[.*\])(\(.*\))', re.MULTILINE) links = [] - for tpl in r.findall(read_file(app.config['MARKDOWN_ROOT'] + filepath)): + for tpl in r.findall(read_file(get_path(filepath))): for item in tpl: if re.match(r'\(.*\)', item): if item == '(/)': @@ -67,8 +73,8 @@ def parse_content_links(filepath: str) -> list: return links def check_password(password: str) -> bool: - if os.path.exists('.pw'): - pw_hash = read_file('.pw') + if os.path.exists(app.config['PASSWORD_FILE']): + pw_hash = read_file(app.config['PASSWORD_FILE']) return bcrypt.check_password_hash(pw_hash, password) else: return False @@ -129,7 +135,7 @@ def index(): @app.route('/