♻️Extrae los componentes base de PageTop

This commit is contained in:
Manuel Cillero 2023-05-14 10:10:43 +02:00
parent efdd72f4ad
commit f0a32d7467
45 changed files with 82 additions and 4677 deletions

View file

@ -1,6 +1,6 @@
<div align="center">
<img src="https://raw.githubusercontent.com/manuelcillero/pagetop/main/pagetop/static/pagetop-banner.png" />
<img src="https://raw.githubusercontent.com/manuelcillero/pagetop/main/banner/pagetop.png" />
<h1>PageTop</h1>

View file

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Before After
Before After

View file

@ -71,9 +71,6 @@ mysql = ["database", "sea-orm/sqlx-mysql"]
postgres = ["database", "sea-orm/sqlx-postgres"]
sqlite = ["database", "sea-orm/sqlx-sqlite"]
[build-dependencies]
pagetop-build = { path = "../pagetop-build", version = "0.0" }
[dev-dependencies]
tokio = { version = "1.28.1", features = ["macros", "rt-multi-thread"] }

View file

@ -24,4 +24,4 @@ serde = { version = "1.0", features = ["derive"] }
[build-dependencies]
# Para incluir archivos y recursos binarios en el ejecutable (opcional):
pagetop = { path = "../pagetop" }
pagetop-build = { path = "../pagetop-build", version = "0.0" }

View file

@ -21,4 +21,4 @@ serde = { version = "1.0", features = ["derive"] }
[build-dependencies]
# Para incluir archivos y recursos binarios en la propia librería (opcional):
pagetop = { path = "../pagetop" }
pagetop-build = { path = "../pagetop-build", version = "0.0" }

View file

@ -1,3 +0,0 @@
fn main() -> std::io::Result<()> {
pagetop_build::bundle_resources("./static/theme", "theme", None)
}

View file

@ -2,7 +2,7 @@
name = "PageTop Application"
description = "Developed with the amazing PageTop framework."
# Tema predeterminado.
theme = "Saturn"
theme = "Basic"
# Idioma (localización) predeterminado.
language = "en-US"
# Dirección predeterminada para el texto: "ltr", "rtl" o "auto".
@ -21,17 +21,17 @@ db_user = ""
db_pass = ""
# Servidor (para mysql/postgres).
db_host = "localhost"
# Puerto (para mysql/postgres), siendo 0 el puerto predeterminado (3306 ó 5432).
# Puerto, normalmente 3306 (para mysql) ó 5432 (para postgres).
db_port = 0
# Número máximo de conexiones habilitadas.
max_pool_size = 5
[dev]
# Los archivos estáticos requeridos por temas y componentes incluidos en PageTop
# se integran de manera predeterminada en el binario ejecutable. Sin embargo, es
# útil servir estos archivos desde su propio directorio durante el desarrollo ya
# que no requiere compilar cada vez que se modifican. En este caso, normalmente,
# basta con indicar el directorio "../pagetop/static".
# Los archivos estáticos requeridos por la aplicación se integran de manera
# predeterminada en el binario ejecutable. Sin embargo, durante el desarrollo
# puede resultar útil servir estos archivos desde su propio directorio para
# evitar compilar cada vez que se modifican. En este caso, normalmente, basta
# con indicar la ruta "../ruta/static".
static_files = ""
[log]

View file

@ -1,2 +0,0 @@
pub mod component;
pub mod module;

View file

@ -1,22 +0,0 @@
mod container;
pub use container::{Container, ContainerType, COMPONENT_CONTAINER};
pub mod grid;
mod html;
pub use html::{Html, COMPONENT_HTML};
mod icon;
pub use icon::{Icon, COMPONENT_ICON};
mod heading;
pub use heading::{Heading, HeadingDisplay, HeadingType, COMPONENT_HEADING};
mod paragraph;
pub use paragraph::{Paragraph, ParagraphDisplay, COMPONENT_PARAGRAPH};
mod anchor;
pub use anchor::{Anchor, AnchorIcon, AnchorTarget, AnchorType, COMPONENT_ANCHOR};
mod block;
pub use block::{Block, COMPONENT_BLOCK};
mod image;
pub use image::{Image, COMPONENT_IMAGE};
pub mod form_element;
pub use form_element::{Form, FormMethod, COMPONENT_FORM};

View file

@ -1,220 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_ANCHOR);
#[derive(Default)]
pub enum AnchorType {
#[default]
Link,
Button,
Location,
}
#[derive(Default)]
pub enum AnchorTarget {
#[default]
Default,
Blank,
Parent,
Top,
Context(String),
}
pub type AnchorIcon = ComponentsBundle;
#[rustfmt::skip]
#[derive(Default)]
pub struct Anchor {
weight : isize,
renderable : Renderable,
id : IdentifierValue,
classes : Classes,
anchor_type: AnchorType,
href : AttributeValue,
html : HtmlMarkup,
left_icon : AnchorIcon,
right_icon : AnchorIcon,
target : AnchorTarget,
template : String,
}
impl ComponentTrait for Anchor {
fn new() -> Self {
Anchor::default()
}
fn handle(&self) -> Handle {
COMPONENT_ANCHOR
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
#[rustfmt::skip]
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
let target = match &self.target() {
AnchorTarget::Blank => Some("_blank"),
AnchorTarget::Parent => Some("_parent"),
AnchorTarget::Top => Some("_top"),
AnchorTarget::Context(name) => Some(name.as_str()),
_ => None,
};
html! {
a
id=[self.id().get()]
class=[self.classes().get()]
href=[self.href().get()]
target=[target]
{
(self.left_icon().render(rcx))
span { (*self.html()) }
(self.right_icon().render(rcx))
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Anchor {
pub fn link(href: &str, html: Markup) -> Self {
Anchor::new().with_href(href).with_html(html)
}
pub fn button(href: &str, html: Markup) -> Self {
Anchor::new()
.with_type(AnchorType::Button)
.with_href(href)
.with_html(html)
}
pub fn location(id: &str) -> Self {
Anchor::new().with_type(AnchorType::Location).with_id(id)
}
// Anchor BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_type(&mut self, anchor_type: AnchorType) -> &mut Self {
self.anchor_type = anchor_type;
self.classes.alter_value(
ClassesOp::SetDefault,
match self.anchor_type {
AnchorType::Button => "btn btn-primary",
_ => "",
},
);
self
}
#[fn_builder]
pub fn alter_href(&mut self, href: &str) -> &mut Self {
self.href.alter_value(href);
self
}
#[fn_builder]
pub fn alter_html(&mut self, html: Markup) -> &mut Self {
self.html.markup = html;
self
}
#[fn_builder]
pub fn alter_left_icon(&mut self, icon: Icon) -> &mut Self {
self.left_icon.clear();
self.left_icon.add(icon);
self
}
#[fn_builder]
pub fn alter_right_icon(&mut self, icon: Icon) -> &mut Self {
self.right_icon.clear();
self.right_icon.add(icon);
self
}
#[fn_builder]
pub fn alter_target(&mut self, target: AnchorTarget) -> &mut Self {
self.target = target;
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Anchor GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn anchor_type(&self) -> &AnchorType {
&self.anchor_type
}
pub fn href(&self) -> &AttributeValue {
&self.href
}
pub fn html(&self) -> &Markup {
&self.html.markup
}
pub fn left_icon(&self) -> &AnchorIcon {
&self.left_icon
}
pub fn right_icon(&self) -> &AnchorIcon {
&self.right_icon
}
pub fn target(&self) -> &AnchorTarget {
&self.target
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,129 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_BLOCK);
hook_before_render_component!(HOOK_BEFORE_RENDER_BLOCK, Block);
#[rustfmt::skip]
#[derive(Default)]
pub struct Block {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
title : AttributeValue,
components: ComponentsBundle,
template : String,
}
impl ComponentTrait for Block {
fn new() -> Self {
Block::default().with_classes(ClassesOp::SetDefault, "block")
}
fn handle(&self) -> Handle {
COMPONENT_BLOCK
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
before_render_inline(self, rcx);
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
let id = rcx.required_id::<Block>(self.id());
html! {
div id=(id) class=[self.classes().get()] {
@if let Some(title) = self.title().get() {
h2 class="block-title" { (title) }
}
div class="block-body" {
(self.components().render(rcx))
}
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Block {
// Block BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_title(&mut self, title: &str) -> &mut Self {
self.title.alter_value(title);
self
}
#[fn_builder]
pub fn alter_component(&mut self, component: impl ComponentTrait) -> &mut Self {
self.components.add(component);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Block GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn title(&self) -> &AttributeValue {
&self.title
}
pub fn components(&self) -> &ComponentsBundle {
&self.components
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,194 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_CONTAINER);
hook_before_render_component!(HOOK_BEFORE_RENDER_CONTAINER, Container);
#[derive(Default)]
pub enum ContainerType {
#[default]
Wrapper,
Header,
Footer,
Main,
Section,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Container {
weight : isize,
renderable : Renderable,
id : IdentifierValue,
classes : Classes,
inner_classes : Classes,
container_type: ContainerType,
components : ComponentsBundle,
template : String,
}
impl ComponentTrait for Container {
fn new() -> Self {
Container::default()
.with_classes(ClassesOp::SetDefault, "container")
.with_inner_classes(ClassesOp::SetDefault, "container")
}
fn handle(&self) -> Handle {
COMPONENT_CONTAINER
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
before_render_inline(self, rcx);
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
match self.container_type() {
ContainerType::Header => html! {
header id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(rcx))
}
}
},
ContainerType::Footer => html! {
footer id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(rcx))
}
}
},
ContainerType::Main => html! {
main id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(rcx))
}
}
},
ContainerType::Section => html! {
section id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(rcx))
}
}
},
_ => html! {
div id=[self.id().get()] class=[self.classes().get()] {
(self.components().render(rcx))
}
},
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Container {
pub fn header() -> Self {
let mut c = Container::new().with_classes(ClassesOp::SetDefault, "header");
c.container_type = ContainerType::Header;
c
}
pub fn footer() -> Self {
let mut c = Container::new().with_classes(ClassesOp::SetDefault, "footer");
c.container_type = ContainerType::Footer;
c
}
pub fn main() -> Self {
let mut c = Container::new().with_classes(ClassesOp::SetDefault, "main");
c.container_type = ContainerType::Main;
c
}
pub fn section() -> Self {
let mut c = Container::new().with_classes(ClassesOp::SetDefault, "section");
c.container_type = ContainerType::Section;
c
}
// Container BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_inner_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.inner_classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_component(&mut self, component: impl ComponentTrait) -> &mut Self {
self.components.add(component);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Container GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn inner_classes(&self) -> &Classes {
&self.inner_classes
}
pub fn container_type(&self) -> &ContainerType {
&self.container_type
}
pub fn components(&self) -> &ComponentsBundle {
&self.components
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,11 +0,0 @@
mod form;
pub use form::{Form, FormMethod, COMPONENT_FORM};
mod input;
pub use input::{Input, InputType, COMPONENT_INPUT};
mod hidden;
pub use hidden::{Hidden, COMPONENT_HIDDEN};
mod date;
pub use date::{Date, COMPONENT_DATE};
mod button;
pub use button::{Button, ButtonType, COMPONENT_BUTTON};

View file

@ -1,183 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_BUTTON);
#[derive(Default)]
pub enum ButtonType {
#[default]
Button,
Submit,
Reset,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Button {
weight : isize,
renderable : Renderable,
classes : Classes,
button_type: ButtonType,
name : AttributeValue,
value : AttributeValue,
autofocus : AttributeValue,
disabled : AttributeValue,
template : String,
}
impl ComponentTrait for Button {
fn new() -> Self {
Button::default()
.with_classes(ClassesOp::SetDefault, "btn btn-primary")
.with_classes(ClassesOp::AddFirst, "form-button")
}
fn handle(&self) -> Handle {
COMPONENT_BUTTON
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
let button_type = match self.button_type() {
ButtonType::Button => "button",
ButtonType::Submit => "submit",
ButtonType::Reset => "reset",
};
let id = self.name().get().map(|name| concat_string!("edit-", name));
html! {
button
type=(button_type)
id=[id]
class=[self.classes().get()]
name=[self.name().get()]
value=[self.value().get()]
autofocus=[self.autofocus().get()]
disabled=[self.disabled().get()]
{
@if let Some(value) = self.value().get() { (value) }
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Button {
pub fn with(value: &str) -> Self {
Button::new().with_value(value)
}
pub fn submit(value: &str) -> Self {
let mut button = Button::new()
.with_classes(ClassesOp::Replace("form-button"), "form-submit")
.with_value(value);
button.button_type = ButtonType::Submit;
button
}
pub fn reset(value: &str) -> Self {
let mut button = Button::new()
.with_classes(ClassesOp::Replace("form-button"), "form-reset")
.with_value(value);
button.button_type = ButtonType::Reset;
button
}
// Button BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.alter_value(name);
self
}
#[fn_builder]
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.alter_value(value);
self
}
#[fn_builder]
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
self.autofocus.alter_value(match toggle {
true => "autofocus",
false => "",
});
self
}
#[fn_builder]
pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
self.disabled.alter_value(match toggle {
true => "disabled",
false => "",
});
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Button GETTERS.
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn button_type(&self) -> &ButtonType {
&self.button_type
}
pub fn name(&self) -> &AttributeValue {
&self.name
}
pub fn value(&self) -> &AttributeValue {
&self.value
}
pub fn autofocus(&self) -> &AttributeValue {
&self.autofocus
}
pub fn disabled(&self) -> &AttributeValue {
&self.disabled
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,236 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_DATE);
#[rustfmt::skip]
#[derive(Default)]
pub struct Date {
weight : isize,
renderable : Renderable,
classes : Classes,
name : AttributeValue,
value : AttributeValue,
label : AttributeValue,
placeholder : AttributeValue,
autofocus : AttributeValue,
autocomplete: AttributeValue,
disabled : AttributeValue,
readonly : AttributeValue,
required : AttributeValue,
help_text : AttributeValue,
template : String,
}
impl ComponentTrait for Date {
fn new() -> Self {
Date::default()
.with_classes(ClassesOp::SetDefault, "form-item")
.with_classes(ClassesOp::AddFirst, "form-type-date")
}
fn handle(&self) -> Handle {
COMPONENT_DATE
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
let id = self.name().get().map(|name| concat_string!("edit-", name));
html! {
div class=[self.classes().get()] {
@if let Some(label) = self.label().get() {
label class="form-label" for=[&id] {
(label) " "
@if self.required().get().is_some() {
span
class="form-required"
title="Este campo es obligatorio." { "*" } " ";
}
}
}
input
type="date"
id=[id]
class="form-control"
name=[self.name().get()]
value=[self.value().get()]
placeholder=[self.placeholder().get()]
autofocus=[self.autofocus().get()]
autocomplete=[self.autocomplete().get()]
readonly=[self.readonly().get()]
required=[self.required().get()]
disabled=[self.disabled().get()];
@if let Some(help_text) = self.help_text().get() {
div class="form-text" { (help_text) }
}
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Date {
// Date BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.alter_value(name);
self
}
#[fn_builder]
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.alter_value(value);
self
}
#[fn_builder]
pub fn alter_label(&mut self, label: &str) -> &mut Self {
self.label.alter_value(label);
self
}
#[fn_builder]
pub fn alter_placeholder(&mut self, placeholder: &str) -> &mut Self {
self.placeholder.alter_value(placeholder);
self
}
#[fn_builder]
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
self.autofocus.alter_value(match toggle {
true => "autofocus",
false => "",
});
self
}
#[fn_builder]
pub fn alter_autocomplete(&mut self, toggle: bool) -> &mut Self {
self.autocomplete.alter_value(match toggle {
true => "",
false => "off",
});
self
}
#[fn_builder]
pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
self.disabled.alter_value(match toggle {
true => "disabled",
false => "",
});
self
}
#[fn_builder]
pub fn alter_readonly(&mut self, toggle: bool) -> &mut Self {
self.readonly.alter_value(match toggle {
true => "readonly",
false => "",
});
self
}
#[fn_builder]
pub fn alter_required(&mut self, toggle: bool) -> &mut Self {
self.required.alter_value(match toggle {
true => "required",
false => "",
});
self
}
#[fn_builder]
pub fn alter_help_text(&mut self, help_text: &str) -> &mut Self {
self.help_text.alter_value(help_text);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Date GETTERS.
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn name(&self) -> &AttributeValue {
&self.name
}
pub fn value(&self) -> &AttributeValue {
&self.value
}
pub fn label(&self) -> &AttributeValue {
&self.label
}
pub fn placeholder(&self) -> &AttributeValue {
&self.placeholder
}
pub fn autofocus(&self) -> &AttributeValue {
&self.autofocus
}
pub fn autocomplete(&self) -> &AttributeValue {
&self.autocomplete
}
pub fn disabled(&self) -> &AttributeValue {
&self.disabled
}
pub fn readonly(&self) -> &AttributeValue {
&self.readonly
}
pub fn required(&self) -> &AttributeValue {
&self.required
}
pub fn help_text(&self) -> &AttributeValue {
&self.help_text
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,164 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_FORM);
hook_before_render_component!(HOOK_BEFORE_RENDER_FORM, Form);
#[derive(Default)]
pub enum FormMethod {
#[default]
Post,
Get,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Form {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
action : AttributeValue,
charset : AttributeValue,
method : FormMethod,
elements : ComponentsBundle,
template : String,
}
impl ComponentTrait for Form {
fn new() -> Self {
Form::default()
.with_classes(ClassesOp::SetDefault, "form")
.with_charset("UTF-8")
}
fn handle(&self) -> Handle {
COMPONENT_FORM
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
before_render_inline(self, rcx);
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
let method = match self.method() {
FormMethod::Post => Some("post".to_owned()),
FormMethod::Get => None,
};
html! {
form
id=[self.id().get()]
class=[self.classes().get()]
action=[self.action().get()]
method=[method]
accept-charset=[self.charset().get()]
{
div { (self.elements().render(rcx)) }
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Form {
// Form BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_action(&mut self, action: &str) -> &mut Self {
self.action.alter_value(action);
self
}
#[fn_builder]
pub fn alter_charset(&mut self, charset: &str) -> &mut Self {
self.charset.alter_value(charset);
self
}
#[fn_builder]
pub fn alter_method(&mut self, method: FormMethod) -> &mut Self {
self.method = method;
self
}
#[fn_builder]
pub fn alter_element(&mut self, element: impl ComponentTrait) -> &mut Self {
self.elements.add(element);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Form GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn action(&self) -> &AttributeValue {
&self.action
}
pub fn charset(&self) -> &AttributeValue {
&self.charset
}
pub fn method(&self) -> &FormMethod {
&self.method
}
pub fn elements(&self) -> &ComponentsBundle {
&self.elements
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,76 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_HIDDEN);
#[rustfmt::skip]
#[derive(Default)]
pub struct Hidden {
weight: isize,
name : NameValue,
value : AttributeValue,
}
impl ComponentTrait for Hidden {
fn new() -> Self {
Hidden::default()
}
fn handle(&self) -> Handle {
COMPONENT_HIDDEN
}
fn weight(&self) -> isize {
self.weight
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
let id = self.name().get().map(|name| concat_string!("value-", name));
html! {
input type="hidden" id=[id] name=[self.name().get()] value=[self.value().get()];
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Hidden {
pub fn set(name: &str, value: &str) -> Self {
Hidden::new().with_name(name).with_value(value)
}
// Hidden BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.alter_value(name);
self
}
#[fn_builder]
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.alter_value(value);
self
}
// Hidden GETTERS.
pub fn name(&self) -> &NameValue {
&self.name
}
pub fn value(&self) -> &AttributeValue {
&self.value
}
}

View file

@ -1,357 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_INPUT);
#[derive(Default)]
pub enum InputType {
#[default]
Textfield,
Password,
Search,
Email,
Telephone,
Url,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Input {
weight : isize,
renderable : Renderable,
classes : Classes,
input_type : InputType,
name : NameValue,
value : AttributeValue,
label : AttributeValue,
size : Option<u16>,
minlength : Option<u16>,
maxlength : Option<u16>,
placeholder : AttributeValue,
autofocus : AttributeValue,
autocomplete: AttributeValue,
disabled : AttributeValue,
readonly : AttributeValue,
required : AttributeValue,
help_text : AttributeValue,
template : String,
}
impl ComponentTrait for Input {
fn new() -> Self {
Input::default()
.with_classes(ClassesOp::SetDefault, "form-item")
.with_classes(ClassesOp::AddFirst, "form-type-textfield")
.with_size(Some(60))
.with_maxlength(Some(128))
}
fn handle(&self) -> Handle {
COMPONENT_INPUT
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
#[rustfmt::skip]
fn default_render(&self, _: &mut RenderContext) -> Markup {
let type_input = match self.input_type() {
InputType::Textfield => "text",
InputType::Password => "password",
InputType::Search => "search",
InputType::Email => "email",
InputType::Telephone => "tel",
InputType::Url => "url",
};
let id = self.name().get().map(|name| concat_string!("edit-", name));
html! {
div class=[self.classes().get()] {
@if let Some(label) = self.label().get() {
label class="form-label" for=[&id] {
(label) " "
@if self.required().get().is_some() {
span
class="form-required"
title="Este campo es obligatorio." { "*" } " ";
}
}
}
input
type=(type_input)
id=[id]
class="form-control"
name=[self.name().get()]
value=[self.value().get()]
size=[self.size()]
minlength=[self.minlength()]
maxlength=[self.maxlength()]
placeholder=[self.placeholder().get()]
autofocus=[self.autofocus().get()]
autocomplete=[self.autocomplete().get()]
readonly=[self.readonly().get()]
required=[self.required().get()]
disabled=[self.disabled().get()];
@if let Some(help_text) = self.help_text().get() {
div class="form-text" { (help_text) }
}
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Input {
pub fn textfield() -> Self {
Input::new()
}
#[rustfmt::skip]
pub fn password() -> Self {
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-password",
);
input.input_type = InputType::Password;
input
}
#[rustfmt::skip]
pub fn search() -> Self {
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-search",
);
input.input_type = InputType::Search;
input
}
#[rustfmt::skip]
pub fn email() -> Self {
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-email"
);
input.input_type = InputType::Email;
input
}
#[rustfmt::skip]
pub fn telephone() -> Self {
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-telephone",
);
input.input_type = InputType::Telephone;
input
}
#[rustfmt::skip]
pub fn url() -> Self {
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-url"
);
input.input_type = InputType::Url;
input
}
// Input BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.alter_value(name);
self.alter_classes(
ClassesOp::SetDefault,
concat_string!("form-item form-item-", name).as_str(),
);
self
}
#[fn_builder]
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.alter_value(value);
self
}
#[fn_builder]
pub fn alter_label(&mut self, label: &str) -> &mut Self {
self.label.alter_value(label);
self
}
#[fn_builder]
pub fn alter_size(&mut self, size: Option<u16>) -> &mut Self {
self.size = size;
self
}
#[fn_builder]
pub fn alter_minlength(&mut self, minlength: Option<u16>) -> &mut Self {
self.minlength = minlength;
self
}
#[fn_builder]
pub fn alter_maxlength(&mut self, maxlength: Option<u16>) -> &mut Self {
self.maxlength = maxlength;
self
}
#[fn_builder]
pub fn alter_placeholder(&mut self, placeholder: &str) -> &mut Self {
self.placeholder.alter_value(placeholder);
self
}
#[fn_builder]
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
self.autofocus.alter_value(match toggle {
true => "autofocus",
false => "",
});
self
}
#[fn_builder]
pub fn alter_autocomplete(&mut self, toggle: bool) -> &mut Self {
self.autocomplete.alter_value(match toggle {
true => "",
false => "off",
});
self
}
#[fn_builder]
pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
self.disabled.alter_value(match toggle {
true => "disabled",
false => "",
});
self
}
#[fn_builder]
pub fn alter_readonly(&mut self, toggle: bool) -> &mut Self {
self.readonly.alter_value(match toggle {
true => "readonly",
false => "",
});
self
}
#[fn_builder]
pub fn alter_required(&mut self, toggle: bool) -> &mut Self {
self.required.alter_value(match toggle {
true => "required",
false => "",
});
self
}
#[fn_builder]
pub fn alter_help_text(&mut self, help_text: &str) -> &mut Self {
self.help_text.alter_value(help_text);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Input GETTERS.
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn input_type(&self) -> &InputType {
&self.input_type
}
pub fn name(&self) -> &NameValue {
&self.name
}
pub fn value(&self) -> &AttributeValue {
&self.value
}
pub fn label(&self) -> &AttributeValue {
&self.label
}
pub fn size(&self) -> Option<u16> {
self.size
}
pub fn minlength(&self) -> Option<u16> {
self.minlength
}
pub fn maxlength(&self) -> Option<u16> {
self.maxlength
}
pub fn placeholder(&self) -> &AttributeValue {
&self.placeholder
}
pub fn autofocus(&self) -> &AttributeValue {
&self.autofocus
}
pub fn autocomplete(&self) -> &AttributeValue {
&self.autocomplete
}
pub fn disabled(&self) -> &AttributeValue {
&self.disabled
}
pub fn readonly(&self) -> &AttributeValue {
&self.readonly
}
pub fn required(&self) -> &AttributeValue {
&self.required
}
pub fn help_text(&self) -> &AttributeValue {
&self.help_text
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,4 +0,0 @@
mod row;
pub use row::{Row, COMPONENT_ROW};
mod column;
pub use column::{Column, ColumnSize, COMPONENT_COLUMN};

View file

@ -1,171 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_COLUMN);
hook_before_render_component!(HOOK_BEFORE_RENDER_COLUMN, Column);
const SIZE__DEFAULT: &str = "col-md";
const SIZE__1_OF_12: &str = "col-md-1";
const SIZE__2_OF_12: &str = "col-md-2";
const SIZE__3_OF_12: &str = "col-md-3";
const SIZE__4_OF_12: &str = "col-md-4";
const SIZE__5_OF_12: &str = "col-md-5";
const SIZE__6_OF_12: &str = "col-md-6";
const SIZE__7_OF_12: &str = "col-md-7";
const SIZE__8_OF_12: &str = "col-md-8";
const SIZE__9_OF_12: &str = "col-md-9";
const SIZE_10_OF_12: &str = "col-md-10";
const SIZE_11_OF_12: &str = "col-md-11";
const SIZE_12_OF_12: &str = "col-md-12";
#[derive(Default)]
pub enum ColumnSize {
#[default]
Default,
Is1of12,
Is2of12,
Is3of12,
Is4of12,
Is5of12,
Is6of12,
Is7of12,
Is8of12,
Is9of12,
Is10of12,
Is11of12,
IsFull,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Column {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
size : ColumnSize,
components: ComponentsBundle,
template : String,
}
impl ComponentTrait for Column {
fn new() -> Self {
Column::default().with_classes(ClassesOp::SetDefault, SIZE__DEFAULT)
}
fn handle(&self) -> Handle {
COMPONENT_COLUMN
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
before_render_inline(self, rcx);
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
html! {
div id=[self.id().get()] class=[self.classes().get()] {
(self.components().render(rcx))
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Column {
// Column BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[rustfmt::skip]
#[fn_builder]
pub fn alter_size(&mut self, size: ColumnSize) -> &mut Self {
match size {
ColumnSize::Default => self.alter_classes(ClassesOp::SetDefault, SIZE__DEFAULT),
ColumnSize::Is1of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__1_OF_12),
ColumnSize::Is2of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__2_OF_12),
ColumnSize::Is3of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__3_OF_12),
ColumnSize::Is4of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__4_OF_12),
ColumnSize::Is5of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__5_OF_12),
ColumnSize::Is6of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__6_OF_12),
ColumnSize::Is7of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__7_OF_12),
ColumnSize::Is8of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__8_OF_12),
ColumnSize::Is9of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__9_OF_12),
ColumnSize::Is10of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_10_OF_12),
ColumnSize::Is11of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_11_OF_12),
ColumnSize::IsFull => self.alter_classes(ClassesOp::SetDefault, SIZE_12_OF_12),
};
self.size = size;
self
}
#[fn_builder]
pub fn alter_component(&mut self, component: impl ComponentTrait) -> &mut Self {
self.components.add(component);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Column GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn size(&self) -> &ColumnSize {
&self.size
}
pub fn components(&self) -> &ComponentsBundle {
&self.components
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,112 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_ROW);
hook_before_render_component!(HOOK_BEFORE_RENDER_ROW, Row);
#[rustfmt::skip]
#[derive(Default)]
pub struct Row {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
columns : ComponentsBundle,
template : String,
}
impl ComponentTrait for Row {
fn new() -> Self {
Row::default().with_classes(ClassesOp::SetDefault, "row")
}
fn handle(&self) -> Handle {
COMPONENT_ROW
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
before_render_inline(self, rcx);
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
html! {
div id=[self.id().get()] class=[self.classes().get()] {
(self.columns().render(rcx))
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Row {
// Row BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_column(&mut self, column: grid::Column) -> &mut Self {
self.columns.add(column);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Row GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn columns(&self) -> &ComponentsBundle {
&self.columns
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,205 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_HEADING);
#[derive(Default)]
pub enum HeadingType {
#[default]
H1,
H2,
H3,
H4,
H5,
H6,
}
#[derive(Default)]
pub enum HeadingDisplay {
#[default]
Normal,
XxLarge,
Large,
Medium,
Small,
XxSmall,
Subtitle,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Heading {
weight : isize,
renderable : Renderable,
id : IdentifierValue,
classes : Classes,
heading_type: HeadingType,
html : HtmlMarkup,
display : HeadingDisplay,
template : String,
}
impl ComponentTrait for Heading {
fn new() -> Self {
Heading::default()
}
fn handle(&self) -> Handle {
COMPONENT_HEADING
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
let id = self.id().get();
let classes = self.classes().get();
html! { @match &self.heading_type() {
HeadingType::H1 => h1 id=[id] class=[classes] { (*self.html()) },
HeadingType::H2 => h2 id=[id] class=[classes] { (*self.html()) },
HeadingType::H3 => h3 id=[id] class=[classes] { (*self.html()) },
HeadingType::H4 => h4 id=[id] class=[classes] { (*self.html()) },
HeadingType::H5 => h5 id=[id] class=[classes] { (*self.html()) },
HeadingType::H6 => h6 id=[id] class=[classes] { (*self.html()) },
}}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Heading {
pub fn h1(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H1)
.with_html(html)
}
pub fn h2(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H2)
.with_html(html)
}
pub fn h3(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H3)
.with_html(html)
}
pub fn h4(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H4)
.with_html(html)
}
pub fn h5(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H5)
.with_html(html)
}
pub fn h6(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H6)
.with_html(html)
}
// Heading BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_heading_type(&mut self, heading_type: HeadingType) -> &mut Self {
self.heading_type = heading_type;
self
}
#[fn_builder]
pub fn alter_html(&mut self, html: Markup) -> &mut Self {
self.html.markup = html;
self
}
#[rustfmt::skip]
#[fn_builder]
pub fn alter_display(&mut self, display: HeadingDisplay) -> &mut Self {
self.display = display;
self.classes.alter_value(
ClassesOp::SetDefault,
match &self.display() {
HeadingDisplay::XxLarge => "display-2",
HeadingDisplay::Large => "display-3",
HeadingDisplay::Medium => "display-4",
HeadingDisplay::Small => "display-5",
HeadingDisplay::XxSmall => "display-6",
HeadingDisplay::Normal => "",
HeadingDisplay::Subtitle => "",
},
);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Paragraph GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn heading_type(&self) -> &HeadingType {
&self.heading_type
}
pub fn html(&self) -> &Markup {
&self.html.markup
}
pub fn display(&self) -> &HeadingDisplay {
&self.display
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,84 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_HTML);
#[rustfmt::skip]
#[derive(Default)]
pub struct Html {
weight : isize,
renderable: Renderable,
html : HtmlMarkup,
template : String,
}
impl ComponentTrait for Html {
fn new() -> Self {
Html::default()
}
fn handle(&self) -> Handle {
COMPONENT_HTML
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
html! { (*self.html()) }
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Html {
pub fn with(html: Markup) -> Self {
Html::new().with_html(html)
}
// Html BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_html(&mut self, html: Markup) -> &mut Self {
self.html.markup = html;
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Html GETTERS.
pub fn html(&self) -> &Markup {
&self.html.markup
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,94 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_ICON);
#[rustfmt::skip]
#[derive(Default)]
pub struct Icon {
weight : isize,
renderable: Renderable,
icon_name : String,
classes : Classes,
}
impl ComponentTrait for Icon {
fn new() -> Self {
Icon::default().with_classes(ClassesOp::SetDefault, "bi-question-circle-fill")
}
fn handle(&self) -> Handle {
COMPONENT_ICON
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
rcx.alter(ContextOp::AddStyleSheet(
StyleSheet::located("/theme/icons/bootstrap-icons.css").with_version("1.8.2"),
));
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
html! { i class=[self.classes().get()] {}; }
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Icon {
pub fn with(icon_name: &str) -> Self {
Icon::new().with_icon_name(icon_name)
}
// Icon BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_icon_name(&mut self, name: &str) -> &mut Self {
self.icon_name = name.to_owned();
self.alter_classes(
ClassesOp::SetDefault,
concat_string!("bi-", self.icon_name).as_str(),
);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
// Icon GETTERS.
pub fn icon_name(&self) -> &str {
self.icon_name.as_str()
}
pub fn classes(&self) -> &Classes {
&self.classes
}
}

View file

@ -1,111 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_IMAGE);
#[rustfmt::skip]
#[derive(Default)]
pub struct Image {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
source : AttributeValue,
template : String,
}
impl ComponentTrait for Image {
fn new() -> Self {
Image::default().with_classes(ClassesOp::SetDefault, "img-fluid")
}
fn handle(&self) -> Handle {
COMPONENT_IMAGE
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
html! {
img
src=[self.source().get()]
id=[self.id().get()]
class=[self.classes().get()];
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Image {
pub fn with(source: &str) -> Self {
Image::new().with_source(source)
}
// Image BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_source(&mut self, source: &str) -> &mut Self {
self.source.alter_value(source);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Image GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn source(&self) -> &AttributeValue {
&self.source
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,147 +0,0 @@
use crate::prelude::*;
pub_handle!(COMPONENT_PARAGRAPH);
#[derive(Default)]
pub enum ParagraphDisplay {
#[default]
Normal,
XxLarge,
Large,
Medium,
Small,
XxSmall,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Paragraph {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
components: ComponentsBundle,
display : ParagraphDisplay,
template : String,
}
impl ComponentTrait for Paragraph {
fn new() -> Self {
Paragraph::default()
}
fn handle(&self) -> Handle {
COMPONENT_PARAGRAPH
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
html! {
p
id=[self.id().get()]
class=[self.classes().get()]
{
(self.components().render(rcx))
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Paragraph {
pub fn with(html: Markup) -> Self {
Paragraph::new().with_component(Html::with(html))
}
// Paragraph BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_component(&mut self, component: impl ComponentTrait) -> &mut Self {
self.components.add(component);
self
}
#[rustfmt::skip]
#[fn_builder]
pub fn alter_display(&mut self, display: ParagraphDisplay) -> &mut Self {
self.display = display;
self.classes.alter_value(
ClassesOp::SetDefault,
match &self.display() {
ParagraphDisplay::XxLarge => "fs-2",
ParagraphDisplay::Large => "fs-3",
ParagraphDisplay::Medium => "fs-4",
ParagraphDisplay::Small => "fs-5",
ParagraphDisplay::XxSmall => "fs-6",
ParagraphDisplay::Normal => "",
},
);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Paragraph GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn components(&self) -> &ComponentsBundle {
&self.components
}
pub fn display(&self) -> &ParagraphDisplay {
&self.display
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,3 +0,0 @@
pub mod saturn;
pub mod menu;

View file

@ -1,21 +0,0 @@
use crate::prelude::*;
pub_handle!(MODULE_MENU);
pub_locale!("src/base/module/menu/locales");
pub struct Menu;
impl ModuleTrait for Menu {
fn handle(&self) -> Handle {
MODULE_MENU
}
fn name(&self) -> String {
l("module_name")
}
fn description(&self) -> Option<String> {
Some(l("module_description"))
}
}

View file

@ -1,2 +0,0 @@
module_name = Menu
module_description = ...

View file

@ -1,2 +0,0 @@
module_name = Menú
module_description = ...

View file

@ -1,30 +0,0 @@
use crate::prelude::*;
pub_handle!(THEME_SATURN);
include!(concat!(env!("OUT_DIR"), "/theme.rs"));
pub struct Saturn;
impl ModuleTrait for Saturn {
fn handle(&self) -> Handle {
THEME_SATURN
}
fn theme(&self) -> Option<ThemeStaticRef> {
Some(&Saturn)
}
fn configure_service(&self, cfg: &mut server::web::ServiceConfig) {
serve_static_files!(cfg, "/theme", bundle_theme);
}
}
impl ThemeTrait for Saturn {
fn before_render_page(&self, page: &mut Page) {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
.alter_context(ContextOp::AddStyleSheet(
StyleSheet::located("/theme/css/styles.css").with_weight(-99),
));
}
}

View file

@ -204,7 +204,7 @@ pub struct App {
pub name: String,
/// Valor predefinido: *"Developed with the amazing PageTop framework."*
pub description: String,
/// Valor predefinido: *"Saturn"*
/// Valor predefinido: *"Basic"*
pub theme: String,
/// Valor predefinido: *"en-US"*
pub language: String,
@ -278,7 +278,7 @@ pub_config!(SETTINGS: Settings,
// [app]
"app.name" => "PageTop Application",
"app.description" => "Developed with the amazing PageTop framework.",
"app.theme" => "Saturn",
"app.theme" => "Basic",
"app.language" => "en-US",
"app.direction" => "ltr",
"app.startup_banner" => "Slant",

View file

@ -6,3 +6,6 @@ pub mod hook;
// API to add new features with modules and themes.
pub mod module;
// Basic theme.
mod basic;

19
pagetop/src/core/basic.rs Normal file
View file

@ -0,0 +1,19 @@
use crate::core::module::{ModuleTrait, ThemeStaticRef, ThemeTrait};
use crate::pub_handle;
use crate::util::Handle;
pub_handle!(THEME_BASIC);
pub struct Basic;
impl ModuleTrait for Basic {
fn handle(&self) -> Handle {
THEME_BASIC
}
fn theme(&self) -> Option<ThemeStaticRef> {
Some(&Basic)
}
}
impl ThemeTrait for Basic {}

View file

@ -1,7 +1,7 @@
use crate::core::module::{all::theme_by_single_name, ThemeStaticRef};
use crate::html::{html, Assets, IdentifierValue, JavaScript, Markup, StyleSheet};
use crate::server::HttpRequest;
use crate::{base, concat_string, config, util, LazyStatic};
use crate::{concat_string, config, util, LazyStatic};
use std::collections::HashMap;
use std::str::FromStr;
@ -9,7 +9,7 @@ use std::str::FromStr;
static DEFAULT_THEME: LazyStatic<ThemeStaticRef> =
LazyStatic::new(|| match theme_by_single_name(&config::SETTINGS.app.theme) {
Some(theme) => theme,
None => &base::module::saturn::Saturn,
None => &crate::core::basic::Basic,
});
pub enum ContextOp {

View file

@ -1,4 +1,9 @@
use crate::core::component::{AnyComponent, ComponentTrait, RenderContext};
use crate::html::{html, Markup};
use crate::pub_handle;
use crate::util::Handle;
pub_handle!(HTML_MARKUP);
pub struct HtmlMarkup {
pub markup: Markup,
@ -9,3 +14,34 @@ impl Default for HtmlMarkup {
HtmlMarkup { markup: html! {} }
}
}
impl ComponentTrait for HtmlMarkup {
fn new() -> Self {
HtmlMarkup::default()
}
fn handle(&self) -> Handle {
HTML_MARKUP
}
fn default_render(&self, _rcx: &mut RenderContext) -> Markup {
html! {
(self.markup)
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl HtmlMarkup {
pub fn with(mut self, html: Markup) -> Self {
self.markup = html;
self
}
}

View file

@ -1,6 +1,5 @@
use super::{ModuleStaticRef, ThemeStaticRef};
use crate::base;
use crate::core::hook::add_action;
use crate::{server, trace, LazyStatic};
@ -46,9 +45,8 @@ pub fn register_modules(app: ModuleStaticRef) {
// List of modules to enable.
let mut list: Vec<ModuleStaticRef> = Vec::new();
// Enable base modules.
add_to_enabled(&mut list, &base::module::menu::Menu);
add_to_enabled(&mut list, &base::module::saturn::Saturn);
// Enable basic theme.
add_to_enabled(&mut list, &crate::core::basic::Basic);
// Enable application modules.
add_to_enabled(&mut list, app);

View file

@ -1,7 +1,6 @@
use super::ModuleTrait;
use crate::base::component::{Container, Html};
use crate::core::component::{ComponentTrait, RenderContext};
use crate::core::component::{ComponentTrait, HtmlMarkup, RenderContext};
use crate::html::{html, Favicon, Markup};
use crate::response::page::Page;
use crate::{concat_string, config};
@ -120,19 +119,19 @@ pub trait ThemeTrait: ModuleTrait + Send + Sync {
*/
}
fn error_404_not_found(&self) -> Container {
Container::new().with_component(Html::with(html! {
fn error_404_not_found(&self) -> HtmlMarkup {
HtmlMarkup::new().with(html! {
div {
h1 { ("RESOURCE NOT FOUND") }
}
}))
})
}
fn error_403_access_denied(&self) -> Container {
Container::new().with_component(Html::with(html! {
fn error_403_access_denied(&self) -> HtmlMarkup {
HtmlMarkup::new().with(html! {
div {
h1 { ("FORBIDDEN ACCESS") }
}
}))
})
}
}

View file

@ -75,8 +75,7 @@ pub mod server;
// Tipos de respuestas a peticiones web.
pub mod response;
// Base de componentes, módulos y temas.
pub mod base;
// Macros y funciones útiles.
pub mod util;

View file

@ -30,6 +30,4 @@ pub use crate::response::page::*;
pub use crate::response::FatalError;
pub use crate::response::ResponseError;
pub use crate::base::component::*;
pub use crate::app::Application;

View file

@ -1,356 +0,0 @@
html {
background-color: white;
padding: 1px 3px;
}
body {
padding: 1px 3px;
}
div {
padding: 1px 3px;
margin: 5px;
}
h1, h2, h3, h4,h5, h6, p {
background-color: snow;
}
* * {
outline: 5px solid rgba(255,0,0,.1);
}
* * * {
outline: 3px dashed rgba(255,0,0,.4);
}
* * * * {
outline: 2px dotted rgba(255,0,0,.6);
}
* * * * * {
outline: 1px dotted rgba(255,0,0,.9);
}
* * * * * * {
outline-color: gray;
}
*::before, *::after {
background: #faa;
border-radius: 3px;
font: normal normal 400 10px/1.2 monospace;
vertical-align: middle;
padding: 1px 3px;
margin: 0 3px;
}
*::before {
content: "(";
}
*::after {
content: ")";
}
a::before { content: "<a>"; }
a::after { content: "</a>"; }
abbr::before { content: "<abbr>"; }
abbr::after { content: "</abbr>"; }
acronym::before { content: "<acronym>"; }
acronym::after { content: "</acronym>"; }
address::before { content: "<address>"; }
address::after { content: "</address>"; }
applet::before { content: "<applet>"; }
applet::after { content: "</applet>"; }
area::before { content: "<area>"; }
area::after { content: "</area>"; }
article::before { content: "<article>"; }
article::after { content: "</article>"; }
aside::before { content: "<aside>"; }
aside::after { content: "</aside>"; }
audio::before { content: "<audio>"; }
audio::after { content: "</audio>"; }
b::before { content: "<b>"; }
b::after { content: "</b>"; }
base::before { content: "<base>"; }
base::after { content: "</base>"; }
basefont::before { content: "<basefont>"; }
basefont::after { content: "</basefont>"; }
bdi::before { content: "<bdi>"; }
bdi::after { content: "</bdi>"; }
bdo::before { content: "<bdo>"; }
bdo::after { content: "</bdo>"; }
bgsound::before { content: "<bgsound>"; }
bgsound::after { content: "</bgsound>"; }
big::before { content: "<big>"; }
big::after { content: "</big>"; }
blink::before { content: "<blink>"; }
blink::after { content: "</blink>"; }
blockquote::before { content: "<blockquote>"; }
blockquote::after { content: "</blockquote>"; }
body::before { content: "<body>"; }
body::after { content: "</body>"; }
br::before { content: "<br>"; }
br::after { content: "</br>"; }
button::before { content: "<button>"; }
button::after { content: "</button>"; }
caption::before { content: "<caption>"; }
caption::after { content: "</caption>"; }
canvas::before { content: "<canvas>"; }
canvas::after { content: "</canvas>"; }
center::before { content: "<center>"; }
center::after { content: "</center>"; }
cite::before { content: "<cite>"; }
cite::after { content: "</cite>"; }
code::before { content: "<code>"; }
code::after { content: "</code>"; }
col::before { content: "<col>"; }
col::after { content: "</col>"; }
colgroup::before { content: "<colgroup>"; }
colgroup::after { content: "</colgroup>"; }
command::before { content: "<command>"; }
command::after { content: "</command>"; }
content::before { content: "<content>"; }
content::after { content: "</content>"; }
data::before { content: "<data>"; }
data::after { content: "</data>"; }
datalist::before { content: "<datalist>"; }
datalist::after { content: "</datalist>"; }
dd::before { content: "<dd>"; }
dd::after { content: "</dd>"; }
del::before { content: "<del>"; }
del::after { content: "</del>"; }
details::before { content: "<details>"; }
details::after { content: "</details>"; }
dfn::before { content: "<dfn>"; }
dfn::after { content: "</dfn>"; }
dialog::before { content: "<dialog>"; }
dialog::after { content: "</dialog>"; }
dir::before { content: "<dir>"; }
dir::after { content: "</dir>"; }
div::before { content: "<div>"; }
div::after { content: "</div>"; }
dl::before { content: "<dl>"; }
dl::after { content: "</dl>"; }
dt::before { content: "<dt>"; }
dt::after { content: "</dt>"; }
element::before { content: "<element>"; }
element::after { content: "</element>"; }
em::before { content: "<em>"; }
em::after { content: "</em>"; }
embed::before { content: "<embed>"; }
embed::after { content: "</embed>"; }
fieldset::before { content: "<fieldset>"; }
fieldset::after { content: "</fieldset>"; }
figcaption::before { content: "<figcaption>"; }
figcaption::after { content: "</figcaption>"; }
figure::before { content: "<figure>"; }
figure::after { content: "</figure>"; }
font::before { content: "<font>"; }
font::after { content: "</font>"; }
footer::before { content: "<footer>"; }
footer::after { content: "</footer>"; }
form::before { content: "<form>"; }
form::after { content: "</form>"; }
frame::before { content: "<frame>"; }
frame::after { content: "</frame>"; }
frameset::before { content: "<frameset>"; }
frameset::after { content: "</frameset>"; }
h1::before { content: "<h1>"; }
h1::after { content: "</h1>"; }
h2::before { content: "<h2>"; }
h2::after { content: "</h2>"; }
h3::before { content: "<h3>"; }
h3::after { content: "</h3>"; }
h4::before { content: "<h4>"; }
h4::after { content: "</h4>"; }
h5::before { content: "<h5>"; }
h5::after { content: "</h5>"; }
h6::before { content: "<h6>"; }
h6::after { content: "</h6>"; }
head::before { content: "<head>"; }
head::after { content: "</head>"; }
header::before { content: "<header>"; }
header::after { content: "</header>"; }
hgroup::before { content: "<hgroup>"; }
hgroup::after { content: "</hgroup>"; }
hr::before { content: "<hr>"; }
hr::after { content: "</hr>"; }
html::before { content: "<html>"; }
html::after { content: "</html>"; }
i::before { content: "<i>"; }
i::after { content: "</i>"; }
iframe::before { content: "<iframe>"; }
iframe::after { content: "</iframe>"; }
image::before { content: "<image>"; }
image::after { content: "</image>"; }
img::before { content: "<img>"; }
img::after { content: "</img>"; }
input::before { content: "<input>"; }
input::after { content: "</input>"; }
ins::before { content: "<ins>"; }
ins::after { content: "</ins>"; }
isindex::before { content: "<isindex>"; }
isindex::after { content: "</isindex>"; }
kbd::before { content: "<kbd>"; }
kbd::after { content: "</kbd>"; }
keygen::before { content: "<keygen>"; }
keygen::after { content: "</keygen>"; }
label::before { content: "<label>"; }
label::after { content: "</label>"; }
legend::before { content: "<legend>"; }
legend::after { content: "</legend>"; }
li::before { content: "<li>"; }
li::after { content: "</li>"; }
link::before { content: "<link>"; }
link::after { content: "</link>"; }
listing::before { content: "<listing>"; }
listing::after { content: "</listing>"; }
main::before { content: "<main>"; }
main::after { content: "</main>"; }
map::before { content: "<map>"; }
map::after { content: "</map>"; }
mark::before { content: "<mark>"; }
mark::after { content: "</mark>"; }
marquee::before { content: "<marquee>"; }
marquee::after { content: "</marquee>"; }
menu::before { content: "<menu>"; }
menu::after { content: "</menu>"; }
menuitem::before { content: "<menuitem>"; }
menuitem::after { content: "</menuitem>"; }
meta::before { content: "<meta>"; }
meta::after { content: "</meta>"; }
meter::before { content: "<meter>"; }
meter::after { content: "</meter>"; }
multicol::before { content: "<multicol>"; }
multicol::after { content: "</multicol>"; }
nav::before { content: "<nav>"; }
nav::after { content: "</nav>"; }
nextid::before { content: "<nextid>"; }
nextid::after { content: "</nextid>"; }
nobr::before { content: "<nobr>"; }
nobr::after { content: "</nobr>"; }
noembed::before { content: "<noembed>"; }
noembed::after { content: "</noembed>"; }
noframes::before { content: "<noframes>"; }
noframes::after { content: "</noframes>"; }
noscript::before { content: "<noscript>"; }
noscript::after { content: "</noscript>"; }
object::before { content: "<object>"; }
object::after { content: "</object>"; }
ol::before { content: "<ol>"; }
ol::after { content: "</ol>"; }
optgroup::before { content: "<optgroup>"; }
optgroup::after { content: "</optgroup>"; }
option::before { content: "<option>"; }
option::after { content: "</option>"; }
output::before { content: "<output>"; }
output::after { content: "</output>"; }
p::before { content: "<p>"; }
p::after { content: "</p>"; }
param::before { content: "<param>"; }
param::after { content: "</param>"; }
picture::before { content: "<picture>"; }
picture::after { content: "</picture>"; }
plaintext::before { content: "<plaintext>"; }
plaintext::after { content: "</plaintext>"; }
pre::before { content: "<pre>"; }
pre::after { content: "</pre>"; }
progress::before { content: "<progress>"; }
progress::after { content: "</progress>"; }
q::before { content: "<q>"; }
q::after { content: "</q>"; }
rb::before { content: "<rb>"; }
rb::after { content: "</rb>"; }
rp::before { content: "<rp>"; }
rp::after { content: "</rp>"; }
rt::before { content: "<rt>"; }
rt::after { content: "</rt>"; }
rtc::before { content: "<rtc>"; }
rtc::after { content: "</rtc>"; }
ruby::before { content: "<ruby>"; }
ruby::after { content: "</ruby>"; }
s::before { content: "<s>"; }
s::after { content: "</s>"; }
samp::before { content: "<samp>"; }
samp::after { content: "</samp>"; }
script::before { content: "<script>"; }
script::after { content: "</script>"; }
section::before { content: "<section>"; }
section::after { content: "</section>"; }
select::before { content: "<select>"; }
select::after { content: "</select>"; }
shadow::before { content: "<shadow>"; }
shadow::after { content: "</shadow>"; }
slot::before { content: "<slot>"; }
slot::after { content: "</slot>"; }
small::before { content: "<small>"; }
small::after { content: "</small>"; }
source::before { content: "<source>"; }
source::after { content: "</source>"; }
spacer::before { content: "<spacer>"; }
spacer::after { content: "</spacer>"; }
span::before { content: "<span>"; }
span::after { content: "</span>"; }
strike::before { content: "<strike>"; }
strike::after { content: "</strike>"; }
strong::before { content: "<strong>"; }
strong::after { content: "</strong>"; }
style::before { content: "<style>"; }
style::after { content: "<\/style>"; }
sub::before { content: "<sub>"; }
sub::after { content: "</sub>"; }
summary::before { content: "<summary>"; }
summary::after { content: "</summary>"; }
sup::before { content: "<sup>"; }
sup::after { content: "</sup>"; }
table::before { content: "<table>"; }
table::after { content: "</table>"; }
tbody::before { content: "<tbody>"; }
tbody::after { content: "</tbody>"; }
td::before { content: "<td>"; }
td::after { content: "</td>"; }
template::before { content: "<template>"; }
template::after { content: "</template>"; }
textarea::before { content: "<textarea>"; }
textarea::after { content: "</textarea>"; }
tfoot::before { content: "<tfoot>"; }
tfoot::after { content: "</tfoot>"; }
th::before { content: "<th>"; }
th::after { content: "</th>"; }
thead::before { content: "<thead>"; }
thead::after { content: "</thead>"; }
time::before { content: "<time>"; }
time::after { content: "</time>"; }
title::before { content: "<title>"; }
title::after { content: "</title>"; }
tr::before { content: "<tr>"; }
tr::after { content: "</tr>"; }
track::before { content: "<track>"; }
track::after { content: "</track>"; }
tt::before { content: "<tt>"; }
tt::after { content: "</tt>"; }
u::before { content: "<u>"; }
u::after { content: "</u>"; }
ul::before { content: "<ul>"; }
ul::after { content: "</ul>"; }
var::before { content: "<var>"; }
var::after { content: "</var>"; }
video::before { content: "<video>"; }
video::after { content: "</video>"; }
wbr::before { content: "<wbr>"; }
wbr::after { content: "</wbr>"; }
xmp::before { content: "<xmp>"; }
xmp::after { content: "</xmp>"; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because it is too large Load diff