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/[\*_\[\]\(\)\^`\%\\~<>#\|]/
|
||||
|
||||
# When your NIF is loaded, it will override this function.
|
||||
def to_html(text), do: Philomena.Native.markdown_to_html(text)
|
||||
def to_html_unsafe(text), do: Philomena.Native.markdown_to_html_unsafe(text)
|
||||
def to_html(text, replacements), do: Philomena.Native.markdown_to_html(text, replacements)
|
||||
def to_html_unsafe(text, replacements), do: Philomena.Native.markdown_to_html_unsafe(text, replacements)
|
||||
|
||||
def escape_markdown(text) do
|
||||
@markdown_chars
|
||||
|
|
|
@ -2,8 +2,8 @@ defmodule Philomena.Native do
|
|||
use Rustler, otp_app: :philomena
|
||||
|
||||
# Markdown
|
||||
def markdown_to_html(_text), do: :erlang.nif_error(:nif_not_loaded)
|
||||
def markdown_to_html_unsafe(_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, _replacements), do: :erlang.nif_error(:nif_not_loaded)
|
||||
|
||||
# Camo
|
||||
def camo_image_url(_uri), do: :erlang.nif_error(:nif_not_loaded)
|
||||
|
|
|
@ -1,7 +1,96 @@
|
|||
defmodule PhilomenaWeb.MarkdownRenderer do
|
||||
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
|
||||
Markdown.to_html(text)
|
||||
@image_view Module.concat(["PhilomenaWeb.ImageView"])
|
||||
|
||||
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
|
||||
|
|
42
native/philomena/Cargo.lock
generated
42
native/philomena/Cargo.lock
generated
|
@ -87,9 +87,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.7.0"
|
||||
version = "3.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
|
||||
checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538"
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
|
@ -143,7 +143,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "comrak"
|
||||
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 = [
|
||||
"clap",
|
||||
"entities",
|
||||
|
@ -306,9 +306,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.54"
|
||||
version = "0.3.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1866b355d9c878e5e607473cbe3f63282c0b7aad2db1dbebf55076c686918254"
|
||||
checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -327,9 +327,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.101"
|
||||
version = "0.2.102"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21"
|
||||
checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103"
|
||||
|
||||
[[package]]
|
||||
name = "line-wrap"
|
||||
|
@ -785,9 +785,9 @@ checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
|
@ -853,9 +853,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.77"
|
||||
version = "0.2.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e68338db6becec24d3c7977b5bf8a48be992c934b5d07177e3931f5dc9b076c"
|
||||
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
|
@ -863,9 +863,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.77"
|
||||
version = "0.2.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f34c405b4f0658583dba0c1c7c9b694f3cac32655db463b56c254a1c75269523"
|
||||
checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
|
@ -878,9 +878,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.77"
|
||||
version = "0.2.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9d5a6580be83b19dc570a8f9c324251687ab2184e57086f71625feb57ec77c8"
|
||||
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
@ -888,9 +888,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.77"
|
||||
version = "0.2.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3775a030dc6f5a0afd8a84981a21cc92a781eb429acef9ecce476d0c9113e92"
|
||||
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -901,15 +901,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.77"
|
||||
version = "0.2.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c279e376c7a8e8752a8f1eaa35b7b0bee6bb9fb0cdacfa97cc3f1f289c87e2b4"
|
||||
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.54"
|
||||
version = "0.3.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a84d70d1ec7d2da2d26a5bd78f4bca1b8c3254805363ce743b7a05bc30d195a"
|
||||
checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use jemallocator::Jemalloc;
|
||||
use rustler::Term;
|
||||
|
||||
mod camo;
|
||||
mod markdown;
|
||||
|
@ -14,13 +15,13 @@ rustler::init! {
|
|||
// Markdown NIF wrappers.
|
||||
|
||||
#[rustler::nif(schedule = "DirtyCpu")]
|
||||
fn markdown_to_html(input: String) -> String {
|
||||
markdown::to_html(input)
|
||||
fn markdown_to_html<'a>(input: String, reps: Term<'a>) -> String {
|
||||
markdown::to_html(input, reps)
|
||||
}
|
||||
|
||||
#[rustler::nif(schedule = "DirtyCpu")]
|
||||
fn markdown_to_html_unsafe(input: String) -> String {
|
||||
markdown::to_html_unsafe(input)
|
||||
fn markdown_to_html_unsafe<'a>(input: String, reps: Term<'a>) -> String {
|
||||
markdown::to_html_unsafe(input, reps)
|
||||
}
|
||||
|
||||
// Camo NIF wrappers.
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use comrak::ComrakOptions;
|
||||
use crate::camo;
|
||||
use rustler::{MapIterator, Term};
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn common_options() -> ComrakOptions {
|
||||
let mut options = ComrakOptions::default();
|
||||
|
@ -13,21 +15,34 @@ fn common_options() -> ComrakOptions {
|
|||
options.render.hardbreaks = 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
|
||||
}
|
||||
|
||||
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();
|
||||
options.render.escape = true;
|
||||
|
||||
options.extension.philomena_replacements = map_to_hashmap(reps);
|
||||
|
||||
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();
|
||||
options.render.unsafe_ = true;
|
||||
|
||||
options.extension.philomena_replacements = map_to_hashmap(reps);
|
||||
|
||||
comrak::markdown_to_html(&input, &options)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue