109 lines
2.1 KiB
Plaintext
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
|
|
}
|
|
}
|