@sveltekit-i18n/parser-curly 3.0.0-next.0 → 3.0.0-next.2

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/README.md CHANGED
@@ -378,6 +378,40 @@ i18n.t('common.welcome', { aplicationName: 'My app' })
378
378
 
379
379
  `Config<Payload, Props>` types the payload and the props `i18n.t` accepts; left bare, `Config` accepts any payload key and the built-in modifiers' props. A custom modifier types its own props through `Modifier.T<OwnProps>`. The factory's type arguments check the parser options the same way: with `Props` spelled as the second, `parser<Payload, Props>({ ... })`, a `modifierDefaults` entry for a custom modifier is checked; a modifier written inline reads typed `props` once the modifier names are spelled as the third argument too, `parser<Payload, Props, 'truncate'>({ ... })`. `Parser` holds the option and parameter types (`Parser.Options`, `Parser.OnReport`, `Parser.Params`, `Parser.Payload`), `Modifier` the modifier and wrapper types (`Modifier.T`, `Modifier.Wrapper`, `Modifier.Props`), and `Report` is the report.
380
380
 
381
+ ## Extracting Parameters
382
+
383
+ What a message expects of its payload is fixed when the message is written, so a catalogue can be read for its parameters instead of them being discovered at render time. `extractParamsFactory` is the build-time half of the base parser contract, a named export beside the default one: a message scanner is of no use while rendering, so the package declares `sideEffects: false` and a bundle that never reaches it drops it.
384
+
385
+ ```typescript
386
+ import { extractParamsFactory } from '@sveltekit-i18n/parser-curly';
387
+
388
+ const extractParams = extractParamsFactory();
389
+
390
+ extractParams('You have {{count:number;}} {{count; 1:message; default:messages;}}.');
391
+ // → [{ name: 'count', kind: 'number', values: ['1'], optional: true }]
392
+ ```
393
+
394
+ Each parameter is reported once, in the order the message first names it, and says what every placeholder naming it says together. `name` is the payload key, already unescaped and arbitrary text rather than an identifier, so whatever writes it down quotes it. `kind` is what the modifiers narrow the value to; every value reaches a modifier as text, so a modifier reading it as text narrows nothing and the parameter accepts `unknown`.
395
+
396
+ | Modifier | `kind` |
397
+ | --- | --- |
398
+ | none, `eq`, `ne` | `'unknown'` |
399
+ | `lt`, `gt` | `'number'` |
400
+ | `lte`, `gte` | `['number', 'string']` — the equality leg selects on text before the numeric one is reached |
401
+ | `number`, `currency` | `'number'` |
402
+ | `ago` | `'number'` — a signed millisecond delta relative to now, not a point in time |
403
+ | `date` | `['date', 'string']` — milliseconds since the epoch, and failing that text the host reads as a date |
404
+
405
+ A parameter several placeholders name accepts what all of them say together, and `unknown` is the top of that lattice rather than a member of it: it is what a parameter accepts while nothing has narrowed it, and it drops out the moment something does. So `{{count}}` alone reports `unknown`, and the example above — where a second placeholder formats the same key with `number` — reports `'number'` rather than `['unknown', 'number']`.
406
+
407
+ `values` lists the option keys of an `eq` selection, which is the one comparison whose keys are values of the parameter: `ne`'s are what the value must differ from, and an inequality's are thresholds it is ordered against. It is a hint and never a closed set — a value none of them matches takes the fallback chain rather than failing.
408
+
409
+ `optional` reports what the message says rather than what resolution tolerates. Every placeholder renders without its value, an absent one taking the fallback chain, so a placeholder declaring an inline `default` is the message saying the value may be missing, and one declaring none is the message saying it is expected.
410
+
411
+ Build the extractor from the same options `parser()` is built from: a custom modifier registered under a name the format defines changes what a message naming it says about its value. `onReport` is not required here, and neither it nor `modifierDefaults` reaches anything — extraction formats nothing and reports nothing.
412
+
413
+ Only the text of a message is scanned. A translation leaf that is not text names no parameters rather than throwing, and a placeholder a payload value carries into a later interpolation pass is not one the message itself names.
414
+
381
415
  ## Examples
382
416
 
383
417
  See the [parser-curly example](https://github.com/sveltekit-i18n/lib/tree/master/examples/parser-default) for a complete working application.
package/dist/index.d.ts CHANGED
@@ -23,6 +23,23 @@ declare namespace Parser {
23
23
  type Params<P = PayloadDefault, M = Modifier.DefaultProps> = [payload?: Payload<P, M>, props?: Modifier.Props<M>];
24
24
  type T<P extends Parser$2.Params = Params> = Parser$2.T<P, string>;
25
25
  type Factory = <Payload = {}, Props = {}, Key extends string = Modifier.Key>(options: Options<Key, Props>) => T<Params<Payload & PayloadDefault, Props & Modifier.DefaultProps>>;
26
+ /**
27
+ * The options `extractParamsFactory()` takes: the same ones `parser()` takes,
28
+ * so an extractor is built the way the app builds its parser — a custom
29
+ * modifier registered under a name the format defines changes what a message
30
+ * naming it says about its value. `onReport` is not required here, and
31
+ * neither it nor `modifierDefaults` reaches anything: extraction formats
32
+ * nothing and reports nothing.
33
+ */
34
+ type ExtractOptions<Key extends string = Modifier.Key, Props = Modifier.DefaultProps> = Parser$1.Options<Key, Props>;
35
+ /**
36
+ * Reports the parameters a message names. The build-time half of the parser
37
+ * contract, which is why it is a named export rather than a member of the
38
+ * parser object: a message scanner is of no use while rendering, and a
39
+ * bundle that never reaches it drops it.
40
+ */
41
+ type ExtractParams = Parser$2.ExtractParams;
42
+ type ExtractParamsFactory = <Props = {}, Key extends string = Modifier.Key>(options?: ExtractOptions<Key, Props>) => ExtractParams;
26
43
  }
27
44
  /**
28
45
  * The base config carrying this parser, typed by the payload the messages
@@ -30,6 +47,15 @@ declare namespace Parser {
30
47
  */
31
48
  type Config<P = Parser.PayloadDefault, M = Modifier.DefaultProps> = Config$1.T<Parser.Params<P, M>, string>;
32
49
 
50
+ /**
51
+ * Builds the extractor the base library's build-time contract describes, from
52
+ * the same options `parser()` takes. The format's own scanner answers it: what
53
+ * a message expects of its payload is fixed when the message is written, so a
54
+ * catalogue is read for its parameters rather than them being discovered at
55
+ * render time.
56
+ */
57
+ declare const extractParamsFactory: Parser.ExtractParamsFactory;
58
+
33
59
  declare const parser: Parser.Factory;
34
60
 
35
- export { type Config, Parser, parser as default };
61
+ export { type Config, Parser, parser as default, extractParamsFactory };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{createParser as i}from"@curly-message/parser";var f=r=>{let{resolve:e}=i(r);return{parse:(o,[t,p],s,a)=>e(o,{payload:t,props:p,locale:s,key:a})}},c=f;export{c as default};
1
+ import{createParser as f}from"@curly-message/parser";import{createExtractor as i}from"@curly-message/parser";var c=i;var m=r=>{let{resolve:e}=f(r);return{parse:(t,[o,a],p,s)=>e(t,{payload:o,props:a,locale:p,key:s})}},n=m;export{n as default,c as extractParamsFactory};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltekit-i18n/parser-curly",
3
- "version": "3.0.0-next.0",
3
+ "version": "3.0.0-next.2",
4
4
  "description": "Curly Message Format parser for the sveltekit-i18n library.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -50,10 +50,10 @@
50
50
  "@sveltekit-i18n/base": "^3.0.0-next.0"
51
51
  },
52
52
  "dependencies": {
53
- "@curly-message/parser": "^1.0.0-next.2"
53
+ "@curly-message/parser": "^1.0.0"
54
54
  },
55
55
  "devDependencies": {
56
- "@curly-message/conformance": "^1.0.0-next.2",
56
+ "@curly-message/conformance": "^1.0.0",
57
57
  "@eslint/js": "^10.0.1",
58
58
  "@stylistic/eslint-plugin": "^5.10.0",
59
59
  "@sveltekit-i18n/base": "^3.0.0-next.0",