This repository has been archived on 2020-11-02. You can view files and clone it, but cannot push or open issues or pull requests.
2020-11-01 22:46:04 +00:00

109 lines
2.1 KiB
Plaintext

// @flow
declare class MatchData extends Array<string> {
index: number;
}
export type { MatchData }
const DEFAULT_INDEX = 2
function DEFAULT_TEMPLATE(value) {
return value
}
/**
* Properties for a strategy.
*
* @typedef
*/
export type StrategyProperties = {
match: RegExp | (string => MatchData | null),
search: Function,
replace: any => string[] | string | null,
cache?: boolean,
context?: Function,
template?: any => string,
index?: number,
id?: string,
}
/**
* Encapsulate a single strategy.
*/
export default class Strategy {
props: StrategyProperties
cache: ?Object
constructor(props: StrategyProperties) {
this.props = props
this.cache = props.cache ? {} : null
}
/**
* @return {this}
*/
destroy() {
this.cache = null
return this
}
search(term: string, callback: Function, match: MatchData): void {
if (this.cache) {
this.searchWithCache(term, callback, match)
} else {
this.props.search(term, callback, match)
}
}
/**
* @param {object} data - An element of array callbacked by search function.
*/
replace(data: any) {
return this.props.replace(data)
}
/** @private */
searchWithCache(term: string, callback: Function, match: MatchData): void {
if (this.cache && this.cache[term]) {
callback(this.cache[term])
} else {
this.props.search(
term,
results => {
if (this.cache) {
this.cache[term] = results
}
callback(results)
},
match,
)
}
}
/** @private */
matchText(text: string): MatchData | null {
if (typeof this.match === "function") {
return this.match(text)
} else {
return (text.match(this.match): any)
}
}
/** @private */
get match(): $PropertyType<StrategyProperties, "match"> {
return this.props.match
}
/** @private */
get index(): number {
return typeof this.props.index === "number"
? this.props.index
: DEFAULT_INDEX
}
get template(): (...any) => string {
return this.props.template || DEFAULT_TEMPLATE
}
}