coveo-search-ui
Version:
Coveo JavaScript Search Framework
250 lines (211 loc) • 8.04 kB
text/typescript
import { IQueryResults } from '../rest/QueryResults';
import { IQueryResult } from '../rest/QueryResult';
import { IQuery } from '../rest/Query';
import { Assert } from '../misc/Assert';
import { Utils } from '../utils/Utils';
import * as _ from 'underscore';
declare let crypto: Crypto;
export class QueryUtils {
static createGuid(): string {
let guid: string;
let success: boolean = false;
if (typeof crypto != 'undefined' && typeof crypto.getRandomValues != 'undefined') {
try {
guid = QueryUtils.generateWithCrypto();
success = true;
} catch (e) {
success = false;
}
}
if (!success) {
guid = QueryUtils.generateWithRandom();
}
return guid;
}
// This method is a fallback as it's generate a lot of collisions in Chrome.
static generateWithRandom(): string {
// http://stackoverflow.com/a/2117523
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = (Math.random() * 16) | 0,
v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
static generateWithCrypto(): string {
let buf = new Uint16Array(8);
crypto.getRandomValues(buf);
let S4 = function (num) {
let ret = num.toString(16);
while (ret.length < 4) {
ret = '0' + ret;
}
return ret;
};
const prefix = function (str: string, version: number) {
return version + str.slice(1);
};
return (
S4(buf[0]) +
S4(buf[1]) +
'-' +
S4(buf[2]) +
'-' +
prefix(S4(buf[3]), 4) +
'-' +
S4(buf[4]) +
'-' +
S4(buf[5]) +
S4(buf[6]) +
S4(buf[7])
);
}
static setStateObjectOnQueryResults(state: any, results: IQueryResults) {
QueryUtils.setPropertyOnResults(results, 'state', state);
}
static setStateObjectOnQueryResult(state: any, result: IQueryResult) {
QueryUtils.setPropertyOnResult(result, 'state', state);
}
static setSearchInterfaceObjectOnQueryResult(searchInterface, result: IQueryResult) {
QueryUtils.setPropertyOnResult(result, 'searchInterface', searchInterface);
}
static setIndexAndUidOnQueryResults(query: IQuery, results: IQueryResults, queryUid: string, pipeline: string, splitTestRun: string) {
Assert.exists(query);
Assert.exists(results);
let index = query.firstResult;
QueryUtils.setPropertyOnResults(results, 'queryUid', queryUid);
QueryUtils.setPropertyOnResults(results, 'pipeline', pipeline);
QueryUtils.setPropertyOnResults(results, 'splitTestRun', splitTestRun);
QueryUtils.setPropertyOnResults(results, 'index', index, () => ++index);
}
static setTermsToHighlightOnQueryResults(query: IQuery, results: IQueryResults) {
QueryUtils.setPropertyOnResults(results, 'termsToHighlight', results.termsToHighlight);
QueryUtils.setPropertyOnResults(results, 'phrasesToHighlight', results.phrasesToHighlight);
}
static splitFlags(flags: string, delimiter: string = ';') {
Assert.exists(flags);
return flags.split(delimiter);
}
static isAttachment(result: IQueryResult) {
return _.contains(QueryUtils.splitFlags(result.flags), 'IsAttachment');
}
static containsAttachment(result: IQueryResult) {
return _.contains(QueryUtils.splitFlags(result.flags), 'ContainsAttachment');
}
static hasHTMLVersion(result: IQueryResult) {
return _.contains(QueryUtils.splitFlags(result.flags), 'HasHtmlVersion');
}
static hasThumbnail(result: IQueryResult) {
return _.contains(QueryUtils.splitFlags(result.flags), 'HasThumbnail');
}
static hasExcerpt(result: IQueryResult) {
return result.excerpt != undefined && result.excerpt != '';
}
static getAuthor(result: IQueryResult): string {
return result.raw['author'];
}
static getUriHash(result: IQueryResult): string {
return result.raw['urihash'];
}
static getObjectType(result: IQueryResult): string {
return result.raw['objecttype'];
}
static getCollection(result: IQueryResult): string {
return result.raw['collection'] || 'default';
}
static getSource(result: IQueryResult): string {
return result.raw['source'];
}
static getLanguage(result: IQueryResult): string[] {
return result.raw['language'];
}
static getPermanentId(result: IQueryResult): { fieldValue: string; fieldUsed: string } {
let fieldValue;
let fieldUsed;
let permanentId = Utils.getFieldValue(result, 'permanentid');
if (permanentId) {
fieldUsed = 'permanentid';
fieldValue = permanentId;
} else {
fieldUsed = 'urihash';
fieldValue = Utils.getFieldValue(result, 'urihash');
}
return {
fieldValue: fieldValue,
fieldUsed: fieldUsed
};
}
static quoteAndEscapeIfNeeded(str: string, forceEscape = false): string {
Assert.isString(str);
return !forceEscape &&
(QueryUtils.isAtomicString(str) || QueryUtils.isRangeString(str) || QueryUtils.isRangeWithoutOuterBoundsString(str))
? str
: QueryUtils.quoteAndEscape(str);
}
static quoteAndEscape(str: string): string {
Assert.isString(str);
return `"${QueryUtils.escapeString(str)}"`;
}
static escapeString(str: string): string {
Assert.isString(str);
return str.replace(/"/g, ' ');
}
static isAtomicString(str: string): boolean {
Assert.isString(str);
return /^\d+(\.\d+)?$|^[\d\w]+$/.test(str);
}
static isRangeString(str: string): boolean {
Assert.isString(str);
return /^\d+(\.\d+)?\.\.\d+(\.\d+)?$|^\d{4}\/\d{2}\/\d{2}@\d{2}:\d{2}:\d{2}\.\.\d{4}\/\d{2}\/\d{2}@\d{2}:\d{2}:\d{2}$/.test(str);
}
static isRangeWithoutOuterBoundsString(str: string): boolean {
Assert.isString(str);
return /^\d+(\.\d+)?$|^\d{4}\/\d{2}\/\d{2}@\d{2}:\d{2}:\d{2}$/.test(str);
}
static buildFieldExpression(field: string, operator: string, values: string[], forceEscape = false) {
Assert.isNonEmptyString(field);
Assert.stringStartsWith(field, '@');
Assert.isNonEmptyString(operator);
Assert.isLargerOrEqualsThan(1, values.length);
if (values.length == 1) {
return field + operator + QueryUtils.quoteAndEscapeIfNeeded(values[0], forceEscape);
} else {
return field + operator + '(' + _.map(values, str => QueryUtils.quoteAndEscapeIfNeeded(str, forceEscape)).join(',') + ')';
}
}
static buildFieldNotEqualExpression(field: string, values: string[], forceEscape = false) {
Assert.isNonEmptyString(field);
Assert.stringStartsWith(field, '@');
Assert.isLargerOrEqualsThan(1, values.length);
let filter: string;
if (values.length == 1) {
filter = field + '==' + QueryUtils.quoteAndEscapeIfNeeded(values[0], forceEscape);
} else {
filter = field + '==' + '(' + _.map(values, str => QueryUtils.quoteAndEscapeIfNeeded(str, forceEscape)).join(',') + ')';
}
return '(NOT ' + filter + ')';
}
public static setPropertyOnResults(results: IQueryResults, property: string, value: any, afterOneLoop?: () => any) {
_.each(results.results, (result: IQueryResult) => {
QueryUtils.setPropertyOnResult(result, property, value);
value = afterOneLoop ? afterOneLoop() : value;
});
}
public static setPropertyOnResult(result: IQueryResult, property: string, value: any) {
result[property] = value;
_.each(result.childResults, (child: IQueryResult) => {
child[property] = value;
});
if (!Utils.isNullOrUndefined(result.parentResult)) {
result.parentResult[property] = value;
}
}
public static isStratusAgnosticField(fieldToVerify: string, fieldToMatch: string): boolean {
let checkForSystem = /^(@?)(sys)?(.*)/i;
let matchFieldToVerify = checkForSystem.exec(fieldToVerify);
let matchFieldToMatch = checkForSystem.exec(fieldToMatch);
if (matchFieldToVerify && matchFieldToMatch) {
return (matchFieldToVerify[1] + matchFieldToVerify[3]).toLowerCase() == (matchFieldToMatch[1] + matchFieldToMatch[3]).toLowerCase();
}
return false;
}
}