afformative 0.6.2 → 0.6.3

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
@@ -81,13 +81,13 @@ Although formatters can render icons or custom translation components, we often
81
81
 
82
82
  > Lexicographic sorting of items based on translations is a typical real world example, especially when you are using a custom React component for visualising the translation keys alongside the actual translations.
83
83
 
84
- This is where usage suggestions comes into play. Suggestions can be used to tell formatters that a value needs to be rendered with some special care. For example, pass `"primitive"` to tell a formatter that it should return a primitive value, such as a string.
84
+ This is where usage suggestions come into play. Suggestions can be used to tell formatters that a value needs to be rendered with some special care. For example, pass `"primitive"` to tell a formatter that it should return a primitive value, such as a string.
85
85
 
86
86
  ```js
87
87
  import { makeFormatter } from "afformative"
88
88
 
89
- const booleanFormatter = makeFormatter((value, usageSuggestions) => {
90
- if (usageSuggestions.includes("primitive")) {
89
+ const booleanFormatter = makeFormatter((value, suggestions) => {
90
+ if (suggestions.includes("primitive")) {
91
91
  return value ? "True" : "False"
92
92
  }
93
93
 
@@ -3,25 +3,18 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
6
- var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
7
6
 
8
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
8
 
10
9
  var _toConsumableArray__default = /*#__PURE__*/_interopDefaultLegacy(_toConsumableArray);
11
- var _objectWithoutProperties__default = /*#__PURE__*/_interopDefaultLegacy(_objectWithoutProperties);
12
10
 
13
- // TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly
14
- // verify the return type of the format definition based on the suggestions, printing errors such
15
- // as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'`
16
- // which is, of course, nonsense. Same applies to `FormatChainDefinition`.
17
- //
18
- // interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
19
- // <TSuggestion extends Suggestion>(
20
- // value: TInput,
21
- // usageSuggestions: TSuggestion[],
22
- // dataContext: Partial<TDataContext>,
23
- // ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput
24
- // }
11
+ var ensureFormatSuggestionIntegrity = function ensureFormatSuggestionIntegrity(suggestions) {
12
+ return suggestions.includes("primitive") || !suggestions.includes("comparable") ? suggestions : ["primitive"].concat(_toConsumableArray__default["default"](suggestions));
13
+ };
14
+
15
+ var ensureFormatAsPrimitiveSuggestionIntegrity = function ensureFormatAsPrimitiveSuggestionIntegrity(suggestions) {
16
+ return suggestions.includes("primitive") ? suggestions : ["primitive"].concat(_toConsumableArray__default["default"](suggestions));
17
+ };
25
18
 
26
19
  /**
27
20
  * Creates a new formatter.
@@ -30,38 +23,33 @@ var _objectWithoutProperties__default = /*#__PURE__*/_interopDefaultLegacy(_obje
30
23
  * @param formatterOptions Additional options for the formatter.
31
24
  */
32
25
  var makeFormatter = function makeFormatter(format, formatterOptions) {
33
- var formatter = function formatter(_ref) {
34
- var _format;
35
-
36
- var children = _ref.children,
37
- _ref$suggestions = _ref.suggestions,
38
- suggestions = _ref$suggestions === void 0 ? [] : _ref$suggestions,
39
- dataContext = _objectWithoutProperties__default['default'](_ref, ["children", "suggestions"]);
26
+ var formatter = function formatter(props) {
27
+ var _format, _props$suggestions;
40
28
 
41
- return (_format = format(children, suggestions, dataContext)) !== null && _format !== void 0 ? _format : null;
29
+ return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null;
42
30
  };
43
31
 
44
32
  formatter.displayName = formatterOptions === null || formatterOptions === void 0 ? void 0 : formatterOptions.displayName;
45
33
 
46
34
  formatter.format = function (value) {
47
- var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
35
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
48
36
  var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
49
- return format(value, usageSuggestions, dataContext);
37
+ return format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext);
50
38
  };
51
39
 
52
40
  formatter.formatAsPrimitive = function (value) {
53
- var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
41
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
54
42
  var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
55
- return format(value, ["primitive"].concat(_toConsumableArray__default['default'](usageSuggestions)), dataContext);
43
+ return format(value, ensureFormatAsPrimitiveSuggestionIntegrity(suggestions), dataContext);
56
44
  };
57
45
 
58
46
  formatter.wrap = function (nextFormat, nextFormatterOptions) {
59
- var nextFormatter = makeFormatter(function (value, usageSuggestions, dataContext) {
60
- var delegate = function delegate(delegatedValue, delegatedUsageSuggestions, delegatedDataContext) {
61
- return formatter.format(delegatedValue, delegatedUsageSuggestions !== null && delegatedUsageSuggestions !== void 0 ? delegatedUsageSuggestions : usageSuggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
47
+ var nextFormatter = makeFormatter(function (value, suggestions, dataContext) {
48
+ var delegate = function delegate(delegatedValue, delegatedSuggestions, delegatedDataContext) {
49
+ return formatter.format(delegatedValue, delegatedSuggestions !== null && delegatedSuggestions !== void 0 ? delegatedSuggestions : suggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
62
50
  };
63
51
 
64
- return nextFormat(delegate, value, usageSuggestions, dataContext);
52
+ return nextFormat(delegate, value, suggestions, dataContext);
65
53
  }, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions);
66
54
  nextFormatter.innerFormatter = formatter;
67
55
  return nextFormatter;
@@ -1,18 +1,12 @@
1
1
  import _toConsumableArray from '@babel/runtime/helpers/esm/toConsumableArray';
2
- import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
3
2
 
4
- // TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly
5
- // verify the return type of the format definition based on the suggestions, printing errors such
6
- // as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'`
7
- // which is, of course, nonsense. Same applies to `FormatChainDefinition`.
8
- //
9
- // interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
10
- // <TSuggestion extends Suggestion>(
11
- // value: TInput,
12
- // usageSuggestions: TSuggestion[],
13
- // dataContext: Partial<TDataContext>,
14
- // ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput
15
- // }
3
+ var ensureFormatSuggestionIntegrity = function ensureFormatSuggestionIntegrity(suggestions) {
4
+ return suggestions.includes("primitive") || !suggestions.includes("comparable") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions));
5
+ };
6
+
7
+ var ensureFormatAsPrimitiveSuggestionIntegrity = function ensureFormatAsPrimitiveSuggestionIntegrity(suggestions) {
8
+ return suggestions.includes("primitive") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions));
9
+ };
16
10
 
17
11
  /**
18
12
  * Creates a new formatter.
@@ -21,38 +15,33 @@ import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutPr
21
15
  * @param formatterOptions Additional options for the formatter.
22
16
  */
23
17
  var makeFormatter = function makeFormatter(format, formatterOptions) {
24
- var formatter = function formatter(_ref) {
25
- var _format;
26
-
27
- var children = _ref.children,
28
- _ref$suggestions = _ref.suggestions,
29
- suggestions = _ref$suggestions === void 0 ? [] : _ref$suggestions,
30
- dataContext = _objectWithoutProperties(_ref, ["children", "suggestions"]);
18
+ var formatter = function formatter(props) {
19
+ var _format, _props$suggestions;
31
20
 
32
- return (_format = format(children, suggestions, dataContext)) !== null && _format !== void 0 ? _format : null;
21
+ return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null;
33
22
  };
34
23
 
35
24
  formatter.displayName = formatterOptions === null || formatterOptions === void 0 ? void 0 : formatterOptions.displayName;
36
25
 
37
26
  formatter.format = function (value) {
38
- var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
27
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
39
28
  var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
40
- return format(value, usageSuggestions, dataContext);
29
+ return format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext);
41
30
  };
42
31
 
43
32
  formatter.formatAsPrimitive = function (value) {
44
- var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
33
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
45
34
  var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
46
- return format(value, ["primitive"].concat(_toConsumableArray(usageSuggestions)), dataContext);
35
+ return format(value, ensureFormatAsPrimitiveSuggestionIntegrity(suggestions), dataContext);
47
36
  };
48
37
 
49
38
  formatter.wrap = function (nextFormat, nextFormatterOptions) {
50
- var nextFormatter = makeFormatter(function (value, usageSuggestions, dataContext) {
51
- var delegate = function delegate(delegatedValue, delegatedUsageSuggestions, delegatedDataContext) {
52
- return formatter.format(delegatedValue, delegatedUsageSuggestions !== null && delegatedUsageSuggestions !== void 0 ? delegatedUsageSuggestions : usageSuggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
39
+ var nextFormatter = makeFormatter(function (value, suggestions, dataContext) {
40
+ var delegate = function delegate(delegatedValue, delegatedSuggestions, delegatedDataContext) {
41
+ return formatter.format(delegatedValue, delegatedSuggestions !== null && delegatedSuggestions !== void 0 ? delegatedSuggestions : suggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
53
42
  };
54
43
 
55
- return nextFormat(delegate, value, usageSuggestions, dataContext);
44
+ return nextFormat(delegate, value, suggestions, dataContext);
56
45
  }, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions);
57
46
  nextFormatter.innerFormatter = formatter;
58
47
  return nextFormatter;
@@ -2,7 +2,7 @@
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
3
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Afformative = {}));
5
- }(this, (function (exports) { 'use strict';
5
+ })(this, (function (exports) { 'use strict';
6
6
 
7
7
  function _arrayLikeToArray(arr, len) {
8
8
  if (len == null || len > arr.length) len = arr.length;
@@ -39,52 +39,13 @@ function _toConsumableArray(arr) {
39
39
  return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
40
40
  }
41
41
 
42
- function _objectWithoutPropertiesLoose(source, excluded) {
43
- if (source == null) return {};
44
- var target = {};
45
- var sourceKeys = Object.keys(source);
46
- var key, i;
47
-
48
- for (i = 0; i < sourceKeys.length; i++) {
49
- key = sourceKeys[i];
50
- if (excluded.indexOf(key) >= 0) continue;
51
- target[key] = source[key];
52
- }
53
-
54
- return target;
55
- }
56
-
57
- function _objectWithoutProperties(source, excluded) {
58
- if (source == null) return {};
59
- var target = _objectWithoutPropertiesLoose(source, excluded);
60
- var key, i;
61
-
62
- if (Object.getOwnPropertySymbols) {
63
- var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
64
-
65
- for (i = 0; i < sourceSymbolKeys.length; i++) {
66
- key = sourceSymbolKeys[i];
67
- if (excluded.indexOf(key) >= 0) continue;
68
- if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
69
- target[key] = source[key];
70
- }
71
- }
72
-
73
- return target;
74
- }
42
+ var ensureFormatSuggestionIntegrity = function ensureFormatSuggestionIntegrity(suggestions) {
43
+ return suggestions.includes("primitive") || !suggestions.includes("comparable") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions));
44
+ };
75
45
 
76
- // TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly
77
- // verify the return type of the format definition based on the suggestions, printing errors such
78
- // as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'`
79
- // which is, of course, nonsense. Same applies to `FormatChainDefinition`.
80
- //
81
- // interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
82
- // <TSuggestion extends Suggestion>(
83
- // value: TInput,
84
- // usageSuggestions: TSuggestion[],
85
- // dataContext: Partial<TDataContext>,
86
- // ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput
87
- // }
46
+ var ensureFormatAsPrimitiveSuggestionIntegrity = function ensureFormatAsPrimitiveSuggestionIntegrity(suggestions) {
47
+ return suggestions.includes("primitive") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions));
48
+ };
88
49
 
89
50
  /**
90
51
  * Creates a new formatter.
@@ -93,38 +54,33 @@ function _objectWithoutProperties(source, excluded) {
93
54
  * @param formatterOptions Additional options for the formatter.
94
55
  */
95
56
  var makeFormatter = function makeFormatter(format, formatterOptions) {
96
- var formatter = function formatter(_ref) {
97
- var _format;
98
-
99
- var children = _ref.children,
100
- _ref$suggestions = _ref.suggestions,
101
- suggestions = _ref$suggestions === void 0 ? [] : _ref$suggestions,
102
- dataContext = _objectWithoutProperties(_ref, ["children", "suggestions"]);
57
+ var formatter = function formatter(props) {
58
+ var _format, _props$suggestions;
103
59
 
104
- return (_format = format(children, suggestions, dataContext)) !== null && _format !== void 0 ? _format : null;
60
+ return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null;
105
61
  };
106
62
 
107
63
  formatter.displayName = formatterOptions === null || formatterOptions === void 0 ? void 0 : formatterOptions.displayName;
108
64
 
109
65
  formatter.format = function (value) {
110
- var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
66
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
111
67
  var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
112
- return format(value, usageSuggestions, dataContext);
68
+ return format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext);
113
69
  };
114
70
 
115
71
  formatter.formatAsPrimitive = function (value) {
116
- var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
72
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
117
73
  var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
118
- return format(value, ["primitive"].concat(_toConsumableArray(usageSuggestions)), dataContext);
74
+ return format(value, ensureFormatAsPrimitiveSuggestionIntegrity(suggestions), dataContext);
119
75
  };
120
76
 
121
77
  formatter.wrap = function (nextFormat, nextFormatterOptions) {
122
- var nextFormatter = makeFormatter(function (value, usageSuggestions, dataContext) {
123
- var delegate = function delegate(delegatedValue, delegatedUsageSuggestions, delegatedDataContext) {
124
- return formatter.format(delegatedValue, delegatedUsageSuggestions !== null && delegatedUsageSuggestions !== void 0 ? delegatedUsageSuggestions : usageSuggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
78
+ var nextFormatter = makeFormatter(function (value, suggestions, dataContext) {
79
+ var delegate = function delegate(delegatedValue, delegatedSuggestions, delegatedDataContext) {
80
+ return formatter.format(delegatedValue, delegatedSuggestions !== null && delegatedSuggestions !== void 0 ? delegatedSuggestions : suggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
125
81
  };
126
82
 
127
- return nextFormat(delegate, value, usageSuggestions, dataContext);
83
+ return nextFormat(delegate, value, suggestions, dataContext);
128
84
  }, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions);
129
85
  nextFormatter.innerFormatter = formatter;
130
86
  return nextFormatter;
@@ -137,4 +93,4 @@ exports.makeFormatter = makeFormatter;
137
93
 
138
94
  Object.defineProperty(exports, '__esModule', { value: true });
139
95
 
140
- })));
96
+ }));
@@ -1 +1 @@
1
- !function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((t="undefined"!=typeof globalThis?globalThis:t||self).Afformative={})}(this,(function(t){"use strict";function r(t,r){(null==r||r>t.length)&&(r=t.length);for(var e=0,n=Array(r);r>e;e++)n[e]=t[e];return n}function e(t){return function(t){if(Array.isArray(t))return r(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return r(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?r(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function n(t,r){if(null==t)return{};var e,n,o=function(t,r){if(null==t)return{};var e,n,o={},i=Object.keys(t);for(n=0;i.length>n;n++)0>r.indexOf(e=i[n])&&(o[e]=t[e]);return o}(t,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;i.length>n;n++)0>r.indexOf(e=i[n])&&Object.prototype.propertyIsEnumerable.call(t,e)&&(o[e]=t[e])}return o}t.makeFormatter=function t(r,o){var i=function(t){var e,o=t.children,i=t.suggestions,u=void 0===i?[]:i,l=n(t,["children","suggestions"]);return null!==(e=r(o,u,l))&&void 0!==e?e:null};return i.displayName=null==o?void 0:o.displayName,i.format=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return r(t,e,n)},i.formatAsPrimitive=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return r(t,["primitive"].concat(e(n)),o)},i.wrap=function(r,e){var n=t((function(t,e,n){return r((function(t,r,o){return i.format(t,null!=r?r:e,null!=o?o:n)}),t,e,n)}),null!=e?e:o);return n.innerFormatter=i,n},i},Object.defineProperty(t,"__esModule",{value:!0})}));
1
+ !function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).Afformative={})}(this,(function(t){"use strict";function n(t,n){(null==n||n>t.length)&&(n=t.length);for(var r=0,e=Array(n);n>r;r++)e[r]=t[r];return e}function r(t){return function(t){if(Array.isArray(t))return n(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,r){if(t){if("string"==typeof t)return n(t,r);var e=Object.prototype.toString.call(t).slice(8,-1);return"Object"===e&&t.constructor&&(e=t.constructor.name),"Map"===e||"Set"===e?Array.from(t):"Arguments"===e||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e)?n(t,r):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}var e=function(t){return t.includes("primitive")||!t.includes("comparable")?t:["primitive"].concat(r(t))},i=function(t){return t.includes("primitive")?t:["primitive"].concat(r(t))};t.makeFormatter=function t(n,r){var o=function(t){var r,e;return null!==(r=n(t.children,null!==(e=t.suggestions)&&void 0!==e?e:[],t))&&void 0!==r?r:null};return o.displayName=null==r?void 0:r.displayName,o.format=function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return n(t,e(r),i)},o.formatAsPrimitive=function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return n(t,i(r),e)},o.wrap=function(n,e){var i=t((function(t,r,e){return n((function(t,n,i){return o.format(t,null!=n?n:r,null!=i?i:e)}),t,r,e)}),null!=e?e:r);return i.innerFormatter=o,i},o},Object.defineProperty(t,"__esModule",{value:!0})}));
@@ -1,2 +1,2 @@
1
- export * from "./makeFormatter";
1
+ export * from "./makeFormatter";
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1,94 +1,97 @@
1
- declare type PrimitiveSuggestion = "primitive";
2
- declare type SemanticSuggestion = "abbreviated" | "icon" | "verbose";
3
- declare type Suggestion = PrimitiveSuggestion | SemanticSuggestion;
4
- interface FormatterOptions {
5
- /** Formatter name, useful for debugging or advanced pattern matching. */
6
- displayName?: string;
7
- }
8
- declare type DataContext = Record<string, any>;
9
- interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
10
- (
11
- /** Value to format. */
12
- value: TInput,
13
- /** Suggestions passed by the consumer of a formatter. */
14
- usageSuggestions: Suggestion[],
15
- /** Additional data context to be used by the formatter. */
16
- dataContext: Partial<TDataContext>): TOutput | TPrimitiveOutput;
17
- }
18
- interface FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
19
- <TSuggestion extends Suggestion>(
20
- /** Value to format. */
21
- value: TInput,
22
- /** Suggestions the formatter should take note of. */
23
- usageSuggestions?: TSuggestion[],
24
- /** Additional data context the formatter might find useful. */
25
- dataContext?: Partial<TDataContext>): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput;
26
- }
27
- interface FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext extends DataContext> {
28
- (
29
- /** Value to format. */
30
- value: TInput,
31
- /** Suggestions the formatter should take note of in addition to `primitive`. */
32
- usageSuggestions?: Suggestion[],
33
- /** Additional data context the formatter might find useful. */
34
- dataContext?: Partial<TDataContext>): TPrimitiveOutput;
35
- }
36
- interface FormatChainDefinition<TInnerInput, TInnerOutput, TInnerPrimitiveInput, TInnerDataContext extends DataContext, TOuterInput, TOuterOutput, TOuterPrimitiveOutput, TOuterDataContext extends DataContext> {
37
- (
38
- /**
39
- * The `formatter.format` method which can be used to delegate the formatting
40
- * to the wrapped formatter. Delegation is simplified so if no suggestions or contextual
41
- * props are passed, the original ones are used instead.
42
- */
43
- delegate: FormatMethod<TInnerInput, TInnerOutput, TInnerPrimitiveInput, TInnerDataContext>,
44
- /** Value to format. */
45
- value: TOuterInput,
46
- /** Suggestions the formatter should take note of. */
47
- usageSuggestions: Suggestion[],
48
- /** Additional data context the formatter might find useful. */
49
- dataContext: Partial<TOuterDataContext>): TOuterOutput | TOuterPrimitiveOutput;
50
- }
51
- declare type FormatterProps<TInput, TDataContext extends DataContext> = {
52
- /** Value to format. */
53
- children: TInput;
54
- /** Suggestions the formatter should take note of. */
55
- suggestions?: Suggestion[];
56
- } & Partial<TDataContext>;
57
- export interface Formatter<TInput, TOutput, TPrimitiveOutput = TOutput, TDataContext extends DataContext = DataContext> {
58
- /** Formatter name, useful for debugging or advanced pattern matching. */
59
- displayName?: string;
60
- /** Formats a value. */
61
- format: FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext>;
62
- /** Formats a value with the `primitive` suggestion. */
63
- formatAsPrimitive: FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext>;
64
- /** The callee of the `.wrap` method used to produce this formatter. */
65
- innerFormatter?: Formatter<any, any, any, any>;
66
- /**
67
- * Creates a new formatter from an existing one. Allows overriding of formatter behaviour
68
- * for certain values.
69
- */
70
- wrap: <TNextInput = TInput, TNextOutput = TOutput, TNextPrimitiveOutput = TPrimitiveOutput, TNextDataContext extends DataContext = TDataContext>(
71
- /**
72
- * Function used to format the value. Has the same signature as the one passed
73
- * to `makeFormatter`, except a `delegate` function is passed in the first position.
74
- * This function can be used to delegate formatting to the original (inner) formatter.
75
- */
76
- nextFormat: FormatChainDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext, TNextInput, TNextOutput, TNextPrimitiveOutput, TNextDataContext>,
77
- /** New formatter options, replacing the original ones. */
78
- nextFormatterOptions?: FormatterOptions) => Formatter<TNextInput, TNextOutput, TNextPrimitiveOutput, TNextDataContext>;
79
- /**
80
- * Backwards-compatible way to use the formatter as a React component.
81
- *
82
- * @deprecated Since v0.6.0. Prefer using the `Formatter.format` method instead.
83
- */
84
- (props: FormatterProps<TInput, TDataContext>): TOutput | TPrimitiveOutput | null;
85
- }
86
- /**
87
- * Creates a new formatter.
88
- *
89
- * @param format Function used to format the value.
90
- * @param formatterOptions Additional options for the formatter.
91
- */
92
- export declare const makeFormatter: <TInput, TOutput, TPrimitiveOutput = TOutput, TDataContext extends DataContext = DataContext>(format: FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext>, formatterOptions?: FormatterOptions | undefined) => Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext>;
93
- export {};
1
+ declare type PrimitiveSuggestion = "primitive" | "comparable";
2
+ declare type Suggestion = PrimitiveSuggestion | "abbreviated" | "as-icon"
3
+ /**
4
+ * @deprecated Since v0.6.3. Use `"as-icon"` or `"with-icon"` instead.
5
+ */
6
+ | "icon" | "verbose" | "with-icon";
7
+ declare type DataContext = Record<string, any>;
8
+ interface FormatterOptions {
9
+ /** Formatter name, useful for debugging or advanced pattern matching. */
10
+ displayName?: string;
11
+ }
12
+ interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
13
+ (
14
+ /** Value to format. */
15
+ value: TInput,
16
+ /** Suggestions passed by the consumer of a formatter. */
17
+ suggestions: Suggestion[],
18
+ /** Additional data context to be used by the formatter. */
19
+ dataContext: Partial<TDataContext>): TOutput | TPrimitiveOutput;
20
+ }
21
+ interface FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
22
+ (
23
+ /** Value to format. */
24
+ value: TInput,
25
+ /** Suggestions the formatter should take note of. */
26
+ suggestions?: Suggestion[],
27
+ /** Additional data context the formatter might find useful. */
28
+ dataContext?: Partial<TDataContext>): TOutput | TPrimitiveOutput;
29
+ }
30
+ interface FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext extends DataContext> {
31
+ (
32
+ /** Value to format. */
33
+ value: TInput,
34
+ /** Suggestions the formatter should take note of in addition to `primitive`. */
35
+ suggestions?: Suggestion[],
36
+ /** Additional data context the formatter might find useful. */
37
+ dataContext?: Partial<TDataContext>): TPrimitiveOutput;
38
+ }
39
+ interface FormatChainDefinition<TInnerInput, TInnerOutput, TInnerPrimitiveInput, TInnerDataContext extends DataContext, TOuterInput, TOuterOutput, TOuterPrimitiveOutput, TOuterDataContext extends DataContext> {
40
+ (
41
+ /**
42
+ * The `formatter.format` method which can be used to delegate the formatting
43
+ * to the wrapped formatter. Delegation is simplified so if no suggestions or contextual
44
+ * props are passed, the original ones are used instead.
45
+ */
46
+ delegate: FormatMethod<TInnerInput, TInnerOutput, TInnerPrimitiveInput, TInnerDataContext>,
47
+ /** Value to format. */
48
+ value: TOuterInput,
49
+ /** Suggestions the formatter should take note of. */
50
+ suggestions: Suggestion[],
51
+ /** Additional data context the formatter might find useful. */
52
+ dataContext: Partial<TOuterDataContext>): TOuterOutput | TOuterPrimitiveOutput;
53
+ }
54
+ declare type FormatterProps<TInput, TDataContext extends DataContext> = {
55
+ /** Value to format. */
56
+ children: TInput;
57
+ /** Suggestions the formatter should take note of. */
58
+ suggestions?: Suggestion[];
59
+ } & Partial<TDataContext>;
60
+ export interface Formatter<TInput, TOutput, TPrimitiveOutput = TOutput, TDataContext extends DataContext = DataContext> {
61
+ /** Formatter name, useful for debugging or advanced pattern matching. */
62
+ displayName?: string;
63
+ /** Formats a value. */
64
+ format: FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext>;
65
+ /** Formats a value with the `primitive` suggestion. */
66
+ formatAsPrimitive: FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext>;
67
+ /** The callee of the `wrap` method used to produce this formatter. */
68
+ innerFormatter?: Formatter<any, any, any, any>;
69
+ /**
70
+ * Creates a new formatter from an existing one. Allows overriding of formatter behaviour
71
+ * for certain values.
72
+ */
73
+ wrap: <TNextInput = TInput, TNextOutput = TOutput, TNextPrimitiveOutput = TPrimitiveOutput, TNextDataContext extends TDataContext = TDataContext>(
74
+ /**
75
+ * Function used to format the value. Has the same signature as the one passed
76
+ * to `makeFormatter`, except a `delegate` function is passed in the first position.
77
+ * This function can be used to delegate formatting to the original (inner) formatter.
78
+ */
79
+ nextFormat: FormatChainDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext, TNextInput, TNextOutput, TNextPrimitiveOutput, TNextDataContext>,
80
+ /** New formatter options, replacing the original ones. */
81
+ nextFormatterOptions?: FormatterOptions) => Formatter<TNextInput, TNextOutput, TNextPrimitiveOutput, TNextDataContext>;
82
+ /**
83
+ * Backwards-compatible way to use the formatter as a React component.
84
+ *
85
+ * @deprecated Since v0.6.0. Prefer using the `format` method instead.
86
+ */
87
+ (props: FormatterProps<TInput, TDataContext>): TOutput | TPrimitiveOutput | null;
88
+ }
89
+ /**
90
+ * Creates a new formatter.
91
+ *
92
+ * @param format Function used to format the value.
93
+ * @param formatterOptions Additional options for the formatter.
94
+ */
95
+ export declare const makeFormatter: <TInput, TOutput, TPrimitiveOutput = TOutput, TDataContext extends DataContext = DataContext>(format: FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext>, formatterOptions?: FormatterOptions | undefined) => Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext>;
96
+ export {};
94
97
  //# sourceMappingURL=makeFormatter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"makeFormatter.d.ts","sourceRoot":"","sources":["../../src/makeFormatter.ts"],"names":[],"mappings":"AAAA,aAAK,mBAAmB,GAAG,WAAW,CAAA;AACtC,aAAK,kBAAkB,GAAG,aAAa,GAAG,MAAM,GAAG,SAAS,CAAA;AAC5D,aAAK,UAAU,GAAG,mBAAmB,GAAG,kBAAkB,CAAA;AAE1D,UAAU,gBAAgB;IACxB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,aAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AAetC,UAAU,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAAY,SAAS,WAAW;IAC5F;IACE,uBAAuB;IACvB,KAAK,EAAE,MAAM;IACb,yDAAyD;IACzD,gBAAgB,EAAE,UAAU,EAAE;IAC9B,2DAA2D;IAC3D,WAAW,EAAE,OAAO,CAAC,YAAY,CAAC,GACjC,OAAO,GAAG,gBAAgB,CAAA;CAC9B;AAED,UAAU,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAAY,SAAS,WAAW;IACxF,CAAC,WAAW,SAAS,UAAU;IAC7B,uBAAuB;IACvB,KAAK,EAAE,MAAM;IACb,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,WAAW,EAAE;IAChC,+DAA+D;IAC/D,WAAW,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAClC,mBAAmB,SAAS,WAAW,GAAG,gBAAgB,GAAG,OAAO,CAAA;CACxE;AAED,UAAU,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,EAAE,YAAY,SAAS,WAAW;IAC1F;IACE,uBAAuB;IACvB,KAAK,EAAE,MAAM;IACb,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,UAAU,EAAE;IAC/B,+DAA+D;IAC/D,WAAW,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAClC,gBAAgB,CAAA;CACpB;AAED,UAAU,qBAAqB,CAC7B,WAAW,EACX,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,SAAS,WAAW,EACrC,WAAW,EACX,YAAY,EACZ,qBAAqB,EACrB,iBAAiB,SAAS,WAAW;IAErC;IACE;;;;OAIG;IACH,QAAQ,EAAE,YAAY,CAAC,WAAW,EAAE,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,CAAC;IAC1F,uBAAuB;IACvB,KAAK,EAAE,WAAW;IAClB,qDAAqD;IACrD,gBAAgB,EAAE,UAAU,EAAE;IAC9B,+DAA+D;IAC/D,WAAW,EAAE,OAAO,CAAC,iBAAiB,CAAC,GACtC,YAAY,GAAG,qBAAqB,CAAA;CACxC;AAED,aAAK,cAAc,CAAC,MAAM,EAAE,YAAY,SAAS,WAAW,IAAI;IAC9D,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,qDAAqD;IACrD,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;CAC3B,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;AAEzB,MAAM,WAAW,SAAS,CACxB,MAAM,EACN,OAAO,EACP,gBAAgB,GAAG,OAAO,EAC1B,YAAY,SAAS,WAAW,GAAG,WAAW;IAE9C,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uBAAuB;IACvB,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAAY,CAAC,CAAA;IACrE,uDAAuD;IACvD,iBAAiB,EAAE,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,EAAE,YAAY,CAAC,CAAA;IAClF,uEAAuE;IACvE,cAAc,CAAC,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IAC9C;;;OAGG;IACH,IAAI,EAAE,CACJ,UAAU,GAAG,MAAM,EACnB,WAAW,GAAG,OAAO,EACrB,oBAAoB,GAAG,gBAAgB,EACvC,gBAAgB,SAAS,WAAW,GAAG,YAAY;IAEnD;;;;OAIG;IACH,UAAU,EAAE,qBAAqB,CAC/B,MAAM,EACN,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,gBAAgB,CACjB;IACD,0DAA0D;IAC1D,oBAAoB,CAAC,EAAE,gBAAgB,KACpC,SAAS,CAAC,UAAU,EAAE,WAAW,EAAE,oBAAoB,EAAE,gBAAgB,CAAC,CAAA;IAC/E;;;;OAIG;IACH,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,OAAO,GAAG,gBAAgB,GAAG,IAAI,CAAA;CACjF;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,yRAmEzB,CAAA"}
1
+ {"version":3,"file":"makeFormatter.d.ts","sourceRoot":"","sources":["../../src/makeFormatter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "afformative",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "license": "MIT",
5
5
  "main": "dist/afformative.cjs.js",
6
6
  "module": "dist/afformative.esm.js",
@@ -34,5 +34,5 @@
34
34
  "access": "public"
35
35
  },
36
36
  "sideEffects": false,
37
- "gitHead": "3e3b893eee2b69d29019b3683b9d1d719192a2b5"
37
+ "gitHead": "ddc8c8682e2777c730108466792b7670d8a43f06"
38
38
  }
@@ -2,158 +2,217 @@ import { makeFormatter } from "./makeFormatter"
2
2
 
3
3
  const toUpperCase = (string: string) => string.toUpperCase()
4
4
 
5
+ const upperCaseFormatter = makeFormatter<string, string>(toUpperCase)
6
+
7
+ interface ValueRecord {
8
+ value: string
9
+ }
10
+
11
+ const valueRecordUpperCaseFormatter = makeFormatter<ValueRecord, ValueRecord, string>(
12
+ ({ value }, suggestions) => {
13
+ if (suggestions.includes("primitive")) {
14
+ return toUpperCase(value)
15
+ }
16
+
17
+ return { value: toUpperCase(value) }
18
+ },
19
+ )
20
+
5
21
  describe("makeFormatter", () => {
6
- it("handles trivial formatting", () => {
7
- const formatter = makeFormatter<string, string>(toUpperCase)
8
- expect(formatter.format("foo")).toBe("FOO")
9
- })
22
+ const format = jest.fn()
10
23
 
11
- it("accepts a `name` option", () => {
12
- const formatter = makeFormatter<string, string>(toUpperCase, { displayName: "UpperFormatter" })
13
- expect(formatter.displayName).toBe("UpperFormatter")
24
+ afterEach(() => {
25
+ jest.clearAllMocks()
14
26
  })
15
27
 
16
- it("passes `suggestions` to `format`", () => {
17
- const formatter = makeFormatter<string, string>((value, suggestions) => {
18
- if (suggestions.includes("abbreviated")) {
19
- return value[0]
20
- }
28
+ describe("displayName", () => {
29
+ it("accepts a `displayName` option", () => {
30
+ const displayName = "upperCaseFormatter"
31
+ const formatter = makeFormatter<string, string>(toUpperCase, { displayName })
32
+ expect(formatter.displayName).toBe(displayName)
33
+ })
34
+ })
21
35
 
22
- return value
36
+ describe("format", () => {
37
+ it("handles trivial formatting", () => {
38
+ expect(upperCaseFormatter.format("foo")).toBe("FOO")
23
39
  })
24
40
 
25
- expect(formatter.format("foo", ["abbreviated"])).toBe("f")
26
- expect(formatter.format("foo", [])).toBe("foo")
27
- expect(formatter.format("foo")).toBe("foo")
28
- })
41
+ it("passes through non-empty suggestions", () => {
42
+ const formatter = makeFormatter<string, string>(format)
43
+ formatter.format("foo", ["abbreviated"])
44
+ expect(format.mock.calls[0][1]).toEqual(["abbreviated"])
45
+ })
29
46
 
30
- it("handles formatting with the `primitive` suggestion", () => {
31
- type Structure = { value: string }
47
+ it("passes through empty suggestions", () => {
48
+ const formatter = makeFormatter<string, string>(format)
49
+ formatter.format("foo", [])
50
+ expect(format.mock.calls[0][1]).toEqual([])
51
+ })
32
52
 
33
- const formatter = makeFormatter<Structure, Structure, string>((value, suggestions) => {
34
- if (suggestions.includes("primitive")) {
35
- return value.value
36
- }
53
+ it("defaults suggestions to an empty array", () => {
54
+ const formatter = makeFormatter<string, string>(format)
55
+ formatter.format("foo")
56
+ expect(format.mock.calls[0][1]).toEqual([])
57
+ })
37
58
 
38
- return value
59
+ it("passes through the `primitive` suggestion", () => {
60
+ const formatter = makeFormatter<string, string>(format)
61
+ formatter.format("foo", ["primitive"])
62
+ expect(format.mock.calls[0][1]).toEqual(["primitive"])
39
63
  })
40
64
 
41
- expect(formatter.format({ value: "foo" }, ["primitive"])).toBe("foo")
42
- expect(formatter.formatAsPrimitive({ value: "foo" })).toBe("foo")
43
- expect(formatter.formatAsPrimitive({ value: "foo" }, ["primitive"])).toBe("foo")
44
- })
65
+ it("passes the `primitive` suggestion alongside `comparable` when missing", () => {
66
+ const formatter = makeFormatter<string, string>(format)
67
+ formatter.format("foo", ["comparable"])
68
+ expect(format.mock.calls[0][1]).toEqual(["primitive", "comparable"])
69
+ })
45
70
 
46
- it("supports simple behavior wrapping", () => {
47
- const formatter = makeFormatter<string, string>(toUpperCase)
71
+ it("does not pass the `primitive` suggestion alongside other suggestions when missing", () => {
72
+ const formatter = makeFormatter<string, string>(format)
73
+ formatter.format("foo", ["abbreviated", "verbose"])
74
+ expect(format.mock.calls[0][1]).toEqual(["abbreviated", "verbose"])
75
+ })
48
76
 
49
- const wrappedFormatter = formatter.wrap((delegate, value) =>
50
- value === "foo" ? "override" : delegate(value),
51
- )
77
+ it("supports data context", () => {
78
+ const formatter = makeFormatter<string, string>(format)
79
+ formatter.format("foo", [], { foo: "bar" })
80
+ expect(format.mock.calls[0][2]).toEqual({ foo: "bar" })
81
+ })
52
82
 
53
- expect(wrappedFormatter.format("foo")).toBe("override")
54
- expect(wrappedFormatter.format("bar")).toBe("BAR")
83
+ it("defaults data context to an empty object", () => {
84
+ const formatter = makeFormatter<string, string>(format)
85
+ formatter.format("foo")
86
+ expect(format.mock.calls[0][2]).toEqual({})
87
+ })
55
88
  })
56
89
 
57
- it("supports simple behavior wrapping with suggestions", () => {
58
- const formatter = makeFormatter<string, string>(toUpperCase)
90
+ describe("formatAsPrimitive", () => {
91
+ it("handles trivial formatting", () => {
92
+ expect(upperCaseFormatter.formatAsPrimitive("foo")).toBe("FOO")
93
+ })
59
94
 
60
- const wrappedFormatter = formatter.wrap((delegate, value, suggestions) =>
61
- value === "foo" && suggestions.includes("abbreviated") ? "f" : delegate(value),
62
- )
95
+ it("passes the `primitive` suggestion when no suggestions are passed", () => {
96
+ const formatter = makeFormatter<string, string>(format)
97
+ formatter.formatAsPrimitive("foo")
98
+ expect(format.mock.calls[0][1]).toEqual(["primitive"])
99
+ })
63
100
 
64
- expect(wrappedFormatter.format("foo")).toBe("FOO")
65
- expect(wrappedFormatter.format("foo", ["abbreviated"])).toBe("f")
66
- expect(wrappedFormatter.format("bar")).toBe("BAR")
67
- })
101
+ it("passes the `primitive` suggestion when empty suggestions are passed", () => {
102
+ const formatter = makeFormatter<string, string>(format)
103
+ formatter.formatAsPrimitive("foo", [])
104
+ expect(format.mock.calls[0][1]).toEqual(["primitive"])
105
+ })
68
106
 
69
- it("supports simple behavior wrapping with the `primitive` suggestion", () => {
70
- type Structure = { value: string }
107
+ it("passes the `primitive` suggestion when a different suggestion is passed", () => {
108
+ const formatter = makeFormatter<string, string>(format)
109
+ formatter.formatAsPrimitive("foo", ["abbreviated"])
110
+ expect(format.mock.calls[0][1]).toEqual(["primitive", "abbreviated"])
111
+ })
71
112
 
72
- const formatter = makeFormatter<string, string>(toUpperCase)
113
+ it("passes through the `primitive` suggestion", () => {
114
+ const formatter = makeFormatter<string, string>(format)
115
+ formatter.formatAsPrimitive("foo", ["primitive"])
116
+ expect(format.mock.calls[0][1]).toEqual(["primitive"])
117
+ })
73
118
 
74
- const wrappedFormatter = formatter.wrap<Structure, Structure, string>(
75
- (delegate, value, suggestions) => (suggestions.includes("primitive") ? value.value : value),
76
- )
119
+ it("passes the `primitive` suggestion alongside `comparable`", () => {
120
+ const formatter = makeFormatter<string, string>(format)
121
+ formatter.formatAsPrimitive("foo", ["comparable"])
122
+ expect(format.mock.calls[0][1]).toEqual(["primitive", "comparable"])
123
+ })
124
+
125
+ it("supports data context", () => {
126
+ const formatter = makeFormatter<string, string>(format)
127
+ formatter.formatAsPrimitive("foo", [], { foo: "bar" })
128
+ expect(format.mock.calls[0][2]).toEqual({ foo: "bar" })
129
+ })
77
130
 
78
- expect(wrappedFormatter.format({ value: "foo" }, ["primitive"])).toBe("foo")
79
- expect(wrappedFormatter.formatAsPrimitive({ value: "foo" })).toBe("foo")
80
- expect(wrappedFormatter.formatAsPrimitive({ value: "foo" }, ["primitive"])).toBe("foo")
131
+ it("defaults data context to an empty object", () => {
132
+ const formatter = makeFormatter<string, string>(format)
133
+ formatter.formatAsPrimitive("foo")
134
+ expect(format.mock.calls[0][2]).toEqual({})
135
+ })
81
136
  })
82
137
 
83
- it("supports simple behavior wrapping with data context", () => {
84
- const formatter = makeFormatter<string, string>(toUpperCase)
138
+ describe("wrap", () => {
139
+ it("handles trivial wrapping", () => {
140
+ const formatter = makeFormatter<string, string>(format).wrap(() => "bar")
141
+ expect(formatter.format("foo")).toBe("bar")
142
+ })
85
143
 
86
- interface WrappedDataContext {
87
- forcedValue?: string
88
- }
144
+ it("handles single-value mapping", () => {
145
+ const formatter = makeFormatter<string, string>(format).wrap((delegate, value) =>
146
+ value === "ping" ? "pong" : delegate(value),
147
+ )
89
148
 
90
- const wrappedFormatter = formatter.wrap(
91
- (delegate, value, suggestions, { forcedValue }: WrappedDataContext) =>
92
- forcedValue ?? delegate(value),
93
- )
149
+ expect(formatter.format("ping")).toBe("pong")
150
+ })
94
151
 
95
- expect(wrappedFormatter.format("foo")).toBe("FOO")
96
- expect(wrappedFormatter.format("foo", undefined, { forcedValue: "override" })).toBe("override")
97
- })
152
+ it("handles delegation to the original formatter", () => {
153
+ const formatter = upperCaseFormatter.wrap((delegate, value) =>
154
+ value === "ping" ? "pong" : delegate(value),
155
+ )
98
156
 
99
- it("passes the original suggestions when they are not passed manually to `format` when wrapping", () => {
100
- const formatter = makeFormatter<string, string>((value, suggestions) => {
101
- if (suggestions.includes("abbreviated")) {
102
- return value[0]
103
- }
157
+ expect(formatter.format("foo")).toBe("FOO")
158
+ })
104
159
 
105
- return value
160
+ it("sets the `innerFormatter` property", () => {
161
+ const wrappedFormatter = upperCaseFormatter.wrap((delegate, value) => delegate(value))
162
+ expect(wrappedFormatter.innerFormatter).toBe(upperCaseFormatter)
106
163
  })
107
164
 
108
- const wrappedFormatter = formatter.wrap((delegate, value) => delegate(value))
109
- expect(wrappedFormatter.format("foo", ["abbreviated"])).toBe("f")
110
- })
165
+ it("passes the `primitive` suggestion to `delegate` when using `formatAsPrimitive`", () => {
166
+ const formatter = valueRecordUpperCaseFormatter.wrap((delegate, value) => delegate(value))
167
+ expect(formatter.formatAsPrimitive({ value: "foo" })).toBe("FOO")
168
+ })
111
169
 
112
- it("sets the `innerFormatter` static property when wrapping", () => {
113
- const formatter = makeFormatter<string, string>(toUpperCase)
114
- const wrappedFormatter = formatter.wrap((delegate, value) => delegate(value))
115
- expect(wrappedFormatter.innerFormatter).toBe(formatter)
116
- })
170
+ it("passes suggestions through to `delegate` when not overriden", () => {
171
+ const formatter = valueRecordUpperCaseFormatter.wrap((delegate, value) => delegate(value))
172
+ expect(formatter.format({ value: "foo" }, ["primitive"])).toBe("FOO")
173
+ })
117
174
 
118
- it("handles complex wrapping with structural changes", () => {
119
- interface BasicDataContext {
120
- index?: number
121
- }
175
+ it("supports overriding of suggestions for `delegate`", () => {
176
+ const formatter = valueRecordUpperCaseFormatter.wrap((delegate, value) => delegate(value, []))
177
+ expect(formatter.format({ value: "foo" }, ["primitive"])).toEqual({ value: "FOO" })
178
+ })
122
179
 
123
- const basicFormatter = makeFormatter(
124
- (value: string, suggestions, dataContext: BasicDataContext): string | undefined =>
125
- value[dataContext.index ?? 0],
126
- )
180
+ it("supports modifying the input structure", () => {
181
+ const formatter = upperCaseFormatter.wrap<ValueRecord>((delegate, { value }) =>
182
+ delegate(value),
183
+ )
127
184
 
128
- expect(basicFormatter.format("test", [], { index: 2 })).toBe("s")
185
+ expect(formatter.format({ value: "foo" })).toBe("FOO")
186
+ })
129
187
 
130
- interface ComplexStructure {
131
- index: number
132
- value: string
133
- }
188
+ it("supports modifying the output structure", () => {
189
+ const formatter = upperCaseFormatter.wrap<ValueRecord, ValueRecord>(
190
+ (delegate, { value }) => ({ value: delegate(value) }),
191
+ )
134
192
 
135
- interface ComplexDataContext {
136
- getIndex?: (structure: ComplexStructure) => number
137
- }
193
+ expect(formatter.format({ value: "foo" })).toEqual({ value: "FOO" })
194
+ })
195
+
196
+ it("supports modifying the data context structure", () => {
197
+ interface ListContext {
198
+ row: string
199
+ }
138
200
 
139
- const complexFormatter = basicFormatter.wrap(
140
- (delegate, value: ComplexStructure, suggestions, dataContext: ComplexDataContext) =>
141
- delegate(value.value, suggestions, { index: dataContext.getIndex?.(value) }),
142
- )
201
+ const listFormatter = upperCaseFormatter.wrap<string, string, string, ListContext>(
202
+ (delegate, value, suggestions, { row }) => `${row}: ${delegate(value)}`,
203
+ )
143
204
 
144
- expect(complexFormatter.format({ index: 3, value: "procrastination" })).toBe("p")
205
+ interface GridContext extends ListContext {
206
+ column: string
207
+ }
145
208
 
146
- expect(
147
- complexFormatter.format({ index: 3, value: "procrastination" }, [], {
148
- getIndex: ({ index }) => index,
149
- }),
150
- ).toBe("c")
209
+ expect(listFormatter.format("foo", [], { row: "A" })).toBe("A: FOO")
151
210
 
152
- const boundComplexFormatter = complexFormatter.wrap(
153
- (delegate, value, suggestions, dataContext) =>
154
- delegate(value, suggestions, { ...dataContext, getIndex: ({ index }) => index }),
155
- )
211
+ const gridFormatter = listFormatter.wrap<string, string, string, GridContext>(
212
+ (delegate, value, suggestions, { column }) => delegate(value).replace(":", `${column}:`),
213
+ )
156
214
 
157
- expect(boundComplexFormatter.format({ index: 2, value: "swag" })).toBe("a")
215
+ expect(gridFormatter.format("foo", [], { row: "B", column: "1" })).toBe("B1: FOO")
216
+ })
158
217
  })
159
218
  })
@@ -1,47 +1,51 @@
1
- type PrimitiveSuggestion = "primitive"
2
- type SemanticSuggestion = "abbreviated" | "icon" | "verbose"
3
- type Suggestion = PrimitiveSuggestion | SemanticSuggestion
1
+ type PrimitiveSuggestion = "primitive" | "comparable"
2
+
3
+ type Suggestion =
4
+ | PrimitiveSuggestion
5
+ | "abbreviated"
6
+ | "as-icon"
7
+ /**
8
+ * @deprecated Since v0.6.3. Use `"as-icon"` or `"with-icon"` instead.
9
+ */
10
+ | "icon"
11
+ | "verbose"
12
+ | "with-icon"
13
+
14
+ const ensureFormatSuggestionIntegrity = (suggestions: Suggestion[]): Suggestion[] =>
15
+ suggestions.includes("primitive") || !suggestions.includes("comparable")
16
+ ? suggestions
17
+ : ["primitive", ...suggestions]
18
+
19
+ const ensureFormatAsPrimitiveSuggestionIntegrity = (suggestions: Suggestion[]): Suggestion[] =>
20
+ suggestions.includes("primitive") ? suggestions : ["primitive", ...suggestions]
21
+
22
+ type DataContext = Record<string, any>
4
23
 
5
24
  interface FormatterOptions {
6
25
  /** Formatter name, useful for debugging or advanced pattern matching. */
7
26
  displayName?: string
8
27
  }
9
28
 
10
- type DataContext = Record<string, any>
11
-
12
- // TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly
13
- // verify the return type of the format definition based on the suggestions, printing errors such
14
- // as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'`
15
- // which is, of course, nonsense. Same applies to `FormatChainDefinition`.
16
- //
17
- // interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
18
- // <TSuggestion extends Suggestion>(
19
- // value: TInput,
20
- // usageSuggestions: TSuggestion[],
21
- // dataContext: Partial<TDataContext>,
22
- // ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput
23
- // }
24
-
25
29
  interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
26
30
  (
27
31
  /** Value to format. */
28
32
  value: TInput,
29
33
  /** Suggestions passed by the consumer of a formatter. */
30
- usageSuggestions: Suggestion[],
34
+ suggestions: Suggestion[],
31
35
  /** Additional data context to be used by the formatter. */
32
36
  dataContext: Partial<TDataContext>,
33
37
  ): TOutput | TPrimitiveOutput
34
38
  }
35
39
 
36
40
  interface FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
37
- <TSuggestion extends Suggestion>(
41
+ (
38
42
  /** Value to format. */
39
43
  value: TInput,
40
44
  /** Suggestions the formatter should take note of. */
41
- usageSuggestions?: TSuggestion[],
45
+ suggestions?: Suggestion[],
42
46
  /** Additional data context the formatter might find useful. */
43
47
  dataContext?: Partial<TDataContext>,
44
- ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput
48
+ ): TOutput | TPrimitiveOutput
45
49
  }
46
50
 
47
51
  interface FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext extends DataContext> {
@@ -49,7 +53,7 @@ interface FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext extends
49
53
  /** Value to format. */
50
54
  value: TInput,
51
55
  /** Suggestions the formatter should take note of in addition to `primitive`. */
52
- usageSuggestions?: Suggestion[],
56
+ suggestions?: Suggestion[],
53
57
  /** Additional data context the formatter might find useful. */
54
58
  dataContext?: Partial<TDataContext>,
55
59
  ): TPrimitiveOutput
@@ -75,7 +79,7 @@ interface FormatChainDefinition<
75
79
  /** Value to format. */
76
80
  value: TOuterInput,
77
81
  /** Suggestions the formatter should take note of. */
78
- usageSuggestions: Suggestion[],
82
+ suggestions: Suggestion[],
79
83
  /** Additional data context the formatter might find useful. */
80
84
  dataContext: Partial<TOuterDataContext>,
81
85
  ): TOuterOutput | TOuterPrimitiveOutput
@@ -100,7 +104,7 @@ export interface Formatter<
100
104
  format: FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext>
101
105
  /** Formats a value with the `primitive` suggestion. */
102
106
  formatAsPrimitive: FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext>
103
- /** The callee of the `.wrap` method used to produce this formatter. */
107
+ /** The callee of the `wrap` method used to produce this formatter. */
104
108
  innerFormatter?: Formatter<any, any, any, any>
105
109
  /**
106
110
  * Creates a new formatter from an existing one. Allows overriding of formatter behaviour
@@ -110,7 +114,7 @@ export interface Formatter<
110
114
  TNextInput = TInput,
111
115
  TNextOutput = TOutput,
112
116
  TNextPrimitiveOutput = TPrimitiveOutput,
113
- TNextDataContext extends DataContext = TDataContext
117
+ TNextDataContext extends TDataContext = TDataContext
114
118
  >(
115
119
  /**
116
120
  * Function used to format the value. Has the same signature as the one passed
@@ -133,7 +137,7 @@ export interface Formatter<
133
137
  /**
134
138
  * Backwards-compatible way to use the formatter as a React component.
135
139
  *
136
- * @deprecated Since v0.6.0. Prefer using the `Formatter.format` method instead.
140
+ * @deprecated Since v0.6.0. Prefer using the `format` method instead.
137
141
  */
138
142
  (props: FormatterProps<TInput, TDataContext>): TOutput | TPrimitiveOutput | null
139
143
  }
@@ -153,25 +157,26 @@ export const makeFormatter = <
153
157
  format: FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext>,
154
158
  formatterOptions?: FormatterOptions,
155
159
  ): Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext> => {
156
- const formatter: Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext> = ({
157
- children,
158
- suggestions = [],
159
- ...dataContext
160
- }) => format(children, suggestions, dataContext as any) ?? null
160
+ const formatter: Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext> = props =>
161
+ format(props.children, props.suggestions ?? [], props) ?? null
161
162
 
162
163
  formatter.displayName = formatterOptions?.displayName
163
164
 
164
- formatter.format = (value, usageSuggestions = [], dataContext = {}) =>
165
- format(value, usageSuggestions, dataContext) as any
165
+ formatter.format = (value, suggestions = [], dataContext = {}) =>
166
+ format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext)
166
167
 
167
- formatter.formatAsPrimitive = (value, usageSuggestions = [], dataContext = {}) =>
168
- format(value, ["primitive", ...usageSuggestions], dataContext) as any
168
+ formatter.formatAsPrimitive = (value, suggestions = [], dataContext = {}) =>
169
+ format(
170
+ value,
171
+ ensureFormatAsPrimitiveSuggestionIntegrity(suggestions),
172
+ dataContext,
173
+ ) as TPrimitiveOutput
169
174
 
170
175
  formatter.wrap = <
171
176
  TNextInput,
172
177
  TNextOutput,
173
178
  TNextPrimitiveOutput,
174
- TNextDataContext extends DataContext
179
+ TNextDataContext extends TDataContext
175
180
  >(
176
181
  nextFormat: FormatChainDefinition<
177
182
  TInput,
@@ -185,24 +190,24 @@ export const makeFormatter = <
185
190
  >,
186
191
  nextFormatterOptions?: FormatterOptions,
187
192
  ) => {
188
- const nextFormatter: Formatter<
193
+ const nextFormatter = makeFormatter<
189
194
  TNextInput,
190
195
  TNextOutput,
191
196
  TNextPrimitiveOutput,
192
197
  TNextDataContext
193
- > = makeFormatter((value, usageSuggestions, dataContext) => {
198
+ >((value, suggestions, dataContext) => {
194
199
  const delegate: FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext> = (
195
200
  delegatedValue,
196
- delegatedUsageSuggestions,
201
+ delegatedSuggestions,
197
202
  delegatedDataContext,
198
203
  ) =>
199
204
  formatter.format(
200
205
  delegatedValue,
201
- delegatedUsageSuggestions ?? usageSuggestions,
202
- (delegatedDataContext ?? dataContext) as any,
203
- ) as any
206
+ delegatedSuggestions ?? suggestions,
207
+ delegatedDataContext ?? dataContext,
208
+ )
204
209
 
205
- return nextFormat(delegate, value, usageSuggestions, dataContext) as any
210
+ return nextFormat(delegate, value, suggestions, dataContext)
206
211
  }, nextFormatterOptions ?? formatterOptions)
207
212
 
208
213
  nextFormatter.innerFormatter = formatter