Merge branch 'seo-improvements' into 'master'
feat: Add social media and SEO tags to head See merge request mythic-insight/legendary!128
This commit is contained in:
commit
5b6af077bf
8 changed files with 122 additions and 9 deletions
|
@ -2,6 +2,7 @@ defmodule Kaffy.ResourceQuery do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
import Ecto.Query.API, only: [field: 2]
|
||||||
|
|
||||||
def list_resource(conn, resource, params \\ %{}) do
|
def list_resource(conn, resource, params \\ %{}) do
|
||||||
per_page = Map.get(params, "limit", "100") |> String.to_integer()
|
per_page = Map.get(params, "limit", "100") |> String.to_integer()
|
||||||
|
|
2
apps/app/assets/package-lock.json
generated
2
apps/app/assets/package-lock.json
generated
|
@ -11238,7 +11238,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"../../../deps/phoenix_live_view": {
|
"../../../deps/phoenix_live_view": {
|
||||||
"version": "0.16.0",
|
"version": "0.16.3",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/stylehacks": {
|
"node_modules/stylehacks": {
|
||||||
|
|
28
apps/app/lib/app_web/templates/layout/_social.html.eex
Normal file
28
apps/app/lib/app_web/templates/layout/_social.html.eex
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<%= live_title_tag title(@view_module, @view_template, assigns) %>
|
||||||
|
|
||||||
|
<%= tag :meta, itemprop: "name", content: title(@view_module, @view_template, assigns) %>
|
||||||
|
<%= tag :meta, itemprop: "description", content: excerpt(@view_module, @view_template, assigns) %>
|
||||||
|
<%= tag :meta, name: "description", content: excerpt(@view_module, @view_template, assigns) %>
|
||||||
|
|
||||||
|
<!-- Twitter Card -->
|
||||||
|
<%= tag :meta, name: "twitter:card", content: "summary_large_image" %>
|
||||||
|
<%= tag :meta, name: "twitter:title", content: title(@view_module, @view_template, assigns) %>
|
||||||
|
<%= tag :meta, name: "twitter:description", content: excerpt(@view_module, @view_template, assigns) %>
|
||||||
|
<!-- <meta name="twitter:site" content="@site_handle"> -->
|
||||||
|
<!-- <meta name="twitter:creator" content="@author_handle"> -->
|
||||||
|
|
||||||
|
<!-- Facebook / Open Graph -->
|
||||||
|
<%= tag :meta, property: "og:title", content: title(@view_module, @view_template, assigns) %>
|
||||||
|
<%= tag :meta, property: "og:type", content: "article" %>
|
||||||
|
<%= tag :meta, property: "og:description", content: excerpt(@view_module, @view_template, assigns) %>
|
||||||
|
<%= tag :meta, property: "og:site_name", content: Legendary.I18n.t!("en", "site.title") %>
|
||||||
|
<%= modified_tag(@view_module, @view_template, assigns) %>
|
||||||
|
<%= published_tag(@view_module, @view_template, assigns) %>
|
||||||
|
<!-- <meta property="article:section" content="Article Section" /> -->
|
||||||
|
<!-- <meta property="article:tag" content="Article Tag" /> -->
|
||||||
|
<!-- <meta property="fb:admins" content="Facebook numberic ID" /> -->
|
||||||
|
|
||||||
|
<!-- Preview Images -->
|
||||||
|
<!-- <meta itemprop="image" content="http://www.example.com/image.jpg"> -->
|
||||||
|
<!-- <meta name="twitter:image:src" content="http://www.example.com/image.jpg"> -->
|
||||||
|
<!-- <meta property="og:image" content="http://example.com/image.jpg" /> -->
|
|
@ -5,7 +5,7 @@
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<%= csrf_meta_tag() %>
|
<%= csrf_meta_tag() %>
|
||||||
<%= live_title_tag title(@view_module, @view_template, assigns) %>
|
<%= render "_social.html", assigns %>
|
||||||
<link phx-track-static rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
<link phx-track-static rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||||
<script defer phx-track-static type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
<script defer phx-track-static type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -1,15 +1,47 @@
|
||||||
defmodule AppWeb.LayoutView do
|
defmodule AppWeb.LayoutView do
|
||||||
use AppWeb, :view
|
use AppWeb, :view
|
||||||
|
|
||||||
|
def title(view, template, %{post: post}), do: "#{post.title} | #{title(view, template, nil)}"
|
||||||
|
|
||||||
def title(_, _, _) do
|
def title(_, _, _) do
|
||||||
Legendary.I18n.t!("en", "site.title")
|
Legendary.I18n.t!("en", "site.title")
|
||||||
end
|
end
|
||||||
|
|
||||||
def excerpt(_, _, _) do
|
def excerpt(_, _, %{post: post}) do
|
||||||
Legendary.I18n.t!("en", "site.excerpt")
|
post.excerpt
|
||||||
end
|
end
|
||||||
|
|
||||||
def feed_tag(_, _, _, _) do
|
def excerpt(_, _, _) do
|
||||||
nil
|
Legendary.I18n.t!("en", "site.excerpt")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def feed_tag(_, _, _, _) do
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def modified_tag(_, _, %{post: post}) do
|
||||||
|
content =
|
||||||
|
post.modified_gmt
|
||||||
|
|> DateTime.from_naive!("Etc/UTC")
|
||||||
|
|> DateTime.to_iso8601()
|
||||||
|
|
||||||
|
tag :meta, property: "article:modified_time", content: content
|
||||||
|
end
|
||||||
|
|
||||||
|
def modified_tag(_, _, _) do
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def published_tag(_, _, %{post: post}) do
|
||||||
|
content =
|
||||||
|
post.date_gmt
|
||||||
|
|> DateTime.from_naive!("Etc/UTC")
|
||||||
|
|> DateTime.to_iso8601()
|
||||||
|
|
||||||
|
tag :meta, property: "article:published_time", content: content
|
||||||
|
end
|
||||||
|
|
||||||
|
def published_tag(_, _, _) do
|
||||||
|
nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,16 @@ defmodule App.LayoutViewTest do
|
||||||
use AppWeb.ConnCase, async: true
|
use AppWeb.ConnCase, async: true
|
||||||
|
|
||||||
import AppWeb.LayoutView
|
import AppWeb.LayoutView
|
||||||
|
import Phoenix.HTML, only: [safe_to_string: 1]
|
||||||
|
|
||||||
|
alias Legendary.Content.Post
|
||||||
|
|
||||||
|
@post %Post{
|
||||||
|
title: "Test Post",
|
||||||
|
excerpt: "This is a test post.",
|
||||||
|
modified_gmt: ~N[2021-09-17T00:00:00],
|
||||||
|
date_gmt: ~N[2021-09-15T00:00:00]
|
||||||
|
}
|
||||||
|
|
||||||
describe "title/3" do
|
describe "title/3" do
|
||||||
def default_title do
|
def default_title do
|
||||||
|
@ -11,6 +21,10 @@ defmodule App.LayoutViewTest do
|
||||||
test "for nil" do
|
test "for nil" do
|
||||||
assert title(nil, nil, nil) =~ default_title()
|
assert title(nil, nil, nil) =~ default_title()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "for post" do
|
||||||
|
assert title(nil, nil, %{post: @post}) =~ "Test Post | #{default_title()}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "excerpt/3" do
|
describe "excerpt/3" do
|
||||||
|
@ -21,6 +35,10 @@ defmodule App.LayoutViewTest do
|
||||||
test "for nil" do
|
test "for nil" do
|
||||||
assert excerpt(nil, nil, nil) =~ default_excerpt()
|
assert excerpt(nil, nil, nil) =~ default_excerpt()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "for post" do
|
||||||
|
assert excerpt(nil, nil, %{post: @post}) =~ "This is a test post."
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "feed_tag/4" do
|
describe "feed_tag/4" do
|
||||||
|
@ -28,4 +46,24 @@ defmodule App.LayoutViewTest do
|
||||||
assert feed_tag(nil, nil, nil, nil) == nil
|
assert feed_tag(nil, nil, nil, nil) == nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "modified_tag/3" do
|
||||||
|
test "for a post" do
|
||||||
|
assert safe_to_string(modified_tag(nil, nil, %{post: @post})) =~ "2021-09-17"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "without a post" do
|
||||||
|
assert modified_tag(nil, nil, nil) == nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "published_tag/3" do
|
||||||
|
test "for a post" do
|
||||||
|
assert safe_to_string(published_tag(nil, nil, %{post: @post})) =~ "2021-09-15"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "without a post" do
|
||||||
|
assert published_tag(nil, nil, nil) == nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -150,6 +150,7 @@ defmodule Legendary.Core.MixProject do
|
||||||
{:ecto_sql, "~> 3.6"},
|
{:ecto_sql, "~> 3.6"},
|
||||||
{:ex_prompt, "~> 0.2.0"},
|
{:ex_prompt, "~> 0.2.0"},
|
||||||
{:linguist, "~> 0.3.2"},
|
{:linguist, "~> 0.3.2"},
|
||||||
|
{:oban, "~> 2.1"},
|
||||||
{:postgrex, ">= 0.0.0"},
|
{:postgrex, ">= 0.0.0"},
|
||||||
{:phoenix_html, "~> 3.0"},
|
{:phoenix_html, "~> 3.0"},
|
||||||
{:phoenix_live_reload, "~> 1.3", only: :dev},
|
{:phoenix_live_reload, "~> 1.3", only: :dev},
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
defmodule Legendary.Core.Repo.Migrations.UpdateObanTable do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
Oban.Migrations.up()
|
||||||
|
end
|
||||||
|
|
||||||
|
# We specify `version: 1` in `down`, ensuring that we'll roll all the way back down if
|
||||||
|
# necessary, regardless of which version we've migrated `up` to.
|
||||||
|
def down do
|
||||||
|
Oban.Migrations.down(version: 1)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue