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 {
|
function parseTask(startElementId: string, doc: HTMLDocument): TaskAssignmentData {
|
||||||
const titleElement = doc.getElementById(startElementId)
|
const titleElement = doc.getElementById(startElementId)
|
||||||
if (!titleElement)
|
if (!titleElement)
|
||||||
throw new Error(`Document does not contain ${startElementId}`)
|
throw new Error(`Document does not contain ${startElementId}`)
|
||||||
fixAllLinks(titleElement)
|
fixAllLinks(titleElement)
|
||||||
const elements = []
|
|
||||||
|
|
||||||
let e = titleElement
|
let e = titleElement
|
||||||
|
|
||||||
|
@ -90,37 +95,52 @@ function parseTask(startElementId: string, doc: HTMLDocument): TaskAssignmentDat
|
||||||
|
|
||||||
e = e.nextElementSibling as HTMLElement
|
e = e.nextElementSibling as HTMLElement
|
||||||
|
|
||||||
|
// skip first <hr>
|
||||||
while (e.nextElementSibling &&
|
while (e.nextElementSibling &&
|
||||||
e.tagName.toLowerCase() == "hr")
|
e.tagName.toLowerCase() == "hr")
|
||||||
e = e.nextElementSibling as HTMLElement
|
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
|
// 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")) {
|
if (intoImgTag && intoImgTag.tagName.toLowerCase() == "img" && intoImgTag.classList.contains("leftfloat")) {
|
||||||
intoImgTag.remove()
|
intoImgTag.remove()
|
||||||
}
|
}
|
||||||
|
|
||||||
let r = ""
|
let r = ""
|
||||||
for (const e of elements) {
|
|
||||||
// hack: remove the paragraph with the matching text. Occurs in KSP-H, but is useless in this context.
|
copyElements: while (!e.classList.contains("story") &&
|
||||||
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.") {
|
// !e.classList.contains("clearfloat") &&
|
||||||
continue;
|
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.") {
|
||||||
|
break processElement
|
||||||
|
}
|
||||||
|
|
||||||
|
fixAllLinks(e)
|
||||||
|
|
||||||
|
r += e.outerHTML + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
fixAllLinks(e)
|
let n = e.nextSibling
|
||||||
r += e.outerHTML + "\n"
|
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 {
|
return {
|
||||||
description: r,
|
description: r,
|
||||||
id: id.trim(),
|
id: id.trim(),
|
||||||
|
|
|
@ -48,4 +48,6 @@ ANO
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfloat"></div>
|
<div class="clearfloat"></div>
|
||||||
<i>Poznámka:</i>
|
<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)
|
const assignmentFiles = readdirSync(assignmentDir)
|
||||||
for (const a of assignmentFiles) {
|
for (const a of assignmentFiles) {
|
||||||
const [_, id] = /(.*?)\.html/.exec(a)!
|
const [_, id] = /(.*?)\.html/.exec(a)!
|
||||||
test(id, async () => {
|
test.concurrent(id, async () => {
|
||||||
const assignment = await g.grabAssignment(id)
|
const assignment = await g.grabAssignment(id)
|
||||||
const expected = readFileSync(resolve(assignmentDir, a)).toString()
|
const expected = readFileSync(resolve(assignmentDir, a)).toString()
|
||||||
try {
|
try {
|
||||||
|
@ -98,7 +98,7 @@ describe('task solution (exact match)', () => {
|
||||||
const assignmentFiles = readdirSync(assignmentDir)
|
const assignmentFiles = readdirSync(assignmentDir)
|
||||||
for (const a of assignmentFiles) {
|
for (const a of assignmentFiles) {
|
||||||
const [_, id] = /(.*?)\.html/.exec(a)!
|
const [_, id] = /(.*?)\.html/.exec(a)!
|
||||||
test(id, async () => {
|
test.concurrent(id, async () => {
|
||||||
const solution = await g.grabSolution(id)
|
const solution = await g.grabSolution(id)
|
||||||
const expected = readFileSync(resolve(assignmentDir, a)).toString()
|
const expected = readFileSync(resolve(assignmentDir, a)).toString()
|
||||||
try {
|
try {
|
||||||
|
|
Reference in a new issue