motion-markdown-it 0.4.0.3.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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +243 -0
  3. data/lib/motion-markdown-it.rb +71 -0
  4. data/lib/motion-markdown-it/common/entities.rb +1084 -0
  5. data/lib/motion-markdown-it/common/html_blocks.rb +60 -0
  6. data/lib/motion-markdown-it/common/html_re.rb +28 -0
  7. data/lib/motion-markdown-it/common/string.rb +14 -0
  8. data/lib/motion-markdown-it/common/url_schemas.rb +173 -0
  9. data/lib/motion-markdown-it/common/utils.rb +216 -0
  10. data/lib/motion-markdown-it/helpers/parse_link_destination.rb +75 -0
  11. data/lib/motion-markdown-it/helpers/parse_link_label.rb +51 -0
  12. data/lib/motion-markdown-it/helpers/parse_link_title.rb +48 -0
  13. data/lib/motion-markdown-it/index.rb +507 -0
  14. data/lib/motion-markdown-it/parser_block.rb +113 -0
  15. data/lib/motion-markdown-it/parser_core.rb +46 -0
  16. data/lib/motion-markdown-it/parser_inline.rb +121 -0
  17. data/lib/motion-markdown-it/presets/commonmark.rb +76 -0
  18. data/lib/motion-markdown-it/presets/default.rb +42 -0
  19. data/lib/motion-markdown-it/presets/zero.rb +59 -0
  20. data/lib/motion-markdown-it/renderer.rb +286 -0
  21. data/lib/motion-markdown-it/ruler.rb +327 -0
  22. data/lib/motion-markdown-it/rules_block/blockquote.rb +138 -0
  23. data/lib/motion-markdown-it/rules_block/code.rb +35 -0
  24. data/lib/motion-markdown-it/rules_block/fence.rb +94 -0
  25. data/lib/motion-markdown-it/rules_block/heading.rb +56 -0
  26. data/lib/motion-markdown-it/rules_block/hr.rb +45 -0
  27. data/lib/motion-markdown-it/rules_block/html_block.rb +73 -0
  28. data/lib/motion-markdown-it/rules_block/lheading.rb +54 -0
  29. data/lib/motion-markdown-it/rules_block/list.rb +242 -0
  30. data/lib/motion-markdown-it/rules_block/paragraph.rb +51 -0
  31. data/lib/motion-markdown-it/rules_block/reference.rb +161 -0
  32. data/lib/motion-markdown-it/rules_block/state_block.rb +184 -0
  33. data/lib/motion-markdown-it/rules_block/table.rb +161 -0
  34. data/lib/motion-markdown-it/rules_core/block.rb +20 -0
  35. data/lib/motion-markdown-it/rules_core/inline.rb +20 -0
  36. data/lib/motion-markdown-it/rules_core/linkify.rb +138 -0
  37. data/lib/motion-markdown-it/rules_core/normalize.rb +44 -0
  38. data/lib/motion-markdown-it/rules_core/replacements.rb +90 -0
  39. data/lib/motion-markdown-it/rules_core/smartquotes.rb +158 -0
  40. data/lib/motion-markdown-it/rules_core/state_core.rb +20 -0
  41. data/lib/motion-markdown-it/rules_inline/autolink.rb +74 -0
  42. data/lib/motion-markdown-it/rules_inline/backticks.rb +51 -0
  43. data/lib/motion-markdown-it/rules_inline/emphasis.rb +172 -0
  44. data/lib/motion-markdown-it/rules_inline/entity.rb +51 -0
  45. data/lib/motion-markdown-it/rules_inline/escape.rb +55 -0
  46. data/lib/motion-markdown-it/rules_inline/html_inline.rb +49 -0
  47. data/lib/motion-markdown-it/rules_inline/image.rb +158 -0
  48. data/lib/motion-markdown-it/rules_inline/link.rb +153 -0
  49. data/lib/motion-markdown-it/rules_inline/newline.rb +47 -0
  50. data/lib/motion-markdown-it/rules_inline/state_inline.rb +57 -0
  51. data/lib/motion-markdown-it/rules_inline/strikethrough.rb +130 -0
  52. data/lib/motion-markdown-it/rules_inline/text.rb +94 -0
  53. data/lib/motion-markdown-it/token.rb +134 -0
  54. data/lib/motion-markdown-it/version.rb +5 -0
  55. data/spec/motion-markdown-it/bench_mark_spec.rb +44 -0
  56. data/spec/motion-markdown-it/commonmark_spec.rb +16 -0
  57. data/spec/motion-markdown-it/markdown_it_spec.rb +18 -0
  58. data/spec/motion-markdown-it/misc_spec.rb +277 -0
  59. data/spec/motion-markdown-it/ruler_spec.rb +153 -0
  60. data/spec/motion-markdown-it/testgen_helper.rb +68 -0
  61. data/spec/motion-markdown-it/token_spec.rb +17 -0
  62. data/spec/motion-markdown-it/utils_spec.rb +82 -0
  63. data/spec/spec_helper.rb +6 -0
  64. metadata +158 -0
@@ -0,0 +1,286 @@
1
+ # class Renderer
2
+ #
3
+ # Generates HTML from parsed token stream. Each instance has independent
4
+ # copy of rules. Those can be rewritten with ease. Also, you can add new
5
+ # rules if you create plugin and adds new token types.
6
+ #------------------------------------------------------------------------------
7
+ module MarkdownIt
8
+ class Renderer
9
+ include MarkdownIt::Common::Utils
10
+ extend MarkdownIt::Common::Utils
11
+
12
+ # Default Rules
13
+ #------------------------------------------------------------------------------
14
+ def self.code_inline(tokens, idx)
15
+ return '<code>' + escapeHtml(tokens[idx].content) + '</code>'
16
+ end
17
+
18
+ #------------------------------------------------------------------------------
19
+ def self.code_block(tokens, idx)
20
+ return '<pre><code>' + escapeHtml(tokens[idx].content) + "</code></pre>\n"
21
+ end
22
+
23
+ #------------------------------------------------------------------------------
24
+ def self.fence(tokens, idx, options, env, renderer)
25
+ token = tokens[idx]
26
+ langName = ''
27
+
28
+ if !token.info.empty?
29
+ langName = unescapeAll(token.info.strip.split(/\s+/)[0])
30
+ token.attrPush([ 'class', options[:langPrefix] + langName ])
31
+ end
32
+
33
+ if options[:highlight]
34
+ highlighted = options[:highlight].call(token.content, langName) || escapeHtml(token.content)
35
+ else
36
+ highlighted = escapeHtml(token.content)
37
+ end
38
+
39
+ return '<pre><code' + renderer.renderAttrs(token) + '>' + highlighted + "</code></pre>\n"
40
+ end
41
+
42
+ #------------------------------------------------------------------------------
43
+ def self.image(tokens, idx, options, env, renderer)
44
+ token = tokens[idx]
45
+
46
+ # "alt" attr MUST be set, even if empty. Because it's mandatory and
47
+ # should be placed on proper position for tests.
48
+ #
49
+ # Replace content with actual value
50
+
51
+ token.attrs[token.attrIndex('alt')][1] = renderer.renderInlineAsText(token.children, options, env)
52
+
53
+ return renderer.renderToken(tokens, idx, options);
54
+ end
55
+
56
+ #------------------------------------------------------------------------------
57
+ def self.hardbreak(tokens, idx, options)
58
+ return options[:xhtmlOut] ? "<br />\n" : "<br>\n"
59
+ end
60
+ def self.softbreak(tokens, idx, options)
61
+ return options[:breaks] ? (options[:xhtmlOut] ? "<br />\n" : "<br>\n") : "\n"
62
+ end
63
+
64
+ #------------------------------------------------------------------------------
65
+ def self.text(tokens, idx)
66
+ return escapeHtml(tokens[idx].content)
67
+ end
68
+
69
+ #------------------------------------------------------------------------------
70
+ def self.html_block(tokens, idx)
71
+ return tokens[idx].content
72
+ end
73
+ def self.html_inline(tokens, idx)
74
+ return tokens[idx].content
75
+ end
76
+
77
+
78
+ # new Renderer()
79
+ #
80
+ # Creates new [[Renderer]] instance and fill [[Renderer#rules]] with defaults.
81
+ #------------------------------------------------------------------------------
82
+ def initialize
83
+ @default_rules = {
84
+ 'code_inline' => lambda {|tokens, idx, options, env, renderer| Renderer.code_inline(tokens, idx)},
85
+ 'code_block' => lambda {|tokens, idx, options, env, renderer| Renderer.code_block(tokens, idx)},
86
+ 'fence' => lambda {|tokens, idx, options, env, renderer| Renderer.fence(tokens, idx, options, env, renderer)},
87
+ 'image' => lambda {|tokens, idx, options, env, renderer| Renderer.image(tokens, idx, options, env, renderer)},
88
+ 'hardbreak' => lambda {|tokens, idx, options, env, renderer| Renderer.hardbreak(tokens, idx, options)},
89
+ 'softbreak' => lambda {|tokens, idx, options, env, renderer| Renderer.softbreak(tokens, idx, options)},
90
+ 'text' => lambda {|tokens, idx, options, env, renderer| Renderer.text(tokens, idx)},
91
+ 'html_block' => lambda {|tokens, idx, options, env, renderer| Renderer.html_block(tokens, idx)},
92
+ 'html_inline' => lambda {|tokens, idx, options, env, renderer| Renderer.html_inline(tokens, idx)}
93
+ }
94
+
95
+ # Renderer#rules -> Object
96
+ #
97
+ # Contains render rules for tokens. Can be updated and extended.
98
+ #
99
+ # ##### Example
100
+ #
101
+ # ```javascript
102
+ # var md = require('markdown-it')();
103
+ #
104
+ # md.renderer.rules.strong_open = function () { return '<b>'; };
105
+ # md.renderer.rules.strong_close = function () { return '</b>'; };
106
+ #
107
+ # var result = md.renderInline(...);
108
+ # ```
109
+ #
110
+ # Each rule is called as independed static function with fixed signature:
111
+ #
112
+ # ```javascript
113
+ # function my_token_render(tokens, idx, options, env, renderer) {
114
+ # // ...
115
+ # return renderedHTML;
116
+ # }
117
+ # ```
118
+ #
119
+ # See [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js)
120
+ # for more details and examples.
121
+ @rules = assign({}, @default_rules)
122
+ end
123
+
124
+
125
+ # Renderer.renderAttrs(token) -> String
126
+ #
127
+ # Render token attributes to string.
128
+ #------------------------------------------------------------------------------
129
+ def renderAttrs(token)
130
+ return '' if !token.attrs
131
+
132
+ result = ''
133
+ 0.upto(token.attrs.length - 1) do |i|
134
+ result += ' ' + escapeHtml(token.attrs[i][0]) + '="' + escapeHtml(token.attrs[i][1].to_s) + '"'
135
+ end
136
+
137
+ return result
138
+ end
139
+
140
+
141
+ # Renderer.renderToken(tokens, idx, options) -> String
142
+ # - tokens (Array): list of tokens
143
+ # - idx (Numbed): token index to render
144
+ # - options (Object): params of parser instance
145
+ #
146
+ # Default token renderer. Can be overriden by custom function
147
+ # in [[Renderer#rules]].
148
+ #------------------------------------------------------------------------------
149
+ def renderToken(tokens, idx, options, env = nil, renderer = nil)
150
+ result = ''
151
+ needLf = false
152
+ token = tokens[idx]
153
+
154
+ # Tight list paragraphs
155
+ return '' if token.hidden
156
+
157
+ # Insert a newline between hidden paragraph and subsequent opening
158
+ # block-level tag.
159
+ #
160
+ # For example, here we should insert a newline before blockquote:
161
+ # - a
162
+ # >
163
+ #
164
+ if token.block && token.nesting != -1 && idx && tokens[idx - 1].hidden
165
+ result += "\n"
166
+ end
167
+
168
+ # Add token name, e.g. `<img`
169
+ result += (token.nesting == -1 ? '</' : '<') + token.tag
170
+
171
+ # Encode attributes, e.g. `<img src="foo"`
172
+ result += renderAttrs(token)
173
+
174
+ # Add a slash for self-closing tags, e.g. `<img src="foo" /`
175
+ if token.nesting == 0 && options[:xhtmlOut]
176
+ result += ' /'
177
+ end
178
+
179
+ # Check if we need to add a newline after this tag
180
+ if token.block
181
+ needLf = true
182
+
183
+ if token.nesting == 1
184
+ if idx + 1 < tokens.length
185
+ nextToken = tokens[idx + 1]
186
+
187
+ if nextToken.type == 'inline' || nextToken.hidden
188
+ # Block-level tag containing an inline tag.
189
+ #
190
+ needLf = false
191
+
192
+ elsif nextToken.nesting == -1 && nextToken.tag == token.tag
193
+ # Opening tag + closing tag of the same type. E.g. `<li></li>`.
194
+ #
195
+ needLf = false
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ result += needLf ? ">\n" : '>'
202
+
203
+ return result
204
+ end
205
+
206
+
207
+ # Renderer.renderInline(tokens, options, env) -> String
208
+ # - tokens (Array): list on block tokens to renter
209
+ # - options (Object): params of parser instance
210
+ # - env (Object): additional data from parsed input (references, for example)
211
+ #
212
+ # The same as [[Renderer.render]], but for single token of `inline` type.
213
+ #------------------------------------------------------------------------------
214
+ def renderInline(tokens, options, env)
215
+ result = ''
216
+ rules = @rules
217
+
218
+ 0.upto(tokens.length - 1) do |i|
219
+ type = tokens[i].type
220
+
221
+ if rules[type] != nil
222
+ result += rules[type].call(tokens, i, options, env, self)
223
+ else
224
+ result += renderToken(tokens, i, options)
225
+ end
226
+ end
227
+
228
+ return result;
229
+ end
230
+
231
+
232
+ # internal
233
+ # Renderer.renderInlineAsText(tokens, options, env) -> String
234
+ # - tokens (Array): list on block tokens to renter
235
+ # - options (Object): params of parser instance
236
+ # - env (Object): additional data from parsed input (references, for example)
237
+ #
238
+ # Special kludge for image `alt` attributes to conform CommonMark spec.
239
+ # Don't try to use it! Spec requires to show `alt` content with stripped markup,
240
+ # instead of simple escaping.
241
+ #------------------------------------------------------------------------------
242
+ def renderInlineAsText(tokens, options, env)
243
+ result = ''
244
+ rules = @rules
245
+
246
+ 0.upto(tokens.length - 1) do |i|
247
+ if tokens[i].type == 'text'
248
+ result += rules['text'].call(tokens, i, options, env, self)
249
+ elsif tokens[i].type == 'image'
250
+ result += renderInlineAsText(tokens[i].children, options, env)
251
+ end
252
+ end
253
+
254
+ return result
255
+ end
256
+
257
+
258
+ # Renderer.render(tokens, options, env) -> String
259
+ # - tokens (Array): list on block tokens to renter
260
+ # - options (Object): params of parser instance
261
+ # - env (Object): additional data from parsed input (references, for example)
262
+ #
263
+ # Takes token stream and generates HTML. Probably, you will never need to call
264
+ # this method directly.
265
+ #------------------------------------------------------------------------------
266
+ def render(tokens, options, env)
267
+ result = ''
268
+ rules = @rules
269
+
270
+ 0.upto(tokens.length - 1) do |i|
271
+ type = tokens[i].type
272
+
273
+ if type == 'inline'
274
+ result += renderInline(tokens[i].children, options, env)
275
+ elsif rules[type] != nil
276
+ result += rules[tokens[i].type].call(tokens, i, options, env, self)
277
+ else
278
+ result += renderToken(tokens, i, options)
279
+ end
280
+ end
281
+
282
+ return result
283
+ end
284
+
285
+ end
286
+ end
@@ -0,0 +1,327 @@
1
+ # * class Ruler
2
+ # *
3
+ # * Helper class, used by [[MarkdownIt#core]], [[MarkdownIt#block]] and
4
+ # * [[MarkdownIt#inline]] to manage sequences of functions (rules):
5
+ # *
6
+ # * - keep rules in defined order
7
+ # * - assign the name to each rule
8
+ # * - enable/disable rules
9
+ # * - add/replace rules
10
+ # * - allow assign rules to additional named chains (in the same)
11
+ # * - cacheing lists of active rules
12
+ # *
13
+ # * You will not need use this class directly until write plugins. For simple
14
+ # * rules control use [[MarkdownIt.disable]], [[MarkdownIt.enable]] and
15
+ # * [[MarkdownIt.use]].
16
+ #------------------------------------------------------------------------------
17
+
18
+ module MarkdownIt
19
+ class Ruler
20
+
21
+ def initialize
22
+ # // List of added rules. Each element is:
23
+ # //
24
+ # // {
25
+ # // name: XXX,
26
+ # // enabled: Boolean,
27
+ # // fn: Function(),
28
+ # // alt: [ name2, name3 ]
29
+ # // }
30
+ @__rules__ = []
31
+
32
+ # // Cached rule chains.
33
+ # //
34
+ # // First level - chain name, '' for default.
35
+ # // Second level - diginal anchor for fast filtering by charcodes.
36
+ @__cache__ = nil
37
+ end
38
+
39
+ #------------------------------------------------------------------------------
40
+ # // Helper methods, should not be used directly
41
+
42
+
43
+ # // Find rule index by name
44
+ #------------------------------------------------------------------------------
45
+ def __find__(name)
46
+ @__rules__.each_with_index do |rule, index|
47
+ return index if (rule[:name] == name)
48
+ end
49
+ return -1
50
+ end
51
+
52
+
53
+ # // Build rules lookup cache
54
+ #------------------------------------------------------------------------------
55
+ def __compile__
56
+ chains = [ '' ]
57
+
58
+ # // collect unique names
59
+ @__rules__.each do |rule|
60
+ next if !rule[:enabled]
61
+
62
+ rule[:alt].each do |altName|
63
+ if !chains.include?(altName)
64
+ chains.push(altName)
65
+ end
66
+ end
67
+ end
68
+
69
+ @__cache__ = {}
70
+
71
+ chains.each do |chain|
72
+ @__cache__[chain] = []
73
+ @__rules__.each do |rule|
74
+ next if !rule[:enabled]
75
+ next if (chain && !rule[:alt].include?(chain))
76
+
77
+ @__cache__[chain].push(rule[:fn])
78
+ end
79
+ end
80
+ end
81
+
82
+
83
+ # * Ruler.at(name, fn [, options])
84
+ # * - name (String): rule name to replace.
85
+ # * - fn (Function): new rule function.
86
+ # * - options (Object): new rule options (not mandatory).
87
+ # *
88
+ # * Replace rule by name with new function & options. Throws error if name not
89
+ # * found.
90
+ # *
91
+ # * ##### Options:
92
+ # *
93
+ # * - __alt__ - array with names of "alternate" chains.
94
+ # *
95
+ # * ##### Example
96
+ # *
97
+ # * Replace existing typorgapher replacement rule with new one:
98
+ # *
99
+ # * ```javascript
100
+ # * var md = require('markdown-it')();
101
+ # *
102
+ # * md.core.ruler.at('replacements', function replace(state) {
103
+ # * //...
104
+ # * });
105
+ # * ```
106
+ #------------------------------------------------------------------------------
107
+ def at(name, fn, opt = {})
108
+ index = __find__(name)
109
+
110
+ raise(StandardError, "Parser rule not found: #{name}") if index == -1
111
+
112
+ @__rules__[index][:fn] = fn
113
+ @__rules__[index][:alt] = opt[:alt] || ['']
114
+ @__cache__ = nil
115
+ end
116
+
117
+
118
+ # * Ruler.before(beforeName, ruleName, fn [, options])
119
+ # * - beforeName (String): new rule will be added before this one.
120
+ # * - ruleName (String): name of added rule.
121
+ # * - fn (Function): rule function.
122
+ # * - options (Object): rule options (not mandatory).
123
+ # *
124
+ # * Add new rule to chain before one with given name. See also
125
+ # * [[Ruler.after]], [[Ruler.push]].
126
+ # *
127
+ # * ##### Options:
128
+ # *
129
+ # * - __alt__ - array with names of "alternate" chains.
130
+ # *
131
+ # * ##### Example
132
+ # *
133
+ # * ```javascript
134
+ # * var md = require('markdown-it')();
135
+ # *
136
+ # * md.block.ruler.before('paragraph', 'my_rule', function replace(state) {
137
+ # * //...
138
+ # * });
139
+ # * ```
140
+ #------------------------------------------------------------------------------
141
+ def before(beforeName, ruleName, fn, opt = {})
142
+ index = __find__(beforeName)
143
+
144
+ raise(StandardError, "Parser rule not found: #{beforeName}") if index == -1
145
+
146
+ @__rules__.insert(index, {
147
+ name: ruleName,
148
+ enabled: true,
149
+ fn: fn,
150
+ alt: (opt[:alt] || [''])
151
+ })
152
+
153
+ @__cache__ = nil
154
+ end
155
+
156
+
157
+ # * Ruler.after(afterName, ruleName, fn [, options])
158
+ # * - afterName (String): new rule will be added after this one.
159
+ # * - ruleName (String): name of added rule.
160
+ # * - fn (Function): rule function.
161
+ # * - options (Object): rule options (not mandatory).
162
+ # *
163
+ # * Add new rule to chain after one with given name. See also
164
+ # * [[Ruler.before]], [[Ruler.push]].
165
+ # *
166
+ # * ##### Options:
167
+ # *
168
+ # * - __alt__ - array with names of "alternate" chains.
169
+ # *
170
+ # * ##### Example
171
+ # *
172
+ # * ```javascript
173
+ # * var md = require('markdown-it')();
174
+ # *
175
+ # * md.inline.ruler.after('text', 'my_rule', function replace(state) {
176
+ # * //...
177
+ # * });
178
+ # * ```
179
+ #------------------------------------------------------------------------------
180
+ def after(afterName, ruleName, fn, opt = {})
181
+ index = __find__(afterName)
182
+
183
+ raise(StandardError, "Parser rule not found: #{afterName}") if index == -1
184
+
185
+ @__rules__.insert(index + 1, {
186
+ name: ruleName,
187
+ enabled: true,
188
+ fn: fn,
189
+ alt: (opt[:alt] || [''])
190
+ })
191
+
192
+ @__cache__ = nil
193
+ end
194
+
195
+ # * Ruler.push(ruleName, fn [, options])
196
+ # * - ruleName (String): name of added rule.
197
+ # * - fn (Function): rule function.
198
+ # * - options (Object): rule options (not mandatory).
199
+ # *
200
+ # * Push new rule to the end of chain. See also
201
+ # * [[Ruler.before]], [[Ruler.after]].
202
+ # *
203
+ # * ##### Options:
204
+ # *
205
+ # * - __alt__ - array with names of "alternate" chains.
206
+ # *
207
+ # * ##### Example
208
+ # *
209
+ # * ```javascript
210
+ # * var md = require('markdown-it')();
211
+ # *
212
+ # * md.core.ruler.push('emphasis', 'my_rule', function replace(state) {
213
+ # * //...
214
+ # * });
215
+ # * ```
216
+ #------------------------------------------------------------------------------
217
+ def push(ruleName, fn, opt = {})
218
+ @__rules__.push({
219
+ name: ruleName,
220
+ enabled: true,
221
+ fn: fn,
222
+ alt: (opt[:alt] ? [''] + opt[:alt] : [''])
223
+ })
224
+ @__cache__ = nil
225
+ end
226
+
227
+
228
+ # * Ruler.enable(list [, ignoreInvalid]) -> Array
229
+ # * - list (String|Array): list of rule names to enable.
230
+ # * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
231
+ # *
232
+ # * Enable rules with given names. If any rule name not found - throw Error.
233
+ # * Errors can be disabled by second param.
234
+ # *
235
+ # * Returns list of found rule names (if no exception happened).
236
+ # *
237
+ # * See also [[Ruler.disable]], [[Ruler.enableOnly]].
238
+ #------------------------------------------------------------------------------
239
+ def enable(list, ignoreInvalid = false)
240
+ list = [ list ] if !list.is_a?(Array)
241
+ result = []
242
+
243
+ # // Search by name and enable
244
+ list.each do |name|
245
+ idx = __find__(name)
246
+
247
+ if idx < 0
248
+ next if ignoreInvalid
249
+ raise(StandardError, "Rules manager: invalid rule name #{name}")
250
+ end
251
+ @__rules__[idx][:enabled] = true
252
+ result.push(name)
253
+ end
254
+
255
+ @__cache__ = nil
256
+ return result
257
+ end
258
+
259
+
260
+ # * Ruler.enableOnly(list [, ignoreInvalid])
261
+ # * - list (String|Array): list of rule names to enable (whitelist).
262
+ # * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
263
+ # *
264
+ # * Enable rules with given names, and disable everything else. If any rule name
265
+ # * not found - throw Error. Errors can be disabled by second param.
266
+ # *
267
+ # * See also [[Ruler.disable]], [[Ruler.enable]].
268
+ #------------------------------------------------------------------------------
269
+ def enableOnly(list, ignoreInvalid = false)
270
+ list = [ list ] if !list.is_a?(Array)
271
+
272
+ @__rules__.each { |rule| rule[:enabled] = false }
273
+
274
+ enable(list, ignoreInvalid)
275
+ end
276
+
277
+
278
+ # * Ruler.disable(list [, ignoreInvalid]) -> Array
279
+ # * - list (String|Array): list of rule names to disable.
280
+ # * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
281
+ # *
282
+ # * Disable rules with given names. If any rule name not found - throw Error.
283
+ # * Errors can be disabled by second param.
284
+ # *
285
+ # * Returns list of found rule names (if no exception happened).
286
+ # *
287
+ # * See also [[Ruler.enable]], [[Ruler.enableOnly]].
288
+ #------------------------------------------------------------------------------
289
+ def disable(list, ignoreInvalid = false)
290
+ list = [ list ] if !list.is_a?(Array)
291
+ result = []
292
+
293
+ # // Search by name and disable
294
+ list.each do |name|
295
+ idx = __find__(name)
296
+
297
+ if idx < 0
298
+ next if ignoreInvalid
299
+ raise(StandardError, "Rules manager: invalid rule name #{name}")
300
+ end
301
+ @__rules__[idx][:enabled] = false
302
+ result.push(name)
303
+ end
304
+
305
+ @__cache__ = nil
306
+ return result
307
+ end
308
+
309
+
310
+ # * Ruler.getRules(chainName) -> Array
311
+ # *
312
+ # * Return array of active functions (rules) for given chain name. It analyzes
313
+ # * rules configuration, compiles caches if not exists and returns result.
314
+ # *
315
+ # * Default chain name is `''` (empty string). It can't be skipped. That's
316
+ # * done intentionally, to keep signature monomorphic for high speed.
317
+ #------------------------------------------------------------------------------
318
+ def getRules(chainName)
319
+ if @__cache__ == nil
320
+ __compile__
321
+ end
322
+
323
+ # // Chain can be empty, if rules disabled. But we still have to return Array.
324
+ return @__cache__[chainName] || []
325
+ end
326
+ end
327
+ end