master 5f9ae76b4002 cached
15 files
16.2 KB
5.0k tokens
4 symbols
1 requests
Download .txt
Repository: wechat-miniprogram/kbone-template-react
Branch: master
Commit: 5f9ae76b4002
Files: 15
Total size: 16.2 KB

Directory structure:
gitextract_ok9soqir/

├── .babelrc
├── .gitignore
├── LICENSE
├── README.md
├── build/
│   ├── miniprogram.config.js
│   ├── webpack.base.config.js
│   ├── webpack.dev.config.js
│   ├── webpack.mp.config.js
│   └── webpack.prod.config.js
├── index.html
├── package.json
└── src/
    ├── components/
    │   └── counter/
    │       ├── index.css
    │       └── index.jsx
    ├── index.jsx
    └── log.jsx

================================================
FILE CONTENTS
================================================

================================================
FILE: .babelrc
================================================
{
    "presets": [
        "env",
        "stage-3",
        "react"
    ],
    "plugins": [
        "transform-runtime"
    ]
}

================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next

# others
.idea
.DS_Store
dist


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2019 wechat-miniprogram

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# react-kbone

使用 react 多端开发(小程序和Web),基于 [kbone](https://github.com/Tencent/kbone) 的 element 和 render。

## 特性

* 一键接入,立即使用
* 支持完整 JSX 语法,任意位置任意方式书写 JSX

## 一套语法多端运行

```jsx
function Counter() {
  const [count, setCount] = useState(0)
  return (
    <div>
      <button onClick={() => setCount(count - 1)}>-</button>
      <span>{count}</span>
      <button onClick={() => setCount(count + 1)}>+</button>
      <div onClick={clickHandle}>跳转</div>
    </div>
  )
}

function clickHandle() {
  if ('undefined' != typeof wx && wx.getSystemInfoSync) {
    wx.navigateTo({
      url: '../log/index?id=1',
    })
  } else {
    location.href = 'log.html'
  }
}

export default Counter
```

## 快速开始

```
npx kbone-cli init my-app
cd my-app
npm run mp        // 开发小程序
npm run build:mp  // 构建小程序
npm run web       // 开发 web
npm run build     // 构建 web
```


## 目录说明

```
├─ dist
│  ├─ mp     // 微信开发者工具指向的目录,用于生产环境
│  ├─ web    // web 编译出的文件,用于生产环境
├─ build     // 构建相关
├─ src
│  ├─ assets
│  ├─ components     // 存放所有组件
│  ├─ log.jsx        // 入口文件,会 build 成 log.html
│  └─ index.jsx      // 入口文件,会 build 成 index.html
```

## 注意事项

react 并没有提供根组件实例的销毁方法(如 vue.$destroy),所以在多页应用中页面关闭时不会触发该页面组件的 componentWillUnmount 钩子。开发者可自行监听 wxunload 或 beforeunload 事件来进行页面的销毁工作,比如调用 render 方法渲染一个空节点,强行触发页面组件的 componentWillUnmount 钩子。

## 谁在使用 kbone?

<table>
	<tbody>
		<tr>
			<td>
        <a target="_blank" href="https://developers.weixin.qq.com/community/develop/mixflow">
          <img width="200px" src="https://raw.githubusercontent.com/wechat-miniprogram/kbone/develop/docs/images/code1.jpg">
        </a>
      </td>
			<td>
        <a target="_blank" href="http://omijs.org">
          <img width="200px" src="https://github.com/Tencent/omi/raw/master/assets/omi-cloud.jpg">
        </a>
      </td>
			<td width="92px">
        <a target="_blank" href="https://github.com/Tencent/omi/issues/new">告诉我们</a>
      </td>
    </tr>
  </tbody>
</table>

## License

MIT 


================================================
FILE: build/miniprogram.config.js
================================================
/**
 * 配置参考:https://wechat-miniprogram.github.io/kbone/docs/config/
 */

module.exports = {
    origin: 'https://test.miniprogram.com',
    entry: '/',
    router: {
        home: [
            '/(home|index)?',
            '/index.html',
            '/test/(home|index)',
        ],
        other: [
            '/test/list/:id',
            '/test/detail/:id',
        ],
    },
    redirect: {
        notFound: 'home',
        accessDenied: 'home',
    },
    generate: {
        autoBuildNpm: 'npm',
    },
    app: {
        navigationBarTitleText: 'miniprogram-project',
    },
	appExtraConfig: {
        sitemapLocation: 'sitemap.json',
	},
    global: {},
    pages: {},
    optimization: {
		domSubTreeLevel: 10,

		elementMultiplexing: true,
		textMultiplexing: true,
		commentMultiplexing: true,
		domExtendMultiplexing: true,

		styleValueReduce: 5000,
		attrValueReduce: 5000,
	},
    projectConfig: {
        projectname: 'kbone-template-react',
        appid: '',
    },
}


================================================
FILE: build/webpack.base.config.js
================================================
const path = require('path')

module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    index: path.resolve(__dirname, '../src/index.jsx'),
    log: path.resolve(__dirname, '../src/log.jsx'),
  },
  output: {
    path: path.resolve(__dirname, '../dist/web'),
    filename: '[name].js',
    publicPath: '/',
  },
  module: {
    rules: [
      {
        test: /\.[t|j]sx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]',
        },
      },
    ],
  },
  resolve: {
    extensions: ['*', '.js', '.jsx', '.json']
  },
}


================================================
FILE: build/webpack.dev.config.js
================================================
const webpack = require('webpack')
const { merge } = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.config')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const portfinder = require('portfinder')

const htmlPluginList = Object.keys(baseWebpackConfig.entry).map(name => {
  return new HtmlWebpackPlugin({
    filename: `${name}.html`,
    template: 'index.html',
    inject: true,
    chunks: [name],
  })
})

const devWebpackConfig = merge(baseWebpackConfig, {
  mode: 'development',
  devServer: {
    historyApiFallback: {
      rewrites: [{from: /.*/, to: '/index.html'}],
    },
    hot: true,
    compress: true,
    host: process.env.HOST || 'localhost',
    port: +process.env.PORT || 8080,
    open: true, // 自动打开浏览器
    client: {
      logging: 'warn',
      overlay: { // 展示全屏报错
        warnings: false,
        errors: true
      },
    },
    static: {
      publicPath: '/',
    },
    proxy: {},
  },
  watchOptions: {
    poll: false,
  },
  devtool: 'cheap-module-eval-source-map',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"development"',
      },
    }),
    new webpack.HotModuleReplacementPlugin(),
    ...htmlPluginList,
  ],
})

module.exports = new Promise((resolve, reject) => {
  portfinder.basePort = +process.env.PORT || 8080
  portfinder.getPort((err, port) => {
    if (err) {
      reject(err)
    } else {
      devWebpackConfig.devServer.port = port

      resolve(devWebpackConfig)
    }
  })
})


================================================
FILE: build/webpack.mp.config.js
================================================
const path = require('path')
const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const MpPlugin = require('mp-webpack-plugin')

const isOptimize = false // 是否压缩业务代码,开发者工具可能无法完美支持业务代码使用到的 es 特性,建议自己做代码压缩

module.exports = {
  mode: 'production',
  entry: {
    index: path.resolve(__dirname, '../src/index.jsx'),
    log: path.resolve(__dirname, '../src/log.jsx'),
  },
  output: {
    path: path.resolve(__dirname, '../dist/mp/common'), // 放到小程序代码目录中的 common 目录下
    filename: '[name].js', // 必需字段,不能修改
    library: 'createApp', // 必需字段,不能修改
    libraryExport: 'default', // 必需字段,不能修改
    libraryTarget: 'window', // 必需字段,不能修改
  },
  target: 'web', // 必需字段,不能修改
  optimization: {
    runtimeChunk: false, // 必需字段,不能修改
    splitChunks: {
      // 代码分隔配置,不建议修改
      chunks: 'all',
      minSize: 1000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 100,
      maxInitialRequests: 100,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    },

    minimizer: isOptimize
      ? [
          // 压缩CSS
          new OptimizeCSSAssetsPlugin({
            assetNameRegExp: /\.(css|wxss)$/g,
            cssProcessor: require('cssnano'),
            cssProcessorPluginOptions: {
              preset: [
                'default',
                {
                  discardComments: {
                    removeAll: true,
                  },
                  minifySelectors: false, // 因为 wxss 编译器不支持 .some>:first-child 这样格式的代码,所以暂时禁掉这个
                },
              ],
            },
            canPrint: false,
          }),
          // 压缩 js
          new TerserPlugin({
            test: /\.js(\?.*)?$/i,
            parallel: true,
          }),
        ]
      : [],
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
      {
        test: /\.[t|j]sx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]',
        },
      },
    ],
  },
  resolve: {
    extensions: ['*', '.js', '.jsx', '.json'],
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.isMiniprogram': process.env.isMiniprogram, // 注入环境变量,用于业务代码判断
    }),
    new MiniCssExtractPlugin({
      filename: '[name].wxss',
    }),
    new MpPlugin(require('./miniprogram.config')),
  ],
}


================================================
FILE: build/webpack.prod.config.js
================================================
const path = require('path')
const webpack = require('webpack')
const { merge } = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.config')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')

const htmlPluginList = Object.keys(baseWebpackConfig.entry).map(name => {
  return new HtmlWebpackPlugin({
    filename: path.resolve(__dirname, `../dist/web/${name}.html`),
    template: 'index.html',
    inject: true,
    minify: {
      removeComments: true,
      collapseWhitespace: true,
      removeAttributeQuotes: true,
    },
    chunks: [name],
  })
})

const webpackConfig = merge(baseWebpackConfig, {
  mode: 'production',
  output: {
    path: path.resolve(__dirname, '../dist/web'),
    filename: path.posix.join('static', 'js/[name].[chunkhash].js'),
    chunkFilename: path.posix.join('static', 'js/[id].[chunkhash].js'),
  },
  optimization: {
    splitChunks: {
      // 代码分割配置
      chunks: 'async',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    },
    minimizer: [
      // 压缩CSS
      new OptimizeCSSAssetsPlugin({
        assetNameRegExp: /\.css$/g,
        cssProcessor: require('cssnano'),
        cssProcessorPluginOptions: {
          preset: [
            'default',
            {
              discardComments: {
                removeAll: true,
              },
            },
          ],
        },
        canPrint: false,
      }),
      // 压缩 js
      new TerserPlugin({
        test: /\.js(\?.*)?$/i,
        parallel: true,
      }),
    ],
  },
  devtool: false,
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
    ],
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"',
      },
    }),
    // 分离 css 文件
    new MiniCssExtractPlugin({
      filename: path.posix.join('static', 'css/[name].[hash].css'),
    }),
    ...htmlPluginList,
    // 当 vendor 模块没有改变时,保证模块 id 不变
    new webpack.HashedModuleIdsPlugin(),
  ],
})

module.exports = webpackConfig


================================================
FILE: index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no,minimal-ui, viewport-fit=cover" />
    <meta content="yes"name="apple-mobile-web-app-capable"/>
    <meta content="black"name="apple-mobile-web-app-status-bar-style"/>
    <meta name="format-detection"content="telephone=no, email=no" />
    <title>react</title>
    <style type="text/css">
      #app {
        font-family: 'Avenir', Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-align: center;
        color: #2c3e50;
        margin-top: 60px;
      }
    </style>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

================================================
FILE: package.json
================================================
{
  "name": "react-kbone",
  "version": "0.0.1",
  "description": "",
  "author": "wechat-miniprogram",
  "keywords": [
    "react",
    "kbone",
    "mp"
  ],
  "scripts": {
    "start": "npm run mp",
    "web": "cross-env NODE_ENV=development webpack-dev-server --progress --config build/webpack.dev.config.js",
    "mp": "rimraf dist/mp/common && cross-env NODE_ENV=development webpack --config build/webpack.mp.config.js --watch --progress",
    "build": "rimraf dist/web && cross-env NODE_ENV=production webpack --config build/webpack.prod.config.js --progress",
    "build:mp": "rimraf dist/mp/common && cross-env NODE_ENV=production webpack --config build/webpack.mp.config.js --progress"
  },
  "dependencies": {
    "react": "^16.9.0",
    "react-dom": "^16.9.0"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ],
  "devDependencies": {
    "@webpack-cli/serve": "^1.6.1",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.7.0",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-3": "^6.24.1",
    "cross-env": "^5.0.5",
    "css-loader": "^0.28.7",
    "file-loader": "^1.1.4",
    "html-webpack-plugin": "^4.5.2",
    "mini-css-extract-plugin": "^0.5.0",
    "mp-webpack-plugin": "latest",
    "optimize-css-assets-webpack-plugin": "^5.0.8",
    "portfinder": "^1.0.28",
    "rimraf": "^2.7.1",
    "style-loader": "^2.0.0",
    "stylehacks": "^4.0.3",
    "terser-webpack-plugin": "^4.2.3",
    "webpack": "^4.29.6",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.7.4",
    "webpack-merge": "^5.8.0"
  },
  "license": "MIT"
}


================================================
FILE: src/components/counter/index.css
================================================
span{
  color: red;
}

================================================
FILE: src/components/counter/index.jsx
================================================
import React, { useState } from 'react'
import './index.css'

function Counter() {
  const [count, setCount] = useState(0)
  return (
    <div>
      <button onClick={() => setCount(count - 1)}>-</button>
      <span>{count}</span>
      <button onClick={() => setCount(count + 1)}>+</button>
      <div onClick={clickHandle}>跳转</div>
    </div>
  )
}

function clickHandle() {
  if ('undefined' != typeof wx && wx.getSystemInfoSync) {
    wx.navigateTo({
      url: '../log/index?id=1',
    })
  } else {
    location.href = 'log.html'
  }
}

export default Counter


================================================
FILE: src/index.jsx
================================================
import React from 'react'
import ReactDOM from 'react-dom'
import Counter from './components/counter'

export default function createApp() {
  const container = document.createElement('div')
  container.id = 'app'
  document.body.appendChild(container)

  ReactDOM.render(<Counter />, container)
}

;('undefined' != typeof wx && wx.getSystemInfoSync) || createApp()


================================================
FILE: src/log.jsx
================================================
import React from 'react'
import ReactDOM from 'react-dom'

export default function createApp() {
  const container = document.createElement('div')
  container.id = 'app'
  document.body.appendChild(container)

  ReactDOM.render(<div>我是log页面</div>, container)
}

;('undefined' != typeof wx && wx.getSystemInfoSync) || createApp()
Download .txt
gitextract_ok9soqir/

├── .babelrc
├── .gitignore
├── LICENSE
├── README.md
├── build/
│   ├── miniprogram.config.js
│   ├── webpack.base.config.js
│   ├── webpack.dev.config.js
│   ├── webpack.mp.config.js
│   └── webpack.prod.config.js
├── index.html
├── package.json
└── src/
    ├── components/
    │   └── counter/
    │       ├── index.css
    │       └── index.jsx
    ├── index.jsx
    └── log.jsx
Download .txt
SYMBOL INDEX (4 symbols across 3 files)

FILE: src/components/counter/index.jsx
  function Counter (line 4) | function Counter() {
  function clickHandle (line 16) | function clickHandle() {

FILE: src/index.jsx
  function createApp (line 5) | function createApp() {

FILE: src/log.jsx
  function createApp (line 4) | function createApp() {
Condensed preview — 15 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (19K chars).
[
  {
    "path": ".babelrc",
    "chars": 128,
    "preview": "{\n    \"presets\": [\n        \"env\",\n        \"stage-3\",\n        \"react\"\n    ],\n    \"plugins\": [\n        \"transform-runtime\""
  },
  {
    "path": ".gitignore",
    "chars": 945,
    "preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directo"
  },
  {
    "path": "LICENSE",
    "chars": 1075,
    "preview": "MIT License\n\nCopyright (c) 2019 wechat-miniprogram\n\nPermission is hereby granted, free of charge, to any person obtainin"
  },
  {
    "path": "README.md",
    "chars": 1955,
    "preview": "# react-kbone\n\n使用 react 多端开发(小程序和Web),基于 [kbone](https://github.com/Tencent/kbone) 的 element 和 render。\n\n## 特性\n\n* 一键接入,立即"
  },
  {
    "path": "build/miniprogram.config.js",
    "chars": 989,
    "preview": "/**\n * 配置参考:https://wechat-miniprogram.github.io/kbone/docs/config/\n */\n\nmodule.exports = {\n    origin: 'https://test.mi"
  },
  {
    "path": "build/webpack.base.config.js",
    "chars": 700,
    "preview": "const path = require('path')\n\nmodule.exports = {\n  context: path.resolve(__dirname, '../'),\n  entry: {\n    index: path.r"
  },
  {
    "path": "build/webpack.dev.config.js",
    "chars": 1635,
    "preview": "const webpack = require('webpack')\nconst { merge } = require('webpack-merge')\nconst baseWebpackConfig = require('./webpa"
  },
  {
    "path": "build/webpack.mp.config.js",
    "chars": 2844,
    "preview": "const path = require('path')\nconst webpack = require('webpack')\nconst MiniCssExtractPlugin = require('mini-css-extract-p"
  },
  {
    "path": "build/webpack.prod.config.js",
    "chars": 2607,
    "preview": "const path = require('path')\nconst webpack = require('webpack')\nconst { merge } = require('webpack-merge')\nconst baseWeb"
  },
  {
    "path": "index.html",
    "chars": 799,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initia"
  },
  {
    "path": "package.json",
    "chars": 1679,
    "preview": "{\n  \"name\": \"react-kbone\",\n  \"version\": \"0.0.1\",\n  \"description\": \"\",\n  \"author\": \"wechat-miniprogram\",\n  \"keywords\": [\n"
  },
  {
    "path": "src/components/counter/index.css",
    "chars": 21,
    "preview": "span{\n  color: red;\n}"
  },
  {
    "path": "src/components/counter/index.jsx",
    "chars": 567,
    "preview": "import React, { useState } from 'react'\nimport './index.css'\n\nfunction Counter() {\n  const [count, setCount] = useState("
  },
  {
    "path": "src/index.jsx",
    "chars": 366,
    "preview": "import React from 'react'\nimport ReactDOM from 'react-dom'\nimport Counter from './components/counter'\n\nexport default fu"
  },
  {
    "path": "src/log.jsx",
    "chars": 330,
    "preview": "import React from 'react'\nimport ReactDOM from 'react-dom'\n\nexport default function createApp() {\n  const container = do"
  }
]

About this extraction

This page contains the full source code of the wechat-miniprogram/kbone-template-react GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 15 files (16.2 KB), approximately 5.0k tokens, and a symbol index with 4 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!