flora 0.5.0 → 0.6.0

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: d37209dfce3b7a9f42b1f41f261ab64b404a13cfa07bb1246d36718395fb9aff
4
- data.tar.gz: 145c6f72a9e6c82abad143f946bde715e200b693d5963f3568485b04622c14c4
3
+ metadata.gz: 2a7d4bc41b49cc7dba0f424be3b8c3bd62ba19fae76d1d1129dad0875f38ab2c
4
+ data.tar.gz: a52d14ffc096179aba36b232fa76826d29a28ab5f2283cde85b533c2c2bba959
5
5
  SHA512:
6
- metadata.gz: 283edf79dedaa559fa4132a16f4fb79f897fb969436cf252b23fa520aa172232ddc22c65665e2886f3390761e31678bef7b244ada7eac9edf6a6b20c5f8151ba
7
- data.tar.gz: c1e279fa9e7a777bc60bec261c6e7a688f34d88d049865ee639564316ecfb30b1eadf82156ab599bb5f1981125c16841b11fb5b38ec187f1c2680b0d6a2e22ba
6
+ metadata.gz: 92282602b69d8dcdea03660ff8d3446d59b1555d994abf6c7643d1a4ae688c6f1d88b09732d68d40d8c877d9feb39b6067451e4473d281e4e948c1640a9a5fde
7
+ data.tar.gz: de0ae5863a9f75933528d14ee8e8034a16154a207831f958372214990cf544ad2ffc6b1b909454feae15ab62b401120d95bf25b46b92048ea8189a83f93dda71
data/lib/flora/app.rb CHANGED
@@ -50,7 +50,7 @@ class Flora::App
50
50
  end
51
51
 
52
52
  def call(env)
53
- @flora.reload_website_code
53
+ @flora.reload_blueprint
54
54
 
55
55
  @app.call(env)
56
56
  end
@@ -1,4 +1,4 @@
1
- module Flora::Engine::Page::Html
1
+ module Flora::Blueprint::Page::Html
2
2
 
3
3
  TAGS = %i[
4
4
  a abbr address area article aside audio
@@ -1,4 +1,4 @@
1
- class Flora::Engine::Page::Layout
1
+ class Flora::Blueprint::Page::Layout
2
2
 
3
3
  def initialize(layouts)
4
4
  @layouts = layouts
@@ -1,13 +1,13 @@
1
- class Flora::Engine::Page::MarkdownPage < Flora::Engine::Page
1
+ class Flora::Blueprint::Page::MarkdownPage < Flora::Blueprint::Page
2
2
 
3
- def render
4
- silence_warnings do
5
- raw_html(Kramdown::Document.new(@file.read).to_html)
6
- end
7
- end
3
+ private
8
4
 
5
+ def render_tree
6
+ silence_warnings do
7
+ raw_html(Kramdown::Document.new(@file.read).to_html)
8
+ end
9
+ end
9
10
 
10
- private
11
11
 
12
12
  # Remove this if kramdown ever fixes its one warning.
13
13
  def silence_warnings
@@ -0,0 +1,12 @@
1
+ class Flora::Blueprint::Page::RubyPage < Flora::Blueprint::Page
2
+
3
+ private
4
+
5
+ def render_tree
6
+ # The Html DSL uses a global variable internally that needs to be reset every time.
7
+ $flora_added = []
8
+
9
+ instance_eval(@file.read)
10
+ end
11
+
12
+ end
@@ -0,0 +1,49 @@
1
+ # A page is something can be turned into HTML.
2
+ class Flora::Blueprint::Page
3
+
4
+ attr_reader(:blueprint, :file, :route)
5
+
6
+
7
+ def self.for(file)
8
+ # TODO: make this a little more extensible so plugins can implement new page
9
+ # types.
10
+ case file.extname
11
+ when '.rb'
12
+ RubyPage
13
+ when '.md'
14
+ MarkdownPage
15
+ end
16
+ end
17
+
18
+
19
+ def initialize(blueprint, file, route)
20
+ @blueprint = blueprint
21
+ @file = file
22
+ @route = route
23
+ @layout = find_layouts
24
+ end
25
+
26
+
27
+ def render
28
+ tree = @layout.render do
29
+ render_tree
30
+ end
31
+
32
+ Html.to_html(tree)
33
+ end
34
+
35
+
36
+ private
37
+
38
+ def find_layouts
39
+ layouts = []
40
+
41
+ @file.ascend do |dir|
42
+ maybe_layout = dir.join('_layout.rb')
43
+ layouts << maybe_layout if maybe_layout.exist?
44
+ end
45
+
46
+ Layout.new(layouts)
47
+ end
48
+
49
+ end
@@ -0,0 +1,64 @@
1
+ class Flora::Blueprint
2
+
3
+ attr_reader(:dir)
4
+
5
+ IGNORES = ['.git/*', 'lib/*', '**_layout.rb', '_config.rb']
6
+
7
+
8
+ def initialize(dir, config, page_modules)
9
+ @dir = dir
10
+ @config = config
11
+ @page_modules = page_modules
12
+
13
+ @pages = load_pages
14
+
15
+ @loader = Zeitwerk::Loader.new
16
+ if has_supporting_code?
17
+ @loader.push_dir(@dir.join('lib').to_s)
18
+ end
19
+ @loader.enable_reloading
20
+ @loader.setup
21
+ end
22
+
23
+
24
+ def each_page(&block)
25
+ @pages.each(&block)
26
+ end
27
+
28
+
29
+ def reload
30
+ @loader.reload
31
+ @pages = load_pages
32
+ end
33
+
34
+
35
+ private
36
+
37
+ def load_pages
38
+ pages = []
39
+
40
+ @dir.find do |file|
41
+ next if IGNORES.any? { file.fnmatch((@dir / it).to_s) }
42
+ next if file.directory?
43
+ next unless supported_file_type?(file)
44
+
45
+ route = file.relative_path_from(@dir).sub_ext('.html').to_s
46
+ page = Page.for(file).new(self, file, route)
47
+ @page_modules.each { |mod| page.extend(mod) }
48
+ pages << page
49
+ end
50
+
51
+ pages
52
+ end
53
+
54
+
55
+ def supported_file_type?(file)
56
+ file.extname == '.rb' || file.extname == '.md'
57
+ end
58
+
59
+
60
+ def has_supporting_code?
61
+ @dir.join('lib').exist?
62
+ end
63
+
64
+ end
@@ -0,0 +1,21 @@
1
+ class Flora::Config
2
+
3
+ def initialize(file, flora)
4
+ @file = file
5
+ @flora = flora
6
+ load if @file.exist?
7
+ end
8
+
9
+
10
+ def plugin(mod)
11
+ @flora.load_plugin(mod)
12
+ end
13
+
14
+
15
+ private
16
+
17
+ def load
18
+ instance_eval(@file.read)
19
+ end
20
+
21
+ end
@@ -0,0 +1,20 @@
1
+ class Flora::Factory
2
+
3
+ def initialize(blueprint, config)
4
+ @blueprint = blueprint
5
+ @config = config
6
+ end
7
+
8
+
9
+ # Assemble a blueprint and put it into a directory.
10
+ def assemble(out_dir)
11
+ out_dir.mkdir unless out_dir.exist?
12
+
13
+ @blueprint.each_page do |page|
14
+ out_filename = out_dir.join(page.route)
15
+ out_filename.dirname.mkdir unless out_filename.dirname.exist?
16
+ out_filename.write(page.render)
17
+ end
18
+ end
19
+
20
+ end
@@ -3,7 +3,7 @@ module Flora::Plugins::Blog
3
3
  module PageMethods
4
4
 
5
5
  def posts
6
- @root.glob('posts/**').map { Post.new(it, @root) }
6
+ @blueprint.dir.glob('posts/**').map { Post.new(it, @blueprint.dir) }
7
7
  end
8
8
 
9
9
  end
@@ -1,12 +1,12 @@
1
1
  module Flora::Plugins::Redirector
2
2
 
3
- module EngineMethods
3
+ module FactoryMethods
4
4
 
5
- def build(*)
5
+ def assemble(out_dir)
6
6
  super
7
7
 
8
8
  @config.redirects.each do |src, dest|
9
- out_filename = @out_dir.join(src + '.html')
9
+ out_filename = out_dir.join(src + '.html')
10
10
  out_filename.dirname.mkdir unless out_filename.dirname.exist?
11
11
  out_filename.write(build_redir_file(dest))
12
12
  end
@@ -20,14 +20,14 @@ module Flora::Plugins::StaticFiles
20
20
  end
21
21
 
22
22
 
23
- module EngineMethods
23
+ module FactoryMethods
24
24
 
25
- def build(*)
25
+ def assemble(out_dir)
26
26
  super
27
27
 
28
28
  base = @config.static_files_dir || 'public'
29
- copier = Copier.new(@path.join(base))
30
- copier.copy_to(@out_dir.join(base))
29
+ copier = Copier.new(@blueprint.dir.join(base))
30
+ copier.copy_to(out_dir.join(base))
31
31
  end
32
32
 
33
33
  end
data/lib/flora/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Flora
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
data/lib/flora.rb CHANGED
@@ -8,19 +8,45 @@ loader.setup
8
8
  class Flora
9
9
 
10
10
  def initialize(dir)
11
- # A new class so plugins only affect one instance.
12
- @engine = Class.new(Engine).new(dir)
13
- @engine.configure
11
+ dir = Pathname.new(dir)
12
+
13
+ # Inject HTML helpers into Kernel so they're available everywhere. Just
14
+ # instance_eval isn't enough because they'll be missing in lib/ code.
15
+ #
16
+ # TODO: is there a less disruptive way to do this?
17
+ Kernel.prepend(Flora::Blueprint::Page::Html)
18
+
19
+ # The classes that are pluggable get their own instances to avoid conflicting
20
+ # with other instances of Flora in the same process. This is mostly for the
21
+ # unit tests. Maybe one day we can use Ruby::Box or something here instead.
22
+ @config_class = Class.new(Config)
23
+ @factory_class = Class.new(Factory)
24
+
25
+ # Page plugins get mixed in directly to the page instances by Blueprint.
26
+ @page_modules = []
27
+
28
+ @config = @config_class.new(dir.join('_config.rb'), self)
29
+ @blueprint = Blueprint.new(dir, @config, @page_modules)
30
+ @factory = @factory_class.new(@blueprint, @config)
14
31
  end
15
32
 
16
33
 
17
34
  def build(out)
18
- @engine.build(out)
35
+ @factory.assemble(Pathname.new(out))
19
36
  end
20
37
 
21
38
 
22
- def reload_website_code
23
- @engine.website_loader.reload
39
+ def reload_blueprint
40
+ @blueprint.reload
41
+ end
42
+
43
+
44
+ # TODO: it would be nice if this wasn't exposed here. It's just for Config#plugin.
45
+ def load_plugin(mod)
46
+ @factory_class.include(mod::FactoryMethods) if defined?(mod::FactoryMethods)
47
+ @config_class.include(mod::Config) if defined?(mod::Config)
48
+
49
+ @page_modules << mod::PageMethods if defined?(mod::PageMethods)
24
50
  end
25
51
 
26
52
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Vladimiroff
@@ -106,14 +106,15 @@ files:
106
106
  - exe/flora
107
107
  - lib/flora.rb
108
108
  - lib/flora/app.rb
109
+ - lib/flora/blueprint.rb
110
+ - lib/flora/blueprint/page.rb
111
+ - lib/flora/blueprint/page/html.rb
112
+ - lib/flora/blueprint/page/layout.rb
113
+ - lib/flora/blueprint/page/markdown_page.rb
114
+ - lib/flora/blueprint/page/ruby_page.rb
109
115
  - lib/flora/cli.rb
110
- - lib/flora/engine.rb
111
- - lib/flora/engine/config.rb
112
- - lib/flora/engine/page.rb
113
- - lib/flora/engine/page/html.rb
114
- - lib/flora/engine/page/layout.rb
115
- - lib/flora/engine/page/markdown_page.rb
116
- - lib/flora/engine/page/ruby_page.rb
116
+ - lib/flora/config.rb
117
+ - lib/flora/factory.rb
117
118
  - lib/flora/plugins/blog.rb
118
119
  - lib/flora/plugins/blog/post.rb
119
120
  - lib/flora/plugins/redirector.rb
@@ -1,12 +0,0 @@
1
- class Flora::Engine::Config
2
-
3
- def initialize(plugin_loader)
4
- @plugin_loader = plugin_loader
5
- end
6
-
7
-
8
- def plugin(mod)
9
- @plugin_loader.load_plugin(mod)
10
- end
11
-
12
- end
@@ -1,8 +0,0 @@
1
- class Flora::Engine::Page::RubyPage < Flora::Engine::Page
2
-
3
- def render
4
- super
5
- instance_eval(@file.read)
6
- end
7
-
8
- end
@@ -1,64 +0,0 @@
1
- # A page is something can be turned into HTML. It might also have a layout to render into.
2
- class Flora::Engine::Page
3
-
4
- IGNORES = ['.git/*', 'lib/*', '**_layout.rb', '_config.rb']
5
-
6
-
7
- class << self
8
-
9
- def each(path)
10
- path.find do |file|
11
- next if IGNORES.any? { file.fnmatch((path / it).to_s) }
12
- next if file.directory?
13
- next unless supported_file_type?(file)
14
-
15
- yield(self.for(path, file))
16
- end
17
- end
18
-
19
-
20
- def for(root, file)
21
- case file.extname
22
- when '.rb'
23
- RubyPage.new(root, file)
24
- when '.md'
25
- MarkdownPage.new(root, file)
26
- end
27
- end
28
-
29
-
30
- private
31
-
32
- def supported_file_type?(file)
33
- file.extname == '.rb' || file.extname == '.md'
34
- end
35
-
36
- end
37
-
38
-
39
- def initialize(root, file)
40
- @root = root
41
- @file = file
42
- end
43
-
44
-
45
- def render
46
- end
47
-
48
-
49
- def outname
50
- # TODO: this might sub something in the middle instead of just the ext.
51
- @file.relative_path_from(@root).sub(@file.extname, '.html')
52
- end
53
-
54
-
55
- def url
56
- @file.relative_path_from(@root).sub(@file.extname, '')
57
- end
58
-
59
-
60
- def dir
61
- @file.dirname
62
- end
63
-
64
- end
data/lib/flora/engine.rb DELETED
@@ -1,72 +0,0 @@
1
- class Flora::Engine
2
-
3
- attr_reader(:website_loader)
4
-
5
-
6
- def initialize(path)
7
- @path = Pathname.new(path)
8
- @config = Config.new(self)
9
-
10
- @website_loader = Zeitwerk::Loader.new
11
-
12
- if website_has_supporting_code?
13
- @website_loader.push_dir(@path.join('lib').to_s)
14
- end
15
-
16
- @website_loader.enable_reloading
17
- @website_loader.setup
18
-
19
- Kernel.prepend(Flora::Engine::Page::Html)
20
- end
21
-
22
-
23
- def configure
24
- config_file = @path.join('_config.rb')
25
- @config.instance_eval(config_file.read) if config_file.exist?
26
- end
27
-
28
-
29
- def build(out_dir)
30
- @out_dir = Pathname.new(out_dir)
31
- @out_dir.mkdir unless @out_dir.exist?
32
-
33
- Page.each(@path) do |page|
34
- layouts = []
35
- page.dir.ascend do |dir|
36
- maybe_layout = dir.join('_layout.rb')
37
- layouts << maybe_layout if maybe_layout.exist?
38
- break if dir == @path
39
- end
40
-
41
- $flora_added = []
42
- tree = Page::Layout.new(layouts).render do
43
- page.render
44
- end
45
- html = Page::Html.to_html(tree)
46
-
47
- out_filename = @out_dir.join(page.outname)
48
- out_filename.dirname.mkdir unless out_filename.dirname.exist?
49
- out_filename.write(html)
50
- end
51
-
52
- end
53
-
54
-
55
- def load_plugin(mod)
56
- self.class.include(mod::EngineMethods) if defined?(mod::EngineMethods)
57
- Page::RubyPage.include(mod::PageMethods) if defined?(mod::PageMethods)
58
- Config.include(mod::Config) if defined?(mod::Config)
59
- end
60
-
61
-
62
- private
63
-
64
- def website_has_supporting_code?
65
- @path.join('lib').exist?
66
- end
67
-
68
-
69
- def setup_website_loader
70
- end
71
-
72
- end