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

Internal refactor #8

Merged
merged 6 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![Latest Version](https://img.shields.io/hexpm/v/simple_blog?color=b5a3be&label=Latest+version)](https://hexdocs.pm/simple_blog)

# Simple Blog



A blog engine written in elixir to generate static blogs from markdown.

Expand Down Expand Up @@ -39,7 +39,7 @@ $ mix deps.get
### Generate new blog post

```console
$ mix simple_blog.post.new "10 tips for new developers"
$ mix simple_blog.post "10 tips for new developers"
```

The file will be created at `blog/_posts/yyyy-mm-dd-10-tips-for-new-developers.md`.
Expand All @@ -50,7 +50,7 @@ The local http server is designed to local development of your blog. To start it

```console
$ mix clean
$ mix simple_blog.server.start
$ mix simple_blog.server
```

The server will be running at `http://localhost:4000`.
Expand Down
21 changes: 0 additions & 21 deletions lib/flat_files.ex

This file was deleted.

46 changes: 27 additions & 19 deletions lib/mix/tasks/simple_blog/compile.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,45 @@ defmodule Mix.Tasks.SimpleBlog.Compile do
require Logger

@moduledoc """
Module responsible for transpile markdown into html
Command responsible for transpile markdown into html
"""

@doc """
Generates a static blog at output folder

## Examples

iex> Mix.Tasks.SimpleBlog.Compile.run([])
"""
@impl Mix.Task
def run([]) do
def run([]), do: run(["blog", "output"])

def run([root_directory, output_directory]) do
posts =
"blog"
root_directory
|> SimpleBlog.Reader.Posts.read_from_dir()
|> SimpleBlog.Converter.Posts.markdown_to_html()
|> Enum.map(&SimpleBlog.Post.parse(&1))

index_html =
File.read("blog/index.html.eex")
File.read(root_directory <> "/index.html.eex")
|> SimpleBlog.Converter.Page.exx_to_html(posts)
|> rewrite_stylesheets()
|> rewrite_images()

File.mkdir("output")
{:ok, file} = File.open("output/index.html", [:write])
File.mkdir(output_directory)
{:ok, file} = File.open(output_directory <> "/index.html", [:write])

index_html
|> String.split("\n")
|> Enum.each(fn line -> IO.binwrite(file, rewrite_post_links(line) <> "\n") end)

File.close(file)

File.cp_r("blog/css", "output/css")
File.cp_r("blog/images", "output/images")
File.cp_r(root_directory <> "/css", output_directory <> "/css")
File.cp_r(root_directory <> "/images", output_directory <> "/images")

write_html_posts(posts)
write_html_posts(root_directory, output_directory, posts)
end

defp rewrite_stylesheets(html) do
Expand Down Expand Up @@ -104,34 +113,33 @@ defmodule Mix.Tasks.SimpleBlog.Compile do
end
end

defp write_html_posts(posts) do
defp write_html_posts(root_directory, output_directory, posts) do
posts
|> Enum.map(&create_folders/1)
|> IO.inspect()
|> Enum.map(&create_folders(&1, output_directory))

posts
|> Enum.map(&create_posts_html/1)
|> Enum.map(&create_posts_html(&1, root_directory, output_directory))
end

defp create_folders(post) do
defp create_folders(post, output_directory) do
post
|> SimpleBlog.Post.generate_html_dir("output/posts/")
|> SimpleBlog.Post.generate_html_dir(output_directory <> "/posts/")
|> File.mkdir_p()
end

def create_posts_html(post) do
dir = SimpleBlog.Post.generate_html_dir(post, "output/posts/")
def create_posts_html(post, root_directory, output_directory) do
dir = SimpleBlog.Post.generate_html_dir(post, output_directory <> "/posts/")
filename = SimpleBlog.Post.generate_html_filename(post)
postname = SimpleBlog.Post.generate_filename(post)

post =
"blog"
root_directory
|> SimpleBlog.Reader.Posts.read_post(postname)
|> SimpleBlog.Converter.Posts.markdown_to_html()
|> SimpleBlog.Post.parse()

result =
File.read("blog/post.html.eex")
File.read(root_directory <> "/post.html.eex")
|> SimpleBlog.Converter.Page.exx_to_html(post)
|> rewrite_stylesheets_post()
|> rewrite_images_post()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
defmodule Mix.Tasks.SimpleBlog.Post.New do
defmodule Mix.Tasks.SimpleBlog.Post do
use Mix.Task

@moduledoc """
Module responsible for generate a new blog post.
Command responsible for generate a new blog post.
"""

@doc """
It generates a new blog post
Generates a new blog post

## Examples

# iex> Mix.Tasks.SimpleBlog.Post.New.run(["My first blog post"])
# :ok
iex> Mix.Tasks.SimpleBlog.Post.run(["My first blog post"])
"Blog post created at blog_test/_posts/yyyy-mm-dd-my-first-blog-post.md"
"""
@impl Mix.Task
def run([]), do: Mix.shell().info(usage())
Expand All @@ -35,13 +35,20 @@ defmodule Mix.Tasks.SimpleBlog.Post.New do
IO.binwrite(file, "--->" <> "\n")
File.close(file)

Mix.shell().info("""
Blog post created at #{full_file_path}
""")

{:error, :enoent} ->
Mix.shell().info("""
The directory #{root_directory} was not found
""")
end
end

@doc """
Returns instructions about command usage
"""
def usage() do
"""
To generate a new blog post you should pass a title as string:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
defmodule Mix.Tasks.SimpleBlog.Server.Start do
defmodule Mix.Tasks.SimpleBlog.Server do
use Mix.Task
require Logger

@moduledoc """
Module responsible for a simple http server to allow local working on blog
Command responsible for a simple http server to allow local working on blog
"""

@doc """
Starts a local HTTP server in the port 4000

## Examples

iex> Mix.Tasks.SimpleBlog.Server.run([])
"Server running on localhost:4000"
"""
@impl Mix.Task
def run([]) do
webserver = [
Expand Down
18 changes: 0 additions & 18 deletions lib/simple_blog.ex

This file was deleted.

17 changes: 17 additions & 0 deletions lib/simple_blog/converter/page.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
defmodule SimpleBlog.Converter.Page do
@moduledoc """
Module responsible for convert pages from eex to html
"""

@doc """
Convert eex file to html

## Examples

iex> posts = [%SimpleBlog.Post{title: "post 1"}, %SimpleBlog.Post{title: "post 2"}]
iex> SimpleBlog.Converter.Page.exx_to_html({:ok, "<%= for post <- posts do %><%= post.title %><% end %>"}, posts)
"post 1post 2"

iex> post = %SimpleBlog.Post{title: "post 1"}
iex> SimpleBlog.Converter.Page.exx_to_html({:ok, "<%= post.title %>"}, post)
"post 1"
"""
def exx_to_html({:ok, body}, posts) when is_list(posts) do
quoted = EEx.compile_string(body)

Expand Down
18 changes: 18 additions & 0 deletions lib/simple_blog/converter/posts.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
defmodule SimpleBlog.Converter.Posts do
require Earmark

@moduledoc """
Module responsible for convert posts from markdown to html
"""

@doc """
Convert markdown file to html

## Examples

iex> SimpleBlog.Converter.Posts.markdown_to_html(["# post1", "# post2"])
["<h1>\\npost1</h1>\\n", "<h1>\\npost2</h1>\\n"]

iex> SimpleBlog.Converter.Posts.markdown_to_html("# post1")
"<h1>\\npost1</h1>\\n"

iex> SimpleBlog.Converter.Posts.markdown_to_html([])
[]
"""
def markdown_to_html([]), do: []

def markdown_to_html(files) when is_list(files) do
Expand Down
37 changes: 33 additions & 4 deletions lib/simple_blog/post.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ defmodule SimpleBlog.Post do

@extension "md"

defstruct title: "", tags: [], body: "", date: "", filename: ""
defstruct title: "", body: "", date: "", filename: ""

@doc """
Generate filename for blog post
Generate directory name for blog post

## Examples

iex> SimpleBlog.Post.generate_filename(%SimpleBlog.Post{ title: "My first blog post", date: ~D[2023-10-04] })
"2023-10-04-my-first-blog-post.md"
iex> SimpleBlog.Post.generate_filename(%SimpleBlog.Post{ title: "My first blog post", date: ~D[2023-10-04]})
"2023-10-04-my-first-blog-post.md"
"""
def generate_filename(%SimpleBlog.Post{title: title, date: date}) do
normalized_title =
Expand All @@ -24,6 +24,18 @@ defmodule SimpleBlog.Post do
"#{date}-#{normalized_title}.#{@extension}"
end

@doc """
Parse comment with data into %SimpleBlog.Post struct

## Examples
iex> body = "<!---
...>filename: 2023-10-25-dev-onboarding.md
...>title: Dev onboarding
...>date: 2023-10-25
...> --->"
iex> SimpleBlog.Post.parse(body)
%SimpleBlog.Post{body: body, title: "Dev onboarding", date: "2023-10-25", filename: "2023-10-25-dev-onboarding.md"}
"""
def parse(body) do
[_, filename_line, title_line, date_line | _] = String.split(body, "\n")

Expand All @@ -34,14 +46,31 @@ defmodule SimpleBlog.Post do
%SimpleBlog.Post{body: body, title: title, date: date, filename: filename}
end

@doc """
Generate filename for blog post

## Examples

iex> SimpleBlog.Post.generate_html_dir(%SimpleBlog.Post{date: "2023-10-04"}, "output")
"output/2023/10/04/"
"""
def generate_html_dir(%SimpleBlog.Post{date: date}, base_dir) do
[year, month, day] = String.split(date, "-")
base_dir <> "/" <> year <> "/" <> month <> "/" <> day <> "/"
end

@doc """
Generate html filename for blog post

## Examples

iex> SimpleBlog.Post.generate_html_filename(%SimpleBlog.Post{title: "doctests with elixir"})
"doctests-with-elixir.html"
"""
def generate_html_filename(%SimpleBlog.Post{title: title}) do
title
|> String.replace(" ", "-")
|> String.downcase()
|> Kernel.<>(".html")
end
end
20 changes: 19 additions & 1 deletion lib/simple_blog/reader/posts.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
defmodule SimpleBlog.Reader.Posts do
require Logger
@moduledoc """
Module responsible for read blog posts
"""

@doc """
Reads content from markdown files located in _posts

## Examples

iex> SimpleBlog.Reader.Posts.read_from_dir("blog")
["## post title 1", "## post title 2"]
"""
def read_from_dir(root_directory) do
posts_directory = root_directory <> "/_posts/"

Expand All @@ -10,6 +20,14 @@ defmodule SimpleBlog.Reader.Posts do
end
end

@doc """
Reads content from markdown file for specific post

## Examples

iex> SimpleBlog.Reader.Posts.read_post("blog", "2023-10-25-metaprogramming-in-ruby.md")
"### Metaprogramming in ruby"
"""
def read_post(root_directory, post) do
posts_directory = root_directory <> "/_posts/"
post_path = posts_directory <> post
Expand Down
Loading
Loading