From 488dd75e2966edf6d2ece3e288d748fc09ecaa25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20S=C3=A4ume?= Date: Thu, 23 May 2024 19:18:48 +0200 Subject: [PATCH] Setup QS --- .gitea/workflows/lint.yml | 18 +++++ .prettierrc.json | 10 +++ Makefile | 2 + src/answer.js | 43 ++++++----- src/fetch.js | 157 ++++++++++++++++++++------------------ src/main.user.js | 37 ++++----- types/GM_getValue.d.js | 2 +- 7 files changed, 156 insertions(+), 113 deletions(-) create mode 100644 .gitea/workflows/lint.yml create mode 100644 .prettierrc.json create mode 100644 Makefile diff --git a/.gitea/workflows/lint.yml b/.gitea/workflows/lint.yml new file mode 100644 index 0000000..7078994 --- /dev/null +++ b/.gitea/workflows/lint.yml @@ -0,0 +1,18 @@ +name: "Linting" + +on: + push: + branches: + - main + +jobs: + javadoc: + name: "Javadoc" + runs-on: "ubuntu-latest" + container: + image: "git.euph.dev/actions/runner-js-latest:latest" + steps: + - name: "Checkout" + uses: "https://git.euph.dev/actions/checkout@v3" + - name: "Prettier" + run: npx prettier src/ types/ --check --log-level=error \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..70e2b71 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "useTabs": false, + "tabWidth": 4, + "arrowParens": "avoid", + "bracketSameLine": false, + "singleQuote": true, + "semi": true, + "trailingComma": "none", + "endOfLine": "lf" +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1be6144 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +lint: + @npx prettier src/ types/ --write \ No newline at end of file diff --git a/src/answer.js b/src/answer.js index e3893f8..586e55f 100644 --- a/src/answer.js +++ b/src/answer.js @@ -1,24 +1,24 @@ /** - * - * @param {Array} answerData - * @returns + * + * @param {Array} answerData + * @returns */ -function answerQuestion(answerData){ - const question = document.querySelector(".question:not(.hidden)"); +function answerQuestion(answerData) { + const question = document.querySelector('.question:not(.hidden)'); if (!question) { return; } - const questionTextDom = question.querySelector(".questionText .mattext"); + const questionTextDom = question.querySelector('.questionText .mattext'); if (!questionTextDom) return; const questionText = questionTextDom.textContent.trim(); - const answersDom = question.querySelector("ul.coreContent"); + const answersDom = question.querySelector('ul.coreContent'); if (!answersDom) return; const answers = answersDom.children; - for (let answer of Array.from(answers)) { - const input = answer.querySelector("input"); + for (let answer of Array.from(answers)) { + const input = answer.querySelector('input'); if (!input) continue; input.checked = false; } @@ -29,17 +29,17 @@ function answerQuestion(answerData){ } for (const answer of correctAnswers) { - const input = answer.querySelector("input"); + const input = answer.querySelector('input'); if (!input) continue; input.checked = true; } } /** - * - * @param {Array} answerData - * @param {string} questionText - * @returns + * + * @param {Array} answerData + * @param {string} questionText + * @returns */ function findAnswers(answerData, questionText, answers) { if (answerData === null) { @@ -51,7 +51,12 @@ function findAnswers(answerData, questionText, answers) { if (matchAnswer(questionText.trim(), entry.question.trim())) { for (let availableAnswer of answers) { for (let possibleAnswer of entry.answers) { - if (matchAnswer(availableAnswer.textContent.trim(), possibleAnswer)) { + if ( + matchAnswer( + availableAnswer.textContent.trim(), + possibleAnswer + ) + ) { correctAnswers.push(availableAnswer); } } @@ -64,9 +69,9 @@ function findAnswers(answerData, questionText, answers) { function matchAnswer(textA, textB) { const replaceRegex = /[^\w]/gi; - textA = textA.replace(replaceRegex, ""); - textB = textB.replace(replaceRegex, ""); - return (textA === textB); + textA = textA.replace(replaceRegex, ''); + textB = textB.replace(replaceRegex, ''); + return textA === textB; } -window.answerQuestion = answerQuestion; \ No newline at end of file +window.answerQuestion = answerQuestion; diff --git a/src/fetch.js b/src/fetch.js index a1a2e03..1deb0b5 100644 --- a/src/fetch.js +++ b/src/fetch.js @@ -5,22 +5,22 @@ const QUESTION_REGEX = /^[0-9]+\. (.*)$/; * @param {string} [answerURL=""] - The URL to fetch answers from. * @returns {Promise>} A Promise that resolves with the fetched answers. */ -function fetchAnswers(answerURL = "") { - return new Promise((resolve, reject) => { - GM_xmlhttpRequest({ - method: "GET", - url: answerURL, - headers: { - "Content-Type": "text/html", - }, - onload: function (response) { - parseAnswers(response, resolve); - }, - onerror: function (error) { - reject(error); - }, +function fetchAnswers(answerURL = '') { + return new Promise((resolve, reject) => { + GM_xmlhttpRequest({ + method: 'GET', + url: answerURL, + headers: { + 'Content-Type': 'text/html' + }, + onload: function (response) { + parseAnswers(response, resolve); + }, + onerror: function (error) { + reject(error); + } + }); }); - }); } /** @@ -29,19 +29,19 @@ function fetchAnswers(answerURL = "") { * @param {(value: Answer[] | PromiseLike) => void} resolve */ function parseAnswers(response, resolve) { - const results = []; - const allAnswersElement = getAllAnswersElement(response); + const results = []; + const allAnswersElement = getAllAnswersElement(response); - let index = -1; - for (let child of Array.from(allAnswersElement.children)) { - index++; - const result = parseAnswerElement(index, child, allAnswersElement); - if (result != undefined) { - results.push(result); + let index = -1; + for (let child of Array.from(allAnswersElement.children)) { + index++; + const result = parseAnswerElement(index, child, allAnswersElement); + if (result != undefined) { + results.push(result); + } } - } - resolve(results); + resolve(results); } /** @@ -49,14 +49,17 @@ function parseAnswers(response, resolve) { * @returns {Element} */ function getAllAnswersElement(response) { - const parser = new DOMParser(); - const virtualDOM = parser.parseFromString(response.responseText, "text/html"); + const parser = new DOMParser(); + const virtualDOM = parser.parseFromString( + response.responseText, + 'text/html' + ); - let answersElement = virtualDOM.querySelector(".pf-content"); - if (!answersElement) { - answersElement = virtualDOM.querySelector(".thecontent"); - } - return answersElement; + let answersElement = virtualDOM.querySelector('.pf-content'); + if (!answersElement) { + answersElement = virtualDOM.querySelector('.thecontent'); + } + return answersElement; } /** @@ -66,38 +69,38 @@ function getAllAnswersElement(response) { * @returns {Answer} */ function parseAnswerElement(index, element, allAnswersElement) { - // Check for Possible Tags - if ( - !(element.tagName === "P" || element.tagName === "STRONG") || - !element.innerHTML - ) { - return; - } - - // Get Question Element - /** @type {Element} */ - let questionElement = element.querySelector("strong"); - if (questionElement === null) { - if (!element.textContent) { - return; + // Check for Possible Tags + if ( + !(element.tagName === 'P' || element.tagName === 'STRONG') || + !element.innerHTML + ) { + return; } - questionElement = element; - } - // Get Question - const questionText = parseQuestion(questionElement); - if (questionText === null) { - return; - } + // Get Question Element + /** @type {Element} */ + let questionElement = element.querySelector('strong'); + if (questionElement === null) { + if (!element.textContent) { + return; + } + questionElement = element; + } - // Get Awsners - const answersElement = getAnswersElement(index, allAnswersElement); - if (answersElement === null || answersElement.tagName !== "UL") return; + // Get Question + const questionText = parseQuestion(questionElement); + if (questionText === null) { + return; + } - return { - question: questionText, - answers: getAnswers(answersElement), - }; + // Get Awsners + const answersElement = getAnswersElement(index, allAnswersElement); + if (answersElement === null || answersElement.tagName !== 'UL') return; + + return { + question: questionText, + answers: getAnswers(answersElement) + }; } /** @@ -105,9 +108,9 @@ function parseAnswerElement(index, element, allAnswersElement) { * @returns {String} */ function parseQuestion(questionElement) { - const textContent = questionElement.textContent.trim(); - const matches = textContent.match(QUESTION_REGEX); - return matches !== null ? matches[1] : null; + const textContent = questionElement.textContent.trim(); + const matches = textContent.match(QUESTION_REGEX); + return matches !== null ? matches[1] : null; } /** @@ -116,12 +119,12 @@ function parseQuestion(questionElement) { * @returns {Element} */ function getAnswersElement(index, allAnswersElement) { - let answersElement = allAnswersElement.children[index + 1]; + let answersElement = allAnswersElement.children[index + 1]; - if (answersElement.tagName === "P") { - answersElement = allAnswersElement.children[index + 2]; - } - return answersElement; + if (answersElement.tagName === 'P') { + answersElement = allAnswersElement.children[index + 2]; + } + return answersElement; } /** @@ -129,16 +132,18 @@ function getAnswersElement(index, allAnswersElement) { * @returns {Array} */ function getAnswers(answersElement) { - const answers = []; - for (let answerDom of Array.from(answersElement.querySelectorAll("strong"))) { - let answerText = answerDom.textContent.trim(); - if (answerText.endsWith("*")) { - answerText = answerText.substring(0, answerText.length - 1); + const answers = []; + for (let answerDom of Array.from( + answersElement.querySelectorAll('strong') + )) { + let answerText = answerDom.textContent.trim(); + if (answerText.endsWith('*')) { + answerText = answerText.substring(0, answerText.length - 1); + } + answers.push(answerText); } - answers.push(answerText); - } - return answers; + return answers; } window.fetchAnswers = fetchAnswers; diff --git a/src/main.user.js b/src/main.user.js index 6658050..32dbf22 100644 --- a/src/main.user.js +++ b/src/main.user.js @@ -14,25 +14,28 @@ // @author Dominik Säume // ==/UserScript== -const URL_STORAGE_KEY = "itexamanswers.net URL"; +const URL_STORAGE_KEY = 'itexamanswers.net URL'; /** @type {Array} */ let answerData; -window.addEventListener("keydown", async (event) => { - switch(event.key){ - case "p": - const oldAnswersURL = GM_getValue(URL_STORAGE_KEY); - const newAnswersURL = prompt("Please input the answer url (itexamanswers.net)", oldAnswersURL); - GM_setValue(URL_STORAGE_KEY, newAnswersURL); - answerData = await window.fetchAnswers(newAnswersURL); - break; +window.addEventListener('keydown', async event => { + switch (event.key) { + case 'p': + const oldAnswersURL = GM_getValue(URL_STORAGE_KEY); + const newAnswersURL = prompt( + 'Please input the answer url (itexamanswers.net)', + oldAnswersURL + ); + GM_setValue(URL_STORAGE_KEY, newAnswersURL); + answerData = await window.fetchAnswers(newAnswersURL); + break; - case "n": - document.getElementById("next").click(); - break; + case 'n': + document.getElementById('next').click(); + break; - case "a": - window.answerQuestion(answerData); - break; - } -}); \ No newline at end of file + case 'a': + window.answerQuestion(answerData); + break; + } +}); diff --git a/types/GM_getValue.d.js b/types/GM_getValue.d.js index d0bd584..60a8662 100644 --- a/types/GM_getValue.d.js +++ b/types/GM_getValue.d.js @@ -3,5 +3,5 @@ * @returns {string} */ function GM_getValue(storageKey) { - return ""; + return ''; }