Commit 04165438 authored by ransome1's avatar ransome1
Browse files

Merge branch 'develop'

parents 28f89e91 01ee0950
...@@ -12,14 +12,12 @@ snap/local/ ...@@ -12,14 +12,12 @@ snap/local/
*.db:encryptable *.db:encryptable
*.db *.db
System Volume Information/ System Volume Information/
build/
Thumbs.db Thumbs.db
flatpak/generated-sources.json flatpak/generated-sources.json
flatpak/com.github.ransome1.sleek.yml flatpak/com.github.ransome1.sleek.yml
assets/icons/bak assets/icons/bak
squashfs-root/ squashfs-root/
.eslintrc.json .eslintrc.json
build/
package-lock.json package-lock.json
.vs/ .vs/
.vscode/ .vscode/
......
{ {
"name": "sleek", "name": "sleek",
"productName": "sleek", "productName": "sleek",
"version": "1.0.7", "version": "1.0.8",
"description": "Todo app based on todo.txt for Linux, Windows and MacOS, free and open-source", "description": "Todo app based on todo.txt for Linux, Windows and MacOS, free and open-source",
"synopsis": "Todo app based on todo.txt for Linux, Windows and MacOS, free and open-source", "synopsis": "Todo app based on todo.txt for Linux, Windows and MacOS, free and open-source",
"category": "ProjectManagement", "category": "ProjectManagement",
...@@ -92,18 +92,17 @@ ...@@ -92,18 +92,17 @@
"artifactName": "${productName}-${version}-${arch}.${ext}" "artifactName": "${productName}-${version}-${arch}.${ext}"
}, },
"scripts": { "scripts": {
"build:windows": "yarn build:css && electron-builder -w --publish never", "build:windows": "yarn build:css && yarn build:pegjs && electron-builder -w --publish never",
"build:macos": "yarn build:css && electron-builder -m --publish never", "build:macos": "yarn build:css && yarn build:pegjs && electron-builder -m --publish never",
"build:linux": "yarn build:css && electron-builder -l --publish never", "build:linux": "yarn build:css && yarn build:pegjs && electron-builder -l --publish never",
"build:appx": "electron-builder -w appx --publish never", "build:appx": "yarn build:css && yarn build:pegjs && electron-builder -w appx --publish never",
"build:pacman": "electron-builder -l pacman --publish never",
"build:appimage": "yarn build:css && yarn build:pegjs && electron-builder -l AppImage --publish never", "build:appimage": "yarn build:css && yarn build:pegjs && electron-builder -l AppImage --publish never",
"pack": "electron-builder --dir",
"lint": "eslint --ext .js, src --ext .mjs, src",
"test": "mocha --timeout 10000",
"test1": "mocha ./test/onboarding.js --timeout 10000",
"build:css": "sass src/scss/style.scss:src/css/style.css", "build:css": "sass src/scss/style.scss:src/css/style.css",
"build:pegjs": "peggy --format es --output src/js/filterlang.mjs src/js/filterlang.pegjs", "build:pegjs": "peggy --format es --output src/js/filterlang.mjs src/js/filterlang.pegjs",
"pack": "yarn build:css && yarn build:pegjs && electron-builder --dir",
"lint": "eslint --ext .js, src --ext .mjs, src",
"test": "mocha --timeout 10000",
"test1": "mocha ./test/createTodos.js --timeout 10000",
"sass": "sass -w src/scss/style.scss:src/css/style.css", "sass": "sass -w src/scss/style.scss:src/css/style.css",
"start": "yarn sass & electron ." "start": "yarn sass & electron ."
}, },
......
name: sleek name: sleek
base: core18 base: core18
version: '1.0.8'
summary: Todo app based on the todo.txt format for Linux, free and open-source summary: Todo app based on the todo.txt format for Linux, free and open-source
description: | description: |
sleek is an open-source todo app that makes use of the todo.txt format. sleeks GUI is modern and simple but still offers a decent set of functions which help users getting things done. sleek is available as a client for Windows, MacOS and Linux. sleek is an open-source todo app that makes use of the todo.txt format. sleeks GUI is modern and simple but still offers a decent set of functions which help users getting things done. sleek is available as a client for Windows, MacOS and Linux.
...@@ -55,10 +56,6 @@ parts: ...@@ -55,10 +56,6 @@ parts:
--prune=true --out $SNAPCRAFT_PART_INSTALL/ --prune=true --out $SNAPCRAFT_PART_INSTALL/
mv $SNAPCRAFT_PART_INSTALL/$SNAPCRAFT_PROJECT_NAME-linux-* \ mv $SNAPCRAFT_PART_INSTALL/$SNAPCRAFT_PROJECT_NAME-linux-* \
$SNAPCRAFT_PART_INSTALL/sleek $SNAPCRAFT_PART_INSTALL/sleek
VER=$(npm show sleek version)
echo "VERSION $(npm show sleek version)"
snapcraftctl set-version $VER
stage-packages: stage-packages:
- libnss3 - libnss3
cleanup: cleanup:
......
export function createModalJail(modal) { export function createModalJail(modal) {
// add all the elements inside modal which you want to make focusable // add all the elements inside modal which you want to make focusable
const focusableElements = 'a.button, [tabindex]:not([tabindex="-1"])'; const focusableElements = '[tabindex]:not([tabindex="-1"])';
const firstFocusableElement = modal.querySelectorAll(focusableElements)[0]; // get first element to be focused inside modal const firstFocusableElement = modal.querySelectorAll(focusableElements)[0]; // get first element to be focused inside modal
const focusableContent = modal.querySelectorAll(focusableElements); const focusableContent = modal.querySelectorAll(focusableElements);
const lastFocusableElement = focusableContent[focusableContent.length - 1]; // get last element to be focused inside modal const lastFocusableElement = focusableContent[focusableContent.length - 1]; // get last element to be focused inside modal
......
This diff is collapsed.
This diff is collapsed.
...@@ -24,21 +24,20 @@ ...@@ -24,21 +24,20 @@
<nav> <nav>
<ul> <ul>
<li class="logo">sleek</li> <li class="logo">sleek</li>
<li id="navBtnAddTodo" tabindex="0"><i class="fas fa-plus"></i></li> <li><a href="#" id="navBtnAddTodo" tabindex="0"><i class="fas fa-plus"></i></a></li>
<li id="navBtnFilter" class="drawerTrigger" data-drawer="filterDrawer" tabindex="0"><i class="fas fa-filter"></i></li> <li><a href="#" id="navBtnFilter" class="drawerTrigger" data-drawer="filterDrawer" tabindex="0"><i class="fas fa-filter"></i></a></li>
<li id="navBtnView" class="drawerTrigger" data-drawer="viewDrawer"tabindex="0"><i class="fas fa-sliders-h"></i></li> <li><a href="#" id="navBtnView" class="drawerTrigger" data-drawer="viewDrawer"tabindex="0"><i class="fas fa-sliders-h"></i></a></li>
<li id="btnOpenTodoFile" tabindex="-1"><i class="fas fa-folder-open"></i></li> <li><a href="#" id="btnOpenTodoFile" tabindex="0"><i class="fas fa-folder-open"></i></a></li>
<li id="btnTheme" tabindex="-1"><i class="fas fa-adjust"></i></li>
</ul> </ul>
<ul> <ul>
<li id="navBtnSettings" tabindex="-1"><i class="fas fa-cog"></i></li> <li><a href="#" id="navBtnSettings" tabindex="-1"><i class="fas fa-cog"></i></a></li>
<li id="navBtnHelp" tabindex="-1"><i class="fas fa-question-circle"></i></li> <li><a href="#" id="navBtnHelp" tabindex="-1"><i class="fas fa-question-circle"></i></a></li>
</ul> </ul>
<div id="drawerContainer"> <div id="drawerContainer">
<section id="filterDrawer" class="drawer dropdown" tabindex="0"> <section id="filterDrawer" class="drawer dropdown" tabindex="0">
<div class="container"> <div class="container">
<div id="todoFilters"></div> <div id="todoFilters"></div>
<button id="btnFiltersResetFilters" class="button btnResetFilters" tabindex="0"><i class="fas fa-ban"></i>&nbsp;<span></span></button> <button id="btnFiltersResetFilters" class="btnResetFilters" tabindex="0"><i class="fas fa-ban"></i>&nbsp;<span></span></button>
</div> </div>
</section> </section>
<section id="viewDrawer" class="drawer dropdown" tabindex="0"> <section id="viewDrawer" class="drawer dropdown" tabindex="0">
...@@ -178,7 +177,7 @@ ...@@ -178,7 +177,7 @@
</table> </table>
</div> </div>
</section> </section>
<a href="#" id="drawerClose" tabindex="0"><i class="fas fa-chevron-left"></i></a> <button id="drawerClose" tabindex="0"><i class="fas fa-chevron-left"></i></button>
<div id="handle"></div> <div id="handle"></div>
</div> </div>
</nav> </nav>
...@@ -187,24 +186,19 @@ ...@@ -187,24 +186,19 @@
<div id="todoTableWrapper" class="column content"> <div id="todoTableWrapper" class="column content">
<section id="todoTableSearchContainer" class="control has-icons-left"> <section id="todoTableSearchContainer" class="inputWrapper">
<div class="column"> <a href="https://github.com/ransome1/sleek/wiki/FIlter-Expressions-for-Advanced-Search" target="_blank" class="todoTableSearchQuestionmark"><i class="fas fa-question-circle"></i></a>
<input id="todoTableSearch" class="input is-medium" type="text" placeholder="Search" tabindex="10"> <i class="fas fa-search"></i>
<span class="icon is-left"> <label id="todoTableSearchLabel" for="todoTableSearch"></label>
<i class="fas fa-search"></i> <input id="todoTableSearch" class="input is-medium" type="search" tabindex="1" placeholder="(A) Todo text +project @context due:2020-12-12 rec:d">
</span> <button id="todoTableSearchAddTodo" class="tag" tabindex="5"><i class="fas fa-plus"></i>&nbsp;Add as todo</button>
</div> <section id="resultStats">
<span class="tag"></span>
</section>
</section> </section>
<div id="resultStats">
<span class="tag"></span>
</div>
<section id="todoTable" tabindex="-1">
<div id="todoTableContainer"></div> <section id="todoTable" tabindex="-1"></section>
</section>
<section id="onboardingContainer" class="contentContainer"> <section id="onboardingContainer" class="contentContainer">
<h1 id="welcomeToSleek" class="title is-1"></h1> <h1 id="welcomeToSleek" class="title is-1"></h1>
...@@ -225,7 +219,7 @@ ...@@ -225,7 +219,7 @@
<h1 id="addTodoContainerHeadline" class="title is-1"></h1> <h1 id="addTodoContainerHeadline" class="title is-1"></h1>
<p id="addTodoContainerSubtitle" class="subtitle"></p> <p id="addTodoContainerSubtitle" class="subtitle"></p>
<p class="file is-boxed is-centered"> <p class="file is-boxed is-centered">
<a href="#" id="btnAddTodoContainer" class="btnOnboarding"> <a href="#" id="btnAddTodoContainer" class="btnOnboarding" tabindex="0">
<i class="fas fa-plus"></i> <i class="fas fa-plus"></i>
<span id="addTodoContainerButton" class="file-label"></span> <span id="addTodoContainerButton" class="file-label"></span>
</a> </a>
...@@ -235,26 +229,23 @@ ...@@ -235,26 +229,23 @@
<section id="noResultContainer" class="contentContainer"> <section id="noResultContainer" class="contentContainer">
<h1 id="noResultContainerHeadline" class="title is-1"></h1> <h1 id="noResultContainerHeadline" class="title is-1"></h1>
<p id="noResultContainerSubtitle" class="subtitle"></p> <p id="noResultContainerSubtitle" class="subtitle"></p>
<p><button id="btnNoResultContainerResetFilters" class="btnResetFilters button" tabindex="0"><i class="fas fa-ban"></i>&nbsp;<span></span></button></p> <p><button id="btnNoResultContainerResetFilters" class="btnResetFilters" tabindex="0"><i class="fas fa-ban"></i>&nbsp;<span></span></button></p>
</section> </section>
</div> </div>
</div> </div>
<form id="modalForm" class="modal modalFormSubmit"> <section id="modalForm" class="modal">
<div class="modal-background"></div> <div class="modal-background"></div>
<div class="modal-content"> <div class="modal-content">
<div class="card"> <div class="card">
<header id="modalTitle" class="card-header-title"></header>
<div class="card-content"> <div class="card-content">
<div class="content"> <div class="inputWrapper">
<div class="control has-icons-right"> <label id="modalFormInputLabel" for="modalFormInput"></label>
<input id="modalFormInput" class="input is-medium" type="text" tabindex="0"> <input id="modalFormInput" class="input is-medium" type="text" tabindex="0" placeholder="(A) Todo text +project @context due:2020-12-12 rec:d">
<div id="autoCompleteContainer" class="card"></div> <a href="#" id="modalFormInputResize" class="icon is-right" tabindex="-1" data-input-type="input"><i class="fas fa-expand-alt"></i></a>
<a href="#" id="modalFormInputResize" class="icon is-right" tabindex="-1" data-input-type="input">
<i class="fas fa-expand-alt"></i>
</a>
</div> </div>
<section id="autoCompleteContainer" class="card"></section>
<article class="message"> <article class="message">
<div id="modalFormAlert" class="message-body"></div> <div id="modalFormAlert" class="message-body"></div>
</article> </article>
...@@ -342,21 +333,20 @@ ...@@ -342,21 +333,20 @@
</div> </div>
</div> </div>
<footer class="card-footer"> <footer class="card-footer">
<a href="#" class="card-footer-item selection" value="" id="recurrencePickerNoRecurrence" tabindex="0"></a> <a href="#" class="card-footer-item selection" id="recurrencePickerNoRecurrence" tabindex="0"></a>
</footer> </footer>
</div> </div>
</div> </div>
<br />
</div>
</div> </div>
<footer class="card-footer"> <footer class="card-footer">
<button id="btnSave" type="submit" class="card-footer-item" tabindex="0"></button> <button id="btnSave" class="card-footer-item" tabindex="0"></button>
<a href="#" id="btnItemStatus" class="card-footer-item" tabindex="0"></a> <button id="btnItemStatus" class="card-footer-item" tabindex="0"></button>
<a href="#" class="card-footer-item btnModalCancel" tabindex="0"></a> <button class="card-footer-item" role="cancel" tabindex="0"></button>
</footer> </footer>
</div> </div>
</div> </div>
</form> </section>
<div id="modalSettings" class="modal content" tabindex="0"> <div id="modalSettings" class="modal content" tabindex="0">
<div class="modal-background"></div> <div class="modal-background"></div>
...@@ -657,22 +647,24 @@ ...@@ -657,22 +647,24 @@
</div> </div>
</div> </div>
<div id="todoContext" class="dropdown-menu" role="menu" tabindex="0"> <div id="todoContext" role="menu" tabindex="0">
<div class="dropdown-content"> <div class="card">
<a id="todoContextUseAsTemplate" class="dropdown-item" tabindex="0"></a> <div class="card-content">
<a id="todoContextEdit" href="#" class="dropdown-item" tabindex="0"></a> <a id="todoContextUseAsTemplate" class="dropdown-item" tabindex="0"></a>
<a id="todoContextDelete" class="dropdown-item" tabindex="0"></a> <a id="todoContextEdit" href="#" class="dropdown-item" tabindex="0"></a>
<a id="todoContextDelete" class="dropdown-item" tabindex="0"></a>
</div>
</div> </div>
</div> </div>
<div id="filterContext"> <div id="filterContext">
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<input id="filterContextInput" class="input" type="text"> <input id="filterContextInput" class="input" type="text" tabindex="0">
</div> </div>
<footer class="card-footer"> <footer class="card-footer">
<a href="#" id="filterContextSave" class="card-footer-item"></a> <button id="filterContextSave" class="card-footer-item" tabindex="0"></button>
<a href="#" id="filterContextDelete" class="card-footer-item"></a> <button id="filterContextDelete" class="card-footer-item" tabindex="0"></button
</footer> </footer>
</div> </div>
</div> </div>
...@@ -681,16 +673,13 @@ ...@@ -681,16 +673,13 @@
<div class="modal-background"></div> <div class="modal-background"></div>
<div class="modal-content"> <div class="modal-content">
<div class="card"> <div class="card">
<header>
<p id="modalChangeFileTitle" class="card-header-title"></p>
</header>
<div class="card-content"> <div class="card-content">
<table id="modalChangeFileTable"></table> <table id="modalChangeFileTable"></table>
</div> </div>
<footer class="card-footer"> <footer class="card-footer">
<a href="#" id="btnFilesOpenTodoFile" class="card-footer-item" tabindex="0"><i class="fas fa-folder-open"></i>&nbsp;<span id="modalChangeFileOpen"></span></a> <button id="btnFilesOpenTodoFile" class="card-footer-item" tabindex="0"><i class="fas fa-folder-open"></i>&nbsp;<span id="modalChangeFileOpen"></span></button>
<a href="#" id="btnFilesCreateTodoFile" class="card-footer-item" tabindex="0"><i class="fas fa-plus-circle"></i>&nbsp;<span id="modalChangeFileCreate"></span></a> <button id="btnFilesCreateTodoFile" class="card-footer-item" tabindex="0"><i class="fas fa-plus-circle"></i>&nbsp;<span id="modalChangeFileCreate"></span></button>
<a href="#" class="card-footer-item btnModalCancel" tabindex="0"></a> <button class="card-footer-item" role="cancel" tabindex="0"></button>
</footer> </footer>
</div> </div>
</div> </div>
...@@ -702,8 +691,8 @@ ...@@ -702,8 +691,8 @@
<div class="card"> <div class="card">
<div id="modalPromptContent" class="card-content"></div> <div id="modalPromptContent" class="card-content"></div>
<footer class="card-footer"> <footer class="card-footer">
<a href="#" id="modalPromptConfirm" class="card-footer-item" tabindex="0">Confirm</a> <button id="modalPromptConfirm" class="card-footer-item" tabindex="0"></a>
<a href="#" id="modalPromptCancel" class="card-footer-item" tabindex="0">Cancel</a> <button id="modalPromptCancel" role="cancel" class="card-footer-item" tabindex="0"></a>
</footer> </footer>
</div> </div>
</div> </div>
...@@ -714,25 +703,25 @@ ...@@ -714,25 +703,25 @@
<article class="message fixed" data="logging"> <article class="message fixed" data="logging">
<div class="message-header"> <div class="message-header">
<p><span id="messageLoggingTitle"></span></p> <p><span id="messageLoggingTitle"></span></p>
<button class="delete close" aria-label="delete" data-message="logging"></button> <button class="delete close" aria-label="delete" data-message="logging" tabindex="-1"></button>
</div> </div>
<div class="message-body"> <div class="message-body">
<p><span id="messageLoggingBody"></span></p> <p><span id="messageLoggingBody"></span></p>
<p><button id="btnMessageLogging" class="button" tabindex="0"><i class="fas fa-cog"></i>&nbsp;<span id="messageLoggingButton"></span></button></p> <p><button id="btnMessageLogging" tabindex="-1"><i class="fas fa-cog"></i>&nbsp;<span id="messageLoggingButton"></span></button></p>
</div> </div>
</article> </article>
<article class="message fixed" data="share"> <article class="message fixed" data="share">
<div class="message-header"> <div class="message-header">
<p><span id="messageShareTitle"></span></p> <p><span id="messageShareTitle"></span></p>
<button class="delete close" aria-label="delete" data-message="share"></button> <button class="delete close" aria-label="delete" data-message="share" tabindex="-1"></button>
</div> </div>
<div class="message-body"> <div class="message-body">
<p><span id="messageShareBody"></span></p> <p><span id="messageShareBody"></span></p>
<p class="brands"> <p class="brands">
<a href="https://twitter.com/intent/tweet?text=Check%20out%20sleek,%20a%20todo%20app%20based%20on%20todo.txt,%20free%20and%20open-source.%20Available%20for%20Linux,%20Windows%20and%20MacOS.%20https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-twitter"></i></a> <a tabindex="-1" href="https://twitter.com/intent/tweet?text=Check%20out%20sleek,%20a%20todo%20app%20based%20on%20todo.txt,%20free%20and%20open-source.%20Available%20for%20Linux,%20Windows%20and%20MacOS.%20https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-twitter"></i></a>
<a href="https://www.facebook.com/sharer/sharer.php?u=https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-facebook-square"></i></a> <a tabindex="-1" href="https://www.facebook.com/sharer/sharer.php?u=https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-facebook-square"></i></a>
<a href="https://www.linkedin.com/shareArticle?mini=true&url=https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-linkedin"></i></a> <a tabindex="-1" href="https://www.linkedin.com/shareArticle?mini=true&url=https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-linkedin"></i></a>
</p> </p>
</div> </div>
</article> </article>
......
...@@ -215,7 +215,6 @@ function showContent(id) { ...@@ -215,7 +215,6 @@ function showContent(id) {
return Promise.reject(error); return Promise.reject(error);
} }
} }
function setFriendlyLanguageNames() { function setFriendlyLanguageNames() {
try { try {
appData.languages.forEach((language) => { appData.languages.forEach((language) => {
......
...@@ -6,7 +6,7 @@ import { getHandleElement, startDragging } from "./drawer_handle.mjs"; ...@@ -6,7 +6,7 @@ import { getHandleElement, startDragging } from "./drawer_handle.mjs";
const drawerContainer = document.getElementById("drawerContainer"); const drawerContainer = document.getElementById("drawerContainer");
const navBtnFilter = document.getElementById("navBtnFilter"); const navBtnFilter = document.getElementById("navBtnFilter");
const navBtnView = document.getElementById("navBtnView"); const navBtnView = document.getElementById("navBtnView");
const drawers = document.querySelectorAll("nav ul li.drawerTrigger"); const drawers = document.querySelectorAll("nav ul li a.drawerTrigger");
if(userData.filterDrawer) { if(userData.filterDrawer) {
show(document.getElementById("navBtnFilter"), document.getElementById("navBtnFilter").getAttribute("data-drawer")).then(function(result) { show(document.getElementById("navBtnFilter"), document.getElementById("navBtnFilter").getAttribute("data-drawer")).then(function(result) {
......
"use strict"; "use strict";
import { resetModal, handleError, userData, setUserData, translations } from "../render.js"; import { resetFilters, resetModal, handleError, userData, setUserData, translations } from "../render.js";
import { _paq } from "./matomo.mjs"; import { _paq } from "./matomo.mjs";
import { createModalJail } from "../configs/modal.config.mjs"; import { createModalJail } from "../configs/modal.config.mjs";
...@@ -22,11 +22,15 @@ function showFiles() { ...@@ -22,11 +22,15 @@ function showFiles() {
let cell3 = row.insertCell(2); let cell3 = row.insertCell(2);
row.setAttribute("data-path", files[file][1]); row.setAttribute("data-path", files[file][1]);
if(files[file][0]===1) { if(files[file][0]===1) {
cell1.innerHTML = "<button class=\"button\" disabled>" + translations.selected + "</button>"; cell1.innerHTML = "<button disabled>" + translations.selected + "</button>";
} else { } else {
cell1.innerHTML = "<button class=\"button is-link\" tabindex=\"0\">" + translations.select + "</button>"; cell1.innerHTML = "<button tabindex=\"0\">" + translations.select + "</button>";
cell1.onclick = function() { cell1.onclick = function() {
setUserData("selectedFilters", []); resetFilters().then(function(response) {
console.info(response);
}).catch(function(error) {
handleError(error);
});
resetModal().then(response => { resetModal().then(response => {
window.api.send("startFileWatcher", this.parentElement.getAttribute("data-path")); window.api.send("startFileWatcher", this.parentElement.getAttribute("data-path"));
console.info(response); console.info(response);
......
This diff is collapsed.
{{
import { addIntervalToDate } from "./recurrences.mjs";
}}
filterQuery
= _ left:orExpr _ { return left; }
/ _ { return []; }
orExpr
= left:andExpr _ OrOp _ right:orExpr { return left.concat(right, ["||"]); }
/ left:andExpr { return left; }
andExpr
= left:notExpr _ AndOp _ right:andExpr { return left.concat(right, ["&&"]); }
/ left:notExpr { return left; }
notExpr
= NotOp _ left:notExpr { return left.concat(["!!"]); }
/ left:boolExpr { return left; }
boolExpr
= left:project { return left; }
/ left:context { return left; }
/ "(" _ left:orExpr _ ")" { return left; }
/ left:comparison { return left; }
/ "complete" { return ["complete"]; }
/ left:StringLiteral { return ["string", left]; }
/ left:RegexLiteral { return ["regex", left]; }
project
= "+" left:name { return ["++", left]; }
/ "+" { return ["++", "*"]; }
context
= "@" left:name { return ["@@", left]; }
/ "@" { return ["@@", "*"]; }
OrOp
= "||"
/ "or"i
AndOp
= "&&"
/ "and"i
NotOp
= "!"
/ "not"i
comparison
= left:priorityComparison { return left; }
/ left:dueComparison { return left; }
priorityComparison
= priorityKeyword _ op:compareOp _ right:priorityLiteral { return ["pri", right, op]; }
/ priorityKeyword { return ["pri"]; }
/ "(" right:priorityLiteral ")" { return ["pri", right, "=="]; }
priorityLiteral
= [A-Z] { return text(); }
priorityKeyword
= "pri" ("o" ("r" ("i" ("t" "y"?)?)?)?)?
dueComparison
= "due" _ op:compareOp _ right:dateExpr { return ["due"].concat(right, [op]); }
/ "due:" right:dateStr { return ["duestr", right]; }
/ "due" { return ["due"]; }
dateExpr
= left:dateLiteral _ op:dateOp _ count:number unit:[dbwmy] {
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();
}
/ left:dateLiteral { return left; }
dateOp
= "+" { return text(); }
/ "-" { return text(); }
compareOp
= "==" { return text(); }
/ "=" { return "=="; }
/ "!=" { return text(); }
/ ">=" { return text(); }
/ "<=" { return text(); }
/ ">" { return text(); }
/ "<" { return text(); }
dateStr
= [0-9]+ ("-" [0-9]+ ("-" [0-9]+)?)? { return text(); }
dateLiteral
= year:number4 "-" month: number2 "-" day:number2 {