bridgetown-foundation 2.0.0.beta1
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/.rubocop.yml +7 -0
- data/Rakefile +11 -0
- data/benchmark/refinements.rb +50 -0
- data/bridgetown-foundation.gemspec +29 -0
- data/lib/bridgetown/foundation/core_ext/class.rb +24 -0
- data/lib/bridgetown/foundation/core_ext/string.rb +38 -0
- data/lib/bridgetown/foundation/packages/ansi.rb +54 -0
- data/lib/bridgetown/foundation/packages/pid_tracker.rb +37 -0
- data/lib/bridgetown/foundation/packages/safe_translations.rb +51 -0
- data/lib/bridgetown/foundation/questionable_string.rb +19 -0
- data/lib/bridgetown/foundation/refine_ext/deep_duplicatable.rb +44 -0
- data/lib/bridgetown/foundation/refine_ext/module.rb +40 -0
- data/lib/bridgetown/foundation/refine_ext/object.rb +68 -0
- data/lib/bridgetown/foundation/refine_ext/string.rb +37 -0
- data/lib/bridgetown/foundation/version.rb +8 -0
- data/lib/bridgetown-foundation.rb +70 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 00a2692340742728b14ce61beb79b3181409376be73f56c21a60db4e3d28c3ee
|
4
|
+
data.tar.gz: fc2ae32d07c3f218d98ed6409abab7431e6927078005c6dc4dbd158d054ce4c5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 82722f2c1d63bbc05f2d8de93290999316162c0de9f55d91c24fbe831ee67a7b0335c1e3c91846038518b7d944e413c6b1be795fcead56e53815b068c2c2de72
|
7
|
+
data.tar.gz: de9adb2dc49ed52b36fe7f61e7f10f29e30b8b12fced50cd8e2cc678b563f11001c79d038fead8a786898963c8be45352b85207a14aa65be21423abeecc756f6
|
data/.rubocop.yml
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "benchmark"
|
4
|
+
|
5
|
+
class TestInclusion
|
6
|
+
module StringAdder
|
7
|
+
def included_add(num)
|
8
|
+
to_i + num
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
String.include StringAdder
|
13
|
+
|
14
|
+
def self.perform
|
15
|
+
raise "crash!" unless "10".included_add(20) == 30
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module StringAdderRefinement
|
20
|
+
refine String do
|
21
|
+
def refined_add(num)
|
22
|
+
to_i + num
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class TestRefinement
|
28
|
+
using StringAdderRefinement
|
29
|
+
|
30
|
+
def self.perform
|
31
|
+
raise "crash!" unless "10".refined_add(20) == 30
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
raise "Unconfirmed!" unless "".respond_to?(:included_add)
|
36
|
+
raise "Unconfirmed!" if "".respond_to?(:refined_add)
|
37
|
+
|
38
|
+
n = 1_000_000
|
39
|
+
Benchmark.bmbm(12) do |x|
|
40
|
+
x.report("inclusion:") do
|
41
|
+
n.times do
|
42
|
+
TestInclusion.perform
|
43
|
+
end
|
44
|
+
end
|
45
|
+
x.report("refinements:") do
|
46
|
+
n.times do
|
47
|
+
TestRefinement.perform
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/bridgetown/foundation/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "bridgetown-foundation"
|
7
|
+
spec.version = Bridgetown::Foundation::VERSION
|
8
|
+
spec.author = "Bridgetown Team"
|
9
|
+
spec.email = "maintainers@bridgetownrb.com"
|
10
|
+
spec.summary = "Ruby language extensions and other utilities useful for the Bridgetown ecosystem"
|
11
|
+
spec.homepage = "https://github.com/bridgetownrb/bridgetown/tree/main/bridgetown-foundation"
|
12
|
+
spec.license = "MIT"
|
13
|
+
spec.required_ruby_version = ">= 3.1"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r!^(test|script)/!) }
|
16
|
+
spec.require_paths = ["lib"]
|
17
|
+
|
18
|
+
spec.metadata = {
|
19
|
+
"source_code_uri" => "https://github.com/bridgetownrb/bridgetown",
|
20
|
+
"bug_tracker_uri" => "https://github.com/bridgetownrb/bridgetown/issues",
|
21
|
+
"changelog_uri" => "https://github.com/bridgetownrb/bridgetown/releases",
|
22
|
+
"homepage_uri" => spec.homepage,
|
23
|
+
"rubygems_mfa_required" => "true",
|
24
|
+
}
|
25
|
+
|
26
|
+
spec.add_dependency("hash_with_dot_access", "~> 2.0")
|
27
|
+
spec.add_dependency("inclusive", "~> 1.0")
|
28
|
+
spec.add_dependency("zeitwerk", "~> 2.5")
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown::Foundation
|
4
|
+
module CoreExt
|
5
|
+
module Class
|
6
|
+
module Descendants
|
7
|
+
def descendants
|
8
|
+
direct_children = subclasses.select do |klass|
|
9
|
+
next true if klass.name.nil? # anonymous class
|
10
|
+
|
11
|
+
# We do this to weed out old classes pre-Zeitwerk reload
|
12
|
+
klass == Kernel.const_get(klass.name)
|
13
|
+
rescue NameError
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
(direct_children + direct_children.map(&:descendants)).flatten
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
::Class.include Descendants
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown::Foundation
|
4
|
+
module CoreExt
|
5
|
+
module String
|
6
|
+
module Colorize
|
7
|
+
class << self
|
8
|
+
extend Inclusive::Class
|
9
|
+
|
10
|
+
# @return [Bridgetown::Foundation::Packages::Ansi]
|
11
|
+
public_packages def ansi = [Bridgetown::Foundation::Packages::Ansi]
|
12
|
+
|
13
|
+
def included(klass)
|
14
|
+
ansi.tap do |a|
|
15
|
+
a.colors.each_key do |color|
|
16
|
+
klass.define_method(color) { |*args| a.public_send(color, self, *args) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Reset output colors back to a regular string output
|
23
|
+
def reset_ansi
|
24
|
+
Colorize.ansi.reset(self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module StartsWithAndEndsWith
|
29
|
+
def self.included(klass)
|
30
|
+
klass.alias_method :starts_with?, :start_with?
|
31
|
+
klass.alias_method :ends_with?, :end_with?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
::String.include Colorize, StartsWithAndEndsWith
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown::Foundation
|
4
|
+
module Packages
|
5
|
+
module Ansi
|
6
|
+
extend self
|
7
|
+
|
8
|
+
ESCAPE = format("%c", 27)
|
9
|
+
MATCH = %r!#{ESCAPE}\[(?:\d+)(?:;\d+)*(j|k|m|s|u|A|B|G)|\e\(B\e\[m!ix
|
10
|
+
COLORS = {
|
11
|
+
bold: 1,
|
12
|
+
black: 30,
|
13
|
+
red: 31,
|
14
|
+
green: 32,
|
15
|
+
yellow: 33,
|
16
|
+
blue: 34,
|
17
|
+
magenta: 35,
|
18
|
+
cyan: 36,
|
19
|
+
white: 37,
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
def colors = COLORS
|
23
|
+
|
24
|
+
# Strip ANSI from the current string. It also strips cursor stuff,
|
25
|
+
# well some of it, and it also strips some other stuff that a lot of
|
26
|
+
# the other ANSI strippers don't.
|
27
|
+
def strip(str)
|
28
|
+
str.gsub MATCH, ""
|
29
|
+
end
|
30
|
+
|
31
|
+
# Does the string include ANSI color codes?
|
32
|
+
def has?(str)
|
33
|
+
!!(str =~ MATCH)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Reset the color back to the default color so that you do not leak any
|
37
|
+
# colors when you move onto the next line. This is probably normally
|
38
|
+
# used as part of a wrapper so that we don't leak colors.
|
39
|
+
def reset(str = "")
|
40
|
+
@ansi_reset ||= format("%c[0m", 27)
|
41
|
+
"#{@ansi_reset}#{str}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# SEE: `self::COLORS` for a list of methods. They are mostly
|
45
|
+
# standard base colors supported by pretty much any xterm-color, we do
|
46
|
+
# not need more than the base colors so we do not include them.
|
47
|
+
COLORS.each do |color, num|
|
48
|
+
define_method color do |str|
|
49
|
+
"#{format("%c", 27)}[#{num}m#{str}#{reset}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown::Foundation
|
4
|
+
module Packages
|
5
|
+
module PidTracker
|
6
|
+
def create_pid_dir
|
7
|
+
FileUtils.mkdir_p pids_dir
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_pid(pid, file:)
|
11
|
+
File.write pidfile_for(file), "#{pid}\n", mode: "a+"
|
12
|
+
end
|
13
|
+
|
14
|
+
def read_pidfile(file)
|
15
|
+
File.readlines pidfile_for(file), chomp: true
|
16
|
+
end
|
17
|
+
|
18
|
+
def remove_pidfile(file)
|
19
|
+
File.delete pidfile_for(file)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def root_dir
|
25
|
+
Dir.pwd
|
26
|
+
end
|
27
|
+
|
28
|
+
def pids_dir
|
29
|
+
File.join(root_dir, "tmp", "pids")
|
30
|
+
end
|
31
|
+
|
32
|
+
def pidfile_for(file)
|
33
|
+
File.join(pids_dir, "#{file}.pid")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown::Foundation
|
4
|
+
module Packages
|
5
|
+
# NOTE: this is tested by `test/test_ruby_helpers.rb` in bridgetown-core
|
6
|
+
#
|
7
|
+
# This is loosely based on the HtmlSafeTranslation module from ActiveSupport, but you can
|
8
|
+
# actually use it for any kind of safety use case in a translation setting because its
|
9
|
+
# decoupled from any specific escaping or safety mechanisms.
|
10
|
+
module SafeTranslations
|
11
|
+
extend Inclusive::Public
|
12
|
+
|
13
|
+
def translate(key, escaper, safety_method = :html_safe, **options)
|
14
|
+
safe_options = escape_translation_options(options, escaper)
|
15
|
+
|
16
|
+
i18n_error = false
|
17
|
+
|
18
|
+
exception_handler = ->(*args) do
|
19
|
+
i18n_error = true
|
20
|
+
I18n.exception_handler.(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
I18n.translate(key, **safe_options, exception_handler:).then do |translation|
|
24
|
+
i18n_error ? translation : safe_translation(translation, safety_method)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
public_function :translate
|
29
|
+
|
30
|
+
def escape_translation_options(options, escaper)
|
31
|
+
@reserved_i18n_keys ||= I18n::RESERVED_KEYS.to_set
|
32
|
+
|
33
|
+
options.to_h do |name, value|
|
34
|
+
unless @reserved_i18n_keys.include?(name) || (name == :count && value.is_a?(Numeric))
|
35
|
+
next [name, escaper.(value)]
|
36
|
+
end
|
37
|
+
|
38
|
+
[name, value]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def safe_translation(translation, safety_method)
|
43
|
+
@safe_value ||= -> { _1.respond_to?(safety_method) ? _1.send(safety_method) : _1 }
|
44
|
+
|
45
|
+
return translation.map { @safe_value.(_1) } if translation.respond_to?(:map)
|
46
|
+
|
47
|
+
@safe_value.(translation)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown::Foundation
|
4
|
+
class QuestionableString < ::String
|
5
|
+
def method_missing(method_name, *args)
|
6
|
+
value = method_name.to_s
|
7
|
+
if value.end_with?("?")
|
8
|
+
value.chop!
|
9
|
+
return self == value
|
10
|
+
end
|
11
|
+
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def respond_to_missing?(method_name, include_private = false)
|
16
|
+
method_name.end_with?("?") || super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown::Foundation
|
4
|
+
module RefineExt
|
5
|
+
# This is a very simplistic algorithm…it essentially just works on the Array/Hash values level,
|
6
|
+
# which for our purposes is fine.
|
7
|
+
module DeepDuplicatable
|
8
|
+
refine ::Hash do
|
9
|
+
def deep_dup
|
10
|
+
hash = dup
|
11
|
+
each do |key, value|
|
12
|
+
hash.delete(key)
|
13
|
+
if key.is_a?(::String) || key.is_a?(::Symbol)
|
14
|
+
hash[key] = value.dup
|
15
|
+
else
|
16
|
+
hash[key.dup] = if value.is_a?(Array) || value.is_a?(Hash)
|
17
|
+
value.deep_dup
|
18
|
+
else
|
19
|
+
value.dup
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
hash
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
refine ::Array do
|
28
|
+
def deep_dep
|
29
|
+
map do |item|
|
30
|
+
next item.dup unless item.is_a?(Array) || item.is_a?(Hash)
|
31
|
+
|
32
|
+
item.deep_dup
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module Bridgetown
|
41
|
+
module Refinements
|
42
|
+
include Foundation::RefineExt::DeepDuplicatable
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown::Foundation
|
4
|
+
module RefineExt
|
5
|
+
module Module
|
6
|
+
using RefineExt::Object
|
7
|
+
|
8
|
+
refine ::Module do
|
9
|
+
def nested_within?(other)
|
10
|
+
return false if self == other
|
11
|
+
|
12
|
+
other.nested_parents.within?(nested_parents) #[1..])
|
13
|
+
end
|
14
|
+
|
15
|
+
def nested_parents
|
16
|
+
return [] unless name
|
17
|
+
|
18
|
+
nesting_segments = name.split("::")[...-1]
|
19
|
+
nesting_segments.map.each_with_index do |_nesting_name, index|
|
20
|
+
Kernel.const_get(nesting_segments[..-(index + 1)].join("::"))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def nested_parent
|
25
|
+
nested_parents.first
|
26
|
+
end
|
27
|
+
|
28
|
+
def nested_name
|
29
|
+
name&.split("::")&.last
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module Bridgetown
|
37
|
+
module Refinements
|
38
|
+
include Foundation::RefineExt::Module
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown::Foundation
|
4
|
+
module RefineExt
|
5
|
+
module Object
|
6
|
+
refine ::Object do
|
7
|
+
# This method lets you check if the receiver is "within" the other object. In most cases,
|
8
|
+
# this check is accomplished via the `include?` method…aka, `10.within? [5, 10]` would
|
9
|
+
# return `true` as `[5, 10].include? 10` is true. And String/String comparison are
|
10
|
+
# case-insensivitve.
|
11
|
+
#
|
12
|
+
# However, for certain comparison types: Module/Class, Hash, and Set, the lesser-than (`<`)
|
13
|
+
# operator is used instead. This is so you can check `BigDecimal.within? Numeric`,
|
14
|
+
# `{easy_as: 123}.within?({indeed: "it's true", easy_as: 123})`, and if a Set is a
|
15
|
+
# `proper_subset?` of another Set.
|
16
|
+
#
|
17
|
+
# For Array/Array comparisons, a difference is checked, so `[1,2].within? [3,2,1]` is true,
|
18
|
+
# but `[1,2].within? [2,3]` is false.
|
19
|
+
#
|
20
|
+
# Also for Range, the `cover?` method is used instead of `include?`.
|
21
|
+
#
|
22
|
+
# @param other [Object] for determining if receiver lies within this value
|
23
|
+
# @return [Boolean]
|
24
|
+
def within?(other) # rubocop:disable Metrics
|
25
|
+
# rubocop:disable Style/IfUnlessModifier
|
26
|
+
if is_a?(Module) && other.is_a?(Module)
|
27
|
+
return self < other
|
28
|
+
end
|
29
|
+
|
30
|
+
if (is_a?(Hash) && other.is_a?(Hash)) || (is_a?(Set) && other.is_a?(Set))
|
31
|
+
return self < other
|
32
|
+
end
|
33
|
+
|
34
|
+
if is_a?(Array) && other.is_a?(Array)
|
35
|
+
return false if empty?
|
36
|
+
|
37
|
+
return difference(other).empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
if other.is_a?(Range)
|
41
|
+
return other.cover?(self) == true
|
42
|
+
end
|
43
|
+
|
44
|
+
if is_a?(::String) && other.is_a?(::String)
|
45
|
+
return other.downcase.include?(downcase)
|
46
|
+
end
|
47
|
+
|
48
|
+
other&.include?(self) == true
|
49
|
+
# rubocop:enable Style/IfUnlessModifier
|
50
|
+
rescue NoMethodError
|
51
|
+
false
|
52
|
+
end
|
53
|
+
|
54
|
+
# NOTE: if you _really_ need to preserve Active Support's `in?` functionality, you can just
|
55
|
+
# require "active_support/core_ext/object/inclusion"
|
56
|
+
def in?(...) = Bridgetown::Foundation.deprecation_warning(
|
57
|
+
self, :in?, :within?, 2024, 12
|
58
|
+
).then { within?(...) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
module Bridgetown
|
65
|
+
module Refinements
|
66
|
+
include Foundation::RefineExt::Object
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown::Foundation
|
4
|
+
module RefineExt
|
5
|
+
module String
|
6
|
+
refine ::String do
|
7
|
+
def indent!(indent_by, *args)
|
8
|
+
if args.length.positive?
|
9
|
+
Kernel.warn "multiple arguments aren't supported by `indent!' in Bridgetown", uplevel: 1
|
10
|
+
end
|
11
|
+
|
12
|
+
gsub! %r!^(?\!$)!, " " * indent_by
|
13
|
+
end
|
14
|
+
|
15
|
+
def indent(indent_by, *args)
|
16
|
+
if args.length.positive?
|
17
|
+
Kernel.warn "multiple arguments aren't supported by `indent' in Bridgetown", uplevel: 1
|
18
|
+
end
|
19
|
+
|
20
|
+
dup.indent!(indent_by)
|
21
|
+
end
|
22
|
+
|
23
|
+
def questionable = Bridgetown::Foundation::QuestionableString.new(self)
|
24
|
+
|
25
|
+
def inquiry = Bridgetown::Foundation.deprecation_warning(
|
26
|
+
self, :inquiry, :questionable, 2024, 12
|
27
|
+
).then { questionable }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module Bridgetown
|
34
|
+
module Refinements
|
35
|
+
include Foundation::RefineExt::String
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bridgetown/foundation/version"
|
4
|
+
require "hash_with_dot_access"
|
5
|
+
require "inclusive"
|
6
|
+
require "zeitwerk"
|
7
|
+
require "delegate"
|
8
|
+
|
9
|
+
module Bridgetown::Foundation
|
10
|
+
# This is loosly based on the `deprecate` method in `Gem::Deprecate`
|
11
|
+
#
|
12
|
+
# @param target [Object]
|
13
|
+
# @param name [Symbol] e.g. `:howdy`
|
14
|
+
# @param repl [Symbol] e.g. `:hello`
|
15
|
+
# @param year [Integer] e.g. `2025`
|
16
|
+
# @param month [Integer] e.g. `1` for January
|
17
|
+
def self.deprecation_warning(target, name, repl, year, month) # rubocop:disable Metrics/ParameterLists
|
18
|
+
klass = target.is_a?(Module)
|
19
|
+
target = klass ? "#{self}." : "#{self.class}#"
|
20
|
+
msg = [
|
21
|
+
"NOTE: #{target}#{name} is deprecated",
|
22
|
+
repl == :none ? " with no replacement" : "; use #{repl} instead",
|
23
|
+
format(". It will be removed on or after %4d-%02d.", year, month), # rubocop:disable Style/FormatStringToken
|
24
|
+
"\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}",
|
25
|
+
]
|
26
|
+
warn "#{msg.join}."
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# You can add `using Bridgetown::Refinements` to any portion of your Ruby code to load in all
|
31
|
+
# of the refinements available in Foundation. Or you can add a using statement for a particular
|
32
|
+
# refinement which lives inside `Bridgetown::Foundation::RefineExt`.
|
33
|
+
module Bridgetown::Refinements
|
34
|
+
include HashWithDotAccess::Refinements
|
35
|
+
end
|
36
|
+
|
37
|
+
Zeitwerk.with_loader do |l|
|
38
|
+
l.push_dir "#{__dir__}/bridgetown/foundation", namespace: Bridgetown::Foundation
|
39
|
+
l.ignore "#{__dir__}/bridgetown/foundation/version.rb"
|
40
|
+
l.setup
|
41
|
+
l.eager_load
|
42
|
+
end
|
43
|
+
|
44
|
+
module Bridgetown
|
45
|
+
# Any method call sent will be passed along to the wrapped object with refinements activated
|
46
|
+
class WrappedObjectWithRefinements < SimpleDelegator
|
47
|
+
using Bridgetown::Refinements
|
48
|
+
|
49
|
+
# rubocop:disable Style/MissingRespondToMissing
|
50
|
+
def method_missing(method, ...) = __getobj__.send(method, ...)
|
51
|
+
# rubocop:enable Style/MissingRespondToMissing
|
52
|
+
end
|
53
|
+
|
54
|
+
# Call this method to wrap any object(s) in order to use Foundation's refinements
|
55
|
+
#
|
56
|
+
# @param *obj [Object]
|
57
|
+
# @return [WrappedObjectWithRefinements]
|
58
|
+
def self.refine(*obj)
|
59
|
+
if obj.length == 1
|
60
|
+
WrappedObjectWithRefinements.new(obj[0])
|
61
|
+
else
|
62
|
+
obj.map { WrappedObjectWithRefinements.new _1 }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.add_refinement(mod, &)
|
67
|
+
Bridgetown::Refinements.include(mod)
|
68
|
+
Bridgetown::WrappedObjectWithRefinements.class_eval(&)
|
69
|
+
end
|
70
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bridgetown-foundation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0.beta1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bridgetown Team
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-08-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hash_with_dot_access
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: inclusive
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: zeitwerk
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.5'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.5'
|
55
|
+
description:
|
56
|
+
email: maintainers@bridgetownrb.com
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- ".rubocop.yml"
|
62
|
+
- Rakefile
|
63
|
+
- benchmark/refinements.rb
|
64
|
+
- bridgetown-foundation.gemspec
|
65
|
+
- lib/bridgetown-foundation.rb
|
66
|
+
- lib/bridgetown/foundation/core_ext/class.rb
|
67
|
+
- lib/bridgetown/foundation/core_ext/string.rb
|
68
|
+
- lib/bridgetown/foundation/packages/ansi.rb
|
69
|
+
- lib/bridgetown/foundation/packages/pid_tracker.rb
|
70
|
+
- lib/bridgetown/foundation/packages/safe_translations.rb
|
71
|
+
- lib/bridgetown/foundation/questionable_string.rb
|
72
|
+
- lib/bridgetown/foundation/refine_ext/deep_duplicatable.rb
|
73
|
+
- lib/bridgetown/foundation/refine_ext/module.rb
|
74
|
+
- lib/bridgetown/foundation/refine_ext/object.rb
|
75
|
+
- lib/bridgetown/foundation/refine_ext/string.rb
|
76
|
+
- lib/bridgetown/foundation/version.rb
|
77
|
+
homepage: https://github.com/bridgetownrb/bridgetown/tree/main/bridgetown-foundation
|
78
|
+
licenses:
|
79
|
+
- MIT
|
80
|
+
metadata:
|
81
|
+
source_code_uri: https://github.com/bridgetownrb/bridgetown
|
82
|
+
bug_tracker_uri: https://github.com/bridgetownrb/bridgetown/issues
|
83
|
+
changelog_uri: https://github.com/bridgetownrb/bridgetown/releases
|
84
|
+
homepage_uri: https://github.com/bridgetownrb/bridgetown/tree/main/bridgetown-foundation
|
85
|
+
rubygems_mfa_required: 'true'
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '3.1'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 1.3.1
|
100
|
+
requirements: []
|
101
|
+
rubygems_version: 3.3.26
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: Ruby language extensions and other utilities useful for the Bridgetown ecosystem
|
105
|
+
test_files: []
|