mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
server-ts: Port services/search/services/search
This commit is contained in:
parent
15169289f0
commit
2fbd2e3c29
@ -1,4 +1,4 @@
|
|||||||
const searchService = require('../../src/services/search/services/search.js');
|
const searchService = require('../../src/services/search/services/search');
|
||||||
const BNote = require('../../src/becca/entities/bnote.js');
|
const BNote = require('../../src/becca/entities/bnote.js');
|
||||||
const BBranch = require('../../src/becca/entities/bbranch.js');
|
const BBranch = require('../../src/becca/entities/bbranch.js');
|
||||||
const SearchContext = require('../../src/services/search/search_context');
|
const SearchContext = require('../../src/services/search/search_context');
|
||||||
|
@ -78,13 +78,13 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
|||||||
|
|
||||||
// following attributes are filled during searching in the database
|
// following attributes are filled during searching in the database
|
||||||
/** size of the content in bytes */
|
/** size of the content in bytes */
|
||||||
private contentSize!: number | null;
|
contentSize!: number | null;
|
||||||
/** size of the note content, attachment contents in bytes */
|
/** size of the note content, attachment contents in bytes */
|
||||||
private contentAndAttachmentsSize!: number | null;
|
contentAndAttachmentsSize!: number | null;
|
||||||
/** size of the note content, attachment contents and revision contents in bytes */
|
/** size of the note content, attachment contents and revision contents in bytes */
|
||||||
private contentAndAttachmentsAndRevisionsSize!: number | null;
|
contentAndAttachmentsAndRevisionsSize!: number | null;
|
||||||
/** number of note revisions for this note */
|
/** number of note revisions for this note */
|
||||||
private revisionCount!: number | null;
|
revisionCount!: number | null;
|
||||||
|
|
||||||
constructor(row?: Partial<NoteRow>) {
|
constructor(row?: Partial<NoteRow>) {
|
||||||
super();
|
super();
|
||||||
|
@ -5,7 +5,7 @@ const mappers = require('./mappers.js');
|
|||||||
const noteService = require('../services/notes');
|
const noteService = require('../services/notes');
|
||||||
const TaskContext = require('../services/task_context');
|
const TaskContext = require('../services/task_context');
|
||||||
const v = require('./validators.js');
|
const v = require('./validators.js');
|
||||||
const searchService = require('../services/search/services/search.js');
|
const searchService = require('../services/search/services/search');
|
||||||
const SearchContext = require('../services/search/search_context');
|
const SearchContext = require('../services/search/search_context');
|
||||||
const zipExportService = require('../services/export/zip.js');
|
const zipExportService = require('../services/export/zip.js');
|
||||||
const zipImportService = require('../services/import/zip.js');
|
const zipImportService = require('../services/import/zip.js');
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const beccaService = require('../../becca/becca_service');
|
const beccaService = require('../../becca/becca_service');
|
||||||
const searchService = require('../../services/search/services/search.js');
|
const searchService = require('../../services/search/services/search');
|
||||||
const log = require('../../services/log');
|
const log = require('../../services/log');
|
||||||
const utils = require('../../services/utils');
|
const utils = require('../../services/utils');
|
||||||
const cls = require('../../services/cls');
|
const cls = require('../../services/cls');
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
const optionService = require('../../services/options');
|
const optionService = require('../../services/options');
|
||||||
const log = require('../../services/log');
|
const log = require('../../services/log');
|
||||||
const searchService = require('../../services/search/services/search.js');
|
const searchService = require('../../services/search/services/search');
|
||||||
const ValidationError = require('../../errors/validation_error');
|
const ValidationError = require('../../errors/validation_error');
|
||||||
|
|
||||||
// options allowed to be updated directly in the Options dialog
|
// options allowed to be updated directly in the Options dialog
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
const becca = require('../../becca/becca');
|
const becca = require('../../becca/becca');
|
||||||
const SearchContext = require('../../services/search/search_context');
|
const SearchContext = require('../../services/search/search_context');
|
||||||
const searchService = require('../../services/search/services/search.js');
|
const searchService = require('../../services/search/services/search');
|
||||||
const bulkActionService = require('../../services/bulk_actions.js');
|
const bulkActionService = require('../../services/bulk_actions.js');
|
||||||
const cls = require('../../services/cls');
|
const cls = require('../../services/cls');
|
||||||
const {formatAttrForSearch} = require('../../services/attribute_formatter');
|
const {formatAttrForSearch} = require('../../services/attribute_formatter');
|
||||||
|
@ -46,7 +46,7 @@ const attributesRoute = require('./api/attributes.js');
|
|||||||
const scriptRoute = require('./api/script.js');
|
const scriptRoute = require('./api/script.js');
|
||||||
const senderRoute = require('./api/sender.js');
|
const senderRoute = require('./api/sender.js');
|
||||||
const filesRoute = require('./api/files.js');
|
const filesRoute = require('./api/files.js');
|
||||||
const searchRoute = require('./api/search.js');
|
const searchRoute = require('./api/search');
|
||||||
const bulkActionRoute = require('./api/bulk_action.js');
|
const bulkActionRoute = require('./api/bulk_action.js');
|
||||||
const specialNotesRoute = require('./api/special_notes.js');
|
const specialNotesRoute = require('./api/special_notes.js');
|
||||||
const noteMapRoute = require('./api/note_map.js');
|
const noteMapRoute = require('./api/note_map.js');
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const searchService = require('./search/services/search.js');
|
const searchService = require('./search/services/search');
|
||||||
const sql = require('./sql');
|
const sql = require('./sql');
|
||||||
const becca = require('../becca/becca');
|
const becca = require('../becca/becca');
|
||||||
const BAttribute = require('../becca/entities/battribute');
|
const BAttribute = require('../becca/entities/battribute');
|
||||||
|
@ -11,7 +11,7 @@ const dayjs = require('dayjs');
|
|||||||
const xml2js = require('xml2js');
|
const xml2js = require('xml2js');
|
||||||
const cloningService = require('./cloning.js');
|
const cloningService = require('./cloning.js');
|
||||||
const appInfo = require('./app_info');
|
const appInfo = require('./app_info');
|
||||||
const searchService = require('./search/services/search.js');
|
const searchService = require('./search/services/search');
|
||||||
const SearchContext = require('./search/search_context');
|
const SearchContext = require('./search/search_context');
|
||||||
const becca = require('../becca/becca');
|
const becca = require('../becca/becca');
|
||||||
const ws = require('./ws');
|
const ws = require('./ws');
|
||||||
|
@ -5,7 +5,7 @@ const attributeService = require('./attributes.js');
|
|||||||
const dateUtils = require('./date_utils');
|
const dateUtils = require('./date_utils');
|
||||||
const sql = require('./sql');
|
const sql = require('./sql');
|
||||||
const protectedSessionService = require('./protected_session');
|
const protectedSessionService = require('./protected_session');
|
||||||
const searchService = require('../services/search/services/search.js');
|
const searchService = require('../services/search/services/search');
|
||||||
const SearchContext = require('../services/search/search_context');
|
const SearchContext = require('../services/search/search_context');
|
||||||
const hoistedNoteService = require('./hoisted_note');
|
const hoistedNoteService = require('./hoisted_note');
|
||||||
|
|
||||||
|
@ -1,20 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import hoistedNoteService = require('../hoisted_note');
|
import hoistedNoteService = require('../hoisted_note');
|
||||||
|
import { SearchParams } from './services/types';
|
||||||
interface SearchParams {
|
|
||||||
fastSearch?: boolean;
|
|
||||||
includeArchivedNotes?: boolean;
|
|
||||||
includeHiddenNotes?: boolean;
|
|
||||||
ignoreHoistedNote?: boolean;
|
|
||||||
ancestorNoteId?: string;
|
|
||||||
ancestorDepth?: string;
|
|
||||||
orderBy?: string;
|
|
||||||
orderDirection?: string;
|
|
||||||
limit?: number;
|
|
||||||
debug?: boolean;
|
|
||||||
fuzzyAttributeSearch?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SearchContext {
|
class SearchContext {
|
||||||
|
|
||||||
@ -26,9 +13,9 @@ class SearchContext {
|
|||||||
ancestorDepth?: string;
|
ancestorDepth?: string;
|
||||||
orderBy?: string;
|
orderBy?: string;
|
||||||
orderDirection?: string;
|
orderDirection?: string;
|
||||||
limit?: number;
|
limit?: number | null;
|
||||||
debug?: boolean;
|
debug?: boolean;
|
||||||
debugInfo: string | null;
|
debugInfo: {} | null;
|
||||||
fuzzyAttributeSearch: boolean;
|
fuzzyAttributeSearch: boolean;
|
||||||
highlightedTokens: string[];
|
highlightedTokens: string[];
|
||||||
originalQuery: string;
|
originalQuery: string;
|
||||||
|
@ -4,13 +4,15 @@ import beccaService = require('../../becca/becca_service');
|
|||||||
import becca = require('../../becca/becca');
|
import becca = require('../../becca/becca');
|
||||||
|
|
||||||
class SearchResult {
|
class SearchResult {
|
||||||
private notePathArray: string[];
|
notePathArray: string[];
|
||||||
private notePathTitle: string;
|
score: number;
|
||||||
private score?: number;
|
notePathTitle: string;
|
||||||
|
highlightedNotePathTitle?: string;
|
||||||
|
|
||||||
constructor(notePathArray: string[]) {
|
constructor(notePathArray: string[]) {
|
||||||
this.notePathArray = notePathArray;
|
this.notePathArray = notePathArray;
|
||||||
this.notePathTitle = beccaService.getNoteTitleForPath(notePathArray);
|
this.notePathTitle = beccaService.getNoteTitleForPath(notePathArray);
|
||||||
|
this.score = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
get notePath() {
|
get notePath() {
|
||||||
|
@ -448,13 +448,14 @@ function getExpression(tokens: TokenData[], searchContext: SearchContext, level
|
|||||||
|
|
||||||
function parse({fulltextTokens, expressionTokens, searchContext}: {
|
function parse({fulltextTokens, expressionTokens, searchContext}: {
|
||||||
fulltextTokens: TokenData[],
|
fulltextTokens: TokenData[],
|
||||||
expressionTokens: TokenData[],
|
expressionTokens: (TokenData | TokenData[])[],
|
||||||
searchContext: SearchContext
|
searchContext: SearchContext,
|
||||||
|
originalQuery: string
|
||||||
}) {
|
}) {
|
||||||
let expression: Expression | undefined | null;
|
let expression: Expression | undefined | null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
expression = getExpression(expressionTokens, searchContext);
|
expression = getExpression(expressionTokens as TokenData[], searchContext);
|
||||||
}
|
}
|
||||||
catch (e: any) {
|
catch (e: any) {
|
||||||
searchContext.addError(e.message);
|
searchContext.addError(e.message);
|
||||||
@ -475,7 +476,7 @@ function parse({fulltextTokens, expressionTokens, searchContext}: {
|
|||||||
exp = new OrderByAndLimitExp([{
|
exp = new OrderByAndLimitExp([{
|
||||||
valueExtractor: new ValueExtractor(searchContext, ['note', searchContext.orderBy]),
|
valueExtractor: new ValueExtractor(searchContext, ['note', searchContext.orderBy]),
|
||||||
direction: searchContext.orderDirection
|
direction: searchContext.orderDirection
|
||||||
}], searchContext.limit);
|
}], searchContext.limit || undefined);
|
||||||
|
|
||||||
(exp as any).subExpression = filterExp;
|
(exp as any).subExpression = filterExp;
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,28 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const normalizeString = require("normalize-strings");
|
import normalizeString = require("normalize-strings");
|
||||||
const lex = require('./lex');
|
import lex = require('./lex');
|
||||||
const handleParens = require('./handle_parens');
|
import handleParens = require('./handle_parens');
|
||||||
const parse = require('./parse');
|
import parse = require('./parse');
|
||||||
const SearchResult = require('../search_result');
|
import SearchResult = require('../search_result');
|
||||||
const SearchContext = require('../search_context');
|
import SearchContext = require('../search_context');
|
||||||
const becca = require('../../../becca/becca');
|
import becca = require('../../../becca/becca');
|
||||||
const beccaService = require('../../../becca/becca_service');
|
import beccaService = require('../../../becca/becca_service');
|
||||||
const utils = require('../../utils');
|
import utils = require('../../utils');
|
||||||
const log = require('../../log');
|
import log = require('../../log');
|
||||||
const hoistedNoteService = require('../../hoisted_note');
|
import hoistedNoteService = require('../../hoisted_note');
|
||||||
|
import BNote = require("../../../becca/entities/bnote");
|
||||||
|
import BAttribute = require("../../../becca/entities/battribute");
|
||||||
|
import { SearchParams, TokenData } from "./types";
|
||||||
|
import Expression = require("../expressions/expression");
|
||||||
|
import sql = require("../../sql");
|
||||||
|
|
||||||
function searchFromNote(note) {
|
function searchFromNote(note: BNote) {
|
||||||
let searchResultNoteIds, highlightedTokens;
|
let searchResultNoteIds;
|
||||||
|
let highlightedTokens: string[];
|
||||||
|
|
||||||
const searchScript = note.getRelationValue('searchScript');
|
const searchScript = note.getRelationValue('searchScript');
|
||||||
const searchString = note.getLabelValue('searchString');
|
const searchString = note.getLabelValue('searchString') || "";
|
||||||
let error = null;
|
let error = null;
|
||||||
|
|
||||||
if (searchScript) {
|
if (searchScript) {
|
||||||
@ -25,12 +31,12 @@ function searchFromNote(note) {
|
|||||||
} else {
|
} else {
|
||||||
const searchContext = new SearchContext({
|
const searchContext = new SearchContext({
|
||||||
fastSearch: note.hasLabel('fastSearch'),
|
fastSearch: note.hasLabel('fastSearch'),
|
||||||
ancestorNoteId: note.getRelationValue('ancestor'),
|
ancestorNoteId: note.getRelationValue('ancestor') || undefined,
|
||||||
ancestorDepth: note.getLabelValue('ancestorDepth'),
|
ancestorDepth: note.getLabelValue('ancestorDepth') || undefined,
|
||||||
includeArchivedNotes: note.hasLabel('includeArchivedNotes'),
|
includeArchivedNotes: note.hasLabel('includeArchivedNotes'),
|
||||||
orderBy: note.getLabelValue('orderBy'),
|
orderBy: note.getLabelValue('orderBy') || undefined,
|
||||||
orderDirection: note.getLabelValue('orderDirection'),
|
orderDirection: note.getLabelValue('orderDirection') || undefined,
|
||||||
limit: note.getLabelValue('limit'),
|
limit: parseInt(note.getLabelValue('limit') || "0", 10),
|
||||||
debug: note.hasLabel('debug'),
|
debug: note.hasLabel('debug'),
|
||||||
fuzzyAttributeSearch: false
|
fuzzyAttributeSearch: false
|
||||||
});
|
});
|
||||||
@ -51,7 +57,7 @@ function searchFromNote(note) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchFromRelation(note, relationName) {
|
function searchFromRelation(note: BNote, relationName: string) {
|
||||||
const scriptNote = note.getRelationTarget(relationName);
|
const scriptNote = note.getRelationTarget(relationName);
|
||||||
|
|
||||||
if (!scriptNote) {
|
if (!scriptNote) {
|
||||||
@ -90,18 +96,21 @@ function searchFromRelation(note, relationName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadNeededInfoFromDatabase() {
|
function loadNeededInfoFromDatabase() {
|
||||||
const sql = require('../../sql');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This complex structure is needed to calculate total occupied space by a note. Several object instances
|
* This complex structure is needed to calculate total occupied space by a note. Several object instances
|
||||||
* (note, revisions, attachments) can point to a single blobId, and thus the blob size should count towards the total
|
* (note, revisions, attachments) can point to a single blobId, and thus the blob size should count towards the total
|
||||||
* only once.
|
* only once.
|
||||||
*
|
*
|
||||||
* @var {Object.<string, Object.<string, int>>} - noteId => { blobId => blobSize }
|
* noteId => { blobId => blobSize }
|
||||||
*/
|
*/
|
||||||
const noteBlobs = {};
|
const noteBlobs: Record<string, Record<string, number>> = {};
|
||||||
|
|
||||||
const noteContentLengths = sql.getRows(`
|
type NoteContentLengthsRow = {
|
||||||
|
noteId: string;
|
||||||
|
blobId: string;
|
||||||
|
length: number;
|
||||||
|
};
|
||||||
|
const noteContentLengths = sql.getRows<NoteContentLengthsRow>(`
|
||||||
SELECT
|
SELECT
|
||||||
noteId,
|
noteId,
|
||||||
blobId,
|
blobId,
|
||||||
@ -122,7 +131,12 @@ function loadNeededInfoFromDatabase() {
|
|||||||
noteBlobs[noteId] = { [blobId]: length };
|
noteBlobs[noteId] = { [blobId]: length };
|
||||||
}
|
}
|
||||||
|
|
||||||
const attachmentContentLengths = sql.getRows(`
|
type AttachmentContentLengthsRow = {
|
||||||
|
noteId: string;
|
||||||
|
blobId: string;
|
||||||
|
length: number;
|
||||||
|
};
|
||||||
|
const attachmentContentLengths = sql.getRows<AttachmentContentLengthsRow>(`
|
||||||
SELECT
|
SELECT
|
||||||
ownerId AS noteId,
|
ownerId AS noteId,
|
||||||
attachments.blobId,
|
attachments.blobId,
|
||||||
@ -151,7 +165,13 @@ function loadNeededInfoFromDatabase() {
|
|||||||
becca.notes[noteId].contentAndAttachmentsSize = Object.values(noteBlobs[noteId]).reduce((acc, size) => acc + size, 0);
|
becca.notes[noteId].contentAndAttachmentsSize = Object.values(noteBlobs[noteId]).reduce((acc, size) => acc + size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const revisionContentLengths = sql.getRows(`
|
type RevisionRow = {
|
||||||
|
noteId: string;
|
||||||
|
blobId: string;
|
||||||
|
length: number;
|
||||||
|
isNoteRevision: true;
|
||||||
|
};
|
||||||
|
const revisionContentLengths = sql.getRows<RevisionRow>(`
|
||||||
SELECT
|
SELECT
|
||||||
noteId,
|
noteId,
|
||||||
revisions.blobId,
|
revisions.blobId,
|
||||||
@ -186,8 +206,11 @@ function loadNeededInfoFromDatabase() {
|
|||||||
|
|
||||||
noteBlobs[noteId][blobId] = length;
|
noteBlobs[noteId][blobId] = length;
|
||||||
|
|
||||||
if (isNoteRevision) {
|
if (isNoteRevision) {
|
||||||
becca.notes[noteId].revisionCount++;
|
const noteRevision = becca.notes[noteId];
|
||||||
|
if (noteRevision && noteRevision.revisionCount) {
|
||||||
|
noteRevision.revisionCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,20 +219,16 @@ function loadNeededInfoFromDatabase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function findResultsWithExpression(expression: Expression, searchContext: SearchContext): SearchResult[] {
|
||||||
* @param {Expression} expression
|
|
||||||
* @param {SearchContext} searchContext
|
|
||||||
* @returns {SearchResult[]}
|
|
||||||
*/
|
|
||||||
function findResultsWithExpression(expression, searchContext) {
|
|
||||||
if (searchContext.dbLoadNeeded) {
|
if (searchContext.dbLoadNeeded) {
|
||||||
loadNeededInfoFromDatabase();
|
loadNeededInfoFromDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
const allNoteSet = becca.getAllNoteSet();
|
const allNoteSet = becca.getAllNoteSet();
|
||||||
|
|
||||||
|
const noteIdToNotePath: Record<string, string[]> = {};
|
||||||
const executionContext = {
|
const executionContext = {
|
||||||
noteIdToNotePath: {}
|
noteIdToNotePath
|
||||||
};
|
};
|
||||||
|
|
||||||
const noteSet = expression.execute(allNoteSet, executionContext, searchContext);
|
const noteSet = expression.execute(allNoteSet, executionContext, searchContext);
|
||||||
@ -250,16 +269,16 @@ function findResultsWithExpression(expression, searchContext) {
|
|||||||
return searchResults;
|
return searchResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseQueryToExpression(query, searchContext) {
|
function parseQueryToExpression(query: string, searchContext: SearchContext) {
|
||||||
const {fulltextQuery, fulltextTokens, expressionTokens} = lex(query);
|
const {fulltextQuery, fulltextTokens, expressionTokens} = lex(query);
|
||||||
searchContext.fulltextQuery = fulltextQuery;
|
searchContext.fulltextQuery = fulltextQuery;
|
||||||
|
|
||||||
let structuredExpressionTokens;
|
let structuredExpressionTokens: (TokenData | TokenData[])[];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
structuredExpressionTokens = handleParens(expressionTokens);
|
structuredExpressionTokens = handleParens(expressionTokens);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e: any) {
|
||||||
structuredExpressionTokens = [];
|
structuredExpressionTokens = [];
|
||||||
searchContext.addError(e.message);
|
searchContext.addError(e.message);
|
||||||
}
|
}
|
||||||
@ -284,23 +303,13 @@ function parseQueryToExpression(query, searchContext) {
|
|||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function searchNotes(query: string, params: SearchParams = {}): BNote[] {
|
||||||
* @param {string} query
|
|
||||||
* @param {object} params - see SearchContext
|
|
||||||
* @returns {BNote[]}
|
|
||||||
*/
|
|
||||||
function searchNotes(query, params = {}) {
|
|
||||||
const searchResults = findResultsWithQuery(query, new SearchContext(params));
|
const searchResults = findResultsWithQuery(query, new SearchContext(params));
|
||||||
|
|
||||||
return searchResults.map(sr => becca.notes[sr.noteId]);
|
return searchResults.map(sr => becca.notes[sr.noteId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function findResultsWithQuery(query: string, searchContext: SearchContext): SearchResult[] {
|
||||||
* @param {string} query
|
|
||||||
* @param {SearchContext} searchContext
|
|
||||||
* @returns {SearchResult[]}
|
|
||||||
*/
|
|
||||||
function findResultsWithQuery(query, searchContext) {
|
|
||||||
query = query || "";
|
query = query || "";
|
||||||
searchContext.originalQuery = query;
|
searchContext.originalQuery = query;
|
||||||
|
|
||||||
@ -313,18 +322,13 @@ function findResultsWithQuery(query, searchContext) {
|
|||||||
return findResultsWithExpression(expression, searchContext);
|
return findResultsWithExpression(expression, searchContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function findFirstNoteWithQuery(query: string, searchContext: SearchContext): BNote | null {
|
||||||
* @param {string} query
|
|
||||||
* @param {SearchContext} searchContext
|
|
||||||
* @returns {BNote|null}
|
|
||||||
*/
|
|
||||||
function findFirstNoteWithQuery(query, searchContext) {
|
|
||||||
const searchResults = findResultsWithQuery(query, searchContext);
|
const searchResults = findResultsWithQuery(query, searchContext);
|
||||||
|
|
||||||
return searchResults.length > 0 ? becca.notes[searchResults[0].noteId] : null;
|
return searchResults.length > 0 ? becca.notes[searchResults[0].noteId] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchNotesForAutocomplete(query) {
|
function searchNotesForAutocomplete(query: string) {
|
||||||
const searchContext = new SearchContext({
|
const searchContext = new SearchContext({
|
||||||
fastSearch: true,
|
fastSearch: true,
|
||||||
includeArchivedNotes: false,
|
includeArchivedNotes: false,
|
||||||
@ -351,7 +355,7 @@ function searchNotesForAutocomplete(query) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function highlightSearchResults(searchResults, highlightedTokens) {
|
function highlightSearchResults(searchResults: SearchResult[], highlightedTokens: string[]) {
|
||||||
highlightedTokens = Array.from(new Set(highlightedTokens));
|
highlightedTokens = Array.from(new Set(highlightedTokens));
|
||||||
|
|
||||||
// we remove < signs because they can cause trouble in matching and overwriting existing highlighted chunks
|
// we remove < signs because they can cause trouble in matching and overwriting existing highlighted chunks
|
||||||
@ -387,7 +391,7 @@ function highlightSearchResults(searchResults, highlightedTokens) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapText(text, start, length, prefix, suffix) {
|
function wrapText(text: string, start: number, length: number, prefix: string, suffix: string) {
|
||||||
return text.substring(0, start) + prefix + text.substr(start, length) + suffix + text.substring(start + length);
|
return text.substring(0, start) + prefix + text.substr(start, length) + suffix + text.substring(start + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,6 +407,7 @@ function highlightSearchResults(searchResults, highlightedTokens) {
|
|||||||
let match;
|
let match;
|
||||||
|
|
||||||
// Find all matches
|
// Find all matches
|
||||||
|
if (!result.highlightedNotePathTitle) { continue; }
|
||||||
while ((match = tokenRegex.exec(normalizeString(result.highlightedNotePathTitle))) !== null) {
|
while ((match = tokenRegex.exec(normalizeString(result.highlightedNotePathTitle))) !== null) {
|
||||||
result.highlightedNotePathTitle = wrapText(result.highlightedNotePathTitle, match.index, token.length, "{", "}");
|
result.highlightedNotePathTitle = wrapText(result.highlightedNotePathTitle, match.index, token.length, "{", "}");
|
||||||
|
|
||||||
@ -413,6 +418,7 @@ function highlightSearchResults(searchResults, highlightedTokens) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const result of searchResults) {
|
for (const result of searchResults) {
|
||||||
|
if (!result.highlightedNotePathTitle) { continue; }
|
||||||
result.highlightedNotePathTitle = result.highlightedNotePathTitle
|
result.highlightedNotePathTitle = result.highlightedNotePathTitle
|
||||||
.replace(/"/g, "<small>")
|
.replace(/"/g, "<small>")
|
||||||
.replace(/'/g, "</small>")
|
.replace(/'/g, "</small>")
|
||||||
@ -421,7 +427,7 @@ function highlightSearchResults(searchResults, highlightedTokens) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatAttribute(attr) {
|
function formatAttribute(attr: BAttribute) {
|
||||||
if (attr.type === 'relation') {
|
if (attr.type === 'relation') {
|
||||||
return `~${utils.escapeHtml(attr.name)}=…`;
|
return `~${utils.escapeHtml(attr.name)}=…`;
|
||||||
}
|
}
|
||||||
@ -438,7 +444,7 @@ function formatAttribute(attr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
export = {
|
||||||
searchFromNote,
|
searchFromNote,
|
||||||
searchNotesForAutocomplete,
|
searchNotesForAutocomplete,
|
||||||
findResultsWithQuery,
|
findResultsWithQuery,
|
@ -3,4 +3,18 @@ export interface TokenData {
|
|||||||
inQuotes?: boolean;
|
inQuotes?: boolean;
|
||||||
startIndex?: number;
|
startIndex?: number;
|
||||||
endIndex?: number;
|
endIndex?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchParams {
|
||||||
|
fastSearch?: boolean;
|
||||||
|
includeArchivedNotes?: boolean;
|
||||||
|
includeHiddenNotes?: boolean;
|
||||||
|
ignoreHoistedNote?: boolean;
|
||||||
|
ancestorNoteId?: string;
|
||||||
|
ancestorDepth?: string;
|
||||||
|
orderBy?: string;
|
||||||
|
orderDirection?: string;
|
||||||
|
limit?: number | null;
|
||||||
|
debug?: boolean;
|
||||||
|
fuzzyAttributeSearch?: boolean;
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ const noteService = require('./notes');
|
|||||||
const dateUtils = require('./date_utils');
|
const dateUtils = require('./date_utils');
|
||||||
const log = require('./log');
|
const log = require('./log');
|
||||||
const hoistedNoteService = require('./hoisted_note');
|
const hoistedNoteService = require('./hoisted_note');
|
||||||
const searchService = require('./search/services/search.js');
|
const searchService = require('./search/services/search');
|
||||||
const SearchContext = require('./search/search_context');
|
const SearchContext = require('./search/search_context');
|
||||||
const {LBTPL_NOTE_LAUNCHER, LBTPL_CUSTOM_WIDGET, LBTPL_SPACER, LBTPL_SCRIPT} = require('./hidden_subtree');
|
const {LBTPL_NOTE_LAUNCHER, LBTPL_CUSTOM_WIDGET, LBTPL_SPACER, LBTPL_SCRIPT} = require('./hidden_subtree');
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ const shareRoot = require('./share_root.js');
|
|||||||
const contentRenderer = require('./content_renderer.js');
|
const contentRenderer = require('./content_renderer.js');
|
||||||
const assetPath = require('../services/asset_path');
|
const assetPath = require('../services/asset_path');
|
||||||
const appPath = require('../services/app_path');
|
const appPath = require('../services/app_path');
|
||||||
const searchService = require('../services/search/services/search.js');
|
const searchService = require('../services/search/services/search');
|
||||||
const SearchContext = require('../services/search/search_context');
|
const SearchContext = require('../services/search/search_context');
|
||||||
const log = require('../services/log');
|
const log = require('../services/log');
|
||||||
|
|
||||||
|
5
src/types.d.ts
vendored
5
src/types.d.ts
vendored
@ -11,4 +11,9 @@ declare module 'unescape' {
|
|||||||
declare module 'html2plaintext' {
|
declare module 'html2plaintext' {
|
||||||
function html2plaintext(htmlText: string): string;
|
function html2plaintext(htmlText: string): string;
|
||||||
export = html2plaintext;
|
export = html2plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'normalize-strings' {
|
||||||
|
function normalizeString(string: string): string;
|
||||||
|
export = normalizeString;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user