mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-01-19 14:17:59 +01:00
implement >>image syntax
This commit is contained in:
parent
35a227e938
commit
e864a99a43
6 changed files with 139 additions and 34 deletions
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
42
native/philomena/Cargo.lock
generated
42
native/philomena/Cargo.lock
generated
|
@ -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",
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue