postwave-client 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,10 @@
1
+ require "rake/testtask"
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << "spec"
5
+ t.test_files = FileList["spec/**/*_spec.rb"]
6
+ t.verbose = true
7
+ end
8
+
9
+ # rake test
10
+ task :default => :test
@@ -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
+
@@ -0,0 +1,3 @@
1
+ module Postwave
2
+ VERSION = "0.0.1"
3
+ end
data/lib/postwave.rb ADDED
@@ -0,0 +1,6 @@
1
+ require_relative "postwave/client"
2
+
3
+ module Postwave
4
+ PostStub = Struct.new(:date, :title, :slug)
5
+ Tag = Struct.new(:name, :count, :post_slugs)
6
+ end
@@ -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: []