change how backlinks work
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-11-04 23:27:00 -04:00
parent 1b49b668b3
commit e2378279d7
20 changed files with 293 additions and 212 deletions

View File

@ -8,7 +8,7 @@ defmodule MemexWeb.CoreComponents do
alias Memex.{Accounts, Accounts.Invite, Accounts.User}
alias Memex.Contexts.Context
alias Memex.Notes.Note
alias Memex.Pipelines.Steps.Step
alias Memex.Pipelines.{Pipeline, Steps.Step}
alias Phoenix.HTML
alias Phoenix.LiveView.JS
@ -130,53 +130,118 @@ defmodule MemexWeb.CoreComponents do
def step_content(assigns)
defp add_links_to_content(content, data_qa_prefix) do
# replace links
attr :pipeline, Pipeline, required: true
# link regex from
# https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url
# and modified with additional schemes from
# https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml
def pipeline_content(assigns)
content =
Regex.replace(
~r<((file|git|https?|ipfs|ipns|irc|jabber|magnet|mailto|mumble|tel|udp|xmpp):\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*))>,
content,
fn _whole_match, link ->
link =
HTML.Link.link(
link,
to: link,
class: "link inline",
target: "_blank",
rel: "noopener noreferrer"
)
|> HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
defp display_backlinks(record) do
record
|> get_text()
|> replace_links(record)
|> replace_triple_backlinks(record)
|> replace_double_backlinks(record)
|> replace_single_backlinks(record)
|> HTML.raw()
end
"</p>#{link}<p class=\"inline\">"
end
)
defp get_text(%{content: content}), do: content
defp get_text(%{description: description}), do: description
defp get_text(_fallthrough), do: ""
content =
Regex.replace(
~r/\[\[([\p{L}\p{N}\-]+)\]\]/,
content,
fn _whole_match, slug ->
link =
HTML.Link.link(
"[[#{slug}]]",
to: ~p"/note/#{slug}",
class: "link inline",
data: [qa: "#{data_qa_prefix}-#{slug}"]
)
|> HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
# link regex from
# https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url
# and modified with additional schemes from
# https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml
defp replace_links(content, _record) do
Regex.replace(
~r<((file|git|https?|ipfs|ipns|irc|jabber|magnet|mailto|mumble|tel|udp|xmpp):\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*))>,
content,
fn _whole_match, link ->
link =
HTML.Link.link(
link,
to: link,
class: "link inline",
target: "_blank",
rel: "noopener noreferrer"
)
|> HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
"</p>#{link}<p class=\"inline\">"
end
)
"</p>#{link}<p class=\"inline\">"
end
)
end
content |> HTML.raw()
defp replace_triple_backlinks(content, _record) do
Regex.replace(
~r/(^|[^\[])\[\[\[([\p{L}\p{N}\-]+)\]\]\]($|[^\]])/,
content,
fn _whole_match, prefix, slug, suffix ->
link =
HTML.Link.link(
"[[[#{slug}]]]",
to: ~p"/note/#{slug}",
class: "link inline"
)
|> HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
"#{prefix}</p>#{link}<p class=\"inline\">#{suffix}"
end
)
end
defp replace_double_backlinks(content, record) do
Regex.replace(
~r/(^|[^\[])\[\[([\p{L}\p{N}\-]+)\]\]($|[^\]])/,
content,
fn _whole_match, prefix, slug, suffix ->
target =
case record do
%Pipeline{} -> ~p"/context/#{slug}"
%Step{} -> ~p"/context/#{slug}"
_context -> ~p"/note/#{slug}"
end
link =
HTML.Link.link(
"[[#{slug}]]",
to: target,
class: "link inline"
)
|> HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
"#{prefix}</p>#{link}<p class=\"inline\">#{suffix}"
end
)
end
defp replace_single_backlinks(content, record) do
Regex.replace(
~r/(^|[^\[])\[([\p{L}\p{N}\-]+)\]($|[^\]])/,
content,
fn _whole_match, prefix, slug, suffix ->
target =
case record do
%Pipeline{} -> ~p"/pipeline/#{slug}"
%Step{} -> ~p"/pipeline/#{slug}"
%Context{} -> ~p"/context/#{slug}"
_note -> ~p"/note/#{slug}"
end
link =
HTML.Link.link(
"[#{slug}]",
to: target,
class: "link inline"
)
|> HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
"#{prefix}</p>#{link}<p class=\"inline\">#{suffix}"
end
)
end
end

View File

@ -4,4 +4,4 @@
phx-update="ignore"
readonly
phx-no-format
><p class="inline"><%= add_links_to_content(@context.content, "context-note") %></p></div>
><p class="inline"><%= display_backlinks(@context) %></p></div>

View File

@ -4,4 +4,4 @@
phx-update="ignore"
readonly
phx-no-format
><p class="inline"><%= add_links_to_content(@note.content, "note-link") %></p></div>
><p class="inline"><%= display_backlinks(@note) %></p></div>

View File

@ -0,0 +1,7 @@
<div
id={"show-pipeline-description-#{@pipeline.id}"}
class="input input-primary h-32 min-h-32 inline-block whitespace-pre-wrap overflow-x-hidden overflow-y-auto resize-y"
phx-update="ignore"
readonly
phx-no-format
><p class="inline"><%= display_backlinks(@pipeline) %></p></div>

View File

@ -4,4 +4,4 @@
phx-update="ignore"
readonly
phx-no-format
><p class="inline"><%= add_links_to_content(@step.content, "step-context") %></p></div>
><p class="inline"><%= display_backlinks(@step) %></p></div>

View File

@ -21,8 +21,10 @@
id: "context-form-content",
class: "input input-primary h-64 min-h-64",
phx_update: "ignore",
placeholder: gettext("use [[note-slug]] to link to a note"),
aria_label: gettext("use [[note-slug]] to link to a note"),
placeholder:
gettext("use [[note-slug]] to link to a note or [context-slug] to link to a context"),
aria_label:
gettext("use [[note-slug]] to link to a note or [context-slug] to link to a context"),
phx_debounce: 300
) %>
<%= error_tag(f, :content) %>

View File

@ -21,8 +21,8 @@
id: "note-form-content",
class: "input input-primary h-64 min-h-64",
phx_update: "ignore",
placeholder: gettext("content"),
aria_label: gettext("content"),
placeholder: gettext("use [note-slug] to link to a note"),
aria_label: gettext("use [note-slug] to link to a note"),
phx_debounce: 300
) %>
<%= error_tag(f, :content) %>

View File

@ -21,8 +21,14 @@
id: "pipeline-form-description",
class: "input input-primary h-64 min-h-64",
phx_update: "ignore",
placeholder: gettext("description"),
aria_label: gettext("description"),
placeholder:
gettext(
"use [[[note-slug]]] to link to a note or use [[context-slug]] to link to a context or [pipeline-slug] to link to a pipeline"
),
aria_label:
gettext(
"use [[[note-slug]]] to link to a note or use [[context-slug]] to link to a context or [pipeline-slug] to link to a pipeline"
),
phx_debounce: 300
) %>
<%= error_tag(f, :description) %>

View File

@ -9,14 +9,7 @@
</.link>
</div>
<textarea
:if={@pipeline.description}
id="show-pipeline-description"
class="input input-primary h-32 min-h-32"
phx-update="ignore"
readonly
phx-no-format
><%= @pipeline.description %></textarea>
<.pipeline_content pipeline={@pipeline} />
<p class="self-end">
<%= gettext("Visibility: %{visibility}", visibility: @pipeline.visibility) %>

View File

@ -21,8 +21,14 @@
id: "step-form-content",
class: "input input-primary h-64 min-h-64",
phx_update: "ignore",
placeholder: gettext("use [[context-slug]] to link to a context"),
aria_label: gettext("use [[context-slug]] to link to a context"),
placeholder:
gettext(
"use [[[note-slug]]] to link to a note or use [[context-slug]] to link to a context or [pipeline-slug] to link to a pipeline"
),
aria_label:
gettext(
"use [[[note-slug]]] to link to a note or use [[context-slug]] to link to a context or [pipeline-slug] to link to a pipeline"
),
phx_debounce: 300
) %>
<%= error_tag(f, :content) %>