npm package: @lark-apaas/fullstack-presets
Description: 独立拆分 simple 目录，属于全栈精简版，目前妙搭场景专用。
Latest version: 1.1.14

# 全栈技术栈 Presets
独立拆分 simple 目录，属于全栈精简版，目前妙搭场景专用。

## ESLint 自定义规则

### `no-nested-styled-jsx`

检测嵌套的 styled-jsx 标签，防止编译错误。https://nextjs.org/docs/messages/nested-styled-jsx-tags

该规则镜像了 styled-jsx babel 插件中的验证逻辑：
- [babel.js#L215](https://github.com/vercel/styled-jsx/blob/d7a59379134d73afaeb98177387cd62d54d746be/src/babel.js#L215)
- [babel.js#L222](https://github.com/vercel/styled-jsx/blob/d7a59379134d73afaeb98177387cd62d54d746be/src/babel.js#L222)

#### 使用方式

该规则已在 `eslint-client.ts` 配置中默认启用，无需额外配置：

```typescript
import clientConfig from '@lark-apaas/fullstack-presets/recommend/eslint/eslint-client';

export default [
  clientConfig,
  // 其他配置...
];
```

如需单独使用该规则：

```typescript
import { customRules } from '@lark-apaas/fullstack-presets/custom-eslint-rules';

export default [
  {
    plugins: {
      '@lark-apaas': { rules: customRules },
    },
    rules: {
      '@lark-apaas/no-nested-styled-jsx': 'error',
    },
  },
];
```

#### 错误信息

当检测到嵌套的 styled-jsx 标签时，规则会提供详细的错误信息，指出与哪一行的外层 styled-jsx 标签冲突：

```
17:23  error  Detected nested styled-jsx tag. The outer styled-jsx tag is at line 4. Read more: https://nextjs.org/docs/messages/nested-styled-jsx-tags  @lark-apaas/no-nested-styled-jsx
```

这样可以快速定位到冲突的外层 styled-jsx 标签，方便修复问题。

#### 自定义错误信息

可通过配置自定义报错信息：

```typescript
rules: {
  '@lark-apaas/no-nested-styled-jsx': ['error', {
    message: '禁止嵌套 styled-jsx 标签，请将 <style jsx> 移到组件根级别'
  }],
}
```

注意：使用自定义错误信息时，将不会显示外层 styled-jsx 标签的行号信息。

#### 参考资料

- [Next.js 错误说明](https://nextjs.org/docs/messages/nested-styled-jsx-tags)
- [styled-jsx GitHub Issue #42](https://github.com/vercel/styled-jsx/issues/42)

---

### 路由守卫规则 (RoutesComponent)

保护 `client/src/app.tsx` 中的 RoutesComponent 组件结构，确保路由配置不被意外破坏。

#### 规则目的

该规则强制 `RoutesComponent` 必须直接返回 `<Routes>` 组件，不允许在外层添加任何包装元素（如 `<div>`、`<BrowserRouter>` 等）。这确保了：
- ✅ 路由结构保持一致和可预测
- ✅ 防止开发者误修改核心路由架构
- ✅ 允许在 `<Routes>` 内部自由添加/修改/删除路由配置

#### 生效范围

**仅在 loose 模式下对 `client/src/app.tsx` 文件生效**

该规则通过环境变量 `FORCE_FRAMEWORK_LINT_LOOSE_MODE=true` 启用，并且只检查项目中的 `client/src/app.tsx` 文件。

#### 错误示例

❌ **不允许：添加外层包装元素**

```tsx
// ❌ 错误：使用 div 包装
const RoutesComponent = () => (
  <div>
    <Routes>
      <Route path="/" element={<HomePage />} />
    </Routes>
  </div>
);

// ❌ 错误：使用 BrowserRouter 包装
const RoutesComponent = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<HomePage />} />
      </Routes>
    </BrowserRouter>
  );
};
```

#### 正确示例

✅ **允许：直接返回 Routes，在内部修改路由**

```tsx
// ✅ 正确：直接返回 Routes
const RoutesComponent = () => (
  <Routes>
    <Route path="/" element={<HomePage />} />
    <Route path="/about" element={<AboutPage />} />
    <Route path="/users" element={<UsersPage />} />
    <Route path="*" element={<NotFound />} />
  </Routes>
);

// ✅ 正确：使用嵌套路由
const RoutesComponent = () => (
  <Routes>
    <Route element={<Layout />}>
      <Route index element={<HomePage />} />
      <Route path="/about" element={<AboutPage />} />
    </Route>
    <Route path="*" element={<NotFound />} />
  </Routes>
);
```

#### 错误信息

当违反规则时，会看到以下错误信息：

```
47:23  error  RoutesComponent must return <Routes> directly without any wrapper. Do not add <div>, <BrowserRouter> or other wrappers. You can only modify routes inside <Routes> (add/edit/remove <Route> elements).  no-restricted-syntax
```

错误信息包含三个层次的指导：
1. **明确要求**：必须直接返回 `<Routes>`，不能有包装器
2. **具体禁止**：不要添加 `<div>`、`<BrowserRouter>` 或其他包装器
3. **允许操作**：可以在 `<Routes>` 内部添加/编辑/删除 `<Route>` 元素

#### 使用场景

该规则主要用于妙搭等需要保护核心路由结构的场景。在这些场景中：
- 框架会自动管理路由的外层结构（如 BrowserRouter）
- 开发者只需关注路由配置本身（路径、组件映射等）
- 防止开发者误修改导致路由失效