Skip to content

Commit

Permalink
chore: add docs automation
Browse files Browse the repository at this point in the history
  • Loading branch information
PedroBern committed Feb 2, 2021
1 parent efcaf65 commit f2aacf5
Show file tree
Hide file tree
Showing 17 changed files with 927 additions and 113 deletions.
310 changes: 206 additions & 104 deletions README.md

Large diffs are not rendered by default.

143 changes: 143 additions & 0 deletions documentation/README_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# react-native-collapsible-tab-view

[![Build Status][build-badge]][build]
[![Version][version-badge]][package]
[![MIT License][license-badge]][license]
[![runs with expo][expo-badge]][expo]

> Due to time constraints we weren't able to finish the documentation yet. You can navigate through the code and examples.
- [Expo app](#expo-app)
- [Demo](#demo)
- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Guides](#guides)
- [Scroll on header](#scroll-on-header)
- [API reference](#api-reference)
- [createCollapsibleTabs](#createcollapsibletabs)
- [Tabs.Container](#tabscontainer)
- [Tabs.Lazy](#tabslazy)
- [Tabs.FlatList](#tabsflatlist)
- [Tabs.ScrollView](#tabsscrollview)
- [useTabsContext](#usetabscontext)
- [useCollapsibleStyle](#usecollapsiblestyle)
- [useTabNameContext](#usetabnamecontext)
- [Default Tab Bar](#default-tab-bar)
- [MaterialTabBar](#materialtabbar)
- [MaterialTabItem](#materialtabitem)
- [Contributing](#contributing)
- [Documentation changes](#documentation-changes)

# Expo app

> If you are looking for the integration with [react-native-tab-view](https://github.com/satya164/react-native-tab-view) and/or [react-navigation](https://github.com/react-navigation/react-navigation), you need to use the [v2](https://github.com/PedroBern/react-native-collapsible-tab-view/tree/v2), we are currenlty on v3.
Collapsible Tab View for React Native, with [Reanimated](https://github.com/software-mansion/react-native-reanimated).

- [View it with Expo](https://expo.io/@pedrobern/react-native-collapsible-tab-view-demos).
- Checkout the [examples](https://github.com/PedroBern/react-native-collapsible-tab-view/tree/main/example) for the source code of the Expo app.

<a href="https://expo.io/@pedrobern/react-native-collapsible-tab-view-demos"><img src="https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=exp://exp.host/@pedrobern/react-native-collapsible-tab-view-demos" height="200px" width="200px"></a>

**Credits**

The [react-native-tab-view](https://github.com/satya164/react-native-tab-view) example app was used as template for the demos.

# Demo

| Default | Snap | DiffClamp | DiffClamp + Snap |
| :--------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------: |
| <img src="https://github.com/PedroBern/react-native-collapsible-tab-view/raw/main/demo/default.gif" width="360"> | <img src="https://github.com/PedroBern/react-native-collapsible-tab-view/raw/main/demo/snap.gif" width="360"> | <img src="https://github.com/PedroBern/react-native-collapsible-tab-view/raw/main/demo/diffClamp.gif" width="360"> | <img src="https://github.com/PedroBern/react-native-collapsible-tab-view/raw/main/demo/diffClamp_snap.gif" width="360"> |

<!-- todo -->

# Features

- Animations and interactions on the UI thread
- Highly customizable
- Fully typed with [TypeScript](https://typescriptlang.org)
- Lazy support with fade-in animation
- DiffClamp header
- Interpolated header
- Scroll snap (with interpolated header)
- Animated snap (with diffClamp header)
- Scrollable tabs, inspired by the [react-native-tab-view](https://github.com/satya164/react-native-tab-view) tab bar
- Support horizontal and vertical window

# Installation

Open a Terminal in the project root and run:

```sh
yarn add react-native-collapsible-tab-view
```

Then, add Reanimated v2, [follow the official installation guide](https://docs.swmansion.com/react-native-reanimated/docs/next/installation).

# Quick Start

```tsx
$QUICK_START_CODE
```

# Guides

## Scroll on header

If you want to allow scrolling from the header:

- If the `HeaderComponent` **doesn't** contain touchables set `pointerEvents='none'`
- If `HeaderComponent` **does** contain touchables set `pointerEvents='box-none'` for them to work.

_Note: With this setting any child component that should **not** respond to touches (e.g. `<Image />`) needs to have `pointerEvents` set to `'none'`. Otherwise it can become the target of a touch gesture on iOS devices and thereby preventing scrolling._

# API reference

$CORE_API

$CORE_COMPONENTS_API

## Default Tab Bar

$TAB_BAR_API

# Contributing

While developing, you can run the [example app](/example/README.md) to test your changes.

Please follow the [angular commit message format](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-format).

Make sure your code passes TypeScript and ESLint. Run the following to verify:

```sh
yarn typescript
yarn lint
```

To fix formatting errors, run the following:

```sh
yarn lint -- --fix
```

Remember to add tests for your change if possible.

## Documentation changes

Edit the [README_TEMPLATE](https://github.com/PedroBern/react-native-collapsible-tab-view/tree/main/documentation/README_TEMPLATE.md), or update the docstrings inside the `src` folder, and run:

```sh
yarn docs
```

<!-- badges -->

[build-badge]: https://img.shields.io/circleci/build/github/PedroBern/react-native-collapsible-tab-view/main.svg?style=flat-square
[build]: https://app.circleci.com/pipelines/github/PedroBern/react-native-collapsible-tab-view
[version-badge]: https://img.shields.io/npm/v/react-native-collapsible-tab-view.svg?style=flat-square
[package]: https://www.npmjs.com/package/react-native-collapsible-tab-view
[license-badge]: https://img.shields.io/npm/l/react-native-collapsible-tab-view.svg?style=flat-square
[license]: https://opensource.org/licenses/MIT
[expo-badge]: https://img.shields.io/badge/Runs%20with%20Expo-4630EB.svg?style=flat-square&logo=EXPO&labelColor=f3f3f3&logoColor=000
[expo]: https://github.com/expo/expo
31 changes: 31 additions & 0 deletions documentation/buildDocs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* nasty script to build a funky docs.
*/

const fs = require('fs')
const path = require('path')

const getCoreAPI = require('./getCoreAPI')
const getCoreComponentsAPI = require('./getCoreComponentsAPI')
const getQuickStartCode = require('./getQuickStartCode')
const getTabBarAPI = require('./getTabBarAPI')

const TEMPLATE = path.join(__dirname, 'README_TEMPLATE.md')
const README = path.join(__dirname, '..', 'README.md')

fs.copyFileSync(TEMPLATE, README)
let data = fs.readFileSync(README, 'utf-8')

const coreAPI = getCoreAPI()
const coreComponentsAPI = getCoreComponentsAPI()
const tabBarAPI = getTabBarAPI()
const quickStartCode = getQuickStartCode()

data = data.replace('$CORE_API', coreAPI)
data = data.replace('$CORE_COMPONENTS_API', coreComponentsAPI)
data = data.replace('$TAB_BAR_API', tabBarAPI)
data = data.replace('$QUICK_START_CODE', quickStartCode)

fs.writeFileSync(README, data)

export {}
18 changes: 18 additions & 0 deletions documentation/getCoreAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const path = require('path')

const getFunctionDocstring = require('./getFunctionDocstring')

const basePath = path.join(__dirname, '../src')

const inputFile = path.join(basePath, 'createCollapsibleTabs.tsx')
const functionName = 'createCollapsibleTabs'

const getCoreAPI = () => {
let docs = '## ' + functionName + '\n\n'
docs += getFunctionDocstring(inputFile, functionName)
return docs
}

module.exports = getCoreAPI

export {}
86 changes: 86 additions & 0 deletions documentation/getCoreComponentsAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
const fs = require('fs')
const path = require('path')
const docgen = require('react-docgen-typescript')

const generateMarkdown = require('./mdGenerator')

const options = {
savePropValueAsString: true,
propFilter: (prop: any, component: any) => {
if (
prop.parent ||
component.name === 'Tabs.FlatList' ||
component.name === 'Tabs.ScrollView'
) {
return false
}

return true
},
componentNameResolver: (exp: any, _source: any) => {
return exp.escapedName.startsWith('Use')
? exp.escapedName.replace('Use', 'use')
: 'Tabs.' + exp.escapedName
},
}

const tsconfig = path.join(__dirname, '../tsconfig.json')
const docs = docgen.withCustomConfig(tsconfig, options)

const basePath = path.join(__dirname, '../src')

const paths = {
createCollapsibleTabs: path.join(basePath, 'createCollapsibleTabs.tsx'),
createCollapsibleTabs_tmp: path.join(
basePath,
'createCollapsibleTabs_tmp.tsx'
),
}

// copy createCollapsibleTabs
const getCoreComponents = () => {
fs.copyFileSync(paths.createCollapsibleTabs, paths.createCollapsibleTabs_tmp)
let data = fs.readFileSync(paths.createCollapsibleTabs_tmp, 'utf-8')

// remove HOC from createCollapsibleTabs
let regex = new RegExp('const createCollapsibleTabs.*', 'gm')
data = data.replace(regex, 'type T = string')

// remove the hoc closing bracket
regex = new RegExp('}(?=\n*const styles)', 'mg')
data = data.replace(regex, '')

// replace each hook
regex = new RegExp('.*function useTabsContext.*', 'mg')
data = data.replace(regex, 'function UseTabsContext(c: ContextType<T>) {')

regex = new RegExp('.*function useTabNameContext.*', 'mg')
data = data.replace(regex, 'function UseTabNameContext(c: {name: T}) {')

regex = new RegExp('.*function useCollapsibleStyle.*', 'mg')
data = data.replace(
regex,
'function UseCollapsibleStyle(c: CollapsibleStyle) {'
)

// export everything
data +=
'export { Container, Lazy, FlatList, ScrollView, UseTabsContext, UseCollapsibleStyle }'

return data
}

const getCoreComponentsAPI = () => {
const core = getCoreComponents()
fs.writeFileSync(paths.createCollapsibleTabs_tmp, core)
const core_docs = docs.parse(paths.createCollapsibleTabs_tmp)
const md = core_docs.map((c: string) => generateMarkdown(c)).join('\n')
fs.unlink(paths.createCollapsibleTabs_tmp, (err: any) => {
if (err) throw err
})
return md
}

module.exports = getCoreComponentsAPI

export {}
45 changes: 45 additions & 0 deletions documentation/getFunctionDocstring.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const { TSDocParser } = require('@microsoft/tsdoc')
const fs = require('fs')

const Formatter = require('./tsDocsFormatter')

function getFunctionDocstring(
inputFile: string,
functionName: string,
raw: boolean = false
): void {
const inputBuffer: string = fs.readFileSync(inputFile).toString()

// need to skip empty lines between docstring and function name
// the regex is wrong
const regex = new RegExp(
'\\/\\*\\*\n.*(const|function) ' + functionName,
'gms'
)
let docstring = inputBuffer.match(regex)
if (!docstring) {
console.log(docstring)
const errorMessage = 'Function not found for ' + functionName
console.log(errorMessage)
throw new Error('Function not found for ')
}
docstring = docstring[0].split('\n')
docstring.pop()
// @ts-ignore
docstring = docstring.join('\n')

// @ts-ignore
if (raw) return docstring

// NOTE: Optionally, can provide a TSDocConfiguration here
const tsdocParser = new TSDocParser()
const parserContext = tsdocParser.parseString(docstring)

const docComment = parserContext.docComment

return Formatter.renderDocNode(docComment.summarySection)
}

module.exports = getFunctionDocstring

export {}
13 changes: 13 additions & 0 deletions documentation/getQuickStartCode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const fs = require('fs')
const path = require('path')

const file = path.join(__dirname, '../example/src/Shared/QuickStartDemo.tsx')

const getQuickStartCode = () => {
const md = fs.readFileSync(file, 'utf-8')
return md
}

module.exports = getQuickStartCode

export {}
49 changes: 49 additions & 0 deletions documentation/getTabBarAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const path = require('path')
const docgen = require('react-docgen-typescript')

const generateMarkdown = require('./mdGenerator')

const basePath = path.join(__dirname, '../src/MaterialTabBar')

const paths = {
TabBar: path.join(basePath, 'TabBar.tsx'),
TabItem: path.join(basePath, 'TabItem.tsx'),
}

const options = {
savePropValueAsString: true,
propFilter: (prop: any, _component: any) => {
if (prop.parent) return false
return true
},
componentNameResolver: (exp: any, _source: any) => {
return 'Material' + exp.escapedName
},
}

const tsconfig = path.join(__dirname, '../tsconfig.json')
const docs = docgen.withCustomConfig(tsconfig, options)

const getTabBarAPI = () => {
let md = ''

const tabBarDocs = docs.parse(paths.TabBar)
const TabItemDocs = docs.parse(paths.TabItem)

md += tabBarDocs
.map((c: any) =>
c.displayName.indexOf('FunctionComponent') === -1
? generateMarkdown(c)
: ''
)
.join('\n')
md += TabItemDocs.map((c: any) =>
c.displayName.indexOf('FunctionComponent') === -1 ? generateMarkdown(c) : ''
).join('\n')

return md
}

module.exports = getTabBarAPI

export {}
Loading

0 comments on commit f2aacf5

Please sign in to comment.