postwave-client 0.0.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 +7 -0
- data/.gitignore +1 -0
- data/README.md +95 -0
- data/Rakefile +10 -0
- data/lib/postwave/blog_utilities.rb +40 -0
- data/lib/postwave/client.rb +92 -0
- data/lib/postwave/errors.rb +16 -0
- data/lib/postwave/post.rb +67 -0
- data/lib/postwave/version.rb +3 -0
- data/lib/postwave.rb +6 -0
- data/postwave-client.gemspec +24 -0
- metadata +81 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dcf237beec10b8cff85f7ca70cb4f63a23b43555c70a0fa00d20fbbf01abc7d2
|
4
|
+
data.tar.gz: 6400cff762bb34f29084d3ca21de96c97e395239e79592bc53c476ac636b46cf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2c4611af08d26282c042f9695a7291d07ab1eb103fadf082e6a505f63297c20411848c9dba7669c9a63d7beeb15f5ef5ed0b52c83a0b6bbd72ce7a0cbd8fe5ba
|
7
|
+
data.tar.gz: 7314600e6fea02aac7cfb9359f8ac82d254efc54f5bf302a278e1dd6f5cf358d2d2a233371a455c45472501a6699a62b78ba67c66acb8d2a66884f4cc2113e0b
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Postwave Ruby Client 🌊
|
2
|
+
|
3
|
+
A Ruby client for displaying [Postwave](https://github.com/dorkrawk/postwave) blogs.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```
|
8
|
+
gem install postwave-client
|
9
|
+
```
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
### Create a Postwave Client
|
14
|
+
```ruby
|
15
|
+
postwave_client = Postwave::Client.new("path/to/config/postwave.yaml")
|
16
|
+
```
|
17
|
+
|
18
|
+
If you'd like to preload all the posts:
|
19
|
+
```ruby
|
20
|
+
postwave_client = Postwave::Client.new("path/to/config/postwave.yaml", preload: true)
|
21
|
+
```
|
22
|
+
|
23
|
+
### Get a Single Post
|
24
|
+
|
25
|
+
Pass in the stub (the filename without '.md') for the post.
|
26
|
+
```ruby
|
27
|
+
post = postwave_client.post("my-great-post")
|
28
|
+
|
29
|
+
# <Postwave::Post title="My Great Post", date=<Time ...>, tags=["tag1"], body="bla bla bla..">
|
30
|
+
|
31
|
+
puts post.title
|
32
|
+
# "My Great Post"
|
33
|
+
```
|
34
|
+
|
35
|
+
### Get a Collection of Posts
|
36
|
+
|
37
|
+
This will give you a list of posts for displaying on a page.
|
38
|
+
|
39
|
+
You can also filter by tags and specify offsets and limits (useful for pagination).
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
posts = postwave_client.posts
|
43
|
+
|
44
|
+
# [<Postwave::Post ...>, <Postwave::Post ...>, ...]
|
45
|
+
|
46
|
+
tagged_posts = postwave_client.posts(tag: "lizards")
|
47
|
+
|
48
|
+
page2_posts = postwave_client.posts(offset: 10, limit: 10)
|
49
|
+
```
|
50
|
+
Posts will be in reverse chronological order.
|
51
|
+
|
52
|
+
### Get an Index of Posts
|
53
|
+
|
54
|
+
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.
|
55
|
+
|
56
|
+
You can also specify offsets and limits (useful for pagination).
|
57
|
+
```ruby
|
58
|
+
index = postwave_client(index)
|
59
|
+
|
60
|
+
# [<Postwave::PostStub title="My Great Post", date=<Time ...>, stub="my-great-post">, <Postwave::PostStub ...>, ...]
|
61
|
+
|
62
|
+
puts index.first.stub
|
63
|
+
# my-great-post
|
64
|
+
|
65
|
+
page2_index = postwave_client.index(offset: 10, limit: 10)
|
66
|
+
```
|
67
|
+
Index will be in reverse chronological order.
|
68
|
+
|
69
|
+
### Get Tags Used In the Blog
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
tags = postwave_client.tags
|
73
|
+
|
74
|
+
# ["tag1", "tag2", "another-tag"]
|
75
|
+
```
|
76
|
+
|
77
|
+
### Get Details For A Tag
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
tag = postwave_clinet.tag("tag1")
|
81
|
+
|
82
|
+
# <Postwave::Tag tile="tag1", count=1, post_slugs=["my-great-post"]>
|
83
|
+
```
|
84
|
+
|
85
|
+
## Want To Know More About Postwave?
|
86
|
+
|
87
|
+
Check out the [Postwave](https://github.com/dorkrawk/postwave) repo.
|
88
|
+
|
89
|
+
## Development
|
90
|
+
|
91
|
+
### Run the Tests!
|
92
|
+
|
93
|
+
```
|
94
|
+
rake test
|
95
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Postwave
|
2
|
+
module BlogUtilities
|
3
|
+
CONFIG_FILE_NAME = "postwave.yaml"
|
4
|
+
INDEX_FILE_NAME = "index.csv"
|
5
|
+
SUMMARY_FILE_NAME = "summary.yaml"
|
6
|
+
POSTS_DIR = "_posts"
|
7
|
+
META_DIR = "meta"
|
8
|
+
TAGS_DIR = "tags"
|
9
|
+
|
10
|
+
def is_set_up?(blog_root)
|
11
|
+
missing_paths = find_missing_paths(blog_root)
|
12
|
+
missing_paths.empty?
|
13
|
+
end
|
14
|
+
|
15
|
+
def file_paths(blog_root)
|
16
|
+
[
|
17
|
+
File.join(blog_root, CONFIG_FILE_NAME),
|
18
|
+
File.join(blog_root, POSTS_DIR, META_DIR, INDEX_FILE_NAME),
|
19
|
+
File.join(blog_root, POSTS_DIR, META_DIR, SUMMARY_FILE_NAME),
|
20
|
+
]
|
21
|
+
end
|
22
|
+
|
23
|
+
def directory_paths(blog_root)
|
24
|
+
[
|
25
|
+
File.join(blog_root, POSTS_DIR),
|
26
|
+
File.join(blog_root, POSTS_DIR, META_DIR),
|
27
|
+
File.join(blog_root, POSTS_DIR, META_DIR, TAGS_DIR),
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
31
|
+
def find_missing_paths(blog_root)
|
32
|
+
paths_to_check = directory_paths(blog_root) + file_paths(blog_root)
|
33
|
+
missing_paths = []
|
34
|
+
paths_to_check.each do |path|
|
35
|
+
missing_paths << path if !FileTest.exist?(path)
|
36
|
+
end
|
37
|
+
missing_paths
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,92 @@
|
|
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
|
+
module Postwave
|
10
|
+
class Client
|
11
|
+
include BlogUtilities
|
12
|
+
|
13
|
+
def initialize(config_path, preload: false)
|
14
|
+
raise MissingConfigError unless is_valid_config?(config_path)
|
15
|
+
|
16
|
+
@blog_root = File.dirname(config_path)
|
17
|
+
raise InvalidBlogError unless is_set_up?(@blog_root)
|
18
|
+
|
19
|
+
@all_posts = get_all_posts if preload
|
20
|
+
end
|
21
|
+
|
22
|
+
# returns: an array of PostStub Structs - [<struct PostStub date=Time, title="", stub="">]
|
23
|
+
def index(offset: 0, limit: nil)
|
24
|
+
working_index = @full_index || get_full_index
|
25
|
+
count = limit || working_index.size
|
26
|
+
working_index[offset, count]
|
27
|
+
end
|
28
|
+
|
29
|
+
# returns: a post - Postwave::Post
|
30
|
+
def post(slug)
|
31
|
+
post_file_path = Dir["#{File.join(@blog_root, POSTS_DIR)}/*#{slug}.md"].first
|
32
|
+
|
33
|
+
raise PostNotFoundError unless post_file_path && File.exist?(post_file_path)
|
34
|
+
|
35
|
+
Postwave::Post.new_from_file_path(post_file_path)
|
36
|
+
end
|
37
|
+
|
38
|
+
# returns: an array of posts - [Postwave::Post]
|
39
|
+
def posts(offset: 0, limit: nil, tag: nil)
|
40
|
+
posts = @all_posts || get_all_posts
|
41
|
+
posts = posts.select { |post| post.tags.include?(tag) } if tag
|
42
|
+
count = limit || posts.size
|
43
|
+
posts[offset, count]
|
44
|
+
end
|
45
|
+
|
46
|
+
# returns: an array of tags - [String]
|
47
|
+
def tags
|
48
|
+
summary = @blog_summary || get_summary
|
49
|
+
summary[:tags]
|
50
|
+
end
|
51
|
+
|
52
|
+
# returns: a Tag Struct - <Tag tag: "", count: Integer, post_slugs: ["post-slug",..]
|
53
|
+
def tag(tag)
|
54
|
+
tag_file_path = File.join(@blog_root, POSTS_DIR, META_DIR, TAGS_DIR, "#{tag}.yaml")
|
55
|
+
raise TagNotFoundError unless File.exist?(tag_file_path)
|
56
|
+
|
57
|
+
tag_info = YAML.load_file(tag_file_path)
|
58
|
+
|
59
|
+
Postwave::Tag.new(tag, tag_info[:count], tag_info[:post_slugs])
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def is_valid_config?(config_path)
|
65
|
+
File.exist?(config_path)
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_all_posts
|
69
|
+
posts = []
|
70
|
+
Dir.glob(File.join(@blog_root, POSTS_DIR, "*.md")) do |post_file_path|
|
71
|
+
posts << Postwave::Post.new_from_file_path(post_file_path)
|
72
|
+
end
|
73
|
+
posts.reject! { |p| p.draft if p.respond_to? :draft }
|
74
|
+
posts.sort_by { |p| p.date }.reverse
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_full_index
|
78
|
+
full_index = []
|
79
|
+
index_contents = CSV.read(File.join(@blog_root, POSTS_DIR, META_DIR, INDEX_FILE_NAME))
|
80
|
+
index_contents.shift # skip header
|
81
|
+
index_contents.each do |post|
|
82
|
+
full_index << Postwave::PostStub.new(Time.parse(post[1]), post[2], post[0])
|
83
|
+
end
|
84
|
+
full_index
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_summary
|
88
|
+
summary_file_path = File.join(@blog_root, POSTS_DIR, META_DIR, SUMMARY_FILE_NAME)
|
89
|
+
YAML.load_file(summary_file_path)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
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
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require_relative "blog_utilities"
|
2
|
+
|
3
|
+
module Postwave
|
4
|
+
class Post
|
5
|
+
include BlogUtilities
|
6
|
+
|
7
|
+
MEATADATA_DELIMTER = "---"
|
8
|
+
|
9
|
+
attr_reader :file_name, :slug
|
10
|
+
|
11
|
+
def self.new_from_file_path(path)
|
12
|
+
metadata_delimter_count = 0
|
13
|
+
body_buffer_count = 0
|
14
|
+
field_content = { "body" => "" }
|
15
|
+
|
16
|
+
File.readlines(path).each do |line|
|
17
|
+
clean_line = line.chomp
|
18
|
+
if clean_line == MEATADATA_DELIMTER
|
19
|
+
metadata_delimter_count += 1
|
20
|
+
next
|
21
|
+
end
|
22
|
+
|
23
|
+
if metadata_delimter_count == 0
|
24
|
+
next
|
25
|
+
elsif metadata_delimter_count == 1
|
26
|
+
field, value = clean_line.split(":", 2).map(&:strip)
|
27
|
+
field_content[field] = value
|
28
|
+
else
|
29
|
+
if body_buffer_count == 0
|
30
|
+
body_buffer_count += 1
|
31
|
+
next if clean_line.empty?
|
32
|
+
end
|
33
|
+
|
34
|
+
field_content["body"] += "#{line}\n"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# turn "date" into a Time object
|
39
|
+
field_content["date"] = Time.parse(field_content["date"])
|
40
|
+
|
41
|
+
# turn "tags" into an array
|
42
|
+
if field_content["tags"]
|
43
|
+
field_content["tags"] = field_content["tags"].split(",").map do |tag|
|
44
|
+
tag.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# turn "draft" into boolean
|
49
|
+
if field_content["draft"]
|
50
|
+
field_content["draft"] = field_content["draft"].downcase == "true"
|
51
|
+
end
|
52
|
+
|
53
|
+
self.new(path, field_content)
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize(file_name, field_content = {})
|
57
|
+
@file_name = file_name
|
58
|
+
@slug = file_name.split("/").last[...-3] # cut off ".md"
|
59
|
+
|
60
|
+
field_content.each do |field, value|
|
61
|
+
instance_variable_set("@#{field}", value) unless self.instance_variables.include?("@#{field}".to_sym)
|
62
|
+
self.class.send(:attr_reader, field) unless self.public_methods.include?(field.to_sym)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
data/lib/postwave.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'postwave/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "postwave-client"
|
8
|
+
spec.version = Postwave::VERSION
|
9
|
+
spec.authors = ["Dave Schwantes"]
|
10
|
+
spec.email = ["dave.schwantes@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = "A Ruby client for interacting with Postwave blogs."
|
13
|
+
spec.description = "Write your posts statically. Interact with them dynamically."
|
14
|
+
spec.homepage = "https://github.com/dorkrawk/postwave-client-ruby"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# spec.add_dependency ""
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler"
|
23
|
+
spec.add_development_dependency "rake", "~> 12.3"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: postwave-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dave Schwantes
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-09-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12.3'
|
41
|
+
description: Write your posts statically. Interact with them dynamically.
|
42
|
+
email:
|
43
|
+
- dave.schwantes@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- lib/postwave.rb
|
52
|
+
- lib/postwave/blog_utilities.rb
|
53
|
+
- lib/postwave/client.rb
|
54
|
+
- lib/postwave/errors.rb
|
55
|
+
- lib/postwave/post.rb
|
56
|
+
- lib/postwave/version.rb
|
57
|
+
- postwave-client.gemspec
|
58
|
+
homepage: https://github.com/dorkrawk/postwave-client-ruby
|
59
|
+
licenses:
|
60
|
+
- MIT
|
61
|
+
metadata: {}
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubygems_version: 3.2.22
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: A Ruby client for interacting with Postwave blogs.
|
81
|
+
test_files: []
|