refactor(tools,client): remove head and tail logic (#66524)

This commit is contained in:
Sem Bauke
2026-03-17 17:59:16 +01:00
committed by GitHub
parent 1990ba6794
commit e66bf09dce
34 changed files with 24 additions and 998 deletions

View File

@@ -10,10 +10,8 @@ exports[`add-seed plugin > should have an output to match the snapshot 1`] = `
</html>",
"editableRegionBoundaries": [],
"ext": "html",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
{
"contents": "body {
@@ -21,19 +19,15 @@ exports[`add-seed plugin > should have an output to match the snapshot 1`] = `
}",
"editableRegionBoundaries": [],
"ext": "css",
"head": "",
"id": "",
"name": "styles",
"tail": "",
},
{
"contents": "var x = 'y';",
"editableRegionBoundaries": [],
"ext": "js",
"head": "",
"id": "",
"name": "script",
"tail": "",
},
{
"contents": "{
@@ -43,10 +37,8 @@ exports[`add-seed plugin > should have an output to match the snapshot 1`] = `
}",
"editableRegionBoundaries": [],
"ext": "json",
"head": "",
"id": "",
"name": "tsconfig",
"tail": "",
},
],
}

View File

@@ -10,28 +10,22 @@ exports[`add solution plugin > should have an output to match the snapshot 1`] =
</body>
</html>",
"ext": "html",
"head": "",
"id": "html-key",
"name": "index",
"tail": "",
},
{
"contents": "body {
background: white;
}",
"ext": "css",
"head": "",
"id": "",
"name": "styles",
"tail": "",
},
{
"contents": "var x = 'y';",
"ext": "js",
"head": "",
"id": "",
"name": "script",
"tail": "",
},
],
],

View File

@@ -38,22 +38,17 @@ function addSeeds() {
// processing in these cases.
if (isEmpty(seedTree.children)) return;
const contentsTree = root(getSection(seedTree, `--seed-contents--`));
const headTree = root(getSection(seedTree, `--before-user-code--`));
const tailTree = root(getSection(seedTree, `--after-user-code--`));
const seeds = {};
// While before and after code are optional, the contents are not
// Seed contents are required.
if (isEmpty(contentsTree.children))
throw Error('## --seed-contents-- must appear in # --seed-- sections');
const visitForContents = visitChildren(
getFileVisitor(seeds, 'contents', validateEditableMarkers)
);
const visitForHead = visitChildren(getFileVisitor(seeds, 'head'));
const visitForTail = visitChildren(getFileVisitor(seeds, 'tail'));
visitForContents(contentsTree);
visitForHead(headTree);
visitForTail(tailTree);
const seedVals = Object.values(seeds);
file.data = {
...file.data,

View File

@@ -7,14 +7,9 @@ import addSeed from './add-seed';
describe('add-seed plugin', () => {
let adjacentKeysAST,
withSeedKeysAST,
withBeforeAfterAST,
cCodeAST,
withErmsOnOneLineAST,
withEmptyAfterAST,
withEmptyBeforeAST,
withEmptyContentsAST,
withInvalidBeforeAST,
withInvalidAfterAST,
simpleAST,
withEditableMarkersAST,
withSeedKeysOrphanAST,
@@ -27,16 +22,11 @@ describe('add-seed plugin', () => {
beforeAll(async () => {
adjacentKeysAST = await parseFixture('with-seed-keys-adjacent.md');
withSeedKeysAST = await parseFixture('with-seed-keys.md');
withBeforeAfterAST = await parseFixture('with-before-and-after.md');
cCodeAST = await parseFixture('with-c-code.md');
withErmsOnOneLineAST = await parseFixture(
'with-editable-markers-on-one-line.md'
);
withEmptyAfterAST = await parseFixture('with-empty-after.md');
withEmptyBeforeAST = await parseFixture('with-empty-before.md');
withEmptyContentsAST = await parseFixture('with-empty-contents.md');
withInvalidBeforeAST = await parseFixture('with-invalid-before.md');
withInvalidAfterAST = await parseFixture('with-invalid-after.md');
simpleAST = await parseFixture('simple.md');
withEditableMarkersAST = await parseFixture('with-editable-markers.md');
withSeedKeysOrphanAST = await parseFixture('with-seed-keys-orphan.md');
@@ -65,23 +55,19 @@ describe('add-seed plugin', () => {
});
it('adds test objects to the challengeFiles array following a schema', () => {
expect.assertions(15);
expect.assertions(11);
plugin(simpleAST, file);
const {
data: { challengeFiles }
} = file;
const testObject = challengeFiles.find(x => x.ext === 'js');
expect(Object.keys(testObject).length).toEqual(7);
expect(Object.keys(testObject).length).toEqual(5);
expect(testObject).toHaveProperty('ext');
expect(typeof testObject['ext']).toBe('string');
expect(testObject).toHaveProperty('name');
expect(typeof testObject['name']).toBe('string');
expect(testObject).toHaveProperty('contents');
expect(typeof testObject['contents']).toBe('string');
expect(testObject).toHaveProperty('head');
expect(typeof testObject['head']).toBe('string');
expect(testObject).toHaveProperty('tail');
expect(typeof testObject['tail']).toBe('string');
expect(testObject).toHaveProperty('id');
expect(typeof testObject['id']).toBe('string');
expect(testObject).toHaveProperty('editableRegionBoundaries');
@@ -155,96 +141,14 @@ describe('add-seed plugin', () => {
expect(file).toEqual(fileTwo);
});
it('gets the before-user-code for each language', () => {
expect.assertions(3);
plugin(withBeforeAfterAST, file);
const {
data: { challengeFiles }
} = file;
const scriptjs = challengeFiles.find(x => x.ext === 'js');
const indexhtml = challengeFiles.find(x => x.ext === 'html');
const stylescss = challengeFiles.find(x => x.ext === 'css');
expect(scriptjs.head).toBe('');
expect(indexhtml.head).toBe(`<!-- comment -->`);
expect(stylescss.head).toBe(`body {
etc: ''
}`);
});
it('gets the after-user-code for each language', () => {
expect.assertions(3);
plugin(withBeforeAfterAST, file);
const {
data: { challengeFiles }
} = file;
const scriptjs = challengeFiles.find(x => x.ext === 'js');
const indexhtml = challengeFiles.find(x => x.ext === 'html');
const stylescss = challengeFiles.find(x => x.ext === 'css');
expect(scriptjs.tail).toBe(`function teardown(params) {
// after
}`);
expect(indexhtml.tail).toBe('');
expect(stylescss.tail).toBe(`body {
background: blue;
}`);
});
it('throws an error if there is any code of an unsupported language', () => {
expect.assertions(1);
expect(() => plugin(cCodeAST, file)).toThrow(
"On line 30 'c' is not a supported language.\n" +
"On line 18 'c' is not a supported language.\n" +
' Please use one of js, css, html, jsx, ts, tsx or py'
);
});
it('throws if there is before/after code with empty blocks', () => {
expect.assertions(2);
expect(() => plugin(withInvalidBeforeAST, file)).toThrow(
'Empty code block in --before-user-code-- section'
);
expect(() => plugin(withInvalidAfterAST, file)).toThrow(
'Empty code block in --after-user-code-- section'
);
});
it('quietly ignores empty before sections', () => {
expect.assertions(6);
plugin(withEmptyBeforeAST, file);
const {
data: { challengeFiles }
} = file;
const scriptjs = challengeFiles.find(x => x.ext === 'js');
const indexhtml = challengeFiles.find(x => x.ext === 'html');
const stylescss = challengeFiles.find(x => x.ext === 'css');
expect(scriptjs.head).toBe('');
expect(scriptjs.tail).toBe('function teardown(params) {\n // after\n}');
expect(indexhtml.head).toBe('');
expect(indexhtml.tail).toBe('');
expect(stylescss.head).toBe('');
expect(stylescss.tail).toBe('body {\n background: blue;\n}');
});
it('quietly ignores empty after sections', () => {
expect.assertions(6);
plugin(withEmptyAfterAST, file);
const {
data: { challengeFiles }
} = file;
const scriptjs = challengeFiles.find(x => x.ext === 'js');
const indexhtml = challengeFiles.find(x => x.ext === 'html');
const stylescss = challengeFiles.find(x => x.ext === 'css');
expect(scriptjs.head).toBe('');
expect(scriptjs.tail).toBe('');
expect(indexhtml.head).toBe('<!-- comment -->');
expect(indexhtml.tail).toBe('');
expect(stylescss.head).toBe("body {\n etc: ''\n}");
expect(stylescss.tail).toBe('');
});
it('throws an error (with line number) if 2 markers appear on 1 line', () => {
expect.assertions(1);
expect(() => plugin(withErmsOnOneLineAST, file)).toThrow(
@@ -253,17 +157,13 @@ describe('add-seed plugin', () => {
});
it('handles jsx', () => {
expect.assertions(3);
expect.assertions(1);
plugin(withSeedKeysJSXAST, file);
const {
data: { challengeFiles }
} = file;
const indexjsx = challengeFiles.find(x => x.ext === 'jsx');
expect(indexjsx.head).toBe(`function setup() {}`);
expect(indexjsx.tail).toBe(`function teardown(params) {
// after
}`);
expect(indexjsx.contents).toBe(`var x = 'y';
/* comment */

View File

@@ -40,23 +40,19 @@ describe('add solution plugin', () => {
});
it('adds solution objects to the challengeFiles array following a schema', () => {
expect.assertions(13);
expect.assertions(9);
plugin(mockAST, file);
const {
data: { solutions }
} = file;
const testObject = solutions[0].find(solution => solution.ext === 'js');
expect(Object.keys(testObject).length).toEqual(6);
expect(Object.keys(testObject).length).toEqual(4);
expect(testObject).toHaveProperty('ext');
expect(typeof testObject['ext']).toBe('string');
expect(testObject).toHaveProperty('name');
expect(typeof testObject['name']).toBe('string');
expect(testObject).toHaveProperty('contents');
expect(typeof testObject['contents']).toBe('string');
expect(testObject).toHaveProperty('head');
expect(typeof testObject['head']).toBe('string');
expect(testObject).toHaveProperty('tail');
expect(typeof testObject['tail']).toBe('string');
expect(testObject).toHaveProperty('id');
expect(typeof testObject['id']).toBe('string');
});

View File

@@ -4,10 +4,6 @@ const position = require('unist-util-position');
const getId = require('./get-id');
const keyToSection = {
head: 'before-user-code',
tail: 'after-user-code'
};
const supportedLanguages = [
'js',
'css',
@@ -29,8 +25,6 @@ function defaultFile(lang, id) {
ext: lang,
name: getFilenames(lang),
contents: '',
head: '',
tail: '',
id
};
}
@@ -74,11 +68,6 @@ function codeToData(node, seeds, seedKey, validate) {
if (!seeds[fileId]) {
seeds[fileId] = defaultFile(shortLang, id);
}
if (isEmpty(node.value) && seedKey !== 'contents') {
const section = keyToSection[seedKey];
throw Error(`Empty code block in --${section}-- section`);
}
seeds[fileId][seedKey] = isEmpty(seeds[fileId][seedKey])
? node.value
: seeds[fileId][seedKey] + '\n' + node.value;

View File

@@ -30,9 +30,6 @@ const VALID_MARKERS = [
'## --sentence--',
'## --text--',
'## --video-solution--',
// TODO: Remove these two markers when https://github.com/freeCodeCamp/freeCodeCamp/issues/57107 is resolved
'## --after-user-code--',
'## --before-user-code--',
// Level 3
'### --audio-id--',