mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-30 09:56:36 +01:00 
			
		
		
		
	attribute parser and tests WIP
This commit is contained in:
		| @@ -19,7 +19,8 @@ | ||||
|     "build-frontend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/collapsible_widget.js", | ||||
|     "build-docs": "npm run build-backend-docs && npm run build-frontend-docs", | ||||
|     "webpack": "npx webpack -c webpack-desktop.config.js && npx webpack -c webpack-mobile.config.js && npx webpack -c webpack-setup.config.js", | ||||
|     "test": "jasmine" | ||||
|     "test": "jasmine", | ||||
|     "test-es6": "node -r esm spec-es6/attribute_parser.spec.js " | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "async-mutex": "0.2.2", | ||||
|   | ||||
| @@ -1,10 +1,62 @@ | ||||
| import attributeParser from '../src/public/app/services/attribute_parser.js'; | ||||
| import {describe, it, expect, execute} from './mini_test.js'; | ||||
|  | ||||
| describe("Lexer fulltext", () => { | ||||
| describe("Lexer", () => { | ||||
|     it("simple label", () => { | ||||
|         expect(attributeParser.lexer("#label")).toEqual(["#label"]); | ||||
|     }); | ||||
|  | ||||
|     it("label with value", () => { | ||||
|         expect(attributeParser.lexer("#label=Hallo")).toEqual(["#label", "=", "Hallo"]); | ||||
|     }); | ||||
|  | ||||
|     it("relation with value", () => { | ||||
|         expect(attributeParser.lexer('~relation=<a class="reference-link" href="#root/RclIpMauTOKS/NFi2gL4xtPxM" data-note-path="root/RclIpMauTOKS/NFi2gL4xtPxM">note</a>')).toEqual(["~relation", "=", "#root/RclIpMauTOKS/NFi2gL4xtPxM"]); | ||||
|     }); | ||||
|  | ||||
|     it("use quotes to define value", () => { | ||||
|         expect(attributeParser.lexer("#'label a'='hello\"` world'")) | ||||
|             .toEqual(["#label a", "=", 'hello"` world']); | ||||
|  | ||||
|         expect(attributeParser.lexer('#"label a" = "hello\'` world"')) | ||||
|             .toEqual(["#label a", "=", "hello'` world"]); | ||||
|  | ||||
|         expect(attributeParser.lexer('#`label a` = `hello\'" world`')) | ||||
|             .toEqual(["#label a", "=", "hello'\" world"]); | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| describe("Parser", () => { | ||||
|     it("simple label", () => { | ||||
|         const attrs = attributeParser.parser(["#token"]); | ||||
|  | ||||
|         expect(attrs.length).toEqual(1); | ||||
|         expect(attrs[0].type).toEqual('label'); | ||||
|         expect(attrs[0].name).toEqual('token'); | ||||
|         expect(attrs[0].value).toBeFalsy(); | ||||
|     }); | ||||
|  | ||||
|     it("label with value", () => { | ||||
|         const attrs = attributeParser.parser(["#token", "=", "val"]); | ||||
|  | ||||
|         expect(attrs.length).toEqual(1); | ||||
|         expect(attrs[0].type).toEqual('label'); | ||||
|         expect(attrs[0].name).toEqual('token'); | ||||
|         expect(attrs[0].value).toEqual("val"); | ||||
|     }); | ||||
|  | ||||
|     it("relation", () => { | ||||
|         const attrs = attributeParser.parser(["~token", "=", "#root/RclIpMauTOKS/NFi2gL4xtPxM"]); | ||||
|  | ||||
|         expect(attrs.length).toEqual(1); | ||||
|         expect(attrs[0].type).toEqual('relation'); | ||||
|         expect(attrs[0].name).toEqual("token"); | ||||
|         expect(attrs[0].value).toEqual('#root/RclIpMauTOKS/NFi2gL4xtPxM'); | ||||
|     }); | ||||
|  | ||||
|     it("error cases", () => { | ||||
|         expect(() => attributeParser.parser(["~token"])).toThrow('Relation "~token" should point to a note.'); | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| execute(); | ||||
|   | ||||
| @@ -25,6 +25,36 @@ export function expect(val) { | ||||
|  | ||||
|                 errorCount++; | ||||
|             } | ||||
|         }, | ||||
|         toBeFalsy: () => { | ||||
|             if (!!val) { | ||||
|                 console.trace("toBeFalsy failed."); | ||||
|                 console.error(`expected: null, false, undefined, 0 or empty string`); | ||||
|                 console.error(`got:      ${val}`); | ||||
|  | ||||
|                 errorCount++; | ||||
|             } | ||||
|         }, | ||||
|         toThrow: errorMessage => { | ||||
|             try { | ||||
|                 val(); | ||||
|             } | ||||
|             catch (e) { | ||||
|                 if (e.message !== errorMessage) { | ||||
|                     console.trace("toThrow caught exception, but messages differ"); | ||||
|                     console.error(`expected: ${errorMessage}`); | ||||
|                     console.error(`got:      ${e.message}`); | ||||
|  | ||||
|                     errorCount++; | ||||
|                 } | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             console.trace("toThrow did not catch any exception."); | ||||
|             console.error(`expected: ${errorMessage}`); | ||||
|             console.error(`got:      [none]`); | ||||
|             errorCount++; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,9 @@ | ||||
| function preprocessRelations(str) { | ||||
|     return str.replace(/<a[^>]+href="(#root[A-Za-z0-9/]*)"[^>]*>[^<]*<\/a>/g, "$1"); | ||||
| } | ||||
|  | ||||
| function lexer(str) { | ||||
|     str = str.toLowerCase(); | ||||
|     str = preprocessRelations(str); | ||||
|  | ||||
|     const expressionTokens = []; | ||||
|  | ||||
| @@ -95,6 +99,55 @@ function lexer(str) { | ||||
|     return expressionTokens; | ||||
| } | ||||
|  | ||||
| export default { | ||||
|     lexer | ||||
| function parser(tokens) { | ||||
|     const attrs = []; | ||||
|  | ||||
|     for (let i = 0; i < tokens.length; i++) { | ||||
|         const token = tokens[i]; | ||||
|  | ||||
|         if (token.startsWith('#')) { | ||||
|             const attr = { | ||||
|                 type: 'label', | ||||
|                 name: token.substr(1) | ||||
|             }; | ||||
|  | ||||
|             if (tokens[i + 1] === "=") { | ||||
|                 if (i + 2 >= tokens.length) { | ||||
|                     throw new Error(`Missing value for label "${token}"`); | ||||
|                 } | ||||
|  | ||||
|                 i += 2; | ||||
|  | ||||
|                 attr.value = tokens[i]; | ||||
|             } | ||||
|  | ||||
|             attrs.push(attr); | ||||
|         } | ||||
|         else if (token.startsWith('~')) { | ||||
|             const attr = { | ||||
|                 type: 'relation', | ||||
|                 name: token.substr(1) | ||||
|             }; | ||||
|  | ||||
|             if (i + 2 >= tokens.length || tokens[i + 1] !== '=') { | ||||
|                 throw new Error(`Relation "${token}" should point to a note.`); | ||||
|             } | ||||
|  | ||||
|             i += 2; | ||||
|  | ||||
|             attr.value = tokens[i]; | ||||
|  | ||||
|             attrs.push(attr); | ||||
|         } | ||||
|         else { | ||||
|             throw new Error(`Unrecognized attribute "${token}"`); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return attrs; | ||||
| } | ||||
|  | ||||
| export default { | ||||
|     lexer, | ||||
|     parser | ||||
| } | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| const noteCache = require('./note_cache'); | ||||
| const hoistedNoteService = require('../hoisted_note'); | ||||
| const protectedSessionService = require('../protected_session'); | ||||
| const stringSimilarity = require('string-similarity'); | ||||
|  | ||||
| function isNotePathArchived(notePath) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user