diff --git a/.all-contributorsrc b/.all-contributorsrc index 1a7915787..05b43c84d 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -743,11 +743,65 @@ "bug", "code" ] + }, + { + "login": "Semperia", + "name": "Semesse", + "avatar_url": "https://avatars1.githubusercontent.com/u/13726406?v=4", + "profile": "https://blog.semesse.me", + "contributions": [ + "code" + ] + }, + { + "login": "bmihelac", + "name": "Bojan Mihelac", + "avatar_url": "https://avatars0.githubusercontent.com/u/13813?v=4", + "profile": "https://informatikamihelac.com", + "contributions": [ + "code" + ] + }, + { + "login": "dandv", + "name": "Dan Dascalescu", + "avatar_url": "https://avatars3.githubusercontent.com/u/33569?v=4", + "profile": "https://dandascalescu.com/", + "contributions": [ + "doc" + ] + }, + { + "login": "yuriy636", + "name": "Yuriy Burychka", + "avatar_url": "https://avatars3.githubusercontent.com/u/6631050?v=4", + "profile": "https://github.com/yuriy636", + "contributions": [ + "code" + ] + }, + { + "login": "jssee", + "name": "Jesse Hoyos", + "avatar_url": "https://avatars1.githubusercontent.com/u/2642936?v=4", + "profile": "https://github.com/jssee", + "contributions": [ + "code" + ] + }, + { + "login": "devrelm", + "name": "Mike Deverell", + "avatar_url": "https://avatars0.githubusercontent.com/u/2008333?v=4", + "profile": "https://twitter.com/devrelm", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, "projectName": "tsdx", - "projectOwner": "jaredpalmer", + "projectOwner": "formium", "repoType": "github", "repoHost": "https://github.com", "skipCi": true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..3ba13e0ce --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/README.md b/README.md index 58eeae19b..d272a64b5 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,10 @@ Despite all the recent hype, setting up a new TypeScript (x React) library can b - [Rollup](#rollup) - [Example: Adding Postcss](#example-adding-postcss) - [Babel](#babel) + - [Jest](#jest) + - [ESLint](#eslint) - [Inspiration](#inspiration) - - [Comparison to Microbundle](#comparison-to-microbundle) + - [Comparison with Microbundle](#comparison-with-microbundle) - [API Reference](#api-reference) - [`tsdx watch`](#tsdx-watch) - [`tsdx build`](#tsdx-build) @@ -373,13 +375,21 @@ module.exports = { ### Babel -You can add your own `.babelrc` to the root of your project and TSDX will **merge** it with its own babel transforms (which are mostly for optimization). +You can add your own `.babelrc` to the root of your project and TSDX will **merge** it with [its own Babel transforms](./src/babelPluginTsdx.ts) (which are mostly for optimization), putting any new presets and plugins at the end of its list. + +### Jest + +You can add your own `jest.config.js` to the root of your project and TSDX will **shallow merge** it with [its own Jest config](./src/createJestConfig.ts). + +### ESLint + +You can add your own `.eslintrc.js` to the root of your project and TSDX will **deep merge** it with [its own ESLint config](./src/createEslintConfig.ts). ## Inspiration TSDX is ripped out of [Formik's](https://github.com/jaredpalmer/formik) build tooling. TSDX is very similar to [@developit/microbundle](https://github.com/developit/microbundle), but that is because Formik's Rollup configuration and Microbundle's internals have converged around similar plugins over the last year or so. -### Comparison to Microbundle +### Comparison with Microbundle - TSDX includes out-of-the-box test running via Jest - TSDX includes a bootstrap command and default package template @@ -455,7 +465,7 @@ Examples ### `tsdx test` -This runs Jest v24.x. See [https://jestjs.io](https://jestjs.io) for options. For example, if you would like to run in watch mode, you can run `tsdx test --watch`. So you could set up your `package.json` `scripts` like: +This runs Jest v24.x, forwarding all CLI flags to it. See [https://jestjs.io](https://jestjs.io) for options. For example, if you would like to run in watch mode, you can run `tsdx test --watch`. So you could set up your `package.json` `scripts` like: ```json { @@ -512,97 +522,103 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + - - + + - + + + + + + +

Jared Palmer

πŸ“– 🎨 πŸ‘€ πŸ”§ ⚠️ 🚧 πŸ’»

swyx

πŸ› πŸ’» πŸ“– 🎨 πŸ€” πŸš‡ 🚧 πŸ‘€

Jason Etcovitch

πŸ› ⚠️

Sam Kvale

πŸ’» ⚠️ πŸ› πŸ“– πŸ‘€ πŸ€” πŸ’¬

Lucas Polito

πŸ’» πŸ“– πŸ’¬

Steven Kalt

πŸ’»

Harry Hedger

πŸ€” πŸ“– πŸ’» πŸ’¬

Jared Palmer

πŸ“– 🎨 πŸ‘€ πŸ”§ ⚠️ 🚧 πŸ’»

swyx

πŸ› πŸ’» πŸ“– 🎨 πŸ€” πŸš‡ 🚧 πŸ‘€

Jason Etcovitch

πŸ› ⚠️

Sam Kvale

πŸ’» ⚠️ πŸ› πŸ“– πŸ‘€ πŸ€” πŸ’¬

Lucas Polito

πŸ’» πŸ“– πŸ’¬

Steven Kalt

πŸ’»

Harry Hedger

πŸ€” πŸ“– πŸ’» πŸ’¬

Arthur Denner

πŸ› πŸ’» πŸ’¬

Carl

πŸ€” πŸ“– πŸ’» ⚠️ πŸ’¬

LoΓ―c Mahieu

πŸ’» ⚠️

Sebastian Sebald

πŸ“– πŸ’» ⚠️

Karl Horky

πŸ“– πŸ€”

James George

πŸ“–

Anton Gilgur

🚧 πŸ“– πŸ’» πŸ› πŸ’‘ πŸ€” πŸ’¬ πŸ‘€ ⚠️

Arthur Denner

πŸ› πŸ’» πŸ’¬

Carl

πŸ€” πŸ“– πŸ’» ⚠️ πŸ’¬

LoΓ―c Mahieu

πŸ’» ⚠️

Sebastian Sebald

πŸ“– πŸ’» ⚠️

Karl Horky

πŸ“– πŸ€”

James George

πŸ“–

Anton Gilgur

🚧 πŸ“– πŸ’» πŸ› πŸ’‘ πŸ€” πŸ’¬ πŸ‘€ ⚠️

Kyle Holmberg

πŸ’» πŸ’‘ ⚠️

Sigurd Spieckermann

πŸ› πŸ’»

Kristofer Giltvedt Selbekk

πŸ’»

TomΓ‘Ε‘ Ehrlich

πŸ› πŸ’»

Kyle Johnson

πŸ› πŸ’»

Etienne Dldc

πŸ› πŸ’» ⚠️

Florian Knop

πŸ›

Kyle Holmberg

πŸ’» πŸ’‘ ⚠️

Sigurd Spieckermann

πŸ› πŸ’»

Kristofer Giltvedt Selbekk

πŸ’»

TomΓ‘Ε‘ Ehrlich

πŸ› πŸ’»

Kyle Johnson

πŸ› πŸ’»

Etienne Dldc

πŸ› πŸ’» ⚠️

Florian Knop

πŸ›

Gonzalo D'Elia

πŸ’»

Alec Larson

πŸ’» πŸ‘€ πŸ€” πŸ’¬

Justin Grant

πŸ› πŸ€” πŸ’¬

Jirat Ki.

πŸ’» ⚠️ πŸ›

Nate Moore

πŸ’» πŸ€”

Haz

πŸ“–

Basti Buck

πŸ’» πŸ›

Gonzalo D'Elia

πŸ’»

Alec Larson

πŸ’» πŸ‘€ πŸ€” πŸ’¬

Justin Grant

πŸ› πŸ€” πŸ’¬

Jirat Ki.

πŸ’» ⚠️ πŸ›

Nate Moore

πŸ’» πŸ€”

Haz

πŸ“–

Basti Buck

πŸ’» πŸ›

Pablo Saez

πŸ’» πŸ›

Jake Gavin

πŸ› πŸ’»

Grant Forrest

πŸ’» ⚠️ πŸ›

SΓ©bastien Lorber

πŸ’»

Kirils Ladovs

πŸ“–

Enes TΓΌfekΓ§i

πŸ’» πŸ“–

Bogdan Chadkin

πŸ‘€ πŸ’¬ πŸ€”

Pablo Saez

πŸ’» πŸ›

Jake Gavin

πŸ› πŸ’»

Grant Forrest

πŸ’» ⚠️ πŸ›

SΓ©bastien Lorber

πŸ’»

Kirils Ladovs

πŸ“–

Enes TΓΌfekΓ§i

πŸ’» πŸ“–

Bogdan Chadkin

πŸ‘€ πŸ’¬ πŸ€”

Daniel K.

πŸ’» πŸ“– ⚠️ πŸ€” πŸ›

Quentin Sommer

πŸ“–

Hyan Mandian

πŸ’» ⚠️

Sung M. Kim

πŸ› πŸ’»

John Johnson

πŸ’» πŸ“–

Jun Tomioka

πŸ’» ⚠️

Leonardo Dino

πŸ’» πŸ›

Daniel K.

πŸ’» πŸ“– ⚠️ πŸ€” πŸ›

Quentin Sommer

πŸ“–

Hyan Mandian

πŸ’» ⚠️

Sung M. Kim

πŸ› πŸ’»

John Johnson

πŸ’» πŸ“–

Jun Tomioka

πŸ’» ⚠️

Leonardo Dino

πŸ’» πŸ›

Honza BΕ™ečka

πŸ’» πŸ›

Ward Loos

πŸ’» πŸ€”

Brian Bugh

πŸ’» πŸ›

Cody Carse

πŸ“–

Josh Biddick

πŸ’»

Jose Albizures

πŸ’» ⚠️ πŸ›

Rahel LΓΌthy

πŸ“–

Honza BΕ™ečka

πŸ’» πŸ›

Ward Loos

πŸ’» πŸ€”

Brian Bugh

πŸ’» πŸ›

Cody Carse

πŸ“–

Josh Biddick

πŸ’»

Jose Albizures

πŸ’» ⚠️ πŸ›

Rahel LΓΌthy

πŸ“–

Michael Edelman

πŸ’» πŸ€”

Charlike Mike Reagent

πŸ‘€ πŸ’» πŸ€”

Michael Edelman

πŸ’» πŸ€”

Charlike Mike Reagent

πŸ‘€ πŸ’» πŸ€”

Frederik Wessberg

πŸ’¬

Elad Ossadon

πŸ’» ⚠️ πŸ›

Kevin Kipp

πŸ’»

Matija Folnovic

πŸ’» πŸ“–

Andrew

πŸ’»

Elad Ossadon

πŸ’» ⚠️ πŸ›

Kevin Kipp

πŸ’»

Matija Folnovic

πŸ’» πŸ“–

Andrew

πŸ’»

Ryan Castner

πŸ’» ⚠️ πŸ€”

Yordis Prieto

πŸ’»

NCPhillips

πŸ“–

Arnaud BarrΓ©

πŸ’» πŸ“–

Peter W

πŸ“–

Joe Flateau

πŸ’» πŸ“–

H.John Choi

πŸ“–

Ryan Castner

πŸ’» ⚠️ πŸ€”

Yordis Prieto

πŸ’»

NCPhillips

πŸ“–

Arnaud BarrΓ©

πŸ’» πŸ“–

Peter W

πŸ“–

Joe Flateau

πŸ’» πŸ“–

H.John Choi

πŸ“–

Jon Stevens

πŸ“– πŸ€” πŸ›

greenkeeper[bot]

πŸš‡ πŸ’»

allcontributors[bot]

πŸš‡ πŸ“–

dependabot[bot]

πŸš‡ πŸ›‘οΈ πŸ’»

Jon Stevens

πŸ“– πŸ€” πŸ›

greenkeeper[bot]

πŸš‡ πŸ’»

allcontributors[bot]

πŸš‡ πŸ“–

dependabot[bot]

πŸš‡ πŸ›‘οΈ πŸ’»

GitHub

πŸš‡

Eugene Samonenko

⚠️ πŸ’‘ πŸ’¬ πŸ€”

Joseph Wang

πŸ›

Eugene Samonenko

⚠️ πŸ’‘ πŸ’¬ πŸ€”

Joseph Wang

πŸ›

Kotaro Sugawara

πŸ› πŸ’»

Kotaro Sugawara

πŸ› πŸ’»

Semesse

πŸ’»

Bojan Mihelac

πŸ’»

Dan Dascalescu

πŸ“–

Yuriy Burychka

πŸ’»

Jesse Hoyos

πŸ’»

Mike Deverell

πŸ’»
diff --git a/greenkeeper.json b/greenkeeper.json index ef70c1fef..c2c0e7059 100644 --- a/greenkeeper.json +++ b/greenkeeper.json @@ -3,8 +3,7 @@ "default": { "packages": [ "package.json", - "templates/react/example/package.json", - "website/package.json" + "templates/react/example/package.json" ] } } diff --git a/netlify.toml b/netlify.toml deleted file mode 100644 index a7dfe48c7..000000000 --- a/netlify.toml +++ /dev/null @@ -1,5 +0,0 @@ -# example netlify.toml -[build] - command = "yarn run build" - publish = "build" - base = "website" diff --git a/package.json b/package.json index e6e5d7608..68255950d 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "tsdx", - "version": "0.13.2", + "version": "0.13.3", "author": "Jared Palmer ", "description": "Zero-config TypeScript package development", "license": "MIT", + "homepage": "https://github.com/formium/tsdx", "repository": { "type": "git", - "url": "git+https://github.com/jaredpalmer/tsdx.git" + "url": "git+https://github.com/formium/tsdx.git" }, "keywords": [ "react", @@ -15,7 +16,7 @@ "rollup" ], "bugs": { - "url": "https://github.com/jaredpalmer/tsdx/issues" + "url": "https://github.com/formium/tsdx/issues" }, "bin": { "tsdx": "./dist/index.js" diff --git a/src/createBuildConfigs.ts b/src/createBuildConfigs.ts index b53bdee54..261c4f755 100644 --- a/src/createBuildConfigs.ts +++ b/src/createBuildConfigs.ts @@ -35,9 +35,9 @@ export async function createBuildConfigs( ); return await Promise.all( - allInputs.map(async (options: TsdxOptions) => { + allInputs.map(async (options: TsdxOptions, index: number) => { // pass the full rollup config to tsdx.config.js override - const config = await createRollupConfig(options); + const config = await createRollupConfig(options, index); return tsdxConfig.rollup(config, options); }) ); diff --git a/src/createRollupConfig.ts b/src/createRollupConfig.ts index eedc7dd5b..cd310f5d5 100644 --- a/src/createRollupConfig.ts +++ b/src/createRollupConfig.ts @@ -24,7 +24,8 @@ const errorCodeOpts = { let shebang: any = {}; export async function createRollupConfig( - opts: TsdxOptions + opts: TsdxOptions, + outputNum: number ): Promise { const findAndRecordErrorCodes = await extractErrors({ ...errorCodeOpts, @@ -145,7 +146,6 @@ export async function createRollupConfig( }, typescript({ typescript: ts, - cacheRoot: `./node_modules/.cache/tsdx/${opts.format}/`, tsconfig: opts.tsconfig, tsconfigDefaults: { exclude: [ @@ -170,9 +170,13 @@ export async function createRollupConfig( compilerOptions: { // TS -> esnext, then leave the rest to babel-preset-env target: 'esnext', + // don't output declarations more than once + ...(outputNum > 0 + ? { declaration: false, declarationMap: false } + : {}), }, }, - check: !opts.transpileOnly, + check: !opts.transpileOnly && outputNum === 0, useTsconfigDeclarationDir: Boolean(tsCompilerOptions?.declarationDir), }), babelPluginTsdx({ diff --git a/src/deprecated.ts b/src/deprecated.ts index 275caadb8..41319cdcc 100644 --- a/src/deprecated.ts +++ b/src/deprecated.ts @@ -21,27 +21,14 @@ export async function moveTypes() { '[tsdx]: Your rootDir is currently set to "./". Please change your ' + 'rootDir to "./src".\n' + 'TSDX has deprecated setting tsconfig.compilerOptions.rootDir to ' + - '"./" as it caused buggy output for declarationMaps and occassionally ' + - 'for type declarations themselves.\n' + + '"./" as it caused buggy output for declarationMaps and more.\n' + 'You may also need to change your include to remove "test", which also ' + 'caused declarations to be unnecessarily created for test files.' ); - try { - // Move the typescript types to the base of the ./dist folder - await fs.copy(appDistSrc, paths.appDist, { - overwrite: true, - }); - } catch (err) { - // ignore errors about the destination dir already existing or files not - // existing as those always occur for some reason, re-throw any other - // unexpected failures - // NOTE: these errors mean that sometimes files don't get moved properly, - // meaning that it's buggy / unreliable (see console.warn above) - if (err.code !== 'EEXIST' && err.code !== 'ENOENT') { - throw err; - } - } - + // Move the typescript types to the base of the ./dist folder + await fs.copy(appDistSrc, paths.appDist, { + overwrite: true, + }); await fs.remove(appDistSrc); } diff --git a/src/index.ts b/src/index.ts index b5d8254d6..30ca3db16 100755 --- a/src/index.ts +++ b/src/index.ts @@ -85,19 +85,16 @@ async function getInputs( entries?: string | string[], source?: string ): Promise { - let inputs: string[] = []; - let stub: any[] = []; - stub - .concat( - entries && entries.length - ? entries - : (source && resolveApp(source)) || - ((await isDir(resolveApp('src'))) && (await jsOrTs('src/index'))) - ) - .map(file => glob(file)) - .forEach(input => inputs.push(input)); - - return concatAllArray(inputs); + return concatAllArray( + ([] as any[]) + .concat( + entries && entries.length + ? entries + : (source && resolveApp(source)) || + ((await isDir(resolveApp('src'))) && (await jsOrTs('src/index'))) + ) + .map(file => glob(file)) + ); } prog @@ -401,11 +398,13 @@ prog async (inputOptions: RollupOptions & { output: OutputOptions }) => { let bundle = await rollup(inputOptions); await bundle.write(inputOptions.output); - await deprecated.moveTypes(); } ) .catch((e: any) => { throw e; + }) + .then(async () => { + await deprecated.moveTypes(); }); logger(promise, 'Building modules'); await promise; @@ -482,9 +481,7 @@ function setAuthorName(author: string) { prog .command('test') - .describe( - 'Run jest test runner in watch mode. Passes through all flags directly to Jest' - ) + .describe('Run jest test runner. Passes through all flags directly to Jest') .action(async (opts: { config?: string }) => { // Do this as the first thing so that any code reading it knows the right env. process.env.BABEL_ENV = 'test'; diff --git a/src/messages.ts b/src/messages.ts index e40287959..627aeee88 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -11,7 +11,7 @@ export const help = function() { return ` Only ${chalk.green('')} is required. If you have any problems, do not hesitate to file an issue: - ${chalk.cyan('https://github.com/jaredpalmer/tsdx/issues/new')} + ${chalk.cyan('https://github.com/formium/tsdx/issues/new')} `; }; @@ -86,7 +86,7 @@ export const start = async function(projectName: string) { ${Output.cmd(commands.test)} Questions? Feedback? Please let me know! - ${chalk.green('https://github.com/jaredpalmer/tsdx/issues')} + ${chalk.green('https://github.com/formium/tsdx/issues')} `; }; diff --git a/templates/basic/.github/workflows/main.yml b/templates/basic/.github/workflows/main.yml index 11023c28f..3ce3e4023 100644 --- a/templates/basic/.github/workflows/main.yml +++ b/templates/basic/.github/workflows/main.yml @@ -14,7 +14,7 @@ jobs: node-version: 12.x - name: Use cached node_modules - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: node_modules key: nodeModules-${{ hashFiles('**/yarn.lock') }} diff --git a/templates/basic/README.md b/templates/basic/README.md index 7555d824d..c3d865fa5 100644 --- a/templates/basic/README.md +++ b/templates/basic/README.md @@ -1,27 +1,99 @@ -# TSDX Bootstrap +# TSDX User Guide -This project was bootstrapped with [TSDX](https://github.com/jaredpalmer/tsdx). +Congrats! You just saved yourself hours of work by bootstrapping this project with TSDX. Let’s get you oriented with what’s here and how to use it. -## Local Development +> This TSDX setup is meant for developing libraries (not apps!) that can be published to NPM. If you’re looking to build a Node app, you could use `ts-node-dev`, plain `ts-node`, or simple `tsc`. -Below is a list of commands you will probably find useful. +> If you’re new to TypeScript, checkout [this handy cheatsheet](https://devhints.io/typescript) -### `npm start` or `yarn start` +## Commands -Runs the project in development/watch mode. Your project will be rebuilt upon changes. TSDX has a special logger for you convenience. Error messages are pretty printed and formatted for compatibility VS Code's Problems tab. +TSDX scaffolds your new library inside `/src`. - +To run TSDX, use: -Your library will be rebuilt if you make edits. +```bash +npm start # or yarn start +``` -### `npm run build` or `yarn build` +This builds to `/dist` and runs the project in watch mode so any edits you save inside `src` causes a rebuild to `/dist`. -Bundles the package to the `dist` folder. -The package is optimized and bundled with Rollup into multiple formats (CommonJS, UMD, and ES Module). +To do a one-off build, use `npm run build` or `yarn build`. - +To run tests, use `npm test` or `yarn test`. -### `npm test` or `yarn test` +## Configuration -Runs the test watcher (Jest) in an interactive mode. -By default, runs tests related to files changed since the last commit. +Code quality is set up for you with `prettier`, `husky`, and `lint-staged`. Adjust the respective fields in `package.json` accordingly. + +### Jest + +Jest tests are set up to run with `npm test` or `yarn test`. + +#### Setup Files + +This is the folder structure we set up for you: + +```txt +/src + index.tsx # EDIT THIS +/test + blah.test.tsx # EDIT THIS +.gitignore +package.json +README.md # EDIT THIS +tsconfig.json +``` + +### Rollup + +TSDX uses [Rollup](https://rollupjs.org) as a bundler and generates multiple rollup configs for various module formats and build settings. See [Optimizations](#optimizations) for details. + +### TypeScript + +`tsconfig.json` is set up to interpret `dom` and `esnext` types, as well as `react` for `jsx`. Adjust according to your needs. + +## Continuous Integration + +### GitHub Actions + +A simple action is included that runs these steps on all pushes: + +- Installs deps w/ cache +- Lints, tests, and builds + +## Optimizations + +Please see the main `tsdx` [optimizations docs](https://github.com/palmerhq/tsdx#optimizations). In particular, know that you can take advantage of development-only optimizations: + +```js +// ./types/index.d.ts +declare var __DEV__: boolean; + +// inside your code... +if (__DEV__) { + console.log('foo'); +} +``` + +You can also choose to install and use [invariant](https://github.com/palmerhq/tsdx#invariant) and [warning](https://github.com/palmerhq/tsdx#warning) functions. + +## Module Formats + +CJS, ESModules, and UMD module formats are supported. + +The appropriate paths are configured in `package.json` and `dist/index.js` accordingly. Please report if any issues are found. + +## Named Exports + +Per Palmer Group guidelines, [always use named exports.](https://github.com/palmerhq/typescript#exports) Code split inside your React app instead of your React library. + +## Including Styles + +There are many ways to ship styles, including with CSS-in-JS. TSDX has no opinion on this, configure how you like. + +For vanilla CSS, you can include it at the root directory and add it to the `files` section in your `package.json`, so that it can be imported separately by your users and run through their bundler's loader. + +## Publishing to NPM + +We recommend using [np](https://github.com/sindresorhus/np). diff --git a/templates/basic/tsconfig.json b/templates/basic/tsconfig.json index 1e79b510b..816d09263 100644 --- a/templates/basic/tsconfig.json +++ b/templates/basic/tsconfig.json @@ -13,10 +13,6 @@ "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", - "baseUrl": "./", - "paths": { - "*": ["src/*", "node_modules/*"] - }, "jsx": "react", "esModuleInterop": true } diff --git a/templates/react-with-storybook/.github/workflows/main.yml b/templates/react-with-storybook/.github/workflows/main.yml index 11023c28f..3ce3e4023 100644 --- a/templates/react-with-storybook/.github/workflows/main.yml +++ b/templates/react-with-storybook/.github/workflows/main.yml @@ -14,7 +14,7 @@ jobs: node-version: 12.x - name: Use cached node_modules - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: node_modules key: nodeModules-${{ hashFiles('**/yarn.lock') }} diff --git a/templates/react-with-storybook/README.md b/templates/react-with-storybook/README.md index c63cfdec7..be3a99082 100644 --- a/templates/react-with-storybook/README.md +++ b/templates/react-with-storybook/README.md @@ -1,8 +1,8 @@ -# TSDX React User Guide +# TSDX React w/ Storybook User Guide Congrats! You just saved yourself hours of work by bootstrapping this project with TSDX. Let’s get you oriented with what’s here and how to use it. -> This TSDX setup is meant for developing React components (not apps!) that can be published to NPM. If you’re looking to build an app, you should use `create-react-app`, `razzle`, `nextjs`, `gatsby`, or `react-static`. +> This TSDX setup is meant for developing React component libraries (not apps!) that can be published to NPM. If you’re looking to build a React-based app, you should use `create-react-app`, `razzle`, `nextjs`, `gatsby`, or `react-static`. > If you’re new to TypeScript and React, checkout [this handy cheatsheet](https://github.com/sw-yx/react-typescript-cheatsheet/) @@ -12,19 +12,19 @@ TSDX scaffolds your new library inside `/src`, and also sets up a [Parcel-based] The recommended workflow is to run TSDX in one terminal: -``` +```bash npm start # or yarn start ``` This builds to `/dist` and runs the project in watch mode so any edits you save inside `src` causes a rebuild to `/dist`. -Then run either example playground or storybook: +Then run either Storybook or the example playground: ### Storybook Run inside another terminal: -``` +```bash yarn storybook ``` @@ -36,13 +36,13 @@ This loads the stories from `./stories`. Then run the example inside another: -``` +```bash cd example npm i # or yarn to install dependencies npm start # or yarn start ``` -The default example imports and live reloads whatever is in `/dist`, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**, [we use Parcel's aliasing](https://github.com/palmerhq/tsdx/pull/88/files). +The default example imports and live reloads whatever is in `/dist`, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**, we use [Parcel's aliasing](https://parceljs.org/module_resolution.html#aliases). To do a one-off build, use `npm run build` or `yarn build`. @@ -50,17 +50,17 @@ To run tests, use `npm test` or `yarn test`. ## Configuration -Code quality is [set up for you](https://github.com/palmerhq/tsdx/pull/45/files) with `prettier`, `husky`, and `lint-staged`. Adjust the respective fields in `package.json` accordingly. +Code quality is set up for you with `prettier`, `husky`, and `lint-staged`. Adjust the respective fields in `package.json` accordingly. ### Jest -Jest tests are set up to run with `npm test` or `yarn test`. This runs the test watcher (Jest) in an interactive mode. By default, runs tests related to files changed since the last commit. +Jest tests are set up to run with `npm test` or `yarn test`. #### Setup Files This is the folder structure we set up for you: -``` +```txt /example index.html index.tsx # test your component here in a demo app @@ -82,7 +82,7 @@ We do not set up `react-testing-library` for you yet, we welcome contributions a ### Rollup -TSDX uses [Rollup v1.x](https://rollupjs.org) as a bundler and generates multiple rollup configs for various module formats and build settings. See [Optimizations](#optimizations) for details. +TSDX uses [Rollup](https://rollupjs.org) as a bundler and generates multiple rollup configs for various module formats and build settings. See [Optimizations](#optimizations) for details. ### TypeScript @@ -90,13 +90,12 @@ TSDX uses [Rollup v1.x](https://rollupjs.org) as a bundler and generates multipl ## Continuous Integration -### Travis - -_to be completed_ +### GitHub Actions -### Circle +A simple action is included that runs these steps on all pushes: -_to be completed_ +- Installs deps w/ cache +- Lints, tests, and builds ## Optimizations @@ -120,17 +119,7 @@ CJS, ESModules, and UMD module formats are supported. The appropriate paths are configured in `package.json` and `dist/index.js` accordingly. Please report if any issues are found. -## Using the Playground - -``` -cd example -npm i # or yarn to install dependencies -npm start # or yarn start -``` - -The default example imports and live reloads whatever is in `/dist`, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**! - -## Deploying the Playground +## Deploying the Example Playground The Playground is just a simple [Parcel](https://parceljs.org) app, you can deploy it anywhere you would normally deploy that. Here are some guidelines for **manually** deploying with the Netlify CLI (`npm i -g netlify-cli`): @@ -161,7 +150,7 @@ For vanilla CSS, you can include it at the root directory and add it to the `fil ## Publishing to NPM -We recommend using https://github.com/sindresorhus/np. +We recommend using [np](https://github.com/sindresorhus/np). ## Usage with Lerna diff --git a/templates/react-with-storybook/example/tsconfig.json b/templates/react-with-storybook/example/tsconfig.json index 6d518675d..1e2e4fd9c 100644 --- a/templates/react-with-storybook/example/tsconfig.json +++ b/templates/react-with-storybook/example/tsconfig.json @@ -13,7 +13,6 @@ "preserveConstEnums": true, "sourceMap": true, "lib": ["es2015", "es2016", "dom"], - "baseUrl": ".", "types": ["node"] } } diff --git a/templates/react-with-storybook/tsconfig.json b/templates/react-with-storybook/tsconfig.json index 71606db2f..816d09263 100644 --- a/templates/react-with-storybook/tsconfig.json +++ b/templates/react-with-storybook/tsconfig.json @@ -13,11 +13,6 @@ "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", - "baseUrl": "./", - "paths": { - "@": ["./"], - "*": ["src/*", "node_modules/*"] - }, "jsx": "react", "esModuleInterop": true } diff --git a/templates/react/.github/workflows/main.yml b/templates/react/.github/workflows/main.yml index 11023c28f..3ce3e4023 100644 --- a/templates/react/.github/workflows/main.yml +++ b/templates/react/.github/workflows/main.yml @@ -14,7 +14,7 @@ jobs: node-version: 12.x - name: Use cached node_modules - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: node_modules key: nodeModules-${{ hashFiles('**/yarn.lock') }} diff --git a/templates/react/README.md b/templates/react/README.md index 33ce67704..cdb1f9d45 100644 --- a/templates/react/README.md +++ b/templates/react/README.md @@ -2,7 +2,7 @@ Congrats! You just saved yourself hours of work by bootstrapping this project with TSDX. Let’s get you oriented with what’s here and how to use it. -> This TSDX setup is meant for developing React components (not apps!) that can be published to NPM. If you’re looking to build an app, you should use `create-react-app`, `razzle`, `nextjs`, `gatsby`, or `react-static`. +> This TSDX setup is meant for developing React component libraries (not apps!) that can be published to NPM. If you’re looking to build a React-based app, you should use `create-react-app`, `razzle`, `nextjs`, `gatsby`, or `react-static`. > If you’re new to TypeScript and React, checkout [this handy cheatsheet](https://github.com/sw-yx/react-typescript-cheatsheet/) @@ -26,7 +26,7 @@ npm i # or yarn to install dependencies npm start # or yarn start ``` -The default example imports and live reloads whatever is in `/dist`, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**, [we use Parcel's aliasing](https://github.com/palmerhq/tsdx/pull/88/files). +The default example imports and live reloads whatever is in `/dist`, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**, we use [Parcel's aliasing](https://parceljs.org/module_resolution.html#aliases). To do a one-off build, use `npm run build` or `yarn build`. @@ -34,17 +34,17 @@ To run tests, use `npm test` or `yarn test`. ## Configuration -Code quality is [set up for you](https://github.com/palmerhq/tsdx/pull/45/files) with `prettier`, `husky`, and `lint-staged`. Adjust the respective fields in `package.json` accordingly. +Code quality is set up for you with `prettier`, `husky`, and `lint-staged`. Adjust the respective fields in `package.json` accordingly. ### Jest -Jest tests are set up to run with `npm test` or `yarn test`. This runs the test watcher (Jest) in an interactive mode. By default, runs tests related to files changed since the last commit. +Jest tests are set up to run with `npm test` or `yarn test`. #### Setup Files This is the folder structure we set up for you: -```shell +```txt /example index.html index.tsx # test your component here in a demo app @@ -66,7 +66,7 @@ We do not set up `react-testing-library` for you yet, we welcome contributions a ### Rollup -TSDX uses [Rollup v1.x](https://rollupjs.org) as a bundler and generates multiple rollup configs for various module formats and build settings. See [Optimizations](#optimizations) for details. +TSDX uses [Rollup](https://rollupjs.org) as a bundler and generates multiple rollup configs for various module formats and build settings. See [Optimizations](#optimizations) for details. ### TypeScript @@ -74,13 +74,12 @@ TSDX uses [Rollup v1.x](https://rollupjs.org) as a bundler and generates multipl ## Continuous Integration -### Travis +### GitHub Actions -_to be completed_ +A simple action is included that runs these steps on all pushes: -### Circle - -_to be completed_ +- Installs deps w/ cache +- Lints, tests, and builds ## Optimizations @@ -104,17 +103,7 @@ CJS, ESModules, and UMD module formats are supported. The appropriate paths are configured in `package.json` and `dist/index.js` accordingly. Please report if any issues are found. -## Using the Playground - -```bash -cd example -npm i # or yarn to install dependencies -npm start # or yarn start -``` - -The default example imports and live reloads whatever is in `/dist`, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**! - -## Deploying the Playground +## Deploying the Example Playground The Playground is just a simple [Parcel](https://parceljs.org) app, you can deploy it anywhere you would normally deploy that. Here are some guidelines for **manually** deploying with the Netlify CLI (`npm i -g netlify-cli`): diff --git a/templates/react/example/tsconfig.json b/templates/react/example/tsconfig.json index 6d518675d..1e2e4fd9c 100644 --- a/templates/react/example/tsconfig.json +++ b/templates/react/example/tsconfig.json @@ -13,7 +13,6 @@ "preserveConstEnums": true, "sourceMap": true, "lib": ["es2015", "es2016", "dom"], - "baseUrl": ".", "types": ["node"] } } diff --git a/templates/react/tsconfig.json b/templates/react/tsconfig.json index 1e79b510b..816d09263 100644 --- a/templates/react/tsconfig.json +++ b/templates/react/tsconfig.json @@ -13,10 +13,6 @@ "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", - "baseUrl": "./", - "paths": { - "*": ["src/*", "node_modules/*"] - }, "jsx": "react", "esModuleInterop": true } diff --git a/test/e2e/fixtures/build-default/tsconfig.json b/test/e2e/fixtures/build-default/tsconfig.json index 7f2bd50c5..b25c2e554 100644 --- a/test/e2e/fixtures/build-default/tsconfig.json +++ b/test/e2e/fixtures/build-default/tsconfig.json @@ -6,21 +6,11 @@ "sourceMap": true, "rootDir": "./src", "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictPropertyInitialization": true, - "noImplicitThis": true, - "alwaysStrict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", - "baseUrl": "./", - "paths": { - "*": ["src/*", "node_modules/*"] - }, "jsx": "react", "esModuleInterop": true }, diff --git a/test/e2e/fixtures/build-invalid/tsconfig.json b/test/e2e/fixtures/build-invalid/tsconfig.json index 7f2bd50c5..b25c2e554 100644 --- a/test/e2e/fixtures/build-invalid/tsconfig.json +++ b/test/e2e/fixtures/build-invalid/tsconfig.json @@ -6,21 +6,11 @@ "sourceMap": true, "rootDir": "./src", "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictPropertyInitialization": true, - "noImplicitThis": true, - "alwaysStrict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", - "baseUrl": "./", - "paths": { - "*": ["src/*", "node_modules/*"] - }, "jsx": "react", "esModuleInterop": true }, diff --git a/test/e2e/fixtures/build-withTsconfig/tsconfig.base.json b/test/e2e/fixtures/build-withTsconfig/tsconfig.base.json index 8197363fc..c5a66c1ea 100644 --- a/test/e2e/fixtures/build-withTsconfig/tsconfig.base.json +++ b/test/e2e/fixtures/build-withTsconfig/tsconfig.base.json @@ -8,21 +8,11 @@ "sourceMap": true, "rootDir": "./src", "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictPropertyInitialization": true, - "noImplicitThis": true, - "alwaysStrict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", - "baseUrl": "./", - "paths": { - "*": ["src/*", "node_modules/*"] - }, "jsx": "react", "esModuleInterop": false }, diff --git a/test/integration/fixtures/build-options/tsconfig.json b/test/integration/fixtures/build-options/tsconfig.json index a8c8432ed..3645ceed5 100644 --- a/test/integration/fixtures/build-options/tsconfig.json +++ b/test/integration/fixtures/build-options/tsconfig.json @@ -6,21 +6,11 @@ "sourceMap": true, "rootDir": "./src", "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictPropertyInitialization": true, - "noImplicitThis": true, - "alwaysStrict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", - "baseUrl": "./", - "paths": { - "*": ["src/*", "node_modules/*"] - }, "jsx": "react", "esModuleInterop": true }, diff --git a/test/integration/fixtures/build-withBabel/tsconfig.json b/test/integration/fixtures/build-withBabel/tsconfig.json index a8c8432ed..3645ceed5 100644 --- a/test/integration/fixtures/build-withBabel/tsconfig.json +++ b/test/integration/fixtures/build-withBabel/tsconfig.json @@ -6,21 +6,11 @@ "sourceMap": true, "rootDir": "./src", "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictPropertyInitialization": true, - "noImplicitThis": true, - "alwaysStrict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", - "baseUrl": "./", - "paths": { - "*": ["src/*", "node_modules/*"] - }, "jsx": "react", "esModuleInterop": true }, diff --git a/test/integration/fixtures/build-withConfig/tsconfig.json b/test/integration/fixtures/build-withConfig/tsconfig.json index a8c8432ed..3645ceed5 100644 --- a/test/integration/fixtures/build-withConfig/tsconfig.json +++ b/test/integration/fixtures/build-withConfig/tsconfig.json @@ -6,21 +6,11 @@ "sourceMap": true, "rootDir": "./src", "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictPropertyInitialization": true, - "noImplicitThis": true, - "alwaysStrict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", - "baseUrl": "./", - "paths": { - "*": ["src/*", "node_modules/*"] - }, "jsx": "react", "esModuleInterop": true }, diff --git a/website/.babelrc b/website/.babelrc new file mode 100644 index 000000000..357e43654 --- /dev/null +++ b/website/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["next/babel"], + "plugins": ["babel-plugin-macros", "./.nextra/babel-plugin-nextjs-mdx-patch"] +} \ No newline at end of file diff --git a/website/.gitignore b/website/.gitignore old mode 100755 new mode 100644 index 1b34df512..c3ee72b81 --- a/website/.gitignore +++ b/website/.gitignore @@ -1,20 +1,4 @@ -# dependencies -/node_modules - -# production -/build - -# generated files -.docusaurus -.cache-loader - -# misc +node_modules +.next .DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* \ No newline at end of file +yarn-error.log \ No newline at end of file diff --git a/website/.nextra/arrow-right.js b/website/.nextra/arrow-right.js new file mode 100644 index 000000000..50c8163f8 --- /dev/null +++ b/website/.nextra/arrow-right.js @@ -0,0 +1,19 @@ +export default ({ width = 24, height = 24, ...props }) => { + return ( + + + + ) +} diff --git a/website/.nextra/babel-plugin-nextjs-mdx-patch.js b/website/.nextra/babel-plugin-nextjs-mdx-patch.js new file mode 100644 index 000000000..c7bfec273 --- /dev/null +++ b/website/.nextra/babel-plugin-nextjs-mdx-patch.js @@ -0,0 +1,34 @@ +/** + * Currently it's not possible to export data fetching functions from MDX pages + * because MDX includes them in `layoutProps`, and Next.js removes them at some + * point, causing a `ReferenceError`. + * + * https://github.com/mdx-js/mdx/issues/742#issuecomment-612652071 + * + * This plugin can be removed once MDX removes `layoutProps`, at least that + * seems to be the current plan. + */ + +// https://nextjs.org/docs/basic-features/data-fetching +const DATA_FETCH_FNS = ['getStaticPaths', 'getStaticProps', 'getServerProps'] + +module.exports = () => { + return { + visitor: { + ObjectProperty(path) { + if ( + DATA_FETCH_FNS.includes(path.node.value.name) && + path.findParent( + (path) => + path.isVariableDeclarator() && + path.node.id.name === 'layoutProps', + ) + ) { + path.remove() + } + }, + }, + } +} + +// https://github.com/vercel/next.js/issues/12053#issuecomment-622939046 diff --git a/website/.nextra/config.js b/website/.nextra/config.js new file mode 100644 index 000000000..0b055a4c5 --- /dev/null +++ b/website/.nextra/config.js @@ -0,0 +1,11 @@ +import userConfig from '../nextra.config'; + +const defaultConfig = { + nextLinks: true, + prevLinks: true, + search: true, +}; + +export default () => { + return { ...defaultConfig, ...userConfig }; +}; diff --git a/website/.nextra/directories.js b/website/.nextra/directories.js new file mode 100644 index 000000000..4d3bf8740 --- /dev/null +++ b/website/.nextra/directories.js @@ -0,0 +1,96 @@ +import preval from 'preval.macro' +import title from 'title' + +const excludes = ['/_app.js', '/_document.js', '/_error.js'] + +// watch all meta files +const meta = {} +function importAll(r) { + return r.keys().forEach(key => { + meta[key.slice(1)] = r(key) + }) +} +importAll(require.context('../pages/', true, /meta\.json$/)) + +// use macro to load the file list +const items = preval` + const { readdirSync, readFileSync } = require('fs') + const { resolve, join } = require('path') + const extension = /\.(mdx?|jsx?)$/ + + function getFiles(dir, route) { + const files = readdirSync(dir, { withFileTypes: true }) + + // go through the directory + const items = files + .map(f => { + const filePath = resolve(dir, f.name) + const fileRoute = join(route, f.name.replace(extension, '').replace(/^index$/, '')) + + if (f.isDirectory()) { + const children = getFiles(filePath, fileRoute) + if (!children.length) return null + return { name: f.name, children, route: fileRoute } + } else if (f.name === 'meta.json') { + return null + } else if (extension.test(f.name)) { + return { name: f.name.replace(extension, ''), route: fileRoute } + } + }) + .map(item => { + if (!item) return + return { ...item, metaPath: join(route, 'meta.json') } + }) + .filter(Boolean) + + return items + } + module.exports = getFiles(join(process.cwd(), 'pages'), '/') +` + +const attachPageConfig = function (items) { + let folderMeta = null + let fnames = null + + return items + .filter(item => !excludes.includes(item.name)) + .map(item => { + const { metaPath, ...rest } = item + folderMeta = meta[metaPath] + if (folderMeta) { + fnames = Object.keys(folderMeta) + } + + const pageConfig = folderMeta?.[item.name] + + if (rest.children) rest.children = attachPageConfig(rest.children) + + if (pageConfig) { + if (typeof pageConfig === 'string') { + return { ...rest, title: pageConfig } + } + return { ...rest, ...pageConfig } + } else { + if (folderMeta) { + return null + } + return { ...rest, title: title(item.name) } + } + }) + .filter(Boolean) + .sort((a, b) => { + if (folderMeta) { + return fnames.indexOf(a.name) - fnames.indexOf(b.name) + } + // by default, we put directories first + if (!!a.children !== !!b.children) { + return !!a.children ? -1 : 1 + } + // sort by file name + return a.name < b.name ? -1 : 1 + }) +} + +export default () => { + return attachPageConfig(items) +} diff --git a/website/.nextra/docsearch.js b/website/.nextra/docsearch.js new file mode 100644 index 000000000..8dd6f4757 --- /dev/null +++ b/website/.nextra/docsearch.js @@ -0,0 +1,44 @@ +import { useRef, useEffect } from 'react' + +export default function () { + const input = useRef(null) + + useEffect(() => { + const inputs = ['input', 'select', 'button', 'textarea'] + + const down = (e) => { + if ( + document.activeElement && + inputs.indexOf(document.activeElement.tagName.toLowerCase() !== -1) + ) { + if (e.key === '/') { + e.preventDefault() + input.current?.focus() + } + } + } + + window.addEventListener('keydown', down) + return () => window.removeEventListener('keydown', down) + }, []) + + useEffect(() => { + if (window.docsearch) { + window.docsearch({ + apiKey: '247dd86c8ddbbbe6d7a2d4adf4f3a68a', + indexName: 'vercel_swr', + inputSelector: 'input#algolia-doc-search' + }) + } + }, []) + + return
+ +
+} diff --git a/website/.nextra/github-icon.js b/website/.nextra/github-icon.js new file mode 100644 index 000000000..46b77c994 --- /dev/null +++ b/website/.nextra/github-icon.js @@ -0,0 +1,5 @@ +export default ({ height = 40 }) => { + return + + +} \ No newline at end of file diff --git a/website/.nextra/layout.js b/website/.nextra/layout.js new file mode 100644 index 000000000..18a857bd9 --- /dev/null +++ b/website/.nextra/layout.js @@ -0,0 +1,332 @@ +import React, { + useState, + useEffect, + useMemo, + useContext, + createContext, +} from 'react'; +import { useRouter } from 'next/router'; +import Head from 'next/head'; +import Link from 'next/link'; +import slugify from '@sindresorhus/slugify'; +import 'focus-visible'; +import cn from 'classnames'; +import { SkipNavContent } from '@reach/skip-nav'; + +import Theme from './theme'; +import SSGContext from './ssg'; +import Search from './search'; +// import DocSearch from './docsearch' +import GitHubIcon from './github-icon'; +import ArrowRight from './arrow-right'; + +import getDirectories from './directories'; +import getConfig from './config'; +import * as ReactDOM from 'react-dom/server'; +import stripHtml from 'string-strip-html'; +const config = getConfig(); +const directories = getDirectories(); +const TreeState = new Map(); +const titleType = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']; +const MenuContext = createContext(false); + +const flatten = list => { + return list.reduce((flat, toFlatten) => { + return flat.concat( + toFlatten.children ? flatten(toFlatten.children) : toFlatten + ); + }, []); +}; + +const flatDirectories = flatten(directories); + +function Folder({ item, anchors }) { + const route = useRouter().route + '/'; + const active = route.startsWith(item.route + '/'); + const open = TreeState[item.route] ?? true; + const [_, render] = useState(false); + + useEffect(() => { + if (active) { + TreeState[item.route] = true; + } + }, [active]); + + return ( +
  • + +
    + +
    +
  • + ); +} + +function File({ item, anchors }) { + const { setMenu } = useContext(MenuContext); + const route = useRouter().route + '/'; + const active = route.startsWith(item.route + '/'); + + let title = item.title; + // if (item.title.startsWith('> ')) { + // title = title.substr(2) + if (anchors?.length) { + if (active) { + return ( +
  • + + {title} + + +
  • + ); + } + } + + return ( +
  • + + setMenu(false)} className="focus:shadow-outline"> + {title} + + +
  • + ); +} + +function Menu({ dir, anchors }) { + return ( +
      + {dir.map(item => { + if (item.children) { + return ; + } + return ; + })} +
    + ); +} + +function Sidebar({ show, anchors }) { + return ( + + ); +} + +const NextLink = ({ currentIndex }) => { + let next = flatDirectories[currentIndex + 1]; + + if (!config.nextLinks || !next) { + return null; + } + + return ( + + + {next.title} + + + + ); +}; + +const PrevLink = ({ currentIndex }) => { + let prev = flatDirectories[currentIndex - 1]; + + if (!config.prevLinks || !prev) { + return null; + } + + return ( + + + + {prev.title} + + + ); +}; + +const Layout = ({ filename, full, title: _title, ssg = {}, children }) => { + const [menu, setMenu] = useState(false); + const router = useRouter(); + const { route, pathname } = router; + + const filepath = route.slice(0, route.lastIndexOf('/') + 1); + const titles = React.Children.toArray(children).filter(child => + titleType.includes(child.props.mdxType) + ); + const anchors = titles + .filter(child => child.props.mdxType === 'h2') + .map(child => child.props.children); + + useEffect(() => { + if (menu) { + document.body.classList.add('overflow-hidden'); + } else { + document.body.classList.remove('overflow-hidden'); + } + }, [menu]); + + const currentIndex = useMemo( + () => flatDirectories.findIndex(dir => dir.route === pathname), + [flatDirectories, pathname] + ); + + const title = + flatDirectories[currentIndex]?.title || + titles.find(child => child.props.mdxType === 'h1')?.props.children || + 'Untitled'; + + const props = { + filepath: filepath + filename, + route, + }; + + return ( + <> + + + {title} + {config.titleSuffix || ''} + + {config.head ? config.head(props) : null} + +
    + +
    + + + + + {full ? ( + + {children} + + ) : ( + <> + + +
    + {children} +
    + + +
    + + {config.footer ? config.footer(props) : null} +
    +
    {' '} +
    + + )} +
    +
    +
    + + ); +}; + +export default filename => { + return props => ; +}; diff --git a/website/.nextra/nextra-loader.js b/website/.nextra/nextra-loader.js new file mode 100644 index 000000000..b3a4dab9d --- /dev/null +++ b/website/.nextra/nextra-loader.js @@ -0,0 +1,8 @@ +module.exports = function(source, map) { + this.cacheable() + const fileName = this.resourcePath.slice(this.resourcePath.lastIndexOf('/') + 1) + const prefix = `import withNextraLayout from '.nextra/layout'\n\n` + const suffix = `\n\nexport default withNextraLayout("${fileName}")` + source = prefix + source + suffix + this.callback(null, source, map) +} diff --git a/website/.nextra/nextra.js b/website/.nextra/nextra.js new file mode 100644 index 000000000..7b16277c1 --- /dev/null +++ b/website/.nextra/nextra.js @@ -0,0 +1,33 @@ +const path = require('path') + +module.exports = (pluginOptions = { + extension: /\.mdx?$/ +}) => (nextConfig = { + pageExtensions: ['js', 'jsx', 'md', 'mdx'] +}) => { + const extension = pluginOptions.extension || /\.mdx$/ + + return Object.assign({}, nextConfig, { + webpack(config, options) { + config.module.rules.push({ + test: extension, + use: [ + options.defaultLoaders.babel, + { + loader: '@mdx-js/loader', + options: pluginOptions.options + }, + { + loader: path.resolve('.nextra', 'nextra-loader.js') + } + ] + }) + + if (typeof nextConfig.webpack === 'function') { + return nextConfig.webpack(config, options) + } + + return config + } + }) +} diff --git a/website/.nextra/search.js b/website/.nextra/search.js new file mode 100644 index 000000000..511f50b89 --- /dev/null +++ b/website/.nextra/search.js @@ -0,0 +1,149 @@ +import { useMemo, useCallback, useRef, useState, useEffect } from 'react'; +import matchSorter from 'match-sorter'; +import cn from 'classnames'; +import { useRouter } from 'next/router'; +import Link from 'next/link'; + +const Item = ({ title, active, href, onMouseOver, search }) => { + const highlight = title.toLowerCase().indexOf(search.toLowerCase()); + + return ( + + +
  • + {title.substring(0, highlight)} + + {title.substring(highlight, highlight + search.length)} + + {title.substring(highlight + search.length)} +
  • +
    + + ); +}; + +const Search = ({ directories }) => { + const router = useRouter(); + const [show, setShow] = useState(false); + const [search, setSearch] = useState(''); + const [active, setActive] = useState(0); + const input = useRef(null); + + const results = useMemo(() => { + if (!search) return []; + + // Will need to scrape all the headers from each page and search through them here + // (similar to what we already do to render the hash links in sidebar) + // We could also try to search the entire string text from each page + return matchSorter(directories, search, { keys: ['title'] }); + }, [search]); + + const handleKeyDown = useCallback( + (e) => { + switch (e.key) { + case 'ArrowDown': { + e.preventDefault(); + if (active + 1 < results.length) { + setActive(active + 1); + } + break; + } + case 'ArrowUp': { + e.preventDefault(); + if (active - 1 >= 0) { + setActive(active - 1); + } + break; + } + case 'Enter': { + router.push(results[active].route); + break; + } + } + }, + [active, results, router] + ); + + useEffect(() => { + setActive(0); + }, [search]); + + useEffect(() => { + const inputs = ['input', 'select', 'button', 'textarea']; + + const down = (e) => { + if ( + document.activeElement && + inputs.indexOf(document.activeElement.tagName.toLowerCase() !== -1) + ) { + if (e.key === '/') { + e.preventDefault(); + input.current.focus(); + } else if (e.key === 'Escape') { + setShow(false); + } + } + }; + + window.addEventListener('keydown', down); + return () => window.removeEventListener('keydown', down); + }, []); + + const renderList = show && results.length > 0; + + return ( +
    + {renderList && ( +
    setShow(false)} /> + )} +
    + + + +
    + { + setSearch(e.target.value); + setShow(true); + }} + className="appearance-none pl-8 border rounded-md py-2 pr-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline w-full" + type="search" + placeholder='Search ("/" to focus)' + onKeyDown={handleKeyDown} + onFocus={() => setShow(true)} + ref={input} + aria-label="Search documentation" + /> + {renderList && ( +
      + {results.map((res, i) => { + return ( + setActive(i)} + /> + ); + })} +
    + )} +
    + ); +}; + +export default Search; diff --git a/website/.nextra/ssg.js b/website/.nextra/ssg.js new file mode 100644 index 000000000..2e4fb8f9a --- /dev/null +++ b/website/.nextra/ssg.js @@ -0,0 +1,6 @@ +import { createContext, useContext } from 'react' + +const SSGContext = createContext({}) + +export default SSGContext +export const useSSG = () => useContext(SSGContext) diff --git a/website/.nextra/styles.css b/website/.nextra/styles.css new file mode 100644 index 000000000..50350ac2a --- /dev/null +++ b/website/.nextra/styles.css @@ -0,0 +1,211 @@ +@tailwind base; + +html { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', + 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; +} +@supports (font-variation-settings: normal) { + html { + font-family: 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', + 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', + 'Helvetica Neue', sans-serif; + } +} + +html { + @apply subpixel-antialiased; + font-size: 16px; + font-feature-settings: 'rlig' 1, 'calt' 1, 'ss01' 1; +} +body { + @apply bg-white; +} + +h1 { + @apply text-4xl font-bold tracking-tight; +} +h2 { + @apply text-3xl font-semibold tracking-tight mt-10; + @apply border-b; +} +h3 { + @apply text-2xl font-semibold tracking-tight mt-8; +} +h4 { + @apply text-xl font-semibold tracking-tight mt-8; +} +h5 { + @apply text-lg font-semibold tracking-tight mt-8; +} +h6 { + @apply text-base font-semibold tracking-tight mt-8; +} +a { + @apply text-blue-600 underline; +} +p { + @apply mt-6 leading-7; +} +hr { + @apply my-8; +} +code { + @apply p-1 text-sm text-gray-800 bg-gray-500 bg-opacity-25 rounded; +} +pre { + @apply p-4 bg-gray-200 rounded-lg mt-6 mb-4 overflow-x-auto scrolling-touch; +} +pre code { + @apply p-0 text-black bg-transparent rounded-none; +} +a code { + @apply text-current no-underline; +} +figure { + @apply mb-8 relative; +} +video { + @apply absolute top-0 left-0; + cursor: pointer; +} +figure figcaption { + @apply text-sm text-gray-600; +} +@media (min-width: 768px) { + figure { + /* allow figures to overflow, but not exceeding the viewport width */ + @apply -mr-56; + max-width: calc(100vw - 20rem); + } +} + +table { + @apply my-8 w-full text-gray-700 text-sm; +} + +table > thead > tr { + @apply border-b border-t rounded-t-lg; +} + +table > thead > tr > th { + @apply px-3 py-2 text-left text-sm font-bold bg-gray-200 text-gray-700; +} + +table > tbody > tr { + @apply border-b; +} + +table > tbody > tr > td { + @apply p-3; +} + +table > tbody > tr > td:not(:first-child) > code { + @apply text-xs; +} + +table > tbody > tr > td > a > code, +table > tbody > tr > td > code { + @apply text-sm; +} +table > tbody > tr > td > a { + @apply text-blue-600 font-semibold transition-colors duration-150 ease-out; +} +table > tbody > tr > td > a:hover { + @apply text-blue-800 transition-colors duration-150 ease-out; +} +@tailwind components; +@tailwind utilities; + +.main-container { + min-height: 100vh; +} + +.sidebar { + @apply select-none; +} +.sidebar ul ul { + @apply ml-5; +} +.sidebar a:focus-visible, +.sidebar button:focus-visible { + @apply shadow-outline; +} +.sidebar li.active > a { + @apply font-semibold text-black bg-gray-200; +} +.sidebar button, +.sidebar a { + @apply block w-full text-left text-base text-black no-underline text-gray-600 mt-1 p-2 rounded select-none outline-none; + -webkit-tap-highlight-color: transparent; + -webkit-touch-callout: none; +} +.sidebar a:hover, +.sidebar button:hover { + @apply text-gray-900 bg-gray-100; +} + +.sidebar .active-route > button { + @apply text-black font-medium; +} + +.sidebar .active-route > button:hover { + @apply text-current bg-transparent cursor-default; +} + +content ul { + @apply list-disc ml-6 mt-6; +} +content li { + @apply mt-2; +} +.subheading-anchor { + margin-top: -84px; + display: inline-block; + position: absolute; + width: 1px; +} + +.subheading-anchor + a:hover .anchor-icon, +.subheading-anchor + a:focus .anchor-icon { + opacity: 1; +} +.anchor-icon { + opacity: 0; + @apply ml-2 text-gray-500; +} + +h2 a { + @apply no-underline; +} +input[type='search']::-webkit-search-decoration, +input[type='search']::-webkit-search-cancel-button, +input[type='search']::-webkit-search-results-button, +input[type='search']::-webkit-search-results-decoration { + -webkit-appearance: none; +} + +.search-overlay { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--category-header span { + display: inline-block; +} +.algolia-autocomplete .ds-dropdown-menu { + width: 500px; + min-width: 300px; + max-width: calc(100vw - 50px); +} + +[data-reach-skip-link] { + @apply sr-only; +} + +[data-reach-skip-link]:focus { + @apply not-sr-only fixed ml-6 top-0 bg-white text-lg px-6 py-2 mt-2 outline-none shadow-outline z-50; +} diff --git a/website/.nextra/theme.js b/website/.nextra/theme.js new file mode 100644 index 000000000..e27834972 --- /dev/null +++ b/website/.nextra/theme.js @@ -0,0 +1,194 @@ +import { MDXProvider } from '@mdx-js/react'; +import * as ReactDOM from 'react-dom/server'; +import Link from 'next/link'; +import Highlight, { defaultProps } from 'prism-react-renderer'; +import stripHtml from 'string-strip-html'; +import slugify from '@sindresorhus/slugify'; + +const THEME = { + plain: { + color: '#000', + backgroundColor: 'transparent', + }, + styles: [ + { + types: ['keyword'], + style: { + color: '#ff0078', + fontWeight: 'bold', + }, + }, + { + types: ['comment'], + style: { + color: '#999', + fontStyle: 'italic', + }, + }, + { + types: ['string', 'url', 'attr-value'], + style: { + color: '#028265', + }, + }, + { + types: ['builtin', 'char', 'constant', 'language-javascript'], + style: { + color: '#000', + }, + }, + { + types: ['attr-name'], + style: { + color: '#d9931e', + fontStyle: 'normal', + }, + }, + { + types: ['punctuation', 'operator'], + style: { + color: '#333', + }, + }, + { + types: ['number', 'function', 'tag'], + style: { + color: '#0076ff', + }, + }, + { + types: ['boolean', 'regex'], + style: { + color: '#d9931e', + }, + }, + ], +}; + +// Anchor links + +const HeaderLink = ({ tag: Tag, children, ...props }) => { + const slug = slugify(ReactDOM.renderToString(children) || ''); + return ( + + + + {children} + + # + + + + ); +}; + +const H2 = ({ children, ...props }) => { + return ( + + {children} + + ); +}; + +const H3 = ({ children, ...props }) => { + return ( + + {children} + + ); +}; + +const H4 = ({ children, ...props }) => { + return ( + + {children} + + ); +}; + +const H5 = ({ children, ...props }) => { + return ( + + {children} + + ); +}; + +const H6 = ({ children, ...props }) => { + return ( + + {children} + + ); +}; + +const A = ({ children, ...props }) => { + const isExternal = props.href?.startsWith('https://'); + if (isExternal) { + return ( + + {children} + + ); + } + return ( + + {children} + + ); +}; + +const Code = ({ children, className, highlight, ...props }) => { + if (!className) return {children}; + + const highlightedLines = highlight ? highlight.split(',').map(Number) : []; + + // https://mdxjs.com/guides/syntax-highlighting#all-together + const language = className.replace(/language-/, ''); + return ( + + {({ className, style, tokens, getLineProps, getTokenProps }) => ( + + {tokens.map((line, i) => ( +
    + {line.map((token, key) => ( + + ))} +
    + ))} +
    + )} +
    + ); +}; + +const components = { + h2: H2, + h3: H3, + h4: H4, + h5: H5, + h6: H6, + a: A, + code: Code, +}; + +export default ({ children }) => { + return {children}; +}; diff --git a/website/README.md b/website/README.md deleted file mode 100755 index 71505291a..000000000 --- a/website/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Website - -This website is built using Docusaurus 2, a modern static website generator. - -### Installation - -``` -$ yarn -``` - -### Local Development - -``` -$ yarn start -``` - -This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. - -### Build - -``` -$ yarn build -``` - -This command generates static content into the `build` directory and can be served using any static contents hosting service. - -### Deployment - -``` -$ GIT_USER= USE_SSH=1 yarn deploy -``` - -If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. diff --git a/website/blog/2019-08-28-hello-tsdx.md b/website/blog/2019-08-28-hello-tsdx.md deleted file mode 100755 index 901702bbb..000000000 --- a/website/blog/2019-08-28-hello-tsdx.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: hello-tsdx -title: Hello TSDX -author: Jared Palmer -authorTitle: Creator -authorURL: https://palmer.net -authorImageURL: https://avatars2.githubusercontent.com/u/4060187?s=180&v=4 -authorTwitter: jaredpalmer -tags: [tsdx] ---- - -Welcome to the tsdx docs! [We set it up today](https://github.com/palmerhq/tsdx/pull/180). diff --git a/website/components/features.js b/website/components/features.js new file mode 100644 index 000000000..1fd11ffcd --- /dev/null +++ b/website/components/features.js @@ -0,0 +1,819 @@ +import React from 'react'; +import styles from './features.module.css'; + +const Feature = ({ text, icon }) => ( +
    + {icon} +

    {text}

    +
    +); + +export default () => ( +
    +

    + Zero-config CLI for TypeScript package development +

    +
    + CJS, ESM, UMD} + icon={ + + + + + } + /> + Treeshaking} + icon={ + + + + + + + + } + /> + + Live Playground + + } + icon={ + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + + + } + /> + + + + } + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } + /> + + + + + + + } + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } + /> + + + + + + + } + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } + /> +
    +
    +); diff --git a/website/components/features.module.css b/website/components/features.module.css new file mode 100644 index 000000000..cba1aec08 --- /dev/null +++ b/website/components/features.module.css @@ -0,0 +1,27 @@ +.features { + display: flex; + flex-wrap: wrap; + margin: 2.5rem -0.5rem 2rem; +} + +.feature { + flex: 0 0 33%; + align-items: center; + display: inline-flex; + padding: 0 0.5rem 1.5rem; + margin: 0 auto; +} +.feature h4 { + margin: 0 0 0 0.5rem; + font-weight: 700; + font-size: 0.95rem; + white-space: nowrap; +} +@media (max-width: 860px) { + .feature { + padding-left: 0; + } + .feature h4 { + font-size: 0.75rem; + } +} diff --git a/website/components/logo.js b/website/components/logo.js new file mode 100644 index 000000000..98be9e794 --- /dev/null +++ b/website/components/logo.js @@ -0,0 +1,28 @@ +import React from 'react'; + +export const Logo = ({ height }) => ( + + + + + + + +); diff --git a/website/components/video.js b/website/components/video.js new file mode 100644 index 000000000..9b4b65ade --- /dev/null +++ b/website/components/video.js @@ -0,0 +1,52 @@ +import React, { useRef, useCallback, useEffect } from 'react'; +import { useInView } from 'react-intersection-observer'; +import 'intersection-observer'; + +export default ({ src, caption, ratio }) => { + const [inViewRef, inView] = useInView({ + threshold: 1, + }); + const videoRef = useRef(); + + const setRefs = useCallback( + node => { + // Ref's from useRef needs to have the node assigned to `current` + videoRef.current = node; + // Callback refs, like the one from `useInView`, is a function that takes the node as an argument + inViewRef(node); + + if (node) { + node.addEventListener('click', function() { + if (this.paused) { + this.play(); + } else { + this.pause(); + } + }); + } + }, + [inViewRef] + ); + + useEffect(() => { + if (!videoRef || !videoRef.current) { + return; + } + + if (inView) { + videoRef.current.play(); + } else { + videoRef.current.pause(); + } + }, [inView]); + + return ( +
    +
    + + {caption &&
    {caption}
    } +
    + ); +}; diff --git a/website/docs/contributing.md b/website/docs/contributing.md deleted file mode 100644 index a19df8192..000000000 --- a/website/docs/contributing.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: contributing -title: Contributor's Guide ---- - -Thanks for your interest in TSDX! You are very welcome to contribute. - -> ⚠️If you are proposing a new feature, make sure to [open an issue](https://github.com/palmerhq/tsdx/issues/new/choose) first to make sure it is inline with the project goals. - -If you'd like to work on any existing issues, [please be our guest](https://github.com/palmerhq/tsdx/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc)! - -## Setup - -0. First, remove any existing `tsdx` global installations that may conflict. - - ``` - yarn global remove tsdx # or npm uninstall -g tsdx - ``` - -1. Fork this repository to your own GitHub account and clone it to your local device: - - ``` - git clone https://github.com/your-name/tsdx.git - cd tsdx - ``` - -1. Install the dependencies and build the Typescript files to Javascript: - - ``` - yarn && yarn build - ``` - - > **Note:** you'll need to run `yarn build` any time you want to see your changes, or run `yarn watch` to leave it in watch mode. - -1. Make it so running `tsdx` anywhere will run your local dev version: - - ``` - yarn link - ``` - -4) To use your local version when running `yarn build`/`yarn start`/`yarn test` in a TSDX project, run this in the project: - - ``` - yarn link tsdx - ``` - - You should see a success message: `success Using linked package for "tsdx".` The project will now use the locally linked version instead of a copy from `node_modules`. - -## Submitting a PR - -Be sure to run `yarn test` before you make your PR to make sure you haven't broken anything. diff --git a/website/docs/docusaurus.md b/website/docs/docusaurus.md deleted file mode 100755 index de0ceb363..000000000 --- a/website/docs/docusaurus.md +++ /dev/null @@ -1,163 +0,0 @@ ---- -id: docusaurus -title: Docusaurus Style Guide ---- - -TSDX docs use Docusaurus. This is their default Style Guide. - -You can write content using [GitHub-flavored Markdown syntax](https://github.github.com/gfm/). - -## Markdown Syntax - -To serve as an example page when styling markdown based Docusaurus sites. - -## Headers - -# H1 - Create the best documentation - -## H2 - Create the best documentation - -### H3 - Create the best documentation - -#### H4 - Create the best documentation - -##### H5 - Create the best documentation - -###### H6 - Create the best documentation - ---- - -## Emphasis - -Emphasis, aka italics, with _asterisks_ or _underscores_. - -Strong emphasis, aka bold, with **asterisks** or **underscores**. - -Combined emphasis with **asterisks and _underscores_**. - -Strikethrough uses two tildes. ~~Scratch this.~~ - ---- - -## Lists - -1. First ordered list item -1. Another item β‹…β‹…\* Unordered sub-list. -1. Actual numbers don't matter, just that it's a number β‹…β‹…1. Ordered sub-list -1. And another item. - -β‹…β‹…β‹…You can have properly indented paragraphs within list items. Notice the blank line above, and the leading spaces (at least one, but we'll use three here to also align the raw Markdown). - -β‹…β‹…β‹…To have a line break without a paragraph, you will need to use two trailing spaces.β‹…β‹… β‹…β‹…β‹…Note that this line is separate, but within the same paragraph.β‹…β‹… β‹…β‹…β‹…(This is contrary to the typical GFM line break behaviour, where trailing spaces are not required.) - -- Unordered list can use asterisks - -* Or minuses - -- Or pluses - ---- - -## Links - -[I'm an inline-style link](https://www.google.com) - -[I'm an inline-style link with title](https://www.google.com "Google's Homepage") - -[I'm a reference-style link][arbitrary case-insensitive reference text] - -[I'm a relative reference to a repository file](../blob/master/LICENSE) - -[You can use numbers for reference-style link definitions][1] - -Or leave it empty and use the [link text itself]. - -URLs and URLs in angle brackets will automatically get turned into links. http://www.example.com or and sometimes example.com (but not on Github, for example). - -Some text to show that the reference links can follow later. - -[arbitrary case-insensitive reference text]: https://www.mozilla.org -[1]: http://slashdot.org -[link text itself]: http://www.reddit.com - ---- - -## Images - -Here's our logo (hover to see the title text): - -Inline-style: ![alt text](https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png 'Logo Title Text 1') - -Reference-style: ![alt text][logo] - -[logo]: https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png 'Logo Title Text 2' - ---- - -## Code - -```javascript -var s = 'JavaScript syntax highlighting'; -alert(s); -``` - -```python -s = "Python syntax highlighting" -print s -``` - -``` -No language indicated, so no syntax highlighting. -But let's throw in a tag. -``` - ---- - -## Tables - -Colons can be used to align columns. - -| Tables | Are | Cool | -| ------------- | :-----------: | -----: | -| col 3 is | right-aligned | \$1600 | -| col 2 is | centered | \$12 | -| zebra stripes | are neat | \$1 | - -There must be at least 3 dashes separating each header cell. The outer pipes (|) are optional, and you don't need to make the raw Markdown line up prettily. You can also use inline Markdown. - -| Markdown | Less | Pretty | -| -------- | --------- | ---------- | -| _Still_ | `renders` | **nicely** | -| 1 | 2 | 3 | - ---- - -## Blockquotes - -> Blockquotes are very handy in email to emulate reply text. This line is part of the same quote. - -Quote break. - -> This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can _put_ **Markdown** into a blockquote. - ---- - -## Inline HTML - -
    -
    Definition list
    -
    Is something people use sometimes.
    - -
    Markdown in HTML
    -
    Does *not* work **very** well. Use HTML tags.
    -
    - ---- - -## Line Breaks - -Here's a line for us to start with. - -This line is separated from the one above by two newlines, so it will be a _separate paragraph_. - -This line is also a separate paragraph, but... This line is only separated by a single newline, so it's a separate line in the _same paragraph_. diff --git a/website/docs/get-started.md b/website/docs/get-started.md deleted file mode 100755 index d51351d1b..000000000 --- a/website/docs/get-started.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: get-started -title: Getting Started ---- - -## Overview - -Despite all the recent hype, setting up a new TypeScript (x React) library can be tough. Between [Rollup](https://github.com/rollup/rollup), [Jest](https://github.com/facebook/jest), `tsconfig`, [Yarn resolutions](https://yarnpkg.com/en/docs/selective-version-resolutions), ESLint, and getting VSCode to play nicely....there is just a whole lot of stuff to do (and things to screw up). TSDX is a zero-config CLI that helps you develop, test, and publish modern TypeScript packages with ease--so you can focus on your awesome new library and not waste another afternoon on the configuration. - -## Features - -TSDX comes with the "battery-pack included" and is part of a complete TypeScript breakfast: - -- Bundles your code with [Rollup](https://github.com/rollup/rollup) and outputs multiple module formats (CJS & ESM by default, and also UMD if you want) plus development and production builds -- Comes with treeshaking, ready-to-rock lodash optimizations, and minification/compression -- Live reload / watch-mode -- Works with React -- Human readable error messages (and in VSCode-friendly format) -- Bundle size snapshots -- Opt-in to extract `invariant` error codes -- Jest test runner setup with sensible defaults via `tsdx test` -- Zero-config, single dependency - -## Quick Start - -``` -npx tsdx create mylib -cd mylib -yarn start -``` - -That's it. You don't need to worry about setting up Typescript or Rollup or Jest or other plumbing. Just start editing `src/index.ts` and go! - -Below is a list of commands you will probably find useful: - -### `npm start` or `yarn start` - -Runs the project in development/watch mode. Your project will be rebuilt upon changes. TSDX has a special logger for your convenience. Error messages are pretty printed and formatted for compatibility VS Code's Problems tab. - - - -Your library will be rebuilt if you make edits. - -### `npm run build` or `yarn build` - -Bundles the package to the `dist` folder. -The package is optimized and bundled with Rollup into multiple formats (CommonJS, UMD, and ES Module). - - - -### `npm test` or `yarn test` - -Runs the test watcher (Jest) in an interactive mode. -By default, runs tests related to files changed since the last commit. - -### `npm run lint` or `yarn lint` - -Runs Eslint with Prettier on .ts and .tsx files. -If you want to customize eslint you can add an `eslint` block to your package.json, or you can run `yarn lint --write-file` and edit the generated `.eslintrc.js` file. diff --git a/website/docs/philosophy.md b/website/docs/philosophy.md deleted file mode 100644 index d6cc93bc3..000000000 --- a/website/docs/philosophy.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -id: philosophy -title: Philosophy ---- - -## Inspiration - -TSDX is ripped out of [Formik's](https://github.com/jaredpalmer/formik) build tooling. TSDX is very similar to [@developit/microbundle](https://github.com/developit/microbundle), but that is because Formik's Rollup configuration and Microbundle's internals have converged around similar plugins over the last year or so. - -### Comparison to Microbundle - -- TSDX includes out-of-the-box test running via Jest -- TSDX includes a bootstrap command and default package template -- TSDX is 100% TypeScript focused. While yes, TSDX does use Babel to run a few optimizations (related to treeshaking and lodash), it does not support custom babel configurations. -- TSDX outputs distinct development and production builds (like React does) for CJS and UMD builds. This means you can include rich error messages and other dev-friendly goodies without sacrificing final bundle size. diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js deleted file mode 100755 index e723980b4..000000000 --- a/website/docusaurus.config.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -module.exports = { - title: 'TSDX', - tagline: 'Zero-config TypeScript package development', - url: 'https://your-docusaurus-test-site.com', - baseUrl: '/', - favicon: 'img/favicon.ico', - organizationName: 'palmerhq', // Usually your GitHub org/user name. - projectName: 'tsdx', // Usually your repo name. - themeConfig: { - navbar: { - // title: 'My Site', - logo: { - alt: 'TSDX Logo', - src: 'img/logo.svg', - }, - links: [ - { to: 'docs/get-started', label: 'Docs', position: 'right' }, - { to: 'help', label: 'Help', position: 'right' }, - { to: 'users', label: 'Users', position: 'right' }, - // { to: 'blog', label: 'Blog', position: 'right' }, - { - href: 'https://github.com/palmerhq/tsdx', - label: 'GitHub', - position: 'right', - }, - ], - }, - footer: { - style: 'light', - links: [ - { - title: 'Docs', - items: [ - { - label: 'Docs', - to: 'docs/get-started', - }, - ], - }, - // { - // title: 'Community', - // items: [ - // { - // label: 'Discord', - // href: 'https://discordapp.com/invite/docusaurus', - // }, - // ], - // }, - { - title: 'Social', - items: [ - { - label: 'Blog', - to: 'blog', - }, - ], - }, - ], - - copyright: `Copyright Β© ${new Date().getFullYear()} The Palmer Group. Built with Docusaurus.`, - }, - }, - presets: [ - [ - '@docusaurus/preset-classic', - { - docs: { - sidebarPath: require.resolve('./sidebars.js'), - }, - theme: { - customCss: require.resolve('./src/css/custom.css'), - }, - }, - ], - ], -}; diff --git a/website/jsconfig.json b/website/jsconfig.json new file mode 100644 index 000000000..b639b0f8f --- /dev/null +++ b/website/jsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "baseUrl": "." + } +} \ No newline at end of file diff --git a/website/next.config.js b/website/next.config.js new file mode 100644 index 000000000..c09e915a8 --- /dev/null +++ b/website/next.config.js @@ -0,0 +1,2 @@ +const withNextra = require('./.nextra/nextra')(); +module.exports = withNextra(); diff --git a/website/nextra.config.js b/website/nextra.config.js new file mode 100644 index 000000000..9febdeee4 --- /dev/null +++ b/website/nextra.config.js @@ -0,0 +1,91 @@ +import React from 'react'; +import { Logo } from 'components/logo'; + +export default { + github: 'https://github.com/formium/tsdx', + titleSuffix: ' – TSDX', + logo: ( + <> + + TSDX + + ), + head: () => ( + <> + {/* Favicons, meta */} + + + + + + + + + + + + + + + + + + + {/* */} + + ), + footer: ({ filepath }) => ( + <> +
    + + A Jared Palmer Project + + + + ), +}; diff --git a/website/package.json b/website/package.json old mode 100755 new mode 100644 index eedc8a949..17281bc0e --- a/website/package.json +++ b/website/package.json @@ -1,31 +1,37 @@ { - "name": "website", - "version": "0.0.0", - "private": true, + "name": "tsdx-site", + "version": "1.0.0", + "description": "", + "main": "index.js", "scripts": { - "docusaurus": "docusaurus", - "start": "docusaurus start", - "build": "docusaurus build", - "swizzle": "docusaurus swizzle", - "deploy": "docusaurus deploy" + "dev": "next", + "start": "next", + "build": "next build" }, + "author": "Jared Palmer", + "license": "MIT", "dependencies": { - "@docusaurus/core": "^2.0.0-alpha.32", - "@docusaurus/preset-classic": "^2.0.0-alpha.32", + "@reach/skip-nav": "^0.10.5", + "@sindresorhus/slugify": "^1.0.0", "classnames": "^2.2.6", - "react": "^16.11.0", - "react-dom": "^16.11.0" + "focus-visible": "^5.1.0", + "intersection-observer": "^0.10.0", + "markdown-to-jsx": "^6.11.4", + "match-sorter": "^4.1.0", + "next": "^9.4.4", + "next-google-fonts": "^1.1.0", + "prism-react-renderer": "^1.1.1", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-intersection-observer": "^8.26.2", + "string-strip-html": "^4.5.0" }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] + "devDependencies": { + "@mdx-js/loader": "^1.6.5", + "babel-plugin-macros": "^2.8.0", + "postcss-preset-env": "^6.7.0", + "preval.macro": "^5.0.0", + "tailwindcss": "^1.4.6", + "title": "^3.4.2" } -} \ No newline at end of file +} diff --git a/website/pages/_app.js b/website/pages/_app.js new file mode 100644 index 000000000..1c0291bd5 --- /dev/null +++ b/website/pages/_app.js @@ -0,0 +1,15 @@ +import React from 'react'; +import '.nextra/styles.css'; +import GoogleFonts from 'next-google-fonts'; + +export default function Nextra({ Component, pageProps }) { + return ( + <> + + + + ); +} diff --git a/website/pages/_document.js b/website/pages/_document.js new file mode 100644 index 000000000..f46b5a21e --- /dev/null +++ b/website/pages/_document.js @@ -0,0 +1,25 @@ +import React from 'react'; +import Document, { Html, Head, Main, NextScript } from 'next/document'; +import { SkipNavLink } from '@reach/skip-nav'; + +class MyDocument extends Document { + render() { + return ( + + + + +
    + +