diff --git a/.gitignore b/.gitignore index a87f5d7a..a06e9ee1 100755 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ package-lock.json .vscode/ .stylelintrc.json src/css/ +src/js/filterlang.mjs diff --git a/src/js/datePicker.mjs b/src/js/datePicker.mjs index df8c623d..c03aa707 100644 --- a/src/js/datePicker.mjs +++ b/src/js/datePicker.mjs @@ -2,7 +2,7 @@ import { translations, userData } from "../render.js"; import { _paq } from "./matomo.mjs"; import { resizeInput } from "./form.mjs"; -import { RecExtension, SugarDueExtension } from "./todotxtExtensions.mjs"; +import { RecExtension, SugarDueExtension, ThresholdExtension } from "./todotxtExtensions.mjs"; import "../../node_modules/jstodotxt/jsTodoExtensions.js"; import "../../node_modules/jstodotxt/jsTodoTxt.js"; import Datepicker from "../../node_modules/vanillajs-datepicker/js/Datepicker.js"; @@ -21,7 +21,7 @@ datePickerInput.addEventListener("changeDate", function (e) { // we only update the object if there is a date selected. In case of a refresh it would throw an error otherwise if(e.detail.date) { // generate the object on what is written into input, so we don't overwrite previous inputs of user - let todo = new TodoTxtItem(document.getElementById("modalFormInput").value, [ new SugarDueExtension(), new HiddenExtension(), new RecExtension() ]); + let todo = new TodoTxtItem(document.getElementById("modalFormInput").value, [ new SugarDueExtension(), new HiddenExtension(), new RecExtension(), new ThresholdExtension() ]); todo.due = new Date(e.detail.date); todo.dueString = new Date(e.detail.date.getTime() - (e.detail.date.getTimezoneOffset() * 60000 )).toISOString().split("T")[0]; // if suggestion box was open, it needs to be closed @@ -53,7 +53,7 @@ const datePicker = new Datepicker(datePickerInput, { } }); document.querySelector(".datepicker .clear-btn").onclick = function() { - let todo = new TodoTxtItem(document.getElementById("modalFormInput").value, [ new SugarDueExtension(), new HiddenExtension(), new RecExtension() ]); + let todo = new TodoTxtItem(document.getElementById("modalFormInput").value, [ new SugarDueExtension(), new HiddenExtension(), new RecExtension(), new ThresholdExtension() ]); todo.due = undefined; todo.dueString = undefined; document.getElementById("modalFormInput").value = todo.toString(); diff --git a/src/js/filterlang.mjs b/src/js/filterlang.mjs deleted file mode 100644 index 37ee58bc..00000000 --- a/src/js/filterlang.mjs +++ /dev/null @@ -1,2051 +0,0 @@ -// Generated by Peggy 1.2.0. -// -// https://peggyjs.org/ - - - import { addIntervalToDate } from "./recurrences.mjs"; - - -function peg$subclass(child, parent) { - function C() { this.constructor = child; } - C.prototype = parent.prototype; - child.prototype = new C(); -} - -function peg$SyntaxError(message, expected, found, location) { - var self = Error.call(this, message); - if (Object.setPrototypeOf) { - Object.setPrototypeOf(self, peg$SyntaxError.prototype); - } - self.expected = expected; - self.found = found; - self.location = location; - self.name = "SyntaxError"; - return self; -} - -peg$subclass(peg$SyntaxError, Error); - -function peg$padEnd(str, targetLength, padString) { - padString = padString || " "; - if (str.length > targetLength) { return str; } - targetLength -= str.length; - padString += padString.repeat(targetLength); - return str + padString.slice(0, targetLength); -} - -peg$SyntaxError.prototype.format = function(sources) { - var str = "Error: " + this.message; - if (this.location) { - var src = null; - var k; - for (k = 0; k < sources.length; k++) { - if (sources[k].source === this.location.source) { - src = sources[k].text.split(/\r\n|\n|\r/g); - break; - } - } - var s = this.location.start; - var loc = this.location.source + ":" + s.line + ":" + s.column; - if (src) { - var e = this.location.end; - var filler = peg$padEnd("", s.line.toString().length); - var line = src[s.line - 1]; - var last = s.line === e.line ? e.column : line.length + 1; - str += "\n --> " + loc + "\n" - + filler + " |\n" - + s.line + " | " + line + "\n" - + filler + " | " + peg$padEnd("", s.column - 1) - + peg$padEnd("", last - s.column, "^"); - } else { - str += "\n at " + loc; - } - } - return str; -}; - -peg$SyntaxError.buildMessage = function(expected, found) { - var DESCRIBE_EXPECTATION_FNS = { - literal: function(expectation) { - return "\"" + literalEscape(expectation.text) + "\""; - }, - - class: function(expectation) { - var escapedParts = expectation.parts.map(function(part) { - return Array.isArray(part) - ? classEscape(part[0]) + "-" + classEscape(part[1]) - : classEscape(part); - }); - - return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; - }, - - any: function() { - return "any character"; - }, - - end: function() { - return "end of input"; - }, - - other: function(expectation) { - return expectation.description; - } - }; - - function hex(ch) { - return ch.charCodeAt(0).toString(16).toUpperCase(); - } - - function literalEscape(s) { - return s - .replace(/\\/g, "\\\\") - .replace(/"/g, "\\\"") - .replace(/\0/g, "\\0") - .replace(/\t/g, "\\t") - .replace(/\n/g, "\\n") - .replace(/\r/g, "\\r") - .replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); }) - .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); }); - } - - function classEscape(s) { - return s - .replace(/\\/g, "\\\\") - .replace(/\]/g, "\\]") - .replace(/\^/g, "\\^") - .replace(/-/g, "\\-") - .replace(/\0/g, "\\0") - .replace(/\t/g, "\\t") - .replace(/\n/g, "\\n") - .replace(/\r/g, "\\r") - .replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); }) - .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); }); - } - - function describeExpectation(expectation) { - return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation); - } - - function describeExpected(expected) { - var descriptions = expected.map(describeExpectation); - var i, j; - - descriptions.sort(); - - if (descriptions.length > 0) { - for (i = 1, j = 1; i < descriptions.length; i++) { - if (descriptions[i - 1] !== descriptions[i]) { - descriptions[j] = descriptions[i]; - j++; - } - } - descriptions.length = j; - } - - switch (descriptions.length) { - case 1: - return descriptions[0]; - - case 2: - return descriptions[0] + " or " + descriptions[1]; - - default: - return descriptions.slice(0, -1).join(", ") - + ", or " - + descriptions[descriptions.length - 1]; - } - } - - function describeFound(found) { - return found ? "\"" + literalEscape(found) + "\"" : "end of input"; - } - - return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; -}; - -function peg$parse(input, options) { - options = options !== undefined ? options : {}; - - var peg$FAILED = {}; - var peg$source = options.grammarSource; - - var peg$startRuleFunctions = { filterQuery: peg$parsefilterQuery }; - var peg$startRuleFunction = peg$parsefilterQuery; - - var peg$c0 = "("; - var peg$c1 = ")"; - var peg$c2 = "complete"; - var peg$c3 = "+"; - var peg$c4 = "@"; - var peg$c5 = "||"; - var peg$c6 = "or"; - var peg$c7 = "&&"; - var peg$c8 = "and"; - var peg$c9 = "!"; - var peg$c10 = "not"; - var peg$c11 = "pri"; - var peg$c12 = "o"; - var peg$c13 = "r"; - var peg$c14 = "i"; - var peg$c15 = "t"; - var peg$c16 = "y"; - var peg$c17 = "due"; - var peg$c18 = "-"; - var peg$c19 = "=="; - var peg$c20 = "!="; - var peg$c21 = ">="; - var peg$c22 = "<="; - var peg$c23 = ">"; - var peg$c24 = "<"; - var peg$c25 = "today"; - var peg$c26 = "tomorrow"; - var peg$c27 = "yesterday"; - var peg$c28 = "\""; - var peg$c29 = "'"; - var peg$c30 = "\\"; - var peg$c31 = "/"; - - var peg$r0 = /^[A-Z]/; - var peg$r1 = /^[dbwmy]/; - var peg$r2 = /^[0-9]/; - var peg$r3 = /^[^ \t\n\r"()]/; - var peg$r4 = /^[ \t\n\r]/; - - var peg$e0 = peg$literalExpectation("(", false); - var peg$e1 = peg$literalExpectation(")", false); - var peg$e2 = peg$literalExpectation("complete", false); - var peg$e3 = peg$literalExpectation("+", false); - var peg$e4 = peg$literalExpectation("@", false); - var peg$e5 = peg$literalExpectation("||", false); - var peg$e6 = peg$literalExpectation("or", true); - var peg$e7 = peg$literalExpectation("&&", false); - var peg$e8 = peg$literalExpectation("and", true); - var peg$e9 = peg$literalExpectation("!", false); - var peg$e10 = peg$literalExpectation("not", true); - var peg$e11 = peg$classExpectation([["A", "Z"]], false, false); - var peg$e12 = peg$literalExpectation("pri", false); - var peg$e13 = peg$literalExpectation("o", false); - var peg$e14 = peg$literalExpectation("r", false); - var peg$e15 = peg$literalExpectation("i", false); - var peg$e16 = peg$literalExpectation("t", false); - var peg$e17 = peg$literalExpectation("y", false); - var peg$e18 = peg$literalExpectation("due", false); - var peg$e19 = peg$classExpectation(["d", "b", "w", "m", "y"], false, false); - var peg$e20 = peg$literalExpectation("-", false); - var peg$e21 = peg$literalExpectation("==", false); - var peg$e22 = peg$literalExpectation("!=", false); - var peg$e23 = peg$literalExpectation(">=", false); - var peg$e24 = peg$literalExpectation("<=", false); - var peg$e25 = peg$literalExpectation(">", false); - var peg$e26 = peg$literalExpectation("<", false); - var peg$e27 = peg$literalExpectation("today", false); - var peg$e28 = peg$literalExpectation("tomorrow", false); - var peg$e29 = peg$literalExpectation("yesterday", false); - var peg$e30 = peg$classExpectation([["0", "9"]], false, false); - var peg$e31 = peg$otherExpectation("string"); - var peg$e32 = peg$literalExpectation("\"", false); - var peg$e33 = peg$literalExpectation("'", false); - var peg$e34 = peg$literalExpectation("\\", false); - var peg$e35 = peg$otherExpectation("regex"); - var peg$e36 = peg$literalExpectation("/", false); - var peg$e37 = peg$anyExpectation(); - var peg$e38 = peg$classExpectation([" ", "\t", "\n", "\r", "\"", "(", ")"], true, false); - var peg$e39 = peg$otherExpectation("whitespace"); - var peg$e40 = peg$classExpectation([" ", "\t", "\n", "\r"], false, false); - - var peg$f0 = function(left) { return left; }; - var peg$f1 = function() { return []; }; - var peg$f2 = function(left, right) { return left.concat(right, ["||"]); }; - var peg$f3 = function(left, right) { return left.concat(right, ["&&"]); }; - var peg$f4 = function(left) { return left.concat(["!!"]); }; - var peg$f5 = function() { return ["complete"]; }; - var peg$f6 = function(left) { return ["string", left]; }; - var peg$f7 = function(left) { return ["regex", left]; }; - var peg$f8 = function(left) { return ["++", left]; }; - var peg$f9 = function() { return ["++", "*"]; }; - var peg$f10 = function(left) { return ["@@", left]; }; - var peg$f11 = function() { return ["@@", "*"]; }; - var peg$f12 = function(op, right) { return ["priority", right, op]; }; - var peg$f13 = function() { return ["priority"]; }; - var peg$f14 = function() { return text(); }; - var peg$f15 = function(op, right) { return ["due"].concat(right, [op]); }; - var peg$f16 = function() { return ["due"]; }; - var peg$f17 = function(left, op, count, unit) { - if (op == "-") { - count = count * -1; - } - // we do our date math with the same code as we use for - // recurrence calculations. All dates are returned from - // the parser as millisec since epoch (getTime()) to - // simplify comparisons in the filter lang execution engine. - let d = addIntervalToDate(new Date(left), count, unit); - return d.getTime(); - }; - var peg$f18 = function(year, month, day) { - let d = new Date(year, month-1, day); - return d.getTime(); - }; - var peg$f19 = function() { - let d = new Date(); // now, w current time of day - d = new Date(d.getFullYear(), d.getMonth(), d.getDate()); - return d.getTime(); - }; - var peg$f20 = function() { - let d = new Date(); // now, w current time of day - d = new Date(d.getFullYear(), d.getMonth(), d.getDate()); - return d.getTime() + 24*60*60*1000; - }; - var peg$f21 = function() { - let d = new Date(); // now, w current time of day - d = new Date(d.getFullYear(), d.getMonth(), d.getDate()); - return d.getTime() - 24*60*60*1000; - }; - var peg$f22 = function(chars) { - return chars.join(""); - }; - var peg$f23 = function() { return '"'; }; - var peg$f24 = function() { return "'"; }; - var peg$f25 = function(chars) { - return new RegExp(chars.join(""), "i"); - }; - var peg$f26 = function(chars) { - return new RegExp(chars.join("")); - }; - var peg$f27 = function() { return "/"; }; - var peg$f28 = function() { return '"' + text(); }; - - var peg$currPos = 0; - var peg$savedPos = 0; - var peg$posDetailsCache = [{ line: 1, column: 1 }]; - var peg$maxFailPos = 0; - var peg$maxFailExpected = []; - var peg$silentFails = 0; - - var peg$result; - - if ("startRule" in options) { - if (!(options.startRule in peg$startRuleFunctions)) { - throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); - } - - peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; - } - - function text() { - return input.substring(peg$savedPos, peg$currPos); - } - - function offset() { - return peg$savedPos; - } - - function range() { - return { - source: peg$source, - start: peg$savedPos, - end: peg$currPos - }; - } - - function location() { - return peg$computeLocation(peg$savedPos, peg$currPos); - } - - function expected(description, location) { - location = location !== undefined - ? location - : peg$computeLocation(peg$savedPos, peg$currPos); - - throw peg$buildStructuredError( - [peg$otherExpectation(description)], - input.substring(peg$savedPos, peg$currPos), - location - ); - } - - function error(message, location) { - location = location !== undefined - ? location - : peg$computeLocation(peg$savedPos, peg$currPos); - - throw peg$buildSimpleError(message, location); - } - - function peg$literalExpectation(text, ignoreCase) { - return { type: "literal", text: text, ignoreCase: ignoreCase }; - } - - function peg$classExpectation(parts, inverted, ignoreCase) { - return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase }; - } - - function peg$anyExpectation() { - return { type: "any" }; - } - - function peg$endExpectation() { - return { type: "end" }; - } - - function peg$otherExpectation(description) { - return { type: "other", description: description }; - } - - function peg$computePosDetails(pos) { - var details = peg$posDetailsCache[pos]; - var p; - - if (details) { - return details; - } else { - p = pos - 1; - while (!peg$posDetailsCache[p]) { - p--; - } - - details = peg$posDetailsCache[p]; - details = { - line: details.line, - column: details.column - }; - - while (p < pos) { - if (input.charCodeAt(p) === 10) { - details.line++; - details.column = 1; - } else { - details.column++; - } - - p++; - } - - peg$posDetailsCache[pos] = details; - - return details; - } - } - - function peg$computeLocation(startPos, endPos) { - var startPosDetails = peg$computePosDetails(startPos); - var endPosDetails = peg$computePosDetails(endPos); - - return { - source: peg$source, - start: { - offset: startPos, - line: startPosDetails.line, - column: startPosDetails.column - }, - end: { - offset: endPos, - line: endPosDetails.line, - column: endPosDetails.column - } - }; - } - - function peg$fail(expected) { - if (peg$currPos < peg$maxFailPos) { return; } - - if (peg$currPos > peg$maxFailPos) { - peg$maxFailPos = peg$currPos; - peg$maxFailExpected = []; - } - - peg$maxFailExpected.push(expected); - } - - function peg$buildSimpleError(message, location) { - return new peg$SyntaxError(message, null, null, location); - } - - function peg$buildStructuredError(expected, found, location) { - return new peg$SyntaxError( - peg$SyntaxError.buildMessage(expected, found), - expected, - found, - location - ); - } - - function peg$parsefilterQuery() { - var s0, s1, s2, s3; - - s0 = peg$currPos; - s1 = peg$parse_(); - s2 = peg$parseorExpr(); - if (s2 !== peg$FAILED) { - s3 = peg$parse_(); - peg$savedPos = s0; - s0 = peg$f0(s2); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parse_(); - peg$savedPos = s0; - s1 = peg$f1(); - s0 = s1; - } - - return s0; - } - - function peg$parseorExpr() { - var s0, s1, s2, s3, s4, s5; - - s0 = peg$currPos; - s1 = peg$parseandExpr(); - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - s3 = peg$parseOrOp(); - if (s3 !== peg$FAILED) { - s4 = peg$parse_(); - s5 = peg$parseorExpr(); - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f2(s1, s5); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parseandExpr(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f0(s1); - } - s0 = s1; - } - - return s0; - } - - function peg$parseandExpr() { - var s0, s1, s2, s3, s4, s5; - - s0 = peg$currPos; - s1 = peg$parsenotExpr(); - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - s3 = peg$parseAndOp(); - if (s3 !== peg$FAILED) { - s4 = peg$parse_(); - s5 = peg$parseandExpr(); - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f3(s1, s5); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsenotExpr(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f0(s1); - } - s0 = s1; - } - - return s0; - } - - function peg$parsenotExpr() { - var s0, s1, s2, s3; - - s0 = peg$currPos; - s1 = peg$parseNotOp(); - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - s3 = peg$parsenotExpr(); - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f4(s3); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parseboolExpr(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f0(s1); - } - s0 = s1; - } - - return s0; - } - - function peg$parseboolExpr() { - var s0, s1, s2, s3, s4, s5; - - s0 = peg$currPos; - s1 = peg$parseproject(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f0(s1); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsecontext(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f0(s1); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 40) { - s1 = peg$c0; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e0); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - s3 = peg$parseorExpr(); - if (s3 !== peg$FAILED) { - s4 = peg$parse_(); - if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c1; - peg$currPos++; - } else { - s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e1); } - } - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f0(s3); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsecomparison(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f0(s1); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 8) === peg$c2) { - s1 = peg$c2; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e2); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f5(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parseStringLiteral(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f6(s1); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parseRegexLiteral(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f7(s1); - } - s0 = s1; - } - } - } - } - } - } - - return s0; - } - - function peg$parseproject() { - var s0, s1, s2; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 43) { - s1 = peg$c3; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e3); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parsename(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f8(s2); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 43) { - s1 = peg$c3; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e3); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f9(); - } - s0 = s1; - } - - return s0; - } - - function peg$parsecontext() { - var s0, s1, s2; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 64) { - s1 = peg$c4; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e4); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parsename(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f10(s2); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 64) { - s1 = peg$c4; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e4); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f11(); - } - s0 = s1; - } - - return s0; - } - - function peg$parseOrOp() { - var s0; - - if (input.substr(peg$currPos, 2) === peg$c5) { - s0 = peg$c5; - peg$currPos += 2; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e5); } - } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 2).toLowerCase() === peg$c6) { - s0 = input.substr(peg$currPos, 2); - peg$currPos += 2; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e6); } - } - } - - return s0; - } - - function peg$parseAndOp() { - var s0; - - if (input.substr(peg$currPos, 2) === peg$c7) { - s0 = peg$c7; - peg$currPos += 2; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e7); } - } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 3).toLowerCase() === peg$c8) { - s0 = input.substr(peg$currPos, 3); - peg$currPos += 3; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e8); } - } - } - - return s0; - } - - function peg$parseNotOp() { - var s0; - - if (input.charCodeAt(peg$currPos) === 33) { - s0 = peg$c9; - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e9); } - } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 3).toLowerCase() === peg$c10) { - s0 = input.substr(peg$currPos, 3); - peg$currPos += 3; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e10); } - } - } - - return s0; - } - - function peg$parsecomparison() { - var s0, s1; - - s0 = peg$currPos; - s1 = peg$parsepriorityComparison(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f0(s1); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsedueComparison(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f0(s1); - } - s0 = s1; - } - - return s0; - } - - function peg$parsepriorityComparison() { - var s0, s1, s2, s3, s4, s5; - - s0 = peg$currPos; - s1 = peg$parsepriorityKeyword(); - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - s3 = peg$parsecompareOp(); - if (s3 !== peg$FAILED) { - s4 = peg$parse_(); - s5 = peg$parsepriorityLiteral(); - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f12(s3, s5); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsepriorityKeyword(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f13(); - } - s0 = s1; - } - - return s0; - } - - function peg$parsepriorityLiteral() { - var s0, s1; - - s0 = peg$currPos; - if (peg$r0.test(input.charAt(peg$currPos))) { - s1 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e11); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f14(); - } - s0 = s1; - - return s0; - } - - function peg$parsepriorityKeyword() { - var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10; - - s0 = peg$currPos; - if (input.substr(peg$currPos, 3) === peg$c11) { - s1 = peg$c11; - peg$currPos += 3; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e12); } - } - if (s1 !== peg$FAILED) { - s2 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 111) { - s3 = peg$c12; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e13); } - } - if (s3 !== peg$FAILED) { - s4 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 114) { - s5 = peg$c13; - peg$currPos++; - } else { - s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e14); } - } - if (s5 !== peg$FAILED) { - s6 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 105) { - s7 = peg$c14; - peg$currPos++; - } else { - s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e15); } - } - if (s7 !== peg$FAILED) { - s8 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 116) { - s9 = peg$c15; - peg$currPos++; - } else { - s9 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e16); } - } - if (s9 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 121) { - s10 = peg$c16; - peg$currPos++; - } else { - s10 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e17); } - } - if (s10 === peg$FAILED) { - s10 = null; - } - s9 = [s9, s10]; - s8 = s9; - } else { - peg$currPos = s8; - s8 = peg$FAILED; - } - if (s8 === peg$FAILED) { - s8 = null; - } - s7 = [s7, s8]; - s6 = s7; - } else { - peg$currPos = s6; - s6 = peg$FAILED; - } - if (s6 === peg$FAILED) { - s6 = null; - } - s5 = [s5, s6]; - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - if (s4 === peg$FAILED) { - s4 = null; - } - s3 = [s3, s4]; - s2 = s3; - } else { - peg$currPos = s2; - s2 = peg$FAILED; - } - if (s2 === peg$FAILED) { - s2 = null; - } - s1 = [s1, s2]; - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - return s0; - } - - function peg$parsedueComparison() { - var s0, s1, s2, s3, s4, s5; - - s0 = peg$currPos; - if (input.substr(peg$currPos, 3) === peg$c17) { - s1 = peg$c17; - peg$currPos += 3; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e18); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - s3 = peg$parsecompareOp(); - if (s3 !== peg$FAILED) { - s4 = peg$parse_(); - s5 = peg$parsedateExpr(); - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f15(s3, s5); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 3) === peg$c17) { - s1 = peg$c17; - peg$currPos += 3; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e18); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f16(); - } - s0 = s1; - } - - return s0; - } - - function peg$parsedateExpr() { - var s0, s1, s2, s3, s4, s5, s6; - - s0 = peg$currPos; - s1 = peg$parsedateLiteral(); - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - s3 = peg$parsedateOp(); - if (s3 !== peg$FAILED) { - s4 = peg$parse_(); - s5 = peg$parsenumber(); - if (s5 !== peg$FAILED) { - if (peg$r1.test(input.charAt(peg$currPos))) { - s6 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e19); } - } - if (s6 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f17(s1, s3, s5, s6); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsedateLiteral(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f0(s1); - } - s0 = s1; - } - - return s0; - } - - function peg$parsedateOp() { - var s0, s1; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 43) { - s1 = peg$c3; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e3); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f14(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 45) { - s1 = peg$c18; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e20); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f14(); - } - s0 = s1; - } - - return s0; - } - - function peg$parsecompareOp() { - var s0, s1; - - s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c19) { - s1 = peg$c19; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e21); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f14(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c20) { - s1 = peg$c20; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e22); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f14(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c21) { - s1 = peg$c21; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f14(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c22) { - s1 = peg$c22; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e24); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f14(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c23; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e25); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f14(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c24; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f14(); - } - s0 = s1; - } - } - } - } - } - - return s0; - } - - function peg$parsedateLiteral() { - var s0, s1, s2, s3, s4, s5; - - s0 = peg$currPos; - s1 = peg$parsenumber4(); - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 45) { - s2 = peg$c18; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e20); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsenumber2(); - if (s3 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 45) { - s4 = peg$c18; - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e20); } - } - if (s4 !== peg$FAILED) { - s5 = peg$parsenumber2(); - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f18(s1, s3, s5); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c25) { - s1 = peg$c25; - peg$currPos += 5; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e27); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f19(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 8) === peg$c26) { - s1 = peg$c26; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f20(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 9) === peg$c27) { - s1 = peg$c27; - peg$currPos += 9; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e29); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f21(); - } - s0 = s1; - } - } - } - - return s0; - } - - function peg$parsenumber4() { - var s0, s1, s2, s3, s4; - - s0 = peg$currPos; - if (peg$r2.test(input.charAt(peg$currPos))) { - s1 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } - } - if (s1 !== peg$FAILED) { - if (peg$r2.test(input.charAt(peg$currPos))) { - s2 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } - } - if (s2 !== peg$FAILED) { - if (peg$r2.test(input.charAt(peg$currPos))) { - s3 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } - } - if (s3 !== peg$FAILED) { - if (peg$r2.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } - } - if (s4 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f14(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - return s0; - } - - function peg$parsenumber2() { - var s0, s1, s2; - - s0 = peg$currPos; - if (peg$r2.test(input.charAt(peg$currPos))) { - s1 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } - } - if (s1 !== peg$FAILED) { - if (peg$r2.test(input.charAt(peg$currPos))) { - s2 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } - } - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f14(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - return s0; - } - - function peg$parsenumber() { - var s0, s1, s2; - - s0 = peg$currPos; - s1 = []; - if (peg$r2.test(input.charAt(peg$currPos))) { - s2 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } - } - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - if (peg$r2.test(input.charAt(peg$currPos))) { - s2 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } - } - } - } else { - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f14(); - } - s0 = s1; - - return s0; - } - - function peg$parseStringLiteral() { - var s0, s1, s2, s3; - - peg$silentFails++; - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 34) { - s1 = peg$c28; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } - } - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parseDoubleStringCharacter(); - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parseDoubleStringCharacter(); - } - if (input.charCodeAt(peg$currPos) === 34) { - s3 = peg$c28; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } - } - if (s3 === peg$FAILED) { - s3 = null; - } - peg$savedPos = s0; - s0 = peg$f22(s2); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 39) { - s1 = peg$c29; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } - } - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parseSingleStringCharacter(); - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parseSingleStringCharacter(); - } - if (input.charCodeAt(peg$currPos) === 39) { - s3 = peg$c29; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } - } - if (s3 === peg$FAILED) { - s3 = null; - } - peg$savedPos = s0; - s0 = peg$f22(s2); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - peg$silentFails--; - if (s0 === peg$FAILED) { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e31); } - } - - return s0; - } - - function peg$parseDoubleStringCharacter() { - var s0, s1, s2; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 92) { - s1 = peg$c30; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } - } - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 34) { - s2 = peg$c28; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } - } - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f23(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$currPos; - peg$silentFails++; - if (input.charCodeAt(peg$currPos) === 34) { - s2 = peg$c28; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } - } - peg$silentFails--; - if (s2 === peg$FAILED) { - s1 = undefined; - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - s2 = peg$parseSourceCharacter(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f14(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - - return s0; - } - - function peg$parseSingleStringCharacter() { - var s0, s1, s2; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 92) { - s1 = peg$c30; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } - } - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 39) { - s2 = peg$c29; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } - } - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f24(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$currPos; - peg$silentFails++; - if (input.charCodeAt(peg$currPos) === 39) { - s2 = peg$c29; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } - } - peg$silentFails--; - if (s2 === peg$FAILED) { - s1 = undefined; - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - s2 = peg$parseSourceCharacter(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f14(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - - return s0; - } - - function peg$parseRegexLiteral() { - var s0, s1, s2, s3, s4; - - peg$silentFails++; - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 47) { - s1 = peg$c31; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } - } - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parseRegexCharacter(); - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parseRegexCharacter(); - } - if (input.charCodeAt(peg$currPos) === 47) { - s3 = peg$c31; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } - } - if (s3 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 105) { - s4 = peg$c14; - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e15); } - } - if (s4 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f25(s2); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 47) { - s1 = peg$c31; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } - } - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parseRegexCharacter(); - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parseRegexCharacter(); - } - if (input.charCodeAt(peg$currPos) === 47) { - s3 = peg$c31; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } - } - if (s3 === peg$FAILED) { - s3 = null; - } - peg$savedPos = s0; - s0 = peg$f26(s2); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - peg$silentFails--; - if (s0 === peg$FAILED) { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } - } - - return s0; - } - - function peg$parseRegexCharacter() { - var s0, s1, s2; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 92) { - s1 = peg$c30; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } - } - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 47) { - s2 = peg$c31; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } - } - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f27(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$currPos; - peg$silentFails++; - if (input.charCodeAt(peg$currPos) === 47) { - s2 = peg$c31; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } - } - peg$silentFails--; - if (s2 === peg$FAILED) { - s1 = undefined; - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - s2 = peg$parseSourceCharacter(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f14(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - - return s0; - } - - function peg$parseSourceCharacter() { - var s0; - - if (input.length > peg$currPos) { - s0 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e37); } - } - - return s0; - } - - function peg$parsename() { - var s0, s1, s2, s3; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 34) { - s1 = peg$c28; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } - } - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parsenonblank(); - if (s3 !== peg$FAILED) { - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parsenonblank(); - } - } else { - s2 = peg$FAILED; - } - if (s2 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 34) { - s3 = peg$c28; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f14(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = []; - s2 = peg$parsenonblank(); - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parsenonblank(); - } - } else { - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 34) { - s2 = peg$c28; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } - } - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f28(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = []; - s2 = peg$parsenonblank(); - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parsenonblank(); - } - } else { - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f14(); - } - s0 = s1; - } - } - - return s0; - } - - function peg$parsenonblank() { - var s0; - - if (peg$r3.test(input.charAt(peg$currPos))) { - s0 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } - } - - return s0; - } - - function peg$parse_() { - var s0, s1; - - peg$silentFails++; - s0 = []; - if (peg$r4.test(input.charAt(peg$currPos))) { - s1 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } - } - while (s1 !== peg$FAILED) { - s0.push(s1); - if (peg$r4.test(input.charAt(peg$currPos))) { - s1 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } - } - } - peg$silentFails--; - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } - - return s0; - } - - peg$result = peg$startRuleFunction(); - - if (peg$result !== peg$FAILED && peg$currPos === input.length) { - return peg$result; - } else { - if (peg$result !== peg$FAILED && peg$currPos < input.length) { - peg$fail(peg$endExpectation()); - } - - throw peg$buildStructuredError( - peg$maxFailExpected, - peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, - peg$maxFailPos < input.length - ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) - : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) - ); - } -} - -export { - peg$SyntaxError as SyntaxError, - peg$parse as parse -}; diff --git a/src/js/filterlang.pegjs b/src/js/filterlang.pegjs index 3ec72e24..b12b6868 100644 --- a/src/js/filterlang.pegjs +++ b/src/js/filterlang.pegjs @@ -50,6 +50,7 @@ NotOp comparison = left:priorityComparison { return left; } / left:dueComparison { return left; } + / left:thresholdComparison { return left; } priorityComparison = priorityKeyword _ op:compareOp _ right:priorityLiteral { return ["pri", right, op]; } @@ -67,8 +68,17 @@ dueComparison / "due:" right:dateStr { return ["duestr", right]; } / "due" { return ["due"]; } +thresholdComparison + = "t" _ op:compareOp _ right:dateExpr { return ["threshold"].concat(right, [op]); } + / "t:" right:dateStr { return ["tstr", right]; } + / "t" { return ["threshold"]; } + dateExpr = left:dateLiteral _ op:dateOp _ count:number unit:[dbwmy] { + if (count.length == 0) { + /* empty count string means default "1" value */ + count = 1; + } if (op == "-") { count = count * -1; } @@ -99,19 +109,19 @@ dateStr dateLiteral = year:number4 "-" month: number2 "-" day:number2 { - let d = new Date(year, month-1, day); - return d.getTime(); + let m = month > 0 ? (month <= 12 ? month-1 : 11) : 0; + let d = day > 0 ? (day <= 31 ? day : 31) : 1; /* ignores lengths of months */ + return new Date(year, m, d).getTime(); } / year:number4 "-" month: number2 { - let d = new Date(year, month-1, 1); - return d.getTime(); + let m = month > 0 ? (month <= 12 ? month-1 : 11) : 0; + return new Date(year, m, 1).getTime(); } / year:number4 { - let d = new Date(year, 0, 1); - return d.getTime(); + return new Date(year, 0, 1).getTime(); } / "today" { - let d = new Date(); // now, w current time of day + let d = new Date(); // now, w current time of day d = new Date(d.getFullYear(), d.getMonth(), d.getDate()); return d.getTime(); } @@ -130,10 +140,10 @@ number4 = [0-9][0-9][0-9][0-9] { return text(); } number2 - = [0-9][0-9] { return text(); } + = [0-9][0-9]? { return text(); } number - = [0-9]+ { return text(); } + = [0-9]* { return text(); } /* used in date intervals only */ StringLiteral "string" = '"' chars:DoubleStringCharacter* '"'? { @@ -167,9 +177,9 @@ SourceCharacter = . name - = '"' nonblank+ '"' { return text(); } - / nonblankparen+ '"' { return '"' + text(); } - / nonblankparen+ { return text(); } + = '"' nonblank+ '"' { return text(); } + / nonblankparen+ '"' { return '"' + text(); } + / nonblankparen+ { return text(); } nonblank = [^ \t\n\r"] @@ -178,4 +188,4 @@ nonblankparen = [^ \t\n\r"()] _ "whitespace" - = [ \t\n\r]* + = [ \t\n\r]* diff --git a/src/js/filterquery.mjs b/src/js/filterquery.mjs index d31d1e48..3633bd85 100644 --- a/src/js/filterquery.mjs +++ b/src/js/filterquery.mjs @@ -41,6 +41,29 @@ function runQuery(item, compiledQuery) { stack.push(false); // no due date } break; + case "threshold": + if (item.t) { + // normalize date to have time of midnight in local zone + // we represent dates as millisec from epoch to simplify comparison + let d = item.t; + stack.push(new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime()); + } else { + stack.push(undefined); // all comparisons will return false + } + break; + case "tstr": + // match next value (a string) as prefix of ISO date string of threshold date + next = q.shift(); // the string to compare + if (item.t) { + // normalize date to have time of midnight in local zone + // we represent dates as millisec from epoch to simplify comparison + let d = item.t; + d = new Date(d.getFullYear(), d.getMonth(), d.getDate()); + stack.push(d.toISOString().slice(0, 10).startsWith(next)); + } else { + stack.push(false); // no threshold date + } + break; case "complete": stack.push(item.complete); break; diff --git a/src/js/form.mjs b/src/js/form.mjs index 2baa6a8e..57538040 100644 --- a/src/js/form.mjs +++ b/src/js/form.mjs @@ -2,7 +2,7 @@ import "../../node_modules/jstodotxt/jsTodoExtensions.js"; import { resetModal, handleError, userData, setUserData, translations, getConfirmation } from "../render.js"; import { _paq } from "./matomo.mjs"; -import { RecExtension, SugarDueExtension } from "./todotxtExtensions.mjs"; +import { RecExtension, SugarDueExtension, ThresholdExtension } from "./todotxtExtensions.mjs"; import { generateFilterData } from "./filters.mjs"; import { items, item, setTodoComplete } from "./todos.mjs"; import { datePickerInput } from "./datePicker.mjs"; @@ -303,7 +303,7 @@ function show(todo, templated) { if(todo) { // replace invisible multiline ascii character with new line // we need to check if there already is a due date in the object - todo = new TodoTxtItem(todo, [ new DueExtension(), new RecExtension() ]); + todo = new TodoTxtItem(todo, [ new DueExtension(), new HiddenExtension(), new RecExtension(), new ThresholdExtension() ]); // set the priority setPriority(todo.priority); // @@ -393,7 +393,7 @@ function submitForm() { const index = items.objects.map(function(item) {return item.toString(); }).indexOf(modalForm.getAttribute("data-item")); // create a todo.txt object // replace new lines with spaces (https://stackoverflow.com/a/34936253) - let todo = new TodoTxtItem(document.getElementById("modalFormInput").value.replaceAll(/[\r\n]+/g, String.fromCharCode(16)), [ new SugarDueExtension(), new HiddenExtension(), new RecExtension() ]); + let todo = new TodoTxtItem(document.getElementById("modalFormInput").value.replaceAll(/[\r\n]+/g, String.fromCharCode(16)), [ new SugarDueExtension(), new HiddenExtension(), new RecExtension(), new ThresholdExtension() ]); // check and prevent duplicate todo if(items.objects.map(function(item) {return item.toString(); }).indexOf(todo.toString())!=-1) { modalFormAlert.innerHTML = translations.formInfoDuplicate; @@ -413,7 +413,7 @@ function submitForm() { } else if(!modalForm.getAttribute("data-item") && document.getElementById("modalFormInput").value!="") { // in case there hasn't been a passed data item, we just push the input value as a new item into the array // replace new lines with spaces (https://stackoverflow.com/a/34936253) - let todo = new TodoTxtItem(document.getElementById("modalFormInput").value.replaceAll(/[\r\n]+/g, String.fromCharCode(16)), [ new SugarDueExtension(), new HiddenExtension(), new RecExtension() ]); + let todo = new TodoTxtItem(document.getElementById("modalFormInput").value.replaceAll(/[\r\n]+/g, String.fromCharCode(16)), [ new SugarDueExtension(), new HiddenExtension(), new RecExtension(), new ThresholdExtension() ]); // we add the current date to the start date attribute of the todo.txt object todo.date = new Date(); // check and prevent duplicate todo diff --git a/src/js/recurrences.mjs b/src/js/recurrences.mjs index 5af55194..6326561e 100644 --- a/src/js/recurrences.mjs +++ b/src/js/recurrences.mjs @@ -34,13 +34,48 @@ function generateRecurrence(todo) { try { // duplicate not reference let recurringTodo = Object.assign({}, todo); + recurringTodo.date = new Date; + + // if the item to be duplicated has been completed before the due date, the recurring item needs to be set incomplete again recurringTodo.complete = false; recurringTodo.completed = null; - // if the item to be duplicated has been completed before the due date, the recurring item needs to be set incomplete again - recurringTodo.date = new Date; - // if todo has no due date, the recurrence time frame will be added to the date of completion - recurringTodo.due = getDueDate(todo.due, todo.rec); - recurringTodo.dueString = convertDate(recurringTodo.due); + + // adjust due and threshold dates + let recSplit = splitRecurrence(todo.rec); + if (recSplit.plus) { + // strict recurrence is based on previous date value + if (todo.t) + recurringTodo.t = addIntervalToDate(todo.t, recSplit.mul, recSplit.period); + if (todo.due) + recurringTodo.due = addIntervalToDate(todo.due, recSplit.mul, recSplit.period); + } else { + // non-strict recurrence is based on today's date + if (todo.t) { + let threshold_base = new Date(); + if (todo.due) { + // preserve interval between threshold and due date + let interval = todo.due - todo.t; // millisec + threshold_base = new Date(threshold_base.getTime() - interval); + } + recurringTodo.t = addIntervalToDate(threshold_base, recSplit.mul, recSplit.period); + console.log("t based on today plus rec: " + recurringTodo + " todo.t is " + recurringTodo.t); + } + if (todo.due) + recurringTodo.due = addIntervalToDate(new Date(), recSplit.mul, recSplit.period); + } + if (!todo.t && !todo.due) { + // This is an ambiguous case: there is a rec: tag but no dates to apply it to. + // Some would prefer to make this a no-op, but past versions of sleek have added + // a due date when there is only a recurrence, so we will continue to do that here. + recurringTodo.due = addIntervalToDate(new Date(), recSplit.mul, recSplit.period); + } + // the following strings are magic from jsTodoTxt and must be changed when dates are changed + // because TodoTxtItem.toString() relies on the fieldString values, not the field values themselves. + if (recurringTodo.t) + recurringTodo.tString = convertDate(recurringTodo.t); + if (recurringTodo.due) + recurringTodo.dueString = convertDate(recurringTodo.due); + // get index of recurring todo const index = items.objects.map(function(item) {return item.toString().replaceAll(String.fromCharCode(16)," "); }).indexOf(recurringTodo.toString().replaceAll(String.fromCharCode(16)," ")); // only add recurring todo if it is not already in the list @@ -57,15 +92,6 @@ function generateRecurrence(todo) { return Promise.reject(error); } } -function getDueDate(due, recurrence) { - let recSplit = splitRecurrence(recurrence); - if (!recSplit.plus || !due) { - // no plus in recurrence expression, so do the default "non-strict" recurrence. - // (Otherwise we will use the previous due date, for strict recurrence.) - due = new Date(); // use today's date as base for recurrence - } - return addIntervalToDate(due, recSplit.mul, recSplit.period); -} // addIntervalToDate used to compute recurrences, but now also used to add // or subtract a time interval to/from dates in filter query language. diff --git a/src/js/todos.mjs b/src/js/todos.mjs index 18fc0b80..f37d6bd3 100644 --- a/src/js/todos.mjs +++ b/src/js/todos.mjs @@ -6,7 +6,7 @@ import { categories } from "./filters.mjs"; import { generateRecurrence } from "./recurrences.mjs"; import { convertDate, isToday, isTomorrow, isPast } from "./date.mjs"; import { show } from "./form.mjs"; -import { SugarDueExtension, RecExtension } from "./todotxtExtensions.mjs"; +import { SugarDueExtension, RecExtension, ThresholdExtension } from "./todotxtExtensions.mjs"; const modalForm = document.getElementById("modalForm"); const todoContext = document.getElementById("todoContext"); @@ -99,7 +99,7 @@ function configureTodoTableTemplate(append) { } function generateItems(content) { try { - items = { objects: TodoTxt.parse(content, [ new DueExtension(), new HiddenExtension(), new RecExtension() ]) } + items = { objects: TodoTxt.parse(content, [ new DueExtension(), new HiddenExtension(), new RecExtension(), new ThresholdExtension() ]) } items.objects = items.objects.filter(function(item) { if(!item.text) return false; return true; @@ -429,7 +429,7 @@ function sortTodoData(group) { function setTodoComplete(todo) { try { // first convert the string to a todo.txt object - todo = new TodoTxtItem(todo, [ new DueExtension(), new HiddenExtension(), new RecExtension() ]); + todo = new TodoTxtItem(todo, [ new DueExtension(), new HiddenExtension(), new RecExtension(), new ThresholdExtension() ]); // get index of todo const index = items.objects.map(function(item) {return item.toString(); }).indexOf(todo.toString()); // mark item as in progress @@ -472,7 +472,7 @@ function setTodoDelete(todo) { // in case edit form is open, text has changed and complete button is pressed, we do not fall back to the initial value of todo but instead choose input value if(document.getElementById("modalFormInput").value) todo = document.getElementById("modalFormInput").value; // first convert the string to a todo.txt object - todo = new TodoTxtItem(todo, [ new DueExtension(), new HiddenExtension(), new RecExtension() ]); + todo = new TodoTxtItem(todo, [ new DueExtension(), new HiddenExtension(), new RecExtension(), new ThresholdExtension() ]); // get index of todo const index = items.objects.map(function(item) {return item.toString(); }).indexOf(todo.toString()); // Delete item @@ -498,7 +498,7 @@ function setTodoDelete(todo) { } function addTodo(todo) { try { - todo = new TodoTxtItem(todo, [ new SugarDueExtension(), new HiddenExtension(), new RecExtension() ]); + todo = new TodoTxtItem(todo, [ new SugarDueExtension(), new HiddenExtension(), new RecExtension(), new ThresholdExtension() ]); // abort if there is no text if(!todo.text) return Promise.resolve("Info: Text is missing, no todo is written"); // we add the current date to the start date attribute of the todo.txt object diff --git a/src/js/todotxtExtensions.mjs b/src/js/todotxtExtensions.mjs index 2eb0185c..920db86e 100644 --- a/src/js/todotxtExtensions.mjs +++ b/src/js/todotxtExtensions.mjs @@ -33,7 +33,7 @@ SugarDueExtension.prototype.parsingFunction = function (line) { // Try to parse a valid date until the end of the text for (var i = Math.max(5, words.length); i > 0; i--) { match = words.slice(0, i).join(" "); - dueDate = Sugar.Date.create(match); + dueDate = Sugar.Date.create(match, {future: true}); if (Sugar.Date.isValid(dueDate)) { return [dueDate, line.replace("due:" + match, ''), Sugar.Date.format(dueDate, '%Y-%m-%d')]; } @@ -42,4 +42,20 @@ SugarDueExtension.prototype.parsingFunction = function (line) { return [null, null, null]; }; -export { RecExtension, SugarDueExtension }; +function ThresholdExtension() { + this.name = "t"; +} +ThresholdExtension.prototype = new TodoTxtExtension(); +ThresholdExtension.prototype.parsingFunction = function (line) { + var thresholdDate = null; + var thresholdRegex = /t:([0-9]{4}-[0-9]{1,2}-[0-9]{1,2})\s*/; + var matchThreshold = thresholdRegex.exec(line); + if ( matchThreshold !== null ) { + var datePieces = matchThreshold[1].split('-'); + thresholdDate = new Date( datePieces[0], datePieces[1] - 1, datePieces[2] ); + return [thresholdDate, line.replace(thresholdRegex, ''), matchThreshold[1]]; + } + return [null, null, null]; +}; + +export { RecExtension, SugarDueExtension, ThresholdExtension }; diff --git a/src/main.js b/src/main.js index d9e4491e..38fd6e61 100755 --- a/src/main.js +++ b/src/main.js @@ -174,6 +174,9 @@ const createWindow = async function() { if(process.env.SLEEK_CUSTOM_FILE && fs.existsSync(process.env.SLEEK_CUSTOM_FILE)) { file = process.env.SLEEK_CUSTOM_FILE; } + if(process.argv.length > 1 && fs.existsSync(process.argv[1])) { + file = process.argv[1]; + } // use the loop to check if the new path is already in the user data let fileFound = false; if(userData.data.files) {