create project and some linker impl
This commit is contained in:
commit
dd3d135611
7 changed files with 184 additions and 0 deletions
20
.gitignore
vendored
Normal file
20
.gitignore
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# The directory Mix will write compiled artifacts to.
|
||||||
|
/_build
|
||||||
|
|
||||||
|
# If you run "mix test --cover", coverage assets end up here.
|
||||||
|
/cover
|
||||||
|
|
||||||
|
# The directory Mix downloads your dependencies sources to.
|
||||||
|
/deps
|
||||||
|
|
||||||
|
# Where 3rd-party dependencies like ExDoc output generated docs.
|
||||||
|
/doc
|
||||||
|
|
||||||
|
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||||
|
/.fetch
|
||||||
|
|
||||||
|
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||||
|
erl_crash.dump
|
||||||
|
|
||||||
|
# Also ignore archive artifacts (built via "mix archive.build").
|
||||||
|
*.ez
|
19
README.md
Normal file
19
README.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# AutoLinker
|
||||||
|
|
||||||
|
**TODO: Add description**
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
||||||
|
by adding `auto_linker` to your list of dependencies in `mix.exs`:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
def deps do
|
||||||
|
[{:auto_linker, "~> 0.1.0"}]
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
||||||
|
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
||||||
|
be found at [https://hexdocs.pm/auto_linker](https://hexdocs.pm/auto_linker).
|
||||||
|
|
30
config/config.exs
Normal file
30
config/config.exs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# This file is responsible for configuring your application
|
||||||
|
# and its dependencies with the aid of the Mix.Config module.
|
||||||
|
use Mix.Config
|
||||||
|
|
||||||
|
# This configuration is loaded before any dependency and is restricted
|
||||||
|
# to this project. If another project depends on this project, this
|
||||||
|
# file won't be loaded nor affect the parent project. For this reason,
|
||||||
|
# if you want to provide default values for your application for
|
||||||
|
# 3rd-party users, it should be done in your "mix.exs" file.
|
||||||
|
|
||||||
|
# You can configure for your application as:
|
||||||
|
#
|
||||||
|
# config :auto_linker, key: :value
|
||||||
|
#
|
||||||
|
# And access this configuration in your application as:
|
||||||
|
#
|
||||||
|
# Application.get_env(:auto_linker, :key)
|
||||||
|
#
|
||||||
|
# Or configure a 3rd-party app:
|
||||||
|
#
|
||||||
|
# config :logger, level: :info
|
||||||
|
#
|
||||||
|
|
||||||
|
# It is also possible to import configuration files, relative to this
|
||||||
|
# directory. For example, you can emulate configuration per environment
|
||||||
|
# by uncommenting the line below and defining dev.exs, test.exs and such.
|
||||||
|
# Configuration from the imported file will override the ones defined
|
||||||
|
# here (which is why it is important to import them last).
|
||||||
|
#
|
||||||
|
# import_config "#{Mix.env}.exs"
|
73
lib/auto_linker.ex
Normal file
73
lib/auto_linker.ex
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
defmodule AutoLinker do
|
||||||
|
@moduledoc """
|
||||||
|
Documentation for AutoLinker.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def link(text, opts \\ []) do
|
||||||
|
opts =
|
||||||
|
:url_linker
|
||||||
|
|> Application.get_all_env()
|
||||||
|
|> Keyword.merge(opts)
|
||||||
|
|
||||||
|
# rel = opts[:rel] || "noopener noreferrer"
|
||||||
|
# new_window if opts[:target]
|
||||||
|
end
|
||||||
|
|
||||||
|
# state = {buffer, acc, state}
|
||||||
|
defp parse(text, opts) do
|
||||||
|
parse(text, Keyword.get(opts, :scheme, false), {"", "", false})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse("", _scheme, opts ,{_, acc, _}), do: acc
|
||||||
|
|
||||||
|
defp parse(text, scheme, opts, {buffer, acc, state}) do
|
||||||
|
acc <> create_link(text, opts)
|
||||||
|
parse("", scheme, opts, {buffer, acc, state})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp create_link(url, opts) do
|
||||||
|
[]
|
||||||
|
|> build_attrs(url, opts, :rel)
|
||||||
|
|> build_attrs(url, opts, :target)
|
||||||
|
|> build_attrs(url, opts, :scheme)
|
||||||
|
|> build_url(url, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp build_attrs(attrs, _, opts, :rel) do
|
||||||
|
if rel = Keyword.get(opts, :rel, "noopener noreferrer"),
|
||||||
|
do: [{:rel, rel} | attrs], else: attrs
|
||||||
|
end
|
||||||
|
defp build_attrs(attrs, _, opts, :target) do
|
||||||
|
if Keyword.get(opts, :new_window, true),
|
||||||
|
do: [{:target, :_blank} | attrs], else: attrs
|
||||||
|
end
|
||||||
|
defp build_attrs(attrs, url, opts, :scheme) do
|
||||||
|
if String.starts_with?(url, ["http://", "https://"]),
|
||||||
|
do: [{:href, url} | attrs], else: [{:href, "http://" <> url} | attrs]
|
||||||
|
end
|
||||||
|
|
||||||
|
defp format_url(attrs, url, opts) do
|
||||||
|
url =
|
||||||
|
url
|
||||||
|
|> strip_prefix(Keyword.get(opts, :strip_prefix, true))
|
||||||
|
|> truncate(Keyword.get(opts, :truncate, false))
|
||||||
|
attrs =
|
||||||
|
attrs
|
||||||
|
|> Enum.map(fn {key, value} -> ~s(#{key}='#{value}') end)
|
||||||
|
|> Enum.join(" ")
|
||||||
|
"<a #{attrs}>" <> url <> "</a>"
|
||||||
|
end
|
||||||
|
|
||||||
|
defp truncate(url, false), do: url
|
||||||
|
defp truncate(url, len) when len < 3, do: url
|
||||||
|
defp truncate(url, len) do
|
||||||
|
if String.length(url) > len, do: String.slice(url, 0, len - 2) <> "..", else: url
|
||||||
|
end
|
||||||
|
|
||||||
|
defp strip_prefix(url, true) do
|
||||||
|
url
|
||||||
|
|> String.replace(~r/^https?:\/\//, "")
|
||||||
|
|> String.replace(~r/^www\./, "")
|
||||||
|
end
|
||||||
|
defp strip_prefix(url, _), do: url
|
||||||
|
end
|
33
mix.exs
Normal file
33
mix.exs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
defmodule AutoLinker.Mixfile do
|
||||||
|
use Mix.Project
|
||||||
|
|
||||||
|
def project do
|
||||||
|
[app: :auto_linker,
|
||||||
|
version: "0.1.0",
|
||||||
|
elixir: "~> 1.4",
|
||||||
|
build_embedded: Mix.env == :prod,
|
||||||
|
start_permanent: Mix.env == :prod,
|
||||||
|
deps: deps()]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Configuration for the OTP application
|
||||||
|
#
|
||||||
|
# Type "mix help compile.app" for more information
|
||||||
|
def application do
|
||||||
|
# Specify extra applications you'll use from Erlang/Elixir
|
||||||
|
[extra_applications: [:logger]]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Dependencies can be Hex packages:
|
||||||
|
#
|
||||||
|
# {:my_dep, "~> 0.3.0"}
|
||||||
|
#
|
||||||
|
# Or git/path repositories:
|
||||||
|
#
|
||||||
|
# {:my_dep, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||||
|
#
|
||||||
|
# Type "mix help deps" for more examples and options
|
||||||
|
defp deps do
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
8
test/auto_linker_test.exs
Normal file
8
test/auto_linker_test.exs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
defmodule AutoLinkerTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
doctest AutoLinker
|
||||||
|
|
||||||
|
test "the truth" do
|
||||||
|
assert 1 + 1 == 2
|
||||||
|
end
|
||||||
|
end
|
1
test/test_helper.exs
Normal file
1
test/test_helper.exs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ExUnit.start()
|
Reference in a new issue