dirload 0.6.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/lib/adapters/adapter.rb +17 -0
- data/lib/adapters/markdown_adapter.rb +11 -0
- data/lib/adapters/rbx_adapter.rb +78 -0
- data/lib/adapters/ruby_adapter.rb +26 -0
- data/lib/dirload.rb +71 -0
- data/lib/loader.rb +46 -0
- data/lib/metadata.rb +21 -0
- data/lib/version.rb +5 -0
- metadata +64 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 96c8cec00fefea226ccd40b45b876c674ab1c58782033134d42b202c3b4fe27e
|
|
4
|
+
data.tar.gz: 52bd411227f4d22d78162e0a4a90eb1c23a80d9b63ce434d88e274eb173b4dec
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 70624c6d69e6a945a3e1cb18c55483ca07724cc683641dfe6ff1a3d2b733c5079c3294e1e4dada1c1612be38c7292cd064882cc0d8efb79eddcf52b2ebf74d73
|
|
7
|
+
data.tar.gz: 86c1ea5c9d70fe629351f2b07a6f1441c3bef6ff71ac6b7df2d8350e417c2dbebe09eb9f2025fe8d01aa56b01c268682d364e3ba9d3383fdec286da7b8a9e97b
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
|
4
|
+
|
|
5
|
+
module Dirload
|
|
6
|
+
class Adapter
|
|
7
|
+
EXTENSIONS = [].freeze
|
|
8
|
+
|
|
9
|
+
def mapload(file_path:) = nil
|
|
10
|
+
|
|
11
|
+
def preload(file_path:) = nil
|
|
12
|
+
|
|
13
|
+
def evaluate(file_path:, top_level_binding: nil) = nil
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lowkey'
|
|
4
|
+
require_relative 'adapter'
|
|
5
|
+
require_relative '../loader'
|
|
6
|
+
|
|
7
|
+
def top_level_binding
|
|
8
|
+
binding
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module Dirload
|
|
12
|
+
class RBXAdapter < Adapter
|
|
13
|
+
EXTENSIONS = ['rbx'].freeze
|
|
14
|
+
|
|
15
|
+
# Map all definitions and dependencies.
|
|
16
|
+
def mapload(file_path:)
|
|
17
|
+
Lowkey.load(file_path)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Then autoload all dependencies for those files.
|
|
21
|
+
def preload(file_path:)
|
|
22
|
+
Loader.add_autoloads(file_proxy: Lowkey[file_path])
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Now we can load the file into Ruby.
|
|
26
|
+
def evaluate(file_path:)
|
|
27
|
+
# 1. "File Load" phase.
|
|
28
|
+
file_proxy = Lowkey[file_path] || Lowkey.load(file_path)
|
|
29
|
+
templates = wrap_render_methods(file_proxy:)
|
|
30
|
+
|
|
31
|
+
# 2. "Class Load" phase.
|
|
32
|
+
# Not a security risk because "eval" is equivalent to "load" or "require_relative" in this context.
|
|
33
|
+
eval(file_proxy.export, top_level_binding, file_proxy.file_path, 0) # rubocop:disable Security/Eval
|
|
34
|
+
|
|
35
|
+
# 3. "Runtime" phase (before low nodes are rendered).
|
|
36
|
+
# Templates only exist if antlers gem has been required by another gem (like LowNode) and the template contains antlers syntax.
|
|
37
|
+
templates.each do |namespace, method_template|
|
|
38
|
+
klass = Object.const_get(namespace)
|
|
39
|
+
method, template = method_template
|
|
40
|
+
# TODO: If params contain "**props" or similar then send that, so that LowNode can replicate it.
|
|
41
|
+
params = method.params.map(&:name)
|
|
42
|
+
|
|
43
|
+
next unless supports_templates?(klass) || raise(UnsupportedTemplate, "Template for '#{namespace}' identified but not implemented")
|
|
44
|
+
|
|
45
|
+
# TODO: Make template engine configurable.
|
|
46
|
+
klass.build_template(template:, params:, engine: Antlers, namespace:)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def supports_templates?(klass)
|
|
53
|
+
klass.respond_to?(:render) && klass.respond_to?(:template) && klass.respond_to?(:build_template)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def wrap_render_methods(file_proxy:)
|
|
57
|
+
# GOAL: Templates could be organised by method and template rendering engine.
|
|
58
|
+
templates = {}
|
|
59
|
+
|
|
60
|
+
file_proxy.definitions.each_value do |class_proxy|
|
|
61
|
+
render_method = class_proxy.respond_to?(:instance_methods) ? class_proxy.instance_methods[:render] : nil
|
|
62
|
+
|
|
63
|
+
next unless render_method
|
|
64
|
+
|
|
65
|
+
render_method_body = render_method.body.export
|
|
66
|
+
|
|
67
|
+
if defined?(Antlers) && ['{', '<{'].any? { |needle| render_method_body.include?(needle) }
|
|
68
|
+
templates[class_proxy.namespace] = [render_method, render_method_body]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Intended to target HTML or Antlers tags. Use HEREDOC "<<~" in a plain Ruby (".rb") file, not RBX.
|
|
72
|
+
render_method.body.wrap(prefix: '%q{', suffix: '}') if render_method_body.strip.start_with?('<')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
templates
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lowkey'
|
|
4
|
+
require_relative 'adapter'
|
|
5
|
+
require_relative '../loader'
|
|
6
|
+
|
|
7
|
+
module Dirload
|
|
8
|
+
class RubyAdapter < Adapter
|
|
9
|
+
EXTENSIONS = ['rb'].freeze
|
|
10
|
+
|
|
11
|
+
# Map all definitions and dependencies.
|
|
12
|
+
def mapload(file_path:)
|
|
13
|
+
Lowkey.load(file_path)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Then autoload all dependencies for those files.
|
|
17
|
+
def preload(file_path:)
|
|
18
|
+
Loader.add_autoloads(file_proxy: Lowkey[file_path])
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Now we can load the file into Ruby.
|
|
22
|
+
def evaluate(file_path:)
|
|
23
|
+
load(file_path)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/dirload.rb
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'adapters/markdown_adapter'
|
|
4
|
+
require_relative 'adapters/rbx_adapter'
|
|
5
|
+
require_relative 'adapters/ruby_adapter'
|
|
6
|
+
require_relative 'loader'
|
|
7
|
+
require_relative 'metadata'
|
|
8
|
+
|
|
9
|
+
module Dirload
|
|
10
|
+
class UnsupportedFileType < StandardError; end
|
|
11
|
+
class UnsupportedTemplate < StandardError; end
|
|
12
|
+
|
|
13
|
+
ADAPTERS = [MarkdownAdapter.new, RBXAdapter.new, RubyAdapter.new].freeze
|
|
14
|
+
|
|
15
|
+
def dirload(path, pwd = Dir.pwd, error: false) # rubocop:disable Metrics/AbcSize
|
|
16
|
+
absolute_path = File.expand_path(path, pwd)
|
|
17
|
+
|
|
18
|
+
return adapter_load(file_path: absolute_path) unless File.directory?(absolute_path)
|
|
19
|
+
|
|
20
|
+
loaded_paths = {}
|
|
21
|
+
missed_paths = []
|
|
22
|
+
file_types = {}
|
|
23
|
+
|
|
24
|
+
file_paths(absolute_path:).each do |file_path|
|
|
25
|
+
if (adapter = find_adapter(file_path:))
|
|
26
|
+
loaded_paths[file_path] = adapter
|
|
27
|
+
else
|
|
28
|
+
missed_paths << adapter
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
file_types[extension(file_path:)] ||= []
|
|
32
|
+
file_types[extension(file_path:)] << file_path
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
step(:mapload, loaded_paths:)
|
|
36
|
+
step(:preload, loaded_paths:)
|
|
37
|
+
step(:evaluate, loaded_paths:)
|
|
38
|
+
|
|
39
|
+
Metadata.new(loaded_paths:, missed_paths:, file_types:)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def file_paths(absolute_path:)
|
|
45
|
+
Dir["#{absolute_path}/**/*"].filter { !File.directory?(it) }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def adapter_load(file_path:)
|
|
49
|
+
adapter = find_adapter(file_path:)
|
|
50
|
+
|
|
51
|
+
raise(UnsupportedFileType, "Could not load #{file_path}") if adapter.nil?
|
|
52
|
+
|
|
53
|
+
adapter.evaluate(file_path:)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def step(step, loaded_paths:)
|
|
57
|
+
loaded_paths.each do |file_path, adapter|
|
|
58
|
+
adapter&.send(step, file_path:)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def find_adapter(file_path:)
|
|
63
|
+
ADAPTERS.find { |adapter| adapter.class::EXTENSIONS.include?(extension(file_path:)) }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def extension(file_path:)
|
|
67
|
+
File.extname(file_path).delete_prefix('.')
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
Kernel.send(:include, Dirload)
|
data/lib/loader.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dirload
|
|
4
|
+
class Loader
|
|
5
|
+
class MissingDependencyError < StandardError; end
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
def add_autoloads(file_proxy:)
|
|
9
|
+
autoloads = []
|
|
10
|
+
|
|
11
|
+
file_proxy.dependencies.each do |namespace_with_dependency|
|
|
12
|
+
*namespace, dependency = namespace_with_dependency.split('::')
|
|
13
|
+
|
|
14
|
+
dependency_proxies = find_dependency_proxies(namespace:, dependency:)
|
|
15
|
+
|
|
16
|
+
current_namespace = Object
|
|
17
|
+
namespace.each do |module_name|
|
|
18
|
+
current_namespace.const_set(module_name, Module.new) unless current_namespace.const_defined?(module_name)
|
|
19
|
+
current_namespace = current_namespace.const_get(module_name)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
dependency_proxies.each do |dependency_proxy|
|
|
23
|
+
autoloads << { origin: file_proxy.file_path, current_namespace:, dependency:, file_path: dependency_proxy.file_path }
|
|
24
|
+
current_namespace.autoload(dependency.to_sym, dependency_proxy.file_path)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
autoloads
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def find_dependency_proxies(namespace:, dependency:)
|
|
32
|
+
return Lowkey[dependency] || raise(MissingDependencyError) if namespace.empty?
|
|
33
|
+
|
|
34
|
+
namespace_with_dependency = [namespace, dependency].join('::')
|
|
35
|
+
return Lowkey[namespace_with_dependency] if Lowkey[namespace_with_dependency]
|
|
36
|
+
|
|
37
|
+
namespace.pop
|
|
38
|
+
find_dependency_proxies(namespace:, dependency:)
|
|
39
|
+
rescue MissingDependencyError => e
|
|
40
|
+
raise(MissingDependencyError, "Couldn't autoload #{dependency}. Require it manually?") unless const_get(dependency)
|
|
41
|
+
|
|
42
|
+
[]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/metadata.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'adapters/markdown_adapter'
|
|
4
|
+
|
|
5
|
+
module Dirload
|
|
6
|
+
class Metadata
|
|
7
|
+
EXTENSIONS = [
|
|
8
|
+
*::Dirload::MarkdownAdapter::EXTENSIONS,
|
|
9
|
+
*::Dirload::RBXAdapter::EXTENSIONS,
|
|
10
|
+
*::Dirload::RubyAdapter::EXTENSIONS
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
attr_accessor :loaded_paths, :missed_paths, :file_types
|
|
14
|
+
|
|
15
|
+
def initialize(loaded_paths:, missed_paths:, file_types:)
|
|
16
|
+
@loaded_paths = loaded_paths
|
|
17
|
+
@missed_paths = missed_paths
|
|
18
|
+
@file_types = file_types
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/version.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: dirload
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.6.2
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- maedi
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: lowkey
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
description: An autoloader that lets you use any module namespace with any folder
|
|
27
|
+
structure and mix in manual requires.
|
|
28
|
+
email:
|
|
29
|
+
- maediprichard@gmail.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- lib/adapters/adapter.rb
|
|
35
|
+
- lib/adapters/markdown_adapter.rb
|
|
36
|
+
- lib/adapters/rbx_adapter.rb
|
|
37
|
+
- lib/adapters/ruby_adapter.rb
|
|
38
|
+
- lib/dirload.rb
|
|
39
|
+
- lib/loader.rb
|
|
40
|
+
- lib/metadata.rb
|
|
41
|
+
- lib/version.rb
|
|
42
|
+
homepage: https://github.com/low-rb/dirload
|
|
43
|
+
licenses: []
|
|
44
|
+
metadata:
|
|
45
|
+
homepage_uri: https://github.com/low-rb/dirload
|
|
46
|
+
source_code_uri: https://github.com/low-rb/dirload/src/branch/main
|
|
47
|
+
rdoc_options: []
|
|
48
|
+
require_paths:
|
|
49
|
+
- lib
|
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 3.3.0
|
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '0'
|
|
60
|
+
requirements: []
|
|
61
|
+
rubygems_version: 4.0.6
|
|
62
|
+
specification_version: 4
|
|
63
|
+
summary: An autoloader without namespace and folder structure conventions
|
|
64
|
+
test_files: []
|