Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
matrix:
ruby:
- '3.2.0'
- '3.4.0'
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
Expand Down
42 changes: 23 additions & 19 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,76 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

* `Added` for new features.
* `Changed` for changes in existing functionality.
* `Deprecated` for soon-to-be removed features.
* `Removed` for now removed features.
* `Fixed` for any bug fixes.
- `Added` for new features.
- `Changed` for changes in existing functionality.
- `Deprecated` for soon-to-be removed features.
- `Removed` for now removed features.
- `Fixed` for any bug fixes.

## [1.4.0] - 2025-08-23

## [Unreleased]
### Added

- RSS

## [1.3.0] - 2024-01-05

### Added

[#3](https://github.com/carlwiedemann/foresite/pull/3) version & watch commands (not sure how to test these best right now).
- version & watch commands (not sure how to test these best right now).

## [1.2.0] - 2023-02-11

### Added

[#2](https://github.com/carlwiedemann/foresite/pull/2) Dynamic `<title>` tag based on post title
- Dynamic `<title>` tag based on post title

### Fixed

* Typo in README.
* Link to blog post in README.
- Typo in README.
- Link to blog post in README.

## [1.1.3] - 2023-01-16

### Fixed

* Use the top-level directory for the index.html file because you can't set subdirectories for github pages.
- Use the top-level directory for the index.html file because you can't set subdirectories for github pages.

## [1.1.2] - 2023-01-16

### Fixed

* DRYing things up.
- DRYing things up.

## [1.1.1] - 2023-01-15

### Fixed

* Small typo in gemspec.
- Small typo in gemspec.

## [1.1.0] - 2023-01-15

### Added

* Can use templates for both post markdown and links list on index page.
- Can use templates for both post markdown and links list on index page.

### Fixed

* Reverse chronological order for posts on index page.
* Fleshed-out README and fixed typos.
- Reverse chronological order for posts on index page.
- Fleshed-out README and fixed typos.

## [1.0.1] - 2023-01-15

### Changed

* Fleshed-out README and CHANGELOG files from default boilerplate.
- Fleshed-out README and CHANGELOG files from default boilerplate.

### Fixed

* Bug with trailing non-alphanumeric characters in post titles.
- Bug with trailing non-alphanumeric characters in post titles.

## [1.0.0] - 2023-01-14

### Added

* Initial stable release, a global executable that provides the ability to generate HTML from markdown.
- Initial stable release, a global executable that provides the ability to generate HTML from markdown.
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Create a project directory for your site and run `foresite init` from within it:
Created erb/post.md.erb
Created erb/wrapper.html.erb
Created erb/_list.html.erb
Created erb/feed.xml.erb

Three subdirectories are created, along with three [ERB](https://docs.ruby-lang.org/en/3.2/ERB.html) template files.

Expand All @@ -52,6 +53,7 @@ Some facts:
* `post.md.erb` is the default markdown file for every post.
* `wrapper.html.erb` is a HTML wrapper template for every generated HTML file.
* `_list.html.erb` is a HTML template partial for the list of posts on the `index.html` page.
* `feed.xml.erb` is a XML template for an RSS feed.

### 2. Write your first post

Expand All @@ -69,8 +71,8 @@ A single markdown file is created in the `md` subdirectory. **This file is meant

Some facts:

* The title is the first line formatted as H1 (mandatory).
* Current date in YYYY-MM-DD format is the first markdown paragraph (optional).
* The title is the first line formatted as H1.
* Current date in YYYY-MM-DD format is the first markdown paragraph.
* Current date and title are "slugified" for filename.

### 3. Modify templates as desired
Expand All @@ -81,23 +83,27 @@ Some facts:

`_list.html.erb` is used to generate the `<ul>` list of posts on the `index.html` file. Modify to show posts in a different way.

`feed.xml.erb` is an RSS feed, it will require a `title` as well as a `base_url` for where you host your site.

### 4. Generate HTML from markdown

Run `foresite build` to create HTML in the `post` subdirectory and the `index.html` file:

$ foresite build
Created post/2023-01-15-welcome-to-my-site.html
Created index.html
Created feed.xml

In this example, two HTML files are created.
In this example, two HTML files and an XML file are created.

Some facts:

* For every post markdown file in the `md` subdirectory an equivalent HTML file is generated in the `post` subdirectory, each wrapped with wrapper template markup.
* A single `index.html` file shows a list of links to all posts in reverse-chronological order, prefixed with post date.
* Post titles are parsed from the first H1 tag in each post markdown file.
* Post dates are parsed from the post markdown filename.
* Re-running `foresite build` removes and recreates all HTML files in the `post` subdirectory as well as the `index.html` file.
* The `feed.xml` file reflects the list posts in RSS 2.0 format.
* Re-running `foresite build` removes and recreates all HTML files in the `post` subdirectory as well as the `index.html` file and `feed.xml` file.

In this example, the `index.html` will contain:

Expand Down
15 changes: 8 additions & 7 deletions foresite.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
spec.summary = "An extremely minimal static site generator."
spec.homepage = "https://github.com/carlwiedemann/foresite"
spec.license = "MIT"
spec.required_ruby_version = ">= 2.7.0"
spec.required_ruby_version = ">= 3.3.0"

spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
Expand All @@ -28,19 +28,20 @@ Gem::Specification.new do |spec|
"lib/foresite/version.rb",
"lib/skeleton/_list.html.erb",
"lib/skeleton/post.md.erb",
"lib/skeleton/wrapper.html.erb"
"lib/skeleton/wrapper.html.erb",
"lib/skeleton/feed.xml.erb"
]

spec.bindir = "bin"
spec.executables = spec.files.grep(%r{\Abin/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]

spec.add_dependency "kramdown", "~> 2.4"
spec.add_dependency "thor", "~> 1.2"
spec.add_dependency "zeitwerk", "~> 2.6"
spec.add_dependency "kramdown", "~> 2.5"
spec.add_dependency "thor", "~> 1.4"
spec.add_dependency "zeitwerk", "~> 2.7"
spec.add_dependency "filewatcher", "~> 2.1"

spec.add_development_dependency "rspec", "~> 3.2"
spec.add_development_dependency "standard", "~> 1.3"
spec.add_development_dependency "rspec", "~> 3.13"
spec.add_development_dependency "standard", "~> 1.50"
spec.add_development_dependency "rake", "~> 13"
end
14 changes: 13 additions & 1 deletion lib/foresite.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module Foresite
FILENAME_POST_MD = "post.md.erb"
FILENAME_WRAPPER_HTML = "wrapper.html.erb"
FILENAME_LIST_HTML = "_list.html.erb"
FILENAME_FEED_XML = "feed.xml.erb"

ENV_ROOT = "FORESITE_ROOT"

Expand Down Expand Up @@ -68,6 +69,10 @@ def self.get_path_to_index_file
File.join(get_path_to_root, "index.html")
end

def self.get_path_to_feed_file
File.join(get_path_to_root, "feed.xml")
end

def self.relative_path(full_path)
full_path.gsub(get_path_to_root, "").gsub(Regexp.new("^#{File::SEPARATOR}"), "")
end
Expand Down Expand Up @@ -98,6 +103,13 @@ def self.render_wrapped_index(links)
})
end

def self.render_feed(items, date_build_822)
render_erb_file(FILENAME_FEED_XML, {
items: items.reverse,
date_build_822: date_build_822
})
end

def self.touch_directories
[get_path_to_md, get_path_to_out, get_path_to_erb].map do |path|
if Dir.exist?(path)
Expand All @@ -110,7 +122,7 @@ def self.touch_directories
end

def self.copy_templates
[FILENAME_POST_MD, FILENAME_WRAPPER_HTML, FILENAME_LIST_HTML].map do |filename|
[FILENAME_POST_MD, FILENAME_WRAPPER_HTML, FILENAME_LIST_HTML, FILENAME_FEED_XML].map do |filename|
full_file_path = File.join(get_path_to_erb, filename)
if File.exist?(full_file_path)
"#{relative_path(full_file_path)} already exists"
Expand Down
15 changes: 12 additions & 3 deletions lib/foresite/cli.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require "date"

module Foresite
##
# Cli class.
Expand Down Expand Up @@ -88,6 +90,7 @@ def build
# Wipe all output files.
Dir.glob(File.join(Foresite.get_path_to_out, "*.html")).each { File.delete(_1) }
File.delete(Foresite.get_path_to_index_file) if File.exist?(Foresite.get_path_to_index_file)
File.delete(Foresite.get_path_to_feed_file) if File.exist?(Foresite.get_path_to_feed_file)

markdown_paths = Dir.glob(File.join(Foresite.get_path_to_md, "*.md"))

Expand All @@ -106,11 +109,14 @@ def build
File.write(html_path, Foresite.render_wrapped(title, markdown_content))
$stdout.puts("Created #{Foresite.relative_path(html_path)}")

# Extract date if it exists.
# Extract date.
match_data = /\d{4}-\d{2}-\d{2}/.match(filename_markdown)
date_ymd = match_data[0]
date_822 = DateTime.strptime(date_ymd, "%F").strftime("%a, %d %b %Y %H:%M:%S %z")

{
date_ymd: match_data.nil? ? "" : match_data[0],
date_ymd: date_ymd,
date_822: date_822,
href: Foresite.relative_path(html_path),
title: title
}
Expand All @@ -119,8 +125,11 @@ def build
# Generate index file.
index_html_path = Foresite.get_path_to_index_file
File.write(index_html_path, Foresite.render_wrapped_index(links))

$stdout.puts("Created #{Foresite.relative_path(index_html_path)}")

feed_xml_path = Foresite.get_path_to_feed_file
File.write(feed_xml_path, Foresite.render_feed(links, links.last[:date_822]))
$stdout.puts("Created #{Foresite.relative_path(feed_xml_path)}")
end

desc "watch", "Watches markdown and templates files and runs `build` when they change"
Expand Down
1 change: 1 addition & 0 deletions lib/foresite/renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Renderer
# @param [Hash] vars Variables for template.
def initialize(path, vars)
@path = path
@vars_original = @vars
vars.each do |k, v|
if k.is_a?(Symbol)
instance_variable_set(:"@#{k}", v)
Expand Down
2 changes: 1 addition & 1 deletion lib/foresite/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Foresite
VERSION = "1.3.0"
VERSION = "1.4.0"
end
23 changes: 23 additions & 0 deletions lib/skeleton/feed.xml.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<%
title = 'Another Foresite Blog'
base_url = 'https://example.com'
-%>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
<channel>
<title><%= title %></title>
<link><%= base_url %>/feed.xml</link>
<language>en-us</language>
<pubDate><%= @date_build_822 %></pubDate>
<lastBuildDate><%= @date_build_822 %></lastBuildDate>
<generator>Foresite</generator>
<atom:link href="<%= base_url %>/feed.xml" rel="self" type="application/rss+xml"/>
<% @items.each do |item| -%>
<item>
<title><%= item[:title] %></title>
<link><%= "#{base_url}/#{item[:href]}" %></link>
<guid><%= "#{base_url}/#{item[:href]}" %></guid>
<pubDate><%= item[:date_822] %></pubDate>
</item>
<%- end %>
</channel>
</rss>
1 change: 1 addition & 0 deletions lib/skeleton/wrapper.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<head>
<meta charset="utf-8">
<title><%= @title ? "#{@title} - #{index_title}" : index_title %></title>
<link rel="alternate" type="application/rss+xml" title="<%= index_title %>" href="/feed.xml">
<style></style>
</head>
<body>
Expand Down
Loading