parsing and setting isInheritable flag

This commit is contained in:
zadam 2020-07-13 23:27:23 +02:00
parent 5dd73562da
commit 528418aecb
8 changed files with 82 additions and 27 deletions

6
package-lock.json generated
View File

@ -2841,9 +2841,9 @@
} }
}, },
"electron": { "electron": {
"version": "10.0.0-beta.10", "version": "10.0.0-beta.11",
"resolved": "https://registry.npmjs.org/electron/-/electron-10.0.0-beta.10.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-10.0.0-beta.11.tgz",
"integrity": "sha512-ARJaqzKFjP3DSyv0G50Uo3JMvi+kMP6k4J2pJXPhWJt7BZkI/AV2aWlHqe4SxBYRKuiUtFW16dF/wMcIWU2sdA==", "integrity": "sha512-2310EB2H9mjlRCHY/Zdd7TuItnF0wqs171vSp/0oluh+VHJZVc+MaecMayGpHiyCBnIqmzVB0f9YUB5r0xmJGQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@electron/get": "^1.0.1", "@electron/get": "^1.0.1",

View File

@ -75,7 +75,7 @@
}, },
"devDependencies": { "devDependencies": {
"cross-env": "^7.0.2", "cross-env": "^7.0.2",
"electron": "10.0.0-beta.10", "electron": "10.0.0-beta.11",
"electron-builder": "22.7.0", "electron-builder": "22.7.0",
"electron-packager": "15.0.0", "electron-packager": "15.0.0",
"electron-rebuild": "1.11.0", "electron-rebuild": "1.11.0",

View File

@ -14,6 +14,14 @@ describe("Lexer", () => {
.toEqual(["#label"]); .toEqual(["#label"]);
}); });
it("inherited label", () => {
expect(attributeParser.lexer("#label(inheritable)").map(t => t.text))
.toEqual(["#label", "(", "inheritable", ")"]);
expect(attributeParser.lexer("#label ( inheritable ) ").map(t => t.text))
.toEqual(["#label", "(", "inheritable", ")"]);
});
it("label with value", () => { it("label with value", () => {
expect(attributeParser.lexer("#label=Hallo").map(t => t.text)) expect(attributeParser.lexer("#label=Hallo").map(t => t.text))
.toEqual(["#label", "=", "Hallo"]); .toEqual(["#label", "=", "Hallo"]);
@ -49,6 +57,17 @@ describe("Parser", () => {
expect(attrs.length).toEqual(1); expect(attrs.length).toEqual(1);
expect(attrs[0].type).toEqual('label'); expect(attrs[0].type).toEqual('label');
expect(attrs[0].name).toEqual('token'); expect(attrs[0].name).toEqual('token');
expect(attrs[0].isInheritable).toBeFalsy();
expect(attrs[0].value).toBeFalsy();
});
it("inherited label", () => {
const attrs = attributeParser.parser(["#token", "(", "inheritable", ")"].map(t => ({text: t})));
expect(attrs.length).toEqual(1);
expect(attrs[0].type).toEqual('label');
expect(attrs[0].name).toEqual('token');
expect(attrs[0].isInheritable).toBeTruthy();
expect(attrs[0].value).toBeFalsy(); expect(attrs[0].value).toBeFalsy();
}); });
@ -77,10 +96,10 @@ describe("Parser", () => {
expect(attrs[0].value).toEqual('NFi2gL4xtPxM'); expect(attrs[0].value).toEqual('NFi2gL4xtPxM');
}); });
it("error cases", () => { // it("error cases", () => {
expect(() => attributeParser.parser(["~token"].map(t => ({text: t})), "~token")) // expect(() => attributeParser.parser(["~token"].map(t => ({text: t})), "~token"))
.toThrow('Relation "~token" should point to a note.'); // .toThrow('Relation "~token" should point to a note.');
}); // });
}); });
execute(); execute();

View File

@ -26,6 +26,15 @@ export function expect(val) {
errorCount++; errorCount++;
} }
}, },
toBeTruthy: () => {
if (!val) {
console.trace("toBeTruthy failed.");
console.error(`expected: truthy value`);
console.error(`got: ${val}`);
errorCount++;
}
},
toBeFalsy: () => { toBeFalsy: () => {
if (!!val) { if (!!val) {
console.trace("toBeFalsy failed."); console.trace("toBeFalsy failed.");

View File

@ -19,7 +19,7 @@ class Attribute {
/** @param {int} position */ /** @param {int} position */
this.position = row.position; this.position = row.position;
/** @param {boolean} isInheritable */ /** @param {boolean} isInheritable */
this.isInheritable = row.isInheritable; this.isInheritable = !!row.isInheritable;
} }
/** @returns {NoteShort} */ /** @returns {NoteShort} */

View File

@ -92,6 +92,15 @@ function lexer(str) {
finishWord(i - 1); finishWord(i - 1);
continue; continue;
} }
else if (['(', ')'].includes(chr)) {
finishWord(i - 1);
currentWord = chr;
finishWord(i);
continue;
}
else if (previousOperatorSymbol() !== isOperatorSymbol(chr)) { else if (previousOperatorSymbol() !== isOperatorSymbol(chr)) {
finishWord(i - 1); finishWord(i - 1);
@ -122,15 +131,30 @@ function parser(tokens, str, allowEmptyRelations = false) {
} }
for (let i = 0; i < tokens.length; i++) { for (let i = 0; i < tokens.length; i++) {
const {text, startIndex, endIndex} = tokens[i]; const {text, startIndex} = tokens[i];
function isInheritable() {
if (tokens.length > i + 3
&& tokens[i + 1].text === '('
&& tokens[i + 2].text === 'inheritable'
&& tokens[i + 3].text === ')') {
i += 3;
return true;
}
else {
return false;
}
}
if (text.startsWith('#')) { if (text.startsWith('#')) {
const attr = { const attr = {
type: 'label', type: 'label',
name: text.substr(1), name: text.substr(1),
isInheritable: false, // FIXME isInheritable: isInheritable(),
startIndex: startIndex, startIndex: startIndex,
endIndex: endIndex endIndex: tokens[i].endIndex // i could be moved by isInheritable
}; };
if (i + 1 < tokens.length && tokens[i + 1].text === "=") { if (i + 1 < tokens.length && tokens[i + 1].text === "=") {
@ -150,9 +174,9 @@ function parser(tokens, str, allowEmptyRelations = false) {
const attr = { const attr = {
type: 'relation', type: 'relation',
name: text.substr(1), name: text.substr(1),
isInheritable: false, // FIXME isInheritable: isInheritable(),
startIndex: startIndex, startIndex: startIndex,
endIndex: endIndex endIndex: tokens[i].endIndex // i could be moved by isInheritable
}; };
attrs.push(attr); attrs.push(attr);

View File

@ -117,6 +117,8 @@ export default class AttributeDetailWidget extends BasicWidget {
}); });
this.$attrEditInheritable = this.$widget.find('.attr-edit-inheritable'); this.$attrEditInheritable = this.$widget.find('.attr-edit-inheritable');
this.$attrEditInheritable.on('change', () => this.updateParent());
this.$closeAttrDetailButton = this.$widget.find('.close-attr-detail-button'); this.$closeAttrDetailButton = this.$widget.find('.close-attr-detail-button');
this.$attrIsOwnedBy = this.$widget.find('.attr-is-owned-by'); this.$attrIsOwnedBy = this.$widget.find('.attr-is-owned-by');
@ -210,6 +212,8 @@ export default class AttributeDetailWidget extends BasicWidget {
.setSelectedNotePath(attribute.value); .setSelectedNotePath(attribute.value);
} }
this.$attrEditInheritable.prop("checked", !!attribute.isInheritable);
this.$widget.css("left", x - this.$widget.width() / 2); this.$widget.css("left", x - this.$widget.width() / 2);
this.$widget.css("top", y + 30); this.$widget.css("top", y + 30);
this.$widget.show(); this.$widget.show();
@ -218,6 +222,7 @@ export default class AttributeDetailWidget extends BasicWidget {
updateParent() { updateParent() {
this.attribute.name = this.$attrEditName.val(); this.attribute.name = this.$attrEditName.val();
this.attribute.value = this.$attrEditValue.val(); this.attribute.value = this.$attrEditValue.val();
this.attribute.isInheritable = this.$attrEditInheritable.is(":checked");
this.triggerCommand('updateAttributeList', { attributes: this.allAttributes }); this.triggerCommand('updateAttributeList', { attributes: this.allAttributes });
} }

View File

@ -496,7 +496,7 @@ export default class NoteAttributesWidget extends TabAwareWidget {
this.$inheritedAttributes.empty(); this.$inheritedAttributes.empty();
await this.renderAttributesIntoDiv(inheritedAttributes, this.$inheritedAttributes); await this.renderInheritedAttributes(inheritedAttributes, this.$inheritedAttributes);
this.parseAttributes(); this.parseAttributes();
} }
@ -504,7 +504,9 @@ export default class NoteAttributesWidget extends TabAwareWidget {
async renderOwnedAttributes(ownedAttributes) { async renderOwnedAttributes(ownedAttributes) {
const $attributesContainer = $("<div>"); const $attributesContainer = $("<div>");
await this.renderAttributesIntoCKEditor(ownedAttributes, $attributesContainer); for (const attribute of ownedAttributes) {
this.renderAttribute(attribute, $attributesContainer, true);
}
await this.spacedUpdate.allowUpdateWithoutChange(() => { await this.spacedUpdate.allowUpdateWithoutChange(() => {
this.textEditor.setData($attributesContainer.html()); this.textEditor.setData($attributesContainer.html());
@ -523,13 +525,7 @@ export default class NoteAttributesWidget extends TabAwareWidget {
}); });
} }
async renderAttributesIntoCKEditor(attributes, $container) { renderInheritedAttributes(attributes, $container) {
for (const attribute of attributes) {
this.renderAttribute(attribute, $container);
}
}
renderAttributesIntoDiv(attributes, $container) {
for (const attribute of attributes) { for (const attribute of attributes) {
const $span = $("<span>") const $span = $("<span>")
.on('click', e => this.attributeDetailWidget.showAttributeDetail({ .on('click', e => this.attributeDetailWidget.showAttributeDetail({
@ -546,13 +542,15 @@ export default class NoteAttributesWidget extends TabAwareWidget {
$container.append($span); $container.append($span);
this.renderAttribute(attribute, $span); this.renderAttribute(attribute, $span, false);
} }
} }
renderAttribute(attribute, $container) { renderAttribute(attribute, $container, renderIsInheritable) {
const isInheritable = renderIsInheritable && attribute.isInheritable ? `(inheritable)` : '';
if (attribute.type === 'label') { if (attribute.type === 'label') {
$container.append(document.createTextNode('#' + attribute.name)); $container.append(document.createTextNode('#' + attribute.name + isInheritable));
if (attribute.value) { if (attribute.value) {
$container.append('='); $container.append('=');
@ -566,7 +564,7 @@ export default class NoteAttributesWidget extends TabAwareWidget {
} }
if (attribute.value) { if (attribute.value) {
$container.append(document.createTextNode('~' + attribute.name + "=")); $container.append(document.createTextNode('~' + attribute.name + isInheritable + "="));
$container.append(this.createNoteLink(attribute.value)); $container.append(this.createNoteLink(attribute.value));
$container.append(" "); $container.append(" ");
} else { } else {