diff --git a/CHANGELOG b/CHANGELOG index e69de29..9a86229 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -0,0 +1,5 @@ +# Change Log + +## [0.1.0] - 2017-02-25 + +Initial release. diff --git a/README.md b/README.md index 2408416..dfafd8f 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,29 @@ [![Inline docs](http://inch-ci.org/github/r8/elixir-oembed.svg?branch=master&style=flat)](http://inch-ci.org/github/r8/elixir-oembed) [![Ebert](https://ebertapp.io/github/r8/elixir-oembed.svg)](https://ebertapp.io/github/r8/elixir-oembed) -Work in progress +oEmbed consumer library for Elixir applications. -oEmbed consumer for Elixir +> oEmbed is a format for allowing an embedded representation of a URL on third party sites. The simple API allows a website to display embedded content (such as photos or videos) when a user posts a link to that resource, without having to parse the resource directly. +> -- See [oembed.com](http://oembed.com) for more info about the protocol. + +This library supports any discoverable oEmbed endpoint and some other services via custom adapters. +Among them: + + - Instagram + - Pinterest + +## Installation + +Add `oembed` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [{:oembed, "~> 0.1.0"}] +end +``` + +## Usage + +```elixir +{:ok, result} = OEmbed.for("https://www.youtube.com/watch?v=dQw4w9WgXcQ") +``` diff --git a/lib/oembed.ex b/lib/oembed.ex index 404e222..24d710c 100644 --- a/lib/oembed.ex +++ b/lib/oembed.ex @@ -1,8 +1,27 @@ defmodule OEmbed do @moduledoc """ - oEmbed consumer for Elixir. + oEmbed consumer library for Elixir applications. + + ## Usage + + ```elixir + {:ok, result} = OEmbed.for("https://www.youtube.com/watch?v=dQw4w9WgXcQ") + ``` """ + @core_providers [OEmbed.InstagramProvider, + OEmbed.PinterestProvider, + OEmbed.DiscoverableProvider] + + @doc """ + Get oEmbed structure for given URL. + + ## Example + + ```elixir + {:ok, result} = OEmbed.for("https://www.youtube.com/watch?v=dQw4w9WgXcQ") + ``` + """ def for(url) do case Enum.find(get_providers(), fn(provider) -> provider.provides?(url) end) do nil -> @@ -13,8 +32,6 @@ defmodule OEmbed do end defp get_providers do - [OEmbed.InstagramProvider, - OEmbed.PinterestProvider, - OEmbed.DiscoverProvider] + @core_providers end end diff --git a/lib/oembed/provider.ex b/lib/oembed/provider.ex index 48f3d09..1e78ee0 100644 --- a/lib/oembed/provider.ex +++ b/lib/oembed/provider.ex @@ -1,29 +1,37 @@ defmodule OEmbed.Provider do + @moduledoc """ + oEmbed provider behaviour. + """ + defmacro __using__(_) do quote do import OEmbed.Provider - @behaviour OEmbed.Provider - end - end + alias OEmbed.Link + alias OEmbed.Photo + alias OEmbed.Rich + alias OEmbed.Video - alias OEmbed.{Link, Photo, Rich, Video} + @behaviour OEmbed.Provider - @callback provides?(String.t) :: boolean + defp get_oembed(url) do + with {:ok, %HTTPoison.Response{body: body}} <- HTTPoison.get(url, [], [follow_redirect: true, ssl: [{:versions, [:'tlsv1.2']}]]), + {:ok, struct} <- Poison.decode(body), + resource <- get_resource(struct) do + {:ok, resource} + else + _ -> {:error, "oEmbed url not found"} + end + end - def get_oembed(url) do - with {:ok, %HTTPoison.Response{body: body}} <- HTTPoison.get(url, [], [follow_redirect: true, ssl: [{:versions, [:'tlsv1.2']}]]), - {:ok, struct} <- Poison.decode(body), - resource <- get_resource(struct) do - {:ok, resource} - else - _ -> {:error, "oEmbed url not found"} + defp get_resource(%{"type" => "link"} = struct), do: Link.new(struct) + defp get_resource(%{"type" => "photo"} = struct), do: Photo.new(struct) + defp get_resource(%{"type" => "rich"} = struct), do: Rich.new(struct) + defp get_resource(%{"type" => "video"} = struct), do: Video.new(struct) + defp get_resource(struct), do: struct end end - defp get_resource(%{"type" => "link"} = struct), do: Link.new(struct) - defp get_resource(%{"type" => "photo"} = struct), do: Photo.new(struct) - defp get_resource(%{"type" => "rich"} = struct), do: Rich.new(struct) - defp get_resource(%{"type" => "video"} = struct), do: Video.new(struct) - defp get_resource(struct), do: struct -end + @callback provides?(String.t) :: boolean + @callback get(String.t) :: struct + end diff --git a/lib/oembed/providers/discover_provider.ex b/lib/oembed/providers/discoverable_provider.ex similarity index 73% rename from lib/oembed/providers/discover_provider.ex rename to lib/oembed/providers/discoverable_provider.ex index 9a7ce0e..2383ed9 100644 --- a/lib/oembed/providers/discover_provider.ex +++ b/lib/oembed/providers/discoverable_provider.ex @@ -1,10 +1,20 @@ -defmodule OEmbed.DiscoverProvider do +defmodule OEmbed.DiscoverableProvider do + @moduledoc """ + oEmbed provider for discoverable endpoints. + """ + use OEmbed.Provider + @doc """ + Check if this provider supports given URL. + """ def provides?(_) do true end + @doc """ + Get oEmbed result for given URL. + """ def get(url) do with {:ok, href} <- discover(url), {:ok, oembed} <- get_oembed(href) do @@ -15,7 +25,7 @@ defmodule OEmbed.DiscoverProvider do end end - def discover(url) do + defp discover(url) do with {:ok, %HTTPoison.Response{body: html}} <- HTTPoison.get(url, [], [follow_redirect: true, ssl: [{:versions, [:'tlsv1.2']}]]), [_ | _] = tags <- Floki.find(html, "head link[type='application/json+oembed']"), {"link", attributes, _} <- List.first(tags), diff --git a/lib/oembed/providers/instagram_provider.ex b/lib/oembed/providers/instagram_provider.ex index 858c5fe..259183c 100644 --- a/lib/oembed/providers/instagram_provider.ex +++ b/lib/oembed/providers/instagram_provider.ex @@ -1,12 +1,21 @@ defmodule OEmbed.InstagramProvider do + @moduledoc """ + oEmbed provider for Instagram URLs. + """ use OEmbed.Provider @oembed_endpoint "https://api.instagram.com/oembed?url=" + @doc """ + Check if this provider supports given URL. + """ def provides?(url) do Regex.match?(~r/^(?:(?:http|https):\/\/)?(?:www.)?(?:instagram.com|instagr.am)\/([A-Za-z0-9-_]+)/im, url) end + @doc """ + Get oEmbed result for given URL. + """ def get(url) do get_oembed(@oembed_endpoint <> url) end diff --git a/lib/oembed/providers/pinterest_provider.ex b/lib/oembed/providers/pinterest_provider.ex index 67d9ad7..74bd0f1 100644 --- a/lib/oembed/providers/pinterest_provider.ex +++ b/lib/oembed/providers/pinterest_provider.ex @@ -1,12 +1,21 @@ defmodule OEmbed.PinterestProvider do + @moduledoc """ + oEmbed provider for Pinterest URLs. + """ use OEmbed.Provider alias OEmbed.Rich + @doc """ + Check if this provider supports given URL. + """ def provides?(url) do Regex.match?(~r/^(?:(?:http|https):\/\/)?(?:[A-Za-z0-9-_]+\.)*?(?:pinterest.com)\/(?:pin)?\/(?:[0-9-_]+)/im, url) end + @doc """ + Get oEmbed result for given URL. + """ def get(url) do oembed = Rich.new(%{ html: get_pin_html(url) @@ -15,7 +24,7 @@ defmodule OEmbed.PinterestProvider do {:ok, oembed} end - def get_pin_html(url) do + defp get_pin_html(url) do """ diff --git a/lib/oembed/resource.ex b/lib/oembed/resource.ex index 9c6f740..d4199cf 100644 --- a/lib/oembed/resource.ex +++ b/lib/oembed/resource.ex @@ -1,6 +1,6 @@ defmodule OEmbed.Resource do @moduledoc """ - oEmbed resource + oEmbed resource. """ defmacro __using__(_) do diff --git a/lib/oembed/resources/link.ex b/lib/oembed/resources/link.ex index b689731..6a1c9ba 100644 --- a/lib/oembed/resources/link.ex +++ b/lib/oembed/resources/link.ex @@ -1,4 +1,7 @@ defmodule OEmbed.Link do + @moduledoc """ + oEmbed Link resource. + """ @keys [type: "link"] diff --git a/lib/oembed/resources/photo.ex b/lib/oembed/resources/photo.ex index e8bdc25..5238853 100644 --- a/lib/oembed/resources/photo.ex +++ b/lib/oembed/resources/photo.ex @@ -1,4 +1,7 @@ defmodule OEmbed.Photo do + @moduledoc """ + oEmbed Photo resource. + """ @keys [type: "photo", url: nil, width: nil, height: nil] diff --git a/lib/oembed/resources/rich.ex b/lib/oembed/resources/rich.ex index b9f8860..14e95cb 100644 --- a/lib/oembed/resources/rich.ex +++ b/lib/oembed/resources/rich.ex @@ -1,4 +1,7 @@ defmodule OEmbed.Rich do + @moduledoc """ + oEmbed Rich resource. + """ @keys [type: "rich", html: nil, width: nil, height: nil] diff --git a/lib/oembed/resources/video.ex b/lib/oembed/resources/video.ex index af37b63..a746e91 100644 --- a/lib/oembed/resources/video.ex +++ b/lib/oembed/resources/video.ex @@ -1,4 +1,7 @@ defmodule OEmbed.Video do + @moduledoc """ + oEmbed Video resource. + """ @keys [type: "video", html: nil, width: nil, height: nil] diff --git a/mix.exs b/mix.exs index 6ee3a98..e3c17e2 100644 --- a/mix.exs +++ b/mix.exs @@ -39,7 +39,9 @@ defmodule OEmbed.Mixfile do {:exconstructor, ">= 1.0.0"}, {:exvcr, "~> 0.8", only: :test}, {:inch_ex, only: :docs}, - {:credo, "~> 0.6.1", only: :dev}] + {:credo, "~> 0.6.1", only: :dev}, + {:earmark, ">= 0.0.0", only: :dev}, + {:ex_doc, "~> 0.10", only: :dev}] end defp docs do @@ -50,7 +52,7 @@ defmodule OEmbed.Mixfile do defp description do """ - oEmbed consumer for Elixir. + oEmbed consumer library for Elixir applications. """ end