fix: index.css/js to styles/script (#44356)
* fix: replace index with script/styles as needed * fix: remove redundant fileKey It's overwritten by createPoly, so the parser does not need to create it * fix: curriculum test suite * Update client/src/templates/Challenges/classic/MultifileEditor.js Co-authored-by: Shaun Hamilton <shauhami020@gmail.com> Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>
This commit is contained in:
committed by
GitHub
parent
7a5e805769
commit
f613a1e5fd
@ -297,7 +297,7 @@ export type CompletedChallenge = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Ext = 'js' | 'html' | 'css' | 'jsx';
|
export type Ext = 'js' | 'html' | 'css' | 'jsx';
|
||||||
export type FileKey = 'indexjs' | 'indexhtml' | 'indexcss';
|
export type FileKey = 'scriptjs' | 'indexhtml' | 'stylescss';
|
||||||
|
|
||||||
export type ChallengeMeta = {
|
export type ChallengeMeta = {
|
||||||
block: string;
|
block: string;
|
||||||
|
@ -40,14 +40,13 @@ const propTypes = {
|
|||||||
saveEditorContent: PropTypes.func.isRequired,
|
saveEditorContent: PropTypes.func.isRequired,
|
||||||
setEditorFocusability: PropTypes.func,
|
setEditorFocusability: PropTypes.func,
|
||||||
theme: PropTypes.string,
|
theme: PropTypes.string,
|
||||||
// TODO: is this used?
|
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
updateFile: PropTypes.func.isRequired,
|
updateFile: PropTypes.func.isRequired,
|
||||||
usesMultifileEditor: PropTypes.bool,
|
usesMultifileEditor: PropTypes.bool,
|
||||||
visibleEditors: PropTypes.shape({
|
visibleEditors: PropTypes.shape({
|
||||||
indexjs: PropTypes.bool,
|
scriptjs: PropTypes.bool,
|
||||||
indexjsx: PropTypes.bool,
|
indexjsx: PropTypes.bool,
|
||||||
indexcss: PropTypes.bool,
|
stylescss: PropTypes.bool,
|
||||||
indexhtml: PropTypes.bool
|
indexhtml: PropTypes.bool
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
@ -83,7 +82,7 @@ const MultifileEditor = props => {
|
|||||||
theme,
|
theme,
|
||||||
resizeProps,
|
resizeProps,
|
||||||
title,
|
title,
|
||||||
visibleEditors: { indexcss, indexhtml, indexjs, indexjsx },
|
visibleEditors: { stylescss, indexhtml, scriptjs, indexjsx },
|
||||||
usesMultifileEditor
|
usesMultifileEditor
|
||||||
} = props;
|
} = props;
|
||||||
const editorTheme = theme === 'night' ? 'vs-dark-custom' : 'vs-custom';
|
const editorTheme = theme === 'night' ? 'vs-dark-custom' : 'vs-custom';
|
||||||
@ -105,8 +104,8 @@ const MultifileEditor = props => {
|
|||||||
|
|
||||||
if (indexjsx) editorKeys.push('indexjsx');
|
if (indexjsx) editorKeys.push('indexjsx');
|
||||||
if (indexhtml) editorKeys.push('indexhtml');
|
if (indexhtml) editorKeys.push('indexhtml');
|
||||||
if (indexcss) editorKeys.push('indexcss');
|
if (stylescss) editorKeys.push('stylescss');
|
||||||
if (indexjs) editorKeys.push('indexjs');
|
if (scriptjs) editorKeys.push('scriptjs');
|
||||||
|
|
||||||
const editorAndSplitterKeys = editorKeys.reduce((acc, key) => {
|
const editorAndSplitterKeys = editorKeys.reduce((acc, key) => {
|
||||||
if (acc.length === 0) {
|
if (acc.length === 0) {
|
||||||
|
@ -227,11 +227,11 @@ const transformIncludes = async function (fileP) {
|
|||||||
div.querySelector('script[src="./script.js"]');
|
div.querySelector('script[src="./script.js"]');
|
||||||
const importedFiles = [];
|
const importedFiles = [];
|
||||||
if (link) {
|
if (link) {
|
||||||
importedFiles.push('index.css');
|
importedFiles.push('styles.css');
|
||||||
link.remove();
|
link.remove();
|
||||||
}
|
}
|
||||||
if (script) {
|
if (script) {
|
||||||
importedFiles.push('index.js');
|
importedFiles.push('script.js');
|
||||||
script.remove();
|
script.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,17 +51,10 @@ const composeFunctions = (...fns) =>
|
|||||||
fns.map(applyFunction).reduce((f, g) => x => f(x).then(g));
|
fns.map(applyFunction).reduce((f, g) => x => f(x).then(g));
|
||||||
|
|
||||||
function buildSourceMap(challengeFiles) {
|
function buildSourceMap(challengeFiles) {
|
||||||
// TODO: concatenating the source/contents is a quick hack for multi-file
|
// TODO: rename sources.index to sources.contents.
|
||||||
// editing. It is used because all the files (js, html and css) end up with
|
|
||||||
// the same name 'index'. This made the last file the only file to appear in
|
|
||||||
// sources.
|
|
||||||
// A better solution is to store and handle them separately. Perhaps never
|
|
||||||
// setting the name to 'index'. Use 'contents' instead?
|
|
||||||
// TODO: is file.source ever defined?
|
|
||||||
const source = challengeFiles.reduce(
|
const source = challengeFiles.reduce(
|
||||||
(sources, challengeFile) => {
|
(sources, challengeFile) => {
|
||||||
sources[challengeFile.name] +=
|
sources.index += challengeFile.source || challengeFile.contents;
|
||||||
challengeFile.source || challengeFile.contents;
|
|
||||||
sources.editableContents += challengeFile.editableContents || '';
|
sources.editableContents += challengeFile.editableContents || '';
|
||||||
return sources;
|
return sources;
|
||||||
},
|
},
|
||||||
|
@ -459,7 +459,9 @@ ${inspect(commentMap)}
|
|||||||
challengeFile.editableContents = getLines(
|
challengeFile.editableContents = getLines(
|
||||||
challengeFile.contents,
|
challengeFile.contents,
|
||||||
challenge.challengeFiles.find(
|
challenge.challengeFiles.find(
|
||||||
x => x.fileKey === challengeFile.fileKey
|
x =>
|
||||||
|
x.ext === challengeFile.ext &&
|
||||||
|
x.name === challengeFile.name
|
||||||
).editableRegionBoundaries
|
).editableRegionBoundaries
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -523,7 +525,7 @@ async function createTestRunner(
|
|||||||
const challengeFiles = cloneDeep(challenge.challengeFiles);
|
const challengeFiles = cloneDeep(challenge.challengeFiles);
|
||||||
solutionFiles.forEach(solutionFile => {
|
solutionFiles.forEach(solutionFile => {
|
||||||
const challengeFile = challengeFiles.find(
|
const challengeFile = challengeFiles.find(
|
||||||
x => x.fileKey === solutionFile.fileKey
|
x => x.ext === solutionFile.ext && x.name === solutionFile.name
|
||||||
);
|
);
|
||||||
challengeFile.contents = solutionFile.contents;
|
challengeFile.contents = solutionFile.contents;
|
||||||
challengeFile.editableContents = solutionFile.editableContents;
|
challengeFile.editableContents = solutionFile.editableContents;
|
||||||
|
@ -60,7 +60,6 @@ Object {
|
|||||||
</html>",
|
</html>",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "html",
|
"ext": "html",
|
||||||
"fileKey": "indexhtml",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
@ -72,10 +71,9 @@ Object {
|
|||||||
}",
|
}",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "css",
|
"ext": "css",
|
||||||
"fileKey": "indexcss",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "styles",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
@ -86,10 +84,9 @@ for (let index = 0; index < array.length; index++) {
|
|||||||
}",
|
}",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "js",
|
"ext": "js",
|
||||||
"fileKey": "indexjs",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "custom-name",
|
"id": "custom-name",
|
||||||
"name": "index",
|
"name": "script",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -129,7 +126,6 @@ Object {
|
|||||||
</html>",
|
</html>",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "html",
|
"ext": "html",
|
||||||
"fileKey": "indexhtml",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
@ -141,20 +137,18 @@ Object {
|
|||||||
}",
|
}",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "css",
|
"ext": "css",
|
||||||
"fileKey": "indexcss",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "styles",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contents": "var x = 'y';",
|
"contents": "var x = 'y';",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "js",
|
"ext": "js",
|
||||||
"fileKey": "indexjs",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "script",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -222,7 +216,6 @@ Object {
|
|||||||
23,
|
23,
|
||||||
],
|
],
|
||||||
"ext": "html",
|
"ext": "html",
|
||||||
"fileKey": "indexhtml",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "html-key",
|
"id": "html-key",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
@ -246,20 +239,18 @@ a {
|
|||||||
9,
|
9,
|
||||||
],
|
],
|
||||||
"ext": "css",
|
"ext": "css",
|
||||||
"fileKey": "indexcss",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "styles",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contents": "var x = 'y';",
|
"contents": "var x = 'y';",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "js",
|
"ext": "js",
|
||||||
"fileKey": "indexjs",
|
|
||||||
"head": " // this runs before the user's code is evaluated.",
|
"head": " // this runs before the user's code is evaluated.",
|
||||||
"id": "final-key",
|
"id": "final-key",
|
||||||
"name": "index",
|
"name": "script",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -307,7 +298,6 @@ a {
|
|||||||
</body>
|
</body>
|
||||||
</html>",
|
</html>",
|
||||||
"ext": "html",
|
"ext": "html",
|
||||||
"fileKey": "indexhtml",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "html-key",
|
"id": "html-key",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
@ -327,19 +317,17 @@ a {
|
|||||||
color: green;
|
color: green;
|
||||||
}",
|
}",
|
||||||
"ext": "css",
|
"ext": "css",
|
||||||
"fileKey": "indexcss",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "styles",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contents": "var x = 'y';",
|
"contents": "var x = 'y';",
|
||||||
"ext": "js",
|
"ext": "js",
|
||||||
"fileKey": "indexjs",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "final-key",
|
"id": "final-key",
|
||||||
"name": "index",
|
"name": "script",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -393,7 +381,6 @@ Object {
|
|||||||
</html>",
|
</html>",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "html",
|
"ext": "html",
|
||||||
"fileKey": "indexhtml",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
@ -405,20 +392,18 @@ Object {
|
|||||||
}",
|
}",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "css",
|
"ext": "css",
|
||||||
"fileKey": "indexcss",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "styles",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contents": "var x = 'y';",
|
"contents": "var x = 'y';",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "js",
|
"ext": "js",
|
||||||
"fileKey": "indexjs",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "script",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -440,7 +425,6 @@ Object {
|
|||||||
</body>
|
</body>
|
||||||
</html>",
|
</html>",
|
||||||
"ext": "html",
|
"ext": "html",
|
||||||
"fileKey": "indexhtml",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "html-key",
|
"id": "html-key",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
@ -451,20 +435,18 @@ Object {
|
|||||||
background: white;
|
background: white;
|
||||||
}",
|
}",
|
||||||
"ext": "css",
|
"ext": "css",
|
||||||
"fileKey": "indexcss",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "styles",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contents": "var x = 'y';
|
"contents": "var x = 'y';
|
||||||
\`\`",
|
\`\`",
|
||||||
"ext": "js",
|
"ext": "js",
|
||||||
"fileKey": "indexjs",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "script",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -499,7 +481,6 @@ Object {
|
|||||||
</html>",
|
</html>",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "html",
|
"ext": "html",
|
||||||
"fileKey": "indexhtml",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
@ -511,20 +492,18 @@ Object {
|
|||||||
}",
|
}",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "css",
|
"ext": "css",
|
||||||
"fileKey": "indexcss",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "styles",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contents": "var x = 'y';",
|
"contents": "var x = 'y';",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "js",
|
"ext": "js",
|
||||||
"fileKey": "indexjs",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "script",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -565,7 +544,6 @@ Object {
|
|||||||
</html>",
|
</html>",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "html",
|
"ext": "html",
|
||||||
"fileKey": "indexhtml",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
@ -577,20 +555,18 @@ Object {
|
|||||||
}",
|
}",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "css",
|
"ext": "css",
|
||||||
"fileKey": "indexcss",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "styles",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contents": "var x = 'y';",
|
"contents": "var x = 'y';",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "js",
|
"ext": "js",
|
||||||
"fileKey": "indexjs",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "script",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -626,7 +602,6 @@ Object {
|
|||||||
</body>
|
</body>
|
||||||
</html>",
|
</html>",
|
||||||
"ext": "html",
|
"ext": "html",
|
||||||
"fileKey": "indexhtml",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "html-key",
|
"id": "html-key",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
@ -637,20 +612,18 @@ Object {
|
|||||||
background: white;
|
background: white;
|
||||||
}",
|
}",
|
||||||
"ext": "css",
|
"ext": "css",
|
||||||
"fileKey": "indexcss",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "styles",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contents": "var x = 'y';
|
"contents": "var x = 'y';
|
||||||
\`\`",
|
\`\`",
|
||||||
"ext": "js",
|
"ext": "js",
|
||||||
"fileKey": "indexjs",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "script",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -10,7 +10,6 @@ Object {
|
|||||||
</html>",
|
</html>",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "html",
|
"ext": "html",
|
||||||
"fileKey": "indexhtml",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
@ -22,20 +21,18 @@ Object {
|
|||||||
}",
|
}",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "css",
|
"ext": "css",
|
||||||
"fileKey": "indexcss",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "styles",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contents": "var x = 'y';",
|
"contents": "var x = 'y';",
|
||||||
"editableRegionBoundaries": Array [],
|
"editableRegionBoundaries": Array [],
|
||||||
"ext": "js",
|
"ext": "js",
|
||||||
"fileKey": "indexjs",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "script",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -10,7 +10,6 @@ Object {
|
|||||||
</body>
|
</body>
|
||||||
</html>",
|
</html>",
|
||||||
"ext": "html",
|
"ext": "html",
|
||||||
"fileKey": "indexhtml",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "html-key",
|
"id": "html-key",
|
||||||
"name": "index",
|
"name": "index",
|
||||||
@ -21,20 +20,18 @@ Object {
|
|||||||
background: white;
|
background: white;
|
||||||
}",
|
}",
|
||||||
"ext": "css",
|
"ext": "css",
|
||||||
"fileKey": "indexcss",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "styles",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"contents": "var x = 'y';
|
"contents": "var x = 'y';
|
||||||
\`\`",
|
\`\`",
|
||||||
"ext": "js",
|
"ext": "js",
|
||||||
"fileKey": "indexjs",
|
|
||||||
"head": "",
|
"head": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"name": "index",
|
"name": "script",
|
||||||
"tail": "",
|
"tail": "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -2,7 +2,6 @@ const { isEmpty } = require('lodash');
|
|||||||
const { root } = require('mdast-builder');
|
const { root } = require('mdast-builder');
|
||||||
const visitChildren = require('unist-util-visit-children');
|
const visitChildren = require('unist-util-visit-children');
|
||||||
const getAllBetween = require('./utils/between-headings');
|
const getAllBetween = require('./utils/between-headings');
|
||||||
// const visit = require('unist-util-visit');
|
|
||||||
const { getFileVisitor } = require('./utils/get-file-visitor');
|
const { getFileVisitor } = require('./utils/get-file-visitor');
|
||||||
|
|
||||||
const editableRegionMarker = '--fcc-editable-region--';
|
const editableRegionMarker = '--fcc-editable-region--';
|
||||||
|
@ -42,15 +42,13 @@ describe('add-seed plugin', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('adds test objects to the challengeFiles array following a schema', () => {
|
it('adds test objects to the challengeFiles array following a schema', () => {
|
||||||
expect.assertions(17);
|
expect.assertions(15);
|
||||||
plugin(simpleAST, file);
|
plugin(simpleAST, file);
|
||||||
const {
|
const {
|
||||||
data: { challengeFiles }
|
data: { challengeFiles }
|
||||||
} = file;
|
} = file;
|
||||||
const testObject = challengeFiles.find(x => x.fileKey === 'indexjs');
|
const testObject = challengeFiles.find(x => x.ext === 'js');
|
||||||
expect(Object.keys(testObject).length).toEqual(8);
|
expect(Object.keys(testObject).length).toEqual(7);
|
||||||
expect(testObject).toHaveProperty('fileKey');
|
|
||||||
expect(typeof testObject['fileKey']).toBe('string');
|
|
||||||
expect(testObject).toHaveProperty('ext');
|
expect(testObject).toHaveProperty('ext');
|
||||||
expect(typeof testObject['ext']).toBe('string');
|
expect(typeof testObject['ext']).toBe('string');
|
||||||
expect(testObject).toHaveProperty('name');
|
expect(testObject).toHaveProperty('name');
|
||||||
@ -73,16 +71,16 @@ describe('add-seed plugin', () => {
|
|||||||
const {
|
const {
|
||||||
data: { challengeFiles }
|
data: { challengeFiles }
|
||||||
} = file;
|
} = file;
|
||||||
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
|
const scriptjs = challengeFiles.find(x => x.ext === 'js');
|
||||||
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
|
const indexhtml = challengeFiles.find(x => x.ext === 'html');
|
||||||
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
|
const stylescss = challengeFiles.find(x => x.ext === 'css');
|
||||||
|
|
||||||
expect(indexjs.contents).toBe(`var x = 'y';`);
|
expect(scriptjs.contents).toBe(`var x = 'y';`);
|
||||||
expect(indexhtml.contents).toBe(`<html>
|
expect(indexhtml.contents).toBe(`<html>
|
||||||
<body>
|
<body>
|
||||||
</body>
|
</body>
|
||||||
</html>`);
|
</html>`);
|
||||||
expect(indexcss.contents).toBe(`body {
|
expect(stylescss.contents).toBe(`body {
|
||||||
background: green;
|
background: green;
|
||||||
}`);
|
}`);
|
||||||
});
|
});
|
||||||
@ -93,10 +91,10 @@ describe('add-seed plugin', () => {
|
|||||||
const {
|
const {
|
||||||
data: { challengeFiles }
|
data: { challengeFiles }
|
||||||
} = file;
|
} = file;
|
||||||
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
|
const stylescss = challengeFiles.find(x => x.ext === 'css');
|
||||||
|
|
||||||
expect(indexcss.contents).not.toMatch('--fcc-editable-region--');
|
expect(stylescss.contents).not.toMatch('--fcc-editable-region--');
|
||||||
expect(indexcss.editableRegionBoundaries).toEqual([1, 4]);
|
expect(stylescss.editableRegionBoundaries).toEqual([1, 4]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: can we reuse 'name'? It's always 'index', I think, which suggests
|
// TODO: can we reuse 'name'? It's always 'index', I think, which suggests
|
||||||
@ -107,13 +105,13 @@ describe('add-seed plugin', () => {
|
|||||||
const {
|
const {
|
||||||
data: { challengeFiles }
|
data: { challengeFiles }
|
||||||
} = file;
|
} = file;
|
||||||
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
|
const scriptjs = challengeFiles.find(x => x.ext === 'js');
|
||||||
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
|
const indexhtml = challengeFiles.find(x => x.ext === 'html');
|
||||||
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
|
const stylescss = challengeFiles.find(x => x.ext === 'css');
|
||||||
|
|
||||||
expect(indexhtml.id).toBe('');
|
expect(indexhtml.id).toBe('');
|
||||||
expect(indexcss.id).toBe('key-for-css');
|
expect(stylescss.id).toBe('key-for-css');
|
||||||
expect(indexjs.id).toBe('key-for-js');
|
expect(scriptjs.id).toBe('key-for-js');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws if an id is anywhere except directly before a code node', () => {
|
it('throws if an id is anywhere except directly before a code node', () => {
|
||||||
@ -140,13 +138,13 @@ describe('add-seed plugin', () => {
|
|||||||
const {
|
const {
|
||||||
data: { challengeFiles }
|
data: { challengeFiles }
|
||||||
} = file;
|
} = file;
|
||||||
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
|
const scriptjs = challengeFiles.find(x => x.ext === 'js');
|
||||||
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
|
const indexhtml = challengeFiles.find(x => x.ext === 'html');
|
||||||
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
|
const stylescss = challengeFiles.find(x => x.ext === 'css');
|
||||||
|
|
||||||
expect(indexjs.head).toBe('');
|
expect(scriptjs.head).toBe('');
|
||||||
expect(indexhtml.head).toBe(`<!-- comment -->`);
|
expect(indexhtml.head).toBe(`<!-- comment -->`);
|
||||||
expect(indexcss.head).toBe(`body {
|
expect(stylescss.head).toBe(`body {
|
||||||
etc: ''
|
etc: ''
|
||||||
}`);
|
}`);
|
||||||
});
|
});
|
||||||
@ -157,15 +155,15 @@ describe('add-seed plugin', () => {
|
|||||||
const {
|
const {
|
||||||
data: { challengeFiles }
|
data: { challengeFiles }
|
||||||
} = file;
|
} = file;
|
||||||
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
|
const scriptjs = challengeFiles.find(x => x.ext === 'js');
|
||||||
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
|
const indexhtml = challengeFiles.find(x => x.ext === 'html');
|
||||||
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
|
const stylescss = challengeFiles.find(x => x.ext === 'css');
|
||||||
|
|
||||||
expect(indexjs.tail).toBe(`function teardown(params) {
|
expect(scriptjs.tail).toBe(`function teardown(params) {
|
||||||
// after
|
// after
|
||||||
}`);
|
}`);
|
||||||
expect(indexhtml.tail).toBe('');
|
expect(indexhtml.tail).toBe('');
|
||||||
expect(indexcss.tail).toBe(`body {
|
expect(stylescss.tail).toBe(`body {
|
||||||
background: blue;
|
background: blue;
|
||||||
}`);
|
}`);
|
||||||
});
|
});
|
||||||
@ -194,16 +192,16 @@ describe('add-seed plugin', () => {
|
|||||||
const {
|
const {
|
||||||
data: { challengeFiles }
|
data: { challengeFiles }
|
||||||
} = file;
|
} = file;
|
||||||
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
|
const scriptjs = challengeFiles.find(x => x.ext === 'js');
|
||||||
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
|
const indexhtml = challengeFiles.find(x => x.ext === 'html');
|
||||||
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
|
const stylescss = challengeFiles.find(x => x.ext === 'css');
|
||||||
|
|
||||||
expect(indexjs.head).toBe('');
|
expect(scriptjs.head).toBe('');
|
||||||
expect(indexjs.tail).toBe('function teardown(params) {\n // after\n}');
|
expect(scriptjs.tail).toBe('function teardown(params) {\n // after\n}');
|
||||||
expect(indexhtml.head).toBe('');
|
expect(indexhtml.head).toBe('');
|
||||||
expect(indexhtml.tail).toBe('');
|
expect(indexhtml.tail).toBe('');
|
||||||
expect(indexcss.head).toBe('');
|
expect(stylescss.head).toBe('');
|
||||||
expect(indexcss.tail).toBe('body {\n background: blue;\n}');
|
expect(stylescss.tail).toBe('body {\n background: blue;\n}');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('quietly ignores empty after sections', () => {
|
it('quietly ignores empty after sections', () => {
|
||||||
@ -212,16 +210,16 @@ describe('add-seed plugin', () => {
|
|||||||
const {
|
const {
|
||||||
data: { challengeFiles }
|
data: { challengeFiles }
|
||||||
} = file;
|
} = file;
|
||||||
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
|
const scriptjs = challengeFiles.find(x => x.ext === 'js');
|
||||||
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
|
const indexhtml = challengeFiles.find(x => x.ext === 'html');
|
||||||
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
|
const stylescss = challengeFiles.find(x => x.ext === 'css');
|
||||||
|
|
||||||
expect(indexjs.head).toBe('');
|
expect(scriptjs.head).toBe('');
|
||||||
expect(indexjs.tail).toBe('');
|
expect(scriptjs.tail).toBe('');
|
||||||
expect(indexhtml.head).toBe('<!-- comment -->');
|
expect(indexhtml.head).toBe('<!-- comment -->');
|
||||||
expect(indexhtml.tail).toBe('');
|
expect(indexhtml.tail).toBe('');
|
||||||
expect(indexcss.head).toBe("body {\n etc: ''\n}");
|
expect(stylescss.head).toBe("body {\n etc: ''\n}");
|
||||||
expect(indexcss.tail).toBe('');
|
expect(stylescss.tail).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws an error (with line number) if 2 markers appear on 1 line', () => {
|
it('throws an error (with line number) if 2 markers appear on 1 line', () => {
|
||||||
@ -239,12 +237,12 @@ describe('add-seed plugin', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('handles jsx', () => {
|
it('handles jsx', () => {
|
||||||
expect.assertions(4);
|
expect.assertions(3);
|
||||||
plugin(jsxSeedAST, file);
|
plugin(jsxSeedAST, file);
|
||||||
const {
|
const {
|
||||||
data: { challengeFiles }
|
data: { challengeFiles }
|
||||||
} = file;
|
} = file;
|
||||||
const indexjsx = challengeFiles.find(x => x.fileKey === 'indexjsx');
|
const indexjsx = challengeFiles.find(x => x.ext === 'jsx');
|
||||||
|
|
||||||
expect(indexjsx.head).toBe(`function setup() {}`);
|
expect(indexjsx.head).toBe(`function setup() {}`);
|
||||||
expect(indexjsx.tail).toBe(`function teardown(params) {
|
expect(indexjsx.tail).toBe(`function teardown(params) {
|
||||||
@ -256,7 +254,6 @@ describe('add-seed plugin', () => {
|
|||||||
const Button = () => {
|
const Button = () => {
|
||||||
return <button> {/* another comment! */} text </button>;
|
return <button> {/* another comment! */} text </button>;
|
||||||
};`);
|
};`);
|
||||||
expect(indexjsx.fileKey).toBe(`indexjsx`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('combines all the code of a specific language into a single file', () => {
|
it('combines all the code of a specific language into a single file', () => {
|
||||||
|
@ -34,17 +34,13 @@ describe('add solution plugin', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('adds solution objects to the challengeFiles array following a schema', () => {
|
it('adds solution objects to the challengeFiles array following a schema', () => {
|
||||||
expect.assertions(15);
|
expect.assertions(13);
|
||||||
plugin(mockAST, file);
|
plugin(mockAST, file);
|
||||||
const {
|
const {
|
||||||
data: { solutions }
|
data: { solutions }
|
||||||
} = file;
|
} = file;
|
||||||
const testObject = solutions[0].find(
|
const testObject = solutions[0].find(solution => solution.ext === 'js');
|
||||||
solution => solution.fileKey === 'indexjs'
|
expect(Object.keys(testObject).length).toEqual(6);
|
||||||
);
|
|
||||||
expect(Object.keys(testObject).length).toEqual(7);
|
|
||||||
expect(testObject).toHaveProperty('fileKey');
|
|
||||||
expect(typeof testObject['fileKey']).toBe('string');
|
|
||||||
expect(testObject).toHaveProperty('ext');
|
expect(testObject).toHaveProperty('ext');
|
||||||
expect(typeof testObject['ext']).toBe('string');
|
expect(typeof testObject['ext']).toBe('string');
|
||||||
expect(testObject).toHaveProperty('name');
|
expect(testObject).toHaveProperty('name');
|
||||||
@ -66,24 +62,22 @@ describe('add solution plugin', () => {
|
|||||||
data: { solutions }
|
data: { solutions }
|
||||||
} = file;
|
} = file;
|
||||||
expect(solutions.length).toBe(3);
|
expect(solutions.length).toBe(3);
|
||||||
expect(
|
expect(solutions[0].find(solution => solution.ext === 'js').contents).toBe(
|
||||||
solutions[0].find(solution => solution.fileKey === 'indexjs').contents
|
"var x = 'y';"
|
||||||
).toBe("var x = 'y';");
|
);
|
||||||
expect(
|
expect(solutions[1].find(solution => solution.ext === 'html').contents)
|
||||||
solutions[1].find(solution => solution.fileKey === 'indexhtml').contents
|
.toBe(`<html>
|
||||||
).toBe(`<html>
|
|
||||||
<body>
|
<body>
|
||||||
solution number two
|
solution number two
|
||||||
</body>
|
</body>
|
||||||
</html>`);
|
</html>`);
|
||||||
expect(
|
expect(solutions[1].find(solution => solution.ext === 'css').contents)
|
||||||
solutions[1].find(solution => solution.fileKey === 'indexcss').contents
|
.toBe(`body {
|
||||||
).toBe(`body {
|
|
||||||
background: white;
|
background: white;
|
||||||
}`);
|
}`);
|
||||||
expect(
|
expect(solutions[2].find(solution => solution.ext === 'js').contents).toBe(
|
||||||
solutions[2].find(solution => solution.fileKey === 'indexjs').contents
|
"var x = 'y3';"
|
||||||
).toBe("var x = 'y3';");
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reject solutions with editable region markers', () => {
|
it('should reject solutions with editable region markers', () => {
|
||||||
|
@ -12,9 +12,8 @@ const supportedLanguages = ['js', 'css', 'html', 'jsx', 'py'];
|
|||||||
|
|
||||||
function defaultFile(lang, id) {
|
function defaultFile(lang, id) {
|
||||||
return {
|
return {
|
||||||
fileKey: `index${lang}`,
|
|
||||||
ext: lang,
|
ext: lang,
|
||||||
name: 'index',
|
name: getFilenames(lang),
|
||||||
contents: '',
|
contents: '',
|
||||||
head: '',
|
head: '',
|
||||||
tail: '',
|
tail: '',
|
||||||
@ -22,6 +21,14 @@ function defaultFile(lang, id) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getFilenames(lang) {
|
||||||
|
const langToFilename = {
|
||||||
|
js: 'script',
|
||||||
|
css: 'styles'
|
||||||
|
};
|
||||||
|
return langToFilename[lang] ?? 'index';
|
||||||
|
}
|
||||||
|
|
||||||
function getFileVisitor(seeds, seedKey, validate) {
|
function getFileVisitor(seeds, seedKey, validate) {
|
||||||
return (node, index, parent) => {
|
return (node, index, parent) => {
|
||||||
if (is(node, 'root')) return;
|
if (is(node, 'root')) return;
|
||||||
@ -43,21 +50,21 @@ function codeToData(node, seeds, seedKey, validate) {
|
|||||||
Please use one of js, css, html, jsx or py
|
Please use one of js, css, html, jsx or py
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const fileKey = `index${lang}`;
|
const fileId = `index${lang}`;
|
||||||
const id = seeds[fileKey] ? seeds[fileKey].id : '';
|
const id = seeds[fileId] ? seeds[fileId].id : '';
|
||||||
// the contents will be missing if there is an id preceding this code
|
// the contents will be missing if there is an id preceding this code
|
||||||
// block.
|
// block.
|
||||||
if (!seeds[fileKey]) {
|
if (!seeds[fileId]) {
|
||||||
seeds[fileKey] = defaultFile(lang, id);
|
seeds[fileId] = defaultFile(lang, id);
|
||||||
}
|
}
|
||||||
if (isEmpty(node.value) && seedKey !== 'contents') {
|
if (isEmpty(node.value) && seedKey !== 'contents') {
|
||||||
const section = keyToSection[seedKey];
|
const section = keyToSection[seedKey];
|
||||||
throw Error(`Empty code block in --${section}-- section`);
|
throw Error(`Empty code block in --${section}-- section`);
|
||||||
}
|
}
|
||||||
|
|
||||||
seeds[fileKey][seedKey] = isEmpty(seeds[fileKey][seedKey])
|
seeds[fileId][seedKey] = isEmpty(seeds[fileId][seedKey])
|
||||||
? node.value
|
? node.value
|
||||||
: seeds[fileKey][seedKey] + '\n' + node.value;
|
: seeds[fileId][seedKey] + '\n' + node.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function idToData(node, index, parent, seeds) {
|
function idToData(node, index, parent, seeds) {
|
||||||
|
@ -4,10 +4,10 @@ exports.challengeFiles = [
|
|||||||
error: null,
|
error: null,
|
||||||
ext: 'css',
|
ext: 'css',
|
||||||
head: '',
|
head: '',
|
||||||
history: ['index.css'],
|
history: ['styles.css'],
|
||||||
fileKey: 'indexcss',
|
fileKey: 'stylescss',
|
||||||
name: 'index',
|
name: 'styles',
|
||||||
path: 'index.css',
|
path: 'styles.css',
|
||||||
seed: 'some css',
|
seed: 'some css',
|
||||||
tail: ''
|
tail: ''
|
||||||
},
|
},
|
||||||
@ -28,10 +28,10 @@ exports.challengeFiles = [
|
|||||||
error: null,
|
error: null,
|
||||||
ext: 'js',
|
ext: 'js',
|
||||||
head: '',
|
head: '',
|
||||||
history: ['index.js'],
|
history: ['script.js'],
|
||||||
fileKey: 'indexjs',
|
fileKey: 'scriptjs',
|
||||||
name: 'index',
|
name: 'script',
|
||||||
path: 'index.js',
|
path: 'script.js',
|
||||||
seed: 'some js',
|
seed: 'some js',
|
||||||
tail: ''
|
tail: ''
|
||||||
},
|
},
|
||||||
|
@ -17,7 +17,7 @@ describe('sort-files', () => {
|
|||||||
it('should sort the objects into html, css, jsx, js order', () => {
|
it('should sort the objects into html, css, jsx, js order', () => {
|
||||||
const sorted = sortChallengeFiles(challengeFiles);
|
const sorted = sortChallengeFiles(challengeFiles);
|
||||||
const sortedKeys = sorted.map(({ fileKey }) => fileKey);
|
const sortedKeys = sorted.map(({ fileKey }) => fileKey);
|
||||||
const expected = ['indexhtml', 'indexcss', 'indexjsx', 'indexjs'];
|
const expected = ['indexhtml', 'stylescss', 'indexjsx', 'scriptjs'];
|
||||||
expect(sortedKeys).toStrictEqual(expected);
|
expect(sortedKeys).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user