text-gen 0.7.1 → 0.8.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: efe92f0e6e0bb6b90a754daff918ef5900d2291d69e594afdba1e0e60ec0694a
4
- data.tar.gz: 1997e875c362f9931c83df43b6a4680fcd58e1b00fa90dcca36db2aa0dd968bc
3
+ metadata.gz: 60294b39f992c96f317ad35a502145577250616b6955133b1502d4671af29517
4
+ data.tar.gz: f9fd5e105682af4c36f11632c1603425b977a59171d6c0597428761e397ce443
5
5
  SHA512:
6
- metadata.gz: c7acd68aa5957831a49fb1fe9c70212873ace7da1e255019b54ca323c9ab50a7dce399ba2627b679d1b38f1dc8fbc7020e1447dd1c0dc8007fee319720acdbaa
7
- data.tar.gz: a8291f893d31cdd2a993c8aa184fae8a29c14712e044c8cf4f2ae31d11ea6d2c233b13314b4fe93207382b2dd1753370e0740978d50d8bd501586d69cf2e983c
6
+ metadata.gz: 84dec457f1b0c2853f014f6e75f1136baa40afffebe3ac8c5e15932fd1ab8938367e30509bb26dd65cb4f50c2be9e18149d7c14a61a876a381ee632e2f9573e2
7
+ data.tar.gz: 7d7bb543d5fe6d6582746f807cf1d31d1e82211749ec54f8abdade318f97cb069960d3d3ef327bdef9f830a19a450506b11cc446c48f8c88218997c4d6d77b6b
data/README.md CHANGED
@@ -1,28 +1,50 @@
1
1
  # Text::Gen
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
4
-
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/text/gen`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ A Ruby gem for building random text strings from rules defined as Ruby hashes. Rules consist of Builders containing Items composed of Segments. Generated text can be modified with filters like pluralize, capitalize, and titleize.
6
4
 
7
5
  ## Installation
8
6
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'text-gen'
11
+ ```
10
12
 
11
- Install the gem and add to the application's Gemfile by executing:
13
+ And then execute:
12
14
 
13
15
  ```bash
14
- bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
16
+ bundle install
15
17
  ```
16
18
 
17
- If bundler is not being used to manage dependencies, install the gem by executing:
19
+ Or install it yourself as:
18
20
 
19
21
  ```bash
20
- gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
22
+ gem install text-gen
21
23
  ```
22
24
 
23
25
  ## Usage
24
26
 
25
- TODO: Write usage instructions here
27
+ ```ruby
28
+ require 'text/gen'
29
+
30
+ # Define builders with items and filters
31
+ random_fruit = {
32
+ "items" => [{ "segments" => Text::Gen::Segment::Parser.parse("[d4] [fruit]") }],
33
+ "filters" => [{ "type" => "pluralize" }, { "type" => "titleize" }]
34
+ }
35
+
36
+ fruit = {
37
+ "items" => %w[apple banana orange pear kiwi].map { |f| { "segments" => Text::Gen::Segment::Parser.parse(f) } }
38
+ }
39
+
40
+ # Create a lookup function
41
+ lookup = lambda { |key| key == "random-fruit" ? random_fruit : fruit }
42
+
43
+ # Run the generator
44
+ runner = Text::Gen::Runner.new(key: "random-fruit", lookup: lookup)
45
+ result = runner.run.first
46
+ puts result.text # => "3 Bananas"
47
+ ```
26
48
 
27
49
  ## Development
28
50
 
@@ -32,7 +54,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
54
 
33
55
  ## Contributing
34
56
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/text-gen. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/text-gen/blob/master/CODE_OF_CONDUCT.md).
57
+ Bug reports and pull requests are welcome on GitHub at https://github.com/palmergs/text-gen. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/palmergs/text-gen/blob/release/CODE_OF_CONDUCT.md).
36
58
 
37
59
  ## License
38
60
 
@@ -40,4 +62,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
40
62
 
41
63
  ## Code of Conduct
42
64
 
43
- Everyone interacting in the Text::Gen project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/text-gen/blob/master/CODE_OF_CONDUCT.md).
65
+ Everyone interacting in the Text::Gen project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/palmergs/text-gen/blob/release/CODE_OF_CONDUCT.md).
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Text
4
+ module Gen
5
+ module Filter
6
+ # Base class for all filters
7
+ # Provides common utilities and template method pattern
8
+ class Base
9
+ attr_reader :filter, :lookup
10
+
11
+ def initialize(filter = {}, lookup: nil)
12
+ @filter = filter
13
+ @lookup = lookup
14
+ end
15
+
16
+ # Template method - must be implemented by subclasses
17
+ def apply(input)
18
+ raise NotImplementedError, "Subclasses must implement #apply"
19
+ end
20
+
21
+ # Shared utilities
22
+ def key
23
+ filter["key"]
24
+ end
25
+
26
+ def value
27
+ filter["value"]
28
+ end
29
+
30
+ def type
31
+ filter["type"]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../item_filter"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ module Item
9
+ class Reject < ItemFilter
10
+ def apply(items)
11
+ items.select do |item|
12
+ pass_reject?(item["meta"])
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def pass_reject?(meta)
19
+ return false if value == "*" && meta.key?(key)
20
+ return false if key == "*" && meta.values.any? { |arr| arr.include?(value) }
21
+
22
+ !meta[key]&.include?(value)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../item_filter"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ module Item
9
+ class Select < ItemFilter
10
+ def apply(items)
11
+ items.select do |item|
12
+ pass_select?(item["meta"])
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def pass_select?(meta)
19
+ return true if value == "*" && meta.key?(key)
20
+ return true if key == "*" && meta.values.any? { |arr| arr.include?(value) }
21
+
22
+ meta[key]&.include?(value)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ # Base class for filters that operate on item arrays
9
+ # Subclasses should implement #apply(items) -> Array
10
+ class ItemFilter < Base
11
+ def apply(items)
12
+ raise NotImplementedError, "Subclasses must implement #apply(items)"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../result_filter"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ module Result
9
+ class Capitalize < ResultFilter
10
+ def apply(result)
11
+ transform_text(result, result.text.capitalize)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../result_filter"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ module Result
9
+ class Censor < ResultFilter
10
+ def apply(result)
11
+ return result if lookup.nil? || key.nil?
12
+
13
+ # Get the censor builder
14
+ builder = lookup.call(key)
15
+ return result unless builder
16
+
17
+ # Create a runner to evaluate each item
18
+ runner = Text::Gen::Runner.new(key: key, lookup: lookup)
19
+
20
+ # Run each item in the builder once
21
+ censor_texts = builder["items"].map do |item|
22
+ item_result = runner.send(:run_item, item, 0)
23
+ apply_function(item_result.text) if item_result
24
+ end.compact.uniq
25
+
26
+ # Get the text to compare
27
+ compare_text = apply_function(result.text)
28
+
29
+ # Check if result text matches any censor text
30
+ return nil if censor_texts.include?(compare_text)
31
+
32
+ result
33
+ end
34
+
35
+ private
36
+
37
+ def apply_function(text)
38
+ return text if value.nil? || value.empty?
39
+
40
+ case value
41
+ when "downcase"
42
+ text.downcase
43
+ when "upcase"
44
+ text.upcase
45
+ when "capitalize"
46
+ text.capitalize
47
+ else
48
+ text
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../result_filter"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ module Result
9
+ class Clear < ResultFilter
10
+ def apply(result)
11
+ transform_with_meta(result) do |new_result|
12
+ new_result.clear_meta(key, value)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../result_filter"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ module Result
9
+ class Downcase < ResultFilter
10
+ def apply(result)
11
+ transform_text(result, result.text.downcase)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../result_filter"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ module Result
9
+ class Exclude < ResultFilter
10
+ def apply(result)
11
+ return nil if result.nil?
12
+ return nil if value == "*" && result.meta.key?(key)
13
+ return nil if key == "*" && result.meta.values.any? { |arr| arr.include?(value) }
14
+ return nil if result.meta[key]&.include?(value)
15
+
16
+ result
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../result_filter"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ module Result
9
+ class Match < ResultFilter
10
+ def apply(result)
11
+ return nil if result.nil?
12
+ return result if value == "*" && result.meta.key?(key)
13
+ return result if key == "*" && result.meta.values.any? { |arr| arr.include?(value) }
14
+ return result if result.meta[key]&.include?(value)
15
+
16
+ nil
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../result_filter"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ module Result
9
+ class Meta < ResultFilter
10
+ def apply(result)
11
+ transform_with_meta(result) do |new_result|
12
+ meta_value = case value
13
+ when "_text_"
14
+ result.text
15
+ when "_value_"
16
+ result.value.to_s
17
+ when "_multiplier_"
18
+ result.multiplier.to_s
19
+ when "_length_"
20
+ result.text.length.to_s
21
+ else
22
+ value
23
+ end
24
+ new_result.merge_kv(key, meta_value)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,37 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "set"
4
+ require_relative "../result_filter"
5
+
3
6
  module Text
4
7
  module Gen
5
- module Function
6
- class Pluralizer
7
- EXCEPTIONS = {
8
- "foot" => "feet",
9
- "axis" => "axes",
10
- "child" => "children",
11
- "codex" => "codices",
12
- "die" => "dice",
13
- "dwarf" => "dwarves",
14
- "goose" => "geese",
15
- "elf" => "elves",
16
- "man" => "men",
17
- "ox" => "oxen",
18
- "cactus" => "cacti",
19
- "thesis" => "theses",
20
- "criterion" => "criteria",
21
- "thief" => "thieves",
22
- "tooth" => "teeth",
23
- "wolf" => "wolves",
24
- "woman" => "women"
25
- }.freeze
26
-
27
- SINGLE = Set.new(%w[a an the this his her its my your our that their])
28
-
29
- class << self
30
- def apply(result, _filter)
31
- text = pluralize(result.text)
32
- Result.from(text:, type: :function, result:)
8
+ module Filter
9
+ module Result
10
+ class Pluralize < ResultFilter
11
+ EXCEPTIONS = {
12
+ "foot" => "feet",
13
+ "axis" => "axes",
14
+ "child" => "children",
15
+ "codex" => "codices",
16
+ "die" => "dice",
17
+ "dwarf" => "dwarves",
18
+ "goose" => "geese",
19
+ "elf" => "elves",
20
+ "man" => "men",
21
+ "ox" => "oxen",
22
+ "cactus" => "cacti",
23
+ "thesis" => "theses",
24
+ "criterion" => "criteria",
25
+ "thief" => "thieves",
26
+ "tooth" => "teeth",
27
+ "wolf" => "wolves",
28
+ "woman" => "women"
29
+ }.freeze
30
+
31
+ SINGLE = Set.new(%w[a an the this his her its my your our that their])
32
+
33
+ def apply(result)
34
+ transform_text(result, pluralize(result.text))
33
35
  end
34
36
 
37
+ private
38
+
35
39
  def pluralize(str)
36
40
  return str if str.empty?
37
41
 
@@ -1,21 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../result_filter"
4
+
3
5
  module Text
4
6
  module Gen
5
- module Function
6
- class Swapper
7
- DIGIT_WORDS = {
8
- "1" => "one", "2" => "two", "3" => "three",
9
- "4" => "four", "5" => "five", "6" => "six",
10
- "7" => "seven", "8" => "eight", "9" => "nine"
11
- }.freeze
12
-
13
- class << self
14
- def apply(result, filter)
15
- text = swap(result.text, filter["key"], filter["value"])
16
- Result.from(text:, type: :function, result:)
7
+ module Filter
8
+ module Result
9
+ class Swap < ResultFilter
10
+ DIGIT_WORDS = {
11
+ "1" => "one", "2" => "two", "3" => "three",
12
+ "4" => "four", "5" => "five", "6" => "six",
13
+ "7" => "seven", "8" => "eight", "9" => "nine"
14
+ }.freeze
15
+
16
+ def apply(result)
17
+ transform_text(result, swap(result.text, key, value))
17
18
  end
18
19
 
20
+ private
21
+
19
22
  def swap(str, key, val)
20
23
  return str if key.nil? || key.empty?
21
24
 
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require_relative "../result_filter"
5
+
6
+ module Text
7
+ module Gen
8
+ module Filter
9
+ module Result
10
+ class Titleize < ResultFilter
11
+ SKIP_WORDS = Set.new(%w[a an and as at but by for if in of on or the to v via vs])
12
+
13
+ def apply(result)
14
+ transform_text(result, titleize(result.text))
15
+ end
16
+
17
+ private
18
+
19
+ def titleize(str)
20
+ str.split(/\s+/).map.with_index do |word, idx|
21
+ idx.zero? || !SKIP_WORDS.include?(word) ? word.capitalize : word
22
+ end.join(" ")
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../result_filter"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ module Result
9
+ class Upcase < ResultFilter
10
+ def apply(result)
11
+ transform_text(result, result.text.upcase)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Text
6
+ module Gen
7
+ module Filter
8
+ # Base class for filters that operate on Result objects
9
+ # Subclasses should implement #apply(result) -> Result or nil
10
+ class ResultFilter < Base
11
+ def apply(result)
12
+ raise NotImplementedError, "Subclasses must implement #apply(result)"
13
+ end
14
+
15
+ protected
16
+
17
+ # Helper to create a new result preserving metadata
18
+ def transform_text(result, new_text)
19
+ Text::Gen::Result.from(text: new_text, type: :function, result: result)
20
+ end
21
+
22
+ # Helper to create a new result and modify metadata
23
+ def transform_with_meta(result, new_text = nil)
24
+ new_result = Text::Gen::Result.from(
25
+ text: new_text || result.text,
26
+ type: :function,
27
+ result: result
28
+ )
29
+ yield new_result if block_given?
30
+ new_result
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,37 +1,60 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "function/capitalizer"
4
- require_relative "function/clear"
5
- require_relative "function/downcase"
6
- require_relative "function/meta"
7
- require_relative "function/pluralizer"
8
- require_relative "function/swapper"
9
- require_relative "function/titleizer"
10
- require_relative "function/upcase"
3
+ require_relative "filter/base"
4
+ require_relative "filter/result_filter"
5
+ require_relative "filter/item_filter"
6
+
7
+ # Result filters
8
+ require_relative "filter/result/capitalize"
9
+ require_relative "filter/result/censor"
10
+ require_relative "filter/result/clear"
11
+ require_relative "filter/result/downcase"
12
+ require_relative "filter/result/exclude"
13
+ require_relative "filter/result/match"
14
+ require_relative "filter/result/meta"
15
+ require_relative "filter/result/pluralize"
16
+ require_relative "filter/result/swap"
17
+ require_relative "filter/result/titleize"
18
+ require_relative "filter/result/upcase"
19
+
20
+ # Item filters
21
+ require_relative "filter/item/select"
22
+ require_relative "filter/item/reject"
11
23
 
12
24
  module Text
13
25
  module Gen
14
- class Filter
26
+ module Filter
15
27
  SEPARATORS = { "tab" => "\t", "newline" => "\n", "space" => " " }.freeze
16
28
 
17
- FUNCTION_CLASSES = {
18
- "capitalize" => Function::Capitalizer,
19
- "clear" => Function::Clear,
20
- "downcase" => Function::Downcase,
21
- "meta" => Function::Meta,
22
- "pluralize" => Function::Pluralizer,
23
- "swap" => Function::Swapper,
24
- "titleize" => Function::Titleizer,
25
- "upcase" => Function::Upcase
29
+ RESULT_FILTER_CLASSES = {
30
+ "capitalize" => Filter::Result::Capitalize,
31
+ "censor" => Filter::Result::Censor,
32
+ "clear" => Filter::Result::Clear,
33
+ "downcase" => Filter::Result::Downcase,
34
+ "exclude" => Filter::Result::Exclude,
35
+ "match" => Filter::Result::Match,
36
+ "meta" => Filter::Result::Meta,
37
+ "pluralize" => Filter::Result::Pluralize,
38
+ "swap" => Filter::Result::Swap,
39
+ "titleize" => Filter::Result::Titleize,
40
+ "upcase" => Filter::Result::Upcase
41
+ }.freeze
42
+
43
+ ITEM_FILTER_CLASSES = {
44
+ "select" => Filter::Item::Select,
45
+ "reject" => Filter::Item::Reject
26
46
  }.freeze
27
47
 
28
48
  class << self
29
- def functions(result, filters)
49
+ def functions(result, filters, lookup: nil)
30
50
  return result if filters.nil? || filters.empty?
31
51
 
32
52
  filters.each do |filter|
33
- function_class = FUNCTION_CLASSES[filter["type"]]
34
- result = function_class.apply(result, filter) if function_class
53
+ filter_class = RESULT_FILTER_CLASSES[filter["type"]]
54
+ if filter_class
55
+ filter_instance = filter_class.new(filter, lookup: lookup)
56
+ result = filter_instance.apply(result)
57
+ end
35
58
  end
36
59
 
37
60
  result
@@ -41,8 +64,12 @@ module Text
41
64
  select_filters = filters_by_type(filters, "select")
42
65
  return items if select_filters.empty?
43
66
 
67
+ # OR logic: any filter matches
44
68
  items.select do |item|
45
- select_filters.any? { |f| pass_select?(item["meta"], f["key"], f["value"]) }
69
+ select_filters.any? do |filter|
70
+ filter_instance = ITEM_FILTER_CLASSES["select"].new(filter)
71
+ filter_instance.apply([item]).any?
72
+ end
46
73
  end
47
74
  end
48
75
 
@@ -50,25 +77,34 @@ module Text
50
77
  reject_filters = filters_by_type(filters, "reject")
51
78
  return items if reject_filters.empty?
52
79
 
53
- items.select do |item|
54
- reject_filters.all? { |f| pass_reject?(item["meta"], f["key"], f["value"]) }
80
+ # AND logic: all filters must pass
81
+ reject_filters.each do |filter|
82
+ filter_instance = ITEM_FILTER_CLASSES["reject"].new(filter)
83
+ items = filter_instance.apply(items)
55
84
  end
85
+ items
56
86
  end
57
87
 
58
88
  def result_select(result, filters)
59
89
  match_filters = filters_by_type(filters, "match")
60
90
  return result if match_filters.empty?
61
- return result if match_filters.any? { |f| pass_select?(result.meta, f["key"], f["value"]) }
62
91
 
63
- nil
92
+ # OR logic: any filter matches
93
+ match_filters.any? do |filter|
94
+ filter_instance = RESULT_FILTER_CLASSES["match"].new(filter)
95
+ filter_instance.apply(result)
96
+ end ? result : nil
64
97
  end
65
98
 
66
99
  def result_reject(result, filters)
67
100
  exclude_filters = filters_by_type(filters, "exclude")
68
101
  return result if exclude_filters.empty?
69
- return result if exclude_filters.all? { |f| pass_reject?(result.meta, f["key"], f["value"]) }
70
102
 
71
- nil
103
+ # AND logic: all filters must pass
104
+ exclude_filters.all? do |filter|
105
+ filter_instance = RESULT_FILTER_CLASSES["exclude"].new(filter)
106
+ filter_instance.apply(result)
107
+ end ? result : nil
72
108
  end
73
109
 
74
110
  # Create a builder that always returns a constant value
@@ -111,20 +147,6 @@ module Text
111
147
  constant_item(locale_text, item)
112
148
  end
113
149
 
114
- def pass_select?(meta, key, value)
115
- return true if value == "*" && meta.key?(key)
116
- return true if key == "*" && meta.values.any? { |arr| arr.include?(value) }
117
-
118
- meta[key]&.include?(value)
119
- end
120
-
121
- def pass_reject?(meta, key, value)
122
- return false if value == "*" && meta.key?(key)
123
- return false if key == "*" && meta.values.any? { |arr| arr.include?(value) }
124
-
125
- !meta[key]&.include?(value)
126
- end
127
-
128
150
  def separator(filters)
129
151
  return "" unless filters
130
152
 
@@ -202,7 +202,7 @@ module Text
202
202
  end
203
203
 
204
204
  def apply_result_function(result, filters)
205
- Filter.functions(result, filters)
205
+ Filter.functions(result, filters, lookup: lookup)
206
206
  end
207
207
 
208
208
  def merge_filters(builder, filters)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Text
4
4
  module Gen
5
- VERSION = "0.7.1"
5
+ VERSION = "0.8.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: text-gen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - G Palmer
@@ -42,14 +42,22 @@ files:
42
42
  - Rakefile
43
43
  - lib/text/gen.rb
44
44
  - lib/text/gen/filter.rb
45
- - lib/text/gen/function/capitalizer.rb
46
- - lib/text/gen/function/clear.rb
47
- - lib/text/gen/function/downcase.rb
48
- - lib/text/gen/function/meta.rb
49
- - lib/text/gen/function/pluralizer.rb
50
- - lib/text/gen/function/swapper.rb
51
- - lib/text/gen/function/titleizer.rb
52
- - lib/text/gen/function/upcase.rb
45
+ - lib/text/gen/filter/base.rb
46
+ - lib/text/gen/filter/item/reject.rb
47
+ - lib/text/gen/filter/item/select.rb
48
+ - lib/text/gen/filter/item_filter.rb
49
+ - lib/text/gen/filter/result/capitalize.rb
50
+ - lib/text/gen/filter/result/censor.rb
51
+ - lib/text/gen/filter/result/clear.rb
52
+ - lib/text/gen/filter/result/downcase.rb
53
+ - lib/text/gen/filter/result/exclude.rb
54
+ - lib/text/gen/filter/result/match.rb
55
+ - lib/text/gen/filter/result/meta.rb
56
+ - lib/text/gen/filter/result/pluralize.rb
57
+ - lib/text/gen/filter/result/swap.rb
58
+ - lib/text/gen/filter/result/titleize.rb
59
+ - lib/text/gen/filter/result/upcase.rb
60
+ - lib/text/gen/filter/result_filter.rb
53
61
  - lib/text/gen/result.rb
54
62
  - lib/text/gen/result_accumulator.rb
55
63
  - lib/text/gen/runner.rb
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Text
4
- module Gen
5
- module Function
6
- class Capitalizer
7
- class << self
8
- def apply(result, _filter)
9
- text = result.text.capitalize
10
- Result.from(text:, type: :function, result:)
11
- end
12
- end
13
- end
14
- end
15
- end
16
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Text
4
- module Gen
5
- module Function
6
- class Clear
7
- class << self
8
- def apply(result, filter)
9
- new_result = Result.from(text: result.text, type: :function, result:)
10
- new_result.clear_meta(filter["key"], filter["value"])
11
- new_result
12
- end
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Text
4
- module Gen
5
- module Function
6
- class Downcase
7
- class << self
8
- def apply(result, _filter)
9
- text = result.text.downcase
10
- Result.from(text:, type: :function, result:)
11
- end
12
- end
13
- end
14
- end
15
- end
16
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Text
4
- module Gen
5
- module Function
6
- class Meta
7
- class << self
8
- def apply(result, filter)
9
- new_result = Result.from(text: result.text, type: :function, result:)
10
- new_result.merge_kv(filter["key"], filter["value"])
11
- new_result
12
- end
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Text
4
- module Gen
5
- module Function
6
- class Titleizer
7
- SKIP_WORDS = Set.new(%w[a an and as at but by for if in of on or the to v via vs])
8
-
9
- class << self
10
- def apply(result, _filter)
11
- text = titleize(result.text)
12
- Result.from(text:, type: :function, result:)
13
- end
14
-
15
- def titleize(str)
16
- str.split(/\s+/).map.with_index do |word, idx|
17
- idx.zero? || !SKIP_WORDS.include?(word) ? word.capitalize : word
18
- end.join(" ")
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Text
4
- module Gen
5
- module Function
6
- class Upcase
7
- class << self
8
- def apply(result, _filter)
9
- text = result.text.upcase
10
- Result.from(text:, type: :function, result:)
11
- end
12
- end
13
- end
14
- end
15
- end
16
- end