Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sitemap generator #64

Merged
merged 3 commits into from
Jul 3, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ jobs:
Test:
strategy:
matrix:
elixir: ['1.10']
otp: [22]
elixir: ['1.12']
otp: [24]
env:
MIX_ENV: test
runs-on: ubuntu-latest
Expand All @@ -33,8 +33,8 @@ jobs:
Format:
strategy:
matrix:
elixir: ['1.10']
otp: [22]
elixir: ['1.12']
otp: [24]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand All @@ -48,8 +48,8 @@ jobs:
Credo:
strategy:
matrix:
elixir: ['1.10']
otp: [22]
elixir: ['1.12']
otp: [24]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand All @@ -63,8 +63,8 @@ jobs:
Dialyzer:
strategy:
matrix:
elixir: ['1.10']
otp: [22]
elixir: ['1.12']
otp: [24]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ erl_crash.dump
.elixir_ls/
/rel
/content
/assets/static/images
/assets/static/feed.xml
/assets/static/sitemap.xml

### Elixir Patch ###

Expand Down
9 changes: 3 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM elixir:1.10.0-alpine AS build
FROM elixir:1.12.0-alpine AS build

# install build dependencies
RUN apk add --no-cache build-base npm git python
RUN apk add --no-cache build-base npm git python3

# prepare build dir
WORKDIR /app
Expand All @@ -26,14 +26,11 @@ COPY lib lib
COPY assets assets
COPY priv priv

# grab images
COPY Makefile Makefile
RUN make content

RUN npm run --prefix ./assets deploy
RUN mix phx.digest

RUN mix do compile, release
RUN mix do phx.digest, compile, school_house.gen.sitemap, school_house.gen.rss, release
doomspork marked this conversation as resolved.
Show resolved Hide resolved

# prepare release image
FROM alpine:3.9 AS app
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ setup: content
mix do deps.get, compile
npm install --prefix assets

content:
content:
rm -rf content assets/static/images
git clone --branch content-only-changes --single-branch --depth 1 https://github.com/elixirschool/elixirschool.git content
mv content/images assets/static/images

build:
docker build .
47 changes: 47 additions & 0 deletions lib/mix/tasks/school_house.gen.rss.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
defmodule Mix.Tasks.SchoolHouse.Gen.Rss do
use Mix.Task

@moduledoc """
Generate an RSS feed from posts
"""

alias SchoolHouse.Posts
alias SchoolHouseWeb.{Endpoint, Router.Helpers}

@destination "assets/static/feed.xml"

def run(_args) do
Mix.Task.run("app.start")

items =
0..(Posts.pages() - 1)
|> Enum.flat_map(&Posts.page/1)
|> Enum.map(&link_xml/1)
|> Enum.join()

document = """
<?xml version="1.0" encoding="UTF-8" ?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
<channel>
#{items}
</channel>
</rss>
"""

File.write!(@destination, document)
end

defp link_xml(post) do
link = Helpers.post_url(Endpoint, :show, post.slug)

"""
<item>
<title>#{post.title}</title>
<description>#{post.excerpt}</description>
<pubDate>#{Calendar.strftime(post.date, "%a, %d %B %Y 00:00:00 +0000")}</pubDate>
<link>#{link}</link>
<guid isPermaLink="true">#{link}</guid>
</item>
"""
end
end
86 changes: 86 additions & 0 deletions lib/mix/tasks/school_house.gen.sitemap.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
defmodule Mix.Tasks.SchoolHouse.Gen.Sitemap do
use Mix.Task

@moduledoc """
Generate a complete sitemap including all locale URLs
"""

alias SchoolHouse.{Lessons, Posts}
alias SchoolHouseWeb.{Endpoint, Router.Helpers}

@destination "assets/static/sitemap.xml"

def run(_args) do
Mix.Task.run("app.start")

links =
all_links()
|> Enum.map(&link_xml/1)
|> Enum.join()

document = """
<?xml version="1.0" encoding="UTF-8" ?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
#{links}
</urlset>
"""

File.write!(@destination, document)
end

defp link_xml(url), do: "<url><loc>#{url}</loc></url>"

defp all_links do
[
Helpers.post_url(Endpoint, :index),
Helpers.page_url(Endpoint, :privacy)
] ++ post_links() ++ Enum.flat_map(supported_locales(), &locale_links/1)
end

defp locale_links(locale), do: page_links(locale) ++ lesson_links(locale)

defp page_links(locale) do
[
Helpers.page_url(Endpoint, :conferences, locale),
Helpers.page_url(Endpoint, :index, locale),
Helpers.page_url(Endpoint, :podcasts, locale),
Helpers.page_url(Endpoint, :why, locale),
Helpers.report_url(Endpoint, :index, locale)
]
end

defp lesson_links(locale) do
config = Application.get_env(:school_house, :lessons)

translated_lesson_links =
for {section, lessons} <- config, lesson <- lessons, translated_lesson?(section, lesson, locale) do
Helpers.lesson_url(Endpoint, :lesson, section, lesson, locale)
end

section_indexes =
for section <- Keyword.keys(config) do
Helpers.lesson_url(Endpoint, :index, section, locale)
end

section_indexes ++ translated_lesson_links
end

defp translated_lesson?(section, lesson, locale) do
case Lessons.get(section, lesson, locale) do
{:ok, _} -> true
_ -> false
end
end

defp post_links do
0..(Posts.pages() - 1)
|> Enum.flat_map(&Posts.page/1)
|> Enum.map(&Helpers.post_url(Endpoint, :show, &1.slug))
end

defp supported_locales do
:school_house
|> Application.get_env(SchoolHouseWeb.Gettext)
|> Keyword.get(:locales)
end
end
17 changes: 16 additions & 1 deletion lib/school_house/content/post.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,23 @@ defmodule SchoolHouse.Content.Post do
:title
]

@doc """
A helper function leveraged used by NimblePublisher to create each of our Post structs provided the filename, file's metadata, and the file body. Generates the post slug by trimming the date from filenames to match the legacy Jekyll blog post format.

Examples

iex> build("2021_06_15_really_smart_blog_post.md", %{}, "")
%Post{slug: "really_smart_blog_post"}

"""
def build(filename, attrs, body) do
slug = Path.basename(filename, ".md")
date_prefix_length = 11

slug =
filename
|> Path.basename(".md")
|> String.slice(date_prefix_length..-1)
doomspork marked this conversation as resolved.
Show resolved Hide resolved

struct!(__MODULE__, [body: body, slug: slug] ++ Map.to_list(attrs))
end
end
2 changes: 1 addition & 1 deletion lib/school_house_web/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ defmodule SchoolHouseWeb.Endpoint do
at: "/",
from: :school_house,
gzip: false,
only: ~w(css fonts images js favicon.ico robots.txt)
only: ~w(css fonts images js favicon.ico robots.txt feed.xml sitemap.xml)

# Code reloading can be explicitly enabled under the
# :code_reloader configuration of your endpoint.
Expand Down
20 changes: 12 additions & 8 deletions lib/school_house_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@ defmodule SchoolHouseWeb.Router do
get "/blog/:slug", PostController, :show

get "/privacy", PageController, :privacy
get "/podcasts", PageController, :podcasts
get "/conferences", PageController, :conferences

get "/:locale", PageController, :index
get "/:locale/report", ReportController, :index
get "/:locale/why", PageController, :why
get "/:locale/:section", LessonController, :index
get "/:locale/:section/:name", LessonController, :lesson

scope "/:locale" do
get "/", PageController, :index
get "/why", PageController, :why
get "/podcasts", PageController, :podcasts
get "/conferences", PageController, :conferences

get "/report", ReportController, :index

get "/:section", LessonController, :index
get "/:section/:name", LessonController, :lesson
end
end

# Other scopes may use custom stacks.
Expand Down
9 changes: 4 additions & 5 deletions lib/school_house_web/templates/layout/_footer.html.leex
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@
<%= link(gettext("Why Elixir?"), to: Routes.page_path(@conn, :why, current_locale()), class: "text-base text-light dark:text-light-dark hover:text-gray-900") %>
</li>
<li>
<%= link("Podcasts", to: Routes.page_path(@conn, :podcasts), class: "text-base text-light dark:text-light-dark hover:text-gray-900") %>
<%= link(gettext("Podcasts"), to: Routes.page_path(@conn, :podcasts, current_locale()), class: "text-base text-light dark:text-light-dark hover:text-gray-900") %>
</li>
<li>
<%= link(gettext("Conferences"), to: Routes.page_path(@conn, :conferences, current_locale()), class: "text-base text-light dark:text-light-dark hover:text-gray-900") %>
</li>
</ul>
</div>
Expand Down Expand Up @@ -102,10 +105,6 @@
</a>
</li>

<li>
<%= link("Conferences", to: Routes.page_path(@conn, :conferences), class: "text-base text-light dark:text-light-dark hover:text-gray-900") %>
</li>

<li>
<a href="#" class="text-base text-light dark:text-light-dark hover:text-gray-900">
Reviews
Expand Down
5 changes: 4 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ defmodule SchoolHouse.MixProject do
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
start_permanent: Mix.env() == :prod,
aliases: aliases(),
deps: deps()
deps: deps(),
dialyzer: [
plt_add_apps: [:mix]
]
]
end

Expand Down
2 changes: 1 addition & 1 deletion test/school_house/conferences_test.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule SchoolHouse.ConferencesTest do
use ExUnit.Case

alias SchoolHouse.{Content.Conference, Conferences}
alias SchoolHouse.Conferences

describe "list/0" do
test "returns conferences ordered by date" do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ defmodule SchoolHouseWeb.ConferenceLiveIndexTest do

describe "mount/3" do
test "can mount live view", %{conn: conn} do
{:ok, view, html} = live_isolated(conn, SchoolHouseWeb.ConferenceLive.Index, session: %{})
{:ok, _view, html} = live_isolated(conn, SchoolHouseWeb.ConferenceLive.Index, session: %{})
doomspork marked this conversation as resolved.
Show resolved Hide resolved
assert html =~ "Filter</p>"
end

test "applying no filters returns both rows", %{conn: conn} do
{:ok, view, html} = live_isolated(conn, SchoolHouseWeb.ConferenceLive.Index, session: %{})
{:ok, view, _html} = live_isolated(conn, SchoolHouseWeb.ConferenceLive.Index, session: %{})

filtered_view = IndexTestHelpers.apply_filter(view, %{filters: %{"online" => "false", "country" => ""}})

Expand All @@ -21,7 +21,7 @@ defmodule SchoolHouseWeb.ConferenceLiveIndexTest do
end

test "applying country filter only returns one row", %{conn: conn} do
{:ok, view, html} = live_isolated(conn, SchoolHouseWeb.ConferenceLive.Index, session: %{})
{:ok, view, _html} = live_isolated(conn, SchoolHouseWeb.ConferenceLive.Index, session: %{})

filtered_view =
IndexTestHelpers.apply_filter(view, %{filters: %{"online" => "false", "country" => "United States"}})
Expand All @@ -31,7 +31,7 @@ defmodule SchoolHouseWeb.ConferenceLiveIndexTest do
end

test "applying online filter only returns one row", %{conn: conn} do
{:ok, view, html} = live_isolated(conn, SchoolHouseWeb.ConferenceLive.Index, session: %{})
{:ok, view, _html} = live_isolated(conn, SchoolHouseWeb.ConferenceLive.Index, session: %{})

filtered_view = IndexTestHelpers.apply_filter(view, %{filters: %{"online" => "true", "country" => ""}})

Expand All @@ -40,7 +40,7 @@ defmodule SchoolHouseWeb.ConferenceLiveIndexTest do
end

test "applying online filter and country filter returns combined set of rows", %{conn: conn} do
{:ok, view, html} = live_isolated(conn, SchoolHouseWeb.ConferenceLive.Index, session: %{})
{:ok, view, _html} = live_isolated(conn, SchoolHouseWeb.ConferenceLive.Index, session: %{})

filtered_view =
IndexTestHelpers.apply_filter(view, %{filters: %{"online" => "true", "country" => "United States"}})
Expand Down