canon 0.1.6 → 0.1.7

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 (136) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +163 -67
  3. data/README.adoc +400 -7
  4. data/docs/Gemfile +9 -0
  5. data/docs/INDEX.adoc +99 -182
  6. data/docs/_config.yml +100 -0
  7. data/docs/advanced/diff-classification.adoc +547 -0
  8. data/docs/advanced/diff-pipeline.adoc +358 -0
  9. data/docs/advanced/index.adoc +214 -0
  10. data/docs/advanced/semantic-diff-report.adoc +390 -0
  11. data/docs/{VERBOSE.adoc → advanced/verbose-mode-architecture.adoc} +51 -53
  12. data/docs/features/diff-formatting/algorithm-specific-output.adoc +533 -0
  13. data/docs/{CHARACTER_VISUALIZATION.adoc → features/diff-formatting/character-visualization.adoc} +23 -62
  14. data/docs/features/diff-formatting/colors-and-symbols.adoc +606 -0
  15. data/docs/features/diff-formatting/context-and-grouping.adoc +490 -0
  16. data/docs/features/diff-formatting/display-filtering.adoc +472 -0
  17. data/docs/features/diff-formatting/index.adoc +140 -0
  18. data/docs/features/environment-configuration/index.adoc +327 -0
  19. data/docs/features/environment-configuration/override-system.adoc +436 -0
  20. data/docs/features/environment-configuration/size-limits.adoc +273 -0
  21. data/docs/features/index.adoc +173 -0
  22. data/docs/features/input-validation/index.adoc +521 -0
  23. data/docs/features/match-options/algorithm-specific-behavior.adoc +365 -0
  24. data/docs/features/match-options/html-policies.adoc +312 -0
  25. data/docs/features/match-options/index.adoc +621 -0
  26. data/docs/getting-started/index.adoc +83 -0
  27. data/docs/getting-started/quick-start.adoc +76 -0
  28. data/docs/guides/choosing-configuration.adoc +689 -0
  29. data/docs/guides/index.adoc +181 -0
  30. data/docs/{CLI.adoc → interfaces/cli/index.adoc} +18 -13
  31. data/docs/interfaces/index.adoc +101 -0
  32. data/docs/{RSPEC.adoc → interfaces/rspec/index.adoc} +242 -31
  33. data/docs/{RUBY_API.adoc → interfaces/ruby-api/index.adoc} +118 -16
  34. data/docs/lychee.toml +65 -0
  35. data/docs/reference/cli-options.adoc +418 -0
  36. data/docs/reference/environment-variables.adoc +375 -0
  37. data/docs/reference/index.adoc +204 -0
  38. data/docs/reference/options-across-interfaces.adoc +417 -0
  39. data/docs/understanding/algorithms/dom-diff.adoc +389 -0
  40. data/docs/understanding/algorithms/index.adoc +314 -0
  41. data/docs/understanding/algorithms/semantic-tree-diff.adoc +533 -0
  42. data/docs/understanding/architecture.adoc +447 -0
  43. data/docs/understanding/comparison-pipeline.adoc +317 -0
  44. data/docs/understanding/formats/html.adoc +380 -0
  45. data/docs/understanding/formats/index.adoc +261 -0
  46. data/docs/understanding/formats/json.adoc +390 -0
  47. data/docs/understanding/formats/xml.adoc +366 -0
  48. data/docs/understanding/formats/yaml.adoc +504 -0
  49. data/docs/understanding/index.adoc +130 -0
  50. data/lib/canon/cli.rb +42 -1
  51. data/lib/canon/commands/diff_command.rb +108 -23
  52. data/lib/canon/comparison/compare_profile.rb +101 -0
  53. data/lib/canon/comparison/comparison_result.rb +41 -2
  54. data/lib/canon/comparison/html_comparator.rb +292 -71
  55. data/lib/canon/comparison/html_compare_profile.rb +117 -0
  56. data/lib/canon/comparison/match_options.rb +42 -4
  57. data/lib/canon/comparison/strategies/base_match_strategy.rb +99 -0
  58. data/lib/canon/comparison/strategies/match_strategy_factory.rb +74 -0
  59. data/lib/canon/comparison/strategies/semantic_tree_match_strategy.rb +220 -0
  60. data/lib/canon/comparison/xml_comparator.rb +695 -91
  61. data/lib/canon/comparison.rb +207 -2
  62. data/lib/canon/config/env_provider.rb +71 -0
  63. data/lib/canon/config/env_schema.rb +58 -0
  64. data/lib/canon/config/override_resolver.rb +55 -0
  65. data/lib/canon/config/type_converter.rb +59 -0
  66. data/lib/canon/config.rb +158 -29
  67. data/lib/canon/data_model.rb +29 -0
  68. data/lib/canon/diff/diff_classifier.rb +74 -14
  69. data/lib/canon/diff/diff_context_builder.rb +41 -0
  70. data/lib/canon/diff/diff_line.rb +18 -2
  71. data/lib/canon/diff/diff_node.rb +18 -3
  72. data/lib/canon/diff/diff_node_mapper.rb +71 -12
  73. data/lib/canon/diff/formatting_detector.rb +53 -0
  74. data/lib/canon/diff_formatter/by_line/base_formatter.rb +60 -5
  75. data/lib/canon/diff_formatter/by_line/html_formatter.rb +68 -16
  76. data/lib/canon/diff_formatter/by_line/json_formatter.rb +0 -37
  77. data/lib/canon/diff_formatter/by_line/simple_formatter.rb +0 -42
  78. data/lib/canon/diff_formatter/by_line/xml_formatter.rb +116 -31
  79. data/lib/canon/diff_formatter/by_line/yaml_formatter.rb +0 -37
  80. data/lib/canon/diff_formatter/by_object/base_formatter.rb +126 -19
  81. data/lib/canon/diff_formatter/by_object/xml_formatter.rb +30 -1
  82. data/lib/canon/diff_formatter/debug_output.rb +7 -1
  83. data/lib/canon/diff_formatter/diff_detail_formatter.rb +674 -57
  84. data/lib/canon/diff_formatter/legend.rb +42 -0
  85. data/lib/canon/diff_formatter.rb +78 -9
  86. data/lib/canon/errors.rb +56 -0
  87. data/lib/canon/formatters/html_formatter_base.rb +35 -1
  88. data/lib/canon/formatters/json_formatter.rb +3 -0
  89. data/lib/canon/formatters/yaml_formatter.rb +3 -0
  90. data/lib/canon/html/data_model.rb +229 -0
  91. data/lib/canon/html.rb +9 -0
  92. data/lib/canon/options/cli_generator.rb +70 -0
  93. data/lib/canon/options/registry.rb +234 -0
  94. data/lib/canon/rspec_matchers.rb +34 -13
  95. data/lib/canon/tree_diff/adapters/html_adapter.rb +316 -0
  96. data/lib/canon/tree_diff/adapters/json_adapter.rb +204 -0
  97. data/lib/canon/tree_diff/adapters/xml_adapter.rb +285 -0
  98. data/lib/canon/tree_diff/adapters/yaml_adapter.rb +213 -0
  99. data/lib/canon/tree_diff/core/attribute_comparator.rb +84 -0
  100. data/lib/canon/tree_diff/core/matching.rb +241 -0
  101. data/lib/canon/tree_diff/core/node_signature.rb +164 -0
  102. data/lib/canon/tree_diff/core/node_weight.rb +135 -0
  103. data/lib/canon/tree_diff/core/tree_node.rb +450 -0
  104. data/lib/canon/tree_diff/matchers/hash_matcher.rb +258 -0
  105. data/lib/canon/tree_diff/matchers/similarity_matcher.rb +168 -0
  106. data/lib/canon/tree_diff/matchers/structural_propagator.rb +242 -0
  107. data/lib/canon/tree_diff/matchers/universal_matcher.rb +220 -0
  108. data/lib/canon/tree_diff/operation_converter.rb +631 -0
  109. data/lib/canon/tree_diff/operations/operation.rb +92 -0
  110. data/lib/canon/tree_diff/operations/operation_detector.rb +626 -0
  111. data/lib/canon/tree_diff/tree_diff_integrator.rb +140 -0
  112. data/lib/canon/tree_diff.rb +33 -0
  113. data/lib/canon/validators/json_validator.rb +3 -1
  114. data/lib/canon/validators/yaml_validator.rb +3 -1
  115. data/lib/canon/version.rb +1 -1
  116. data/lib/canon/xml/data_model.rb +22 -23
  117. data/lib/canon/xml/element_matcher.rb +128 -20
  118. data/lib/canon/xml/namespace_helper.rb +110 -0
  119. data/lib/canon.rb +3 -0
  120. metadata +81 -23
  121. data/_config.yml +0 -116
  122. data/docs/ADVANCED_TOPICS.adoc +0 -20
  123. data/docs/BASIC_USAGE.adoc +0 -16
  124. data/docs/CUSTOMIZING_BEHAVIOR.adoc +0 -19
  125. data/docs/DIFF_ARCHITECTURE.adoc +0 -435
  126. data/docs/DIFF_FORMATTING.adoc +0 -540
  127. data/docs/FORMATS.adoc +0 -447
  128. data/docs/INPUT_VALIDATION.adoc +0 -477
  129. data/docs/MATCH_ARCHITECTURE.adoc +0 -463
  130. data/docs/MATCH_OPTIONS.adoc +0 -719
  131. data/docs/MODES.adoc +0 -432
  132. data/docs/NORMATIVE_INFORMATIVE_DIFFS.adoc +0 -219
  133. data/docs/OPTIONS.adoc +0 -1387
  134. data/docs/PREPROCESSING.adoc +0 -491
  135. data/docs/SEMANTIC_DIFF_REPORT.adoc +0 -528
  136. data/docs/UNDERSTANDING_CANON.adoc +0 -17
@@ -0,0 +1,417 @@
1
+ ---
2
+ layout: default
3
+ title: Options Across Interfaces
4
+ parent: Reference
5
+ nav_order: 5
6
+ ---
7
+
8
+ :toc:
9
+ :toclevels: 3
10
+
11
+ == Purpose
12
+
13
+ Canon provides a unified option system across all three interfaces: CLI, Ruby API, and RSpec. Each option can be expressed in different ways depending on the interface, but they all control the same underlying behavior.
14
+
15
+ This reference shows how to express the same configuration across all interfaces, making it easy to:
16
+
17
+ * Translate between interfaces
18
+ * Understand option equivalence
19
+ * Choose the right interface for your needs
20
+ * Maintain consistent configuration
21
+
22
+ == Option Equivalence Table
23
+
24
+ The following table shows how major Canon options are expressed in each interface:
25
+
26
+ === Layer 1: Preprocessing Options
27
+
28
+ [cols="2,2,3,3,3"]
29
+ |===
30
+ |Option |CLI Flag |Ruby API |RSpec Config |ENV Variable
31
+
32
+ |Preprocessing
33
+ |`--preprocessing normalize`
34
+ |`preprocessing: :normalize`
35
+ |`config.canon.xml.preprocessing = :normalize`
36
+ |`CANON_PREPROCESSING=normalize`
37
+ |===
38
+
39
+ Preprocessing values: `none`, `c14n`, `normalize`, `format`
40
+
41
+ === Layer 2: Algorithm Selection
42
+
43
+ [cols="2,2,3,3,3"]
44
+ |===
45
+ |Option |CLI Flag |Ruby API |RSpec Config |ENV Variable
46
+
47
+ |Diff Algorithm
48
+ |`--diff-algorithm semantic`
49
+ |`diff_algorithm: :semantic`
50
+ |`config.canon.xml.diff.algorithm = :semantic`
51
+ |`CANON_ALGORITHM=semantic`
52
+
53
+ |Diff Mode
54
+ |`--diff-mode by_object`
55
+ |`diff_mode: :by_object`
56
+ |`config.canon.xml.diff.mode = :by_object`
57
+ |`CANON_MODE=by_object`
58
+ |===
59
+
60
+ Algorithm values: `dom`, `semantic` +
61
+ Diff mode values: `by_line`, `by_object`
62
+
63
+ === Layer 3: Match Options
64
+
65
+ ==== Match Profile
66
+
67
+ [cols="2,2,3,3,3"]
68
+ |===
69
+ |Option |CLI Flag |Ruby API |RSpec Config |ENV Variable
70
+
71
+ |Match Profile
72
+ |`--match-profile strict`
73
+ |`match_profile: :strict`
74
+ |`config.canon.xml.match.profile = :strict`
75
+ |`CANON_PROFILE=strict`
76
+ |===
77
+
78
+ Profile values: `strict`, `rendered`, `spec_friendly`, `content_only`
79
+
80
+ ==== Match Dimensions (All Formats)
81
+
82
+ [cols="2,2,3,3,3"]
83
+ |===
84
+ |Dimension |CLI Flag |Ruby API |RSpec Config |ENV Variable
85
+
86
+ |Text Content
87
+ |`--text-content normalize`
88
+ |`match: { text_content: :normalize }`
89
+ |`config.canon.xml.match.options = { text_content: :normalize }`
90
+ |`CANON_TEXT_CONTENT=normalize`
91
+
92
+ |Structural Whitespace
93
+ |`--structural-whitespace ignore`
94
+ |`match: { structural_whitespace: :ignore }`
95
+ |`config.canon.xml.match.options = { structural_whitespace: :ignore }`
96
+ |`CANON_STRUCTURAL_WHITESPACE=ignore`
97
+
98
+ |Comments
99
+ |`--comments ignore`
100
+ |`match: { comments: :ignore }`
101
+ |`config.canon.xml.match.options = { comments: :ignore }`
102
+ |`CANON_COMMENTS=ignore`
103
+
104
+ |Element Structure
105
+ |`--element-structure strict`
106
+ |`match: { element_structure: :strict }`
107
+ |`config.canon.xml.match.options = { element_structure: :strict }`
108
+ |`CANON_ELEMENT_STRUCTURE=strict`
109
+
110
+ |Element Position
111
+ |`--element-position ignore`
112
+ |`match: { element_position: :ignore }`
113
+ |`config.canon.xml.match.options = { element_position: :ignore }`
114
+ |`CANON_ELEMENT_POSITION=ignore`
115
+
116
+ |Element Hierarchy
117
+ |`--element-hierarchy strict`
118
+ |`match: { element_hierarchy: :strict }`
119
+ |`config.canon.xml.match.options = { element_hierarchy: :strict }`
120
+ |`CANON_ELEMENT_HIERARCHY=strict`
121
+ |===
122
+
123
+ Values: `strict`, `normalize`, `ignore` (or `strict`, `ignore` for structure/position/hierarchy)
124
+
125
+ ==== XML/HTML-Specific Match Dimensions
126
+
127
+ [cols="2,2,3,3,3"]
128
+ |===
129
+ |Dimension |CLI Flag |Ruby API |RSpec Config |ENV Variable
130
+
131
+ |Attribute Whitespace
132
+ |`--attribute-whitespace normalize`
133
+ |`match: { attribute_whitespace: :normalize }`
134
+ |`config.canon.xml.match.options = { attribute_whitespace: :normalize }`
135
+ |`CANON_ATTRIBUTE_WHITESPACE=normalize`
136
+
137
+ |Attribute Order
138
+ |`--attribute-order ignore`
139
+ |`match: { attribute_order: :ignore }`
140
+ |`config.canon.xml.match.options = { attribute_order: :ignore }`
141
+ |`CANON_ATTRIBUTE_ORDER=ignore`
142
+
143
+ |Attribute Values
144
+ |`--attribute-values normalize`
145
+ |`match: { attribute_values: :normalize }`
146
+ |`config.canon.xml.match.options = { attribute_values: :normalize }`
147
+ |`CANON_ATTRIBUTE_VALUES=normalize`
148
+ |===
149
+
150
+ Values: `strict`, `normalize`, `ignore` (or `strict`, `ignore` for order)
151
+
152
+ ==== JSON/YAML-Specific Match Dimensions
153
+
154
+ [cols="2,2,3,3,3"]
155
+ |===
156
+ |Dimension |CLI Flag |Ruby API |RSpec Config |ENV Variable
157
+
158
+ |Key Order
159
+ |`--key-order ignore`
160
+ |`match: { key_order: :ignore }`
161
+ |`config.canon.json.match.options = { key_order: :ignore }`
162
+ |`CANON_KEY_ORDER=ignore`
163
+ |===
164
+
165
+ Values: `strict`, `ignore`
166
+
167
+ === Layer 4: Diff Formatting Options
168
+
169
+ [cols="2,2,3,3,3"]
170
+ |===
171
+ |Option |CLI Flag |Ruby API |RSpec Config |ENV Variable
172
+
173
+ |Use Color
174
+ |`--color` / `--no-color`
175
+ |`color: true` / `color: false`
176
+ |`config.canon.xml.diff.use_color = true`
177
+ |`CANON_USE_COLOR=true`
178
+
179
+ |Verbose
180
+ |`--verbose` / `-v`
181
+ |`verbose: true`
182
+ |`config.canon.xml.diff.verbose_diff = true`
183
+ |`CANON_VERBOSE_DIFF=true`
184
+
185
+ |Context Lines
186
+ |`--context-lines 5`
187
+ |`context_lines: 5`
188
+ |`config.canon.xml.diff.context_lines = 5`
189
+ |`CANON_CONTEXT_LINES=5`
190
+
191
+ |Grouping Lines
192
+ |`--diff-grouping-lines 15`
193
+ |`diff_grouping_lines: 15`
194
+ |`config.canon.xml.diff.grouping_lines = 15`
195
+ |`CANON_GROUPING_LINES=15`
196
+ |===
197
+
198
+ === Size Limit Options
199
+
200
+ [cols="2,2,3,3,3"]
201
+ |===
202
+ |Option |CLI Flag |Ruby API |RSpec Config |ENV Variable
203
+
204
+ |Max File Size
205
+ |N/A
206
+ |N/A (config only)
207
+ |`config.canon.xml.diff.max_file_size = 10485760`
208
+ |`CANON_MAX_FILE_SIZE=10485760`
209
+
210
+ |Max Node Count
211
+ |N/A
212
+ |N/A (config only)
213
+ |`config.canon.xml.diff.max_node_count = 50000`
214
+ |`CANON_MAX_NODE_COUNT=50000`
215
+
216
+ |Max Diff Lines
217
+ |N/A
218
+ |N/A (config only)
219
+ |`config.canon.xml.diff.max_diff_lines = 20000`
220
+ |`CANON_MAX_DIFF_LINES=20000`
221
+ |===
222
+
223
+ NOTE: Size limit options are only available through environment variables or programmatic configuration (Ruby API/RSpec), not via CLI flags.
224
+
225
+ == Complete Example: Same Configuration
226
+
227
+ This example shows the SAME configuration expressed in all four ways:
228
+
229
+ .Configuration Goal
230
+ ====
231
+ * Use semantic diff algorithm
232
+ * Apply strict match profile
233
+ * Ignore attribute order (XML/HTML)
234
+ * Normalize text content
235
+ * Disable color output
236
+ * Show 5 context lines
237
+ ====
238
+
239
+ === Via Environment Variables
240
+
241
+ [source,bash]
242
+ ----
243
+ export CANON_ALGORITHM=semantic
244
+ export CANON_PROFILE=strict
245
+ export CANON_ATTRIBUTE_ORDER=ignore
246
+ export CANON_TEXT_CONTENT=normalize
247
+ export CANON_USE_COLOR=false
248
+ export CANON_CONTEXT_LINES=5
249
+ ----
250
+
251
+ === Via CLI
252
+
253
+ [source,bash]
254
+ ----
255
+ canon diff file1.xml file2.xml \
256
+ --diff-algorithm semantic \
257
+ --match-profile strict \
258
+ --attribute-order ignore \
259
+ --text-content normalize \
260
+ --no-color \
261
+ --context-lines 5
262
+ ----
263
+
264
+ === Via Ruby API
265
+
266
+ [source,ruby]
267
+ ----
268
+ Canon.compare(file1, file2,
269
+ format: :xml,
270
+ diff_algorithm: :semantic,
271
+ match_profile: :strict,
272
+ match: {
273
+ attribute_order: :ignore,
274
+ text_content: :normalize
275
+ },
276
+ color: false,
277
+ context_lines: 5
278
+ )
279
+ ----
280
+
281
+ === Via RSpec
282
+
283
+ [source,ruby]
284
+ ----
285
+ RSpec.configure do |config|
286
+ # Algorithm
287
+ config.canon.xml.diff.algorithm = :semantic
288
+
289
+ # Match configuration
290
+ config.canon.xml.match.profile = :strict
291
+ config.canon.xml.match.options = {
292
+ attribute_order: :ignore,
293
+ text_content: :normalize
294
+ }
295
+
296
+ # Formatting
297
+ config.canon.xml.diff.use_color = false
298
+ config.canon.xml.diff.context_lines = 5
299
+ end
300
+
301
+ # In specs
302
+ expect(actual_xml).to match_xml(expected_xml)
303
+ ----
304
+
305
+ == Format-Specific Configuration
306
+
307
+ Different formats can have different configurations:
308
+
309
+ === Via Environment Variables
310
+
311
+ [source,bash]
312
+ ----
313
+ # XML-specific
314
+ export CANON_XML_DIFF_ALGORITHM=semantic
315
+ export CANON_XML_MATCH_PROFILE=strict
316
+
317
+ # HTML-specific
318
+ export CANON_HTML_DIFF_ALGORITHM=dom
319
+ export CANON_HTML_MATCH_PROFILE=rendered
320
+
321
+ # JSON-specific
322
+ export CANON_JSON_MATCH_PROFILE=content_only
323
+ ----
324
+
325
+ === Via RSpec
326
+
327
+ [source,ruby]
328
+ ----
329
+ RSpec.configure do |config|
330
+ # XML configuration
331
+ config.canon.xml.diff.algorithm = :semantic
332
+ config.canon.xml.match.profile = :strict
333
+
334
+ # HTML configuration
335
+ config.canon.html.diff.algorithm = :dom
336
+ config.canon.html.match.profile = :rendered
337
+
338
+ # JSON configuration
339
+ config.canon.json.match.profile = :content_only
340
+ end
341
+ ----
342
+
343
+ == Option Naming Conventions
344
+
345
+ === CLI Naming
346
+
347
+ * Uses kebab-case: `--diff-algorithm`, `--match-profile`
348
+ * Boolean flags: `--color`, `--no-color`, `--verbose`
349
+ * Underscores become hyphens: `text_content` → `--text-content`
350
+
351
+ === Ruby API Naming
352
+
353
+ * Uses snake_case symbols: `:diff_algorithm`, `:match_profile`
354
+ * Boolean values: `true`, `false`
355
+ * Match dimensions in hash: `match: { text_content: :normalize }`
356
+
357
+ === RSpec Naming
358
+
359
+ * Uses snake_case methods: `.diff.algorithm`, `.match.profile`
360
+ * Boolean values: `true`, `false`
361
+ * Match dimensions in hash: `.match.options = { text_content: :normalize }`
362
+
363
+ === ENV Variable Naming
364
+
365
+ * Uses SCREAMING_SNAKE_CASE: `CANON_ALGORITHM`, `CANON_PROFILE`
366
+ * Prefixed with `CANON_`
367
+ * Format-specific: `CANON_XML_DIFF_ALGORITHM`
368
+ * Boolean as strings: `"true"`, `"false"`
369
+
370
+ == Priority Order
371
+
372
+ When multiple configuration sources are present:
373
+
374
+ 1. **Explicit arguments** (highest priority)
375
+ * CLI flags
376
+ * Ruby API parameters
377
+
378
+ 2. **Environment variables**
379
+ * Format-specific ENV vars
380
+ * Global ENV vars
381
+
382
+ 3. **Programmatic configuration**
383
+ * `Canon.configure` blocks
384
+ * `RSpec.configure` blocks
385
+
386
+ 4. **Default values** (lowest priority)
387
+ * Built-in Canon defaults
388
+
389
+ .Priority example
390
+ [example]
391
+ ====
392
+ [source,bash]
393
+ ----
394
+ # Environment variable
395
+ export CANON_ALGORITHM=semantic
396
+
397
+ # RSpec configuration
398
+ RSpec.configure do |config|
399
+ config.canon.xml.diff.algorithm = :dom
400
+ end
401
+
402
+ # Explicit in test - WINS
403
+ expect(actual).to match_xml(expected).with_options(
404
+ diff_algorithm: :semantic
405
+ )
406
+ # Result: Uses semantic (explicit argument overrides all)
407
+ ----
408
+ ====
409
+
410
+ == See Also
411
+
412
+ * link:environment-variables.html[Environment Variables Reference]
413
+ * link:cli-options.html[CLI Options Reference]
414
+ * link:../interfaces/cli/index.html[CLI Interface]
415
+ * link:../interfaces/ruby-api/index.html[Ruby API Interface]
416
+ * link:../interfaces/rspec/index.html[RSpec Interface]
417
+ * link:../guides/choosing-configuration.html[Choosing Configuration Guide]