implement >>image syntax

This commit is contained in:
Luna D 2021-09-19 23:17:50 +02:00
parent 35a227e938
commit e864a99a43
No known key found for this signature in database
GPG key ID: 81AF416F2CC36FC8
6 changed files with 139 additions and 34 deletions

View file

@ -2,8 +2,8 @@ defmodule Philomena.Markdown do
@markdown_chars ~r/[\*_\[\]\(\)\^`\%\\~<>#\|]/ @markdown_chars ~r/[\*_\[\]\(\)\^`\%\\~<>#\|]/
# When your NIF is loaded, it will override this function. # When your NIF is loaded, it will override this function.
def to_html(text), do: Philomena.Native.markdown_to_html(text) def to_html(text, replacements), do: Philomena.Native.markdown_to_html(text, replacements)
def to_html_unsafe(text), do: Philomena.Native.markdown_to_html_unsafe(text) def to_html_unsafe(text, replacements), do: Philomena.Native.markdown_to_html_unsafe(text, replacements)
def escape_markdown(text) do def escape_markdown(text) do
@markdown_chars @markdown_chars

View file

@ -2,8 +2,8 @@ defmodule Philomena.Native do
use Rustler, otp_app: :philomena use Rustler, otp_app: :philomena
# Markdown # Markdown
def markdown_to_html(_text), do: :erlang.nif_error(:nif_not_loaded) def markdown_to_html(_text, _replacements), do: :erlang.nif_error(:nif_not_loaded)
def markdown_to_html_unsafe(_text), do: :erlang.nif_error(:nif_not_loaded) def markdown_to_html_unsafe(_text, _replacements), do: :erlang.nif_error(:nif_not_loaded)
# Camo # Camo
def camo_image_url(_uri), do: :erlang.nif_error(:nif_not_loaded) def camo_image_url(_uri), do: :erlang.nif_error(:nif_not_loaded)

View file

@ -1,7 +1,96 @@
defmodule PhilomenaWeb.MarkdownRenderer do defmodule PhilomenaWeb.MarkdownRenderer do
alias Philomena.Markdown alias Philomena.Markdown
alias Philomena.Images.Image
alias Philomena.Repo
import Phoenix.HTML
import Phoenix.HTML.Link
import Ecto.Query
def render(text, _conn) do @image_view Module.concat(["PhilomenaWeb.ImageView"])
Markdown.to_html(text)
def render(text, conn) do
images = find_images(text)
representations = render_representations(images, conn)
Markdown.to_html(text, representations)
end
defp find_images(text) do
Regex.scan(~r/>>(\d+)([tsp])?/, text, capture: :all_but_first)
|> Enum.map(fn matches -> [Enum.at(matches, 0) |> String.to_integer(), Enum.at(matches, 1) || ""] end)
|> Enum.filter(fn m -> Enum.at(m, 0) < 2_147_483_647 end)
end
defp load_images(images) do
ids = Enum.map(images, fn m -> Enum.at(m, 0) end)
Image
|> where([i], i.id in ^ids)
|> preload(tags: :aliases)
|> Repo.all()
|> Map.new(&{&1.id, &1})
end
defp link_suffix(image) do
cond do
not is_nil(image.duplicate_id) ->
" (merged)"
image.hidden_from_users ->
" (deleted)"
true ->
""
end
end
defp render_representations(images, conn) do
loaded_images = load_images(images)
images
|> Enum.map(fn group ->
img = loaded_images[Enum.at(group, 0)]
text = "#{Enum.at(group, 0)}#{Enum.at(group, 1)}"
rendered = cond do
img != nil ->
case group do
[_id, "p"] when not img.hidden_from_users ->
Phoenix.View.render(@image_view, "_image_target.html",
image: img,
size: :medium,
conn: conn
)
|> safe_to_string()
[_id, "t"] when not img.hidden_from_users ->
Phoenix.View.render(@image_view, "_image_target.html",
image: img,
size: :small,
conn: conn
)
|> safe_to_string()
[_id, "s"] when not img.hidden_from_users ->
Phoenix.View.render(@image_view, "_image_target.html",
image: img,
size: :thumb_small,
conn: conn
)
|> safe_to_string()
[_id, ""] ->
link(">>#{img.id}#{link_suffix(img)}", to: "/images/#{img.id}")
|> safe_to_string()
[_id, suffix] when suffix in ["t", "s", "p"] ->
link(">>#{img.id}#{suffix}#{link_suffix(img)}", to: "/images/#{img.id}")
|> safe_to_string()
[id, suffix] -> # This condition should never trigger, but let's leave it here just in case.
">>#{id}#{suffix}"
end
true ->
">>#{text}"
end
[text, rendered]
end)
|> Map.new(fn [id, html] -> {id, html} end)
end end
end end

View file

@ -87,9 +87,9 @@ dependencies = [
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.7.0" version = "3.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538"
[[package]] [[package]]
name = "byte-tools" name = "byte-tools"
@ -143,7 +143,7 @@ dependencies = [
[[package]] [[package]]
name = "comrak" name = "comrak"
version = "0.12.1" version = "0.12.1"
source = "git+https://github.com/philomena-dev/comrak?branch=main#8160b121f3ccfa5b284c03eedb71add59c3fbb9f" source = "git+https://github.com/philomena-dev/comrak?branch=main#3ecac2425999185fee33991dec6efbe812d82196"
dependencies = [ dependencies = [
"clap", "clap",
"entities", "entities",
@ -306,9 +306,9 @@ dependencies = [
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.54" version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1866b355d9c878e5e607473cbe3f63282c0b7aad2db1dbebf55076c686918254" checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
@ -327,9 +327,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.101" version = "0.2.102"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103"
[[package]] [[package]]
name = "line-wrap" name = "line-wrap"
@ -785,9 +785,9 @@ checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.8" version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
@ -853,9 +853,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.77" version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e68338db6becec24d3c7977b5bf8a48be992c934b5d07177e3931f5dc9b076c" checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"wasm-bindgen-macro", "wasm-bindgen-macro",
@ -863,9 +863,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.77" version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f34c405b4f0658583dba0c1c7c9b694f3cac32655db463b56c254a1c75269523" checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"lazy_static", "lazy_static",
@ -878,9 +878,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.77" version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d5a6580be83b19dc570a8f9c324251687ab2184e57086f71625feb57ec77c8" checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@ -888,9 +888,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.77" version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3775a030dc6f5a0afd8a84981a21cc92a781eb429acef9ecce476d0c9113e92" checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -901,15 +901,15 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.77" version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c279e376c7a8e8752a8f1eaa35b7b0bee6bb9fb0cdacfa97cc3f1f289c87e2b4" checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
[[package]] [[package]]
name = "web-sys" name = "web-sys"
version = "0.3.54" version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a84d70d1ec7d2da2d26a5bd78f4bca1b8c3254805363ce743b7a05bc30d195a" checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
dependencies = [ dependencies = [
"js-sys", "js-sys",
"wasm-bindgen", "wasm-bindgen",

View file

@ -1,4 +1,5 @@
use jemallocator::Jemalloc; use jemallocator::Jemalloc;
use rustler::Term;
mod camo; mod camo;
mod markdown; mod markdown;
@ -14,13 +15,13 @@ rustler::init! {
// Markdown NIF wrappers. // Markdown NIF wrappers.
#[rustler::nif(schedule = "DirtyCpu")] #[rustler::nif(schedule = "DirtyCpu")]
fn markdown_to_html(input: String) -> String { fn markdown_to_html<'a>(input: String, reps: Term<'a>) -> String {
markdown::to_html(input) markdown::to_html(input, reps)
} }
#[rustler::nif(schedule = "DirtyCpu")] #[rustler::nif(schedule = "DirtyCpu")]
fn markdown_to_html_unsafe(input: String) -> String { fn markdown_to_html_unsafe<'a>(input: String, reps: Term<'a>) -> String {
markdown::to_html_unsafe(input) markdown::to_html_unsafe(input, reps)
} }
// Camo NIF wrappers. // Camo NIF wrappers.

View file

@ -1,5 +1,7 @@
use comrak::ComrakOptions; use comrak::ComrakOptions;
use crate::camo; use crate::camo;
use rustler::{MapIterator, Term};
use std::collections::HashMap;
fn common_options() -> ComrakOptions { fn common_options() -> ComrakOptions {
let mut options = ComrakOptions::default(); let mut options = ComrakOptions::default();
@ -13,21 +15,34 @@ fn common_options() -> ComrakOptions {
options.render.hardbreaks = true; options.render.hardbreaks = true;
options.render.github_pre_lang = true; options.render.github_pre_lang = true;
options.extension.camoifier = Some(|s| camo::image_url(s).unwrap_or_else(|| String::from(""))); options.extension.camoifier = Some(|s| camo::image_url(s).unwrap_or(String::from("")));
options options
} }
pub fn to_html(input: String) -> String { fn map_to_hashmap<'a>(map: Term<'a>) -> Option<HashMap<String, String>> {
Some(MapIterator::new(map)?.map(|(key, value)| {
let key: String = key.decode().unwrap_or_else(|_| String::from(""));
let value: String = value.decode().unwrap_or_else(|_| String::from(""));
(key, value)
}).collect())
}
pub fn to_html<'a>(input: String, reps: Term<'a>) -> String {
let mut options = common_options(); let mut options = common_options();
options.render.escape = true; options.render.escape = true;
options.extension.philomena_replacements = map_to_hashmap(reps);
comrak::markdown_to_html(&input, &options) comrak::markdown_to_html(&input, &options)
} }
pub fn to_html_unsafe(input: String) -> String { pub fn to_html_unsafe<'a>(input: String, reps: Term<'a>) -> String {
let mut options = common_options(); let mut options = common_options();
options.render.unsafe_ = true; options.render.unsafe_ = true;
options.extension.philomena_replacements = map_to_hashmap(reps);
comrak::markdown_to_html(&input, &options) comrak::markdown_to_html(&input, &options)
} }