Website Structure
This commit is contained in:
parent
62812f2090
commit
71f0676a62
22365 changed files with 4265753 additions and 791 deletions
342
Frontend-Learner/node_modules/eslint-plugin-jsdoc/dist/generateDocs.cjs
generated
vendored
Normal file
342
Frontend-Learner/node_modules/eslint-plugin-jsdoc/dist/generateDocs.cjs
generated
vendored
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _index = _interopRequireDefault(require("../index.cjs"));
|
||||
var _decamelize = _interopRequireDefault(require("decamelize"));
|
||||
var _gitdown = _interopRequireDefault(require("gitdown"));
|
||||
var _glob = require("glob");
|
||||
var _nodeFs = _interopRequireDefault(require("node:fs"));
|
||||
var _nodePath = _interopRequireDefault(require("node:path"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /**
|
||||
* This script is used to inline assertions into the README.md documents.
|
||||
*/
|
||||
const dirname = __dirname;
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
*/
|
||||
const escapeDescription = str => {
|
||||
return str.replaceAll(/(?<!`|\* +|'|\/\/ )@\w+/gv, '<code>$&</code>');
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
const trimCode = code => {
|
||||
let lines = code.replace(/^\n/v, '').trimEnd().split('\n');
|
||||
const firsLineIndentation = lines[0].match(/^\s+/v);
|
||||
const lastLineIndentation = lines[lines.length - 1].match(/^\s+/v);
|
||||
const firstIndentSize = firsLineIndentation ? firsLineIndentation[0].length : 0;
|
||||
const lastIndentSize = lastLineIndentation ? lastLineIndentation[0].length : 0;
|
||||
lines = lines.map((line, index) => {
|
||||
const lineIndentSize = firstIndentSize !== 0 || index === 0 ? Math.min(firstIndentSize, lastIndentSize) : lastIndentSize;
|
||||
return line.slice(lineIndentSize);
|
||||
});
|
||||
return lines.join('\n').replaceAll('\r', '\\r');
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('eslint').RuleTester.InvalidTestCase|import('eslint').RuleTester.ValidTestCase} setup
|
||||
* @param {string} ruleName
|
||||
* @returns {string}
|
||||
*/
|
||||
const formatCodeSnippet = (setup, ruleName) => {
|
||||
const paragraphs = [];
|
||||
paragraphs.push(trimCode(setup.code));
|
||||
if (setup.settings) {
|
||||
paragraphs.push(`// Settings: ${JSON.stringify(setup.settings)}`);
|
||||
}
|
||||
if (setup.options) {
|
||||
paragraphs.push(`// "jsdoc/${ruleName}": ["error"|"warn", ${JSON.stringify(setup.options).slice(1)}`);
|
||||
}
|
||||
if ('errors' in setup) {
|
||||
paragraphs.push(`// Message: ${/** @type {Array<import('eslint').RuleTester.TestCaseError>} */setup.errors[0].message}`);
|
||||
}
|
||||
return paragraphs.join('\n');
|
||||
};
|
||||
const getAssertions = async () => {
|
||||
const assertionFiles = (await (0, _glob.glob)(_nodePath.default.resolve(dirname, '../../test/rules/assertions/*.js'))).filter(file => {
|
||||
return !file.includes('flatConfig');
|
||||
}).toReversed();
|
||||
const assertionNames = assertionFiles.map(filePath => {
|
||||
return _nodePath.default.basename(filePath, '.js');
|
||||
});
|
||||
const assertionCodes = await Promise.all(assertionFiles.map(async (filePath, idx) => {
|
||||
/**
|
||||
* @type {{
|
||||
* invalid: (import('eslint').RuleTester.InvalidTestCase & {ignoreReadme?: true})[],
|
||||
* valid: (import('eslint').RuleTester.ValidTestCase & {ignoreReadme?: true})[]
|
||||
* }}
|
||||
*/
|
||||
const codes = (await (specifier => new Promise(r => r(`${specifier}`)).then(s => _interopRequireWildcard(require(s))))(filePath)).default;
|
||||
const ruleName = (0, _decamelize.default)(assertionNames[idx], {
|
||||
separator: '-'
|
||||
});
|
||||
return {
|
||||
invalid: codes.invalid.filter(({
|
||||
ignoreReadme
|
||||
}) => {
|
||||
return !ignoreReadme;
|
||||
}).map(setup => {
|
||||
return formatCodeSnippet(setup, ruleName);
|
||||
}),
|
||||
valid: codes.valid.filter(({
|
||||
ignoreReadme
|
||||
}) => {
|
||||
return !ignoreReadme;
|
||||
}).map(setup => {
|
||||
return formatCodeSnippet(setup, ruleName);
|
||||
})
|
||||
};
|
||||
}));
|
||||
return {
|
||||
assertionNames,
|
||||
assertions: Object.fromEntries(assertionNames.map((assertionName, index) => {
|
||||
return [assertionName, assertionCodes[index]];
|
||||
}))
|
||||
};
|
||||
};
|
||||
const getSomeBranch = () => {
|
||||
const gitConfig = _nodeFs.default.readFileSync(_nodePath.default.join(dirname, '../../.git/config')).toString();
|
||||
const [, branch] = /\[branch "([^"]+)"\]/v.exec(gitConfig) || [];
|
||||
return branch;
|
||||
};
|
||||
|
||||
// Scan the directory for these instead?
|
||||
const extraFiles = ['settings.md', 'advanced.md', 'processors.md', 'README.md'];
|
||||
const otherPaths = extraFiles.map(extraFile => {
|
||||
return _nodePath.default.join(dirname, '..', '..', '.README', extraFile);
|
||||
});
|
||||
const generateDocs = async () => {
|
||||
const {
|
||||
assertionNames,
|
||||
assertions
|
||||
} = await getAssertions();
|
||||
|
||||
/** @type {import('json-schema').JSONSchema4[][]} */
|
||||
const schemas = [];
|
||||
|
||||
/**
|
||||
* @type {{
|
||||
* decamelized: string,
|
||||
* row: string
|
||||
* }[]}
|
||||
*/
|
||||
const tableRows = [];
|
||||
const docContents = await Promise.all([...assertionNames.map(assertionName => {
|
||||
const decamelized = (0, _decamelize.default)(assertionName, {
|
||||
separator: '-'
|
||||
});
|
||||
schemas.push(/** @type {import('json-schema').JSONSchema4[]} */
|
||||
_index.default.rules?.[decamelized].meta?.schema);
|
||||
const ruleDescription = _index.default.rules?.[decamelized]?.meta?.docs?.description;
|
||||
if (ruleDescription === undefined) {
|
||||
throw new Error(`Rule ${assertionName} missing description`);
|
||||
}
|
||||
const fixable = _index.default.rules?.[decamelized]?.meta?.fixable ?? null;
|
||||
const recommended = _index.default.configs['flat/recommended'].rules?.['jsdoc/' + decamelized] !== 'off';
|
||||
const tsRecommended = _index.default.configs['flat/recommended-typescript'].rules?.['jsdoc/' + decamelized] !== 'off';
|
||||
const tsRecommendedFlavor = _index.default.configs['flat/recommended-typescript-flavor'].rules?.['jsdoc/' + decamelized] !== 'off';
|
||||
tableRows.push({
|
||||
decamelized,
|
||||
row: `|${recommended ? tsRecommended && tsRecommendedFlavor ? ':heavy_check_mark:' : ':heavy_check_mark: (' + (tsRecommended ? 'On in TS' : 'Off in TS') + '; ' + (tsRecommendedFlavor ? 'On in TS flavor' : 'Off in TS flavor') + ')' : tsRecommended || tsRecommendedFlavor ? (tsRecommended ? 'On in TS' : 'Off in TS') + '; ' + (tsRecommendedFlavor ? 'On in TS flavor' : 'Off in TS flavor') : ''}|${fixable ? ':wrench:' : ''}| [${decamelized}](./docs/rules/${decamelized}.md#readme) | ${ruleDescription} |`
|
||||
});
|
||||
return _nodePath.default.join(dirname, '..', '..', '.README', 'rules', decamelized + '.md');
|
||||
}), ...otherPaths].map(async (docPath, idx) => {
|
||||
const gitdown = await _gitdown.default.readFile(docPath);
|
||||
gitdown.setConfig({
|
||||
gitinfo: {
|
||||
defaultBranchName: getSomeBranch() || 'master',
|
||||
gitPath: _nodePath.default.join(dirname, '../../.git')
|
||||
}
|
||||
});
|
||||
gitdown.registerHelper('rules-table', {
|
||||
compile() {
|
||||
return tableRows.toSorted(({
|
||||
decamelized
|
||||
}, {
|
||||
decamelized: dc
|
||||
}) => {
|
||||
return decamelized < dc ? -1 : decamelized > dc ? 1 : 0;
|
||||
}).map(({
|
||||
row
|
||||
}) => {
|
||||
return row;
|
||||
}).join('\n');
|
||||
}
|
||||
});
|
||||
gitdown.registerHelper('options', {
|
||||
compile() {
|
||||
if (!schemas[idx]) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('json-schema').JSONSchema4} schema
|
||||
* @param {number} jIdx
|
||||
* @param {import('json-schema').JSONSchema4[]} arr
|
||||
* @param {number} [nesting]
|
||||
*/
|
||||
const convertFromSchema = (schema, jIdx, arr, nesting = 3) => {
|
||||
let ret = '';
|
||||
switch (schema.type) {
|
||||
case 'array':
|
||||
ret += convertFromSchema(/** @type {import('json-schema').JSONSchema4} */schema.items, 0, [], nesting + 1);
|
||||
break;
|
||||
case 'object':
|
||||
if (!schema.properties) {
|
||||
break;
|
||||
}
|
||||
if (jIdx === 0) {
|
||||
ret += (nesting > 3 ? '\n' : '') + (arr.length <= 1 ? 'A single' : 'An') + ' options object has the following properties.\n';
|
||||
} else {
|
||||
ret += '\n\nThe next option is an object with the following properties.\n';
|
||||
}
|
||||
if (schema.description) {
|
||||
ret += `\n${escapeDescription(schema.description)}\n`;
|
||||
}
|
||||
for (const [property, innerSchema] of Object.entries(schema.properties)) {
|
||||
const {
|
||||
description,
|
||||
type
|
||||
} = innerSchema;
|
||||
if (!description) {
|
||||
throw new Error('Missing description for property ' + property + ' for rule ' + assertionNames[idx] + ' with schema ' + JSON.stringify(innerSchema));
|
||||
}
|
||||
ret += '\n' + '#'.repeat(nesting) + ` \`${property}\`
|
||||
|
||||
${type === 'object' && innerSchema.properties ? '' : escapeDescription(description) + '\n'}`;
|
||||
if (type === 'object' || type === 'array') {
|
||||
ret += convertFromSchema(innerSchema, 0, [], nesting + 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
if (jIdx !== 0) {
|
||||
throw new Error('Unexpected string schema');
|
||||
}
|
||||
|
||||
// If a simple string, should be documented by parent
|
||||
if (schema.enum) {
|
||||
ret += 'The first option is a string with the following possible values: ';
|
||||
ret += schema.enum?.map(val => {
|
||||
return `"${val}"`;
|
||||
}).join(', ') + '.\n';
|
||||
}
|
||||
if (schema.description) {
|
||||
ret += escapeDescription(schema.description);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Describe on parent object
|
||||
if (schema.anyOf) {
|
||||
break;
|
||||
}
|
||||
throw new Error('Unrecognized type ' + schema.type + ' for schema: ' + JSON.stringify(schema));
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
return schemas[idx].map((schema, jIdx, arr) => {
|
||||
return convertFromSchema(schema, jIdx, arr);
|
||||
}).join('');
|
||||
}
|
||||
});
|
||||
return gitdown.get();
|
||||
}));
|
||||
return docContents.map(docContent => {
|
||||
return docContent.replaceAll(/<!-- assertions-(passing|failing) ([a-z]+?) -->/gvi,
|
||||
/**
|
||||
* @param {string} _assertionsBlock
|
||||
* @param {string} passingFailing
|
||||
* @param {string} ruleName
|
||||
* @returns {string}
|
||||
*/
|
||||
(_assertionsBlock, passingFailing, ruleName) => {
|
||||
const ruleAssertions = assertions[ruleName];
|
||||
if (!ruleAssertions) {
|
||||
throw new Error(`No assertions available for rule "${ruleName}".`);
|
||||
}
|
||||
return passingFailing === 'failing' ? 'The following patterns are considered problems:\n\n````ts\n' + ruleAssertions.invalid.join('\n\n') + '\n````\n\n' : 'The following patterns are not considered problems:\n\n````ts\n' + ruleAssertions.valid.join('\n\n') + '\n````\n';
|
||||
}
|
||||
// Allow relative paths in source for #902 but generate compiled file in
|
||||
// manner compatible with GitHub and npmjs.com
|
||||
).replaceAll('(../#', '(#user-content-eslint-plugin-jsdoc-');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {string[]}
|
||||
*/
|
||||
const getDocPaths = () => {
|
||||
const basePath = _nodePath.default.join(dirname, '..', '..', '.README');
|
||||
const writeBasePath = _nodePath.default.join(dirname, '..', '..', 'docs');
|
||||
const docPaths = /** @type {string[]} */_nodeFs.default.readdirSync(basePath).flatMap(docFile => {
|
||||
if (extraFiles.includes(docFile)) {
|
||||
// Will get path separately below
|
||||
return null;
|
||||
}
|
||||
if (docFile === '.DS_Store') {
|
||||
return null;
|
||||
}
|
||||
const innerBasePath = _nodePath.default.join(basePath, docFile);
|
||||
const writeInnerBasePath = _nodePath.default.join(writeBasePath, docFile);
|
||||
const stat = _nodeFs.default.statSync(innerBasePath);
|
||||
if (stat.isFile()) {
|
||||
// Currently settings and advanced
|
||||
return writeInnerBasePath;
|
||||
}
|
||||
if (stat.isDirectory()) {
|
||||
return _nodeFs.default.readdirSync(innerBasePath).map(innerDocFile => {
|
||||
return _nodePath.default.join(writeInnerBasePath, innerDocFile);
|
||||
}).toSorted((a, b) => {
|
||||
const newA = a.replace(/\.md/v, '');
|
||||
const newB = b.replace(/\.md/v, '');
|
||||
return newA < newB ? -1 : newB > newA ? 1 : 0;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}).filter(Boolean);
|
||||
return [...docPaths, ...extraFiles.slice(0, -1).map(extraFile => {
|
||||
return _nodePath.default.join(dirname, '..', '..', 'docs', extraFile);
|
||||
}), _nodePath.default.join(dirname, '..', '..', 'README.md')];
|
||||
};
|
||||
const generateDocsAndWriteToDisk = async () => {
|
||||
const [docContents, docPaths] = await Promise.all([generateDocs(), getDocPaths()]);
|
||||
for (const [idx, docContent] of docContents.entries()) {
|
||||
const destPath = docPaths[idx];
|
||||
_nodeFs.default.writeFileSync(destPath, docContent);
|
||||
}
|
||||
};
|
||||
const assertDocsAreUpToDate = async () => {
|
||||
const [docContents, docPaths] = await Promise.all([generateDocs(), getDocPaths()]);
|
||||
for (const [idx, docContent] of docContents.entries()) {
|
||||
const docPath = docPaths[idx];
|
||||
const isUpToDate = _nodeFs.default.readFileSync(docPath, 'utf8') === docContent;
|
||||
if (!isUpToDate) {
|
||||
throw new Error('Docs are not up to date, please run `pnpm run create-docs` to update it.');
|
||||
}
|
||||
}
|
||||
};
|
||||
const main = async () => {
|
||||
try {
|
||||
const hasCheckFlag = process.argv.includes('--check');
|
||||
if (hasCheckFlag) {
|
||||
await assertDocsAreUpToDate();
|
||||
} else {
|
||||
await generateDocsAndWriteToDisk();
|
||||
}
|
||||
} catch (error) {
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
main();
|
||||
var _default = exports.default = generateDocs;
|
||||
module.exports = exports.default;
|
||||
//# sourceMappingURL=generateDocs.cjs.map
|
||||
Loading…
Add table
Add a link
Reference in a new issue