feat: manually mirror opencoze's code from bytedance

Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
fanlv
2025-07-20 17:36:12 +08:00
commit 890153324f
14811 changed files with 1923430 additions and 0 deletions

127
frontend/.gitignore vendored Normal file
View File

@@ -0,0 +1,127 @@
# Logs
*.log
*.log.*
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
*.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/
# 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
# OS X temporary files
.DS_Store
# Rush temporary files
common/deploy/
common/temp/
common/autoinstallers/*/.npmrc
**/.rush/temp/
.temp
.pnpm-store/
pnpm-local
autoinstaller*.lock
# Heft
.heft
# pnpm store
.pnpm-store
.eden-mono
dist
dist_*/
!**/auto-generated/*
doc_build
build_cn
## for scm
output
output_resource
.idea
.rush
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
*.tsbuildinfo
log/app.log*
# storybook static assets
storybook-static
**/vscode-prompt/dist/
**/vscode-prompt/public/
.jscpd
lib-ts
packages/builder/card-builder/.vmok
// vscode
.history
# 这是 cloudide 生成的文件,无需提交
core.node.*
*storybook.log
**/typings/auto-generated/idl/
_infra_log
missing-peer-dependencies.json
.cache

70
frontend/.npmignore Normal file
View File

@@ -0,0 +1,70 @@
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
*.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/
# 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
# OS X temporary files
.DS_Store
# Rush temporary files
common/deploy/
common/temp/
common/autoinstallers/*/.npmrc
**/.rush/temp/
# Heft
.heft
.eden-mono

106
frontend/.prettierignore Normal file
View File

@@ -0,0 +1,106 @@
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
*.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/
# 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
# OS X temporary files
.DS_Store
# Rush temporary files
common/deploy/
common/temp/
common/autoinstallers/*/.npmrc
common/changes/
common/scripts/
common/config/**/pnpm-lock.yaml
common/_templates/
**/.rush/temp/
# Heft
.heft
# PIA temp files
.pia
# Build assets
dist
packages/speedy-plugin-pia/lib
# Rush files
CHANGELOG.*
# Emo files
.eden-mono
# Package manager files
pnpm-lock.yaml
yarn.lock
package-lock.json
shrinkwrap.json
.pnpm-store/
# Build outputs
lib
apps/bot/routes_metadata/nestedRoutes.json
# Prettier reformats code blocks inside Markdown, which affects rendered output
*.md
vendors/**/index.d.ts
vendors/**/index.js
tests/configs/src/errors/**
apps/bot/src/typing/env/**

View File

@@ -0,0 +1,3 @@
**/node_modules/**
**/examples/**
**/vendor/**

1
frontend/README.md Normal file
View File

@@ -0,0 +1 @@
TODO: something here

View File

@@ -0,0 +1,5 @@
const { defineConfig } = require('@coze-arch/stylelint-config');
module.exports = defineConfig({
extends: [],
});

View File

@@ -0,0 +1,6 @@
# [🦀️ Rsbuild](https://rsbuild.dev/zh/guide/start/index) & React App
Web项目初始化模板已包含功能
* react + react-router
* slardar
* less(module), [tailwindcss](https://tailwindcss.com/docs)
* vitest

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@@ -0,0 +1,17 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-project.schema.json",
"operationSettings": [
{
"operationName": "build",
"outputFolderNames": ["output"]
},
{
"operationName": "test:cov",
"outputFolderNames": ["coverage"]
},
{
"operationName": "ts-check",
"outputFolderNames": ["dist"]
}
]
}

View File

@@ -0,0 +1,6 @@
const { defineConfig } = require('@coze-arch/eslint-config');
module.exports = defineConfig({
preset: 'web',
packageRoot: __dirname,
});

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@coze-studio/app</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

View File

@@ -0,0 +1,82 @@
{
"name": "@coze-studio/app",
"version": "0.0.1",
"private": true,
"description": "coze studio app",
"keywords": [],
"license": "Apache-2.0",
"author": "fanwenjie.fe@bytedance.com",
"maintainers": [],
"sideEffects": false,
"scripts": {
"build": "IS_OPEN_SOURCE=true rsbuild build",
"dev": "IS_OPEN_SOURCE=true CUSTOM_VERSION=release rsbuild dev",
"lint": "eslint ./ --cache --quiet",
"preview": "rsbuild preview",
"test": "vitest --run --passWithNoTests",
"test:cov": "vitest --run --passWithNoTests --coverage"
},
"dependencies": {
"@coze-agent-ide/agent-publish": "workspace:*",
"@coze-agent-ide/entry-adapter": "workspace:*",
"@coze-agent-ide/layout-adapter": "workspace:*",
"@coze-arch/bot-flags": "workspace:*",
"@coze-arch/bot-md-box-adapter": "workspace:*",
"@coze-arch/coze-design": "0.0.6-alpha.346d77",
"@coze-arch/foundation-sdk": "workspace:*",
"@coze-arch/i18n": "workspace:*",
"@coze-arch/logger": "workspace:*",
"@coze-arch/web-context": "workspace:*",
"@coze-foundation/account-adapter": "workspace:*",
"@coze-foundation/account-ui-adapter": "workspace:*",
"@coze-foundation/foundation-sdk": "workspace:*",
"@coze-foundation/global": "workspace:*",
"@coze-foundation/global-adapter": "workspace:*",
"@coze-foundation/layout": "workspace:*",
"@coze-foundation/space-ui-adapter": "workspace:*",
"@coze-foundation/space-ui-base": "workspace:*",
"@coze-project-ide/main": "workspace:*",
"@coze-studio/api-schema": "workspace:*",
"@coze-studio/default-slardar": "workspace:*",
"@coze-studio/project-publish": "workspace:*",
"@coze-studio/workspace-adapter": "workspace:*",
"@coze-studio/workspace-base": "workspace:*",
"@coze-workflow/playground-adapter": "workspace:*",
"path-browserify": "^1.0.1",
"react": "~18.2.0",
"react-dom": "~18.2.0",
"react-error-boundary": "^4.0.9",
"react-router-dom": "^6.11.1",
"zustand": "^4.4.7"
},
"devDependencies": {
"@coze-arch/bot-env": "workspace:*",
"@coze-arch/bot-typings": "workspace:*",
"@coze-arch/eslint-config": "workspace:*",
"@coze-arch/import-watch-loader": "workspace:*",
"@coze-arch/pkg-root-webpack-plugin": "workspace:*",
"@coze-arch/postcss-config": "workspace:*",
"@coze-arch/responsive-kit": "workspace:*",
"@coze-arch/rsbuild-config": "workspace:*",
"@coze-arch/semi-theme-hand01": "0.0.6-alpha.346d77",
"@coze-arch/stylelint-config": "workspace:*",
"@coze-arch/tailwind-config": "workspace:*",
"@coze-arch/ts-config": "workspace:*",
"@coze-arch/vitest-config": "workspace:*",
"@coze-community/explore": "workspace:*",
"@coze-studio/bot-plugin-store": "workspace:*",
"@rsbuild/core": "~1.1.0",
"@rsdoctor/rspack-plugin": "1.0.0-rc.0",
"@rspack/core": ">=0.7",
"@types/node": "18.18.9",
"@types/react": "18.2.37",
"@types/react-dom": "18.2.15",
"@vitest/coverage-v8": "~3.0.5",
"sucrase": "^3.32.0",
"tailwindcss": "~3.3.3",
"typescript": "~5.8.2",
"vitest": "~3.0.5",
"webpack": "~5.91.0"
}
}

View File

@@ -0,0 +1 @@
module.exports = require('@coze-arch/postcss-config');

View File

@@ -0,0 +1,122 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import path from 'path';
import { defineConfig } from '@coze-arch/rsbuild-config';
import { GLOBAL_ENVS } from '@coze-arch/bot-env';
const API_PROXY_TARGET = `http://localhost:${process.env.WEB_SERVER_PORT || 8888}/`;
const mergedConfig = defineConfig({
server: {
strictPort: true,
proxy: [
{
context: ['/api'],
target: API_PROXY_TARGET,
secure: false,
changeOrigin: true,
},
],
},
html: {
title: '扣子 Studio',
favicon: './assets/favicon.png',
template: './index.html',
crossorigin: 'anonymous',
},
tools: {
postcss: (opts, { addPlugins }) => {
// eslint-disable-next-line @typescript-eslint/no-require-imports
addPlugins([require('tailwindcss')('./tailwind.config.ts')]);
},
rspack(config, { appendPlugins, addRules, mergeConfig }) {
addRules([
{
test: /\.(css|less|jsx|tsx|ts|js)/,
exclude: [
new RegExp('apps/coze-studio/src/index.css'),
/node_modules/,
new RegExp('packages/arch/i18n'),
],
use: '@coze-arch/import-watch-loader',
},
]);
return mergeConfig(config, {
module: {
parser: {
javascript: {
exportsPresence: false,
},
},
},
resolve: {
fallback: {
path: require.resolve('path-browserify'),
},
},
watchOptions: {
poll: true,
},
ignoreWarnings: [
/Critical dependency: the request of a dependency is an expression/,
warning => true,
],
});
},
},
source: {
define: {
'process.env.IS_REACT18': JSON.stringify(true),
// arcosite editor sdk 内部使用
'process.env.ARCOSITE_SDK_REGION': JSON.stringify(
GLOBAL_ENVS.IS_OVERSEA ? 'VA' : 'CN',
),
'process.env.ARCOSITE_SDK_SCOPE': JSON.stringify(
GLOBAL_ENVS.IS_RELEASE_VERSION ? 'PUBLIC' : 'INSIDE',
),
'process.env.TARO_PLATFORM': JSON.stringify('web'),
'process.env.SUPPORT_TARO_POLYFILL': JSON.stringify('disabled'),
'process.env.RUNTIME_ENTRY': JSON.stringify('@coze-dev/runtime'),
'process.env.TARO_ENV': JSON.stringify('h5'),
ENABLE_COVERAGE: JSON.stringify(false),
},
include: [
path.resolve(__dirname, '../../packages'),
path.resolve(__dirname, '../../infra/flags-devtool'),
// 以下几个包包含未降级的 ES 2022 语法private methods需要参与打包
/\/node_modules\/(marked|@dagrejs|@tanstack)\//,
],
alias: {
// TODO: fixme late开源之前需要干掉这个
'@slardar/web/client': '@slardar/web/cn',
'@coze-arch/foundation-sdk': require.resolve(
'@coze-foundation/foundation-sdk',
),
'react-router-dom': require.resolve('react-router-dom'),
},
/**
* support inversify @injectable() and @inject decorators
*/
decorators: {
version: 'legacy',
},
},
});
export default mergedConfig;

View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -ex
# Switch cwd to the project folder
cd $(dirname "$0")
# Import the utilities functions
source ../../scripts/scm_base.sh
# Clean up the build directory
rm -rf dist
rm -rf "${ROOT_DIR}"/output
# Prepare
prepare_environment
# Install the dependencies
CUSTOM_SKIP_POST_INSTALL=true rushx --debug install -t . -t tag:phase-prebuild -t @coze-arch/rush-x -t tag:rush-tools
NO_STARLING=true bash $ROOT_DIR/scripts/post-rush-install.sh
NODE_OPTIONS='--max-old-space-size=8192' NODE_ENV=production npm run build
mkdir -p ${ROOT_DIR}/output
mkdir -p ${ROOT_DIR}/output_resource/static
cp -r ./dist/index.html ${ROOT_DIR}/output/
cp -r ./dist/static/* ${ROOT_DIR}/output_resource/static

View File

@@ -0,0 +1,3 @@
require('sucrase/register');
require('./scripts/serve.ts');

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { RouterProvider } from 'react-router-dom';
import { Suspense } from 'react';
import { Spin } from '@coze-arch/coze-design';
import { router } from './routes';
export function App() {
return (
<Suspense
fallback={
<div className="w-full h-full flex items-center justify-center">
<Spin spinning style={{ height: '100%', width: '100%' }} />
</div>
}
>
<RouterProvider router={router} fallbackElement={<div>loading...</div>} />
</Suspense>
);
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// <reference types="@rsbuild/core/types" />
declare const IS_OVERSEA: boolean;

View File

@@ -0,0 +1,234 @@
// !NOTE: 全局样式代码,不要随便修改!!!
html,
body {
width: 100%;
min-width: 1200px;
height: 100%;
min-height: 600px;
margin: 0;
padding: 0;
// 原来的版本是 冬青(Hiragino) > 苹方;但是项目里大量使用 semi 组件自带 font family没有暴露出来
// 这里修复一下顺序 PingFang > Hiragino
font-family: 'PingFang SC', 'Noto Sans SC', sans-serif;
background: linear-gradient(to bottom, transparent, #fff) #eceeef;
}
body {
// @flowpd/card-web-runtime 依赖 arco design
// arco-design 的 reset css, 搞了 body line-height 1.5
// 没设置 line-height 的元素可能会因为按需加载 arco 产生瞬时抖动
line-height: 1.5;
}
#root {
width: 100%;
height: 100%;
}
p {
margin: 0;
}
* {
box-sizing: border-box;
font-family: 'PingFang SC', 'Noto Sans SC', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
// 去除 safari 浏览器按钮 focus 状态的蓝色框
a:focus,
input:focus,
p:focus,
li:focus,
div:focus,
svg:focus,
a:focus-visible,
input:focus-visible,
p:focus-visible,
li:focus-visible,
div:focus-visible {
outline: none;
-webkit-tap-highlight-color: rgb(0 0 0 / 0% / 0);
}
// TODO: 底层库依赖了这个 class暂时不移除
.operation-admin-base-header {
display: flex;
align-items: flex-end;
justify-content: space-between;
height: 56px;
line-height: 56px;
background-color: #fff;
border-bottom: 1px solid rgb(46 50 56 / 5%);
.semi-tabs-content {
display: none;
}
}
.operation-admin-base-header-title {
display: flex;
align-items: center;
margin: 12px 24px;
font-size: 18px;
line-height: 24px;
color: var(--light-color-grey-grey-9, #1c1f23);
* {
user-select: none;
}
.universe-icon {
margin-right: 6px;
}
}
.operation-admin-base-header-user-avatar {
width: 24px;
height: 24px;
}
.operation-admin-base-header-avatar-method-block {
display: flex;
justify-content: center;
width: 100%;
padding: 8px;
}
.operation-admin-base-header-avatar-sign-out {
text-align: center;
}
.operation-admin-base-aside {
border-right: 1px solid rgb(229 231 235);
// 非本期改动但阻塞了ci的构建
/* stylelint-disable-next-line selector-class-pattern */
.ud__layout__sider-trigger {
border-right: 1px solid rgb(229 231 235);
}
}
.operation-admin-base-app {
height: 100%;
}
.operation-admin-base-module-content {
overflow-y: auto;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.operation-admin-base-module-content[app-name='playground_prompt'] {
background-color: #fff;
}
.operation-admin-base-module-content[app-name='build_bot'] {
background-color: #fff;
}
.operation-admin-base-module-content[app-name='discover'] {
background-color: #fff;
}
.operation-admin-base-404 {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.no-permission {
height: calc(100vh - 64px);
border: 20px solid #f2f3f5;
}
.error-wrapper {
display: flex;
align-items: center;
width: 100%;
height: 100%;
}
.operation-admin-no-permission {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.operation-admin-base-main-content {
overflow: hidden;
}
.operation-admin-base-header-name {
padding: 8px;
padding-bottom: 0;
font-size: 14px;
font-weight: bold;
line-height: 22px;
}
.bp5-overflow-list {
display: flex;
flex-wrap: nowrap;
min-width: 0;
}
.bp5-overflow-list-spacer {
flex-shrink: 1;
width: 1px;
}
// styled-scrollbar 给需要滚动的元素添加的滚动条样式 增加这个 class 即可
.styled-scrollbar::-webkit-scrollbar-thumb {
background-color: rgba(31, 35, 41, 30%);
background-clip: padding-box;
border: 2px solid transparent;
border-radius: 9999px;
transition: background 0.2s cubic-bezier(0.34, 0.69, 0.1, 1);
}
.styled-scrollbar::-webkit-scrollbar {
display: inline-block;
width: 11px;
height: 11px;
background-color: transparent;
}
.styled-scrollbar::-webkit-scrollbar-thumb:hover {
background-color: rgba(31, 35, 41, 60%);
}
.styled-scrollbar::-webkit-scrollbar:hover {
width: 11px;
height: 11px;
}
.styled-scrollbar::-webkit-scrollbar-button {
display: none;
}
.styled-scrollbar::-webkit-scrollbar-track {
background-color: transparent;
}
.styled-scrollbar::-webkit-scrollbar-corner {
background-color: transparent;
}

View File

@@ -0,0 +1,8 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
#root {
width: 100%;
height: 100%;
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createRoot } from 'react-dom/client';
import { initI18nInstance } from '@coze-arch/i18n/raw';
import { dynamicImportMdBoxStyle } from '@coze-arch/bot-md-box-adapter/style';
import { pullFeatureFlags, type FEATURE_FLAGS } from '@coze-arch/bot-flags';
import { App } from './app';
import './global.less';
import './index.less';
const initFlags = () => {
pullFeatureFlags({
timeout: 1000 * 4,
fetchFeatureGating: () => Promise.resolve({} as unknown as FEATURE_FLAGS),
});
};
const main = () => {
// 初始化功能开关的值
initFlags();
// 初始化i18n
initI18nInstance({
lng: (localStorage.getItem('i18next') ?? (IS_OVERSEA ? 'en' : 'zh-CN')) as
| 'en'
| 'zh-CN',
});
// 动态导入mdbox 样式
dynamicImportMdBoxStyle();
const $root = document.getElementById('root');
if (!$root) {
throw new Error('root element not found');
}
const root = createRoot($root);
root.render(<App />);
};
main();

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { GlobalLayout, useAppInit } from '@coze-foundation/global-adapter';
export const Layout = () => {
useAppInit();
return <GlobalLayout />;
};

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useParams } from 'react-router-dom';
import { Develop } from '@coze-studio/workspace-adapter/develop';
const Page = () => {
const { space_id } = useParams();
return space_id ? <Develop spaceId={space_id} /> : null;
};
export default Page;

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useEffect } from 'react';
const DocsRedirect = () => {
useEffect(() => {
location.href = `https://www.coze.cn${location.pathname}`;
}, []);
return null;
};
export default DocsRedirect;

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Navigate, type RouteObject } from 'react-router-dom';
import { lazy } from 'react';
import { BaseEnum } from '@coze-arch/web-context';
const subMenu = lazy(() =>
import('@coze-community/explore').then(exps => ({
default: exps.ExploreSubMenu,
})),
);
const TemplatePage = lazy(() =>
import('@coze-community/explore').then(exps => ({
default: exps.TemplatePage,
})),
);
const PluginPage = lazy(() =>
import('@coze-community/explore').then(exps => ({
default: exps.PluginPage,
})),
);
export const exploreRouter: RouteObject = {
path: 'explore',
Component: null,
loader: () => ({
hasSider: true,
requireAuth: true,
subMenu,
menuKey: BaseEnum.Explore,
}),
children: [
{
index: true,
element: <Navigate to="plugin" replace />,
},
{
path: 'plugin',
element: <PluginPage />,
loader: () => ({
type: 'plugin',
}),
},
{
path: 'template',
element: <TemplatePage />,
loader: () => ({
type: 'template',
}),
},
],
};

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useParams } from 'react-router-dom';
import { LibraryPage } from '@coze-studio/workspace-adapter/library';
const Page = () => {
const { space_id } = useParams();
return space_id ? <LibraryPage spaceId={space_id} /> : null;
};
export default Page;

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Outlet, useNavigate, useParams } from 'react-router-dom';
import { pluginResourceNavigate } from '@coze-studio/workspace-base';
import { BotPluginStoreProvider } from '@coze-studio/bot-plugin-store';
const SpaceLayout = () => {
const { plugin_id, space_id } = useParams();
const navBase = `/space/${space_id}`;
const navigate = useNavigate();
if (!plugin_id || !space_id) {
throw Error('[plugin render error]: need plugin id and space id');
}
return (
<BotPluginStoreProvider
pluginID={plugin_id}
spaceID={space_id}
resourceNavigate={pluginResourceNavigate(navBase, plugin_id, navigate)}
>
<Outlet />
</BotPluginStoreProvider>
);
};
export default SpaceLayout;

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useParams } from 'react-router-dom';
import { useEffect } from 'react';
import { Plugin } from '@coze-studio/workspace-base';
import { usePluginStoreInstance } from '@coze-studio/bot-plugin-store';
const Page = () => {
const { plugin_id, space_id } = useParams();
const pluginStore = usePluginStoreInstance();
if (!plugin_id || !space_id) {
throw Error('[plugin render error]: need plugin id and space id');
}
useEffect(() => {
pluginStore?.getState().init();
}, []);
return <Plugin />;
};
export default Page;

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useParams } from 'react-router-dom';
import { useEffect } from 'react';
import { Tool } from '@coze-studio/workspace-base';
import { usePluginStoreInstance } from '@coze-studio/bot-plugin-store';
const Page = () => {
const { plugin_id, space_id, tool_id } = useParams();
const pluginStore = usePluginStoreInstance();
if (!plugin_id || !space_id || !tool_id) {
throw Error('[plugin render error]: need plugin id and space id');
}
useEffect(() => {
pluginStore?.getState().init();
}, []);
return <Tool toolID={tool_id} />;
};
export default Page;

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useParams } from 'react-router-dom';
import { MocksetDetail } from '@coze-studio/workspace-base';
const Page = () => {
const { plugin_id, space_id, tool_id, mock_set_id } = useParams();
if (!plugin_id || !space_id || !tool_id || !mock_set_id) {
throw Error('[plugin render error]: need plugin id and space id');
}
return (
<MocksetDetail
pluginID={plugin_id}
toolID={tool_id}
spaceID={space_id}
mocksetID={mock_set_id}
/>
);
};
export default Page;

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useParams } from 'react-router-dom';
import { useEffect } from 'react';
import { MocksetList } from '@coze-studio/workspace-base';
import { usePluginStoreInstance } from '@coze-studio/bot-plugin-store';
const Page = () => {
const { plugin_id, space_id, tool_id } = useParams();
const pluginStore = usePluginStoreInstance();
if (!plugin_id || !space_id || !tool_id) {
throw Error('[plugin render error]: need plugin id and space id');
}
useEffect(() => {
pluginStore?.getState().init();
}, []);
return (
<MocksetList pluginID={plugin_id} toolID={tool_id} spaceID={space_id} />
);
};
export default Page;

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useEffect } from 'react';
const Redirect = () => {
useEffect(() => {
location.href = `https://www.coze.cn${location.pathname}`;
}, []);
return null;
};
export default Redirect;

View File

@@ -0,0 +1,312 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createBrowserRouter, Navigate } from 'react-router-dom';
import { lazy } from 'react';
import { SpaceSubModuleEnum } from '@coze-foundation/space-ui-adapter';
import { GlobalError } from '@coze-foundation/layout';
import { BaseEnum } from '@coze-arch/web-context';
import { exploreRouter } from './pages/explore';
import { Layout } from './layout';
const subMenu = lazy(() =>
import('@coze-foundation/space-ui-adapter').then(exps => ({
default: exps.WorkspaceSubMenu,
})),
);
const SpaceLayout = lazy(() =>
import('@coze-foundation/space-ui-adapter').then(exps => ({
default: exps.SpaceLayout,
})),
);
const SpaceIdLayout = lazy(() =>
import('@coze-foundation/space-ui-base').then(exps => ({
default: exps.SpaceIdLayout,
})),
);
const KnowledgePreview = lazy(() =>
import('@coze-studio/workspace-base/knowledge-preview').then(exps => ({
default: exps.KnowledgePreviewPage,
})),
);
const KnowledgeUpload = lazy(() =>
import('@coze-studio/workspace-base/knowledge-upload').then(exps => ({
default: exps.KnowledgeUploadPage,
})),
);
const DatabaseDetail = lazy(() =>
import('@coze-studio/workspace-base').then(exps => ({
default: exps.DatabaseDetailPage,
})),
);
const AgentIDELayout = lazy(() => import('@coze-agent-ide/layout-adapter'));
const AgentIDE = lazy(() =>
import('@coze-agent-ide/entry-adapter').then(res => ({
default: res.BotEditor,
})),
);
const IDELayout = lazy(() =>
import('@coze-project-ide/main').then(exps => ({
default: exps.IDELayout,
})),
);
const IDEPublish = lazy(() =>
import('@coze-studio/project-publish').then(exps => ({
default: exps.ProjectPublish,
})),
);
const Develop = lazy(() => import('./pages/develop'));
const Library = lazy(() => import('./pages/library'));
const WorkflowPage = lazy(() =>
import('@coze-workflow/playground-adapter').then(res => ({
default: res.WorkflowPage,
})),
);
const PluginPageLayout = lazy(() => import('./pages/plugin/layout'));
const PluginPage = lazy(() => import('./pages/plugin/page'));
const PluginToolPage = lazy(() => import('./pages/plugin/tool/page'));
const PluginMocksetPage = lazy(
() => import('./pages/plugin/tool/plugin-mock-set/page'),
);
const PluginMocksetDetailPage = lazy(
() => import('./pages/plugin/tool/plugin-mock-set/detail/page'),
);
const LoginPage = lazy(() =>
import('@coze-foundation/account-ui-adapter').then(res => ({
default: res.LoginPage,
})),
);
const AgentPublishPage = lazy(() =>
import('@coze-agent-ide/agent-publish').then(exps => ({
default: exps.AgentPublishPage,
})),
);
const DocsRedirect = lazy(() => import('./pages/docs'));
export const router: ReturnType<typeof createBrowserRouter> =
createBrowserRouter([
{
path: '/open/docs/*',
Component: DocsRedirect,
loader: () => ({
hasSider: false,
requireAuth: false,
}),
},
{
path: '/docs/*',
Component: DocsRedirect,
loader: () => ({
hasSider: false,
requireAuth: false,
}),
},
{
path: '/',
Component: Layout,
errorElement: <GlobalError />,
children: [
{
index: true,
element: <Navigate to="/space" replace />,
},
exploreRouter,
{
path: 'sign',
Component: LoginPage,
errorElement: <GlobalError />,
loader: () => ({
hasSider: false,
requireAuth: false,
}),
},
{
path: 'space',
Component: SpaceLayout,
loader: () => ({
hasSider: true,
requireAuth: true,
subMenu,
menuKey: BaseEnum.Space,
}),
children: [
{
path: ':space_id',
Component: SpaceIdLayout,
children: [
{
index: true,
element: <Navigate to="develop" replace />,
},
{
path: 'develop',
Component: Develop,
loader: () => ({
subMenuKey: SpaceSubModuleEnum.DEVELOP,
}),
},
{
path: 'project-ide/:project_id/publish',
loader: () => ({
hasSider: false,
}),
Component: IDEPublish,
},
{
path: 'project-ide/:project_id/*',
Component: IDELayout,
loader: () => ({
hasSider: false,
}),
},
{
path: 'library',
Component: Library,
loader: () => ({
subMenuKey: SpaceSubModuleEnum.LIBRARY,
}),
},
{
path: 'project-ide/:project_id/*',
Component: IDELayout,
loader: () => ({
hasSider: false,
}),
},
{
path: 'knowledge',
children: [
{
path: ':dataset_id',
element: <KnowledgePreview />,
},
{
path: ':dataset_id/upload',
element: <KnowledgeUpload />,
},
],
loader: () => ({
pageModeByQuery: true,
}),
},
{
path: 'database',
children: [
{
path: ':table_id',
element: <DatabaseDetail />,
},
],
loader: () => ({
showMobileTips: true,
pageModeByQuery: true,
}),
},
{
path: 'bot/:bot_id',
Component: AgentIDELayout,
children: [
{
index: true,
Component: AgentIDE,
},
{
path: 'publish',
children: [
{
index: true,
Component: AgentPublishPage,
loader: () => ({
hasSider: false,
requireBotEditorInit: false,
pageName: 'publish',
}),
},
],
},
],
loader: () => ({
hasSider: false,
showMobileTips: true,
requireBotEditorInit: true,
pageName: 'bot',
}),
},
{
path: 'plugin/:plugin_id',
Component: PluginPageLayout,
children: [
{
index: true,
Component: PluginPage,
},
{
path: 'tool/:tool_id',
children: [
{
index: true,
Component: PluginToolPage,
},
{
path: 'plugin-mock-set',
Component: PluginMocksetPage,
children: [
{
path: ':mock_set_id',
children: [
{
index: true,
Component: PluginMocksetDetailPage,
},
],
},
],
},
],
},
],
},
],
},
],
},
{
path: 'work_flow',
Component: WorkflowPage,
loader: () => ({
hasSider: false,
requireAuth: true,
}),
},
],
},
]);

View File

@@ -0,0 +1,145 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { lazy } from 'react';
// 登录页面
export const LoginPage = lazy(() =>
import('@coze-foundation/account-ui-adapter').then(res => ({
default: res.LoginPage,
})),
);
// 文档页面
export const Redirect = lazy(() => import('../pages/redirect'));
// 工作空间侧边栏组件
export const spaceSubMenu = lazy(() =>
import('@coze-foundation/space-ui-adapter').then(exps => ({
default: exps.WorkspaceSubMenu,
})),
);
// 工作空间布局组件
export const SpaceLayout = lazy(() =>
import('@coze-foundation/space-ui-adapter').then(exps => ({
default: exps.SpaceLayout,
})),
);
// 某个具体的工作空间布局组件
export const SpaceIdLayout = lazy(() =>
import('@coze-foundation/space-ui-base').then(exps => ({
default: exps.SpaceIdLayout,
})),
);
// 项目开发页面
export const Develop = lazy(() => import('../pages/develop'));
// 资源库页面
export const Library = lazy(() => import('../pages/library'));
// Agent IDE布局组件
export const AgentIDELayout = lazy(
() => import('@coze-agent-ide/layout-adapter'),
);
// Agent IDE页面
export const AgentIDE = lazy(() =>
import('@coze-agent-ide/entry-adapter').then(res => ({
default: res.BotEditor,
})),
);
// Agent IDE发布页面
export const AgentPublishPage = lazy(() =>
import('@coze-agent-ide/agent-publish').then(exps => ({
default: exps.AgentPublishPage,
})),
);
// Project IDE页面
export const ProjectIDE = lazy(() =>
import('@coze-project-ide/main').then(exps => ({
default: exps.IDELayout,
})),
);
// Project IDE发布页面
export const ProjectIDEPublish = lazy(() =>
import('@coze-studio/project-publish').then(exps => ({
default: exps.ProjectPublish,
})),
);
// 知识库预览页面
export const KnowledgePreview = lazy(() =>
import('@coze-studio/workspace-base/knowledge-preview').then(exps => ({
default: exps.KnowledgePreviewPage,
})),
);
// 知识库上传页面
export const KnowledgeUpload = lazy(() =>
import('@coze-studio/workspace-base/knowledge-upload').then(exps => ({
default: exps.KnowledgeUploadPage,
})),
);
// 数据库资源页面
export const DatabaseDetail = lazy(() =>
import('@coze-studio/workspace-base').then(exps => ({
default: exps.DatabaseDetailPage,
})),
);
// 工作流页面
export const WorkflowPage = lazy(() =>
import('@coze-workflow/playground-adapter').then(res => ({
default: res.WorkflowPage,
})),
);
// 插件资源页面布局组件
export const PluginLayout = lazy(() => import('../pages/plugin/layout'));
// 插件资源页面
export const PluginPage = lazy(() => import('../pages/plugin/page'));
// 插件工具页面
export const PluginToolPage = lazy(() => import('../pages/plugin/tool/page'));
// 探索体验页面二级导航组件
export const exploreSubMenu = lazy(() =>
import('@coze-community/explore').then(exps => ({
default: exps.ExploreSubMenu,
})),
);
// 模版页面
export const ExploreTemplatePage = lazy(() =>
import('@coze-community/explore').then(exps => ({
default: exps.TemplatePage,
})),
);
// 插件商店页面
export const ExplorePluginPage = lazy(() =>
import('@coze-community/explore').then(exps => ({
default: exps.PluginPage,
})),
);

View File

@@ -0,0 +1,286 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createBrowserRouter, Navigate } from 'react-router-dom';
import { SpaceSubModuleEnum } from '@coze-foundation/space-ui-adapter';
import { GlobalError } from '@coze-foundation/layout';
import { BaseEnum } from '@coze-arch/web-context';
import { Layout } from '../layout';
import {
LoginPage,
SpaceLayout,
SpaceIdLayout,
Develop,
AgentIDELayout,
AgentIDE,
AgentPublishPage,
Redirect,
spaceSubMenu,
exploreSubMenu,
WorkflowPage,
ProjectIDE,
ProjectIDEPublish,
Library,
PluginLayout,
PluginToolPage,
PluginPage,
KnowledgePreview,
KnowledgeUpload,
DatabaseDetail,
ExplorePluginPage,
ExploreTemplatePage,
} from './async-components';
export const router: ReturnType<typeof createBrowserRouter> =
createBrowserRouter([
// 文档路由
{
path: '/open/docs/*',
Component: Redirect,
loader: () => ({
hasSider: false,
requireAuth: false,
}),
},
{
path: '/docs/*',
Component: Redirect,
loader: () => ({
hasSider: false,
requireAuth: false,
}),
},
{
path: '/information/auth/success',
Component: Redirect,
loader: () => ({
hasSider: false,
requireAuth: false,
}),
},
// 主应用路由
{
path: '/',
Component: Layout,
errorElement: <GlobalError />,
children: [
{
index: true,
element: <Navigate to="/space" replace />,
},
// 登录页路由
{
path: 'sign',
Component: LoginPage,
errorElement: <GlobalError />,
loader: () => ({
hasSider: false,
requireAuth: false,
}),
},
// 工作空间路由
{
path: 'space',
Component: SpaceLayout,
loader: () => ({
hasSider: true,
requireAuth: true,
subMenu: spaceSubMenu,
menuKey: BaseEnum.Space,
}),
children: [
{
path: ':space_id',
Component: SpaceIdLayout,
children: [
{
index: true,
element: <Navigate to="develop" replace />,
},
// 项目开发
{
path: 'develop',
Component: Develop,
loader: () => ({
subMenuKey: SpaceSubModuleEnum.DEVELOP,
}),
},
// Agent IDE
{
path: 'bot/:bot_id',
Component: AgentIDELayout,
children: [
{
index: true,
Component: AgentIDE,
},
{
path: 'publish',
children: [
{
index: true,
Component: AgentPublishPage,
loader: () => ({
hasSider: false,
requireBotEditorInit: false,
pageName: 'publish',
}),
},
],
},
],
loader: () => ({
hasSider: false,
showMobileTips: true,
requireBotEditorInit: true,
pageName: 'bot',
}),
},
// Project IDE
{
path: 'project-ide/:project_id/publish',
loader: () => ({
hasSider: false,
}),
Component: ProjectIDEPublish,
},
{
path: 'project-ide/:project_id/*',
Component: ProjectIDE,
loader: () => ({
hasSider: false,
}),
},
// 资源库
{
path: 'library',
Component: Library,
loader: () => ({
subMenuKey: SpaceSubModuleEnum.LIBRARY,
}),
},
// 知识库资源
{
path: 'knowledge',
children: [
{
path: ':dataset_id',
element: <KnowledgePreview />,
},
{
path: ':dataset_id/upload',
element: <KnowledgeUpload />,
},
],
loader: () => ({
pageModeByQuery: true,
}),
},
// 数据库资源
{
path: 'database',
children: [
{
path: ':table_id',
element: <DatabaseDetail />,
},
],
loader: () => ({
showMobileTips: true,
pageModeByQuery: true,
}),
},
// 插件资源
{
path: 'plugin/:plugin_id',
Component: PluginLayout,
children: [
{
index: true,
Component: PluginPage,
},
{
path: 'tool/:tool_id',
children: [
{
index: true,
Component: PluginToolPage,
},
],
},
],
},
],
},
],
},
// 工作流路由
{
path: 'work_flow',
Component: WorkflowPage,
loader: () => ({
hasSider: false,
requireAuth: true,
}),
},
// 探索
{
path: 'explore',
Component: null,
loader: () => ({
hasSider: true,
requireAuth: true,
subMenu: exploreSubMenu,
menuKey: BaseEnum.Explore,
}),
children: [
{
index: true,
element: <Navigate to="plugin" replace />,
},
// 插件商店
{
path: 'plugin',
element: <ExplorePluginPage />,
loader: () => ({
type: 'plugin',
}),
},
// 模版
{
path: 'template',
element: <ExploreTemplatePage />,
loader: () => ({
type: 'template',
}),
},
],
},
],
},
]);

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { Config } from 'tailwindcss';
import {
designTokenToTailwindConfig,
getTailwindContents,
} from '@coze-arch/tailwind-config/design-token';
import json from '@coze-arch/semi-theme-hand01/raw.json';
import { SCREENS_TOKENS } from '@coze-arch/responsive-kit/constant';
const contents = getTailwindContents('@coze-studio/app');
console.log(`Got ${contents.length} contents for tailwind`);
export default {
content: contents,
// safelist的内容可以允许动态生成tailwind className
safelist: [
{
pattern: /(gap-|grid-).+/,
variants: ['sm', 'md', 'lg', 'xl', '2xl'],
},
],
important: '',
// eslint-disable-next-line @typescript-eslint/no-require-imports
presets: [require('@coze-arch/tailwind-config')],
theme: {
screens: {
mobile: { max: '1200px' },
},
extend: {
screens: SCREENS_TOKENS,
...designTokenToTailwindConfig(json),
},
},
corePlugins: {
preflight: false, // 关闭@tailwind base默认样式避免对现有样式影响
},
// eslint-disable-next-line @typescript-eslint/no-require-imports
plugins: [require('@coze-arch/tailwind-config/coze')],
} satisfies Config;

View File

@@ -0,0 +1,133 @@
{
"extends": "@coze-arch/ts-config/tsconfig.web.json",
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"jsx": "react-jsx",
"lib": ["DOM", "ESNext"],
"module": "ESNext",
"isolatedModules": true,
"target": "ES2020",
"moduleResolution": "bundler",
"tsBuildInfoFile": "dist/tsconfig.build.tsbuildinfo"
},
"include": ["src"],
"exclude": ["node_modules", "dist"],
"references": [
{
"path": "../../config/eslint-config/tsconfig.build.json"
},
{
"path": "../../config/postcss-config/tsconfig.build.json"
},
{
"path": "../../config/rsbuild-config/tsconfig.build.json"
},
{
"path": "../../config/stylelint-config/tsconfig.build.json"
},
{
"path": "../../config/tailwind-config/tsconfig.build.json"
},
{
"path": "../../config/ts-config/tsconfig.build.json"
},
{
"path": "../../config/vitest-config/tsconfig.build.json"
},
{
"path": "../../infra/plugins/import-watch-loader/tsconfig.build.json"
},
{
"path": "../../infra/plugins/pkg-root-webpack-plugin/tsconfig.build.json"
},
{
"path": "../../packages/agent-ide/agent-publish/tsconfig.build.json"
},
{
"path": "../../packages/agent-ide/entry-adapter/tsconfig.build.json"
},
{
"path": "../../packages/agent-ide/layout-adapter/tsconfig.build.json"
},
{
"path": "../../packages/arch/api-schema/tsconfig.build.json"
},
{
"path": "../../packages/arch/bot-env/tsconfig.build.json"
},
{
"path": "../../packages/arch/bot-flags/tsconfig.build.json"
},
{
"path": "../../packages/arch/bot-md-box-adapter/tsconfig.build.json"
},
{
"path": "../../packages/arch/bot-typings/tsconfig.build.json"
},
{
"path": "../../packages/arch/default-slardar/tsconfig.build.json"
},
{
"path": "../../packages/arch/foundation-sdk/tsconfig.build.json"
},
{
"path": "../../packages/arch/i18n/tsconfig.build.json"
},
{
"path": "../../packages/arch/logger/tsconfig.build.json"
},
{
"path": "../../packages/arch/responsive-kit/tsconfig.build.json"
},
{
"path": "../../packages/arch/web-context/tsconfig.build.json"
},
{
"path": "../../packages/community/explore/tsconfig.build.json"
},
{
"path": "../../packages/foundation/account-adapter/tsconfig.build.json"
},
{
"path": "../../packages/foundation/account-ui-adapter/tsconfig.build.json"
},
{
"path": "../../packages/foundation/foundation-sdk/tsconfig.build.json"
},
{
"path": "../../packages/foundation/global-adapter/tsconfig.build.json"
},
{
"path": "../../packages/foundation/global/tsconfig.build.json"
},
{
"path": "../../packages/foundation/layout/tsconfig.build.json"
},
{
"path": "../../packages/foundation/space-ui-adapter/tsconfig.build.json"
},
{
"path": "../../packages/foundation/space-ui-base/tsconfig.build.json"
},
{
"path": "../../packages/project-ide/main/tsconfig.build.json"
},
{
"path": "../../packages/studio/stores/bot-plugin/tsconfig.build.json"
},
{
"path": "../../packages/studio/workspace/entry-adapter/tsconfig.build.json"
},
{
"path": "../../packages/studio/workspace/entry-base/tsconfig.build.json"
},
{
"path": "../../packages/studio/workspace/project-publish/tsconfig.build.json"
},
{
"path": "../../packages/workflow/adapter/playground/tsconfig.build.json"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"exclude": ["**/*"],
"compilerOptions": {
"composite": true
},
"references": [
{
"path": "./tsconfig.build.json"
},
{
"path": "./tsconfig.misc.json"
}
]
}

View File

@@ -0,0 +1,27 @@
{
"extends": "@coze-arch/ts-config/tsconfig.web.json",
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"rootDir": "./",
"outDir": "./dist",
"jsx": "react-jsx",
"lib": ["DOM", "ESNext"],
"module": "ESNext",
"target": "ES2020",
"moduleResolution": "bundler",
"types": ["vitest/globals", "node"]
},
"include": [
"__tests__",
"vitest.config.ts",
"tailwind.config.ts",
"rsbuild.config.ts",
"scripts/**/*.ts"
],
"exclude": ["./dist"],
"references": [
{
"path": "./tsconfig.build.json"
}
]
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { defineConfig } from '@coze-arch/vitest-config';
export default defineConfig({
dirname: __dirname,
preset: 'web',
});

View File

@@ -0,0 +1,35 @@
// Documentation for this file: https://prettier.io/docs/en/options.html
module.exports = {
// We use a larger print width because Prettier's word-wrapping seems to be tuned
// for plain JavaScript without type annotations
printWidth: 80,
// Use .gitattributes to manage newlines
endOfLine: 'auto',
semi: true,
plugins: [require.resolve('prettier-plugin-packagejson')],
tabWidth: 2,
useTabs: false,
singleQuote: true,
trailingComma: 'all',
bracketSpacing: true,
jsxBracketSameLine: false,
arrowParens: 'avoid',
overrides: [
{
files: '.prettierrc',
options: { parser: 'json', trailingComma: 'none' },
},
{
files: '.babelrc',
options: { parser: 'json', trailingComma: 'none' },
},
{
files: '*.json',
options: { trailingComma: 'none' },
},
],
};

View File

@@ -0,0 +1,275 @@
# @coze-arch/eslint-config
A comprehensive ESLint configuration package for the Coze architecture ecosystem, providing standardized linting rules for JavaScript, TypeScript, React, and Node.js projects.
## Features
- 🔧 **Multi-environment support**: Separate configurations for web, node, and base environments
- 🎯 **TypeScript-first**: Full TypeScript support with advanced rules
- ⚛️ **React optimized**: Built-in React hooks and XSS protection rules
- 🔒 **Security focused**: Integrated security plugins and best practices
- 🎨 **Prettier integration**: Seamless code formatting with Prettier
- 📦 **Workspace-aware**: Import resolution for monorepo environments
- 🚫 **Dependency control**: Built-in rules to prevent disallowed dependencies
- 🧪 **Test-friendly**: Special configurations for test files
## Get Started
### Installation
```bash
# Install the package
pnpm add @coze-arch/eslint-config --save-dev
# Update workspace dependencies
rush update
```
### Basic Usage
Create an `eslint.config.js` file in your project root:
```javascript
const { defineConfig } = require('@coze-arch/eslint-config');
module.exports = defineConfig({
packageRoot: __dirname,
preset: 'web', // or 'node' or 'base'
});
```
## API Reference
### `defineConfig(config)`
The main function to create ESLint configurations.
#### Parameters
- `config` (EnhanceESLintConfig): Configuration object
#### EnhanceESLintConfig Interface
```typescript
interface EnhanceESLintConfig extends ESLintConfig {
/**
* Project root directory
*/
packageRoot: string;
/**
* Configuration preset mode
*/
preset: 'web' | 'node' | 'base';
/**
* Additional configuration overrides
*/
overrides?: ESLintConfig[];
/**
* Custom ignore patterns
*/
ignores?: string[];
/**
* Custom rules
*/
rules?: Linter.RulesRecord;
/**
* ESLint settings
*/
settings?: any;
}
```
### Configuration Presets
#### Web Preset (`preset: 'web'`)
Optimized for React web applications:
```javascript
module.exports = defineConfig({
packageRoot: __dirname,
preset: 'web',
});
```
**Includes:**
- React and React Hooks rules
- XSS protection with `eslint-plugin-risxss`
- Browser globals
- Restricted imports for architecture compliance
#### Node Preset (`preset: 'node'`)
Optimized for Node.js applications:
```javascript
module.exports = defineConfig({
packageRoot: __dirname,
preset: 'node',
});
```
**Includes:**
- Node.js globals and environment
- Security plugin for Node.js
- Server-side specific rules
#### Base Preset (`preset: 'base'`)
Minimal configuration for libraries:
```javascript
module.exports = defineConfig({
packageRoot: __dirname,
preset: 'base',
});
```
**Includes:**
- Core JavaScript and TypeScript rules
- Import resolution
- Common code quality rules
### Custom Configuration
#### Adding Custom Rules
```javascript
module.exports = defineConfig({
packageRoot: __dirname,
preset: 'web',
rules: {
'no-console': 'warn',
'@typescript-eslint/no-unused-vars': 'error',
},
});
```
#### Adding Overrides
```javascript
module.exports = defineConfig({
packageRoot: __dirname,
preset: 'web',
overrides: [
{
files: ['**/*.test.ts', '**/*.spec.ts'],
rules: {
'max-lines': 'off',
},
},
],
});
```
#### Custom Ignores
```javascript
module.exports = defineConfig({
packageRoot: __dirname,
preset: 'web',
ignores: [
'custom-build/**',
'temp/**',
],
});
```
### CLI Scripts
The package provides convenient CLI scripts:
#### ESLint Script
```bash
# Using the built-in eslint script
npx eslint ./src
# Using the reslint alias
npx reslint ./src
```
#### Prettier Script
```bash
# Format code with Prettier
npx prettier --write ./src
```
## Development
### Project Structure
```
config/eslint-config/
├── src/
│ ├── index.js # Main entry point
│ └── define-config.ts # Configuration function
├── rules/ # Rule configurations
│ ├── common-standard.js # Common rules
│ ├── import.js # Import rules
│ ├── js-standard.js # JavaScript rules
│ ├── ts-standard.js # TypeScript rules
│ └── test-standard.js # Test file rules
├── scripts/
│ ├── reslint.sh # ESLint wrapper script
│ └── rprettier.sh # Prettier wrapper script
├── eslint.config.base.js # Base configuration
├── eslint.config.web.js # Web configuration
├── eslint.config.node.js # Node.js configuration
└── package.json
```
### Building
```bash
# Build the package
rush build --to @coze-arch/eslint-config
# Run linting
rush lint --to @coze-arch/eslint-config
```
### Testing
```bash
# Run tests
rush test --to @coze-arch/eslint-config
```
## Dependencies
### Main Dependencies
- **@typescript-eslint/eslint-plugin**: TypeScript-specific linting rules
- **@typescript-eslint/parser**: TypeScript parser for ESLint
- **eslint-plugin-react**: React-specific linting rules
- **eslint-plugin-react-hooks**: Rules for React Hooks
- **eslint-plugin-prettier**: Prettier integration
- **eslint-plugin-import**: Import/export syntax validation
- **eslint-plugin-security**: Security-focused linting rules
- **eslint-plugin-risxss**: XSS prevention for React
### Internal Dependencies
- **@coze-arch/eslint-plugin**: Custom rules for Coze architecture
- **@coze-arch/ts-config**: TypeScript configuration
### Build Tools
- **sucrase**: Fast TypeScript transpilation
- **prettier**: Code formatting
- **eslint**: Core linting engine
## License
Internal package for Coze architecture ecosystem.
---
For more information about ESLint configuration, visit the [ESLint documentation](https://eslint.org/docs/user-guide/configuring/).

View File

@@ -0,0 +1,8 @@
const { FlatCompat } = require('@eslint/eslintrc');
const compat = new FlatCompat({
baseDirectory: __dirname,
resolvePluginsRelativeTo: __dirname,
});
module.exports = { compat };

View File

@@ -0,0 +1,8 @@
{
"operationSettings": [
{
"operationName": "ts-check",
"outputFolderNames": ["dist"]
}
]
}

View File

@@ -0,0 +1,10 @@
/** @type {(import('eslint').Linter.Config)[]} */
module.exports = [
require('eslint-plugin-prettier/recommended'),
...require('./rules/common-standard'),
...require('./rules/import'),
...require('./rules/js-standard'),
...require('./rules/ts-standard'),
...require('./rules/test-standard'),
];

View File

@@ -0,0 +1,13 @@
const path = require('path');
const { main } = require('./package.json');
const { defineConfig } = require(path.resolve(__dirname, main));
module.exports = defineConfig({
packageRoot: __dirname,
preset: 'node',
rules: {
'@typescript-eslint/no-require-imports': 'off',
},
});

View File

@@ -0,0 +1,17 @@
const globals = require('globals');
const securityPlugin = require('eslint-plugin-security');
/** @type {(import('eslint').Linter.Config[])} */
module.exports = [
...require('./eslint.config.base.js'),
securityPlugin.configs.recommended,
{
languageOptions: {
globals: {
...globals.node,
NodeJS: true,
},
},
rules: {},
},
];

View File

@@ -0,0 +1,66 @@
const globals = require('globals');
/** @type {(import('eslint').Linter.Config[])} */
module.exports = [
...require('./eslint.config.base.js'),
{
plugins: {
// TODO: 需要根据不同类型配置plugin需要阅读源码确认是否影响性能
'react-hooks': require('eslint-plugin-react-hooks'),
react: require('eslint-plugin-react'),
risxss: require('eslint-plugin-risxss'),
},
languageOptions: {
globals: {
...globals.node,
...globals.browser,
JSX: true,
React: true,
},
},
settings: {
// for eslint-plugin-react
react: {
pragma: 'React',
version: '18.2',
},
},
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
'risxss/catch-potential-xss-react': 'error',
'no-restricted-imports': [
'error',
{
patterns: [
{
group: ['@douyinfe/semi-ui', '@douyinfe/semi-ui/*'],
message:
'请勿直接使用@douyinfe/semi-ui, 请使用 @coze-arch/bot-semi',
},
{
group: ['@douyinfe/semi-ui/lib/es/*'],
message:
'如果你的代码为 import { foo } from "@douyinfe/semi-ui/lib/es/bar", 可以尝试替换为 import { foo } from "@coze-arch/bot-semi/Bar"',
},
{
group: ['@edenx/runtime/intl'],
message:
'请勿直接使用@edenx/runtime/intl, 请使用 @coze-arch/i18n',
},
{
group: ['@edenx/runtime/router'],
message:
'请勿直接使用@edenx/runtime/router, 请使用 react-router-dom',
},
{
group: ['@edenx/runtime/styled'],
message:
'请勿直接使用@edenx/runtime/styled, 请使用 styled-components',
},
],
},
],
},
},
];

View File

@@ -0,0 +1,76 @@
{
"name": "@coze-arch/eslint-config",
"version": "0.0.1",
"author": "fanwenjie.fe@bytedance.com",
"maintainers": [],
"main": "src/index.js",
"bin": {
"eslint": "./scripts/reslint.sh",
"prettier": "./scripts/rprettier.sh",
"reslint": "./scripts/reslint.sh"
},
"scripts": {
"build": "exit 0",
"dev": "npm run build -- -w",
"lint": "eslint ./ --cache --quiet",
"test": "exit",
"test:cov": "exit"
},
"dependencies": {
"@babel/eslint-parser": "~7.25.8",
"@babel/eslint-plugin": "~7.25.7",
"@babel/plugin-proposal-async-generator-functions": "~7.20.7",
"@babel/plugin-proposal-class-properties": "~7.18.6",
"@babel/plugin-proposal-decorators": "~7.23.6",
"@babel/plugin-proposal-do-expressions": "~7.23.3",
"@babel/plugin-proposal-export-default-from": "~7.23.3",
"@babel/plugin-proposal-export-namespace-from": "~7.18.9",
"@babel/plugin-proposal-function-bind": "~7.23.3",
"@babel/plugin-proposal-nullish-coalescing-operator": "~7.18.6",
"@babel/plugin-proposal-object-rest-spread": "~7.20.7",
"@babel/plugin-proposal-optional-catch-binding": "~7.18.6",
"@babel/plugin-proposal-optional-chaining": "~7.21.0",
"@babel/plugin-proposal-pipeline-operator": "~7.23.3",
"@babel/plugin-syntax-dynamic-import": "~7.8.3",
"@babel/plugin-syntax-jsx": "~7.23.3",
"@babel/preset-env": "~7.20.2",
"@babel/preset-react": "~7.13.13",
"@coze-arch/eslint-plugin": "workspace:*",
"@coze-arch/ts-config": "workspace:*",
"@eslint/compat": "~1.2.0",
"@eslint/eslintrc": "~3.1.0",
"@rushstack/eslint-config": "~3.1.1",
"@stylistic/eslint-plugin-ts": "^2.8.0",
"@typescript-eslint/eslint-plugin": "^8.5.0",
"@typescript-eslint/parser": "~8.17.0",
"eslint": "~9.12.0",
"eslint-config-airbnb": "^18.0.1",
"eslint-config-prettier": "~9.1.0",
"eslint-config-react-app": "^7",
"eslint-define-config": "~1.12.0",
"eslint-import-resolver-typescript": "^3",
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-cypress": "^2.6.1",
"eslint-plugin-eslint-comments": "~3.2.0",
"eslint-plugin-import": "^2.29.0",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "~5.2.1",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-react": "~7.37.1",
"eslint-plugin-react-hooks": "5.1.0-beta-26f2496093-20240514",
"eslint-plugin-redux-saga": "^1.1.0",
"eslint-plugin-risxss": "~2.1.0",
"eslint-plugin-security": "3.0.1",
"eslint-plugin-unicorn": "48.0.1",
"globals": "~15.11.0",
"json5": "^2.2.1",
"prettier": "~3.3.3",
"prettier-plugin-packagejson": "^2.3.0",
"sucrase": "^3.32.0"
},
"devDependencies": {
"@types/eslint": "~9.6.1",
"@types/node": "^18",
"typescript": "~5.8.2"
}
}

View File

@@ -0,0 +1,200 @@
const path = require('path');
const fs = require('fs');
const JSON5 = require('json5');
const noRestrictedSyntaxRule = [
'error',
{
selector: 'LabeledStatement',
message:
'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.',
},
{
selector: 'WithStatement',
message:
'`with` is disallowed in strict mode because it makes code impossible to predict and optimize.',
},
];
const readBlockList = () =>
JSON5.parse(
fs.readFileSync(
// fixme @fanwenjie.fe
path.resolve(__dirname, '../../../disallowed_3rd_libraries.json'),
'utf-8',
),
);
/** @type {(import('eslint').Linter.Config)[]} */
module.exports = [
// NOTE: 不能和下一项配置合并
{
ignores: [
'**/*.d.ts',
'**/.storybook/**',
'**/storybook-static/**',
'**/coverage/**',
'**/node_modules/**',
'**/build/**',
'**/__dist__/**',
'**/dist/**',
'**/es/**',
'**/lib/**',
'**/.codebase/**',
'**/.changeset/**',
'**/config/**',
'**/common/scripts/**',
'**/output/**',
'**/output_resource/**',
'**/__tests__/fixtures/**',
'**/__tests__/outputs/**',
'error-log-str.js',
'*.bundle.js',
'*.min.js',
'*.js.map',
'**/*.log',
'**/tsconfig.tsbuildinfo',
'**/.jscpd',
],
},
{
plugins: {
'@coze-arch': require('@coze-arch/eslint-plugin'),
'@coze-arch/zustand': require('@coze-arch/eslint-plugin/zustand'),
},
},
...require('@coze-arch/eslint-plugin').configs.recommended,
require('@coze-arch/eslint-plugin/zustand').configs.recommended,
{
files: ['**/*.?(m|c)?(j|t)s?(x)'], // 排除规则对package.json生效
plugins: {
prettier: require('eslint-plugin-prettier'),
'@babel': require('@babel/eslint-plugin'),
import: require('eslint-plugin-import'),
unicorn: require('eslint-plugin-unicorn'),
'@typescript-eslint': require('@typescript-eslint/eslint-plugin'),
'@stylistic/ts': require('@stylistic/eslint-plugin-ts'),
'eslint-comments': require('eslint-plugin-eslint-comments'),
},
rules: {
'@coze-arch/package-disallow-deps': ['error', readBlockList()],
'no-restricted-syntax': noRestrictedSyntaxRule,
'prettier/prettier': [
'warn',
require('../.prettierrc'),
{ usePrettierrc: false },
],
'no-empty': 'error',
'import/no-duplicates': 'error',
'unicorn/no-static-only-class': 'error',
curly: 'error',
'no-mixed-spaces-and-tabs': 'error',
'max-statements-per-line': 'error',
'rest-spread-spacing': 'error',
'max-len': [
'warn',
{
code: 120,
tabWidth: 2,
ignoreUrls: true,
ignoreStrings: true,
},
],
'no-unexpected-multiline': 'error',
'no-irregular-whitespace': [
'error',
{
skipStrings: true,
skipComments: true,
},
],
'no-var': 'error',
'prefer-const': 'error',
'no-inner-declarations': ['error', 'both'],
'no-self-assign': 'error',
'prefer-destructuring': [
'warn',
{
object: true,
array: false,
},
],
'no-sparse-arrays': 'error',
'no-new-object': 'error',
'object-shorthand': 'error',
'no-empty-pattern': 'error',
'no-unsafe-optional-chaining': 'error',
'no-class-assign': 'error',
'arrow-body-style': 'error',
'no-async-promise-executor': 'error',
'prefer-promise-reject-errors': 'error',
// TODO: complexity is stricter after we updated to eslint 9.
complexity: ['warn', 15],
'max-params': [
'error',
{
max: 3,
},
],
'no-extra-bind': 'error',
'no-prototype-builtins': 'error',
'new-parens': 'error',
'prefer-template': 'warn',
'no-multi-str': 'error',
'use-isnan': 'error',
'no-floating-decimal': 'error',
'guard-for-in': 'warn',
'for-direction': 'error',
'no-unmodified-loop-condition': 'error',
'no-unsafe-finally': 'error',
'no-cond-assign': ['error', 'always'],
'no-constant-condition': [
'error',
{
checkLoops: false,
},
],
'no-dupe-else-if': 'error',
'no-extra-boolean-cast': [
'error',
{
enforceForLogicalOperands: true,
},
],
'no-useless-catch': 'error',
'no-ex-assign': 'error',
'no-fallthrough': 'error',
'default-case': 'error',
'default-case-last': 'error',
'no-duplicate-case': 'error',
'no-case-declarations': 'error',
eqeqeq: 'error',
'no-compare-neg-zero': 'error',
'no-invalid-regexp': 'error',
'no-control-regex': 'error',
'no-empty-character-class': 'error',
'no-with': 'error',
'no-eval': 'error',
'no-new-wrappers': 'error',
'no-global-assign': 'error',
'no-debugger': 'error',
'no-caller': 'error',
'prefer-rest-params': 'error',
'no-implicit-coercion': [
'error',
{
allow: ['!!'],
},
],
'array-bracket-newline': ['error', 'consistent'],
'eslint-comments/require-description': 'warn',
'eslint-comments/no-unused-disable': 'error',
'max-lines': [
'error',
{ max: 500, skipComments: true, skipBlankLines: true },
],
'no-unused-labels': 'error',
},
},
];

View File

@@ -0,0 +1,80 @@
const importPlugin = require('eslint-plugin-import');
/** @type {(import('eslint').Linter.Config)[]} */
module.exports = [
{
files: ['**/*.?(m|c)?(j|t)s?(x)'],
settings: {
// TODO: 全局保留一份配置
'import/resolver': {
node: {
moduleDirectory: ['node_modules', 'src'],
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
},
rules: {
'import/no-cycle': ['error', { ignoreExternal: true }],
'import/prefer-default-export': 'off',
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: true,
},
],
'import/no-relative-packages': 'error',
'import/extensions': 'off',
'import/order': [
'warn',
{
groups: [
'builtin',
'external',
['internal', 'parent', 'sibling', 'index'],
'unknown',
],
pathGroups: [
{
pattern: 'react*',
group: 'builtin',
position: 'before',
},
{
pattern: '@/**',
group: 'internal',
position: 'before',
},
{
pattern: './*.+(css|sass|less|scss|pcss|styl)',
patternOptions: { dot: true, nocomment: true },
group: 'unknown',
position: 'after',
},
],
alphabetize: {
order:
'desc' /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */,
caseInsensitive: true /* ignore case. Options: [true, false] */,
},
pathGroupsExcludedImportTypes: ['builtin'],
'newlines-between': 'always',
},
],
},
},
{
files: ['**/*.?(m|c)ts?(x)'],
...importPlugin.configs.typescript,
settings: {
'import/resolver': {
typescript: true,
node: true,
},
},
rules: {
// TODO: 目前由于 edenx 会动态生成一些插件模块,因此启动会报错
// 后续需要修复问题,启动下述规则
// "import/no-unresolved": "error"
},
},
];

View File

@@ -0,0 +1,163 @@
const babelOptions = {
plugins: [
[
require.resolve('@babel/plugin-proposal-decorators'),
{
legacy: true,
},
],
[
require.resolve('@babel/plugin-proposal-class-properties'),
{
loose: true,
},
],
require.resolve('@babel/plugin-proposal-object-rest-spread'),
require.resolve('@babel/plugin-proposal-optional-catch-binding'),
require.resolve('@babel/plugin-proposal-async-generator-functions'),
require.resolve('@babel/plugin-proposal-export-namespace-from'),
require.resolve('@babel/plugin-proposal-export-default-from'),
require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
require.resolve('@babel/plugin-proposal-optional-chaining'),
[
require.resolve('@babel/plugin-proposal-pipeline-operator'),
{
proposal: 'minimal',
},
],
require.resolve('@babel/plugin-proposal-do-expressions'),
require.resolve('@babel/plugin-proposal-function-bind'),
require.resolve('@babel/plugin-syntax-dynamic-import'),
require.resolve('@babel/plugin-syntax-jsx'),
],
};
/** @type {(import('eslint').Linter.Config)[]} */
module.exports = [
{
files: ['**/*.?(m|c)js?(x)'],
rules: {
'no-import-assign': 'error',
'no-extra-semi': 'error',
'no-undef': 'error',
'no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
},
],
'comma-dangle': ['error', 'always-multiline'],
'no-array-constructor': 'error',
'dot-notation': 'error',
'constructor-super': 'error',
'no-this-before-super': 'error',
'no-useless-constructor': 'error',
'getter-return': [
'error',
{
allowImplicit: true,
},
],
'no-setter-return': 'error',
'no-dupe-class-members': 'error',
'default-param-last': 'error',
'no-func-assign': 'error',
'no-unsafe-negation': 'error',
'valid-typeof': 'error',
'no-empty-function': 'error',
quotes: [
'error',
'single',
{
avoidEscape: true,
},
],
'no-loss-of-precision': 'error',
'no-magic-numbers': [
'warn',
{
ignoreArrayIndexes: true,
ignoreDefaultValues: true,
enforceConst: true,
ignore: [0, 1, -1],
ignoreClassFieldInitialValues: true,
},
],
'no-unreachable': 'error',
'no-throw-literal': 'error',
'no-implied-eval': 'error',
'no-new-symbol': 'error',
'no-obj-calls': 'error',
camelcase: [
'error',
{
properties: 'never',
allow: ['^UNSAFE_'],
ignoreDestructuring: true,
},
],
'unicorn/filename-case': [
'error',
{
cases: {
kebabCase: true,
},
},
],
'max-lines-per-function': [
'error',
{
max: 300,
IIFEs: true,
},
],
},
languageOptions: {
parser: require('@babel/eslint-parser'),
parserOptions: {
ecmaVersion: 11,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
legacyDecorators: true,
},
requireConfigFile: false,
babelOptions,
},
},
},
{
// for jsx
files: ['**/*.?(m|c)jsx'],
rules: {
'react/jsx-uses-react': 'error',
'react/jsx-uses-vars': 'error',
'unicorn/filename-case': [
'warn',
{
cases: {
kebabCase: true,
snakeCase: true,
pascalCase: true,
},
ignore: ['^(?!.*?\\.jsx$)(?!.*?\\.tsx$).+'],
},
],
'max-lines-per-function': [
'warn',
{
max: 300,
IIFEs: true,
},
],
'max-lines': [
'error',
{
max: 500,
skipComments: true,
skipBlankLines: true,
},
],
},
},
];

View File

@@ -0,0 +1,53 @@
const globals = require('globals');
/** @type {(import('eslint').Linter.Config)[]} */
module.exports = [
{
files: [
'**/*.{test,spec}.?(m|c){js,ts}?(x)',
'**/{tests,__tests__,__test__}/**/*.?(m|c){js,ts}?(x)',
],
languageOptions: {
globals: {
...globals.jest,
vi: 'readonly',
},
},
rules: {
'max-lines': 'off',
'max-lines-per-function': 'off',
'no-magic-numbers': 'off',
'no-restricted-syntax': 'off',
'import/no-named-as-default-member': 'off',
'@coze-arch/max-line-per-function': 'off',
'@coze-arch/no-deep-relative-import': 'off',
'@typescript-eslint/consistent-type-assertions': 'off',
},
},
{
files: [
'**/*.{test,spec}.?(m|c)ts?(x)',
'**/{tests,__tests__,__test__}/**/*.?(m|c)ts?(x)',
],
rules: {
'@stylistic/ts/member-delimiter-style': [
'warn',
{
multiline: {
delimiter: 'semi',
requireLast: true,
},
singleline: {
delimiter: 'semi',
requireLast: false,
},
},
],
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-magic-numbers': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@coze-arch/no-batch-import-or-export': 'off',
},
},
];

View File

@@ -0,0 +1,371 @@
/** @type {(import('eslint').Linter.Config)[]} */
module.exports = [
{
files: ['**/*.?(m|c)ts?(x)'],
rules: {
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/prefer-namespace-keyword': 'off',
'@typescript-eslint/dot-notation': 'error',
'@typescript-eslint/require-await': 'error',
'max-lines': [
'error',
{
max: 500,
skipComments: true,
skipBlankLines: true,
},
],
'@typescript-eslint/no-array-constructor': 'error',
'@typescript-eslint/prefer-for-of': 'warn',
'@typescript-eslint/prefer-literal-enum-member': 'error',
'@typescript-eslint/no-duplicate-enum-values': 'error',
'@typescript-eslint/adjacent-overload-signatures': 'error',
'@typescript-eslint/unified-signatures': 'error',
'@typescript-eslint/no-this-alias': 'error',
'@typescript-eslint/method-signature-style': 'error',
'@typescript-eslint/no-misused-new': 'error',
'@typescript-eslint/consistent-type-assertions': [
'error',
{
assertionStyle: 'as',
objectLiteralTypeAssertions: 'never',
},
],
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-extra-non-null-assertion': 'error',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
'@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
'@typescript-eslint/ban-ts-comment': [
'error',
{
'ts-expect-error': 'allow-with-description',
},
],
'@typescript-eslint/prefer-ts-expect-error': 'error',
'@typescript-eslint/no-inferrable-types': 'error',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/prefer-as-const': 'error',
'@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
'@typescript-eslint/no-empty-interface': 'error',
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unnecessary-type-constraint': 'error',
'@typescript-eslint/no-invalid-void-type': 'error',
'@typescript-eslint/no-namespace': 'error',
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/consistent-type-imports': 'error',
'@typescript-eslint/no-unused-vars': [
'error',
{
vars: 'all',
args: 'none', // function arguments should not force to match this rule.
argsIgnorePattern: '^_', // 规范允许下划线
ignoreRestSiblings: true, //使用rest语法如 `var { foo, ...rest } = data`) 忽略foo。
destructuredArrayIgnorePattern: '^_', //结构数组允许使用_
caughtErrors: 'none',
// "caughtErrorsIgnorePattern": "^e$"
},
],
'@stylistic/ts/quotes': [
'error',
'single',
{
avoidEscape: true,
},
],
'@typescript-eslint/no-magic-numbers': [
'warn',
{
ignoreArrayIndexes: true,
ignoreDefaultValues: true,
ignoreEnums: true,
ignoreNumericLiteralTypes: true,
enforceConst: true,
ignore: [-1, 0, 1],
ignoreTypeIndexes: true,
ignoreReadonlyClassProperties: true,
ignoreClassFieldInitialValues: true,
},
],
'@stylistic/ts/no-extra-semi': 'error',
'@typescript-eslint/no-dupe-class-members': 'error',
'@typescript-eslint/no-useless-constructor': 'error',
'@typescript-eslint/default-param-last': 'error',
'@typescript-eslint/no-loss-of-precision': 'error',
'@stylistic/ts/comma-dangle': [
'error',
{
arrays: 'always-multiline',
objects: 'always-multiline',
imports: 'always-multiline',
exports: 'always-multiline',
enums: 'always-multiline',
generics: 'ignore',
tuples: 'always-multiline',
functions: 'always-multiline',
},
],
'@typescript-eslint/no-empty-function': 'error',
'@typescript-eslint/no-extraneous-class': 'error',
'no-import-assign': 'off',
'no-undef': 'off',
'dot-notation': 'off',
'constructor-super': 'off',
'no-this-before-super': 'off',
'getter-return': 'off',
'no-setter-return': 'off',
'no-func-assign': 'off',
'no-unsafe-negation': 'off',
'valid-typeof': 'off',
'no-unreachable': 'off',
'no-throw-literal': 'off',
'no-implied-eval': 'off',
'no-new-symbol': 'off',
'no-obj-calls': 'off',
camelcase: 'off',
'no-const-assign': 'off',
'no-dupe-args': 'off',
'no-dupe-class-members': 'off',
'no-dupe-keys': 'off',
'no-redeclare': 'off',
'no-array-constructor': 'off',
'no-empty-function': 'off',
'no-extra-semi': 'off',
'no-loss-of-precision': 'off',
'no-unused-vars': 'off',
'default-param-last': 'off',
'no-useless-constructor': 'off',
quotes: 'off',
'comma-dangle': 'off',
indent: 'off',
'no-magic-numbers': 'off',
'@typescript-eslint/naming-convention': [
'error',
{
selector: ['default', 'variableLike'],
format: ['camelCase', 'UPPER_CASE'],
},
{
selector: ['class', 'interface', 'typeLike'],
format: ['PascalCase'],
},
{
selector: ['variable'],
format: ['UPPER_CASE', 'camelCase'],
modifiers: ['global', 'exported'],
},
{
selector: 'objectLiteralProperty',
format: null,
},
{
selector: 'enumMember',
format: ['UPPER_CASE', 'PascalCase'],
},
{
selector: 'typeProperty',
format: ['camelCase', 'snake_case'],
},
{
selector: 'function',
format: ['camelCase'],
leadingUnderscore: 'forbid',
trailingUnderscore: 'forbid',
},
{
selector: 'parameter',
format: ['camelCase'],
leadingUnderscore: 'allow',
trailingUnderscore: 'forbid',
},
{
selector: 'variable',
modifiers: ['destructured'],
format: [
'camelCase',
'PascalCase',
'snake_case',
'strictCamelCase',
'StrictPascalCase',
'UPPER_CASE',
],
},
{
selector: 'import',
format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
},
],
'unicorn/filename-case': [
'error',
{
cases: {
kebabCase: true,
},
},
],
'max-lines-per-function': [
'warn',
{
max: 120,
IIFEs: true,
},
],
},
languageOptions: {
parser: require('@typescript-eslint/parser'),
parserOptions: {
ecmaVersion: 11,
projectService: true,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
legacyDecorators: true,
},
},
},
},
{
files: ['**/*.?(m|c)tsx'],
rules: {
'@typescript-eslint/naming-convention': [
'error',
{
selector: ['default', 'variableLike'],
format: ['camelCase', 'UPPER_CASE'],
},
{
selector: ['class', 'interface', 'typeLike'],
format: ['PascalCase'],
},
{
selector: ['variable'],
format: ['UPPER_CASE', 'camelCase', 'PascalCase'],
modifiers: ['global', 'exported'],
},
{
selector: 'objectLiteralProperty',
format: null,
},
{
selector: 'enumMember',
format: ['UPPER_CASE', 'PascalCase'],
},
{
selector: 'typeProperty',
format: ['camelCase', 'snake_case'],
},
{
selector: 'parameter',
format: ['camelCase'],
leadingUnderscore: 'allow',
trailingUnderscore: 'forbid',
},
{
selector: 'parameter',
format: ['camelCase', 'snake_case'],
modifiers: ['destructured'],
},
{
selector: 'variable',
modifiers: ['destructured'],
format: [
'camelCase',
'PascalCase',
'snake_case',
'strictCamelCase',
'StrictPascalCase',
'UPPER_CASE',
],
},
{
selector: 'import',
format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
},
{
selector: 'function',
format: ['camelCase', 'PascalCase'],
leadingUnderscore: 'forbid',
trailingUnderscore: 'forbid',
},
{
selector: 'variable',
format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
leadingUnderscore: 'allow',
},
],
'unicorn/filename-case': [
'warn',
{
cases: {
kebabCase: true,
snakeCase: true,
pascalCase: true,
},
ignore: ['^(?!.*?\\.jsx$)(?!.*?\\.tsx$).+'],
},
],
'max-lines-per-function': [
'warn',
{
max: 300,
IIFEs: true,
},
],
},
},
// TODO: 之前overides的内容后需可考虑直接合入上面标准配置
{
files: ['**/*.?(m|c)ts?(x)'],
rules: {
'@typescript-eslint/consistent-type-imports': [
'error',
{
fixStyle: 'inline-type-imports',
},
],
// 这些规则都是从 packages/config/.eslintrc.react.js 复制迁移过来
// 后续在做调整
'@typescript-eslint/no-redundant-type-constituents': 0,
'@typescript-eslint/no-throw-literal': 'off',
'@typescript-eslint/no-unnecessary-condition': 0,
'@typescript-eslint/prefer-optional-chain': 0,
'@typescript-eslint/indent': 0,
'@babel/new-cap': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'no-shadow': 'off',
'@typescript-eslint/no-shadow': 'error',
// TODO: 后续开启
// 'import/no-cycle': 'error',
'@typescript-eslint/prefer-string-starts-ends-with': 0,
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 0,
'@typescript-eslint/no-implied-eval': 0, // warning
// TODO: 打开下面这些配置
// fix: https://stackoverflow.com/questions/63961803/eslint-says-all-enums-in-typescript-app-are-already-declared-in-the-upper-scope
// 'no-shadow': 'off',
// '@typescript-eslint/no-shadow': ['error'],
// '@typescript-eslint/consistent-type-imports': [
// 'error',
// {
// fixStyle: 'inline-type-imports',
// },
// ],
// according to: https://typescript-eslint.io/linting/troubleshooting/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
// 'no-undef': 'off',
// 'no-unused-vars': 'off',
// '@typescript-eslint/no-unused-vars': [
// 'error',
// {
// vars: 'all',
// args: 'none', // function arguments should not force to match this rule.
// ignoreRestSiblings: false,
// },
// ],
// complexity: ['error', { max: 15 }],
// 后面统一使用CustomError后 再开启
'@coze-arch/no-new-error': 'off',
},
},
];

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
BASE_DIR=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
# 某些系统可能没有 realpath 命令,
if ! command -v realpath &>/dev/null; then
echo "未找到 realpath 命令"
echo "请执行以下命令安装必要依赖"
echo " brew install coreutils"
exit 1
fi
ROOT_DIR=$(realpath "$BASE_DIR/../")
args=("--cache")
if [ "$CI" = "true" ]; then
args+=("--quiet")
fi
bash "$ROOT_DIR/node_modules/.bin/eslint" "${args[@]}" "$@"

View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
BASE_DIR=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
# 某些系统可能没有 realpath 命令,
if ! command -v realpath &>/dev/null; then
echo "未找到 realpath 命令"
echo "请执行以下命令安装必要依赖"
echo " brew install coreutils"
exit 1
fi
ROOT_DIR=$(realpath "$BASE_DIR/../")
bash "$ROOT_DIR/node_modules/.bin/prettier" "$@"

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import path from 'path';
import fs from 'fs';
import type { Linter } from 'eslint';
import { includeIgnoreFile } from '@eslint/compat';
type ESLintConfigMode = 'web' | 'node' | 'base';
type ESLintConfig = Linter.Config;
type Rules = Linter.RulesRecord;
export interface EnhanceESLintConfig extends ESLintConfig {
/**
* project root dir
*/
packageRoot: string;
/**
* config mode
*/
preset: ESLintConfigMode;
/** overrides config */
overrides: ESLintConfig[];
}
/**
* Define an ESLint config.
*
* @param config ESLint config.
* @returns ESLint config.
*/
export const defineConfig = (config: EnhanceESLintConfig): ESLintConfig[] => {
const {
packageRoot,
preset,
overrides = [],
ignores = [],
rules,
settings,
...userConfig
} = config;
if (!packageRoot) {
throw new Error('should provider "packageRoot" params');
}
const defaultRules: Rules = {};
const ignorePath = path.resolve(packageRoot, '.gitignore');
return [
...require(`../eslint.config.${preset}.js`),
fs.existsSync(ignorePath) ? includeIgnoreFile(ignorePath) : {},
// root ignore file
includeIgnoreFile(path.resolve(__dirname, '../../../.gitignore')),
{
ignores,
},
{
files: ['**/*.?(m|c)?(j|t)s?(x)'],
settings: {
...settings,
'import/resolver': {
typescript: {
project: packageRoot,
},
},
},
plugins: {},
rules: {
...defaultRules,
...rules,
},
...userConfig,
},
...overrides,
];
};

View File

@@ -0,0 +1,12 @@
require('sucrase/register/ts');
const { defineConfig } = require('./define-config');
// node@16 没有 structuredClone 方法导致报错:
// ReferenceError: Error while loading rule '@typescript-eslint/naming-convention': structuredClone is not defined
// 此处做个简单 polyfill
if (typeof structuredClone === 'undefined') {
global.structuredClone = obj => JSON.parse(JSON.stringify(obj));
}
module.exports = { defineConfig };

View File

@@ -0,0 +1,22 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@coze-arch/ts-config/tsconfig.node.json",
"compilerOptions": {
"sourceMap": false,
"lib": ["ES2021"],
"esModuleInterop": true,
"types": ["node"],
"rootDir": "./src",
"outDir": "dist",
"tsBuildInfoFile": "dist/tsconfig.build.tsbuildinfo"
},
"include": ["./src", "./src/**/*.json"],
"references": [
{
"path": "../../infra/eslint-plugin/tsconfig.build.json"
},
{
"path": "../ts-config/tsconfig.build.json"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"composite": true
},
"references": [
{
"path": "./tsconfig.build.json"
},
{
"path": "./tsconfig.misc.json"
}
],
"exclude": ["**/*"]
}

View File

@@ -0,0 +1,18 @@
{
"extends": "@coze-arch/ts-config/tsconfig.node.json",
"$schema": "https://json.schemastore.org/tsconfig",
"include": ["__tests__", "vitest.config.ts"],
"exclude": ["./dist"],
"references": [
{
"path": "./tsconfig.build.json"
}
],
"compilerOptions": {
"rootDir": "./",
"outDir": "./dist",
"sourceMap": false,
"lib": ["ES2021"],
"esModuleInterop": true
}
}

View File

@@ -0,0 +1,225 @@
# @coze-arch/postcss-config
A shared PostCSS configuration for Coze architecture projects that provides a standardized set of PostCSS plugins for modern CSS preprocessing and Tailwind CSS integration.
## Features
- **PostCSS Import**: Process `@import` statements and inline imported files
- **Tailwind CSS Nesting**: Full support for CSS nesting with Tailwind CSS compatibility
- **Autoprefixer**: Automatic vendor prefixing for cross-browser compatibility
- **Modern CSS Support**: Enhanced pseudo-class support with `:is()` functionality
- **Zero Configuration**: Works out of the box with sensible defaults
- **Optimized Build**: Configured for both development and production workflows
## Get Started
### Installation
```bash
# Install as a workspace dependency
npm install @coze-arch/postcss-config@workspace:*
# Update rush dependencies
rush update
```
### Basic Usage
Create a `postcss.config.js` file in your project root:
```javascript
module.exports = require('@coze-arch/postcss-config');
```
Or extend the configuration:
```javascript
const baseConfig = require('@coze-arch/postcss-config');
module.exports = {
...baseConfig,
plugins: {
...baseConfig.plugins,
// Add your custom plugins here
'postcss-custom-plugin': {},
},
};
```
### Integration with Build Tools
#### Webpack
```javascript
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader', // Will automatically use postcss.config.js
],
},
],
},
};
```
#### Vite
```javascript
// vite.config.js
export default {
css: {
postcss: require('@coze-arch/postcss-config'),
},
};
```
#### Rsbuild
```javascript
// rsbuild.config.js
export default {
tools: {
postcss: require('@coze-arch/postcss-config'),
},
};
```
## API Reference
### Default Configuration
The package exports a PostCSS configuration object with the following plugins:
```javascript
{
plugins: {
'postcss-import': {},
'tailwindcss/nesting': 'postcss-nesting',
'tailwindcss': {},
'autoprefixer': {},
'@csstools/postcss-is-pseudo-class': {},
}
}
```
### Plugin Details
#### postcss-import
- **Purpose**: Processes `@import` statements and inlines imported CSS files
- **Configuration**: Default settings (empty object)
- **Use Case**: Modular CSS organization and file imports
#### tailwindcss/nesting
- **Purpose**: Enables CSS nesting syntax compatible with Tailwind CSS
- **Configuration**: Uses `postcss-nesting` as the nesting implementation
- **Use Case**: Writing nested CSS with Tailwind utility classes
#### tailwindcss
- **Purpose**: Processes Tailwind CSS utility classes and directives
- **Configuration**: Default settings (reads from `tailwind.config.js`)
- **Use Case**: Utility-first CSS framework integration
#### autoprefixer
- **Purpose**: Automatically adds vendor prefixes to CSS properties
- **Configuration**: Default settings (uses browserslist configuration)
- **Use Case**: Cross-browser compatibility without manual prefixing
#### @csstools/postcss-is-pseudo-class
- **Purpose**: Transforms `:is()` pseudo-class for better browser support
- **Configuration**: Default settings
- **Use Case**: Modern CSS pseudo-class support in older browsers
### Customization Examples
#### Adding Custom Plugins
```javascript
const baseConfig = require('@coze-arch/postcss-config');
module.exports = {
...baseConfig,
plugins: {
...baseConfig.plugins,
'postcss-custom-properties': {
preserve: false,
},
'cssnano': {
preset: 'default',
},
},
};
```
#### Plugin Order Customization
```javascript
const baseConfig = require('@coze-arch/postcss-config');
module.exports = {
plugins: {
'postcss-import': baseConfig.plugins['postcss-import'],
'custom-plugin': {},
'tailwindcss/nesting': baseConfig.plugins['tailwindcss/nesting'],
'tailwindcss': baseConfig.plugins['tailwindcss'],
'autoprefixer': baseConfig.plugins['autoprefixer'],
'@csstools/postcss-is-pseudo-class': baseConfig.plugins['@csstools/postcss-is-pseudo-class'],
},
};
```
## Development
### Project Structure
```
config/postcss-config/
├── src/
│ └── index.js # Main configuration export
├── package.json # Package configuration
├── eslint.config.js # ESLint configuration
├── tsconfig.*.json # TypeScript configurations
└── README.md # This file
```
### Development Commands
```bash
# Lint the code
rush lint
# Run all checks
rush build
```
### Contributing
1. Follow the existing code style and configuration patterns
2. Ensure all linting passes before submitting changes
3. Test the configuration with actual PostCSS processing
4. Update documentation for any configuration changes
## Dependencies
### Runtime Dependencies
- **postcss**: Core PostCSS processor
- **postcss-import**: Import processing plugin
- **postcss-loader**: Webpack integration
- **postcss-nesting**: CSS nesting support
- **@tailwindcss/nesting**: Tailwind-compatible nesting
- **@csstools/postcss-is-pseudo-class**: Modern pseudo-class support
### Development Dependencies
- **@coze-arch/eslint-config**: Shared ESLint configuration
- **@coze-arch/ts-config**: Shared TypeScript configuration
- **@types/node**: Node.js type definitions
## License
Internal use within Coze architecture projects.

View File

@@ -0,0 +1,8 @@
{
"operationSettings": [
{
"operationName": "ts-check",
"outputFolderNames": ["dist"]
}
]
}

View File

@@ -0,0 +1,6 @@
const { defineConfig } = require('@coze-arch/eslint-config');
module.exports = defineConfig({
preset: 'node',
packageRoot: __dirname,
});

View File

@@ -0,0 +1,27 @@
{
"name": "@coze-arch/postcss-config",
"version": "0.0.1",
"author": "huangjian@bytedance.com",
"maintainers": [],
"main": "src/index.js",
"scripts": {
"build": "exit",
"dev": "npm run build -- -w",
"lint": "eslint ./ --cache --quiet",
"test": "exit",
"test:cov": "exit"
},
"dependencies": {
"@csstools/postcss-is-pseudo-class": "^4.0.5",
"@tailwindcss/nesting": "latest",
"postcss": "^8.4.32",
"postcss-import": "^16.1.0",
"postcss-loader": "^7.3.3",
"postcss-nesting": "^12.1.0"
},
"devDependencies": {
"@coze-arch/eslint-config": "workspace:*",
"@coze-arch/ts-config": "workspace:*",
"@types/node": "^18"
}
}

View File

@@ -0,0 +1,9 @@
module.exports = {
plugins: {
'postcss-import': {},
'tailwindcss/nesting': 'postcss-nesting',
tailwindcss: {},
autoprefixer: {},
'@csstools/postcss-is-pseudo-class': {},
},
};

View File

@@ -0,0 +1,22 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@coze-arch/ts-config/tsconfig.node.json",
"compilerOptions": {
"sourceMap": false,
"esModuleInterop": true,
"types": [],
"rootDir": "./src",
"outDir": "dist",
"allowJs": true,
"tsBuildInfoFile": "dist/tsconfig.build.tsbuildinfo"
},
"include": ["./src", "./src/**/*.json"],
"references": [
{
"path": "../eslint-config/tsconfig.build.json"
},
{
"path": "../ts-config/tsconfig.build.json"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"composite": true
},
"references": [
{
"path": "./tsconfig.build.json"
},
{
"path": "./tsconfig.misc.json"
}
],
"exclude": ["**/*"]
}

View File

@@ -0,0 +1,17 @@
{
"extends": "@coze-arch/ts-config/tsconfig.node.json",
"$schema": "https://json.schemastore.org/tsconfig",
"include": ["__tests__", "vitest.config.ts"],
"exclude": ["./dist"],
"references": [
{
"path": "./tsconfig.build.json"
}
],
"compilerOptions": {
"rootDir": "./",
"outDir": "./dist",
"sourceMap": false,
"esModuleInterop": true
}
}

View File

@@ -0,0 +1,61 @@
# @coze-arch/rsbuild-config
rsbuild config
## Overview
This package is part of the Coze Studio monorepo and provides ui component functionality. It includes plugin.
## Getting Started
### Installation
Add this package to your `package.json`:
```json
{
"dependencies": {
"@coze-arch/rsbuild-config": "workspace:*"
}
}
```
Then run:
```bash
rush update
```
### Usage
```typescript
import { /* exported functions/components */ } from '@coze-arch/rsbuild-config';
// Example usage
// TODO: Add specific usage examples
```
## Features
- Plugin
## API Reference
Please refer to the TypeScript definitions for detailed API documentation.
## Development
This package is built with:
- TypeScript
- Modern JavaScript
- Vitest for testing
- ESLint for code quality
## Contributing
This package is part of the Coze Studio monorepo. Please follow the monorepo contribution guidelines.
## License
Apache-2.0

View File

@@ -0,0 +1,12 @@
{
"operationSettings": [
{
"operationName": "test:cov",
"outputFolderNames": ["coverage"]
},
{
"operationName": "ts-check",
"outputFolderNames": ["dist"]
}
]
}

View File

@@ -0,0 +1,7 @@
const { defineConfig } = require('@coze-arch/eslint-config');
module.exports = defineConfig({
packageRoot: __dirname,
preset: 'node',
rules: {},
});

View File

@@ -0,0 +1,42 @@
{
"name": "@coze-arch/rsbuild-config",
"version": "0.0.1",
"description": "rsbuild config ",
"license": "Apache-2.0",
"author": "fanwenjie.fe@bytedance.com",
"maintainers": [],
"main": "src/index.ts",
"scripts": {
"build": "exit 0",
"lint": "eslint ./ --cache",
"test": "vitest --run --passWithNoTests",
"test:cov": "npm run test -- --coverage"
},
"dependencies": {
"@coze-arch/bot-env": "workspace:*",
"@coze-arch/pkg-root-webpack-plugin": "workspace:*",
"@coze-arch/semi-theme-hand01": "0.0.6-alpha.346d77",
"@coze-common/assets": "workspace:*",
"@douyinfe/semi-rspack-plugin": "2.61.0",
"@rsbuild/core": "~1.1.0",
"@rsbuild/plugin-less": "~1.1.0",
"@rsbuild/plugin-react": "~1.1.0",
"@rsbuild/plugin-sass": "~1.1.0",
"@rsbuild/plugin-svgr": "~1.0.6",
"postcss": "^8.4.32",
"postcss-nesting": "^12.1.0",
"tailwindcss": "~3.3.3"
},
"devDependencies": {
"@coze-arch/eslint-config": "workspace:*",
"@coze-arch/ts-config": "workspace:*",
"@coze-arch/vitest-config": "workspace:*",
"@types/node": "^18",
"@vitest/coverage-v8": "~3.0.5",
"sucrase": "^3.32.0",
"typescript": "~5.8.2",
"vitest": "~3.0.5",
"webpack": "~5.91.0"
}
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import path from 'path';
import { pluginSvgr } from '@rsbuild/plugin-svgr';
import { pluginSass } from '@rsbuild/plugin-sass';
import { pluginReact } from '@rsbuild/plugin-react';
import { pluginLess } from '@rsbuild/plugin-less';
import { type RsbuildConfig, mergeRsbuildConfig } from '@rsbuild/core';
import { PkgRootWebpackPlugin } from '@coze-arch/pkg-root-webpack-plugin';
import { GLOBAL_ENVS } from '@coze-arch/bot-env';
import { SemiRspackPlugin } from '@douyinfe/semi-rspack-plugin';
const getDefine = () => {
const define = {};
Object.keys(GLOBAL_ENVS).forEach(key => {
// 在rspack的define中字符串需要前后拼接上双引号才能在代码中作为字符串使用。
if (typeof GLOBAL_ENVS[key] === 'string') {
define[key] = `"${GLOBAL_ENVS[key]}"`;
} else {
define[key] = GLOBAL_ENVS[key];
}
});
return define;
};
export const overrideBrowserslist = [
'chrome >= 51',
'edge >= 15',
'firefox >= 54',
'safari >= 10',
'ios_saf >= 10',
];
const generateCdnPrefix = () => {
if (process.env.CDN_INNER_CN) {
return `https://${process.env.CDN_INNER_CN}/${process.env.CDN_PATH_PREFIX ? `${process.env.CDN_PATH_PREFIX}/` : ''}`;
}
return '/';
};
export const defineConfig = (options: Partial<RsbuildConfig>) => {
const cdnPrefix = generateCdnPrefix();
const port = 8080;
const commonAssertsUrl = path.dirname(
require.resolve('@coze-common/assets/package.json'),
);
const config: RsbuildConfig = {
dev: {
client: {
port,
host: '127.0.0.1',
protocol: 'ws',
},
},
server: {
port,
},
plugins: [
pluginReact(),
pluginSvgr({
mixedImport: true,
svgrOptions: {
exportType: 'named',
},
}),
pluginLess({
lessLoaderOptions: {
additionalData: `@import "${path.resolve(
commonAssertsUrl,
'style/variables.less',
)}";`,
},
}),
pluginSass({
sassLoaderOptions: {
sassOptions: {
silenceDeprecations: ['mixed-decls', 'import', 'function-units'],
},
},
}),
],
output: {
filenameHash: true,
assetPrefix: cdnPrefix,
injectStyles: true,
cssModules: {
auto: true,
},
sourceMap: {
js: 'source-map',
},
overrideBrowserslist,
},
source: {
define: getDefine(),
alias: {
'@coze-arch/semi-theme-hand01': path.dirname(
require.resolve('@coze-arch/semi-theme-hand01/package.json'),
),
},
include: [
// 以下几个包包含未降级的 ES 2022 语法private methods需要参与打包
/\/node_modules\/(marked|@dagrejs|@tanstack)\//,
],
},
tools: {
postcss: (opts, { addPlugins }) => {
addPlugins([
// eslint-disable-next-line @typescript-eslint/no-require-imports
require('tailwindcss/nesting')(require('postcss-nesting')),
]);
},
rspack: (_, { appendPlugins }) => {
appendPlugins([
new PkgRootWebpackPlugin(),
new SemiRspackPlugin({
theme: '@coze-arch/semi-theme-hand01',
}),
]);
},
},
};
return mergeRsbuildConfig(config, options);
};

View File

@@ -0,0 +1,34 @@
{
"extends": "@coze-arch/ts-config/tsconfig.node.json",
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"module": "CommonJS",
"target": "ES2020",
"moduleResolution": "node",
"tsBuildInfoFile": "dist/tsconfig.build.tsbuildinfo"
},
"include": ["src"],
"exclude": ["node_modules", "dist"],
"references": [
{
"path": "../eslint-config/tsconfig.build.json"
},
{
"path": "../../infra/plugins/pkg-root-webpack-plugin/tsconfig.build.json"
},
{
"path": "../../packages/arch/bot-env/tsconfig.build.json"
},
{
"path": "../../packages/common/assets/tsconfig.build.json"
},
{
"path": "../ts-config/tsconfig.build.json"
},
{
"path": "../vitest-config/tsconfig.build.json"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"exclude": ["**/*"],
"compilerOptions": {
"composite": true
},
"references": [
{
"path": "./tsconfig.build.json"
},
{
"path": "./tsconfig.misc.json"
}
]
}

View File

@@ -0,0 +1,18 @@
{
"extends": "@coze-arch/ts-config/tsconfig.node.json",
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"rootDir": "./",
"outDir": "./dist",
"module": "CommonJS",
"target": "ES2020",
"moduleResolution": "node"
},
"include": ["__tests__", "vitest.config.ts"],
"exclude": ["./dist"],
"references": [
{
"path": "./tsconfig.build.json"
}
]
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { defineConfig } from '@coze-arch/vitest-config';
export default defineConfig({
dirname: __dirname,
preset: 'node',
});

View File

@@ -0,0 +1,39 @@
module.exports = {
extends: [
'stylelint-config-standard',
'stylelint-config-standard-less',
'stylelint-config-clean-order',
],
plugins: ['./plugins/plugin-disallow-nesting-level-one-global.js'],
rules: {
// 变量命名规则,适应仓库内的代码风格
'custom-property-pattern': '^([A-Za-z0-9]*)([-_]+[A-Za-z0-9]+)*$',
// 对于less函数判断有问题
'less/no-duplicate-variables': null,
'media-feature-range-notation': null,
'max-nesting-depth': [
3,
{
ignore: ['pseudo-classes'],
ignoreRules: ['/:global/'],
message: 'Expected nesting depth to be no more than 3.',
},
],
'plugin/disallow-first-level-global': true,
'selector-class-pattern': [
'^([a-z][a-z0-9]*)(-[a-z0-9]+)*(_[a-z0-9]+)?$',
{
resolveNestedSelectors: true,
message: 'Expected class pattern is $block-$element_$modifier.',
},
],
'declaration-no-important': true,
'color-function-notation': null,
'at-rule-no-unknown': [
true,
{
ignoreAtRules: ['tailwind'],
},
],
},
};

View File

@@ -0,0 +1,250 @@
# @coze-arch/stylelint-config
A comprehensive and opinionated stylelint configuration package designed for Coze's frontend projects. This package provides a standardized set of CSS/Less linting rules that enforce consistent code style, maintainability, and best practices across the codebase.
## Features
- 🔧 **Pre-configured Rules**: Built on top of industry-standard configurations including `stylelint-config-standard`, `stylelint-config-standard-less`, and `stylelint-config-clean-order`
- 📏 **BEM-style Class Naming**: Enforces `$block-$element_$modifier` naming pattern for CSS classes
- 🏗️ **Nesting Control**: Limits CSS nesting depth to 3 levels for better readability and performance
- 🚫 **Custom Rules**: Includes custom plugins to prevent first-level `:global` selectors and enforce coding standards
- 🎨 **Less Support**: Full support for Less syntax and variables
- 📋 **Property Ordering**: Automatic CSS property ordering for consistent code structure
-**Tailwind Compatible**: Configured to work seamlessly with Tailwind CSS
## Get Started
### Installation
Add the package to your project:
```bash
# In your project's package.json
{
"devDependencies": {
"@coze-arch/stylelint-config": "workspace:*"
}
}
```
Then run:
```bash
rush update
```
### Basic Usage
Create a `.stylelintrc.js` file in your project root:
```javascript
const { defineConfig } = require('@coze-arch/stylelint-config');
module.exports = defineConfig({
extends: [],
rules: {
// Add your custom rules here
}
});
```
Or use the configuration directly:
```javascript
module.exports = {
extends: ['@coze-arch/stylelint-config']
};
```
## API Reference
### `defineConfig(config)`
The main configuration function that extends the base stylelint configuration.
**Parameters:**
- `config` (Config): Stylelint configuration object
**Returns:**
- `Config`: Extended stylelint configuration
**Example:**
```javascript
const { defineConfig } = require('@coze-arch/stylelint-config');
module.exports = defineConfig({
extends: ['stylelint-config-recommended-scss'],
rules: {
'color-hex-length': 'long',
'declaration-block-trailing-semicolon': 'always'
},
ignoreFiles: ['dist/**/*']
});
```
## Configuration Rules
### Class Naming Pattern
The configuration enforces BEM-style class naming with the pattern: `$block-$element_$modifier`
```css
/* ✅ Good */
.button { }
.button-large { }
.button-large_disabled { }
.nav-item { }
.nav-item_active { }
/* ❌ Bad */
.Button { }
.button_large_disabled { }
.nav-item-active-disabled { }
.camelCaseClass { }
```
### Nesting Depth
Maximum nesting depth is limited to 3 levels (excluding pseudo-classes):
```less
/* ✅ Good */
.component {
.header {
.title {
color: blue;
}
}
}
/* ❌ Bad */
.component {
.header {
.title {
.text {
.span { // Too deep!
color: blue;
}
}
}
}
}
```
### Global Selectors
First-level `:global` selectors are disallowed:
```less
/* ❌ Bad */
:global {
.some-class {
color: red;
}
}
/* ✅ Good */
.component {
:global {
.some-class {
color: red;
}
}
}
```
### Important Declarations
The use of `!important` is prohibited:
```css
/* ❌ Bad */
.class {
color: red !important;
}
/* ✅ Good */
.class {
color: red;
}
```
## Examples
### Basic Less File
```less
// Good example following all rules
.card {
padding: 16px;
border: 1px solid #ccc;
border-radius: 4px;
&-header {
margin-bottom: 12px;
font-weight: bold;
&_featured {
background-color: #f0f0f0;
}
}
&-content {
line-height: 1.5;
}
}
```
### With Tailwind Classes
```less
.custom-component {
@apply flex items-center justify-between;
&-item {
@apply px-4 py-2 rounded;
&_active {
@apply bg-blue-500 text-white;
}
}
}
```
## Development
### Running Examples
Test the configuration against example files:
```bash
rush stylelint-config example
```
This will run stylelint against the files in the `examples/` directory.
### Custom Rules
The package includes a custom plugin located at `plugins/plugin-disallow-nesting-level-one-global.js` that prevents first-level `:global` selectors.
## Dependencies
### Runtime Dependencies
This package has no runtime dependencies.
### Development Dependencies
- **stylelint**: ^15.11.0 - Core stylelint engine
- **stylelint-config-standard**: ^34.0.0 - Standard CSS rules
- **stylelint-config-standard-less**: ^2.0.0 - Less-specific rules
- **stylelint-config-clean-order**: ^5.2.0 - CSS property ordering
- **stylelint-config-rational-order**: ^0.1.2 - Alternative property ordering
- **sucrase**: ^3.32.0 - TypeScript compilation
## License
Apache-2.0 License
---
For more information about stylelint configuration options, visit the [official stylelint documentation](https://stylelint.io/user-guide/configuration/).

View File

@@ -0,0 +1,8 @@
{
"operationSettings": [
{
"operationName": "ts-check",
"outputFolderNames": ["./output"]
}
]
}

View File

@@ -0,0 +1,6 @@
const { defineConfig } = require('@coze-arch/eslint-config');
module.exports = defineConfig({
preset: 'node',
packageRoot: __dirname,
});

View File

@@ -0,0 +1,54 @@
// bad
.a1_b1_c1 {
margin: auto;
}
// bad
.a2-b2_c2-d2 {
margin: auto;
}
// bad
.a3-b3_c3_d3 {
margin: auto;
}
// bad
.a4-b4 {
&_c4_d4 {
margin: auto;
}
}
// bad
.a5-cammelCase {
margin: auto;
}
// good
.a5-b5-c5 {
margin: auto;
}
// good
.a6-b6-c6_d6 {
margin: auto;
}
// good
.a7_b7 {
margin: auto;
}
// good
.a8 {
&-b8 {
&-c8 {
margin: auto;
}
&_d8 {
margin: auto;
}
}
}

View File

@@ -0,0 +1,17 @@
// bad
// bad
/* stylelint-disable plugin/disallow-first-level-global */
:global {
.semi-button {
width: 300px;
}
}
// ok
.a {
:global {
.semi-button {
width: 300px;
}
}
}

View File

@@ -0,0 +1,28 @@
// bad
.a1 {
.b1 {
.c1 {
.d1 {
.e1 {
margin: auto;
}
}
}
}
}
// good
.a2 .b2 .c2 .d2 .e2 {
margin: auto;
}
// still good
.a3 .b3 {
.c3 {
.d3 {
.e3 {
margin: auto;
}
}
}
}

View File

@@ -0,0 +1,10 @@
// avoid
.a {
opacity: 0 !important;
}
// if you have to
.b {
/* stylelint-disable-next-line declaration-no-important */
opacity: 0 !important;
}

View File

@@ -0,0 +1,27 @@
{
"name": "@coze-arch/stylelint-config",
"version": "1.0.0",
"description": "",
"keywords": [],
"license": "Apache-2.0",
"author": "liukaizhan.038@bytedance.com",
"main": "src/index.js",
"scripts": {
"build": "exit 0",
"example": "stylelint './examples/*.{css,less}'",
"lint": "eslint ./"
},
"dependencies": {},
"devDependencies": {
"@coze-arch/eslint-config": "workspace:*",
"@coze-arch/ts-config": "workspace:*",
"@types/node": "^18",
"stylelint": "^15.11.0",
"stylelint-config-clean-order": "^5.2.0",
"stylelint-config-rational-order": "^0.1.2",
"stylelint-config-recommended": "^13.0.0",
"stylelint-config-standard": "^34.0.0",
"stylelint-config-standard-less": "^2.0.0",
"sucrase": "^3.32.0"
}
}

View File

@@ -0,0 +1,28 @@
const stylelint = require('stylelint');
const ruleName = 'plugin/disallow-first-level-global';
module.exports = stylelint.createPlugin(ruleName, function (ruleValue) {
if (ruleValue === null || ruleValue === undefined || ruleValue === false) {
return () => {
// Nop.
};
}
return function (postcssRoot, postcssResult) {
postcssRoot.walkRules(rule => {
if (rule.parent.type === 'root' && /:global/.test(rule.selector)) {
stylelint.utils.report({
ruleName,
result: postcssResult,
node: rule,
message: 'Disallow :global class with nesting level of 1',
});
}
});
};
});
module.exports.ruleName = ruleName;
module.exports.messages = stylelint.utils.ruleMessages(ruleName, {
expected: 'Disallow :global class with nesting level of 1',
});

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import path from 'path';
import { type Config } from 'stylelint';
/**
* Define an Lint config.
*
* @param config StyleLint config.
* @returns StyleLint config.
*/
export const defineConfig = (config: Config): Config => {
const { extends: rawExtends, rules = {}, ...userConfig } = config;
return {
// @ts-expect-error -- linter-disable-autofix
extends: [path.resolve(__dirname, '../.stylelintrc.js'), ...rawExtends],
rules: {
...rules,
},
...userConfig,
};
};

View File

@@ -0,0 +1,5 @@
require('sucrase/register/ts');
const { defineConfig } = require('./define-config');
module.exports = { defineConfig };

View File

@@ -0,0 +1,22 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@coze-arch/ts-config/tsconfig.node.json",
"include": ["src"],
"compilerOptions": {
"sourceMap": false,
"esModuleInterop": true,
"target": "ESNext",
"strictNullChecks": true,
"rootDir": "./src",
"outDir": "./output",
"tsBuildInfoFile": "output/tsconfig.build.tsbuildinfo"
},
"references": [
{
"path": "../eslint-config/tsconfig.build.json"
},
{
"path": "../ts-config/tsconfig.build.json"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"composite": true
},
"references": [
{
"path": "./tsconfig.build.json"
},
{
"path": "./tsconfig.misc.json"
}
],
"exclude": ["**/*"]
}

View File

@@ -0,0 +1,19 @@
{
"extends": "@coze-arch/ts-config/tsconfig.node.json",
"$schema": "https://json.schemastore.org/tsconfig",
"include": ["__tests__", "vitest.config.ts"],
"exclude": ["./dist"],
"references": [
{
"path": "./tsconfig.build.json"
}
],
"compilerOptions": {
"rootDir": "./",
"outDir": "./dist",
"sourceMap": false,
"esModuleInterop": true,
"target": "ESNext",
"strictNullChecks": true
}
}

View File

@@ -0,0 +1,276 @@
# @coze-arch/tailwind-config
A comprehensive Tailwind CSS configuration package for the Coze design system, providing consistent theming, color palettes, and semantic design tokens across all applications.
## Features
- 🎨 **Complete Design System**: Pre-configured colors, spacing, typography, and component styles
- 🌙 **Dark Mode Support**: Built-in light/dark theme switching with CSS variables
- 🎯 **Semantic Classes**: Meaningful utility classes like `coz-fg-primary`, `coz-bg-secondary`
- 🧩 **Component-Ready**: Pre-defined styles for buttons, inputs, and other UI components
- 🎨 **Rich Color Palette**: Extensive color system including brand, functional, and semantic colors
- 📐 **Consistent Spacing**: Standardized spacing system across all dimensions
- 🔧 **Design Token Integration**: Support for converting design tokens to Tailwind config
## Get Started
### Installation
```bash
# Install the package in your workspace
pnpm add @coze-arch/tailwind-config@workspace:*
# Update Rush to install dependencies
rush update
```
### Basic Usage
In your `tailwind.config.js`:
```javascript
const cozeConfig = require('@coze-arch/tailwind-config');
module.exports = {
...cozeConfig,
content: [
'./src/**/*.{js,ts,jsx,tsx}',
// your content paths
],
// extend or override as needed
theme: {
extend: {
...cozeConfig.theme.extend,
// your custom extensions
},
},
};
```
### Using the Coze Plugin
For semantic utilities and CSS variables:
```javascript
const cozePlugin = require('@coze-arch/tailwind-config/coze');
module.exports = {
// ... your config
plugins: [
cozePlugin,
// other plugins
],
};
```
### Design Token Integration
Convert design tokens to Tailwind configuration:
```javascript
import { designTokenToTailwindConfig, getPackagesContents } from '@coze-arch/tailwind-config/design-token';
const tokenConfig = designTokenToTailwindConfig(yourDesignTokens);
module.exports = {
content: [
'./src/**/*.{js,ts,jsx,tsx}',
...getPackagesContents(), // Auto-discover package contents
],
theme: {
extend: tokenConfig,
},
};
```
## API Reference
### Main Configuration
The default export provides a complete Tailwind configuration with:
#### Colors
```javascript
// Brand colors
'text-brand-5' // Primary brand color
'bg-brand-1' // Light brand background
'border-brand-3' // Brand border
// Semantic colors
'text-foreground-3' // Primary text
'text-foreground-2' // Secondary text
'bg-background-1' // Primary background
'bg-background-0' // Secondary background
// Functional colors
'text-red-5' // Error/danger
'text-yellow-5' // Warning
'text-green-5' // Success
```
#### Spacing & Sizing
```javascript
// Semantic spacing
'p-normal' // 32px padding
'm-small' // 20px margin
'gap-mini' // 16px gap
// Precise spacing
'w-320px' // 320px width
'h-240px' // 240px height
'p-24px' // 24px padding
```
#### Typography
```javascript
// Font sizes
'text-mini' // 10px
'text-base' // 12px
'text-lg' // 14px
'text-xl' // 15px
'text-xxl' // 16px
'text-24px' // 24px
```
### Coze Plugin
The Coze plugin adds semantic utility classes and CSS variables:
```javascript
// Semantic foreground classes
'coz-fg-primary' // Primary text color
'coz-fg-secondary' // Secondary text color
'coz-fg-hglt' // Highlight text color
// Semantic background classes
'coz-bg-primary' // Primary background
'coz-bg-secondary' // Secondary background
'coz-mg-hglt' // Highlight background
// Component-specific classes
'coz-btn-rounded-normal' // Button border radius
'coz-input-height-large' // Input height
'coz-shadow-large' // Large shadow
```
### Design Token Functions
#### `designTokenToTailwindConfig(tokenJson)`
Converts design tokens to Tailwind configuration:
```javascript
const tokenConfig = designTokenToTailwindConfig({
palette: {
light: { 'primary-500': '#3b82f6' },
dark: { 'primary-500': '#60a5fa' }
},
tokens: {
color: {
light: { 'primary-color': 'var(primary-500)' },
dark: { 'primary-color': 'var(primary-500)' }
},
spacing: {
'spacing-sm': '8px',
'spacing-md': '16px'
}
}
});
```
#### `getPackagesContents(subPath?)`
Auto-discovers package source files for content configuration:
```javascript
const contents = getPackagesContents();
// Returns: [
// '/path/to/package1/src/**/*.{ts,tsx}',
// '/path/to/package2/src/**/*.{ts,tsx}',
// ...
// ]
```
## Development
### Project Structure
```
src/
├── index.js # Main Tailwind configuration
├── coze.js # Coze plugin with semantic utilities
├── design-token.ts # Design token conversion utilities
├── light.js # Light theme CSS variables
└── dark.js # Dark theme CSS variables
```
### Theme System
The package uses CSS variables for theming:
```css
:root {
--coze-brand-5: 81, 71, 255;
--coze-fg-3: 15, 21, 40;
--coze-bg-1: 247, 247, 252;
}
.dark {
--coze-brand-5: 166, 166, 255;
--coze-fg-3: 255, 255, 255;
--coze-bg-1: 24, 28, 43;
}
```
Colors are defined as RGB values to support alpha transparency:
```css
.text-brand-5 {
color: rgba(var(--coze-brand-5), 1);
}
.bg-brand-1 {
background-color: rgba(var(--coze-brand-1), var(--coze-brand-1-alpha));
}
```
### Adding New Colors
1. Add the RGB values to `light.js` and `dark.js`
2. Add alpha values for transparency support
3. Update the main configuration in `index.js`
4. Add semantic classes to `coze.js` if needed
### Testing
```bash
# Run linting
pnpm lint
# Build (no-op for this package)
pnpm build
```
## Dependencies
### Runtime Dependencies
- **tailwindcss** (~3.3.3) - Core Tailwind CSS framework
- **@tailwindcss/forms** (^0.5.7) - Form styling plugin
- **@tailwindcss/nesting** (latest) - CSS nesting support
- **postcss** (^8.4.32) - CSS transformation tool
- **postcss-loader** (^7.3.3) - Webpack PostCSS loader
- **autoprefixer** (^10.4.16) - CSS vendor prefixing
### Development Dependencies
- **@coze-arch/eslint-config** (workspace:*) - Shared ESLint configuration
- **@coze-arch/ts-config** (workspace:*) - Shared TypeScript configuration
- **@types/node** (^18) - Node.js type definitions
## License
This package is part of the Coze architecture and follows the project's licensing terms.

View File

@@ -0,0 +1,8 @@
{
"operationSettings": [
{
"operationName": "ts-check",
"outputFolderNames": ["dist"]
}
]
}

View File

@@ -0,0 +1,7 @@
const { defineConfig } = require('@coze-arch/eslint-config');
module.exports = defineConfig({
preset: 'node',
packageRoot: __dirname,
rules: {},
});

View File

@@ -0,0 +1,35 @@
{
"name": "@coze-arch/tailwind-config",
"version": "0.0.1",
"author": "huangjian@bytedance.com",
"maintainers": [],
"exports": {
".": "./src/index.js",
"./coze": "./src/coze.js",
"./design-token": "./src/design-token.ts"
},
"main": "src/index.js",
"scripts": {
"build": "exit",
"dev": "npm run build -- -w",
"lint": "eslint ./ --cache --quiet",
"test": "exit",
"test:cov": "exit"
},
"dependencies": {
"@coze-arch/monorepo-kits": "workspace:*",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/nesting": "latest",
"autoprefixer": "^10.4.16",
"fast-glob": "^3.2.11",
"postcss": "^8.4.32",
"postcss-loader": "^7.3.3",
"tailwindcss": "~3.3.3"
},
"devDependencies": {
"@coze-arch/eslint-config": "workspace:*",
"@coze-arch/ts-config": "workspace:*",
"@types/node": "^18"
}
}

View File

@@ -0,0 +1,258 @@
// tailwindcss-plugin.js
const plugin = require('tailwindcss/plugin');
// theme colors
const lightModeVariables = require('./light');
const darkModeVariables = require('./dark');
// 用于生成 CSS 变量的帮助函数
function generateCssVariables(variables, theme) {
return Object.entries(variables).reduce((acc, [key, value]) => {
acc[`--${key}`] = theme ? theme(value) : value;
return acc;
}, {});
}
// 样式语义化
function generateSemanticVariables(semantics, theme, property) {
return Object.entries(semantics).map(([key, value]) => ({
[`.${key}`]: {
[property]: theme(value),
},
}));
}
const semanticForeground = {
/* Theme */
'coz-fg-hglt-plus': 'colors.foreground.5',
'coz-fg-hglt-plus-dim': 'colors.foreground.5',
'coz-fg-hglt': 'colors.brand.5',
'coz-fg-hglt-dim': 'colors.brand.3',
'coz-fg-plus': 'colors.foreground.4',
'coz-fg': 'colors.foreground.3',
'coz-fg-primary': 'colors.foreground.3',
'coz-fg-secondary': 'colors.foreground.2',
'coz-fg-dim': 'colors.foreground.1',
'coz-fg-white': 'colors.foreground.7',
'coz-fg-white-dim': 'colors.foreground.white',
'coz-fg-hglt-ai': 'colors.purple.5',
'coz-fg-hglt-ai-dim': 'colors.purple.3',
/* Functional Color */
'coz-fg-hglt-red': 'colors.red.5',
'coz-fg-hglt-red-dim': 'colors.red.3',
'coz-fg-hglt-yellow': 'colors.yellow.5',
'coz-fg-hglt-yellow-dim': 'colors.yellow.3',
'coz-fg-hglt-green': 'colors.green.5',
'coz-fg-hglt-green-dim': 'colors.green.3',
/* Chart, Tag Only */
'coz-fg-color-orange': 'colors.yellow.5',
'coz-fg-color-orange-dim': 'colors.yellow.3',
'coz-fg-color-emerald': 'colors.green.5',
'coz-fg-color-emerald-dim': 'colors.green.3',
'coz-fg-color-cyan': 'colors.cyan.50',
'coz-fg-color-cyan-dim': 'colors.cyan.30',
'coz-fg-color-blue': 'colors.blue.50',
'coz-fg-color-blue-dim': 'colors.blue.30',
'coz-fg-color-purple': 'colors.purple.50',
'coz-fg-color-purple-dim': 'colors.purple.30',
'coz-fg-color-magenta': 'colors.magenta.50',
'coz-fg-color-magenta-dim': 'colors.magenta.3',
'coz-fg-color-yellow': 'colors.yellow.50',
'coz-fg-color-yellow-dim': 'colors.yellow.30',
/* Code Only */
'coz-fg-hglt-orange': 'colors.orange.5',
'coz-fg-hglt-orange-dim': 'colors.orange.3',
'coz-fg-hglt-emerald': 'colors.emerald.5',
'coz-fg-hglt-emerald-dim': 'colors.emerald.3',
'coz-fg-hglt-cyan': 'colors.cyan.5',
'coz-fg-hglt-cyan-dim': 'colors.cyan.3',
'coz-fg-hglt-blue': 'colors.blue.5',
'coz-fg-hglt-blue-dim': 'colors.blue.3',
'coz-fg-hglt-purple': 'colors.purple.5',
'coz-fg-hglt-purple-dim': 'colors.purple.3',
'coz-fg-hglt-magenta': 'colors.magenta.5',
'coz-fg-hglt-magenta-dim': 'colors.magenta.3',
/* branding Only */
'coz-fg-color-brand': 'colors.brand.50',
'coz-fg-color-brand-dim': 'colors.brand.30',
'coz-fg-color-alternative': 'colors.alternative.50',
'coz-fg-color-alternative-dim': 'colors.alternative.30',
};
const semanticMiddleground = {
/* Theme */
'coz-mg-hglt-plus-pressed': 'colors.brand.7',
'coz-mg-hglt-plus-hovered': 'colors.brand.6',
'coz-mg-hglt-plus': 'colors.brand.5',
'coz-mg-hglt-plus-dim': 'colors.brand.3',
'coz-mg-hglt-secondary-pressed': 'colors.brand.2',
'coz-mg-hglt-secondary-hovered': 'colors.brand.1',
'coz-mg-hglt-secondary': 'colors.brand.0',
'coz-mg-hglt-secondary-red': 'colors.red.0',
'coz-mg-hglt-secondary-yellow': 'colors.yellow.0',
'coz-mg-hglt-secondary-green': 'colors.green.0',
'coz-mg-plus-pressed': 'colors.background.8',
'coz-mg-plus-hovered': 'colors.background.7',
'coz-mg-plus': 'colors.background.6',
'coz-mg-hglt-pressed': 'colors.brand.3',
'coz-mg-hglt-hovered': 'colors.brand.2',
'coz-mg-hglt-plus-ai-pressed': 'colors.purple.7',
'coz-mg-hglt-plus-ai-hovered': 'colors.purple.6',
'coz-mg-hglt-plus-ai': 'colors.purple.5',
'coz-mg-hglt-plus-ai-dim': 'colors.purple.3',
'coz-mg-hglt': 'colors.brand.1',
'coz-mg-hglt-ai-pressed': 'colors.purple.3',
'coz-mg-hglt-ai-hovered': 'colors.purple.2',
'coz-mg-hglt-ai': 'colors.purple.1',
/* Functional Color */
'coz-mg-hglt-plus-red-pressed': 'colors.red.7',
'coz-mg-hglt-plus-red-hovered': 'colors.red.6',
'coz-mg-hglt-plus-red': 'colors.red.5',
'coz-mg-hglt-plus-red-dim': 'colors.red.3',
'coz-mg-hglt-plus-yellow-pressed': 'colors.yellow.7',
'coz-mg-hglt-plus-yellow-hovered': 'colors.yellow.6',
'coz-mg-hglt-plus-yellow': 'colors.yellow.5',
'coz-mg-hglt-plus-yellow-dim': 'colors.yellow.3',
'coz-mg-hglt-plus-green-pressed': 'colors.green.7',
'coz-mg-hglt-plus-green-hovered': 'colors.green.6',
'coz-mg-hglt-plus-green': 'colors.green.5',
'coz-mg-hglt-plus-green-dim': 'colors.green.3',
'coz-mg-hglt-red-pressed': 'colors.red.3',
'coz-mg-hglt-red-hovered': 'colors.red.2',
'coz-mg-hglt-red': 'colors.red.1',
'coz-mg-hglt-yellow-pressed': 'colors.yellow.3',
'coz-mg-hglt-yellow-hovered': 'colors.yellow.2',
'coz-mg-hglt-yellow': 'colors.yellow.1',
'coz-mg-hglt-green-pressed': 'colors.green.3',
'coz-mg-hglt-green-hovered': 'colors.green.2',
'coz-mg-hglt-green': 'colors.green.1',
/* Card, Tag, Avatar Only */
'coz-mg-color-plus-orange': 'colors.yellow.5',
'coz-mg-color-plus-emerald': 'colors.green.5',
'coz-mg-color-plus-cyan': 'colors.cyan.50',
'coz-mg-color-plus-blue': 'colors.blue.50',
'coz-mg-color-plus-purple': 'colors.purple.50',
'coz-mg-color-plus-magenta': 'colors.magenta.50',
'coz-mg-color-plus-yellow': 'colors.yellow.50',
'coz-mg-color-orange-pressed': 'colors.yellow.3',
'coz-mg-color-orange-hovered': 'colors.yellow.2',
'coz-mg-color-orange': 'colors.yellow.1',
'coz-mg-color-emerald-pressed': 'colors.green.3',
'coz-mg-color-emerald-hovered': 'colors.green.2',
'coz-mg-color-emerald': 'colors.green.1',
'coz-mg-color-cyan-pressed': 'colors.cyan.30',
'coz-mg-color-cyan-hovered': 'colors.cyan.20',
'coz-mg-color-cyan': 'colors.cyan.10',
'coz-mg-color-blue-pressed': 'colors.blue.30',
'coz-mg-color-blue-hovered': 'colors.blue.20',
'coz-mg-color-blue': 'colors.blue.10',
'coz-mg-color-purple-pressed': 'colors.purple.30',
'coz-mg-color-purple-hovered': 'colors.purple.20',
'coz-mg-color-purple': 'colors.purple.10',
'coz-mg-color-magenta-pressed': 'colors.magenta.30',
'coz-mg-color-magenta-hovered': 'colors.magenta.20',
'coz-mg-color-magenta': 'colors.magenta.10',
'coz-mg-primary-pressed': 'colors.background.7',
'coz-mg-primary-hovered': 'colors.background.6',
'coz-mg-primary': 'colors.background.5',
'coz-mg-secondary-pressed': 'colors.background.6',
'coz-mg-secondary-hovered': 'colors.background.5',
'coz-mg-secondary': 'colors.background.4',
'coz-mg': 'colors.background.4',
'coz-mg-mask': 'colors.mask.5',
'coz-mg-table-fixed-hovered': 'colors.background.0',
'coz-mg-card-pressed': 'colors.background.3',
'coz-mg-card-hovered': 'colors.background.3',
'coz-mg-card': 'colors.background.3',
/** brand */
'coz-mg-color-plus-brand': 'colors.brand.50',
};
const semanticBackground = {
'coz-bg-max': 'colors.background.3',
'coz-bg-plus': 'colors.background.2',
'coz-bg-primary': 'colors.background.1',
'coz-bg': 'colors.background.1',
'coz-bg-secondary': 'colors.background.0',
};
const semanticShadow = {
'coz-shadow': 'boxShadow.normal',
'coz-shadow-large': 'boxShadow.large',
'coz-shadow-default': 'boxShadow.normal',
'coz-shadow-small': 'boxShadow.small',
};
// Add button rounded definitions
const buttonRounded = {
'coz-btn-rounded-large': 'btnBorderRadius.large',
'coz-btn-rounded-normal': 'btnBorderRadius.normal',
'coz-btn-rounded-small': 'btnBorderRadius.small',
'coz-btn-rounded-mini': 'btnBorderRadius.mini',
};
const inputRounded = {
'coz-input-rounded-large': 'inputBorderRadius.large',
'coz-input-rounded-normal': 'inputBorderRadius.normal',
'coz-input-rounded-small': 'inputBorderRadius.small',
};
const inputHeight = {
'coz-input-height-large': 'inputHeight.large',
'coz-input-height-normal': 'inputHeight.normal',
'coz-input-height-small': 'inputHeight.small',
};
const semanticStroke = {
'coz-stroke-hglt': 'colors.brand.5',
'coz-stroke-plus': 'colors.stroke.6',
'coz-stroke-primary': 'colors.stroke.5',
'coz-stroke-hglt-red': 'colors.red.5',
'coz-stroke-hglt-yellow': 'colors.yellow.5',
'coz-stroke-hglt-green': 'colors.green.5',
'coz-stroke-color-orange': 'colors.yellow.5',
'coz-stroke-color-emerald': 'colors.green.5',
'coz-stroke-color-cyan': 'colors.cyan.50',
'coz-stroke-color-blue': 'colors.blue.50',
'coz-stroke-color-purple': 'colors.purple.50',
'coz-stroke-color-magenta': 'colors.magenta.50',
'coz-stroke-color-yellow': 'colors.yellow.50',
'coz-stroke-color-brand': 'colors.brand.50',
'coz-stroke-opaque': 'colors.stroke.opaque',
'coz-stroke-max': 'colors.stroke.max',
};
module.exports = plugin(function ({ addBase, addUtilities, theme }) {
addBase({
':root': generateCssVariables(lightModeVariables),
'.dark': generateCssVariables(darkModeVariables),
});
addBase({
':root': {
...generateCssVariables(semanticForeground, theme),
...generateCssVariables(semanticMiddleground, theme),
...generateCssVariables(semanticBackground, theme),
...generateCssVariables(semanticStroke, theme),
...generateCssVariables(semanticShadow, theme),
...generateCssVariables(buttonRounded, theme),
...generateCssVariables(inputRounded, theme),
...generateCssVariables(inputHeight, theme),
},
});
addUtilities([
...generateSemanticVariables(semanticForeground, theme, 'color'),
...generateSemanticVariables(
semanticMiddleground,
theme,
'background-color',
),
...generateSemanticVariables(semanticBackground, theme, 'background-color'),
...generateSemanticVariables(semanticStroke, theme, 'border-color'),
...generateSemanticVariables(semanticShadow, theme, 'box-shadow'),
...generateSemanticVariables(buttonRounded, theme, 'border-radius'),
...generateSemanticVariables(inputRounded, theme, 'border-radius'),
...generateSemanticVariables(inputHeight, theme, 'height'),
]);
});

Some files were not shown because too many files have changed in this diff Show More