diff --git a/core/core/package.json b/core/core/package.json index 8ab55fba6..1e48ca7e5 100644 --- a/core/core/package.json +++ b/core/core/package.json @@ -33,6 +33,7 @@ "deepmerge": "^4.2.2", "escape-html": "^1.0.3", "faker": "^4.1.0", + "react": "^16.13.1", "typescript": "^3.8.3" }, "devDependencies": { @@ -43,6 +44,9 @@ "jest": "^24.9.0", "webpack": "^4.43.0" }, + "peerDependencies": { + "react": "^16.13.1" + }, "publishConfig": { "access": "public" }, diff --git a/core/core/src/configuration.ts b/core/core/src/configuration.ts index 028a7c66e..f5630ef07 100644 --- a/core/core/src/configuration.ts +++ b/core/core/src/configuration.ts @@ -1,4 +1,5 @@ import { Configuration as WebpackConfiguration } from 'webpack'; +import { ComponentType } from 'react'; import { StoryRenderFn } from './utility'; export type PageType = 'story' | 'blog' | 'page' | 'tags' | 'author'; @@ -128,6 +129,11 @@ export interface RunOnlyConfiguration { * story sorting function */ storySort?: (a: string, b: string) => number; + + /** + * page container react component + */ + container?: ComponentType; } export type RunConfiguration = RunOnlyConfiguration & diff --git a/core/core/src/stories.ts b/core/core/src/stories.ts index f534ea14b..abbd7db01 100644 --- a/core/core/src/stories.ts +++ b/core/core/src/stories.ts @@ -258,9 +258,14 @@ export interface StoriesDoc { sidebars?: boolean; /** - * optional date the document was created + * optional date the document was created. If not assigned, the instrumentation process will use birthtime */ - date?: string; + date?: Date; + + /** + * optional date the document was last modified. If not assigned, the instrumentation process will use mtime + */ + dateModified?: Date; /** * comma-separated list of document tags, used for search @@ -276,10 +281,14 @@ export interface StoriesDoc { * document author */ author?: string; - - [name: string]: any; } +export const dateToLocalString = (date?: Date): string => + date + ? new Date(date).toLocaleDateString('en-US', { + timeZone: 'UTC', + }) + : ''; /** * list of components used in stories */ diff --git a/core/instrument/src/index.ts b/core/instrument/src/index.ts index 1b7931f1a..f2b77ce4a 100644 --- a/core/instrument/src/index.ts +++ b/core/instrument/src/index.ts @@ -1,4 +1,5 @@ import * as parser from '@babel/parser'; +import * as fs from 'fs'; import mdx from '@mdx-js/mdx'; import matter from 'gray-matter'; import { File } from '@babel/types'; @@ -102,6 +103,9 @@ const parseSource = async ( store.packages[storyPackage.fileHash] = storyPackage; doc.package = storyPackage.fileHash; } + const stats = fs.statSync(filePath); + doc.dateModified = doc.dateModified || stats.mtime; + doc.date = doc.date || stats.birthtime; } for (const key of Object.keys(store.stories)) { const story: Story = store.stories[key]; diff --git a/core/loader/src/loader.ts b/core/loader/src/loader.ts index ded2b4072..3a1edaf10 100644 --- a/core/loader/src/loader.ts +++ b/core/loader/src/loader.ts @@ -1,8 +1,7 @@ import * as fs from 'fs'; -import * as path from 'path'; import * as chalk from 'chalk'; import { getOptions } from 'loader-utils'; -import { loader } from 'webpack'; + import { InstrumentOptions, parseStories, @@ -12,7 +11,6 @@ import { addStoriesDoc } from './store'; module.exports.pitch = async function() { const options: InstrumentOptions = getOptions(this) || {}; - const context = this as loader.LoaderContext; const filePath = this.resource; const source = fs.readFileSync(filePath, 'utf8'); const { transformed, ...store } = await parseStories( @@ -21,8 +19,6 @@ module.exports.pitch = async function() { options, ); if (store) { - const relPath = path.relative(context.rootContext, filePath); - const moduleId = relPath.startsWith('.') ? relPath : `./${relPath}`; if (store.doc) { console.log(chalk.bgRgb(244, 147, 66)('@loaded: '), filePath); addStoriesDoc(filePath, { @@ -32,7 +28,6 @@ module.exports.pitch = async function() { doc: { ...store.doc, fileName: filePath, - moduleId: moduleId, }, }); } diff --git a/core/loader/src/store.ts b/core/loader/src/store.ts index 27cb69656..5d6178a6f 100644 --- a/core/loader/src/store.ts +++ b/core/loader/src/store.ts @@ -58,6 +58,7 @@ class Store implements LoadingStore { getUniquesByField = (field: string) => { return this.stores.reduce((acc: { [key: string]: number }, store) => { if (store?.doc) { + //@ts-ignore const value = store.doc[field]; const values = Array.isArray(value) ? value : [value]; values.forEach(v => { diff --git a/core/store/src/Store/Store.ts b/core/store/src/Store/Store.ts index 847a1cd7c..571fbb15b 100644 --- a/core/store/src/Store/Store.ts +++ b/core/store/src/Store/Store.ts @@ -196,6 +196,32 @@ export class Store implements StoryStore { } return []; }; + getPrevPage = ( + type: PageType | undefined, + docId: string, + ): StoriesDoc | undefined => { + if (docId) { + const pages = this.getPageList(type); + const index = pages.findIndex(p => p.title === docId); + if (index > 0) { + return pages[index - 1]; + } + } + return undefined; + }; + getNextPage = ( + type: PageType | undefined, + docId: string, + ): StoriesDoc | undefined => { + if (docId) { + const pages = this.getPageList(type); + const index = pages.findIndex(p => p.title === docId); + if (index >= 0 && index < pages.length - 1) { + return pages[index + 1]; + } + } + return undefined; + }; getPagesByCategory = (category: string, value?: any): Pages => { if (this.loadedStore?.docs) { @@ -203,6 +229,7 @@ export class Store implements StoryStore { return Object.keys(docs) .filter(key => { const doc = docs[key]; + //@ts-ignore const cateValue = doc[category]; if (value === undefined) { return cateValue !== undefined; @@ -221,6 +248,7 @@ export class Store implements StoryStore { this._categoryItems[category] = Object.keys(docs).reduce( (acc: { [key: string]: number }, key) => { const doc = docs[key]; + //@ts-ignore const value = doc[category]; const values = Array.isArray(value) ? value : [value]; values.forEach(v => { diff --git a/core/store/src/serialization/load-store.ts b/core/store/src/serialization/load-store.ts index 8f876d6c4..3b12be523 100644 --- a/core/store/src/serialization/load-store.ts +++ b/core/store/src/serialization/load-store.ts @@ -49,7 +49,6 @@ export const loadStoryStore = ( source, component, fileName, - repository, components, excludeStories, includeStories, diff --git a/core/store/src/types.ts b/core/store/src/types.ts index 1cb57ace0..16a7beab4 100644 --- a/core/store/src/types.ts +++ b/core/store/src/types.ts @@ -21,6 +21,14 @@ export interface StoryStore { getDocs: () => Pages; getBlogs: () => Pages; getPageList: (type: PageType) => Pages; + getPrevPage: ( + type: PageType | undefined, + docId: string, + ) => StoriesDoc | undefined; + getNextPage: ( + type: PageType | undefined, + docId: string, + ) => StoriesDoc | undefined; getPagesByCategory: (category: string, value?: any) => Pages; getUniquesByCategory: (category: string) => { [key: string]: number }; config: RunConfiguration | undefined; diff --git a/examples/gatsby/.config/runtime.js b/examples/gatsby/.config/runtime.js index 93be94514..c2b2a350f 100644 --- a/examples/gatsby/.config/runtime.js +++ b/examples/gatsby/.config/runtime.js @@ -1,6 +1,8 @@ +import { Container } from "@component-controls/app"; const categories = ['Introduction', 'Application','Controls','Blocks', 'Editors', 'Components', 'Plugins'] module.exports = { + container: Container, siteTitle: `Component controls`, siteTitleAlt: `Component controls - https://github.com/ccontrols/component-controls`, siteHeadline: `Component controls gatsby`, diff --git a/examples/stories/src/blogs/custom-docs-pages.mdx b/examples/stories/src/blogs/custom-docs-pages.mdx index eed06a333..167c04561 100644 --- a/examples/stories/src/blogs/custom-docs-pages.mdx +++ b/examples/stories/src/blogs/custom-docs-pages.mdx @@ -1,7 +1,7 @@ --- title: Custom documentation pages for storybookjs type: blog -date: 2019-11-07 +date: 2020-04-27 author: atanasster description: Storybookjs plugin that overcomes some "docs page" storybook architecture flaws to display multiple documentation pages. tags: diff --git a/ui/app/src/App/App.tsx b/ui/app/src/App/App.tsx index f8e720af5..f75f70c84 100644 --- a/ui/app/src/App/App.tsx +++ b/ui/app/src/App/App.tsx @@ -1,8 +1,8 @@ /** @jsx jsx */ -import { FC, Fragment } from 'react'; +import { FC, Fragment, useContext } from 'react'; import { jsx, Box } from 'theme-ui'; import { SkipLinks, SkiLinksItemProps } from '@component-controls/components'; -import { useStoryContext } from '@component-controls/blocks'; +import { BlockContext } from '@component-controls/blocks'; import { SEO } from '../SEO'; import { Header } from '../Header'; import { Footer } from '../Footer'; @@ -19,7 +19,8 @@ export interface AppProps { * */ export const App: FC = ({ title, children }) => { - const { doc } = useStoryContext({ id: '.' }); + const { storeProvider, docId } = useContext(BlockContext); + const doc = docId ? storeProvider.getStoryDoc(docId) : undefined; const items: SkiLinksItemProps[] = [ { target: 'content', @@ -43,6 +44,7 @@ export const App: FC = ({ title, children }) => {
+ {children}