Repository: styleguidist/react-styleguidist
Pull request #1368 (2019-05-18 19:47:47)

Allow section content to be function
Marking this PR as a WIP, as I am not sure how to refactor to maintain consistency across the project

Refers: #1224 

Edit: Removing WIP status, this PR is good to go

codecov-io: # [Codecov](https://codecov.io/gh/styleguidist/react-styleguidist/pull/1368?src=pr&el=h1) Report
> Merging [#1368](https://codecov.io/gh/styleguidist/react-styleguidist/pull/1368?src=pr&el=desc) into [master](https://codecov.io/gh/styleguidist/react-styleguidist/commit/f35b30761c40c9df44cb48cb19c2ad59302d95f4?src=pr&el=desc) will **decrease** coverage by `0.04%`.
> The diff coverage is `91.66%`.

| [Impacted Files](https://codecov.io/gh/styleguidist/react-styleguidist/pull/1368?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/loaders/utils/getSections.js](https://codecov.io/gh/styleguidist/react-styleguidist/pull/1368/diff?src=pr&el=tree#diff-c3JjL2xvYWRlcnMvdXRpbHMvZ2V0U2VjdGlvbnMuanM=) | `97.29% <91.66%> (-2.71%)` | :arrow_down: |

eragon512: @sapegin this PR is good to go, added your requested changes
eragon512: hey @sapegin , any more changes needed to this PR?


Patch:
diff --git a/src/client/rsg-components/Section/SectionRenderer.js b/src/client/rsg-components/Section/SectionRenderer.js
index 9520b965..ab6504ca 100644
--- a/src/client/rsg-components/Section/SectionRenderer.js
+++ b/src/client/rsg-components/Section/SectionRenderer.js
@@ -49,7 +49,6 @@ SectionRenderer.propTypes = {
 	name: PropTypes.string,
 	description: PropTypes.string,
 	slug: PropTypes.string,
-	filepath: PropTypes.string,
 	content: PropTypes.node,
 	components: PropTypes.node,
 	sections: PropTypes.node,
diff --git a/src/loaders/utils/getComponentFiles.js b/src/loaders/utils/getComponentFiles.js
index d15dbca3..4dc48110 100644
--- a/src/loaders/utils/getComponentFiles.js
+++ b/src/loaders/utils/getComponentFiles.js
@@ -47,7 +47,7 @@ module.exports = function getComponentFiles(components, rootDir, ignore) {
 
 	// Resolve list of components from globs
 	const componentFiles = getFilesMatchingGlobs(componentGlobs, rootDir, ignore);
-	
+
 	// Get absolute component file paths with correct slash separator format
 	const resolvedComponentFiles = componentFiles.map(file => path.resolve(file));
 
diff --git a/src/loaders/utils/getSections.js b/src/loaders/utils/getSections.js
index 9d1bbdd1..2f233ba5 100644
--- a/src/loaders/utils/getSections.js
+++ b/src/loaders/utils/getSections.js
@@ -10,6 +10,28 @@ const slugger = require('./slugger');
 
 const examplesLoader = path.resolve(__dirname, '../examples-loader.js');
 
+function processSectionContent(section, config) {
+	const contentRelativePath = section.content;
+
+	if (!section.content) {
+		return undefined;
+	}
+
+	if (_.isFunction(section.content)) {
+		return {
+			type: 'markdown',
+			content: section.content(),
+		};
+	}
+
+	// Try to load section content file
+	const contentAbsolutePath = path.resolve(config.configDir, contentRelativePath);
+	if (!fs.existsSync(contentAbsolutePath)) {
+		throw new Error(`Styleguidist: Section content file not found: ${contentAbsolutePath}`);
+	}
+	return requireIt(`!!${examplesLoader}!${contentAbsolutePath}`);
+}
+
 /**
  * Return object for one level of sections.
  *
@@ -39,17 +61,7 @@ const getSectionComponents = (section, config) => {
  * @returns {object}
  */
 function processSection(section, config, parentDepth) {
-	const contentRelativePath = section.content;
-
-	// Try to load section content file
-	let content;
-	if (contentRelativePath) {
-		const contentAbsolutePath = path.resolve(config.configDir, contentRelativePath);
-		if (!fs.existsSync(contentAbsolutePath)) {
-			throw new Error(`Styleguidist: Section content file not found: ${contentAbsolutePath}`);
-		}
-		content = requireIt(`!!${examplesLoader}!${contentAbsolutePath}`);
-	}
+	const content = processSectionContent(section, config);
 
 	let sectionDepth;
 
@@ -67,7 +79,6 @@ function processSection(section, config, parentDepth) {
 		description: section.description,
 		slug: `section-${slugger.slug(section.name)}`,
 		sections: getSections(section.sections || [], config, sectionDepth),
-		filepath: contentRelativePath,
 		href: section.href,
 		components: getSectionComponents(section, config),
 		content,


Test patch:
diff --git a/src/loaders/utils/__tests__/__snapshots__/getSections.spec.js.snap b/src/loaders/utils/__tests__/__snapshots__/getSections.spec.js.snap
index 57e4fa20..25029506 100644
--- a/src/loaders/utils/__tests__/__snapshots__/getSections.spec.js.snap
+++ b/src/loaders/utils/__tests__/__snapshots__/getSections.spec.js.snap
@@ -10,7 +10,6 @@ Array [
     "description": undefined,
     "exampleMode": "collapse",
     "external": undefined,
-    "filepath": "components/Button/Readme.md",
     "href": undefined,
     "name": "Readme",
     "sectionDepth": 0,
@@ -92,7 +91,6 @@ Array [
     "description": undefined,
     "exampleMode": "collapse",
     "external": undefined,
-    "filepath": undefined,
     "href": undefined,
     "name": "Components",
     "sectionDepth": 0,
@@ -174,12 +172,27 @@ Array [
     "description": undefined,
     "exampleMode": "collapse",
     "external": undefined,
-    "filepath": undefined,
     "href": undefined,
     "name": "Ignore",
     "sectionDepth": 0,
     "sections": Array [],
-    "slug": "section-ignore-1",
+    "slug": "section-ignore-2",
+    "usageMode": "collapse",
+  },
+  Object {
+    "components": Array [],
+    "content": Object {
+      "content": "Hello World",
+      "type": "markdown",
+    },
+    "description": undefined,
+    "exampleMode": "collapse",
+    "external": undefined,
+    "href": undefined,
+    "name": "Ignore",
+    "sectionDepth": 0,
+    "sections": Array [],
+    "slug": "section-ignore-3",
     "usageMode": "collapse",
   },
 ]
@@ -260,7 +273,6 @@ Object {
   "description": undefined,
   "exampleMode": "collapse",
   "external": undefined,
-  "filepath": undefined,
   "href": undefined,
   "name": "Components",
   "sectionDepth": 0,
@@ -279,7 +291,6 @@ Object {
   "description": undefined,
   "exampleMode": "collapse",
   "external": undefined,
-  "filepath": "components/Button/Readme.md",
   "href": undefined,
   "name": "Readme",
   "sectionDepth": 0,
@@ -289,6 +300,25 @@ Object {
 }
 `;
 
+exports[`processSection() should return an object for section with content as function 1`] = `
+Object {
+  "components": Array [],
+  "content": Object {
+    "content": "Hello World",
+    "type": "markdown",
+  },
+  "description": undefined,
+  "exampleMode": "collapse",
+  "external": undefined,
+  "href": undefined,
+  "name": "Ignore",
+  "sectionDepth": 0,
+  "sections": Array [],
+  "slug": "section-ignore-1",
+  "usageMode": "collapse",
+}
+`;
+
 exports[`processSection() should return an object for section without ignored components 1`] = `
 Object {
   "components": Array [
@@ -364,7 +394,6 @@ Object {
   "description": undefined,
   "exampleMode": "collapse",
   "external": undefined,
-  "filepath": undefined,
   "href": undefined,
   "name": "Ignore",
   "sectionDepth": 0,
diff --git a/src/loaders/utils/__tests__/getSections.spec.js b/src/loaders/utils/__tests__/getSections.spec.js
index aa355398..c2094adf 100644
--- a/src/loaders/utils/__tests__/getSections.spec.js
+++ b/src/loaders/utils/__tests__/getSections.spec.js
@@ -23,6 +23,10 @@ const sections = [
 		components: 'components/**/*.js',
 		ignore: '**/components/Annotation/*',
 	},
+	{
+		name: 'Ignore',
+		content: () => 'Hello World',
+	},
 ];
 const sectionsWithDepth = [
 	{
@@ -102,6 +106,12 @@ it('processSection() should return an object for section without ignored compone
 	expect(result).toMatchSnapshot();
 });
 
+it('processSection() should return an object for section with content as function', () => {
+	const result = processSection(sections[3], config);
+
+	expect(result).toMatchSnapshot();
+});
+
 it('getSections() should return an array', () => {
 	const result = getSections(sections, config);