frontman-ssg 0.0.2
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/.circleci/config.yml +42 -0
- data/.github/CODE_OF_CONDUCT.md +9 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +25 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +88 -0
- data/CHANGELOG.md +11 -0
- data/CONTRIBUTING.md +42 -0
- data/Gemfile +5 -0
- data/LICENSE.md +21 -0
- data/Rakefile +94 -0
- data/SECURITY.md +6 -0
- data/bin/frontman +6 -0
- data/frontman-ssg.gemspec +48 -0
- data/frontman.svg +2 -0
- data/lib/frontman.rb +15 -0
- data/lib/frontman/app.rb +175 -0
- data/lib/frontman/bootstrapper.rb +70 -0
- data/lib/frontman/builder/asset_pipeline.rb +55 -0
- data/lib/frontman/builder/builder.rb +193 -0
- data/lib/frontman/builder/file.rb +55 -0
- data/lib/frontman/builder/mapping.rb +54 -0
- data/lib/frontman/builder/statistics_collector.rb +37 -0
- data/lib/frontman/cli.rb +6 -0
- data/lib/frontman/commands/build.rb +76 -0
- data/lib/frontman/commands/init.rb +58 -0
- data/lib/frontman/commands/serve.rb +110 -0
- data/lib/frontman/concerns/dispatch_events.rb +56 -0
- data/lib/frontman/concerns/forward_calls_to_app.rb +28 -0
- data/lib/frontman/config.rb +52 -0
- data/lib/frontman/context.rb +125 -0
- data/lib/frontman/custom_struct.rb +44 -0
- data/lib/frontman/data_store.rb +106 -0
- data/lib/frontman/data_store_file.rb +60 -0
- data/lib/frontman/helpers/app_helper.rb +18 -0
- data/lib/frontman/helpers/link_helper.rb +35 -0
- data/lib/frontman/helpers/render_helper.rb +76 -0
- data/lib/frontman/helpers/url_helper.rb +11 -0
- data/lib/frontman/iterator.rb +48 -0
- data/lib/frontman/process/chain.rb +43 -0
- data/lib/frontman/process/processor.rb +11 -0
- data/lib/frontman/renderers/erb_renderer.rb +21 -0
- data/lib/frontman/renderers/haml_renderer.rb +22 -0
- data/lib/frontman/renderers/markdown_renderer.rb +26 -0
- data/lib/frontman/renderers/renderer.rb +26 -0
- data/lib/frontman/renderers/renderer_resolver.rb +26 -0
- data/lib/frontman/resource.rb +279 -0
- data/lib/frontman/sitemap_tree.rb +211 -0
- data/lib/frontman/toolbox/timer.rb +49 -0
- data/lib/frontman/version.rb +6 -0
- data/project-templates/default/.gitignore +2 -0
- data/project-templates/default/Gemfile +3 -0
- data/project-templates/default/config.rb +17 -0
- data/project-templates/default/data/site.yml +4 -0
- data/project-templates/default/helpers/site_helper.rb +7 -0
- data/project-templates/default/public/code.css +77 -0
- data/project-templates/default/public/frontman-logo.svg +2 -0
- data/project-templates/default/public/main.css +27 -0
- data/project-templates/default/public/main.js +1 -0
- data/project-templates/default/source/index.html.md.erb +7 -0
- data/project-templates/default/source/sitemap.xml.erb +11 -0
- data/project-templates/default/views/layouts/main.erb +19 -0
- data/project-templates/default/views/layouts/main.haml +15 -0
- data/project-templates/default/views/partials/menu.erb +7 -0
- data/project-templates/webpack/.gitignore +4 -0
- data/project-templates/webpack/Gemfile +3 -0
- data/project-templates/webpack/README.md +54 -0
- data/project-templates/webpack/assets/css/code.css +77 -0
- data/project-templates/webpack/assets/css/style.css +27 -0
- data/project-templates/webpack/assets/images/.gitkeep +0 -0
- data/project-templates/webpack/assets/images/frontman_logo.svg +2 -0
- data/project-templates/webpack/assets/js/index.js +1 -0
- data/project-templates/webpack/config.rb +24 -0
- data/project-templates/webpack/data/site.yml +4 -0
- data/project-templates/webpack/helpers/assets_helper.rb +24 -0
- data/project-templates/webpack/helpers/site_helper.rb +7 -0
- data/project-templates/webpack/package-lock.json +7603 -0
- data/project-templates/webpack/package.json +34 -0
- data/project-templates/webpack/source/index.html.md.erb +7 -0
- data/project-templates/webpack/source/sitemap.xml.erb +11 -0
- data/project-templates/webpack/views/layouts/main.erb +20 -0
- data/project-templates/webpack/views/layouts/main.haml +14 -0
- data/project-templates/webpack/views/partials/menu.erb +7 -0
- data/project-templates/webpack/views/partials/script_with_vendors.haml +5 -0
- data/project-templates/webpack/webpack/base.config.js +51 -0
- data/project-templates/webpack/webpack/dev.config.js +6 -0
- data/project-templates/webpack/webpack/prod.config.js +30 -0
- data/readme.md +80 -0
- data/sorbet/config +2 -0
- data/sorbet/rbi/hidden-definitions/errors.txt +27259 -0
- data/sorbet/rbi/hidden-definitions/hidden.rbi +45122 -0
- data/sorbet/rbi/sorbet-typed/lib/rainbow/all/rainbow.rbi +276 -0
- data/sorbet/rbi/todo.rbi +6 -0
- data/spec/frontman/app_spec.rb +48 -0
- data/spec/frontman/bootstrapper_spec.rb +26 -0
- data/spec/frontman/builder/builder_spec.rb +79 -0
- data/spec/frontman/builder/file_spec.rb +45 -0
- data/spec/frontman/builder/mapping_spec.rb +8 -0
- data/spec/frontman/concerns/dispatch_events_spec.rb +70 -0
- data/spec/frontman/concerns/forward_calls_to_app_spec.rb +21 -0
- data/spec/frontman/config_spec.rb +54 -0
- data/spec/frontman/context_spec.rb +48 -0
- data/spec/frontman/custom_struct_spec.rb +51 -0
- data/spec/frontman/data_store_file_spec.rb +9 -0
- data/spec/frontman/data_store_spec.rb +36 -0
- data/spec/frontman/frontman_ssg_spec.rb +7 -0
- data/spec/frontman/helpers/app_helper_spec.rb +24 -0
- data/spec/frontman/helpers/link_helper_spec.rb +37 -0
- data/spec/frontman/helpers/render_helper_spec.rb +55 -0
- data/spec/frontman/helpers/url_helper_spec.rb +21 -0
- data/spec/frontman/iterator_spec.rb +47 -0
- data/spec/frontman/mocks/asset.css +3 -0
- data/spec/frontman/mocks/config.rb +0 -0
- data/spec/frontman/mocks/helpers/formatting_helper.rb +5 -0
- data/spec/frontman/mocks/helpers/language_helper.rb +5 -0
- data/spec/frontman/mocks/helpers/link_helper.rb +5 -0
- data/spec/frontman/mocks/helpers/test_command.rb +5 -0
- data/spec/frontman/mocks/html_file.html +8 -0
- data/spec/frontman/mocks/html_file.html.md.erb +9 -0
- data/spec/frontman/mocks/html_file.md.html +8 -0
- data/spec/frontman/mocks/info.yml +4 -0
- data/spec/frontman/mocks/layouts/raw_without_body.haml +1 -0
- data/spec/frontman/mocks/nested/data.yml +4 -0
- data/spec/frontman/mocks/nested/more_data.yml +4 -0
- data/spec/frontman/mocks/partials/paragraph.haml +2 -0
- data/spec/frontman/mocks/snippet/html_file.html +8 -0
- data/spec/frontman/mocks/snippet/html_file.yml +670 -0
- data/spec/frontman/mocks/test.html +8 -0
- data/spec/frontman/mocks/wrap.haml +3 -0
- data/spec/frontman/process/chain_spec.rb +56 -0
- data/spec/frontman/renderers/erb_renderer_spec.rb +22 -0
- data/spec/frontman/renderers/haml_renderer_spec.rb +12 -0
- data/spec/frontman/renderers/markdown_renderer_spec.rb +12 -0
- data/spec/frontman/renderers/renderer_spec.rb +16 -0
- data/spec/frontman/resource_spec.rb +151 -0
- data/spec/frontman/sitemap_tree_spec.rb +128 -0
- data/spec/frontman/toolbox/timer_spec.rb +34 -0
- data/spec/spec_setup.rb +19 -0
- metadata +507 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Frontman
|
|
5
|
+
module ForwardCallsToApp
|
|
6
|
+
def self.included(klass)
|
|
7
|
+
klass.extend Frontman::ForwardCallsToApp::ClassMethods
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def method_missing(method_id, *arguments, &block)
|
|
11
|
+
Frontman::App.instance.public_send(method_id, *arguments, &block)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def respond_to_missing?(method_name, _ = false)
|
|
15
|
+
Frontman::App.instance.respond_to?(method_name)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module ClassMethods
|
|
19
|
+
def method_missing(method_id, *arguments, &block)
|
|
20
|
+
Frontman::App.instance.public_send(method_id, *arguments, &block)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def respond_to_missing?(method_name, _ = false)
|
|
24
|
+
Frontman::App.instance.respond_to?(method_name)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'sorbet-runtime'
|
|
5
|
+
|
|
6
|
+
module Frontman
|
|
7
|
+
class Config
|
|
8
|
+
class << self
|
|
9
|
+
extend T::Sig
|
|
10
|
+
|
|
11
|
+
sig do
|
|
12
|
+
params(
|
|
13
|
+
key: T.any(String, Symbol), value: T.untyped
|
|
14
|
+
).returns(T.self_type)
|
|
15
|
+
end
|
|
16
|
+
def set(key, value)
|
|
17
|
+
@@values ||= {}
|
|
18
|
+
@@values[key.to_sym] = value
|
|
19
|
+
self
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
sig do
|
|
23
|
+
params(
|
|
24
|
+
key: T.any(String, Symbol), fallback: T.untyped
|
|
25
|
+
).returns(T.untyped)
|
|
26
|
+
end
|
|
27
|
+
def get(key, fallback: nil)
|
|
28
|
+
@@values ||= {}
|
|
29
|
+
@@values.key?(key.to_sym) ? @@values[key.to_sym] : fallback
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
sig { params(key: T.any(String, Symbol)).returns(T.self_type) }
|
|
33
|
+
def delete(key)
|
|
34
|
+
@@values ||= {}
|
|
35
|
+
@@values.delete(key)
|
|
36
|
+
self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
sig { params(key: T.any(String, Symbol)).returns(T::Boolean) }
|
|
40
|
+
def has?(key)
|
|
41
|
+
@@values ||= {}
|
|
42
|
+
@@values.key?(key.to_sym)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
sig { returns(Hash) }
|
|
46
|
+
def all
|
|
47
|
+
@@values ||= {}
|
|
48
|
+
@@values
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
4
|
+
require 'frontman/app'
|
|
5
|
+
require 'frontman/concerns/forward_calls_to_app'
|
|
6
|
+
require 'frontman/config'
|
|
7
|
+
require 'sorbet-runtime'
|
|
8
|
+
|
|
9
|
+
module Frontman
|
|
10
|
+
class Context
|
|
11
|
+
extend T::Sig
|
|
12
|
+
include Frontman::ForwardCallsToApp
|
|
13
|
+
|
|
14
|
+
sig { params(layout: String).returns(String) }
|
|
15
|
+
def wrap_layout(layout)
|
|
16
|
+
layout_dir = Frontman::Config.get(:layout_dir, fallback: 'views/layouts')
|
|
17
|
+
layout_path = File.join(layout_dir, layout)
|
|
18
|
+
|
|
19
|
+
# Haml is not designed to do handle wrap_layout properly
|
|
20
|
+
# so we need to hack the buffer of haml that is set
|
|
21
|
+
# inside the context by haml
|
|
22
|
+
save_buffer
|
|
23
|
+
|
|
24
|
+
# We don't save the content of the yield, it will be saved in the buffer
|
|
25
|
+
yield
|
|
26
|
+
|
|
27
|
+
# The buffer now contains the content of the yield
|
|
28
|
+
content = load_buffer
|
|
29
|
+
|
|
30
|
+
# Restore the buffer so the rendering of the file can continue
|
|
31
|
+
restore_buffer
|
|
32
|
+
|
|
33
|
+
Resource.from_path(layout_path, nil, false).render(content)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
sig do
|
|
37
|
+
params(key: T.any(String, Symbol), content: T.untyped)
|
|
38
|
+
.returns(T.untyped)
|
|
39
|
+
end
|
|
40
|
+
def content_for(key, content = nil)
|
|
41
|
+
# Haml is not designed to do handle content_for properly
|
|
42
|
+
# so we need to hack the buffer of haml that is set
|
|
43
|
+
# inside the context by haml
|
|
44
|
+
save_buffer
|
|
45
|
+
|
|
46
|
+
content ||= ''
|
|
47
|
+
|
|
48
|
+
if block_given?
|
|
49
|
+
# We don't save the content of the yield, it will be saved in the buffer
|
|
50
|
+
yield
|
|
51
|
+
|
|
52
|
+
# The buffer now contains the content of the yield
|
|
53
|
+
content = load_buffer
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Restore the buffer so the rendering of the file can continue
|
|
57
|
+
restore_buffer
|
|
58
|
+
|
|
59
|
+
# We store the the content block inside the current page
|
|
60
|
+
# because we don't know which renderer/layout/template will need it
|
|
61
|
+
current_page = Frontman::App.instance.current_page
|
|
62
|
+
current_page.content_blocks[key.to_sym] = content unless current_page.nil?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
sig { params(key: T.any(String, Symbol)).returns(T::Boolean) }
|
|
66
|
+
def content_for?(key)
|
|
67
|
+
Frontman::App.instance.current_page.content_blocks.key?(key.to_sym)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
sig do
|
|
71
|
+
params(key: T.any(String, Symbol), _args: T.untyped).returns(T.untyped)
|
|
72
|
+
end
|
|
73
|
+
def yield_content(key, *_args)
|
|
74
|
+
Frontman::App.instance.current_page.content_blocks[key.to_sym]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
sig do
|
|
78
|
+
params(content: T.untyped).returns(T.untyped)
|
|
79
|
+
end
|
|
80
|
+
def get_binding(&content)
|
|
81
|
+
binding { content }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
sig { void }
|
|
87
|
+
def save_buffer
|
|
88
|
+
haml_locals = instance_variable_get(:@_haml_locals)
|
|
89
|
+
|
|
90
|
+
if haml_locals
|
|
91
|
+
# save buffer
|
|
92
|
+
@buffer = haml_locals[:_hamlout].buffer
|
|
93
|
+
# empty the buffer so we can capture everything from the new render
|
|
94
|
+
haml_locals[:_hamlout].buffer = ''
|
|
95
|
+
else
|
|
96
|
+
# save buffer
|
|
97
|
+
@buffer = instance_variable_get(:@_erbout)
|
|
98
|
+
# empty the buffer so we can capture everything from the new render
|
|
99
|
+
instance_variable_set(:@_erbout, '')
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
sig { void }
|
|
104
|
+
def restore_buffer
|
|
105
|
+
haml_locals = instance_variable_get(:@_haml_locals)
|
|
106
|
+
|
|
107
|
+
if haml_locals
|
|
108
|
+
haml_locals[:_hamlout].buffer = @buffer
|
|
109
|
+
else
|
|
110
|
+
instance_variable_set(:@_erbout, @buffer)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
sig { returns(T.untyped) }
|
|
115
|
+
def load_buffer
|
|
116
|
+
haml_locals = instance_variable_get(:@_haml_locals)
|
|
117
|
+
|
|
118
|
+
if haml_locals
|
|
119
|
+
haml_locals[:_hamlout].buffer
|
|
120
|
+
else
|
|
121
|
+
instance_variable_get(:@_erbout)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
class CustomStruct < OpenStruct
|
|
7
|
+
def respond_to_missing?(method_id, *_arguments)
|
|
8
|
+
to_h.respond_to?(method_id) || super(method_id)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def key?(key)
|
|
12
|
+
to_h.key?(key)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def method_missing(method_id, *arguments, &block)
|
|
16
|
+
if to_h.respond_to?(method_id)
|
|
17
|
+
to_h.public_send(method_id, *arguments, &block)
|
|
18
|
+
else
|
|
19
|
+
super(method_id, *arguments)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class Hash
|
|
25
|
+
def to_ostruct
|
|
26
|
+
arr = map do |k, v|
|
|
27
|
+
if v.is_a? Array
|
|
28
|
+
[k, v.map { |el| el.respond_to?(:to_ostruct) ? el.to_ostruct : el }]
|
|
29
|
+
else
|
|
30
|
+
[k, v.respond_to?(:to_ostruct) ? v.to_ostruct : v]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
CustomStruct.new(Hash[arr])
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class Array
|
|
39
|
+
def to_ostruct
|
|
40
|
+
map do |item|
|
|
41
|
+
item.respond_to?(:to_ostruct) ? item.to_ostruct : item
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
4
|
+
require 'pathname'
|
|
5
|
+
require 'frontman/data_store_file'
|
|
6
|
+
require 'sorbet-runtime'
|
|
7
|
+
|
|
8
|
+
module Frontman
|
|
9
|
+
class DataStore
|
|
10
|
+
extend T::Sig
|
|
11
|
+
|
|
12
|
+
attr_reader :base_file_name, :path, :parent
|
|
13
|
+
|
|
14
|
+
sig do
|
|
15
|
+
params(
|
|
16
|
+
path: String,
|
|
17
|
+
base_file_name: T.nilable(String),
|
|
18
|
+
parent: T.nilable(DataStore)
|
|
19
|
+
).void
|
|
20
|
+
end
|
|
21
|
+
def initialize(path, base_file_name = nil, parent = nil)
|
|
22
|
+
@path = path
|
|
23
|
+
@cache = {}
|
|
24
|
+
@parent = parent
|
|
25
|
+
@base_file_name = base_file_name
|
|
26
|
+
|
|
27
|
+
load_files
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
sig { returns(Array) }
|
|
31
|
+
def flatten
|
|
32
|
+
elements = []
|
|
33
|
+
|
|
34
|
+
@cache.sort_by { |_k, v| v.path }.each do |_k, v|
|
|
35
|
+
if v.instance_of?(Frontman::DataStoreFile)
|
|
36
|
+
v.refresh
|
|
37
|
+
elements.push(v)
|
|
38
|
+
else
|
|
39
|
+
elements.push(*v.flatten)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
elements
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def method_missing(method_id, *arguments, &block)
|
|
47
|
+
method_name = method_id
|
|
48
|
+
|
|
49
|
+
# Make sure we are able to access data files with an array syntax
|
|
50
|
+
method_name = arguments[0].to_sym if method_id == :[]
|
|
51
|
+
|
|
52
|
+
if @cache.key?(method_name.to_s)
|
|
53
|
+
cached = @cache[method_name.to_s]
|
|
54
|
+
|
|
55
|
+
if Frontman::App.instance.refresh_data_files
|
|
56
|
+
cached.refresh if cached.is_a?(Frontman::DataStoreFile)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
return cached
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Make sure we forward the access to the data
|
|
63
|
+
if @cache.respond_to?(method_name)
|
|
64
|
+
return @cache.public_send(method_name, &block)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
nil
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def respond_to_missing?(method_name, _)
|
|
71
|
+
@cache.key?(method_name.to_s) || @cache.respond_to?(method_name)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
sig { returns(String) }
|
|
75
|
+
def to_s
|
|
76
|
+
"<DataStore #{@cache.keys.join(', ')} >"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
sig { void }
|
|
82
|
+
def load_files
|
|
83
|
+
Dir.entries(@path).sort.each do |file|
|
|
84
|
+
next if (file == '.') || (file == '..')
|
|
85
|
+
|
|
86
|
+
file_path = @path + '/' + file
|
|
87
|
+
|
|
88
|
+
# remove numbers and first '-' from the filename so we can
|
|
89
|
+
# - generate nice urls
|
|
90
|
+
# - omit the number when accessing the object
|
|
91
|
+
base_file_name = file.gsub(/[0-9]*+-?(.+)/, '\1')
|
|
92
|
+
|
|
93
|
+
if File.file?(file_path) && (File.extname(file) == '.yml')
|
|
94
|
+
method_name = File.basename(base_file_name, File.extname(file))
|
|
95
|
+
@cache[method_name.to_s] = Frontman::DataStoreFile.new(
|
|
96
|
+
file_path, file, method_name, self
|
|
97
|
+
)
|
|
98
|
+
elsif File.directory?(file_path)
|
|
99
|
+
@cache[base_file_name] = DataStore.new(
|
|
100
|
+
file_path, base_file_name, self
|
|
101
|
+
)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
4
|
+
require 'pathname'
|
|
5
|
+
require 'sorbet-runtime'
|
|
6
|
+
require 'yaml'
|
|
7
|
+
|
|
8
|
+
module Frontman
|
|
9
|
+
class DataStoreFile
|
|
10
|
+
extend T::Sig
|
|
11
|
+
attr_accessor :path, :file_name, :base_file_name, :parent,
|
|
12
|
+
:position, :data
|
|
13
|
+
|
|
14
|
+
sig do
|
|
15
|
+
params(
|
|
16
|
+
path: String,
|
|
17
|
+
file_name: String,
|
|
18
|
+
base_file_name: String,
|
|
19
|
+
parent: DataStore
|
|
20
|
+
).void
|
|
21
|
+
end
|
|
22
|
+
def initialize(path, file_name, base_file_name, parent)
|
|
23
|
+
@path = path
|
|
24
|
+
@file_name = file_name
|
|
25
|
+
@base_file_name = base_file_name
|
|
26
|
+
@parent = parent
|
|
27
|
+
@data = (YAML.load_file(@path) || {}).to_ostruct
|
|
28
|
+
|
|
29
|
+
@@i ||= 0
|
|
30
|
+
@position = @@i
|
|
31
|
+
@@i += 1
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def method_missing(method_id, *arguments, &block)
|
|
35
|
+
@data.public_send(method_id, *arguments, &block)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def respond_to_missing?(method_id, _)
|
|
39
|
+
@data.respond_to? method_id
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
sig { returns(String) }
|
|
43
|
+
def current_path
|
|
44
|
+
@path
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
sig { void }
|
|
48
|
+
def refresh
|
|
49
|
+
return unless Frontman::App.instance.refresh_data_files
|
|
50
|
+
|
|
51
|
+
data = YAML.load_file(@path) || {}
|
|
52
|
+
@data = data.to_ostruct
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
sig { returns(String) }
|
|
56
|
+
def to_s
|
|
57
|
+
"<DataStoreFile #{@data.keys.join(', ')} >"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
4
|
+
require 'frontman/config'
|
|
5
|
+
|
|
6
|
+
module AppHelper
|
|
7
|
+
extend T::Sig
|
|
8
|
+
|
|
9
|
+
sig { returns(T::Boolean) }
|
|
10
|
+
def build?
|
|
11
|
+
Frontman::Config.get(:mode) == 'build'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
sig { returns(T::Boolean) }
|
|
15
|
+
def serve?
|
|
16
|
+
!build?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
4
|
+
require 'htmlentities'
|
|
5
|
+
require 'singleton'
|
|
6
|
+
require 'sorbet-runtime'
|
|
7
|
+
|
|
8
|
+
module LinkHelper
|
|
9
|
+
extend T::Sig
|
|
10
|
+
|
|
11
|
+
sig { params(str: String, salt: String).returns(String) }
|
|
12
|
+
def generate_id(str, salt = '')
|
|
13
|
+
id = slugify(str)
|
|
14
|
+
|
|
15
|
+
@ids ||= {}
|
|
16
|
+
@ids[salt.to_s + id] ||= 0
|
|
17
|
+
@ids[salt.to_s + id] += 1
|
|
18
|
+
@ids[salt.to_s + id] == 1 ? id : "#{id}-#{@ids[salt.to_s + id]}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
sig { void }
|
|
22
|
+
def reset_ids_generation
|
|
23
|
+
@ids = {}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
sig { params(string: String).returns(String) }
|
|
27
|
+
def slugify(string)
|
|
28
|
+
HTMLEntities.new
|
|
29
|
+
.decode(string)
|
|
30
|
+
.gsub(%r{</?[^>]*>}, '')
|
|
31
|
+
.gsub(/\s/, '-')
|
|
32
|
+
.gsub(%r{[\[\]()/",`'&<>\.*]}, '')
|
|
33
|
+
.downcase
|
|
34
|
+
end
|
|
35
|
+
end
|