@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,826 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "curly-message-1",
|
|
3
|
+
"level": "extensions",
|
|
4
|
+
"section": "11.3",
|
|
5
|
+
"cases": [
|
|
6
|
+
{
|
|
7
|
+
"id": "extensions/registers-by-name",
|
|
8
|
+
"description": "A host registers a modifier under a name, and a placeholder naming it gets that modifier's answer.",
|
|
9
|
+
"section": "11.3",
|
|
10
|
+
"message": "{{v:up}}",
|
|
11
|
+
"payload": {
|
|
12
|
+
"v": "abc"
|
|
13
|
+
},
|
|
14
|
+
"modifiers": {
|
|
15
|
+
"up": "upper"
|
|
16
|
+
},
|
|
17
|
+
"expected": {
|
|
18
|
+
"output": "ABC"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "extensions/replaces-a-comparison",
|
|
23
|
+
"description": "A host modifier registered under a comparison's name replaces it, so the options are handed to the host modifier as written rather than selected.",
|
|
24
|
+
"section": "11.3",
|
|
25
|
+
"message": "{{v:eq; x:HIT; default:D}}",
|
|
26
|
+
"payload": {
|
|
27
|
+
"v": "x"
|
|
28
|
+
},
|
|
29
|
+
"modifiers": {
|
|
30
|
+
"eq": "options"
|
|
31
|
+
},
|
|
32
|
+
"expected": {
|
|
33
|
+
"output": "x=HIT"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"id": "extensions/replaced-eq-answers-unnamed-selection",
|
|
38
|
+
"description": "A selection that names no modifier asks eq, so a host modifier registered under eq answers it.",
|
|
39
|
+
"section": "9.5",
|
|
40
|
+
"message": "{{v; x:HIT; default:D}}",
|
|
41
|
+
"payload": {
|
|
42
|
+
"v": "x"
|
|
43
|
+
},
|
|
44
|
+
"modifiers": {
|
|
45
|
+
"eq": "upper"
|
|
46
|
+
},
|
|
47
|
+
"expected": {
|
|
48
|
+
"output": "X"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "extensions/replaces-a-formatting-modifier",
|
|
53
|
+
"description": "A host modifier registered under a formatting modifier's name replaces it, so the placeholder needs no locale and reports none missing.",
|
|
54
|
+
"section": "11.3",
|
|
55
|
+
"message": "[{{v:number; default:D}}]",
|
|
56
|
+
"payload": {
|
|
57
|
+
"v": "abc"
|
|
58
|
+
},
|
|
59
|
+
"key": "extensions.replaces-number",
|
|
60
|
+
"modifiers": {
|
|
61
|
+
"number": "upper"
|
|
62
|
+
},
|
|
63
|
+
"expected": {
|
|
64
|
+
"output": "[ABC]",
|
|
65
|
+
"reports": []
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "extensions/replaced-comparison-no-options",
|
|
70
|
+
"description": "A placeholder naming a replaced comparison without options asks a host-defined modifier, so it is no message error.",
|
|
71
|
+
"section": "9.5",
|
|
72
|
+
"message": "{{v:eq}}",
|
|
73
|
+
"payload": {
|
|
74
|
+
"v": "x"
|
|
75
|
+
},
|
|
76
|
+
"key": "extensions.replaced-eq",
|
|
77
|
+
"modifiers": {
|
|
78
|
+
"eq": "echo"
|
|
79
|
+
},
|
|
80
|
+
"expected": {
|
|
81
|
+
"output": "x",
|
|
82
|
+
"reports": []
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "extensions/replaced-comparison-no-options-absent-value",
|
|
87
|
+
"description": "What answers to the name decides the report, not the payload: a replaced comparison without options is not reported over an absent value either.",
|
|
88
|
+
"section": "9.5",
|
|
89
|
+
"message": "[{{v:eq; default:d}}]",
|
|
90
|
+
"payload": {},
|
|
91
|
+
"key": "extensions.replaced-eq-absent",
|
|
92
|
+
"modifiers": {
|
|
93
|
+
"eq": "upper"
|
|
94
|
+
},
|
|
95
|
+
"expected": {
|
|
96
|
+
"output": "[d]",
|
|
97
|
+
"reports": []
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"id": "extensions/replaced-lt-no-options",
|
|
102
|
+
"description": "missing-options names a comparison no host replaced, so a replaced lt without options reports nothing.",
|
|
103
|
+
"section": "14.2",
|
|
104
|
+
"message": "{{v:lt}}",
|
|
105
|
+
"payload": {
|
|
106
|
+
"v": "x"
|
|
107
|
+
},
|
|
108
|
+
"key": "extensions.replaced-lt",
|
|
109
|
+
"modifiers": {
|
|
110
|
+
"lt": "echo"
|
|
111
|
+
},
|
|
112
|
+
"expected": {
|
|
113
|
+
"output": "x",
|
|
114
|
+
"reports": []
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"id": "extensions/registered-name-case-sensitive",
|
|
119
|
+
"description": "A registered name is matched case-sensitively, so a spelling differing by case names a modifier nobody registered.",
|
|
120
|
+
"section": "11",
|
|
121
|
+
"message": "[{{v:UP; default:D}}]",
|
|
122
|
+
"payload": {
|
|
123
|
+
"v": "x"
|
|
124
|
+
},
|
|
125
|
+
"key": "extensions.case",
|
|
126
|
+
"modifiers": {
|
|
127
|
+
"up": "upper"
|
|
128
|
+
},
|
|
129
|
+
"expected": {
|
|
130
|
+
"output": "[D]",
|
|
131
|
+
"reports": [
|
|
132
|
+
{
|
|
133
|
+
"code": "unknown-modifier",
|
|
134
|
+
"origin": "message",
|
|
135
|
+
"key": "extensions.case"
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"id": "extensions/unknown-beside-registered",
|
|
142
|
+
"description": "A name nobody registered is a message error beside one a host registered: the chain and one unknown-modifier report, never an equality selection.",
|
|
143
|
+
"section": "11.4",
|
|
144
|
+
"message": "{{a:up}} {{b:down; x:HIT; default:D}}",
|
|
145
|
+
"payload": {
|
|
146
|
+
"a": "x",
|
|
147
|
+
"b": "x"
|
|
148
|
+
},
|
|
149
|
+
"key": "extensions.beside",
|
|
150
|
+
"modifiers": {
|
|
151
|
+
"up": "upper"
|
|
152
|
+
},
|
|
153
|
+
"expected": {
|
|
154
|
+
"output": "X D",
|
|
155
|
+
"reports": [
|
|
156
|
+
{
|
|
157
|
+
"code": "unknown-modifier",
|
|
158
|
+
"origin": "message",
|
|
159
|
+
"key": "extensions.beside"
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": "extensions/nosuch-unregistered",
|
|
166
|
+
"description": "A name nobody registered resolves to the chain and is reported as unknown, which is what the non-modifier registrations of A.18 should have read as.",
|
|
167
|
+
"section": "11.4",
|
|
168
|
+
"message": "{{v:nosuch; default:D}}",
|
|
169
|
+
"payload": {
|
|
170
|
+
"v": "x"
|
|
171
|
+
},
|
|
172
|
+
"key": "extensions.nosuch",
|
|
173
|
+
"expected": {
|
|
174
|
+
"output": "D",
|
|
175
|
+
"reports": [
|
|
176
|
+
{
|
|
177
|
+
"code": "unknown-modifier",
|
|
178
|
+
"origin": "message",
|
|
179
|
+
"key": "extensions.nosuch"
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"id": "extensions/keyless-placeholder-does-not-ask",
|
|
186
|
+
"description": "A placeholder naming no key resolves at parse to the chain and is no selection, so the registered modifier it names is not asked and nothing is reported.",
|
|
187
|
+
"section": "9.5",
|
|
188
|
+
"message": "[{{:boom; default:d}}]",
|
|
189
|
+
"payload": {
|
|
190
|
+
"v": "x"
|
|
191
|
+
},
|
|
192
|
+
"key": "extensions.keyless",
|
|
193
|
+
"modifiers": {
|
|
194
|
+
"boom": "raise"
|
|
195
|
+
},
|
|
196
|
+
"expected": {
|
|
197
|
+
"output": "[d]",
|
|
198
|
+
"reports": []
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"id": "extensions/absent-value-does-not-ask",
|
|
203
|
+
"description": "An absent value takes the fallback chain before any modifier is asked, so a host-defined modifier that would raise is never called.",
|
|
204
|
+
"section": "11.1",
|
|
205
|
+
"message": "[{{v:boom; default:abc}}]",
|
|
206
|
+
"payload": {},
|
|
207
|
+
"key": "extensions.absent",
|
|
208
|
+
"modifiers": {
|
|
209
|
+
"boom": "raise"
|
|
210
|
+
},
|
|
211
|
+
"expected": {
|
|
212
|
+
"output": "[abc]",
|
|
213
|
+
"reports": []
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"id": "extensions/value-number-as-text",
|
|
218
|
+
"description": "No modifier sees a value at the type it was authored with: a number reaches it as text.",
|
|
219
|
+
"section": "11",
|
|
220
|
+
"message": "{{v:obj}}",
|
|
221
|
+
"payload": {
|
|
222
|
+
"v": 1
|
|
223
|
+
},
|
|
224
|
+
"modifiers": {
|
|
225
|
+
"obj": "object"
|
|
226
|
+
},
|
|
227
|
+
"expected": {
|
|
228
|
+
"output": "{\"answer\":\"1\"}"
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"id": "extensions/value-plain-object-as-json",
|
|
233
|
+
"description": "A plain object reaches a host-defined modifier as its JSON serialization, so a structured value survives into one that reads it back.",
|
|
234
|
+
"section": "4",
|
|
235
|
+
"message": "{{v:obj}}",
|
|
236
|
+
"payload": {
|
|
237
|
+
"v": {
|
|
238
|
+
"a": 1
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
"modifiers": {
|
|
242
|
+
"obj": "object"
|
|
243
|
+
},
|
|
244
|
+
"expected": {
|
|
245
|
+
"output": "{\"answer\":\"{\\\"a\\\":1}\"}"
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"id": "extensions/value-array-as-json",
|
|
250
|
+
"description": "An array reaches a host-defined modifier as its JSON serialization.",
|
|
251
|
+
"section": "4",
|
|
252
|
+
"message": "{{v:obj}}",
|
|
253
|
+
"payload": {
|
|
254
|
+
"v": [
|
|
255
|
+
1,
|
|
256
|
+
2
|
|
257
|
+
]
|
|
258
|
+
},
|
|
259
|
+
"modifiers": {
|
|
260
|
+
"obj": "object"
|
|
261
|
+
},
|
|
262
|
+
"expected": {
|
|
263
|
+
"output": "{\"answer\":\"[1,2]\"}"
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
"id": "extensions/blank-value-reaches-modifier",
|
|
268
|
+
"description": "The blank-text rule governs formatting alone, so a value that is only whitespace reaches a host-defined modifier as that text rather than taking the chain.",
|
|
269
|
+
"section": "11.2",
|
|
270
|
+
"message": "{{v:obj; default:D}}",
|
|
271
|
+
"payload": {
|
|
272
|
+
"v": " "
|
|
273
|
+
},
|
|
274
|
+
"modifiers": {
|
|
275
|
+
"obj": "object"
|
|
276
|
+
},
|
|
277
|
+
"expected": {
|
|
278
|
+
"output": "{\"answer\":\" \"}"
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"id": "extensions/options-as-written",
|
|
283
|
+
"description": "A modifier is handed the options in source order: a value, the empty string after a bare colon, and a valueless key standing for itself.",
|
|
284
|
+
"section": "9.4",
|
|
285
|
+
"message": "{{v:opts; a:A; b:; c}}",
|
|
286
|
+
"payload": {
|
|
287
|
+
"v": "x"
|
|
288
|
+
},
|
|
289
|
+
"modifiers": {
|
|
290
|
+
"opts": "options"
|
|
291
|
+
},
|
|
292
|
+
"expected": {
|
|
293
|
+
"output": "a=A,b=,c=c"
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
"id": "extensions/options-keep-duplicates",
|
|
298
|
+
"description": "Collection keeps every option in source order, duplicates included, so a host-defined modifier is handed the list as the placeholder wrote it.",
|
|
299
|
+
"section": "9.4",
|
|
300
|
+
"message": "{{v:opts; a:1; b:2; a:3}}",
|
|
301
|
+
"payload": {
|
|
302
|
+
"v": "x"
|
|
303
|
+
},
|
|
304
|
+
"modifiers": {
|
|
305
|
+
"opts": "options"
|
|
306
|
+
},
|
|
307
|
+
"expected": {
|
|
308
|
+
"output": "a=1,b=2,a=3"
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"id": "extensions/options-exclude-inline-default",
|
|
313
|
+
"description": "The reserved key default is not among the options a modifier is handed, wherever the inline default stands.",
|
|
314
|
+
"section": "9.4",
|
|
315
|
+
"message": "{{v:opts; a:A; default:D; b:B}}",
|
|
316
|
+
"payload": {
|
|
317
|
+
"v": "x"
|
|
318
|
+
},
|
|
319
|
+
"modifiers": {
|
|
320
|
+
"opts": "options"
|
|
321
|
+
},
|
|
322
|
+
"expected": {
|
|
323
|
+
"output": "a=A,b=B"
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"id": "extensions/options-skip-segments-declaring-none",
|
|
328
|
+
"description": "A segment whose option key is empty declares no option, with or without a value, so none reaches the modifier.",
|
|
329
|
+
"section": "9.4",
|
|
330
|
+
"message": "{{v:opts; a:A; ; :B; c:C}}",
|
|
331
|
+
"payload": {
|
|
332
|
+
"v": "x"
|
|
333
|
+
},
|
|
334
|
+
"modifiers": {
|
|
335
|
+
"opts": "options"
|
|
336
|
+
},
|
|
337
|
+
"expected": {
|
|
338
|
+
"output": "a=A,c=C"
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"id": "extensions/options-none",
|
|
343
|
+
"description": "A placeholder that declares no option hands a modifier an empty list of them.",
|
|
344
|
+
"section": "9.4",
|
|
345
|
+
"message": "[{{v:opts}}]",
|
|
346
|
+
"payload": {
|
|
347
|
+
"v": "x"
|
|
348
|
+
},
|
|
349
|
+
"modifiers": {
|
|
350
|
+
"opts": "options"
|
|
351
|
+
},
|
|
352
|
+
"expected": {
|
|
353
|
+
"output": "[]"
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
"id": "extensions/host-modifier-needs-no-options",
|
|
358
|
+
"description": "Whether a host-defined modifier needs options is its own business, so a placeholder naming one without options is no message error and nothing is reported.",
|
|
359
|
+
"section": "9.5",
|
|
360
|
+
"message": "{{v:own}}",
|
|
361
|
+
"payload": {
|
|
362
|
+
"v": "x"
|
|
363
|
+
},
|
|
364
|
+
"key": "extensions.own-business",
|
|
365
|
+
"modifiers": {
|
|
366
|
+
"own": "echo"
|
|
367
|
+
},
|
|
368
|
+
"expected": {
|
|
369
|
+
"output": "x",
|
|
370
|
+
"reports": []
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"id": "extensions/default-wrapper-first",
|
|
375
|
+
"description": "The default a modifier reads is the chain of section 10, the wrapper's link first.",
|
|
376
|
+
"section": "10",
|
|
377
|
+
"message": "{{v:read; default:Inline}}",
|
|
378
|
+
"payload": {
|
|
379
|
+
"v": {
|
|
380
|
+
"value": "x",
|
|
381
|
+
"default": "W"
|
|
382
|
+
},
|
|
383
|
+
"default": "P"
|
|
384
|
+
},
|
|
385
|
+
"modifiers": {
|
|
386
|
+
"read": "default"
|
|
387
|
+
},
|
|
388
|
+
"expected": {
|
|
389
|
+
"output": "W"
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
"id": "extensions/default-payload-over-inline",
|
|
394
|
+
"description": "The payload's own default outranks the inline one in the default a modifier reads.",
|
|
395
|
+
"section": "10",
|
|
396
|
+
"message": "{{v:read; default:Inline}}",
|
|
397
|
+
"payload": {
|
|
398
|
+
"v": "x",
|
|
399
|
+
"default": "P"
|
|
400
|
+
},
|
|
401
|
+
"modifiers": {
|
|
402
|
+
"read": "default"
|
|
403
|
+
},
|
|
404
|
+
"expected": {
|
|
405
|
+
"output": "P"
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
"id": "extensions/default-inline",
|
|
410
|
+
"description": "Where no earlier link yields text, the default a modifier reads is the placeholder's inline default.",
|
|
411
|
+
"section": "10",
|
|
412
|
+
"message": "{{v:read; default:Inline}}",
|
|
413
|
+
"payload": {
|
|
414
|
+
"v": "x"
|
|
415
|
+
},
|
|
416
|
+
"modifiers": {
|
|
417
|
+
"read": "default"
|
|
418
|
+
},
|
|
419
|
+
"expected": {
|
|
420
|
+
"output": "Inline"
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
"id": "extensions/default-empty-string",
|
|
425
|
+
"description": "Where no link of the chain yields text, the default a modifier reads is the empty string.",
|
|
426
|
+
"section": "10",
|
|
427
|
+
"message": "[{{v:read}}]",
|
|
428
|
+
"payload": {
|
|
429
|
+
"v": "x"
|
|
430
|
+
},
|
|
431
|
+
"modifiers": {
|
|
432
|
+
"read": "default"
|
|
433
|
+
},
|
|
434
|
+
"expected": {
|
|
435
|
+
"output": "[]"
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
"id": "extensions/default-as-text",
|
|
440
|
+
"description": "The default reaches a modifier as the text the chain resolved to: a zero as its text, an array as JSON, neither skipped for being falsy.",
|
|
441
|
+
"section": "11",
|
|
442
|
+
"message": "{{a:read}} {{b:read}}",
|
|
443
|
+
"payload": {
|
|
444
|
+
"a": {
|
|
445
|
+
"value": "x",
|
|
446
|
+
"default": 0
|
|
447
|
+
},
|
|
448
|
+
"b": {
|
|
449
|
+
"value": "y",
|
|
450
|
+
"default": [
|
|
451
|
+
1,
|
|
452
|
+
2
|
|
453
|
+
]
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
"modifiers": {
|
|
457
|
+
"read": "default"
|
|
458
|
+
},
|
|
459
|
+
"expected": {
|
|
460
|
+
"output": "0 [1,2]"
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
"id": "extensions/default-skips-undescribable-link",
|
|
465
|
+
"description": "A link of the chain that no conversion can describe is skipped when a modifier reads its default, and reported against the payload.",
|
|
466
|
+
"section": "10",
|
|
467
|
+
"message": "{{v:read; default:Inline}}",
|
|
468
|
+
"payload": {
|
|
469
|
+
"v": "x",
|
|
470
|
+
"default": {
|
|
471
|
+
"$curly": "unserializable"
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
"key": "extensions.undescribable-link",
|
|
475
|
+
"modifiers": {
|
|
476
|
+
"read": "default"
|
|
477
|
+
},
|
|
478
|
+
"expected": {
|
|
479
|
+
"output": "Inline",
|
|
480
|
+
"reports": [
|
|
481
|
+
{
|
|
482
|
+
"code": "unserializable-value",
|
|
483
|
+
"origin": "payload",
|
|
484
|
+
"key": "extensions.undescribable-link"
|
|
485
|
+
}
|
|
486
|
+
]
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
"id": "extensions/default-unread-is-not-reported",
|
|
491
|
+
"description": "A modifier that answers without its default leaves the chain unread, so a link nothing needed is neither converted nor reported.",
|
|
492
|
+
"section": "10",
|
|
493
|
+
"message": "{{v:echo}}",
|
|
494
|
+
"payload": {
|
|
495
|
+
"v": "x",
|
|
496
|
+
"default": {
|
|
497
|
+
"$curly": "unserializable"
|
|
498
|
+
}
|
|
499
|
+
},
|
|
500
|
+
"key": "extensions.unread-link",
|
|
501
|
+
"modifiers": {
|
|
502
|
+
"echo": "echo"
|
|
503
|
+
},
|
|
504
|
+
"expected": {
|
|
505
|
+
"output": "x",
|
|
506
|
+
"reports": []
|
|
507
|
+
}
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
"id": "extensions/props-layered",
|
|
511
|
+
"description": "A host-defined modifier receives its props layered as section 11.2 layers them: the defaults, then the props, then the wrapper's props, each overriding only what it names.",
|
|
512
|
+
"section": "11.3",
|
|
513
|
+
"message": "{{v:p}}",
|
|
514
|
+
"payload": {
|
|
515
|
+
"v": {
|
|
516
|
+
"value": "x",
|
|
517
|
+
"props": {
|
|
518
|
+
"p": {
|
|
519
|
+
"c": 3
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
"props": {
|
|
525
|
+
"p": {
|
|
526
|
+
"b": 2,
|
|
527
|
+
"c": 2
|
|
528
|
+
}
|
|
529
|
+
},
|
|
530
|
+
"modifiers": {
|
|
531
|
+
"p": "props"
|
|
532
|
+
},
|
|
533
|
+
"defaults": {
|
|
534
|
+
"p": {
|
|
535
|
+
"a": 1,
|
|
536
|
+
"b": 1,
|
|
537
|
+
"c": 1
|
|
538
|
+
}
|
|
539
|
+
},
|
|
540
|
+
"expected": {
|
|
541
|
+
"output": "a=1,b=2,c=3"
|
|
542
|
+
}
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
"id": "extensions/props-null-names-a-property",
|
|
546
|
+
"description": "A property a layer holds null under is one it names, so null overrides the layer beneath and reaches the modifier.",
|
|
547
|
+
"section": "11.2",
|
|
548
|
+
"message": "{{v:p}}",
|
|
549
|
+
"payload": {
|
|
550
|
+
"v": "x"
|
|
551
|
+
},
|
|
552
|
+
"props": {
|
|
553
|
+
"p": {
|
|
554
|
+
"a": null
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
"modifiers": {
|
|
558
|
+
"p": "props"
|
|
559
|
+
},
|
|
560
|
+
"defaults": {
|
|
561
|
+
"p": {
|
|
562
|
+
"a": 1,
|
|
563
|
+
"b": 2
|
|
564
|
+
}
|
|
565
|
+
},
|
|
566
|
+
"expected": {
|
|
567
|
+
"output": "a=null,b=2"
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
"id": "extensions/props-undefined-names-nothing",
|
|
572
|
+
"description": "A property a layer holds the host's undefined under is one it does not name, so the layer beneath keeps it.",
|
|
573
|
+
"section": "11.2",
|
|
574
|
+
"message": "{{v:p}}",
|
|
575
|
+
"payload": {
|
|
576
|
+
"v": "x"
|
|
577
|
+
},
|
|
578
|
+
"props": {
|
|
579
|
+
"p": {
|
|
580
|
+
"a": {
|
|
581
|
+
"$curly": "undefined"
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
},
|
|
585
|
+
"modifiers": {
|
|
586
|
+
"p": "props"
|
|
587
|
+
},
|
|
588
|
+
"defaults": {
|
|
589
|
+
"p": {
|
|
590
|
+
"a": 1,
|
|
591
|
+
"b": 2
|
|
592
|
+
}
|
|
593
|
+
},
|
|
594
|
+
"expected": {
|
|
595
|
+
"output": "a=1,b=2"
|
|
596
|
+
}
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
"id": "extensions/props-own-name-only",
|
|
600
|
+
"description": "A modifier receives what the layers wrote under its own name and nothing they wrote under another's.",
|
|
601
|
+
"section": "11.3",
|
|
602
|
+
"message": "{{v:p}}",
|
|
603
|
+
"payload": {
|
|
604
|
+
"v": {
|
|
605
|
+
"value": "x",
|
|
606
|
+
"props": {
|
|
607
|
+
"number": {
|
|
608
|
+
"z": 3
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
},
|
|
613
|
+
"props": {
|
|
614
|
+
"number": {
|
|
615
|
+
"y": 2
|
|
616
|
+
},
|
|
617
|
+
"p": {
|
|
618
|
+
"a": 1
|
|
619
|
+
}
|
|
620
|
+
},
|
|
621
|
+
"modifiers": {
|
|
622
|
+
"p": "props"
|
|
623
|
+
},
|
|
624
|
+
"defaults": {
|
|
625
|
+
"number": {
|
|
626
|
+
"x": 1
|
|
627
|
+
}
|
|
628
|
+
},
|
|
629
|
+
"expected": {
|
|
630
|
+
"output": "a=1"
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
"id": "extensions/props-none",
|
|
635
|
+
"description": "Where no layer wrote under its name, a modifier receives no properties at all, whatever the layers wrote under other names.",
|
|
636
|
+
"section": "11.3",
|
|
637
|
+
"message": "[{{v:p}}]",
|
|
638
|
+
"payload": {
|
|
639
|
+
"v": {
|
|
640
|
+
"value": "x",
|
|
641
|
+
"props": {
|
|
642
|
+
"number": {
|
|
643
|
+
"z": 3
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
},
|
|
648
|
+
"props": {
|
|
649
|
+
"number": {
|
|
650
|
+
"y": 2
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
"key": "extensions.props-none",
|
|
654
|
+
"modifiers": {
|
|
655
|
+
"p": "props"
|
|
656
|
+
},
|
|
657
|
+
"defaults": {
|
|
658
|
+
"number": {
|
|
659
|
+
"x": 1
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
"expected": {
|
|
663
|
+
"output": "[]",
|
|
664
|
+
"reports": []
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
"id": "extensions/replaced-number-props-none",
|
|
669
|
+
"description": "A host modifier registered under a formatting modifier's name receives only the three layers of section 11.3, so where none wrote under that name it receives no properties, not the defaults section 11.2 states for the modifier it replaced.",
|
|
670
|
+
"section": "11.3",
|
|
671
|
+
"message": "[{{v:number}}]",
|
|
672
|
+
"payload": {
|
|
673
|
+
"v": "x"
|
|
674
|
+
},
|
|
675
|
+
"key": "extensions.replaced-number-props-none",
|
|
676
|
+
"modifiers": {
|
|
677
|
+
"number": "props"
|
|
678
|
+
},
|
|
679
|
+
"expected": {
|
|
680
|
+
"output": "[]",
|
|
681
|
+
"reports": []
|
|
682
|
+
}
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
"id": "extensions/locale",
|
|
686
|
+
"description": "A host-defined modifier receives the locale the caller supplied.",
|
|
687
|
+
"section": "11",
|
|
688
|
+
"message": "{{v:loc}}",
|
|
689
|
+
"payload": {
|
|
690
|
+
"v": "x"
|
|
691
|
+
},
|
|
692
|
+
"locale": "cs",
|
|
693
|
+
"modifiers": {
|
|
694
|
+
"loc": "locale"
|
|
695
|
+
},
|
|
696
|
+
"expected": {
|
|
697
|
+
"output": "cs"
|
|
698
|
+
}
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
"id": "extensions/locale-none",
|
|
702
|
+
"description": "A host-defined modifier receives no locale where the caller supplied none.",
|
|
703
|
+
"section": "11",
|
|
704
|
+
"message": "{{v:loc}}",
|
|
705
|
+
"payload": {
|
|
706
|
+
"v": "x"
|
|
707
|
+
},
|
|
708
|
+
"modifiers": {
|
|
709
|
+
"loc": "locale"
|
|
710
|
+
},
|
|
711
|
+
"expected": {
|
|
712
|
+
"output": "none"
|
|
713
|
+
}
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
"id": "extensions/locale-as-supplied",
|
|
717
|
+
"description": "A locale the caller supplied is available whatever the host makes of it, so a host-defined modifier receives it as written.",
|
|
718
|
+
"section": "11.2",
|
|
719
|
+
"message": "{{v:loc}}",
|
|
720
|
+
"payload": {
|
|
721
|
+
"v": "x"
|
|
722
|
+
},
|
|
723
|
+
"locale": "not a locale",
|
|
724
|
+
"modifiers": {
|
|
725
|
+
"loc": "locale"
|
|
726
|
+
},
|
|
727
|
+
"expected": {
|
|
728
|
+
"output": "not a locale"
|
|
729
|
+
}
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
"id": "extensions/empty-answer-is-an-answer",
|
|
733
|
+
"description": "The empty string is an answer, so the placeholder does not take the chain.",
|
|
734
|
+
"section": "11",
|
|
735
|
+
"message": "[{{v:empty; default:D}}]",
|
|
736
|
+
"payload": {
|
|
737
|
+
"v": "x"
|
|
738
|
+
},
|
|
739
|
+
"modifiers": {
|
|
740
|
+
"empty": "empty"
|
|
741
|
+
},
|
|
742
|
+
"expected": {
|
|
743
|
+
"output": "[]"
|
|
744
|
+
}
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
"id": "extensions/nothing-takes-the-chain",
|
|
748
|
+
"description": "An answer that is nothing at all is no answer: the placeholder takes the chain, and no code of the closed set names the condition.",
|
|
749
|
+
"section": "11",
|
|
750
|
+
"message": "[{{v:nothing; default:D}}]",
|
|
751
|
+
"payload": {
|
|
752
|
+
"v": "x"
|
|
753
|
+
},
|
|
754
|
+
"key": "extensions.nothing",
|
|
755
|
+
"modifiers": {
|
|
756
|
+
"nothing": "nothing"
|
|
757
|
+
},
|
|
758
|
+
"expected": {
|
|
759
|
+
"output": "[D]",
|
|
760
|
+
"reports": []
|
|
761
|
+
}
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
"id": "extensions/object-answer-serializes",
|
|
765
|
+
"description": "A structured answer serializes rather than collapsing to the host's word for an object.",
|
|
766
|
+
"section": "11",
|
|
767
|
+
"message": "{{v:obj}}",
|
|
768
|
+
"payload": {
|
|
769
|
+
"v": "X"
|
|
770
|
+
},
|
|
771
|
+
"modifiers": {
|
|
772
|
+
"obj": "object"
|
|
773
|
+
},
|
|
774
|
+
"expected": {
|
|
775
|
+
"output": "{\"answer\":\"X\"}"
|
|
776
|
+
}
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
"id": "extensions/raise-is-contained",
|
|
780
|
+
"description": "A host-defined modifier that raises is contained: the placeholder resolves to the chain, which here ends in the empty string, and the failure is reported.",
|
|
781
|
+
"section": "11.3",
|
|
782
|
+
"message": "{{v:x-boom}}",
|
|
783
|
+
"payload": {
|
|
784
|
+
"v": "x"
|
|
785
|
+
},
|
|
786
|
+
"key": "extensions.raise",
|
|
787
|
+
"modifiers": {
|
|
788
|
+
"x-boom": "raise"
|
|
789
|
+
},
|
|
790
|
+
"expected": {
|
|
791
|
+
"output": "",
|
|
792
|
+
"reports": [
|
|
793
|
+
{
|
|
794
|
+
"code": "failed-modifier",
|
|
795
|
+
"origin": "payload",
|
|
796
|
+
"key": "extensions.raise"
|
|
797
|
+
}
|
|
798
|
+
]
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
"id": "extensions/raise-reported-against-payload",
|
|
803
|
+
"description": "A host-defined modifier that raised is the caller's defect: failed-modifier declares the origin payload, the placeholder takes its declared default, and the rest of the message still renders.",
|
|
804
|
+
"section": "14.2",
|
|
805
|
+
"message": "[{{v:raise; default:D}}] {{w}}",
|
|
806
|
+
"payload": {
|
|
807
|
+
"v": "x",
|
|
808
|
+
"w": "w"
|
|
809
|
+
},
|
|
810
|
+
"key": "extensions.raise-origin",
|
|
811
|
+
"modifiers": {
|
|
812
|
+
"raise": "raise"
|
|
813
|
+
},
|
|
814
|
+
"expected": {
|
|
815
|
+
"output": "[D] w",
|
|
816
|
+
"reports": [
|
|
817
|
+
{
|
|
818
|
+
"code": "failed-modifier",
|
|
819
|
+
"origin": "payload",
|
|
820
|
+
"key": "extensions.raise-origin"
|
|
821
|
+
}
|
|
822
|
+
]
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
]
|
|
826
|
+
}
|