UNPKG

monaca-lib

Version:

Monaca cloud API bindings for JavaScript

211 lines (200 loc) 6.96 kB
/* * Copyright (C) 2013 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @constructor * @param {string} query */ WebInspector.FilePathScoreFunction = function(query) { this._query = query; this._queryUpperCase = query.toUpperCase(); this._score = null; this._sequence = null; this._dataUpperCase = ""; this._fileNameIndex = 0; } /** * @param {string} query * @return {!RegExp} */ WebInspector.FilePathScoreFunction.filterRegex = function(query) { const toEscape = String.regexSpecialCharacters(); var regexString = ""; for (var i = 0; i < query.length; ++i) { var c = query.charAt(i); if (toEscape.indexOf(c) !== -1) c = "\\" + c; if (i) regexString += "[^" + c + "]*"; regexString += c; } return new RegExp(regexString, "i"); } WebInspector.FilePathScoreFunction.prototype = { /** * @param {string} data * @param {?Array.<!Number>} matchIndexes * @return {number} */ score: function(data, matchIndexes) { if (!data || !this._query) return 0; var n = this._query.length; var m = data.length; if (!this._score || this._score.length < n * m) { this._score = new Int32Array(n * m * 2); this._sequence = new Int32Array(n * m * 2); } var score = this._score; var sequence = /** @type {!Int32Array} */ (this._sequence); this._dataUpperCase = data.toUpperCase(); this._fileNameIndex = data.lastIndexOf("/"); for (var i = 0; i < n; ++i) { for (var j = 0; j < m; ++j) { var skipCharScore = j === 0 ? 0 : score[i * m + j - 1]; var prevCharScore = i === 0 || j === 0 ? 0 : score[(i - 1) * m + j - 1]; var consecutiveMatch = i === 0 || j === 0 ? 0 : sequence[(i - 1) * m + j - 1]; var pickCharScore = this._match(this._query, data, i, j, consecutiveMatch); if (pickCharScore && prevCharScore + pickCharScore >= skipCharScore) { sequence[i * m + j] = consecutiveMatch + 1; score[i * m + j] = (prevCharScore + pickCharScore); } else { sequence[i * m + j] = 0; score[i * m + j] = skipCharScore; } } } if (matchIndexes) this._restoreMatchIndexes(sequence, n, m, matchIndexes); return score[n * m - 1]; }, /** * @param {string} data * @param {number} j * @return {boolean} */ _testWordStart: function(data, j) { var prevChar = data.charAt(j - 1); return j === 0 || prevChar === "_" || prevChar === "-" || prevChar === "/" || (data[j - 1] !== this._dataUpperCase[j - 1] && data[j] === this._dataUpperCase[j]); }, /** * @param {!Int32Array} sequence * @param {number} n * @param {number} m * @param {!Array.<!Number>} out */ _restoreMatchIndexes: function(sequence, n, m, out) { var i = n - 1, j = m - 1; while (i >= 0 && j >= 0) { switch (sequence[i * m + j]) { case 0: --j; break; default: out.push(j); --i; --j; break; } } out.reverse(); }, /** * @param {string} query * @param {string} data * @param {number} i * @param {number} j * @return {number} */ _singleCharScore: function(query, data, i, j) { var isWordStart = this._testWordStart(data, j); var isFileName = j > this._fileNameIndex; var isPathTokenStart = j === 0 || data[j - 1] === "/"; var isCapsMatch = query[i] === data[j] && query[i] == this._queryUpperCase[i]; var score = 10; if (isPathTokenStart) score += 4; if (isWordStart) score += 2; if (isCapsMatch) score += 6; if (isFileName) score += 4; // promote the case of making the whole match in the filename if (j === this._fileNameIndex + 1 && i === 0) score += 5; if (isFileName && isWordStart) score += 3; return score; }, /** * @param {string} query * @param {string} data * @param {number} i * @param {number} j * @param {number} sequenceLength * @return {number} */ _sequenceCharScore: function(query, data, i, j, sequenceLength) { var isFileName = j > this._fileNameIndex; var isPathTokenStart = j === 0 || data[j - 1] === "/"; var score = 10; if (isFileName) score += 4; if (isPathTokenStart) score += 5; score += sequenceLength * 4; return score; }, /** * @param {string} query * @param {string} data * @param {number} i * @param {number} j * @param {number} consecutiveMatch * @return {number} */ _match: function(query, data, i, j, consecutiveMatch) { if (this._queryUpperCase[i] !== this._dataUpperCase[j]) return 0; if (!consecutiveMatch) return this._singleCharScore(query, data, i, j); else return this._sequenceCharScore(query, data, i, j - consecutiveMatch, consecutiveMatch); } }