@ -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 |
@ -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). | |||||
@ -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" |
@ -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 |
@ -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 |
@ -0,0 +1,8 @@ | |||||
defmodule AutoLinkerTest do | |||||
use ExUnit.Case | |||||
doctest AutoLinker | |||||
test "the truth" do | |||||
assert 1 + 1 == 2 | |||||
end | |||||
end |
@ -0,0 +1 @@ | |||||
ExUnit.start() |