From 2f66db59896983d3cedeaa0f8521dd000b407c2a Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Tue, 2 Feb 2021 17:09:19 +0000 Subject: [PATCH] Update API docs, add support for code highlighting, add markdown table support --- app/__init__.py | 28 ++++++--- app/default_data.py | 2 +- app/flatpages/help.md | 1 - app/flatpages/help/api.md | 25 ++++++-- app/flatpages/help/package_tags.md | 33 ---------- app/flatpages/help/top_packages.md | 6 +- app/flatpages/help/update_config.md | 2 +- app/markdown.py | 43 ++++++------- app/scss/custom.scss | 4 +- app/scss/dracula.scss | 94 +++++++++++++++++++++++++++++ app/templates/base.html | 2 +- requirements.lock.txt | 1 + requirements.txt | 1 + 13 files changed, 163 insertions(+), 79 deletions(-) delete mode 100644 app/flatpages/help/package_tags.md create mode 100644 app/scss/dracula.scss diff --git a/app/__init__.py b/app/__init__.py index 3b3d7fbf..e999201f 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,5 +1,5 @@ # ContentDB -# Copyright (C) 2018-1 rubenwardy +# Copyright (C) 2018-21 rubenwardy # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -21,7 +21,7 @@ import flask_menu as menu from flask_mail import Mail from flask_github import GitHub from flask_wtf.csrf import CSRFProtect -from flask_flatpages import FlatPages +from flask_flatpages import FlatPages, pygments_style_defs from flask_babel import Babel from flask_login import logout_user, current_user, LoginManager import os, redis @@ -29,6 +29,14 @@ import os, redis app = Flask(__name__, static_folder="public/static") app.config["FLATPAGES_ROOT"] = "flatpages" app.config["FLATPAGES_EXTENSION"] = ".md" +app.config["FLATPAGES_MARKDOWN_EXTENSIONS"] = ["fenced_code", "tables", "codehilite"] +app.config["FLATPAGES_EXTENSION_CONFIG"] = { + "fenced_code": {}, + "tables": {}, + "codehilite": { + "linenums": "True" + } +} app.config.from_pyfile(os.environ["FLASK_CONFIG"]) r = redis.Redis.from_url(app.config["REDIS_URL"]) @@ -41,8 +49,8 @@ pages = FlatPages(app) babel = Babel(app) gravatar = Gravatar(app, size=58, - rating='g', - default='mp', + rating="g", + default="mp", force_default=False, force_lower=False, use_ssl=True, @@ -66,7 +74,7 @@ init_app(app) # @babel.localeselector # def get_locale(): -# return request.accept_languages.best_match(app.config['LANGUAGES'].keys()) +# return request.accept_languages.best_match(app.config["LANGUAGES"].keys()) from . import models, template_filters @@ -80,13 +88,13 @@ create_blueprints(app) @app.route("/uploads/") def send_upload(path): - return send_from_directory(app.config['UPLOAD_DIR'], path) + return send_from_directory(app.config["UPLOAD_DIR"], path) -@menu.register_menu(app, ".help", "Help", order=19, endpoint_arguments_constructor=lambda: { 'path': 'help' }) -@app.route('//') +@menu.register_menu(app, ".help", "Help", order=19, endpoint_arguments_constructor=lambda: { "path": "help" }) +@app.route("//") def flatpage(path): page = pages.get_or_404(path) - template = page.meta.get('template', 'flatpage.html') + template = page.meta.get("template", "flatpage.html") return render_template(template, page=page) @app.before_request @@ -95,7 +103,7 @@ def check_for_ban(): if current_user.rank == models.UserRank.BANNED: flash("You have been banned.", "danger") logout_user() - return redirect(url_for('users.login')) + return redirect(url_for("users.login")) elif current_user.rank == models.UserRank.NOT_JOINED: current_user.rank = models.UserRank.MEMBER models.db.session.commit() diff --git a/app/default_data.py b/app/default_data.py index 508b2a77..cd3c6bf6 100644 --- a/app/default_data.py +++ b/app/default_data.py @@ -102,7 +102,7 @@ def populate_test_data(session): mod1.desc = """ Majority of awards are back ported from Calinou's old fork in Carbone, under same license. -``` +```lua awards.register_achievement("award_mesefind",{ title = "First Mese Find", description = "Found some Mese!", diff --git a/app/flatpages/help.md b/app/flatpages/help.md index 5499f83c..141c20a8 100644 --- a/app/flatpages/help.md +++ b/app/flatpages/help.md @@ -12,7 +12,6 @@ title: Help ## Help for Package Authors * [Package Inclusion Policy and Guidance](/policy_and_guidance/) -* [Package Tags](package_tags) * [Git Update Detection](update_config) * [Creating Releases using Webhooks](release_webhooks) * [Package Configuration and Releases Guide](package_config) diff --git a/app/flatpages/help/api.md b/app/flatpages/help/api.md index 191b25e3..e69d349d 100644 --- a/app/flatpages/help/api.md +++ b/app/flatpages/help/api.md @@ -5,11 +5,11 @@ title: API Not all endpoints require authentication. Authentication is done using Bearer tokens: - Authorization: Bearer YOURTOKEN +```bash +curl -H "Authorization: Bearer YOURTOKEN" https://content.minetest.net/api/whoami/ +``` -You can use the `/api/whoami` to check authentication. - -Tokens can be attained by visiting [Profile > "API Tokens"](/user/tokens/). +Tokens can be attained by visiting [Settings > API Tokens](/user/tokens/). ## Endpoints @@ -43,8 +43,8 @@ Tokens can be attained by visiting [Profile > "API Tokens"](/user/tokens/). ### Releases -* GET `/api/packages///releases/` -* POST `/api/packages///releases/new/` +* GET `/api/packages///releases/` (List) +* POST `/api/packages///releases/new/` (Create) * Requires authentication. * Body is multipart form if zip upload, JSON otherwise. * `title`: human-readable name of the release. @@ -55,6 +55,19 @@ Tokens can be attained by visiting [Profile > "API Tokens"](/user/tokens/). * `file`: multipart file to upload, like ``. * You can set min and max Minetest Versions [using the content's .conf file](/help/package_config/). +Examples: + +```bash +# Create release from Git +curl -X POST https://content.minetest.net/api/packages/username/name/releases/new/ \ + -H "Authorization: Bearer YOURTOKEN" -H "Content-Type: application/json" \ + -d "{\"method\": \"git\", \"title\": \"My Release\", \"ref\": \"master\" }" + +# Create release from zip upload +curl https://content.minetest.net/api/packages/username/name/releases/new/ \ + -H "Authorization: Bearer YOURTOKEN" \ + -F title="My Release" -F file=@path/to/file.zip +``` ### Topics diff --git a/app/flatpages/help/package_tags.md b/app/flatpages/help/package_tags.md deleted file mode 100644 index b5b4f4a6..00000000 --- a/app/flatpages/help/package_tags.md +++ /dev/null @@ -1,33 +0,0 @@ -title: Package Tags - -## Overview - -Tags should be added to packages to enable easy identification of different types of mods, games and texture packs. - -They are only beneficial when applied correctly, so please use the following guidelines. - -## Tag Usage - -* **Building** - For mods that focus on adding new materials or nodes to build with. -* **Education** - For mods or games created for educational purposes. -* **Environment** - For mods that add environmental effects, including ambient sound and weather effects. -* **Inventory** - For mods that add new inventory systems or new inventory pages. -* **Machines and Electronics** - For mods that include placeable machinery or electronic components which interact to complete tasks. -* **Maintenance** - For mods that assist with world or player maintenance. This includes large-scale map manipulation, area protection and other administrative tools. -* **Mapgen** - For mods that add new biomes, new mapgen decorations, or any other mapgen elements. -* **Mobs and NPCs** - For mods that add mobs or NPCs, or provide tools that assist with mob and NPC creation or manipulation. -* **Plants and Farming** - For mods that add new plants or other farmable resources. -* **Player effects/Food** - For mods that change player effects, for example speed, jump height or gravity, and food. -* **Tools** - For mods that add new tools or new features for existing tools. -* **Transport** - For mods that add transportation methods. This includes teleportation, vehicles and ridable mobs. -* **Survival** - For mods written specifically for survival games. For example, these mods might focus on game-balance or increase the difficulty level. This tag should also be used for games with a heavy survival focus. -* **Creative** - For mods written specifically (and often exclusively) for use in creative mode. For example, these mods may add a large amount of decorative content, or content without crafting recipes. This tag should also be used for games with a heavy creative focus. -* **Multiplayer-focused** - For games that can be played with other players. -* **Singleplayer-focused** - For games that can be played alone. -* **PvP** - For games designed to be played competitively against other players. -* **PvE** - For games designed for one or multiple players which focus on combat against mobs or NPCs. -* **Puzzle** - For mods and games with a focus on puzzle solving instead of combat. -* **16px** - For 16px texture packs. -* **32px** - For 32px texture packs. -* **64px** - For 64px texture packs. -* **128px+** - For 128px or higher texture packs. \ No newline at end of file diff --git a/app/flatpages/help/top_packages.md b/app/flatpages/help/top_packages.md index 5862f078..747a6d70 100644 --- a/app/flatpages/help/top_packages.md +++ b/app/flatpages/help/top_packages.md @@ -11,8 +11,10 @@ plus the sum of the score given by reviews. A review score is 100 if positive, -100 if negative. - reviews_sum = sum(100 * (positive ? 1 : -1)) - score = avg_downloads + reviews_sum +```c +reviews_sum = sum(100 * (positive ? 1 : -1)); +score = avg_downloads + reviews_sum; +``` ## Pseudo rolling average of downloads diff --git a/app/flatpages/help/update_config.md b/app/flatpages/help/update_config.md index cdee258f..814f5ada 100644 --- a/app/flatpages/help/update_config.md +++ b/app/flatpages/help/update_config.md @@ -3,7 +3,7 @@ title: Git Update Detection ## Introduction When you push a change to your Git repository, ContentDB can create a new release automatically or -send you a reminder. ContentDB will check your Git repository every day, but you can use +send you a reminder. ContentDB will check your Git repository one per day, but you can use webhooks or the API for faster updates. Git Update Detection is clever enough to not create a release again if you've already created diff --git a/app/markdown.py b/app/markdown.py index 9f12f991..1d14c5e5 100644 --- a/app/markdown.py +++ b/app/markdown.py @@ -11,25 +11,18 @@ Default whitelist of allowed HTML tags. Any other HTML tags will be escaped or stripped from the text. This applies to the html output that Markdown produces. """ ALLOWED_TAGS = [ - 'ul', - 'ol', - 'li', - 'p', - 'pre', - 'code', - 'blockquote', - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'hr', - 'br', - 'strong', - 'em', - 'a', - 'img' + "h1", "h2", "h3", "h4", "h5", "h6", "hr", + "ul", "ol", "li", + "p", + "br", + "pre", + "code", + "blockquote", + "strong", + "em", + "a", + "img", + "table", "thead", "tbody", "tr", "th", "td" ] """ @@ -38,8 +31,8 @@ tags and the src, title and alt attributes for tags. Any other attribute will be stripped from its tag. """ ALLOWED_ATTRIBUTES = { - 'a': ['href', 'title'], - 'img': ['src', 'title', 'alt'] + "a": ["href", "title"], + "img": ["src", "title", "alt"] } """ @@ -47,10 +40,10 @@ If you allow tags that have attributes containing a URI value (like the href attribute of an anchor tag,) you may want to adapt the accepted protocols. The default list only allows http, https and mailto. """ -ALLOWED_PROTOCOLS = ['http', 'https', 'mailto'] +ALLOWED_PROTOCOLS = ["http", "https", "mailto"] -md = Markdown(extensions=["fenced_code"], output_format="html5") +md = None def render_markdown(source): return bleach.clean(md.convert(source), @@ -58,6 +51,10 @@ def render_markdown(source): styles=[], protocols=ALLOWED_PROTOCOLS) def init_app(app): + global md + + md = Markdown(extensions=app.config["FLATPAGES_MARKDOWN_EXTENSIONS"], output_format="html5") + @app.template_filter() def markdown(source): return Markup(render_markdown(source)) diff --git a/app/scss/custom.scss b/app/scss/custom.scss index e2b1616c..860497bd 100644 --- a/app/scss/custom.scss +++ b/app/scss/custom.scss @@ -67,7 +67,7 @@ p, .content li { pre code { display: block; border: 1px solid rgba(255, 255, 255, 0.1); - background: rgba(255, 255, 255, 0.03); + background: rgba(51, 51, 51, 0.25); padding: 0.75rem 1.25rem; border-radius: 0.25rem; } @@ -157,3 +157,5 @@ pre code { text-align: left; } } + +@import "dracula.scss"; diff --git a/app/scss/dracula.scss b/app/scss/dracula.scss new file mode 100644 index 00000000..04a27eb1 --- /dev/null +++ b/app/scss/dracula.scss @@ -0,0 +1,94 @@ +/* Dracula Theme v1.2.5 + * + * https://github.com/zenorocha/dracula-theme + * + * Copyright 2016, All rights reserved + * + * Code licensed under the MIT license + * http://zenorocha.mit-license.org + * + * @author Rob G + * @author Chris Bracco + * @author Zeno Rocha + */ + +.highlight, .codehilite { + color: #f8f8f2; + + .hll { background-color: #f1fa8c } + .c { color: #6272a4 } /* Comment */ + .err { color: #f8f8f2 } /* Error */ + .g { color: #f8f8f2 } /* Generic */ + .k { color: #ff79c6 } /* Keyword */ + .l { color: #f8f8f2 } /* Literal */ + .n { color: #f8f8f2 } /* Name */ + .o { color: #ff79c6 } /* Operator */ + .x { color: #f8f8f2 } /* Other */ + .p { color: #f8f8f2 } /* Punctuation */ + .ch { color: #6272a4 } /* Comment.Hashbang */ + .cm { color: #6272a4 } /* Comment.Multiline */ + .cp { color: #ff79c6 } /* Comment.Preproc */ + .cpf { color: #6272a4 } /* Comment.PreprocFile */ + .c1 { color: #6272a4 } /* Comment.Single */ + .cs { color: #6272a4 } /* Comment.Special */ + .gd { color: #8b080b } /* Generic.Deleted */ + .ge { color: #f8f8f2; text-decoration: underline } /* Generic.Emph */ + .gr { color: #f8f8f2 } /* Generic.Error */ + .gh { color: #f8f8f2; font-weight: bold } /* Generic.Heading */ + .gi { color: #f8f8f2; font-weight: bold } /* Generic.Inserted */ + .go { color: #44475a } /* Generic.Output */ + .gp { color: #f8f8f2 } /* Generic.Prompt */ + .gs { color: #f8f8f2 } /* Generic.Strong */ + .gu { color: #f8f8f2; font-weight: bold } /* Generic.Subheading */ + .gt { color: #f8f8f2 } /* Generic.Traceback */ + .kc { color: #ff79c6 } /* Keyword.Constant */ + .kd { color: #8be9fd; font-style: italic } /* Keyword.Declaration */ + .kn { color: #ff79c6 } /* Keyword.Namespace */ + .kp { color: #ff79c6 } /* Keyword.Pseudo */ + .kr { color: #ff79c6 } /* Keyword.Reserved */ + .kt { color: #8be9fd } /* Keyword.Type */ + .ld { color: #f8f8f2 } /* Literal.Date */ + .m { color: #bd93f9 } /* Literal.Number */ + .s { color: #f1fa8c } /* Literal.String */ + .na { color: #50fa7b } /* Name.Attribute */ + .nb { color: #8be9fd; font-style: italic } /* Name.Builtin */ + .nc { color: #50fa7b } /* Name.Class */ + .no { color: #f8f8f2 } /* Name.Constant */ + .nd { color: #f8f8f2 } /* Name.Decorator */ + .ni { color: #f8f8f2 } /* Name.Entity */ + .ne { color: #f8f8f2 } /* Name.Exception */ + .nf { color: #50fa7b } /* Name.Function */ + .nl { color: #8be9fd; font-style: italic } /* Name.Label */ + .nn { color: #f8f8f2 } /* Name.Namespace */ + .nx { color: #f8f8f2 } /* Name.Other */ + .py { color: #f8f8f2 } /* Name.Property */ + .nt { color: #ff79c6 } /* Name.Tag */ + .nv { color: #8be9fd; font-style: italic } /* Name.Variable */ + .ow { color: #ff79c6 } /* Operator.Word */ + .w { color: #f8f8f2 } /* Text.Whitespace */ + .mb { color: #bd93f9 } /* Literal.Number.Bin */ + .mf { color: #bd93f9 } /* Literal.Number.Float */ + .mh { color: #bd93f9 } /* Literal.Number.Hex */ + .mi { color: #bd93f9 } /* Literal.Number.Integer */ + .mo { color: #bd93f9 } /* Literal.Number.Oct */ + .sa { color: #f1fa8c } /* Literal.String.Affix */ + .sb { color: #f1fa8c } /* Literal.String.Backtick */ + .sc { color: #f1fa8c } /* Literal.String.Char */ + .dl { color: #f1fa8c } /* Literal.String.Delimiter */ + .sd { color: #f1fa8c } /* Literal.String.Doc */ + .s2 { color: #f1fa8c } /* Literal.String.Double */ + .se { color: #f1fa8c } /* Literal.String.Escape */ + .sh { color: #f1fa8c } /* Literal.String.Heredoc */ + .si { color: #f1fa8c } /* Literal.String.Interpol */ + .sx { color: #f1fa8c } /* Literal.String.Other */ + .sr { color: #f1fa8c } /* Literal.String.Regex */ + .s1 { color: #f1fa8c } /* Literal.String.Single */ + .ss { color: #f1fa8c } /* Literal.String.Symbol */ + .bp { color: #f8f8f2; font-style: italic } /* Name.Builtin.Pseudo */ + .fm { color: #50fa7b } /* Name.Function.Magic */ + .vc { color: #8be9fd; font-style: italic } /* Name.Variable.Class */ + .vg { color: #8be9fd; font-style: italic } /* Name.Variable.Global */ + .vi { color: #8be9fd; font-style: italic } /* Name.Variable.Instance */ + .vm { color: #8be9fd; font-style: italic } /* Name.Variable.Magic */ + .il { color: #bd93f9 } /* Literal.Number.Integer.Long */ +} diff --git a/app/templates/base.html b/app/templates/base.html index 844f7b58..aad4b418 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -7,7 +7,7 @@ {% block title %}title{% endblock %} - {{ config.USER_APP_NAME }} - + diff --git a/requirements.lock.txt b/requirements.lock.txt index 5ef9b88f..be1649ca 100644 --- a/requirements.lock.txt +++ b/requirements.lock.txt @@ -51,6 +51,7 @@ psycopg2==2.8.5 py==1.9.0 pycparser==2.20 pyparsing==2.4.7 +pygments==2.7.4 pyScss==1.3.7 pytest==5.4.3 pytest-cov==2.10.0 diff --git a/requirements.txt b/requirements.txt index baa6cba6..8db71a92 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,6 +15,7 @@ markdown ~= 3.1 bleach ~= 3.1 passlib ~= 1.7 +pygments ~= 2.7 beautifulsoup4 ~= 4.6 celery ~= 4.4