@curly-message/conformance 1.0.0-next.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.
- package/LICENSE +21 -0
- package/README.md +266 -0
- package/bin/conformance.js +37 -0
- package/bin/manifest.js +24 -0
- package/dist/index.d.ts +225 -0
- package/dist/index.js +4 -0
- package/fixtures/comparisons.json +916 -0
- package/fixtures/conversion.json +231 -0
- package/fixtures/escaping-extensions.json +84 -0
- package/fixtures/escaping.json +546 -0
- package/fixtures/extensions.json +826 -0
- package/fixtures/fallback-intl.json +51 -0
- package/fixtures/fallback.json +774 -0
- package/fixtures/grammar.json +875 -0
- package/fixtures/intl.json +3057 -0
- package/fixtures/limits.json +63 -0
- package/fixtures/nesting.json +251 -0
- package/fixtures/reports.json +512 -0
- package/fixtures/resolution.json +742 -0
- package/fixtures/security-extensions.json +52 -0
- package/fixtures/security.json +246 -0
- package/fixtures/whitespace.json +1000 -0
- package/index.json +102 -0
- package/package.json +76 -0
- package/schema/fixture.schema.json +264 -0
|
@@ -0,0 +1,742 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "curly-message-1",
|
|
3
|
+
"level": "core",
|
|
4
|
+
"section": "9",
|
|
5
|
+
"cases": [
|
|
6
|
+
{
|
|
7
|
+
"id": "resolution/wrapper-value",
|
|
8
|
+
"description": "An entry owning only the key value is a wrapper, and its value is the placeholder's value.",
|
|
9
|
+
"section": "4.1",
|
|
10
|
+
"message": "{{v}}",
|
|
11
|
+
"payload": {
|
|
12
|
+
"v": {
|
|
13
|
+
"value": 1
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"expected": {
|
|
17
|
+
"output": "1"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "resolution/wrapper-value-and-default",
|
|
22
|
+
"description": "A wrapper carrying both a value and a default resolves to its value.",
|
|
23
|
+
"section": "4.1",
|
|
24
|
+
"message": "{{v}}",
|
|
25
|
+
"payload": {
|
|
26
|
+
"v": {
|
|
27
|
+
"value": 1,
|
|
28
|
+
"default": "D"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"expected": {
|
|
32
|
+
"output": "1"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "resolution/wrapper-default-only",
|
|
37
|
+
"description": "A wrapper owning only a default has no value, so the placeholder takes that default.",
|
|
38
|
+
"section": "4.1",
|
|
39
|
+
"message": "{{v}}",
|
|
40
|
+
"payload": {
|
|
41
|
+
"v": {
|
|
42
|
+
"default": "D"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"expected": {
|
|
46
|
+
"output": "D"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"id": "resolution/wrapper-props-only",
|
|
51
|
+
"description": "A wrapper owning only props has no value, so the placeholder takes the chain.",
|
|
52
|
+
"section": "4.1",
|
|
53
|
+
"message": "{{v; default:INLINE}}",
|
|
54
|
+
"payload": {
|
|
55
|
+
"v": {
|
|
56
|
+
"props": {
|
|
57
|
+
"number": {}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"expected": {
|
|
62
|
+
"output": "INLINE"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"id": "resolution/wrapper-near-miss-is-value",
|
|
67
|
+
"description": "A plain object owning any other key alongside the wrapper keys is a value and serializes whole.",
|
|
68
|
+
"section": "4.1",
|
|
69
|
+
"message": "{{v}}",
|
|
70
|
+
"payload": {
|
|
71
|
+
"v": {
|
|
72
|
+
"value": 1,
|
|
73
|
+
"unit": "kg"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"expected": {
|
|
77
|
+
"output": "{\"value\":1,\"unit\":\"kg\"}"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"id": "resolution/empty-object-is-value",
|
|
82
|
+
"description": "An empty plain object owns no key, so it is a value and serializes to its own two braces.",
|
|
83
|
+
"section": "4.1",
|
|
84
|
+
"message": "{{v; default:D}}",
|
|
85
|
+
"payload": {
|
|
86
|
+
"v": {}
|
|
87
|
+
},
|
|
88
|
+
"expected": {
|
|
89
|
+
"output": "{}"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"id": "resolution/misspelled-wrapper-key-is-value",
|
|
94
|
+
"description": "An entry whose only key is not exactly one of value, default and props is a value.",
|
|
95
|
+
"section": "4.1",
|
|
96
|
+
"message": "{{v}}",
|
|
97
|
+
"payload": {
|
|
98
|
+
"v": {
|
|
99
|
+
"valu": "X"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"expected": {
|
|
103
|
+
"output": "{\"valu\":\"X\"}"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"id": "resolution/array-is-value",
|
|
108
|
+
"description": "An array entry is a value whatever it holds, because a wrapper is a plain object.",
|
|
109
|
+
"section": "4.1",
|
|
110
|
+
"message": "{{v}}",
|
|
111
|
+
"payload": {
|
|
112
|
+
"v": [
|
|
113
|
+
"value"
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
"expected": {
|
|
117
|
+
"output": "[\"value\"]"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"id": "resolution/unwrap-once",
|
|
122
|
+
"description": "Unwrapping happens exactly once: a wrapper's value that is itself wrapper-shaped is a value and serializes.",
|
|
123
|
+
"section": "4.1",
|
|
124
|
+
"message": "{{v}}",
|
|
125
|
+
"payload": {
|
|
126
|
+
"v": {
|
|
127
|
+
"value": {
|
|
128
|
+
"value": 2
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"expected": {
|
|
133
|
+
"output": "{\"value\":2}"
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"id": "resolution/wrapper-value-undefined",
|
|
138
|
+
"description": "A wrapper whose value is the host's undefined has no value, so its default fills the placeholder.",
|
|
139
|
+
"section": "4.1",
|
|
140
|
+
"message": "{{v}}",
|
|
141
|
+
"payload": {
|
|
142
|
+
"v": {
|
|
143
|
+
"value": {
|
|
144
|
+
"$curly": "undefined"
|
|
145
|
+
},
|
|
146
|
+
"default": "D"
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"expected": {
|
|
150
|
+
"output": "D"
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"id": "resolution/wrapper-value-zero",
|
|
155
|
+
"description": "A wrapper's value of zero is a value, not the absence of one.",
|
|
156
|
+
"section": "4.1",
|
|
157
|
+
"message": "{{v}}",
|
|
158
|
+
"payload": {
|
|
159
|
+
"v": {
|
|
160
|
+
"value": 0,
|
|
161
|
+
"default": "D"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
"expected": {
|
|
165
|
+
"output": "0"
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"id": "resolution/wrapper-value-null",
|
|
170
|
+
"description": "A wrapper's value of the host's null is a value, pinned through a comparison so the host's spelling of null is not.",
|
|
171
|
+
"section": "4.1",
|
|
172
|
+
"message": "{{v:ne; zzz:PRESENT}}",
|
|
173
|
+
"payload": {
|
|
174
|
+
"v": {
|
|
175
|
+
"value": null,
|
|
176
|
+
"default": "ABSENT"
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"expected": {
|
|
180
|
+
"output": "PRESENT"
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"id": "resolution/root-default-never-wrapper",
|
|
185
|
+
"description": "The payload's root default entry is never a wrapper, so one shaped like a default-only wrapper is a value that serializes whole rather than an entry with no value.",
|
|
186
|
+
"section": "4.1",
|
|
187
|
+
"message": "{{v}}",
|
|
188
|
+
"payload": {
|
|
189
|
+
"default": {
|
|
190
|
+
"default": "Y"
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
"expected": {
|
|
194
|
+
"output": "{\"default\":\"Y\"}"
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"id": "resolution/key-matched-whole",
|
|
199
|
+
"description": "A dotted key names one payload entry whole.",
|
|
200
|
+
"section": "9.2",
|
|
201
|
+
"message": "{{user.name}}",
|
|
202
|
+
"payload": {
|
|
203
|
+
"user.name": "Ann"
|
|
204
|
+
},
|
|
205
|
+
"expected": {
|
|
206
|
+
"output": "Ann"
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "resolution/key-is-not-a-path",
|
|
211
|
+
"description": "A payload carrying a user entry with a name inside owns no entry named user.name, so the placeholder takes the chain.",
|
|
212
|
+
"section": "9.2",
|
|
213
|
+
"message": "{{user.name; default:D}}",
|
|
214
|
+
"payload": {
|
|
215
|
+
"user": {
|
|
216
|
+
"name": "Ann"
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
"expected": {
|
|
220
|
+
"output": "D"
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"id": "resolution/object-resolves-whole",
|
|
225
|
+
"description": "No placeholder reaches inside a value: a plain object resolves whole as the text section 4 converts it to.",
|
|
226
|
+
"section": "9.2",
|
|
227
|
+
"message": "{{user}}",
|
|
228
|
+
"payload": {
|
|
229
|
+
"user": {
|
|
230
|
+
"name": "Ann"
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
"expected": {
|
|
234
|
+
"output": "{\"name\":\"Ann\"}"
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"id": "resolution/json-placeholder-next-pass",
|
|
239
|
+
"description": "A placeholder a serialized value carries is found and resolved on the following pass.",
|
|
240
|
+
"section": "9.2",
|
|
241
|
+
"message": "{{v}}",
|
|
242
|
+
"payload": {
|
|
243
|
+
"v": {
|
|
244
|
+
"a": "{{n}}"
|
|
245
|
+
},
|
|
246
|
+
"n": "N"
|
|
247
|
+
},
|
|
248
|
+
"expected": {
|
|
249
|
+
"output": "{\"a\":\"N\"}"
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
"id": "resolution/key-case-sensitive",
|
|
254
|
+
"description": "Keys are compared by exact code-point equality, so a key differing in case names no entry.",
|
|
255
|
+
"section": "9.2",
|
|
256
|
+
"message": "{{Name; default:D}}",
|
|
257
|
+
"payload": {
|
|
258
|
+
"name": "Ann"
|
|
259
|
+
},
|
|
260
|
+
"expected": {
|
|
261
|
+
"output": "D"
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
"id": "resolution/key-non-ascii",
|
|
266
|
+
"description": "A key may be non-ASCII text and is matched by code-point equality.",
|
|
267
|
+
"section": "9.2",
|
|
268
|
+
"message": "{{jm\u00e9no}}",
|
|
269
|
+
"payload": {
|
|
270
|
+
"jm\u00e9no": "Ann"
|
|
271
|
+
},
|
|
272
|
+
"expected": {
|
|
273
|
+
"output": "Ann"
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"id": "resolution/key-not-normalized",
|
|
278
|
+
"description": "Matching is by code point and not by normalization, so a decomposed spelling names no entry the precomposed one does.",
|
|
279
|
+
"section": "9.2",
|
|
280
|
+
"message": "{{e\u0301; default:D}}",
|
|
281
|
+
"payload": {
|
|
282
|
+
"\u00e9": "x"
|
|
283
|
+
},
|
|
284
|
+
"expected": {
|
|
285
|
+
"output": "D"
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
"id": "resolution/absent-no-entry",
|
|
290
|
+
"description": "A key with no own entry is absent and takes the chain.",
|
|
291
|
+
"section": "9.2",
|
|
292
|
+
"message": "{{v; default:D}}",
|
|
293
|
+
"payload": {},
|
|
294
|
+
"expected": {
|
|
295
|
+
"output": "D"
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
"id": "resolution/absent-undefined-entry",
|
|
300
|
+
"description": "An own entry that is the host's undefined is absent, and there is nothing to report.",
|
|
301
|
+
"section": "9.2",
|
|
302
|
+
"message": "{{v; default:D}}",
|
|
303
|
+
"payload": {
|
|
304
|
+
"v": {
|
|
305
|
+
"$curly": "undefined"
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
"expected": {
|
|
309
|
+
"output": "D",
|
|
310
|
+
"reports": []
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
"id": "resolution/present-zero",
|
|
315
|
+
"description": "A value of zero is present, so the placeholder renders it rather than the default.",
|
|
316
|
+
"section": "9.2",
|
|
317
|
+
"message": "{{v; default:D}}",
|
|
318
|
+
"payload": {
|
|
319
|
+
"v": 0
|
|
320
|
+
},
|
|
321
|
+
"expected": {
|
|
322
|
+
"output": "0"
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
"id": "resolution/present-empty-string",
|
|
327
|
+
"description": "An empty string is present, so the placeholder renders it rather than the default.",
|
|
328
|
+
"section": "9.2",
|
|
329
|
+
"message": "[{{v; default:D}}]",
|
|
330
|
+
"payload": {
|
|
331
|
+
"v": ""
|
|
332
|
+
},
|
|
333
|
+
"expected": {
|
|
334
|
+
"output": "[]"
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"id": "resolution/present-false",
|
|
339
|
+
"description": "A value of false is present, pinned through a comparison so the host's spelling of false is not.",
|
|
340
|
+
"section": "9.2",
|
|
341
|
+
"message": "{{v:ne; zzz:PRESENT; default:ABSENT}}",
|
|
342
|
+
"payload": {
|
|
343
|
+
"v": false
|
|
344
|
+
},
|
|
345
|
+
"expected": {
|
|
346
|
+
"output": "PRESENT"
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
"id": "resolution/present-null",
|
|
351
|
+
"description": "The host's null is present, pinned through a comparison so the host's spelling of null is not.",
|
|
352
|
+
"section": "9.2",
|
|
353
|
+
"message": "{{v:ne; zzz:PRESENT; default:ABSENT}}",
|
|
354
|
+
"payload": {
|
|
355
|
+
"v": null
|
|
356
|
+
},
|
|
357
|
+
"expected": {
|
|
358
|
+
"output": "PRESENT"
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"id": "resolution/inline-default-value",
|
|
363
|
+
"description": "The spelling default:x declares x.",
|
|
364
|
+
"section": "9.3",
|
|
365
|
+
"message": "{{v; default:x}}",
|
|
366
|
+
"payload": {},
|
|
367
|
+
"expected": {
|
|
368
|
+
"output": "x"
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"id": "resolution/inline-default-empty",
|
|
373
|
+
"description": "The spelling default: declares the empty string.",
|
|
374
|
+
"section": "9.3",
|
|
375
|
+
"message": "[{{v; default:}}]",
|
|
376
|
+
"payload": {},
|
|
377
|
+
"expected": {
|
|
378
|
+
"output": "[]"
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"id": "resolution/inline-default-bare",
|
|
383
|
+
"description": "The spelling default alone, with no colon, declares the key itself, the text default.",
|
|
384
|
+
"section": "9.3",
|
|
385
|
+
"message": "{{v; default}}",
|
|
386
|
+
"payload": {},
|
|
387
|
+
"expected": {
|
|
388
|
+
"output": "default"
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
"id": "resolution/first-default-wins",
|
|
393
|
+
"description": "The first segment named default is the inline default, and a later one does not displace it.",
|
|
394
|
+
"section": "9.3",
|
|
395
|
+
"message": "{{v; default:FIRST; default:SECOND}}",
|
|
396
|
+
"payload": {},
|
|
397
|
+
"expected": {
|
|
398
|
+
"output": "FIRST"
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"id": "resolution/first-default-wins-when-empty",
|
|
403
|
+
"description": "An empty first default still wins over a later segment named default.",
|
|
404
|
+
"section": "9.3",
|
|
405
|
+
"message": "[{{v; default:; default:SECOND}}]",
|
|
406
|
+
"payload": {},
|
|
407
|
+
"expected": {
|
|
408
|
+
"output": "[]"
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"id": "resolution/default-uppercase-is-option",
|
|
413
|
+
"description": "The word default is reserved in lowercase only, so DEFAULT:UPPER is an option and default:LOWER the inline default.",
|
|
414
|
+
"section": "9.3",
|
|
415
|
+
"message": "{{v; DEFAULT:UPPER; default:LOWER}}",
|
|
416
|
+
"payload": {},
|
|
417
|
+
"expected": {
|
|
418
|
+
"output": "LOWER"
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
"id": "resolution/default-mixed-case-is-option",
|
|
423
|
+
"description": "The segment Default:X is an ordinary option, so an absent value with no default renders nothing.",
|
|
424
|
+
"section": "9.3",
|
|
425
|
+
"message": "[{{v; Default:X}}]",
|
|
426
|
+
"payload": {},
|
|
427
|
+
"expected": {
|
|
428
|
+
"output": "[]"
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
"id": "resolution/default-uppercase-selects",
|
|
433
|
+
"description": "An option keyed DEFAULT selects like any other for the value that matches it, as Appendix A.1 shows.",
|
|
434
|
+
"section": "9.3",
|
|
435
|
+
"message": "{{v; DEFAULT:D}}",
|
|
436
|
+
"payload": {
|
|
437
|
+
"v": "DEFAULT"
|
|
438
|
+
},
|
|
439
|
+
"expected": {
|
|
440
|
+
"output": "D"
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
"id": "resolution/default-uppercase-is-not-the-fallback",
|
|
445
|
+
"description": "An option keyed DEFAULT is not the inline fallback, so an absent value renders nothing, as Appendix A.1 shows.",
|
|
446
|
+
"section": "9.3",
|
|
447
|
+
"message": "{{v; DEFAULT:D}}",
|
|
448
|
+
"payload": {},
|
|
449
|
+
"expected": {
|
|
450
|
+
"output": ""
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"id": "resolution/default-lowercase-beside-uppercase",
|
|
455
|
+
"description": "Only the lowercase default is the inline fallback, so an absent value renders it beside an option keyed DEFAULT, as Appendix A.1 shows.",
|
|
456
|
+
"section": "9.3",
|
|
457
|
+
"message": "{{v; default:LOWER; DEFAULT:UPPER}}",
|
|
458
|
+
"payload": {},
|
|
459
|
+
"expected": {
|
|
460
|
+
"output": "LOWER"
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
"id": "resolution/payload-default-fills-every-placeholder",
|
|
465
|
+
"description": "The payload's default entry is the fallback for every placeholder in the message that resolves to no value.",
|
|
466
|
+
"section": "9.3",
|
|
467
|
+
"message": "{{a}}-{{b}}",
|
|
468
|
+
"payload": {
|
|
469
|
+
"default": "D"
|
|
470
|
+
},
|
|
471
|
+
"expected": {
|
|
472
|
+
"output": "D-D"
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"id": "resolution/payload-default-uppercase-not-reserved",
|
|
477
|
+
"description": "The reserved payload key is default in lowercase only, so an entry named DEFAULT is not the fallback and an absent value renders nothing, as Appendix A.1 shows.",
|
|
478
|
+
"section": "9.3",
|
|
479
|
+
"message": "{{v}}",
|
|
480
|
+
"payload": {
|
|
481
|
+
"DEFAULT": "PD"
|
|
482
|
+
},
|
|
483
|
+
"expected": {
|
|
484
|
+
"output": ""
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"id": "resolution/selection-no-match-payload-default",
|
|
489
|
+
"description": "A selection that matches nothing resolves to no value, so the payload default answers it rather than the value.",
|
|
490
|
+
"section": "9.3",
|
|
491
|
+
"message": "{{v; a:A}}",
|
|
492
|
+
"payload": {
|
|
493
|
+
"v": "RAW",
|
|
494
|
+
"default": "D"
|
|
495
|
+
},
|
|
496
|
+
"expected": {
|
|
497
|
+
"output": "D"
|
|
498
|
+
}
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
"id": "resolution/default-placeholder-reads-fallback",
|
|
502
|
+
"description": "The placeholder {{default}} reads the payload's fallback and not an entry of its own, so a wrapper-shaped default entry serializes as the ordinary value it is rather than unwrapping.",
|
|
503
|
+
"section": "9.3",
|
|
504
|
+
"message": "{{default}}",
|
|
505
|
+
"payload": {
|
|
506
|
+
"default": {
|
|
507
|
+
"value": "X"
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
"expected": {
|
|
511
|
+
"output": "{\"value\":\"X\"}"
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
"id": "resolution/option-key-value",
|
|
516
|
+
"description": "The form key:value yields that key and value, and a comparison selects by the key.",
|
|
517
|
+
"section": "9.4",
|
|
518
|
+
"message": "{{v; 1:ONE; 2:TWO}}",
|
|
519
|
+
"payload": {
|
|
520
|
+
"v": 2
|
|
521
|
+
},
|
|
522
|
+
"expected": {
|
|
523
|
+
"output": "TWO"
|
|
524
|
+
}
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
"id": "resolution/option-key-alone",
|
|
528
|
+
"description": "A key alone, with no colon, yields the key as both key and value.",
|
|
529
|
+
"section": "9.4",
|
|
530
|
+
"message": "{{v; 1}}",
|
|
531
|
+
"payload": {
|
|
532
|
+
"v": 1
|
|
533
|
+
},
|
|
534
|
+
"expected": {
|
|
535
|
+
"output": "1"
|
|
536
|
+
}
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
"id": "resolution/option-key-alone-selected-by-ne",
|
|
540
|
+
"description": "A valueless option stands for its own spelling whichever comparison selects it.",
|
|
541
|
+
"section": "9.4",
|
|
542
|
+
"message": "{{v:ne; z; default:DEF}}",
|
|
543
|
+
"payload": {
|
|
544
|
+
"v": "a"
|
|
545
|
+
},
|
|
546
|
+
"expected": {
|
|
547
|
+
"output": "z"
|
|
548
|
+
}
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
"id": "resolution/option-empty-value",
|
|
552
|
+
"description": "The form key: yields the key and the empty string, which is a value and not an absence.",
|
|
553
|
+
"section": "9.4",
|
|
554
|
+
"message": "{{v; 1:; 5:FIVE; default:DEF}}",
|
|
555
|
+
"payload": {
|
|
556
|
+
"v": 1
|
|
557
|
+
},
|
|
558
|
+
"expected": {
|
|
559
|
+
"output": ""
|
|
560
|
+
}
|
|
561
|
+
},
|
|
562
|
+
{
|
|
563
|
+
"id": "resolution/option-whitespace-value-empty",
|
|
564
|
+
"description": "A value that is only unescaped whitespace is empty, so x: and x: followed by a space both declare the empty string.",
|
|
565
|
+
"section": "9.4",
|
|
566
|
+
"message": "{{v; x: ; 5:FIVE; default:DEF}}",
|
|
567
|
+
"payload": {
|
|
568
|
+
"v": "x"
|
|
569
|
+
},
|
|
570
|
+
"expected": {
|
|
571
|
+
"output": ""
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
"id": "resolution/empty-option-key-declares-nothing",
|
|
576
|
+
"description": "A segment whose option key is empty declares no option even with a value, so the placeholder stays a plain substitution.",
|
|
577
|
+
"section": "9.4",
|
|
578
|
+
"message": "{{v; :X}}",
|
|
579
|
+
"payload": {
|
|
580
|
+
"v": "RAW"
|
|
581
|
+
},
|
|
582
|
+
"expected": {
|
|
583
|
+
"output": "RAW"
|
|
584
|
+
}
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
"id": "resolution/default-not-among-options",
|
|
588
|
+
"description": "The reserved key default is not an option, so a placeholder carrying only an inline default is a plain substitution that renders the value default.",
|
|
589
|
+
"section": "9.4",
|
|
590
|
+
"message": "{{v; default:D}}",
|
|
591
|
+
"payload": {
|
|
592
|
+
"v": "default"
|
|
593
|
+
},
|
|
594
|
+
"expected": {
|
|
595
|
+
"output": "default"
|
|
596
|
+
}
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
"id": "resolution/second-default-not-an-option",
|
|
600
|
+
"description": "A later segment keyed default is neither the inline default nor an option, so the placeholder stays a plain substitution over the value default.",
|
|
601
|
+
"section": "9.4",
|
|
602
|
+
"message": "{{v; default:FIRST; default:SECOND}}",
|
|
603
|
+
"payload": {
|
|
604
|
+
"v": "default"
|
|
605
|
+
},
|
|
606
|
+
"expected": {
|
|
607
|
+
"output": "default"
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
"id": "resolution/plain-substitution",
|
|
612
|
+
"description": "A placeholder with no modifier and no options is a plain substitution: the result is the value.",
|
|
613
|
+
"section": "9.5",
|
|
614
|
+
"message": "{{v}}",
|
|
615
|
+
"payload": {
|
|
616
|
+
"v": "RAW"
|
|
617
|
+
},
|
|
618
|
+
"expected": {
|
|
619
|
+
"output": "RAW"
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
"id": "resolution/selection-by-eq",
|
|
624
|
+
"description": "A placeholder with options and no modifier is a selection performed by eq.",
|
|
625
|
+
"section": "9.5",
|
|
626
|
+
"message": "{{v; a:A; b:B}}",
|
|
627
|
+
"payload": {
|
|
628
|
+
"v": "b"
|
|
629
|
+
},
|
|
630
|
+
"expected": {
|
|
631
|
+
"output": "B"
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
"id": "resolution/first-option-changes-the-question",
|
|
636
|
+
"description": "Giving a placeholder its first option makes it a selection: where no option matches, the result is the chain and never the value.",
|
|
637
|
+
"section": "9.5",
|
|
638
|
+
"message": "{{v; a:A}}",
|
|
639
|
+
"payload": {
|
|
640
|
+
"v": "RAW"
|
|
641
|
+
},
|
|
642
|
+
"expected": {
|
|
643
|
+
"output": ""
|
|
644
|
+
}
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
"id": "resolution/selection-no-match-default",
|
|
648
|
+
"description": "A selection that matches nothing renders the declared default where there is one.",
|
|
649
|
+
"section": "9.5",
|
|
650
|
+
"message": "{{v; a:A; default:D}}",
|
|
651
|
+
"payload": {
|
|
652
|
+
"v": "RAW"
|
|
653
|
+
},
|
|
654
|
+
"expected": {
|
|
655
|
+
"output": "D"
|
|
656
|
+
}
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
"id": "resolution/missing-options",
|
|
660
|
+
"description": "A selection naming a comparison modifier and no options is a message error: the chain, and a missing-options report against the message.",
|
|
661
|
+
"section": "9.5",
|
|
662
|
+
"message": "{{v:eq}}",
|
|
663
|
+
"payload": {
|
|
664
|
+
"v": "RAW"
|
|
665
|
+
},
|
|
666
|
+
"key": "resolution.missing-options",
|
|
667
|
+
"expected": {
|
|
668
|
+
"output": "",
|
|
669
|
+
"reports": [
|
|
670
|
+
{
|
|
671
|
+
"code": "missing-options",
|
|
672
|
+
"origin": "message",
|
|
673
|
+
"key": "resolution.missing-options"
|
|
674
|
+
}
|
|
675
|
+
]
|
|
676
|
+
}
|
|
677
|
+
},
|
|
678
|
+
{
|
|
679
|
+
"id": "resolution/missing-options-takes-chain",
|
|
680
|
+
"description": "A missing-options error takes the fallback chain, the inline default being no option.",
|
|
681
|
+
"section": "9.5",
|
|
682
|
+
"message": "{{v:eq; default:D}}",
|
|
683
|
+
"payload": {
|
|
684
|
+
"v": "RAW"
|
|
685
|
+
},
|
|
686
|
+
"expected": {
|
|
687
|
+
"output": "D",
|
|
688
|
+
"reports": [
|
|
689
|
+
{
|
|
690
|
+
"code": "missing-options",
|
|
691
|
+
"origin": "message"
|
|
692
|
+
}
|
|
693
|
+
]
|
|
694
|
+
}
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
"id": "resolution/missing-options-other-comparison",
|
|
698
|
+
"description": "Every comparison modifier of the format is subject to the error, lt among them.",
|
|
699
|
+
"section": "9.5",
|
|
700
|
+
"message": "{{v:lt; default:D}}",
|
|
701
|
+
"payload": {
|
|
702
|
+
"v": 5
|
|
703
|
+
},
|
|
704
|
+
"expected": {
|
|
705
|
+
"output": "D",
|
|
706
|
+
"reports": [
|
|
707
|
+
{
|
|
708
|
+
"code": "missing-options",
|
|
709
|
+
"origin": "message"
|
|
710
|
+
}
|
|
711
|
+
]
|
|
712
|
+
}
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
"id": "resolution/missing-options-absent-value",
|
|
716
|
+
"description": "The error turns on the placeholder and not the payload: it is reported over an absent value too, which takes the chain before any modifier is asked.",
|
|
717
|
+
"section": "9.5",
|
|
718
|
+
"message": "{{v:eq; default:D}}",
|
|
719
|
+
"payload": {},
|
|
720
|
+
"expected": {
|
|
721
|
+
"output": "D",
|
|
722
|
+
"reports": [
|
|
723
|
+
{
|
|
724
|
+
"code": "missing-options",
|
|
725
|
+
"origin": "message"
|
|
726
|
+
}
|
|
727
|
+
]
|
|
728
|
+
}
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
"id": "resolution/no-key-is-no-selection",
|
|
732
|
+
"description": "A placeholder naming no key is neither a substitution nor a selection: it takes the chain, and a comparison it names was asked nothing, so nothing is reported.",
|
|
733
|
+
"section": "9.5",
|
|
734
|
+
"message": "{{:eq; default:D}}",
|
|
735
|
+
"payload": {},
|
|
736
|
+
"expected": {
|
|
737
|
+
"output": "D",
|
|
738
|
+
"reports": []
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
]
|
|
742
|
+
}
|