@discord/intl 0.2.1-rc.1 → 0.2.1-rc.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.
@@ -4,7 +4,7 @@ import { IntlManager } from '../intl-manager';
4
4
  * Types for formatting functions when calling `formatToParts`, ensuring the
5
5
  * functions yield value AST nodes.
6
6
  */
7
- export type AstFunctionTypes = FunctionTypes<RichTextNode>;
7
+ export type AstFunctionTypes = FunctionTypes<RichTextNode, object>;
8
8
  export declare enum RichTextNodeType {
9
9
  Text = "text",
10
10
  Strong = "strong",
@@ -65,14 +65,6 @@ var RichTextNodeType;
65
65
  */
66
66
  RichTextNodeType["Object"] = "object";
67
67
  })(RichTextNodeType || (exports.RichTextNodeType = RichTextNodeType = {}));
68
- var RICH_TEXT_TAG_TYPES = {
69
- $_: RichTextNodeType.Text,
70
- $b: RichTextNodeType.Strong,
71
- $i: RichTextNodeType.Emphasis,
72
- $code: RichTextNodeType.Code,
73
- $link: RichTextNodeType.Link,
74
- $p: RichTextNodeType.Paragraph,
75
- };
76
68
  var AST_RICH_TEXT_ELEMENTS = {
77
69
  $_: function () { return ({ type: RichTextNodeType.Text, content: '' }); },
78
70
  $b: function (content) { return ({ type: RichTextNodeType.Strong, content: content }); },
@@ -100,7 +92,7 @@ var AstBuilder = /** @class */ (function (_super) {
100
92
  if (!(tag in AST_RICH_TEXT_ELEMENTS)) {
101
93
  throw "".concat(tag, " is not a known rich text formatting tag");
102
94
  }
103
- var result = AST_RICH_TEXT_ELEMENTS[tag](children);
95
+ var result = AST_RICH_TEXT_ELEMENTS[tag](children, '');
104
96
  if (Array.isArray(result)) {
105
97
  (_a = this.result).push.apply(_a, __spreadArray([], __read(result), false));
106
98
  }
@@ -62,7 +62,7 @@ var MarkdownBuilder = /** @class */ (function (_super) {
62
62
  return _this;
63
63
  }
64
64
  MarkdownBuilder.prototype.pushRichTextTag = function (tag, children) {
65
- this.result += MARKDOWN_RICH_TEXT_ELEMENTS[tag](children);
65
+ this.result += MARKDOWN_RICH_TEXT_ELEMENTS[tag](children, '');
66
66
  };
67
67
  return MarkdownBuilder;
68
68
  }(string_1.StringBuilder));
@@ -18,11 +18,14 @@ export type ReactFunctionTypes = FunctionTypes<React.ReactNode, ReactClickHandle
18
18
  onContextMenu: ReactClickHandler;
19
19
  }>;
20
20
  export declare const DEFAULT_REACT_RICH_TEXT_ELEMENTS: RichTextFormattingMap<ReactFunctionTypes['hook']>;
21
- export declare function formatReact(this: IntlManager, message: AnyIntlMessage, values: object, Builder: FormatBuilderConstructor<React.ReactElement>): React.ReactElement;
21
+ export type ReactIntlMessage = React.ReactElement<{}, typeof React.Fragment & {
22
+ __brand: 'discord-intl';
23
+ }>;
24
+ export declare function formatReact(this: IntlManager, message: AnyIntlMessage, values: object, Builder: FormatBuilderConstructor<React.ReactElement>): ReactIntlMessage;
22
25
  /**
23
26
  * Create a new React formatter with the given rich text elements replacing the defaults. Use this
24
27
  * function to inject custom components for things like links and paragraphs, which may be best
25
28
  * suited to use components from a Design System or other library rather than native DOM elements.
26
29
  */
27
- export declare function makeReactFormatter(richTextElements: RichTextFormattingMap<ReactFunctionTypes['hook']>): FormatterImplementation<ReactFunctionTypes, React.ReactElement, React.ReactNode>;
28
- export declare const reactFormatter: FormatterImplementation<ReactFunctionTypes, React.ReactElement<any, string | React.JSXElementConstructor<any>>, React.ReactNode>;
30
+ export declare function makeReactFormatter(richTextElements: RichTextFormattingMap<ReactFunctionTypes['hook']>): FormatterImplementation<ReactFunctionTypes, ReactIntlMessage, React.ReactNode>;
31
+ export declare const reactFormatter: FormatterImplementation<ReactFunctionTypes, ReactIntlMessage, React.ReactNode>;
@@ -48,15 +48,15 @@ var format_1 = require("../format");
48
48
  var h = React.createElement;
49
49
  exports.DEFAULT_REACT_RICH_TEXT_ELEMENTS = {
50
50
  $_: function () { return ''; },
51
- $b: function (content) { return h('strong', undefined, content); },
52
- $code: function (content) { return h('code', undefined, content); },
53
- $i: function (content) { return h('em', undefined, content); },
51
+ $b: function (content, key) { return h('strong', { key: key }, content); },
52
+ $code: function (content, key) { return h('code', { key: key }, content); },
53
+ $i: function (content, key) { return h('em', { key: key }, content); },
54
54
  // $link will always be [href, <empty>, ...content]
55
- $link: function (_a) {
55
+ $link: function (_a, key) {
56
56
  var _b = __read(_a), href = _b[0], content = _b.slice(1);
57
- return h('a', { href: href }, content);
57
+ return h('a', { href: href, key: key }, content);
58
58
  },
59
- $p: function (content) { return h('p', undefined, content); },
59
+ $p: function (content, key) { return h('p', { key: key }, content); },
60
60
  };
61
61
  /**
62
62
  * Creates a new `FormatBuilder` class that constructs a React element tree
@@ -70,11 +70,12 @@ function createReactBuilder(richTextElements) {
70
70
  __extends(class_1, _super);
71
71
  function class_1() {
72
72
  var _this = _super.apply(this, __spreadArray([], __read(arguments), false)) || this;
73
+ _this._nodeKey = 0;
73
74
  _this.result = [];
74
75
  return _this;
75
76
  }
76
77
  class_1.prototype.pushRichTextTag = function (tag, children) {
77
- this.result.push(richTextElements[tag](children));
78
+ this.result.push(richTextElements[tag](children, "".concat(this._nodeKey++)));
78
79
  };
79
80
  class_1.prototype.pushLiteralText = function (text) {
80
81
  this.result.push(text);
@@ -7,7 +7,7 @@ import { FormatBuilderConstructor } from './format';
7
7
  * requested locale is not possible.
8
8
  */
9
9
  export declare const DEFAULT_LOCALE: string;
10
- type FormatterReturnType<F extends FormatterImplementation<any, any>> = F extends FormatterImplementation<any, infer Return> ? Return : never;
10
+ type FormatterReturnType<F extends FormatterImplementation<any, any>> = ReturnType<F['format']>;
11
11
  type FormatterFunctionTypes<F extends FormatterImplementation<any, any>> = F extends FormatterImplementation<infer Functions, any> ? Functions : never;
12
12
  export type FormatFunction<F extends FormatterImplementation<any, any>> = <T extends IntlMessageGetter>(this: IntlManager, message: T, values: RequiredFormatValues<T, FormatterFunctionTypes<F>>) => FormatterReturnType<F>;
13
13
  type ThisWithFormatters<This, T extends Record<string, FormatterImplementation<any, any>>> = This & {
package/dist/types.d.ts CHANGED
@@ -197,9 +197,9 @@ export interface FunctionTypeMap {
197
197
  handler: any;
198
198
  }
199
199
 
200
- export interface FunctionTypes<Result, HandlerType = (content: Result[]) => Result | Result[]> {
201
- link: undefined | ((content: Result[]) => Result | Result[]);
202
- hook: undefined | ((content: Result[]) => Result | Result[]);
200
+ export interface FunctionTypes<Result, HandlerType = () => void> {
201
+ link: undefined | ((content: Result[], key: string) => Result | Result[]);
202
+ hook: undefined | ((content: Result[], key: string) => Result | Result[]);
203
203
  handler: undefined | HandlerType;
204
204
  }
205
205
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@discord/intl",
3
- "version": "0.2.1-rc.1",
3
+ "version": "0.2.1-rc.2",
4
4
  "license": "MIT",
5
5
  "description": "Client runtime for managing messages and translations in a React project.",
6
6
  "main": "./dist/index.js",
@@ -12,7 +12,7 @@ import { FormatBuilder } from '../format';
12
12
  * Types for formatting functions when calling `formatToParts`, ensuring the
13
13
  * functions yield value AST nodes.
14
14
  */
15
- export type AstFunctionTypes = FunctionTypes<RichTextNode>;
15
+ export type AstFunctionTypes = FunctionTypes<RichTextNode, object>;
16
16
 
17
17
  // This structure aims to match `simple-markdown`'s AST, but that type is very
18
18
  // loosely defined as just "type" and "arbitrary map of content". This is more
@@ -36,15 +36,6 @@ export enum RichTextNodeType {
36
36
  Object = 'object',
37
37
  }
38
38
 
39
- const RICH_TEXT_TAG_TYPES: Record<RichTextTagNames, RichTextNodeType> = {
40
- $_: RichTextNodeType.Text,
41
- $b: RichTextNodeType.Strong,
42
- $i: RichTextNodeType.Emphasis,
43
- $code: RichTextNodeType.Code,
44
- $link: RichTextNodeType.Link,
45
- $p: RichTextNodeType.Paragraph,
46
- };
47
-
48
39
  interface RichTextNodeBase<ContentType> {
49
40
  type: RichTextNodeType;
50
41
  content: ContentType;
@@ -101,7 +92,7 @@ class AstBuilder extends FormatBuilder<RichTextNode> {
101
92
  if (!(tag in AST_RICH_TEXT_ELEMENTS)) {
102
93
  throw `${tag} is not a known rich text formatting tag`;
103
94
  }
104
- const result = AST_RICH_TEXT_ELEMENTS[tag](children);
95
+ const result = AST_RICH_TEXT_ELEMENTS[tag](children, '');
105
96
  if (Array.isArray(result)) {
106
97
  this.result.push(...result);
107
98
  } else {
@@ -31,7 +31,7 @@ class MarkdownBuilder extends StringBuilder {
31
31
  result: string = '';
32
32
 
33
33
  pushRichTextTag(tag: RichTextTagNames, children: string[]) {
34
- this.result += MARKDOWN_RICH_TEXT_ELEMENTS[tag](children);
34
+ this.result += MARKDOWN_RICH_TEXT_ELEMENTS[tag](children, '');
35
35
  }
36
36
  }
37
37
 
@@ -28,12 +28,12 @@ export type ReactFunctionTypes = FunctionTypes<
28
28
  const h = React.createElement;
29
29
  export const DEFAULT_REACT_RICH_TEXT_ELEMENTS: RichTextFormattingMap<ReactFunctionTypes['hook']> = {
30
30
  $_: () => '',
31
- $b: (content) => h('strong', undefined, content),
32
- $code: (content) => h('code', undefined, content),
33
- $i: (content) => h('em', undefined, content),
31
+ $b: (content, key) => h('strong', { key }, content),
32
+ $code: (content, key) => h('code', { key }, content),
33
+ $i: (content, key) => h('em', { key }, content),
34
34
  // $link will always be [href, <empty>, ...content]
35
- $link: ([href, ...content]) => h('a', { href }, content),
36
- $p: (content) => h('p', undefined, content),
35
+ $link: ([href, ...content], key) => h('a', { href, key }, content),
36
+ $p: (content, key) => h('p', { key }, content),
37
37
  };
38
38
 
39
39
  /**
@@ -47,10 +47,11 @@ function createReactBuilder(richTextElements: RichTextFormattingMap<ReactFunctio
47
47
  new (): FormatBuilder<React.ReactNode>;
48
48
  } {
49
49
  return class extends FormatBuilder<React.ReactNode> {
50
+ _nodeKey: number = 0;
50
51
  result: React.ReactNode[] = [];
51
52
 
52
53
  pushRichTextTag(tag: RichTextTagNames, children: React.ReactNode[]) {
53
- this.result.push(richTextElements[tag](children));
54
+ this.result.push(richTextElements[tag](children, `${this._nodeKey++}`));
54
55
  }
55
56
 
56
57
  pushLiteralText(text: string) {
@@ -69,18 +70,23 @@ function createReactBuilder(richTextElements: RichTextFormattingMap<ReactFunctio
69
70
  };
70
71
  }
71
72
 
73
+ export type ReactIntlMessage = React.ReactElement<
74
+ {},
75
+ typeof React.Fragment & { __brand: 'discord-intl' }
76
+ >;
77
+
72
78
  export function formatReact(
73
79
  this: IntlManager,
74
80
  message: AnyIntlMessage,
75
81
  values: object,
76
82
  Builder: FormatBuilderConstructor<React.ReactElement>,
77
- ): React.ReactElement {
83
+ ): ReactIntlMessage {
78
84
  if (typeof message === 'string') {
79
- return React.createElement(React.Fragment, undefined, message);
85
+ return React.createElement(React.Fragment, undefined, message) as ReactIntlMessage;
80
86
  }
81
87
 
82
88
  const parts = this.bindFormatValues(Builder, message, values);
83
- return React.createElement(React.Fragment, undefined, parts);
89
+ return React.createElement(React.Fragment, undefined, parts) as ReactIntlMessage;
84
90
  }
85
91
 
86
92
  /**
@@ -90,7 +96,7 @@ export function formatReact(
90
96
  */
91
97
  export function makeReactFormatter(
92
98
  richTextElements: RichTextFormattingMap<ReactFunctionTypes['hook']>,
93
- ): FormatterImplementation<ReactFunctionTypes, React.ReactElement, React.ReactNode> {
99
+ ): FormatterImplementation<ReactFunctionTypes, ReactIntlMessage, React.ReactNode> {
94
100
  return {
95
101
  format: formatReact,
96
102
  builder: createReactBuilder(richTextElements),
package/src/index.ts CHANGED
@@ -26,6 +26,7 @@ export type * from './types.d.ts';
26
26
  * intl message, even if the actual value comes from elsewhere (like a
27
27
  * user-generated string).
28
28
  */
29
+ // TODO: Replace this with ReactIntlMessage from `formatters/react`.
29
30
  export type ReactIntlMessage = string | React.ReactElement;
30
31
 
31
32
  /**
@@ -1,8 +1,6 @@
1
1
  import { createIntl, IntlShape } from '@formatjs/intl';
2
2
  import { Formats, Formatters, IntlMessageFormat } from 'intl-messageformat';
3
3
 
4
- import { LocaleId, LocaleImportMap, MessageLoader } from './message-loader';
5
-
6
4
  import type {
7
5
  FormatterImplementation,
8
6
  IntlMessageGetter,
@@ -18,8 +16,7 @@ import { bindFormatValues, FormatBuilderConstructor } from './format';
18
16
  */
19
17
  export const DEFAULT_LOCALE: string = 'en-US';
20
18
 
21
- type FormatterReturnType<F extends FormatterImplementation<any, any>> =
22
- F extends FormatterImplementation<any, infer Return> ? Return : never;
19
+ type FormatterReturnType<F extends FormatterImplementation<any, any>> = ReturnType<F['format']>;
23
20
 
24
21
  type FormatterFunctionTypes<F extends FormatterImplementation<any, any>> =
25
22
  F extends FormatterImplementation<infer Functions, any> ? Functions : never;
package/src/types.d.ts CHANGED
@@ -197,9 +197,9 @@ export interface FunctionTypeMap {
197
197
  handler: any;
198
198
  }
199
199
 
200
- export interface FunctionTypes<Result, HandlerType = (content: Result[]) => Result | Result[]> {
201
- link: undefined | ((content: Result[]) => Result | Result[]);
202
- hook: undefined | ((content: Result[]) => Result | Result[]);
200
+ export interface FunctionTypes<Result, HandlerType = () => void> {
201
+ link: undefined | ((content: Result[], key: string) => Result | Result[]);
202
+ hook: undefined | ((content: Result[], key: string) => Result | Result[]);
203
203
  handler: undefined | HandlerType;
204
204
  }
205
205