/**
* @file The definition of the class representing a link generation template.
* @author Bart Busschots <opensource@bartificer.ie>
*/
/**
* This module provides as class for representing a template used for generating links.
* @module LinkTemplate
* @requires module:urijs
*/
/**
* A class representing the a template that can be used to render links.
*/
export class LinkTemplate{
/**
* @param {string} templateString - A Moustache template string.
* @param {Array} [filters=[]] - An optional array of filter functions.
* Each element in the array should itself be an array where the first
* element is a string specifying which fields the filter should be applied
* to (one of `'all'`, `'url'`, `'text'`, or `'description'`), and the
* second the filter function itself which should be a function that takes
* a single string as an argument and returns a filtered version of that
* string.
*/
constructor(templateString, filters){
// TO DO - add validation
/**
* The Moustache template string.
*
* @private
* @type {templateString}
*/
this._templateString = '';
this.templateString = templateString;
/**
* The filter functions to be applied to the various fields as a plain
* object of arrays of {@filterFunction} callbacks indexed by:
* * `all` - filters to be applied to all fields.
* * `url` - filters to be applied to just the URL.
* * `text` - filters to be applied just the link text.
* * `description` - filters to be applied just the link description.
*
* @private
* @type {Object.<string, filterFunction>}
*/
this._filters = {
all: [],
url: [],
text: [],
description: []
};
if(Array.isArray(filters)){
for(let f of filters){
if(Array.isArray(f)){
this.addFilter(...f);
}
}
}
}
/**
* Get the template string.
*
* @returns {string}
*/
get templateString(){
return this._templateString;
}
/**
* Set the template string. Should be in Mustache format. All values passed
* will be coerced to strings.
*
* @param {string} templateString
*/
set templateString(templateString){
this._templateString = String(templateString);
}
/**
* Add a filter to be applied to one or all fields.
*
* If an invalid args are passed, the function does not save the filter or
* throw an error, but it does log a warning.
*
* @param {string} fieldName - One of `'all'`, `'url'`, `'text'`, or
* `'description'`.
* @param {function} filterFn - the filter function.
* @returns {LinkTemplate} Returns a reference to self to facilitate function chaining.
*/
addFilter(fieldName, filterFn){
// make sure that args are at least plausibly valid
if(typeof fieldName !== 'string' || typeof filterFn !== 'function'){
console.warn('silently ignoring request to add filter due to invalid args');
return this;
}
// make sure the field name is valid
if(!this._filters[fieldName]){
console.warn(`silently ignoring request to add filter for unknown field (${fieldName})`);
return this;
}
// add the filter
this._filters[fieldName].push(filterFn);
// return a reference to self
return this;
}
/**
* A function get the filter functions that should be applied to any given
* field.
*
* @param {string} fieldName - one of `'url'`, `'text'`, or
* `'description'`.
* @returns {function[]} returns an array of callbacks, which may be
* empty. An empty array is returned if an invalid field name is passed.
*/
filtersFor(fieldName){
fieldName = String(fieldName);
let ans = [];
if(this._filters[fieldName]){
if(fieldName !== 'all'){
for(let f of this._filters.all){
ans.push(f);
}
}
for(let f of this._filters[fieldName]){
ans.push(f);
}
}
return ans;
}
};