diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..40b878d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules/
\ No newline at end of file
diff --git a/dist/index.html b/dist/index.html
new file mode 100755
index 0000000..462ebf4
--- /dev/null
+++ b/dist/index.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+To-Do List
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dist/main.js b/dist/main.js
new file mode 100755
index 0000000..5509104
--- /dev/null
+++ b/dist/main.js
@@ -0,0 +1,146 @@
+/*
+ * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
+ * This devtool is neither made for production nor for readable output files.
+ * It uses "eval()" calls to create a separate source file in the browser devtools.
+ * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
+ * or disable the default devtool with "devtool: false".
+ * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
+ */
+/******/ (() => { // webpackBootstrap
+/******/ "use strict";
+/******/ var __webpack_modules__ = ({
+
+/***/ "./src/domifier.js":
+/*!*************************!*\
+ !*** ./src/domifier.js ***!
+ \*************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"changeCurrentProject\": () => (/* binding */ changeCurrentProject),\n/* harmony export */ \"createProjectDOM\": () => (/* binding */ createProjectDOM),\n/* harmony export */ \"createTodo\": () => (/* binding */ createTodo),\n/* harmony export */ \"displayTodo\": () => (/* binding */ displayTodo),\n/* harmony export */ \"editTodo\": () => (/* binding */ editTodo),\n/* harmony export */ \"initDOM\": () => (/* binding */ initDOM)\n/* harmony export */ });\n/* harmony import */ var _todo_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./todo.js */ \"./src/todo.js\");\n/* harmony import */ var _project_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./project.js */ \"./src/project.js\");\n/* harmony import */ var _projects_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./projects.js */ \"./src/projects.js\");\n\n\n\n\nconst CURRENTPROJECT = document.getElementById(\"dropdownMenuButton1\");\n\n// shim for setting proper prototype when pulling from JSON\nconst PROJECT = (0,_project_js__WEBPACK_IMPORTED_MODULE_1__.project)(\"shim\");\n\n// initializes certain dom objects\nconst initDOM = () => {\n // creates New Todo button\n const newTodo = document.createElement(\"button\");\n newTodo.className = \"btn btn-warning\";\n newTodo.textContent = \"+ New Todo\";\n // event handlers\n newTodo.onclick = () => createTodo();\n // appends\n document.querySelector(\".nav-pills\").appendChild(newTodo)\n\n // creates New Project button\n const newProject = document.createElement(\"button\");\n newProject.className = \"btn btn-success\";\n newProject.textContent = \"+ New Project\";\n // event handlers\n newProject.onclick = () => {\n // asks for a project name\n const projectName = prompt(\"What will your new project be called?\", \"Default Project\");\n const dummyProjects = (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.getArray)();\n // checks for blanks or default values\n if (projectName === null || projectName === \"\" || projectName === \"Default Project\") {\n alert(\"Please enter a valid project name\");\n }\n\n // checks if any projects are named the same way\n else if (dummyProjects.find (item => item.name === projectName)) {\n alert(\"Please enter an unused project name\");\n }\n // if valid, create new project\n else {\n createProject(projectName);\n }\n }\n // appends\n document.querySelector(\".nav-pills\").appendChild(newProject)\n\n // creates Delete Project button\n const delProject = document.createElement(\"button\");\n delProject.className = \"btn btn-danger\";\n delProject.textContent = \"x Delete Project\";\n // event handlers\n delProject.onclick = () => deleteProject();\n // appends\n document.querySelector(\".nav-pills\").appendChild(delProject);\n\n displayProjects();\n}\n\nconst changeCurrentProject = projectName => {\n // changes dropdown button to main project\n CURRENTPROJECT.textContent = projectName;\n // clears the board\n document.querySelector(\"main\").innerHTML = \"\";\n // finds all todos in the project and displays them (if any)\n const dummyProjects = (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.getArray)();\n const projectInArray = dummyProjects.find (item => item.name === CURRENTPROJECT.textContent);\n if (projectInArray.todos.length > -1) {\n projectInArray.todos.forEach(todo => displayTodo(todo));\n }\n}\n\nconst displayTodo = todo => {\n // sets up the necessary containers\n const card = document.createElement('div');\n card.className = \"card\";\n const cardBody = document.createElement('div');\n cardBody.className = \"card-body\";\n // appends title of current todo to DOM\n const title = document.createElement('h5');\n title.className = \"card-title mb-2\";\n title.textContent = todo.title;\n const dueDate = document.createElement('h6');\n dueDate.className = \"card-subtitle text-muted mb-1\";\n // bit of a rigamarole due to localStorage\n const date = new Date(Date.parse(todo.dueDate));\n dueDate.textContent = \"Due: \" + date.toDateString();\n //\n const priority = document.createElement('h6');\n priority.className = \"mb-3 btn prioritybtn\";\n const determinePriority = () => {\n if (todo.priority === 0) {\n priority.className = priority.className + \" btn-success\";\n priority.textContent = \"Low\";\n }\n else if (todo.priority == 1) {\n priority.className = priority.className + \" btn-warning\";\n priority.textContent = \"Medium\";\n }\n else if (todo.priority == 2) {\n priority.className = priority.className + \" btn-danger\";\n priority.textContent = \"High\";\n }\n return priority;\n }\n priority.textContent = \"Priority: \" + determinePriority().textContent;\n\n const comment = document.createElement('p');\n comment.className = \"card-text text-muted\";\n comment.textContent = todo.description;\n\n const editButton = document.createElement('button');\n editButton.className = \"btn btn-primary me-1\";\n const editButtonText = document.createElement('div');\n editButtonText.textContent = \"Edit\";\n editButton.onclick = () => editTodo(cardBody, todo);\n\n const deleteButton = document.createElement('button');\n deleteButton.className = \"btn btn-danger ms-1\";\n const deleteButtonText = document.createElement('div');\n deleteButtonText.textContent = \"Delete\";\n deleteButton.onclick = () => deleteTodo(todo, card);\n\n // append to DOM\n document.querySelector(\"main\").appendChild(card);\n card.appendChild(cardBody);\n cardBody.appendChild(title);\n cardBody.appendChild(dueDate);\n cardBody.appendChild(priority);\n cardBody.appendChild(comment);\n cardBody.appendChild(editButton);\n editButton.appendChild(editButtonText);\n cardBody.appendChild(deleteButton);\n deleteButton.appendChild(deleteButtonText);\n}\n\nconst deleteProject = () => {\n // removes the todos from the project\n const dummyProjects = (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.getArray)();\n const projectInArray = dummyProjects.find (item => item.name === CURRENTPROJECT.textContent);\n projectInArray.todos = [];\n \n // finds the current project in the dropdown menu\n // gets array of dropdown objects in dom and casts it to a \"real\" array;\n const dropdownArray = Array.prototype.slice.call(document.getElementsByClassName(\"dropdown-item\"));\n // finds the project which matches current project\n const currentProjectDropdown = dropdownArray.find(element => element.textContent === CURRENTPROJECT.textContent);\n // finds the next project\n const nextProjectDropdown = dropdownArray[dropdownArray.indexOf(currentProjectDropdown) + 1];\n const prevProjectDropdown = dropdownArray[dropdownArray.indexOf(currentProjectDropdown) - 1];\n\n // removes the current project from dropdowns\n const li = currentProjectDropdown.parentElement;\n li.parentElement.removeChild(li);\n\n // removes from projects array\n const projectNumber = dummyProjects.indexOf(projectInArray);\n dummyProjects.splice(projectNumber, 1);\n (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.setArray)(dummyProjects);\n\n // changes current project\n if (nextProjectDropdown) {\n changeCurrentProject(nextProjectDropdown.textContent);\n }\n else if (prevProjectDropdown) {\n changeCurrentProject(prevProjectDropdown.textContent);\n }\n else {\n CURRENTPROJECT.textContent = \"\";\n }\n}\n\nconst createProjectDOM = projectName => {\n // adds to dropdown\n const li = document.createElement(\"li\");\n document.querySelector(\".dropdown-menu\").appendChild(li);\n const dropdownOption = document.createElement(\"a\");\n dropdownOption.className = \"dropdown-item\";\n dropdownOption.textContent = projectName;\n li.appendChild(dropdownOption);\n // event handler for when user clicks the project in dropdowns\n li.onclick = () => changeCurrentProject(projectName);\n\n // changes to new project\n changeCurrentProject(projectName);\n}\n\nconst createTodo = () => {\n // sets up the necessary containers\n const card = document.createElement('div');\n card.className = \"card\";\n const cardBody = document.createElement('div');\n cardBody.className = \"card-body\";\n\n // creates input fields to get user input for todo info\n const title = document.createElement('input');\n title.className = \"card-title mb-2 form-control\";\n title.type = \"text\";\n title.placeholder = \"Title\";\n\n const dueDate = document.createElement('input');\n dueDate.className = \"card-subtitle text-muted mb-2 form-control\";\n dueDate.type = \"date\";\n dueDate.oninput = () => {\n const dueDateSplit = dueDate.value.split('-'); \n if (dueDateSplit[0] && dueDateSplit[0].length > 4) { \n dueDateSplit[0]=dueDateSplit[0].slice(0,4); \n dueDate.value = dueDateSplit.join('-');\n }\n }\n const priority = document.createElement('h6');\n const oldClassName = \"mb-3 btn btn-primary\";\n priority.className = oldClassName;\n priority.textContent = \"Priority\"\n let priorityLevel;\n let counter = 0;\n priority.onclick = () => {\n if (counter === 0) {\n priority.className = oldClassName + \" btn-success\";\n priority.textContent = \"Priority: Low\";\n priorityLevel = counter;\n counter++;\n }\n else if (counter === 1) {\n priority.className = oldClassName + \" btn-warning\";\n priority.textContent = \"Priority: Medium\";\n priorityLevel = counter;\n counter++;\n }\n else {\n priority.className = oldClassName + \" btn-danger\";\n priority.textContent = \"Priority: High\";\n priorityLevel = counter;\n counter = 0;\n }\n }\n\n const comment = document.createElement('input');\n comment.className = \"card-text text-muted form-control mb-3\";\n comment.type = \"text\";\n comment.placeholder = \"Description\"\n\n const createButton = document.createElement('button');\n createButton.className = \"btn btn-success me-1\";\n const createButtonText = document.createElement('div');\n createButtonText.textContent = \"Create\";\n createButton.onclick = () => finalizeTodo();\n\n const deleteButton = document.createElement('button');\n deleteButton.className = \"btn btn-danger ms-1\";\n const deleteButtonText = document.createElement('div');\n deleteButtonText.textContent = \"Cancel\";\n\n deleteButton.onclick = () => document.querySelector(\"main\").removeChild(card);\n\n document.querySelector('main').appendChild(card);\n card.appendChild(cardBody);\n cardBody.appendChild(title);\n cardBody.appendChild(dueDate);\n cardBody.appendChild(priority);\n cardBody.appendChild(comment);\n cardBody.appendChild(createButton);\n createButton.appendChild(createButtonText);\n cardBody.appendChild(deleteButton);\n deleteButton.appendChild(deleteButtonText);\n\n function finalizeTodo() {\n // some validation\n if (title.value === \"Title\" || title.value === \"\") {\n alert(\"Please enter a name for your to-do\");\n }\n else {\n if (priorityLevel || priorityLevel === 0) {\n // adds todo to project\n const finalizedTodo = (0,_todo_js__WEBPACK_IMPORTED_MODULE_0__.todo)(title.value, comment.value, dueDate.valueAsDate, priorityLevel);\n const dummyProjects = (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.getArray)();\n let foundProject = dummyProjects.find (item => item.name === CURRENTPROJECT.textContent);\n\n foundProject.todos[foundProject.todos.length] = finalizedTodo;\n (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.setArray)(dummyProjects);\n \n // wipes prompt window\n document.querySelector(\"main\").removeChild(card);\n displayTodo(finalizedTodo);\n }\n else {\n alert(\"Please select a priority for your to-do by clicking the Priority button\");\n }\n }\n }\n}\n\nconst editTodo = (cardBody, todo) => {\n // creates title field and fills with existing title\n const title = document.createElement('input');\n title.className = \"card-title mb-2 form-control\";\n title.type = \"text\";\n // gets title out of existing title (title is the first child of cardBody)\n title.value = cardBody.firstChild.textContent;\n\n \n const dueDate = document.createElement('input');\n dueDate.maxLength = 8;\n dueDate.className = \"card-subtitle text-muted mb-2 form-control\";\n dueDate.type = \"date\";\n if (typeof todo.dueDate === \"object\") {\n dueDate.value = todo.dueDate.toISOString().slice(0,10);\n }\n else {\n dueDate.value = todo.dueDate.slice(0,10);\n }\n dueDate.oninput = () => {\n const dueDateSplit = dueDate.value.split('-'); \n if (dueDateSplit[0] && dueDateSplit[0].length > 4) { \n dueDateSplit[0]=dueDateSplit[0].slice(0,4); \n dueDate.value = dueDateSplit.join('-');\n }\n }\n \n const priority = document.createElement('h6');\n const oldClassName = \"mb-3 btn btn-primary\";\n priority.className = oldClassName;\n priority.textContent = \"Priority\";\n let counter;\n let priorityLevel = todo.priority;\n if (todo.priority === 0) {\n priority.className = oldClassName + \" btn-success\";\n priority.textContent = \"Priority: Low\";\n counter = 1;\n }\n else if (todo.priority === 1) {\n priority.className = oldClassName + \" btn-warning\";\n priority.textContent = \"Priority: Medium\";\n counter = 2;\n }\n else {\n priority.className = oldClassName + \" btn-danger\";\n priority.textContent = \"Priority: High\";\n counter = 0;\n }\n\n priority.onclick = () => {\n if (counter === 0) {\n priority.className = oldClassName + \" btn-success\";\n priority.textContent = \"Priority: Low\";\n priorityLevel = counter;\n counter++;\n }\n else if (counter === 1) {\n priority.className = oldClassName + \" btn-warning\";\n priority.textContent = \"Priority: Medium\";\n priorityLevel = counter;\n counter++;\n }\n else {\n priority.className = oldClassName + \" btn-danger\";\n priority.textContent = \"Priority: High\";\n priorityLevel = counter;\n counter = 0;\n }\n }\n\n const comment = document.createElement('input');\n comment.className = \"card-text text-muted form-control mb-3\";\n comment.type = \"text\";\n comment.value = cardBody.children[3].textContent;\n\n for (let i = 0; i < 4; i++) {\n cardBody.removeChild(cardBody.firstChild);\n }\n\n cardBody.firstChild.textContent = \"Finish\";\n cardBody.firstChild.className = \"btn btn-success me-1\";\n cardBody.firstChild.onclick = () => finalizeTodo();\n\n cardBody.prepend(comment);\n cardBody.prepend(priority);\n cardBody.prepend(dueDate);\n cardBody.prepend(title);\n\n function finalizeTodo() {\n // some validation\n if (title.value === \"\") {\n alert(\"Please enter a name for your to-do\");\n }\n else {\n if (priorityLevel || priorityLevel === 0) {\n todo.title = title.value;\n todo.description = comment.value;\n todo.dueDate = dueDate.valueAsDate;\n todo.priority = priorityLevel;\n \n // proper handling\n const dummyProjects = (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.getArray)();\n const foundProject = dummyProjects.find (item => item.name === CURRENTPROJECT.textContent);\n (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.setArray)(dummyProjects);\n \n // wipes prompt window\n document.querySelector(\"main\").removeChild(cardBody.parentElement);\n displayTodo(todo);\n }\n else {\n alert(\"Please select a priority for your to-do by clicking the Priority button\")\n }\n }\n }\n}\n\nconst deleteTodo = (todo, card) => {\n document.querySelector(\"main\").removeChild(card);\n const dummyProjects = (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.getArray)();\n let foundProject = dummyProjects.find (item => item.name === CURRENTPROJECT.textContent);\n const todoIndex = foundProject.todos.indexOf(todo);\n if (todoIndex) {\n foundProject.todos.splice(todoIndex, 1);\n }\n (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.setArray)(dummyProjects);\n}\n\nconst createProject = (projectName) => {\n const dummyProjects = (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.getArray)();\n dummyProjects[dummyProjects.length] = (0,_project_js__WEBPACK_IMPORTED_MODULE_1__.project)(projectName);\n (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.setArray)(dummyProjects);\n createProjectDOM(projectName);\n}\n\nconst displayProjects = () => {\n const dummyProjects = (0,_projects_js__WEBPACK_IMPORTED_MODULE_2__.getArray)();\n dummyProjects.forEach(item => createProjectDOM(item.name));\n}\n\n//# sourceURL=webpack://js-todolist/./src/domifier.js?");
+
+/***/ }),
+
+/***/ "./src/incrementer.js":
+/*!****************************!*\
+ !*** ./src/incrementer.js ***!
+ \****************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"incrementer\": () => (/* binding */ incrementer)\n/* harmony export */ });\n// increments date based from today's date on number of days specified\nconst incrementer = (date, days) => {\n date.setDate(date.getDate() + days);\n return date;\n}\n\n//# sourceURL=webpack://js-todolist/./src/incrementer.js?");
+
+/***/ }),
+
+/***/ "./src/index.js":
+/*!**********************!*\
+ !*** ./src/index.js ***!
+ \**********************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _todo_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./todo.js */ \"./src/todo.js\");\n/* harmony import */ var _incrementer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./incrementer.js */ \"./src/incrementer.js\");\n/* harmony import */ var _domifier_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./domifier.js */ \"./src/domifier.js\");\n/* harmony import */ var _projects_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./projects.js */ \"./src/projects.js\");\n/* harmony import */ var _project_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./project.js */ \"./src/project.js\");\n\n\n\n\n\n\n\nconst TODAY = new Date();\nlet dummyProjects = (0,_projects_js__WEBPACK_IMPORTED_MODULE_3__.getArray)();\n\ndummyProjects[0] = (0,_project_js__WEBPACK_IMPORTED_MODULE_4__.project)(\"Default Project\");\n\nconst defaultTodo = (0,_todo_js__WEBPACK_IMPORTED_MODULE_0__.todo)(\n \"Default Todo\", \n \"This is the default to-do for the to-do list. Feel free to add some more!\", \n (0,_incrementer_js__WEBPACK_IMPORTED_MODULE_1__.incrementer)(TODAY, 7),\n 0\n);\n\n\ndummyProjects[0].todos[dummyProjects[0].todos.length] = defaultTodo;\n(0,_projects_js__WEBPACK_IMPORTED_MODULE_3__.setArray)(dummyProjects);\n\n(0,_domifier_js__WEBPACK_IMPORTED_MODULE_2__.initDOM)();\n(0,_domifier_js__WEBPACK_IMPORTED_MODULE_2__.changeCurrentProject)(dummyProjects[0].name);\n\n//# sourceURL=webpack://js-todolist/./src/index.js?");
+
+/***/ }),
+
+/***/ "./src/project.js":
+/*!************************!*\
+ !*** ./src/project.js ***!
+ \************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"project\": () => (/* binding */ project)\n/* harmony export */ });\nconst project = (name) => {\r\n // sets up array of todo objects\r\n let todos = []\r\n \r\n return {\r\n name,\r\n todos\r\n }\r\n}\n\n//# sourceURL=webpack://js-todolist/./src/project.js?");
+
+/***/ }),
+
+/***/ "./src/projects.js":
+/*!*************************!*\
+ !*** ./src/projects.js ***!
+ \*************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"getArray\": () => (/* binding */ getArray),\n/* harmony export */ \"setArray\": () => (/* binding */ setArray)\n/* harmony export */ });\n/* harmony import */ var _storageAvailable_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./storageAvailable.js */ \"./src/storageAvailable.js\");\n// logic for the projects array itself\n\n\n// get and set arrays - get from local storage if available, if not then get from a global var\n// set it here too, as well as extend the regular array methods\n// everything will be here regards getting and setting this stuff, without a need to expose the actual array out to other modules\n\n// master projects array\nlet projectsArray = [];\n\n// tests if a \"projects\" item exists in local storage\nconst projectsExists = localStorage.getItem(\"projects\") ? true : false;\n\n// returns the proper array depending on where it is\nconst getArray = () => {\n // localStorage exists\n if (_storageAvailable_js__WEBPACK_IMPORTED_MODULE_0__.storageAvailable) {\n // \"projects\" exists\n if (projectsExists) {\n // set projects array to local storage and return\n projectsArray = JSON.parse(localStorage.projects);\n return projectsArray;\n }\n else {\n return projectsArray;\n }\n }\n // otherwise return the projects array here\n else {\n return projectsArray;\n }\n}\n\n// easiest workaround to getting too in-depth - passed array is set as the main, depending on if storage exists, etc.\nconst setArray = (array) => {\n // set the master array to passed array - regardless of localStorage\n projectsArray = array;\n // check for localStorage\n if (_storageAvailable_js__WEBPACK_IMPORTED_MODULE_0__.storageAvailable) {\n // and existing \"projects\"\n if (projectsExists) {\n // remove existing array from localStorage\n localStorage.removeItem(\"projects\");\n // add the modified array\n localStorage.projects = JSON.stringify(projectsArray);\n }\n // if \"projects\" doesn't exist, add it\n else {\n localStorage.projects = JSON.stringify(projectsArray);\n }\n }\n}\n\n//# sourceURL=webpack://js-todolist/./src/projects.js?");
+
+/***/ }),
+
+/***/ "./src/storageAvailable.js":
+/*!*********************************!*\
+ !*** ./src/storageAvailable.js ***!
+ \*********************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"storageAvailable\": () => (/* binding */ storageAvailable)\n/* harmony export */ });\nfunction storageAvailableFunc(type) {\n let storage;\n try {\n storage = window[type];\n const x = \"__storage_test__\";\n storage.setItem(x, x);\n storage.removeItem(x);\n return true;\n } catch (e) {\n return (\n e instanceof DOMException &&\n // everything except Firefox\n (e.code === 22 ||\n // Firefox\n e.code === 1014 ||\n // test name field too, because code might not be present\n // everything except Firefox\n e.name === \"QuotaExceededError\" ||\n // Firefox\n e.name === \"NS_ERROR_DOM_QUOTA_REACHED\") &&\n // acknowledge QuotaExceededError only if there's something already stored\n storage &&\n storage.length !== 0\n );\n }\n}\n// copyright MDN https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API\n\nconst storageAvailable = storageAvailableFunc(\"localStorage\");\n\n//# sourceURL=webpack://js-todolist/./src/storageAvailable.js?");
+
+/***/ }),
+
+/***/ "./src/todo.js":
+/*!*********************!*\
+ !*** ./src/todo.js ***!
+ \*********************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"todo\": () => (/* binding */ todo)\n/* harmony export */ });\n// todo factory function\r\nconst todo = (title, description, dueDate, priority) => {\r\n return {\r\n title,\r\n description,\r\n dueDate,\r\n priority\r\n }\r\n}\n\n//# sourceURL=webpack://js-todolist/./src/todo.js?");
+
+/***/ })
+
+/******/ });
+/************************************************************************/
+/******/ // The module cache
+/******/ var __webpack_module_cache__ = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/ // Check if module is in cache
+/******/ var cachedModule = __webpack_module_cache__[moduleId];
+/******/ if (cachedModule !== undefined) {
+/******/ return cachedModule.exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = __webpack_module_cache__[moduleId] = {
+/******/ // no module.id needed
+/******/ // no module.loaded needed
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/************************************************************************/
+/******/ /* webpack/runtime/define property getters */
+/******/ (() => {
+/******/ // define getter functions for harmony exports
+/******/ __webpack_require__.d = (exports, definition) => {
+/******/ for(var key in definition) {
+/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ }
+/******/ }
+/******/ };
+/******/ })();
+/******/
+/******/ /* webpack/runtime/hasOwnProperty shorthand */
+/******/ (() => {
+/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ })();
+/******/
+/******/ /* webpack/runtime/make namespace object */
+/******/ (() => {
+/******/ // define __esModule on exports
+/******/ __webpack_require__.r = (exports) => {
+/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ }
+/******/ Object.defineProperty(exports, '__esModule', { value: true });
+/******/ };
+/******/ })();
+/******/
+/************************************************************************/
+/******/
+/******/ // startup
+/******/ // Load entry module and return exports
+/******/ // This entry module can't be inlined because the eval devtool is used.
+/******/ var __webpack_exports__ = __webpack_require__("./src/index.js");
+/******/
+/******/ })()
+;
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100755
index 0000000..b2b0ed2
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1331 @@
+{
+ "name": "js-todolist",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "js-todolist",
+ "version": "1.0.0",
+ "license": "AGPL-3.0-or-later",
+ "devDependencies": {
+ "webpack": "^5.77.0",
+ "webpack-cli": "^5.0.1"
+ }
+ },
+ "node_modules/@discoveryjs/json-ext": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
+ "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.17",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
+ "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "node_modules/@types/eslint": {
+ "version": "8.37.0",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.37.0.tgz",
+ "integrity": "sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "node_modules/@types/eslint-scope": {
+ "version": "3.7.4",
+ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz",
+ "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==",
+ "dev": true,
+ "dependencies": {
+ "@types/eslint": "*",
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "0.0.51",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz",
+ "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==",
+ "dev": true
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "18.15.11",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz",
+ "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/ast": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
+ "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/helper-numbers": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz",
+ "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-api-error": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz",
+ "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-buffer": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz",
+ "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-numbers": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz",
+ "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/floating-point-hex-parser": "1.11.1",
+ "@webassemblyjs/helper-api-error": "1.11.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz",
+ "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-wasm-section": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz",
+ "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-buffer": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/wasm-gen": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/ieee754": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz",
+ "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==",
+ "dev": true,
+ "dependencies": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "node_modules/@webassemblyjs/leb128": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz",
+ "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==",
+ "dev": true,
+ "dependencies": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/utf8": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz",
+ "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/wasm-edit": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz",
+ "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-buffer": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/helper-wasm-section": "1.11.1",
+ "@webassemblyjs/wasm-gen": "1.11.1",
+ "@webassemblyjs/wasm-opt": "1.11.1",
+ "@webassemblyjs/wasm-parser": "1.11.1",
+ "@webassemblyjs/wast-printer": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-gen": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz",
+ "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/ieee754": "1.11.1",
+ "@webassemblyjs/leb128": "1.11.1",
+ "@webassemblyjs/utf8": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-opt": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
+ "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-buffer": "1.11.1",
+ "@webassemblyjs/wasm-gen": "1.11.1",
+ "@webassemblyjs/wasm-parser": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-parser": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz",
+ "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-api-error": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/ieee754": "1.11.1",
+ "@webassemblyjs/leb128": "1.11.1",
+ "@webassemblyjs/utf8": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wast-printer": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz",
+ "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webpack-cli/configtest": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.0.1.tgz",
+ "integrity": "sha512-njsdJXJSiS2iNbQVS0eT8A/KPnmyH4pv1APj2K0d1wrZcBLw+yppxOy4CGqa0OxDJkzfL/XELDhD8rocnIwB5A==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x",
+ "webpack-cli": "5.x.x"
+ }
+ },
+ "node_modules/@webpack-cli/info": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.1.tgz",
+ "integrity": "sha512-fE1UEWTwsAxRhrJNikE7v4EotYflkEhBL7EbajfkPlf6E37/2QshOy/D48Mw8G5XMFlQtS6YV42vtbG9zBpIQA==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x",
+ "webpack-cli": "5.x.x"
+ }
+ },
+ "node_modules/@webpack-cli/serve": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.1.tgz",
+ "integrity": "sha512-0G7tNyS+yW8TdgHwZKlDWYXFA6OJQnoLCQvYKkQP0Q2X205PSQ6RNUj0M+1OB/9gRQaUZ/ccYfaxd0nhaWKfjw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x",
+ "webpack-cli": "5.x.x"
+ },
+ "peerDependenciesMeta": {
+ "webpack-dev-server": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+ "dev": true
+ },
+ "node_modules/@xtuc/long": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+ "dev": true
+ },
+ "node_modules/acorn": {
+ "version": "8.8.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
+ "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-import-assertions": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
+ "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-keywords": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+ "dev": true,
+ "peerDependencies": {
+ "ajv": "^6.9.1"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.21.5",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz",
+ "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001449",
+ "electron-to-chromium": "^1.4.284",
+ "node-releases": "^2.0.8",
+ "update-browserslist-db": "^1.0.10"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001473",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001473.tgz",
+ "integrity": "sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/chrome-trace-event": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
+ "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "dev": true,
+ "dependencies": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/colorette": {
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
+ "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==",
+ "dev": true
+ },
+ "node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.349",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.349.tgz",
+ "integrity": "sha512-34LBfVDiL6byWorSmQOPwq4gD5wpN8Mhh5yPGQr67FbcxsfUS0BDJP9y6RykSgeWVUfSkN/2dChywnsrmKVyUg==",
+ "dev": true
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.12.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
+ "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/envinfo": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz",
+ "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==",
+ "dev": true,
+ "bin": {
+ "envinfo": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
+ "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==",
+ "dev": true
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fastest-levenshtein": {
+ "version": "1.0.16",
+ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
+ "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.9.1"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "node_modules/glob-to-regexp": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+ "dev": true
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+ "dev": true,
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/interpret": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz",
+ "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "dependencies": {
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/loader-runner": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
+ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.11.5"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz",
+ "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==",
+ "dev": true
+ },
+ "node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/rechoir": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz",
+ "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==",
+ "dev": true,
+ "dependencies": {
+ "resolve": "^1.20.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/schema-utils": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+ "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/serialize-javascript": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
+ "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tapable": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.16.8",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.8.tgz",
+ "integrity": "sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.2",
+ "acorn": "^8.5.0",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/terser-webpack-plugin": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz",
+ "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jest-worker": "^27.4.5",
+ "schema-utils": "^3.1.1",
+ "serialize-javascript": "^6.0.1",
+ "terser": "^5.16.5"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "uglify-js": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
+ "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "browserslist-lint": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/watchpack": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
+ "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
+ "dev": true,
+ "dependencies": {
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/webpack": {
+ "version": "5.77.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.77.0.tgz",
+ "integrity": "sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/eslint-scope": "^3.7.3",
+ "@types/estree": "^0.0.51",
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/wasm-edit": "1.11.1",
+ "@webassemblyjs/wasm-parser": "1.11.1",
+ "acorn": "^8.7.1",
+ "acorn-import-assertions": "^1.7.6",
+ "browserslist": "^4.14.5",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^5.10.0",
+ "es-module-lexer": "^0.9.0",
+ "eslint-scope": "5.1.1",
+ "events": "^3.2.0",
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.2.9",
+ "json-parse-even-better-errors": "^2.3.1",
+ "loader-runner": "^4.2.0",
+ "mime-types": "^2.1.27",
+ "neo-async": "^2.6.2",
+ "schema-utils": "^3.1.0",
+ "tapable": "^2.1.1",
+ "terser-webpack-plugin": "^5.1.3",
+ "watchpack": "^2.4.0",
+ "webpack-sources": "^3.2.3"
+ },
+ "bin": {
+ "webpack": "bin/webpack.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependenciesMeta": {
+ "webpack-cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-cli": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.0.1.tgz",
+ "integrity": "sha512-S3KVAyfwUqr0Mo/ur3NzIp6jnerNpo7GUO6so51mxLi1spqsA17YcMXy0WOIJtBSnj748lthxC6XLbNKh/ZC+A==",
+ "dev": true,
+ "dependencies": {
+ "@discoveryjs/json-ext": "^0.5.0",
+ "@webpack-cli/configtest": "^2.0.1",
+ "@webpack-cli/info": "^2.0.1",
+ "@webpack-cli/serve": "^2.0.1",
+ "colorette": "^2.0.14",
+ "commander": "^9.4.1",
+ "cross-spawn": "^7.0.3",
+ "envinfo": "^7.7.3",
+ "fastest-levenshtein": "^1.0.12",
+ "import-local": "^3.0.2",
+ "interpret": "^3.1.1",
+ "rechoir": "^0.8.0",
+ "webpack-merge": "^5.7.3"
+ },
+ "bin": {
+ "webpack-cli": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x"
+ },
+ "peerDependenciesMeta": {
+ "@webpack-cli/generators": {
+ "optional": true
+ },
+ "webpack-bundle-analyzer": {
+ "optional": true
+ },
+ "webpack-dev-server": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-cli/node_modules/commander": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
+ "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || >=14"
+ }
+ },
+ "node_modules/webpack-merge": {
+ "version": "5.8.0",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz",
+ "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==",
+ "dev": true,
+ "dependencies": {
+ "clone-deep": "^4.0.1",
+ "wildcard": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/webpack-sources": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
+ "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wildcard": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz",
+ "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==",
+ "dev": true
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100755
index 0000000..3a0606d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "js-todolist",
+ "version": "1.0.0",
+ "description": "to-do list implemented in ES6",
+ "main": "js/index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "build": "webpack"
+ },
+ "keywords": [
+ "js",
+ "javascript",
+ "odin",
+ "todo",
+ "list"
+ ],
+ "author": "ak",
+ "license": "AGPL-3.0-or-later",
+ "devDependencies": {
+ "webpack": "^5.77.0",
+ "webpack-cli": "^5.0.1"
+ }
+}
diff --git a/src/domifier.js b/src/domifier.js
new file mode 100755
index 0000000..fbae5ca
--- /dev/null
+++ b/src/domifier.js
@@ -0,0 +1,429 @@
+import { todo } from "./todo.js";
+import { project } from "./project.js";
+import { getArray, setArray } from "./projects.js"
+
+const CURRENTPROJECT = document.getElementById("dropdownMenuButton1");
+
+// shim for setting proper prototype when pulling from JSON
+const PROJECT = project("shim");
+
+// initializes certain dom objects
+export const initDOM = () => {
+ // creates New Todo button
+ const newTodo = document.createElement("button");
+ newTodo.className = "btn btn-warning";
+ newTodo.textContent = "+ New Todo";
+ // event handlers
+ newTodo.onclick = () => createTodo();
+ // appends
+ document.querySelector(".nav-pills").appendChild(newTodo)
+
+ // creates New Project button
+ const newProject = document.createElement("button");
+ newProject.className = "btn btn-success";
+ newProject.textContent = "+ New Project";
+ // event handlers
+ newProject.onclick = () => {
+ // asks for a project name
+ const projectName = prompt("What will your new project be called?", "Default Project");
+ const dummyProjects = getArray();
+ // checks for blanks or default values
+ if (projectName === null || projectName === "" || projectName === "Default Project") {
+ alert("Please enter a valid project name");
+ }
+
+ // checks if any projects are named the same way
+ else if (dummyProjects.find (item => item.name === projectName)) {
+ alert("Please enter an unused project name");
+ }
+ // if valid, create new project
+ else {
+ createProject(projectName);
+ }
+ }
+ // appends
+ document.querySelector(".nav-pills").appendChild(newProject)
+
+ // creates Delete Project button
+ const delProject = document.createElement("button");
+ delProject.className = "btn btn-danger";
+ delProject.textContent = "x Delete Project";
+ // event handlers
+ delProject.onclick = () => deleteProject();
+ // appends
+ document.querySelector(".nav-pills").appendChild(delProject);
+
+ displayProjects();
+}
+
+export const changeCurrentProject = projectName => {
+ // changes dropdown button to main project
+ CURRENTPROJECT.textContent = projectName;
+ // clears the board
+ document.querySelector("main").innerHTML = "";
+ // finds all todos in the project and displays them (if any)
+ const dummyProjects = getArray();
+ const projectInArray = dummyProjects.find (item => item.name === CURRENTPROJECT.textContent);
+ if (projectInArray.todos.length > -1) {
+ projectInArray.todos.forEach(todo => displayTodo(todo));
+ }
+}
+
+export const displayTodo = todo => {
+ // sets up the necessary containers
+ const card = document.createElement('div');
+ card.className = "card";
+ const cardBody = document.createElement('div');
+ cardBody.className = "card-body";
+ // appends title of current todo to DOM
+ const title = document.createElement('h5');
+ title.className = "card-title mb-2";
+ title.textContent = todo.title;
+ const dueDate = document.createElement('h6');
+ dueDate.className = "card-subtitle text-muted mb-1";
+ // bit of a rigamarole due to localStorage
+ const date = new Date(Date.parse(todo.dueDate));
+ dueDate.textContent = "Due: " + date.toDateString();
+ //
+ const priority = document.createElement('h6');
+ priority.className = "mb-3 btn prioritybtn";
+ const determinePriority = () => {
+ if (todo.priority === 0) {
+ priority.className = priority.className + " btn-success";
+ priority.textContent = "Low";
+ }
+ else if (todo.priority == 1) {
+ priority.className = priority.className + " btn-warning";
+ priority.textContent = "Medium";
+ }
+ else if (todo.priority == 2) {
+ priority.className = priority.className + " btn-danger";
+ priority.textContent = "High";
+ }
+ return priority;
+ }
+ priority.textContent = "Priority: " + determinePriority().textContent;
+
+ const comment = document.createElement('p');
+ comment.className = "card-text text-muted";
+ comment.textContent = todo.description;
+
+ const editButton = document.createElement('button');
+ editButton.className = "btn btn-primary me-1";
+ const editButtonText = document.createElement('div');
+ editButtonText.textContent = "Edit";
+ editButton.onclick = () => editTodo(cardBody, todo);
+
+ const deleteButton = document.createElement('button');
+ deleteButton.className = "btn btn-danger ms-1";
+ const deleteButtonText = document.createElement('div');
+ deleteButtonText.textContent = "Delete";
+ deleteButton.onclick = () => deleteTodo(todo, card);
+
+ // append to DOM
+ document.querySelector("main").appendChild(card);
+ card.appendChild(cardBody);
+ cardBody.appendChild(title);
+ cardBody.appendChild(dueDate);
+ cardBody.appendChild(priority);
+ cardBody.appendChild(comment);
+ cardBody.appendChild(editButton);
+ editButton.appendChild(editButtonText);
+ cardBody.appendChild(deleteButton);
+ deleteButton.appendChild(deleteButtonText);
+}
+
+const deleteProject = () => {
+ // removes the todos from the project
+ const dummyProjects = getArray();
+ const projectInArray = dummyProjects.find (item => item.name === CURRENTPROJECT.textContent);
+ projectInArray.todos = [];
+
+ // finds the current project in the dropdown menu
+ // gets array of dropdown objects in dom and casts it to a "real" array;
+ const dropdownArray = Array.prototype.slice.call(document.getElementsByClassName("dropdown-item"));
+ // finds the project which matches current project
+ const currentProjectDropdown = dropdownArray.find(element => element.textContent === CURRENTPROJECT.textContent);
+ // finds the next project
+ const nextProjectDropdown = dropdownArray[dropdownArray.indexOf(currentProjectDropdown) + 1];
+ const prevProjectDropdown = dropdownArray[dropdownArray.indexOf(currentProjectDropdown) - 1];
+
+ // removes the current project from dropdowns
+ const li = currentProjectDropdown.parentElement;
+ li.parentElement.removeChild(li);
+
+ // removes from projects array
+ const projectNumber = dummyProjects.indexOf(projectInArray);
+ dummyProjects.splice(projectNumber, 1);
+ setArray(dummyProjects);
+
+ // changes current project
+ if (nextProjectDropdown) {
+ changeCurrentProject(nextProjectDropdown.textContent);
+ }
+ else if (prevProjectDropdown) {
+ changeCurrentProject(prevProjectDropdown.textContent);
+ }
+ else {
+ CURRENTPROJECT.textContent = "";
+ }
+}
+
+export const createProjectDOM = projectName => {
+ // adds to dropdown
+ const li = document.createElement("li");
+ document.querySelector(".dropdown-menu").appendChild(li);
+ const dropdownOption = document.createElement("a");
+ dropdownOption.className = "dropdown-item";
+ dropdownOption.textContent = projectName;
+ li.appendChild(dropdownOption);
+ // event handler for when user clicks the project in dropdowns
+ li.onclick = () => changeCurrentProject(projectName);
+
+ // changes to new project
+ changeCurrentProject(projectName);
+}
+
+export const createTodo = () => {
+ // sets up the necessary containers
+ const card = document.createElement('div');
+ card.className = "card";
+ const cardBody = document.createElement('div');
+ cardBody.className = "card-body";
+
+ // creates input fields to get user input for todo info
+ const title = document.createElement('input');
+ title.className = "card-title mb-2 form-control";
+ title.type = "text";
+ title.placeholder = "Title";
+
+ const dueDate = document.createElement('input');
+ dueDate.className = "card-subtitle text-muted mb-2 form-control";
+ dueDate.type = "date";
+ dueDate.oninput = () => {
+ const dueDateSplit = dueDate.value.split('-');
+ if (dueDateSplit[0] && dueDateSplit[0].length > 4) {
+ dueDateSplit[0]=dueDateSplit[0].slice(0,4);
+ dueDate.value = dueDateSplit.join('-');
+ }
+ }
+ const priority = document.createElement('h6');
+ const oldClassName = "mb-3 btn btn-primary";
+ priority.className = oldClassName;
+ priority.textContent = "Priority"
+ let priorityLevel;
+ let counter = 0;
+ priority.onclick = () => {
+ if (counter === 0) {
+ priority.className = oldClassName + " btn-success";
+ priority.textContent = "Priority: Low";
+ priorityLevel = counter;
+ counter++;
+ }
+ else if (counter === 1) {
+ priority.className = oldClassName + " btn-warning";
+ priority.textContent = "Priority: Medium";
+ priorityLevel = counter;
+ counter++;
+ }
+ else {
+ priority.className = oldClassName + " btn-danger";
+ priority.textContent = "Priority: High";
+ priorityLevel = counter;
+ counter = 0;
+ }
+ }
+
+ const comment = document.createElement('input');
+ comment.className = "card-text text-muted form-control mb-3";
+ comment.type = "text";
+ comment.placeholder = "Description"
+
+ const createButton = document.createElement('button');
+ createButton.className = "btn btn-success me-1";
+ const createButtonText = document.createElement('div');
+ createButtonText.textContent = "Create";
+ createButton.onclick = () => finalizeTodo();
+
+ const deleteButton = document.createElement('button');
+ deleteButton.className = "btn btn-danger ms-1";
+ const deleteButtonText = document.createElement('div');
+ deleteButtonText.textContent = "Cancel";
+
+ deleteButton.onclick = () => document.querySelector("main").removeChild(card);
+
+ document.querySelector('main').appendChild(card);
+ card.appendChild(cardBody);
+ cardBody.appendChild(title);
+ cardBody.appendChild(dueDate);
+ cardBody.appendChild(priority);
+ cardBody.appendChild(comment);
+ cardBody.appendChild(createButton);
+ createButton.appendChild(createButtonText);
+ cardBody.appendChild(deleteButton);
+ deleteButton.appendChild(deleteButtonText);
+
+ function finalizeTodo() {
+ // some validation
+ if (title.value === "Title" || title.value === "") {
+ alert("Please enter a name for your to-do");
+ }
+ else {
+ if (priorityLevel || priorityLevel === 0) {
+ // adds todo to project
+ const finalizedTodo = todo(title.value, comment.value, dueDate.valueAsDate, priorityLevel);
+ const dummyProjects = getArray();
+ let foundProject = dummyProjects.find (item => item.name === CURRENTPROJECT.textContent);
+
+ foundProject.todos[foundProject.todos.length] = finalizedTodo;
+ setArray(dummyProjects);
+
+ // wipes prompt window
+ document.querySelector("main").removeChild(card);
+ displayTodo(finalizedTodo);
+ }
+ else {
+ alert("Please select a priority for your to-do by clicking the Priority button");
+ }
+ }
+ }
+}
+
+export const editTodo = (cardBody, todo) => {
+ // creates title field and fills with existing title
+ const title = document.createElement('input');
+ title.className = "card-title mb-2 form-control";
+ title.type = "text";
+ // gets title out of existing title (title is the first child of cardBody)
+ title.value = cardBody.firstChild.textContent;
+
+
+ const dueDate = document.createElement('input');
+ dueDate.maxLength = 8;
+ dueDate.className = "card-subtitle text-muted mb-2 form-control";
+ dueDate.type = "date";
+ if (typeof todo.dueDate === "object") {
+ dueDate.value = todo.dueDate.toISOString().slice(0,10);
+ }
+ else {
+ dueDate.value = todo.dueDate.slice(0,10);
+ }
+ dueDate.oninput = () => {
+ const dueDateSplit = dueDate.value.split('-');
+ if (dueDateSplit[0] && dueDateSplit[0].length > 4) {
+ dueDateSplit[0]=dueDateSplit[0].slice(0,4);
+ dueDate.value = dueDateSplit.join('-');
+ }
+ }
+
+ const priority = document.createElement('h6');
+ const oldClassName = "mb-3 btn btn-primary";
+ priority.className = oldClassName;
+ priority.textContent = "Priority";
+ let counter;
+ let priorityLevel = todo.priority;
+ if (todo.priority === 0) {
+ priority.className = oldClassName + " btn-success";
+ priority.textContent = "Priority: Low";
+ counter = 1;
+ }
+ else if (todo.priority === 1) {
+ priority.className = oldClassName + " btn-warning";
+ priority.textContent = "Priority: Medium";
+ counter = 2;
+ }
+ else {
+ priority.className = oldClassName + " btn-danger";
+ priority.textContent = "Priority: High";
+ counter = 0;
+ }
+
+ priority.onclick = () => {
+ if (counter === 0) {
+ priority.className = oldClassName + " btn-success";
+ priority.textContent = "Priority: Low";
+ priorityLevel = counter;
+ counter++;
+ }
+ else if (counter === 1) {
+ priority.className = oldClassName + " btn-warning";
+ priority.textContent = "Priority: Medium";
+ priorityLevel = counter;
+ counter++;
+ }
+ else {
+ priority.className = oldClassName + " btn-danger";
+ priority.textContent = "Priority: High";
+ priorityLevel = counter;
+ counter = 0;
+ }
+ }
+
+ const comment = document.createElement('input');
+ comment.className = "card-text text-muted form-control mb-3";
+ comment.type = "text";
+ comment.value = cardBody.children[3].textContent;
+
+ for (let i = 0; i < 4; i++) {
+ cardBody.removeChild(cardBody.firstChild);
+ }
+
+ cardBody.firstChild.textContent = "Finish";
+ cardBody.firstChild.className = "btn btn-success me-1";
+ cardBody.firstChild.onclick = () => finalizeTodo();
+
+ cardBody.prepend(comment);
+ cardBody.prepend(priority);
+ cardBody.prepend(dueDate);
+ cardBody.prepend(title);
+
+ function finalizeTodo() {
+ // some validation
+ if (title.value === "") {
+ alert("Please enter a name for your to-do");
+ }
+ else {
+ if (priorityLevel || priorityLevel === 0) {
+ todo.title = title.value;
+ todo.description = comment.value;
+ todo.dueDate = dueDate.valueAsDate;
+ todo.priority = priorityLevel;
+
+ // proper handling
+ const dummyProjects = getArray();
+ const foundProject = dummyProjects.find (item => item.name === CURRENTPROJECT.textContent);
+ setArray(dummyProjects);
+
+ // wipes prompt window
+ document.querySelector("main").removeChild(cardBody.parentElement);
+ displayTodo(todo);
+ }
+ else {
+ alert("Please select a priority for your to-do by clicking the Priority button")
+ }
+ }
+ }
+}
+
+const deleteTodo = (todo, card) => {
+ document.querySelector("main").removeChild(card);
+ const dummyProjects = getArray();
+ let foundProject = dummyProjects.find (item => item.name === CURRENTPROJECT.textContent);
+ const todoIndex = foundProject.todos.indexOf(todo);
+ if (todoIndex) {
+ foundProject.todos.splice(todoIndex, 1);
+ }
+ setArray(dummyProjects);
+}
+
+const createProject = (projectName) => {
+ const dummyProjects = getArray();
+ dummyProjects[dummyProjects.length] = project(projectName);
+ setArray(dummyProjects);
+ createProjectDOM(projectName);
+}
+
+const displayProjects = () => {
+ const dummyProjects = getArray();
+ dummyProjects.forEach(item => createProjectDOM(item.name));
+}
\ No newline at end of file
diff --git a/src/incrementer.js b/src/incrementer.js
new file mode 100755
index 0000000..f82184b
--- /dev/null
+++ b/src/incrementer.js
@@ -0,0 +1,5 @@
+// increments date based from today's date on number of days specified
+export const incrementer = (date, days) => {
+ date.setDate(date.getDate() + days);
+ return date;
+}
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
new file mode 100755
index 0000000..55d9acc
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,25 @@
+import { todo } from "./todo.js"
+import { incrementer } from "./incrementer.js";
+import { changeCurrentProject, createProjectDOM } from "./domifier.js";
+import { initDOM } from "./domifier.js";
+import { getArray, setArray } from "./projects.js";
+import { project } from "./project.js";
+
+const TODAY = new Date();
+let dummyProjects = getArray();
+
+dummyProjects[0] = project("Default Project");
+
+const defaultTodo = todo(
+ "Default Todo",
+ "This is the default to-do for the to-do list. Feel free to add some more!",
+ incrementer(TODAY, 7),
+ 0
+);
+
+
+dummyProjects[0].todos[dummyProjects[0].todos.length] = defaultTodo;
+setArray(dummyProjects);
+
+initDOM();
+changeCurrentProject(dummyProjects[0].name);
\ No newline at end of file
diff --git a/src/project.js b/src/project.js
new file mode 100755
index 0000000..46acd20
--- /dev/null
+++ b/src/project.js
@@ -0,0 +1,9 @@
+export const project = (name) => {
+ // sets up array of todo objects
+ let todos = []
+
+ return {
+ name,
+ todos
+ }
+}
\ No newline at end of file
diff --git a/src/projects.js b/src/projects.js
new file mode 100755
index 0000000..72028f9
--- /dev/null
+++ b/src/projects.js
@@ -0,0 +1,52 @@
+// logic for the projects array itself
+import { storageAvailable } from "./storageAvailable.js";
+
+// get and set arrays - get from local storage if available, if not then get from a global var
+// set it here too, as well as extend the regular array methods
+// everything will be here regards getting and setting this stuff, without a need to expose the actual array out to other modules
+
+// master projects array
+let projectsArray = [];
+
+// tests if a "projects" item exists in local storage
+const projectsExists = localStorage.getItem("projects") ? true : false;
+
+// returns the proper array depending on where it is
+export const getArray = () => {
+ // localStorage exists
+ if (storageAvailable) {
+ // "projects" exists
+ if (projectsExists) {
+ // set projects array to local storage and return
+ projectsArray = JSON.parse(localStorage.projects);
+ return projectsArray;
+ }
+ else {
+ return projectsArray;
+ }
+ }
+ // otherwise return the projects array here
+ else {
+ return projectsArray;
+ }
+}
+
+// easiest workaround to getting too in-depth - passed array is set as the main, depending on if storage exists, etc.
+export const setArray = (array) => {
+ // set the master array to passed array - regardless of localStorage
+ projectsArray = array;
+ // check for localStorage
+ if (storageAvailable) {
+ // and existing "projects"
+ if (projectsExists) {
+ // remove existing array from localStorage
+ localStorage.removeItem("projects");
+ // add the modified array
+ localStorage.projects = JSON.stringify(projectsArray);
+ }
+ // if "projects" doesn't exist, add it
+ else {
+ localStorage.projects = JSON.stringify(projectsArray);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/storageAvailable.js b/src/storageAvailable.js
new file mode 100755
index 0000000..81b01fb
--- /dev/null
+++ b/src/storageAvailable.js
@@ -0,0 +1,29 @@
+function storageAvailableFunc(type) {
+ let storage;
+ try {
+ storage = window[type];
+ const x = "__storage_test__";
+ storage.setItem(x, x);
+ storage.removeItem(x);
+ return true;
+ } catch (e) {
+ return (
+ e instanceof DOMException &&
+ // everything except Firefox
+ (e.code === 22 ||
+ // Firefox
+ e.code === 1014 ||
+ // test name field too, because code might not be present
+ // everything except Firefox
+ e.name === "QuotaExceededError" ||
+ // Firefox
+ e.name === "NS_ERROR_DOM_QUOTA_REACHED") &&
+ // acknowledge QuotaExceededError only if there's something already stored
+ storage &&
+ storage.length !== 0
+ );
+ }
+}
+// copyright MDN https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
+
+export const storageAvailable = storageAvailableFunc("localStorage");
\ No newline at end of file
diff --git a/src/style.css b/src/style.css
new file mode 100755
index 0000000..600b41e
--- /dev/null
+++ b/src/style.css
@@ -0,0 +1,45 @@
+.nav-pills {
+ gap: 1rem;
+}
+
+.dropdown-toggle::after {
+ margin-left: .3em;
+ vertical-align: .15em;
+}
+
+.card {
+ width: 18rem;
+}
+
+.col-sm-6 {
+ flex: 1;
+ width: auto;
+}
+
+.card {
+ box-shadow: 0.5px 0.5px 5px black;
+ margin: 0rem 1.5rem 1.5rem 0rem;
+ flex-grow: 0;
+ flex-shrink: 0;
+}
+
+.prioritybtn {
+ cursor: default;
+}
+
+main {
+ display: inline-flex;
+ flex-flow: row wrap;
+ overflow: scroll;
+ justify-content: flex-start
+}
+
+/* hides scrollbar*/
+main::-webkit-scrollbar {
+ display: none;
+}
+
+main {
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+}
\ No newline at end of file
diff --git a/src/todo.js b/src/todo.js
new file mode 100755
index 0000000..338b17b
--- /dev/null
+++ b/src/todo.js
@@ -0,0 +1,9 @@
+// todo factory function
+export const todo = (title, description, dueDate, priority) => {
+ return {
+ title,
+ description,
+ dueDate,
+ priority
+ }
+}
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100755
index 0000000..51ed023
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ mode: 'development'
+};
\ No newline at end of file