commit: dd3d13561164b55a98596a30793d2b2ae16ac016
Author: Stephen M. Pallen <smpallen99@yahoo.com>
Date:   Wed, 29 Mar 2017 10:11:22 -0400
create project and some linker impl
Diffstat:
7 files changed, 184 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -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
diff --git a/README.md b/README.md
@@ -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).
+
diff --git a/config/config.exs b/config/config.exs
@@ -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"
diff --git a/lib/auto_linker.ex b/lib/auto_linker.ex
@@ -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
diff --git a/mix.exs b/mix.exs
@@ -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
diff --git a/test/auto_linker_test.exs b/test/auto_linker_test.exs
@@ -0,0 +1,8 @@
+defmodule AutoLinkerTest do
+  use ExUnit.Case
+  doctest AutoLinker
+
+  test "the truth" do
+    assert 1 + 1 == 2
+  end
+end
diff --git a/test/test_helper.exs b/test/test_helper.exs
@@ -0,0 +1 @@
+ExUnit.start()