Skip to content

Commit

Permalink
Merge pull request #217 from inversify/chore/update-code-examples-wit…
Browse files Browse the repository at this point in the history
…h-exclude-feature

Update example generator
  • Loading branch information
notaphplover authored Dec 30, 2024
2 parents f2438c8 + a0fcb91 commit 9b35f08
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 47 deletions.
5 changes: 3 additions & 2 deletions packages/docs/tools/inversify-code-examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ Inversify docs code examples.
## Adding code examples

1. Just create your code example in the `src/examples` folder with an integration test to verify the expected behavior.
2. User a `// Begin-example` comment to set the begining of the example.
3. Use a `// End-example` comment to set the end of the example.
2. Use a `// Begin-example` comment to set the begining of the example.
3. Use a `// Exclude-from-example` comment to exclude a sentence from the example.
4. Use a `// End-example` comment to set the end of the example.

2. Run the `build` script.
3. Your code example will be available in the `generated/examples` folder.
2 changes: 1 addition & 1 deletion packages/docs/tools/inversify-code-examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"scripts": {
"build": "pnpm run build:cjs && pnpm run generate:examples",
"build:cjs": "tsc --build tsconfig.cjs.json && pnpm exec foundation-ts-package-cjs ./lib/cjs",
"build:clean": "rimraf lib",
"build:clean": "rimraf generated lib",
"format": "prettier --write ./src/**/*.ts",
"generate:examples": "node ./lib/cjs/scripts/generateExamples.mjs",
"lint": "eslint ./src",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,37 @@ const EXAMPLES_GLOB_PATTERN: string = `${SRC_FOLDER}/examples/*.ts`;
const TEST_EXAMPLES_GLOB_PATTERN: string = `${SRC_FOLDER}/examples/*.spec.ts`;

enum RelevanCommentKind {
beginExample,
endExample,
begin,
end,
exclude,
}

interface RelevanCommentPositions {
[RelevanCommentKind.beginExample]: [ts.CommentRange, ts.Node][];
[RelevanCommentKind.endExample]: [ts.CommentRange, ts.Node][];
[RelevanCommentKind.begin]: [ts.CommentRange, ts.Node][];
[RelevanCommentKind.end]: [ts.CommentRange, ts.Node][];
[RelevanCommentKind.exclude]: [ts.CommentRange, ts.Node][];
}

const BEGIN_EXAMPLE_COMMENT: string = '// Begin-example';
const END_EXAMPLE_COMMENT: string = '// End-example';
const EXCLUDE_FROM_EXAMPLE_COMMENT: string = '// Exclude-from-example';

const commentToRelevantCommentKindMap: {
[key: string]: RelevanCommentKind;
} = {
[BEGIN_EXAMPLE_COMMENT]: RelevanCommentKind.beginExample,
[END_EXAMPLE_COMMENT]: RelevanCommentKind.endExample,
[BEGIN_EXAMPLE_COMMENT]: RelevanCommentKind.begin,
[END_EXAMPLE_COMMENT]: RelevanCommentKind.end,
[EXCLUDE_FROM_EXAMPLE_COMMENT]: RelevanCommentKind.exclude,
};

function findRelevantCommentPositions(
fileContent: string,
sourceFileNode: ts.Node,
): RelevanCommentPositions {
const positions: RelevanCommentPositions = {
[RelevanCommentKind.beginExample]: [],
[RelevanCommentKind.endExample]: [],
[RelevanCommentKind.begin]: [],
[RelevanCommentKind.end]: [],
[RelevanCommentKind.exclude]: [],
};

visitRelevantCommentPositions(fileContent, sourceFileNode, positions);
Expand Down Expand Up @@ -76,38 +81,6 @@ function visitRelevantCommentPositions(
}
}

function getCodeExampleBegining(
sourceFile: ts.SourceFile,
positions: RelevanCommentPositions,
): number {
const [firstBeginExamplePosition]: [ts.CommentRange, ts.Node][] =
positions[RelevanCommentKind.beginExample];

if (firstBeginExamplePosition === undefined) {
return 0;
}

const [, node] = firstBeginExamplePosition;

return node.getStart(sourceFile);
}

function getCodeExampleEnd(
sourceFile: ts.SourceFile,
positions: RelevanCommentPositions,
): number {
const lastEndExamplePosition: [ts.CommentRange, ts.Node] | undefined =
positions[RelevanCommentKind.endExample].at(-1);

if (lastEndExamplePosition === undefined) {
return sourceFile.end;
}

const [comment] = lastEndExamplePosition;

return comment.pos;
}

async function getExamplePaths(): Promise<string[]> {
return glob(EXAMPLES_GLOB_PATTERN, { ignore: TEST_EXAMPLES_GLOB_PATTERN });
}
Expand All @@ -126,10 +99,7 @@ async function generateExampleFromSourceCode(
const relevantCommentPositions: RelevanCommentPositions =
findRelevantCommentPositions(fileContent, sourceFile);

return fileContent.slice(
getCodeExampleBegining(sourceFile, relevantCommentPositions),
getCodeExampleEnd(sourceFile, relevantCommentPositions),
);
return transformSourceFile(sourceFile, relevantCommentPositions);
}

async function writeSourceCodeExample(
Expand All @@ -153,11 +123,73 @@ async function run(): Promise<void> {
const codeExamplePaths: string[] = await getExamplePaths();

for (const codeExamplePath of codeExamplePaths) {
console.log(`Generating code example at ${codeExamplePath}...`);

await writeSourceCodeExample(
codeExamplePath,
await generateExampleFromSourceCode(codeExamplePath),
);

console.log('Code example generated successfully');
}
}

await run();

function getExcludeRanges(
sourceFile: ts.SourceFile,
positions: RelevanCommentPositions,
): [number, number][] {
const [firstBeginOfExamplePosition]: [ts.CommentRange, ts.Node][] =
positions[RelevanCommentKind.begin];

const lastEndOfExamplePosition: [ts.CommentRange, ts.Node] | undefined =
positions[RelevanCommentKind.end].at(-1);

const excludedRanges: [number, number][] = [];

if (firstBeginOfExamplePosition !== undefined) {
const [commentNode] = firstBeginOfExamplePosition;

excludedRanges.push([0, commentNode.end]);
}

for (const [, node] of positions[RelevanCommentKind.exclude]) {
excludedRanges.push([node.pos, node.end]);
}

if (lastEndOfExamplePosition !== undefined) {
const [, node] = lastEndOfExamplePosition;

excludedRanges.push([node.pos, sourceFile.end]);
}

return excludedRanges;
}

function transformSourceFile(
sourceFile: ts.SourceFile,
positions: RelevanCommentPositions,
): string {
const excludedRanges: [number, number][] = getExcludeRanges(
sourceFile,
positions,
);

let transformedSourceCode: string = '';
let currentIndex: number = 0;

for (const [min, max] of excludedRanges) {
while (currentIndex <= max) {
if (currentIndex < min) {
transformedSourceCode += sourceFile.text[currentIndex];
}

++currentIndex;
}
}

transformedSourceCode += sourceFile.text.slice(currentIndex);

return transformedSourceCode;
}

0 comments on commit 9b35f08

Please sign in to comment.