Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
},
"dependencies": {
"commander": "^13.0.0",
"dedent": "^1.5.3",
"github-slugger": "^2.0.0",
"glob": "^11.0.0",
"hast-util-to-string": "^3.0.1",
Expand Down
44 changes: 17 additions & 27 deletions src/generators/addon-verify/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,13 @@ import { join } from 'node:path';

import { visit } from 'unist-util-visit';

import { updateFilesForBuild } from './utils/updateFilesForBuild.mjs';
import { generateFileList } from './utils/generateFileList.mjs';
import { EXTRACT_CODE_FILENAME_COMMENT } from './constants.mjs';

/**
* Normalizes a section name.
*
* @param {string} sectionName Section name
* @returns {string}
*/
export function normalizeSectionName(sectionName) {
return sectionName.toLowerCase().replace(/\s/g, '_').replace(/\W/g, '');
}
import {
generateSectionFolderName,
isBuildableSection,
normalizeSectionName,
} from './utils/section.mjs';

/**
* This generator generates a file list from code blocks extracted from
Expand Down Expand Up @@ -73,31 +68,26 @@ export default {

const files = await Promise.all(
Object.entries(sectionsCodeBlocks)
.filter(([, files]) => {
// Must have a .cc and a .js to be a valid test.
return (
files.some(file => file.name.endsWith('.cc')) &&
files.some(file => file.name.endsWith('.js'))
);
})
.flatMap(async ([sectionName, files], index) => {
const newFiles = updateFilesForBuild(files);
.filter(([, codeBlocks]) => isBuildableSection(codeBlocks))
.flatMap(async ([sectionName, codeBlocks], index) => {
const files = generateFileList(codeBlocks);

if (output) {
const normalizedSectionName = normalizeSectionName(sectionName);

const identifier = String(index + 1).padStart(2, '0');

const folder = `${identifier}_${normalizedSectionName}`;
const folderName = generateSectionFolderName(
normalizedSectionName,
index
);

await mkdir(join(output, folder), { recursive: true });
await mkdir(join(output, folderName), { recursive: true });

newFiles.forEach(async ({ name, content }) => {
await writeFile(join(output, folder, name), content);
files.forEach(async ({ name, content }) => {
await writeFile(join(output, folderName, name), content);
});
}

return newFiles;
return files;
})
);

Expand Down
60 changes: 60 additions & 0 deletions src/generators/addon-verify/utils/generateFileList.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import dedent from 'dedent';

/**
* Updates JavaScript files with correct require paths for the build tree.
*
* @param {string} content Original code
* @returns {string}
*/
const updateJsRequirePaths = content => {
return dedent`'use strict';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@araujogui I think you incorrectly used dedent.

const common = require('../../common');
${content.replace(
"'./build/Release/addon'",
'`./build/${common.buildType}/addon`'
)}
`;
};

/**
* Creates a binding.gyp configuration for C++ addon compilation.
*
* @param {string[]} sourceFiles List of source file names
* @returns {string}
*/
const createBindingGyp = sourceFiles => {
const config = {
targets: [
{
target_name: 'addon',
sources: sourceFiles,
includes: ['../common.gypi'],
},
],
};

return JSON.stringify(config);
};

/**
* Generates required files list from section's code blocks for C++ addon
* compilation.
*
* @param {{name: string, content: string}[]} codeBlocks Array of code blocks
* @returns {{name: string, content: string}[]}
*/
export const generateFileList = codeBlocks => {
const files = codeBlocks.map(({ name, content }) => {
return {
name,
content: name === 'test.js' ? updateJsRequirePaths(content) : content,
};
});

files.push({
name: 'binding.gyp',
content: createBindingGyp(files.map(({ name }) => name)),
});

return files;
};
37 changes: 37 additions & 0 deletions src/generators/addon-verify/utils/section.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Checks if a section contains the required code blocks for building.
* A buildable section must contain at least one C++ (.cc) file and one
* JavaScript (.js) file.
*
* @param {Array<{name: string; content: string}>} codeBlocks Array of code blocks
* @returns {boolean}
*/
export const isBuildableSection = codeBlocks => {
return (
codeBlocks.some(codeBlock => codeBlock.name.endsWith('.cc')) &&
codeBlocks.some(codeBlock => codeBlock.name.endsWith('.js'))
);
};

/**
* Normalizes a section name.
*
* @param {string} sectionName Original section name
* @returns {string}
*/
export const normalizeSectionName = sectionName => {
return sectionName.toLowerCase().replace(/\s/g, '_').replace(/\W/g, '');
};

/**
* Generates a standardized folder name for a section.
*
* @param {string} sectionName Normalized section name
* @param {number} index Zero-based section index
* @returns {string}
*/
export const generateSectionFolderName = (sectionName, index) => {
const identifier = String(index + 1).padStart(2, '0');

return `${identifier}_${sectionName}`;
};
41 changes: 0 additions & 41 deletions src/generators/addon-verify/utils/updateFilesForBuild.mjs

This file was deleted.

Loading