Render instance description to HTML
https://codeberg.org/silverpill/mitra-web/issues/3
This commit is contained in:
parent
581e72ce65
commit
4ec5cf0f9b
3 changed files with 49 additions and 25 deletions
|
@ -4,6 +4,7 @@ use serde_json::{to_value, Value};
|
||||||
use crate::config::{BlockchainConfig, Config};
|
use crate::config::{BlockchainConfig, Config};
|
||||||
use crate::ethereum::contracts::ContractSet;
|
use crate::ethereum::contracts::ContractSet;
|
||||||
use crate::mastodon_api::MASTODON_API_VERSION;
|
use crate::mastodon_api::MASTODON_API_VERSION;
|
||||||
|
use crate::utils::markdown::markdown_to_html;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct InstanceStats {
|
struct InstanceStats {
|
||||||
|
@ -32,7 +33,9 @@ pub struct InstanceInfo {
|
||||||
uri: String,
|
uri: String,
|
||||||
title: String,
|
title: String,
|
||||||
short_description: String,
|
short_description: String,
|
||||||
|
// TODO: HTML by default
|
||||||
description: String,
|
description: String,
|
||||||
|
description_html: String,
|
||||||
version: String,
|
version: String,
|
||||||
registrations: bool,
|
registrations: bool,
|
||||||
stats: InstanceStats,
|
stats: InstanceStats,
|
||||||
|
@ -106,6 +109,7 @@ impl InstanceInfo {
|
||||||
title: config.instance_title.clone(),
|
title: config.instance_title.clone(),
|
||||||
short_description: config.instance_short_description.clone(),
|
short_description: config.instance_short_description.clone(),
|
||||||
description: config.instance_description.clone(),
|
description: config.instance_description.clone(),
|
||||||
|
description_html: markdown_to_html(&config.instance_description),
|
||||||
version: get_full_api_version(&config.version),
|
version: get_full_api_version(&config.version),
|
||||||
registrations: config.registrations_open,
|
registrations: config.registrations_open,
|
||||||
stats: InstanceStats {
|
stats: InstanceStats {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::mastodon_api::accounts::types::Account;
|
||||||
use crate::mastodon_api::media::types::Attachment;
|
use crate::mastodon_api::media::types::Attachment;
|
||||||
use crate::models::posts::types::{Post, PostCreateData, Visibility};
|
use crate::models::posts::types::{Post, PostCreateData, Visibility};
|
||||||
use crate::models::profiles::types::DbActorProfile;
|
use crate::models::profiles::types::DbActorProfile;
|
||||||
use crate::utils::markdown::markdown_to_html;
|
use crate::utils::markdown::markdown_lite_to_html;
|
||||||
|
|
||||||
/// https://docs.joinmastodon.org/entities/mention/
|
/// https://docs.joinmastodon.org/entities/mention/
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -170,7 +170,7 @@ impl TryFrom<StatusData> for PostCreateData {
|
||||||
let content = match status_data.content_type.as_str() {
|
let content = match status_data.content_type.as_str() {
|
||||||
"text/html" => status_data.status,
|
"text/html" => status_data.status,
|
||||||
"text/markdown" => {
|
"text/markdown" => {
|
||||||
markdown_to_html(&status_data.status)
|
markdown_lite_to_html(&status_data.status)
|
||||||
.map_err(|_| ValidationError("invalid markdown"))?
|
.map_err(|_| ValidationError("invalid markdown"))?
|
||||||
},
|
},
|
||||||
_ => return Err(ValidationError("unsupported content type")),
|
_ => return Err(ValidationError("unsupported content type")),
|
||||||
|
|
|
@ -19,6 +19,21 @@ pub enum MarkdownError {
|
||||||
Utf8Error(#[from] std::string::FromUtf8Error),
|
Utf8Error(#[from] std::string::FromUtf8Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_comrak_options() -> ComrakOptions {
|
||||||
|
ComrakOptions {
|
||||||
|
extension: ComrakExtensionOptions {
|
||||||
|
autolink: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
parse: ComrakParseOptions::default(),
|
||||||
|
render: ComrakRenderOptions {
|
||||||
|
hardbreaks: true,
|
||||||
|
escape: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn iter_nodes<'a, F>(
|
fn iter_nodes<'a, F>(
|
||||||
node: &'a AstNode<'a>,
|
node: &'a AstNode<'a>,
|
||||||
func: &F,
|
func: &F,
|
||||||
|
@ -48,19 +63,8 @@ fn node_to_markdown<'a>(
|
||||||
/// - bold and italic
|
/// - bold and italic
|
||||||
/// - links and autolinks
|
/// - links and autolinks
|
||||||
/// - inline code and code blocks
|
/// - inline code and code blocks
|
||||||
pub fn markdown_to_html(text: &str) -> Result<String, MarkdownError> {
|
pub fn markdown_lite_to_html(text: &str) -> Result<String, MarkdownError> {
|
||||||
let options = ComrakOptions {
|
let options = build_comrak_options();
|
||||||
extension: ComrakExtensionOptions {
|
|
||||||
autolink: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
parse: ComrakParseOptions::default(),
|
|
||||||
render: ComrakRenderOptions {
|
|
||||||
hardbreaks: true,
|
|
||||||
escape: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let arena = Arena::new();
|
let arena = Arena::new();
|
||||||
let root = parse_document(
|
let root = parse_document(
|
||||||
&arena,
|
&arena,
|
||||||
|
@ -180,14 +184,20 @@ pub fn markdown_to_html(text: &str) -> Result<String, MarkdownError> {
|
||||||
Ok(html)
|
Ok(html)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Full markdown
|
||||||
|
pub fn markdown_to_html(text: &str) -> String {
|
||||||
|
let options = build_comrak_options();
|
||||||
|
comrak::markdown_to_html(text, &options)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_html() {
|
fn test_markdown_lite_to_html() {
|
||||||
let text = "# heading\n\ntest **bold** test *italic* test ~~strike~~ with `code`, <span>html</span> and https://example.com\nnew line\n\ntwo new lines and a list:\n- item 1\n- item 2\n\n>greentext\n\n---\n\nimage: ![logo](logo.png)\n\ncode block:\n```\nlet test\ntest = 1\n```";
|
let text = "# heading\n\ntest **bold** test *italic* test ~~strike~~ with `code`, <span>html</span> and https://example.com\nnew line\n\ntwo new lines and a list:\n- item 1\n- item 2\n\n>greentext\n\n---\n\nimage: ![logo](logo.png)\n\ncode block:\n```\nlet test\ntest = 1\n```";
|
||||||
let html = markdown_to_html(text).unwrap();
|
let html = markdown_lite_to_html(text).unwrap();
|
||||||
let expected_html = concat!(
|
let expected_html = concat!(
|
||||||
r#"<p># heading</p><p>test <strong>bold</strong> test <em>italic</em> test ~~strike~~ with <code>code</code>, <span>html</span> and <a href="https://example.com">https://example.com</a><br>new line</p><p>two new lines and a list:</p><p>- item 1<br>- item 2</p><p>>greentext</p><p>-----</p><p>image: ![logo](logo.png)</p><p>code block:</p>"#,
|
r#"<p># heading</p><p>test <strong>bold</strong> test <em>italic</em> test ~~strike~~ with <code>code</code>, <span>html</span> and <a href="https://example.com">https://example.com</a><br>new line</p><p>two new lines and a list:</p><p>- item 1<br>- item 2</p><p>>greentext</p><p>-----</p><p>image: ![logo](logo.png)</p><p>code block:</p>"#,
|
||||||
"<pre><code>let test\ntest = 1\n</code></pre>",
|
"<pre><code>let test\ntest = 1\n</code></pre>",
|
||||||
|
@ -196,31 +206,41 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_html_ordered_list() {
|
fn test_markdown_lite_to_html_ordered_list() {
|
||||||
let text = "1. item 1\n2. item 2\n";
|
let text = "1. item 1\n2. item 2\n";
|
||||||
let html = markdown_to_html(text).unwrap();
|
let html = markdown_lite_to_html(text).unwrap();
|
||||||
let expected_html = r#"<p>1. item 1<br>2. item 2</p>"#;
|
let expected_html = r#"<p>1. item 1<br>2. item 2</p>"#;
|
||||||
assert_eq!(html, expected_html);
|
assert_eq!(html, expected_html);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_html_mention() {
|
fn test_markdown_lite_to_html_mention() {
|
||||||
let text = "@user@example.org test";
|
let text = "@user@example.org test";
|
||||||
let html = markdown_to_html(text).unwrap();
|
let html = markdown_lite_to_html(text).unwrap();
|
||||||
assert_eq!(html, format!("<p>{}</p>", text));
|
assert_eq!(html, format!("<p>{}</p>", text));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_html_hashtag() {
|
fn test_markdown_lite_to_html_hashtag() {
|
||||||
let text = "#hashtag test";
|
let text = "#hashtag test";
|
||||||
let html = markdown_to_html(text).unwrap();
|
let html = markdown_lite_to_html(text).unwrap();
|
||||||
assert_eq!(html, format!("<p>{}</p>", text));
|
assert_eq!(html, format!("<p>{}</p>", text));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_html_object_link() {
|
fn test_markdown_lite_to_html_object_link() {
|
||||||
let text = "[[https://example.org/objects/1]] test";
|
let text = "[[https://example.org/objects/1]] test";
|
||||||
let html = markdown_to_html(text).unwrap();
|
let html = markdown_lite_to_html(text).unwrap();
|
||||||
assert_eq!(html, format!("<p>{}</p>", text));
|
assert_eq!(html, format!("<p>{}</p>", text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_markdown_to_html() {
|
||||||
|
let text = "# heading\n\ntest";
|
||||||
|
let html = markdown_to_html(text);
|
||||||
|
assert_eq!(
|
||||||
|
html,
|
||||||
|
"<h1>heading</h1>\n<p>test</p>\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue