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") | 
