mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
support for long syntax of labels and relations
This commit is contained in:
parent
355ffd3d02
commit
ae772288e2
@ -56,6 +56,38 @@ describe("Search", () => {
|
|||||||
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
|
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("label comparison with short syntax", async () => {
|
||||||
|
rootNote
|
||||||
|
.child(note("Europe")
|
||||||
|
.child(note("Austria")
|
||||||
|
.label('capital', 'Vienna'))
|
||||||
|
.child(note("Czech Republic")
|
||||||
|
.label('capital', 'Prague'))
|
||||||
|
);
|
||||||
|
|
||||||
|
const parsingContext = new ParsingContext();
|
||||||
|
|
||||||
|
let searchResults = await searchService.findNotesWithQuery('#capital=Vienna', parsingContext);
|
||||||
|
expect(searchResults.length).toEqual(1);
|
||||||
|
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("label comparison with full syntax", async () => {
|
||||||
|
rootNote
|
||||||
|
.child(note("Europe")
|
||||||
|
.child(note("Austria")
|
||||||
|
.label('capital', 'Vienna'))
|
||||||
|
.child(note("Czech Republic")
|
||||||
|
.label('capital', 'Prague'))
|
||||||
|
);
|
||||||
|
|
||||||
|
const parsingContext = new ParsingContext();
|
||||||
|
|
||||||
|
let searchResults = await searchService.findNotesWithQuery('# note.labels.capital=Prague', parsingContext);
|
||||||
|
expect(searchResults.length).toEqual(1);
|
||||||
|
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
it("numeric label comparison", async () => {
|
it("numeric label comparison", async () => {
|
||||||
rootNote
|
rootNote
|
||||||
.child(note("Europe")
|
.child(note("Europe")
|
||||||
@ -162,12 +194,12 @@ describe("Search", () => {
|
|||||||
|
|
||||||
const parsingContext = new ParsingContext();
|
const parsingContext = new ParsingContext();
|
||||||
|
|
||||||
let searchResults = await searchService.findNotesWithQuery('# note.parent.title = Europe', parsingContext);
|
let searchResults = await searchService.findNotesWithQuery('# note.parents.title = Europe', parsingContext);
|
||||||
expect(searchResults.length).toEqual(2);
|
expect(searchResults.length).toEqual(2);
|
||||||
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
|
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
|
||||||
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
|
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
|
||||||
|
|
||||||
searchResults = await searchService.findNotesWithQuery('# note.parent.title = Asia', parsingContext);
|
searchResults = await searchService.findNotesWithQuery('# note.parents.title = Asia', parsingContext);
|
||||||
expect(searchResults.length).toEqual(1);
|
expect(searchResults.length).toEqual(1);
|
||||||
expect(findNoteByTitle(searchResults, "Taiwan")).toBeTruthy();
|
expect(findNoteByTitle(searchResults, "Taiwan")).toBeTruthy();
|
||||||
});
|
});
|
||||||
@ -182,17 +214,17 @@ describe("Search", () => {
|
|||||||
|
|
||||||
const parsingContext = new ParsingContext();
|
const parsingContext = new ParsingContext();
|
||||||
|
|
||||||
let searchResults = await searchService.findNotesWithQuery('# note.child.title =* Aust', parsingContext);
|
let searchResults = await searchService.findNotesWithQuery('# note.children.title =* Aust', parsingContext);
|
||||||
expect(searchResults.length).toEqual(2);
|
expect(searchResults.length).toEqual(2);
|
||||||
expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy();
|
expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy();
|
||||||
expect(findNoteByTitle(searchResults, "Oceania")).toBeTruthy();
|
expect(findNoteByTitle(searchResults, "Oceania")).toBeTruthy();
|
||||||
|
|
||||||
searchResults = await searchService.findNotesWithQuery('# note.child.title =* Aust AND note.child.title *= republic', parsingContext);
|
searchResults = await searchService.findNotesWithQuery('# note.children.title =* Aust AND note.children.title *= republic', parsingContext);
|
||||||
expect(searchResults.length).toEqual(1);
|
expect(searchResults.length).toEqual(1);
|
||||||
expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy();
|
expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("filter by relation's note properties", async () => {
|
it("filter by relation's note properties using short syntax", async () => {
|
||||||
const austria = note("Austria");
|
const austria = note("Austria");
|
||||||
const portugal = note("Portugal");
|
const portugal = note("Portugal");
|
||||||
|
|
||||||
@ -216,6 +248,27 @@ describe("Search", () => {
|
|||||||
expect(searchResults.length).toEqual(1);
|
expect(searchResults.length).toEqual(1);
|
||||||
expect(findNoteByTitle(searchResults, "Spain")).toBeTruthy();
|
expect(findNoteByTitle(searchResults, "Spain")).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("filter by relation's note properties using long syntax", async () => {
|
||||||
|
const austria = note("Austria");
|
||||||
|
const portugal = note("Portugal");
|
||||||
|
|
||||||
|
rootNote
|
||||||
|
.child(note("Europe")
|
||||||
|
.child(austria)
|
||||||
|
.child(note("Czech Republic")
|
||||||
|
.relation('neighbor', austria.note))
|
||||||
|
.child(portugal)
|
||||||
|
.child(note("Spain")
|
||||||
|
.relation('neighbor', portugal.note))
|
||||||
|
);
|
||||||
|
|
||||||
|
const parsingContext = new ParsingContext();
|
||||||
|
|
||||||
|
const searchResults = await searchService.findNotesWithQuery('# note.relations.neighbor.title = Austria', parsingContext);
|
||||||
|
expect(searchResults.length).toEqual(1);
|
||||||
|
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/** @return {Note} */
|
/** @return {Note} */
|
||||||
|
@ -52,18 +52,40 @@ function getExpression(tokens, parsingContext) {
|
|||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if (tokens[i] === 'parent') {
|
if (tokens[i] === 'parents') {
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
||||||
return new ChildOfExp(parseNoteProperty());
|
return new ChildOfExp(parseNoteProperty());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokens[i] === 'child') {
|
if (tokens[i] === 'children') {
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
||||||
return new ParentOfExp(parseNoteProperty());
|
return new ParentOfExp(parseNoteProperty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tokens[i] === 'labels') {
|
||||||
|
if (tokens[i + 1] !== '.') {
|
||||||
|
parsingContext.addError(`Expected "." to separate field path, god "${tokens[i + 1]}"`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
|
||||||
|
return parseLabel(tokens[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokens[i] === 'relations') {
|
||||||
|
if (tokens[i + 1] !== '.') {
|
||||||
|
parsingContext.addError(`Expected "." to separate field path, god "${tokens[i + 1]}"`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
|
||||||
|
return parseRelation(tokens[i]);
|
||||||
|
}
|
||||||
|
|
||||||
if (tokens[i] === 'title') {
|
if (tokens[i] === 'title') {
|
||||||
const propertyName = tokens[i];
|
const propertyName = tokens[i];
|
||||||
const operator = tokens[i + 1];
|
const operator = tokens[i + 1];
|
||||||
@ -81,6 +103,45 @@ function getExpression(tokens, parsingContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseLabel(labelName) {
|
||||||
|
parsingContext.highlightedTokens.push(labelName);
|
||||||
|
|
||||||
|
if (i < tokens.length - 2 && isOperator(tokens[i + 1])) {
|
||||||
|
let operator = tokens[i + 1];
|
||||||
|
const comparedValue = tokens[i + 2];
|
||||||
|
|
||||||
|
parsingContext.highlightedTokens.push(comparedValue);
|
||||||
|
|
||||||
|
if (parsingContext.fuzzyAttributeSearch && operator === '=') {
|
||||||
|
operator = '*=*';
|
||||||
|
}
|
||||||
|
|
||||||
|
const comparator = comparatorBuilder(operator, comparedValue);
|
||||||
|
|
||||||
|
if (!comparator) {
|
||||||
|
parsingContext.addError(`Can't find operator '${operator}'`);
|
||||||
|
} else {
|
||||||
|
i += 2;
|
||||||
|
|
||||||
|
return new LabelComparisonExp('label', labelName, comparator);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return new AttributeExistsExp('label', labelName, parsingContext.fuzzyAttributeSearch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseRelation(relationName) {
|
||||||
|
parsingContext.highlightedTokens.push(relationName);
|
||||||
|
|
||||||
|
if (i < tokens.length - 2 && tokens[i + 1] === '.') {
|
||||||
|
i += 1;
|
||||||
|
|
||||||
|
return new RelationWhereExp(relationName, parseNoteProperty());
|
||||||
|
} else {
|
||||||
|
return new AttributeExistsExp('relation', relationName, parsingContext.fuzzyAttributeSearch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < tokens.length; i++) {
|
for (i = 0; i < tokens.length; i++) {
|
||||||
const token = tokens[i];
|
const token = tokens[i];
|
||||||
|
|
||||||
@ -93,45 +154,13 @@ function getExpression(tokens, parsingContext) {
|
|||||||
}
|
}
|
||||||
else if (token.startsWith('#')) {
|
else if (token.startsWith('#')) {
|
||||||
const labelName = token.substr(1);
|
const labelName = token.substr(1);
|
||||||
parsingContext.highlightedTokens.push(labelName);
|
|
||||||
|
|
||||||
if (i < tokens.length - 2 && isOperator(tokens[i + 1])) {
|
expressions.push(parseLabel(labelName));
|
||||||
let operator = tokens[i + 1];
|
|
||||||
const comparedValue = tokens[i + 2];
|
|
||||||
|
|
||||||
parsingContext.highlightedTokens.push(comparedValue);
|
|
||||||
|
|
||||||
if (parsingContext.fuzzyAttributeSearch && operator === '=') {
|
|
||||||
operator = '*=*';
|
|
||||||
}
|
|
||||||
|
|
||||||
const comparator = comparatorBuilder(operator, comparedValue);
|
|
||||||
|
|
||||||
if (!comparator) {
|
|
||||||
parsingContext.addError(`Can't find operator '${operator}'`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
expressions.push(new LabelComparisonExp('label', labelName, comparator));
|
|
||||||
|
|
||||||
i += 2;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
expressions.push(new AttributeExistsExp('label', labelName, parsingContext.fuzzyAttributeSearch));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (token.startsWith('~')) {
|
else if (token.startsWith('~')) {
|
||||||
const relationName = token.substr(1);
|
const relationName = token.substr(1);
|
||||||
parsingContext.highlightedTokens.push(relationName);
|
|
||||||
|
|
||||||
if (i < tokens.length - 2 && tokens[i + 1] === '.') {
|
expressions.push(parseRelation(relationName));
|
||||||
i += 1;
|
|
||||||
|
|
||||||
expressions.push(new RelationWhereExp(relationName, parseNoteProperty()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
expressions.push(new AttributeExistsExp('relation', relationName, parsingContext.fuzzyAttributeSearch));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (token === 'note') {
|
else if (token === 'note') {
|
||||||
i++;
|
i++;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user