frontman-ssg 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|