2018-08-31 17:27:21 +00:00
|
|
|
/** @format */
|
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
|
|
|
const { isArray, uniq } = require( 'lodash' );
|
|
|
|
const fs = require( 'fs' );
|
|
|
|
const path = require( 'path' );
|
|
|
|
const recast = require( 'recast' );
|
|
|
|
const types = require( 'ast-types' );
|
|
|
|
const { namedTypes } = types;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
|
|
|
const { camelCaseDash } = require( './formatting' );
|
|
|
|
|
2018-12-22 11:46:10 +00:00
|
|
|
const ANALYTICS_FOLDER = path.resolve( __dirname, '../../../client/analytics/components/' );
|
2018-11-15 18:16:23 +00:00
|
|
|
const PACKAGES_FOLDER = path.resolve( __dirname, '../../../packages/components/src/' );
|
2018-08-31 17:27:21 +00:00
|
|
|
const DOCS_FOLDER = path.resolve( __dirname, '../../../docs/components/' );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get an array of files exported from in the given file
|
|
|
|
*
|
|
|
|
* @param { string } filePath The file to parse for exports.
|
|
|
|
* @return { string } Formatted string.
|
|
|
|
*/
|
|
|
|
function getExportedFileList( filePath ) {
|
|
|
|
const content = fs.readFileSync( filePath );
|
|
|
|
const ast = recast.parse( content );
|
|
|
|
const files = [];
|
|
|
|
types.visit( ast, {
|
|
|
|
// This method will be called for any node with .type "ExportNamedDeclaration":
|
|
|
|
visitExportNamedDeclaration: function( nodePath ) {
|
|
|
|
const { node } = nodePath;
|
|
|
|
if (
|
|
|
|
namedTypes.Literal.check( node.source ) &&
|
|
|
|
isArray( node.specifiers ) &&
|
|
|
|
namedTypes.ExportSpecifier.check( node.specifiers[ 0 ] )
|
|
|
|
) {
|
|
|
|
if ( -1 === node.source.value.indexOf( 'use-filters' ) ) {
|
|
|
|
files.push( node.source.value );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Keep traversing this path…
|
|
|
|
this.traverse( nodePath );
|
|
|
|
},
|
|
|
|
} );
|
|
|
|
|
|
|
|
return files;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the markdown file name for a given component file.
|
|
|
|
*
|
|
|
|
* @param { string } filepath File path for this component.
|
2018-12-22 11:46:10 +00:00
|
|
|
* @param { string } route Folder where the docs must be stored.
|
2018-08-31 17:27:21 +00:00
|
|
|
* @param { boolean } absolute Whether to return full path (true) or just filename (false).
|
|
|
|
* @return { string } Markdown file name.
|
|
|
|
*/
|
2018-12-22 11:46:10 +00:00
|
|
|
function getMdFileName( filepath, route, absolute = true ) {
|
2018-08-31 17:27:21 +00:00
|
|
|
const fileParts = filepath.split( '/components/' );
|
|
|
|
if ( ! fileParts || ! fileParts[ 1 ] ) {
|
|
|
|
return;
|
|
|
|
}
|
2019-08-30 23:06:33 +00:00
|
|
|
let name = fileParts[ 1 ].replace( 'src/', '' ).split( '/' )[ 0 ];
|
|
|
|
|
|
|
|
// Package components have a different structure.
|
|
|
|
if ( 'packages' === route ) {
|
|
|
|
name += '/README';
|
|
|
|
}
|
|
|
|
|
2018-08-31 17:27:21 +00:00
|
|
|
if ( ! absolute ) {
|
|
|
|
return name + '.md';
|
|
|
|
}
|
2018-12-22 11:46:10 +00:00
|
|
|
return path.resolve( DOCS_FOLDER + '/' + route + '/', name + '.md' );
|
2018-08-31 17:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get an array of files exported from in the given file
|
|
|
|
*
|
|
|
|
* @param { array } files A list of files, presumably in the components directory.
|
|
|
|
* @param { string } basePath The absolute path to the components directory.
|
|
|
|
* @return { array } Updated array with absolute paths to all files.
|
|
|
|
*/
|
2018-12-10 22:27:32 +00:00
|
|
|
function getRealFilePaths( files, basePath = PACKAGES_FOLDER ) {
|
2018-08-31 17:27:21 +00:00
|
|
|
files.sort();
|
|
|
|
return files.map( file => {
|
|
|
|
const fullPath = path.resolve( basePath, file );
|
|
|
|
if ( isFile( fullPath ) ) {
|
|
|
|
return fullPath;
|
|
|
|
}
|
|
|
|
if ( isFile( `${ fullPath }.js` ) ) {
|
|
|
|
return `${ fullPath }.js`;
|
|
|
|
}
|
|
|
|
if ( isFile( `${ fullPath }/index.js` ) ) {
|
|
|
|
return `${ fullPath }/index.js`;
|
|
|
|
}
|
|
|
|
const folderName = path.basename( fullPath );
|
|
|
|
if ( isFile( `${ fullPath }/${ folderName }.js` ) ) {
|
|
|
|
return `${ fullPath }/${ folderName }.js`;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fullPath;
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if a file exists and is not a directory.
|
|
|
|
*
|
|
|
|
* @param { string } file A file path to test.
|
|
|
|
* @return { boolean } True if this path exists and is a file.
|
|
|
|
*/
|
|
|
|
function isFile( file ) {
|
|
|
|
if ( ! fs.existsSync( file ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const stats = fs.statSync( file );
|
|
|
|
return stats && stats.isFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a table of contents given a list of markdown files.
|
|
|
|
*
|
2018-12-22 11:46:10 +00:00
|
|
|
* @param { array } files A list of files, presumably in the components directory.
|
|
|
|
* @param { string } route Folder where the docs are stored.
|
|
|
|
* @param { string } title Title of the TOC section
|
|
|
|
* @return { string } TOC contents.
|
2018-08-31 17:27:21 +00:00
|
|
|
*/
|
2018-12-22 11:46:10 +00:00
|
|
|
function getTocSection( files, route, title ) {
|
|
|
|
const mdFiles = files.map( f => getMdFileName( f, route, false ) ).sort();
|
|
|
|
|
|
|
|
const toc = uniq( mdFiles ).map( doc => {
|
2019-08-30 23:06:33 +00:00
|
|
|
const name = camelCaseDash( doc.replace( '.md', '' ).split( '/' )[ 0 ] );
|
2018-12-22 11:46:10 +00:00
|
|
|
return ` * [${ name }](components/${ route }/${ doc })`;
|
|
|
|
} );
|
2018-08-31 17:27:21 +00:00
|
|
|
|
2018-12-22 11:46:10 +00:00
|
|
|
return [
|
|
|
|
' * [' + title + '](components/' + route + '/)',
|
|
|
|
...toc,
|
|
|
|
];
|
2018-08-31 17:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
DOCS_FOLDER,
|
2018-12-22 11:46:10 +00:00
|
|
|
ANALYTICS_FOLDER,
|
2018-11-15 18:16:23 +00:00
|
|
|
PACKAGES_FOLDER,
|
2018-08-31 17:27:21 +00:00
|
|
|
getExportedFileList,
|
|
|
|
getMdFileName,
|
|
|
|
getRealFilePaths,
|
2018-12-22 11:46:10 +00:00
|
|
|
getTocSection,
|
2018-08-31 17:27:21 +00:00
|
|
|
};
|