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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9ded40bea3eeb7f6f76e5de2f3df929f4ced4d3e8045af330747b5390b06e70
4
- data.tar.gz: cc9f0bbe6554d86b510972d59eb979dd41911ad9b081a0a44c04ef974005ee38
3
+ metadata.gz: ee98e42b5e3436991cfb73764252e21db5ed18c9bfd2760045ee268250d1c79a
4
+ data.tar.gz: 63e682e894bb2838ee0a46393b75b600ad83197a1fc4b9735b2a7e77897dafe8
5
5
  SHA512:
6
- metadata.gz: 1550146a4c3967f077312340d58e3b61691a0022e38c5bc225bae21da657be95b3340ac3a5ef04866f8d5a6861b996ec8161f0ecb57c6309a13d97c3e445d435
7
- data.tar.gz: aaec0f9aa5ad0ae598e204e777cfb80eb0087ca59717d6a60a40d7e615407545a4a4d1d1d5190706889ecedfa34c427c00367801c1996a89e5a400330991330e
6
+ metadata.gz: 7df94a047a4875a2f317ed26f0c30bec4f1a6178967ab721280cb5c40fdb41e35f790537ccbf40a151c9fcddf61862adad0c058ffc04f5dab944ccec48b58652
7
+ data.tar.gz: 182ae4013b7064810db4f5358d5202100ef8ce3563c79edcfc0af121f4f95f622f9641f5b9b53563916deb8c385123697b1443260ef1377b0a66d695792cc1be
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in trackstar.gemspec
3
+ # Specify your gem's dependencies in postwave.gemspec
4
4
  gemspec
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
+ [![Gem Version](https://badge.fury.io/rb/postwave.svg)](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 a client library.
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
- ### Installation
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. 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:
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 `index.csv` file
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 `summary.yaml`
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
- ## Available Client Libraries
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
- - [Ruby](https://github.com/dorkrawk/postwave-ruby-client)
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(Dir.pwd, CONFIG_FILE_NAME),
19
- File.join(Dir.pwd, POSTS_DIR, META_DIR, INDEX_FILE_NAME),
20
- File.join(Dir.pwd, POSTS_DIR, META_DIR, SUMMARY_FILE_NAME),
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(Dir.pwd, POSTS_DIR),
27
- File.join(Dir.pwd, POSTS_DIR, META_DIR),
28
- File.join(Dir.pwd, POSTS_DIR, META_DIR, TAGS_DIR),
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.exists?(path)
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
- yaml_load.transform_keys(&:to_sym)
44
- else
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
- class Post
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(:attr_accessor, field)
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"
@@ -1,35 +1,36 @@
1
1
  require_relative "blog_utilities"
2
- require "rss"
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 << rss_content(posts)
13
+ rss << feed_content(posts)
11
14
  end
12
15
  end
13
16
 
14
- def rss_content(posts)
15
- RSS::Maker.make("2.0") do |maker|
16
- maker.channel.title = config_values[:name]
17
- maker.channel.description = config_values[:description]
18
- maker.channel.link = config_values[:url]
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
- maker.items.new_item do |item|
26
- item.title = post.title
27
- item.link = link
28
- item.description = post.body
29
- item.pubDate = post.date
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>
@@ -1,3 +1,3 @@
1
1
  module Postwave
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.1"
3
3
  end
data/lib/postwave.rb CHANGED
@@ -14,7 +14,7 @@ module Postwave
14
14
  Postwave::BlogBuilder.instance.build
15
15
  else
16
16
  if options[:version]
17
- puts "postwave #{VERSION} [ruby]"
17
+ puts "postwave #{VERSION}"
18
18
  end
19
19
  end
20
20
  end
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
- # spec.add_dependency ""
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.0.2
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: 2024-01-17 00:00:00.000000000 Z
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
@@ -1,4 +0,0 @@
1
- require "./postwave/*"
2
-
3
- module Postwave
4
- end