mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	attribute parser preserves indexes from original string
This commit is contained in:
		
							
								
								
									
										2
									
								
								libraries/ckeditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								libraries/ckeditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -3,32 +3,38 @@ import {describe, it, expect, execute} from './mini_test.js'; | ||||
|  | ||||
| describe("Lexer", () => { | ||||
|     it("simple label", () => { | ||||
|         expect(attributeParser.lexer("#label")).toEqual(["#label"]); | ||||
|         expect(attributeParser.lexer("#label").map(t => t.text)) | ||||
|             .toEqual(["#label"]); | ||||
|     }); | ||||
|  | ||||
|     it("label with value", () => { | ||||
|         expect(attributeParser.lexer("#label=Hallo")).toEqual(["#label", "=", "Hallo"]); | ||||
|         expect(attributeParser.lexer("#label=Hallo").map(t => t.text)) | ||||
|             .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"]); | ||||
|         expect(attributeParser.lexer('~relation=<a class="reference-link" href="#root/RclIpMauTOKS/NFi2gL4xtPxM" data-note-path="root/RclIpMauTOKS/NFi2gL4xtPxM">note</a>').map(t => t.text)) | ||||
|             .toEqual(["~relation", "=", "#root/RclIpMauTOKS/NFi2gL4xtPxM"]); | ||||
|  | ||||
|         expect(attributeParser.lexer('~relation=<a class="reference-link" id="abc" href="#NFi2gL4xtPxM">note</a>').map(t => t.text)) | ||||
|             .toEqual(["~relation", "=", "#NFi2gL4xtPxM"]); | ||||
|     }); | ||||
|  | ||||
|     it("use quotes to define value", () => { | ||||
|         expect(attributeParser.lexer("#'label a'='hello\"` world'")) | ||||
|         expect(attributeParser.lexer("#'label a'='hello\"` world'").map(t => t.text)) | ||||
|             .toEqual(["#label a", "=", 'hello"` world']); | ||||
|  | ||||
|         expect(attributeParser.lexer('#"label a" = "hello\'` world"')) | ||||
|         expect(attributeParser.lexer('#"label a" = "hello\'` world"').map(t => t.text)) | ||||
|             .toEqual(["#label a", "=", "hello'` world"]); | ||||
|  | ||||
|         expect(attributeParser.lexer('#`label a` = `hello\'" world`')) | ||||
|         expect(attributeParser.lexer('#`label a` = `hello\'" world`').map(t => t.text)) | ||||
|             .toEqual(["#label a", "=", "hello'\" world"]); | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| describe("Parser", () => { | ||||
|     it("simple label", () => { | ||||
|         const attrs = attributeParser.parser(["#token"]); | ||||
|         const attrs = attributeParser.parser(["#token"].map(t => ({text: t}))); | ||||
|  | ||||
|         expect(attrs.length).toEqual(1); | ||||
|         expect(attrs[0].type).toEqual('label'); | ||||
| @@ -37,7 +43,7 @@ describe("Parser", () => { | ||||
|     }); | ||||
|  | ||||
|     it("label with value", () => { | ||||
|         const attrs = attributeParser.parser(["#token", "=", "val"]); | ||||
|         const attrs = attributeParser.parser(["#token", "=", "val"].map(t => ({text: t}))); | ||||
|  | ||||
|         expect(attrs.length).toEqual(1); | ||||
|         expect(attrs[0].type).toEqual('label'); | ||||
| @@ -46,16 +52,24 @@ describe("Parser", () => { | ||||
|     }); | ||||
|  | ||||
|     it("relation", () => { | ||||
|         const attrs = attributeParser.parser(["~token", "=", "#root/RclIpMauTOKS/NFi2gL4xtPxM"]); | ||||
|         let attrs = attributeParser.parser(["~token", "=", "#root/RclIpMauTOKS/NFi2gL4xtPxM"].map(t => ({text: t}))); | ||||
|  | ||||
|         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'); | ||||
|         expect(attrs[0].value).toEqual('NFi2gL4xtPxM'); | ||||
|  | ||||
|         attrs = attributeParser.parser(["~token", "=", "#NFi2gL4xtPxM"].map(t => ({text: t}))); | ||||
|  | ||||
|         expect(attrs.length).toEqual(1); | ||||
|         expect(attrs[0].type).toEqual('relation'); | ||||
|         expect(attrs[0].name).toEqual("token"); | ||||
|         expect(attrs[0].value).toEqual('NFi2gL4xtPxM'); | ||||
|     }); | ||||
|  | ||||
|     it("error cases", () => { | ||||
|         expect(() => attributeParser.parser(["~token"])).toThrow('Relation "~token" should point to a note.'); | ||||
|         expect(() => attributeParser.parser(["~token"].map(t => ({text: t})))) | ||||
|             .toThrow('Relation "~token" should point to a note.'); | ||||
|     }); | ||||
| }); | ||||
|  | ||||
|   | ||||
| @@ -15,7 +15,7 @@ function preprocess(str) { | ||||
| function lexer(str) { | ||||
|     str = preprocess(str); | ||||
|  | ||||
|     const expressionTokens = []; | ||||
|     const tokens = []; | ||||
|  | ||||
|     let quotes = false; | ||||
|     let currentWord = ''; | ||||
| @@ -33,12 +33,19 @@ function lexer(str) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function finishWord() { | ||||
|     /** | ||||
|      * @param endIndex - index of the last character of the token | ||||
|      */ | ||||
|     function finishWord(endIndex) { | ||||
|         if (currentWord === '') { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         expressionTokens.push(currentWord); | ||||
|         tokens.push({ | ||||
|             text: currentWord, | ||||
|             startIndex: endIndex - currentWord.length, | ||||
|             endIndex: endIndex | ||||
|         }); | ||||
|  | ||||
|         currentWord = ''; | ||||
|     } | ||||
| @@ -61,7 +68,7 @@ function lexer(str) { | ||||
|         else if (['"', "'", '`'].includes(chr)) { | ||||
|             if (!quotes) { | ||||
|                 if (previousOperatorSymbol()) { | ||||
|                     finishWord(); | ||||
|                     finishWord(i - 1); | ||||
|                 } | ||||
|  | ||||
|                 quotes = chr; | ||||
| @@ -69,7 +76,7 @@ function lexer(str) { | ||||
|             else if (quotes === chr) { | ||||
|                 quotes = false; | ||||
|  | ||||
|                 finishWord(); | ||||
|                 finishWord(i - 1); | ||||
|             } | ||||
|             else { | ||||
|                 // it's a quote but within other kind of quotes so it's valid as a literal character | ||||
| @@ -84,17 +91,11 @@ function lexer(str) { | ||||
|                 continue; | ||||
|             } | ||||
|             else if (chr === ' ') { | ||||
|                 finishWord(); | ||||
|                 continue; | ||||
|             } | ||||
|             else if (['(', ')', '.'].includes(chr)) { | ||||
|                 finishWord(); | ||||
|                 currentWord += chr; | ||||
|                 finishWord(); | ||||
|                 finishWord(i - 1); | ||||
|                 continue; | ||||
|             } | ||||
|             else if (previousOperatorSymbol() !== isOperatorSymbol(chr)) { | ||||
|                 finishWord(); | ||||
|                 finishWord(i - 1); | ||||
|  | ||||
|                 currentWord += chr; | ||||
|                 continue; | ||||
| @@ -104,44 +105,46 @@ function lexer(str) { | ||||
|         currentWord += chr; | ||||
|     } | ||||
|  | ||||
|     finishWord(); | ||||
|     finishWord(str.length - 1); | ||||
|  | ||||
|     return expressionTokens; | ||||
|     return tokens; | ||||
| } | ||||
|  | ||||
| function parser(tokens) { | ||||
|     const attrs = []; | ||||
|  | ||||
|     for (let i = 0; i < tokens.length; i++) { | ||||
|         const token = tokens[i]; | ||||
|         const {text, startIndex, endIndex} = tokens[i]; | ||||
|  | ||||
|         if (token.startsWith('#')) { | ||||
|         if (text.startsWith('#')) { | ||||
|             const attr = { | ||||
|                 type: 'label', | ||||
|                 name: token.substr(1), | ||||
|                 isInheritable: false // FIXME | ||||
|                 name: text.substr(1), | ||||
|                 isInheritable: false, // FIXME | ||||
|                 startIndex, | ||||
|                 endIndex | ||||
|             }; | ||||
|  | ||||
|             if (tokens[i + 1] === "=") { | ||||
|             if (i + 1 < tokens.length && tokens[i + 1].text === "=") { | ||||
|                 if (i + 2 >= tokens.length) { | ||||
|                     throw new Error(`Missing value for label "${token}"`); | ||||
|                     throw new Error(`Missing value for label "${text}"`); | ||||
|                 } | ||||
|  | ||||
|                 i += 2; | ||||
|  | ||||
|                 attr.value = tokens[i]; | ||||
|                 attr.value = tokens[i].text; | ||||
|             } | ||||
|  | ||||
|             attrs.push(attr); | ||||
|         } | ||||
|         else if (token.startsWith('~')) { | ||||
|             if (i + 2 >= tokens.length || tokens[i + 1] !== '=') { | ||||
|                 throw new Error(`Relation "${token}" should point to a note.`); | ||||
|         else if (text.startsWith('~')) { | ||||
|             if (i + 2 >= tokens.length || tokens[i + 1].text !== '=') { | ||||
|                 throw new Error(`Relation "${text}" should point to a note.`); | ||||
|             } | ||||
|  | ||||
|             i += 2; | ||||
|  | ||||
|             let notePath = tokens[i]; | ||||
|             let notePath = tokens[i].text; | ||||
|             if (notePath.startsWith("#")) { | ||||
|                 notePath = notePath.substr(1); | ||||
|             } | ||||
| @@ -150,15 +153,17 @@ function parser(tokens) { | ||||
|  | ||||
|             const attr = { | ||||
|                 type: 'relation', | ||||
|                 name: token.substr(1), | ||||
|                 name: text.substr(1), | ||||
|                 isInheritable: false, // FIXME | ||||
|                 value: noteId | ||||
|                 value: noteId, | ||||
|                 startIndex, | ||||
|                 endIndex | ||||
|             }; | ||||
|  | ||||
|             attrs.push(attr); | ||||
|         } | ||||
|         else { | ||||
|             throw new Error(`Unrecognized attribute "${token}"`); | ||||
|             throw new Error(`Unrecognized attribute "${text}"`); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -114,6 +114,11 @@ export default class NoteAttributesWidget extends TabAwareWidget { | ||||
|         // display of $widget in both branches. | ||||
|         this.$widget.show(); | ||||
|  | ||||
|         this.$editor.on("click", () => { | ||||
|             const pos = this.textEditor.model.document.selection.getFirstPosition(); | ||||
|             console.log(pos.textNode && pos.textNode.data, pos.parent.textNode && pos.parent.textNode.data, pos.offset); | ||||
|         }); | ||||
|  | ||||
|         this.textEditor = await BalloonEditor.create(this.$editor[0], { | ||||
|             removePlugins: [ | ||||
|                 'Enter', | ||||
| @@ -168,6 +173,9 @@ export default class NoteAttributesWidget extends TabAwareWidget { | ||||
|         }); | ||||
|  | ||||
|         this.textEditor.model.document.on('change:data', () => this.spacedUpdate.scheduleUpdate()); | ||||
|  | ||||
|         await import(/* webpackIgnore: true */'../../libraries/ckeditor/inspector.js'); | ||||
|         CKEditorInspector.attach(this.textEditor); | ||||
|     } | ||||
|  | ||||
|     async loadReferenceLinkTitle(noteId, $el) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user