postwave 0.0.2 → 0.1.1
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/Gemfile +1 -1
- data/Gemfile.lock +22 -0
- data/README.md +109 -10
- data/lib/postwave/blog_utilities.rb +16 -16
- data/lib/postwave/client.rb +113 -0
- data/lib/postwave/errors.rb +16 -0
- data/lib/postwave/post.rb +10 -3
- data/lib/postwave/rss_helper.rb +20 -19
- data/lib/postwave/templates/feed.erb +28 -0
- data/lib/postwave/version.rb +1 -1
- data/lib/postwave.rb +1 -1
- data/postwave.gemspec +1 -1
- metadata +20 -4
- data/crystal/src/postwave/post.cr +0 -77
- data/crystal/src/postwave.cr +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee98e42b5e3436991cfb73764252e21db5ed18c9bfd2760045ee268250d1c79a
|
4
|
+
data.tar.gz: 63e682e894bb2838ee0a46393b75b600ad83197a1fc4b9735b2a7e77897dafe8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7df94a047a4875a2f317ed26f0c30bec4f1a6178967ab721280cb5c40fdb41e35f790537ccbf40a151c9fcddf61862adad0c058ffc04f5dab944ccec48b58652
|
7
|
+
data.tar.gz: 182ae4013b7064810db4f5358d5202100ef8ce3563c79edcfc0af121f4f95f622f9641f5b9b53563916deb8c385123697b1443260ef1377b0a66d695792cc1be
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
postwave (0.0.2)
|
5
|
+
redcarpet (~> 3.6)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
rake (12.3.3)
|
11
|
+
redcarpet (3.6.0)
|
12
|
+
|
13
|
+
PLATFORMS
|
14
|
+
arm64-darwin-21
|
15
|
+
|
16
|
+
DEPENDENCIES
|
17
|
+
bundler
|
18
|
+
postwave!
|
19
|
+
rake (~> 12.3)
|
20
|
+
|
21
|
+
BUNDLED WITH
|
22
|
+
2.2.31
|
data/README.md
CHANGED
@@ -1,21 +1,23 @@
|
|
1
1
|
# Postwave 🌊
|
2
2
|
|
3
|
+
[](https://badge.fury.io/rb/postwave)
|
4
|
+
|
3
5
|
Write your posts statically. Interact with them dynamically.
|
4
6
|
|
5
7
|
## What is Postwave?
|
6
8
|
|
7
9
|
Postwave is an opinionated flat-file based based blog engine.
|
8
10
|
|
9
|
-
It lets you write posts in Markdown and then display them on a dynamic site using
|
10
|
-
|
11
|
-
## Getting Started
|
11
|
+
It lets you write posts in Markdown and then display them on a dynamic site using the client functionality.
|
12
12
|
|
13
|
-
|
13
|
+
## Installation
|
14
14
|
|
15
15
|
```
|
16
16
|
gem install postwave
|
17
17
|
```
|
18
18
|
|
19
|
+
## Authoring Posts
|
20
|
+
|
19
21
|
### Setup
|
20
22
|
|
21
23
|
```
|
@@ -51,11 +53,11 @@ postwave.yaml
|
|
51
53
|
> postwave post
|
52
54
|
```
|
53
55
|
|
54
|
-
This will generate at new Markdown file in the `_posts/` directory. The filename will be the current timestamp.
|
56
|
+
This will generate at new Markdown file in the `_posts/` directory. The title is set to a random string of characters. The filename will be the current timestamp. This will eventually be overwritten by the `build` command, so don't worry too much about it. The file will have a general structure like this:
|
55
57
|
|
56
58
|
```
|
57
59
|
---
|
58
|
-
title:
|
60
|
+
title: FNJEXWZP
|
59
61
|
date: 2022-01-01
|
60
62
|
tags:
|
61
63
|
---
|
@@ -82,15 +84,112 @@ draft: true
|
|
82
84
|
```
|
83
85
|
|
84
86
|
This will "build" the blog. This involves:
|
85
|
-
- regenerating the
|
87
|
+
- regenerating the `/meta/index.csv` file
|
86
88
|
- generating slugs for each posts based on the post title and ensuring that there are no duplicate slugs
|
87
89
|
- changing the post file names to match `yyyy-dd-mm-slug.md`
|
88
|
-
- updating the
|
90
|
+
- updating the `/meta/summary.yaml`
|
89
91
|
- creating and updating tag files (which will be `/tags/[tag-name].yaml` files for each tag)
|
92
|
+
- updating the `/meta/rss` file to create a feed for your posts
|
93
|
+
|
94
|
+
## Displaying Posts
|
95
|
+
|
96
|
+
You can now use Postwave's build in client to display this posts in your project.
|
97
|
+
|
98
|
+
### Include the Client In Your Project
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
require 'postwave/client'
|
102
|
+
```
|
103
|
+
|
104
|
+
### Create a Postwave Client
|
105
|
+
```ruby
|
106
|
+
postwave_client = Postwave::Client.new("path/to/config/postwave.yaml")
|
107
|
+
```
|
108
|
+
|
109
|
+
If you'd like to preload all the posts:
|
110
|
+
```ruby
|
111
|
+
postwave_client = Postwave::Client.new("path/to/config/postwave.yaml", preload: true)
|
112
|
+
```
|
113
|
+
|
114
|
+
### Get a Single Post
|
115
|
+
|
116
|
+
Pass in the stub (the filename without '.md') for the post.
|
117
|
+
```ruby
|
118
|
+
post = postwave_client.post("my-great-post")
|
119
|
+
|
120
|
+
# <Postwave::Post title="My Great Post", date=<Time ...>, tags=["tag1"], body="bla bla bla..">
|
121
|
+
|
122
|
+
puts post.title
|
123
|
+
# "My Great Post"
|
124
|
+
puts post.body
|
125
|
+
# "bla bla bla..."
|
126
|
+
puts post.body_html # uses Redcarpt to convert body Markdown to HTML
|
127
|
+
# "<p>bla bla bla...</p>"
|
128
|
+
```
|
129
|
+
|
130
|
+
### Get a Collection of Posts
|
131
|
+
|
132
|
+
This will give you a list of posts for displaying on a page.
|
133
|
+
|
134
|
+
You can also filter by tags and specify offsets and limits (useful for pagination).
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
posts = postwave_client.posts
|
138
|
+
|
139
|
+
# [<Postwave::Post ...>, <Postwave::Post ...>, ...]
|
140
|
+
|
141
|
+
tagged_posts = postwave_client.posts(tag: "lizards")
|
90
142
|
|
91
|
-
|
143
|
+
page2_posts = postwave_client.posts(offset: 10, limit: 10)
|
144
|
+
```
|
145
|
+
Posts will be in reverse chronological order.
|
146
|
+
|
147
|
+
### Get an Index of Posts
|
148
|
+
|
149
|
+
This will give you a quick list of post summaries containing the title, date, and stub, useful for building an archive page or quick index of posts.
|
150
|
+
|
151
|
+
You can also specify offsets and limits (useful for pagination).
|
152
|
+
```ruby
|
153
|
+
index = postwave_client(index)
|
154
|
+
|
155
|
+
# [<Postwave::PostStub title="My Great Post", date=<Time ...>, stub="my-great-post">, <Postwave::PostStub ...>, ...]
|
156
|
+
|
157
|
+
puts index.first.stub
|
158
|
+
# my-great-post
|
159
|
+
|
160
|
+
page2_index = postwave_client.index(offset: 10, limit: 10)
|
161
|
+
```
|
162
|
+
Index will be in reverse chronological order.
|
163
|
+
|
164
|
+
### Get Tags Used In the Blog
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
tags = postwave_client.tags
|
168
|
+
|
169
|
+
# ["tag1", "tag2", "another-tag"]
|
170
|
+
```
|
92
171
|
|
93
|
-
|
172
|
+
### Get Details For A Tag
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
tag = postwave_clinet.tag("tag1")
|
176
|
+
|
177
|
+
# <Postwave::Tag tile="tag1", count=1, post_slugs=["my-great-post"]>
|
178
|
+
```
|
179
|
+
|
180
|
+
### Get Text For An RSS Feed
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
rss = postwave_client.rss
|
184
|
+
|
185
|
+
# "<?xml version="1.0" encoding="utf-8"?>..."
|
186
|
+
```
|
187
|
+
|
188
|
+
## Run Tests
|
189
|
+
|
190
|
+
```
|
191
|
+
rake test
|
192
|
+
```
|
94
193
|
|
95
194
|
## What is Postwave Not?
|
96
195
|
|
@@ -8,41 +8,41 @@ module Postwave
|
|
8
8
|
META_DIR = "meta"
|
9
9
|
TAGS_DIR = "tags"
|
10
10
|
|
11
|
-
def is_set_up?
|
12
|
-
missing_paths = find_missing_paths
|
11
|
+
def is_set_up?(blog_root = Dir.pwd)
|
12
|
+
missing_paths = find_missing_paths(blog_root)
|
13
13
|
missing_paths.empty?
|
14
14
|
end
|
15
15
|
|
16
|
-
def file_paths
|
16
|
+
def file_paths(blog_root = Dir.pwd)
|
17
17
|
[
|
18
|
-
File.join(
|
19
|
-
File.join(
|
20
|
-
File.join(
|
18
|
+
File.join(blog_root, CONFIG_FILE_NAME),
|
19
|
+
File.join(blog_root, POSTS_DIR, META_DIR, INDEX_FILE_NAME),
|
20
|
+
File.join(blog_root, POSTS_DIR, META_DIR, SUMMARY_FILE_NAME),
|
21
21
|
]
|
22
22
|
end
|
23
23
|
|
24
|
-
def directory_paths
|
24
|
+
def directory_paths(blog_root = Dir.pwd)
|
25
25
|
[
|
26
|
-
File.join(
|
27
|
-
File.join(
|
28
|
-
File.join(
|
26
|
+
File.join(blog_root, POSTS_DIR),
|
27
|
+
File.join(blog_root, POSTS_DIR, META_DIR),
|
28
|
+
File.join(blog_root, POSTS_DIR, META_DIR, TAGS_DIR),
|
29
29
|
]
|
30
30
|
end
|
31
31
|
|
32
|
-
def find_missing_paths
|
33
|
-
paths_to_check = directory_paths + file_paths
|
32
|
+
def find_missing_paths(blog_root = Dir.pwd)
|
33
|
+
paths_to_check = directory_paths(blog_root) + file_paths(blog_root)
|
34
34
|
missing_paths = []
|
35
35
|
paths_to_check.each do |path|
|
36
|
-
missing_paths << path if !FileTest.
|
36
|
+
missing_paths << path if !FileTest.exist?(path)
|
37
37
|
end
|
38
38
|
missing_paths
|
39
39
|
end
|
40
40
|
|
41
41
|
def config_values
|
42
42
|
@config_values ||= if yaml_load = YAML.load_file(File.join(Dir.pwd, CONFIG_FILE_NAME))
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
yaml_load.transform_keys(&:to_sym)
|
44
|
+
else
|
45
|
+
{}
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require_relative "post"
|
2
|
+
require_relative "errors"
|
3
|
+
require_relative "blog_utilities"
|
4
|
+
|
5
|
+
require "csv"
|
6
|
+
require "time"
|
7
|
+
require "yaml"
|
8
|
+
|
9
|
+
Postwave::PostStub = Struct.new(:date, :title, :slug)
|
10
|
+
Postwave::Tag = Struct.new(:name, :count, :post_slugs)
|
11
|
+
Postwave::Pagination = Struct.new(:current_page, :prev_page, :next_page, :total_pages)
|
12
|
+
|
13
|
+
module Postwave
|
14
|
+
class Client
|
15
|
+
include BlogUtilities
|
16
|
+
|
17
|
+
def initialize(config_path, preload: false)
|
18
|
+
raise MissingConfigError unless is_valid_config?(config_path)
|
19
|
+
|
20
|
+
@blog_root = File.dirname(config_path)
|
21
|
+
raise InvalidBlogError unless is_set_up?(@blog_root)
|
22
|
+
|
23
|
+
@all_posts = get_all_posts if preload
|
24
|
+
end
|
25
|
+
|
26
|
+
# returns: an array of PostStub Structs - [<struct PostStub date=Time, title="", stub="">]
|
27
|
+
def index(offset: 0, limit: nil)
|
28
|
+
working_index = @full_index || get_full_index
|
29
|
+
count = limit || working_index.size
|
30
|
+
working_index[offset, count]
|
31
|
+
end
|
32
|
+
|
33
|
+
# returns: a post - Postwave::Post
|
34
|
+
def post(slug)
|
35
|
+
post_file_path = Dir["#{File.join(@blog_root, POSTS_DIR)}/*#{slug}.md"].first
|
36
|
+
|
37
|
+
raise PostNotFoundError unless post_file_path && File.exist?(post_file_path)
|
38
|
+
|
39
|
+
Postwave::Post.new_from_file_path(post_file_path)
|
40
|
+
end
|
41
|
+
|
42
|
+
# returns: an array of posts - [Postwave::Post]
|
43
|
+
def posts(offset: 0, limit: nil, tag: nil)
|
44
|
+
posts = @all_posts || get_all_posts
|
45
|
+
posts = posts.select { |post| post.tags.include?(tag) } if tag
|
46
|
+
count = limit || posts.size
|
47
|
+
posts[offset, count]
|
48
|
+
end
|
49
|
+
|
50
|
+
# returns: an array of tags - [String]
|
51
|
+
def tags
|
52
|
+
summary = @blog_summary || get_summary
|
53
|
+
summary[:tags]
|
54
|
+
end
|
55
|
+
|
56
|
+
# returns: a Tag Struct - <Tag tag: "", count: Integer, post_slugs: ["post-slug",..]
|
57
|
+
def tag(tag)
|
58
|
+
tag_file_path = File.join(@blog_root, POSTS_DIR, META_DIR, TAGS_DIR, "#{tag}.yaml")
|
59
|
+
raise TagNotFoundError unless File.exist?(tag_file_path)
|
60
|
+
|
61
|
+
tag_info = YAML.load_file(tag_file_path)
|
62
|
+
|
63
|
+
Postwave::Tag.new(tag, tag_info[:count], tag_info[:post_slugs])
|
64
|
+
end
|
65
|
+
|
66
|
+
# returns: a string of the xml representing an RSS feed of posts - String
|
67
|
+
def rss
|
68
|
+
rss_file_path = File.join(@blog_root, POSTS_DIR, META_DIR, RSS_FILE_NAME)
|
69
|
+
rss = File.open(rss_file_path)
|
70
|
+
rss.read
|
71
|
+
end
|
72
|
+
|
73
|
+
# reuturns: a Pagination Struct - <struct Pagination current_page=3, prev_page=2, next_page=4, total_pages=20>
|
74
|
+
def pagination(current_page: 1, per_page: 10)
|
75
|
+
summary = @blog_summary || get_summary
|
76
|
+
total_pages = (summary[:post_count].to_f / per_page).ceil
|
77
|
+
in_bound_current = current_page.clamp(1, total_pages)
|
78
|
+
prev_page = in_bound_current > 1 ? in_bound_current - 1 : nil
|
79
|
+
next_page = in_bound_current < total_pages ? in_bound_current + 1 : nil
|
80
|
+
Postwave::Pagination.new(in_bound_current, prev_page, next_page, total_pages)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def is_valid_config?(config_path)
|
86
|
+
File.exist?(config_path)
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_all_posts
|
90
|
+
posts = []
|
91
|
+
Dir.glob(File.join(@blog_root, POSTS_DIR, "*.md")) do |post_file_path|
|
92
|
+
posts << Postwave::Post.new_from_file_path(post_file_path)
|
93
|
+
end
|
94
|
+
posts.reject! { |p| p.draft if p.respond_to? :draft }
|
95
|
+
posts.sort_by { |p| p.date }.reverse
|
96
|
+
end
|
97
|
+
|
98
|
+
def get_full_index
|
99
|
+
full_index = []
|
100
|
+
index_contents = CSV.read(File.join(@blog_root, POSTS_DIR, META_DIR, INDEX_FILE_NAME))
|
101
|
+
index_contents.shift # skip header
|
102
|
+
index_contents.each do |post|
|
103
|
+
full_index << Postwave::PostStub.new(Time.parse(post[1]), post[2], post[0])
|
104
|
+
end
|
105
|
+
full_index
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_summary
|
109
|
+
summary_file_path = File.join(@blog_root, POSTS_DIR, META_DIR, SUMMARY_FILE_NAME)
|
110
|
+
YAML.load_file(summary_file_path)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Postwave
|
2
|
+
class PostwaveError < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class MissingConfigError < PostwaveError
|
6
|
+
end
|
7
|
+
|
8
|
+
class InvalidBlogError < PostwaveError
|
9
|
+
end
|
10
|
+
|
11
|
+
class PostNotFoundError < PostwaveError
|
12
|
+
end
|
13
|
+
|
14
|
+
class TagNotFoundError < PostwaveError
|
15
|
+
end
|
16
|
+
end
|
data/lib/postwave/post.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require_relative "blog_utilities"
|
2
|
+
require "redcarpet"
|
2
3
|
|
3
4
|
module Postwave
|
4
|
-
|
5
|
+
class Post
|
5
6
|
include BlogUtilities
|
6
7
|
|
7
8
|
KNOWN_FIELDS = %w(title date tags title_slug body draft)
|
@@ -10,6 +11,8 @@ module Postwave
|
|
10
11
|
|
11
12
|
attr_accessor :file_name
|
12
13
|
|
14
|
+
@@markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, fenced_code_blocks: true)
|
15
|
+
|
13
16
|
def self.new_from_file_path(path)
|
14
17
|
metadata_delimter_count = 0
|
15
18
|
body_buffer_count = 0
|
@@ -59,8 +62,8 @@ module Postwave
|
|
59
62
|
@file_name = file_name
|
60
63
|
|
61
64
|
field_content.each do |field, value|
|
62
|
-
instance_variable_set("@#{field}", value)
|
63
|
-
self.class.send(:
|
65
|
+
instance_variable_set("@#{field}", value) unless self.instance_variables.include?("@#{field}".to_sym)
|
66
|
+
self.class.send(:attr_reader, field) unless self.public_methods.include?(field.to_sym)
|
64
67
|
end
|
65
68
|
end
|
66
69
|
|
@@ -76,6 +79,10 @@ module Postwave
|
|
76
79
|
@slug = new_slug
|
77
80
|
end
|
78
81
|
|
82
|
+
def body_html
|
83
|
+
@@markdown.render(@body)
|
84
|
+
end
|
85
|
+
|
79
86
|
def generated_file_name
|
80
87
|
# YYYY-MM-DD-slug-from-title.md
|
81
88
|
"#{@date.to_s[..9]}-#{slug}.md"
|
data/lib/postwave/rss_helper.rb
CHANGED
@@ -1,35 +1,36 @@
|
|
1
1
|
require_relative "blog_utilities"
|
2
|
-
require "
|
2
|
+
require "erb"
|
3
|
+
require 'redcarpet'
|
3
4
|
|
4
5
|
module Postwave
|
5
6
|
module RssHelper
|
6
7
|
include BlogUtilities
|
7
8
|
|
9
|
+
FeedPost = Struct.new(:title, :link, :body, :date, :tags)
|
10
|
+
|
8
11
|
def build_rss(posts)
|
9
12
|
File.open(File.join(Dir.pwd, POSTS_DIR, META_DIR, RSS_FILE_NAME), "w") do |rss|
|
10
|
-
rss <<
|
13
|
+
rss << feed_content(posts)
|
11
14
|
end
|
12
15
|
end
|
13
16
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
maker.channel.generator = "Postwave"
|
20
|
-
maker.channel.updated = Time.now.to_s
|
21
|
-
|
22
|
-
posts.each do |post|
|
23
|
-
link = "#{config_values[:url]}/#{config_values[:posts_path]}/#{post.slug}"
|
17
|
+
def feed_content(posts)
|
18
|
+
link = config_values[:url]
|
19
|
+
updated = Time.now.iso8601.to_s
|
20
|
+
title = config_values[:name]
|
21
|
+
description = config_values[:description]
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
23
|
+
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, fenced_code_blocks: true)
|
24
|
+
feed_posts = posts.map do |post|
|
25
|
+
post_link = "#{config_values[:url]}/#{config_values[:posts_path]}/#{post.slug}"
|
26
|
+
html_body = CGI.unescapeHTML(markdown.render(post.body))
|
27
|
+
FeedPost.new(post.title, post_link, html_body, post.date.iso8601, post.tags)
|
32
28
|
end
|
29
|
+
|
30
|
+
path = File.join(__dir__, "templates/feed.erb")
|
31
|
+
template = File.read(path)
|
32
|
+
renderer = ERB.new(template)
|
33
|
+
renderer.result(binding)
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom">
|
3
|
+
<generator uri="https://github.com/dorkrawk/postwave" version="<%= Postwave::VERSION %>">Postwave</generator>
|
4
|
+
<link href="<%= link %>" rel="self" type="application/atom+xml" />
|
5
|
+
<link href="<%= link %>" />
|
6
|
+
<updated><%= updated %></updated>
|
7
|
+
<id><%= link %></id>
|
8
|
+
<title type="html"><%= title %></title>
|
9
|
+
<subtitle><%= description %></subtitle>
|
10
|
+
<% feed_posts.each do |post| %>
|
11
|
+
<entry>
|
12
|
+
<title><%= post.title %></title>
|
13
|
+
<link href="<%= post.link %>" rel="alternate" type="text/html" title="<%= post.title %>" />
|
14
|
+
<id><%= post.link %></id>
|
15
|
+
<published><%= post.date %></published>
|
16
|
+
<updated><%= post.date %></updated>
|
17
|
+
<author>
|
18
|
+
<name><%= title %></name>
|
19
|
+
</author>
|
20
|
+
<content type="html">
|
21
|
+
<![CDATA[<%= post.body %>]]>
|
22
|
+
</content>
|
23
|
+
<% post.tags.each do |tag| %>
|
24
|
+
<category term="<%= tag %>" />
|
25
|
+
<% end %>
|
26
|
+
</entry>
|
27
|
+
<% end %>
|
28
|
+
</feed>
|
data/lib/postwave/version.rb
CHANGED
data/lib/postwave.rb
CHANGED
data/postwave.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.executables = ['postwave']
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
|
21
|
+
spec.add_dependency "redcarpet", '~> 3.6'
|
22
22
|
|
23
23
|
spec.add_development_dependency "bundler"
|
24
24
|
spec.add_development_dependency "rake", "~> 12.3"
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: postwave
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dave Schwantes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: redcarpet
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.6'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -48,19 +62,21 @@ extra_rdoc_files: []
|
|
48
62
|
files:
|
49
63
|
- ".gitignore"
|
50
64
|
- Gemfile
|
65
|
+
- Gemfile.lock
|
51
66
|
- README.md
|
52
67
|
- Rakefile
|
53
68
|
- bin/postwave
|
54
|
-
- crystal/src/postwave.cr
|
55
|
-
- crystal/src/postwave/post.cr
|
56
69
|
- lib/postwave.rb
|
57
70
|
- lib/postwave/blog_builder.rb
|
58
71
|
- lib/postwave/blog_creator.rb
|
59
72
|
- lib/postwave/blog_utilities.rb
|
73
|
+
- lib/postwave/client.rb
|
60
74
|
- lib/postwave/display_helper.rb
|
75
|
+
- lib/postwave/errors.rb
|
61
76
|
- lib/postwave/post.rb
|
62
77
|
- lib/postwave/post_creator.rb
|
63
78
|
- lib/postwave/rss_helper.rb
|
79
|
+
- lib/postwave/templates/feed.erb
|
64
80
|
- lib/postwave/version.rb
|
65
81
|
- postwave.gemspec
|
66
82
|
homepage: https://github.com/dorkrawk/postwave
|
@@ -1,77 +0,0 @@
|
|
1
|
-
class Postwave::Post
|
2
|
-
KNOWN_FIELDS = %w(title date tags title_slug body draft)
|
3
|
-
REQUIRED_FIELDS = %w(title date)
|
4
|
-
MEATADATA_DELIMTER = "---"
|
5
|
-
|
6
|
-
def self.new_from_file_path(path : String)
|
7
|
-
metadata_delimter_count = 0
|
8
|
-
body_buffer_count = 0
|
9
|
-
field_content = { "body" => "" }
|
10
|
-
|
11
|
-
File.readlines(path).each do |line|
|
12
|
-
clean_line = line.strip
|
13
|
-
|
14
|
-
if clean_line == MEATADATA_DELIMTER
|
15
|
-
metadata_delimter_count += 1
|
16
|
-
next
|
17
|
-
end
|
18
|
-
|
19
|
-
if metadata_delimter_count == 0
|
20
|
-
next
|
21
|
-
elsif metadata_delimter_count == 1
|
22
|
-
field, value = clean_line.split(":", 2).map(&:strip)
|
23
|
-
field_content[field] = value
|
24
|
-
else
|
25
|
-
if body_buffer_count == 0
|
26
|
-
body_buffer_count += 1
|
27
|
-
next if clean_line.empty?
|
28
|
-
end
|
29
|
-
|
30
|
-
field_content["body"] += "#{line}"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# turn "date" into a Time object
|
35
|
-
field_content["date"] = Time.parse(field_content["date"])
|
36
|
-
|
37
|
-
# turn "tags" into an array
|
38
|
-
if field_content["tags"]
|
39
|
-
field_content["tags"] = field_content["tags"].split(",").map do |tag|
|
40
|
-
tag.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, "")
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# turn "draft" into boolean
|
45
|
-
if field_content["draft"]
|
46
|
-
field_content["draft"] = field_content["draft"].downcase == "true"
|
47
|
-
end
|
48
|
-
|
49
|
-
self.new(path, field_content)
|
50
|
-
end
|
51
|
-
|
52
|
-
def initialize(@file_name : String, field_content : Hash)
|
53
|
-
|
54
|
-
field_content.each do |field, value|
|
55
|
-
# instance_variable_set("@#{field}", value)
|
56
|
-
self.send("@#{field}".to_sym, value)
|
57
|
-
self.class.send(:attr_accessor, field)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def title_slug : String
|
62
|
-
@title_slug ||= @title.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, "")
|
63
|
-
end
|
64
|
-
|
65
|
-
def slug : String
|
66
|
-
@slug ||= @title_slug
|
67
|
-
end
|
68
|
-
|
69
|
-
def slug=(new_slug)
|
70
|
-
@slug = new_slug
|
71
|
-
end
|
72
|
-
|
73
|
-
def generated_file_name
|
74
|
-
# YYYY-MM-DD-slug-from-title.md
|
75
|
-
"#{@date.to_s[..9]}-#{slug}.md"
|
76
|
-
end
|
77
|
-
end
|
data/crystal/src/postwave.cr
DELETED