afformative
Advanced tools
Comparing version 0.6.2 to 0.6.3
@@ -6,3 +6,2 @@ 'use strict'; | ||
var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray'); | ||
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties'); | ||
@@ -12,17 +11,11 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var _toConsumableArray__default = /*#__PURE__*/_interopDefaultLegacy(_toConsumableArray); | ||
var _objectWithoutProperties__default = /*#__PURE__*/_interopDefaultLegacy(_objectWithoutProperties); | ||
// TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly | ||
// verify the return type of the format definition based on the suggestions, printing errors such | ||
// as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'` | ||
// which is, of course, nonsense. Same applies to `FormatChainDefinition`. | ||
// | ||
// interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> { | ||
// <TSuggestion extends Suggestion>( | ||
// value: TInput, | ||
// usageSuggestions: TSuggestion[], | ||
// dataContext: Partial<TDataContext>, | ||
// ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput | ||
// } | ||
var ensureFormatSuggestionIntegrity = function ensureFormatSuggestionIntegrity(suggestions) { | ||
return suggestions.includes("primitive") || !suggestions.includes("comparable") ? suggestions : ["primitive"].concat(_toConsumableArray__default["default"](suggestions)); | ||
}; | ||
var ensureFormatAsPrimitiveSuggestionIntegrity = function ensureFormatAsPrimitiveSuggestionIntegrity(suggestions) { | ||
return suggestions.includes("primitive") ? suggestions : ["primitive"].concat(_toConsumableArray__default["default"](suggestions)); | ||
}; | ||
/** | ||
@@ -35,11 +28,6 @@ * Creates a new formatter. | ||
var makeFormatter = function makeFormatter(format, formatterOptions) { | ||
var formatter = function formatter(_ref) { | ||
var _format; | ||
var formatter = function formatter(props) { | ||
var _format, _props$suggestions; | ||
var children = _ref.children, | ||
_ref$suggestions = _ref.suggestions, | ||
suggestions = _ref$suggestions === void 0 ? [] : _ref$suggestions, | ||
dataContext = _objectWithoutProperties__default['default'](_ref, ["children", "suggestions"]); | ||
return (_format = format(children, suggestions, dataContext)) !== null && _format !== void 0 ? _format : null; | ||
return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null; | ||
}; | ||
@@ -50,20 +38,20 @@ | ||
formatter.format = function (value) { | ||
var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
return format(value, usageSuggestions, dataContext); | ||
return format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext); | ||
}; | ||
formatter.formatAsPrimitive = function (value) { | ||
var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
return format(value, ["primitive"].concat(_toConsumableArray__default['default'](usageSuggestions)), dataContext); | ||
return format(value, ensureFormatAsPrimitiveSuggestionIntegrity(suggestions), dataContext); | ||
}; | ||
formatter.wrap = function (nextFormat, nextFormatterOptions) { | ||
var nextFormatter = makeFormatter(function (value, usageSuggestions, dataContext) { | ||
var delegate = function delegate(delegatedValue, delegatedUsageSuggestions, delegatedDataContext) { | ||
return formatter.format(delegatedValue, delegatedUsageSuggestions !== null && delegatedUsageSuggestions !== void 0 ? delegatedUsageSuggestions : usageSuggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext); | ||
var nextFormatter = makeFormatter(function (value, suggestions, dataContext) { | ||
var delegate = function delegate(delegatedValue, delegatedSuggestions, delegatedDataContext) { | ||
return formatter.format(delegatedValue, delegatedSuggestions !== null && delegatedSuggestions !== void 0 ? delegatedSuggestions : suggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext); | ||
}; | ||
return nextFormat(delegate, value, usageSuggestions, dataContext); | ||
return nextFormat(delegate, value, suggestions, dataContext); | ||
}, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions); | ||
@@ -70,0 +58,0 @@ nextFormatter.innerFormatter = formatter; |
import _toConsumableArray from '@babel/runtime/helpers/esm/toConsumableArray'; | ||
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties'; | ||
// TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly | ||
// verify the return type of the format definition based on the suggestions, printing errors such | ||
// as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'` | ||
// which is, of course, nonsense. Same applies to `FormatChainDefinition`. | ||
// | ||
// interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> { | ||
// <TSuggestion extends Suggestion>( | ||
// value: TInput, | ||
// usageSuggestions: TSuggestion[], | ||
// dataContext: Partial<TDataContext>, | ||
// ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput | ||
// } | ||
var ensureFormatSuggestionIntegrity = function ensureFormatSuggestionIntegrity(suggestions) { | ||
return suggestions.includes("primitive") || !suggestions.includes("comparable") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions)); | ||
}; | ||
var ensureFormatAsPrimitiveSuggestionIntegrity = function ensureFormatAsPrimitiveSuggestionIntegrity(suggestions) { | ||
return suggestions.includes("primitive") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions)); | ||
}; | ||
/** | ||
@@ -24,11 +18,6 @@ * Creates a new formatter. | ||
var makeFormatter = function makeFormatter(format, formatterOptions) { | ||
var formatter = function formatter(_ref) { | ||
var _format; | ||
var formatter = function formatter(props) { | ||
var _format, _props$suggestions; | ||
var children = _ref.children, | ||
_ref$suggestions = _ref.suggestions, | ||
suggestions = _ref$suggestions === void 0 ? [] : _ref$suggestions, | ||
dataContext = _objectWithoutProperties(_ref, ["children", "suggestions"]); | ||
return (_format = format(children, suggestions, dataContext)) !== null && _format !== void 0 ? _format : null; | ||
return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null; | ||
}; | ||
@@ -39,20 +28,20 @@ | ||
formatter.format = function (value) { | ||
var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
return format(value, usageSuggestions, dataContext); | ||
return format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext); | ||
}; | ||
formatter.formatAsPrimitive = function (value) { | ||
var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
return format(value, ["primitive"].concat(_toConsumableArray(usageSuggestions)), dataContext); | ||
return format(value, ensureFormatAsPrimitiveSuggestionIntegrity(suggestions), dataContext); | ||
}; | ||
formatter.wrap = function (nextFormat, nextFormatterOptions) { | ||
var nextFormatter = makeFormatter(function (value, usageSuggestions, dataContext) { | ||
var delegate = function delegate(delegatedValue, delegatedUsageSuggestions, delegatedDataContext) { | ||
return formatter.format(delegatedValue, delegatedUsageSuggestions !== null && delegatedUsageSuggestions !== void 0 ? delegatedUsageSuggestions : usageSuggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext); | ||
var nextFormatter = makeFormatter(function (value, suggestions, dataContext) { | ||
var delegate = function delegate(delegatedValue, delegatedSuggestions, delegatedDataContext) { | ||
return formatter.format(delegatedValue, delegatedSuggestions !== null && delegatedSuggestions !== void 0 ? delegatedSuggestions : suggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext); | ||
}; | ||
return nextFormat(delegate, value, usageSuggestions, dataContext); | ||
return nextFormat(delegate, value, suggestions, dataContext); | ||
}, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions); | ||
@@ -59,0 +48,0 @@ nextFormatter.innerFormatter = formatter; |
@@ -5,3 +5,3 @@ (function (global, factory) { | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Afformative = {})); | ||
}(this, (function (exports) { 'use strict'; | ||
})(this, (function (exports) { 'use strict'; | ||
@@ -43,49 +43,10 @@ function _arrayLikeToArray(arr, len) { | ||
function _objectWithoutPropertiesLoose(source, excluded) { | ||
if (source == null) return {}; | ||
var target = {}; | ||
var sourceKeys = Object.keys(source); | ||
var key, i; | ||
var ensureFormatSuggestionIntegrity = function ensureFormatSuggestionIntegrity(suggestions) { | ||
return suggestions.includes("primitive") || !suggestions.includes("comparable") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions)); | ||
}; | ||
for (i = 0; i < sourceKeys.length; i++) { | ||
key = sourceKeys[i]; | ||
if (excluded.indexOf(key) >= 0) continue; | ||
target[key] = source[key]; | ||
} | ||
var ensureFormatAsPrimitiveSuggestionIntegrity = function ensureFormatAsPrimitiveSuggestionIntegrity(suggestions) { | ||
return suggestions.includes("primitive") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions)); | ||
}; | ||
return target; | ||
} | ||
function _objectWithoutProperties(source, excluded) { | ||
if (source == null) return {}; | ||
var target = _objectWithoutPropertiesLoose(source, excluded); | ||
var key, i; | ||
if (Object.getOwnPropertySymbols) { | ||
var sourceSymbolKeys = Object.getOwnPropertySymbols(source); | ||
for (i = 0; i < sourceSymbolKeys.length; i++) { | ||
key = sourceSymbolKeys[i]; | ||
if (excluded.indexOf(key) >= 0) continue; | ||
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; | ||
target[key] = source[key]; | ||
} | ||
} | ||
return target; | ||
} | ||
// TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly | ||
// verify the return type of the format definition based on the suggestions, printing errors such | ||
// as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'` | ||
// which is, of course, nonsense. Same applies to `FormatChainDefinition`. | ||
// | ||
// interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> { | ||
// <TSuggestion extends Suggestion>( | ||
// value: TInput, | ||
// usageSuggestions: TSuggestion[], | ||
// dataContext: Partial<TDataContext>, | ||
// ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput | ||
// } | ||
/** | ||
@@ -98,11 +59,6 @@ * Creates a new formatter. | ||
var makeFormatter = function makeFormatter(format, formatterOptions) { | ||
var formatter = function formatter(_ref) { | ||
var _format; | ||
var formatter = function formatter(props) { | ||
var _format, _props$suggestions; | ||
var children = _ref.children, | ||
_ref$suggestions = _ref.suggestions, | ||
suggestions = _ref$suggestions === void 0 ? [] : _ref$suggestions, | ||
dataContext = _objectWithoutProperties(_ref, ["children", "suggestions"]); | ||
return (_format = format(children, suggestions, dataContext)) !== null && _format !== void 0 ? _format : null; | ||
return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null; | ||
}; | ||
@@ -113,20 +69,20 @@ | ||
formatter.format = function (value) { | ||
var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
return format(value, usageSuggestions, dataContext); | ||
return format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext); | ||
}; | ||
formatter.formatAsPrimitive = function (value) { | ||
var usageSuggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
return format(value, ["primitive"].concat(_toConsumableArray(usageSuggestions)), dataContext); | ||
return format(value, ensureFormatAsPrimitiveSuggestionIntegrity(suggestions), dataContext); | ||
}; | ||
formatter.wrap = function (nextFormat, nextFormatterOptions) { | ||
var nextFormatter = makeFormatter(function (value, usageSuggestions, dataContext) { | ||
var delegate = function delegate(delegatedValue, delegatedUsageSuggestions, delegatedDataContext) { | ||
return formatter.format(delegatedValue, delegatedUsageSuggestions !== null && delegatedUsageSuggestions !== void 0 ? delegatedUsageSuggestions : usageSuggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext); | ||
var nextFormatter = makeFormatter(function (value, suggestions, dataContext) { | ||
var delegate = function delegate(delegatedValue, delegatedSuggestions, delegatedDataContext) { | ||
return formatter.format(delegatedValue, delegatedSuggestions !== null && delegatedSuggestions !== void 0 ? delegatedSuggestions : suggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext); | ||
}; | ||
return nextFormat(delegate, value, usageSuggestions, dataContext); | ||
return nextFormat(delegate, value, suggestions, dataContext); | ||
}, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions); | ||
@@ -144,2 +100,2 @@ nextFormatter.innerFormatter = formatter; | ||
}))); | ||
})); |
@@ -1,1 +0,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})})); | ||
!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})})); |
export * from "./makeFormatter"; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,4 +0,8 @@ | ||
declare type PrimitiveSuggestion = "primitive"; | ||
declare type SemanticSuggestion = "abbreviated" | "icon" | "verbose"; | ||
declare type Suggestion = PrimitiveSuggestion | SemanticSuggestion; | ||
declare type PrimitiveSuggestion = "primitive" | "comparable"; | ||
declare type Suggestion = PrimitiveSuggestion | "abbreviated" | "as-icon" | ||
/** | ||
* @deprecated Since v0.6.3. Use `"as-icon"` or `"with-icon"` instead. | ||
*/ | ||
| "icon" | "verbose" | "with-icon"; | ||
declare type DataContext = Record<string, any>; | ||
interface FormatterOptions { | ||
@@ -8,3 +12,2 @@ /** Formatter name, useful for debugging or advanced pattern matching. */ | ||
} | ||
declare type DataContext = Record<string, any>; | ||
interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> { | ||
@@ -15,3 +18,3 @@ ( | ||
/** Suggestions passed by the consumer of a formatter. */ | ||
usageSuggestions: Suggestion[], | ||
suggestions: Suggestion[], | ||
/** Additional data context to be used by the formatter. */ | ||
@@ -21,9 +24,9 @@ dataContext: Partial<TDataContext>): TOutput | TPrimitiveOutput; | ||
interface FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> { | ||
<TSuggestion extends Suggestion>( | ||
( | ||
/** Value to format. */ | ||
value: TInput, | ||
/** Suggestions the formatter should take note of. */ | ||
usageSuggestions?: TSuggestion[], | ||
suggestions?: Suggestion[], | ||
/** Additional data context the formatter might find useful. */ | ||
dataContext?: Partial<TDataContext>): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput; | ||
dataContext?: Partial<TDataContext>): TOutput | TPrimitiveOutput; | ||
} | ||
@@ -35,3 +38,3 @@ interface FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext extends DataContext> { | ||
/** Suggestions the formatter should take note of in addition to `primitive`. */ | ||
usageSuggestions?: Suggestion[], | ||
suggestions?: Suggestion[], | ||
/** Additional data context the formatter might find useful. */ | ||
@@ -51,3 +54,3 @@ dataContext?: Partial<TDataContext>): TPrimitiveOutput; | ||
/** Suggestions the formatter should take note of. */ | ||
usageSuggestions: Suggestion[], | ||
suggestions: Suggestion[], | ||
/** Additional data context the formatter might find useful. */ | ||
@@ -69,3 +72,3 @@ dataContext: Partial<TOuterDataContext>): TOuterOutput | TOuterPrimitiveOutput; | ||
formatAsPrimitive: FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext>; | ||
/** The callee of the `.wrap` method used to produce this formatter. */ | ||
/** The callee of the `wrap` method used to produce this formatter. */ | ||
innerFormatter?: Formatter<any, any, any, any>; | ||
@@ -76,3 +79,3 @@ /** | ||
*/ | ||
wrap: <TNextInput = TInput, TNextOutput = TOutput, TNextPrimitiveOutput = TPrimitiveOutput, TNextDataContext extends DataContext = TDataContext>( | ||
wrap: <TNextInput = TInput, TNextOutput = TOutput, TNextPrimitiveOutput = TPrimitiveOutput, TNextDataContext extends TDataContext = TDataContext>( | ||
/** | ||
@@ -89,3 +92,3 @@ * Function used to format the value. Has the same signature as the one passed | ||
* | ||
* @deprecated Since v0.6.0. Prefer using the `Formatter.format` method instead. | ||
* @deprecated Since v0.6.0. Prefer using the `format` method instead. | ||
*/ | ||
@@ -92,0 +95,0 @@ (props: FormatterProps<TInput, TDataContext>): TOutput | TPrimitiveOutput | null; |
{ | ||
"name": "afformative", | ||
"version": "0.6.2", | ||
"version": "0.6.3", | ||
"license": "MIT", | ||
@@ -37,3 +37,3 @@ "main": "dist/afformative.cjs.js", | ||
"sideEffects": false, | ||
"gitHead": "3e3b893eee2b69d29019b3683b9d1d719192a2b5" | ||
"gitHead": "ddc8c8682e2777c730108466792b7670d8a43f06" | ||
} |
@@ -84,3 +84,3 @@ <h1 align="center"> | ||
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. | ||
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. | ||
@@ -90,4 +90,4 @@ ```js | ||
const booleanFormatter = makeFormatter((value, usageSuggestions) => { | ||
if (usageSuggestions.includes("primitive")) { | ||
const booleanFormatter = makeFormatter((value, suggestions) => { | ||
if (suggestions.includes("primitive")) { | ||
return value ? "True" : "False" | ||
@@ -94,0 +94,0 @@ } |
@@ -5,156 +5,215 @@ import { makeFormatter } from "./makeFormatter" | ||
const upperCaseFormatter = makeFormatter<string, string>(toUpperCase) | ||
interface ValueRecord { | ||
value: string | ||
} | ||
const valueRecordUpperCaseFormatter = makeFormatter<ValueRecord, ValueRecord, string>( | ||
({ value }, suggestions) => { | ||
if (suggestions.includes("primitive")) { | ||
return toUpperCase(value) | ||
} | ||
return { value: toUpperCase(value) } | ||
}, | ||
) | ||
describe("makeFormatter", () => { | ||
it("handles trivial formatting", () => { | ||
const formatter = makeFormatter<string, string>(toUpperCase) | ||
expect(formatter.format("foo")).toBe("FOO") | ||
const format = jest.fn() | ||
afterEach(() => { | ||
jest.clearAllMocks() | ||
}) | ||
it("accepts a `name` option", () => { | ||
const formatter = makeFormatter<string, string>(toUpperCase, { displayName: "UpperFormatter" }) | ||
expect(formatter.displayName).toBe("UpperFormatter") | ||
describe("displayName", () => { | ||
it("accepts a `displayName` option", () => { | ||
const displayName = "upperCaseFormatter" | ||
const formatter = makeFormatter<string, string>(toUpperCase, { displayName }) | ||
expect(formatter.displayName).toBe(displayName) | ||
}) | ||
}) | ||
it("passes `suggestions` to `format`", () => { | ||
const formatter = makeFormatter<string, string>((value, suggestions) => { | ||
if (suggestions.includes("abbreviated")) { | ||
return value[0] | ||
} | ||
describe("format", () => { | ||
it("handles trivial formatting", () => { | ||
expect(upperCaseFormatter.format("foo")).toBe("FOO") | ||
}) | ||
return value | ||
it("passes through non-empty suggestions", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.format("foo", ["abbreviated"]) | ||
expect(format.mock.calls[0][1]).toEqual(["abbreviated"]) | ||
}) | ||
expect(formatter.format("foo", ["abbreviated"])).toBe("f") | ||
expect(formatter.format("foo", [])).toBe("foo") | ||
expect(formatter.format("foo")).toBe("foo") | ||
}) | ||
it("passes through empty suggestions", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.format("foo", []) | ||
expect(format.mock.calls[0][1]).toEqual([]) | ||
}) | ||
it("handles formatting with the `primitive` suggestion", () => { | ||
type Structure = { value: string } | ||
it("defaults suggestions to an empty array", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.format("foo") | ||
expect(format.mock.calls[0][1]).toEqual([]) | ||
}) | ||
const formatter = makeFormatter<Structure, Structure, string>((value, suggestions) => { | ||
if (suggestions.includes("primitive")) { | ||
return value.value | ||
} | ||
it("passes through the `primitive` suggestion", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.format("foo", ["primitive"]) | ||
expect(format.mock.calls[0][1]).toEqual(["primitive"]) | ||
}) | ||
return value | ||
it("passes the `primitive` suggestion alongside `comparable` when missing", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.format("foo", ["comparable"]) | ||
expect(format.mock.calls[0][1]).toEqual(["primitive", "comparable"]) | ||
}) | ||
expect(formatter.format({ value: "foo" }, ["primitive"])).toBe("foo") | ||
expect(formatter.formatAsPrimitive({ value: "foo" })).toBe("foo") | ||
expect(formatter.formatAsPrimitive({ value: "foo" }, ["primitive"])).toBe("foo") | ||
}) | ||
it("does not pass the `primitive` suggestion alongside other suggestions when missing", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.format("foo", ["abbreviated", "verbose"]) | ||
expect(format.mock.calls[0][1]).toEqual(["abbreviated", "verbose"]) | ||
}) | ||
it("supports simple behavior wrapping", () => { | ||
const formatter = makeFormatter<string, string>(toUpperCase) | ||
it("supports data context", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.format("foo", [], { foo: "bar" }) | ||
expect(format.mock.calls[0][2]).toEqual({ foo: "bar" }) | ||
}) | ||
const wrappedFormatter = formatter.wrap((delegate, value) => | ||
value === "foo" ? "override" : delegate(value), | ||
) | ||
expect(wrappedFormatter.format("foo")).toBe("override") | ||
expect(wrappedFormatter.format("bar")).toBe("BAR") | ||
it("defaults data context to an empty object", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.format("foo") | ||
expect(format.mock.calls[0][2]).toEqual({}) | ||
}) | ||
}) | ||
it("supports simple behavior wrapping with suggestions", () => { | ||
const formatter = makeFormatter<string, string>(toUpperCase) | ||
describe("formatAsPrimitive", () => { | ||
it("handles trivial formatting", () => { | ||
expect(upperCaseFormatter.formatAsPrimitive("foo")).toBe("FOO") | ||
}) | ||
const wrappedFormatter = formatter.wrap((delegate, value, suggestions) => | ||
value === "foo" && suggestions.includes("abbreviated") ? "f" : delegate(value), | ||
) | ||
it("passes the `primitive` suggestion when no suggestions are passed", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.formatAsPrimitive("foo") | ||
expect(format.mock.calls[0][1]).toEqual(["primitive"]) | ||
}) | ||
expect(wrappedFormatter.format("foo")).toBe("FOO") | ||
expect(wrappedFormatter.format("foo", ["abbreviated"])).toBe("f") | ||
expect(wrappedFormatter.format("bar")).toBe("BAR") | ||
}) | ||
it("passes the `primitive` suggestion when empty suggestions are passed", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.formatAsPrimitive("foo", []) | ||
expect(format.mock.calls[0][1]).toEqual(["primitive"]) | ||
}) | ||
it("supports simple behavior wrapping with the `primitive` suggestion", () => { | ||
type Structure = { value: string } | ||
it("passes the `primitive` suggestion when a different suggestion is passed", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.formatAsPrimitive("foo", ["abbreviated"]) | ||
expect(format.mock.calls[0][1]).toEqual(["primitive", "abbreviated"]) | ||
}) | ||
const formatter = makeFormatter<string, string>(toUpperCase) | ||
it("passes through the `primitive` suggestion", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.formatAsPrimitive("foo", ["primitive"]) | ||
expect(format.mock.calls[0][1]).toEqual(["primitive"]) | ||
}) | ||
const wrappedFormatter = formatter.wrap<Structure, Structure, string>( | ||
(delegate, value, suggestions) => (suggestions.includes("primitive") ? value.value : value), | ||
) | ||
it("passes the `primitive` suggestion alongside `comparable`", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.formatAsPrimitive("foo", ["comparable"]) | ||
expect(format.mock.calls[0][1]).toEqual(["primitive", "comparable"]) | ||
}) | ||
expect(wrappedFormatter.format({ value: "foo" }, ["primitive"])).toBe("foo") | ||
expect(wrappedFormatter.formatAsPrimitive({ value: "foo" })).toBe("foo") | ||
expect(wrappedFormatter.formatAsPrimitive({ value: "foo" }, ["primitive"])).toBe("foo") | ||
it("supports data context", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.formatAsPrimitive("foo", [], { foo: "bar" }) | ||
expect(format.mock.calls[0][2]).toEqual({ foo: "bar" }) | ||
}) | ||
it("defaults data context to an empty object", () => { | ||
const formatter = makeFormatter<string, string>(format) | ||
formatter.formatAsPrimitive("foo") | ||
expect(format.mock.calls[0][2]).toEqual({}) | ||
}) | ||
}) | ||
it("supports simple behavior wrapping with data context", () => { | ||
const formatter = makeFormatter<string, string>(toUpperCase) | ||
describe("wrap", () => { | ||
it("handles trivial wrapping", () => { | ||
const formatter = makeFormatter<string, string>(format).wrap(() => "bar") | ||
expect(formatter.format("foo")).toBe("bar") | ||
}) | ||
interface WrappedDataContext { | ||
forcedValue?: string | ||
} | ||
it("handles single-value mapping", () => { | ||
const formatter = makeFormatter<string, string>(format).wrap((delegate, value) => | ||
value === "ping" ? "pong" : delegate(value), | ||
) | ||
const wrappedFormatter = formatter.wrap( | ||
(delegate, value, suggestions, { forcedValue }: WrappedDataContext) => | ||
forcedValue ?? delegate(value), | ||
) | ||
expect(formatter.format("ping")).toBe("pong") | ||
}) | ||
expect(wrappedFormatter.format("foo")).toBe("FOO") | ||
expect(wrappedFormatter.format("foo", undefined, { forcedValue: "override" })).toBe("override") | ||
}) | ||
it("handles delegation to the original formatter", () => { | ||
const formatter = upperCaseFormatter.wrap((delegate, value) => | ||
value === "ping" ? "pong" : delegate(value), | ||
) | ||
it("passes the original suggestions when they are not passed manually to `format` when wrapping", () => { | ||
const formatter = makeFormatter<string, string>((value, suggestions) => { | ||
if (suggestions.includes("abbreviated")) { | ||
return value[0] | ||
} | ||
expect(formatter.format("foo")).toBe("FOO") | ||
}) | ||
return value | ||
it("sets the `innerFormatter` property", () => { | ||
const wrappedFormatter = upperCaseFormatter.wrap((delegate, value) => delegate(value)) | ||
expect(wrappedFormatter.innerFormatter).toBe(upperCaseFormatter) | ||
}) | ||
const wrappedFormatter = formatter.wrap((delegate, value) => delegate(value)) | ||
expect(wrappedFormatter.format("foo", ["abbreviated"])).toBe("f") | ||
}) | ||
it("passes the `primitive` suggestion to `delegate` when using `formatAsPrimitive`", () => { | ||
const formatter = valueRecordUpperCaseFormatter.wrap((delegate, value) => delegate(value)) | ||
expect(formatter.formatAsPrimitive({ value: "foo" })).toBe("FOO") | ||
}) | ||
it("sets the `innerFormatter` static property when wrapping", () => { | ||
const formatter = makeFormatter<string, string>(toUpperCase) | ||
const wrappedFormatter = formatter.wrap((delegate, value) => delegate(value)) | ||
expect(wrappedFormatter.innerFormatter).toBe(formatter) | ||
}) | ||
it("passes suggestions through to `delegate` when not overriden", () => { | ||
const formatter = valueRecordUpperCaseFormatter.wrap((delegate, value) => delegate(value)) | ||
expect(formatter.format({ value: "foo" }, ["primitive"])).toBe("FOO") | ||
}) | ||
it("handles complex wrapping with structural changes", () => { | ||
interface BasicDataContext { | ||
index?: number | ||
} | ||
it("supports overriding of suggestions for `delegate`", () => { | ||
const formatter = valueRecordUpperCaseFormatter.wrap((delegate, value) => delegate(value, [])) | ||
expect(formatter.format({ value: "foo" }, ["primitive"])).toEqual({ value: "FOO" }) | ||
}) | ||
const basicFormatter = makeFormatter( | ||
(value: string, suggestions, dataContext: BasicDataContext): string | undefined => | ||
value[dataContext.index ?? 0], | ||
) | ||
it("supports modifying the input structure", () => { | ||
const formatter = upperCaseFormatter.wrap<ValueRecord>((delegate, { value }) => | ||
delegate(value), | ||
) | ||
expect(basicFormatter.format("test", [], { index: 2 })).toBe("s") | ||
expect(formatter.format({ value: "foo" })).toBe("FOO") | ||
}) | ||
interface ComplexStructure { | ||
index: number | ||
value: string | ||
} | ||
it("supports modifying the output structure", () => { | ||
const formatter = upperCaseFormatter.wrap<ValueRecord, ValueRecord>( | ||
(delegate, { value }) => ({ value: delegate(value) }), | ||
) | ||
interface ComplexDataContext { | ||
getIndex?: (structure: ComplexStructure) => number | ||
} | ||
expect(formatter.format({ value: "foo" })).toEqual({ value: "FOO" }) | ||
}) | ||
const complexFormatter = basicFormatter.wrap( | ||
(delegate, value: ComplexStructure, suggestions, dataContext: ComplexDataContext) => | ||
delegate(value.value, suggestions, { index: dataContext.getIndex?.(value) }), | ||
) | ||
it("supports modifying the data context structure", () => { | ||
interface ListContext { | ||
row: string | ||
} | ||
expect(complexFormatter.format({ index: 3, value: "procrastination" })).toBe("p") | ||
const listFormatter = upperCaseFormatter.wrap<string, string, string, ListContext>( | ||
(delegate, value, suggestions, { row }) => `${row}: ${delegate(value)}`, | ||
) | ||
expect( | ||
complexFormatter.format({ index: 3, value: "procrastination" }, [], { | ||
getIndex: ({ index }) => index, | ||
}), | ||
).toBe("c") | ||
interface GridContext extends ListContext { | ||
column: string | ||
} | ||
const boundComplexFormatter = complexFormatter.wrap( | ||
(delegate, value, suggestions, dataContext) => | ||
delegate(value, suggestions, { ...dataContext, getIndex: ({ index }) => index }), | ||
) | ||
expect(listFormatter.format("foo", [], { row: "A" })).toBe("A: FOO") | ||
expect(boundComplexFormatter.format({ index: 2, value: "swag" })).toBe("a") | ||
const gridFormatter = listFormatter.wrap<string, string, string, GridContext>( | ||
(delegate, value, suggestions, { column }) => delegate(value).replace(":", `${column}:`), | ||
) | ||
expect(gridFormatter.format("foo", [], { row: "B", column: "1" })).toBe("B1: FOO") | ||
}) | ||
}) | ||
}) |
@@ -1,5 +0,24 @@ | ||
type PrimitiveSuggestion = "primitive" | ||
type SemanticSuggestion = "abbreviated" | "icon" | "verbose" | ||
type Suggestion = PrimitiveSuggestion | SemanticSuggestion | ||
type PrimitiveSuggestion = "primitive" | "comparable" | ||
type Suggestion = | ||
| PrimitiveSuggestion | ||
| "abbreviated" | ||
| "as-icon" | ||
/** | ||
* @deprecated Since v0.6.3. Use `"as-icon"` or `"with-icon"` instead. | ||
*/ | ||
| "icon" | ||
| "verbose" | ||
| "with-icon" | ||
const ensureFormatSuggestionIntegrity = (suggestions: Suggestion[]): Suggestion[] => | ||
suggestions.includes("primitive") || !suggestions.includes("comparable") | ||
? suggestions | ||
: ["primitive", ...suggestions] | ||
const ensureFormatAsPrimitiveSuggestionIntegrity = (suggestions: Suggestion[]): Suggestion[] => | ||
suggestions.includes("primitive") ? suggestions : ["primitive", ...suggestions] | ||
type DataContext = Record<string, any> | ||
interface FormatterOptions { | ||
@@ -10,17 +29,2 @@ /** Formatter name, useful for debugging or advanced pattern matching. */ | ||
type DataContext = Record<string, any> | ||
// TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly | ||
// verify the return type of the format definition based on the suggestions, printing errors such | ||
// as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'` | ||
// which is, of course, nonsense. Same applies to `FormatChainDefinition`. | ||
// | ||
// interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> { | ||
// <TSuggestion extends Suggestion>( | ||
// value: TInput, | ||
// usageSuggestions: TSuggestion[], | ||
// dataContext: Partial<TDataContext>, | ||
// ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput | ||
// } | ||
interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> { | ||
@@ -31,3 +35,3 @@ ( | ||
/** Suggestions passed by the consumer of a formatter. */ | ||
usageSuggestions: Suggestion[], | ||
suggestions: Suggestion[], | ||
/** Additional data context to be used by the formatter. */ | ||
@@ -39,10 +43,10 @@ dataContext: Partial<TDataContext>, | ||
interface FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> { | ||
<TSuggestion extends Suggestion>( | ||
( | ||
/** Value to format. */ | ||
value: TInput, | ||
/** Suggestions the formatter should take note of. */ | ||
usageSuggestions?: TSuggestion[], | ||
suggestions?: Suggestion[], | ||
/** Additional data context the formatter might find useful. */ | ||
dataContext?: Partial<TDataContext>, | ||
): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput | ||
): TOutput | TPrimitiveOutput | ||
} | ||
@@ -55,3 +59,3 @@ | ||
/** Suggestions the formatter should take note of in addition to `primitive`. */ | ||
usageSuggestions?: Suggestion[], | ||
suggestions?: Suggestion[], | ||
/** Additional data context the formatter might find useful. */ | ||
@@ -82,3 +86,3 @@ dataContext?: Partial<TDataContext>, | ||
/** Suggestions the formatter should take note of. */ | ||
usageSuggestions: Suggestion[], | ||
suggestions: Suggestion[], | ||
/** Additional data context the formatter might find useful. */ | ||
@@ -108,3 +112,3 @@ dataContext: Partial<TOuterDataContext>, | ||
formatAsPrimitive: FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext> | ||
/** The callee of the `.wrap` method used to produce this formatter. */ | ||
/** The callee of the `wrap` method used to produce this formatter. */ | ||
innerFormatter?: Formatter<any, any, any, any> | ||
@@ -119,3 +123,3 @@ /** | ||
TNextPrimitiveOutput = TPrimitiveOutput, | ||
TNextDataContext extends DataContext = TDataContext | ||
TNextDataContext extends TDataContext = TDataContext | ||
>( | ||
@@ -143,3 +147,3 @@ /** | ||
* | ||
* @deprecated Since v0.6.0. Prefer using the `Formatter.format` method instead. | ||
* @deprecated Since v0.6.0. Prefer using the `format` method instead. | ||
*/ | ||
@@ -164,15 +168,16 @@ (props: FormatterProps<TInput, TDataContext>): TOutput | TPrimitiveOutput | null | ||
): Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext> => { | ||
const formatter: Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext> = ({ | ||
children, | ||
suggestions = [], | ||
...dataContext | ||
}) => format(children, suggestions, dataContext as any) ?? null | ||
const formatter: Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext> = props => | ||
format(props.children, props.suggestions ?? [], props) ?? null | ||
formatter.displayName = formatterOptions?.displayName | ||
formatter.format = (value, usageSuggestions = [], dataContext = {}) => | ||
format(value, usageSuggestions, dataContext) as any | ||
formatter.format = (value, suggestions = [], dataContext = {}) => | ||
format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext) | ||
formatter.formatAsPrimitive = (value, usageSuggestions = [], dataContext = {}) => | ||
format(value, ["primitive", ...usageSuggestions], dataContext) as any | ||
formatter.formatAsPrimitive = (value, suggestions = [], dataContext = {}) => | ||
format( | ||
value, | ||
ensureFormatAsPrimitiveSuggestionIntegrity(suggestions), | ||
dataContext, | ||
) as TPrimitiveOutput | ||
@@ -183,3 +188,3 @@ formatter.wrap = < | ||
TNextPrimitiveOutput, | ||
TNextDataContext extends DataContext | ||
TNextDataContext extends TDataContext | ||
>( | ||
@@ -198,3 +203,3 @@ nextFormat: FormatChainDefinition< | ||
) => { | ||
const nextFormatter: Formatter< | ||
const nextFormatter = makeFormatter< | ||
TNextInput, | ||
@@ -204,6 +209,6 @@ TNextOutput, | ||
TNextDataContext | ||
> = makeFormatter((value, usageSuggestions, dataContext) => { | ||
>((value, suggestions, dataContext) => { | ||
const delegate: FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext> = ( | ||
delegatedValue, | ||
delegatedUsageSuggestions, | ||
delegatedSuggestions, | ||
delegatedDataContext, | ||
@@ -213,7 +218,7 @@ ) => | ||
delegatedValue, | ||
delegatedUsageSuggestions ?? usageSuggestions, | ||
(delegatedDataContext ?? dataContext) as any, | ||
) as any | ||
delegatedSuggestions ?? suggestions, | ||
delegatedDataContext ?? dataContext, | ||
) | ||
return nextFormat(delegate, value, usageSuggestions, dataContext) as any | ||
return nextFormat(delegate, value, suggestions, dataContext) | ||
}, nextFormatterOptions ?? formatterOptions) | ||
@@ -220,0 +225,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
42883
649