Skip to content

Commit

Permalink
Merge pull request #33 from vidhanio/hypertext
Browse files Browse the repository at this point in the history
feat: enhance hypertext usage
  • Loading branch information
HookedBehemoth authored Jan 13, 2024
2 parents 31b1d16 + fc1a5e7 commit 6458baa
Show file tree
Hide file tree
Showing 11 changed files with 377 additions and 375 deletions.
540 changes: 274 additions & 266 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ rustls = { version = "0.21", default-features = false }
rustls-native-certs = "0.6"
pico-args = "0.5.0"
tl = "0.7.7"
hypertext = "0.3.1"
hypertext = "0.4"

[build-dependencies]
grass = "0.13"
Expand Down
10 changes: 5 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ mod render;
mod routes;

use api::error::ApiError;
use hypertext::{html_elements, maud, GlobalAttributes, Renderable};
use routes::{
about::render_about,
article::render_article,
internet_news::render_legacy_article,
markets::render_market,
search::{render_search, render_section, render_topic},
};
use hypertext::{html_elements, maud, GlobalAttributes};

const CSS: &str = include_str!(concat!(env!("OUT_DIR"), "/main.css"));

Expand Down Expand Up @@ -147,12 +147,12 @@ fn main() {
}

fn render_error(code: u16, message: &str, path: &str) -> rouille::Response {
let title = format!("{} - {}", code, message);
let title = maud!((code) " - " (message));

let doc = document!(
title.as_str(),
&maud! {
h1 { (title.as_str()) }
title,
maud! {
h1 { (title) }
p { "You tried to access \"" (path) "\"" }
p { a href="/" { "Go home" } }
p { a href=(path) { "Try again" } }
Expand Down
51 changes: 25 additions & 26 deletions src/render/byline.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,34 @@
use crate::api::common::Topic;
use std::fmt::Write;
use hypertext::{maud, Renderable};

pub fn render_byline(authors: &[Topic]) -> String {
match authors.len() {
0 => "".to_string(),
1 => format_author(&authors[0]),
author_count => {
/* Chain author names together */
let mut byline = "By ".to_string();
use crate::api::common::Topic;
use hypertext::html_elements;

for author in authors[..author_count - 2].iter() {
byline.push_str(&format_author(author));
byline.push_str(", ");
pub fn render_byline(authors: &[Topic]) -> impl Renderable + '_ {
maud! {
@match authors.len() {
0 => {},
1 => (format_author(&authors[0])),
author_count => {
"By "
@for author in &authors[..author_count - 2] {
(format_author(author)) ", "
}
(format_author(&authors[author_count - 2]))
" and "
(format_author(&authors[author_count - 1]))
}

let _ = write!(
byline,
"{} and {}",
format_author(&authors[author_count - 2]),
format_author(&authors[author_count - 1])
);

byline
}
}
}

pub fn format_author(author: &Topic) -> String {
if let Some(url) = &author.topic_url {
format!("<a href=\"{}\">{}</a>", url, author.byline)
} else {
author.byline.clone()
pub fn format_author(author: &Topic) -> impl Renderable + '_ {
maud! {
@if let Some(url) = &author.topic_url {
a href=(url) {
(&author.byline)
}
} @else {
(&author.byline)
}
}
}
55 changes: 27 additions & 28 deletions src/render/legacy_article_byline.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
use std::fmt::Write;
use hypertext::{html_elements, maud, Renderable};

use crate::api::legacy_article::LegacyArticleAuthor;

pub fn render_byline(authors: &[LegacyArticleAuthor]) -> String {
match authors.len() {
0 => "".to_string(),
1 => format_author(&authors[0]),
author_count => {
/* Chain author names together */
let mut byline = "By ".to_string();

for author in authors[..author_count - 2].iter() {
byline.push_str(&format_author(author));
byline.push_str(", ");
pub fn render_byline(authors: &[LegacyArticleAuthor]) -> impl Renderable + '_ {
maud! {
@match authors.len() {
0 => {},
1 => (format_author(&authors[0])),
author_count => {
"By "
@for author in &authors[..author_count - 2] {
(format_author(author)) ", "
}
(format_author(&authors[author_count - 2]))
" and "
(format_author(&authors[author_count - 1]))
}

let _ = write!(
byline,
"{} and {}",
format_author(&authors[author_count - 2]),
format_author(&authors[author_count - 1])
);

byline
}
}
}

pub fn format_author(author: &LegacyArticleAuthor) -> String {
match author
.url
.strip_prefix("https://www.reuters.com/journalists/")
{
Some(path) => format!("<a href=\"/authors/{}/\">{}</a>", path, author.name),
None => format!("<a href=\"{}\">{}</a>", author.url, author.name),
pub fn format_author(author: &LegacyArticleAuthor) -> impl Renderable + '_ {
maud! {
a href=@if let Some(path) = author
.url
.strip_prefix("https://www.reuters.com/journalists/")
{
"/journalists/" (path) "/"
} @else {
(&author.url)
}
{
(&author.name)
}
}
}
6 changes: 3 additions & 3 deletions src/routes/about.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::api::error::ApiResult;
use crate::document;
use hypertext::{html_elements, maud, GlobalAttributes};
use hypertext::{html_elements, maud, GlobalAttributes, Renderable};
use std::env;
const GIT_HASH: &str = env!("GIT_HASH");

Expand Down Expand Up @@ -32,9 +32,9 @@ pub fn render_about() -> ApiResult<String> {
p { "This project is licensed under the " a href="https://www.gnu.org/licenses/licenses.html#AGPL" { "GNU Affero General Public License" } "." }

h2 { "Build information" }
p { "This version is based off the git commit " a href=(format!("https://github.com/HookedBehemoth/neuters/commit/{}", GIT_HASH)) { (GIT_HASH) }}
p { "This version is based off the git commit " a href={ "https://github.com/HookedBehemoth/neuters/commit/" (GIT_HASH) } { (GIT_HASH) }}
},
);

Ok(doc.render().0)
Ok(doc.render().into_inner())
}
35 changes: 14 additions & 21 deletions src/routes/article.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
use crate::{
api::{article::fetch_article_by_url, error::ApiResult},
render::byline,
routes::HtmxAttributes,
};
use chrono::{DateTime, Utc};
use hypertext::{html_elements, maud, GlobalAttributes, Rendered, Raw, Attribute};

trait HtmxAttributes: GlobalAttributes {
#[allow(non_upper_case_globals)]
const property: Attribute = Attribute;
}

impl<T: GlobalAttributes> HtmxAttributes for T {}
use hypertext::{html_elements, maud, maud_move, GlobalAttributes, Raw, Renderable};

pub fn render_article(client: &ureq::Agent, path: &str) -> ApiResult<String> {
let article = fetch_article_by_url(client, path)?;
Expand All @@ -21,35 +15,34 @@ pub fn render_article(client: &ureq::Agent, path: &str) -> ApiResult<String> {
.map(|time| time.format("%Y-%m-%d %H:%M").to_string());

let doc = crate::document!(
article.title.as_str(),
&article.title,
maud!(
h1 { (article.title.as_str()) }
h1 { (&article.title) }
p class="byline" {
@if let Some(authors) = &article.authors {
@let byline = byline::render_byline(authors);
@if let Ok(time) = &published_time {
(time.as_str()) " - "
(time) " - "
}
(Raw(byline))
(byline::render_byline(authors))
}
}
@if let Some(articles) = &article.content_elements {
(Raw(render_items(articles)))
(render_items(articles))
}
),
maud! {
meta property="og:title" content=(article.title.as_str());
meta property="og:title" content=(&article.title);
meta property="og:type" content="article";
meta property="og:description" content=(article.description.as_str());
meta property="og:description" content=(&article.description);
meta property="og:url" content=(path);
}
);

Ok(doc.render().0)
Ok(doc.render().into_inner())
}

fn render_items(items: &[serde_json::Value]) -> Rendered<String> {
maud! {
fn render_items(items: &[serde_json::Value]) -> impl Renderable + '_ {
maud_move! {
@for content in items {
@match content["type"].as_str() {
Some("header") => {
Expand Down Expand Up @@ -112,7 +105,7 @@ fn render_items(items: &[serde_json::Value]) -> Rendered<String> {
}
Some("list") => {
@if let Some(items) = content["items"].as_array() {
(Raw(render_items(items)))
(render_items(items))
}
}
Some("social_media") => {
Expand All @@ -129,5 +122,5 @@ fn render_items(items: &[serde_json::Value]) -> Rendered<String> {
None => { p { "Failed to parse content element" } }
}
}
}.render()
}
}
27 changes: 10 additions & 17 deletions src/routes/internet_news.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
use chrono::{DateTime, Utc};
use hypertext::{html_elements, maud, GlobalAttributes, Attribute, Raw};
use hypertext::{html_elements, maud, GlobalAttributes, Renderable};

use crate::{
api::{
error::{ApiError, ApiResult},
legacy_article::{fetch_legacy_article, parse_legacy_article},
},
render::legacy_article_byline::render_byline,
routes::HtmxAttributes,
};

trait HtmxAttributes: GlobalAttributes {
#[allow(non_upper_case_globals)]
const property: Attribute = Attribute;
}

impl<T: GlobalAttributes> HtmxAttributes for T {}

pub fn render_legacy_article(
client: &ureq::Agent,
path: &str,
Expand Down Expand Up @@ -64,21 +58,20 @@ pub fn render_legacy_article(
.map(|time| time.format("%Y-%m-%d %H:%M").to_string());

let doc = crate::document!(
article.headline.as_str(),
&article.headline,
maud! {
h1 { (article.headline.as_str()) }
h1 { (&article.headline) }
p class="byline" {
@let byline = render_byline(&article.authors);
@if let Ok(time) = &published_time {
(time.as_str()) " - "
(time) " - "
}
(Raw(byline))
(render_byline(&article.authors))
}
@for content in article.body_items.iter() {
@match content.r#type.as_str() {
"paragraph" => {
p {
(content.content.as_str())
(&content.content)
}
}
t => {
Expand All @@ -90,12 +83,12 @@ pub fn render_legacy_article(
}
},
maud! {
meta property="og:title" content=(article.headline.as_str());
meta property="og:title" content=(&article.headline);
meta property="og:type" content="article";
meta property="og:description" content=(article.description.as_str());
meta property="og:description" content=(&article.description);
meta property="og:url" content=(path);
}
);

Ok(Ok(doc.render().0))
Ok(Ok(doc.render().into_inner()))
}
9 changes: 5 additions & 4 deletions src/routes/markets.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::api::{error::ApiResult, markit::fetch_by_stock_symbol};
use hypertext::{html_elements, maud, GlobalAttributes};
use hypertext::{html_elements, maud, GlobalAttributes, Renderable};

pub fn render_market(client: &ureq::Agent, path: &str) -> ApiResult<String> {
let company = if let Some(end) = path.find('/') {
Expand All @@ -10,16 +10,17 @@ pub fn render_market(client: &ureq::Agent, path: &str) -> ApiResult<String> {

let articles = fetch_by_stock_symbol(client, company)?;

let document = crate::document!(
let doc = crate::document!(
company,
maud! {
(company)
ul {
@for article in articles.articles.iter() {
li { a href=(article.canonical_url.as_str()) { (article.title.as_str()) } }
li { a href=(&article.canonical_url) { (&article.title) } }
}
}
},
);
Ok(document.render().0)

Ok(doc.render().into_inner())
}
9 changes: 9 additions & 0 deletions src/routes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
use hypertext::{Attribute, GlobalAttributes};

pub mod about;
pub mod article;
pub mod internet_news;
pub mod markets;
pub mod search;

trait HtmxAttributes: GlobalAttributes {
#[allow(non_upper_case_globals)]
const property: Attribute = Attribute;
}

impl<T: GlobalAttributes> HtmxAttributes for T {}
Loading

0 comments on commit 6458baa

Please sign in to comment.