drawght 1.0.0 → 1.1.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 +4 -4
- data/CHANGELOG.yaml +9 -0
- data/README.md +57 -16
- data/lib/drawght/compiler.rb +32 -11
- data/lib/drawght/parser.rb +152 -39
- data/lib/drawght/tracker.rb +24 -0
- data/lib/drawght/version.rb +5 -6
- data/lib/drawght.rb +1 -62
- metadata +8 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9ed4619bbd991ccf58bd7e7c89407879181c656e98667b933a25cdf751a9c273
|
|
4
|
+
data.tar.gz: ae541e430afcc2ee112cd78d0549767845fbb1a8def0204de1d29e4db14baef9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 704e351d12da61369698dd568740d3943ee9542ac01c3d5e52c9bad514063ea6e1d395ba503df518a91605d44fb1bb7df0b68893527fa036ea74132d6680cafa
|
|
7
|
+
data.tar.gz: e10c78a814d001c3c7baa5eec7b748c5e34256b4a1dc7206d109372ec815279ba658f2ed1017838e7e233bf62befbe847b9df1af9fa4a4bc7b74090c9651b40a
|
data/CHANGELOG.yaml
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
- version: 1.1.0
|
|
2
|
+
date: 2025-12-22
|
|
3
|
+
summary:
|
|
4
|
+
Syntax validation and new expression.
|
|
5
|
+
changes:
|
|
6
|
+
- Syntax validation.
|
|
7
|
+
- Refined extension methods have been moved to their respective modules.
|
|
8
|
+
- Syntax for getting the length of a collection.
|
|
9
|
+
|
|
1
10
|
- version: 1.0.0
|
|
2
11
|
date: 2025-12-03
|
|
3
12
|
summary:
|
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Drawght
|
|
2
2
|
|
|
3
|
-
Drawght is a data handler for texts without logical
|
|
4
|
-
to use a dataset (such as the subject of a text) to
|
|
5
|
-
template. It can be considered a mini template processor.
|
|
3
|
+
Drawght (like draft/draught) is a data handler for texts without logical
|
|
4
|
+
statements. The goal is to use a dataset (such as the subject of a text) to
|
|
5
|
+
draft a document template. It can be considered a mini template processor.
|
|
6
6
|
|
|
7
7
|
Data is accessed through `{}` braces, replaced by their respective values.
|
|
8
8
|
|
|
@@ -196,22 +196,63 @@ puts result
|
|
|
196
196
|
|
|
197
197
|
Drawght has a simple syntax:
|
|
198
198
|
|
|
199
|
-
- `{
|
|
200
|
-
collection, then the row will be replicated and converted with the
|
|
201
|
-
values.
|
|
199
|
+
- `{identifier}`: converts `identifier` to its respective value. If the value
|
|
200
|
+
is a collection, then the row will be replicated and converted with the
|
|
201
|
+
respective values.
|
|
202
202
|
|
|
203
|
-
- `{
|
|
204
|
-
assuming the same behavior as `{
|
|
203
|
+
- `{structure.attribute}`: converts `attribute` to its respective value inside
|
|
204
|
+
`structure`, assuming the same behavior as `{identifier}`.
|
|
205
205
|
|
|
206
|
-
- `{collection:
|
|
207
|
-
in the collection, and converts `
|
|
208
|
-
|
|
209
|
-
`
|
|
210
|
-
will be converted following the same
|
|
206
|
+
- `{collection:attribute}`: selects `collection`, replicates the line for each
|
|
207
|
+
item in the collection, and converts `attribute` to its respective value
|
|
208
|
+
contained in an structure within `collection`. The `collection` key can also
|
|
209
|
+
be accessed by `structure.collection`, just as `attribute` can also be
|
|
210
|
+
accessed by `structure.attribute` which will be converted following the same
|
|
211
|
+
process in case it is a collection.
|
|
211
212
|
|
|
212
|
-
- `{collection#
|
|
213
|
-
converts `
|
|
214
|
-
`
|
|
213
|
+
- `{collection#nth.attribute}`: selects the `nth` (start from 1) item from
|
|
214
|
+
`collection` and converts `attribute` to its respective value. The whole
|
|
215
|
+
process is similar to `structure.attribute`.
|
|
216
|
+
|
|
217
|
+
- `{collection#$.attribute}`: selects the `nth` (start from 1) item from
|
|
218
|
+
`collection` and converts `attribute` to its respective value. The whole
|
|
219
|
+
process is similar to `structure.attribute`.
|
|
220
|
+
|
|
221
|
+
### EBNF
|
|
222
|
+
|
|
223
|
+
```ebnf
|
|
224
|
+
identifier ::= initial_name { compound_name | space compound_name } ;
|
|
225
|
+
|
|
226
|
+
initial_name ::= letter | "_" ;
|
|
227
|
+
|
|
228
|
+
compound_name ::= letter | digit | "_" | "-" ;
|
|
229
|
+
|
|
230
|
+
letter ::= "A"…"Z" | "a"…"z" ;
|
|
231
|
+
|
|
232
|
+
digit ::= "0"…"9" ;
|
|
233
|
+
|
|
234
|
+
space ::= " " ;
|
|
235
|
+
|
|
236
|
+
expression ::= path [ length ] ;
|
|
237
|
+
|
|
238
|
+
path ::= [ structural_path ] { sequential_path } ;
|
|
239
|
+
|
|
240
|
+
structural_path ::= attribute { "." attribute } ;
|
|
241
|
+
|
|
242
|
+
scoped_path ::= ":" structural_path ;
|
|
243
|
+
|
|
244
|
+
attribute ::= element | item ;
|
|
245
|
+
|
|
246
|
+
element ::= identifier [ index ] ;
|
|
247
|
+
|
|
248
|
+
item ::= index ;
|
|
249
|
+
|
|
250
|
+
index ::= "#" ( number | "$" ) ;
|
|
251
|
+
|
|
252
|
+
number ::= digit { digit } ;
|
|
253
|
+
|
|
254
|
+
length ::= "#&" ;
|
|
255
|
+
```
|
|
215
256
|
|
|
216
257
|
## How it works
|
|
217
258
|
|
data/lib/drawght/compiler.rb
CHANGED
|
@@ -3,10 +3,31 @@
|
|
|
3
3
|
|
|
4
4
|
module Drawght
|
|
5
5
|
|
|
6
|
+
module HashExtensions
|
|
7
|
+
refine Hash do
|
|
8
|
+
def deep_stringify_keys!
|
|
9
|
+
transform_keys! do |key|
|
|
10
|
+
case value = fetch(key)
|
|
11
|
+
when Hash then value.deep_stringify_keys!
|
|
12
|
+
when Array then
|
|
13
|
+
value.map! do |item|
|
|
14
|
+
(item.is_a? Hash) ? item.deep_stringify_keys! : item
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
key.to_s
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
self
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
6
26
|
class Compiler
|
|
7
|
-
using
|
|
27
|
+
using HashExtensions
|
|
8
28
|
|
|
9
29
|
include Parser
|
|
30
|
+
include Tracker
|
|
10
31
|
|
|
11
32
|
attr_reader :template, :dataset, :result
|
|
12
33
|
|
|
@@ -30,11 +51,11 @@ class Compiler
|
|
|
30
51
|
|
|
31
52
|
def convert
|
|
32
53
|
lines = template.lines.map do |line|
|
|
33
|
-
next line unless
|
|
54
|
+
next line unless has_placeholders? line
|
|
34
55
|
|
|
35
56
|
mapping_placeholders_from line
|
|
36
57
|
|
|
37
|
-
newline =
|
|
58
|
+
newline = convert_structural_placeholders_from line
|
|
38
59
|
|
|
39
60
|
convert_sequential_placeholders_from newline
|
|
40
61
|
end
|
|
@@ -42,12 +63,12 @@ class Compiler
|
|
|
42
63
|
result.replace lines.join
|
|
43
64
|
end
|
|
44
65
|
|
|
45
|
-
def
|
|
46
|
-
|
|
47
|
-
matter = dataset
|
|
66
|
+
def convert_structural_placeholders_from string
|
|
67
|
+
structural_placeholders.reduce string.dup do |template, expression|
|
|
68
|
+
matter = pathing dataset, *pathkeys_from(expression)
|
|
48
69
|
|
|
49
70
|
converted = [matter].flatten.map do |value|
|
|
50
|
-
template.dup.gsub!
|
|
71
|
+
template.dup.gsub! pathize(expression), value.to_s
|
|
51
72
|
end
|
|
52
73
|
|
|
53
74
|
template.replace converted.join
|
|
@@ -56,12 +77,12 @@ class Compiler
|
|
|
56
77
|
|
|
57
78
|
def convert_sequential_placeholders_from string
|
|
58
79
|
sequential_placeholders.reduce string.dup do |template, (attribute, mappings)|
|
|
59
|
-
matter = dataset
|
|
80
|
+
matter = pathing dataset, *pathkeys_from(attribute)
|
|
60
81
|
|
|
61
82
|
converted = matter.map do |values|
|
|
62
|
-
mappings.inject template.dup do |partial, (
|
|
63
|
-
value = values
|
|
64
|
-
partial.dup.gsub!
|
|
83
|
+
mappings.inject template.dup do |partial, (expression, key)|
|
|
84
|
+
value = pathing(values, *pathkeys_from(key)) || key
|
|
85
|
+
partial.dup.gsub! pathize(expression), value.to_s
|
|
65
86
|
end
|
|
66
87
|
end
|
|
67
88
|
|
data/lib/drawght/parser.rb
CHANGED
|
@@ -2,22 +2,126 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Drawght
|
|
5
|
+
module ArrayExtensions
|
|
6
|
+
refine Array do
|
|
7
|
+
def add_unique item
|
|
8
|
+
push item unless include? item
|
|
9
|
+
self
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
5
14
|
module Parser
|
|
6
|
-
using
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
using ArrayExtensions
|
|
16
|
+
|
|
17
|
+
TOKENS = [
|
|
18
|
+
PREFIX = '{',
|
|
19
|
+
SUFFIX = '}',
|
|
20
|
+
ACCESSOR = '.',
|
|
21
|
+
INDEX = '#',
|
|
22
|
+
SCOPE = ':',
|
|
23
|
+
CONTEXT = '@',
|
|
24
|
+
LAST = '$',
|
|
25
|
+
LENGTH = '&',
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
# Identifiers/name matches:
|
|
29
|
+
#
|
|
30
|
+
# - "name"
|
|
31
|
+
# - "variable name"
|
|
32
|
+
# - "variable-name"
|
|
33
|
+
# - "variable_name"
|
|
34
|
+
# - "_name_"
|
|
35
|
+
# - "name_"
|
|
36
|
+
# - "_name"
|
|
37
|
+
IDENTIFIER_MATCHES = "[A-Za-z_][A-Za-z0-9_\\-]*(?: [A-Za-z0-9_\\-]+)*"
|
|
38
|
+
|
|
39
|
+
# Index/item matches:
|
|
40
|
+
#
|
|
41
|
+
# - "#1" for first item.
|
|
42
|
+
# - "#n" for n-th item.
|
|
43
|
+
# - "#$" for last item.
|
|
44
|
+
INDEX_MATCHES = "\\#{INDEX}(?:\\d+|\\#{LAST})"
|
|
45
|
+
|
|
46
|
+
# Element matches:
|
|
47
|
+
#
|
|
48
|
+
# - "items#1" for first named item.
|
|
49
|
+
# - "items#n" for n-th named item.
|
|
50
|
+
# - "items#$" for last named item.
|
|
51
|
+
#
|
|
52
|
+
# Matches with IDENTIFIER_MATCHES and INDEX_MATCHES.
|
|
53
|
+
ELEMENT_MATCHES = "#{IDENTIFIER_MATCHES}(?:#{INDEX_MATCHES})?"
|
|
54
|
+
|
|
55
|
+
# Attribute matches.
|
|
56
|
+
ATTRIBUTE_MATCHES = "\\#{ACCESSOR}(?:#{ELEMENT_MATCHES})"
|
|
57
|
+
|
|
58
|
+
# Validation
|
|
59
|
+
#
|
|
60
|
+
# Structural matches:
|
|
61
|
+
#
|
|
62
|
+
# - "struct.attribute" for attribute value from struct.
|
|
63
|
+
# - "struct.substruct.attribute" for attribute value of the substruct from
|
|
64
|
+
# struct.
|
|
65
|
+
# - "struct.items#1" for first item value in items of the struct.
|
|
66
|
+
# - "struct.items#1.attribute" for attribute value of the first item in
|
|
67
|
+
# items of the struct.
|
|
68
|
+
# - "#1.attribute" for attribute value of the first item.
|
|
69
|
+
# - "#1.struct.attribute" for attribute value of the struct from the first item.
|
|
70
|
+
# - "items#1.attribute" for attribute value of the first item in items.
|
|
71
|
+
# - "items#1.struct.attribute" for attribute value of the struct of the
|
|
72
|
+
# first item in items.
|
|
73
|
+
# - "items#1.subitems#1" for subitem value of the first item in items.
|
|
74
|
+
# - "items#1.subitems#1.attribute" for attribute value of the subitem from
|
|
75
|
+
# first item in items.
|
|
76
|
+
#
|
|
77
|
+
# Scoped matches:
|
|
78
|
+
#
|
|
79
|
+
# ":attribute"
|
|
80
|
+
# ":collection:attribute"
|
|
81
|
+
# "collection:attribute"
|
|
82
|
+
# "collection:subcollection:attribute"
|
|
83
|
+
# "items#1:attribute"
|
|
84
|
+
# "struct.collection:attribute"
|
|
85
|
+
# "items#1.collection:attribute"
|
|
86
|
+
# "items#1.subitems#1:attribute"
|
|
87
|
+
# "items#1.subitems#1.collection:attribute"
|
|
88
|
+
# "struct.collection:noitcelloc.tcurts:attribute"
|
|
89
|
+
VALIDATION_PATTERN = Regexp.new "^(?=.*[A-Za-z_\\#{INDEX}])(?:(?:#{ELEMENT_MATCHES}|#{INDEX_MATCHES})(?:#{ATTRIBUTE_MATCHES})*)?(?:\\#{SCOPE}(?:#{ELEMENT_MATCHES})(?:#{ATTRIBUTE_MATCHES})*)*(?:\\#{INDEX}\\#{LENGTH})?$"
|
|
90
|
+
|
|
91
|
+
PLACEHOLDERS_PATTERN = Regexp.new "\\#{PREFIX}([^\\#{SUFFIX}]+)\\#{SUFFIX}"
|
|
92
|
+
STRUCTURE_TOKEN_PATTERN = Regexp.new "(\\#{ACCESSOR}|\\#{INDEX}|\\#{LENGTH}$)"
|
|
93
|
+
SCOPE_TOKEN_PATTERN = Regexp.new "(\\#{SCOPE})"
|
|
94
|
+
SCOPE_PATH_PATTERN = Regexp.new "^(.*)#{SCOPE_TOKEN_PATTERN}(.*)$"
|
|
95
|
+
|
|
96
|
+
NUMBER_PATTERN = /^\d+/
|
|
97
|
+
|
|
98
|
+
using ArrayExtensions
|
|
99
|
+
|
|
100
|
+
class SyntaxError < StandardError
|
|
101
|
+
def initialize syntax
|
|
102
|
+
super "Invalid syntax for \"#{syntax}\""
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def pathkeys_from string
|
|
107
|
+
raise SyntaxError.new string unless syntax_valid? string
|
|
108
|
+
|
|
109
|
+
path = case string
|
|
110
|
+
when STRUCTURE_TOKEN_PATTERN then
|
|
111
|
+
pathkeys_for_structure string
|
|
112
|
+
when SCOPE_TOKEN_PATTERN then
|
|
113
|
+
pathkeys_for_collection string
|
|
114
|
+
else
|
|
115
|
+
[string]
|
|
116
|
+
end
|
|
17
117
|
|
|
18
118
|
path.flatten
|
|
19
119
|
end
|
|
20
120
|
|
|
121
|
+
def syntax_valid? string
|
|
122
|
+
string.match? VALIDATION_PATTERN
|
|
123
|
+
end
|
|
124
|
+
|
|
21
125
|
def placeholders_from string
|
|
22
126
|
return [] unless string =~ PLACEHOLDERS_PATTERN
|
|
23
127
|
|
|
@@ -28,61 +132,70 @@ module Drawght
|
|
|
28
132
|
clear_placeholder_mappings!
|
|
29
133
|
|
|
30
134
|
placeholders_from(string).map do |placeholder|
|
|
31
|
-
if placeholder =~
|
|
32
|
-
placeholder.scan
|
|
135
|
+
if placeholder =~ SCOPE_TOKEN_PATTERN
|
|
136
|
+
placeholder.scan SCOPE_PATH_PATTERN do |pathkeys, _delimiter, attribute|
|
|
33
137
|
(sequential_placeholders[pathkeys] ||= {}).update placeholder => attribute
|
|
34
138
|
end
|
|
35
139
|
else
|
|
36
|
-
|
|
140
|
+
structural_placeholders.add_unique placeholder
|
|
37
141
|
end
|
|
38
142
|
|
|
39
143
|
placeholder
|
|
40
144
|
end
|
|
41
145
|
end
|
|
42
146
|
|
|
43
|
-
def
|
|
44
|
-
@
|
|
147
|
+
def structural_placeholders
|
|
148
|
+
@structural_placeholders ||= []
|
|
45
149
|
end
|
|
46
150
|
|
|
47
151
|
def sequential_placeholders
|
|
48
152
|
@sequential_placeholders ||= {}
|
|
49
153
|
end
|
|
50
154
|
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
else
|
|
58
|
-
replace_placeholder_variables_from template, value
|
|
59
|
-
end
|
|
155
|
+
def has_placeholders? string
|
|
156
|
+
string.match? PLACEHOLDERS_PATTERN
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def pathize string
|
|
160
|
+
"#{PREFIX}#{string}#{SUFFIX}"
|
|
60
161
|
end
|
|
61
162
|
|
|
62
163
|
private
|
|
63
164
|
|
|
64
|
-
def
|
|
65
|
-
placeholder
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
165
|
+
def pathkeys_for_structure placeholder
|
|
166
|
+
placeholder
|
|
167
|
+
.split(STRUCTURE_TOKEN_PATTERN)
|
|
168
|
+
.reject{ |expression| [ACCESSOR, INDEX].include? expression }
|
|
169
|
+
.map do |expression|
|
|
170
|
+
value = zeroize expression
|
|
171
|
+
|
|
172
|
+
if value =~ SCOPE_TOKEN_PATTERN
|
|
173
|
+
pathkeys_for_collection expression
|
|
174
|
+
else
|
|
175
|
+
value =~ NUMBER_PATTERN ? value.to_i - 1 : expression unless value.empty?
|
|
176
|
+
end
|
|
177
|
+
end.compact
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def zeroize value, token: LAST
|
|
181
|
+
value.to_s.sub token, '0'
|
|
72
182
|
end
|
|
73
183
|
|
|
74
|
-
def
|
|
75
|
-
placeholder.
|
|
76
|
-
|
|
77
|
-
|
|
184
|
+
def pathkeys_for_collection placeholder
|
|
185
|
+
placeholder.split(SCOPE_TOKEN_PATTERN).map do |expression|
|
|
186
|
+
case expression.to_s
|
|
187
|
+
when STRUCTURE_TOKEN_PATTERN then
|
|
188
|
+
pathkeys_for_structure expression
|
|
189
|
+
when SCOPE then
|
|
190
|
+
CONTEXT
|
|
78
191
|
else
|
|
79
|
-
|
|
192
|
+
expression
|
|
80
193
|
end
|
|
81
194
|
end
|
|
82
195
|
end
|
|
83
196
|
|
|
84
197
|
def clear_placeholder_mappings!
|
|
85
|
-
|
|
198
|
+
structural_placeholders.clear && sequential_placeholders.clear
|
|
86
199
|
end
|
|
87
200
|
end
|
|
88
201
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Drawght
|
|
4
|
+
|
|
5
|
+
module Tracker
|
|
6
|
+
LENGTH = Parser::LENGTH
|
|
7
|
+
CONTEXT = Parser::CONTEXT
|
|
8
|
+
|
|
9
|
+
def pathing hash, *pathkeys
|
|
10
|
+
if i = pathkeys.index CONTEXT
|
|
11
|
+
prefixes, suffixes = pathkeys.slice(0..i - 1), pathkeys.slice(i + 1..-1)
|
|
12
|
+
result = pathing(hash, *prefixes).map{ |item| pathing item, *suffixes }
|
|
13
|
+
suffixes.last == LENGTH ? result.reduce(&:+) : result
|
|
14
|
+
elsif pathkeys.last == LENGTH
|
|
15
|
+
hash.dig(*pathkeys.slice(0..-2)).length
|
|
16
|
+
else
|
|
17
|
+
hash.dig *pathkeys
|
|
18
|
+
end
|
|
19
|
+
rescue => error
|
|
20
|
+
raise error, "The pathkeys \"#{pathkeys.join ' '}\" is a not valid path"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end # Drawght
|
data/lib/drawght/version.rb
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
3
|
module Drawght
|
|
4
|
-
VERSION = "1.
|
|
5
|
-
RELEASE_DATE = "2025-12-
|
|
4
|
+
VERSION = "1.1.0"
|
|
5
|
+
RELEASE_DATE = "2025-12-22"
|
|
6
6
|
CHANGESET = [
|
|
7
|
-
"
|
|
8
|
-
"Refined extension methods have been
|
|
9
|
-
"
|
|
10
|
-
"Syntax revision for nested values in collections.",
|
|
7
|
+
"Syntax validation.",
|
|
8
|
+
"Refined extension methods have been moved to their respective modules.",
|
|
9
|
+
"Syntax for getting the length of a collection.",
|
|
11
10
|
]
|
|
12
11
|
end
|
data/lib/drawght.rb
CHANGED
|
@@ -2,69 +2,8 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Drawght
|
|
5
|
-
TOKENS = [
|
|
6
|
-
PREFIX = '{',
|
|
7
|
-
SUFFIX = '}',
|
|
8
|
-
ATTRIBUTE = '.',
|
|
9
|
-
ITEM = '#',
|
|
10
|
-
QUERY = ':',
|
|
11
|
-
]
|
|
12
|
-
|
|
13
|
-
PLACEHOLDERS_PATTERN = Regexp.new "\\#{PREFIX}([^\\#{SUFFIX}]+)\\#{SUFFIX}"
|
|
14
|
-
|
|
15
|
-
ATTRIBUTES_PATTERN = Regexp.new "\\#{ATTRIBUTE}|\\#{ITEM}"
|
|
16
|
-
ATTRIBUTE_PATTERN = Regexp.new "\\#{ATTRIBUTE}"
|
|
17
|
-
ITEM_PATTERN = Regexp.new "\\#{ITEM}"
|
|
18
|
-
QUERY_PATTERN = Regexp.new "\\#{QUERY}"
|
|
19
|
-
|
|
20
|
-
PATH_PATTERN = Regexp.new "\\#{ATTRIBUTE}|\\#{ITEM}|\\#{QUERY}"
|
|
21
|
-
|
|
22
|
-
module Extensions
|
|
23
|
-
refine Hash do
|
|
24
|
-
def deep_stringify_keys!
|
|
25
|
-
transform_keys! do |key|
|
|
26
|
-
case value = fetch(key)
|
|
27
|
-
when Hash then value.deep_stringify_keys!
|
|
28
|
-
when Array then
|
|
29
|
-
value.map! do |item|
|
|
30
|
-
(item.is_a? Hash) ? item.deep_stringify_keys! : item
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
key.to_s
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
self
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def ditch *pathkeys
|
|
41
|
-
if i = pathkeys.index('&')
|
|
42
|
-
list, subpath = pathkeys[0..i - 1], pathkeys[i + 1..-1]
|
|
43
|
-
dig(*list).map{ |item| item.ditch *subpath }
|
|
44
|
-
else
|
|
45
|
-
dig *pathkeys
|
|
46
|
-
end
|
|
47
|
-
rescue => error
|
|
48
|
-
error.message += "The pathkeys \"#{pathkeys.join ','}\" is a not valid path"
|
|
49
|
-
raise error
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
refine Array do
|
|
54
|
-
def add item
|
|
55
|
-
push item unless include? item
|
|
56
|
-
self
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
refine String do
|
|
61
|
-
def to_placeholder
|
|
62
|
-
"#{PREFIX}#{self}#{SUFFIX}"
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
5
|
require_relative "drawght/parser"
|
|
6
|
+
require_relative "drawght/tracker"
|
|
68
7
|
require_relative "drawght/compiler"
|
|
69
8
|
require_relative "drawght/version"
|
|
70
9
|
|
metadata
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: drawght
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hallison Batista
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2025-12-
|
|
10
|
+
date: 2025-12-22 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
12
|
description: |
|
|
13
|
-
Drawght v1.
|
|
13
|
+
Drawght v1.1.0 (2025-12-22)
|
|
14
14
|
|
|
15
15
|
Drawght is a data handler for texts without logical statements. The goal is
|
|
16
16
|
to use a dataset (such as the subject of a text) to draft a document
|
|
@@ -18,10 +18,9 @@ description: |
|
|
|
18
18
|
|
|
19
19
|
Latest changes:
|
|
20
20
|
|
|
21
|
-
-
|
|
22
|
-
- Refined extension methods have been
|
|
23
|
-
-
|
|
24
|
-
- Syntax revision for nested values in collections.
|
|
21
|
+
- Syntax validation.
|
|
22
|
+
- Refined extension methods have been moved to their respective modules.
|
|
23
|
+
- Syntax for getting the length of a collection.
|
|
25
24
|
email: email@hallison.dev.br
|
|
26
25
|
executables: []
|
|
27
26
|
extensions: []
|
|
@@ -34,6 +33,7 @@ files:
|
|
|
34
33
|
- lib/drawght/compiler.rb
|
|
35
34
|
- lib/drawght/mapper.rb
|
|
36
35
|
- lib/drawght/parser.rb
|
|
36
|
+
- lib/drawght/tracker.rb
|
|
37
37
|
- lib/drawght/version.rb
|
|
38
38
|
homepage: https://drawght.github.io
|
|
39
39
|
licenses:
|
|
@@ -55,5 +55,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
55
55
|
requirements: []
|
|
56
56
|
rubygems_version: 3.6.7
|
|
57
57
|
specification_version: 4
|
|
58
|
-
summary: Drawght
|
|
58
|
+
summary: Drawght implementation in Ruby.
|
|
59
59
|
test_files: []
|