forked from ParadigmEducation/snowflake-notes
feat: 初始化 Astro 学习博客骨架
- Astro+TS 严格模式(禁止 any、显式返回类型) - ESLint Flat Config + Prettier 格式化 - 内容集合(posts)与示例文章 - OSS 图床可配置 Img 组件 - 抽离 posts 数据逻辑(更易类型检查) - getStaticPaths 修正(rest 路由传字符串) - README/AGENTS 中文文档与约定 - Gitea CI:typecheck + lint - 忽略 ref/(仅作临时参考)
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
name: Check
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
- develop
|
||||
- feature/**
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
lint-and-typecheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10
|
||||
|
||||
- name: Install
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Typecheck
|
||||
run: pnpm typecheck
|
||||
|
||||
- name: Lint
|
||||
run: pnpm lint
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
# Node.js
|
||||
node_modules/
|
||||
|
||||
# Astro
|
||||
.astro/
|
||||
|
||||
# Build output
|
||||
dist/
|
||||
public/images/
|
||||
ref/
|
||||
|
||||
# Miscellaneous
|
||||
.DS_Store
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"semi": true,
|
||||
"trailingComma": "all",
|
||||
"plugins": ["prettier-plugin-astro"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.mdx",
|
||||
"options": { "proseWrap": "always" }
|
||||
},
|
||||
{
|
||||
"files": "*.md",
|
||||
"options": { "proseWrap": "always" }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
# AGENTS 指南(本仓库)
|
||||
|
||||
本仓库用于搭建一套基于 Astro 的内部学习博客站点。目标:TypeScript 严格(拒绝 any)、代码与文档统一格式化、内容格式可扩展(不仅限于 Markdown),图片优先走外部 OSS,不建议把图片直接提交进仓库。
|
||||
|
||||
## 工作流原则
|
||||
|
||||
- 语言与文档:优先中文说明;代码与注释保持简洁明确。
|
||||
- TypeScript 严格:启用 `strict` 和 `noImplicitAny`;ESLint 禁止 `any`。
|
||||
- 格式化:统一使用 Prettier(含 Astro、Markdown);提交前请执行 `pnpm format` 或启用编辑器保存自动格式化。
|
||||
- 类型与检查:强制显式函数返回类型,禁止隐式 any;建议在 CI 中执行 `pnpm typecheck` 与 `pnpm lint`。
|
||||
- 目录结构:见下文“项目结构”。
|
||||
- 内容来源:默认支持 `md`/`mdx`,并预留可扩展的内容加载层(如将来支持 Typst 等)。
|
||||
- 图片与静态资源:默认不入库。通过环境变量配置外部 OSS 图床地址,在组件中统一引用。
|
||||
- `ref/` 目录仅作临时参考:不纳入版本管理与检查(已在 `.gitignore`、TS 与 ESLint 忽略)。
|
||||
|
||||
## 项目结构(约定)
|
||||
|
||||
- `src/pages`:页面路由(如首页、文章详情)。
|
||||
- `src/layouts`:页面与文章的布局模版。
|
||||
- `src/components`:通用组件(如 `Img.astro`)。
|
||||
- `src/content`:Astro Content Collections 与文章内容(`posts`)。
|
||||
- `src/lib/content`:内容加载抽象层,便于未来扩展除 Markdown 以外的格式。
|
||||
- `public`:公开静态资源(尽量不要放图片)。
|
||||
|
||||
## TypeScript 与 ESLint
|
||||
|
||||
- `tsconfig.json` 开启:`strict: true`、`noImplicitAny: true`、`noFallthroughCasesInSwitch: true` 等。
|
||||
- ESLint(使用 Flat Config):统一使用根目录 `eslint.config.js`,不要新增 `.eslintrc.*` 文件;启用 `@typescript-eslint/no-explicit-any: error` 等类型感知规则,并结合 Astro 插件。
|
||||
|
||||
## 格式化
|
||||
|
||||
- Prettier 统一代码、Astro 与 Markdown 的格式。
|
||||
- 命令:`pnpm format` 全量格式化,`pnpm format:check` 校验。
|
||||
|
||||
## 内容与多格式扩展
|
||||
|
||||
- 文章位于 `src/content/posts`,默认使用 Astro Content Collections(`config.ts`)定义元数据 Schema。
|
||||
- 已提供 `src/lib/content` 抽象:
|
||||
- 通过扩展“加载器(loader)”注册新的后缀(如 `.typ`)。
|
||||
- 新增格式时,请实现接口并在注册表中添加映射,无需改动现有渲染逻辑。
|
||||
|
||||
## 图片与外部 OSS 配置
|
||||
|
||||
- 使用 `PUBLIC_MEDIA_BASE_URL` 指定外部图床(OSS/CDN)前缀。
|
||||
- 组件 `src/components/Img.astro` 会根据配置拼接完整图片地址。
|
||||
- 若必须本地存放,建议放置在 `public/images/`,但该目录默认已在 `.gitignore` 中忽略。
|
||||
|
||||
## 开发与运行(建议)
|
||||
|
||||
- 包管理器:使用 `pnpm`(无需指定具体版本)。
|
||||
- 常用脚本:
|
||||
- `pnpm dev` 启动本地开发(热更新)。
|
||||
- `pnpm build` 产出静态文件。
|
||||
- `pnpm preview` 预览构建结果。
|
||||
- `pnpm lint` 代码检查;`pnpm typecheck` 类型检查;`pnpm format` 统一格式化。
|
||||
|
||||
### 依赖版本策略
|
||||
|
||||
- 版本范围由 pnpm 写入:不要在 `package.json` 手写 `latest` 或具体版本号。
|
||||
- 默认使用 caret 范围(`^x.x.x`):
|
||||
- 新增依赖:`pnpm add <pkg>`(由 pnpm 写入 `^` 范围)。
|
||||
- 升级依赖:`pnpm up <pkg> -L`(按范围更新到可用最新)。
|
||||
- Node 版本:`>=20`(见 `package.json` 的 `engines.node`)。
|
||||
- CI 构建建议使用:`pnpm install --frozen-lockfile` 保证可重复。
|
||||
|
||||
## 代码提交规范(简要)
|
||||
|
||||
- 小步提交,信息清晰:`feat: ...` / `fix: ...` / `docs: ...` / `chore: ...` 等。
|
||||
- 不提交大体积二进制与图片,图片走外部 OSS。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 任何需要引入新内容格式,请优先在 `src/lib/content` 添加 loader,而不是在页面层做分支判断。
|
||||
- 若需新增全局配置项,请优先考虑使用 `PUBLIC_` 前缀暴露给客户端,或通过服务器端/构建时注入。
|
||||
- 路由与 getStaticPaths:对 rest 参数页面(如 `src/pages/posts/[...slug].astro`),`params.slug` 必须是字符串(包含斜杠的完整路径),不能返回数组;推荐将 `getStaticPaths` 放在独立的 TS 文件并显式标注类型(见 `src/pages/posts/getStaticPaths.ts`)。
|
||||
@@ -0,0 +1,34 @@
|
||||
# 内部学习博客(Astro + TypeScript)
|
||||
|
||||
基于 Astro 构建的内部学习博客。目标:严格 TypeScript、统一格式化、内容可扩展(不仅 Markdown/MDX),图片优先使用外部 OSS。
|
||||
|
||||
## 快速开始
|
||||
|
||||
- 要求:Node >= 20,包管理器使用 pnpm
|
||||
- 安装依赖:`pnpm install`
|
||||
- 启动开发:`pnpm dev`
|
||||
|
||||
常用脚本:
|
||||
- 构建:`pnpm build` ;预览:`pnpm preview`
|
||||
- 代码检查:`pnpm lint` ;类型检查:`pnpm typecheck`
|
||||
- 格式化:`pnpm format`
|
||||
|
||||
## 内容与结构
|
||||
|
||||
- 文章与集合:`src/content/`(示例:`src/content/posts/hello-world.mdx`)
|
||||
- 页面与布局:`src/pages/`、`src/layouts/`
|
||||
- 通用组件:`src/components/`(如 `Img.astro` 支持外部图床)
|
||||
- 内容扩展抽象:`src/lib/content/`(为未来 Typst 等格式预留)
|
||||
|
||||
## 配置
|
||||
|
||||
- `PUBLIC_MEDIA_BASE_URL`:外部图床前缀(避免图片入库)
|
||||
- `PUBLIC_SITE_URL`:站点地址(可选,用于 canonical 等)
|
||||
|
||||
## 约定
|
||||
|
||||
- 严格 TypeScript:禁止 any,导出函数需显式返回类型
|
||||
- 统一格式化:Prettier(含 Astro/Markdown/MDX)
|
||||
- 图片默认不入库,建议走外部 OSS
|
||||
|
||||
更多细节与约定见 `AGENTS.md`。
|
||||
@@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import mdx from '@astrojs/mdx';
|
||||
|
||||
export default defineConfig({
|
||||
integrations: [mdx()],
|
||||
site: process.env.PUBLIC_SITE_URL || 'http://localhost:4321',
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
/// <reference types="astro/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly PUBLIC_MEDIA_BASE_URL?: string;
|
||||
readonly PUBLIC_SITE_URL?: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// Flat config for ESLint v9
|
||||
import tseslint from 'typescript-eslint';
|
||||
import astro from 'eslint-plugin-astro';
|
||||
import astroParser from 'astro-eslint-parser';
|
||||
|
||||
export default [
|
||||
// Astro flat recommended
|
||||
...astro.configs['flat/recommended'],
|
||||
|
||||
// TS typed linting only for TS files
|
||||
...tseslint.configs.recommendedTypeChecked,
|
||||
...tseslint.configs.stylisticTypeChecked,
|
||||
{
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
languageOptions: {
|
||||
parser: tseslint.parser,
|
||||
parserOptions: {
|
||||
project: true,
|
||||
tsconfigRootDir: process.cwd(),
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 'latest'
|
||||
}
|
||||
},
|
||||
plugins: { '@typescript-eslint': tseslint.plugin },
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }],
|
||||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'error',
|
||||
'@typescript-eslint/explicit-function-return-type': [
|
||||
'error',
|
||||
{
|
||||
allowExpressions: false,
|
||||
allowHigherOrderFunctions: true,
|
||||
allowDirectConstAssertionInArrowFunctions: true,
|
||||
allowTypedFunctionExpressions: true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Astro files: use astro parser; do not inject TS typed rules here
|
||||
{
|
||||
files: ['**/*.astro'],
|
||||
languageOptions: {
|
||||
parser: astroParser,
|
||||
parserOptions: {
|
||||
parser: tseslint.parser,
|
||||
project: true,
|
||||
tsconfigRootDir: process.cwd(),
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module'
|
||||
}
|
||||
},
|
||||
plugins: { '@typescript-eslint': tseslint.plugin, astro },
|
||||
rules: {
|
||||
// 在 .astro 文件中放宽部分 type-aware 规则,避免模板区误报
|
||||
'@typescript-eslint/no-unsafe-return': 'off',
|
||||
'@typescript-eslint/no-unsafe-assignment': 'off',
|
||||
'@typescript-eslint/no-unsafe-member-access': 'off',
|
||||
'@typescript-eslint/non-nullable-type-assertion-style': 'off'
|
||||
}
|
||||
},
|
||||
|
||||
// Ignores
|
||||
{ ignores: ['dist', 'node_modules', 'eslint.config.js', '.astro', 'astro.config.*', 'ref/**'] }
|
||||
];
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "snowflake-notes",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc -p tsconfig.json --noEmit",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/mdx": "^4.3.12",
|
||||
"astro": "^5.16.1",
|
||||
"zod": "^4.1.13"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"packageManager": "pnpm@10.0.0+",
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.10.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.48.0",
|
||||
"@typescript-eslint/parser": "^8.48.0",
|
||||
"astro-eslint-parser": "^1.2.2",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-astro": "^1.5.0",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-astro": "^0.14.1",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.48.0"
|
||||
}
|
||||
}
|
||||
Generated
+4831
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
---
|
||||
export interface Props {
|
||||
src: string;
|
||||
alt: string;
|
||||
width?: number | string;
|
||||
height?: number | string;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const { src, alt, width, height, class: className } = Astro.props;
|
||||
|
||||
const base = import.meta.env.PUBLIC_MEDIA_BASE_URL?.replace(/\/$/, '') ?? '';
|
||||
const isAbsolute = /^(https?:)?\/\//.test(src) || src.startsWith('/');
|
||||
const resolved = isAbsolute ? src : `${base}/${src}`.replace(/([^:]?)\/\/+/, '$1/');
|
||||
---
|
||||
<img src={resolved} alt={alt} width={width} height={height} class={className} />
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { defineCollection, z } from 'astro:content';
|
||||
|
||||
const posts = defineCollection({
|
||||
type: 'content',
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string().optional(),
|
||||
pubDate: z.date().optional(),
|
||||
tags: z.array(z.string()).default([])
|
||||
})
|
||||
});
|
||||
|
||||
export const collections = { posts };
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: 你好,Astro!
|
||||
description: 内部学习博客的第一篇文章。
|
||||
pubDate: 2024-11-27
|
||||
tags: ["简介", "Astro"]
|
||||
---
|
||||
|
||||
欢迎来到新的内部学习博客!这是第一篇文章,使用 MDX 撰写。
|
||||
|
||||
可以直接在文中插入 React/JSX 组件或 Astro 组件。
|
||||
|
||||
```ts
|
||||
export function add(a: number, b: number): number {
|
||||
return a + b;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
interface Props {
|
||||
title?: string;
|
||||
}
|
||||
const { title } = Astro.props;
|
||||
const site = import.meta.env.PUBLIC_SITE_URL ?? '';
|
||||
---
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{title ? `${title} | 学习博客` : '学习博客'}</title>
|
||||
<link rel="canonical" href={site} />
|
||||
</head>
|
||||
<body>
|
||||
<header style="padding: 12px; border-bottom: 1px solid #eee">
|
||||
<a href="/">首页</a>
|
||||
<span style="margin: 0 8px">|</span>
|
||||
<a href="/posts">文章</a>
|
||||
</header>
|
||||
<main style="padding: 16px">
|
||||
<slot />
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
import BaseLayout from './BaseLayout.astro';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
description?: string;
|
||||
pubDate?: Date;
|
||||
}
|
||||
|
||||
const { title, description, pubDate } = Astro.props;
|
||||
---
|
||||
<BaseLayout title={title}>
|
||||
<article>
|
||||
<h1>{title}</h1>
|
||||
{pubDate && <p style="color:#666;">{pubDate.toLocaleDateString('zh-CN')}</p>}
|
||||
{description && <p>{description}</p>}
|
||||
<slot />
|
||||
</article>
|
||||
</BaseLayout>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
export type ContentFormat = 'md' | 'mdx' | 'typ';
|
||||
|
||||
export interface ContentLoader {
|
||||
readonly extensions: readonly string[];
|
||||
canLoad: (ext: string) => boolean;
|
||||
// 未来扩展:根据路径或数据源加载内容并返回统一结构
|
||||
// load: (path: string) => Promise<LoadedContent>;
|
||||
}
|
||||
|
||||
export function createLoader(extensions: string[]): ContentLoader {
|
||||
const canLoad = (ext: string): boolean => extensions.includes(ext);
|
||||
return { extensions, canLoad } as const satisfies ContentLoader;
|
||||
}
|
||||
|
||||
// 默认注册:Markdown/MDX;Typst 预留
|
||||
export const builtInLoaders: readonly ContentLoader[] = [
|
||||
createLoader(['.md', '.mdx']),
|
||||
createLoader(['.typ'])
|
||||
];
|
||||
|
||||
export function findLoaderByExtension(ext: string): ContentLoader | undefined {
|
||||
return builtInLoaders.find((l) => l.canLoad(ext));
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { getCollection, getEntry } from 'astro:content';
|
||||
import type { CollectionEntry } from 'astro:content';
|
||||
|
||||
export async function listAllPosts(): Promise<CollectionEntry<'posts'>[]> {
|
||||
const posts = await getCollection('posts');
|
||||
// 按发布日期倒序
|
||||
return posts.sort((a, b) => {
|
||||
const ad = a.data.pubDate ? new Date(a.data.pubDate).getTime() : 0;
|
||||
const bd = b.data.pubDate ? new Date(b.data.pubDate).getTime() : 0;
|
||||
return bd - ad;
|
||||
});
|
||||
}
|
||||
|
||||
export async function listRecentPosts(limit = 5): Promise<CollectionEntry<'posts'>[]> {
|
||||
const all = await listAllPosts();
|
||||
return all.slice(0, limit);
|
||||
}
|
||||
|
||||
export async function getPostBySlug(slug: string): Promise<CollectionEntry<'posts'>> {
|
||||
const entry = await getEntry('posts', slug);
|
||||
if (!entry) {
|
||||
throw new Error(`Post not found: ${slug}`);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import { listRecentPosts } from '../lib/posts';
|
||||
const posts = await listRecentPosts(5);
|
||||
---
|
||||
<BaseLayout title="首页">
|
||||
<h2>最近文章</h2>
|
||||
<ul>
|
||||
{posts.slice(0, 5).map((p) => (
|
||||
<li>
|
||||
<a href={`/posts/${p.slug}/`}>{p.data.title}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
import PostLayout from '../../layouts/PostLayout.astro';
|
||||
import { getEntry } from 'astro:content';
|
||||
import { getStaticPaths } from './getStaticPaths';
|
||||
|
||||
export { getStaticPaths };
|
||||
|
||||
const { slug } = Astro.params as { slug: string };
|
||||
const entry = await getEntry('posts', slug);
|
||||
if (!entry) {
|
||||
throw new Error(`Post not found: ${slug}`);
|
||||
}
|
||||
const { Content } = await entry.render();
|
||||
const data = entry.data;
|
||||
---
|
||||
<PostLayout title={data.title} description={data.description} pubDate={data.pubDate}>
|
||||
<Content />
|
||||
</PostLayout>
|
||||
@@ -0,0 +1,8 @@
|
||||
import { getCollection } from 'astro:content';
|
||||
import type { GetStaticPaths, GetStaticPathsResult } from 'astro';
|
||||
|
||||
// 为 rest 参数 `[...slug]` 显式声明字符串类型,防止误用数组
|
||||
export const getStaticPaths: GetStaticPaths = async (): Promise<GetStaticPathsResult> => {
|
||||
const posts = (await getCollection('posts')) as { slug: string }[];
|
||||
return posts.map((p) => ({ params: { slug: p.slug } }));
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import { listAllPosts } from '../../lib/posts';
|
||||
const posts = await listAllPosts();
|
||||
---
|
||||
<BaseLayout title="文章">
|
||||
<h2>全部文章</h2>
|
||||
<ul>
|
||||
{posts.map((p) => (
|
||||
<li>
|
||||
<a href={`/posts/${p.slug}/`}>{p.data.title}</a> — {p.data.pubDate?.toLocaleDateString?.('zh-CN')}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"jsx": "preserve",
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"allowJs": false,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"include": [
|
||||
"src",
|
||||
"env.d.ts",
|
||||
"astro.config.mjs",
|
||||
".astro/types.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"dist",
|
||||
"node_modules",
|
||||
"ref"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"extends": [
|
||||
"astro/tsconfigs/base",
|
||||
"./tsconfig.base.json"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"types": [
|
||||
"astro/client"
|
||||
],
|
||||
"verbatimModuleSyntax": true
|
||||
},
|
||||
"include": [
|
||||
"src",
|
||||
"env.d.ts",
|
||||
"astro.config.mjs",
|
||||
".astro/types.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"dist",
|
||||
"node_modules",
|
||||
"ref"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user