sawsge 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|