diff --git a/core/routes/src/routes/docs-index-pages.ts b/core/routes/src/routes/docs-index-pages.ts index 86fbfddf2..3cb0080af 100644 --- a/core/routes/src/routes/docs-index-pages.ts +++ b/core/routes/src/routes/docs-index-pages.ts @@ -9,11 +9,12 @@ import { } from '@component-controls/core'; import { getUniquesByField } from './docs-pages'; export interface DocHomePagesPath { - type: DocType; + type?: DocType; path: string; docId?: string; storyId?: string; lastModified?: string; + docIndex?: boolean; } export const getHomePages = (store?: Store): DocHomePagesPath[] => { @@ -45,25 +46,32 @@ export const getHomePages = (store?: Store): DocHomePagesPath[] => { const storyId: string | undefined = docStories.length ? docStories[0] : undefined; - return { - lastModified: doc?.dateModified - ? new Date(doc?.dateModified).toISOString() - : undefined, + const result: DocHomePagesPath = { type, path, - docId, - storyId, + docIndex: true, }; + if (docId) { + result.docId = docId; + } + if (storyId) { + result.storyId = storyId; + } + const lastModified = doc?.dateModified + ? new Date(doc?.dateModified).toISOString() + : undefined; + if (lastModified) { + result.lastModified = lastModified; + } + return result; }) .filter(({ path }) => path); const categoryPaths: DocHomePagesPath[] = categories .map(category => { const uniques = getUniquesByField(store, category); return { - lastModified: undefined, type: category, - docId: undefined, - storyId: undefined, + docIndex: true, path: Object.keys(uniques).length ? getCategoryPath(store, category) : '', diff --git a/core/routes/src/routes/docs-pages.ts b/core/routes/src/routes/docs-pages.ts index ceef878ac..2392ecdcf 100644 --- a/core/routes/src/routes/docs-pages.ts +++ b/core/routes/src/routes/docs-pages.ts @@ -51,7 +51,7 @@ export const getUniquesByField = ( }; export interface DocPagesPath { - type: DocType; + type?: DocType; path: string; query?: string; lastModified?: string; @@ -99,17 +99,27 @@ export const getDocPages = (store?: Store): DocPagesPath[] => { route, ); if (!docPaths.find(p => p.path === path)) { - docPaths.push({ - lastModified: doc.dateModified - ? new Date(doc.dateModified).toISOString() - : undefined, + const result: DocPagesPath = { path, - query, type: docType, - activeTab: route, docId: doc.title, - storyId, - }); + }; + if (storyId) { + result.storyId = storyId; + } + if (route) { + result.activeTab = route; + } + const lastModified = doc.dateModified + ? new Date(doc.dateModified).toISOString() + : undefined; + if (lastModified) { + result.lastModified = lastModified; + } + if (query) { + result.query = query; + } + docPaths.push(result); } }); } diff --git a/core/routes/src/routes/index-page.ts b/core/routes/src/routes/index-page.ts index b9b609f82..149067753 100644 --- a/core/routes/src/routes/index-page.ts +++ b/core/routes/src/routes/index-page.ts @@ -6,7 +6,7 @@ import { } from '@component-controls/core'; export interface HomePageInfo { - type: string; + type?: string; docId?: string; storyId?: string; path: string; @@ -29,18 +29,26 @@ export const getIndexPage = (store?: Store): HomePageInfo => { const docId = homePage?.title; const docStories: string[] = docId && store.docs[docId] ? store.docs[docId].stories || [] : []; - const storyId: string | undefined = docStories.length - ? docStories[0] - : undefined; - return { - lastModified: homePage?.dateModified - ? new Date(homePage?.dateModified).toISOString() - : undefined, + const result: HomePageInfo = { path: homePath, - storyId, - docId, type: homePage?.type || defDocType, }; + const lastModified = homePage?.dateModified + ? new Date(homePage?.dateModified).toISOString() + : undefined; + if (lastModified) { + result.lastModified = lastModified; + } + const storyId: string | undefined = docStories.length + ? docStories[0] + : undefined; + if (storyId) { + result.storyId = storyId; + } + if (docId) { + result.docId = docId; + } + return result; } return { type: defDocType, diff --git a/core/routes/src/routes/index.ts b/core/routes/src/routes/index.ts index bc83f20a6..efc706e0c 100644 --- a/core/routes/src/routes/index.ts +++ b/core/routes/src/routes/index.ts @@ -1,3 +1,29 @@ +import { Store } from '@component-controls/core'; +import { getHomePages, DocHomePagesPath } from './docs-index-pages'; +import { getDocPages, DocPagesPath } from './docs-pages'; +import { getIndexPage, HomePageInfo } from './index-page'; + export * from './docs-index-pages'; export * from './docs-pages'; export * from './index-page'; + +export type RoutePath = DocHomePagesPath & DocPagesPath & HomePageInfo; + +export const getRoutes = (store: Store): RoutePath[] => { + const routes = []; + //home page + const index = getIndexPage(store) || {}; + routes.push(index); + //docs index pages + const homePages = getHomePages(store); + homePages.forEach(page => { + routes.push(page); + }); + + //document pages + const docPages = getDocPages(store); + docPages.forEach(page => { + routes.push(page); + }); + return routes; +}; diff --git a/core/store/loader.d.ts b/core/store/loader.d.ts deleted file mode 100644 index 66ed8e3da..000000000 --- a/core/store/loader.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/webpack/loader'; diff --git a/core/store/loader.js b/core/store/loader.js deleted file mode 100644 index 6cc4e38b8..000000000 --- a/core/store/loader.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./dist/loader'); diff --git a/core/store/package.json b/core/store/package.json index 7ef7ba2ab..d89f70e4f 100644 --- a/core/store/package.json +++ b/core/store/package.json @@ -14,9 +14,7 @@ "static_store.js", "static_store.d.ts", "controls-store.js", - "controls-store.d.ts", - "loader.js", - "loader.d.ts" + "controls-store.d.ts" ], "scripts": { "build": "yarn cross-env NODE_ENV=production rollup -c", diff --git a/core/store/src/webpack/loader.ts b/core/store/src/webpack/loader.ts deleted file mode 100644 index a4e628f65..000000000 --- a/core/store/src/webpack/loader.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { getOptions } from 'loader-utils'; -import { normalizePath } from '@component-controls/core'; -import { - WebpackLoaderContext, - LoaderOptions, -} from '@component-controls/core/node-utils'; -function loader(this: WebpackLoaderContext, content: string): string { - const options = getOptions(this) || {}; - const { bundleFileName } = options; - const bundleNormalized = normalizePath(bundleFileName as string); - content = ` - import { loadStore } from './dist/load-store'; - export let store = loadStore(require('${bundleNormalized}')); - - if (module.hot) { - module.hot.accept('${bundleNormalized}', () => { - import('${bundleNormalized}').then(updated => { - store = loadStore(updated); - }); - }); - } - `; - return content; -} - -export default loader; - -/** - * expose public types via declaration merging - */ -// eslint-disable-next-line @typescript-eslint/no-namespace -namespace loader { - // eslint-disable-next-line @typescript-eslint/no-empty-interface - export interface Options extends LoaderOptions {} -} diff --git a/examples/nextjs/next.config.js b/examples/nextjs/next.config.js index ce6c04aa9..67156884b 100644 --- a/examples/nextjs/next.config.js +++ b/examples/nextjs/next.config.js @@ -5,5 +5,4 @@ module.exports = withStories({ webpack5: true, }, configPath: '.config', - distDir: 'dist', }); diff --git a/examples/nextjs/pages/[doctype].tsx b/examples/nextjs/pages/[doctype].tsx index 1b3f17a6f..e1b2ca381 100644 --- a/examples/nextjs/pages/[doctype].tsx +++ b/examples/nextjs/pages/[doctype].tsx @@ -1,13 +1,13 @@ import React from 'react'; import { GetStaticProps, GetStaticPaths } from 'next'; import { - DocHomeTemplate, + NextLayout, store, getHomePagesPaths, getDocHomePage, } from '@component-controls/nextjs-plugin'; -const DocHome: typeof DocHomeTemplate = props => ; +const DocHome: typeof NextLayout = props => ; export const getStaticPaths: GetStaticPaths = async () => { return { paths: getHomePagesPaths(store), fallback: false }; @@ -15,9 +15,7 @@ export const getStaticPaths: GetStaticPaths = async () => { export const getStaticProps: GetStaticProps = async ({ params }) => { const { doctype: basepath } = params as { doctype: string }; - const page = getDocHomePage(store, basepath); - const { type = null, docId = null, storyId = null } = page || {}; - return { props: { docId, storyId, type } }; + return { props: getDocHomePage(store, basepath) }; }; export default DocHome; diff --git a/examples/nextjs/pages/[doctype]/[...docid].tsx b/examples/nextjs/pages/[doctype]/[...docid].tsx index 4b9ff6fe9..a919cf37e 100644 --- a/examples/nextjs/pages/[doctype]/[...docid].tsx +++ b/examples/nextjs/pages/[doctype]/[...docid].tsx @@ -1,13 +1,13 @@ import React from 'react'; import { GetStaticProps, GetStaticPaths } from 'next'; import { - DocPageTemplate, + NextLayout, store, getDocPagesPaths, getDocPage, } from '@component-controls/nextjs-plugin'; -const DocPage: typeof DocPageTemplate = props => ; +const DocPage: typeof NextLayout = props => ; export const getStaticPaths: GetStaticPaths = async () => { return { paths: getDocPagesPaths(store), fallback: false }; @@ -15,15 +15,7 @@ export const getStaticPaths: GetStaticPaths = async () => { export const getStaticProps: GetStaticProps = async ({ params }) => { const { doctype, docid } = params as { doctype: string; docid: string[] }; - const page = getDocPage(store, doctype, docid); - const { - type = null, - docId = null, - storyId = null, - category = null, - activeTab = null, - } = page || {}; - return { props: { docId, type, storyId, category, activeTab } }; + return { props: getDocPage(store, doctype, docid) }; }; export default DocPage; diff --git a/examples/nextjs/pages/index.tsx b/examples/nextjs/pages/index.tsx index 1e249a79f..6d07f8065 100644 --- a/examples/nextjs/pages/index.tsx +++ b/examples/nextjs/pages/index.tsx @@ -1,19 +1,15 @@ import React from 'react'; import { GetStaticProps } from 'next'; import { - DocPageTemplate, + NextLayout, store, getIndexPage, } from '@component-controls/nextjs-plugin'; -const HomePage: typeof DocPageTemplate = props => ( - -); +const HomePage: typeof NextLayout = props => ; export const getStaticProps: GetStaticProps = async () => { - const homePage = getIndexPage(store); - const { docId = null, type = null, storyId = null } = homePage; - return { props: { docId, type, storyId } }; + return { props: getIndexPage(store) }; }; export default HomePage; diff --git a/examples/react-webpack/webpack.dev.config.js b/examples/react-webpack/webpack.dev.config.js index e44632ec5..caccfad40 100644 --- a/examples/react-webpack/webpack.dev.config.js +++ b/examples/react-webpack/webpack.dev.config.js @@ -58,6 +58,5 @@ module.exports = withComponentControls({ options: { configPath: '.config', distFolder: publicPath, - fastRefresh: false, }, }); diff --git a/examples/simple/next.config.js b/examples/simple/next.config.js index a34e951b2..05fe190de 100644 --- a/examples/simple/next.config.js +++ b/examples/simple/next.config.js @@ -5,5 +5,4 @@ module.exports = withStories({ webpack5: true, }, configPath: 'docs', - distDir: 'dist', }); diff --git a/examples/simple/package.json b/examples/simple/package.json index c54b0f55d..d917910d1 100644 --- a/examples/simple/package.json +++ b/examples/simple/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@component-controls/gatsby-theme-stories": "^3.3.0", + "@component-controls/nextjs-plugin": "^3.3.0", "gatsby": "^3.0.0", "next": "^10.0.7", "react": "^17.0.1", diff --git a/examples/simple/pages/[doctype].tsx b/examples/simple/pages/[doctype].tsx index 1b3f17a6f..e1b2ca381 100644 --- a/examples/simple/pages/[doctype].tsx +++ b/examples/simple/pages/[doctype].tsx @@ -1,13 +1,13 @@ import React from 'react'; import { GetStaticProps, GetStaticPaths } from 'next'; import { - DocHomeTemplate, + NextLayout, store, getHomePagesPaths, getDocHomePage, } from '@component-controls/nextjs-plugin'; -const DocHome: typeof DocHomeTemplate = props => ; +const DocHome: typeof NextLayout = props => ; export const getStaticPaths: GetStaticPaths = async () => { return { paths: getHomePagesPaths(store), fallback: false }; @@ -15,9 +15,7 @@ export const getStaticPaths: GetStaticPaths = async () => { export const getStaticProps: GetStaticProps = async ({ params }) => { const { doctype: basepath } = params as { doctype: string }; - const page = getDocHomePage(store, basepath); - const { type = null, docId = null, storyId = null } = page || {}; - return { props: { docId, storyId, type } }; + return { props: getDocHomePage(store, basepath) }; }; export default DocHome; diff --git a/examples/simple/pages/[doctype]/[...docid].tsx b/examples/simple/pages/[doctype]/[...docid].tsx index 4b9ff6fe9..a919cf37e 100644 --- a/examples/simple/pages/[doctype]/[...docid].tsx +++ b/examples/simple/pages/[doctype]/[...docid].tsx @@ -1,13 +1,13 @@ import React from 'react'; import { GetStaticProps, GetStaticPaths } from 'next'; import { - DocPageTemplate, + NextLayout, store, getDocPagesPaths, getDocPage, } from '@component-controls/nextjs-plugin'; -const DocPage: typeof DocPageTemplate = props => ; +const DocPage: typeof NextLayout = props => ; export const getStaticPaths: GetStaticPaths = async () => { return { paths: getDocPagesPaths(store), fallback: false }; @@ -15,15 +15,7 @@ export const getStaticPaths: GetStaticPaths = async () => { export const getStaticProps: GetStaticProps = async ({ params }) => { const { doctype, docid } = params as { doctype: string; docid: string[] }; - const page = getDocPage(store, doctype, docid); - const { - type = null, - docId = null, - storyId = null, - category = null, - activeTab = null, - } = page || {}; - return { props: { docId, type, storyId, category, activeTab } }; + return { props: getDocPage(store, doctype, docid) }; }; export default DocPage; diff --git a/examples/simple/pages/index.tsx b/examples/simple/pages/index.tsx index 1e249a79f..6d07f8065 100644 --- a/examples/simple/pages/index.tsx +++ b/examples/simple/pages/index.tsx @@ -1,19 +1,15 @@ import React from 'react'; import { GetStaticProps } from 'next'; import { - DocPageTemplate, + NextLayout, store, getIndexPage, } from '@component-controls/nextjs-plugin'; -const HomePage: typeof DocPageTemplate = props => ( - -); +const HomePage: typeof NextLayout = props => ; export const getStaticProps: GetStaticProps = async () => { - const homePage = getIndexPage(store); - const { docId = null, type = null, storyId = null } = homePage; - return { props: { docId, type, storyId } }; + return { props: getIndexPage(store) }; }; export default HomePage; diff --git a/examples/simple/tsconfig.json b/examples/simple/tsconfig.json index 35d51eac9..21cfe61a2 100644 --- a/examples/simple/tsconfig.json +++ b/examples/simple/tsconfig.json @@ -1,29 +1,31 @@ { "compilerOptions": { - "target": "es5", + "module": "esnext", + "target": "esnext", + "jsx": "preserve", "lib": [ "dom", - "dom.iterable", "esnext" ], + "strict": true, + "noEmit": true, + "isolatedModules": true, + "esModuleInterop": true, + "noUnusedLocals": false, "allowJs": true, "skipLibCheck": true, - "strict": false, "forceConsistentCasingInFileNames": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve" + "moduleResolution": "node" }, + "exclude": [ + "node_modules", + "public", + ".cache" + ], "include": [ "next-env.d.ts", "**/*.ts", "**/*.tsx" - ], - "exclude": [ - "node_modules" ] } diff --git a/examples/starter/package.json b/examples/starter/package.json index 69f52aec2..0b0e8d078 100644 --- a/examples/starter/package.json +++ b/examples/starter/package.json @@ -17,12 +17,8 @@ "url": "https://github.com/atanasster/gatsby-controls-starter.git" }, "dependencies": { - "@component-controls/axe-plugin": "^3.3.0", - "@component-controls/blocks": "^3.3.0", - "@component-controls/core": "^3.3.0", "@component-controls/gatsby-theme-stories": "^3.3.0", "@component-controls/nextjs-plugin": "^3.3.0", - "@component-controls/viewport-plugin": "^3.3.0", "gatsby": "^3.0.0", "next": "^10.0.7", "react": "^17.0.1", diff --git a/examples/starter/pages/root.tsx b/examples/starter/pages/root.tsx index c37604ad9..e49ddfb59 100644 --- a/examples/starter/pages/root.tsx +++ b/examples/starter/pages/root.tsx @@ -1,13 +1,11 @@ import React from 'react'; import { GetStaticProps } from 'next'; -import { DocPageTemplate, store, getIndexPage } from '@component-controls/nextjs-plugin'; +import { NextLayout, store, getIndexPage } from '@component-controls/nextjs-plugin'; -const HomePage: typeof DocPageTemplate = props => ; +const HomePage: typeof NextLayout = props => ; export const getStaticProps: GetStaticProps = async () => { - const homePage = getIndexPage(store); - const { docId = null, type = null, storyId = null } = homePage; - return { props: { docId, type, storyId } }; + return { props: getIndexPage(store) }; }; export default HomePage; diff --git a/examples/starter/pages/root/[doctype].tsx b/examples/starter/pages/root/[doctype].tsx index 884d0a801..6d7028f47 100644 --- a/examples/starter/pages/root/[doctype].tsx +++ b/examples/starter/pages/root/[doctype].tsx @@ -1,14 +1,13 @@ -import React, { FC } from 'react'; +import React from 'react'; import { GetStaticProps, GetStaticPaths } from 'next'; import { - DocHomeTemplate, + NextLayout, store, getHomePagesPaths, getDocHomePage, } from '@component-controls/nextjs-plugin'; -const DocHome: typeof DocHomeTemplate = props => ; - +const DocHome: typeof NextLayout = props => ; export const getStaticPaths: GetStaticPaths = async () => { return { paths: getHomePagesPaths(store), fallback: false }; @@ -16,9 +15,7 @@ export const getStaticPaths: GetStaticPaths = async () => { export const getStaticProps: GetStaticProps = async ({ params }) => { const { doctype: basepath } = params as { doctype: string }; - const page = getDocHomePage(store, basepath); - const { type = null, docId = null, storyId = null } = page || {}; - return { props: { docId, storyId, type } }; + return { props: getDocHomePage(store, basepath)}; }; export default DocHome; diff --git a/examples/starter/pages/root/[doctype]/[...docid].tsx b/examples/starter/pages/root/[doctype]/[...docid].tsx index daad8945b..a919cf37e 100644 --- a/examples/starter/pages/root/[doctype]/[...docid].tsx +++ b/examples/starter/pages/root/[doctype]/[...docid].tsx @@ -1,15 +1,13 @@ -import React, { FC } from 'react'; +import React from 'react'; import { GetStaticProps, GetStaticPaths } from 'next'; import { - DocPageTemplate, + NextLayout, store, getDocPagesPaths, getDocPage, } from '@component-controls/nextjs-plugin'; - - -const DocPage: typeof DocPageTemplate = props => ; +const DocPage: typeof NextLayout = props => ; export const getStaticPaths: GetStaticPaths = async () => { return { paths: getDocPagesPaths(store), fallback: false }; @@ -17,15 +15,7 @@ export const getStaticPaths: GetStaticPaths = async () => { export const getStaticProps: GetStaticProps = async ({ params }) => { const { doctype, docid } = params as { doctype: string; docid: string[] }; - const page = getDocPage(store, doctype, docid); - const { - type = null, - docId = null, - storyId = null, - category = null, - activeTab = null, - } = page || {}; - return { props: { docId, type, storyId, category, activeTab } }; + return { props: getDocPage(store, doctype, docid) }; }; export default DocPage; diff --git a/examples/starter/tsconfig.json b/examples/starter/tsconfig.json index 341378467..a32b96596 100644 --- a/examples/starter/tsconfig.json +++ b/examples/starter/tsconfig.json @@ -4,10 +4,7 @@ "module": "esnext", "target": "esnext", "jsx": "preserve", - "lib": [ - "dom", - "esnext" - ], + "lib": ["dom", "esnext"], "strict": true, "noEmit": true, "isolatedModules": true, @@ -18,14 +15,6 @@ "forceConsistentCasingInFileNames": true, "resolveJsonModule": true }, - "exclude": [ - "node_modules", - "public", - ".cache" - ], - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx" - ] + "exclude": ["node_modules", "public", ".cache"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"] } diff --git a/examples/stories/src/tutorial/getting-started/ssg/webpack.mdx b/examples/stories/src/tutorial/getting-started/ssg/webpack.mdx index 0ec75d98f..4b40e3242 100644 --- a/examples/stories/src/tutorial/getting-started/ssg/webpack.mdx +++ b/examples/stories/src/tutorial/getting-started/ssg/webpack.mdx @@ -87,8 +87,6 @@ module.exports = withComponentControls({ options: { configPath: '.config', distFolder: publicPath, - // for webpack 4 you will need to disable react fast-refresh: - // fastRefresh: false, }, }); ``` diff --git a/integrations/base-integration/.eslintignore b/integrations/base-integration/.eslintignore new file mode 100644 index 000000000..53c37a166 --- /dev/null +++ b/integrations/base-integration/.eslintignore @@ -0,0 +1 @@ +dist \ No newline at end of file diff --git a/integrations/base-integration/LICENSE.md b/integrations/base-integration/LICENSE.md new file mode 100644 index 000000000..a64cf9401 --- /dev/null +++ b/integrations/base-integration/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Atanas Stoyanov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/integrations/base-integration/README.md b/integrations/base-integration/README.md new file mode 100644 index 000000000..5573fadad --- /dev/null +++ b/integrations/base-integration/README.md @@ -0,0 +1,16 @@ +# Table of contents + +# In action + +[Live site](https://component-controls.com) + +# Overview + +react-router integration plugin for webpack sites documenting your projects with component controls + +- Exports list of routes for use in node.js environment +- Exports react ui components to use in browser environment + +# API + + diff --git a/integrations/base-integration/package.json b/integrations/base-integration/package.json new file mode 100644 index 000000000..f5369a273 --- /dev/null +++ b/integrations/base-integration/package.json @@ -0,0 +1,67 @@ +{ + "name": "@component-controls/base-integration", + "version": "3.3.0", + "description": "base integration routines and components", + "keywords": [ + "story", + "nextjs" + ], + "main": "dist/index.js", + "module": "dist/index.esm.js", + "typings": "dist/index.d.ts", + "files": [ + "dist/", + "package.json", + "README.md", + "webpack-build.js", + "webpack-build.d.ts" + ], + "scripts": { + "build": "yarn cross-env NODE_ENV=production rollup -c", + "dev": "yarn cross-env NODE_ENV=development rollup -cw", + "docs": "ts-md", + "fix": "yarn lint --fix", + "lint": "yarn eslint . --ext mdx,ts,tsx", + "prepare": "yarn build", + "test": "yarn jest --passWithNoTests" + }, + "homepage": "https://github.com/ccontrols/component-controls", + "bugs": { + "url": "https://github.com/ccontrols/component-controls/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/ccontrols/component-controls.git", + "directory": "integrations/base-integration" + }, + "license": "MIT", + "dependencies": { + "@component-controls/app": "^3.3.0", + "@component-controls/core": "^3.3.0", + "@component-controls/logger": "^2.10.4", + "@component-controls/pages": "^3.3.0", + "@component-controls/routes": "^3.3.0", + "@component-controls/search-algolia": "^3.3.0", + "@component-controls/search-fusejs": "^3.3.0", + "@component-controls/store": "^3.3.0", + "@component-controls/webpack-compile": "^3.3.0", + "@types/react-router": "^5.1.11", + "@types/react-router-dom": "^5.1.7", + "react": "^17.0.1", + "react-dom": "^17.0.1" + }, + "devDependencies": { + "@component-controls/logger": "^2.10.4", + "@component-controls/ts-markdown-docs": "^2.6.0", + "@types/react": "^16.9.0", + "@types/react-dom": "^16.9.0", + "typescript": "^4.0.5" + }, + "publishConfig": { + "access": "public" + }, + "authors": [ + "Atanas Stoyanov" + ], + "gitHead": "e30d62f101e104711a16261fce04785d58cac1eb" +} diff --git a/integrations/base-integration/rollup.config.js b/integrations/base-integration/rollup.config.js new file mode 100644 index 000000000..b5e235f9c --- /dev/null +++ b/integrations/base-integration/rollup.config.js @@ -0,0 +1,5 @@ +import { config } from '../../rollup-config'; + +export default config({ + input: ['./src/index.tsx', './src/webpack-build.ts'], +}); diff --git a/integrations/base-integration/src/components/Layout.tsx b/integrations/base-integration/src/components/Layout.tsx new file mode 100644 index 000000000..fd2384579 --- /dev/null +++ b/integrations/base-integration/src/components/Layout.tsx @@ -0,0 +1,43 @@ +import React, { FC } from 'react'; +import { + AppContext, + AppContextProps, + DocumentHomePage, + DocPage, +} from '@component-controls/app'; +import { RoutePath } from '@component-controls/routes'; +import { store } from '../store'; + +export type LayoutProps = Omit & { + Link: AppContextProps['linkClass']; + Helmet: AppContextProps['Helmet']; +}; + +export const Layout: FC = ({ + docId, + storyId, + activeTab, + category, + type, + docIndex, + Link, + Helmet, + children, +}) => ( + + {children || + (docIndex ? ( + + ) : ( + + ))} + +); diff --git a/integrations/base-integration/src/index.tsx b/integrations/base-integration/src/index.tsx new file mode 100644 index 000000000..79b3f9de5 --- /dev/null +++ b/integrations/base-integration/src/index.tsx @@ -0,0 +1,2 @@ +export { Layout, LayoutProps } from './components/Layout'; +export { store } from './store'; diff --git a/integrations/nextjs-plugin/src/store.ts b/integrations/base-integration/src/store.ts similarity index 75% rename from integrations/nextjs-plugin/src/store.ts rename to integrations/base-integration/src/store.ts index a815502cb..cb95148a5 100644 --- a/integrations/nextjs-plugin/src/store.ts +++ b/integrations/base-integration/src/store.ts @@ -1,5 +1,5 @@ import { Store } from '@component-controls/core'; import { loadStore } from '@component-controls/store'; +const bundle = require('component-controls-bundle'); -const bundle = require('./component-controls'); export const store: Store = loadStore(bundle, true); diff --git a/integrations/base-integration/src/webpack-build.ts b/integrations/base-integration/src/webpack-build.ts new file mode 100644 index 000000000..28534a470 --- /dev/null +++ b/integrations/base-integration/src/webpack-build.ts @@ -0,0 +1,126 @@ +import path from 'path'; +import fs from 'fs'; +import { + BuildProps, + Store, + mergeConfig, + defaultCompileProps, +} from '@component-controls/core'; +import { getSiteMap } from '@component-controls/routes'; +import { getBundleName } from '@component-controls/core/node-utils'; +import { LoadingStore, loadStore } from '@component-controls/store'; +import { log } from '@component-controls/logger'; +import { + CompilerCallbackFn, + searchIndexing, + compile, + watch, +} from '@component-controls/webpack-compile'; + +export type OnEndBuild = (props: { store: Store }) => void; +export const postBuild = async ( + staticFolder: string, + loadingStore?: LoadingStore, + mode?: string, + onEndBuild?: OnEndBuild, +): Promise => { + if (loadingStore) { + const store: Store = loadStore(loadingStore, true); + if (mode || process.env.NODE_ENV === 'production') { + if (store.config.siteMap) { + const sitemap = getSiteMap(store); + const sitemapfolder = path.resolve(staticFolder, '..'); + if (!fs.existsSync(sitemapfolder)) { + fs.mkdirSync(sitemapfolder, { recursive: true }); + } + const sitemapname = path.join(sitemapfolder, 'sitemap.xml'); + log('creating sitemap', sitemapname); + fs.writeFileSync(sitemapname, sitemap, 'utf8'); + } + await searchIndexing(store); + } + if (onEndBuild) { + onEndBuild({ store }); + } + } +}; + +const createOptions = (buildOptions?: BuildProps): BuildProps => { + const keys = buildOptions ? Object.keys(buildOptions) : []; + const options = keys.reduce((acc: BuildProps, key) => { + if ((buildOptions as Record)[key] !== undefined) { + return { ...acc, [key]: (buildOptions as Record)[key] }; + } + return acc; + }, {}); + + const distFolder = options.distFolder || path.join(process.cwd(), 'dist'); + const staticFolder = path.join(options.distFolder || distFolder, 'static'); + return mergeConfig( + mergeConfig(defaultCompileProps, { + configPath: '.config', + distFolder, + staticFolder, + }), + options, + ); +}; + +export const buildBundle = async ({ + options, + onEndBuild, +}: { + options?: BuildProps; + onEndBuild?: OnEndBuild; +}): Promise => { + const mode = options?.mode || process.env.NODE_ENV; + if (typeof process.env.NODE_ENV === 'undefined') { + process.env.NODE_ENV = mode; + } + const buildOptions = createOptions(options); + const onBundle: CompilerCallbackFn = async ({ store }) => { + await postBuild( + buildOptions.staticFolder as string, + store, + mode, + onEndBuild, + ); + }; + + const run = mode === 'production' ? compile : watch; + await run(buildOptions, onBundle); +}; + +export const webpackConfig = ({ + config = {}, + options, +}: { + config?: any; + options: BuildProps; +}): any => { + const buildOptions = createOptions(options); + const bundleFilePath = getBundleName(buildOptions); + return { + ...config, + resolve: { + ...config.resolve, + alias: { + ...config.resolve?.alias, + 'component-controls-bundle': bundleFilePath, + }, + }, + }; +}; + +export const asyncWebpackConfig = async ({ + config, + options, +}: { + config: any; + options?: BuildProps; +}): Promise => { + await buildBundle({ + options, + }); + return webpackConfig(config); +}; diff --git a/integrations/base-integration/tsconfig.json b/integrations/base-integration/tsconfig.json new file mode 100644 index 000000000..d26fdb148 --- /dev/null +++ b/integrations/base-integration/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "module": "esnext", + "declaration": true, + "resolveJsonModule": true, + "sourceMap": false, + "outDir": "./dist", + "rootDir": "./src", + "baseUrl": "./", + "typeRoots": ["../../node_modules/@types", "node_modules/@types"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules/**"] +} diff --git a/integrations/base-integration/webpack-build.d.ts b/integrations/base-integration/webpack-build.d.ts new file mode 100644 index 000000000..f0061e072 --- /dev/null +++ b/integrations/base-integration/webpack-build.d.ts @@ -0,0 +1 @@ +export * from './dist/webpack-build'; diff --git a/integrations/base-integration/webpack-build.js b/integrations/base-integration/webpack-build.js new file mode 100644 index 000000000..0fe080a4a --- /dev/null +++ b/integrations/base-integration/webpack-build.js @@ -0,0 +1 @@ +module.exports = require('./dist/webpack-build'); diff --git a/integrations/gatsby-theme-stories/package.json b/integrations/gatsby-theme-stories/package.json index b368d9654..d78f3141e 100644 --- a/integrations/gatsby-theme-stories/package.json +++ b/integrations/gatsby-theme-stories/package.json @@ -38,15 +38,11 @@ }, "license": "MIT", "dependencies": { - "@component-controls/app": "^3.3.0", - "@component-controls/core": "^3.3.0", + "@component-controls/base-integration": "^3.3.0", "@component-controls/pages": "^3.3.0", "@component-controls/routes": "^3.3.0", "@component-controls/search-algolia": "^3.3.0", "@component-controls/search-fusejs": "^3.3.0", - "@component-controls/store": "^3.3.0", - "@component-controls/webpack-compile": "^3.3.0", - "@component-controls/webpack-configs": "^3.3.0", "gatsby-plugin-typescript": "^2.4.24", "react-helmet": "^6.0.0", "theme-ui": "^0.6.0-alpha.7" diff --git a/integrations/gatsby-theme-stories/src/components/GatsbyLayout.tsx b/integrations/gatsby-theme-stories/src/components/GatsbyLayout.tsx new file mode 100644 index 000000000..d26e4009e --- /dev/null +++ b/integrations/gatsby-theme-stories/src/components/GatsbyLayout.tsx @@ -0,0 +1,10 @@ +import React, { FC } from 'react'; +import { Helmet } from 'react-helmet'; +import { Layout, LayoutProps } from '@component-controls/base-integration'; +import { GatsbyLink } from '../components/GatsbyLink'; + +export type GatsbyLayoutProps = Omit; + +export const GatsbyLayout: FC = props => { + return ; +}; diff --git a/integrations/gatsby-theme-stories/src/components/Layout.tsx b/integrations/gatsby-theme-stories/src/components/Layout.tsx deleted file mode 100644 index c860ef36e..000000000 --- a/integrations/gatsby-theme-stories/src/components/Layout.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { FC } from 'react'; -import { Helmet } from 'react-helmet'; -import { AppContext } from '@component-controls/app'; -import { store } from '@component-controls/store/controls-store'; - -import { GatsbyLink } from './GatsbyLink'; - -interface LayoutProps { - docId?: string; - storyId?: string; - activeTab?: string; - type?: string; -} - -export const Layout: FC = ({ - docId, - storyId, - children, - activeTab, - type, -}) => { - return ( - - {children} - - ); -}; diff --git a/integrations/gatsby-theme-stories/src/components/types.ts b/integrations/gatsby-theme-stories/src/components/types.ts deleted file mode 100644 index d675cef13..000000000 --- a/integrations/gatsby-theme-stories/src/components/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ReactNode } from 'react'; - -export interface PageConfig { - key: string; - title: string; - render: () => ReactNode; -} - -export type PagesConfig = (route: string) => PageConfig[]; diff --git a/integrations/gatsby-theme-stories/src/gatsby-node.ts b/integrations/gatsby-theme-stories/src/gatsby-node.ts index f90e786ac..1bb4c14a3 100644 --- a/integrations/gatsby-theme-stories/src/gatsby-node.ts +++ b/integrations/gatsby-theme-stories/src/gatsby-node.ts @@ -1,39 +1,17 @@ import fs from 'fs'; -import sysPath from 'path'; -import { log } from '@component-controls/logger'; +import { BuildProps } from '@component-controls/core'; +import { getCSSBundleName } from '@component-controls/core/node-utils'; import { - compile, - watch, - CompilerCallbackFn, - searchIndexing, -} from '@component-controls/webpack-compile'; -import { - BuildProps, - Store, - defaultCompileProps, -} from '@component-controls/core'; -import { - getBundleName, - getCSSBundleName, -} from '@component-controls/core/node-utils'; - -import { mergeBuildConfiguration } from '@component-controls/config'; - + buildBundle, + webpackConfig, +} from '@component-controls/base-integration/webpack-build'; import { CreatePagesArgs, CreateWebpackConfigArgs, PluginCallback, Page, } from 'gatsby'; -import { loadStore } from '@component-controls/store'; -import { - getIndexPage, - getHomePages, - DocHomePagesPath, - getDocPages, - DocPagesPath, - getSiteMap, -} from '@component-controls/routes'; +import { getRoutes } from '@component-controls/routes'; export const createPagesStatefully = async ( { actions, store: gatsbyStore }: CreatePagesArgs, @@ -41,91 +19,36 @@ export const createPagesStatefully = async ( doneCb: PluginCallback, ): Promise => { const { createPage, deletePage } = actions; - const config: BuildProps = { - ...defaultCompileProps, - ...options, - }; - const onBundle: CompilerCallbackFn = async ({ store: loadingStore }) => { - if (loadingStore) { - const store: Store = loadStore(loadingStore, true); - const createGatsbyPage: CreatePagesArgs['actions']['createPage'] = props => { - gatsbyStore.getState().pages.forEach((page: Page) => { - if (page.path === props.path && page.component === props.component) { - deletePage({ - path: page.path, - component: props.component, - }); - } + const createGatsbyPage: CreatePagesArgs['actions']['createPage'] = props => { + gatsbyStore.getState().pages.forEach((page: Page) => { + if (page.path === props.path && page.component === props.component) { + deletePage({ + path: page.path, + component: props.component, }); - createPage(props); - }; - //home page - const { path, docId, type, storyId } = getIndexPage(store) || {}; - createGatsbyPage({ - path, - component: require.resolve(`../src/templates/DocPage.tsx`), - context: { - docId, - type, - storyId, - }, - }); - const homePages = getHomePages(store); - homePages.forEach(({ path, docId, storyId, type }: DocHomePagesPath) => { + } + }); + createPage(props); + }; + await buildBundle({ + options, + onEndBuild: ({ store }) => { + const routes = getRoutes(store); + routes.forEach(({ path, ...route }) => { createGatsbyPage({ path, - component: require.resolve(`../src/templates/DocHome.tsx`), - context: { - type, - docId, - storyId, - }, + component: require.resolve(`../src/templates/DocPage.tsx`), + context: route, }); }); - - const docPages = getDocPages(store); - docPages.forEach( - ({ path, type, docId, storyId, category, activeTab }: DocPagesPath) => { - createGatsbyPage({ - path, - component: require.resolve(`../src/templates/DocPage.tsx`), - context: { - type, - docId, - storyId, - category, - activeTab, - }, - }); - }, - ); - if (process.env.NODE_ENV === 'production') { - if (store.config.siteMap) { - const sitemap = getSiteMap(store); - const staticFolder = - config.staticFolder || - sysPath.join(process.cwd(), 'public', 'static'); - const sitemapfolder = sysPath.resolve(staticFolder as string, '..'); - if (!fs.existsSync(sitemapfolder)) { - fs.mkdirSync(sitemapfolder, { recursive: true }); - } - const sitemapname = sysPath.resolve(sitemapfolder, 'sitemap.xml'); - log('creating sitemap', sitemapname); - fs.writeFileSync(sitemapname, sitemap, 'utf8'); - } - await searchIndexing(store); - } const cssBundle = getCSSBundleName(store.config); if (fs.existsSync(cssBundle)) { const cssStyles = fs.readFileSync(cssBundle, 'utf8'); process.env.GATSBY_CC_CSS = JSON.stringify(cssStyles); } - } - - doneCb(null, null); - }; - const run = process.env.NODE_ENV === 'development' ? watch : compile; - await run(config, onBundle); + }, + }); + doneCb(null, null); }; export const onCreateWebpackConfig = ( @@ -133,19 +56,5 @@ export const onCreateWebpackConfig = ( options: BuildProps, ): void => { //inject store bundle name - actions.setWebpackConfig({ - module: { - rules: [ - { - test: require.resolve('@component-controls/store/controls-store'), - use: { - loader: require.resolve('@component-controls/store/loader.js'), - options: { - bundleFileName: getBundleName(mergeBuildConfiguration(options)), - }, - }, - }, - ], - }, - }); + actions.setWebpackConfig(webpackConfig({ options })); }; diff --git a/integrations/gatsby-theme-stories/src/pages/404.tsx b/integrations/gatsby-theme-stories/src/pages/404.tsx index ca29b3be1..8e3ce66e6 100644 --- a/integrations/gatsby-theme-stories/src/pages/404.tsx +++ b/integrations/gatsby-theme-stories/src/pages/404.tsx @@ -1,20 +1,21 @@ -import React, { FC } from 'react'; -import { Label, Themed } from 'theme-ui'; +/** @jsx jsx */ +import { FC } from 'react'; +import { jsx, Label, Themed } from 'theme-ui'; import { Search } from '@component-controls/blocks'; import { Subtitle } from '@component-controls/components'; -import { Layout } from '../components/Layout'; +import { GatsbyLayout } from '../components/GatsbyLayout'; const ErrorPage: FC = () => { return ( - +
@@ -23,24 +24,21 @@ const ErrorPage: FC = () => { Oops! The page you are looking for has been removed or relocated
-
-
+ ); }; diff --git a/integrations/gatsby-theme-stories/src/templates/DocHome.tsx b/integrations/gatsby-theme-stories/src/templates/DocHome.tsx deleted file mode 100644 index c83624afa..000000000 --- a/integrations/gatsby-theme-stories/src/templates/DocHome.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React, { FC } from 'react'; - -import { DocType, defDocType } from '@component-controls/core'; -import { DocumentHomePage } from '@component-controls/app'; -import { Layout } from '../components/Layout'; - -interface PageListProps { - pageContext: { - type: DocType; - docId?: string; - storyId?: string; - }; -} - -const DocHomeTemplate: FC = ({ - pageContext: { type = defDocType, docId, storyId }, -}) => { - return ( - - - - ); -}; - -export default DocHomeTemplate; diff --git a/integrations/gatsby-theme-stories/src/templates/DocPage.tsx b/integrations/gatsby-theme-stories/src/templates/DocPage.tsx index fdfa48a5f..146423df6 100644 --- a/integrations/gatsby-theme-stories/src/templates/DocPage.tsx +++ b/integrations/gatsby-theme-stories/src/templates/DocPage.tsx @@ -1,31 +1,11 @@ import React, { FC } from 'react'; -import { DocType } from '@component-controls/core'; -import { DocPage } from '@component-controls/app'; -import { Layout } from '../components/Layout'; +import { GatsbyLayout, GatsbyLayoutProps } from '../components/GatsbyLayout'; interface DocPageProps { - pageContext: { - docId?: string; - storyId?: string; - type: DocType; - activeTab?: string; - category?: string; - }; + pageContext: GatsbyLayoutProps; } -const DocPageTemplate: FC = ({ - pageContext: { docId, storyId, type, activeTab, category }, -}) => { - return ( - - - - ); -}; - -export default DocPageTemplate; +const DocPage: FC = ({ pageContext }) => ( + +); +export default DocPage; diff --git a/integrations/nextjs-plugin/package.json b/integrations/nextjs-plugin/package.json index 95cbe436b..902333c2b 100644 --- a/integrations/nextjs-plugin/package.json +++ b/integrations/nextjs-plugin/package.json @@ -36,14 +36,11 @@ }, "license": "MIT", "dependencies": { - "@component-controls/app": "^3.3.0", + "@component-controls/base-integration": "^3.3.0", "@component-controls/pages": "^3.3.0", "@component-controls/routes": "^3.3.0", "@component-controls/search-algolia": "^3.3.0", "@component-controls/search-fusejs": "^3.3.0", - "@component-controls/store": "^3.3.0", - "@component-controls/webpack-compile": "^3.3.0", - "@component-controls/webpack-configs": "^3.3.0", "@emotion/babel-plugin": "^11.0.0", "next": "^10.0.7" }, diff --git a/integrations/nextjs-plugin/rollup.config.js b/integrations/nextjs-plugin/rollup.config.js index ad7e8d6a4..a5df16557 100644 --- a/integrations/nextjs-plugin/rollup.config.js +++ b/integrations/nextjs-plugin/rollup.config.js @@ -1,10 +1,5 @@ import { config } from '../../rollup-config'; export default config({ - input: [ - './src/index.ts', - './src/build.ts', - './src/store.ts', - './src/component-controls.ts', - ], + input: ['./src/index.tsx', './src/build.ts'], }); diff --git a/integrations/nextjs-plugin/src/build.ts b/integrations/nextjs-plugin/src/build.ts index 747064f4e..83c9f6b6a 100644 --- a/integrations/nextjs-plugin/src/build.ts +++ b/integrations/nextjs-plugin/src/build.ts @@ -1,81 +1,37 @@ -import fs from 'fs'; -import path from 'path'; -import { - compile, - watch, - CompilerCallbackFn, - searchIndexing, -} from '@component-controls/webpack-compile'; -import { log } from '@component-controls/logger'; -import { - BuildProps, - RuleOptions, - defaultCompileProps, -} from '@component-controls/core'; +import { BuildProps, RuleOptions } from '@component-controls/core'; import { getCSSBundleName } from '@component-controls/core/node-utils'; -import { Store } from '@component-controls/core'; -import { loadStore } from '@component-controls/store'; -import { getSiteMap } from '@component-controls/routes'; +import { + buildBundle, + webpackConfig, +} from '@component-controls/base-integration/webpack-build'; module.exports = ({ bundleName, configPath, presets, staticFolder, - distFolder: userDistFolder, + distFolder, webpack, ...rest }: BuildProps) => () => { - const userProps: BuildProps = { + const buildOptions: BuildProps = { bundleName, configPath, + presets, + staticFolder, + distFolder, webpack, }; - const distFolder = userDistFolder || path.join(process.cwd(), 'public'); - const buildConfig: BuildProps = { - ...defaultCompileProps, - ...{ - distFolder: path.resolve(__dirname), - staticFolder: staticFolder || path.join(distFolder, 'static'), - }, - ...userProps, - }; - if (presets) { - buildConfig.presets = presets; - } return { /** * we need some async function, to make sure the compilation process is completed */ async headers() { - const onBundle: CompilerCallbackFn = async ({ store: loadingStore }) => { - if (loadingStore) { - const store: Store = loadStore(loadingStore, true); - if (process.env.NODE_ENV === 'production') { - if (store.config.siteMap) { - const sitemap = getSiteMap(store); - const sitemapfolder = path.resolve( - buildConfig.staticFolder as string, - '..', - ); - if (!fs.existsSync(sitemapfolder)) { - fs.mkdirSync(sitemapfolder, { recursive: true }); - } - const sitemapname = path.join(sitemapfolder, 'sitemap.xml'); - log('creating sitemap', sitemapname); - fs.writeFileSync(sitemapname, sitemap, 'utf8'); - } - await searchIndexing(store); - } - process.env.NEXT_CC_CSS_FILENAME = getCSSBundleName(store.config); - } - }; - const compiler = - process.env.NODE_ENV === 'development' - ? watch(buildConfig, onBundle) - : compile(buildConfig, onBundle); - await compiler; - + await buildBundle({ + options: buildOptions, + onEndBuild: ({ store }) => + (process.env.NEXT_CC_CSS_FILENAME = getCSSBundleName(store.config)), + }); return []; }, webpack: (config: RuleOptions['config']) => { @@ -87,7 +43,7 @@ module.exports = ({ '@emotion/babel-plugin', ); } - return config; + return webpackConfig({ config, options: buildOptions }); }, ...rest, diff --git a/integrations/nextjs-plugin/src/component-controls.ts b/integrations/nextjs-plugin/src/component-controls.ts deleted file mode 100644 index 73949d2f0..000000000 --- a/integrations/nextjs-plugin/src/component-controls.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { LoadingStore } from '@component-controls/loader'; -const bundle = {} as LoadingStore; -module.exports = bundle; diff --git a/integrations/nextjs-plugin/src/components/Layout.tsx b/integrations/nextjs-plugin/src/components/Layout.tsx deleted file mode 100644 index 9ab4d94aa..000000000 --- a/integrations/nextjs-plugin/src/components/Layout.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { FC } from 'react'; -import { AppContext, AppContextProps } from '@component-controls/app'; -import Helmet from 'next/head'; -import { store } from '../store'; -import { NextLink } from './NextLink'; - -interface LayoutProps { - docId?: string; - storyId?: string; - activeTab?: string; - type?: string; -} - -export const Layout: FC = ({ - docId, - storyId, - children, - activeTab, - type, -}) => { - return ( - - {children} - - ); -}; diff --git a/integrations/nextjs-plugin/src/components/NextLayout.tsx b/integrations/nextjs-plugin/src/components/NextLayout.tsx new file mode 100644 index 000000000..935520e4f --- /dev/null +++ b/integrations/nextjs-plugin/src/components/NextLayout.tsx @@ -0,0 +1,14 @@ +import React, { FC } from 'react'; +import Helmet from 'next/head'; +import { Layout, LayoutProps } from '@component-controls/base-integration'; +import { NextLink } from './NextLink'; + +export const NextLayout: FC> = props => { + return ( + + ); +}; diff --git a/integrations/nextjs-plugin/src/components/types.ts b/integrations/nextjs-plugin/src/components/types.ts deleted file mode 100644 index d675cef13..000000000 --- a/integrations/nextjs-plugin/src/components/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ReactNode } from 'react'; - -export interface PageConfig { - key: string; - title: string; - render: () => ReactNode; -} - -export type PagesConfig = (route: string) => PageConfig[]; diff --git a/integrations/nextjs-plugin/src/index.ts b/integrations/nextjs-plugin/src/index.ts deleted file mode 100644 index 4524e1855..000000000 --- a/integrations/nextjs-plugin/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Helmet from 'next/head'; -export * from './components/Layout'; -export * from './store'; -export * from './page-links'; -export * from './templates/DocHome'; -export * from './templates/DocPage'; -export { Helmet }; diff --git a/integrations/nextjs-plugin/src/index.tsx b/integrations/nextjs-plugin/src/index.tsx new file mode 100644 index 000000000..248c347c2 --- /dev/null +++ b/integrations/nextjs-plugin/src/index.tsx @@ -0,0 +1,4 @@ +import { store } from '@component-controls/base-integration'; +export { NextLayout } from './components/NextLayout'; +export * from './page-links'; +export { store }; diff --git a/integrations/nextjs-plugin/src/page-links.ts b/integrations/nextjs-plugin/src/page-links.ts index dcd0f38f2..8117dbf95 100644 --- a/integrations/nextjs-plugin/src/page-links.ts +++ b/integrations/nextjs-plugin/src/page-links.ts @@ -22,11 +22,11 @@ export const getHomePagesPaths = (store: Store): string[] => { export const getDocHomePage = ( store: Store, path: string, -): DocHomePagesPath | undefined => { +): DocHomePagesPath => { const pages = getHomePages(store); const resolvedPath = getRoutePath(store, path); const page = pages.find(page => page.path === resolvedPath); - return page; + return page || { path }; }; export const getDocPagesPaths = (store: Store): string[] => { @@ -36,12 +36,12 @@ export const getDocPagesPaths = (store: Store): string[] => { export const getDocPage = ( store: Store, - docTyoe: DocType, + docType: DocType, docId: string[], -): DocPagesPath | undefined => { +): DocPagesPath => { const homePath = getHomePath(store); - const path = `${ensureTrailingSlash(homePath)}${docTyoe}/${docId.join('/')}`; + const path = `${ensureTrailingSlash(homePath)}${docType}/${docId.join('/')}`; const pages = getDocPages(store); const page = pages.find(page => page.path === path); - return page; + return page || { path }; }; diff --git a/integrations/nextjs-plugin/src/templates/DocHome.tsx b/integrations/nextjs-plugin/src/templates/DocHome.tsx deleted file mode 100644 index ef63689e8..000000000 --- a/integrations/nextjs-plugin/src/templates/DocHome.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React, { FC } from 'react'; - -import { DocType, defDocType } from '@component-controls/core'; -import { DocumentHomePage } from '@component-controls/app'; -import { Layout } from '../components/Layout'; - -export interface DocHomeTemplateProps { - type: DocType; - docId?: string; - storyId?: string; -} - -export const DocHomeTemplate: FC = ({ - type = defDocType, - docId, - storyId, -}) => ( - - - -); diff --git a/integrations/nextjs-plugin/src/templates/DocPage.tsx b/integrations/nextjs-plugin/src/templates/DocPage.tsx deleted file mode 100644 index fdaac0cd7..000000000 --- a/integrations/nextjs-plugin/src/templates/DocPage.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React, { FC } from 'react'; -import { DocType } from '@component-controls/core'; -import { DocPage } from '@component-controls/app'; -import { Layout } from '../components/Layout'; - -interface DocPageTemplateProps { - docId?: string; - storyId?: string; - type: DocType; - activeTab?: string; - category?: string; -} - -export const DocPageTemplate: FC = ({ - docId, - storyId, - type, - activeTab, - category, -}) => ( - - - -); diff --git a/integrations/react-router-integration/README.md b/integrations/react-router-integration/README.md index 66d4d2df4..f64484383 100644 --- a/integrations/react-router-integration/README.md +++ b/integrations/react-router-integration/README.md @@ -1,23 +1,23 @@ # Table of contents -- [In action](#in-action) -- [Overview](#overview) -- [API](#api) - - [Layout](#inslayoutins) - - [ReactRouterLink](#insreactrouterlinkins) - - [DocHomeTemplate](#insdochometemplateins) - - [DocPageTemplate](#insdocpagetemplateins) +- [In action](#in-action) +- [Overview](#overview) +- [API](#api) + - [Layout](#inslayoutins) + - [ReactRouterLink](#insreactrouterlinkins) + - [DocHomeTemplate](#insdochometemplateins) + - [DocPageTemplate](#insdocpagetemplateins) # In action -[Live site](https://nextjs.component-controls.com) +[Live site](https://webpack5.component-controls.com) # Overview react-router integration plugin for webpack sites documenting your projects with component controls -- Exports list of routes with their components. -- Exports post-build routine to generate sitemaps and search indexes. +- Exports list of routes with their components. +- Exports post-build routine to generate sitemaps and search indexes. [Getting started with webpack](https://component-controls.com/tutorial/getting-started/webpack) diff --git a/integrations/react-router-integration/package.json b/integrations/react-router-integration/package.json index a7a93da9b..e76d675d7 100644 --- a/integrations/react-router-integration/package.json +++ b/integrations/react-router-integration/package.json @@ -36,15 +36,11 @@ }, "license": "MIT", "dependencies": { - "@component-controls/app": "^3.3.0", - "@component-controls/core": "^3.3.0", - "@component-controls/logger": "^2.10.4", + "@component-controls/base-integration": "^3.3.0", "@component-controls/pages": "^3.3.0", - "@component-controls/routes": "^3.3.0", "@component-controls/search-algolia": "^3.3.0", "@component-controls/search-fusejs": "^3.3.0", - "@component-controls/store": "^3.3.0", - "@component-controls/webpack-compile": "^3.3.0", + "@component-controls/routes": "^3.3.0", "@types/react-router": "^5.1.11", "@types/react-router-dom": "^5.1.7", "react": "^17.0.1", diff --git a/integrations/react-router-integration/src/components/Layout.tsx b/integrations/react-router-integration/src/components/Layout.tsx deleted file mode 100644 index 576f81376..000000000 --- a/integrations/react-router-integration/src/components/Layout.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { FC } from 'react'; -import { AppContext, AppContextProps } from '@component-controls/app'; -import { Helmet } from 'react-helmet'; -import { store } from '@component-controls/store/controls-store'; -import { ReactRouterLink } from './ReactRouterLink'; - -interface LayoutProps { - docId?: string; - storyId?: string; - activeTab?: string; - type?: string; -} - -export const Layout: FC = ({ - docId, - storyId, - children, - activeTab, - type, -}) => { - return ( - - {children} - - ); -}; diff --git a/integrations/react-router-integration/src/components/types.ts b/integrations/react-router-integration/src/components/types.ts deleted file mode 100644 index d675cef13..000000000 --- a/integrations/react-router-integration/src/components/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ReactNode } from 'react'; - -export interface PageConfig { - key: string; - title: string; - render: () => ReactNode; -} - -export type PagesConfig = (route: string) => PageConfig[]; diff --git a/integrations/react-router-integration/src/index.tsx b/integrations/react-router-integration/src/index.tsx index 55745d39d..de6c05b59 100644 --- a/integrations/react-router-integration/src/index.tsx +++ b/integrations/react-router-integration/src/index.tsx @@ -1,66 +1,39 @@ -import React, { ReactElement, useMemo } from 'react'; +import React, { FC, ReactElement, useMemo } from 'react'; import { Route } from 'react-router-dom'; -import { store } from '@component-controls/store/controls-store'; - +import { Helmet } from 'react-helmet'; import { - DocHomePagesPath, - DocPagesPath, - getDocPages, - getHomePages, - getIndexPage, -} from '@component-controls/routes'; -import { DocPageTemplate } from './templates/DocPage'; -import { DocHomeTemplate } from './templates/DocHome'; + store, + Layout, + LayoutProps, +} from '@component-controls/base-integration'; + +import { getRoutes } from '@component-controls/routes'; +import { ReactRouterLink } from './components/ReactRouterLink'; + +export const ControlsPage = ( + props: Omit, +): FC => { + const DocHome: FC = () => ( + + ); + return DocHome; +}; export const useRoutes = (): ReactElement[] => { const routes = useMemo(() => { - const routes = []; - //home page - const { path, docId, type, storyId } = getIndexPage(store) || {}; - routes.push( + const paths = getRoutes(store); + const routes = paths.map(props => ( , - ); - - const homePages = getHomePages(store); - homePages.forEach(({ path, docId, storyId, type }: DocHomePagesPath) => { - routes.push( - , - ); - }); - - const docPages = getDocPages(store); - docPages.forEach( - ({ path, type, docId, storyId, category, activeTab }: DocPagesPath) => { - routes.push( - , - ); - }, - ); + path={props.path} + component={ControlsPage(props)} + /> + )); return routes; }, []); return routes; diff --git a/integrations/react-router-integration/src/templates/DocHome.tsx b/integrations/react-router-integration/src/templates/DocHome.tsx deleted file mode 100644 index 15fc093e6..000000000 --- a/integrations/react-router-integration/src/templates/DocHome.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React, { FC } from 'react'; - -import { DocType, defDocType } from '@component-controls/core'; -import { DocumentHomePage } from '@component-controls/app'; -import { Layout } from '../components/Layout'; - -interface DocHomeProps { - type: DocType; - docId?: string; - storyId?: string; -} - -export const DocHomeTemplate = ({ - type = defDocType, - docId, - storyId, -}: DocHomeProps): FC => { - const DocHome: FC = () => ( - - - - ); - return DocHome; -}; diff --git a/integrations/react-router-integration/src/templates/DocPage.tsx b/integrations/react-router-integration/src/templates/DocPage.tsx deleted file mode 100644 index 613c69a22..000000000 --- a/integrations/react-router-integration/src/templates/DocPage.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React, { FC } from 'react'; -import { DocType } from '@component-controls/core'; -import { DocPage } from '@component-controls/app'; -import { Layout } from '../components/Layout'; - -interface DocPageProps { - docId?: string; - storyId?: string; - type: DocType; - activeTab?: string; - category?: string; -} - -export const DocPageTemplate = ({ - docId, - storyId, - type, - activeTab, - category, -}: DocPageProps): FC => { - const DocHome: FC = () => ( - - - - ); - return DocHome; -}; diff --git a/integrations/react-router-integration/src/webpack-build.ts b/integrations/react-router-integration/src/webpack-build.ts index a956e8629..86b003892 100644 --- a/integrations/react-router-integration/src/webpack-build.ts +++ b/integrations/react-router-integration/src/webpack-build.ts @@ -1,87 +1,7 @@ -import path from 'path'; -import fs from 'fs'; -import { - BuildProps, - Store, - defaultCompileProps, -} from '@component-controls/core'; -import { getSiteMap } from '@component-controls/routes'; -import { LoadingStore, loadStore } from '@component-controls/store'; -import { log } from '@component-controls/logger'; -import { - CompilerCallbackFn, - searchIndexing, -} from '@component-controls/webpack-compile'; -import { getBundleName } from '@component-controls/core/node-utils'; -import { compile, watch } from '@component-controls/webpack-compile'; +import { BuildProps } from '@component-controls/core'; +import { asyncWebpackConfig } from '@component-controls/base-integration/webpack-build'; -export const postBuild = async ( - staticFolder: string, - loadingStore?: LoadingStore, -): Promise => { - if (loadingStore) { - const store: Store = loadStore(loadingStore, true); - if (process.env.NODE_ENV === 'production') { - if (store.config.siteMap) { - const sitemap = getSiteMap(store); - const sitemapfolder = path.resolve(staticFolder, '..'); - if (!fs.existsSync(sitemapfolder)) { - fs.mkdirSync(sitemapfolder, { recursive: true }); - } - const sitemapname = path.join(sitemapfolder, 'sitemap.xml'); - log('creating sitemap', sitemapname); - fs.writeFileSync(sitemapname, sitemap, 'utf8'); - } - await searchIndexing(store); - } - } -}; - -export const withComponentControls = ({ - config, - mode: userMode, - options, -}: { +export const withComponentControls = (props: { config: any; - mode?: string; options?: BuildProps; -}) => - async function(): Promise { - const mode = userMode || process.env.NODE_ENV || config.mode; - if (typeof process.env.NODE_ENV === 'undefined') { - process.env.NODE_ENV = mode; - } - const distFolder = options?.distFolder || path.join(process.cwd(), 'dist'); - const staticFolder = path.join(options?.distFolder || distFolder, 'static'); - const buildOptions: BuildProps = { - ...defaultCompileProps, - configPath: '.config', - distFolder, - staticFolder, - ...options, - }; - const onBundle: CompilerCallbackFn = async ({ store }) => { - await postBuild(buildOptions.staticFolder as string, store); - }; - - const run = mode === 'production' ? compile : watch; - await run(buildOptions, onBundle); - return { - ...config, - module: { - ...config.module, - rules: [ - ...(config.module?.rules || []), - { - test: require.resolve('@component-controls/store/controls-store'), - use: { - loader: require.resolve('@component-controls/store/loader.js'), - options: { - bundleFileName: getBundleName(buildOptions), - }, - }, - }, - ], - }, - }; - }; +}) => async (): Promise => asyncWebpackConfig(props); diff --git a/ui/app/src/DocPage/DocPage.tsx b/ui/app/src/DocPage/DocPage.tsx index 5e04cdc4a..8eac768fd 100644 --- a/ui/app/src/DocPage/DocPage.tsx +++ b/ui/app/src/DocPage/DocPage.tsx @@ -5,13 +5,14 @@ import { useCurrentDocument, useTheme } from '@component-controls/store'; import { PageContainer } from '../PageContainer'; import { SidebarsPage, DocPageProps } from '../SidebarsPage'; import { CategoryPage } from '../CategoryPage'; +import { defDocType } from '@component-controls/core'; /** * documentation page for current document. * will check if the page has a layout with sidebars or if the page is standalone. */ export const DocPage: FC & { category?: string }> = ({ - type = 'story', + type = defDocType, category, ...props }) => { diff --git a/ui/app/src/DocumentHomePage/DocumentHomePage.tsx b/ui/app/src/DocumentHomePage/DocumentHomePage.tsx index e8ad36d72..a0afb30eb 100644 --- a/ui/app/src/DocumentHomePage/DocumentHomePage.tsx +++ b/ui/app/src/DocumentHomePage/DocumentHomePage.tsx @@ -1,7 +1,7 @@ /** @jsx jsx */ import { FC } from 'react'; import { jsx, Themed } from 'theme-ui'; -import { DocType } from '@component-controls/core'; +import { defDocType, DocType } from '@component-controls/core'; import { useConfig, useSortedDocByType } from '@component-controls/store'; import { PageContainer } from '../PageContainer'; import { DocumentsList } from '../DocumentsList'; @@ -9,13 +9,15 @@ import { DocPage } from '../DocPage'; import { CategoryList } from '../CategoryList'; export interface DocumentHomePageProps { - type: DocType; + type?: DocType; } /** * list of documents for a specific document type */ -export const DocumentHomePage: FC = ({ type }) => { +export const DocumentHomePage: FC = ({ + type = defDocType, +}) => { const config = useConfig(); const { categories } = config || {}; const isCategory = categories?.includes(type); diff --git a/ui/app/src/DocumentsList/DocumentsList.stories.tsx b/ui/app/src/DocumentsList/DocumentsList.stories.tsx index c85e02620..d30312aed 100644 --- a/ui/app/src/DocumentsList/DocumentsList.stories.tsx +++ b/ui/app/src/DocumentsList/DocumentsList.stories.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Document, Example } from '@component-controls/core'; +import { defDocType, Document, Example } from '@component-controls/core'; import { mockDecorators } from '@component-controls/blocks'; import { useDocByType } from '@component-controls/store'; import { DocumentsList } from './DocumentsList'; @@ -12,6 +12,6 @@ export default { } as Document; export const overview: Example = () => { - const pages = useDocByType('story'); + const pages = useDocByType(defDocType); return ; }; diff --git a/ui/app/src/Links/DocLink.tsx b/ui/app/src/Links/DocLink.tsx index a1ce43cbe..120e89bba 100644 --- a/ui/app/src/Links/DocLink.tsx +++ b/ui/app/src/Links/DocLink.tsx @@ -2,6 +2,7 @@ import React, { FC } from 'react'; import { LinkProps } from 'theme-ui'; import { Link } from '@component-controls/components'; import { useDocumentPath } from '@component-controls/store'; +import { defDocType } from '@component-controls/core'; export interface DocLinkProps { id: string; @@ -14,7 +15,7 @@ export const DocLink: FC> = ({ id, ...props }) => { - const href = useDocumentPath('story', id); + const href = useDocumentPath(defDocType, id); return ( {children} diff --git a/ui/app/src/Links/DocsLink.tsx b/ui/app/src/Links/DocsLink.tsx index 0f3ab41cb..6cdc20a54 100644 --- a/ui/app/src/Links/DocsLink.tsx +++ b/ui/app/src/Links/DocsLink.tsx @@ -2,6 +2,7 @@ import React, { FC } from 'react'; import { LinkProps } from 'theme-ui'; import { Link } from '@component-controls/components'; import { useConfig } from '@component-controls/store'; +import { defDocType } from '@component-controls/core'; /** * native lonk to the documentation @@ -11,7 +12,7 @@ export const DocsLink: FC> = ({ ...props }) => { const config = useConfig(); - const { basePath = '' } = config.pages?.['story'] || {}; + const { basePath = '' } = config.pages?.[defDocType] || {}; return ( diff --git a/ui/app/src/SidebarsPage/SidebarsMDXPage.tsx b/ui/app/src/SidebarsPage/SidebarsMDXPage.tsx index 5d73560d2..64da4ec8b 100644 --- a/ui/app/src/SidebarsPage/SidebarsMDXPage.tsx +++ b/ui/app/src/SidebarsPage/SidebarsMDXPage.tsx @@ -1,7 +1,7 @@ /** @jsx jsx */ import { FC, useRef } from 'react'; import { jsx, Box } from 'theme-ui'; -import { DocType, Document } from '@component-controls/core'; +import { defDocType, DocType, Document } from '@component-controls/core'; import { PageContainer } from '../PageContainer'; import { Sidebar } from '../Sidebar'; import { SideContext } from '../SideContext'; @@ -11,7 +11,7 @@ export interface SidebarsMDXPageProps { /** * document type */ - type: DocType; + type?: DocType; /** * document object @@ -22,7 +22,10 @@ export interface SidebarsMDXPageProps { /** * document page - rendering with sidebars and tabs for multiple document views */ -export const SidebarsMDXPage: FC = ({ type, doc }) => { +export const SidebarsMDXPage: FC = ({ + type = defDocType, + doc, +}) => { const pageRef = useRef(null); return ( diff --git a/ui/app/src/SidebarsPage/SidebarsStoryPage.tsx b/ui/app/src/SidebarsPage/SidebarsStoryPage.tsx index 872106d0e..91f40c2fe 100644 --- a/ui/app/src/SidebarsPage/SidebarsStoryPage.tsx +++ b/ui/app/src/SidebarsPage/SidebarsStoryPage.tsx @@ -6,6 +6,7 @@ import { TabConfiguration, Document, PageTab, + defDocType, } from '@component-controls/core'; import { useActiveTab, @@ -30,7 +31,7 @@ export interface DocPageProps { /** * document type */ - type: DocType; + type?: DocType; /** * document object */ @@ -40,7 +41,10 @@ export interface DocPageProps { /** * document page - rendering with sidebars and tabs for multiple document views */ -export const SidebarsStoryPage: FC = ({ type, doc }) => { +export const SidebarsStoryPage: FC = ({ + type = defDocType, + doc, +}) => { const docId = doc.title; const story = useCurrentStory(); const config = useConfig();