fix(client): parse learner code with DOMParser (#55763)

pull/55773/head
Oliver Eyton-Williams 2024-08-06 15:40:45 +02:00 committed by GitHub
parent 7410ed0aa7
commit bde209bbba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 32 deletions

View File

@ -213,13 +213,11 @@ export const embedFilesInHtml = async function (challengeFiles) {
script.removeAttribute('src');
script.setAttribute('data-src', 'script.js');
}
return {
contents: documentElement.innerHTML
};
return documentElement.innerHTML;
};
if (indexHtml) {
const { contents } = await transformWithFrame(
const contents = await parseAndTransform(
embedStylesAndScript,
indexHtml.contents
);
@ -243,32 +241,11 @@ function challengeFilesToObject(challengeFiles) {
return { indexHtml, indexJsx, stylesCss, scriptJs };
}
const transformWithFrame = async function (transform, contents) {
// we use iframe here since file.contents is destined to be be inserted into
// the root of an iframe.
const frame = document.createElement('iframe');
frame.style = 'display: none';
let out = { contents };
try {
// the frame needs to be inserted into the document to create the html
// element
document.body.appendChild(frame);
// replace the root element with user code
frame.contentDocument.documentElement.innerHTML = contents;
// grab the contents now, in case the transformation fails
out = { contents: frame.contentDocument.documentElement.innerHTML };
// it's important to pass around the documentElement and NOT the frame
// itself. It appears that the frame's documentElement can get replaced by a
// blank documentElement without the contents. This seems only to happen on
// Firefox.
out = await transform(
frame.contentDocument.documentElement,
frame.contentDocument
);
} finally {
document.body.removeChild(frame);
}
return out;
const parseAndTransform = async function (transform, contents) {
const parser = new DOMParser();
const newDoc = parser.parseFromString(contents, 'text/html');
return await transform(newDoc.documentElement, newDoc);
};
const transformHtml = async function (file) {
@ -277,10 +254,10 @@ const transformHtml = async function (file) {
transformSASS(documentElement),
transformScript(documentElement)
]);
return { contents: documentElement.innerHTML };
return documentElement.innerHTML;
};
const { contents } = await transformWithFrame(transform, file.contents);
const contents = await parseAndTransform(transform, file.contents);
return transformContents(() => contents, file);
};

View File

@ -77,6 +77,7 @@ const handleRejection = err => {
const dom = new jsdom.JSDOM('');
global.document = dom.window.document;
global.DOMParser = dom.window.DOMParser;
const oldRunnerFail = Mocha.Runner.prototype.fail;
Mocha.Runner.prototype.fail = function (test, err) {