Skip to content
Snippets Groups Projects
Verified Commit befc2841 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Added basic HTML generator from schema

parent 4c8ba468
Branches
No related tags found
No related merge requests found
Pipeline #3949 passed
import click import click
import jinja2
import json import json
import jsonschema import jsonschema
import os
from . import models
from . import schemas from . import schemas
PROJECT_DIR = os.path.abspath(os.path.dirname(__file__))
@click.group() @click.group()
def cli(): def cli():
pass pass
...@@ -22,9 +29,51 @@ def validate(document, version): ...@@ -22,9 +29,51 @@ def validate(document, version):
except KeyError: except KeyError:
version = schemas.latest_schema_version version = schemas.latest_schema_version
schema = schemas.get(version) try:
schema = schemas.get(version)
except FileNotFoundError:
raise click.ClickException("{} is not a valid version".format(version))
jsonschema.validate(instance=payload, schema=schema) jsonschema.validate(instance=payload, schema=schema)
click.echo("Schema is valid!") click.echo("Document is valid!")
def get_template_context(document):
context = {"doc": document, "version": document["version"]}
context["sorted_means"] = [
models.Mean(**mean_data)
for mean_data in sorted(
document.get("means", []), key=lambda v: v["weight"], reverse=True
)
]
context["sorted_identities"] = [
models.Identity(**identity_data)
for identity_data in sorted(
document.get("identities", []), key=lambda v: v["weight"], reverse=True
)
]
return context
@cli.command()
@click.argument("document", type=click.File("r"))
@click.argument("output", type=click.File("w"))
@click.option("--template", "-t", type=click.File("r"))
def html(document, output, template):
content = document.read()
document = json.loads(content)
context = get_template_context(document)
if not template:
default_template = os.path.join(PROJECT_DIR, "templates", "profile.jinja2")
with open(default_template, "r") as f:
template_content = f.read()
else:
template_content = template.read()
t = jinja2.Template(
"{% autoescape true %}" + template_content + "{% endautoescape %}",
undefined=jinja2.StrictUndefined,
)
click.echo(t.render(**context))
if __name__ == "__main__": if __name__ == "__main__":
......
class Identity(object):
def __init__(self, provider, id, weight, name=None, summary=None, url=None):
self.provider = provider
self.id = id
self.summary = summary
self.weight = weight
self.name = name
self.url = url
def get_full_name(self):
if self.name:
return self.name
return "{} on {}".format(self.id, self.provider)
class Mean(object):
def __init__(self, provider, id, weight, name=None, summary=None, url=None):
self.provider = provider
self.id = id
self.summary = summary
self.weight = weight
self.name = name
self.url = url
def get_full_name(self):
if self.name:
return self.name
return "{} on {}".format(self.id, self.provider)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>{{ doc['title'] }}</title>
{%- if "summary" in doc %}
<meta name="description" content="{{ doc['summary'] }}" />
{% endif %}
</head>
<body>
<header>
<h1>{{ doc['title'] }}</h1>
{%- if "summary" in doc %}
<p>{{ doc['summary'] }}</p>
{% endif %}
</header>
<main>
{%- if sorted_identities|length > 0 %}
<section class="identity">
<h2>My other identities</h2>
{% for identity in sorted_identities %}
<article>
<h3>
{%- if identity.url %}
<a href="{{ identity.url }}" rel="me noopener">
{{ identity.get_full_name() }}
</a>
{%- else %}
{{ identity.get_full_name() }}
{%- endif %}
</h3>
{%- if identity.summary %}
<p>{{ identity.summary }}</p>
{%- endif %}
</article>
{% endfor %}
</section>
{%- endif %}
{%- if sorted_means|length > 0 %}
<section>
<h2>Support me!</h2>
{% for mean in sorted_means %}
<article class="mean">
<h3>
{%- if mean.url %}
<a href="{{ mean.url }}" rel="me noopener">
{{ mean.get_full_name() }}
</a>
{%- else %}
{{ mean.get_full_name() }}
{%- endif %}
</h3>
{%- if mean.summary %}
<p>{{ mean.summary }}</p>
{%- endif %}
</article>
{% endfor %}
</section>
{%- endif %}
</main>
</body>
</html>
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
"version": "0.1", "version": "0.1",
"id": "https://retribute.me/@Alice.json", "id": "https://retribute.me/@Alice.json",
"url": "https://retribute.me/@Alice.html", "url": "https://retribute.me/@Alice.html",
"title": "Caring is loving",
"summary": "My name is Alice, I produce Creative Commons electro music. I need your support to continue working on my audio pieces!", "summary": "My name is Alice, I produce Creative Commons electro music. I need your support to continue working on my audio pieces!",
"identities": [ "identities": [
{ {
...@@ -19,6 +20,7 @@ ...@@ -19,6 +20,7 @@
{ {
"provider": "custom", "provider": "custom",
"id": "personal-website", "id": "personal-website",
"name": "My personal website",
"url": "https://alice.me", "url": "https://alice.me",
"weight": 3 "weight": 3
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
"additionalProperties": false, "additionalProperties": false,
"required": [ "required": [
"id", "id",
"title",
"version", "version",
"means" "means"
], ],
...@@ -30,26 +31,38 @@ ...@@ -30,26 +31,38 @@
"https://retribute.me/@Alice.html" "https://retribute.me/@Alice.html"
] ]
}, },
"title": {
"description": "A human readable title to go with the profile",
"type": "string"
},
"summary": { "summary": {
"description": "A human readable exaplanation to go with the profile", "description": "A human readable explanation to go with the profile",
"type": "string" "type": "string"
}, },
"means": { "means": {
"description": "A list of retribution means", "description": "A list of retribution means",
"type": "array", "type": "array",
"items": { "$ref": "#/definitions/mean" } "items": {
"$ref": "#/definitions/mean"
}
}, },
"identities": { "identities": {
"description": "A list of identities lined to the profile", "description": "A list of identities lined to the profile",
"type": "array", "type": "array",
"items": { "$ref": "#/definitions/identity" } "items": {
"$ref": "#/definitions/identity"
}
} }
}, },
"definitions": { "definitions": {
"identity": { "identity": {
"description": "A single retribution mean. The provider and id must form a unique combination", "description": "A single retribution mean. The provider and id must form a unique combination",
"type": "object", "type": "object",
"required": ["provider", "id", "weight"], "required": [
"provider",
"id",
"weight"
],
"minItems": 0, "minItems": 0,
"properties": { "properties": {
"provider": { "provider": {
...@@ -89,7 +102,11 @@ ...@@ -89,7 +102,11 @@
"mean": { "mean": {
"description": "A single retribution mean. The provider and id must form a unique combination", "description": "A single retribution mean. The provider and id must form a unique combination",
"type": "object", "type": "object",
"required": ["provider", "id", "weight"], "required": [
"provider",
"id",
"weight"
],
"minItems": 1, "minItems": 1,
"properties": { "properties": {
"provider": { "provider": {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment