marked-conductor 1.0.26 → 1.0.28
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/.irbrc +2 -2
- data/CHANGELOG.md +18 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +4 -4
- data/bin/conductor +8 -98
- data/lib/conductor/array.rb +36 -2
- data/lib/conductor/boolean.rb +10 -0
- data/lib/conductor/command.rb +25 -1
- data/lib/conductor/condition.rb +41 -16
- data/lib/conductor/config.rb +37 -8
- data/lib/conductor/env.rb +3 -3
- data/lib/conductor/filter.rb +343 -198
- data/lib/conductor/hash.rb +15 -0
- data/lib/conductor/script.rb +2 -2
- data/lib/conductor/string.rb +51 -8
- data/lib/conductor/version.rb +1 -1
- data/lib/conductor/{yui-compressor.rb → yui_compressor.rb} +105 -85
- data/lib/conductor.rb +94 -2
- data/marked-conductor.gemspec +2 -1
- metadata +4 -4
data/lib/conductor/hash.rb
CHANGED
@@ -1,10 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Hash helpers
|
3
4
|
class ::Hash
|
5
|
+
##
|
6
|
+
## Destructive version of #symbolize_keys
|
7
|
+
##
|
8
|
+
## @see #symbolize_keys
|
9
|
+
##
|
10
|
+
## @return [Hash] hash with keys as symbols
|
11
|
+
##
|
4
12
|
def symbolize_keys!
|
5
13
|
replace symbolize_keys
|
6
14
|
end
|
7
15
|
|
16
|
+
##
|
17
|
+
## Convert all keys in hash to symbols. Works on nested hashes
|
18
|
+
##
|
19
|
+
## @see #symbolize_keys!
|
20
|
+
##
|
21
|
+
## @return [Hash] hash with keys as symbols
|
22
|
+
##
|
8
23
|
def symbolize_keys
|
9
24
|
each_with_object({}) { |(k, v), hsh| hsh[k.to_sym] = (v.is_a?(Hash) || v.is_a?(Array)) ? v.symbolize_keys : v }
|
10
25
|
end
|
data/lib/conductor/script.rb
CHANGED
@@ -22,7 +22,7 @@ module Conductor
|
|
22
22
|
## @param path The path
|
23
23
|
##
|
24
24
|
def path=(path)
|
25
|
-
@path = if %r{^[
|
25
|
+
@path = if %r{^[~/.]}.match?(path)
|
26
26
|
File.expand_path(path)
|
27
27
|
else
|
28
28
|
script_dir = File.expand_path("~/.config/conductor/scripts")
|
@@ -56,7 +56,7 @@ module Conductor
|
|
56
56
|
## @return [String] script results (STDOUT)
|
57
57
|
##
|
58
58
|
def run
|
59
|
-
stdin = Conductor.stdin
|
59
|
+
stdin = Conductor.stdin unless /\$\{?file\}?/.match?(args)
|
60
60
|
|
61
61
|
raise "Script path not defined" unless @path
|
62
62
|
|
data/lib/conductor/string.rb
CHANGED
@@ -15,6 +15,11 @@ class ::String
|
|
15
15
|
split(/,/).map { |s| Shellwords.shellsplit(s) }
|
16
16
|
end
|
17
17
|
|
18
|
+
##
|
19
|
+
## Normalize positional string to symbol
|
20
|
+
##
|
21
|
+
## @return [Symbol] position symbol (:start, :h1, :h2, :end)
|
22
|
+
##
|
18
23
|
def normalize_position
|
19
24
|
case self
|
20
25
|
when /^(be|s|t)/
|
@@ -28,6 +33,11 @@ class ::String
|
|
28
33
|
end
|
29
34
|
end
|
30
35
|
|
36
|
+
##
|
37
|
+
## Normalize a file include string to symbol
|
38
|
+
##
|
39
|
+
## @return [Symbol] include type symbol (:code, :raw, :file)
|
40
|
+
##
|
31
41
|
def normalize_include_type
|
32
42
|
case self
|
33
43
|
when /^c/
|
@@ -61,7 +71,7 @@ class ::String
|
|
61
71
|
## @return [Boolean] test result
|
62
72
|
##
|
63
73
|
def date?
|
64
|
-
dup.force_encoding("utf-8")
|
74
|
+
dup.force_encoding("utf-8") =~ /^\d{4}-\d{2}-\d{2}( \d{1,2}(:\d\d)? *([ap]m)?)?$/ ? true : false
|
65
75
|
end
|
66
76
|
|
67
77
|
##
|
@@ -70,7 +80,7 @@ class ::String
|
|
70
80
|
## @return [Boolean] test result
|
71
81
|
##
|
72
82
|
def time?
|
73
|
-
dup.force_encoding("utf-8")
|
83
|
+
dup.force_encoding("utf-8") =~ / \d{1,2}(:\d\d)? *([ap]m)?/i ? true : false
|
74
84
|
end
|
75
85
|
|
76
86
|
##
|
@@ -92,6 +102,11 @@ class ::String
|
|
92
102
|
dup.force_encoding("utf-8").sub(/ \d{1,2}(:\d\d)? *([ap]m)?/i, "")
|
93
103
|
end
|
94
104
|
|
105
|
+
##
|
106
|
+
## Round a date string to a day
|
107
|
+
##
|
108
|
+
## @param time [Symbol] :start or :end
|
109
|
+
##
|
95
110
|
def to_day(time = :end)
|
96
111
|
t = time == :end ? "23:59" : "00:00"
|
97
112
|
Chronic.parse("#{strip_time} #{t}")
|
@@ -134,13 +149,12 @@ class ::String
|
|
134
149
|
end
|
135
150
|
|
136
151
|
##
|
137
|
-
##
|
152
|
+
## Test if a string starts with Pandoc metadata
|
138
153
|
##
|
154
|
+
## @return [Boolean] test result
|
139
155
|
##
|
140
|
-
|
141
|
-
|
142
|
-
def to_bool!
|
143
|
-
replace to_bool
|
156
|
+
def pandoc?
|
157
|
+
dup.force_encoding('utf-8').match?(/^% \S/m)
|
144
158
|
end
|
145
159
|
|
146
160
|
##
|
@@ -149,11 +163,40 @@ class ::String
|
|
149
163
|
## @return [Boolean] Bool representation of the object.
|
150
164
|
##
|
151
165
|
def to_bool
|
152
|
-
case self.force_encoding('utf-8')
|
166
|
+
case self.dup.force_encoding('utf-8')
|
153
167
|
when /^[yt]/i
|
154
168
|
true
|
155
169
|
else
|
156
170
|
false
|
157
171
|
end
|
158
172
|
end
|
173
|
+
|
174
|
+
##
|
175
|
+
## Convert a string to a regular expression
|
176
|
+
##
|
177
|
+
## If the string matches /xxx/, it will be interpreted
|
178
|
+
## directly as a regex. Otherwise it will be escaped and
|
179
|
+
## converted to regex.
|
180
|
+
##
|
181
|
+
## @return [Regexp] Regexp representation of the string.
|
182
|
+
##
|
183
|
+
def to_rx
|
184
|
+
if self =~ %r{^/(.*?)/([im]+)?$}
|
185
|
+
m = Regexp.last_match
|
186
|
+
regex = m[1]
|
187
|
+
flags = m[2]
|
188
|
+
Regexp.new(regex, flags)
|
189
|
+
else
|
190
|
+
Regexp.new(Regexp.escape(self))
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
##
|
195
|
+
## Convert a string containing $1, $2 to a Regexp replace pattern
|
196
|
+
##
|
197
|
+
## @return [String] Pattern representation of the object.
|
198
|
+
##
|
199
|
+
def to_pattern
|
200
|
+
gsub(/\$(\d+)/, '\\\\\1').gsub(/(^["']|["']$)/, "")
|
201
|
+
end
|
159
202
|
end
|
data/lib/conductor/version.rb
CHANGED
@@ -1,42 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
1
3
|
# This is a Ruby port of the YUI CSS compressor
|
2
4
|
# See LICENSE for license information
|
3
5
|
|
4
6
|
module YuiCompressor
|
5
7
|
# Compress CSS rules using a variety of techniques
|
6
|
-
|
7
8
|
class Yui
|
8
9
|
attr_reader :input_size, :output_size
|
9
10
|
|
11
|
+
##
|
12
|
+
## Instantiate compressor
|
13
|
+
##
|
14
|
+
## @return [Yui] self
|
15
|
+
##
|
10
16
|
def initialize
|
11
|
-
@
|
17
|
+
@preserved_tokens = []
|
12
18
|
@comments = []
|
13
19
|
@input_size = 0
|
14
20
|
@output_size = 0
|
15
21
|
end
|
16
22
|
|
23
|
+
##
|
24
|
+
## YUI Compress string
|
25
|
+
##
|
26
|
+
## @param css [String] The css
|
27
|
+
## @param line_length [Integer] The line length
|
28
|
+
##
|
17
29
|
def compress(css, line_length = 0)
|
18
30
|
@input_size = css.length
|
19
31
|
|
20
32
|
css = process_comments_and_strings(css)
|
21
33
|
|
22
34
|
# Normalize all whitespace strings to single spaces. Easier to work with that way.
|
23
|
-
css.gsub!(/\s+/,
|
35
|
+
css.gsub!(/\s+/, " ")
|
24
36
|
|
25
37
|
# Remove the spaces before the things that should not have spaces before them.
|
26
38
|
# But, be careful not to turn "p :link {...}" into "p:link{...}"
|
27
39
|
# Swap out any pseudo-class colons with the token, and then swap back.
|
28
40
|
css.gsub!(/(?:^|\})[^{:]+\s+:+[^{]*\{/) do |match|
|
29
|
-
match.gsub(
|
41
|
+
match.gsub(":", "___PSEUDOCLASSCOLON___")
|
30
42
|
end
|
31
43
|
css.gsub!(/\s+([!{};:>+()\],])/, '\1')
|
32
44
|
css.gsub!(/([!{}:;>+(\[,])\s+/, '\1')
|
33
|
-
css.gsub!(
|
45
|
+
css.gsub!("___PSEUDOCLASSCOLON___", ":")
|
34
46
|
|
35
47
|
# special case for IE
|
36
48
|
css.gsub!(/:first-(line|letter)(\{|,)/, ':first-\1 \2')
|
37
49
|
|
38
50
|
# no space after the end of a preserved comment
|
39
|
-
css.gsub!(%r{\*/ },
|
51
|
+
css.gsub!(%r{\*/ }, "*/")
|
40
52
|
|
41
53
|
# If there is a @charset, then only allow one, and push to the top of the file.
|
42
54
|
css.gsub!(/^(.*)(@charset "[^"]*";)/i, '\2\1')
|
@@ -44,10 +56,10 @@ module YuiCompressor
|
|
44
56
|
|
45
57
|
# Put the space back in some cases, to support stuff like
|
46
58
|
# @media screen and (-webkit-min-device-pixel-ratio:0){
|
47
|
-
css.gsub!(/\band\(/i,
|
59
|
+
css.gsub!(/\band\(/i, "and (")
|
48
60
|
|
49
61
|
# remove unnecessary semicolons
|
50
|
-
css.gsub!(/;+\}/,
|
62
|
+
css.gsub!(/;+\}/, "}")
|
51
63
|
|
52
64
|
# Replace 0(%, em, ex, px, in, cm, mm, pt, pc) with just 0.
|
53
65
|
css.gsub!(/([\s:])([+-]?0)(?:%|em|ex|px|in|cm|mm|pt|pc)/i, '\1\2')
|
@@ -56,8 +68,9 @@ module YuiCompressor
|
|
56
68
|
css.gsub!(/:(?:0 )+0(;|\})/, ':0\1')
|
57
69
|
|
58
70
|
# Restore background-position:0 0; if required
|
59
|
-
css.gsub!(/(background-position|
|
60
|
-
|
71
|
+
css.gsub!(/(background-position|(?:(?:webkit|moz|o|ms)-)?transform-origin):0(;|\})/i) do
|
72
|
+
"#{::Regexp.last_match(1).downcase}:0 0#{::Regexp.last_match(2)}"
|
73
|
+
end
|
61
74
|
|
62
75
|
# Replace 0.6 with .6, but only when preceded by : or a space.
|
63
76
|
css.gsub!(/(:|\s)0+\.(\d+)/, '\1.\2')
|
@@ -65,7 +78,7 @@ module YuiCompressor
|
|
65
78
|
# Shorten colors from rgb(51,102,153) to #336699
|
66
79
|
# This makes it more likely that it'll get further compressed in the next step.
|
67
80
|
css.gsub!(/rgb\s*\(\s*([0-9,\s]+)\s*\)/) do |_match|
|
68
|
-
|
81
|
+
"#".dup << ::Regexp.last_match(1).scan(/\d+/).map { |n| n.to_i.to_s(16).rjust(2, "0") }.join
|
69
82
|
end
|
70
83
|
|
71
84
|
# Shorten colors from #AABBCC to #ABC. Note that we want to make sure
|
@@ -77,34 +90,35 @@ module YuiCompressor
|
|
77
90
|
css.gsub!(/([^"'=\s])(\s?)\s*#([0-9a-f])\3([0-9a-f])\4([0-9a-f])\5/i, '\1\2#\3\4\5')
|
78
91
|
|
79
92
|
# border: none -> border:0
|
80
|
-
css.gsub!(/(border|border-top|
|
81
|
-
|
93
|
+
css.gsub!(/(border|border-(top|right|bottom)|outline|background):none(;|\})/i) do
|
94
|
+
"#{::Regexp.last_match(1).downcase}:0#{::Regexp.last_match(2)}"
|
95
|
+
end
|
82
96
|
|
83
97
|
# shorter opacity IE filter
|
84
|
-
css.gsub!(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/i,
|
98
|
+
css.gsub!(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/i, "alpha(opacity=")
|
85
99
|
|
86
100
|
# Remove empty rules.
|
87
|
-
css.gsub!(%r{[^\};\{/]+\{\}},
|
101
|
+
css.gsub!(%r{[^\};\{/]+\{\}}, "")
|
88
102
|
|
89
|
-
if line_length
|
103
|
+
if line_length.positive?
|
90
104
|
# Some source control tools don't like it when files containing lines longer
|
91
105
|
# than, say 8000 characters, are checked in. The linebreak option is used in
|
92
106
|
# that case to split long lines after a specific column.
|
93
|
-
|
94
|
-
|
107
|
+
start_index = 0
|
108
|
+
idx = 0
|
95
109
|
length = css.length
|
96
|
-
while
|
97
|
-
|
98
|
-
if css[
|
99
|
-
css = css.slice(0,
|
100
|
-
|
110
|
+
while idx < length
|
111
|
+
idx += 1
|
112
|
+
if css[idx - 1, 1] == "}" && idx - start_index > line_length
|
113
|
+
css = "#{css.slice(0, idx)}\n#{css.slice(idx, length)}"
|
114
|
+
start_index = idx
|
101
115
|
end
|
102
116
|
end
|
103
117
|
end
|
104
118
|
|
105
119
|
# Replace multiple semi-colons in a row by a single one
|
106
120
|
# See SF bug #1980989
|
107
|
-
css.gsub!(/;+/,
|
121
|
+
css.gsub!(/;+/, ";")
|
108
122
|
|
109
123
|
# restore preserved comments and strings
|
110
124
|
css = restore_preserved_comments_and_strings(css)
|
@@ -116,26 +130,28 @@ module YuiCompressor
|
|
116
130
|
css
|
117
131
|
end
|
118
132
|
|
133
|
+
##
|
134
|
+
## Replace comments and strings with placeholders
|
135
|
+
##
|
136
|
+
## @param css_text [String] The css text
|
137
|
+
##
|
138
|
+
## @return [String] css text with strings replaced
|
119
139
|
def process_comments_and_strings(css_text)
|
120
|
-
css = css_text.
|
140
|
+
css = css_text.dup.force_encoding("ISO-8859-1").encode("utf-8", replace: nil)
|
121
141
|
|
122
|
-
|
123
|
-
|
124
|
-
i = 0
|
125
|
-
max = 0
|
126
|
-
token = ''
|
142
|
+
start_index = 0
|
143
|
+
token = ""
|
127
144
|
totallen = css.length
|
128
|
-
placeholder =
|
145
|
+
placeholder = ""
|
129
146
|
|
130
147
|
# collect all comment blocks
|
131
|
-
while (
|
132
|
-
|
133
|
-
|
134
|
-
token = css.slice(
|
148
|
+
while (start_index = css.index(%r{/\*}, start_index))
|
149
|
+
end_index = css.index(%r{\*/}, start_index + 2)
|
150
|
+
end_index ||= totallen
|
151
|
+
token = css.slice(start_index + 2..end_index - 1)
|
135
152
|
@comments.push(token)
|
136
|
-
css =
|
137
|
-
|
138
|
-
startIndex += 2
|
153
|
+
css = "#{css.slice(0..start_index + 1)}___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_#{@comments.length - 1}___#{css.slice(end_index, totallen)}"
|
154
|
+
start_index += 2
|
139
155
|
end
|
140
156
|
|
141
157
|
# preserve strings so their content doesn't get accidentally minified
|
@@ -146,82 +162,86 @@ endIndex, totallen).to_s
|
|
146
162
|
# maybe the string contains a comment-like substring?
|
147
163
|
# one, maybe more? put'em back then
|
148
164
|
if string =~ /___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_/
|
149
|
-
@comments.each_index do |
|
150
|
-
string.gsub!(/___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_#{
|
165
|
+
@comments.each_index do |idx|
|
166
|
+
string.gsub!(/___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_#{idx}___/, @comments[idx])
|
151
167
|
end
|
152
168
|
end
|
153
169
|
|
154
170
|
# minify alpha opacity in filter strings
|
155
|
-
string.gsub!(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/i,
|
156
|
-
@
|
171
|
+
string.gsub!(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/i, "alpha(opacity=")
|
172
|
+
@preserved_tokens.push(string)
|
157
173
|
|
158
|
-
quote
|
174
|
+
"#{quote}___YUICSSMIN_PRESERVED_TOKEN_#{@preserved_tokens.length - 1}___#{quote}"
|
159
175
|
end
|
160
176
|
|
161
|
-
# used to jump one index in loop
|
162
|
-
ie5_hack = false
|
177
|
+
# # used to jump one index in loop
|
178
|
+
# ie5_hack = false
|
163
179
|
# strings are safe, now wrestle the comments
|
164
|
-
@comments.each_index do |
|
165
|
-
if ie5_hack
|
166
|
-
|
167
|
-
|
168
|
-
end
|
180
|
+
@comments.each_index do |idx|
|
181
|
+
# if ie5_hack
|
182
|
+
# ie5_hack = false
|
183
|
+
# next
|
184
|
+
# end
|
169
185
|
|
170
|
-
token = @comments[
|
171
|
-
placeholder =
|
186
|
+
token = @comments[idx]
|
187
|
+
placeholder = "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_#{idx}___"
|
172
188
|
|
173
189
|
# ! in the first position of the comment means preserve
|
174
190
|
# so push to the preserved tokens keeping the !
|
175
|
-
if token[0, 1]
|
176
|
-
@
|
177
|
-
css.gsub!(/#{placeholder}/i,
|
191
|
+
if token[0, 1] == "!"
|
192
|
+
@preserved_tokens.push(token)
|
193
|
+
css.gsub!(/#{placeholder}/i, "___YUICSSMIN_PRESERVED_TOKEN_#{@preserved_tokens.length - 1}___")
|
178
194
|
next
|
179
195
|
end
|
180
196
|
|
181
|
-
# \ in the last position looks like hack for Mac/IE5
|
182
|
-
# shorten that to /*\*/ and the next one to /**/
|
183
|
-
if token[-1, 1]
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
end
|
193
|
-
|
194
|
-
# keep empty comments after child selectors (IE7 hack)
|
195
|
-
# e.g. html >/**/ body
|
196
|
-
if
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
197
|
+
# # \ in the last position looks like hack for Mac/IE5
|
198
|
+
# # shorten that to /*\*/ and the next one to /**/
|
199
|
+
# if token[-1, 1] == "\\"
|
200
|
+
# @preserved_tokens.push("\\")
|
201
|
+
# css.gsub!(/#{placeholder}/, "___YUICSSMIN_PRESERVED_TOKEN_#{@preserved_tokens.length - 1}___")
|
202
|
+
# # keep the next comment but remove its content
|
203
|
+
# @preserved_tokens.push("")
|
204
|
+
# css.gsub!(/___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_#{idx + 1}___/,
|
205
|
+
# "___YUICSSMIN_PRESERVED_TOKEN_#{@preserved_tokens.length - 1}___")
|
206
|
+
# ie5_hack = true
|
207
|
+
# next
|
208
|
+
# end
|
209
|
+
|
210
|
+
# # keep empty comments after child selectors (IE7 hack)
|
211
|
+
# # e.g. html >/**/ body
|
212
|
+
# if token.empty? && (start_index = css.index(/#{placeholder}/)) &&
|
213
|
+
# (start_index > 2) && (css[start_index - 3, 1] == ">")
|
214
|
+
# @preserved_tokens.push("")
|
215
|
+
# css.gsub!(/#{placeholder}/, "___YUICSSMIN_PRESERVED_TOKEN_#{@preserved_tokens.length - 1}___")
|
216
|
+
# end
|
204
217
|
|
205
218
|
# in all other cases kill the comment
|
206
|
-
css.gsub!(%r{/\*#{placeholder}\*/},
|
219
|
+
css.gsub!(%r{/\*#{placeholder}\*/}, "")
|
207
220
|
end
|
208
221
|
|
209
222
|
css
|
210
223
|
end
|
211
224
|
|
225
|
+
##
|
226
|
+
## Restore saved comments and strings
|
227
|
+
##
|
228
|
+
## @param clean_css [String] The processed css
|
229
|
+
##
|
230
|
+
## @return [String] restored CSS
|
231
|
+
##
|
212
232
|
def restore_preserved_comments_and_strings(clean_css)
|
213
233
|
css = clean_css.clone
|
214
234
|
css_length = css.length
|
215
|
-
@
|
235
|
+
@preserved_tokens.each_index do |idx|
|
216
236
|
# slice these back into place rather than regex, because
|
217
237
|
# complex nested strings cause the replacement to fail
|
218
|
-
placeholder = "___YUICSSMIN_PRESERVED_TOKEN_#{
|
219
|
-
|
220
|
-
next unless
|
238
|
+
placeholder = "___YUICSSMIN_PRESERVED_TOKEN_#{idx}___"
|
239
|
+
start_index = css.index(placeholder, 0)
|
240
|
+
next unless start_index # skip if nil
|
221
241
|
|
222
|
-
|
242
|
+
end_index = start_index + placeholder.length
|
223
243
|
|
224
|
-
css = css.slice(0..
|
244
|
+
css = css.slice(0..start_index - 1).to_s + @preserved_tokens[idx] + css.slice(end_index, css_length).to_s
|
225
245
|
end
|
226
246
|
|
227
247
|
css
|
data/lib/conductor.rb
CHANGED
@@ -19,16 +19,108 @@ require_relative "conductor/filter"
|
|
19
19
|
require_relative "conductor/script"
|
20
20
|
require_relative "conductor/command"
|
21
21
|
require_relative "conductor/condition"
|
22
|
-
require_relative "conductor/
|
22
|
+
require_relative "conductor/yui_compressor"
|
23
23
|
|
24
|
+
# Main Conductor module
|
24
25
|
module Conductor
|
25
26
|
class << self
|
26
27
|
attr_accessor :original_input
|
27
28
|
attr_writer :stdin
|
28
29
|
|
30
|
+
##
|
31
|
+
## Return STDIN value, reading from STDIN if needed
|
32
|
+
##
|
33
|
+
## @return [String] STDIN contents
|
34
|
+
##
|
29
35
|
def stdin
|
30
|
-
warn "input on STDIN required" unless $stdin.stat.size.positive? || $stdin.fcntl(Fcntl::F_GETFL, 0).zero?
|
36
|
+
warn "input on STDIN required" unless ENV["CONDUCTOR_TEST"] || $stdin.stat.size.positive? || $stdin.fcntl(Fcntl::F_GETFL, 0).zero?
|
31
37
|
@stdin ||= $stdin.read.force_encoding("utf-8")
|
32
38
|
end
|
39
|
+
|
40
|
+
##
|
41
|
+
## Execute commands/scripts in the track
|
42
|
+
##
|
43
|
+
## @param track The track
|
44
|
+
##
|
45
|
+
## @return Resulting STDOUT output
|
46
|
+
##
|
47
|
+
def execute_track(track)
|
48
|
+
if track[:sequence]
|
49
|
+
track[:sequence].each do |cmd|
|
50
|
+
if cmd[:script]
|
51
|
+
script = Script.new(cmd[:script])
|
52
|
+
|
53
|
+
res = script.run
|
54
|
+
elsif cmd[:command]
|
55
|
+
command = Command.new(cmd[:command])
|
56
|
+
|
57
|
+
res = command.run
|
58
|
+
elsif cmd[:filter]
|
59
|
+
filter = Filter.new(cmd[:filter])
|
60
|
+
|
61
|
+
res = filter.process
|
62
|
+
end
|
63
|
+
|
64
|
+
Conductor.stdin = res unless res.nil?
|
65
|
+
end
|
66
|
+
elsif track[:script]
|
67
|
+
script = Script.new(track[:script])
|
68
|
+
|
69
|
+
Conductor.stdin = script.run
|
70
|
+
elsif track[:command]
|
71
|
+
command = Command.new(track[:command])
|
72
|
+
|
73
|
+
Conductor.stdin = command.run
|
74
|
+
elsif track[:filter]
|
75
|
+
filter = Filter.new(track[:filter])
|
76
|
+
|
77
|
+
Conductor.stdin = filter.process
|
78
|
+
end
|
79
|
+
|
80
|
+
Conductor.stdin
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
## Main function to parse conditions and
|
85
|
+
## execute actions. Executes recursively for
|
86
|
+
## sub-tracks.
|
87
|
+
##
|
88
|
+
## @param tracks The tracks to process
|
89
|
+
## @param res The current result
|
90
|
+
## @param condition The current condition
|
91
|
+
##
|
92
|
+
## @return [Array] result, matched condition(s)
|
93
|
+
##
|
94
|
+
def conduct(tracks, res = nil, condition = nil)
|
95
|
+
tracks.each do |track|
|
96
|
+
cond = Condition.new(track[:condition])
|
97
|
+
|
98
|
+
next unless cond.true?
|
99
|
+
|
100
|
+
# Build "matched condition" message
|
101
|
+
title = track[:title] || track[:condition]
|
102
|
+
condition ||= [""]
|
103
|
+
condition << title
|
104
|
+
condition.push(track.key?(:continue) ? " -> " : ", ")
|
105
|
+
|
106
|
+
res = execute_track(track)
|
107
|
+
|
108
|
+
if track[:tracks]
|
109
|
+
ts = track[:tracks]
|
110
|
+
|
111
|
+
res, condition = conduct(ts, res, condition)
|
112
|
+
|
113
|
+
next if res.nil?
|
114
|
+
end
|
115
|
+
|
116
|
+
break unless track[:continue]
|
117
|
+
end
|
118
|
+
|
119
|
+
if res&.strip == Conductor.original_input.strip
|
120
|
+
[nil, "No change in output"]
|
121
|
+
else
|
122
|
+
[res, condition]
|
123
|
+
end
|
124
|
+
end
|
33
125
|
end
|
34
126
|
end
|
data/marked-conductor.gemspec
CHANGED
@@ -9,7 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.email = ["me@brettterpstra.com"]
|
10
10
|
|
11
11
|
spec.summary = "A custom processor manager for Marked 2 (Mac)"
|
12
|
-
spec.description = "Conductor allows easy configuration of multiple scripts
|
12
|
+
spec.description = "Conductor allows easy configuration of multiple scripts" \
|
13
|
+
"which are run as custom pre/processors for Marked based on conditional statements."
|
13
14
|
spec.homepage = "https://github.com/ttscoff/marked-conductor"
|
14
15
|
spec.license = "MIT"
|
15
16
|
spec.required_ruby_version = ">= 2.6.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: marked-conductor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awesome_print
|
@@ -184,7 +184,7 @@ dependencies:
|
|
184
184
|
- - "~>"
|
185
185
|
- !ruby/object:Gem::Version
|
186
186
|
version: 0.5.0
|
187
|
-
description: Conductor allows easy configuration of multiple
|
187
|
+
description: Conductor allows easy configuration of multiple scriptswhich are run
|
188
188
|
as custom pre/processors for Marked based on conditional statements.
|
189
189
|
email:
|
190
190
|
- me@brettterpstra.com
|
@@ -218,7 +218,7 @@ files:
|
|
218
218
|
- lib/conductor/script.rb
|
219
219
|
- lib/conductor/string.rb
|
220
220
|
- lib/conductor/version.rb
|
221
|
-
- lib/conductor/
|
221
|
+
- lib/conductor/yui_compressor.rb
|
222
222
|
- marked-conductor.gemspec
|
223
223
|
- src/_README.md
|
224
224
|
- test.sh
|