megadoc-plugin-markdown
Version:
Markdown documentation generator for megadoc.
176 lines (144 loc) • 4.72 kB
JavaScript
const React = require("react");
const Link = require('components/Link');
const HotItemIndicator = require('components/HotItemIndicator');
const { ROOT_FOLDER_ID } = require('constants');
const ArticleTOC = require('./ArticleTOC');
const filterDocuments = require('utils/filterDocuments')
const strHumanize = require('../../lib/utils/strHumanize');
const { object } = React.PropTypes;
var Browser = React.createClass({
propTypes: {
namespaceNode: object,
documentNode: object,
documentEntityNode: object,
expanded: React.PropTypes.bool,
flat: React.PropTypes.bool,
filter: React.PropTypes.array,
},
getInitialState() {
return {
groupByFolder: false
};
},
render() {
const { namespaceNode } = this.props;
return (
<nav className="megadoc-document-browser markdown-browser">
<div>
{Array.isArray(namespaceNode.config.folders) && namespaceNode.config.folders.length > 0 ? (
FolderHierarchy(namespaceNode).map(this.renderFolder)
) : (
namespaceNode.documents
.filter(filterDocuments(this.props.filter))
.map(this.renderArticle)
)}
</div>
</nav>
);
},
renderFolders(folders) {
return (
<div>
{folders.map(this.renderFolder)}
</div>
);
},
renderFolder(folder) {
const { documents } = folder;
const filtered = documents.filter(filterDocuments(this.props.filter))
const { config } = this.props.namespaceNode;
if (!filtered.length) {
return null;
}
const effectiveFolderTitle = folder.title === '.' ? config.rootFolderTitle : folder.title
return (
<div key={folder.path} className="class-browser__category">
{effectiveFolderTitle && effectiveFolderTitle.length > 0 && (
<h3 className="class-browser__category-name">
{effectiveFolderTitle}
</h3>
)}
<div>
{documents.map(this.renderArticle)}
</div>
</div>
);
},
renderArticle(documentNode) {
const article = documentNode.properties;
const isActive = this.props.documentNode === documentNode || this.props.expanded;
let title = article.title || '';
if (this.state.groupByFolder &&
article.folder !== ROOT_FOLDER_ID &&
article.folder !== '.') {
if (title.indexOf(article.folder + '/') === 0) {
title = title.substr(article.folder.length + 1 /* '/' */);
}
}
return (
<div key={documentNode.uid}>
<Link to={documentNode} className="class-browser__entry-link">
{documentNode.title}
{documentNode.meta.gitStats && (
<HotItemIndicator timestamp={documentNode.meta.gitStats.lastCommittedAt} />
)}
</Link>
{isActive && !this.props.flat && this.renderTOC(documentNode)}
</div>
);
},
renderTOC(documentNode) {
return <ArticleTOC documentNode={documentNode} />
},
});
function FolderHierarchy(namespaceNode) {
const { assign, findWhere, sortBy } = require('lodash');
const { config, documents } = namespaceNode;
const folders = {};
sortBy(documents, 'title').forEach(documentNode => {
const folderPath = documentNode.properties.folder;
if (!(folderPath in folders)) {
folders[folderPath] = createFolderConfig(folderPath);
}
folders[folderPath].documents.push(documentNode);
});
Object.keys(folders).forEach(folderPath => {
const folder = folders[folderPath];
if (folder.series) {
folder.documents = sortBy(folder.documents, 'properties.fileName');
}
// README always comes first
folder.documents = sortBy(folder.documents, function(a) {
if (a.properties.fileName === 'README') {
return -1;
}
else {
return 1;
}
});
})
// TODO: can we please do this at compile-time instead??
//
// no we can't, zip it
function createFolderConfig(folderPath) {
const folderConfig = findWhere(config.folders, { path: folderPath });
const folder = assign({}, folderConfig, {
path: folderPath,
documents: []
});
// generate a title
if (!folder.title) {
const normalFolderPath = folderPath
.replace(config.commonPrefix, '')
.replace(new RegExp(config.discardFolderPrefix || ''), '')
let fragments = normalFolderPath.split('/')
if (!config.fullFolderTitles) {
fragments = fragments.slice(-1)
}
folder.title = fragments.map(strHumanize).join(config.fullFolderTitleDelimiter);
}
return folder;
}
return sortBy(Object.keys(folders).map(x => folders[x]), 'title');
}
module.exports = Browser;