lb-project 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +41 -0
  3. data/.rspec +6 -0
  4. data/.rubocop.yml +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +7 -0
  7. data/Guardfile +43 -0
  8. data/LICENSE +20 -0
  9. data/README.md +28 -0
  10. data/Rakefile +6 -0
  11. data/bin/lb-project +29 -0
  12. data/config/devtools.yml +2 -0
  13. data/config/flay.yml +3 -0
  14. data/config/flog.yml +2 -0
  15. data/config/mutant.yml +3 -0
  16. data/config/reek.yml +103 -0
  17. data/config/rubocop.yml +10 -0
  18. data/config/yardstick.yml +2 -0
  19. data/lb-project.gemspec +42 -0
  20. data/lib/lb/project/app.rb +9 -0
  21. data/lib/lb/project/config.rb +35 -0
  22. data/lib/lb/project/page.rb +19 -0
  23. data/lib/lb/project/registry/registration.rb +73 -0
  24. data/lib/lb/project/registry.rb +58 -0
  25. data/lib/lb/project/render.rb +28 -0
  26. data/lib/lb/project/route.rb +15 -0
  27. data/lib/lb/project/site.rb +41 -0
  28. data/lib/lb/project/types.rb +10 -0
  29. data/lib/lb/project/version.rb +8 -0
  30. data/lib/lb/project/view.rb +19 -0
  31. data/lib/lb/project.rb +159 -0
  32. data/lib/lb-project.rb +5 -0
  33. data/rakelib/ci.rake +24 -0
  34. data/spec/fixtures/config/application.yml +10 -0
  35. data/spec/fixtures/config/lb-project.yml +3 -0
  36. data/spec/fixtures/config.ru +9 -0
  37. data/spec/fixtures/docs/assets/javascripts/main.bundle.js +0 -0
  38. data/spec/fixtures/docs/assets/stylesheets/main.bundle.css +0 -0
  39. data/spec/fixtures/lib/example/app.rb +14 -0
  40. data/spec/fixtures/lib/example/page/index.rb +13 -0
  41. data/spec/fixtures/lib/example/page.rb +8 -0
  42. data/spec/fixtures/lib/example.rb +15 -0
  43. data/spec/fixtures/locales/en.yml +7 -0
  44. data/spec/fixtures/templates/index.html.slim +7 -0
  45. data/spec/fixtures/templates/layouts/main.html.slim +13 -0
  46. data/spec/fixtures/webpack-assets.json +1 -0
  47. data/spec/spec_helper.rb +31 -0
  48. data/spec/support/helper.rb +5 -0
  49. data/spec/unit/lb/project/class_methods/config_spec.rb +57 -0
  50. data/spec/unit/lb/project/class_methods/development_quest_spec.rb +39 -0
  51. data/spec/unit/lb/project/class_methods/logger_spec.rb +25 -0
  52. data/spec/unit/lb/project/class_methods/rack_env_spec.rb +39 -0
  53. data/spec/unit/lb/project/class_methods/root_for_spec.rb +28 -0
  54. data/spec/unit/lb/project/class_methods/root_spec.rb +31 -0
  55. data/spec/unit/lb/project/class_methods/setup_spec.rb +23 -0
  56. metadata +373 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 43956f0e7b1f6e48a65014512abd750ad68c18318bbf3c00aa6d1d49a46a96bc
4
+ data.tar.gz: 40a8e5823b486781458458dd931f4669ccc722bb48a2503f9c846a700c251c50
5
+ SHA512:
6
+ metadata.gz: ec0c25e1e978a2c8b261de4ad35febecbb21165032863a597020047b0a15932e79258b83f455671f5c829923b3fafdf0d0345074c316c5b85a6298a17f192e00
7
+ data.tar.gz: 5bf9094b84a40341f9465fd9a777528c0a1b90f10d5215d532e1b2be2dcfde17cf7e05da585a6d2776579dc2c089497058f7e6ca7d9fb93d365117b2772da575
data/.gitignore ADDED
@@ -0,0 +1,41 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.sw[op]
15
+
16
+ ## Rubinius
17
+ *.rbc
18
+ .rbx
19
+
20
+ ## PROJECT::GENERAL
21
+ *.gem
22
+ coverage
23
+ profiling
24
+ turbulence
25
+ rdoc
26
+ pkg
27
+ tmp
28
+ doc
29
+ log
30
+ .yardoc
31
+ measurements
32
+
33
+ ## BUNDLER
34
+ .bundle
35
+ Gemfile.lock
36
+
37
+ ## ctags
38
+ tags
39
+ gems.tags
40
+
41
+ ## PROJECT::SPECIFIC
data/.rspec ADDED
@@ -0,0 +1,6 @@
1
+ --color
2
+ --fail-fast
3
+ --format progress
4
+ --profile
5
+ --order random
6
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1 @@
1
+ ./config/rubocop.yml
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.5.0
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ ruby '2.5.0'
6
+
7
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ guard :bundler do
5
+ watch('Gemfile')
6
+ watch('Gemfile.lock')
7
+ watch(/\A(.+)\.gemspec\z/)
8
+ end
9
+
10
+ guard :rspec, cmd: 'bundle exec rspec ' +
11
+ File.read('.rspec').split.join(' '),
12
+ failed_mode: :keep do
13
+ # Run all specs if configuration is modified
14
+ watch('.rspec') { 'spec' }
15
+ watch('Guardfile') { 'spec' }
16
+ watch('Gemfile.lock') { 'spec' }
17
+ watch('spec/spec_helper.rb') { 'spec' }
18
+
19
+ # Run all specs if supporting files files are modified
20
+ watch(%r{\Aspec/(?:fixtures|lib|support|shared)/.+\.rb\z}) { 'spec' }
21
+
22
+ # Run unit specs if associated lib code is modified
23
+ watch(%r{\Alib/(.+)\.rb\z}) do |m|
24
+ Dir["spec/unit/#{m[1]}*"]
25
+ end
26
+
27
+ watch(%r{\Alib/(.+)/support/(.+)\.rb\z}) do |m|
28
+ Dir["spec/unit/#{m[1]}/#{m[2]}*"]
29
+ end
30
+
31
+ watch("lib/#{File.basename(File.expand_path('../', __FILE__))}.rb") do
32
+ 'spec'
33
+ end
34
+
35
+ # Run a spec if it is modified
36
+ watch(%r{\Aspec/(?:unit|integration|features)/.+_spec\.rb\z})
37
+ end
38
+
39
+ guard :rubocop, cli: %w[--config config/rubocop.yml] do
40
+ watch(/.+\.(?:rb|rake|gemspec)\z/)
41
+ watch(%r{\Aconfig/rubocop\.yml\z}) { |m| File.dirname(m[0]) }
42
+ watch(%r{(?:.+/)?\.rubocop\.yml\z}) { |m| File.dirname(m[0]) }
43
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2017-2018 Firas Zaidan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ [gem]: https://rubygems.org/gems/lb-project
2
+ [gemnasium]: https://gemnasium.com/lb-rb/lb-project
3
+ [roda]: http://roda.jeremyevans.net/
4
+ [dry-view]: http://dry-rb.org/gems/dry-view/
5
+
6
+ # lb-project
7
+
8
+ [![Gem Version](https://badge.fury.io/rb/lb-project.svg)][gem]
9
+ [![Dependency Status](https://gemnasium.com/lb-rb/lb-project.svg)][gemnasium]
10
+
11
+ This static site builder allows an easy migration to a dynamic site. In many
12
+ projects it is unclear if or when a static site has to be migrated to a dynamic
13
+ one. Maintaining a static site is less work, so we want to keep it static until
14
+ the point is reached, where we have to migrate the project to a full dynamic
15
+ stack.
16
+
17
+ The target of lb-project is to minimize this migration effort. We use
18
+ [Roda][roda] and [dry-view][dry-view] because this are currently excellent
19
+ solutions that are suited for big projects. This means you can start
20
+ lightweight, without worrying that it becomes to small.
21
+
22
+ ## Credits
23
+
24
+ * [Firas Zaidan](https://github.com/zaidan)
25
+
26
+ ## License
27
+
28
+ See `LICENSE` file.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'devtools'
5
+
6
+ Devtools.init_rake_tasks
data/bin/lb-project ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ root = Dir.pwd
5
+ $LOAD_PATH << File.join(root, 'lib')
6
+
7
+ require 'yaml'
8
+ LB_PROJECT_YML = 'config/lb-project.yml'
9
+ config_file = File.join(root, LB_PROJECT_YML)
10
+ unless File.exist?(config_file)
11
+ puts "#{LB_PROJECT_YML} not found: '#{config_file}'"
12
+ exit 1
13
+ end
14
+ config = YAML.load_file(config_file)
15
+
16
+ begin
17
+ namespace = config.fetch('namespace')
18
+ require namespace
19
+ LB::Project::Render.new.call
20
+ exit 0
21
+ rescue KeyError
22
+ puts "'namespace' not set in '#{LB_PROJECT_YML}'!"
23
+ raise
24
+ rescue LoadError
25
+ puts "Can not require namespace '#{namespace}'!"
26
+ puts "Please fix namespace in '#{LB_PROJECT_YML}'."
27
+ raise
28
+ end
29
+ exit 1
@@ -0,0 +1,2 @@
1
+ ---
2
+ unit_test_timeout: 0.1
data/config/flay.yml ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ threshold: 4
3
+ total_score: 18
data/config/flog.yml ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ threshold: 8.6
data/config/mutant.yml ADDED
@@ -0,0 +1,3 @@
1
+ name: lb-project
2
+ namespace: LB::Project
3
+ ignore_subjects: []
data/config/reek.yml ADDED
@@ -0,0 +1,103 @@
1
+ ---
2
+ Attribute:
3
+ enabled: false
4
+ exclude: []
5
+ BooleanParameter:
6
+ enabled: true
7
+ exclude: []
8
+ ClassVariable:
9
+ enabled: true
10
+ exclude: []
11
+ ControlParameter:
12
+ enabled: true
13
+ exclude: []
14
+ DataClump:
15
+ enabled: true
16
+ exclude: []
17
+ max_copies: 0
18
+ min_clump_size: 2
19
+ DuplicateMethodCall:
20
+ enabled: true
21
+ exclude: []
22
+ max_calls: 1
23
+ allow_calls: []
24
+ FeatureEnvy:
25
+ enabled: true
26
+ exclude: []
27
+ IrresponsibleModule:
28
+ enabled: true
29
+ exclude: []
30
+ LongParameterList:
31
+ enabled: true
32
+ exclude: []
33
+ max_params: 2
34
+ overrides: {}
35
+ LongYieldList:
36
+ enabled: true
37
+ exclude: []
38
+ max_params: 0
39
+ NestedIterators:
40
+ enabled: true
41
+ exclude: []
42
+ max_allowed_nesting: 1
43
+ ignore_iterators: []
44
+ NilCheck:
45
+ enabled: true
46
+ exclude: []
47
+ RepeatedConditional:
48
+ enabled: true
49
+ exclude: []
50
+ max_ifs: 1
51
+ TooManyConstants:
52
+ enabled: true
53
+ exclude: []
54
+ TooManyInstanceVariables:
55
+ enabled: true
56
+ exclude: []
57
+ max_instance_variables: 2
58
+ TooManyMethods:
59
+ enabled: true
60
+ exclude: []
61
+ max_methods: 15
62
+ TooManyStatements:
63
+ enabled: true
64
+ exclude: []
65
+ max_statements: 5
66
+ UncommunicativeMethodName:
67
+ enabled: true
68
+ exclude: []
69
+ reject:
70
+ - !ruby/regexp /^[a-z]$/
71
+ - !ruby/regexp /[0-9]$/
72
+ - !ruby/regexp /[A-Z]/
73
+ accept: []
74
+ UncommunicativeModuleName:
75
+ enabled: true
76
+ exclude: []
77
+ reject:
78
+ - !ruby/regexp /^.$/
79
+ - !ruby/regexp /[0-9]$/
80
+ accept: []
81
+ UncommunicativeParameterName:
82
+ enabled: true
83
+ exclude: []
84
+ reject:
85
+ - !ruby/regexp /^.$/
86
+ - !ruby/regexp /[0-9]$/
87
+ - !ruby/regexp /[A-Z]/
88
+ accept: []
89
+ UncommunicativeVariableName:
90
+ enabled: true
91
+ exclude: []
92
+ reject:
93
+ - !ruby/regexp /^.$/
94
+ - !ruby/regexp /[0-9]$/
95
+ - !ruby/regexp /[A-Z]/
96
+ accept: []
97
+ UnusedParameters:
98
+ enabled: true
99
+ exclude: []
100
+ UtilityFunction:
101
+ enabled: true
102
+ exclude: []
103
+ max_helper_calls: 0
@@ -0,0 +1,10 @@
1
+ AllCops:
2
+ DisplayCopNames: true
3
+ Exclude: []
4
+ Naming/FileName:
5
+ Exclude:
6
+ - Rakefile
7
+ Metrics/BlockLength:
8
+ Exclude:
9
+ - 'spec/**/*'
10
+ - '*.gemspec'
@@ -0,0 +1,2 @@
1
+ ---
2
+ threshold: 100.0
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require File.expand_path('../lib/lb/project/version', __FILE__)
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'lb-project'
8
+ gem.version = LB::Project::VERSION.dup
9
+ gem.authors = ['Firas Zaidan']
10
+ gem.email = ['firas@zaidan.de']
11
+ gem.description = 'Static site builder with easy migration to dynamic site'
12
+ gem.summary = gem.description
13
+ gem.homepage = 'https://github.com/lb-rb/lb-project'
14
+ gem.license = 'MIT'
15
+
16
+ gem.bindir = 'bin'
17
+ gem.require_paths = %w[lib bin]
18
+ gem.files = `git ls-files`
19
+ .split($INPUT_RECORD_SEPARATOR)
20
+ gem.executables = `git ls-files -- bin/*`
21
+ .split("\n").map { |f| File.basename(f) }
22
+ gem.test_files = `git ls-files -- spec`
23
+ .split($INPUT_RECORD_SEPARATOR)
24
+ gem.extra_rdoc_files = %w[README.md]
25
+ gem.required_ruby_version = '>= 2.5'
26
+
27
+ gem.add_dependency 'dry-initializer', '~> 2.3', '< 2.4'
28
+ gem.add_dependency 'dry-struct', '~> 0.4', '< 0.5'
29
+ gem.add_dependency 'dry-types', '~> 0.12', '< 0.13'
30
+ gem.add_dependency 'dry-view', '~> 0.3', '>= 0.3.0', '< 0.3.1'
31
+ gem.add_dependency 'r18n-core', '~> 2.2', '< 2.3'
32
+ gem.add_dependency 'roda', '~> 2.29', '< 2.30'
33
+ gem.add_dependency 'roda-i18n', '~> 0.3', '< 0.4'
34
+
35
+ gem.add_development_dependency 'devtools', '~> 0.1.19'
36
+ gem.add_development_dependency 'guard', '~> 2.14'
37
+ gem.add_development_dependency 'guard-bundler', '~> 2.1'
38
+ gem.add_development_dependency 'guard-rspec', '~> 4.7', '>= 4.7.3'
39
+ gem.add_development_dependency 'guard-rubocop', '~> 1.3'
40
+ gem.add_development_dependency 'rubocop', '~> 0.52'
41
+ gem.add_development_dependency 'slim', '~> 3.0'
42
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LB
4
+ module Project
5
+ # Base class for main routing entry point
6
+ class App < LB::Project::Route
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LB
4
+ module Project
5
+ # Configuration
6
+ class Config < Dry::Struct
7
+ RequiredString = Types::Strict::String.constrained(min_size: 1)
8
+
9
+ attribute :base_path, Types::Strict::String
10
+ attribute :image_base_path, Types::Strict::String
11
+ attribute :public_path, Types::Strict::String
12
+ attribute :template_path, Types::Strict::String
13
+
14
+ def self.load(root, name, env)
15
+ path = File.join(File.join(root, 'config'), "#{name}.yml")
16
+ yaml = File.exist?(path) ? YAML.load_file(path) : {}
17
+
18
+ new(config(yaml, env))
19
+ end
20
+
21
+ def self.config(yaml, env)
22
+ schema.keys.each_with_object({}) do |key, memo|
23
+ memo[key] = value_for(yaml, env, key)
24
+ end
25
+ end
26
+
27
+ def self.value_for(yaml, env, key)
28
+ ENV.fetch(
29
+ key.to_s.upcase,
30
+ yaml.fetch(env.to_s, {})[key.to_s]
31
+ )
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LB
4
+ module Project
5
+ # Page view
6
+ class Page < View
7
+ extend LB::Project::Registry::Registration[:page]
8
+
9
+ def title
10
+ t = LB::Project.t.page
11
+ self.class.page_key.split('/').each do |key|
12
+ t = t.send(key)
13
+ end
14
+
15
+ t.title
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LB
4
+ module Project
5
+ class Registry
6
+ # Mixin for registration
7
+ module Registration
8
+ def self.[](registry_name, registry = LB::Project::Registry.new)
9
+ rcmethod = "#{registry_name}_registry_config"
10
+ setup(registry_name, registry, rcmethod)
11
+ define_helpers(registry_name, rcmethod) unless respond_to?(rcmethod)
12
+
13
+ self
14
+ end
15
+
16
+ def self.define_helpers(registry_name, rcmethod)
17
+ rmethod = "#{registry_name}_registry"
18
+
19
+ define_registry_config(rcmethod)
20
+ define_registry(rcmethod, rmethod)
21
+ define_registry_name(registry_name, rcmethod)
22
+ define_registry_as(registry_name, rmethod)
23
+ define_key(registry_name)
24
+ end
25
+
26
+ def self.define_registry_config(rcmethod)
27
+ define_method(rcmethod) do
28
+ Registration.instance_variable_get("@#{rcmethod}")
29
+ end
30
+ end
31
+
32
+ def self.define_registry(rcmethod, rmethod)
33
+ define_method(rmethod) do
34
+ send(rcmethod).registry
35
+ end
36
+ end
37
+
38
+ def self.define_registry_name(registry_name, rcmethod)
39
+ rnmethod = "#{registry_name}_registry_name"
40
+ define_method(rnmethod) do
41
+ send(rcmethod).name
42
+ end
43
+ end
44
+
45
+ def self.define_registry_as(registry_name, rmethod)
46
+ define_method("register_#{registry_name}_as") do |key|
47
+ send(rmethod).register(key.to_s, self)
48
+ instance_variable_set("@#{registry_name}_key", key.to_s)
49
+ end
50
+ end
51
+
52
+ def self.define_key(registry_name)
53
+ define_method("#{registry_name}_key") do
54
+ instance_variable_get("@#{registry_name}_key")
55
+ end
56
+ end
57
+
58
+ def self.setup(registry_name, registry, rcmethod)
59
+ config = Config.new(registry_name, registry)
60
+ Registration.instance_variable_set("@#{rcmethod}", config)
61
+ end
62
+
63
+ # Stores the registration configuration
64
+ class Config
65
+ extend Dry::Initializer
66
+
67
+ param :name, Dry::Types['coercible.string']
68
+ param :registry
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LB
4
+ module Project
5
+ # Basic key value store
6
+ class Registry
7
+ include Dry::Equalizer(:keys)
8
+ include Enumerable
9
+
10
+ attr_reader :keys
11
+
12
+ # Error that is raised when key is not found in registry
13
+ class KeyNotFoundError < KeyError
14
+ def initialize(key)
15
+ super("#{key.inspect} doesn't exist in registry")
16
+ end
17
+ end
18
+
19
+ def initialize(keys = {})
20
+ @keys = keys
21
+ end
22
+
23
+ def each(&block)
24
+ return to_enum unless block
25
+ keys.each_pair { |key, value| yield(key, value) }
26
+ end
27
+
28
+ def key?(key)
29
+ !key.nil? && keys.key?(key.to_sym)
30
+ end
31
+
32
+ def fetch(key)
33
+ raise ArgumentError, 'key cannot be nil' if key.nil?
34
+
35
+ keys.fetch(key.to_sym) do
36
+ return yield if block_given?
37
+
38
+ raise KeyNotFoundError, key
39
+ end
40
+ end
41
+ alias [] fetch
42
+
43
+ def respond_to_missing?(key, include_private = false)
44
+ keys.key?(key) || super
45
+ end
46
+
47
+ def register(key, value)
48
+ keys[key] = value
49
+ end
50
+
51
+ private
52
+
53
+ def method_missing(key, *)
54
+ keys.fetch(key) { super }
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LB
4
+ module Project
5
+ # Render
6
+ class Render
7
+ def call
8
+ Page.page_registry.each do |name, klass|
9
+ page = klass.new
10
+ File.write(file_for(name), page.call(options(page)))
11
+ end
12
+ end
13
+
14
+ def file_for(name)
15
+ File.expand_path("#{name}.html", LB::Project.public_path).tap do |file|
16
+ FileUtils.mkdir_p File.dirname(file)
17
+ end
18
+ end
19
+
20
+ def options(page, locals = {})
21
+ {
22
+ context: ::Struct.new(:site, :page).new(LB::Project::Site.new, page),
23
+ locals: locals
24
+ }
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LB
4
+ module Project
5
+ # Base route
6
+ class Route < Roda
7
+ def self.setup(route)
8
+ translations = [File.join(LB::Project.root, 'locales')]
9
+ route.plugin :i18n, translations: translations
10
+ route.opts[:root] = LB::Project.root
11
+ route.plugin :public, root: 'docs'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LB
4
+ module Project
5
+ # Site context for templates
6
+ class Site
7
+ include R18n::Helpers
8
+
9
+ def initialize(context = {})
10
+ @context = context
11
+ end
12
+
13
+ def options
14
+ @options ||= {}
15
+ end
16
+
17
+ def [](*args)
18
+ options.fetch(*args)
19
+ end
20
+
21
+ def path_for(bundle, type)
22
+ path = 'webpack-assets.json'
23
+ file = File.read(path)
24
+ json = JSON.parse(file)
25
+ LB::Project.config.base_path + json[bundle][type]
26
+ end
27
+
28
+ def js_for(bundle)
29
+ path_for(bundle, 'js')
30
+ end
31
+
32
+ def css_for(bundle)
33
+ path_for(bundle, 'css')
34
+ end
35
+
36
+ def image_path(path)
37
+ "#{LB::Project.config.image_base_path}/#{path}"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LB
4
+ module Project
5
+ # Custom Types
6
+ module Types
7
+ include Dry::Types.module
8
+ end
9
+ end
10
+ end