Fix grabber bug when task contained text not inside of an element
This commit is contained in:
parent
4093f6b63e
commit
fd971c528f
3 changed files with 43 additions and 21 deletions
|
@ -72,12 +72,17 @@ function getLocation(id: string, solution: boolean): TaskLocation {
|
|||
}
|
||||
}
|
||||
|
||||
function htmlEncode(text: string): string {
|
||||
const p = document.createElement("p")
|
||||
p.textContent = text
|
||||
return p.innerHTML
|
||||
}
|
||||
|
||||
function parseTask(startElementId: string, doc: HTMLDocument): TaskAssignmentData {
|
||||
const titleElement = doc.getElementById(startElementId)
|
||||
if (!titleElement)
|
||||
throw new Error(`Document does not contain ${startElementId}`)
|
||||
fixAllLinks(titleElement)
|
||||
const elements = []
|
||||
|
||||
let e = titleElement
|
||||
|
||||
|
@ -90,37 +95,52 @@ function parseTask(startElementId: string, doc: HTMLDocument): TaskAssignmentDat
|
|||
|
||||
e = e.nextElementSibling as HTMLElement
|
||||
|
||||
// skip first <hr>
|
||||
while (e.nextElementSibling &&
|
||||
e.tagName.toLowerCase() == "hr")
|
||||
e = e.nextElementSibling as HTMLElement
|
||||
|
||||
while (!e.classList.contains("story") &&
|
||||
// !e.classList.contains("clearfloat") &&
|
||||
e.tagName.toLowerCase() != "h3" &&
|
||||
e.textContent!.trim() != "Řešení"
|
||||
)
|
||||
{
|
||||
elements.push(e)
|
||||
if (!e.nextElementSibling) break;
|
||||
e = e.nextElementSibling as HTMLElement
|
||||
}
|
||||
|
||||
// hack: remove img tag that shows this task is a practical one. Some tasks have it, some don't, so we remove it for consistency
|
||||
const intoImgTag = elements[0]?.firstElementChild
|
||||
const intoImgTag = e.firstElementChild
|
||||
if (intoImgTag && intoImgTag.tagName.toLowerCase() == "img" && intoImgTag.classList.contains("leftfloat")) {
|
||||
intoImgTag.remove()
|
||||
}
|
||||
|
||||
let r = ""
|
||||
for (const e of elements) {
|
||||
|
||||
copyElements: while (!e.classList.contains("story") &&
|
||||
// !e.classList.contains("clearfloat") &&
|
||||
e.tagName.toLowerCase() != "h3" &&
|
||||
e.textContent!.trim() != "Řešení"
|
||||
) {
|
||||
|
||||
processElement: {
|
||||
// hack: remove the paragraph with the matching text. Occurs in KSP-H, but is useless in this context.
|
||||
if (e.textContent!.trim().replace(/\s+/g, " ") == "Toto je praktická open-data úloha. V odevzdávacím systému si necháte vygenerovat vstupy a odevzdáte příslušné výstupy. Záleží jen na vás, jak výstupy vyrobíte.") {
|
||||
continue;
|
||||
break processElement
|
||||
}
|
||||
|
||||
fixAllLinks(e)
|
||||
|
||||
r += e.outerHTML + "\n"
|
||||
}
|
||||
|
||||
let n = e.nextSibling
|
||||
copyNodes: while(true) {
|
||||
if (!n) {
|
||||
break copyElements
|
||||
}
|
||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||
e = n as HTMLElement
|
||||
break copyNodes
|
||||
} else if (n.nodeType == Node.TEXT_NODE && n.textContent!.trim() != "") {
|
||||
r += htmlEncode(n.textContent!)
|
||||
}
|
||||
n = n.nextSibling
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
description: r,
|
||||
id: id.trim(),
|
||||
|
|
|
@ -48,4 +48,6 @@ ANO
|
|||
</div>
|
||||
<div class="clearfloat"></div>
|
||||
<i>Poznámka:</i>
|
||||
BUG
|
||||
Všimněte si, že stejnou černou figurkou (střelcem) můžeme vzít
|
||||
dva bílé pěšce. Naopak bílého pěšce vpravo nahoře nemůžeme vzít ani spodní věží
|
||||
(v cestě stojí střelec), ani levou věží (v cestě stojí jiné bílé figurky).
|
||||
|
|
|
@ -81,7 +81,7 @@ describe('task assignment (exact match)', () => {
|
|||
const assignmentFiles = readdirSync(assignmentDir)
|
||||
for (const a of assignmentFiles) {
|
||||
const [_, id] = /(.*?)\.html/.exec(a)!
|
||||
test(id, async () => {
|
||||
test.concurrent(id, async () => {
|
||||
const assignment = await g.grabAssignment(id)
|
||||
const expected = readFileSync(resolve(assignmentDir, a)).toString()
|
||||
try {
|
||||
|
@ -98,7 +98,7 @@ describe('task solution (exact match)', () => {
|
|||
const assignmentFiles = readdirSync(assignmentDir)
|
||||
for (const a of assignmentFiles) {
|
||||
const [_, id] = /(.*?)\.html/.exec(a)!
|
||||
test(id, async () => {
|
||||
test.concurrent(id, async () => {
|
||||
const solution = await g.grabSolution(id)
|
||||
const expected = readFileSync(resolve(assignmentDir, a)).toString()
|
||||
try {
|
||||
|
|
Reference in a new issue