postwave 0.1.2 → 0.1.4
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 +14 -4
- data/lib/postwave/client.rb +2 -2
- data/lib/postwave/post.rb +39 -3
- data/lib/postwave/rss_helper.rb +4 -3
- data/lib/postwave/version.rb +1 -1
- data/postwave.gemspec +5 -0
- metadata +59 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0eb03ce8fdc3e97f2f54515cbfaa7d527e2f0df541ffd4d993966535b7a8483
|
4
|
+
data.tar.gz: c4b81108e5facc67d6e1799c8907f9d220f34ab9779e270b18bf9787408ca571
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84e334c164a2b1d02ff90b03657493bfd693985f52ef171311dd0319b915439ee04fa315982ab4b6052a295ea229ac0443421e9bbe08fe8ff9050023c4f26be9
|
7
|
+
data.tar.gz: 4f98af33627b143439e7aa75827705c5a74162791e2d066ba3024f99afa5de0df0b13437801da31f40ac00051bea9cca26f96b57c15484f83cab26a9594329ac
|
data/README.md
CHANGED
@@ -4,12 +4,16 @@
|
|
4
4
|
|
5
5
|
Write your posts statically. Interact with them dynamically.
|
6
6
|
|
7
|
+
[postwave.blog](https://postwave.blog/)
|
8
|
+
|
7
9
|
## What is Postwave?
|
8
10
|
|
9
11
|
Postwave is an opinionated flat-file based based blog engine.
|
10
12
|
|
11
13
|
It lets you write posts in Markdown and then display them on a dynamic site using the client functionality.
|
12
14
|
|
15
|
+
Read more about the philosophy behind [what Postwave is for](https://postwave.blog/posts/what-is-postwave-for).
|
16
|
+
|
13
17
|
## Installation
|
14
18
|
|
15
19
|
```
|
@@ -113,18 +117,20 @@ postwave_client = Postwave::Client.new("path/to/config/postwave.yaml", preload:
|
|
113
117
|
|
114
118
|
### Get a Single Post
|
115
119
|
|
116
|
-
Pass in the stub (the filename without '.md') for the post.
|
120
|
+
Pass in the stub (the filename without the date and '.md') for the post.
|
117
121
|
```ruby
|
118
122
|
post = postwave_client.post("my-great-post")
|
119
123
|
|
120
|
-
# <Postwave::Post title="My Great Post", date=<Time ...>, tags=["tag1"], body="bla bla bla
|
124
|
+
# <Postwave::Post title="My Great Post", date=<Time ...>, tags=["tag1"], body="bla bla bla">
|
121
125
|
|
122
126
|
puts post.title
|
123
127
|
# "My Great Post"
|
124
128
|
puts post.body
|
125
|
-
# "bla bla bla
|
129
|
+
# "bla bla bla"
|
126
130
|
puts post.body_html # uses Redcarpt to convert body Markdown to HTML
|
127
|
-
# "<p>bla bla bla
|
131
|
+
# "<p>bla bla bla</p>"
|
132
|
+
puts post.body_preview(8) # an HTML free preview of the post with optional `limit` and `ellipsis` params
|
133
|
+
# "bla bla..."
|
128
134
|
```
|
129
135
|
|
130
136
|
### Get a Collection of Posts
|
@@ -227,6 +233,10 @@ archive = postwave_client.archive(by: "month")
|
|
227
233
|
# }
|
228
234
|
```
|
229
235
|
|
236
|
+
## Example Site
|
237
|
+
|
238
|
+
The code for [postwave.blog](https://postwave.blog/) is available at [github.com/dorkrawk/postwave-site](https://github.com/dorkrawk/postwave-site) and serves as a good example of how to use Postwave in a real world project.
|
239
|
+
|
230
240
|
## Run Tests
|
231
241
|
|
232
242
|
```
|
data/lib/postwave/client.rb
CHANGED
@@ -32,7 +32,7 @@ module Postwave
|
|
32
32
|
|
33
33
|
def archive(by: "year")
|
34
34
|
working_index = @full_index || get_full_index
|
35
|
-
post_hash =
|
35
|
+
post_hash = working_index.group_by { |post| post.date.year }.transform_values { |posts| posts.sort_by(&:date) }
|
36
36
|
if by == "month"
|
37
37
|
post_hash.each do |key, value|
|
38
38
|
post_hash[key] = value.group_by { |post| post.date.month }
|
@@ -119,7 +119,7 @@ module Postwave
|
|
119
119
|
|
120
120
|
def get_summary
|
121
121
|
summary_file_path = File.join(@blog_root, POSTS_DIR, META_DIR, SUMMARY_FILE_NAME)
|
122
|
-
YAML.load_file(summary_file_path)
|
122
|
+
YAML.load_file(summary_file_path, permitted_classes: [Time, Symbol])
|
123
123
|
end
|
124
124
|
end
|
125
125
|
end
|
data/lib/postwave/post.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require_relative "blog_utilities"
|
2
2
|
require "redcarpet"
|
3
|
+
require "cgi"
|
3
4
|
|
4
5
|
module Postwave
|
5
6
|
class Post
|
@@ -7,7 +8,8 @@ module Postwave
|
|
7
8
|
|
8
9
|
KNOWN_FIELDS = %w(title date tags title_slug body draft)
|
9
10
|
REQUIRED_FIELDS = %w(title date)
|
10
|
-
|
11
|
+
METADATA_DELIMITER = "---"
|
12
|
+
FILE_NAME_DATE_LEN = 11 # YYYY-MM-DD-
|
11
13
|
|
12
14
|
attr_accessor :file_name
|
13
15
|
|
@@ -20,7 +22,7 @@ module Postwave
|
|
20
22
|
|
21
23
|
File.readlines(path).each do |line|
|
22
24
|
clean_line = line.strip
|
23
|
-
if clean_line ==
|
25
|
+
if clean_line == METADATA_DELIMITER
|
24
26
|
metadata_delimter_count += 1
|
25
27
|
next
|
26
28
|
end
|
@@ -65,11 +67,18 @@ module Postwave
|
|
65
67
|
instance_variable_set("@#{field}", value) unless self.instance_variables.include?("@#{field}".to_sym)
|
66
68
|
self.class.send(:attr_reader, field) unless self.public_methods.include?(field.to_sym)
|
67
69
|
end
|
70
|
+
|
71
|
+
@slug = file_name_slug&.empty? ? title_slug : file_name_slug
|
68
72
|
end
|
69
73
|
|
70
74
|
def title_slug
|
71
75
|
@title_slug ||= @title.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
|
72
76
|
end
|
77
|
+
|
78
|
+
def file_name_slug
|
79
|
+
# YYYY-MM-DD-slug.md
|
80
|
+
File.basename(@file_name, ".md")[FILE_NAME_DATE_LEN..]
|
81
|
+
end
|
73
82
|
|
74
83
|
def slug
|
75
84
|
@slug ||= @title_slug
|
@@ -80,7 +89,34 @@ module Postwave
|
|
80
89
|
end
|
81
90
|
|
82
91
|
def body_html
|
83
|
-
@@markdown.render(@body)
|
92
|
+
@body_html ||= @@markdown.render(@body)
|
93
|
+
end
|
94
|
+
|
95
|
+
def body_preview(limit = 100, ellipsis = "...")
|
96
|
+
text = body_html.to_s
|
97
|
+
|
98
|
+
# Turn common block boundaries into newlines first
|
99
|
+
text = text.gsub(/<(br|\/p|\/div|\/h\d|\/li)[^>]*>/i, "\n")
|
100
|
+
# Strip remaining tags
|
101
|
+
text = text.gsub(/<[^>]*>/, "")
|
102
|
+
# Decode entities
|
103
|
+
text = CGI.unescapeHTML(text)
|
104
|
+
# Collapse spaces but keep single newlines
|
105
|
+
text = text.gsub(/[ \t]+/, " ").gsub(/\n+/, "\n").strip
|
106
|
+
|
107
|
+
# Unicode-safe character counting (grapheme clusters)
|
108
|
+
graphemes = text.scan(/\X/)
|
109
|
+
return text if graphemes.length <= limit
|
110
|
+
|
111
|
+
candidate = graphemes.first(limit).join
|
112
|
+
|
113
|
+
# If we cut mid-word, trim back to the previous word boundary.
|
114
|
+
# Word characters = letters, numbers, marks, connector punctuation (e.g., underscore)
|
115
|
+
# This removes a trailing partial word if present.
|
116
|
+
cut = candidate.sub(/[\p{L}\p{N}\p{M}\p{Pc}]+\z/u, "").rstrip
|
117
|
+
|
118
|
+
# If the very first "word" exceeds the limit, we err under limit and just show an ellipsis.
|
119
|
+
cut.empty? ? ellipsis : "#{cut}#{ellipsis}"
|
84
120
|
end
|
85
121
|
|
86
122
|
def generated_file_name
|
data/lib/postwave/rss_helper.rb
CHANGED
@@ -15,16 +15,17 @@ module Postwave
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def feed_content(posts)
|
18
|
-
link = config_values[:url]
|
18
|
+
link = config_values[:url].chomp("/")
|
19
19
|
updated = Time.now.iso8601.to_s
|
20
20
|
title = config_values[:name]
|
21
21
|
description = config_values[:description]
|
22
22
|
|
23
23
|
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, fenced_code_blocks: true)
|
24
24
|
feed_posts = posts.map do |post|
|
25
|
-
post_link = "#{
|
25
|
+
post_link = "#{link}/#{config_values[:posts_path]}/#{post.slug}"
|
26
26
|
html_body = CGI.unescapeHTML(markdown.render(post.body))
|
27
|
-
|
27
|
+
post_title = CGI.escapeHTML(post.title)
|
28
|
+
FeedPost.new(post_title, post_link, html_body, post.date.iso8601, post.tags)
|
28
29
|
end
|
29
30
|
|
30
31
|
path = File.join(__dir__, "templates/feed.erb")
|
data/lib/postwave/version.rb
CHANGED
data/postwave.gemspec
CHANGED
@@ -19,7 +19,12 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "redcarpet", '~> 3.6'
|
22
|
+
spec.add_dependency "csv"
|
23
|
+
spec.add_dependency "time"
|
24
|
+
spec.add_dependency "yaml"
|
25
|
+
|
22
26
|
|
23
27
|
spec.add_development_dependency "bundler"
|
24
28
|
spec.add_development_dependency "rake", "~> 12.3"
|
29
|
+
spec.add_development_dependency "rss"
|
25
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: postwave
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dave Schwantes
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: redcarpet
|
@@ -24,6 +23,48 @@ dependencies:
|
|
24
23
|
- - "~>"
|
25
24
|
- !ruby/object:Gem::Version
|
26
25
|
version: '3.6'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: csv
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: time
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: yaml
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
27
68
|
- !ruby/object:Gem::Dependency
|
28
69
|
name: bundler
|
29
70
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +93,20 @@ dependencies:
|
|
52
93
|
- - "~>"
|
53
94
|
- !ruby/object:Gem::Version
|
54
95
|
version: '12.3'
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: rss
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
55
110
|
description: Write your posts statically. Interact with them dynamically.
|
56
111
|
email:
|
57
112
|
- dave.schwantes@gmail.com
|
@@ -83,7 +138,6 @@ homepage: https://github.com/dorkrawk/postwave
|
|
83
138
|
licenses:
|
84
139
|
- MIT
|
85
140
|
metadata: {}
|
86
|
-
post_install_message:
|
87
141
|
rdoc_options: []
|
88
142
|
require_paths:
|
89
143
|
- lib
|
@@ -98,8 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
152
|
- !ruby/object:Gem::Version
|
99
153
|
version: '0'
|
100
154
|
requirements: []
|
101
|
-
rubygems_version: 3.
|
102
|
-
signing_key:
|
155
|
+
rubygems_version: 3.7.1
|
103
156
|
specification_version: 4
|
104
157
|
summary: An opinionated flatfile based blog engine.
|
105
158
|
test_files: []
|