This commit is contained in:
parent
69fb65deb7
commit
9c0c80902e
7 changed files with 156 additions and 113 deletions
18
.gitea/workflows/lint.yml
Normal file
18
.gitea/workflows/lint.yml
Normal file
|
@ -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: npm_config_yes=true npx prettier src/ types/ --check --log-level=error
|
10
.prettierrc.json
Normal file
10
.prettierrc.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"useTabs": false,
|
||||
"tabWidth": 4,
|
||||
"arrowParens": "avoid",
|
||||
"bracketSameLine": false,
|
||||
"singleQuote": true,
|
||||
"semi": true,
|
||||
"trailingComma": "none",
|
||||
"endOfLine": "lf"
|
||||
}
|
2
Makefile
Normal file
2
Makefile
Normal file
|
@ -0,0 +1,2 @@
|
|||
lint:
|
||||
@npx prettier src/ types/ --write
|
|
@ -3,22 +3,22 @@
|
|||
* @param {Array<Answer>} 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,7 +29,7 @@ function answerQuestion(answerData){
|
|||
}
|
||||
|
||||
for (const answer of correctAnswers) {
|
||||
const input = answer.querySelector("input");
|
||||
const input = answer.querySelector('input');
|
||||
if (!input) continue;
|
||||
input.checked = true;
|
||||
}
|
||||
|
@ -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;
|
157
src/fetch.js
157
src/fetch.js
|
@ -5,22 +5,22 @@ const QUESTION_REGEX = /^[0-9]+\. (.*)$/;
|
|||
* @param {string} [answerURL=""] - The URL to fetch answers from.
|
||||
* @returns {Promise<Array<Answer>>} 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<Answer[]>) => 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<string>}
|
||||
*/
|
||||
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;
|
||||
|
|
|
@ -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<Answer>} */
|
||||
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;
|
||||
}
|
||||
case 'a':
|
||||
window.answerQuestion(answerData);
|
||||
break;
|
||||
}
|
||||
});
|
|
@ -3,5 +3,5 @@
|
|||
* @returns {string}
|
||||
*/
|
||||
function GM_getValue(storageKey) {
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue