Added docs.

This commit is contained in:
retoor 2025-01-24 23:41:54 +01:00
parent 9b93403a93
commit b56371994f
7 changed files with 356 additions and 0 deletions

Binary file not shown.

33
src/snek/docs/app.py Normal file
View File

@ -0,0 +1,33 @@
from app.app import Application as BaseApplication
import pathlib
from aiohttp import web
from snek.system.markdown import MarkdownExtension
from snek.system.markdown import render_markdown
class Application(BaseApplication):
def __init__(self, path=None, *args,**kwargs):
self.path = pathlib.Path(path)
template_path = self.path
super().__init__(template_path=template_path ,*args, **kwargs)
self.jinja2_env.add_extension(MarkdownExtension)
self.router.add_get("/{tail:.*}",self.handle_document)
async def handle_document(self, request):
relative_path = request.match_info['tail'].strip("/")
if relative_path == '':
relative_path = 'index.html'
document_path = self.path.joinpath(relative_path)
if not document_path.exists():
return web.Response(status=404,body=b'Resource is not found on this server.',content_type="text/plain")
if document_path.is_dir():
document_path = document_path.joinpath("index.html")
if not document_path.exists():
return web.Response(status=404,body=b'Resource is not found on this server.',content_type="text/plain")
response = await self.render_template(str(document_path.relative_to(self.path)),request)
return response

View File

@ -0,0 +1,61 @@
{% extends "docs/base.html" %}
{% block main %}
{% markdown %}
# API Documentation
Currently only some details about the internal API are available.
## How to create a user
```python
# Save user to the table named 'user'
# Password gets sha256 encrypted with default a salt string
# of the snek.system.security module.
new_user_object = await app.service.user.register(
username="retoor",
password="retoorded"
)
```
## Encrypt string
```python
from snek.system import security
# Support for both utf and bytes.
var1 = security.encrypt("data")
var2 = security.encrypt(b"data")
# Is correct:
assert(var1 == var2)
```
## How to create a basic HTML / Markdown view
```python
from snek.system.view import BaseView
class IndexView(BaseView):
async def get(self):
# The render function supports markdown.
# It will render with syntax highlighting.
# Just use the .md file extension in the file name.
return await self.render("index.html")
```
## How to create a FormView
```python
from snek.system.view import BaseFormView
from snek.form.register import RegisterForm
class RegisterFormView(BaseFormView):
form = RegisterForm
```
## How to register a class view
```python
app.routes.add_view("/your-page.html", YourViewClass)
```
{% endmarkdown %}
{% endblock %}

View File

@ -0,0 +1,116 @@
<html>
<head>
<style>{{ highlight_styles }}</style>
<style>
* {
box-sizing: border-box;
}
.dialog {
background-color: #0f0f0f;
border-radius: 10px;
padding: 30px;
width: 800px;
margin: 30px;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
}
@media screen and (max-width: 500px) {
.center {
width: 100%;
left: 0px;
}
.dialog {
width: 100%;
left: 0px;
}
}
h1 {
font-size: 2em;
color: #f05a28;
margin-bottom: 20px;
}
h2 {
font-size: 1.4em;
color: #f05a28;
margin-bottom: 20px;
}
html,body,main {
font-family: Arial, sans-serif;
background-color: #1a1a1a;
color: #e6e6e6;
line-height: 1.5;
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
width: 100%;
}
article {
max-width: 100%;
width: 60%;
background-color: #0f0f0f;
padding: 30px;
min-height: 100vh;
word-break: break-all;
}
footer {
position: fixed;
width: 60%;
text-align: center;
bottom: 0;
left: 20%;
background-color: #000;
}
a {
color: #f05a28;
display: block;
margin-top: 15px;
font-size: 0.9em;
transition: color 0.3s;
}
header {
text-align: left;
width: 60%;
padding: 30px;
}
header a {
display: inline;
}
div {
text-align: left;
}
</style>
</head>
<body>
<main>
<header>
<a href="/">Snek</a>
<a href="/docs/docs">Docs</a>
</header>
<article>
{% block main %}
{% endblock %}
</article>
</main>
<footer>
{% markdown %}
[Respository](https://github.com/retoor/snek)
{% endmarkdown %}
</footer>
</body>
</html>

View File

@ -0,0 +1,17 @@
{% extends "docs/base.html" %}
{% block main %}
{% markdown %}
# Form API Javascript
## Dependencies
- generic-form.js
## Usage
It's just a HTML component that can be declared using an one liner. Buttons and title are specified server side.
```html
<generic-form url="/url-to-form-api"></generic-form>
```
{% endmarkdown %}
{% endblock %}

View File

@ -0,0 +1,92 @@
{% extends "docs/base.html" %}
{% block main %}
{% markdown %}
# Form API Javascript
## Dependencies
- `snek.system.form.Form`
- `snek.system.form.HTMLElement`
- `snek.system.form.FormInputElement`
- `snek.system.form.FormButtonElement`
## Usage
Here is an example with custom validation.
This example contains a field that checks if user already exists.
If invalid, it adds an error message which automatically invalidates the field.
Handling of the error messages will automatically done client side.
Forms are usaly located in `snek/form/[form name].py`.
```python
from snek.system.form import Form, HTMLElement,FormInputElement,FormButtonElement
class UsernameField(FormInputElement):
@property
async def errors(self):
result = await super().errors
if self.value and await self.app.services.user.count(username=self.value):
result.append("Username is not available.")
return result
class RegisterForm(Form):
title = HTMLElement(tag="h1", text="Register")
username = UsernameField(
name="username",
required=True,
min_length=2,
max_length=20,
regex=r"^[a-zA-Z0-9_]+$",
place_holder="Username",
type="text"
)
email = FormInputElement(
name="email",
required=False,
regex=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
place_holder="Email address",
type="email"
)
password = FormInputElement(
name="password",
required=True,
regex=r"^[a-zA-Z0-9_.+-]{6,}",
type="password",
place_holder="Password"
)
action = FormButtonElement(
name="action",
value="submit",
text="Register",
type="button"
)
```
## Set data
```python
# The input structure is in same format as output structure.
# Output structure is the result of await form.to_json()
data = dict(
username=dict(value="retoor"),
password=dict(value="retoorded")
)
form.set_user_data(data)
# Check if form is valid.
is_valid = await form.is_valid
# Convert form to a record (kv pairs) to be used for persistance.
# It does contain an filled uid (UUID4) field already to be used as primary key.
# Default fields:
# - uid (automatically generated, it's an UUID4 wich you can use as private key for database)
# - created_at (automatically generated, it's a string representation of UTC locale)
# - updated_at (execute await form.updated_at.update() before saving to set value)
key_value_values = await form.record
```
{% endmarkdown %}
{% endblock %}

View File

@ -0,0 +1,37 @@
{% extends "docs/base.html" %}
{% block main %}
{% markdown %}
# Snek
# Introduction
Snek is a high customizable chat application.
It is made because Rocket Chat didn't fit my needs anymore. It became bloathed and very heavy commercialized. You would get upsell messages on your locally hosted instance!
This documentation is under construction. Only the form API and the small introduction is a bit documented.
## Quick API notes
[Small introduction / cheatsheet](/docs/docs/api.html)
## View API
With the view classes of Snek you can render HTML and Markdown
- [API Python](#)
- [API Javascript](#)
## ORM API
Snek's database model is based on Python dataset library.
Snek uses a model/mapper architecture build on top of that library.
- [API](#)
## Form API
Snek does have his own components for creating and rendering forms.
All forms are made server side and client side is generated client side using a HTML component.
It's client side only one line to include a form that can validate and submit.
Validation is server side using REST. Page won't refresh.
[API Python](/docs/docs/form_api_python.html)
[API Javascript](/docs/docs/form_api_javascript.html)
{% endmarkdown %}
{% endblock %}