sawsge 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +35 -6
- data/lib/blog.rb +14 -14
- data/lib/home.rb +8 -8
- data/lib/page.rb +11 -13
- data/lib/post.rb +1 -0
- data/lib/resource.rb +4 -0
- data/lib/sawsge/version.rb +1 -1
- data/lib/sawsge.rb +3 -11
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8cb16b8c9c5893d01c2d1fc0ba82457e24a9f6fcb670781f9990aecac4773ba
|
4
|
+
data.tar.gz: 9388f1a50ff785504b8e5b9463b45418f25f9b43de33f93838d06742b8ab6e02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb1c6014f224e896b001420fbf3c96a30b16571d1dbadcc05f6d5f623b7bf550692b3dbccd721453ca520a8b74df8ada8e9cccfc9e41c3d31959aa62428c1231
|
7
|
+
data.tar.gz: 67e941e2c2ea82468bf51b30232fcfb32e9103b4d762336652d29de3211997217d265cafe349b0f74c7db534ef27713974edf26d8d4baeeec25463d4b0b61240
|
data/README.md
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# sawsge
|
2
|
+
|
2
3
|
My simple static site generator for blogs or projects.
|
3
4
|
|
4
5
|
## Installation
|
5
6
|
|
6
7
|
Sawsge is availible as a
|
7
8
|
[Gem](https://rubygems.org/gems/sawsge) and as an [AUR
|
8
|
-
package].
|
9
|
+
package](https://aur.archlinux.org/packages/sawsge).
|
9
10
|
|
10
11
|
Install as a Gem: `gem install sawsge`
|
11
12
|
|
@@ -14,10 +15,20 @@ installed.
|
|
14
15
|
|
15
16
|
Install from the AUR: `paru -S sawsge`
|
16
17
|
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
Run `sawsge [DIRECTORY]` where `[DIRECTORY]` is the source
|
21
|
+
directory root. If `[DIRECTORY]` is not provided, Sawsge
|
22
|
+
will target `./`
|
23
|
+
|
17
24
|
## File Structure
|
18
|
-
|
25
|
+
|
26
|
+
In the source directory root should exist `header.html`,
|
27
|
+
`footer.html`, and `config.toml`. Additional files may need
|
28
|
+
to exist for different modes.
|
19
29
|
|
20
30
|
## Config
|
31
|
+
|
21
32
|
Here's an example config for a project:
|
22
33
|
```toml
|
23
34
|
[general]
|
@@ -48,10 +59,28 @@ posts_dirname = "post"
|
|
48
59
|
```
|
49
60
|
|
50
61
|
# General Operation
|
51
|
-
|
62
|
+
|
63
|
+
Sawsge makes all links on the site point to directories, so
|
64
|
+
there is no `index.html` at the end of any URL
|
65
|
+
(example.com/thing/index.html vs example.com/thing/). Sawsge
|
66
|
+
will build your website to `out_dirname` in your config;
|
67
|
+
make sure there are no files in there, as they will be
|
68
|
+
deleted!
|
52
69
|
|
53
70
|
## Blog Mode
|
54
|
-
Blog mode creates a special homepage with the title and a summary of each post, with latest posts at the top. In blog mode, sawsge will look for posts under `posts_dirname` in the config. In `posts_dirname`, each post should be in a directory specifying its date in YYYY/MM/DD format, e.g. `/[posts_dirname]/2021/03/09/index.md`. In its source, the post should include at least one `<h1></h1>` and one `<summary></summary>`HTML block. Both will be used to generate the summary on the front page.
|
55
71
|
|
56
|
-
|
57
|
-
|
72
|
+
Blog mode creates a special homepage with the title and a
|
73
|
+
summary of each post, with latest posts at the top. In blog
|
74
|
+
mode, sawsge will look for posts under `posts_dirname` in
|
75
|
+
the config. In `posts_dirname`, each post should be in a
|
76
|
+
directory specifying its date in YYYY/MM/DD format, e.g.
|
77
|
+
`/[posts_dirname]/2021/03/09/index.md`. In its source, the
|
78
|
+
post should include at least one `<h1></h1>` and one
|
79
|
+
`<summary></summary>`HTML block. Both will be used to
|
80
|
+
generate the summary on the front page.
|
81
|
+
|
82
|
+
## Project Mode
|
83
|
+
|
84
|
+
Project mode is much simpler than blog mode. It performs no
|
85
|
+
special handling with different files--each Markdown file
|
86
|
+
will be generated as a plain page.
|
data/lib/blog.rb
CHANGED
@@ -2,22 +2,22 @@
|
|
2
2
|
|
3
3
|
module Sawsge
|
4
4
|
def self.blog
|
5
|
-
|
5
|
+
home_path = 'index.md'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
# Does not work if you have parent directories for your
|
8
|
+
# posts dir, e.g. you set posts_dirname in config.toml to
|
9
|
+
# foo/bar/baz/etc...
|
10
|
+
post_paths = resource_paths.select do |path|
|
11
|
+
top_parent_dir(path) == POSTS_DIRNAME && File.extname(path) == '.md'
|
12
|
+
end
|
13
|
+
# So posts are added to Home in chronological order
|
14
|
+
post_paths.reverse!
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
@resource_paths.subtract post_paths
|
17
|
+
@resource_paths.delete home_path
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
post_objects = post_paths.map { |path| Post.new(path) }
|
20
|
+
home_object = Home.new(home_path, post_objects)
|
21
|
+
@all_objects = post_objects + [home_object]
|
22
22
|
end
|
23
23
|
end
|
data/lib/home.rb
CHANGED
@@ -9,14 +9,14 @@ module Sawsge
|
|
9
9
|
# Adds collapseable summary of each post on the front
|
10
10
|
# page
|
11
11
|
summary_fragment = Nokogiri::HTML5.fragment <<~HTML
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
<details open>
|
13
|
+
<summary>
|
14
|
+
<a href=\"/#{File.dirname(post.path)}\">#{post.title}</a> <date>#{post.date}</date>
|
15
|
+
</summary>
|
16
|
+
<p>#{post.summary}</p>
|
17
|
+
<a href=\"#{File.dirname(post.path)}\">Read more</a>
|
18
|
+
</details>
|
19
|
+
HTML
|
20
20
|
@document.at_css('footer').add_previous_sibling summary_fragment
|
21
21
|
end
|
22
22
|
end
|
data/lib/page.rb
CHANGED
@@ -4,6 +4,7 @@ module Sawsge
|
|
4
4
|
# An HTML page
|
5
5
|
class Page < Resource
|
6
6
|
attr_reader :title
|
7
|
+
|
7
8
|
def initialize(path)
|
8
9
|
super(path)
|
9
10
|
html_body_fragment = PandocRuby.convert(File.new(@path, 'r').read, from: :markdown, to: :html)
|
@@ -17,9 +18,9 @@ module Sawsge
|
|
17
18
|
# Parse the body fragment instead of the whole document,
|
18
19
|
# as the header may have another h1 within
|
19
20
|
@title = begin
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
h1 = @body.at_css('h1')
|
22
|
+
h1 ? h1.content : ''
|
23
|
+
end
|
23
24
|
@document.at_css('title').content = @title
|
24
25
|
|
25
26
|
if EXTERNAL_LINKS_TARGET_BLANK
|
@@ -29,21 +30,18 @@ module Sawsge
|
|
29
30
|
# blank. mailto links are also ignored, as common
|
30
31
|
# obfuscation techniques can interfere with Nokogiri.
|
31
32
|
external_links = @document.css('a').reject do |link|
|
32
|
-
begin
|
33
33
|
uri = URI(link['href'])
|
34
34
|
# If a link is malformed, it's not sawsge's problem
|
35
35
|
# to fix.
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
36
|
+
rescue URI::InvalidComponentError
|
37
|
+
false
|
38
|
+
else
|
39
|
+
host = uri.host
|
40
|
+
scheme = uri.scheme
|
41
|
+
host.nil? or host.empty? or scheme == 'mailto' or !link['target'].nil?
|
43
42
|
end
|
44
43
|
external_links.each { |link| link['target'] = '_blank' }
|
45
44
|
end
|
46
|
-
|
47
45
|
end
|
48
46
|
|
49
47
|
def build
|
@@ -52,7 +50,7 @@ module Sawsge
|
|
52
50
|
out_dir = File.join(OUT_DIRNAME, File.dirname(@path))
|
53
51
|
|
54
52
|
FileUtils.mkpath out_dir
|
55
|
-
File.new(out_path,
|
53
|
+
File.new(out_path, 'w').syswrite(serialized_html)
|
56
54
|
end
|
57
55
|
end
|
58
56
|
end
|
data/lib/post.rb
CHANGED
data/lib/resource.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sawsge
|
2
4
|
# Any generic file in the website directory
|
3
5
|
class Resource
|
4
6
|
attr_reader :path
|
7
|
+
|
5
8
|
def initialize(path)
|
6
9
|
# Path is relative to SRC_DIR, does not include it
|
7
10
|
@path = path
|
8
11
|
end
|
12
|
+
|
9
13
|
def build
|
10
14
|
FileUtils.mkpath File.join(OUT_DIRNAME, File.dirname(@path))
|
11
15
|
FileUtils.cp @path, File.join(OUT_DIRNAME, @path)
|
data/lib/sawsge/version.rb
CHANGED
data/lib/sawsge.rb
CHANGED
@@ -16,7 +16,6 @@ require_relative 'blog'
|
|
16
16
|
require_relative 'project'
|
17
17
|
|
18
18
|
module Sawsge
|
19
|
-
|
20
19
|
HELP_STRING = 'Usage: sawsge [DIRECTORY]'
|
21
20
|
|
22
21
|
SRC_DIR = ARGV[0] || Dir.pwd
|
@@ -30,7 +29,6 @@ module Sawsge
|
|
30
29
|
# TODO: Put these in the config
|
31
30
|
POSTS_DIRNAME = CONFIG['blog']['posts_dirname']
|
32
31
|
|
33
|
-
|
34
32
|
HEADER_FILENAME = CONFIG['general']['header_filename']
|
35
33
|
FOOTER_FILENAME = CONFIG['general']['footer_filename']
|
36
34
|
|
@@ -46,7 +44,6 @@ module Sawsge
|
|
46
44
|
|
47
45
|
MODE = CONFIG['general']['mode']
|
48
46
|
|
49
|
-
|
50
47
|
# Returns the first directory in a path, eg.
|
51
48
|
# `foo/bar/bin.txt` becomes `foo`
|
52
49
|
def self.top_parent_dir(path)
|
@@ -67,21 +64,16 @@ module Sawsge
|
|
67
64
|
@resource_objects = Set.new
|
68
65
|
@all_objects = Set.new
|
69
66
|
|
70
|
-
|
71
|
-
self.send MODE
|
67
|
+
send MODE
|
72
68
|
|
73
69
|
resources = @resource_paths.map { |path| Resource.new(path) }
|
74
70
|
@all_objects.merge resources
|
75
71
|
|
76
|
-
|
77
72
|
# Delete any old builds
|
78
|
-
if Pathname.new(OUT_DIRNAME).exist?
|
79
|
-
FileUtils.remove_dir OUT_DIRNAME
|
80
|
-
end
|
73
|
+
FileUtils.remove_dir OUT_DIRNAME if Pathname.new(OUT_DIRNAME).exist?
|
81
74
|
FileUtils.mkpath OUT_DIRNAME
|
82
75
|
|
83
|
-
|
84
76
|
# Write each file
|
85
|
-
@all_objects.each
|
77
|
+
@all_objects.each(&:build)
|
86
78
|
end
|
87
79
|
end
|