Use Ructe (#327)

All the template are now compiled at compile-time with the `ructe` crate.

I preferred to use it instead of askama because it allows more complex Rust expressions, where askama only supports a small subset of expressions and doesn't allow them everywhere (for instance, `{{ macro!() | filter }}` would result in a parsing error).

The diff is quite huge, but there is normally no changes in functionality.

Fixes #161 and unblocks #110 and #273
This commit is contained in:
Baptiste Gelez
2018-12-06 18:54:16 +01:00
committed by GitHub
parent 5f059c3e98
commit 70af57c6e1
121 changed files with 3132 additions and 3260 deletions
-41
View File
@@ -1,41 +0,0 @@
{% extends "base" %}
{% import "macros" as macros %}
{% block title %}
About {{ instance.name }}
{% endblock title %}
{% block content %}
<h1>{{ "About {{ instance_name }}" | _(instance_name=instance.name) }}</h1>
<section>
{{ instance.short_description_html | safe }}
</section>
<div class="banner">
<section class="stats">
<div>
<p>{{ "Home to" | _ }}</p>
<em>{{ n_users }}</em>
<p>{{ "people" | _ }}</p>
</div>
<div>
<p>{{ "Who wrote" | _ }}</p>
<em>{{ n_articles }}</em>
<p>{{ "articles" | _ }}</p>
</div>
<div>
<p>{{ "And connected to" | _ }}</p>
<em>{{ n_instances }}</em>
<p>{{ "other instances" | _ }}</p>
</div>
<div>
<p>{{ "Administred by" | _ }}</p>
{{ macros::avatar(user=admin) }}
<p><a href="/@/{{ admin.fqn }}">{{ admin.name }}</a><small>(@{{ admin.fqn }})</small></p>
</div>
</section>
<p>{{ "Runs Plume {{ version }}" | _(version=version) }}
</div>
<section>
{{ instance.long_description_html | safe }}
</section>
{% endblock content %}
+34
View File
@@ -0,0 +1,34 @@
@use templates::base;
@use template_utils::*;
@use plume_models::{instance::Instance, users::User};
@(ctx: BaseContext, instance: Instance, admin: User, n_users: usize, n_articles: usize, n_instances: i64)
@:base(ctx, i18n!(ctx.1, "About {0}"; instance.name.clone()).as_str(), {}, {}, {
<h1>@i18n!(ctx.1, "About {0}"; instance.name)</h1>
<section>
@Html(instance.short_description_html)
</section>
<div class="banner">
<section class="stats">
<div>
<p>@Html(i18n!(ctx.1, "Home to <em>{0}</em> users"; n_users))</p>
</div>
<div>
<p>@Html(i18n!(ctx.1, "Who wrote <em>{0}</em> articles"; n_articles))</p>
</div>
<div>
<p>@Html(i18n!(ctx.1, "And connected to <em>{0}</em> other instances"; n_instances))</p>
</div>
<div>
<p>@i18n!(ctx.1, "Administred by")</p>
@avatar(ctx.0, &admin, Size::Small, false, ctx.1)
<p><a href="/@@/@admin.get_fqn(ctx.0)">@admin.name(ctx.0)</a><small>@@@admin.get_fqn(ctx.0)</small></p>
</div>
</section>
<p>@i18n!(ctx.1, "Runs Plume {0}"; env!("CARGO_PKG_VERSION"))</p>
</div>
<section>
@Html(instance.long_description_html)
</section>
})
-35
View File
@@ -1,35 +0,0 @@
{% extends "base" %}
{% import "macros" as macros %}
{% block title %}
{{ "Administration of {{ instance.name }}" | _(instance=instance) }}
{% endblock title %}
{% block content %}
<h1>{{ "Administration" | _ }}</h1>
{{ macros::tabs(links=['/admin', '/admin/instances', '/admin/users'], titles=['Configuration', 'Instances', 'Users'], selected=1) }}
<form method="post">
{{ macros::input(name="name", label="Name", errors=errors, form=form, props='minlenght="1"', default=instance) }}
<label for="open_registrations">
{% if instance.open_registrations %}
<input type="checkbox" name="open_registrations" id="open_registrations" checked>
{% else %}
<input type="checkbox" name="open_registrations" id="open_registrations">
{% endif %}
{{ "Allow anyone to register" | _ }}
</label>
<label for="short_description">{{ "Short description" | _ }}<small>{{ "Markdown is supported" | _ }}</small></label>
<textarea id="short_description" name="short_description">{{ form.short_description | default(value=instance.short_description | safe) }}</textarea>
<label for="long_description">{{ "Long description" | _ }}<small>{{ "Markdown is supported" | _ }}</small></label>
<textarea id="long_description" name="long_description">{{ form.long_description | default(value=instance.long_description | safe) }}</textarea>
{{ macros::input(name="default_license", label="Default license", errors=errors, form=form, props='minlenght="1"', default=instance) }}
<input type="submit" value="{{ "Save settings" | _ }}"/>
</form>
{% endblock content %}
+39
View File
@@ -0,0 +1,39 @@
@use templates::base;
@use template_utils::*;
@use plume_models::instance::Instance;
@use routes::instance::InstanceSettingsForm;
@use validator::ValidationErrors;
@(ctx: BaseContext, instance: Instance, form: InstanceSettingsForm, errors: ValidationErrors)
@:base(ctx, i18n!(ctx.1, "Administration of {0}"; instance.name.clone()).as_str(), {}, {}, {
<h1>@i18n!(ctx.1, "Administration")</h1>
@tabs(&[
("/admin", i18n!(ctx.1, "Configuration"), true),
("/admin/instances", i18n!(ctx.1, "Instances"), false),
("/admin/users", i18n!(ctx.1, "Users"), false),
])
<form method="post">
@input!(ctx.1, name (text), "Name", form, errors.clone(), "props")
<label for="open_registrations">
@if instance.open_registrations {
<input type="checkbox" name="open_registrations" id="open_registrations" checked>
} else {
<input type="checkbox" name="open_registrations" id="open_registrations">
}
@i18n!(ctx.1, "Allow anyone to register")
<label for="short_description">@i18n!(ctx.1, "Short description")<small>@i18n!(ctx.1, "Markdown is supported")</small></label>
<textarea id="short_description" name="short_description">@Html(form.short_description)</textarea>
<label for="long_description">@i18n!(ctx.1, "Long description")<small>@i18n!(ctx.1, "Markdown is supported")</small></label>
<textarea id="long_description" name="long_description">@Html(form.long_description)</textarea>
@input!(ctx.1, default_license (text), "Default license", form, errors, "minlenght=\"1\"")
<input type="submit" value="@i18n!(ctx.1, "Save settings")"/>
</form>
})
-32
View File
@@ -1,32 +0,0 @@
<section class="spaced">
<div class="cards">
<div class="presentation card">
<h2>{{ "What is Plume?" | _ }}</h2>
<main>
<p>{{ "Plume is a decentralized blogging engine." | _ }}</p>
<p>{{ "Authors can manage various blogs from an unique website." | _ }}</p>
<p>{{ "Articles are also visible on other Plume websites, and you can interact with them directly from other platforms like Mastodon." | _ }}</p>
</main>
<a href="/users/new">{{ "Create your account" | _ }}</a>
</div>
<div class="presentation card">
<h2>{{ "About {{ instance_name }}" | _(instance_name=instance.name) }}</h2>
<main>
{{ instance.short_description_html | safe }}
<section class="stats">
<div>
<p>{{ "Home to" | _ }}</p>
<em>{{ n_users }}</em>
<p>{{ "people" | _ }}</p>
</div>
<div>
<p>{{ "Who wrote" | _ }}</p>
<em>{{ n_articles }}</em>
<p>{{ "articles" | _ }}</p>
</div>
</section>
</main>
<a href="/about">{{ "Read the detailed rules" | _ }}</a>
</div>
</div>
</section>
-23
View File
@@ -1,23 +0,0 @@
{% extends "base" %}
{% import "macros" as macros %}
{% block title %}
{{ "All the articles of the Fediverse" | _ }}
{% endblock title %}
{% block content %}
<h1>{{ "All the articles of the Fediverse" | _ }}</h1>
{% if account %}
{{ macros::tabs(links=['/', '/feed', '/federated', '/local'], titles=['Latest articles', 'Your feed', 'Federated feed', 'Local feed'], selected=3) }}
{% else %}
{{ macros::tabs(links=['/', '/federated', '/local'], titles=['Latest articles', 'Federated feed', 'Local feed'], selected=2) }}
{% endif %}
<div class="cards">
{% for article in articles %}
{{ macros::post_card(article=article) }}
{% endfor %}
</div>
{{ macros::paginate(page=page, total=n_pages) }}
{% endblock content %}
+31
View File
@@ -0,0 +1,31 @@
@use templates::{base, partials::post_card};
@use template_utils::*;
@use plume_models::posts::Post;
@(ctx: BaseContext, articles: Vec<Post>, page: i32, n_pages: i32)
@:base(ctx, "All the articles of the Fediverse", {}, {}, {
<h1>@i18n!(ctx.1, "All the articles of the Fediverse")</h1>
@if let Some(_) = ctx.2 {
@tabs(&[
("/", i18n!(ctx.1, "Latest articles"), false),
("/feed", i18n!(ctx.1, "Your feed"), false),
("/federated", i18n!(ctx.1, "Federated feed"), true),
("/local", i18n!(ctx.1, "Local feed"), false),
])
} else {
@tabs(&[
("/", i18n!(ctx.1, "Latest articles"), false),
("/federated", i18n!(ctx.1, "Federated feed"), true),
("/local", i18n!(ctx.1, "Local feed"), false),
])
}
<div class="cards">
@for article in articles {
@:post_card(ctx, article)
}
</div>
@paginate(ctx.1, page, n_pages)
})
-25
View File
@@ -1,25 +0,0 @@
{% extends "base" %}
{% import "macros" as macros %}
{% block title %}
{{ "Your feed" | _ }}
{% endblock title %}
{% block content %}
<h1>
{{ "Your feed" | _ }}
</h1>
{{ macros::tabs(links=['/', '/feed', '/federated', '/local'], titles=['Latest articles', 'Your feed', 'Federated feed', 'Local feed'], selected=2) }}
{% if articles | length > 0 %}
<div class="cards">
{% for article in articles %}
{{ macros::post_card(article=article) }}
{% endfor %}
</div>
{{ macros::paginate(page=page, total=n_pages) }}
{% else %}
<p class="center">{{ "Nothing to see here yet. Try to follow more people." | _ }}</p>
{% endif %}
{% endblock content %}
+27
View File
@@ -0,0 +1,27 @@
@use templates::{base, partials::post_card};
@use template_utils::*;
@use plume_models::posts::Post;
@(ctx: BaseContext, articles: Vec<Post>, page: i32, n_pages: i32)
@:base(ctx, "Your feed", {}, {}, {
<h1>@i18n!(ctx.1, "Your feed")</h1>
@tabs(&[
("/", i18n!(ctx.1, "Latest articles"), false),
("/feed", i18n!(ctx.1, "Your feed"), true),
("/federated", i18n!(ctx.1, "Federated feed"), false),
("/local", i18n!(ctx.1, "Local feed"), false),
])
@if !articles.is_empty() {
<div class="cards">
@for article in articles {
@:post_card(ctx, article)
}
</div>
} else {
<p class="center">@i18n!(ctx.1, "Nothing to see here yet. Try to follow more people.")</p>
}
@paginate(ctx.1, page, n_pages)
})
-25
View File
@@ -1,25 +0,0 @@
{% extends "base" %}
{% import "macros" as macros %}
{% block title %}
{{ instance.name }}
{% endblock title %}
{% block content %}
<h1>{{ "Welcome to {{ instance_name | escape }}" | _(instance_name=instance.name) }}</h1>
{% if account %}
{{ macros::tabs(links=['/', '/feed', '/federated', '/local'], titles=['Latest articles', 'Your feed', 'Federated feed', 'Local feed'], selected=1) }}
{{ macros::home_feed(title='Your feed', link='/feed', articles=user_feed) }}
{{ macros::home_feed(title='Federated feed', link='/federated', articles=federated) }}
{{ macros::home_feed(title='Local feed', link='/local', articles=local) }}
{% include "instance/description" %}
{% else %}
{{ macros::tabs(links=['/', '/federated', '/local'], titles=['Latest articles', 'Federated feed', 'Local feed'], selected=1) }}
{{ macros::home_feed(title='Federated feed', link='/federated', articles=federated) }}
{% include "instance/description" %}
{{ macros::home_feed(title='Local feed', link='/local', articles=local) }}
{% endif %}
{% endblock content %}
+34
View File
@@ -0,0 +1,34 @@
@use templates::{base, partials::*};
@use template_utils::*;
@use plume_models::instance::Instance;
@use plume_models::posts::Post;
@(ctx: BaseContext, instance: Instance, n_users: i32, n_articles: i32, local: Vec<Post>, federated: Vec<Post>, user_feed: Option<Vec<Post>>)
@:base(ctx, instance.name.clone().as_ref(), {}, {}, {
<h1>@i18n!(ctx.1, "Welcome on {}"; instance.name.as_str())</h1>
@if ctx.2.is_some() {
@tabs(&[
("/", i18n!(ctx.1, "Latest articles"), true),
("/feed", i18n!(ctx.1, "Your feed"), false),
("/federated", i18n!(ctx.1, "Federated feed"), false),
("/local", i18n!(ctx.1, "Local feed"), false),
])
@:home_feed(ctx, user_feed.unwrap_or_default(), "/feed", "Your feed")
@:home_feed(ctx, federated, "/federated", "Federated feed")
@:home_feed(ctx, local, "/local", "Local feed")
@:instance_description(ctx, instance, n_users, n_articles)
} else {
@tabs(&[
("/", i18n!(ctx.1, "Latest articles"), true),
("/federated", i18n!(ctx.1, "Federated feed"), false),
("/local", i18n!(ctx.1, "Local feed"), false),
])
@:home_feed(ctx, federated, "/federated", "Federated feed")
@:home_feed(ctx, local, "/local", "Local feed")
@:instance_description(ctx, instance, n_users, n_articles)
}
})
-33
View File
@@ -1,33 +0,0 @@
{% extends "base" %}
{% import "macros" as macros %}
{% block title %}
{{ "Administration of {{ instance.name }}" | _(instance=instance) }}
{% endblock title %}
{% block content %}
<h1>{{ "Instances" | _ }}</h1>
{{ macros::tabs(links=['/admin', '/admin/instances', '/admin/users'], titles=['Configuration', 'Instances', 'Users'], selected=2) }}
<div class="list">
{% for instance in instances %}
<div class="flex">
<p class="grow">
<a href="https://{{ instance.public_domain }}">{{ instance.name }}</a>
<small>{{ instance.public_domain }}</small>
</p>
{% if not instance.local %}
<form class="inline" method="post" action="/admin/instances/{{ instance.id }}/block">
{% if instance.blocked %}
<input type="submit" value="{{ 'Unblock' | _ }}">
{% else %}
<input type="submit" value="{{ 'Block' | _ }}">
{% endif %}
</form>
{% endif %}
</div>
{% endfor %}
</div>
{{ macros::paginate(page=page, total=n_pages) }}
{% endblock content %}
+32
View File
@@ -0,0 +1,32 @@
@use templates::base;
@use template_utils::*;
@use plume_models::instance::Instance;
@(ctx: BaseContext, instance: Instance, instances: Vec<Instance>, page: i32, n_pages: i32)
@:base(ctx, i18n!(ctx.1, "Administration of {0}"; instance.name.clone()).as_str(), {}, {}, {
<h1>@i18n!(ctx.1, "Instances")</h1>
@tabs(&[
("/admin", i18n!(ctx.1, "Configuration"), false),
("/admin/instances", i18n!(ctx.1, "Instances"), true),
("/admin/users", i18n!(ctx.1, "Users"), false),
])
<div class="list">
@for instance in instances {
<div class="flex">
<p class="grow">
<a href="https://@instance.public_domain">@instance.name</a>
<small>@instance.public_domain</small>
</p>
@if !instance.local {
<form class="inline" method="post" action="/admin/instances/@instance.id/block">
<input type="submit" value="@i18n!(ctx.1, if instance.blocked { "Unblock" } else { "Block"})">
</form>
}
</div>
}
</div>
@paginate(ctx.1, page, n_pages)
})
-23
View File
@@ -1,23 +0,0 @@
{% extends "base" %}
{% import "macros" as macros %}
{% block title %}
{{ "Articles from {{ instance.name }}" | _(instance=instance) }}
{% endblock title %}
{% block content %}
<h1>{{ "Articles from {{ instance.name }}" | _(instance=instance) }}</h1>
{% if account %}
{{ macros::tabs(links=['/', '/feed', '/federated', '/local'], titles=['Latest articles', 'Your feed', 'Federated feed', 'Local feed'], selected=4) }}
{% else %}
{{ macros::tabs(links=['/', '/federated', '/local'], titles=['Latest articles', 'Federated feed', 'Local feed'], selected=3) }}
{% endif %}
<div class="cards">
{% for article in articles %}
{{ macros::post_card(article=article) }}
{% endfor %}
</div>
{{ macros::paginate(page=page, total=n_pages) }}
{% endblock content %}
+32
View File
@@ -0,0 +1,32 @@
@use templates::{base, partials::post_card};
@use template_utils::*;
@use plume_models::posts::Post;
@use plume_models::instance::Instance;
@(ctx: BaseContext, instance: Instance, articles: Vec<Post>, page: i32, n_pages: i32)
@:base(ctx, i18n!(ctx.1, "Articles from {}"; instance.name.clone()).as_str(), {}, {}, {
<h1>@i18n!(ctx.1, "Articles from {}"; instance.name)</h1>
@if let Some(_) = ctx.2 {
@tabs(&[
("/", i18n!(ctx.1, "Latest articles"), false),
("/feed", i18n!(ctx.1, "Your feed"), false),
("/federated", i18n!(ctx.1, "Federated feed"), false),
("/local", i18n!(ctx.1, "Local feed"), true),
])
} else {
@tabs(&[
("/", i18n!(ctx.1, "Latest articles"), false),
("/federated", i18n!(ctx.1, "Federated feed"), false),
("/local", i18n!(ctx.1, "Local feed"), true),
])
}
<div class="cards">
@for article in articles {
@:post_card(ctx, article)
}
</div>
@paginate(ctx.1, page, n_pages)
})
-30
View File
@@ -1,30 +0,0 @@
{% extends "base" %}
{% import "macros" as macros %}
{% block title %}
{{ "Users" | _ }}
{% endblock title %}
{% block content %}
<h1>{{ "Users" | _ }}</h1>
{{ macros::tabs(links=['/admin', '/admin/instances', '/admin/users'], titles=['Configuration', 'Instances', 'Users'], selected=3) }}
<div class="list">
{% for user in users %}
<div class="flex">
{{ macros::avatar(user=user) }}
<p class="grow">
<a href="/@/{{ user.fqn }}">{{ user.name }}</a>
<small>@{{ user.username }}</small>
</p>
{% if not user.is_admin %}
<form class="inline" method="post" href="/admin/users/{{ user.id }}/ban">
<input type="submit" value="{{ 'Ban' | _ }}">
</form>
{% endif %}
</div>
{% endfor %}
</div>
{{ macros::paginate(page=page, total=n_pages) }}
{% endblock content %}
+33
View File
@@ -0,0 +1,33 @@
@use templates::base;
@use template_utils::*;
@use plume_models::users::User;
@(ctx: BaseContext, users: Vec<User>, page: i32, n_pages: i32)
@:base(ctx, "Users", {}, {}, {
<h1>@i18n!(ctx.1, "Users")</h1>
@tabs(&[
("/admin", i18n!(ctx.1, "Configuration"), false),
("/admin/instances", i18n!(ctx.1, "Instances"), false),
("/admin/users", i18n!(ctx.1, "Users"), true),
])
<div class="list">
@for user in users {
<div class="flex">
@avatar(ctx.0, &user, Size::Small, false, ctx.1)
<p class="grow">
<a href="/@@/@user.get_fqn(ctx.0)">@user.name(ctx.0)</a>
<small>@format!("@{}", user.username)</small>
</p>
@if !user.is_admin {
<form class="inline" method="post" action="/admin/users/@user.id/ban">
<input type="submit" value="@i18n!(ctx.1, "Ban")">
</form>
}
</div>
}
</div>
@paginate(ctx.1, page, n_pages)
})