mirror of https://github.com/tiyn/amphora-wiki
parent
1c57f74541
commit
51682d00f0
@ -0,0 +1,68 @@
|
||||
# Python Flask Wiki
|
||||
|
||||
This is a simple wiki based on Pythons Flask framework.
|
||||
There is much great wiki software.
|
||||
Most of them are using some kind of database.
|
||||
I however just want to put my markdown files in a directory and get a working wiki.
|
||||
|
||||
## Features/To-Dos
|
||||
|
||||
- [ ] Plain text support for blog entries
|
||||
- [ ] Markdown Files (.md)
|
||||
- [ ] Entry page
|
||||
- [ ] Navigation
|
||||
- [ ] Header
|
||||
- [ ] Footer
|
||||
- [ ] Switchable CSS
|
||||
- [ ] CSS dark-theme
|
||||
- [ ] CSS light-theme
|
||||
- [ ] Config file
|
||||
- [ ] Docker installation
|
||||
- [ ] Enable variables/environment variables
|
||||
- [ ] Logo
|
||||
|
||||
## Usage
|
||||
|
||||
### Create entries
|
||||
|
||||
Wiki entries are managed by plain markdown files in the `templates/entry/` directory.
|
||||
The first line of each document is reserved as the title of the document.
|
||||
|
||||
## Deployment
|
||||
|
||||
### PIP/Python
|
||||
|
||||
- `git clone https://github.com/tiyn/tiyny-blog`
|
||||
- `cd flaskblog/src`
|
||||
- edit the `config.py` file according to your needs
|
||||
- `pip3install -r requirements.txt` - install depenencies
|
||||
- run `python app.py`
|
||||
- blog is available on port 5000
|
||||
|
||||
### Docker
|
||||
|
||||
Make sure you copy an example `config.py` and edit it before running the container.
|
||||
The `config.py` can be found in the `src` folder.
|
||||
|
||||
#### Volumes
|
||||
|
||||
Set the following volumes with the -v tag.
|
||||
|
||||
| Volume-Name | Container mount | Description |
|
||||
|-------------|---------------------------|--------------------------------------------------------------|
|
||||
| config-file | /blog/src/config.py | Config file |
|
||||
| entries | /blog/src/templates/entry | Directory for blog entries |
|
||||
| css | /blog/src/static/css | (optional) Directory for css files |
|
||||
| html | /blog/src/templates | (optional) Directory for templates (entry-volume not needed) |
|
||||
|
||||
#### Ports
|
||||
|
||||
Set the following ports with the -p tag.
|
||||
|
||||
| Container-Port | Recommended outside port | Protocol | Description |
|
||||
|----------------|--------------------------|----------|-------------|
|
||||
| 5000 | 80 | TCP | HTTP port |
|
||||
|
||||
#### Example run-command
|
||||
|
||||
`docker run --name wiki --restart unless-stopped -v ./config.py:/wiki/src/config.py -v entries:/wiki/src/templates/entry -p 80:5000 -d tiynger/tiyny-wiki`
|
@ -0,0 +1,21 @@
|
||||
FROM ubuntu
|
||||
|
||||
MAINTAINER Tiyn tiyn@martenkante.eu
|
||||
|
||||
RUN apt-get update
|
||||
|
||||
RUN apt-get install python3 python3-pip git -y
|
||||
|
||||
RUN git clone https://github.com/tiyn/tiyny-wiki /wiki
|
||||
|
||||
WORKDIR /wiki/src
|
||||
|
||||
RUN pip3 install -r requirements.txt
|
||||
|
||||
VOLUME /wiki/src/templates/entry
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
ENTRYPOINT [ "python3" ]
|
||||
|
||||
CMD [ "app.py" ]
|
@ -0,0 +1,22 @@
|
||||
from flask import Flask, flash, make_response, render_template, request, redirect, abort
|
||||
|
||||
import content as con_gen
|
||||
import config
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(e):
|
||||
return render_template('error.html', title=config.TITLE, errorcode='404', style=config.STYLE), 404
|
||||
|
||||
|
||||
@app.route('/')
|
||||
@app.route('/index.html')
|
||||
def index():
|
||||
return 'ok'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0')
|
@ -0,0 +1,8 @@
|
||||
# Name/title of your blog
|
||||
TITLE = 'Tiyny-Wiki'
|
||||
|
||||
# URL for your website: e.g. https://domain.tld
|
||||
WEBSITE = 'localhost:5000'
|
||||
|
||||
# Theme for the blog: dark, light
|
||||
STYLE = 'dark'
|
@ -0,0 +1,10 @@
|
||||
import datetime
|
||||
from datetime import datetime
|
||||
import markdown
|
||||
import os
|
||||
from os import path
|
||||
import pathlib
|
||||
|
||||
import config
|
||||
|
||||
ENTRY_DIR = 'templates/entry'
|
@ -0,0 +1,2 @@
|
||||
Flask==1.1.2
|
||||
Markdown==3.1.1
|
@ -0,0 +1,72 @@
|
||||
@import 'style.css';
|
||||
|
||||
:root {
|
||||
--bg0: rgb(29,32,33);
|
||||
--color0: rgb(220,120,0);
|
||||
--error: rgb(255,0,0);
|
||||
--footerbg0: rgb(29,32,33);
|
||||
--link0: rgb(220, 120, 0);
|
||||
--link1: rgb(255,255,255);
|
||||
--menulink0: rgb(220, 120, 0);
|
||||
--menulink1: rgb(255,255,255);
|
||||
--menubg0: rgb(29,32,33);
|
||||
--text0: rgb(235,219,178);
|
||||
--text1: rgb(220, 120, 0);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link0);
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--link1);
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg0);
|
||||
}
|
||||
|
||||
footer {
|
||||
background: var(--footerbg0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container {
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
.container h1,
|
||||
.container h2 {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container .flash {
|
||||
background-color: var(--error);
|
||||
}
|
||||
|
||||
.hide-menu:hover,
|
||||
.main-menu a:hover,
|
||||
.show-menu:hover {
|
||||
color: var(--menulink1);
|
||||
}
|
||||
|
||||
.main-menu a {
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
.main-menu-dropdown {
|
||||
background: var(--menubg0);
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
@media screen and (max-width:800px) {
|
||||
|
||||
.main-menu {
|
||||
background: var(--menubg0);
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
@import 'style.css';
|
||||
|
||||
:root {
|
||||
--bg0: rgb(255,255,255);
|
||||
--color0: rgb(0,0,120);
|
||||
--error: rgb(255,0,0);
|
||||
--footerbg0: rgb(192,192,192);
|
||||
--link0: rgb(0,0,120);
|
||||
--link1: rgb(255,255,255);
|
||||
--menulink0: rgb(0,0,120);
|
||||
--menulink1: rgb(255,255,255);
|
||||
--menubg0: rgb(192,192,192);
|
||||
--text0: rgb(0,0,0);
|
||||
--text1: rgb(0,0,120);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link0);
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--link1);
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg0);
|
||||
}
|
||||
|
||||
footer {
|
||||
background: var(--footerbg0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container {
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
.container h1,
|
||||
.container h2 {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container .flash {
|
||||
background-color: var(--error);
|
||||
}
|
||||
|
||||
.hide-menu:hover,
|
||||
.main-menu a:hover,
|
||||
.show-menu:hover {
|
||||
color: var(--menulink1);
|
||||
}
|
||||
|
||||
.main-menu a {
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
.main-menu-dropdown {
|
||||
background: var(--menubg0);
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
@media screen and (max-width:800px) {
|
||||
|
||||
.main-menu {
|
||||
background: var(--menubg0);
|
||||
}
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
:root {
|
||||
--error: rgb(255,0,0);
|
||||
--transtime: 0.7s;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
footer {
|
||||
height: 100px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
footer .center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
min-height: 100%;
|
||||
padding-bottom: 50px;
|
||||
padding-left: 10%;
|
||||
padding-right: 10%;
|
||||
padding-top: 5%;
|
||||
}
|
||||
|
||||
.container .flash {
|
||||
padding: 10px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.hide-menu,
|
||||
.show-menu {
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
font-size: 30px;
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
.important {
|
||||
font-size: xx-large;
|
||||
padding-left: 25vw;
|
||||
padding-right: 25vw;
|
||||
padding-top: 30vh;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.important span {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 80px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.main-menu-dropdown span {
|
||||
float: left;
|
||||
font-family: monospace;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
line-height: 100px;
|
||||
padding: 0 10px;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
transition: 0.7s;
|
||||
}
|
||||
|
||||
.main-menu {
|
||||
float: right;
|
||||
font-family: monospace;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
line-height: 100px;
|
||||
}
|
||||
|
||||
.main-menu a {
|
||||
padding: 0 10px;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
transition: 0.7s;
|
||||
}
|
||||
|
||||
.main-menu-dropdown {
|
||||
height: 100px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.show-menu {
|
||||
float: right;
|
||||
line-height: 100px;
|
||||
}
|
||||
|
||||
#main-menu-check {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
z-index: -1111;
|
||||
}
|
||||
|
||||
@media screen and (max-width:800px) {
|
||||
.hide-menu {
|
||||
position: absolute;
|
||||
right: 40px;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
.hide-menu,
|
||||
.show-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.main-menu {
|
||||
height: 100vh;
|
||||
line-height: normal;
|
||||
padding: 80px 0;
|
||||
position: fixed;
|
||||
right: -100%;
|
||||
text-align: center;
|
||||
top: 0;
|
||||
transition: var(--transtime);
|
||||
width: 100%;
|
||||
}
|
||||
.main-menu a {
|
||||
display: block;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#main-menu-check:checked ~ .main-menu {
|
||||
right: 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
Test Entry Title 3
|
||||
This is a markdown file
|
||||
|
||||
- list entry
|
||||
- list entry
|
||||
- list entry
|
||||
|
||||
# md-header
|
||||
|
||||
more content
|
@ -0,0 +1,10 @@
|
||||
Test Entry Title 3
|
||||
This is a markdown file
|
||||
|
||||
- list entry
|
||||
- list entry
|
||||
- list entry
|
||||
|
||||
# md-header
|
||||
|
||||
more content
|
@ -0,0 +1,10 @@
|
||||
Test Entry Title 3
|
||||
This is a markdown file
|
||||
|
||||
- list entry
|
||||
- list entry
|
||||
- list entry
|
||||
|
||||
# md-header
|
||||
|
||||
more content
|
@ -0,0 +1,9 @@
|
||||
{% extends "template.html" %}
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="important">
|
||||
Error<br>
|
||||
<span>{{ errorcode }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -0,0 +1,32 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ title }}</title>
|
||||
<link href="{{ url_for('static', filename='css/' + style + '.css') }}" rel="stylesheet" type="text/css">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width", initial-scale=1.0>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Menu -->
|
||||
<div class="main-menu-dropdown">
|
||||
<!-- <img class="logo" src="/static/images/logo.png"> -->
|
||||
<span>{{ title }}</span>
|
||||
<input type="checkbox" id="main-menu-check">
|
||||
<label for="main-menu-check" class="show-menu">☰</label>
|
||||
<div class="main-menu">
|
||||
<a href="/">Startpage</a>
|
||||
<label for="main-menu-check" class="hide-menu">X</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Menu -->
|
||||
<!-- Content -->
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<!-- Content -->
|
||||
<footer>
|
||||
<div class="center">
|
||||
Dieser Blog enthält kein Javascript oder PHP.<br>
|
||||
Dies ist eine Instanz vom <a href="https://github.com/tiyn/tiyny-wiki">Tiyny-Wiki</a>.
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in new issue