From 5e72bb4b22ba9a61cd1b91d70b530793f520ab74 Mon Sep 17 00:00:00 2001 From: Wes Appler <145372368+wes-otf@users.noreply.github.com> Date: Tue, 15 Oct 2024 08:05:23 -0400 Subject: [PATCH] Updated ESLint to v9.12.0 & migrated to a flat config file (#4162) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some of the translation features I was using optional chaining & eslint would toss errors saying it was invalid despite it working. This led me to exploring the config to find the [yaml config we used was depreciated](https://eslint.org/docs/latest/use/configure/configuration-files-deprecated). This PR updates to a newer version of eslint & migrates the config to the [flat file version](https://eslint.org/docs/latest/use/configure/configuration-files#configuration-file) (and now optional chaining is recognized 🥳). Some code changes that came with the updated linting: - [As of ES6](https://262.ecma-international.org/6.0/#sec-strict-mode-code) modules are always in strict mode, thus `"use strict"` isn't needed - Removed unused var - Removed unneeded `eslint-disable` comment There are also a ton of JSDoc warnings now - I was going to remove them but I think JSDoc is actually a weak point in our code documentation so maybe the in-terminal annoyances will be a good reminder to do a quick write up --- .eslintrc.yaml | 132 ---- eslint.config.mjs | 155 +++++ .../cookieconsent/static/js/cookieconsent.js | 36 +- .../javascript/all-reviews-table.js | 2 - .../javascript/all-submissions-table.js | 2 - .../application-form-links-new-window.js | 2 - .../static_src/javascript/application-form.js | 2 - hypha/static_src/javascript/batch-actions.js | 2 - hypha/static_src/javascript/deliverables.js | 2 - .../javascript/determination-template.js | 1 - .../javascript/document-category.js | 2 - hypha/static_src/javascript/edit-comment.js | 2 - .../static_src/javascript/fancybox-global.js | 2 - hypha/static_src/javascript/file-uploads.js | 2 - .../javascript/form-group-toggle.js | 2 - hypha/static_src/javascript/main.js | 10 +- .../javascript/multi-input-fields.js | 2 - .../javascript/past-reports-pagination.js | 2 - .../javascript/report-calculator.js | 56 +- .../javascript/submission-filters.js | 4 +- .../javascript/submission-form-copy.js | 2 - .../javascript/submission-text-cleanup.js | 2 - hypha/static_src/javascript/tabs.js | 2 - .../javascript/tinymce-word-count.js | 4 +- .../javascript/toggle-payment-block.js | 2 - hypha/static_src/javascript/toggle-related.js | 2 - .../static_src/javascript/two-factor-focus.js | 2 - package-lock.json | 572 +++++++++++++----- package.json | 8 +- 29 files changed, 657 insertions(+), 359 deletions(-) delete mode 100644 .eslintrc.yaml create mode 100644 eslint.config.mjs diff --git a/.eslintrc.yaml b/.eslintrc.yaml deleted file mode 100644 index 6e674e488a..0000000000 --- a/.eslintrc.yaml +++ /dev/null @@ -1,132 +0,0 @@ -extends: - - eslint:recommended - - prettier -env: - browser: true - commonjs: true - es6: true - -ignorePatterns: - - "*.min.js" - - "**/esm/*.js" - -globals: - jQuery: true -rules: - array-bracket-spacing: - - "error" - - never - block-scoped-var: "error" - comma-spacing: "error" - comma-style: - - "error" - - last - computed-property-spacing: - - "error" - - never - curly: - - "error" - - all - eol-last: "error" - eqeqeq: - - "error" - - smart - guard-for-in: "error" - key-spacing: - - "error" - - beforeColon: false - afterColon: true - keyword-spacing: - - "error" - - before: true - after: true - linebreak-style: - - "error" - - unix - lines-around-comment: - - "error" - - beforeBlockComment: true - afterBlockComment: false - new-parens: "error" - no-array-constructor: "error" - no-caller: "error" - no-catch-shadow: "error" - no-eval: "error" - no-extend-native: "error" - no-extra-bind: "error" - no-extra-parens: - - "error" - - functions - no-implied-eval: "error" - no-iterator: "error" - no-label-var: "error" - no-labels: "error" - no-lone-blocks: "error" - no-loop-func: "error" - no-multi-spaces: "error" - no-multi-str: "error" - no-native-reassign: "error" - no-nested-ternary: "error" - no-new-func: "error" - no-new-object: "error" - no-new-wrappers: "error" - no-octal-escape: "error" - no-process-exit: "error" - no-proto: "error" - no-return-assign: "error" - no-script-url: "error" - no-sequences: "error" - no-shadow-restricted-names: "error" - no-spaced-func: "error" - no-trailing-spaces: "error" - no-undef-init: "error" - no-undefined: "error" - no-unused-expressions: "error" - no-unused-vars: - - "error" - - vars: all - args: none - no-with: "error" - one-var: - - "error" - - never - semi: - - "error" - - always - semi-spacing: - - "error" - - before: false - after: true - space-before-blocks: - - "error" - - always - space-before-function-paren: - - "error" - - anonymous: always - named: never - space-in-parens: - - "error" - - never - space-infix-ops: "error" - space-unary-ops: - - "error" - - words: true - nonwords: false - spaced-comment: - - "error" - - always - strict: - - "error" - - function - yoda: - - "error" - - never - max-nested-callbacks: - - "warn" - - 3 - valid-jsdoc: - - "warn" - - prefer: - returns: return - property: prop - requireReturn: false diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..8dcd75faa9 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,155 @@ +import globals from "globals"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import js from "@eslint/js"; +import jsdoc from "eslint-plugin-jsdoc"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +export default [ + { + ignores: ["**/*.min.js", "**/esm/*.js"], + }, + ...compat.extends("eslint:recommended", "prettier"), + jsdoc.configs["flat/recommended"], + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.commonjs, + jQuery: true, + }, + }, + + plugins: { + jsdoc, + }, + + rules: { + "array-bracket-spacing": ["error", "never"], + "block-scoped-var": "error", + "comma-spacing": "error", + "comma-style": ["error", "last"], + "computed-property-spacing": ["error", "never"], + curly: ["error", "all"], + "eol-last": "error", + eqeqeq: ["error", "smart"], + "guard-for-in": "error", + + "key-spacing": [ + "error", + { + beforeColon: false, + afterColon: true, + }, + ], + + "keyword-spacing": [ + "error", + { + before: true, + after: true, + }, + ], + + "linebreak-style": ["error", "unix"], + + "lines-around-comment": [ + "error", + { + beforeBlockComment: true, + afterBlockComment: false, + }, + ], + + "new-parens": "error", + "no-array-constructor": "error", + "no-caller": "error", + "no-catch-shadow": "error", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-extra-parens": ["error", "functions"], + "no-implied-eval": "error", + "no-iterator": "error", + "no-label-var": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-loop-func": "error", + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-native-reassign": "error", + "no-nested-ternary": "error", + "no-new-func": "error", + "no-new-object": "error", + "no-new-wrappers": "error", + "no-octal-escape": "error", + "no-process-exit": "error", + "no-proto": "error", + "no-return-assign": "error", + "no-script-url": "error", + "no-sequences": "error", + "no-shadow-restricted-names": "error", + "no-spaced-func": "error", + "no-trailing-spaces": "error", + "no-undef-init": "error", + "no-undefined": "error", + "no-unused-expressions": "error", + + "no-unused-vars": [ + "error", + { + vars: "all", + args: "none", + }, + ], + + "no-with": "error", + "one-var": ["error", "never"], + semi: ["error", "always"], + + "semi-spacing": [ + "error", + { + before: false, + after: true, + }, + ], + + "space-before-blocks": ["error", "always"], + + "space-before-function-paren": [ + "error", + { + anonymous: "always", + named: "never", + }, + ], + + "space-in-parens": ["error", "never"], + "space-infix-ops": "error", + + "space-unary-ops": [ + "error", + { + words: true, + nonwords: false, + }, + ], + + "spaced-comment": ["error", "always"], + strict: ["error", "function"], + yoda: ["error", "never"], + "max-nested-callbacks": ["warn", 3], + "jsdoc/require-description": "warn", + "jsdoc/tag-lines": ["off", "never"], + }, + }, +]; diff --git a/hypha/cookieconsent/static/js/cookieconsent.js b/hypha/cookieconsent/static/js/cookieconsent.js index 5c060b8053..3a33c43b68 100644 --- a/hypha/cookieconsent/static/js/cookieconsent.js +++ b/hypha/cookieconsent/static/js/cookieconsent.js @@ -1,6 +1,4 @@ (function () { - "use strict"; - // Used when an analytics cookie notice is enabled const ACCEPT = "accept"; const DECLINE = "decline"; @@ -19,7 +17,9 @@ const CLASS_JS_LEARNMORE_EXPAND = `${CLASS_JS_LEARNMORE}-expand`; const cookieconsent = document.querySelector(`.${CLASS_COOKIECONSENT}`); - if (!cookieconsent) return; + if (!cookieconsent) { + return; + } const cookieButtons = cookieconsent.querySelectorAll( "button[data-consent]" @@ -28,10 +28,20 @@ ".button--learn-more" ); + /** + * Pull the cookie consent value from localStorage + * + * @returns {(string|null)} A string if consent value exists, null if not + */ function getConsentValue() { return localStorage.getItem(COOKIECONSENT_KEY); } + /** + * Set the cookie consent value in localStorage + * + * @param {("accept"|"decline"|"ack")} value - consent value to set + */ function setConsentValue(value) { if ([ACCEPT, DECLINE, ACK].includes(value)) { localStorage.setItem(COOKIECONSENT_KEY, value); @@ -41,10 +51,16 @@ } } + /** + * Trigger the cookie consent prompt to open + */ function openConsentPrompt() { cookieconsent.classList.add(CLASS_JS_CONSENT_OPEN); } + /** + * Trigger cookie consent prompt to close + */ function closeConsentPrompt() { cookieconsent.classList.remove(CLASS_JS_CONSENT_OPEN); } @@ -53,6 +69,11 @@ window.openConsentPrompt = openConsentPrompt; window.closeConsentPrompt = closeConsentPrompt; + /** + * Trigger the "Learn More" prompt on the cookie banner to open/close + * + * @param {boolean} open - true to open learn more prompt, false to close + */ function toggleLearnMore(open) { const content = cookieconsent.querySelector(`.${CLASS_COOKIECONTENT}`); if (open) { @@ -66,7 +87,12 @@ setInputTabIndex(`.${CLASS_COOKIEBRIEF}`, open ? -1 : 0); } - // Adds "tabability" to menu buttons/toggles + /** + * Adds "tabability" to menu buttons/toggles + * + * @param {string} wrapperClassSelector - wrapper class to set tabability of inputs on + * @param {number} tabValue - tab index value to set on all input items in the wrapper class + */ function setInputTabIndex(wrapperClassSelector, tabValue) { const wrapper = cookieconsent.querySelector(wrapperClassSelector); const tabables = wrapper.querySelectorAll("button, input"); @@ -75,7 +101,7 @@ // Open the prompt if consent value is undefined OR if analytics has been added since the user ack'd essential cookies if ( - getConsentValue() == undefined || + getConsentValue() == null || (getConsentValue() === ACK && cookieButtons.length > 2) ) { openConsentPrompt(); diff --git a/hypha/static_src/javascript/all-reviews-table.js b/hypha/static_src/javascript/all-reviews-table.js index 41063de80a..37b697e275 100644 --- a/hypha/static_src/javascript/all-reviews-table.js +++ b/hypha/static_src/javascript/all-reviews-table.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - // Allow click and drag scrolling within reviews table wrapper $(".js-reviews-table").attachDragger(); diff --git a/hypha/static_src/javascript/all-submissions-table.js b/hypha/static_src/javascript/all-submissions-table.js index 89526e7052..412498d39f 100644 --- a/hypha/static_src/javascript/all-submissions-table.js +++ b/hypha/static_src/javascript/all-submissions-table.js @@ -1,6 +1,4 @@ (function () { - "use strict"; - let submission_arrow = document.createElement("span"); submission_arrow.classList.add("arrow"); diff --git a/hypha/static_src/javascript/application-form-links-new-window.js b/hypha/static_src/javascript/application-form-links-new-window.js index e2a2160e06..b6ef3ce5d9 100644 --- a/hypha/static_src/javascript/application-form-links-new-window.js +++ b/hypha/static_src/javascript/application-form-links-new-window.js @@ -1,6 +1,4 @@ (function () { - "use strict"; - // Make links on application forms open in a new window/tab. const links = document.querySelectorAll(".application-form a"); links.forEach(function (link) { diff --git a/hypha/static_src/javascript/application-form.js b/hypha/static_src/javascript/application-form.js index 433d207955..096fb7f8ad 100644 --- a/hypha/static_src/javascript/application-form.js +++ b/hypha/static_src/javascript/application-form.js @@ -1,6 +1,4 @@ (function () { - "use strict"; - const form = document.querySelector(".application-form"); const button = form.querySelector("[type=submit]"); const required = form.querySelectorAll("input[required]"); diff --git a/hypha/static_src/javascript/batch-actions.js b/hypha/static_src/javascript/batch-actions.js index d900d749df..bac984732f 100644 --- a/hypha/static_src/javascript/batch-actions.js +++ b/hypha/static_src/javascript/batch-actions.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - const $body = $("body"); const $checkbox = $(".js-batch-select"); const $allCheckboxInput = $(".js-batch-select-all"); diff --git a/hypha/static_src/javascript/deliverables.js b/hypha/static_src/javascript/deliverables.js index daaed11626..a42506ee84 100644 --- a/hypha/static_src/javascript/deliverables.js +++ b/hypha/static_src/javascript/deliverables.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - $("#deliverables").on("change", function (e) { e.preventDefault(); var $selected = $(this).find("option:selected"); diff --git a/hypha/static_src/javascript/determination-template.js b/hypha/static_src/javascript/determination-template.js index d23f2fce09..fb3d6a4d76 100644 --- a/hypha/static_src/javascript/determination-template.js +++ b/hypha/static_src/javascript/determination-template.js @@ -1,5 +1,4 @@ (function () { - "use strict"; const field_blocks_ids = JSON.parse( document.getElementById("block-ids").textContent ); diff --git a/hypha/static_src/javascript/document-category.js b/hypha/static_src/javascript/document-category.js index 7069d9fa4b..5f951f01eb 100644 --- a/hypha/static_src/javascript/document-category.js +++ b/hypha/static_src/javascript/document-category.js @@ -1,7 +1,5 @@ // eslint-disable-next-line no-unused-vars function handleCategory(category) { - "use strict"; - document.getElementById("id_category").value = category; document.getElementsByClassName("form__group id_category")[0].hidden = "true"; diff --git a/hypha/static_src/javascript/edit-comment.js b/hypha/static_src/javascript/edit-comment.js index d092bf5fe0..78539b6a9a 100644 --- a/hypha/static_src/javascript/edit-comment.js +++ b/hypha/static_src/javascript/edit-comment.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - const comment = ".js-comment"; const pageDown = ".js-pagedown"; const editBlock = ".js-edit-block"; diff --git a/hypha/static_src/javascript/fancybox-global.js b/hypha/static_src/javascript/fancybox-global.js index a4b6374c32..485dfe2c70 100644 --- a/hypha/static_src/javascript/fancybox-global.js +++ b/hypha/static_src/javascript/fancybox-global.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - $("[data-fancybox]").fancybox({ animationDuration: 350, animationEffect: "fade", diff --git a/hypha/static_src/javascript/file-uploads.js b/hypha/static_src/javascript/file-uploads.js index 3b91e99225..8894f72092 100644 --- a/hypha/static_src/javascript/file-uploads.js +++ b/hypha/static_src/javascript/file-uploads.js @@ -1,6 +1,4 @@ jQuery(function ($) { - "use strict"; - // Initialize django-file-form $("form") .get() diff --git a/hypha/static_src/javascript/form-group-toggle.js b/hypha/static_src/javascript/form-group-toggle.js index 8035cf70f5..2f0ea92d05 100644 --- a/hypha/static_src/javascript/form-group-toggle.js +++ b/hypha/static_src/javascript/form-group-toggle.js @@ -1,7 +1,5 @@ /* eslint-disable no-loop-func */ (function ($) { - "use strict"; - var i; for (i = 2; i < 20; i++) { var $field_group = $(".field-group-" + i); diff --git a/hypha/static_src/javascript/main.js b/hypha/static_src/javascript/main.js index 731e1c3088..f5a4fd4cfc 100644 --- a/hypha/static_src/javascript/main.js +++ b/hypha/static_src/javascript/main.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - // reset mobile filters if they're open past the tablet breakpoint $(window) .resize(function resize() { @@ -32,10 +30,18 @@ if (typeof window.Cookies !== "undefined") { csrftoken = window.Cookies.get("csrftoken"); } + + /** + * Checks that the specified HTTP method doesn't require CSRF protection + * + * @param {string} method - HTTP method to check + * @returns {boolean} true if the method doesn't require CSRF protection, true otherwise. + */ function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return /^(GET|HEAD|OPTIONS|TRACE)$/.test(method); } + $.ajaxSetup({ beforeSend: function (xhr, settings) { if ( diff --git a/hypha/static_src/javascript/multi-input-fields.js b/hypha/static_src/javascript/multi-input-fields.js index f64a74b1c2..651905e43a 100644 --- a/hypha/static_src/javascript/multi-input-fields.js +++ b/hypha/static_src/javascript/multi-input-fields.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - // Visibility Index is set to 0 initially in the backend. But in case of edit application forms // with multiple values already set, we need to update it. The visibility index helps // to get the next field from the list of hidden inputs to be shown to an applicant on clicking the add button. diff --git a/hypha/static_src/javascript/past-reports-pagination.js b/hypha/static_src/javascript/past-reports-pagination.js index 533db9baab..33a32f1c05 100644 --- a/hypha/static_src/javascript/past-reports-pagination.js +++ b/hypha/static_src/javascript/past-reports-pagination.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - function pastReportsPagination() { $(".js-data-block-pagination").click((e) => { e.preventDefault(); diff --git a/hypha/static_src/javascript/report-calculator.js b/hypha/static_src/javascript/report-calculator.js index 755e28e34b..8a81cc67e9 100644 --- a/hypha/static_src/javascript/report-calculator.js +++ b/hypha/static_src/javascript/report-calculator.js @@ -1,5 +1,4 @@ (function ($) { - "use strict"; const reportDataEl = document.getElementById("reportData"); if (!reportDataEl) { return; @@ -25,6 +24,9 @@ ".js-next-report-due-slot" ); + /** + * Set initial values & setup event listeners + */ function init() { // Set on page load setProjectEnd(); @@ -37,24 +39,33 @@ addReportPeriodEvents(); } - // Sets the project end date in the form info box + /** + * Sets the project end date in the form info box + */ function setProjectEnd() { projectEndSlot.innerHTML = reportData.projectEndDate; } - // Set the reporting frequency + /** + * Set the reporting frequency + */ function setFrequency() { frequencyPeriodSlot.innerHTML = `${frequencyPeriodSlot.value}`; frequencyNumberSlot.innerHTML = frequencyNumberInput.value; pluraliseTimePeriod(frequencyNumberInput.value); } - // Set the reporting period start date + /** + * Set the reporting period start date + */ function setReportPeriodStart() { const startDate = new Date(reportData.startDate); periodStartSlot.innerHTML = startDate.toISOString().slice(0, 10); } + /** + * Set the reporting period + */ function setReportPeriod() { // Update the reporting period end date (next report date) periodEndSlot.innerHTML = startDateInput.value; @@ -76,13 +87,18 @@ `; } + /** + * Set report period once start date recieves input + */ function addReportPeriodEvents() { startDateInput.oninput = () => { setReportPeriod(); }; } - // Update reporting frequency as the options are changed + /** + * Update reporting frequency as the options are changed + */ function addFrequencyEvents() { frequencyNumberInput.oninput = () => { setFrequency(); @@ -93,14 +109,26 @@ }; } + /** + * Adds an "s" to the frequencyPeriodSelect text if plural, removes "s" otherwise. + * + * @param {number} number - number to determine plural for + */ function pluraliseTimePeriod(number) { frequencyPeriodSlot.innerHTML = `${frequencyPeriodSelect.value}${ Number(number) === 1 ? "" : "s" }`; } - // Get the number of days between two dates - function dateDiffInDays(startDate, EndDate) { + /** + * Get the difference of days between two dates + * + * @param {Date} startDate - the subtrahend date + * @param {Date} endDate - the minuend date + * + * @returns {number} Difference of days betwen the given dates + */ + function dateDiffInDays(startDate, endDate) { const msPerDay = 1000 * 60 * 60 * 24; const utc1 = Date.UTC( startDate.getFullYear(), @@ -108,15 +136,21 @@ startDate.getDate() ); const utc2 = Date.UTC( - EndDate.getFullYear(), - EndDate.getMonth(), - EndDate.getDate() + endDate.getFullYear(), + endDate.getMonth(), + endDate.getDate() ); return Math.floor((utc2 - utc1) / msPerDay); } - // Convert days into weeks and days + /** + * Convert days into weeks and days + * + * @param {number} days - number of days + * + * @returns {{weeks: number, days: number}} number of weeks & days + */ function getWeeks(days) { return { weeks: Math.floor(days / 7), diff --git a/hypha/static_src/javascript/submission-filters.js b/hypha/static_src/javascript/submission-filters.js index 2559211c5f..bb015a8c35 100644 --- a/hypha/static_src/javascript/submission-filters.js +++ b/hypha/static_src/javascript/submission-filters.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - // Variables const $toggleButton = $(".js-toggle-filters"); const $closeButton = $(".js-close-filters"); @@ -148,7 +146,7 @@ dropdowns.forEach((dropdown) => { $(dropdown).val(null).trigger("change"); $(".select2-selection.is-active").removeClass(filterActiveClass); - mobileFilterPadding(dropdown); // eslint-disable-line no-undef + mobileFilterPadding(dropdown); }); }); diff --git a/hypha/static_src/javascript/submission-form-copy.js b/hypha/static_src/javascript/submission-form-copy.js index 5a7f89beea..d2b4db8a05 100644 --- a/hypha/static_src/javascript/submission-form-copy.js +++ b/hypha/static_src/javascript/submission-form-copy.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - // Strip html tags from text. function strip(html) { var doc = new DOMParser().parseFromString(html, "text/html"); diff --git a/hypha/static_src/javascript/submission-text-cleanup.js b/hypha/static_src/javascript/submission-text-cleanup.js index 409e46b5cf..34e26db18a 100644 --- a/hypha/static_src/javascript/submission-text-cleanup.js +++ b/hypha/static_src/javascript/submission-text-cleanup.js @@ -1,6 +1,4 @@ (function () { - "use strict"; - const richtextanswers = document.querySelector(".rich-text--answers"); // Remove p tags with only whitespace inside. diff --git a/hypha/static_src/javascript/tabs.js b/hypha/static_src/javascript/tabs.js index 905accbbff..a6b85df9f2 100644 --- a/hypha/static_src/javascript/tabs.js +++ b/hypha/static_src/javascript/tabs.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - let Tabs = class { static selector() { return ".js-tabs"; diff --git a/hypha/static_src/javascript/tinymce-word-count.js b/hypha/static_src/javascript/tinymce-word-count.js index d776654a08..dc9d8f006b 100644 --- a/hypha/static_src/javascript/tinymce-word-count.js +++ b/hypha/static_src/javascript/tinymce-word-count.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - var word_count_interval; const observer_options = { @@ -11,7 +9,7 @@ let word_count; try { word_count = parseInt(el.innerText.match(/\d+/)[0], 10); - } catch (e) { + } catch { word_count = 0; } const word_limit = parseInt( diff --git a/hypha/static_src/javascript/toggle-payment-block.js b/hypha/static_src/javascript/toggle-payment-block.js index ad123ec868..9b1825ca76 100644 --- a/hypha/static_src/javascript/toggle-payment-block.js +++ b/hypha/static_src/javascript/toggle-payment-block.js @@ -1,6 +1,4 @@ (function ($) { - "use strict"; - function togglePaymentBlock() { $(".js-payment-block-rejected-link").click(function (e) { e.preventDefault(); diff --git a/hypha/static_src/javascript/toggle-related.js b/hypha/static_src/javascript/toggle-related.js index 721cd1871c..8862eb5b03 100644 --- a/hypha/static_src/javascript/toggle-related.js +++ b/hypha/static_src/javascript/toggle-related.js @@ -1,6 +1,4 @@ (function () { - "use strict"; - const related_sidebar = document.querySelector(".related-sidebar"); if (related_sidebar) { const content_height = related_sidebar diff --git a/hypha/static_src/javascript/two-factor-focus.js b/hypha/static_src/javascript/two-factor-focus.js index b031686063..0d6adb8e58 100644 --- a/hypha/static_src/javascript/two-factor-focus.js +++ b/hypha/static_src/javascript/two-factor-focus.js @@ -1,5 +1,3 @@ (function ($) { - "use strict"; - $("#id_generator-token").focus(); })(jQuery); diff --git a/package-lock.json b/package-lock.json index 8d14a5610d..3b0ec4ab8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,14 +13,18 @@ "@babel/cli": "^7.25.6", "@babel/core": "^7.25.2", "@babel/preset-env": "^7.25.4", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "^9.12.0", "@tailwindcss/forms": "^0.5.9", "@tailwindcss/typography": "^0.5.15", "alpinejs": "^3.14.1", "core-js": "^3.38.1", "daterangepicker": "^3.1.0", - "eslint": "^8.57.1", + "eslint": "^9.12.0", "eslint-config-prettier": "^8.10.0", + "eslint-plugin-jsdoc": "^50.3.1", "eslint-plugin-template": "^0.7.0", + "globals": "^15.11.0", "htmx.org": "^2.0.2", "nodemon": "^3.1.7", "npm-run-all2": "^6.2.3", @@ -955,6 +959,15 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", @@ -1781,6 +1794,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { "version": "7.25.6", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", @@ -1873,6 +1895,21 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.48.0.tgz", + "integrity": "sha512-G6QUWIcC+KvSwXNsJyDTHvqUdNoAVJPPgkc3+Uk4WBKqZvoXhlvazOgm9aL0HwihJLQf0l+tOE2UFzXBqCqgDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~4.1.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -1889,24 +1926,51 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -1914,51 +1978,79 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", "dev": true, "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@eslint/plugin-kit": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.18.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -1974,13 +2066,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -2149,6 +2247,19 @@ "node": ">=14" } }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@tailwindcss/forms": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.9.tgz", @@ -2178,11 +2289,19 @@ "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" }, "node_modules/@vue/reactivity": { "version": "3.1.5", @@ -2285,6 +2404,16 @@ "node": ">= 8" } }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -2535,6 +2664,16 @@ "node": ">= 6" } }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2705,18 +2844,6 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "dev": true }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -2816,6 +2943,13 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true, + "license": "MIT" + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2836,59 +2970,64 @@ } }, "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.12.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.3.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-prettier": { @@ -2903,6 +3042,58 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-plugin-jsdoc": { + "version": "50.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.1.tgz", + "integrity": "sha512-SY9oUuTMr6aWoJggUS40LtMjsRzJPB5ZT7F432xZIHK3EfHF+8i48GbUBpwanrtlL9l1gILNTHK9o8gEhYLcKA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.48.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.3.6", + "escape-string-regexp": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.6.0", + "parse-imports": "^2.1.1", + "semver": "^7.6.3", + "spdx-expression-parse": "^4.0.0", + "synckit": "^0.9.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/eslint-plugin-template": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/eslint-plugin-template/-/eslint-plugin-template-0.7.0.tgz", @@ -2913,16 +3104,17 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -3001,6 +3193,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -3013,21 +3218,6 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3050,27 +3240,42 @@ } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.1.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -3083,6 +3288,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -3161,15 +3367,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -3201,17 +3408,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -3361,12 +3568,16 @@ } }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", + "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globby": { @@ -3404,12 +3615,6 @@ "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", "dev": true }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -3605,15 +3810,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -3680,6 +3876,16 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz", + "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -4220,6 +4426,20 @@ "node": ">=6" } }, + "node_modules/parse-imports": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", + "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", + "dev": true, + "license": "Apache-2.0 AND MIT", + "dependencies": { + "es-module-lexer": "^1.5.3", + "slashes": "^3.0.12" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -4821,22 +5041,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -4981,6 +5185,13 @@ "node": ">=6" } }, + "node_modules/slashes": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", + "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", + "dev": true, + "license": "ISC" + }, "node_modules/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -5041,6 +5252,31 @@ "node": ">=0.10.0" } }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5563,6 +5799,23 @@ "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", "dev": true }, + "node_modules/synckit": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/tabbable": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", @@ -5733,6 +5986,13 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5745,18 +6005,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", diff --git a/package.json b/package.json index 49051352ed..394fb0e6fd 100644 --- a/package.json +++ b/package.json @@ -33,14 +33,18 @@ "@babel/cli": "^7.25.6", "@babel/core": "^7.25.2", "@babel/preset-env": "^7.25.4", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "^9.12.0", "@tailwindcss/forms": "^0.5.9", "@tailwindcss/typography": "^0.5.15", "alpinejs": "^3.14.1", "core-js": "^3.38.1", "daterangepicker": "^3.1.0", - "eslint": "^8.57.1", + "eslint": "^9.12.0", "eslint-config-prettier": "^8.10.0", + "eslint-plugin-jsdoc": "^50.3.1", "eslint-plugin-template": "^0.7.0", + "globals": "^15.11.0", "htmx.org": "^2.0.2", "nodemon": "^3.1.7", "npm-run-all2": "^6.2.3", @@ -72,7 +76,7 @@ "dev:build:images": "npm run build:images", "lint:prettier": "prettier . --check", "lint:sass": "stylelint \"hypha/static_src/sass/**/*.scss\"", - "lint:js": "eslint \"hypha/static_src/javascript/**/*.js\"", + "lint:js": "eslint \"hypha/static_src/javascript/**/*.js\" \"hypha/cookieconsent/static/js/**/*.js\"", "collectstatic": "python manage.py collectstatic --no-post-process --noinput --verbosity 0 --settings=hypha.settings.dev", "clean": "rm -rf ./static ./hypha/static_compiled" },