github-action-readme-generator
Version:
The docs generator for GitHub Actions. Auto-syncs action.yml to README.md with 8 sections: inputs, outputs, usage, badges, branding & more. Works as CLI or GitHub Action.
104 lines • 4.14 kB
JavaScript
/**
* This TypeScript code imports the necessary modules and defines a class named `ReadmeEditor`.
* The class represents an editor for modifying a README file.
* It has methods to update specific sections within the file and dump the modified content back to the file.
*/
import * as fs from 'node:fs';
import { EOL } from 'node:os';
import * as core from '@actions/core';
import { indexOfRegex, lastIndexOfRegex } from './helpers.js';
import LogTask from './logtask/index.js';
import { formatMarkdown } from './prettier.js';
/**
* The format for the start token of a section.
*/
export const startTokenFormat = '(^|[^`\\\\])<!--\\s+start\\s+%s\\s+-->';
/**
* The format for the end token of a section.
*/
export const endTokenFormat = '(^|[^`\\\\])<!--\\s+end\\s+%s\\s+-->';
export default class ReadmeEditor {
log = new LogTask('ReadmeEditor');
/**
* The path to the README file.
*/
filePath;
fileContent;
/**
* Creates a new instance of `ReadmeEditor`.
* @param {string} filePath - The path to the README file.
*/
constructor(filePath) {
this.filePath = filePath;
try {
fs.accessSync(filePath);
this.fileContent = fs.readFileSync(filePath, 'utf8');
if (process.env.GITHUB_ACTIONS) {
core.setOutput('readme_before', this.fileContent);
}
}
catch (error) {
this.log.fail(`Readme at '${filePath}' does not exist.`);
throw error;
}
}
/**
* Gets the current README content.
* @returns {string} - The README file content.
*/
getReadmeContent() {
return this.fileContent;
}
/**
* Gets the indexes of the start and end tokens for a given section.
* @param {string} token - The section token.
* @returns {number[]} - The indexes of the start and end tokens.
*/
getTokenIndexes(token, logTask) {
const log = logTask ?? new LogTask('getTokenIndexes');
const startRegExp = new RegExp(startTokenFormat.replace('%s', token));
const stopRegExp = new RegExp(endTokenFormat.replace('%s', token));
const startIndex = lastIndexOfRegex(this.fileContent, startRegExp);
if (startIndex === -1) {
log.debug(`No start token found for section '${token}'. Skipping`);
return [];
}
const stopIndex = indexOfRegex(this.fileContent, stopRegExp);
if (stopIndex === -1) {
log.debug(`No start or end token found for section '${token}'. Skipping`);
return [];
}
return [startIndex, stopIndex];
}
/**
* Updates a specific section in the README file with the provided content.
* @param {string} name - The name of the section.
* @param {string | string[]} providedContent - The content to update the section with.
* @param {boolean} addNewlines - Whether to add newlines before and after the content.
*/
updateSection(name, providedContent, addNewlines = true) {
const log = new LogTask(name);
const content = (Array.isArray(providedContent) ? providedContent.join(EOL) : (providedContent ?? '')).trim();
log.info(`Looking for the ${name} token in ${this.filePath}`);
const [startIndex, stopIndex] = this.getTokenIndexes(name, log);
if (startIndex && stopIndex) {
const beforeContent = this.fileContent.slice(0, startIndex);
const afterContent = this.fileContent.slice(stopIndex);
this.fileContent = addNewlines
? `${beforeContent}\n\n${content}\n${afterContent}`
: `${beforeContent}${content}${afterContent}`;
}
}
/**
* Dumps the modified content back to the README file.
* @returns {Promise<void>}
*/
async dumpToFile() {
const content = await formatMarkdown(this.fileContent);
if (process.env.GITHUB_ACTIONS) {
core.setOutput('readme_after', content);
}
return fs.promises.writeFile(this.filePath, content, 'utf8');
}
}
//# sourceMappingURL=readme-editor.js.map