diff options
author | mjfernez <mjfernez@gmail.com> | 2021-06-07 00:03:12 -0400 |
---|---|---|
committer | mjfernez <mjfernez@gmail.com> | 2021-06-07 00:40:39 -0400 |
commit | ca5b85fb744221588859f3639ba7e4da0bc82649 (patch) | |
tree | 2595d1e315e09e5d35c362d95a35585416a7a2fb | |
download | ezcms-ca5b85fb744221588859f3639ba7e4da0bc82649.tar.gz |
first commit
28 files changed, 886 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a81c8ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,138 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ @@ -0,0 +1,178 @@ +# EZCMS - a minimal and simple way to manage a website + +## Requirements + +Python 3.7+ + + +## Huh/What/Why? + +EZCMS (or "Easy CMS" for those of you who call that "zed" instead) is a minimal +and simple way of managing content and serving static files on a website. It +was mostly made for my own website which I wanted to be simple, but with some +ability to easily add new pages in a template I like. + +EZCMS is designed around the idea that web servers are really just glorified +file cabinets and draws heavily from the Unix philosophy of "everything is a +file". When a user finds a site managed by this program, they are primarily +greeted with a series of folders and files, but in a neat and easy to +understand index. Each folder--preferably labeled appropriately so users +know what they're links to other sites--will index itself on click, containing +a short description of the directory, sub-directories, files, and links +elsewhere. + +Why not just use a database or the million other CMS software packages out +there? Zero reason not to! I just wanted to see what it would look like to +build something from the ground up WITHOUT having to copy HTML over and over +again. Databases are great, but so are filesystems, and I see no reason to +overcomplicate when making a simple home page. This software is primarily +geared towards bloggers or people who want a home page like it's 1999, but +Flask has great documentation so I think you'll find it a pleasure to build on +top of. + + +## Quick start + +It's recommended to run each server in it's own virtual environment. This +program uses python 3.7, so change `python` to either `python3` or `python3.7` +depending on your needs. First clone this repo (with git clone, or download the +zip), change into the directory, then: + + +`python -m venv env` +`pip install -r requirements.txt` +`python server.py` + + +Your server will (by default) be hosted on http://localhost:8000 + + +## Adding Pages + +To add a new page, all you need to do is add a new file (or a folder and a +group of files) somewhere under one of the folders in `site`. This folder in +particular is special since it contains the top-level folders which will be +used to navigate your site, but any folders beneath will be automatically +indexed. + +As an excercise, add a file to the `templates/site/thoughts/rants` folder +called `myrant.html` and put the following content: + +`<p>I don't like spam!</p>` + +The new page will be rendered with your navbar on top and footer on the bottom +when navigated to in the `rants folder` HTML files will by default be rendered +in page, and all other types of files (like txt) will be returned without +rendering. + +An important note, since these HTML files are being rendered by Flask, +*you can make full use of the Jinja templating language*! So in other words, +any template you've developed for flask is fully usable here--but remember it +will be rendered *inside* the `templates/base.html` template. If you need to +make tweaks to the navbar or footer, you'll want to edit that file instead. + + +## Customization (or things you'll want to change right now) + +To make customization easier, this program comes with a configuration file with +variables to tweak the display of your site call `siteconfig.py`. +For example by default this program makes the navbar out of the directories in +the `templates/site` directory, but you might want include other directories, +or even external sites. Examples of how to change these options are provided +in the comments on that file. Customization is also provided through the use of +specific files. + + +### Navbar customization + +Be default, the top navbar is populated by indexing and sorting the top-level +`templates/site/` directory. You can override this to include any directories +you want in any order, so long as they exist, but it's advised to still keep +them all in the `site` directory to avoid confusion. + + +### Index File Configuration + +This program uses a single master index file which is used when navigating to +any directory--instead of having to put in an 'index.html' in each folder, or +using the default apache/nginx/httpd auto-indexer. In it's place, you can +optionally put a `.description` file to provide a short description of what's +in the directory or a `.links` file + +The `.description` file should just be a text file with no formatting. If you +want to add formatting, you can edit the `templates\index.html` file around the +`{{ description }}` variable (for example, you could wrap it in <i></i> for +*italics* + +The `.links` file is a pseudo-csv file which should contain a comma separated +list containing a description and a relative or absolute URL to be linked. For +example this line: + +`About,/about` + +Produces (roughly) the following HTML on your index page: + +`<li><a href="/about">About</a></li>` + +You can of course link to external sites, but you must specify the protocol +(i.e. https://google.com, not google.com). Otherwise, it will be interpreted as +a relative path like `example.net/google.com`. + + +### Making Secret Directories and Files + +This program follows the Unix convention of placing a "." before directories +and files to make them hidden. Aside from the special files mentioned above, +this program will not index any file or directory with a "." prepended--and a +user will receive a 404 error if they attempt to do so. + + +### Mimetype Configuration + +Default mime types are primarily sourced from this page with some of my own +additions for common source code files (like .c or .py): + +https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types + +You can add your own by editing the 'mimetypes.csv' file in the following +format: + +`.file_extension,type/yourcoolmimetype` + +Otherwise, the default mime type is `application/octet-stream`, which (for most +browsers) triggers the browser to download the file + + +### License Configuration + +The default license type is the same as this program's: CC0. The HTML is from +Creative Commons, with some modifications I like to add. You can of course +replace the HTML with your own license (or none), by editing +`templates/site/license.html` + + +### Other tips + +There are a few special directories linked that are needed to +customize your site. First the `static` directory, which holds your static +files like CSS templates and images. Second the `raw` directory, which allows +the user to access files the `templates/site` as raw files instead of HTML. +You can disable it by deleting the code under `send_file_from_site` or +`send_file_from_static` in `server.py`. + + +## Deploying a server + +You should NOT run this server as in the quick start, but instead deploy it in +an appropriate container. Refer to https://flask.palletsprojects.com/en/2.0.x/deploying/ +for options, but an easy option I like is to use uswgi. On a Debian-like distro + + +`sudo apt install uwsgi` +`python -m venv env` +`uwsgi -s /tmp/yourapplication.sock --manage-script-name --mount /yourapplication=server:app` + +Then point your main http daemon (niginx, apache, httpd) to the socket you +made. See nginx as an example here, more in the same doc: + +https://uwsgi-docs.readthedocs.io/en/latest/Nginx.html diff --git a/mimetypes.csv b/mimetypes.csv new file mode 100644 index 0000000..aa3b678 --- /dev/null +++ b/mimetypes.csv @@ -0,0 +1,92 @@ +.aac,audio/aac +.abw,application/x-abiword +.arc,application/x-freearc +.avi,video/x-msvideo +.azw,application/vnd.amazon.ebook +.bin,application/octet-stream +.bmp,image/bmp +.bz,application/x-bzip +.bz2,application/x-bzip2 +.cda,application/x-cdf +.csh,application/x-csh +.css,text/css +.csv,text/csv +.doc,application/msword +.docx,application/vnd.openxmlformats-officedocument.wordprocessingml.document +.eot,application/vnd.ms-fontobject +.epub,application/epub+zip +.gz,application/gzip +.gif,image/gif +.html,text/html +.ico,image/vnd.microsoft.icon +.ics,text/calendar +.jar,application/java-archive +.jpeg,image/jpeg +.js,text/javascript +.json,application/json +.jsonld,application/ld+json +.midi,audio/midi audio/x-midi +.mjs,text/javascript +.mp3,audio/mpeg +.mp4,video/mp4 +.mpeg,video/mpeg +.mpkg,application/vnd.apple.installer+xml +.odp,application/vnd.oasis.opendocument.presentation +.ods,application/vnd.oasis.opendocument.spreadsheet +.odt,application/vnd.oasis.opendocument.text +.oga,audio/ogg +.ogv,video/ogg +.ogx,application/ogg +.opus,audio/opus +.otf,font/otf +.png,image/png +.pdf,application/pdf +.php,application/x-httpd-php +.ppt,application/vnd.ms-powerpoint +.pptx,application/vnd.openxmlformats-officedocument.presentationml.presentation +.rar,application/vnd.rar +.rtf,application/rtf +.sh,application/x-sh +.svg,image/svg+xml +.swf,application/x-shockwave-flash +.tar,application/x-tar +.tiff,image/tiff +.ts,video/mp2t +.ttf,font/ttf +.txt,text/plain +.vsd,application/vnd.visio +.wav,audio/wav +.weba,audio/webm +.webm,video/webm +.webp,image/webp +.woff,font/woff +.woff2,font/woff2 +.xhtml,application/xhtml+xml +.xls,application/vnd.ms-excel +.xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet +.xml,application/xml +.xul,application/vnd.mozilla.xul+xml +.zip,application/zip +.7z,application/x-7z-compressed +.c,text/plain +.py,text/plain +.php,text/plain +.java,text/plain +.sh,text/plain +.bash,text/plain +.fish,text/plain +.lua,text/plain +.cpp,text/plain +.asm,text/plain +.vbs,text/plain +.ksh,text/plain +.csh,text/plain +.zsh,text/plain +.h,text/plain +.hpp,text/plain +.awk,text/plain +.bat,text/plain +.pl,text/plain +.R,text/plain +.yml,text/plain +.yaml,text/plain
\ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..565424f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,9 @@ +click==8.0.1 +Flask==2.0.1 +itsdangerous==2.0.1 +Jinja2==3.0.1 +MarkupSafe==2.0.1 +pip==20.3.4 +pkg-resources==0.0.0 +setuptools==44.1.1 +Werkzeug==2.0.1 diff --git a/server.py b/server.py new file mode 100644 index 0000000..8614fe3 --- /dev/null +++ b/server.py @@ -0,0 +1,198 @@ +import os +from flask import Flask +from flask import request, send_from_directory, abort +from flask import render_template, render_template_string +from siteconfig import siteconfig + +app = Flask(__name__) + +# bit of a hack. +# Brackets don't play nicely with Jinja so instead of using .format, +# we just replace the special charcater $ +CONTENT_BLOCK = ( + "{% extends 'base.html' %}" + "{% block content %}" + "$" + "{% endblock %}" +) + + +def default_context(): + """ + default_context - returns the minimum info needed to render a template--the + domain name (for the home directory), and the top site directories which + make up the navbar + """ + return { + 'domain': app.config['DOMAIN'], + 'navbar': sorted(app.config['MAIN_SITE_DIRS']) + } + + +def index_dir(path): + """ + index_dir - Given a directory at `path`, list it's contents, + and sort each item as a file or a directory. + + return - a tuple with the values: + > a list of directories in `path`, + > a list of files in `path`, + > (if present), a list of external links to add to the index.html of the + directory + > (if present), a short description (string) of what the directory contains + + Lists are sorted alphabetically + """ + dirs = [] + files = [] + links = [] + description = "" + contents = os.listdir(path) + for obj in contents: + if os.path.isfile(path + '/' + obj): + if obj == siteconfig.LINKS_FILE: + with open(path + '/' + obj) as f: + links = f.readlines() + elif obj == siteconfig.DESC_FILE: + with open(path + '/' + obj) as f: + description = f.read() + elif obj.startswith('.'): + continue + else: + files.append(obj) + elif os.path.isdir(path + '/' + obj): + if obj.startswith('.'): + continue + else: + dirs.append(obj) + + return sorted(dirs), sorted(files), sorted(links), description + + +def is_hidden_path(path): + """ + Tests if last object specified in `path` is hidden. + Inspired by Unix. On Windows, diretories won't actually be "hidden" but + they are still not indexed by this program + """ + return path.split('/')[-1].startswith('.') + + +@app.route("/") +def home(): + """ + home - renders the template `home.html` as the main index file + + If you'd like to customize your home page, that is the file you want to + edit, though you can optionally change the title here if you wish + """ + context = default_context() + context.update( + { + 'title': app.config['HOME_TITLE'], + 'parent_dir': '/' + } + ) + return render_template("site/home.html", **context) + + +# from: https://pythonise.com/series/learning-flask/sending-files-with-flask +@app.route("/<path:path>") +def render_file(path): + """ + render_file - renders an HTML document for the given `path`. + + If `path` is an HTML file it is rendered within the base template, + otherwise, the raw file is returned. If `path` points to a directory, this + function instead creates an index for the directory containing it's files, + links, and other info. + """ + if is_hidden_path(path): + abort(404) + abs_path = "./templates/site/" + path + context = default_context() + context.update( + { + 'title': path.split('.')[0].upper(), + 'parent_dir': '/' + '/'.join(path.split('/')[:-1]) + } + ) + if os.path.isfile(abs_path): + if abs_path.endswith('.html'): + with open(abs_path) as f: + content = f.read() + print(path.split('/')[-2] + '/') + return render_template_string(CONTENT_BLOCK.replace('$', content), **context) + else: + # not an html file, so don't render it + return send_from_directory('templates/site/', path, + mimetype=siteconfig.MIMETYPES.get( + f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE + ) + ) + elif os.path.isdir(abs_path): + dirs, files, links, description = index_dir(abs_path) + context.update( + { + 'cur_dir': path.split('/')[-1] + '/', + 'dirs': dirs, + 'files': files, + 'links': links, + 'description': description + } + ) + return render_template("index.html", **context) + else: + context.update({'errors': "404 File not found"}) + return render_template("base.html", **context) + + +@app.route("/raw/<path:path>") +def send_file_from_site(path): + """ + send_file - instead of rendering a file within a template as with + `render_file`, send the raw file to the user + """ + return send_from_directory('template/site/', path, + mimetype=siteconfig.MIMETYPES.get( + f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE + ) + ) + + +@app.route("/static/<path:path>") +def send_file_from_static(path): + """ + send_file - instead of rendering a file within a template as with + `render_file`, send the raw file to the user + """ + return send_from_directory('static/', path, + mimetype=siteconfig.MIMETYPES.get( + f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE + ) + ) + + +def setup(): + """ + setup - sets up the app according to the settings specified (or not + speified) in `siteconfig` + """ + if siteconfig.SECRET_KEY: + app.config['SECRET_KEY'] = siteconfig.SECRET_KEY + else: + SECRET_KEY = os.urandom(32) + app.config['SECRET_KEY'] = SECRET_KEY + + if siteconfig.MAIN_SITE_DIRS: + app.config.update({'MAIN_SITE_DIRS': siteconfig.MAIN_SITE_DIRS}) + else: + app.config.update({'MAIN_SITE_DIRS': index_dir('./templates/site')[0]}) + + app.config.update({'DOMAIN': siteconfig.DOMAIN}) + app.config.update({'HOME_TITLE': siteconfig.HOME_TITLE}) + + +if __name__ == '__main__': + setup() + app.run(host=siteconfig.HOST, port=siteconfig.PORT) diff --git a/siteconfig.py b/siteconfig.py new file mode 100644 index 0000000..28c3cbd --- /dev/null +++ b/siteconfig.py @@ -0,0 +1,21 @@ +class siteconfig: + # REQUIRED SETTINGS# + DOMAIN = "example.net" # Your domain name, or site title + HOME_TITLE = "WELCOME" # "HELLO WORLD!" + LINKS_FILE = ".links" # ".lnx" + DESC_FILE = ".description" # ".desc`" + HOST = "127.0.0.1" # "192.168.1.1" "1.2.3.4" + PORT = 8000 # 8080, 8001, 8002 + DEFAULT_MIMETYPE = "application/octet-stream" # "text/plain" + + MIMETYPES = {} + with open('mimetypes.csv') as f: + for line in f.readlines(): + ext, mime = line.strip().split(',') + MIMETYPES.update({ext: mime}) + + # OPTIONAL SETTINGS # + # Remove 'None' to add custom values + MAIN_SITE_DIRS = None # ["dir1", "dir2", "dir3"] + # b"\xca\x05\x80\xa3|\xdbh@\xec<\xcd\x19\xf4\nRN:)\x13\x917|km\xb0'>'\x1d&G\xe8" + SECRET_KEY = None diff --git a/static/main.css b/static/main.css new file mode 100644 index 0000000..f8837d0 --- /dev/null +++ b/static/main.css @@ -0,0 +1,48 @@ +h1,h2,h3,h4 { + text-align: center; + margin: 0.5em auto; +} +body { + margin-left: auto; + margin-right: auto; + text-align: center; + font-family: Courier, Monospace; + word-wrap: normal; +} +/* some Stallman trickery for making mobile text bigger */ +@media screen and (max-device-width: 480px) { + body { + font-size: 200% + } + .loicense { + font-size: 75%; + } +} +.navbar { + text-align: center; + max-width: 1000px; + display: block; +} +.content { + text-align: justify; + max-width: 500px; + display: inline-block; +} +.license { + font-size: 65%; + text-align: center; + max-width: 350px; + display: block; +} +p { + margin-top: 0.75em; + margin-bottom: 0.75em; +} + +table { + border-spacing: 0 10px; +} +td { + text-align: left +} + diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..b2e8e74 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,28 @@ +<html> + <title>{{ domain }}/{{ title }}</title> + <head> + {% block css%} + <link rel="stylesheet" type="text/css" href="/static/main.css"> + {% endblock %} + </head> + <body><center> + <h1><a href="/">{{ domain }}</a></h1> + <!-- navbar --> + <div class="navbar"> + <b>|</b> <!-- This makes the bar symmetrical --> + {% for dir in navbar %} + <b> <a href="/{{ dir }}">{{ dir }}/</a> |</b> + {% endfor %} + </div> + <h2>{{ title }}</h2> + <div class="content"> + {% block content %} + {% endblock %} + <h3>{{ errors }}</h3> + {% if parent_dir != '/' %} + <h3><a href="{{ parent_dir }}">Go up to parent folder ({{ parent_dir }})</a></h3> + {% endif %} + </div> + <div class="license">{% include 'site/license.html' %}</div> + </center></body> +</html> diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..7e815e2 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,26 @@ +{% extends 'base.html' %} +{% block content %} + +<p>{{ description }}</p> + +{% if dirs %} +<h3>Topics</h3> +{% for d in dirs %} +<li><a href="{{ cur_dir }}{{ d }}">{{ d }}</a></li> +{% endfor %} +{% endif %} + +{% if files %} +<h3>File Listing</h3> +{% for f in files %} +<li><a href="{{ cur_dir }}{{ f }}">{{ f }}</a></li> +{% endfor %} +{% endif %} + +{% if links %} +{% for l in links %} +<li><a href="{{ l.split(',')[1] }}" target="_blank" rel="noopener noreferrer">{{l.split(',')[0]}}</a></li> +{% endfor %} +{% endif %} + +{% endblock %} diff --git a/templates/site/about/.description b/templates/site/about/.description new file mode 100644 index 0000000..eee24f1 --- /dev/null +++ b/templates/site/about/.description @@ -0,0 +1 @@ +Who runs this place anyway? diff --git a/templates/site/about/faq.html b/templates/site/about/faq.html new file mode 100644 index 0000000..0ad0c1a --- /dev/null +++ b/templates/site/about/faq.html @@ -0,0 +1,3 @@ +<h2>Frequently Anticipated Questions</h2> +<li><i>A question?</i></li> +<p>Yes, that is a question. Nice one</p> diff --git a/templates/site/about/whoami.html b/templates/site/about/whoami.html new file mode 100644 index 0000000..954d8db --- /dev/null +++ b/templates/site/about/whoami.html @@ -0,0 +1 @@ +<p>Person that does things</p> diff --git a/templates/site/files/.description b/templates/site/files/.description new file mode 100644 index 0000000..0dd21eb --- /dev/null +++ b/templates/site/files/.description @@ -0,0 +1 @@ +Everything else I don't have a place for diff --git a/templates/site/files/1.html b/templates/site/files/1.html new file mode 100644 index 0000000..6be9b63 --- /dev/null +++ b/templates/site/files/1.html @@ -0,0 +1,11 @@ +<p>This is some text</p> +<br> +<br> +<br> +<p> +This is a whole lot more text including very very very long lines, like wowza +this is long! Fortunately, css should wrap it nicely +</p> +<p> +Separate each paragraph! +</p> diff --git a/templates/site/fun/.description b/templates/site/fun/.description new file mode 100644 index 0000000..37c5a36 --- /dev/null +++ b/templates/site/fun/.description @@ -0,0 +1 @@ +The internet is srs business these days. Here's some fun stuff instead diff --git a/templates/site/fun/.links b/templates/site/fun/.links new file mode 100644 index 0000000..b3ea8fb --- /dev/null +++ b/templates/site/fun/.links @@ -0,0 +1 @@ +???,http://www.nyan.cat/ diff --git a/templates/site/home.html b/templates/site/home.html new file mode 100644 index 0000000..01d676e --- /dev/null +++ b/templates/site/home.html @@ -0,0 +1,4 @@ +{% extends 'base.html' %} +{% block content %} +<p>Home</p> +{% endblock %} diff --git a/templates/site/license.html b/templates/site/license.html new file mode 100644 index 0000000..172b43f --- /dev/null +++ b/templates/site/license.html @@ -0,0 +1,17 @@ +<p xmlns:dct="http://purl.org/dc/terms/" xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#"> + <a rel="license" + href="http://creativecommons.org/publicdomain/zero/1.0/"> + <img src="http://i.creativecommons.org/p/zero/1.0/88x31.png" style="border-style: none;" alt="CC0" /> + </a> + <br /> + To the extent possible under law, + <span property="dct:title">The author</span> + has waived all copyright and related or neighboring rights to + content on <span property="dct:title">{{ domain }}</span>. + All work may be cited without attribution at the reader's discretion. + However, if you do use the work here, or otherwise benefit from it, + the author would love to hear about it! + This work is published from: +<span property="vcard:Country" datatype="dct:ISO3166" content="US" about="{{ domain }}"> + United States</span>. +</p> diff --git a/templates/site/thoughts/.description b/templates/site/thoughts/.description new file mode 100644 index 0000000..f9004b2 --- /dev/null +++ b/templates/site/thoughts/.description @@ -0,0 +1,3 @@ +My thoughts on various topics that I may or may not be qualified to write about +When I can't figure out exactly what I'm thinking, it gets written somewhere +here. diff --git a/templates/site/thoughts/rants/dontread.txt b/templates/site/thoughts/rants/dontread.txt new file mode 100644 index 0000000..e90754c --- /dev/null +++ b/templates/site/thoughts/rants/dontread.txt @@ -0,0 +1,2 @@ +I hate people who try to beep me while I'm turning left... like what do you +want me to do? Run the kids over? diff --git a/templates/site/tutorials/.description b/templates/site/tutorials/.description new file mode 100644 index 0000000..ec41834 --- /dev/null +++ b/templates/site/tutorials/.description @@ -0,0 +1,3 @@ +There's a lot of tutorials out there that can show you something if you know +what to look for. Here's some tutorials that might help when you don't know +what to search. diff --git a/templates/site/tutorials/.links b/templates/site/tutorials/.links new file mode 100644 index 0000000..a0e2e99 --- /dev/null +++ b/templates/site/tutorials/.links @@ -0,0 +1 @@ +Cool site,https://fsf.org diff --git a/templates/site/tutorials/.secret/secretfile.txt b/templates/site/tutorials/.secret/secretfile.txt new file mode 100644 index 0000000..cae75f7 --- /dev/null +++ b/templates/site/tutorials/.secret/secretfile.txt @@ -0,0 +1 @@ +You shouldn't be able to see this file. It is a secret diff --git a/templates/site/tutorials/how-to-make-this-site.html b/templates/site/tutorials/how-to-make-this-site.html new file mode 100644 index 0000000..09dc877 --- /dev/null +++ b/templates/site/tutorials/how-to-make-this-site.html @@ -0,0 +1 @@ +<p>Carefully</p> diff --git a/templates/site/tutorials/linux/linuz1.html b/templates/site/tutorials/linux/linuz1.html new file mode 100644 index 0000000..c299a06 --- /dev/null +++ b/templates/site/tutorials/linux/linuz1.html @@ -0,0 +1 @@ +Linux is cool diff --git a/templates/site/tutorials/python/.description b/templates/site/tutorials/python/.description new file mode 100644 index 0000000..d69e5c3 --- /dev/null +++ b/templates/site/tutorials/python/.description @@ -0,0 +1 @@ +Some basics and thoughts on Python diff --git a/templates/site/tutorials/python/py-style.md b/templates/site/tutorials/python/py-style.md new file mode 100644 index 0000000..2a68fac --- /dev/null +++ b/templates/site/tutorials/python/py-style.md @@ -0,0 +1,93 @@ +# Coding Style Guide + +The purpose of this document is twofold: +1) To ensure that anyone who might like to make my code better understands + why I write python the way I do +2) to ensure *I* adhere to my own style because I'm terribly inconsistent + +Being terribly inconsistent, the guidelines are not set in stone and if +you have a good argument for doing things a particular, I don't really care. + +*BUT* first and foremost, *code must comply with PEP8 first*. This is easy +to automate. I like coala since it's friendly but there' plenty of advanced +linters out there. + +That aside, I have the following idiosyncracies: + +## 1) *Strings* are *double-quoted*. *Keys* and *chars* are *single-quoted*. + +This is really just because I like how C does it. And Cpython's C-based so +why not? + +Like so: + ``` + string = "This is a phrase" + word = "word" + cur_char = 'a' + newline = '\n' # note, two characters, but it's still ONE char in output + # keys are single-quoted to avoid confusion + dictionary = { 'key' : "1245dqw3w431", 'return': newline } + ``` + +The only exception is for strings with quotes in them (anything to avoid +escapes, really) + ``` + quoted_string = ( + '"You miss 100% of the shots you don't take - Wayne Gretsky" - Michael Scott' + ) + ``` +That brings me to my next point. + +## 2) Long strings belong in parentheses + +As in: + ``` + longboi = ( + "This is a really long string usefull when making help menus. Be\n" + "sure to leave s space at the end of each line, or add a new line\n" + "when needed.\n" + + "Try your best to keep formatting accurate like this." + ) + ``` + +## 3) Tabs are four spaces and spaces are *ALWAYS* prefered to tabs +Again, see PEP8. + +## 4) Always add spaces between arithmetic, but never for brackets +It's a pain to read: + ``` + 1/(2*sqrt(pi))*exp(x**2) + ``` +Do this + ``` + 1 / (2 * sqrt(pi)) * exp(x ** 2) + ``` +The same goes for logic operators + ``` + true & false ^ true + ``` + +## 5) EVERYTHING should be snake_case +This is python. Unless there's a compatibility thing (like a library's +code was written that way, or it matches an API variable), +snake_case is preferred. + ``` + + user_input = int(input()) # variable + MAX_INPUT = 1000 # constant + def judge_input(_input, _max): # function + if _max > _input: + print("Too big!") + + judge_input(user_input, MAX_INPUT + class Input_Judger: # a class + # etc etc + ``` +Example exception + ``` + # this doesn't actually work, but you get the idea + r = requests.get("www.debian.org") + pageSize = r.json()['pageSize'] # camel case ok + ``` + diff --git a/templates/site/tutorials/python/test.py b/templates/site/tutorials/python/test.py new file mode 100644 index 0000000..83b87a6 --- /dev/null +++ b/templates/site/tutorials/python/test.py @@ -0,0 +1,2 @@ +#!/usr/bin/python3 +print("hi") |