mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-11 06:04:55 +08:00
Move and rename files. NOAUTOREVERT=true NOPRESUBMIT=true NOTREECHECKS=true Bug: 768828 TBR=darin@chromium.org NOTRY=true Change-Id: I66d3b155808bc5bdbf237b80208e1e552bcf7f28 Reviewed-on: https://chromium-review.googlesource.com/1001153 Reviewed-by: Blink Reformat <blink-reformat@chromium.org> Commit-Queue: Blink Reformat <blink-reformat@chromium.org> Cr-Original-Commit-Position: refs/heads/master@{#549061} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 0aee4434a4dba42a42abaea9bfbc0cd196a63bc1
595 lines
18 KiB
JavaScript
595 lines
18 KiB
JavaScript
/*
|
|
* Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
|
|
* Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
|
|
* Copyright (C) 2009 Joseph Pecoraro
|
|
* Copyright (C) 2011 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:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. 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.
|
|
* 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
|
|
*/
|
|
|
|
/**
|
|
* @unrestricted
|
|
*/
|
|
UI.SearchableView = class extends UI.VBox {
|
|
/**
|
|
* @param {!UI.Searchable} searchable
|
|
* @param {string=} settingName
|
|
*/
|
|
constructor(searchable, settingName) {
|
|
super(true);
|
|
this.registerRequiredCSS('ui/searchableView.css');
|
|
this.element[UI.SearchableView._symbol] = this;
|
|
|
|
this._searchProvider = searchable;
|
|
this._setting = settingName ? Common.settings.createSetting(settingName, {}) : null;
|
|
this._replaceable = false;
|
|
|
|
this.contentElement.createChild('content');
|
|
this._footerElementContainer = this.contentElement.createChild('div', 'search-bar hidden');
|
|
this._footerElementContainer.style.order = 100;
|
|
this._footerElement = this._footerElementContainer.createChild('div', 'toolbar-search');
|
|
|
|
const replaceToggleToolbar = new UI.Toolbar('replace-toggle-toolbar', this._footerElement);
|
|
this._replaceToggleButton = new UI.ToolbarToggle(Common.UIString('Replace'), 'mediumicon-replace');
|
|
this._replaceToggleButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleReplace, this);
|
|
replaceToggleToolbar.appendToolbarItem(this._replaceToggleButton);
|
|
|
|
const searchInputElements = this._footerElement.createChild('div', 'toolbar-search-inputs');
|
|
const searchControlElement = searchInputElements.createChild('div', 'toolbar-search-control');
|
|
|
|
this._searchInputElement = UI.HistoryInput.create();
|
|
this._searchInputElement.classList.add('search-replace');
|
|
this._searchInputElement.id = 'search-input-field';
|
|
this._searchInputElement.placeholder = Common.UIString('Find');
|
|
searchControlElement.appendChild(this._searchInputElement);
|
|
|
|
this._matchesElement = searchControlElement.createChild('label', 'search-results-matches');
|
|
this._matchesElement.setAttribute('for', 'search-input-field');
|
|
|
|
const searchNavigationElement = searchControlElement.createChild('div', 'toolbar-search-navigation-controls');
|
|
|
|
this._searchNavigationPrevElement =
|
|
searchNavigationElement.createChild('div', 'toolbar-search-navigation toolbar-search-navigation-prev');
|
|
this._searchNavigationPrevElement.addEventListener('click', this._onPrevButtonSearch.bind(this), false);
|
|
this._searchNavigationPrevElement.title = Common.UIString('Search previous');
|
|
|
|
this._searchNavigationNextElement =
|
|
searchNavigationElement.createChild('div', 'toolbar-search-navigation toolbar-search-navigation-next');
|
|
this._searchNavigationNextElement.addEventListener('click', this._onNextButtonSearch.bind(this), false);
|
|
this._searchNavigationNextElement.title = Common.UIString('Search next');
|
|
|
|
this._searchInputElement.addEventListener('keydown', this._onSearchKeyDown.bind(this), true);
|
|
this._searchInputElement.addEventListener('input', this._onInput.bind(this), false);
|
|
|
|
this._replaceInputElement =
|
|
searchInputElements.createChild('input', 'search-replace toolbar-replace-control hidden');
|
|
this._replaceInputElement.addEventListener('keydown', this._onReplaceKeyDown.bind(this), true);
|
|
this._replaceInputElement.placeholder = Common.UIString('Replace');
|
|
|
|
this._buttonsContainer = this._footerElement.createChild('div', 'toolbar-search-buttons');
|
|
const firstRowButtons = this._buttonsContainer.createChild('div', 'first-row-buttons');
|
|
|
|
const toolbar = new UI.Toolbar('toolbar-search-options', firstRowButtons);
|
|
|
|
if (this._searchProvider.supportsCaseSensitiveSearch()) {
|
|
this._caseSensitiveButton = new UI.ToolbarToggle(Common.UIString('Match Case'));
|
|
this._caseSensitiveButton.setText('Aa');
|
|
this._caseSensitiveButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleCaseSensitiveSearch, this);
|
|
toolbar.appendToolbarItem(this._caseSensitiveButton);
|
|
}
|
|
|
|
if (this._searchProvider.supportsRegexSearch()) {
|
|
this._regexButton = new UI.ToolbarToggle(Common.UIString('Use Regular Expression'));
|
|
this._regexButton.setText('.*');
|
|
this._regexButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleRegexSearch, this);
|
|
toolbar.appendToolbarItem(this._regexButton);
|
|
}
|
|
|
|
const cancelButtonElement =
|
|
UI.createTextButton(Common.UIString('Cancel'), this.closeSearch.bind(this), 'search-action-button');
|
|
firstRowButtons.appendChild(cancelButtonElement);
|
|
|
|
this._secondRowButtons = this._buttonsContainer.createChild('div', 'second-row-buttons hidden');
|
|
|
|
this._replaceButtonElement =
|
|
UI.createTextButton(Common.UIString('Replace'), this._replace.bind(this), 'search-action-button');
|
|
this._replaceButtonElement.disabled = true;
|
|
this._secondRowButtons.appendChild(this._replaceButtonElement);
|
|
|
|
this._replaceAllButtonElement =
|
|
UI.createTextButton(Common.UIString('Replace all'), this._replaceAll.bind(this), 'search-action-button');
|
|
this._secondRowButtons.appendChild(this._replaceAllButtonElement);
|
|
this._replaceAllButtonElement.disabled = true;
|
|
|
|
this._minimalSearchQuerySize = 3;
|
|
this._loadSetting();
|
|
}
|
|
|
|
/**
|
|
* @param {?Element} element
|
|
* @return {?UI.SearchableView}
|
|
*/
|
|
static fromElement(element) {
|
|
let view = null;
|
|
while (element && !view) {
|
|
view = element[UI.SearchableView._symbol];
|
|
element = element.parentElementOrShadowHost();
|
|
}
|
|
return view;
|
|
}
|
|
|
|
_toggleCaseSensitiveSearch() {
|
|
this._caseSensitiveButton.setToggled(!this._caseSensitiveButton.toggled());
|
|
this._saveSetting();
|
|
this._performSearch(false, true);
|
|
}
|
|
|
|
_toggleRegexSearch() {
|
|
this._regexButton.setToggled(!this._regexButton.toggled());
|
|
this._saveSetting();
|
|
this._performSearch(false, true);
|
|
}
|
|
|
|
_toggleReplace() {
|
|
this._replaceToggleButton.setToggled(!this._replaceToggleButton.toggled());
|
|
this._updateSecondRowVisibility();
|
|
}
|
|
|
|
_saveSetting() {
|
|
if (!this._setting)
|
|
return;
|
|
const settingValue = this._setting.get() || {};
|
|
settingValue.caseSensitive = this._caseSensitiveButton.toggled();
|
|
settingValue.isRegex = this._regexButton.toggled();
|
|
this._setting.set(settingValue);
|
|
}
|
|
|
|
_loadSetting() {
|
|
const settingValue = this._setting ? (this._setting.get() || {}) : {};
|
|
if (this._searchProvider.supportsCaseSensitiveSearch())
|
|
this._caseSensitiveButton.setToggled(!!settingValue.caseSensitive);
|
|
if (this._searchProvider.supportsRegexSearch())
|
|
this._regexButton.setToggled(!!settingValue.isRegex);
|
|
}
|
|
|
|
/**
|
|
* @param {number} minimalSearchQuerySize
|
|
*/
|
|
setMinimalSearchQuerySize(minimalSearchQuerySize) {
|
|
this._minimalSearchQuerySize = minimalSearchQuerySize;
|
|
}
|
|
|
|
/**
|
|
* @param {string} placeholder
|
|
*/
|
|
setPlaceholder(placeholder) {
|
|
this._searchInputElement.placeholder = placeholder;
|
|
}
|
|
|
|
/**
|
|
* @param {boolean} replaceable
|
|
*/
|
|
setReplaceable(replaceable) {
|
|
this._replaceable = replaceable;
|
|
}
|
|
|
|
/**
|
|
* @param {number} matches
|
|
*/
|
|
updateSearchMatchesCount(matches) {
|
|
if (this._searchProvider.currentSearchMatches === matches)
|
|
return;
|
|
this._searchProvider.currentSearchMatches = matches;
|
|
this._updateSearchMatchesCountAndCurrentMatchIndex(this._searchProvider.currentQuery ? matches : 0, -1);
|
|
}
|
|
|
|
/**
|
|
* @param {number} currentMatchIndex
|
|
*/
|
|
updateCurrentMatchIndex(currentMatchIndex) {
|
|
this._updateSearchMatchesCountAndCurrentMatchIndex(this._searchProvider.currentSearchMatches, currentMatchIndex);
|
|
}
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
isSearchVisible() {
|
|
return this._searchIsVisible;
|
|
}
|
|
|
|
closeSearch() {
|
|
this.cancelSearch();
|
|
if (this._footerElementContainer.hasFocus())
|
|
this.focus();
|
|
}
|
|
|
|
_toggleSearchBar(toggled) {
|
|
this._footerElementContainer.classList.toggle('hidden', !toggled);
|
|
this.doResize();
|
|
}
|
|
|
|
cancelSearch() {
|
|
if (!this._searchIsVisible)
|
|
return;
|
|
this.resetSearch();
|
|
delete this._searchIsVisible;
|
|
this._toggleSearchBar(false);
|
|
}
|
|
|
|
resetSearch() {
|
|
this._clearSearch();
|
|
this._updateReplaceVisibility();
|
|
this._matchesElement.textContent = '';
|
|
}
|
|
|
|
refreshSearch() {
|
|
if (!this._searchIsVisible)
|
|
return;
|
|
this.resetSearch();
|
|
this._performSearch(false, false);
|
|
}
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
handleFindNextShortcut() {
|
|
if (!this._searchIsVisible)
|
|
return false;
|
|
this._searchProvider.jumpToNextSearchResult();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
handleFindPreviousShortcut() {
|
|
if (!this._searchIsVisible)
|
|
return false;
|
|
this._searchProvider.jumpToPreviousSearchResult();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
handleFindShortcut() {
|
|
this.showSearchField();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
handleCancelSearchShortcut() {
|
|
if (!this._searchIsVisible)
|
|
return false;
|
|
this.closeSearch();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param {boolean} enabled
|
|
*/
|
|
_updateSearchNavigationButtonState(enabled) {
|
|
this._replaceButtonElement.disabled = !enabled;
|
|
this._replaceAllButtonElement.disabled = !enabled;
|
|
this._searchNavigationPrevElement.classList.toggle('enabled', enabled);
|
|
this._searchNavigationNextElement.classList.toggle('enabled', enabled);
|
|
}
|
|
|
|
/**
|
|
* @param {number} matches
|
|
* @param {number} currentMatchIndex
|
|
*/
|
|
_updateSearchMatchesCountAndCurrentMatchIndex(matches, currentMatchIndex) {
|
|
if (!this._currentQuery)
|
|
this._matchesElement.textContent = '';
|
|
else if (matches === 0 || currentMatchIndex >= 0)
|
|
this._matchesElement.textContent = Common.UIString('%d of %d', currentMatchIndex + 1, matches);
|
|
else if (matches === 1)
|
|
this._matchesElement.textContent = Common.UIString('1 match');
|
|
else
|
|
this._matchesElement.textContent = Common.UIString('%d matches', matches);
|
|
this._updateSearchNavigationButtonState(matches > 0);
|
|
}
|
|
|
|
showSearchField() {
|
|
if (this._searchIsVisible)
|
|
this.cancelSearch();
|
|
|
|
let queryCandidate;
|
|
if (!this._searchInputElement.hasFocus()) {
|
|
const selection = UI.inspectorView.element.window().getSelection();
|
|
if (selection.rangeCount)
|
|
queryCandidate = selection.toString().replace(/\r?\n.*/, '');
|
|
}
|
|
|
|
this._toggleSearchBar(true);
|
|
this._updateReplaceVisibility();
|
|
if (queryCandidate)
|
|
this._searchInputElement.value = queryCandidate;
|
|
this._performSearch(false, false);
|
|
this._searchInputElement.focus();
|
|
this._searchInputElement.select();
|
|
this._searchIsVisible = true;
|
|
}
|
|
|
|
_updateReplaceVisibility() {
|
|
this._replaceToggleButton.setVisible(this._replaceable);
|
|
if (!this._replaceable) {
|
|
this._replaceToggleButton.setToggled(false);
|
|
this._updateSecondRowVisibility();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {!Event} event
|
|
*/
|
|
_onSearchKeyDown(event) {
|
|
if (isEscKey(event)) {
|
|
this.closeSearch();
|
|
event.consume(true);
|
|
return;
|
|
}
|
|
if (!isEnterKey(event))
|
|
return;
|
|
|
|
if (!this._currentQuery)
|
|
this._performSearch(true, true, event.shiftKey);
|
|
else
|
|
this._jumpToNextSearchResult(event.shiftKey);
|
|
}
|
|
|
|
/**
|
|
* @param {!Event} event
|
|
*/
|
|
_onReplaceKeyDown(event) {
|
|
if (isEnterKey(event))
|
|
this._replace();
|
|
}
|
|
|
|
/**
|
|
* @param {boolean=} isBackwardSearch
|
|
*/
|
|
_jumpToNextSearchResult(isBackwardSearch) {
|
|
if (!this._currentQuery || !this._searchNavigationPrevElement.classList.contains('enabled'))
|
|
return;
|
|
|
|
if (isBackwardSearch)
|
|
this._searchProvider.jumpToPreviousSearchResult();
|
|
else
|
|
this._searchProvider.jumpToNextSearchResult();
|
|
}
|
|
|
|
_onNextButtonSearch(event) {
|
|
if (!this._searchNavigationNextElement.classList.contains('enabled'))
|
|
return;
|
|
this._jumpToNextSearchResult();
|
|
this._searchInputElement.focus();
|
|
}
|
|
|
|
_onPrevButtonSearch(event) {
|
|
if (!this._searchNavigationPrevElement.classList.contains('enabled'))
|
|
return;
|
|
this._jumpToNextSearchResult(true);
|
|
this._searchInputElement.focus();
|
|
}
|
|
|
|
_onFindClick(event) {
|
|
if (!this._currentQuery)
|
|
this._performSearch(true, true);
|
|
else
|
|
this._jumpToNextSearchResult();
|
|
this._searchInputElement.focus();
|
|
}
|
|
|
|
_onPreviousClick(event) {
|
|
if (!this._currentQuery)
|
|
this._performSearch(true, true, true);
|
|
else
|
|
this._jumpToNextSearchResult(true);
|
|
this._searchInputElement.focus();
|
|
}
|
|
|
|
_clearSearch() {
|
|
delete this._currentQuery;
|
|
if (!!this._searchProvider.currentQuery) {
|
|
delete this._searchProvider.currentQuery;
|
|
this._searchProvider.searchCanceled();
|
|
}
|
|
this._updateSearchMatchesCountAndCurrentMatchIndex(0, -1);
|
|
}
|
|
|
|
/**
|
|
* @param {boolean} forceSearch
|
|
* @param {boolean} shouldJump
|
|
* @param {boolean=} jumpBackwards
|
|
*/
|
|
_performSearch(forceSearch, shouldJump, jumpBackwards) {
|
|
const query = this._searchInputElement.value;
|
|
if (!query || (!forceSearch && query.length < this._minimalSearchQuerySize && !this._currentQuery)) {
|
|
this._clearSearch();
|
|
return;
|
|
}
|
|
|
|
this._currentQuery = query;
|
|
this._searchProvider.currentQuery = query;
|
|
|
|
const searchConfig = this._currentSearchConfig();
|
|
this._searchProvider.performSearch(searchConfig, shouldJump, jumpBackwards);
|
|
}
|
|
|
|
/**
|
|
* @return {!UI.SearchableView.SearchConfig}
|
|
*/
|
|
_currentSearchConfig() {
|
|
const query = this._searchInputElement.value;
|
|
const caseSensitive = this._caseSensitiveButton ? this._caseSensitiveButton.toggled() : false;
|
|
const isRegex = this._regexButton ? this._regexButton.toggled() : false;
|
|
return new UI.SearchableView.SearchConfig(query, caseSensitive, isRegex);
|
|
}
|
|
|
|
_updateSecondRowVisibility() {
|
|
const secondRowVisible = this._replaceToggleButton.toggled();
|
|
this._footerElementContainer.classList.toggle('replaceable', secondRowVisible);
|
|
this._secondRowButtons.classList.toggle('hidden', !secondRowVisible);
|
|
this._replaceInputElement.classList.toggle('hidden', !secondRowVisible);
|
|
|
|
if (secondRowVisible)
|
|
this._replaceInputElement.focus();
|
|
else
|
|
this._searchInputElement.focus();
|
|
this.doResize();
|
|
}
|
|
|
|
_replace() {
|
|
const searchConfig = this._currentSearchConfig();
|
|
/** @type {!UI.Replaceable} */ (this._searchProvider)
|
|
.replaceSelectionWith(searchConfig, this._replaceInputElement.value);
|
|
delete this._currentQuery;
|
|
this._performSearch(true, true);
|
|
}
|
|
|
|
_replaceAll() {
|
|
const searchConfig = this._currentSearchConfig();
|
|
/** @type {!UI.Replaceable} */ (this._searchProvider).replaceAllWith(searchConfig, this._replaceInputElement.value);
|
|
}
|
|
|
|
/**
|
|
* @param {!Event} event
|
|
*/
|
|
_onInput(event) {
|
|
if (this._valueChangedTimeoutId)
|
|
clearTimeout(this._valueChangedTimeoutId);
|
|
const timeout = this._searchInputElement.value.length < 3 ? 200 : 0;
|
|
this._valueChangedTimeoutId = setTimeout(this._onValueChanged.bind(this), timeout);
|
|
}
|
|
|
|
_onValueChanged() {
|
|
if (!this._searchIsVisible)
|
|
return;
|
|
delete this._valueChangedTimeoutId;
|
|
this._performSearch(false, true);
|
|
}
|
|
};
|
|
|
|
|
|
UI.SearchableView._symbol = Symbol('searchableView');
|
|
|
|
|
|
/**
|
|
* @interface
|
|
*/
|
|
UI.Searchable = function() {};
|
|
|
|
UI.Searchable.prototype = {
|
|
searchCanceled() {},
|
|
|
|
/**
|
|
* @param {!UI.SearchableView.SearchConfig} searchConfig
|
|
* @param {boolean} shouldJump
|
|
* @param {boolean=} jumpBackwards
|
|
*/
|
|
performSearch(searchConfig, shouldJump, jumpBackwards) {},
|
|
|
|
jumpToNextSearchResult() {},
|
|
|
|
jumpToPreviousSearchResult() {},
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
supportsCaseSensitiveSearch() {},
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
supportsRegexSearch() {}
|
|
};
|
|
|
|
/**
|
|
* @interface
|
|
*/
|
|
UI.Replaceable = function() {};
|
|
|
|
UI.Replaceable.prototype = {
|
|
/**
|
|
* @param {!UI.SearchableView.SearchConfig} searchConfig
|
|
* @param {string} replacement
|
|
*/
|
|
replaceSelectionWith(searchConfig, replacement) {},
|
|
|
|
/**
|
|
* @param {!UI.SearchableView.SearchConfig} searchConfig
|
|
* @param {string} replacement
|
|
*/
|
|
replaceAllWith(searchConfig, replacement) {}
|
|
};
|
|
|
|
/**
|
|
* @unrestricted
|
|
*/
|
|
UI.SearchableView.SearchConfig = class {
|
|
/**
|
|
* @param {string} query
|
|
* @param {boolean} caseSensitive
|
|
* @param {boolean} isRegex
|
|
*/
|
|
constructor(query, caseSensitive, isRegex) {
|
|
this.query = query;
|
|
this.caseSensitive = caseSensitive;
|
|
this.isRegex = isRegex;
|
|
}
|
|
|
|
/**
|
|
* @param {boolean=} global
|
|
* @return {!RegExp}
|
|
*/
|
|
toSearchRegex(global) {
|
|
let modifiers = this.caseSensitive ? '' : 'i';
|
|
if (global)
|
|
modifiers += 'g';
|
|
const query = this.isRegex ? '/' + this.query + '/' : this.query;
|
|
|
|
let regex;
|
|
|
|
// First try creating regex if user knows the / / hint.
|
|
try {
|
|
if (/^\/.+\/$/.test(query)) {
|
|
regex = new RegExp(query.substring(1, query.length - 1), modifiers);
|
|
regex.__fromRegExpQuery = true;
|
|
}
|
|
} catch (e) {
|
|
// Silent catch.
|
|
}
|
|
|
|
// Otherwise just do a plain text search.
|
|
if (!regex)
|
|
regex = createPlainTextSearchRegex(query, modifiers);
|
|
|
|
return regex;
|
|
}
|
|
};
|