@ -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() |