@typescript-package/affix
Version:
A lightweight TypeScript library for different kind of affixes.
583 lines (573 loc) • 23.3 kB
JavaScript
/**
* @description A core abstract class to manage affixes with the value and kind that can be applied to strings.
* @export
* @abstract
* @class AffixCore
* @template {string | [string, string]} [Value=string | [string, string]] The type of affix constrained by the `string` and tuple of strings. Defaults to `string`.
* @template {BasicAffixKind | undefined} [Kind=BasicAffixKind | undefined] The kind of affix.
*/
class AffixCore {
/**
* @description Checks if the given instance is an instance of `AffixCore`.
* @public
* @static
* @param {any} instance The instance to check.
* @returns {boolean} The boolean value indicating whether the instance is of type `AffixCore`.
*/
static is(instance) {
return Object.prototype.toString.call(instance).match(/\[object (\w+)]/)?.[1] === this.tagName;
}
/**
* @description Tag name for the `toStringTag`.
* @public
* @static
* @type {string}
*/
static tagName = 'AffixCore';
/**
* @description Returns the `string` tag representation of the `Affix` class when used in `Object.prototype.toString.call(instance)`.
* @public
* @readonly
* @type {string}
*/
get [Symbol.toStringTag]() {
return AffixCore.tagName;
}
/**
* @description Returns the kind of affix.
* @public
* @readonly
* @type {(Kind)}
*/
get kind() {
return this.#kind;
}
/**
* @description Returns the privately stored affix of generic type variable `Value` constrained by `string` type.
* @public
* @readonly
* @type {Value}
*/
get value() {
return this.#value;
}
/**
* @description Privately stored kind of `Kind` to define the type of affix.
* @type {Kind | undefined}
*/
#kind;
/**
* @description Privately stored affix of generic type variable `Value` constrained by `string` type.
* @type {Value}
*/
#value;
/**
* Creates an instance of `AffixCore`.
* @constructor
* @param {Value} value An optional initial affix of generic type variable `Value` constrained by `string` type. Defaults to `Affix.pattern`.
* @param {?Kind} [kind] The kind of generic type variable `Kind` constrained by `BasicAffixKind` type. Defaults to `undefined`.
*/
constructor(value, kind) {
this.#kind = kind;
this.#value = value;
}
/**
* @description Sets the kind of affix.
* @public
* @param {Kind} kind The kind of generic type variable `Kind` constrained by `BasicAffixKind` type.
* @returns {this} The returned value is current instance for method chaining.
*/
setKind(kind) {
this.#kind = kind;
return this;
}
/**
* @description Sets the value of the affix, sanitizing it according to the defined pattern.
* @public
* @param {Value} value
* @returns {this}
*/
setValue(value) {
this.#value = value;
return this;
}
}
// Abstract.
/**
* @description A concrete class to manage affixes that can be applied to strings with additional sanitization.
* @export
* @class Affix
* @template {string | [string, string]} [Value=string | [string, string]] The type of affix constrained by the `string`. Defaults to `string`.
* @template {BasicAffixKind | undefined} [Kind=BasicAffixKind | undefined]
* @template {RegExp | string | undefined} [Pattern=RegExp | string | undefined]
*/
class Affix extends AffixCore {
/**
* @description Defines the affix sanitized by specified pattern.
* @public
* @static
* @template {string | [string, string]} [Value=string | [string, string]] The type of affix constrained by the `string` type. Defaults to `string`.
* @param {Value} value A value of generic type variable `Value` constrained by the `string` type to be sanitized with the `pattern`.
* @param {RegExp | string} [pattern=Affix.pattern] The pattern of `RegExp` to sanitize the `affix`. Defaults to static `Affix.pattern`.
* @returns {Value} The returned value is an affix of a generic type variable `Value`, optionally sanitized by the `pattern`.
*/
static sanitize(value, pattern = this.pattern) {
return (typeof value === 'string'
? value.replace(pattern, '')
: value.map(v => v.replace(pattern, '')));
}
/**
* @description The default pattern used to sanitize the affix, which removes characters that are not part of the valid characters for the affix.
* @public
* @static
* @type {RegExp | string}
*/
static pattern = /[^a-zA-Z0-9$_]/g;
/**
* @description Tag name for the `toStringTag`.
* @public
* @static
* @type {string}
*/
static tagName = Affix.name;
/**
* @description Returns the `string` tag representation of the `Affix` class when used in `Object.prototype.toString.call(instance)`.
* @public
* @readonly
* @type {string}
*/
get [Symbol.toStringTag]() {
return Affix.tagName;
}
/**
* @description Returns the privately stored pattern of `PatternValue` type to sanitize the affix.
* @public
* @readonly
* @type {(Pattern)}
*/
get pattern() {
return this.#pattern;
}
/**
* @description Privately stored pattern of `Pattern` to sanitize the affix.
* @type {Pattern | undefined}
*/
#pattern;
/**
* Creates an instance of `Affix`.
* @constructor
* @param {Value} value An optional initial affix of generic type variable `Value` constrained by `string` type. Defaults to `Affix.pattern`.
* @param {{ kind?: Kind, pattern?: Pattern }} [param0={}] The options object to set the kind and pattern of the affix.
* @param {Kind} param0.kind The kind of affix constrained by `BasicAffixKind` type.
* @param {Pattern} param0.pattern The pattern of `PatternValue` to sanitize the affix.
*/
constructor(value, { kind, pattern } = {}) {
super(Affix.sanitize(value, pattern), kind);
this.#pattern = pattern ?? Affix.pattern;
}
/**
* @description Returns the affix, optionally sanitized by the `pattern`.
* @public
* @param {(Pattern)} [pattern=this.#pattern] The pattern of `RegExp` to sanitize privately stored affix.
* @returns {Value} Returns privately stored `#affix` of `Value` type optionally sanitized by the `pattern`.
*/
get(pattern = this.#pattern) {
return Affix.sanitize(super.value, pattern);
}
/**
* @description Sets and stores privately sanitized affix of generic type variable `Value` constrained by `string` type.
* @public
* @param {({ kind?: Kind, pattern?: Pattern, value?: Value})} [param0={}]
* @param {Kind} param0.kind The kind of affix constrained by `BasicAffixKind` type.
* @param {Pattern} param0.pattern The pattern of `Pattern` to sanitize the affix.
* @param {Value} param0.value The value of the affix constrained by `string` type.
* @returns {this} The returned value is current instance for method chaining.
*/
set({ kind, pattern, value } = {}) {
typeof value === 'string' && this.setValue(Affix.sanitize(value, pattern));
'kind' in arguments[0] && this.setKind(kind);
'pattern' in arguments[0] && this.setPattern(pattern);
return this;
}
/**
* @description Sets the pattern to sanitize the affix.
* @public
* @param {Pattern} pattern The pattern of `Pattern` to sanitize the affix.
* @returns {this} The returned value is current instance for method chaining.
*/
setPattern(pattern) {
this.#pattern = pattern;
return this;
}
}
// Class.
/**
* @description A class to manage circumfixes that can be applied to strings.
* @export
* @class Circumfix
* @template {string} [Start=string] The type of circumfix constrained by the `string`. Defaults to `string`.
* @template {string} [End=Start] The type of circumfix end constrained by the `string`, defaults to the same type as `Start`.
* @template {RegExp | string | undefined} [Pattern=RegExp | string | undefined] The type of pattern constrained by the `RegExp` or `string`.
* @extends {Affix<[Start, End], 'circumfix', Pattern>}
*/
class Circumfix extends Affix {
/**
* @description Inserts a circumfix to a given stem with an optional delimiter.
* @public
* @static
* @template {string} [Start=string] The type of circumfix start constrained by the `string`. Defaults to `string`.
* @template {string} [Stem=string] The type of stem constrained by the `string`. Defaults to `string`.
* @template {string} [End=Start] The type of circumfix end constrained by the `string`, defaults to the same type as `Start`.
* @template {string} [Delimiter=''] The type of delimiter constrained by the `string`, defaults to an empty string.
* @param {Stem} stem The stem to which the circumfix will be inserted.
* @param {(Start | [Start, End])} [circumfix=Circumfix.default as Start] The circumfix to be applied.
* @param {Delimiter} [delimiter='' as Delimiter] The delimiter to be used.
* @returns {CircumfixTemplate<Start, Stem, End, Delimiter>} The resulting circumfixed string.
*/
static insert(stem, circumfix = Circumfix.default, delimiter = '') {
return `${typeof circumfix === 'string' ? circumfix : circumfix[0]}${delimiter}${stem}${delimiter}${typeof circumfix === 'string' ? circumfix : circumfix[1]}`;
}
/**
* @inheritdoc
* @public
* @static
* @type {string}
*/
static tagName = 'Circumfix';
/**
* @description The default circumfix value, which is an empty string. This is used when no circumfix is provided.
* @public
* @static
* @type {string | [string, string]}
*/
static default = '';
/**
* @description Returns the `string` tag representation of the `Circumfix` class when used in `Object.prototype.toString.call(instance)`.
* @public
* @readonly
* @type {string}
*/
get [Symbol.toStringTag]() {
return Circumfix.tagName;
}
/**
* @description The circumfix value, which is a tuple containing the start and end of the circumfix.
* @public
* @readonly
* @type {[Start, End]}
*/
get circumfix() {
return this.value;
}
/**
* @description The end of the circumfix, which is the second element of the tuple.
* @public
* @readonly
* @type {End}
*/
get end() {
return this.value[1];
}
/**
* @description The start of the circumfix, which is the first element of the tuple.
* @public
* @readonly
* @type {Start}
*/
get start() {
return this.value[0];
}
/**
* Creates an instance of `Circumfix`.
* @constructor
* @param {Start} [start='' as Value] The value of the prefix, constrained by the `string` type. Defaults to an empty string.
* @param {End} [end=start as End] The value of the suffix, constrained by the `string` type, defaults to the same type as `start`.
* @param {Pattern} [pattern=Circumfix.pattern] The pattern to sanitize the prefix. Defaults to the static `Circumfix.pattern`.
*/
constructor(start = '', end = start, pattern = Circumfix.pattern) {
super([start, end], { kind: 'circumfix', pattern });
}
/**
* @description Inserts the circumfix to a given stem with an optional delimiter.
* @param {string} stem The stem to which the circumfix will be inserted.
* @returns {string} The resulting string with the circumfix inserted.
*/
insertTo(stem, delimiter = '') {
return Circumfix.insert(stem, [this.start, this.end], delimiter);
}
}
// Class.
/**
* @description A class to manage infixes that can be applied to strings.
* @export
* @class Infix
* @template {string} [Value=string] The type of infix constrained by the `string`.
* @template {RegExp | string | undefined} [Pattern=RegExp | string | undefined] The type of pattern constrained by the `RegExp` or `string`.
* @extends {Affix<Value, 'infix', Pattern>}
*/
class Infix extends Affix {
/**
* @description Inserts the infix into a given stem at a specified position with an optional delimiter.
* @public
* @static
* @template {string} Infix Type of the infix constrained by the `string`.
* @template {string} [Stem=string] The type of the stem string.
* @template {number} [Position=number] The type of the position number, defaults to `Math.floor(stem.length / 2)`.
* @template {string} [Delimiter=''] The type of delimiter string, defaults to an empty string.
* @param {Infix} infix The infix to insert into the stem at specified position.
* @param {Stem} stem The stem to insert the infix into its specified position.
* @param {Position} [position=Math.floor(stem.length / 2) as Position] The position of stem to insert the infix.
* @param {Delimiter} [delimiter='' as Delimiter] The delimiter to use between the two halves of stem and infix.
* @returns {InfixTemplate<SplitAt<Stem, Position>[0], Infix, SplitAt<Stem, Position>[1], Delimiter>}
*/
static insert(stem, infix, position = Math.floor(stem.length / 2), delimiter = '') {
return `${stem.slice(0, position)}${delimiter}${infix}${delimiter}${stem.slice(position)}`;
}
/**
* @description Tag name for the `toStringTag`.
* @public
* @static
* @type {string}
*/
static tagName = 'Infix';
/**
* @description The default infix to use.
* @public
* @static
* @type {string}
*/
static default = '';
/**
* @description Returns the `string` tag representation of the `Infix` class when used in `Object.prototype.toString.call(instance)`.
* @public
* @readonly
* @type {string}
*/
get [Symbol.toStringTag]() {
return Infix.tagName;
}
/**
* @description The infix value, which is a generic type variable `Value` constrained by the `string` type.
* @public
* @readonly
* @type {Value}
*/
get infix() {
return this.value;
}
/**
* Creates an instance of `Infix`.
* @constructor
* @param {Value} [value='' as Value] The value of the infix, constrained by the `string` type. Defaults to an empty string.
* @param {Pattern} [pattern=Infix.pattern] The pattern to sanitize the infix. Defaults to the static `Infix.pattern`.
*/
constructor(value = '', pattern = Infix.pattern) {
super(value, { kind: 'infix', pattern });
}
/**
* @description Inserts the infix into a given stem at a specified position with an optional delimiter.
* @public
* @template {string} [Stem=string] The type of the stem string.
* @template {number} [Position=number] The type of the position number, defaults to `Math.floor(stem.length / 2)`.
* @template {string} [Delimiter=''] The type of delimiter string, defaults to an empty string.
* @param {Stem} stem The stem to insert the infix into specified position of stem.
* @param {Position} [position=Math.floor(stem.length / 2) as Position] The position of stem to insert the infix.
* @param {Delimiter} [delimiter='' as Delimiter] The delimiter to use between the two halves of stem and infix.
* @returns {InfixTemplate<SplitAt<Stem, Position>[0], Value, SplitAt<Stem, Position>[1], Delimiter>}
*/
insertTo(stem, position = Math.floor(stem.length / 2), delimiter = '') {
return Infix.insert(stem, this.value, position, delimiter);
}
}
// Class.
/**
* @description A class to manage prefixes that can be applied to strings.
* @export
* @class Prefix
* @template {string} [Value=string] The type of prefix constrained by the `string`.
* @template {RegExp | string | undefined} [Pattern=RegExp | string | undefined] The type of pattern constrained by the `RegExp` or `string`.
* @extends {Affix<Value, 'prefix', Pattern>}
*/
class Prefix extends Affix {
/**
* @description Prepends the prefix to stem string.
* @public
* @static
* @template {string} [Stem=string] The type of stem string constrained by the `string`.
* @template {string} [Prefix=string] The type of prefix constrained by the `string`.
* @param {Stem} stem The stem string to append the prefix.
* @param {Prefix} [prefix=Prefix.default as Prefix] Prefix to append to stem.
* @param {Delimiter} [delimiter='' as Delimiter] The delimiter to use between the prefix and the stem.
* @param {boolean} [sanitize=true] Whether to sanitize the prefix using the static `Prefix.pattern`.
* @returns {PrefixTemplate<Prefix, Stem, Delimiter>}
*/
static prepend(stem, prefix = Prefix.default, delimiter = '', sanitize = true) {
return `${sanitize ? super.sanitize(prefix, this.pattern) : prefix}${delimiter}${stem}`;
}
/**
* @description Tag name for the `toStringTag`.
* @public
* @static
* @type {string}
*/
static tagName = 'Prefix';
/**
* @description The default prefix to use.
* @public
* @static
* @type {string}
*/
static default = '';
/**
* @description Returns the `string` tag representation of the `Prefix` class when used in `Object.prototype.toString.call(instance)`.
* @public
* @readonly
* @type {string}
*/
get [Symbol.toStringTag]() {
return Prefix.tagName;
}
/**
* @description The prefix value of the generic type variable `Value` constrained by the `string` type.
* @public
* @readonly
* @type {Value}
*/
get prefix() {
return this.value;
}
/**
* Creates an instance of `Prefix`.
* @constructor
* @param {Value} [value='' as Value] The value of the prefix, constrained by the `string` type. Defaults to an empty string.
* @param {Pattern} [pattern=Prefix.pattern] The pattern to sanitize the prefix. Defaults to the static `Prefix.pattern`.
*/
constructor(value = '', pattern = Prefix.pattern) {
super(value, { kind: 'prefix', pattern });
}
/**
* @description Prepends the prefix to stem string.
* @public
* @template {string} [Stem=string] The type of the stem string.
* @template {string} [Delimiter=''] The type of delimiter string.
* @param {Stem} stem The stem to prepend the prefix.
* @param {Delimiter} [delimiter='' as Delimiter] The delimiter to use between the prefix and the stem.
* @returns {PrefixTemplate<Value, Stem, Delimiter>} The resulting string with the prefix prepended.
*/
prependTo(stem, delimiter = '') {
return Prefix.prepend(stem, Prefix.sanitize(this.prefix, this.pattern), delimiter);
}
/**
* Sets the pattern and value for the prefix affix.
* @inheritdoc
* @public
* @param {{ pattern?: Pattern, value?: Value }} [param0={}]
* @param {Pattern} param0.pattern The pattern to sanitize the prefix.
* @param {Value} param0.value The value of the prefix, constrained by the `string` type.
* @returns {this} The current instance of `Prefix`.
*/
set({ pattern, value } = {}) {
super.set({ pattern, value });
return this;
}
}
// Class.
/**
* @description A class to manage suffixes that can be applied to strings.
* @export
* @class Suffix
* @template {string} [Value=string] The type of suffix constrained by the `string`.
* @template {RegExp | string | undefined} [Pattern=RegExp | string | undefined] The type of pattern constrained by the `RegExp` or `string`.
* @extends {Affix<Value, 'suffix', Pattern>}
*/
class Suffix extends Affix {
/**
* @description Appends the suffix to the stem string.
* @public
* @static
* @template {string} [Stem=string] The type of stem string constrained by the `string`.
* @template {string} [Suffix=string] The type of suffix constrained by the `string`.
* @param {Stem} stem The stem string to append the suffix.
* @param {Suffix} [suffix=Suffix.default as Suffix] Suffix to append to stem.
* @param {Delimiter} [delimiter='' as Delimiter] The delimiter to use between the stem and the suffix.
* @param {boolean} [sanitize=true] Whether to sanitize the suffix using the static `Suffix.pattern`.
* @returns {SuffixTemplate<Stem, Suffix>}
*/
static append(stem, suffix = Suffix.default, delimiter = '', sanitize = true) {
return `${stem}${delimiter}${sanitize ? super.sanitize(suffix, this.pattern) : suffix}`;
}
/**
* @description Tag name for the `toStringTag`.
* @public
* @static
* @type {string}
*/
static tagName = 'Suffix';
/**
* @description The default suffix to use.
* @public
* @static
* @type {string}
*/
static default = '';
/**
* @description Returns the `string` tag representation of the `Suffix` class when used in `Object.prototype.toString.call(instance)`.
* @public
* @readonly
* @type {string}
*/
get [Symbol.toStringTag]() {
return Suffix.tagName;
}
/**
* @description The suffix value of generic type variable `Value` constrained by the `string` type.
* @public
* @readonly
* @type {Value}
*/
get suffix() {
return this.value;
}
/**
* Creates an instance of `Suffix`.
* @constructor
* @param {Value} [value='' as Value] The value of the suffix, constrained by the `string` type. Defaults to an empty string.
* @param {(Pattern)} [pattern=Suffix.pattern] The pattern to sanitize the suffix. Defaults to the static `Suffix.pattern`.
*/
constructor(value = '', pattern = Suffix.pattern) {
super(value, { kind: 'suffix', pattern });
}
/**
* @description Appends the internal suffix to the stem string.
* @public
* @template {string} Stem The type of stem string.
* @param {Stem} stem The stem string to append the suffix.
* @param {Delimiter} delimiter The delimiter between stem and suffix.
* @returns {SuffixTemplate<Stem, Value, Delimiter>} The returned value is a template of stem and suffix.
*/
appendTo(stem, delimiter = '') {
return Suffix.append(stem, Suffix.sanitize(this.suffix, this.pattern), delimiter, false);
}
/**
* Sets the pattern and value for the suffix affix.
* @inheritdoc
* @public
* @param {{ pattern?: Pattern, value?: Value }} [param0={}]
* @param {Pattern} param0.pattern The pattern to sanitize the suffix.
* @param {Value} param0.value The value of the suffix, constrained by the `string` type.
* @returns {this} The current instance of `Suffix`.
*/
set({ pattern, value } = {}) {
super.set({ pattern, value });
return this;
}
}
// Abstract.
/*
* Public API Surface of affix
*/
/**
* Generated bundle index. Do not edit.
*/
export { Affix, AffixCore, Circumfix, Infix, Prefix, Suffix };
//# sourceMappingURL=typescript-package-affix.mjs.map