motion-markdown-it 0.4.0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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