├── examples ├── .env ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── src │ ├── react-app-env.d.ts │ ├── index.tsx │ ├── App.css │ ├── App.test.tsx │ ├── index.node.tsx │ └── App.tsx ├── .gitignore ├── tsconfig.json ├── package.json └── README.md ├── packages ├── demoboard-core │ ├── .env.test │ ├── src │ │ ├── @types │ │ │ └── sass.js.d.ts │ │ ├── types │ │ │ ├── DemoboardGeneratedFile.ts │ │ │ ├── DemoboardPanelType.ts │ │ │ ├── DemoboardExporter.ts │ │ │ ├── DemoboardConsoleLine.ts │ │ │ ├── DemoboardGenerator.ts │ │ │ ├── index.ts │ │ │ ├── DemoboardInstance.ts │ │ │ ├── DemoboardHistory.ts │ │ │ ├── DemoboardBuild.ts │ │ │ └── DemoboardLayout.ts │ │ ├── utils │ │ │ ├── clamp.ts │ │ │ ├── normalizeReferencedPathname.ts │ │ │ ├── shallowCompare.ts │ │ │ └── history.ts │ │ ├── vendor │ │ │ ├── SourceMapConsumer.js │ │ │ └── SourceMapConsumer.d.ts │ │ ├── index.ts │ │ ├── exporters │ │ │ └── basicExporter.ts │ │ ├── worker │ │ │ ├── getWorker.ts │ │ │ └── getWorkerByFetch.ts │ │ ├── generators │ │ │ ├── indexHTMLGenerator.ts │ │ │ └── markdownCSSGenerator.ts │ │ ├── layout │ │ │ ├── useDemoboardLayout.ts │ │ │ └── ClientDimensions.ts │ │ ├── DemoboardContext.tsx │ │ ├── instance │ │ │ └── DemoboardInstanceIFrame.tsx │ │ ├── build │ │ │ └── DemoboardBuildErrors.ts │ │ ├── defaultURLs.ts │ │ └── project │ │ │ └── createInitialDemoboardProjectState.ts │ ├── test │ │ ├── mocks │ │ │ └── getWorkerShim.ts │ │ └── useDemoboardBuild.test.tsx │ ├── jest.config.js │ ├── tsconfig.json │ ├── rollup.config.js │ └── package.json ├── demoboard-ui │ ├── src │ │ ├── components │ │ │ ├── Console.styles.tsx.stub │ │ │ ├── input │ │ │ │ ├── index.ts │ │ │ │ └── input.tsx │ │ │ ├── tooltip │ │ │ │ ├── index.ts │ │ │ │ └── tooltip.tsx │ │ │ ├── buildError │ │ │ │ ├── index.ts │ │ │ │ ├── buildError.stories.tsx │ │ │ │ └── buildError.tsx │ │ │ ├── openTabList │ │ │ │ ├── index.ts │ │ │ │ ├── openTabList.stories.tsx │ │ │ │ └── openTabList.tsx │ │ │ ├── panelTabList │ │ │ │ ├── index.ts │ │ │ │ └── panelTabList.tsx │ │ │ ├── iconButton │ │ │ │ ├── index.ts │ │ │ │ ├── iconButton.stories.tsx │ │ │ │ └── iconButton.tsx │ │ │ ├── navigationBar │ │ │ │ ├── index.ts │ │ │ │ └── navigationBar.stories.tsx │ │ │ ├── demoboardView.stories.tsx │ │ │ ├── Buttons.tsx │ │ │ ├── Icon.tsx │ │ │ ├── Spinner.tsx │ │ │ └── CodeMirrorEditor.tsx │ │ ├── icons │ │ │ ├── .gitignore │ │ │ ├── icomoon │ │ │ │ └── SVG │ │ │ │ │ ├── play.svg │ │ │ │ │ ├── add.svg │ │ │ │ │ ├── check.svg │ │ │ │ │ ├── menu.svg │ │ │ │ │ ├── forward.svg │ │ │ │ │ ├── download.svg │ │ │ │ │ ├── back.svg │ │ │ │ │ ├── code.svg │ │ │ │ │ ├── close.svg │ │ │ │ │ ├── fork.svg │ │ │ │ │ ├── undo.svg │ │ │ │ │ ├── delete.svg │ │ │ │ │ ├── edit.svg │ │ │ │ │ ├── delete_outline.svg │ │ │ │ │ ├── console.svg │ │ │ │ │ ├── refresh.svg │ │ │ │ │ ├── key.svg │ │ │ │ │ ├── more.svg │ │ │ │ │ ├── lock.svg │ │ │ │ │ ├── share.svg │ │ │ │ │ ├── lock_outline.svg │ │ │ │ │ └── lock_closed.svg │ │ │ └── components.ts │ │ ├── utils │ │ │ ├── cleanUpPathname.ts │ │ │ └── addDefaultPixelUnits.ts │ │ ├── filetypes.d.ts │ │ ├── index.ts │ │ └── @types │ │ │ └── modules.d.ts │ ├── .storybook │ │ ├── addons.js │ │ ├── config.js │ │ └── webpack.config.js │ ├── tsconfig.json │ ├── package.json │ └── rollup.config.js ├── demoboard │ ├── src │ │ ├── index.ts │ │ ├── CodeMirror.d.ts │ │ ├── CodeMirror.js │ │ ├── CodeMirror.import.js │ │ └── CodeMirror.conditional.js │ ├── tsconfig.json │ └── package.json ├── demoboard-worker │ ├── src │ │ ├── npm │ │ │ ├── index.ts │ │ │ ├── npmTypes.ts │ │ │ └── nodeBrowserModules.ts │ │ ├── transforms │ │ │ ├── getTransformImporters.js │ │ │ ├── register.ts │ │ │ ├── css │ │ │ │ └── index.ts │ │ │ ├── getTransformImporters.d.ts │ │ │ ├── sass │ │ │ │ └── index.ts │ │ │ ├── fetchTransformFromNetwork.ts │ │ │ ├── cssModule │ │ │ │ └── index.ts │ │ │ ├── mdx │ │ │ │ ├── rehype-prism.ts │ │ │ │ └── index.ts │ │ │ ├── babel │ │ │ │ ├── babel-plugin-prevent-infinite-loops.ts │ │ │ │ └── index.ts │ │ │ └── load.ts │ │ ├── types │ │ │ ├── DemoboardWorkerTransformContext.ts │ │ │ ├── DemoboardWorkerTransform.ts │ │ │ ├── index.ts │ │ │ ├── DemoboardWorkerTransformFetchOptions.ts │ │ │ ├── DemoboardWorkerTransformedModule.ts │ │ │ ├── DemoboardWorkerGlobalScope.ts │ │ │ └── DemoboardWorkerBuild.ts │ │ ├── utils │ │ │ ├── normalizeReferencedPathname.ts │ │ │ └── Deferred.ts │ │ ├── index.ts │ │ ├── @types │ │ │ └── modules.d.ts │ │ ├── findDependenciesAndTransformModules.ts │ │ ├── DemoboardBuildErrors.ts │ │ └── babel │ │ │ └── babel-plugin-detective.ts │ ├── tsconfig.json │ └── package.json ├── demoboard-messaging │ ├── src │ │ ├── types │ │ │ ├── MessagesToRuntime.ts │ │ │ ├── MessagesToHost.ts │ │ │ └── ConsoleItem.ts │ │ └── replicator │ │ │ ├── arithmeticTransform.ts │ │ │ ├── mapTransform.ts │ │ │ ├── functionTransform.ts │ │ │ ├── htmlTransform.ts │ │ │ ├── promiseTransform.ts │ │ │ └── index.ts │ ├── tsconfig.json │ └── package.json ├── demoboard-runtime │ ├── tsconfig.json │ ├── package.json │ ├── src │ │ ├── captureErrors.ts │ │ ├── captureAnchorClicks.ts │ │ ├── container.html │ │ ├── index.ts │ │ └── captureConsole.ts │ └── rollup.config.js └── demoboard-worker-provider │ ├── tsconfig.json │ ├── src │ └── DemoboardWorkerProvider.tsx │ ├── package.json │ └── rollup.config.js ├── .gitignore ├── .eslintignore ├── lerna.json ├── .prettierrc ├── .eslintrc.js ├── .vscode └── settings.json ├── README.md └── package.json /examples/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | -------------------------------------------------------------------------------- /packages/demoboard-core/.env.test: -------------------------------------------------------------------------------- 1 | NODE_ENV=test -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/Console.styles.tsx.stub: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/input/index.ts: -------------------------------------------------------------------------------- 1 | export * from './input' 2 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/tooltip/index.ts: -------------------------------------------------------------------------------- 1 | export * from './tooltip' 2 | -------------------------------------------------------------------------------- /examples/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/buildError/index.ts: -------------------------------------------------------------------------------- 1 | export * from './buildError' 2 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/openTabList/index.ts: -------------------------------------------------------------------------------- 1 | export * from './openTabList' 2 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/panelTabList/index.ts: -------------------------------------------------------------------------------- 1 | export * from './panelTabList' 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .esm-cache 2 | .env.local 3 | .rpt2_cache 4 | dist 5 | node_modules 6 | notes 7 | *.log -------------------------------------------------------------------------------- /examples/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frontarm/demoboard/HEAD/examples/public/favicon.ico -------------------------------------------------------------------------------- /examples/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frontarm/demoboard/HEAD/examples/public/logo192.png -------------------------------------------------------------------------------- /examples/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frontarm/demoboard/HEAD/examples/public/logo512.png -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/.gitignore: -------------------------------------------------------------------------------- 1 | icomoon/*.* 2 | icomoon/demo-files 3 | !icomoon/selection.json 4 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | packages/demoboard 2 | packages/demoboard-core/dist/* 3 | packages/demoboard-messaging 4 | packages/demoboard-runtime -------------------------------------------------------------------------------- /examples/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "useWorkspaces": true, 4 | "lerna": "3.15.0", 5 | "version": "0.1.29" 6 | } 7 | -------------------------------------------------------------------------------- /packages/demoboard-ui/.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-actions/register'; 2 | import '@storybook/addon-links/register'; 3 | -------------------------------------------------------------------------------- /packages/demoboard/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@frontarm/demoboard-core' 2 | export * from '@frontarm/demoboard-ui' 3 | export * from './Demoboard' 4 | -------------------------------------------------------------------------------- /examples/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './App' 4 | 5 | ReactDOM.hydrate(, document.getElementById('root')) 6 | -------------------------------------------------------------------------------- /packages/demoboard-ui/.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from '@storybook/react' 2 | 3 | // automatically import all files ending in *.stories.js 4 | configure(require.context('../src/components', true, /\.stories\.tsx$/), module) 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": false, 3 | "printWidth": 80, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "trailingComma": "all", 7 | "jsxBracketSameLine": true, 8 | "parser": "typescript", 9 | "semi": false, 10 | "rcVerbose": false 11 | } -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | play 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/src/App.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 16px; 3 | margin: 0; 4 | } 5 | 6 | body { 7 | font-family: Lato, sans-serif; 8 | font-size: 16px; 9 | margin: 0; 10 | } 11 | 12 | h1 { 13 | font-size: 18px; 14 | } 15 | 16 | h2 { 17 | font-size: 12px; 18 | margin-bottom: 6px; 19 | } 20 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | add 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | check 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/@types/sass.js.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare module 'sass.js/dist/sass.js' 9 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/iconButton/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export * from './iconButton' 9 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/navigationBar/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export * from './navigationBar' 9 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/menu.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | menu 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/npm/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export * from './npm' 9 | export * from './npmTypes' 10 | -------------------------------------------------------------------------------- /packages/demoboard/src/CodeMirror.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare const CodeMirror: any 9 | export default CodeMirror 10 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | forward 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/download.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | download 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | back 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/code.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | code 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-messaging/src/types/MessagesToRuntime.ts: -------------------------------------------------------------------------------- 1 | import { FetchResult } from 'polestar' 2 | 3 | export type MessagesToRuntime = { 4 | 'pop-state': { 5 | location: any, 6 | state: any, 7 | length: any, 8 | }, 9 | 10 | 'module': FetchResult, 11 | 12 | 'module-failure': { 13 | url: string, 14 | error: Error, 15 | } 16 | } -------------------------------------------------------------------------------- /packages/demoboard-core/src/types/DemoboardGeneratedFile.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export interface DemoboardGeneratedFile { 9 | type: string 10 | props?: any 11 | } 12 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/transforms/getTransformImporters.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // eslint-disable-next-line no-undef 9 | export default GET_TRANSFORM_IMPORTERS 10 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | close 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/utils/cleanUpPathname.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export default function cleanUpPathname(pathname: string) { 9 | return pathname.replace(/^\//, '') 10 | } 11 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/fork.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | fork 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/undo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | undo 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | delete 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/utils/clamp.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | function clamp(min: number, value: number, max: number) { 9 | return Math.max(min, Math.min(value, max)) 10 | } 11 | 12 | export default clamp 13 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | edit 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/utils/addDefaultPixelUnits.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export default function addDefaultPixelUnits(value: number | string) { 9 | return typeof value === 'number' ? value + 'px' : value 10 | } 11 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/delete_outline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | delete_outline 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/transforms/register.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { DemoboardWorkerGlobalScope } from '../types' 9 | 10 | declare const self: DemoboardWorkerGlobalScope 11 | export default self.demoboard.registerTransform 12 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/types/DemoboardPanelType.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export type DemoboardPanelType = 9 | | 'files' 10 | | 'tabs' 11 | | 'source' 12 | | 'templateSource' 13 | | 'iframe' 14 | | 'navigation' 15 | | 'console' 16 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/console.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | console 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/filetypes.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare module '*.css' { 9 | const content: string 10 | export default content 11 | } 12 | 13 | declare module '*.svg' { 14 | const content: any 15 | export default content 16 | } 17 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/types/DemoboardWorkerTransformContext.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export interface DemoboardWorkerTransformContext { 9 | babelTransform: any 10 | babelDetective: any 11 | errors: typeof import('../DemoboardBuildErrors') 12 | } 13 | -------------------------------------------------------------------------------- /packages/demoboard-core/test/mocks/getWorkerShim.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import worker, { 9 | DemoboardWorker, 10 | } from '@frontarm/demoboard-worker/dist/commonjs' 11 | 12 | function getWorkerShim(): DemoboardWorker { 13 | return worker 14 | } 15 | 16 | export default getWorkerShim 17 | -------------------------------------------------------------------------------- /packages/demoboard/src/CodeMirror.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // 9 | // DO NOT CHANGE - THIS WILL BE REWRITTEN BY THE BUILD PROCESS 10 | // 11 | import CodeMirror from './CodeMirror.CODEMIRROR_IMPORT_METHOD.js' 12 | export * from './CodeMirror.CODEMIRROR_IMPORT_METHOD.js' 13 | export default CodeMirror 14 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | /// 8 | 9 | import {} from 'styled-components/cssprop' 10 | 11 | export { 12 | DemoboardView as DemoboardUI, 13 | DemoboardViewGlobalStyles as DemoboardUIGlobalStyles, 14 | } from './components/DemoboardView' 15 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/types/DemoboardWorkerTransform.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { DemoboardWorkerTransformedModule } from './DemoboardWorkerTransformedModule' 9 | 10 | export type DemoboardWorkerTransform = ( 11 | input: DemoboardWorkerTransformedModule, 12 | ) => Promise 13 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/refresh.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | refresh 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/key.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | key 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/types/DemoboardExporter.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { DemoboardProjectState } from './DemoboardProject' 9 | import { DemoboardBuild } from './DemoboardBuild' 10 | 11 | export type DemoboardExporter = (options: { 12 | build: DemoboardBuild 13 | project: DemoboardProjectState 14 | }) => Promise 15 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/types/DemoboardConsoleLine.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { ConsoleItem } from '@frontarm/demoboard-messaging' 9 | 10 | export type DemoboardConsoleLine = 11 | | { 12 | source: 'console-item' 13 | item: ConsoleItem 14 | } 15 | | { 16 | source: 'error' 17 | error: Error 18 | } 19 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: 'react-app', 3 | parser: '@typescript-eslint/parser', 4 | plugins: ['@typescript-eslint', 'header'], 5 | settings: { 6 | react: { 7 | version: '16.8', 8 | }, 9 | 'import/parsers': { 10 | '@typescript-eslint/parser': ['.ts', '.tsx'], 11 | }, 12 | }, 13 | rules: { 14 | '@typescript-eslint/no-angle-bracket-type-assertion': 'off', 15 | 'header/header': [ 16 | 'error', 17 | 'block', 18 | { pattern: ' Copyright (\\(c\\) )?\\d{4}' }, 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/more.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | more 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/types/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export * from './DemoboardWorkerBuild' 9 | export * from './DemoboardWorkerGlobalScope' 10 | export * from './DemoboardWorkerTransformedModule' 11 | export * from './DemoboardWorkerTransformContext' 12 | export * from './DemoboardWorkerTransform' 13 | export * from './DemoboardWorkerTransformFetchOptions' 14 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/vendor/SourceMapConsumer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // We don't want to import the full library, as it is large and uses CommonJS 9 | // so tree shaking is unlikely to work. Instead, let's just import the one 10 | // bit we use. 11 | const { SourceMapConsumer } = require('source-map/lib/source-map-consumer') 12 | module.exports = { SourceMapConsumer } 13 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/types/DemoboardWorkerTransformFetchOptions.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export interface DemoboardWorkerTransformFetchOptions extends RequestInit { 9 | baseURL?: string 10 | 11 | // If provided, instead of creating a URL by appending a filename to the 12 | // base URL, this will be used as is. 13 | overrideURLs?: { [name: string]: string } 14 | } 15 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/iconButton/iconButton.stories.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react' 9 | import { action } from '@storybook/addon-actions' 10 | import { IconButton } from './iconButton' 11 | 12 | export default { 13 | title: 'IconButton', 14 | } 15 | 16 | export const raised = () => ( 17 | 18 | ) 19 | -------------------------------------------------------------------------------- /packages/demoboard-messaging/src/types/MessagesToHost.ts: -------------------------------------------------------------------------------- 1 | import { ConsoleItem } from './ConsoleItem' 2 | 3 | export type MessagesToHost = { 4 | 'container-ready': {} 5 | 6 | init: {} 7 | 8 | error: Error 9 | 10 | 'console-item': ConsoleItem 11 | 12 | navigate: { 13 | url: string 14 | } 15 | 16 | 'update-history-state': { 17 | operation: 'pushState' | 'replaceState' 18 | state: any 19 | title?: string | null 20 | location: any 21 | } 22 | 23 | 'module-required': { 24 | url: string 25 | requiredById: string 26 | originalRequest: string 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/demoboard-messaging/src/types/ConsoleItem.ts: -------------------------------------------------------------------------------- 1 | export type ConsoleItemPayloads = { 2 | assert: any[], 3 | clear: null, 4 | count: any[] 5 | debug: any[], 6 | error: any[], 7 | info: any[], 8 | log: any[], 9 | table: { 10 | data: string, 11 | columns?: string[], 12 | }, 13 | timeEnd: any[] 14 | warn: any[], 15 | } 16 | 17 | export type ConsoleMethod = keyof ConsoleItemPayloads 18 | 19 | export type ConsoleItem = { 20 | [T in keyof ConsoleItemPayloads]: { 21 | method: T, 22 | id: string 23 | data: ConsoleItemPayloads[T] 24 | } 25 | }[keyof ConsoleItemPayloads] 26 | -------------------------------------------------------------------------------- /examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "noEmit": true, 20 | "jsx": "react" 21 | }, 22 | "include": [ 23 | "src" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /examples/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/vendor/SourceMapConsumer.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { SourceMapConsumerConstructor as BaseSourceMapConsumerConstructor } from 'source-map' 9 | 10 | interface SourceMapConsumerConstructor 11 | extends BaseSourceMapConsumerConstructor { 12 | initialize(options: { 'lib/mappings.wasm': string }): void 13 | } 14 | 15 | export declare const SourceMapConsumer: SourceMapConsumerConstructor 16 | -------------------------------------------------------------------------------- /packages/demoboard/src/CodeMirror.import.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import CodeMirror from 'codemirror' 9 | import 'codemirror/addon/runmode/runmode' 10 | 11 | import 'codemirror/mode/meta' 12 | 13 | import 'codemirror/mode/jsx/jsx' 14 | import 'codemirror/mode/css/css' 15 | import 'codemirror/mode/markdown/markdown' 16 | import 'codemirror/mode/htmlmixed/htmlmixed' 17 | 18 | export default CodeMirror 19 | export * from 'codemirror' 20 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | lock 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/transforms/css/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import register from '../register' 9 | 10 | register( 11 | 'css', 12 | () => 13 | async function transpileCSS({ originalSource, pathname }) { 14 | return { 15 | css: originalSource, 16 | dependencies: [], 17 | originalSource, 18 | map: null, 19 | pathname, 20 | transformedSource: 'module.exports = {}', 21 | } 22 | }, 23 | ) 24 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/share.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | share 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-messaging/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "downlevelIteration": true, 4 | "esModuleInterop": true, 5 | "jsx": "react", 6 | "target": "es5", 7 | "module": "esnext", 8 | "moduleResolution": "node", 9 | "outDir": "dist/es", 10 | "removeComments": false, 11 | "sourceMap": true, 12 | "lib": [ 13 | "es5", 14 | "es6", 15 | "dom", 16 | "dom.iterable", 17 | "es2015", 18 | "es2016", 19 | "es2017" 20 | ] 21 | }, 22 | "exclude": [ 23 | "dist", 24 | "node_modules" 25 | ] 26 | } -------------------------------------------------------------------------------- /packages/demoboard-runtime/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "downlevelIteration": true, 4 | "esModuleInterop": true, 5 | "jsx": "react", 6 | "target": "es5", 7 | "module": "esnext", 8 | "moduleResolution": "node", 9 | "outDir": "dist/es", 10 | "removeComments": false, 11 | "sourceMap": true, 12 | "lib": [ 13 | "es5", 14 | "es6", 15 | "dom", 16 | "dom.iterable", 17 | "es2015", 18 | "es2016", 19 | "es2017" 20 | ] 21 | }, 22 | "exclude": [ 23 | "dist", 24 | "node_modules" 25 | ] 26 | } -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/lock_outline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | lock_outline 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/types/DemoboardWorkerTransformedModule.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export interface DemoboardWorkerTransformedModule { 9 | /** 10 | * Any CSS is stored in a separate variable, so that a single module can 11 | * output both JavaScript and CSS (allowing for CSS Modules support). 12 | */ 13 | css: null | string 14 | 15 | dependencies: string[] 16 | map: null | any 17 | originalSource: string 18 | pathname: string 19 | transformedSource: string 20 | } 21 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/icomoon/SVG/lock_closed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | lock_closed 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/types/DemoboardGenerator.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export interface DemoboardGeneratorOptions { 9 | context: any 10 | dependencies: { 11 | [packageName: string]: string 12 | } 13 | metadata: any 14 | pathname: string 15 | pathnames: string[] 16 | props: any 17 | } 18 | 19 | /** 20 | * Return a string, or `null` in case the source should not be generated. 21 | */ 22 | export type DemoboardGenerator = ( 23 | options: DemoboardGeneratorOptions, 24 | ) => string | null 25 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/transforms/getTransformImporters.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { DemoboardWorkerTransformFetchOptions } from '../types' 9 | 10 | type WrapTranform = ( 11 | name: string, 12 | importFunction?: Function, 13 | ) => (options?: DemoboardWorkerTransformFetchOptions) => void 14 | 15 | declare const GET_TRANSFORM_IMPORTERS: ( 16 | wrapTransform: WrapTranform, 17 | ) => { [name: string]: (options?: DemoboardWorkerTransformFetchOptions) => any } 18 | 19 | export default GET_TRANSFORM_IMPORTERS 20 | -------------------------------------------------------------------------------- /packages/demoboard-core/jest.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | module.exports = { 9 | testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$', 10 | testEnvironment: 'jsdom', 11 | moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx'], 12 | preset: 'ts-jest', 13 | testMatch: null, 14 | moduleNameMapper: { 15 | './worker/getWorker': '/test/mocks/getWorkerShim.ts', 16 | }, 17 | globals: { 18 | 'ts-jest': { 19 | babelConfig: null, 20 | diagnostics: false, 21 | }, 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/types/DemoboardWorkerGlobalScope.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { DemoboardWorkerTransform } from './DemoboardWorkerTransform' 9 | import { DemoboardWorkerTransformContext } from './DemoboardWorkerTransformContext' 10 | 11 | export interface DemoboardWorkerGlobalScope extends DedicatedWorkerGlobalScope { 12 | demoboard: { 13 | registerTransform( 14 | name: string, 15 | factory: ( 16 | context: DemoboardWorkerTransformContext, 17 | ) => DemoboardWorkerTransform, 18 | ): void 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export * from './DemoboardContext' 9 | 10 | export * from './build/DemoboardBuildErrors' 11 | export * from './build/useDemoboardBuild' 12 | export * from './exporters/basicExporter' 13 | export * from './instance/DemoboardInstanceIFrame' 14 | export * from './instance/useDemoboardInstance' 15 | export * from './layout/useDemoboardLayout' 16 | export * from './project/useDemoboardProject' 17 | export * from './types' 18 | 19 | export * from './utils/normalizeReferencedPathname' 20 | export * from './utils/history' 21 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/utils/normalizeReferencedPathname.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { join, dirname } from 'path' 9 | 10 | /** 11 | * Return a path starting with `/`, unless the user specifies a full URL, 12 | * in which case we'll pass it through. 13 | */ 14 | export function normalizeReferencedPathname( 15 | pathname: string, 16 | referencedFromPathname: string = '/', 17 | ) { 18 | if (pathname.indexOf('//') || pathname.indexOf('/') === 0) { 19 | return pathname 20 | } else { 21 | return join(dirname(referencedFromPathname), pathname) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/utils/normalizeReferencedPathname.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { join, dirname } from 'path' 9 | 10 | /** 11 | * Return a path starting with `/`, unless the user specifies a full URL, 12 | * in which case we'll pass it through. 13 | */ 14 | export function normalizeReferencedPathname( 15 | pathname: string, 16 | referencedFromPathname: string = '/', 17 | ) { 18 | if (pathname.indexOf('//') >= 0 || pathname.indexOf('/') === 0) { 19 | return pathname 20 | } else { 21 | return join(dirname(referencedFromPathname), pathname) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/exporters/basicExporter.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import JSZip from 'jszip' 9 | 10 | interface DemoboardExporterOptions { 11 | transformedModules: any 12 | } 13 | 14 | export default async function demoboardExporterBasic({ 15 | transformedModules, 16 | }: DemoboardExporterOptions) { 17 | let zip = new JSZip() 18 | 19 | for (let [name, transpiledModule] of Object.entries(transformedModules)) { 20 | let originalCode = (transpiledModule as any).originalCode 21 | zip.file(name, originalCode) 22 | } 23 | 24 | return zip.generateAsync({ type: 'blob' }) 25 | } 26 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/types/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export { 9 | DemoboardWorkerBuildResult, 10 | DemoboardWorkerTransformedModule, 11 | } from '@frontarm/demoboard-worker' 12 | 13 | export * from './DemoboardBuild' 14 | export * from './DemoboardConsoleLine' 15 | export * from './DemoboardExporter' 16 | export * from './DemoboardGenerator' 17 | export * from './DemoboardGeneratedFile' 18 | export * from './DemoboardHistory' 19 | export * from './DemoboardInstance' 20 | export * from './DemoboardLayout' 21 | export * from './DemoboardPanelType' 22 | export * from './DemoboardProject' 23 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/@types/modules.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare module 'codemirror/mode/jsx/jsx' 9 | declare module 'codemirror/mode/css/css' 10 | declare module 'codemirror/mode/markdown/markdown' 11 | declare module 'codemirror/mode/htmlmixed/htmlmixed' 12 | declare module 'codemirror/keymap/sublime' 13 | declare module 'codemirror/addon/comment/comment' { 14 | const x: typeof import('codemirror/codemirror-comment') 15 | } 16 | declare module 'codemirror/addon/fold/xml-fold' 17 | declare module 'codemirror/addon/scroll/simplescrollbars' 18 | 19 | declare module 'codemirror/addon/runmode/runmode.node' 20 | -------------------------------------------------------------------------------- /packages/demoboard-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationDir": "dist/types", 5 | "downlevelIteration": true, 6 | "esModuleInterop": true, 7 | "jsx": "preserve", 8 | "target": "es5", 9 | "module": "esnext", 10 | "moduleResolution": "node", 11 | "outDir": "dist/es", 12 | "removeComments": false, 13 | "strict": true, 14 | "strictPropertyInitialization": false, 15 | "sourceMap": true, 16 | "lib": [ 17 | "es5", 18 | "es6", 19 | "dom", 20 | "dom.iterable", 21 | "es2015", 22 | "es2016", 23 | "es2017", 24 | "webworker" 25 | ] 26 | }, 27 | "exclude": [ 28 | "dist", 29 | "node_modules", 30 | "test" 31 | ] 32 | } -------------------------------------------------------------------------------- /packages/demoboard/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationDir": "dist/types", 5 | "downlevelIteration": true, 6 | "esModuleInterop": true, 7 | "jsx": "react", 8 | "target": "es5", 9 | "module": "esnext", 10 | "moduleResolution": "node", 11 | "outDir": "dist/es", 12 | "removeComments": false, 13 | "strict": true, 14 | "strictPropertyInitialization": false, 15 | "sourceMap": true, 16 | "lib": [ 17 | "es5", 18 | "es6", 19 | "dom", 20 | "dom.iterable", 21 | "es2015", 22 | "es2016", 23 | "es2017" 24 | ] 25 | }, 26 | "exclude": [ 27 | "dist", 28 | "node_modules", 29 | "test" 30 | ] 31 | } -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples", 3 | "version": "0.1.29", 4 | "private": true, 5 | "dependencies": { 6 | "@frontarm/demoboard-core": "^0.1.29", 7 | "@types/finalhandler": "^1.1.0", 8 | "@types/serve-static": "^1.13.3", 9 | "finalhandler": "^1.1.2", 10 | "serve-static": "^1.14.1", 11 | "universal-react-scripts": "3.2.1" 12 | }, 13 | "scripts": { 14 | "start": "react-scripts start", 15 | "test": "react-scripts test", 16 | "eject": "react-scripts eject" 17 | }, 18 | "eslintConfig": { 19 | "extends": "react-app" 20 | }, 21 | "browserslist": { 22 | "production": [ 23 | ">0.2%", 24 | "not dead", 25 | "not op_mini all" 26 | ], 27 | "development": [ 28 | "last 1 chrome version", 29 | "last 1 firefox version", 30 | "last 1 safari version" 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/worker/getWorker.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { DemoboardWorker } from '@frontarm/demoboard-worker' 9 | import getWorkerByFetch, { DemoboardWorkerURLs } from './getWorkerByFetch' 10 | 11 | function getWorker(urls: DemoboardWorkerURLs): DemoboardWorker { 12 | // If we're in a demoboard, instead of loading the worker again, let's 13 | // use the parent demoboard's worker. 14 | const demoboard: any = (typeof window === 'undefined' ? {} : (window as any)) 15 | .demoboard 16 | if (demoboard && demoboard.worker) { 17 | return demoboard.worker 18 | } 19 | 20 | return getWorkerByFetch(urls) 21 | } 22 | 23 | export default getWorker 24 | -------------------------------------------------------------------------------- /packages/demoboard-worker/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationDir": "dist/types", 5 | "downlevelIteration": true, 6 | "esModuleInterop": true, 7 | "jsx": "react", 8 | "target": "es5", 9 | "module": "esnext", 10 | "moduleResolution": "node", 11 | "outDir": "dist/es", 12 | "removeComments": false, 13 | "resolveJsonModule": true, 14 | "strict": true, 15 | "strictPropertyInitialization": false, 16 | "sourceMap": true, 17 | "lib": [ 18 | "es5", 19 | "es6", 20 | "webworker", 21 | "es2015", 22 | "es2016", 23 | "es2017" 24 | ] 25 | }, 26 | "exclude": [ 27 | "dist", 28 | "node_modules", 29 | "test" 30 | ] 31 | } -------------------------------------------------------------------------------- /packages/demoboard-worker-provider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationDir": "dist/types", 5 | "downlevelIteration": true, 6 | "esModuleInterop": true, 7 | "jsx": "react", 8 | "target": "es5", 9 | "module": "esnext", 10 | "moduleResolution": "node", 11 | "outDir": "dist/es", 12 | "removeComments": false, 13 | "resolveJsonModule": true, 14 | "strict": true, 15 | "strictPropertyInitialization": false, 16 | "sourceMap": true, 17 | "lib": [ 18 | "es5", 19 | "es6", 20 | "webworker", 21 | "es2015", 22 | "es2016", 23 | "es2017" 24 | ] 25 | }, 26 | "exclude": [ 27 | "dist", 28 | "node_modules", 29 | "test" 30 | ] 31 | } -------------------------------------------------------------------------------- /packages/demoboard/src/CodeMirror.conditional.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | let CodeMirror = {} 9 | 10 | if (typeof navigator !== 'undefined') { 11 | // Don't load CodeMirror when executing on the server. 12 | CodeMirror = require('codemirror') 13 | require('codemirror/addon/runmode/runmode.js') 14 | } else { 15 | const { runMode } = require('codemirror/addon/runmode/runmode.node.js') 16 | CodeMirror.runMode = runMode 17 | } 18 | 19 | require('codemirror/mode/meta') 20 | 21 | require('codemirror/mode/jsx/jsx') 22 | require('codemirror/mode/css/css') 23 | require('codemirror/mode/markdown/markdown') 24 | require('codemirror/mode/htmlmixed/htmlmixed') 25 | 26 | module.exports = CodeMirror 27 | -------------------------------------------------------------------------------- /packages/demoboard-core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationDir": "dist/types", 5 | "downlevelIteration": true, 6 | "esModuleInterop": true, 7 | "jsx": "react", 8 | "target": "es5", 9 | "module": "esnext", 10 | "moduleResolution": "node", 11 | "outDir": "dist/es", 12 | "removeComments": false, 13 | "resolveJsonModule": true, 14 | "strict": true, 15 | "strictPropertyInitialization": false, 16 | "sourceMap": true, 17 | "lib": [ 18 | "es5", 19 | "es6", 20 | "dom", 21 | "dom.iterable", 22 | "es2015", 23 | "es2016", 24 | "es2017" 25 | ] 26 | }, 27 | "exclude": [ 28 | "dist", 29 | "node_modules", 30 | "test" 31 | ] 32 | } -------------------------------------------------------------------------------- /packages/demoboard-worker/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import * as Comlink from 'comlink' 9 | import { DemoboardWorkerGlobalScope } from './types' 10 | 11 | import { fetchDependency } from './fetchDependency' 12 | import { build, clearBuildCache } from './build' 13 | 14 | declare const self: DemoboardWorkerGlobalScope 15 | 16 | const worker = { 17 | fetchDependency, 18 | build, 19 | clearBuildCache, 20 | } 21 | 22 | if ( 23 | typeof WorkerGlobalScope !== 'undefined' && 24 | self instanceof WorkerGlobalScope 25 | ) { 26 | Comlink.expose(worker, self) 27 | } 28 | 29 | export type DemoboardWorker = typeof worker 30 | 31 | export * from './types' 32 | 33 | export default worker 34 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/@types/modules.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare module '@babel/standalone' 9 | 10 | declare module 'babel-plugin-dynamic-import-node' 11 | declare module 'babel-plugin-styled-components' 12 | 13 | declare module 'postcss-modules' 14 | 15 | declare module 'sass.js/dist/sass.js' 16 | declare module 'sass.js/dist/sass.worker.js' 17 | 18 | declare module 'unist-util-visit' 19 | declare module 'hast-util-to-string' 20 | declare module 'hast-util-to-html' 21 | declare module 'refractor' 22 | 23 | declare module 'remark-emoji' 24 | declare module 'remark-images' 25 | declare module 'remark-textr' 26 | declare module 'remark-slug' 27 | declare module 'typographic-base' 28 | declare module '@mdx-js/mdx' 29 | -------------------------------------------------------------------------------- /packages/demoboard-messaging/src/replicator/arithmeticTransform.ts: -------------------------------------------------------------------------------- 1 | export enum Arithmetic { 2 | infinity, 3 | minusInfinity, 4 | minusZero 5 | } 6 | 7 | function isMinusZero(value) { 8 | return 1 / value === -Infinity 9 | } 10 | 11 | export default { 12 | type: 'Arithmetic', 13 | shouldTransform(type: any, value: any) { 14 | return ( 15 | type === 'number' && 16 | (value === Infinity || value === -Infinity || isMinusZero(value)) 17 | ) 18 | }, 19 | toSerializable(value): Arithmetic { 20 | return value === Infinity 21 | ? Arithmetic.infinity 22 | : value === -Infinity 23 | ? Arithmetic.minusInfinity 24 | : Arithmetic.minusZero 25 | }, 26 | fromSerializable(data: Arithmetic) { 27 | if (data === Arithmetic.infinity) return Infinity 28 | if (data === Arithmetic.minusInfinity) return -Infinity 29 | if (data === Arithmetic.minusZero) return -0 30 | 31 | return data 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/openTabList/openTabList.stories.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React, { useState } from 'react' 9 | import { action } from '@storybook/addon-actions' 10 | import { OpenTabList } from './openTabList' 11 | 12 | export default { 13 | title: 'OpenTabList', 14 | } 15 | 16 | export const SingleTab = () => ( 17 | 23 | ) 24 | 25 | export const TwoTabs = () => { 26 | const [selected, setSelected] = useState('/App.js') 27 | 28 | return ( 29 | 35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /packages/demoboard/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@frontarm/demoboard", 3 | "version": "0.1.29", 4 | "description": "Embeddable code editor", 5 | "author": "James K Nelson ", 6 | "license": "Apache-2.0", 7 | "main": "dist/commonjs/index.js", 8 | "module": "dist/es/index.js", 9 | "types": "dist/types/index.d.ts", 10 | "scripts": { 11 | "clean": "rimraf dist", 12 | "build": "cross-env NODE_ENV=development rollup -c", 13 | "build:production": "cross-env NODE_ENV=production rollup -c", 14 | "build:watch": "yarn run build --watch", 15 | "lint": "eslint --ext js,ts,tsx src", 16 | "prepare": "yarn run clean && yarn run build:production", 17 | "test": "jest", 18 | "test:watch": "jest --watch" 19 | }, 20 | "dependencies": { 21 | "@frontarm/demoboard-core": "^0.1.29", 22 | "@frontarm/demoboard-ui": "^0.1.29", 23 | "tslib": "1.10.0" 24 | }, 25 | "publishConfig": { 26 | "access": "public" 27 | }, 28 | "gitHead": "c95bc9be5e02686208977653cabb28e7d7b1bd75" 29 | } 30 | -------------------------------------------------------------------------------- /packages/demoboard-messaging/src/replicator/mapTransform.ts: -------------------------------------------------------------------------------- 1 | export interface MapStorage { 2 | name: string 3 | body: object 4 | proto: string 5 | } 6 | 7 | /** 8 | * Serialize a Map into JSON 9 | */ 10 | export default { 11 | type: 'Map', 12 | shouldTransform(type: any, obj: any) { 13 | return obj && obj.constructor && obj.constructor.name === 'Map' 14 | }, 15 | toSerializable(map: any): MapStorage { 16 | let body = {} 17 | 18 | map.forEach(function(value, key) { 19 | const k = typeof key == 'object' ? JSON.stringify(key) : key 20 | body[k] = value 21 | }) 22 | 23 | return { 24 | name: 'Map', 25 | body, 26 | proto: Object.getPrototypeOf(map).constructor.name 27 | } 28 | }, 29 | fromSerializable(data: MapStorage) { 30 | const { body } = data 31 | let obj = Object.assign({}, body) 32 | 33 | if (typeof data.proto === 'string') { 34 | // @ts-ignore 35 | obj.constructor = { 36 | name: data.proto 37 | } 38 | } 39 | 40 | return obj 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/findDependenciesAndTransformModules.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { transform } from '@babel/standalone' 9 | import babelPluginDetective from './babel/babel-plugin-detective' 10 | 11 | // TODO: convert this from a babel plugin to a function that walks an ast, 12 | // and then just return the ast as part of the transpiler output. 13 | 14 | export default function findDependenciesAndTransformModules(source: string) { 15 | let babelOutput = transform(source, { 16 | plugins: [ 17 | 'syntax-object-rest-spread', 18 | 'transform-modules-commonjs', 19 | babelPluginDetective, 20 | ], 21 | 22 | compact: false, 23 | sourceMaps: false, 24 | sourceType: 'module', 25 | }) 26 | 27 | return { 28 | dependencies: babelOutput.metadata.requires || [], 29 | code: babelOutput.code, 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/demoboard-runtime/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@frontarm/demoboard-runtime", 3 | "version": "0.1.29", 4 | "description": "Embeddable code editor runtime", 5 | "author": "James K Nelson ", 6 | "license": "Apache-2.0", 7 | "main": "dist/demoboard-runtime.js", 8 | "files": [ 9 | "dist/*" 10 | ], 11 | "scripts": { 12 | "clean": "rimraf dist", 13 | "build": "cross-env NODE_ENV=development rollup -c -o dist/demoboard-runtime.js", 14 | "build:production": "cross-env NODE_ENV=production rollup -c -o dist/demoboard-runtime.min.js", 15 | "build:watch": "yarn run build --watch", 16 | "prepare": "yarn run clean && yarn run build && yarn run build:production && cp src/container.html dist/container.html" 17 | }, 18 | "dependencies": { 19 | "@frontarm/demoboard-messaging": "^0.1.20", 20 | "polestar": "^0.1.2", 21 | "regenerator-runtime": "^0.12.1", 22 | "replicator": "^1.0.3" 23 | }, 24 | "publishConfig": { 25 | "access": "public" 26 | }, 27 | "gitHead": "c95bc9be5e02686208977653cabb28e7d7b1bd75" 28 | } 29 | -------------------------------------------------------------------------------- /packages/demoboard-messaging/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@frontarm/demoboard-messaging", 3 | "version": "0.1.20", 4 | "description": "Communication between demoboard runtime and host", 5 | "author": "James K Nelson ", 6 | "license": "Apache-2.0", 7 | "main": "dist/commonjs/index.js", 8 | "module": "dist/es/index.js", 9 | "types": "dist/types/index.d.ts", 10 | "scripts": { 11 | "build": "yarn build:es && yarn build:commonjs && yarn build:types", 12 | "build:commonjs": "tsc --pretty --module commonjs --outDir dist/commonjs", 13 | "build:es": "tsc --pretty --module es2015 --outDir dist/es", 14 | "build:types": "tsc --pretty --declaration --emitDeclarationOnly --outDir dist/types --isolatedModules false", 15 | "build:watch": "yarn build:es --watch", 16 | "clean": "rimraf dist", 17 | "prepare": "yarn clean && yarn run build" 18 | }, 19 | "dependencies": { 20 | "comlink": "^4.0.5", 21 | "replicator": "^1.0.3" 22 | }, 23 | "publishConfig": { 24 | "access": "public" 25 | }, 26 | "gitHead": "c95bc9be5e02686208977653cabb28e7d7b1bd75" 27 | } 28 | -------------------------------------------------------------------------------- /packages/demoboard-runtime/src/captureErrors.ts: -------------------------------------------------------------------------------- 1 | import { Host } from '@frontarm/demoboard-messaging' 2 | 3 | export function captureErrors(host: Host) { 4 | window.addEventListener('unhandledrejection', function( 5 | event: PromiseRejectionEvent, 6 | ) { 7 | let error = 8 | event.reason instanceof Error 9 | ? event.reason 10 | : new Error(event.reason || 'Unhandled Promise Rejection') 11 | 12 | host.dispatch('error', error) 13 | }) 14 | 15 | window.addEventListener('error', function(event) { 16 | let error = event.error 17 | let message = event.message || '' 18 | if (message.toLowerCase().indexOf('script error') >= 0) { 19 | // I'm setting this message here instead of in the host application, as 20 | // the error won't reliably serialize as-is, so I'll need to create a 21 | // new error object anyway. 22 | error = new Error( 23 | "An error occured in an external script, but Demoboard couldn't access it due to your browser's cross-domain security policy.", 24 | ) 25 | error.stack = null 26 | } 27 | host.dispatch('error', error) 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/npm/npmTypes.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export interface NPMDirectory { 9 | files: NPMFiles 10 | path: string 11 | type: 'directory' 12 | } 13 | 14 | export type NPMFiles = Map 15 | 16 | export interface NPMFile { 17 | contentType: string 18 | integrity: string 19 | lastModified: string 20 | path: string 21 | size: string 22 | type: 'file' 23 | } 24 | 25 | export interface NPMPackage { 26 | dependencies?: { 27 | [name: string]: string 28 | } 29 | name: string 30 | browser?: string 31 | main?: string 32 | unpkg?: string 33 | meta: NPMDirectory 34 | version: string 35 | } 36 | 37 | export type NPMResolution = 38 | | { 39 | status: 'resolved' 40 | url: string 41 | name: string 42 | browserName: string 43 | version: string 44 | pathname: string 45 | } 46 | | { 47 | status: 'notfound' 48 | url: string 49 | } 50 | -------------------------------------------------------------------------------- /packages/demoboard-runtime/src/captureAnchorClicks.ts: -------------------------------------------------------------------------------- 1 | import { Host } from '@frontarm/demoboard-messaging' 2 | 3 | /** 4 | * Capture clicks on anchors and send "navigate" 5 | */ 6 | export function captureAnchorClicks(host: Host) { 7 | function bubbleAnchorClick(e) { 8 | if (!e.defaultPrevented) { 9 | var target = e.target 10 | while (target && !(target instanceof HTMLAnchorElement)) { 11 | target = target.parentNode 12 | } 13 | var url = target.getAttribute('href') 14 | if (!/^mailto:/.test(url) && !target.target) { 15 | e.preventDefault() 16 | host.dispatch('navigate', { url }) 17 | } 18 | } 19 | } 20 | 21 | function captureWindowClick(e) { 22 | var target = e.target 23 | 24 | do { 25 | if (target instanceof HTMLAnchorElement) { 26 | window.addEventListener('click', bubbleAnchorClick, false) 27 | setTimeout(function() { 28 | window.removeEventListener('click', bubbleAnchorClick, false) 29 | }) 30 | } 31 | } while ((target = target.parentNode) != null) 32 | } 33 | 34 | window.addEventListener('click', captureWindowClick, true) 35 | } 36 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "editor.tabSize": 2, 4 | "eslint.workingDirectories": [ 5 | "./" 6 | ], 7 | "eslint.validate": [ 8 | "javascript", 9 | "javascriptreact", 10 | "typescript", 11 | "typescriptreact" 12 | ], 13 | "typescript.tsdk": "node_modules/typescript/lib", 14 | "[markdown]": { 15 | "editor.formatOnSave": false 16 | }, 17 | "[json]": { 18 | "editor.formatOnSave": false 19 | }, 20 | "psi-header.variables": [ 21 | ["company", "Seven Stripes Kabushiki Kaisha"], 22 | ["projectCreationYear", "2019"], 23 | ], 24 | "psi-header.changes-tracking": { 25 | "autoHeader": "off", 26 | "include": [ 27 | "javascript", 28 | "javascriptreact", 29 | "typescript", 30 | "typescriptreact" 31 | ] 32 | }, 33 | "psi-header.templates": [ 34 | { 35 | "language": "*", 36 | "template": [ 37 | "Copyright <> <>", 38 | "", 39 | "This source code is licensed under the Apache License, Version 2.0, found", 40 | "in the LICENSE file in the root directory of this source tree.", 41 | ] 42 | } 43 | ] 44 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Demoboard 2 | ========= 3 | 4 | An embeddable live editor, with every package on npm. 5 | 6 | 7 | Getting Started 8 | --------------- 9 | 10 | Demoboard can be embedded within any app built with Webpack -- including apps built with Create React App, Gatsby, Next.js, etc. 11 | 12 | ```bash 13 | yarn add @frontarm/demoboard 14 | ``` 15 | 16 | ```js 17 | import React from 'react' 18 | import { Demoboard, DemoboardGlobalStyles } from '@frontarm/demoboard' 19 | 20 | const initialSources = { 21 | '/index.js': ` 22 | import React from 'react@experimental' 23 | import ReactDOM from 'react-dom@experimental' 24 | 25 | const root = ReactDOM.createRoot( 26 | document.getElementById('root') 27 | ) 28 | root.render(

Hello, world!

)`, 29 | } 30 | 31 | const App = () => { 32 | return ( 33 | <> 34 | 35 | 42 | 43 | ) 44 | } 45 | ``` 46 | 47 | 48 | 49 | Contributing 50 | ------------ 51 | 52 | ```bash 53 | yarn install 54 | yarn build 55 | cd examples 56 | yarn start 57 | ``` -------------------------------------------------------------------------------- /packages/demoboard-worker/src/types/DemoboardWorkerBuild.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { 9 | DemoboardBuildError, 10 | DemoboardTransformError, 11 | } from '@frontarm/demoboard-core/src/build/DemoboardBuildErrors' 12 | import { DemoboardWorkerTransformedModule } from './DemoboardWorkerTransformedModule' 13 | import { DemoboardWorkerTransformFetchOptions } from './DemoboardWorkerTransformFetchOptions' 14 | 15 | export interface DemoboardWorkerBuildOptions { 16 | id: string 17 | sources: { [filename: string]: string } 18 | entryPathname: string 19 | rules?: DemoboardWorkerBuildRule[] 20 | transformFetchOptions?: DemoboardWorkerTransformFetchOptions 21 | } 22 | 23 | export interface DemoboardWorkerBuildRule { 24 | test: RegExp 25 | transform: string 26 | } 27 | 28 | export interface DemoboardWorkerBuildResult { 29 | transformedModules: { 30 | [name: string]: DemoboardWorkerTransformedModule 31 | } 32 | shouldRegenerateHTML: boolean 33 | error: null | DemoboardBuildError | DemoboardTransformError 34 | } 35 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/npm/nodeBrowserModules.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export default { 9 | child_process: null, 10 | cluster: null, 11 | console: 'console-browserify', 12 | constants: 'constants-browserify', 13 | crypto: 'crypto-browserify', 14 | dgram: null, 15 | dns: null, 16 | domain: 'domain-browser', 17 | fs: null, 18 | http: 'stream-http', 19 | https: 'https-browserify', 20 | module: null, 21 | net: null, 22 | os: 'os-browserify', 23 | path: 'path-browserify', 24 | querystring: 'querystring-es3', 25 | readline: null, 26 | repl: null, 27 | stream: 'stream-browserify', 28 | _stream_duplex: 'readable-stream', 29 | _stream_passthrough: 'readable-stream', 30 | _stream_readable: 'readable-stream', 31 | _stream_transform: 'readable-stream', 32 | _stream_writable: 'readable-stream', 33 | sys: 'util', 34 | timers: 'timers-browserify', 35 | tls: null, 36 | tty: 'tty-browserify', 37 | vm: 'vm-browserify', 38 | zlib: 'browserify-zlib', 39 | } as { 40 | [name: string]: null | string 41 | } 42 | -------------------------------------------------------------------------------- /packages/demoboard-worker-provider/src/DemoboardWorkerProvider.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import * as Comlink from 'comlink' 9 | import * as React from 'react' 10 | import { DemoboardWorkerContext } from '@frontarm/demoboard-core' 11 | import { DemoboardWorker as IDemoboardWorker } from '@frontarm/demoboard-worker' 12 | 13 | function createWorker() { 14 | // eslint-disable-next-line import/no-webpack-loader-syntax 15 | let mod = require('worker-loader!@frontarm/demoboard-worker') 16 | const DemoboardWorker = new mod() 17 | return Comlink.wrap(DemoboardWorker) 18 | } 19 | 20 | // Leave the workers empty on environments where workers aren't supported, 21 | // e.g. on Node 22 | const worker: IDemoboardWorker = 23 | typeof Worker === 'undefined' ? ({} as any) : createWorker() 24 | 25 | const DemoboardWorkerProvider: React.FC = ({ children }) => { 26 | return ( 27 | 31 | {children} 32 | 33 | ) 34 | } 35 | 36 | export default DemoboardWorkerProvider 37 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/types/DemoboardInstance.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { DemoboardConsoleLine } from './DemoboardConsoleLine' 9 | import { DemoboardHistoryLocation } from './DemoboardHistory' 10 | 11 | export type DemoboardInstanceStatus = 12 | | 'initializing' // Output before the frame has emitted the `init` event 13 | | 'active' // The frame is loaded with the current build 14 | | 'updating' // The frame is loaded, but is out of date 15 | | 'error' // Something went wrong while loading the build within the frame 16 | | 'empty' // There's nothing to render (also used in case of build errors) 17 | | 'external' // The frame's location points to an external URL 18 | 19 | export interface DemoboardInstance { 20 | // This is a map, as it allows us to overwrite previous console lines if 21 | // they're updated with the same id (e.g. for promise results.) 22 | consoleLines: Map 23 | 24 | error?: any 25 | 26 | location: DemoboardHistoryLocation 27 | 28 | ref: (node: HTMLIFrameElement) => void 29 | 30 | status: DemoboardInstanceStatus 31 | } 32 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/types/DemoboardHistory.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export interface DemoboardHistory { 9 | locations: DemoboardHistoryLocation[] 10 | index: number 11 | lastRenderedIndex: number 12 | } 13 | 14 | export interface DemoboardHistoryLocation { 15 | pathname: string 16 | search: string | null 17 | hash: string | null 18 | 19 | /** 20 | * State must be stringified to not confuse automerge. 21 | */ 22 | stringifiedState: string | null 23 | 24 | /** 25 | * Incremented each time refresh is called 26 | */ 27 | refreshCount: number 28 | 29 | /** 30 | * Indicates whether the URL doesn't need to be rendered, as it was added 31 | * by a call to pushState/replaceState from within the iframe. 32 | */ 33 | skipRender: boolean 34 | 35 | /** 36 | * Indicates whether the URL doesn't need to be rendered, as it originated 37 | * from a going back from a skipRender item, or forward to a skipRender item 38 | */ 39 | popState: boolean 40 | 41 | /** 42 | * A URI string that can be displayed in the address bar 43 | */ 44 | uri: string 45 | } 46 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/navigationBar/navigationBar.stories.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react' 9 | import { action } from '@storybook/addon-actions' 10 | import { NavigationBar } from './navigationBar' 11 | 12 | export default { 13 | title: 'NavigationBar', 14 | } 15 | 16 | export const noHistory = () => ( 17 | 27 | ) 28 | 29 | export const hasHistory = () => ( 30 | 40 | ) 41 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/utils/Deferred.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2005-2019 Mozilla and individual contributors. 3 | * https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred 4 | */ 5 | 6 | export default class Deferred { 7 | /* A method to resolve the associated Promise with the value passed. 8 | * If the promise is already settled it does nothing. 9 | * 10 | * @param {anything} value : This value is used to resolve the promise 11 | * If the value is a Promise then the associated promise assumes the state 12 | * of Promise passed as value. 13 | */ 14 | resolve: (value: T) => void = undefined as any 15 | 16 | /* A method to reject the assocaited Promise with the value passed. 17 | * If the promise is already settled it does nothing. 18 | * 19 | * @param {anything} reason: The reason for the rejection of the Promise. 20 | * Generally its an Error object. If however a Promise is passed, then the Promise 21 | * itself will be the reason for rejection no matter the state of the Promise. 22 | */ 23 | reject: (reason: any) => void = undefined as any 24 | 25 | /* A newly created Promise object. 26 | * Initially in pending state. 27 | */ 28 | promise = new Promise((resolve: any, reject: any) => { 29 | this.resolve = resolve 30 | this.reject = reject 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/transforms/sass/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import register from '../register' 9 | import workerURL from 'sass.js/dist/sass.worker.js' 10 | 11 | let sass: any 12 | 13 | register( 14 | 'sass', 15 | ({ errors }) => 16 | async function transpileSass({ originalSource, pathname }) { 17 | const { default: Sass } = await import('sass.js/dist/sass.js') 18 | 19 | if (!sass) { 20 | sass = new Sass(workerURL) 21 | } 22 | 23 | return await new Promise((resolve, reject) => { 24 | sass.compile(originalSource, (result: any) => { 25 | if (result.status === 1) { 26 | reject( 27 | new errors.DemoboardTransformError({ 28 | sourceFile: pathname, 29 | message: result.message, 30 | lineNumber: result.line, 31 | }), 32 | ) 33 | } else { 34 | resolve({ 35 | transformedSource: 'module.exports = {}', 36 | originalSource: originalSource, 37 | map: result.map, 38 | pathname, 39 | dependencies: [], 40 | css: result.text, 41 | }) 42 | } 43 | }) 44 | }) 45 | }, 46 | ) 47 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/generators/indexHTMLGenerator.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { DemoboardGenerator } from '../types' 9 | 10 | const indexHTMLGenerator: DemoboardGenerator = ({ 11 | context = { 12 | title: 'Untitled App', 13 | }, 14 | pathnames, 15 | }) => { 16 | let scripts = '' 17 | let mainIndex = pathnames.findIndex(pathname => 18 | /^\/(index|main).m?jsx?$/.test(pathname), 19 | ) 20 | 21 | if (mainIndex >= 0) { 22 | scripts = ` ` 25 | } else { 26 | scripts = pathnames 27 | .filter(name => /\.jsx?$/.test(name)) 28 | .map(name => ` `) 29 | .join('\n') 30 | } 31 | 32 | return ` 33 | 34 | 35 | ${context && context.title} 36 | ${pathnames 37 | .filter( 38 | name => 39 | /\.s?css$/.test(name) && 40 | !/\.module\.s?css$/.test(name) && 41 | name !== '/markdown.css', 42 | ) 43 | .map(name => ` `) 44 | .join('\n')} 45 | 46 | 47 |
48 | ${scripts} 49 | 50 | ` 51 | } 52 | 53 | export default indexHTMLGenerator 54 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/transforms/fetchTransformFromNetwork.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { 9 | DemoboardWorkerGlobalScope, 10 | DemoboardWorkerTransformFetchOptions, 11 | } from '../types' 12 | import { DemoboardFetchFailedError } from '../DemoboardBuildErrors' 13 | 14 | declare const self: DemoboardWorkerGlobalScope 15 | 16 | export const defaultTransformFetchOptions: DemoboardWorkerTransformFetchOptions = { 17 | credentials: 'same-origin' as const, 18 | } 19 | 20 | export async function fetchTransformFromNetwork( 21 | name: string, 22 | fetchOptions: DemoboardWorkerTransformFetchOptions = defaultTransformFetchOptions, 23 | ): Promise { 24 | const { baseURL, overrideURLs = {}, ...options } = fetchOptions 25 | const transformURL = overrideURLs[name] 26 | const urlToFetch = transformURL || baseURL + name + '.js' 27 | const res = await fetch(urlToFetch, options) 28 | if (!res.ok) { 29 | throw new DemoboardFetchFailedError({ 30 | url: urlToFetch, 31 | sourceFile: name, 32 | status: res.status + ' ' + res.statusText, 33 | }) 34 | } 35 | const source = await res.text() 36 | const blob = new Blob([source], { type: 'text/javascript' }) 37 | const workerURL = URL.createObjectURL(blob) 38 | 39 | self.importScripts(workerURL) 40 | } 41 | -------------------------------------------------------------------------------- /packages/demoboard-ui/.storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = ({ config }) => { 2 | // Remove file-loader, as it interferes with svgr, and this library 3 | // shouldn't export any assets anyway 4 | let existingSVGIndex = config.module.rules.findIndex(x => 5 | x.test.toString().includes('svg'), 6 | ) 7 | if (existingSVGIndex !== -1) { 8 | config.module.rules.splice(existingSVGIndex, 1) 9 | } 10 | 11 | // Add svgr at the top 12 | config.module.rules.unshift({ 13 | test: /\.svg$/, 14 | exclude: /(node_modules)/, 15 | use: ['@svgr/webpack'], 16 | }) 17 | 18 | config.module.rules.push({ 19 | test: /\.(ts|tsx)$/, 20 | exclude: /(node_modules)/, 21 | use: [ 22 | { 23 | loader: require.resolve('babel-loader'), 24 | options: { 25 | presets: [require.resolve('@babel/preset-react')], 26 | plugins: [ 27 | require.resolve('@babel/plugin-syntax-dynamic-import'), 28 | require.resolve('babel-plugin-styled-components'), 29 | require.resolve('@babel/plugin-proposal-export-default-from'), 30 | ], 31 | }, 32 | }, 33 | { 34 | loader: require.resolve('awesome-typescript-loader'), 35 | }, 36 | { 37 | loader: require.resolve('react-docgen-typescript-loader'), 38 | }, 39 | ], 40 | }) 41 | config.resolve.extensions.push('.ts', '.tsx') 42 | 43 | config.node = { 44 | fs: 'empty', 45 | } 46 | 47 | return config 48 | } 49 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/utils/shallowCompare.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | function shallowCompare(a: any, b: any) { 9 | var aIsNull = a === null 10 | var bIsNull = b === null 11 | 12 | if (aIsNull !== bIsNull) return false 13 | 14 | var aIsArray = Array.isArray(a) 15 | var bIsArray = Array.isArray(b) 16 | 17 | if (aIsArray !== bIsArray) return false 18 | 19 | var aTypeof = typeof a 20 | var bTypeof = typeof b 21 | 22 | if (aTypeof !== bTypeof) return false 23 | if (flat(aTypeof)) return a === b 24 | 25 | return aIsArray ? shallowArray(a, b) : shallowObject(a, b) 26 | } 27 | 28 | function shallowArray(a: any, b: any) { 29 | var l = a.length 30 | if (l !== b.length) return false 31 | 32 | for (var i = 0; i < l; i++) { 33 | if (a[i] !== b[i]) return false 34 | } 35 | 36 | return true 37 | } 38 | 39 | function shallowObject(a: any, b: any) { 40 | var ka = 0 41 | var kb = 0 42 | 43 | for (let key in a) { 44 | if (a.hasOwnProperty(key) && a[key] !== b[key]) return false 45 | 46 | ka++ 47 | } 48 | 49 | for (let key in b) { 50 | if (b.hasOwnProperty(key)) kb++ 51 | } 52 | 53 | return ka === kb 54 | } 55 | 56 | function flat(type: any) { 57 | return type !== 'function' && type !== 'object' 58 | } 59 | 60 | export default shallowCompare 61 | -------------------------------------------------------------------------------- /packages/demoboard-messaging/src/replicator/functionTransform.ts: -------------------------------------------------------------------------------- 1 | export interface FunctionStorage { 2 | name: string 3 | body: string 4 | proto: string 5 | } 6 | 7 | /** 8 | * Serialize a function into JSON 9 | */ 10 | export default { 11 | type: 'Function', 12 | shouldTransform(type: any, obj: any) { 13 | return typeof obj === 'function' 14 | }, 15 | toSerializable(func: Function): FunctionStorage { 16 | let body = '' 17 | try { 18 | body = func 19 | .toString() 20 | .substring(body.indexOf('{') + 1, body.lastIndexOf('}')) 21 | } catch (e) {} 22 | 23 | return { 24 | name: func.name, 25 | body, 26 | proto: Object.getPrototypeOf(func).constructor.name 27 | } 28 | }, 29 | fromSerializable(data: FunctionStorage) { 30 | try { 31 | const tempFunc = function() {} 32 | 33 | if (typeof data.name === 'string') { 34 | Object.defineProperty(tempFunc, 'name', { 35 | value: data.name, 36 | writable: false 37 | }) 38 | } 39 | 40 | if (typeof data.body === 'string') { 41 | Object.defineProperty(tempFunc, 'body', { 42 | value: data.body, 43 | writable: false 44 | }) 45 | } 46 | 47 | if (typeof data.proto === 'string') { 48 | // @ts-ignore 49 | tempFunc.constructor = { 50 | name: data.proto 51 | } 52 | } 53 | 54 | return tempFunc 55 | } catch (e) { 56 | return data 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/demoboard-worker-provider/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@frontarm/demoboard-worker-provider", 3 | "version": "0.1.29", 4 | "description": "Embeddable code editor", 5 | "author": "James K Nelson ", 6 | "license": "Apache-2.0", 7 | "module": "dist/es/DemoboardWorkerProvider.js", 8 | "types": "dist/types/DemoboardWorkerProvider.d.ts", 9 | "scripts": { 10 | "clean": "rimraf dist/**", 11 | "build": "cross-env NODE_ENV=development rollup -c", 12 | "build:production": "cross-env NODE_ENV=production rollup -c", 13 | "build:watch": "yarn run build --watch", 14 | "lint": "eslint --ext js,ts,tsx src", 15 | "prepare": "yarn run clean && yarn run build:production", 16 | "test": "jest", 17 | "test:watch": "jest --watch" 18 | }, 19 | "dependencies": { 20 | "@frontarm/demoboard-core": "^0.1.29", 21 | "@frontarm/demoboard-worker": "^0.1.26", 22 | "comlink": "^4.0.5", 23 | "tslib": "1.10.0", 24 | "worker-loader": "^2.0.0" 25 | }, 26 | "devDependencies": { 27 | "file-loader": "^2.0.0" 28 | }, 29 | "peerDependencies": { 30 | "@mdx-js/mdx": "^1.4.5", 31 | "@types/codemirror": "^0.0.77", 32 | "@types/exenv": "^1.2.0", 33 | "@types/jszip": "^3.1.6", 34 | "@types/lru-cache": "^5.1.0", 35 | "@types/react": "^16.9.0", 36 | "@types/react-dom": "^16.9.0", 37 | "react": "^16.8.6", 38 | "react-dom": "^16.8.6" 39 | }, 40 | "publishConfig": { 41 | "access": "public" 42 | }, 43 | "gitHead": "c95bc9be5e02686208977653cabb28e7d7b1bd75" 44 | } 45 | -------------------------------------------------------------------------------- /packages/demoboard-runtime/rollup.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This is based on the rollup config from Redux 3 | * Copyright (c) 2015-present Dan Abramov 4 | */ 5 | 6 | import commonjs from 'rollup-plugin-commonjs' 7 | import nodeBuiltins from 'rollup-plugin-node-builtins' 8 | import nodeResolve from 'rollup-plugin-node-resolve' 9 | import replace from 'rollup-plugin-replace' 10 | import { terser } from 'rollup-plugin-terser' 11 | import typescript from 'rollup-plugin-typescript2' 12 | 13 | const { version } = require('./package.json') 14 | 15 | const env = process.env.NODE_ENV 16 | const config = { 17 | input: 'src/index.ts', 18 | output: { 19 | format: 'umd', 20 | name: 'setupDemoboardRuntime', 21 | sourcemap: true, 22 | footer: `\n//# sourceURL=frontarm.com`, 23 | }, 24 | onwarn: function(warning) { 25 | // Suppress warning caused by TypeScript classes using "this" 26 | // https://github.com/rollup/rollup/wiki/Troubleshooting#this-is-undefined 27 | if (warning.code === 'THIS_IS_UNDEFINED') { 28 | return 29 | } 30 | console.error(warning.message) 31 | }, 32 | plugins: [ 33 | nodeBuiltins(), 34 | nodeResolve({ 35 | mainFields: ['module', 'main', 'jsnext:main'], 36 | }), 37 | commonjs(), 38 | replace({ 39 | 'process.env.NODE_ENV': JSON.stringify(env), 40 | }), 41 | typescript({ 42 | abortOnError: env === 'production', 43 | module: 'ESNext', 44 | }), 45 | ], 46 | } 47 | 48 | if (env === 'production') { 49 | config.plugins.push(terser()) 50 | } 51 | 52 | export default config 53 | -------------------------------------------------------------------------------- /packages/demoboard-worker-provider/rollup.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import commonjs from 'rollup-plugin-commonjs' 9 | import json from 'rollup-plugin-json' 10 | import nodeBuiltins from 'rollup-plugin-node-builtins' 11 | import nodeResolve from 'rollup-plugin-node-resolve' 12 | import replace from 'rollup-plugin-replace' 13 | import { terser } from 'rollup-plugin-terser' 14 | import typescript from 'rollup-plugin-typescript2' 15 | 16 | const env = process.env.NODE_ENV 17 | const config = { 18 | input: 'src/DemoboardWorkerProvider.tsx', 19 | 20 | output: [ 21 | { 22 | dir: 'dist/es', 23 | format: 'es', 24 | sourcemap: true, 25 | }, 26 | ], 27 | 28 | external(id) { 29 | if (/^\w/.test(id) || id[0] === '@' || id.indexOf('worker-loader!') === 0) { 30 | return true 31 | } 32 | }, 33 | 34 | plugins: [ 35 | nodeBuiltins(), 36 | nodeResolve({ 37 | mainFields: ['module', 'main', 'jsnext:main'], 38 | }), 39 | commonjs(), 40 | json(), 41 | replace({ 42 | 'process.env.NODE_ENV': JSON.stringify(env), 43 | }), 44 | typescript({ 45 | abortOnError: env === 'production', 46 | module: 'ESNext', 47 | useTsconfigDeclarationDir: true, 48 | }), 49 | ], 50 | } 51 | 52 | if (env === 'production') { 53 | config.plugins.push(terser()) 54 | } 55 | 56 | export default config 57 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/demoboardView.stories.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { 9 | useDemoboardInstance, 10 | useDemoboardProject, 11 | } from '@frontarm/demoboard-core' 12 | import React from 'react' 13 | import { action } from '@storybook/addon-actions' 14 | import { DemoboardView, DemoboardViewGlobalStyles } from './DemoboardView' 15 | 16 | export default { 17 | title: 'DemoboardView', 18 | } 19 | 20 | const rawExample = ` 21 | const element = document.createElement('h1') 22 | element.innerHTML = \` 23 | Hello, world!
24 | \`.repeat(10) 25 | document.getElementById('root').appendChild(element) 26 | ` 27 | 28 | export const Loading = () => { 29 | const project = useDemoboardProject({ 30 | config: { 31 | initialSources: { 32 | '/index.js': rawExample, 33 | }, 34 | }, 35 | }) 36 | const instance = useDemoboardInstance({ 37 | build: null, 38 | history: project.state.view.history, 39 | pause: false, 40 | onChangeHistory: value => { 41 | project.dispatch({ 42 | type: 'history.set', 43 | history: value, 44 | }) 45 | }, 46 | }) 47 | 48 | return ( 49 | <> 50 | 51 | 59 | 60 | ) 61 | } 62 | -------------------------------------------------------------------------------- /packages/demoboard-core/rollup.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import commonjs from 'rollup-plugin-commonjs' 9 | import json from 'rollup-plugin-json' 10 | import nodeBuiltins from 'rollup-plugin-node-builtins' 11 | import nodeResolve from 'rollup-plugin-node-resolve' 12 | import replace from 'rollup-plugin-replace' 13 | import { terser } from 'rollup-plugin-terser' 14 | import typescript from 'rollup-plugin-typescript2' 15 | 16 | const env = process.env.NODE_ENV 17 | const config = { 18 | input: 'src/index.ts', 19 | 20 | output: [ 21 | { 22 | dir: 'dist/es', 23 | format: 'esm', 24 | sourcemap: true, 25 | }, 26 | { 27 | dir: 'dist/commonjs', 28 | format: 'cjs', 29 | sourcemap: true, 30 | }, 31 | ], 32 | 33 | external(id) { 34 | if (/^\w/.test(id) || id[0] === '@' || id.indexOf('file-loader!') === 0) { 35 | return true 36 | } 37 | }, 38 | 39 | plugins: [ 40 | nodeBuiltins(), 41 | nodeResolve({ 42 | mainFields: ['module', 'main', 'jsnext:main'], 43 | }), 44 | commonjs(), 45 | json(), 46 | replace({ 47 | 'process.env.NODE_ENV': JSON.stringify(env), 48 | }), 49 | typescript({ 50 | abortOnError: env === 'production', 51 | module: 'ESNext', 52 | useTsconfigDeclarationDir: true, 53 | }), 54 | ], 55 | } 56 | 57 | if (env === 'production') { 58 | config.plugins.push(terser()) 59 | } 60 | 61 | export default config 62 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/icons/components.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export { default as add } from './icomoon/SVG/add.svg' 9 | export { default as back } from './icomoon/SVG/back.svg' 10 | export { default as check } from './icomoon/SVG/check.svg' 11 | export { default as close } from './icomoon/SVG/close.svg' 12 | export { default as code } from './icomoon/SVG/code.svg' 13 | export { default as console } from './icomoon/SVG/console.svg' 14 | export { default as delete_outline } from './icomoon/SVG/delete_outline.svg' 15 | export { default as delete } from './icomoon/SVG/delete.svg' 16 | export { default as download } from './icomoon/SVG/download.svg' 17 | export { default as edit } from './icomoon/SVG/edit.svg' 18 | export { default as fork } from './icomoon/SVG/fork.svg' 19 | export { default as forward } from './icomoon/SVG/forward.svg' 20 | export { default as key } from './icomoon/SVG/key.svg' 21 | export { default as lock_closed } from './icomoon/SVG/lock_closed.svg' 22 | export { default as lock_outline } from './icomoon/SVG/lock_outline.svg' 23 | export { default as lock } from './icomoon/SVG/lock.svg' 24 | export { default as menu } from './icomoon/SVG/menu.svg' 25 | export { default as more } from './icomoon/SVG/more.svg' 26 | export { default as play } from './icomoon/SVG/play.svg' 27 | export { default as refresh } from './icomoon/SVG/refresh.svg' 28 | export { default as share } from './icomoon/SVG/share.svg' 29 | export { default as undo } from './icomoon/SVG/undo.svg' 30 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/layout/useDemoboardLayout.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { DemoboardProjectState } from '../types' 9 | 10 | export interface UseDemoboardLayoutOptions { 11 | /** 12 | * The width of the Demoboard container. Note that this may depend on the 13 | * styles of the demoboard itself, so you should *not* set the width 14 | * based on this variable. 15 | */ 16 | containerWidth: number 17 | 18 | /** 19 | * The width of the browser's client area 20 | */ 21 | clientWidth: number 22 | 23 | /** 24 | * The height of the browser's client area 25 | */ 26 | clientHeight: number 27 | 28 | /** 29 | * Whether the left panel should open in a maximized state by default. 30 | * Defaults to false. 31 | */ 32 | defaultLeftPanelMaximized?: boolean 33 | 34 | /** 35 | * Whether the right panel should open in a maximized state by default. 36 | * Defaults to false. 37 | */ 38 | defaultRightPanelMaximized?: boolean 39 | 40 | /** 41 | * If specified, this will be used to set the default height of an embedded 42 | * demoboard, in number of lines. 43 | */ 44 | defaultSizeInLines?: number 45 | 46 | /** 47 | * Indicates whether the layout should take up the full browser viewport. 48 | */ 49 | fullScreen?: boolean 50 | 51 | /** 52 | * The demoboard project which this hook is laying out. The sources, 53 | * panel priorities, and actions will be used. 54 | */ 55 | project: DemoboardProjectState 56 | } 57 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/transforms/cssModule/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import postcss from 'postcss' 9 | import postcssModules from 'postcss-modules' 10 | import register from '../register' 11 | 12 | register( 13 | 'cssModule', 14 | ({ errors }) => 15 | async function transpileCSSModule({ css, originalSource, pathname }) { 16 | if (css === null) { 17 | return { 18 | transformedSource: `module.exports = {}`, 19 | originalSource, 20 | map: null, 21 | pathname, 22 | dependencies: [], 23 | prettyCode: '', 24 | css: '', 25 | } 26 | } 27 | 28 | let jsonString = '{}' 29 | let plugins = [ 30 | postcssModules({ 31 | getJSON: function(cssFileName: any, json: any, outputFileName: any) { 32 | jsonString = JSON.stringify(json) 33 | }, 34 | }), 35 | ] 36 | 37 | try { 38 | let result = await postcss(plugins).process(css) 39 | 40 | return { 41 | transformedSource: `module.exports = ` + jsonString, 42 | originalSource, 43 | map: result.map, 44 | pathname, 45 | dependencies: [], 46 | prettyCode: '', 47 | css: result.css, 48 | } 49 | } catch (error) { 50 | throw new errors.DemoboardTransformError({ 51 | sourceFile: pathname, 52 | message: error.message, 53 | }) 54 | } 55 | }, 56 | ) 57 | -------------------------------------------------------------------------------- /packages/demoboard-runtime/src/container.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demoboard Container 5 | 6 | 7 |
8 | 14 |
15 | 56 | 57 | -------------------------------------------------------------------------------- /packages/demoboard-messaging/src/replicator/htmlTransform.ts: -------------------------------------------------------------------------------- 1 | // Use this to serialize/deserialize elements, without allowing them access to 2 | // the original DOM. However, leave it empty on the server, as 3 | const sandbox: Document = 4 | typeof document === 'undefined' 5 | ? ({} as any) 6 | : document.implementation.createHTMLDocument('sandbox') 7 | 8 | export interface HTMLStorage { 9 | tagName: string 10 | attributes: { 11 | [attribute: string]: string 12 | } 13 | innerHTML: string 14 | } 15 | 16 | function objectifyAttributes(element: any) { 17 | const data = {} 18 | for (let attribute of element.attributes) { 19 | data[attribute.name] = attribute.value 20 | } 21 | return data 22 | } 23 | 24 | /** 25 | * Serialize a HTML element into JSON 26 | */ 27 | export default { 28 | type: 'HTMLElement', 29 | shouldTransform(type: any, obj: any) { 30 | return ( 31 | obj && 32 | obj.children && 33 | typeof obj.innerHTML === 'string' && 34 | typeof obj.tagName === 'string' 35 | ) 36 | }, 37 | toSerializable(element: HTMLElement) { 38 | return { 39 | tagName: element.tagName.toLowerCase(), 40 | attributes: objectifyAttributes(element), 41 | innerHTML: element.innerHTML, 42 | } as HTMLStorage 43 | }, 44 | fromSerializable(data: HTMLStorage) { 45 | try { 46 | const element = sandbox.createElement(data.tagName) as HTMLElement 47 | element.innerHTML = data.innerHTML 48 | for (let attribute of Object.keys(data.attributes)) { 49 | try { 50 | element.setAttribute(attribute, data.attributes[attribute]) 51 | } catch (e) {} 52 | } 53 | return element 54 | } catch (e) { 55 | return data 56 | } 57 | }, 58 | } 59 | -------------------------------------------------------------------------------- /packages/demoboard-messaging/src/replicator/promiseTransform.ts: -------------------------------------------------------------------------------- 1 | export interface SerializedPromise { 2 | outcomeType?: 'fulfilled' | 'rejected', 3 | outcome?: any, 4 | } 5 | 6 | let promiseOutcomes = new WeakMap, SerializedPromise>() 7 | let pendingPromises = new Set>() 8 | let outcomeStoredPromises = [] as Promise[] 9 | 10 | function setOutcome(promise: Promise, type: 'fulfilled' | 'rejected', value: any) { 11 | pendingPromises.delete(promise) 12 | promiseOutcomes.set(promise, { 13 | outcomeType: type, 14 | outcome: value 15 | }) 16 | } 17 | 18 | /** 19 | * Serialize a Map into JSON 20 | */ 21 | export default { 22 | type: 'Promise', 23 | 24 | // After doing an encode, the encoder should listen for outcomes on all of 25 | // these promises, and perform a re-encode once they settle. 26 | outcomeStoredPromises: outcomeStoredPromises, 27 | 28 | shouldTransform(type: any, obj: any) { 29 | return obj && obj instanceof Promise 30 | }, 31 | toSerializable(promise: Promise): SerializedPromise { 32 | let outcome = promiseOutcomes.get(promise) 33 | if (outcome) { 34 | return outcome 35 | } 36 | if (!pendingPromises.has(promise)) { 37 | pendingPromises.add(promise) 38 | outcomeStoredPromises.push( 39 | promise.then( 40 | setOutcome.bind(null, promise, 'fulfilled'), 41 | setOutcome.bind(null, promise, 'rejected'), 42 | ) 43 | ) 44 | } 45 | }, 46 | fromSerializable(data: SerializedPromise) { 47 | // TODO: give promises ids, and use them to deserilize to a promise 48 | // that resolves if a future promise is deserialized with the same 49 | // id and an outcome. 50 | return Object.assign({ type: '[[Promise]]' }, data) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/tooltip/tooltip.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react' 9 | import styled from 'styled-components' 10 | import { 11 | Tooltip as ReakitTooltip, 12 | TooltipReference, 13 | TooltipReferenceProps, 14 | TooltipState, 15 | useTooltipState, 16 | } from 'reakit/Tooltip' 17 | import { colors, fonts, radii } from '../../constants' 18 | 19 | const StyledTooltip = styled(ReakitTooltip)` 20 | background-color: ${colors.black}; 21 | border-radius: ${radii.small}; 22 | color: ${colors.lighterGrey}; 23 | font-family: ${fonts.sansSerif}; 24 | font-size: 11px; 25 | padding: 4px; 26 | margin-top: 0; 27 | z-index: 99999; 28 | ` 29 | 30 | export type TooltipPlacement = TooltipState['placement'] 31 | 32 | export interface TooltipProps 33 | extends Omit, 'children'> { 34 | children: TooltipReferenceProps['children'] 35 | gutter?: number 36 | label: string | null 37 | placement?: TooltipState['placement'] 38 | testID?: string 39 | } 40 | 41 | export function Tooltip({ 42 | children, 43 | gutter = 6, 44 | testID, 45 | label, 46 | placement = 'bottom', 47 | ...rest 48 | }: TooltipProps) { 49 | const tooltipState = useTooltipState({ 50 | gutter, 51 | placement, 52 | }) 53 | 54 | return ( 55 | <> 56 | {children} 57 | {label && ( 58 | 59 | {label} 60 | 61 | )} 62 | 63 | ) 64 | } 65 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/layout/ClientDimensions.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import ExecutionEnvironment from 'exenv' 9 | import * as React from 'react' 10 | 11 | // export interface ClientDimensionsProps { 12 | // children: (props: ClientDimensionsState) => React.ReactNode 13 | // defaultWidth?: number 14 | // defaultHeight?: number 15 | // } 16 | 17 | // export interface ClientDimensionsState { 18 | // width: number 19 | // height: number 20 | // } 21 | 22 | // export class ClientDimensions extends React.Component< 23 | // ClientDimensionsProps, 24 | // ClientDimensionsState 25 | // > { 26 | // static defaultProps = { 27 | // defaultWidth: 1000, 28 | // defaultHeight: 700, 29 | // } 30 | 31 | // constructor(props) { 32 | // super(props) 33 | 34 | // this.state = ExecutionEnvironment.canUseDOM 35 | // ? { 36 | // width: document.body.clientWidth, 37 | // height: document.body.clientHeight, 38 | // } 39 | // : { width: props.defaultWidth, height: props.defaultHeight } 40 | // } 41 | 42 | // componentDidMount() { 43 | // if (ExecutionEnvironment.canUseDOM) { 44 | // window.addEventListener('resize', this.handleResize, true) 45 | // } 46 | // } 47 | 48 | // componentWillUnmount() { 49 | // window.removeEventListener('resize', this.handleResize, true) 50 | // } 51 | 52 | // handleResize = () => { 53 | // this.setState({ 54 | // width: document.body.clientWidth, 55 | // height: document.body.clientHeight, 56 | // }) 57 | // } 58 | 59 | // render() { 60 | // return this.props.children(this.state) 61 | // } 62 | // } 63 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/buildError/buildError.stories.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react' 9 | import { BuildError } from './buildError' 10 | 11 | export default { 12 | title: 'BuildError', 13 | } 14 | 15 | export const DefaultError = () => 16 | 17 | export const FetchFailedError = () => ( 18 | 29 | ) 30 | 31 | export const FileNotFoundError = () => ( 32 | 41 | ) 42 | 43 | export const TransformError = () => ( 44 | 2 | import test from './test 53 | | ^`, 54 | name: 'TransformError', 55 | sourceFile: '/README.mdx', 56 | }} 57 | /> 58 | ) 59 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/Buttons.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { lighten } from 'polished' 9 | import styled, { css } from 'styled-components' 10 | import { 11 | beaconRing, 12 | colors, 13 | dimensions, 14 | easings, 15 | radii, 16 | shadows, 17 | } from '../constants' 18 | 19 | export interface StyledButtonBaseProps { 20 | color: string 21 | inline?: boolean 22 | leaveGlyphSpace?: boolean 23 | textColor: string 24 | } 25 | 26 | export const StyledRaisedButtonBase = styled.button` 27 | border-radius: ${radii.small}; 28 | background-color: ${props => props.color}; 29 | border: none; 30 | box-shadow: ${shadows.bevel()}, ${shadows.drop()}; 31 | color: ${props => props.textColor}; 32 | cursor: pointer; 33 | display: flex; 34 | height: ${dimensions.raisedButtonHeight}; 35 | justify-content: center; 36 | line-height: ${dimensions.raisedButtonHeight}; 37 | outline: none; 38 | position: relative; 39 | text-align: center; 40 | transition: background-color 200ms ${easings.easeOut}, 41 | opacity 200ms ${easings.easeOut}, box-shadow 200ms ${easings.easeOut}, 42 | color 200ms ${easings.easeOut}; 43 | white-space: nowrap; 44 | z-index: 0; 45 | 46 | :hover { 47 | background-color: ${props => lighten(0.03, props.color)}; 48 | } 49 | 50 | :active { 51 | box-shadow: ${shadows.bevelReverse()}, ${shadows.drop()}; 52 | } 53 | 54 | ${beaconRing('::after')} 55 | 56 | ${props => 57 | props.disabled && 58 | css` 59 | opacity: 0.5; 60 | `} 61 | ` 62 | 63 | StyledRaisedButtonBase.defaultProps = { 64 | color: colors.grey, 65 | textColor: colors.white, 66 | } 67 | -------------------------------------------------------------------------------- /packages/demoboard-worker/src/transforms/mdx/rehype-prism.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 Mapbox 3 | * MIT License 4 | */ 5 | 6 | import visit from 'unist-util-visit' 7 | import nodeToString from 'hast-util-to-string' 8 | import nodeToHTML from 'hast-util-to-html' 9 | import refractor from 'refractor' 10 | 11 | const aliases = { 12 | js: 'jsx', 13 | html: 'markup', 14 | } 15 | 16 | export default function rehypePrism(options: any) { 17 | options = options || {} 18 | 19 | return (tree: any) => { 20 | visit(tree, 'element', visitor) 21 | } 22 | 23 | function visitor(node: any, index: any, parent: any) { 24 | if (!parent || parent.tagName !== 'pre' || node.tagName !== 'code') { 25 | return 26 | } 27 | 28 | const lang = getLanguage(node, options.aliases || aliases) 29 | 30 | if (lang === null) { 31 | return 32 | } 33 | 34 | let result = node 35 | try { 36 | parent.properties.className = (parent.properties.className || []).concat( 37 | 'language-' + lang, 38 | ) 39 | result = refractor.highlight(nodeToString(node), lang) 40 | } catch (err) { 41 | if (/Unknown language/.test(err.message)) { 42 | return 43 | } 44 | throw err 45 | } 46 | 47 | node.children = [] 48 | node.properties.dangerouslySetInnerHTML = { 49 | __html: nodeToHTML({ 50 | type: 'root', 51 | children: result, 52 | }), 53 | } 54 | } 55 | } 56 | 57 | function getLanguage(node: any, aliases: any) { 58 | const className = node.properties.className || [] 59 | 60 | for (const classListItem of className) { 61 | if (classListItem.slice(0, 9) === 'language-') { 62 | let language = classListItem.slice(9).replace(/{.*/, '') 63 | let alias = aliases[language] 64 | return alias || language 65 | } 66 | } 67 | 68 | return null 69 | } 70 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/DemoboardContext.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { DemoboardWorker } from '@frontarm/demoboard-worker' 9 | 10 | import * as React from 'react' 11 | 12 | import { DemoboardExporter, DemoboardGenerator } from './types' 13 | import indexHTMLGenerator from './generators/indexHTMLGenerator' 14 | import markdownCSSGenerator from './generators/markdownCSSGenerator' 15 | import { 16 | defaultContainerURL, 17 | defaultRuntimeURL, 18 | defaultWorkerURLs, 19 | } from './defaultURLs' 20 | import getWorker from './worker/getWorker' 21 | 22 | export interface DemoboardContext { 23 | exporterLoaders: { 24 | [name: string]: () => Promise<{ default: DemoboardExporter }> 25 | } 26 | generators: { 27 | [name: string]: DemoboardGenerator 28 | } 29 | containerURL: string 30 | runtimeURL: string 31 | } 32 | 33 | export const DemoboardContext = React.createContext({ 34 | exporterLoaders: {}, 35 | generators: { 36 | 'index-html': indexHTMLGenerator, 37 | 'markdown-css': markdownCSSGenerator, 38 | }, 39 | containerURL: defaultContainerURL, 40 | runtimeURL: defaultRuntimeURL, 41 | }) 42 | 43 | export interface DemoboardWorkerContext { 44 | readonly worker: DemoboardWorker 45 | } 46 | 47 | let defaultWorker: DemoboardWorker 48 | export const DemoboardWorkerContext = React.createContext< 49 | DemoboardWorkerContext 50 | >({ 51 | // Lazily set the worker, so as not to fetch the worker this way if the 52 | // app specifies another worker provider 53 | get worker() { 54 | if (!defaultWorker) { 55 | defaultWorker = getWorker(defaultWorkerURLs) 56 | } 57 | return defaultWorker 58 | }, 59 | }) 60 | -------------------------------------------------------------------------------- /examples/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
%RENDERED_CONTENT%
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /packages/demoboard-ui/src/components/input/input.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { rgba } from 'polished' 9 | import React, { useCallback } from 'react' 10 | import styled from 'styled-components' 11 | 12 | import { beaconRing, colors, easings, shadows } from '../../constants' 13 | 14 | const StyledInputOutline = styled.div`` 15 | const StyledInputWrapper = styled.div` 16 | position: relative; 17 | background-color: ${colors.white}; 18 | border-radius: 99px; 19 | display: flex; 20 | flex: 1; 21 | z-index: 1; 22 | ` 23 | const StyledInput = styled.input` 24 | appearance: none; 25 | background-color: transparent; 26 | border: none; 27 | border-radius: 99px; 28 | box-sizing: border-box; 29 | box-shadow: ${shadows.sunk()}, ${shadows.drop()}; 30 | color: ${colors.darkerGrey}; 31 | display: block; 32 | font-size: 12px; 33 | padding: 0 1rem; 34 | transition: background-color 200ms ${easings.easeOut}; 35 | outline: none; 36 | width: 100%; 37 | 38 | :hover { 39 | background-color: ${rgba(colors.lightGrey, 0.15)}; 40 | } 41 | 42 | ${beaconRing(` + ${StyledInputOutline}`, '99px')} 43 | ` 44 | 45 | export interface InputProps 46 | extends Omit, 'onChange'> { 47 | onChange?: (value: string) => void 48 | } 49 | 50 | export const Input = ({ onChange, ...rest }: InputProps) => ( 51 | 52 | ) => { 56 | if (onChange) { 57 | onChange(event.target.value) 58 | } 59 | }, 60 | [onChange], 61 | )} 62 | /> 63 | 64 | 65 | ) 66 | -------------------------------------------------------------------------------- /packages/demoboard-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@frontarm/demoboard-ui", 3 | "version": "0.1.29", 4 | "description": "Embeddable code editor", 5 | "author": "James K Nelson ", 6 | "license": "Apache-2.0", 7 | "main": "dist/commonjs/index.js", 8 | "module": "dist/es/index.js", 9 | "types": "dist/types/index.d.ts", 10 | "scripts": { 11 | "clean": "rimraf dist", 12 | "build": "cross-env NODE_ENV=development rollup -c", 13 | "build:watch": "yarn run build --watch", 14 | "lint": "eslint --ext js,ts,tsx src", 15 | "prepare": "yarn run clean && yarn run build", 16 | "test": "jest", 17 | "test:watch": "jest --watch", 18 | "storybook": "start-storybook -p 6006", 19 | "build-storybook": "build-storybook" 20 | }, 21 | "dependencies": { 22 | "@frontarm/demoboard-core": "^0.1.29", 23 | "codemirror": "^5.49.2", 24 | "exenv": "^1.2.2", 25 | "json-stringify-safe": "^5.0.1", 26 | "polished": "^3.4.2", 27 | "reakit": "^1.0.0-beta.9", 28 | "tslib": "1.10.0", 29 | "use-codemirror": "^0.2.0" 30 | }, 31 | "peerDependencies": { 32 | "@types/codemirror": "^0.0.79", 33 | "@types/react": "^16.9.0", 34 | "@types/styled-components": "^4.1.8", 35 | "react": "^16.9.0", 36 | "styled-components": "^4.4.1" 37 | }, 38 | "publishConfig": { 39 | "access": "public" 40 | }, 41 | "gitHead": "c95bc9be5e02686208977653cabb28e7d7b1bd75", 42 | "devDependencies": { 43 | "@babel/core": "^7.7.2", 44 | "@babel/plugin-proposal-export-default-from": "^7.5.2", 45 | "@storybook/addon-actions": "^5.2.6", 46 | "@storybook/addon-info": "^5.2.6", 47 | "@storybook/addon-links": "^5.2.6", 48 | "@storybook/addons": "^5.2.6", 49 | "@storybook/react": "^5.2.6", 50 | "@svgr/webpack": "^4.3.3", 51 | "awesome-typescript-loader": "^5.2.1", 52 | "babel-loader": "^8.0.6", 53 | "react-docgen-typescript-loader": "^3.3.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/demoboard-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@frontarm/demoboard-core", 3 | "version": "0.1.29", 4 | "description": "Embeddable code editor", 5 | "author": "James K Nelson ", 6 | "license": "Apache-2.0", 7 | "main": "dist/commonjs/index.js", 8 | "module": "dist/es/index.js", 9 | "types": "dist/types/index.d.ts", 10 | "scripts": { 11 | "clean": "rimraf dist/**", 12 | "build": "cross-env NODE_ENV=development rollup -c", 13 | "build:production": "cross-env NODE_ENV=production rollup -c", 14 | "build:watch": "yarn run build --watch", 15 | "lint": "eslint --ext js,ts,tsx src", 16 | "prepare": "yarn run clean && yarn run build:production", 17 | "test": "env-cmd -f .env.test jest", 18 | "test:watch": "yarn test --watch" 19 | }, 20 | "dependencies": { 21 | "@frontarm/demoboard-messaging": "^0.1.20", 22 | "@frontarm/demoboard-runtime": "^0.1.29", 23 | "@frontarm/demoboard-worker": "^0.1.26", 24 | "automerge": "^0.12.1", 25 | "comlink": "^4.0.5", 26 | "exenv": "^1.2.2", 27 | "file-saver": "^2.0.0", 28 | "jszip": "^3.1.5", 29 | "react-hot-keys": "^1.2.2", 30 | "react-visibility-sensor": "^4.1.2", 31 | "resize-observer-polyfill": "^1.5.0", 32 | "source-map": "^0.7.3", 33 | "tslib": "1.10.0" 34 | }, 35 | "devDependencies": { 36 | "@testing-library/jest-dom": "^4.2.3", 37 | "@testing-library/react": "^9.3.2", 38 | "@testing-library/react-hooks": "^3.2.1", 39 | "env-cmd": "^10.0.1", 40 | "file-loader": "^2.0.0" 41 | }, 42 | "peerDependencies": { 43 | "@types/codemirror": "^0.0.77", 44 | "@types/exenv": "^1.2.0", 45 | "@types/jszip": "^3.1.6", 46 | "@types/react": "^16.9.0", 47 | "@types/react-dom": "^16.9.0", 48 | "react": "^16.8.6", 49 | "react-dom": "^16.8.6" 50 | }, 51 | "publishConfig": { 52 | "access": "public" 53 | }, 54 | "gitHead": "c95bc9be5e02686208977653cabb28e7d7b1bd75" 55 | } 56 | -------------------------------------------------------------------------------- /packages/demoboard-core/test/useDemoboardBuild.test.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import * as React from 'react' 9 | import TestRenderer from 'react-test-renderer' 10 | import { useDemoboardBuild } from '../src' 11 | 12 | const act = TestRenderer.act 13 | 14 | describe('useDemoboardBuild', () => { 15 | test('initially outputs null, and outputs success once complete', async () => { 16 | function Test() { 17 | let project = useDemoboardBuild('testid', { 18 | entryPathname: '/index.js', 19 | sources: { 20 | '/index.js': `console.log("hello, world")`, 21 | }, 22 | }) 23 | 24 | return <>{project && project.status} 25 | } 26 | 27 | let component: any 28 | await act(async () => { 29 | component = TestRenderer.create() 30 | expect(component.toJSON()).toEqual(null) 31 | }) 32 | expect(component.toJSON()).toEqual('success') 33 | }) 34 | 35 | test('transforms mdx files', async () => { 36 | let build: any 37 | 38 | function Test() { 39 | build = useDemoboardBuild('testid', { 40 | entryPathname: '/README.mdx', 41 | sources: { 42 | '/README.mdx': `# Hello world\n\nI'm a markdown file`, 43 | }, 44 | }) 45 | 46 | return <>{build && build.status} 47 | } 48 | 49 | let component: any 50 | await act(async () => { 51 | component = TestRenderer.create() 52 | }) 53 | 54 | expect(component.toJSON()).toEqual('success') 55 | 56 | let transformedSource = 57 | build && 58 | build.transformedModules && 59 | build.transformedModules['/README.mdx'].transformedSource 60 | 61 | expect(transformedSource).toMatch(`"Hello world"`) 62 | expect(transformedSource).toMatch(`function MDXContent`) 63 | }) 64 | }) 65 | -------------------------------------------------------------------------------- /packages/demoboard-core/src/instance/DemoboardInstanceIFrame.tsx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Seven Stripes Kabushiki Kaisha 3 | * 4 | * This source code is licensed under the Apache License, Version 2.0, found 5 | * in the LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import * as React from 'react' 9 | import { DemoboardInstance } from '../types' 10 | 11 | export interface DemoboardInstanceIFrameProps 12 | extends React.IframeHTMLAttributes { 13 | instance: DemoboardInstance 14 | } 15 | 16 | export function DemoboardInstanceIFrame({ 17 | children, 18 | instance, 19 | ...rest 20 | }: DemoboardInstanceIFrameProps) { 21 | let status = instance.status 22 | if (status === 'error' || status === 'empty') { 23 | return
24 | } else if (status === 'external') { 25 | return