# Technical Documentation: yansongda/pay

> ℹ️ **Provenance:** Hybrid Fusion: `yansongda/pay` + `yansongda/yansongda.github.io` · [CodeWiki Reference](https://codewiki.google/github.com/yansongda/pay) · Recency: Active (< 180 days)

## 1. Project Overview & Quickstart (yansongda/pay)

## 前言

v3 版与 v2 版在底层有很大的不同，基础架构做了重新的设计，更易扩展，使用起来更方便。

开发了多次支付宝与微信支付后，很自然产生一种反感，惰性又来了，想在网上找相关的轮子，可是一直没有找到一款自己觉得逞心如意的，要么使用起来太难理解，要么文件结构太杂乱，只有自己撸起袖子干了。

欢迎 Star，欢迎 PR！

hyperf 扩展包请 [传送至这里](https://github.com/yansongda/hyperf-pay)

laravel 扩展包请 [传送至这里](https://github.com/yansongda/laravel-pay)

yii 扩展包请 [传送至这里](https://github.com/guanguans/yii-pay)

## 特点

- 多租户支持
- Swoole 支持
- 灵活的插件机制
- 丰富的事件系统
- 命名不那么乱七八糟
- 隐藏开发者不需要关注的细节
- 根据支付宝、微信最新 API 开发而成
- 高度抽象的类，免去各种拼json与xml的痛苦
- 文件结构清晰易理解，可以随心所欲添加本项目中没有的支付网关
- 方法使用更优雅，不必再去研究那些奇怪的的方法名或者类名是做啥用的
- 内置自动获取微信公共证书方法，再也不用再费劲去考虑第一次获取证书的的问题了
- 符合 PSR2、PSR3、PSR4、PSR7、PSR11、PSR14、PSR18 等各项标准，你可以各种方便的与你的框架集成

## 版本计划

[https://pay.yansongda.cn/docs/v3/overview/planning](https://pay.yansongda.cn/docs/v3/overview/planning)

## 详细文档

[https://pay.yansongda.cn](https://pay.yansongda.cn)

## 支持的支付方法

yansongda/pay 100% 兼容 支付宝/微信/银联 所有功能（包括服务商功能），只需通过「插件机制」引入即可。

同时，SDK 直接支持内置了以下插件，详情请查阅文档。

### 支付宝

- 电脑支付
- 手机网站支付
- APP 支付
- 刷卡支付
- 扫码支付
- 账户转账
- 小程序支付
- ...

### 微信

- 公众号支付
- 小程序支付
- H5 支付
- 扫码支付
- APP 支付
- 刷卡支付
- ...

### 抖音

- 小程序支付（通用交易系统，JSAPI 下单签名）
- 订单查询
- CPS 查询
- 退款
- 退款审核
- 支付/退款/退款申请回调
- ...

### 银联

- 手机网站支付
- 电脑网站支付
- 刷卡支付
- 扫码支付
- ...
- 
### 江苏银行(e融支付)

- 聚合扫码支付(微信,支付宝,银联,e融)
- ...

### 通联支付

- 统一支付（微信/支付宝/银联等 paytype）
- 被扫/主扫支付
- 查询、确认查询、退款、撤销、关单

### 翼支付（BestPay）

- PC 收银台（超级收银台）
- 手机收银台
- 聚合收款码
- 订单查询 / 退款 / 关单
- 支付/退款回调（证书验签）
- ...

### Apple（苹果支付）

- Apple Pay 支付令牌验签解密（服务端本地验签 + 解密卡数据）
- Apple Pay 网页商户验证（merchant session 代理）
- App Store 交易查询 / 退款历史查询 / 订阅状态
- App Store Server Notifications V2 回调验签

## 安装
```shell
composer require yansongda/pay:~3.7.0 -vvv
```

## 深情一撇

### 支付宝
```php
<?php

namespace App\Http\Controllers;

use Yansongda\Pay\Pay;

class AlipayController
{
    protected $config = [
        'alipay' => [
            'default' => [
                // 必填-支付宝分配的 app_id
                'app_id' => '2016082000295641',
                // 必填-应用私钥 字符串或路径
                'app_secret_cert' => '89iZ2iC16H6/6a3YcP+hDZUjiNGQx9cuwi9eJyykvcwhD...',
                // 必填-应用公钥证书 路径
                'app_public_cert_path' => '/Users/yansongda/pay/cert/appCertPublicKey_2016082000295641.crt',
                // 必填-支付宝公钥证书 路径
                'alipay_public_cert_path' => '/Users/yansongda/pay/cert/alipayCertPublicKey_RSA2.crt',
                // 必填-支付宝根证书 路径
                'alipay_root_cert_path' => '/Users/yansongda/pay/cert/alipayRootCert.crt',
                'return_url' => 'https://yansongda.cn/alipay/return',
                'notify_url' => 'https://yansongda.cn/alipay/notify',
                // 选填-第三方应用授权token
                'app_auth_token' => '',
                // 选填-服务商模式下的服务商 id，当 mode 为 PayMode::SERVICE 时使用该参数
                'service_provider_id' => '',
                // 选填-默认为正常模式。可选为： PayMode::NORMAL, PayMode::SANDBOX, PayMode::SERVICE
                'mode' => PayMode::NORMAL,
            ],       
        ],   
        'logger' => [ // optional
            'enable' => false,
            'file' => './logs/alipay.log',
            'level' => 'info', // 建议生产环境等级调整为 info，开发环境为 debug
            'type' => 'single', // optional, 可选 daily.
            'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
        ],
        'http' => [ // optional
            'timeout' => 5.0,
            'connect_timeout' => 5.0,
            // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
        ],
    ];

    public function web()
    {
        Pay::config($this->config);
        
        $result = Pay::alipay()->web([
            'out_trade_no' => ''.time(),
            'total_amount' => '0.01',
            'subject' => 'yansongda 测试 - 1',
        ]);
        
        return $result;
    }

    public function returnCallback()
    {
        Pay::config($this->config);
    
        $data = Pay::alipay()->callback(); // 是的，验签就这么简单！

        // 订单号：$data->out_trade_no
        // 支付宝交易号：$data->trade_no
        // 订单总金额：$data->total_amount
    }

    public function notifyCallback()
    {
        Pay::config($this->config);
        
        try{
            $data = Pay::alipay()->callback(); // 是的，验签就这么简单！

            // 请自行对 trade_status 进行判断及其它逻辑进行判断，在支付宝的业务通知中，只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时，支付宝才会认定为买家付款成功。
            // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号；
            // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额）；
            // 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）；
            // 4、验证app_id是否为该商户本身。
            // 5、其它业务逻辑情况
        } catch (\Throwable $e) {
            dd($e);
        }

        return Pay::alipay()->success();
    }
}
```

### 微信
```php
<?php

namespace App\Http\Controllers;

use Yansongda\Pay\Pay;

class WechatController
{
    protected $config = [
        'wechat' => [
            'default' => [
                // 必填-商户号
                'mch_id' => '',
                // 选填-v2商户私钥
                'mch_secret_key_v2' => '',
                // 必填-v3商户秘钥
                'mch_secret_key' => '',
                // 必填-商户私钥 字符串或路径
                'mch_secret_cert' => '',
                // 必填-商户公钥证书路径
                'mch_public_cert_path' => '',
                // 必填
                'notify_url' => 'https://yansongda.cn/wechat/notify',
                // 选填-公众号 的 app_id
                'mp_app_id' => '',
                // 选填-小程序 的 app_id
                'mini_app_id' => '',
                // 选填-app 的 app_id
                'app_id' => '',
                // 选填-服务商模式下，子公众号 的 app_id
                'sub_mp_app_id' => '',
                // 选填-服务商模式下，子 app 的 app_id
                'sub_app_id' => '',
                // 选填-服务商模式下，子小程序 的 app_id
                'sub_mini_app_id' => '',
                // 选填-服务商模式下，子商户id
                'sub_mch_id' => '',
                // 选填-微信平台公钥证书路径, optional，强烈建议 php-fpm 模式下配置此参数
                'wechat_public_cert_path' => [
                    '45F59D4DABF31918AFCEC556D5D2C6E376675D57' => __DIR__.'/Cert/wechatpay_45F***D57.pem',
                ],
                // 选填-默认为正常模式。可选为： PayMode::NORMAL, PayMode::SERVICE
                'mode' => PayMode::NORMAL,
            ]
        ],
        'logger' => [ // optional
            'enable' => false,
            'file' => './logs/wechat.log',
            'level' => 'info', // 建议生产环境等级调整为 info，开发环境为 debug
            'type' => 'single', // optional, 可选 daily.
            'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
        ],
        'http' => [ // optional
            'timeout' => 5.0,
            'connect_timeout' => 5.0,
            // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
        ],
    ];

    public function index()
    {
        Pay::config($this->config);
        
        $order = [
            'out_trade_no' => time().'',
            'description' => 'subject-测试',
            'amount' => [
                 'total' => 1,
            ],
            'payer' => [
                 'openid' => 'onkVf1FjWS5SBxxxxxxxx',
            ],
        ];

        $pay = Pay::wechat()->mp($order);

        // $pay->appId
        // $pay->timeStamp
        // $pay->nonceStr
        // $pay->package
        // $pay->signType
    }

    public function callback()
    {
        Pay::config($this->config);
        
        try{
            $data = Pay::wechat()->callback(); // 是的，验签就这么简单！
        } catch (\Throwable $e) {
            dd($e);
        }
        
        return Pay::wechat()->success();
    }
}
```

### 抖音
```php
<?php

namespace App\Http\Controllers;

use Psr\Http\Message\ServerRequestInterface;
use Yansongda\Pay\Pay;

class DouyinController
{
    protected $config = [
        'douyin' => [
            'default' => [
                // 必填-小程序 app_id（即 client_key）
                // 抖音开放平台 --> 应用详情 --> 基础信息
                'app_id' => 'tt226e54d3bd581bf801',
                // 必填-应用密钥，用于获取 client_token
                // 抖音开放平台 --> 应用详情 --> 基础信息
                'app_secret' => 'your-app-secret',
                // 必填-应用私钥，用于下单加签
                // 抖音开放平台 --> 应用详情 --> 支付信息 --> 支付设置 --> 小程序支付密钥
                'app_private_key' => "-----BEGIN RSA PRIVATE KEY-----\n...",
                // 必填-抖音平台公钥，用于回调验签
                // 抖音开放平台 --> 应用详情 --> 支付信息 --> 支付设置 --> 抖音平台公钥
                'douyin_public_key' => "-----BEGIN PUBLIC KEY-----\n...",
                // 选填-抖音支付/退款回调地址
                'notify_url' => 'https://yansongda.cn/douyin/notify',
            ],
        ],
        'logger' => [ // optional
            'enable' => false,
            'file' => './logs/alipay.log',
            'level' => 'info', // 建议生产环境等级调整为 info，开发环境为 debug
            'type' => 'single', // optional, 可选 daily.
            'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
        ],
        'http' => [ // optional
            'timeout' => 5.0,
            'connect_timeout' => 5.0,
            // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
        ],
    ];

    public function pay()
    {
        Pay::config($this->config);

        // 服务端不发 HTTP 请求，只负责透传官方 camelCase 字段并生成签名
        $result = Pay::douyin()->mini([
            'outOrderNo' => date('YmdHis').mt_rand(1000, 9999),
            'totalAmount' => 1,
            'skuList' => [
                [
                    'skuId' => 'sku-001',
                    'title' => '闫嵩达 - test - subject - 01',
                    'quantity' => 1,
                    'price' => 1,
                ],
            ],
            'orderEntrySchema' => [
                'path' => 'pages/order/detail',
                'params' => '{"out_order_no":"202408040747147327"}',
            ],
        ]);

        // 将 data 与 byteAuthorization 原样返回给前端，调用 tt.requestOrder 完成下单
        return json_encode($result->all());
    }

    public function callback(ServerRequestInterface $request)
    {
        Pay::config($this->config);

        try {
            $data = Pay::douyin()->callback($request); // 是的，验签就这么简单！
        } catch (\Throwable $e) {
            dd($e);
        }

        return Pay::douyin()->success();
    }
}
```

### 江苏银行(e融支付)
```php
<?php

namespace App\Http\Controllers;

use Yansongda\Pay\Pay;

class JsbController
{
    protected $config = [
        'jsb' => [
            'default' => [
                // 服务代码
                'svr_code' => '',
                // 必填-合作商ID
                'partner_id' => '',
                // 必填-公私钥对编号
                'public_key_code' => '00',
                // 必填-商户私钥(加密签名)
                'mch_secret_cert_path' => '',
                // 必填-商户公钥证书路径(提供江苏银行进行验证签名用)
                'mch_public_cert_path' => '',
                // 必填-江苏银行的公钥(用于解密江苏银行返回的数据)
                'jsb_public_cert_path' => '',
                //支付通知地址
                'notify_url'            => '', 
                // 选填-默认为正常模式。可选为： PayMode::NORMAL:正式环境, PayMode::SANDBOX:测试环境
                'mode' => PayMode::NORMAL,
            ]
        ],
        'logger' => [ // optional
            'enable' => false,
            'file' => './logs/epay.log',
            'level' => 'info', // 建议生产环境等级调整为 info，开发环境为 debug
            'type' => 'single', // optional, 可选 daily.
            'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
        ],
        'http' => [ // optional
            'timeout' => 5.0,
            'connect_timeout' => 5.0,
            // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
        ],
    ];

    public function index()
    {
        Pay::config($this->config);
        
        $order = [
            'outTradeNo' => time().'',
            'proInfo' => 'subject-测试',
            'totalFee'=> 1,
        ];

        $pay = Pay::jsb()->scan($order);
    }

    public function notifyCallback()
    {
        Pay::config($this->config);

        try{
            $data = Pay::jsb()->callback(); // 是的，验签就这么简单！
        } catch (\Throwable $e) {
            dd($e);
        }
        
        return Pay::jsb()->success();
    }
}
```

## 代码贡献

由于测试及使用环境的限制，本项目中只开发了「支付宝」、「微信支付」、「抖音支付」、「银联」、「江苏银行」、「通联支付」、「翼支付」的相关支付网关。

如果您有其它支付网关的需求，或者发现本项目中需要改进的代码，**_欢迎 Fork 并提交 PR！_**

## 赏一杯咖啡吧



## LICENSE

MIT

## 2. Official Technical Reference & Guides (yansongda/yansongda.github.io)

## File: README.md

# 闫嵩达
个人博客

## License

博客模板来自 [astro-aria](https://github.com/ccbikai/astro-aria)

---

## File: biome.json

{
  "$schema": "https://biomejs.dev/schemas/2.5.10/schema.json",
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "useIgnoreFile": true
  },
  "files": {
    "ignoreUnknown": true
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space"
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "double"
    }
  },
  "css": {
    "parser": {
      "tailwindDirectives": true
    }
  },
  "assist": {
    "enabled": true,
    "actions": {
      "source": {
        "organizeImports": "on"
      }
    }
  },
  "overrides": [
    {
      "includes": ["**/*.astro"],
      "linter": {
        "rules": {
          "correctness": {
            "noUnusedImports": "off",
            "noUnusedVariables": "off"
          }
        }
      }
    }
  ]
}

---

## File: package.json

{
  "name": "yansongda",
  "type": "module",
  "version": "0.9.5",
  "scripts": {
    "dev": "astro dev",
    "start": "astro dev",
    "build": "astro check && astro build",
    "preview": "astro preview",
    "astro": "astro",
    "check": "biome check --fix --unsafe"
  },
  "devDependencies": {
    "@astrojs/check": "^0.9.10",
    "@astrojs/markdown-remark": "^7.2.4",
    "@astrojs/rss": "^4.0.19",
    "@astrojs/sitemap": "^3.7.3",
    "@biomejs/biome": "2.5.10",
    "@tailwindcss/typography": "^0.5.20",
    "@tailwindcss/vite": "^4.3.3",
    "astro": "^7.2.6",
    "rehype-autolink-headings": "^7.1.0",
    "rehype-slug": "^6.0.0",
    "sharp": "^0.35.3",
    "tailwindcss": "^4.3.3",
    "typescript": "^6.0.3"
  }
}

---

## File: pnpm-lock.yaml

lockfileVersion: '9.0'

settings:
  autoInstallPeers: true
  excludeLinksFromLockfile: false

importers:

  .:
    devDependencies:
      '@astrojs/check':
        specifier: ^0.9.10
        version: 0.9.10(prettier@3.9.6)(typescript@6.0.3)
      '@astrojs/markdown-remark':
        specifier: ^7.2.4
        version: 7.2.4
      '@astrojs/rss':
        specifier: ^4.0.19
        version: 4.0.19
      '@astrojs/sitemap':
        specifier: ^3.7.3
        version: 3.7.3
      '@biomejs/biome':
        specifier: 2.5.10
        version: 2.5.10
      '@tailwindcss/typography':
        specifier: ^0.5.20
        version: 0.5.20(tailwindcss@4.3.3)
      '@tailwindcss/vite':
        specifier: ^4.3.3
        version: 4.3.3(vite@8.2.2(@types/node@24.10.1)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))
      astro:
        specifier: ^7.2.6
        version: 7.2.6(@astrojs/markdown-remark@7.2.4)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.3)(@types/node@24.10.1)(jiti@2.7.0)(yaml@2.9.0)
      rehype-autolink-headings:
        specifier: ^7.1.0
        version: 7.1.0
      rehype-slug:
        specifier: ^6.0.0
        version: 6.0.0
      sharp:
        specifier: ^0.35.3
        version: 0.35.3(@types/node@24.10.1)
      tailwindcss:
        specifier: ^4.3.3
        version: 4.3.3
      typescript:
        specifier: ^6.0.3
        version: 6.0.3

packages:

  '@astrojs/check@0.9.10':
    resolution: {integrity: sha512-zgx/UQMozdjOa3bOxjgeCFdtpE3c9rRX6xHwa+2QXvy8z8Akifu2AtubHyv/zzC2znO8dl8fFWL4K+Ba9kS8HQ==}
    hasBin: true
    peerDependencies:
      typescript: ^5.0.0 || ^6.0.0

  '@astrojs/compiler-binding-darwin-arm64@0.4.0':
    resolution: {integrity: sha512-ZVUwHundaQyFNjE6uoa0usaC0WOCitDCLS/4mdb4rOiJXwVUuKJBMxI5WMzXLWmamsXtK/Z//ifLXvV5Yeh4Hw==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm64]
    os: [darwin]

  '@astrojs/compiler-binding-darwin-x64@0.4.0':
    resolution: {integrity: sha512-FI6G8AY8u6fR1SI/QRR5yGMwtvZwP34CDmZpZ5HwJGa50UM1VISTLhqkhV4a476pmgd25X1Aur2dqw6hUnrlKA==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [x64]
    os: [darwin]

  '@astrojs/compiler-binding-linux-arm64-gnu@0.4.0':
    resolution: {integrity: sha512-lB9gLFJK7m82EnjaU8nlRBEfcwGNeHidW3sSjODTUjMNaoewVuUz9fwwdY5M4jiSXIqWLH3yl6TX8FTDKA74Sw==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm64]
    os: [linux]

  '@astrojs/compiler-binding-linux-arm64-musl@0.4.0':
    resolution: {integrity: sha512-HPbvWqbxFxyaoQJhLxCaSjtYBx9KBo7JGVzEFZCmMl968a2PsSH0UfiODYgYPXofTOIsIH2aoCcrHXML0IA3ig==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm64]
    os: [linux]

  '@astrojs/compiler-binding-linux-x64-gnu@0.4.0':
    resolution: {integrity: sha512-tQKolMxoJ/+0AmLWm1PmJ/i+z3i10ZU1bNuVjEDulCf48azEMtUNjTZgHJ5MPtpYRNc7dlETr8QujUfduzoC7Q==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [x64]
    os: [linux]

  '@astrojs/compiler-binding-linux-x64-musl@0.4.0':
    resolution: {integrity: sha512-5v5YymudsxMHp3NBLCS8BUlu5CRqeLtWD9cKS/4nIhIEHCbpz9okmVV6I0HWqmBAPhWYcDa3vw/vltYPrOQCTA==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [x64]
    os: [linux]

  '@astrojs/compiler-binding-wasm32-wasi@0.4.0':
    resolution: {integrity: sha512-m/phuH3x3PREvv1OnkM44NoPh4MatUadix1fB1u5SvMLCyDTUZykDJbKnWf1cjnYmHdlB8HcjTjl6JrCqAIXcw==}
    engines: {node: '>=14.0.0'}
    cpu: [wasm32]

  '@astrojs/compiler-binding-win32-arm64-msvc@0.4.0':
    resolution: {integrity: sha512-B9zYf3okEY83kM8gydlpH2BHP00w4ifxPqlYlWrgTwuD6wnkrJDCwBlgy1q31cERjCJRXN1lrE2VmkLvFjv/6g==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm64]
    os: [win32]

  '@astrojs/compiler-binding-win32-x64-msvc@0.4.0':
    resolution: {integrity: sha512-zB0Nrv0dGc0zZWPGDRmmETTPhDRqyZjAjk+gWMlVrJX5U89obpB3VUUE1ZiHxOCN5LQojeLK6O8L/dnoHolvNQ==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [x64]
    os: [win32]

  '@astrojs/compiler-binding@0.4.0':
    resolution: {integrity: sha512-x2RjDUuWfwLNtc3mjAdSRInwqh/rqbLar9cm/5FOMbHvmYZB7yfKewzSclAxWjIZsypJDXv1lhaP2WG+P8TK3g==}
    engines: {node: ^20.19.0 || >=22.12.0}

  '@astrojs/compiler-rs@0.4.0':
    resolution: {integrity: sha512-koVikeon1kreEy+/JzLQRy3vzHHQVOjycs4degg4vFufKApZOwMZvSSAEztYNhmcQVfNVsVZZI4cEge3cexAbQ==}
    engines: {node: '>=22.12.0'}

  '@astrojs/compiler@2.13.1':
    resolution: {integrity: sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==}

  '@astrojs/internal-helpers@0.10.4':
    resolution: {integrity: sha512-nozZSy/mKYLqe4YrqbKtdOszedAfXYCtw3wZ0d+CAjz4GqQ4L9rl1ltIL5BlgwmYVinJg/RZ0MgGuWOdlyRZlA==}

  '@astrojs/language-server@2.16.14':
    resolution: {integrity: sha512-YPXkBu6N4d1sT09pvBmIDGZay+1MemV551FSgdEM3aZRDzbkxd2H7Cvf8MsVJLVB1mIEyTf1XbMN/30gp7s46w==}
    hasBin: true
    peerDependencies:
      prettier: ^3.0.0
      prettier-plugin-astro: '>=0.11.0'
    peerDependenciesMeta:
      prettier:
        optional: true
      prettier-plugin-astro:
        optional: true

  '@astrojs/markdown-remark@7.2.4':
    resolution: {integrity: sha512-MvspGMynWKAjTe4/lTUdmBPHIFKNVLTCF6UlyWGogTGzNrTvjD+D4n48k7h8swxsEPKHK2TwxkZO7uoaCv1Pow==}

  '@astrojs/markdown-satteri@0.3.8':
    resolution: {integrity: sha512-n8ItpFTCmlDsVR5+rwDmehSf+jFCYLWmZiisZNGuF7xILqYhsVeBfcha4qgS2Seq3fAc9Tm58ZVrvqFQ6RQgRQ==}

  '@astrojs/prism@4.0.2':
    resolution: {integrity: sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==}
    engines: {node: '>=22.12.0'}

  '@astrojs/rss@4.0.19':
    resolution: {integrity: sha512-e+z5wYeYtffQdHQO8c2tkSd2JEBdAuRXJV4ZEU5IxkYeE6e39woDd7nw1PH1Kk2tEYNCYuKdylnnbhGmt61awA==}

  '@astrojs/sitemap@3.7.3':
    resolution: {integrity: sha512-f8euLVsyeAmAkSm/1M2Kb8sL8byQmfgbvBNaHFItCheTj/IpiJYSEWVcqDHZ/yEHxiS7+w87mQkzwZaPHmk5GA==}

  '@astrojs/telemetry@3.3.3':
    resolution: {integrity: sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ==}
    engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}

  '@astrojs/yaml2ts@0.2.4':
    resolution: {integrity: sha512-8oddpOae35pJsXPQXhTkM0ypfKPskVsh2bCxRtbf7e+/Epw2nReakFYpLKjZMEr75CsoF203PMnCocpfz0s69A==}

  '@babel/helper-string-parser@7.29.7':
    resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
    engines: {node: '>=6.9.0'}

  '@babel/helper-validator-identifier@7.29.7':
    resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
    engines: {node: '>=6.9.0'}

  '@babel/parser@7.29.8':
    resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==}
    engines: {node: '>=6.0.0'}
    hasBin: true

  '@babel/types@7.29.8':
    resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==}
    engines: {node: '>=6.9.0'}

  '@biomejs/biome@2.5.10':
    resolution: {integrity: sha512-WRKXARA3kTuiV5sxqTpobJ/I0MVd4vk3pOL6wnp5az4LntFIhWTj1RWZq3DI9PCEN3lXcqy7p5aqUHzvq8AXyQ==}
    engines: {node: '>=14.21.3'}
    hasBin: true

  '@biomejs/cli-darwin-arm64@2.5.10':
    resolution: {integrity: sha512-ItCrxKK6SXVT6flYs0qIuBd4AA3TTTl4d66Re6YI2FuGZnN85NmuYNzkiTJUyYw8qBLv69L5zTUB6uyWd++h3Q==}
    engines: {node: '>=14.21.3'}
    cpu: [arm64]
    os: [darwin]

  '@biomejs/cli-darwin-x64@2.5.10':
    resolution: {integrity: sha512-yLsPU9pAmtChXDu8vhKAzErqe+LeeYuwuUB2FZMkRitsmdodxsYRa9KHrFispsUHzzOu+9HB3nP/TQxyia+Sjw==}
    engines: {node: '>=14.21.3'}
    cpu: [x64]
    os: [darwin]

  '@biomejs/cli-linux-arm64-musl@2.5.10':
    resolution: {integrity: sha512-t1QAKZwQJRB4dvgJSgFiQ4BNfNPChg69BNonz854qLVxnjT3UvDzQg9mbkTJRu35ZqU0Rw10A73J8Urgbg2RPw==}
    engines: {node: '>=14.21.3'}
    cpu: [arm64]
    os: [linux]

  '@biomejs/cli-linux-arm64@2.5.10':
    resolution: {integrity: sha512-VG8uQW/86a1roLaIFvtIbEigxIdzdJ190oGyg1tV7VYeQtOS+x10sflk7WbuXgw91EtZX5DlIIIej1YqkNLlcg==}
    engines: {node: '>=14.21.3'}
    cpu: [arm64]
    os: [linux]

  '@biomejs/cli-linux-x64-musl@2.5.10':
    resolution: {integrity: sha512-pgDDqp9JybHm2I0KRgzN6i4+lt8xu4iqxUwLzglUMmOmyRTU1AYBGKzh9sNMOtIjah7xoWvKHlLVetvyifzoiQ==}
    engines: {node: '>=14.21.3'}
    cpu: [x64]
    os: [linux]

  '@biomejs/cli-linux-x64@2.5.10':
    resolution: {integrity: sha512-4O6T0eq2heoHZN0a9UX+rWQoxXEBaKf+lRi2hbsGlHneUz9BWXM76nEWMK7Eeq8gzMxR1khQB6BFpAASpeXqGg==}
    engines: {node: '>=14.21.3'}
    cpu: [x64]
    os: [linux]

  '@biomejs/cli-win32-arm64@2.5.10':
    resolution: {integrity: sha512-pxAbxduPO4xq/Cvgaa2lOrs9BB0hEXmmDqfMNP4ZOffGOkUrD1/QGw9UAMpFQpX2P8MqTIIRuQKcmetum4Oa6A==}
    engines: {node: '>=14.21.3'}
    cpu: [arm64]
    os: [win32]

  '@biomejs/cli-win32-x64@2.5.10':
    resolution: {integrity: sha512-M+2dgBsl3lXRiTfgPVc2p3anS4Tocojke4rzFLScZ2Y/wmF+36dRb1iHCLiyGqOzQGyTplZH1HnEYviiAqi3nA==}
    engines: {node: '>=14.21.3'}
    cpu: [x64]
    os: [win32]

  '@bruits/satteri-darwin-arm64@0.10.5':
    resolution: {integrity: sha512-27KTVl4TJkVahMy/ohyA7qd4938G5UNneFUz/PsScYfpIhj0IVAS23mpcJXdPF44sa6nva198lmV/cKIb2YPyA==}
    cpu: [arm64]
    os: [darwin]

  '@bruits/satteri-darwin-x64@0.10.5':
    resolution: {integrity: sha512-IjnLe3nKspq6qaeqGgjT7MT8VrTV74yWRlaag7ZdNsI8TDAYZ0iPxMCo+9KQZHUk5EyVB+reBI/PFWL5KuFw9Q==}
    cpu: [x64]
    os: [darwin]

  '@bruits/satteri-linux-arm64-gnu@0.10.5':
    resolution: {integrity: sha512-glkYXZCJywjP13v67eAyAMSJdF+ncvEbYvgi/wOtffL9tQ27lr/zsyzUfgs+ovjJ9d8JNQKiXeiArJcX8PJL9w==}
    cpu: [arm64]
    os: [linux]

  '@bruits/satteri-linux-arm64-musl@0.10.5':
    resolution: {integrity: sha512-yWdgG1g17Nh2QyGVlFUxGRa3FEFwiMcpZEyMNWkbM3deC94cmVc+/i9OuyFpdKuWo3GkgoCtYVOoxk1uCnCZIA==}
    cpu: [arm64]
    os: [linux]

  '@bruits/satteri-linux-x64-gnu@0.10.5':
    resolution: {integrity: sha512-FVaLoPT1fBgGl0J+AYebyyXJYBachGl8Oyyrf1lye4RTqCB4S0Gwkj1uM9RJyThUOvx5VUmAT1CnNh1SFHA+kw==}
    cpu: [x64]
    os: [linux]

  '@bruits/satteri-linux-x64-musl@0.10.5':
    resolution: {integrity: sha512-EHpVAx2bqW3GINHTKkljtxVfQmVDGWIuwOYOP5YghTj+0PkBa2o8oKPRtQ9Kbsr1Fye8jtUcDjhwj2jMNugZKg==}
    cpu: [x64]
    os: [linux]

  '@bruits/satteri-wasm32-wasi@0.10.5':
    resolution: {integrity: sha512-ypz8c/Zmipxp4IoeDa228Gstv6TLzVmNs3yC6wKCoNSOjx1iwpgzu87Y3hTkXFdwChVGU85qeUDuOIarGUZQLw==}
    engines: {node: '>=14.0.0'}
    cpu: [wasm32]

  '@bruits/satteri-win32-arm64-msvc@0.10.5':
    resolution: {integrity: sha512-siTV88nb0LRqNpkL2gXboqCwVdq95sLtzMHS1/3eONV2gLbB3NAK46wmSMvCO/yquBvI2lvaFIfd8P12ecsxBw==}
    cpu: [arm64]
    os: [win32]

  '@bruits/satteri-win32-x64-msvc@0.10.5':
    resolution: {integrity: sha512-C3IfPvfvMXmlzBxaMPKFS1XiuV9pu2mC7YqkPk7PSvTgPZ8gbdASIpHpztDLvTTQjqZ0z1Ol8tK5X+V6XXC0wQ==}
    cpu: [x64]
    os: [win32]

  '@capsizecss/unpack@4.0.0':
    resolution: {integrity: sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==}
    engines: {node: '>=18'}

  '@clack/core@1.4.3':
    resolution: {integrity: sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==}
    engines: {node: '>= 20.12.0'}

  '@clack/prompts@1.7.0':
    resolution: {integrity: sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==}
    engines: {node: '>= 20.12.0'}

  '@emmetio/abbreviation@2.3.3':
    resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==}

  '@emmetio/css-abbreviation@2.1.8':
    resolution: {integrity: sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==}

  '@emmetio/css-parser@0.4.1':
    resolution: {integrity: sha512-2bC6m0MV/voF4CTZiAbG5MWKbq5EBmDPKu9Sb7s7nVcEzNQlrZP6mFFFlIaISM8X6514H9shWMme1fCm8cWAfQ==}

  '@emmetio/html-matcher@1.3.0':
    resolution: {integrity: sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==}

  '@emmetio/scanner@1.0.4':
    resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==}

  '@emmetio/stream-reader-utils@0.1.0':
    resolution: {integrity: sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==}

  '@emmetio/stream-reader@2.2.0':
    resolution: {integrity: sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==}

  '@emnapi/core@1.11.1':
    resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==}

  '@emnapi/runtime@1.11.1':
    resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==}

  '@emnapi/runtime@1.11.3':
    resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}

  '@emnapi/wasi-threads@1.2.2':
    resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==}

  '@esbuild/aix-ppc64@0.28.2':
    resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==}
    engines: {node: '>=18'}
    cpu: [ppc64]
    os: [aix]

  '@esbuild/android-arm64@0.28.2':
    resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [android]

  '@esbuild/android-arm@0.28.2':
    resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==}
    engines: {node: '>=18'}
    cpu: [arm]
    os: [android]

  '@esbuild/android-x64@0.28.2':
    resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [android]

  '@esbuild/darwin-arm64@0.28.2':
    resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [darwin]

  '@esbuild/darwin-x64@0.28.2':
    resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [darwin]

  '@esbuild/freebsd-arm64@0.28.2':
    resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [freebsd]

  '@esbuild/freebsd-x64@0.28.2':
    resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [freebsd]

  '@esbuild/linux-arm64@0.28.2':
    resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [linux]

  '@esbuild/linux-arm@0.28.2':
    resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==}
    engines: {node: '>=18'}
    cpu: [arm]
    os: [linux]

  '@esbuild/linux-ia32@0.28.2':
    resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==}
    engines: {node: '>=18'}
    cpu: [ia32]
    os: [linux]

  '@esbuild/linux-loong64@0.28.2':
    resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==}
    engines: {node: '>=18'}
    cpu: [loong64]
    os: [linux]

  '@esbuild/linux-mips64el@0.28.2':
    resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==}
    engines: {node: '>=18'}
    cpu: [mips64el]
    os: [linux]

  '@esbuild/linux-ppc64@0.28.2':
    resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==}
    engines: {node: '>=18'}
    cpu: [ppc64]
    os: [linux]

  '@esbuild/linux-riscv64@0.28.2':
    resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==}
    engines: {node: '>=18'}
    cpu: [riscv64]
    os: [linux]

  '@esbuild/linux-s390x@0.28.2':
    resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==}
    engines: {node: '>=18'}
    cpu: [s390x]
    os: [linux]

  '@esbuild/linux-x64@0.28.2':
    resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [linux]

  '@esbuild/netbsd-arm64@0.28.2':
    resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [netbsd]

  '@esbuild/netbsd-x64@0.28.2':
    resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [netbsd]

  '@esbuild/openbsd-arm64@0.28.2':
    resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [openbsd]

  '@esbuild/openbsd-x64@0.28.2':
    resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [openbsd]

  '@esbuild/openharmony-arm64@0.28.2':
    resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [openharmony]

  '@esbuild/sunos-x64@0.28.2':
    resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [sunos]

  '@esbuild/win32-arm64@0.28.2':
    resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [win32]

  '@esbuild/win32-ia32@0.28.2':
    resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==}
    engines: {node: '>=18'}
    cpu: [ia32]
    os: [win32]

  '@esbuild/win32-x64@0.28.2':
    resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [win32]

  '@img/colour@1.1.0':
    resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
    engines: {node: '>=18'}

  '@img/sharp-darwin-arm64@0.35.3':
    resolution: {integrity: sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==}
    engines: {node: '>=20.9.0'}
    cpu: [arm64]
    os: [darwin]

  '@img/sharp-darwin-x64@0.35.3':
    resolution: {integrity: sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==}
    engines: {node: '>=20.9.0'}
    cpu: [x64]
    os: [darwin]

  '@img/sharp-freebsd-wasm32@0.35.3':
    resolution: {integrity: sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==}
    engines: {node: '>=20.9.0'}
    os: [freebsd]

  '@img/sharp-libvips-darwin-arm64@1.3.2':
    resolution: {integrity: sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==}
    cpu: [arm64]
    os: [darwin]

  '@img/sharp-libvips-darwin-x64@1.3.2':
    resolution: {integrity: sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==}
    cpu: [x64]
    os: [darwin]

  '@img/sharp-libvips-linux-arm64@1.3.2':
    resolution: {integrity: sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==}
    cpu: [arm64]
    os: [linux]

  '@img/sharp-libvips-linux-arm@1.3.2':
    resolution: {integrity: sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==}
    cpu: [arm]
    os: [linux]

  '@img/sharp-libvips-linux-ppc64@1.3.2':
    resolution: {integrity: sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==}
    cpu: [ppc64]
    os: [linux]

  '@img/sharp-libvips-linux-riscv64@1.3.2':
    resolution: {integrity: sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==}
    cpu: [riscv64]
    os: [linux]

  '@img/sharp-libvips-linux-s390x@1.3.2':
    resolution: {integrity: sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==}
    cpu: [s390x]
    os: [linux]

  '@img/sharp-libvips-linux-x64@1.3.2':
    resolution: {integrity: sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==}
    cpu: [x64]
    os: [linux]

  '@img/sharp-libvips-linuxmusl-arm64@1.3.2':
    resolution: {integrity: sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==}
    cpu: [arm64]
    os: [linux]

  '@img/sharp-libvips-linuxmusl-x64@1.3.2':
    resolution: {integrity: sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==}
    cpu: [x64]
    os: [linux]

  '@img/sharp-linux-arm64@0.35.3':
    resolution: {integrity: sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==}
    engines: {node: '>=20.9.0'}
    cpu: [arm64]
    os: [linux]

  '@img/sharp-linux-arm@0.35.3':
    resolution: {integrity: sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==}
    engines: {node: '>=20.9.0'}
    cpu: [arm]
    os: [linux]

  '@img/sharp-linux-ppc64@0.35.3':
    resolution: {integrity: sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==}
    engines: {node: '>=20.9.0'}
    cpu: [ppc64]
    os: [linux]

  '@img/sharp-linux-riscv64@0.35.3':
    resolution: {integrity: sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==}
    engines: {node: '>=20.9.0'}
    cpu: [riscv64]
    os: [linux]

  '@img/sharp-linux-s390x@0.35.3':
    resolution: {integrity: sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==}
    engines: {node: '>=20.9.0'}
    cpu: [s390x]
    os: [linux]

  '@img/sharp-linux-x64@0.35.3':
    resolution: {integrity: sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==}
    engines: {node: '>=20.9.0'}
    cpu: [x64]
    os: [linux]

  '@img/sharp-linuxmusl-arm64@0.35.3':
    resolution: {integrity: sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==}
    engines: {node: '>=20.9.0'}
    cpu: [arm64]
    os: [linux]

  '@img/sharp-linuxmusl-x64@0.35.3':
    resolution: {integrity: sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==}
    engines: {node: '>=20.9.0'}
    cpu: [x64]
    os: [linux]

  '@img/sharp-wasm32@0.35.3':
    resolution: {integrity: sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==}
    engines: {node: '>=20.9.0'}

  '@img/sharp-webcontainers-wasm32@0.35.3':
    resolution: {integrity: sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==}
    engines: {node: '>=20.9.0'}
    cpu: [wasm32]

  '@img/sharp-win32-arm64@0.35.3':
    resolution: {integrity: sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==}
    engines: {node: '>=20.9.0'}
    cpu: [arm64]
    os: [win32]

  '@img/sharp-win32-ia32@0.35.3':
    resolution: {integrity: sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==}
    engines: {node: ^20.9.0}
    cpu: [ia32]
    os: [win32]

  '@img/sharp-win32-x64@0.35.3':
    resolution: {integrity: sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==}
    engines: {node: '>=20.9.0'}
    cpu: [x64]
    os: [win32]

  '@jridgewell/gen-mapping@0.3.13':
    resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}

  '@jridgewell/remapping@2.3.5':
    resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}

  '@jridgewell/resolve-uri@3.1.2':
    resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
    engines: {node: '>=6.0.0'}

  '@jridgewell/sourcemap-codec@1.5.5':
    resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}

  '@jridgewell/trace-mapping@0.3.31':
    resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}

  '@napi-rs/wasm-runtime@1.2.3':
    resolution: {integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==}
    engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0}
    peerDependencies:
      '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4
      '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4

  '@nodable/entities@3.0.0':
    resolution: {integrity: sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw==}

  '@oslojs/encoding@1.1.0':
    resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}

  '@oxc-project/types@0.146.0':
    resolution: {integrity: sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA==}

  '@rolldown/binding-android-arm-eabi@1.2.5':
    resolution: {integrity: sha512-DLe/i+l8ynIBY7XEQ191TeZvCoowIGa18R+dIV30GW7DiOtp74i/xX8hs8GUjW5ARV7VZuie3d6AumSmCwbeRA==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm]
    os: [android]

  '@rolldown/binding-android-arm64@1.2.5':
    resolution: {integrity: sha512-zXcwKlQApYAOELHd8PwKDFkagYF9Wy4e0RJ+0qnzl9Pjnpj75TEG8ufv40p2J7kCEfwZAsNiuzRIyNNMWT38ig==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm64]
    os: [android]

  '@rolldown/binding-darwin-arm64@1.2.5':
    resolution: {integrity: sha512-dK4QakI42nzWgJT5sm4y4y/O//D4OxM75/cH28RLV+nzIN9AY+YsbuUVrUTjlLjXR6vpyxFbSsbmNuJ6BP9sww==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm64]
    os: [darwin]

  '@rolldown/binding-darwin-x64@1.2.5':
    resolution: {integrity: sha512-fqSALaUu1Wjd1nK2uW2kJDWdLCc8lx1IcY+MTY26Aurfdx19anlzhqXOgCFbBFQnlFDTn4TC1/7Nz4Bl2mLP3A==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [x64]
    os: [darwin]

  '@rolldown/binding-freebsd-x64@1.2.5':
    resolution: {integrity: sha512-/vCnNxlkxs9tKxNDcyWUePpJ/PgTzxIaVhoM5SmG8UV+GR/IcPam4VYxi7GIMo7PSDuNqlJqvprqii9NqqVCMw==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [x64]
    os: [freebsd]

  '@rolldown/binding-linux-arm-gnueabihf@1.2.5':
    resolution: {integrity: sha512-abk0NLA519LxRCszmbE0jYKuQ9YPocOXTiOXOo6Yr+YAT95VH+PtqYAjOJvGKt3viEd/x4qzabAlwd5bHOOARg==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm]
    os: [linux]

  '@rolldown/binding-linux-arm64-gnu@1.2.5':
    resolution: {integrity: sha512-Y7eALiJ8lr0M2HH103Js+g7V34wf6snlpZLAsHI90uLhr3PVlNsbFVAXJC9d/V6BnPyKtpSwI+NcB/RLxsQxuA==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm64]
    os: [linux]

  '@rolldown/binding-linux-arm64-musl@1.2.5':
    resolution: {integrity: sha512-xMvZgnbZg4YVnR/AX2b3oOPDTFYJvUVaJg5FedA/LuvexAtXibZQej4cnTkw3rjsJ/ggUROB64TdtETiim+FYA==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm64]
    os: [linux]

  '@rolldown/binding-linux-ppc64-gnu@1.2.5':
    resolution: {integrity: sha512-GRjeqTUDHTo5GwntsLaAMcBahG3nlpjftXWZLN73HiYQlhwEowvarFgQnRnQZtIp4keXX7quXFbG38uPZBa2EA==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [ppc64]
    os: [linux]

  '@rolldown/binding-linux-s390x-gnu@1.2.5':
    resolution: {integrity: sha512-vLNTR45F2Uwc8AufkNXPmB4VliaXs+FvcheEogIzOXzO4l+LzieXF5A/TWxLy5HtqpsRCHUfd0lPVrrdgXdLHQ==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [s390x]
    os: [linux]

  '@rolldown/binding-linux-x64-gnu@1.2.5':
    resolution: {integrity: sha512-Mgj59/HTuYeK9Gz2MA+mBWKnHsAgkBSec15ZMb1st3oIfFbX7gCjOae7GydHhzcyQi9Z/7M1QuN9bR3oFqF0jQ==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [x64]
    os: [linux]

  '@rolldown/binding-linux-x64-musl@1.2.5':
    resolution: {integrity: sha512-mY8AP0/ichsbhAxGnLa3d3+MwV0EfgrPND2bplI3Ym8T6R2pJ0N87bvrKVwNXmdy3jnr6eQBecdqx/HMknBmpA==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [x64]
    os: [linux]

  '@rolldown/binding-openharmony-arm64@1.2.5':
    resolution: {integrity: sha512-8SLssA2oweAxyRgDp789ACfRb/3P+zNRJpzZxSizxF9m8NUDQ4+3xjo8ttjhVGGw6Qxb70oZiEtIjaKikCO7Yw==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm64]
    os: [openharmony]

  '@rolldown/binding-win32-arm64-msvc@1.2.5':
    resolution: {integrity: sha512-vGbruD5zquhoc8D9SViXgN2FBJtNdTyQ4DtG+SWiEGlJiAzoKcZ2xp+xuXCffhubVdt0NJlTZqkeRuERy7g8Cw==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [arm64]
    os: [win32]

  '@rolldown/binding-win32-x64-msvc@1.2.5':
    resolution: {integrity: sha512-e/SXpgISz+IoqVcSSI0rx/d/he8zqLex+/rCWpnHpmVfmPIUjag9H6P7zotf0gJHwPUhQxZ/mF8tr6acebT9yw==}
    engines: {node: ^20.19.0 || >=22.12.0}
    cpu: [x64]
    os: [win32]

  '@rolldown/pluginutils@1.0.1':
    resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}

  '@shikijs/core@4.4.3':
    resolution: {integrity: sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==}
    engines: {node: '>=20'}

  '@shikijs/engine-javascript@4.4.3':
    resolution: {integrity: sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==}
    engines: {node: '>=20'}

  '@shikijs/engine-oniguruma@4.4.3':
    resolution: {integrity: sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==}
    engines: {node: '>=20'}

  '@shikijs/langs@4.4.3':
    resolution: {integrity: sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==}
    engines: {node: '>=20'}

  '@shikijs/primitive@4.4.3':
    resolution: {integrity: sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==}
    engines: {node: '>=20'}

  '@shikijs/themes@4.4.3':
    resolution: {integrity: sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==}
    engines: {node: '>=20'}

  '@shikijs/types@4.4.3':
    resolution: {integrity: sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==}
    engines: {node: '>=20'}

  '@shikijs/vscode-textmate@10.0.2':
    resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}

  '@tailwindcss/node@4.3.3':
    resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==}

  '@tailwindcss/oxide-android-arm64@4.3.3':
    resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==}
    engines: {node: '>= 20'}
    cpu: [arm64]
    os: [android]

  '@tailwindcss/oxide-darwin-arm64@4.3.3':
    resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==}
    engines: {node: '>= 20'}
    cpu: [arm64]
    os: [darwin]

  '@tailwindcss/oxide-darwin-x64@4.3.3':
    resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==}
    engines: {node: '>= 20'}
    cpu: [x64]
    os: [darwin]

  '@tailwindcss/oxide-freebsd-x64@4.3.3':
    resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==}
    engines: {node: '>= 20'}
    cpu: [x64]
    os: [freebsd]

  '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
    resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==}
    engines: {node: '>= 20'}
    cpu: [arm]
    os: [linux]

  '@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
    resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==}
    engines: {node: '>= 20'}
    cpu: [arm64]
    os: [linux]

  '@tailwindcss/oxide-linux-arm64-musl@4.3.3':
    resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==}
    engines: {node: '>= 20'}
    cpu: [arm64]
    os: [linux]

  '@tailwindcss/oxide-linux-x64-gnu@4.3.3':
    resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==}
    engines: {node: '>= 20'}
    cpu: [x64]
    os: [linux]

  '@tailwindcss/oxide-linux-x64-musl@4.3.3':
    resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==}
    engines: {node: '>= 20'}
    cpu: [x64]
    os: [linux]

  '@tailwindcss/oxide-wasm32-wasi@4.3.3':
    resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==}
    engines: {node: '>=14.0.0'}
    cpu: [wasm32]
    bundledDependencies:
      - '@napi-rs/wasm-runtime'
      - '@emnapi/core'
      - '@emnapi/runtime'
      - '@tybys/wasm-util'
      - '@emnapi/wasi-threads'
      - tslib

  '@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
    resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==}
    engines: {node: '>= 20'}
    cpu: [arm64]
    os: [win32]

  '@tailwindcss/oxide-win32-x64-msvc@4.3.3':
    resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==}
    engines: {node: '>= 20'}
    cpu: [x64]
    os: [win32]

  '@tailwindcss/oxide@4.3.3':
    resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==}
    engines: {node: '>= 20'}

  '@tailwindcss/typography@0.5.20':
    resolution: {integrity: sha512-hwbzQuNUfcPvbegQFatVPl/MY/tcM9KLl963hQ5laJKPh81TEZ1+dNG9PirGvcaDBkp+BCshExAyKVPW91dozw==}
    peerDependencies:
      tailwindcss: '>=3.0.0 || >=4.0.0 || insiders'

  '@tailwindcss/vite@4.3.3':
    resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==}
    peerDependencies:
      vite: ^5.2.0 || ^6 || ^7 || ^8

  '@tybys/wasm-util@0.10.3':
    resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==}

  '@types/debug@4.1.13':
    resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==}

  '@types/estree-jsx@1.0.5':
    resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}

  '@types/estree@1.0.8':
    resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}

  '@types/hast@3.0.5':
    resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==}

  '@types/mdast@4.0.4':
    resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}

  '@types/ms@2.1.0':
    resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}

  '@types/nlcst@2.0.3':
    resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==}

  '@types/node@24.10.1':
    resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==}

  '@types/sax@1.2.7':
    resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}

  '@types/unist@3.0.3':
    resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}

  '@ungap/structured-clone@1.3.0':
    resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
    deprecated: Potential CWE-502 - Update to 1.3.1 or higher

  '@volar/kit@2.4.28':
    resolution: {integrity: sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg==}
    peerDependencies:
      typescript: '*'

  '@volar/language-core@2.4.28':
    resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==}

  '@volar/language-server@2.4.28':
    resolution: {integrity: sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw==}

  '@volar/language-service@2.4.28':
    resolution: {integrity: sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw==}

  '@volar/source-map@2.4.28':
    resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==}

  '@volar/typescript@2.4.28':
    resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==}

  '@vscode/emmet-helper@2.11.0':
    resolution: {integrity: sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw==}

  '@vscode/l10n@0.0.18':
    resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==}

  ajv-draft-04@1.0.0:
    resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==}
    peerDependencies:
      ajv: ^8.5.0
    peerDependenciesMeta:
      ajv:
        optional: true

  ajv-i18n@4.2.0:
    resolution: {integrity: sha512-v/ei2UkCEeuKNXh8RToiFsUclmU+G57LO1Oo22OagNMENIw+Yb8eMwvHu7Vn9fmkjJyv6XclhJ8TbuigSglPkg==}
    peerDependencies:
      ajv: ^8.0.0-beta.0

  ajv@8.17.1:
    resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}

  am-i-vibing@0.4.0:
    resolution: {integrity: sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg==}
    hasBin: true

  ansi-regex@6.2.2:
    resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
    engines: {node: '>=12'}

  ansi-styles@4.3.0:
    resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
    engines: {node: '>=8'}

  ansi-styles@6.2.3:
    resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
    engines: {node: '>=12'}

  anymatch@3.1.3:
    resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
    engines: {node: '>= 8'}

  anynum@1.0.1:
    resolution: {integrity: sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==}

  arg@5.0.2:
    resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}

  argparse@2.0.1:
    resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}

  aria-query@5.3.2:
    resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
    engines: {node: '>= 0.4'}

  array-iterate@2.0.1:
    resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==}

  astro@7.2.6:
    resolution: {integrity: sha512-qzT4tAhgHYX/6/MUGslAkF0PVkM4WNsMw2A1GrbfA9cXp68hmdqF3f7MuF5rRFvwQbjowqjOf90ao9whfgV5mw==}
    engines: {node: '>=22.12.0', npm: '>=9.6.5', pnpm: '>=7.1.0'}
    hasBin: true
    peerDependencies:
      '@astrojs/markdown-remark': 7.2.4
    peerDependenciesMeta:
      '@astrojs/markdown-remark':
        optional: true

  axobject-query@4.1.0:
    resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
    engines: {node: '>= 0.4'}

  bail@2.0.2:
    resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}

  boolbase@1.0.0:
    resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}

  ccount@2.0.1:
    resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}

  chalk@4.1.2:
    resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
    engines: {node: '>=10'}

  character-entities-html4@2.1.0:
    resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}

  character-entities-legacy@3.0.0:
    resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}

  character-entities@2.0.2:
    resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}

  chokidar@4.0.3:
    resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
    engines: {node: '>= 14.16.0'}

  chokidar@5.0.0:
    resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
    engines: {node: '>= 20.19.0'}

  ci-info@4.4.0:
    resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==}
    engines: {node: '>=8'}

  cliui@9.0.1:
    resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==}
    engines: {node: '>=20'}

  clsx@2.1.1:
    resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
    engines: {node: '>=6'}

  color-convert@2.0.1:
    resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
    engines: {node: '>=7.0.0'}

  color-name@1.1.4:
    resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}

  comma-separated-tokens@2.0.3:
    resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}

  commander@11.1.0:
    resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
    engines: {node: '>=16'}

  commander@14.0.3:
    resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==}
    engines: {node: '>=20'}

  common-ancestor-path@2.0.0:
    resolution: {integrity: sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==}
    engines: {node: '>= 18'}

  cookie-es@1.2.3:
    resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==}

  cookie@2.0.1:
    resolution: {integrity: sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==}
    engines: {node: '>=22'}

  crossws@0.3.5:
    resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==}

  css-select@6.0.0:
    resolution: {integrity: sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==}

  css-tree@2.2.1:
    resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==}
    engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}

  css-tree@3.1.0:
    resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==}
    engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}

  css-what@7.0.0:
    resolution: {integrity: sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==}
    engines: {node: '>= 6'}

  cssesc@3.0.0:
    resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
    engines: {node: '>=4'}
    hasBin: true

  csso@5.0.5:
    resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
    engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}

  debug@4.4.3:
    resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
    engines: {node: '>=6.0'}
    peerDependencies:
      supports-color: '*'
    peerDependenciesMeta:
      supports-color:
        optional: true

  decode-named-character-reference@1.3.0:
    resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==}

  defu@6.1.7:
    resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==}

  dequal@2.0.3:
    resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
    engines: {node: '>=6'}

  destr@2.0.5:
    resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}

  detect-libc@2.1.2:
    resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
    engines: {node: '>=8'}

  devalue@5.9.1:
    resolution: {integrity: sha512-+17vil3EVQRzvtDJSFuTWEb8XJRvXqAiV3qZyQWD398QeXUa6CxsUyMdD1fxzEhUrd4FojitFz7lhIHBTlV4fw==}

  devlop@1.1.0:
    resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}

  diff@9.0.0:
    resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==}
    engines: {node: '>=0.3.1'}

  dom-serializer@2.0.0:
    resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}

  domelementtype@2.3.0:
    resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}

  domhandler@5.0.3:
    resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
    engines: {node: '>= 4'}

  domutils@3.2.2:
    resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}

  dset@3.1.4:
    resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
    engines: {node: '>=4'}

  emmet@2.4.11:
    resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==}

  emoji-regex@10.6.0:
    resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}

  enhanced-resolve@5.24.5:
    resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==}
    engines: {node: '>=10.13.0'}

  entities@4.5.0:
    resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
    engines: {node: '>=0.12'}

  entities@6.0.1:
    resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
    engines: {node: '>=0.12'}

  es-module-lexer@2.3.2:
    resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==}

  esbuild@0.28.2:
    resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==}
    engines: {node: '>=18'}
    hasBin: true

  escalade@3.2.0:
    resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
    engines: {node: '>=6'}

  escape-string-regexp@5.0.0:
    resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
    engines: {node: '>=12'}

  eventemitter3@5.0.4:
    resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==}

  extend@3.0.2:
    resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}

  fast-deep-equal@3.1.3:
    resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}

  fast-string-truncated-width@3.0.3:
    resolution: {integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==}

  fast-string-width@3.0.2:
    resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==}

  fast-uri@3.1.0:
    resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}

  fast-wrap-ansi@0.2.2:
    resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==}

  fast-xml-builder@1.3.1:
    resolution: {integrity: sha512-pIM/1n3ntFXKYrUZwW7QCK0gAW7XY+wzj1YMIV3tLDvPj/V+zTGJK5e3/4WJfwj0qWw2ElNXiTixda/R+3YSug==}

  fast-xml-parser@5.11.0:
    resolution: {integrity: sha512-9IGxMqvqLOnqP+Egi1nqDHKv5k8aZ7r9n558enxcucmyVGEBNPAU+MOg/8jPIS7rO7sSq4gFm1/nHtiaubMruw==}
    hasBin: true

  fdir@6.5.0:
    resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
    engines: {node: '>=12.0.0'}
    peerDependencies:
      picomatch: ^3 || ^4
    peerDependenciesMeta:
      picomatch:
        optional: true

  find-process@2.1.1:
    resolution: {integrity: sha512-SrQDx3QhlmHM90iqn9rdjCQcw/T+WlpOkHFsjoRgB+zTpDfltNA1VSNYeYELwhUTJy12UFxqjWhmhOrJc+o4sA==}
    hasBin: true

  flattie@1.1.1:
    resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==}
    engines: {node: '>=8'}

  fontace@0.4.1:
    resolution: {integrity: sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==}

  fontkitten@1.0.0:
    resolution: {integrity: sha512-b0RdzQeztiiUFWEDzq6Ka26qkNVNLCehoRtifOIGNbQ4CfxyYRh73fyWaQX/JshPVcueITOEeoSWPy5XQv8FUg==}
    engines: {node: '>=20'}

  fontkitten@1.0.3:
    resolution: {integrity: sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==}
    engines: {node: '>=20'}

  fsevents@2.3.3:
    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
    engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
    os: [darwin]

  get-caller-file@2.0.5:
    resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
    engines: {node: 6.* || 8.* || >= 10.*}

  get-east-asian-width@1.4.0:
    resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==}
    engines: {node: '>=18'}

  get-east-asian-width@1.6.0:
    resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==}
    engines: {node: '>=18'}

  get-tsconfig@5.0.0-beta.4:
    resolution: {integrity: sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ==}
    engines: {node: '>=20.20.0'}

  github-slugger@2.0.0:
    resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==}

  graceful-fs@4.2.11:
    resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}

  h3@1.15.11:
    resolution: {integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==}

  has-flag@4.0.0:
    resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
    engines: {node: '>=8'}

  hast-util-from-html@2.0.3:
    resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==}

  hast-util-from-parse5@8.0.3:
    resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==}

  hast-util-heading-rank@3.0.0:
    resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==}

  hast-util-is-element@3.0.0:
    resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}

  hast-util-parse-selector@4.0.0:
    resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}

  hast-util-raw@9.1.0:
    resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==}

  hast-util-to-html@9.0.5:
    resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}

  hast-util-to-parse5@8.0.1:
    resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==}

  hast-util-to-string@3.0.1:
    resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==}

  hast-util-to-text@4.0.2:
    resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==}

  hast-util-whitespace@3.0.0:
    resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}

  hastscript@9.0.1:
    resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}

  html-escaper@3.0.3:
    resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}

  html-void-elements@3.0.0:
    resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}

  http-cache-semantics@4.2.0:
    resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}

  iron-webcrypto@1.2.1:
    resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==}

  is-docker@4.0.0:
    resolution: {integrity: sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA==}
    engines: {node: '>=20'}
    hasBin: true

  is-plain-obj@4.1.0:
    resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
    engines: {node: '>=12'}

  is-unsafe@2.0.2:
    resolution: {integrity: sha512-HgbIHPBH0KHHCcjLfGsCvhtPTVxjaAZlXjwdz7/GQC40SjSe4sfQsar8J5VFo8JOSbarkpV0OLG95bbaNd9aAQ==}

  jiti@2.7.0:
    resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
    hasBin: true

  js-yaml@4.3.1:
    resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==}
    hasBin: true

  json-schema-traverse@1.0.0:
    resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}

  jsonc-parser@2.3.1:
    resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==}

  jsonc-parser@3.3.1:
    resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==}

  kleur@4.1.5:
    resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
    engines: {node: '>=6'}

  lightningcss-android-arm64@1.32.0:
    resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm64]
    os: [android]

  lightningcss-android-arm64@1.33.0:
    resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm64]
    os: [android]

  lightningcss-darwin-arm64@1.32.0:
    resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm64]
    os: [darwin]

  lightningcss-darwin-arm64@1.33.0:
    resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm64]
    os: [darwin]

  lightningcss-darwin-x64@1.32.0:
    resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
    engines: {node: '>= 12.0.0'}
    cpu: [x64]
    os: [darwin]

  lightningcss-darwin-x64@1.33.0:
    resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==}
    engines: {node: '>= 12.0.0'}
    cpu: [x64]
    os: [darwin]

  lightningcss-freebsd-x64@1.32.0:
    resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
    engines: {node: '>= 12.0.0'}
    cpu: [x64]
    os: [freebsd]

  lightningcss-freebsd-x64@1.33.0:
    resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==}
    engines: {node: '>= 12.0.0'}
    cpu: [x64]
    os: [freebsd]

  lightningcss-linux-arm-gnueabihf@1.32.0:
    resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm]
    os: [linux]

  lightningcss-linux-arm-gnueabihf@1.33.0:
    resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm]
    os: [linux]

  lightningcss-linux-arm64-gnu@1.32.0:
    resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm64]
    os: [linux]

  lightningcss-linux-arm64-gnu@1.33.0:
    resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm64]
    os: [linux]

  lightningcss-linux-arm64-musl@1.32.0:
    resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm64]
    os: [linux]

  lightningcss-linux-arm64-musl@1.33.0:
    resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm64]
    os: [linux]

  lightningcss-linux-x64-gnu@1.32.0:
    resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
    engines: {node: '>= 12.0.0'}
    cpu: [x64]
    os: [linux]

  lightningcss-linux-x64-gnu@1.33.0:
    resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==}
    engines: {node: '>= 12.0.0'}
    cpu: [x64]
    os: [linux]

  lightningcss-linux-x64-musl@1.32.0:
    resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
    engines: {node: '>= 12.0.0'}
    cpu: [x64]
    os: [linux]

  lightningcss-linux-x64-musl@1.33.0:
    resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==}
    engines: {node: '>= 12.0.0'}
    cpu: [x64]
    os: [linux]

  lightningcss-win32-arm64-msvc@1.32.0:
    resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm64]
    os: [win32]

  lightningcss-win32-arm64-msvc@1.33.0:
    resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==}
    engines: {node: '>= 12.0.0'}
    cpu: [arm64]
    os: [win32]

  lightningcss-win32-x64-msvc@1.32.0:
    resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
    engines: {node: '>= 12.0.0'}
    cpu: [x64]
    os: [win32]

  lightningcss-win32-x64-msvc@1.33.0:
    resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==}
    engines: {node: '>= 12.0.0'}
    cpu: [x64]
    os: [win32]

  lightningcss@1.32.0:
    resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
    engines: {node: '>= 12.0.0'}

  lightningcss@1.33.0:
    resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==}
    engines: {node: '>= 12.0.0'}

  loglevel@1.9.2:
    resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==}
    engines: {node: '>= 0.6.0'}

  longest-streak@3.1.0:
    resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}

  lru-cache@11.5.2:
    resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==}
    engines: {node: 20 || >=22}

  magic-string@0.30.21:
    resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}

  magic-string@1.2.2:
    resolution: {integrity: sha512-veT/+7iXrXzT39XnEN4lOxtNl72dMgJ8Lp+5Bd6YcMSWpb0n0MjBM8Uuooi6jgJr8dhUW2swQgBmoZVMni5SVg==}

  magicast@0.5.4:
    resolution: {integrity: sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==}

  markdown-table@3.0.4:
    resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}

  mdast-util-definitions@6.0.0:
    resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==}

  mdast-util-find-and-replace@3.0.2:
    resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}

  mdast-util-from-markdown@2.0.3:
    resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==}

  mdast-util-gfm-autolink-literal@2.0.1:
    resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}

  mdast-util-gfm-footnote@2.1.0:
    resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==}

  mdast-util-gfm-strikethrough@2.0.0:
    resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}

  mdast-util-gfm-table@2.0.0:
    resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}

  mdast-util-gfm-task-list-item@2.0.0:
    resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}

  mdast-util-gfm@3.1.0:
    resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==}

  mdast-util-phrasing@4.1.0:
    resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}

  mdast-util-to-hast@13.2.1:
    resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}

  mdast-util-to-markdown@2.1.2:
    resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}

  mdast-util-to-string@4.0.0:
    resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}

  mdn-data@2.0.28:
    resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}

  mdn-data@2.12.2:
    resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==}

  micromark-core-commonmark@2.0.3:
    resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}

  micromark-extension-gfm-autolink-literal@2.1.0:
    resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}

  micromark-extension-gfm-footnote@2.1.0:
    resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==}

  micromark-extension-gfm-strikethrough@2.1.0:
    resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==}

  micromark-extension-gfm-table@2.1.1:
    resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==}

  micromark-extension-gfm-tagfilter@2.0.0:
    resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}

  micromark-extension-gfm-task-list-item@2.1.0:
    resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==}

  micromark-extension-gfm@3.0.0:
    resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}

  micromark-factory-destination@2.0.1:
    resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}

  micromark-factory-label@2.0.1:
    resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}

  micromark-factory-space@2.0.1:
    resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}

  micromark-factory-title@2.0.1:
    resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==}

  micromark-factory-whitespace@2.0.1:
    resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==}

  micromark-util-character@2.1.1:
    resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}

  micromark-util-chunked@2.0.1:
    resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==}

  micromark-util-classify-character@2.0.1:
    resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==}

  micromark-util-combine-extensions@2.0.1:
    resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==}

  micromark-util-decode-numeric-character-reference@2.0.2:
    resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}

  micromark-util-decode-string@2.0.1:
    resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}

  micromark-util-encode@2.0.1:
    resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}

  micromark-util-html-tag-name@2.0.1:
    resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}

  micromark-util-normalize-identifier@2.0.1:
    resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==}

  micromark-util-resolve-all@2.0.1:
    resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==}

  micromark-util-sanitize-uri@2.0.1:
    resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}

  micromark-util-subtokenize@2.1.0:
    resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==}

  micromark-util-symbol@2.0.1:
    resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}

  micromark-util-types@2.0.2:
    resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}

  micromark@4.0.2:
    resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}

  mrmime@2.0.1:
    resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
    engines: {node: '>=10'}

  ms@2.1.3:
    resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}

  muggle-string@0.4.1:
    resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}

  nanoid@3.3.18:
    resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==}
    engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
    hasBin: true

  neotraverse@1.0.1:
    resolution: {integrity: sha512-WmmLty1YWwJl9yZi77v2dVIV6X2kuYV8YYBI/G3LWGKdGHmHUvL1z7FW0iDvEvGAwNEoc5x1tOOOyDnf5jJw/w==}
    engines: {node: '>= 10'}

  nlcst-to-string@4.0.0:
    resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==}

  node-fetch-native@1.6.7:
    resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==}

  node-mock-http@1.0.4:
    resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==}

  normalize-path@3.0.0:
    resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
    engines: {node: '>=0.10.0'}

  nth-check@2.1.1:
    resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}

  obug@2.1.4:
    resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==}
    engines: {node: '>=12.20.0'}

  ofetch@1.5.1:
    resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==}

  ohash@2.0.11:
    resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}

  oniguruma-parser@0.12.2:
    resolution: {integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==}

  oniguruma-to-es@4.3.6:
    resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==}

  p-limit@7.3.1:
    resolution: {integrity: sha512-0trZaiG7Y7kN/Egy9a8j47t9osC0Tch4PaIWd9yGF6bvmlk7muExRvGNYb8sXBwEKMoNKsbNN9P8EefuQekE4Q==}
    engines: {node: '>=20'}

  p-queue@9.3.3:
    resolution: {integrity: sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA==}
    engines: {node: '>=20'}

  p-timeout@7.0.1:
    resolution: {integrity: sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==}
    engines: {node: '>=20'}

  package-manager-detector@1.6.0:
    resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}

  parse-latin@7.0.0:
    resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==}

  parse5@7.3.0:
    resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}

  path-browserify@1.0.1:
    resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}

  path-expression-matcher@1.6.2:
    resolution: {integrity: sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==}
    engines: {node: '>=14.0.0'}

  piccolore@0.1.3:
    resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==}

  picocolors@1.1.1:
    resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}

  picomatch@2.3.1:
    resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
    engines: {node: '>=8.6'}

  picomatch@4.0.7:
    resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==}
    engines: {node: '>=12'}

  postcss-selector-parser@6.0.10:
    resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
    engines: {node: '>=4'}

  postcss@8.5.26:
    resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==}
    engines: {node: ^10 || ^12 || >=14}

  prettier@3.9.6:
    resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==}
    engines: {node: '>=14'}
    hasBin: true

  prismjs@1.30.0:
    resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
    engines: {node: '>=6'}

  process-ancestry@0.1.0:
    resolution: {integrity: sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg==}
    engines: {node: '>=18.0.0'}

  property-information@7.1.0:
    resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}

  radix3@1.1.2:
    resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==}

  readdirp@4.1.2:
    resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
    engines: {node: '>= 14.18.0'}

  readdirp@5.1.1:
    resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==}
    engines: {node: '>= 20.19.0'}

  regex-recursion@6.0.2:
    resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}

  regex-utilities@2.3.0:
    resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==}

  regex@6.1.0:
    resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==}

  rehype-autolink-headings@7.1.0:
    resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==}

  rehype-raw@7.0.0:
    resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==}

  rehype-slug@6.0.0:
    resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==}

  rehype-stringify@10.0.1:
    resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==}

  remark-gfm@4.0.1:
    resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}

  remark-parse@11.0.0:
    resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}

  remark-rehype@11.1.2:
    resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}

  remark-smartypants@3.0.3:
    resolution: {integrity: sha512-gCaK+ndZ0hYezlqFegHFCVh2CQemsi0Npdh1qVM9bxlUFknjkbP6VmojWhddOCrbK0PbbacmYLWfTULRiT1eWA==}
    engines: {node: '>=16.0.0'}

  remark-stringify@11.0.0:
    resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}

  request-light@0.5.8:
    resolution: {integrity: sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==}

  request-light@0.7.0:
    resolution: {integrity: sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==}

  require-from-string@2.0.2:
    resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
    engines: {node: '>=0.10.0'}

  resolve-pkg-maps@1.0.0:
    resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}

  retext-latin@4.0.0:
    resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==}

  retext-smartypants@6.2.0:
    resolution: {integrity: sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==}

  retext-stringify@4.0.0:
    resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==}

  retext@9.0.0:
    resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==}

  rolldown@1.2.5:
    resolution: {integrity: sha512-VD2IE5PUG4Oj8zz2VGykiYd5wbnjdIiSsNQb8Qu5B+noEp+A78mu2iVvpp27g8es14Tk9rofNs5Tku9iQCS4fA==}
    engines: {node: ^20.19.0 || >=22.12.0}
    hasBin: true

  satteri@0.10.5:
    resolution: {integrity: sha512-Ao1LKpAEa9Wdg0otgbVKViZHEq9ebdXe4DMrp3s9vQAU0HNIuHnFEuMuOcm0ZIXyV0Yzxj91NvhLpvXZJO/5ZQ==}

  sax@1.6.1:
    resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==}
    engines: {node: '>=11.0.0'}

  semver@7.7.3:
    resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
    engines: {node: '>=10'}
    hasBin: true

  semver@7.8.5:
    resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
    engines: {node: '>=10'}
    hasBin: true

  sharp@0.35.3:
    resolution: {integrity: sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==}
    engines: {node: '>=20.9.0'}
    peerDependencies:
      '@types/node': '*'
    peerDependenciesMeta:
      '@types/node':
        optional: true

  shiki@4.4.3:
    resolution: {integrity: sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==}
    engines: {node: '>=20'}

  sisteransi@1.0.5:
    resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}

  sitemap@9.0.1:
    resolution: {integrity: sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==}
    engines: {node: '>=20.19.5', npm: '>=10.8.2'}
    hasBin: true

  smol-toml@1.6.0:
    resolution: {integrity: sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==}
    engines: {node: '>= 18'}

  source-map-js@1.2.1:
    resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
    engines: {node: '>=0.10.0'}

  space-separated-tokens@2.0.2:
    resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}

  stream-replace-string@2.0.0:
    resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==}

  string-width@7.2.0:
    resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
    engines: {node: '>=18'}

  string-width@8.2.2:
    resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==}
    engines: {node: '>=20'}

  stringify-entities@4.0.4:
    resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}

  strip-ansi@7.1.2:
    resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
    engines: {node: '>=12'}

  strnum@2.4.2:
    resolution: {integrity: sha512-rDG3Ah4TV0k1hWvLSzkZtMmLN9+eS+h3knq4MP6A42Y3Yh5qGNnOUs1jJkoSr8FG5dsL28c7KgkIBzSEykqtuw==}

  supports-color@7.2.0:
    resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
    engines: {node: '>=8'}

  svgo@4.1.0:
    resolution: {integrity: sha512-bkxnTg1kSU0guhIBmibA6UUhrQmPVA1XsQLN+ylCd+UWzbnLkySOcXpyk1mrl05f+pcaCx2eHb+sp6BgMZWX+Q==}
    engines: {node: '>=16'}
    hasBin: true

  tailwindcss@4.3.3:
    resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==}

  tapable@2.3.3:
    resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==}
    engines: {node: '>=6'}

  tiny-inflate@1.0.3:
    resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}

  tinyclip@0.1.15:
    resolution: {integrity: sha512-uo33abH+Ays0xYaDysoBt494Hb3hsEczMpcC0MwFl773pazORx4fmvKhclhR1wonUbB6vvpRsvVMwnhfqeMc+A==}
    engines: {node: ^16.14.0 || >= 17.3.0}

  tinyexec@1.3.0:
    resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==}
    engines: {node: '>=18'}

  tinyglobby@0.2.15:
    resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
    engines: {node: '>=12.0.0'}

  tinyglobby@0.2.17:
    resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
    engines: {node: '>=12.0.0'}

  trim-lines@3.0.1:
    resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}

  trough@2.2.0:
    resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}

  tslib@2.8.1:
    resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}

  typesafe-path@0.2.2:
    resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==}

  typescript-auto-import-cache@0.3.6:
    resolution: {integrity: sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==}

  typescript@6.0.3:
    resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==}
    engines: {node: '>=14.17'}
    hasBin: true

  ufo@1.6.4:
    resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==}

  ultrahtml@1.6.0:
    resolution: {integrity: sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==}

  uncrypto@0.1.3:
    resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}

  undici-types@7.16.0:
    resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}

  undici@8.10.0:
    resolution: {integrity: sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==}
    engines: {node: '>=22.19.0'}

  unified@11.0.5:
    resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}

  unifont@0.7.5:
    resolution: {integrity: sha512-ULe/Cs+ZIsq+dcFofNkhqielCrUJnb5mr+Yc4EBM2VlL+6OZR6+cjtI2mT1bJvRBrVncqHAbLURxmPLcCXzWMg==}

  unist-util-find-after@5.0.0:
    resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==}

  unist-util-is@6.0.1:
    resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}

  unist-util-modify-children@4.0.0:
    resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==}

  unist-util-position@5.0.0:
    resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}

  unist-util-remove-position@5.0.0:
    resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==}

  unist-util-stringify-position@4.0.0:
    resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}

  unist-util-visit-children@3.0.0:
    resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==}

  unist-util-visit-parents@6.0.2:
    resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}

  unist-util-visit@5.0.0:
    resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}

  unist-util-visit@5.1.0:
    resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==}

  unstorage@1.17.5:
    resolution: {integrity: sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==}
    peerDependencies:
      '@azure/app-configuration': ^1.8.0
      '@azure/cosmos': ^4.2.0
      '@azure/data-tables': ^13.3.0
      '@azure/identity': ^4.6.0
      '@azure/keyvault-secrets': ^4.9.0
      '@azure/storage-blob': ^12.26.0
      '@capacitor/preferences': ^6 || ^7 || ^8
      '@deno/kv': '>=0.9.0'
      '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0
      '@planetscale/database': ^1.19.0
      '@upstash/redis': ^1.34.3
      '@vercel/blob': '>=0.27.1'
      '@vercel/functions': ^2.2.12 || ^3.0.0
      '@vercel/kv': ^1 || ^2 || ^3
      aws4fetch: ^1.0.20
      db0: '>=0.2.1'
      idb-keyval: ^6.2.1
      ioredis: ^5.4.2
      uploadthing: ^7.4.4
    peerDependenciesMeta:
      '@azure/app-configuration':
        optional: true
      '@azure/cosmos':
        optional: true
      '@azure/data-tables':
        optional: true
      '@azure/identity':
        optional: true
      '@azure/keyvault-secrets':
        optional: true
      '@azure/storage-blob':
        optional: true
      '@capacitor/preferences':
        optional: true
      '@deno/kv':
        optional: true
      '@netlify/blobs':
        optional: true
      '@planetscale/database':
        optional: true
      '@upstash/redis':
        optional: true
      '@vercel/blob':
        optional: true
      '@vercel/functions':
        optional: true
      '@vercel/kv':
        optional: true
      aws4fetch:
        optional: true
      db0:
        optional: true
      idb-keyval:
        optional: true
      ioredis:
        optional: true
      uploadthing:
        optional: true

  util-deprecate@1.0.2:
    resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}

  vfile-location@5.0.3:
    resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}

  vfile-message@4.0.3:
    resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}

  vfile@6.0.3:
    resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}

  vite@8.2.2:
    resolution: {integrity: sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==}
    engines: {node: ^20.19.0 || >=22.12.0}
    hasBin: true
    peerDependencies:
      '@types/node': ^20.19.0 || >=22.12.0
      '@vitejs/devtools': ^0.4.0 || ^0.5.0
      esbuild: ^0.27.0 || ^0.28.0
      jiti: '>=1.21.0'
      less: ^4.0.0
      sass: ^1.70.0
      sass-embedded: ^1.70.0
      stylus: '>=0.54.8'
      sugarss: ^5.0.0
      terser: ^5.16.0
      tsx: ^4.8.1
      yaml: ^2.4.2
    peerDependenciesMeta:
      '@types/node':
        optional: true
      '@vitejs/devtools':
        optional: true
      esbuild:
        optional: true
      jiti:
        optional: true
      less:
        optional: true
      sass:
        optional: true
      sass-embedded:
        optional: true
      stylus:
        optional: true
      sugarss:
        optional: true
      terser:
        optional: true
      tsx:
        optional: true
      yaml:
        optional: true

  vitefu@1.1.3:
    resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==}
    peerDependencies:
      vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
    peerDependenciesMeta:
      vite:
        optional: true

  volar-service-css@0.0.71:
    resolution: {integrity: sha512-wRRFt9BpjMKCazcgOh67MSjUjiWUCAh99DyYSDIOTuxaRjEtDC7PpB0k1Y1wbJIW/pVtMUSVbpPo3UGSm0Byxw==}
    peerDependencies:
      '@volar/language-service': ~2.4.0
    peerDependenciesMeta:
      '@volar/language-service':
        optional: true

  volar-service-emmet@0.0.71:
    resolution: {integrity: sha512-zqjzt6bN95e3CUstBm0PBFAJnrfz0ZAARka87fart46/gNCLLuP3Vujy8V/J8HEziTFLnfkgIASLFYPUhonJcA==}
    peerDependencies:
      '@volar/language-service': ~2.4.0
    peerDependenciesMeta:
      '@volar/language-service':
        optional: true

  volar-service-html@0.0.71:
    resolution: {integrity: sha512-e8tHPhgQ7ooLfudAEIku+kgd9pWkq3SSz8RbnQDI1+Eb8wbenkLGHqoirLqz5ORLV6wIMr2Iv08RWBG5eOcgpw==}
    peerDependencies:
      '@volar/language-service': ~2.4.0
    peerDependenciesMeta:
      '@volar/language-service':
        optional: true

  volar-service-prettier@0.0.71:
    resolution: {integrity: sha512-Rz7JVH3qD108UCdmIEiZvOBNljMt2nLFdbN8AXcDfn7xD9F5I2aCIsDVqBbXw21PsnxG0b7MfwtNF+zPS/NKUg==}
    peerDependencies:
      '@volar/language-service': ~2.4.0
      prettier: ^2.2 || ^3.0
    peerDependenciesMeta:
      '@volar/language-service':
        optional: true
      prettier:
        optional: true

  volar-service-typescript-twoslash-queries@0.0.71:
    resolution: {integrity: sha512-9K2k72s4n7rV9s4bX0MyjbX9iBribvKZbBJKuEmTCZfeWJXs6Yh7bGpY4eoc7UufAjvpheBqwyZCOIPBvxCv0A==}
    peerDependencies:
      '@volar/language-service': ~2.4.0
    peerDependenciesMeta:
      '@volar/language-service':
        optional: true

  volar-service-typescript@0.0.71:
    resolution: {integrity: sha512-yTtM/BVT6hoyEYnDtaCyAtNhdNeS/mhTTABlBOdw3NNiRBUin3IznFJpgfjer4c6RYopiPjjQjc9VFhxVl1mLw==}
    peerDependencies:
      '@volar/language-service': ~2.4.0
    peerDependenciesMeta:
      '@volar/language-service':
        optional: true

  volar-service-yaml@0.0.71:
    resolution: {integrity: sha512-qYGWGuVpUTnZGu5P/CR4KLK4aIR8RrcVnmfZ2eRcj9q/I8VZCoC5yy9FtEvfNvnDp4MU17yhdJcvpQPIqhJS2Q==}
    peerDependencies:
      '@volar/language-service': ~2.4.0
    peerDependenciesMeta:
      '@volar/language-service':
        optional: true

  vscode-css-languageservice@6.3.9:
    resolution: {integrity: sha512-1tLWfp+TDM5ZuVWht3jmaY5y7O6aZmpeXLoHl5bv1QtRsRKt4xYGRMmdJa5Pqx/FTkgRbsna9R+Gn2xE+evVuA==}

  vscode-html-languageservice@5.6.2:
    resolution: {integrity: sha512-ulCrSnFnfQ16YzvwnYUgEbUEl/ZG7u2eV27YhvLObSHKkb8fw1Z9cgsnUwjTEeDIdJDoTDTDpxuhQwoenoLNMg==}

  vscode-json-languageservice@4.1.8:
    resolution: {integrity: sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==}
    engines: {npm: '>=7.0.0'}

  vscode-jsonrpc@8.2.0:
    resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==}
    engines: {node: '>=14.0.0'}

  vscode-languageserver-protocol@3.17.5:
    resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==}

  vscode-languageserver-textdocument@1.0.12:
    resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==}

  vscode-languageserver-types@3.17.5:
    resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==}

  vscode-languageserver@9.0.1:
    resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==}
    hasBin: true

  vscode-nls@5.2.0:
    resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==}

  vscode-uri@3.1.0:
    resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}

  web-namespaces@2.0.1:
    resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}

  wrap-ansi@9.0.2:
    resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
    engines: {node: '>=18'}

  xml-naming@0.3.0:
    resolution: {integrity: sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ==}
    engines: {node: '>=16.0.0'}

  xxhash-wasm@1.1.0:
    resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==}

  y18n@5.0.8:
    resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
    engines: {node: '>=10'}

  yaml-language-server@1.23.0:
    resolution: {integrity: sha512-3qVyCOexLCWw06PQa5kRPwvMWMZ/eZeCRWUvgD6a0OkqL/4iCnxy2WumbWifa937Uo5xhyWJ0uxlU39ljhNh7A==}
    hasBin: true

  yaml@2.8.3:
    resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==}
    engines: {node: '>= 14.6'}
    hasBin: true

  yaml@2.9.0:
    resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==}
    engines: {node: '>= 14.6'}
    hasBin: true

  yargs-parser@22.0.0:
    resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==}
    engines: {node: ^20.19.0 || ^22.12.0 || >=23}

  yargs@18.1.0:
    resolution: {integrity: sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==}
    engines: {node: ^20.19.0 || ^22.12.0 || >=23}

  yocto-queue@1.2.2:
    resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==}
    engines: {node: '>=12.20'}

  zod@4.4.3:
    resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==}

  zwitch@2.0.4:
    resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}

snapshots:

  '@astrojs/check@0.9.10(prettier@3.9.6)(typescript@6.0.3)':
    dependencies:
      '@astrojs/language-server': 2.16.14(prettier@3.9.6)(typescript@6.0.3)
      chokidar: 4.0.3
      kleur: 4.1.5
      typescript: 6.0.3
      yargs: 18.1.0
    transitivePeerDependencies:
      - prettier
      - prettier-plugin-astro

  '@astrojs/compiler-binding-darwin-arm64@0.4.0':
    optional: true

  '@astrojs/compiler-binding-darwin-x64@0.4.0':
    optional: true

  '@astrojs/compiler-binding-linux-arm64-gnu@0.4.0':
    optional: true

  '@astrojs/compiler-binding-linux-arm64-musl@0.4.0':
    optional: true

  '@astrojs/compiler-binding-linux-x64-gnu@0.4.0':
    optional: true

  '@astrojs/compiler-binding-linux-x64-musl@0.4.0':
    optional: true

  '@astrojs/compiler-binding-wasm32-wasi@0.4.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.3)':
    dependencies:
      '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.3)
    transitivePeerDependencies:
      - '@emnapi/core'
      - '@emnapi/runtime'
    optional: true

  '@astrojs/compiler-binding-win32-arm64-msvc@0.4.0':
    optional: true

  '@astrojs/compiler-binding-win32-x64-msvc@0.4.0':
    optional: true

  '@astrojs/compiler-binding@0.4.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.3)':
    optionalDependencies:
      '@astrojs/compiler-binding-darwin-arm64': 0.4.0
      '@astrojs/compiler-binding-darwin-x64': 0.4.0
      '@astrojs/compiler-binding-linux-arm64-gnu': 0.4.0
      '@astrojs/compiler-binding-linux-arm64-musl': 0.4.0
      '@astrojs/compiler-binding-linux-x64-gnu': 0.4.0
      '@astrojs/compiler-binding-linux-x64-musl': 0.4.0
      '@astrojs/compiler-binding-wasm32-wasi': 0.4.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.3)
      '@astrojs/compiler-binding-win32-arm64-msvc': 0.4.0
      '@astrojs/compiler-binding-win32-x64-msvc': 0.4.0
    transitivePeerDependencies:
      - '@emnapi/core'
      - '@emnapi/runtime'

  '@astrojs/compiler-rs@0.4.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.3)':
    dependencies:
      '@astrojs/compiler-binding': 0.4.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.3)
    transitivePeerDependencies:
      - '@emnapi/core'
      - '@emnapi/runtime'

  '@astrojs/compiler@2.13.1': {}

  '@astrojs/internal-helpers@0.10.4':
    dependencies:
      '@types/hast': 3.0.5
      '@types/mdast': 4.0.4
      js-yaml: 4.3.1
      picomatch: 4.0.7
      retext-smartypants: 6.2.0
      shiki: 4.4.3
      smol-toml: 1.6.0
      unified: 11.0.5

  '@astrojs/language-server@2.16.14(prettier@3.9.6)(typescript@6.0.3)':
    dependencies:
      '@astrojs/compiler': 2.13.1
      '@astrojs/yaml2ts': 0.2.4
      '@jridgewell/sourcemap-codec': 1.5.5
      '@volar/kit': 2.4.28(typescript@6.0.3)
      '@volar/language-core': 2.4.28
      '@volar/language-server': 2.4.28
      '@volar/language-service': 2.4.28
      muggle-string: 0.4.1
      tinyglobby: 0.2.17
      volar-service-css: 0.0.71(@volar/language-service@2.4.28)
      volar-service-emmet: 0.0.71(@volar/language-service@2.4.28)
      volar-service-html: 0.0.71(@volar/language-service@2.4.28)
      volar-service-prettier: 0.0.71(@volar/language-service@2.4.28)(prettier@3.9.6)
      volar-service-typescript: 0.0.71(@volar/language-service@2.4.28)
      volar-service-typescript-twoslash-queries: 0.0.71(@volar/language-service@2.4.28)
      volar-service-yaml: 0.0.71(@volar/language-service@2.4.28)
      vscode-html-languageservice: 5.6.2
      vscode-uri: 3.1.0
    optionalDependencies:
      prettier: 3.9.6
    transitivePeerDependencies:
      - typescript

  '@astrojs/markdown-remark@7.2.4':
    dependencies:
      '@astrojs/internal-helpers': 0.10.4
      '@astrojs/prism': 4.0.2
      github-slugger: 2.0.0
      hast-util-from-html: 2.0.3
      hast-util-to-text: 4.0.2
      mdast-util-definitions: 6.0.0
      rehype-raw: 7.0.0
      rehype-stringify: 10.0.1
      remark-gfm: 4.0.1
      remark-parse: 11.0.0
      remark-rehype: 11.1.2
      remark-smartypants: 3.0.3
      unified: 11.0.5
      unist-util-remove-position: 5.0.0
      unist-util-visit: 5.1.0
      unist-util-visit-parents: 6.0.2
      vfile: 6.0.3
    transitivePeerDependencies:
      - supports-color

  '@astrojs/markdown-satteri@0.3.8':
    dependencies:
      '@astrojs/internal-helpers': 0.10.4
      '@astrojs/prism': 4.0.2
      github-slugger: 2.0.0
      satteri: 0.10.5

  '@astrojs/prism@4.0.2':
    dependencies:
      prismjs: 1.30.0

  '@astrojs/rss@4.0.19':
    dependencies:
      fast-xml-parser: 5.11.0
      piccolore: 0.1.3
      zod: 4.4.3

  '@astrojs/sitemap@3.7.3':
    dependencies:
      sitemap: 9.0.1
      stream-replace-string: 2.0.0
      zod: 4.4.3

  '@astrojs/telemetry@3.3.3':
    dependencies:
      ci-info: 4.4.0
      dset: 3.1.4
      is-docker: 4.0.0
      package-manager-detector: 1.6.0

  '@astrojs/yaml2ts@0.2.4':
    dependencies:
      yaml: 2.9.0

  '@babel/helper-string-parser@7.29.7': {}

  '@babel/helper-validator-identifier@7.29.7': {}

  '@babel/parser@7.29.8':
    dependencies:
      '@babel/types': 7.29.8

  '@babel/types@7.29.8':
    dependencies:
      '@babel/helper-string-parser': 7.29.7
      '@babel/helper-validator-identifier': 7.29.7

  '@biomejs/biome@2.5.10':
    optionalDependencies:
      '@biomejs/cli-darwin-arm64': 2.5.10
      '@biomejs/cli-darwin-x64': 2.5.10
      '@biomejs/cli-linux-arm64': 2.5.10
      '@biomejs/cli-linux-arm64-musl': 2.5.10
      '@biomejs/cli-linux-x64': 2.5.10
      '@biomejs/cli-linux-x64-musl': 2.5.10
      '@biomejs/cli-win32-arm64': 2.5.10
      '@biomejs/cli-win32-x64': 2.5.10

  '@biomejs/cli-darwin-arm64@2.5.10':
    optional: true

  '@biomejs/cli-darwin-x64@2.5.10':
    optional: true

  '@biomejs/cli-linux-arm64-musl@2.5.10':
    optional: true

  '@biomejs/cli-linux-arm64@2.5.10':
    optional: true

  '@biomejs/cli-linux-x64-musl@2.5.10':
    optional: true

  '@biomejs/cli-linux-x64@2.5.10':
    optional: true

  '@biomejs/cli-win32-arm64@2.5.10':
    optional: true

  '@biomejs/cli-win32-x64@2.5.10':
    optional: true

  '@bruits/satteri-darwin-arm64@0.10.5':
    optional: true

  '@bruits/satteri-darwin-x64@0.10.5':
    optional: true

  '@bruits/satteri-linux-arm64-gnu@0.10.5':
    optional: true

  '@bruits/satteri-linux-arm64-musl@0.10.5':
    optional: true

  '@bruits/satteri-linux-x64-gnu@0.10.5':
    optional: true

  '@bruits/satteri-linux-x64-musl@0.10.5':
    optional: true

  '@bruits/satteri-wasm32-wasi@0.10.5':
    dependencies:
      '@emnapi/core': 1.11.1
      '@emnapi/runtime': 1.11.1
      '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)
    optional: true

  '@bruits/satteri-win32-arm64-msvc@0.10.5':
    optional: true

  '@bruits/satteri-win32-x64-msvc@0.10.5':
    optional: true

  '@capsizecss/unpack@4.0.0':
    dependencies:
      fontkitten: 1.0.0

  '@clack/core@1.4.3':
    dependencies:
      fast-wrap-ansi: 0.2.2
      sisteransi: 1.0.5

  '@clack/prompts@1.7.0':
    dependencies:
      '@clack/core': 1.4.3
      fast-string-width: 3.0.2
      fast-wrap-ansi: 0.2.2
      sisteransi: 1.0.5

  '@emmetio/abbreviation@2.3.3':
    dependencies:
      '@emmetio/scanner': 1.0.4

  '@emmetio/css-abbreviation@2.1.8':
    dependencies:
      '@emmetio/scanner': 1.0.4

  '@emmetio/css-parser@0.4.1':
    dependencies:
      '@emmetio/stream-reader': 2.2.0
      '@emmetio/stream-reader-utils': 0.1.0

  '@emmetio/html-matcher@1.3.0':
    dependencies:
      '@emmetio/scanner': 1.0.4

  '@emmetio/scanner@1.0.4': {}

  '@emmetio/stream-reader-utils@0.1.0': {}

  '@emmetio/stream-reader@2.2.0': {}

  '@emnapi/core@1.11.1':
    dependencies:
      '@emnapi/wasi-threads': 1.2.2
      tslib: 2.8.1
    optional: true

  '@emnapi/runtime@1.11.1':
    dependencies:
      tslib: 2.8.1
    optional: true

  '@emnapi/runtime@1.11.3':
    dependencies:
      tslib: 2.8.1
    optional: true

  '@emnapi/wasi-threads@1.2.2':
    dependencies:
      tslib: 2.8.1
    optional: true

  '@esbuild/aix-ppc64@0.28.2':
    optional: true

  '@esbuild/android-arm64@0.28.2':
    optional: true

  '@esbuild/android-arm@0.28.2':
    optional: true

  '@esbuild/android-x64@0.28.2':
    optional: true

  '@esbuild/darwin-arm64@0.28.2':
    optional: true

  '@esbuild/darwin-x64@0.28.2':
    optional: true

  '@esbuild/freebsd-arm64@0.28.2':
    optional: true

  '@esbuild/freebsd-x64@0.28.2':
    optional: true

  '@esbuild/linux-arm64@0.28.2':
    optional: true

  '@esbuild/linux-arm@0.28.2':
    optional: true

  '@esbuild/linux-ia32@0.28.2':
    optional: true

  '@esbuild/linux-loong64@0.28.2':
    optional: true

  '@esbuild/linux-mips64el@0.28.2':
    optional: true

  '@esbuild/linux-ppc64@0.28.2':
    optional: true

  '@esbuild/linux-riscv64@0.28.2':
    optional: true

  '@esbuild/linux-s390x@0.28.2':
    optional: true

  '@esbuild/linux-x64@0.28.2':
    optional: true

  '@esbuild/netbsd-arm64@0.28.2':
    optional: true

  '@esbuild/netbsd-x64@0.28.2':
    optional: true

  '@esbuild/openbsd-arm64@0.28.2':
    optional: true

  '@esbuild/openbsd-x64@0.28.2':
    optional: true

  '@esbuild/openharmony-arm64@0.28.2':
    optional: true

  '@esbuild/sunos-x64@0.28.2':
    optional: true

  '@esbuild/win32-arm64@0.28.2':
    optional: true

  '@esbuild/win32-ia32@0.28.2':
    optional: true

  '@esbuild/win32-x64@0.28.2':
    optional: true

  '@img/colour@1.1.0': {}

  '@img/sharp-darwin-arm64@0.35.3':
    optionalDependencies:
      '@img/sharp-libvips-darwin-arm64': 1.3.2
    optional: true

  '@img/sharp-darwin-x64@0.35.3':
    optionalDependencies:
      '@img/sharp-libvips-darwin-x64': 1.3.2
    optional: true

  '@img/sharp-freebsd-wasm32@0.35.3':
    dependencies:
      '@img/sharp-wasm32': 0.35.3
    optional: true

  '@img/sharp-libvips-darwin-arm64@1.3.2':
    optional: true

  '@img/sharp-libvips-darwin-x64@1.3.2':
    optional: true

  '@img/sharp-libvips-linux-arm64@1.3.2':
    optional: true

  '@img/sharp-libvips-linux-arm@1.3.2':
    optional: true

  '@img/sharp-libvips-linux-ppc64@1.3.2':
    optional: true

  '@img/sharp-libvips-linux-riscv64@1.3.2':
    optional: true

  '@img/sharp-libvips-linux-s390x@1.3.2':
    optional: true

  '@img/sharp-libvips-linux-x64@1.3.2':
    optional: true

  '@img/sharp-libvips-linuxmusl-arm64@1.3.2':
    optional: true

  '@img/sharp-libvips-linuxmusl-x64@1.3.2':
    optional: true

  '@img/sharp-linux-arm64@0.35.3':
    optionalDependencies:
      '@img/sharp-libvips-linux-arm64': 1.3.2
    optional: true

  '@img/sharp-linux-arm@0.35.3':
    optionalDependencies:
      '@img/sharp-libvips-linux-arm': 1.3.2
    optional: true

  '@img/sharp-linux-ppc64@0.35.3':
    optionalDependencies:
      '@img/sharp-libvips-linux-ppc64': 1.3.2
    optional: true

  '@img/sharp-linux-riscv64@0.35.3':
    optionalDependencies:
      '@img/sharp-libvips-linux-riscv64': 1.3.2
    optional: true

  '@img/sharp-linux-s390x@0.35.3':
    optionalDependencies:
      '@img/sharp-libvips-linux-s390x': 1.3.2
    optional: true

  '@img/sharp-linux-x64@0.35.3':
    optionalDependencies:
      '@img/sharp-libvips-linux-x64': 1.3.2
    optional: true

  '@img/sharp-linuxmusl-arm64@0.35.3':
    optionalDependencies:
      '@img/sharp-libvips-linuxmusl-arm64': 1.3.2
    optional: true

  '@img/sharp-linuxmusl-x64@0.35.3':
    optionalDependencies:
      '@img/sharp-libvips-linuxmusl-x64': 1.3.2
    optional: true

  '@img/sharp-wasm32@0.35.3':
    dependencies:
      '@emnapi/runtime': 1.11.3
    optional: true

  '@img/sharp-webcontainers-wasm32@0.35.3':
    dependencies:
      '@img/sharp-wasm32': 0.35.3
    optional: true

  '@img/sharp-win32-arm64@0.35.3':
    optional: true

  '@img/sharp-win32-ia32@0.35.3':
    optional: true

  '@img/sharp-win32-x64@0.35.3':
    optional: true

  '@jridgewell/gen-mapping@0.3.13':
    dependencies:
      '@jridgewell/sourcemap-codec': 1.5.5
      '@jridgewell/trace-mapping': 0.3.31

  '@jridgewell/remapping@2.3.5':
    dependencies:
      '@jridgewell/gen-mapping': 0.3.13
      '@jridgewell/trace-mapping': 0.3.31

  '@jridgewell/resolve-uri@3.1.2': {}

  '@jridgewell/sourcemap-codec@1.5.5': {}

  '@jridgewell/trace-mapping@0.3.31':
    dependencies:
      '@jridgewell/resolve-uri': 3.1.2
      '@jridgewell/sourcemap-codec': 1.5.5

  '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)':
    dependencies:
      '@emnapi/core': 1.11.1
      '@emnapi/runtime': 1.11.1
      '@tybys/wasm-util': 0.10.3
    optional: true

  '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.3)':
    dependencies:
      '@emnapi/core': 1.11.1
      '@emnapi/runtime': 1.11.3
      '@tybys/wasm-util': 0.10.3
    optional: true

  '@nodable/entities@3.0.0': {}

  '@oslojs/encoding@1.1.0': {}

  '@oxc-project/types@0.146.0': {}

  '@rolldown/binding-android-arm-eabi@1.2.5':
    optional: true

  '@rolldown/binding-android-arm64@1.2.5':
    optional: true

  '@rolldown/binding-darwin-arm64@1.2.5':
    optional: true

  '@rolldown/binding-darwin-x64@1.2.5':
    optional: true

  '@rolldown/binding-freebsd-x64@1.2.5':
    optional: true

  '@rolldown/binding-linux-arm-gnueabihf@1.2.5':
    optional: true

  '@rolldown/binding-linux-arm64-gnu@1.2.5':
    optional: true

  '@rolldown/binding-linux-arm64-musl@1.2.5':
    optional: true

  '@rolldown/binding-linux-ppc64-gnu@1.2.5':
    optional: true

  '@rolldown/binding-linux-s390x-gnu@1.2.5':
    optional: true

  '@rolldown/binding-linux-x64-gnu@1.2.5':
    optional: true

  '@rolldown/binding-linux-x64-musl@1.2.5':
    optional: true

  '@rolldown/binding-openharmony-arm64@1.2.5':
    optional: true

  '@rolldown/binding-win32-arm64-msvc@1.2.5':
    optional: true

  '@rolldown/binding-win32-x64-msvc@1.2.5':
    optional: true

  '@rolldown/pluginutils@1.0.1': {}

  '@shikijs/core@4.4.3':
    dependencies:
      '@shikijs/primitive': 4.4.3
      '@shikijs/types': 4.4.3
      '@shikijs/vscode-textmate': 10.0.2
      '@types/hast': 3.0.5
      hast-util-to-html: 9.0.5

  '@shikijs/engine-javascript@4.4.3':
    dependencies:
      '@shikijs/types': 4.4.3
      '@shikijs/vscode-textmate': 10.0.2
      oniguruma-to-es: 4.3.6

  '@shikijs/engine-oniguruma@4.4.3':
    dependencies:
      '@shikijs/types': 4.4.3
      '@shikijs/vscode-textmate': 10.0.2

  '@shikijs/langs@4.4.3':
    dependencies:
      '@shikijs/types': 4.4.3

  '@shikijs/primitive@4.4.3':
    dependencies:
      '@shikijs/types': 4.4.3
      '@shikijs/vscode-textmate': 10.0.2
      '@types/hast': 3.0.5

  '@shikijs/themes@4.4.3':
    dependencies:
      '@shikijs/types': 4.4.3

  '@shikijs/types@4.4.3':
    dependencies:
      '@shikijs/vscode-textmate': 10.0.2
      '@types/hast': 3.0.5

  '@shikijs/vscode-textmate@10.0.2': {}

  '@tailwindcss/node@4.3.3':
    dependencies:
      '@jridgewell/remapping': 2.3.5
      enhanced-resolve: 5.24.5
      jiti: 2.7.0
      lightningcss: 1.32.0
      magic-string: 0.30.21
      source-map-js: 1.2.1
      tailwindcss: 4.3.3

  '@tailwindcss/oxide-android-arm64@4.3.3':
    optional: true

  '@tailwindcss/oxide-darwin-arm64@4.3.3':
    optional: true

  '@tailwindcss/oxide-darwin-x64@4.3.3':
    optional: true

  '@tailwindcss/oxide-freebsd-x64@4.3.3':
    optional: true

  '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
    optional: true

  '@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
    optional: true

  '@tailwindcss/oxide-linux-arm64-musl@4.3.3':
    optional: true

  '@tailwindcss/oxide-linux-x64-gnu@4.3.3':
    optional: true

  '@tailwindcss/oxide-linux-x64-musl@4.3.3':
    optional: true

  '@tailwindcss/oxide-wasm32-wasi@4.3.3':
    optional: true

  '@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
    optional: true

  '@tailwindcss/oxide-win32-x64-msvc@4.3.3':
    optional: true

  '@tailwindcss/oxide@4.3.3':
    optionalDependencies:
      '@tailwindcss/oxide-android-arm64': 4.3.3
      '@tailwindcss/oxide-darwin-arm64': 4.3.3
      '@tailwindcss/oxide-darwin-x64': 4.3.3
      '@tailwindcss/oxide-freebsd-x64': 4.3.3
      '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3
      '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3
      '@tailwindcss/oxide-linux-arm64-musl': 4.3.3
      '@tailwindcss/oxide-linux-x64-gnu': 4.3.3
      '@tailwindcss/oxide-linux-x64-musl': 4.3.3
      '@tailwindcss/oxide-wasm32-wasi': 4.3.3
      '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3
      '@tailwindcss/oxide-win32-x64-msvc': 4.3.3

  '@tailwindcss/typography@0.5.20(tailwindcss@4.3.3)':
    dependencies:
      postcss-selector-parser: 6.0.10
      tailwindcss: 4.3.3

  '@tailwindcss/vite@4.3.3(vite@8.2.2(@types/node@24.10.1)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))':
    dependencies:
      '@tailwindcss/node': 4.3.3
      '@tailwindcss/oxide': 4.3.3
      tailwindcss: 4.3.3
      vite: 8.2.2(@types/node@24.10.1)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)

  '@tybys/wasm-util@0.10.3':
    dependencies:
      tslib: 2.8.1
    optional: true

  '@types/debug@4.1.13':
    dependencies:
      '@types/ms': 2.1.0

  '@types/estree-jsx@1.0.5':
    dependencies:
      '@types/estree': 1.0.8

  '@types/estree@1.0.8': {}

  '@types/hast@3.0.5':
    dependencies:
      '@types/unist': 3.0.3

  '@types/mdast@4.0.4':
    dependencies:
      '@types/unist': 3.0.3

  '@types/ms@2.1.0': {}

  '@types/nlcst@2.0.3':
    dependencies:
      '@types/unist': 3.0.3

  '@types/node@24.10.1':
    dependencies:
      undici-types: 7.16.0

  '@types/sax@1.2.7':
    dependencies:
      '@types/node': 24.10.1

  '@types/unist@3.0.3': {}

  '@ungap/structured-clone@1.3.0': {}

  '@volar/kit@2.4.28(typescript@6.0.3)':
    dependencies:
      '@volar/language-service': 2.4.28
      '@volar/typescript': 2.4.28
      typesafe-path: 0.2.2
      typescript: 6.0.3
      vscode-languageserver-textdocument: 1.0.12
      vscode-uri: 3.1.0

  '@volar/language-core@2.4.28':
    dependencies:
      '@volar/source-map': 2.4.28

  '@volar/language-server@2.4.28':
    dependencies:
      '@volar/language-core': 2.4.28
      '@volar/language-service': 2.4.28
      '@volar/typescript': 2.4.28
      path-browserify: 1.0.1
      request-light: 0.7.0
      vscode-languageserver: 9.0.1
      vscode-languageserver-protocol: 3.17.5
      vscode-languageserver-textdocument: 1.0.12
      vscode-uri: 3.1.0

  '@volar/language-service@2.4.28':
    dependencies:
      '@volar/language-core': 2.4.28
      vscode-languageserver-protocol: 3.17.5
      vscode-languageserver-textdocument: 1.0.12
      vscode-uri: 3.1.0

  '@volar/source-map@2.4.28': {}

  '@volar/typescript@2.4.28':
    dependencies:
      '@volar/language-core': 2.4.28
      path-browserify: 1.0.1
      vscode-uri: 3.1.0

  '@vscode/emmet-helper@2.11.0':
    dependencies:
      emmet: 2.4.11
      jsonc-parser: 2.3.1
      vscode-languageserver-textdocument: 1.0.12
      vscode-languageserver-types: 3.17.5
      vscode-uri: 3.1.0

  '@vscode/l10n@0.0.18': {}

  ajv-draft-04@1.0.0(ajv@8.17.1):
    optionalDependencies:
      ajv: 8.17.1

  ajv-i18n@4.2.0(ajv@8.17.1):
    dependencies:
      ajv: 8.17.1

  ajv@8.17.1:
    dependencies:
      fast-deep-equal: 3.1.3
      fast-uri: 3.1.0
      json-schema-traverse: 1.0.0
      require-from-string: 2.0.2

  am-i-vibing@0.4.0:
    dependencies:
      process-ancestry: 0.1.0

  ansi-regex@6.2.2: {}

  ansi-styles@4.3.0:
    dependencies:
      color-convert: 2.0.1

  ansi-styles@6.2.3: {}

  anymatch@3.1.3:
    dependencies:
      normalize-path: 3.0.0
      picomatch: 2.3.1

  anynum@1.0.1: {}

  arg@5.0.2: {}

  argparse@2.0.1: {}

  aria-query@5.3.2: {}

  array-iterate@2.0.1: {}

  astro@7.2.6(@astrojs/markdown-remark@7.2.4)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.3)(@types/node@24.10.1)(jiti@2.7.0)(yaml@2.9.0):
    dependencies:
      '@astrojs/compiler-rs': 0.4.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.3)
      '@astrojs/internal-helpers': 0.10.4
      '@astrojs/markdown-satteri': 0.3.8
      '@astrojs/telemetry': 3.3.3
      '@capsizecss/unpack': 4.0.0
      '@clack/prompts': 1.7.0
      '@oslojs/encoding': 1.1.0
      am-i-vibing: 0.4.0
      aria-query: 5.3.2
      axobject-query: 4.1.0
      ci-info: 4.4.0
      clsx: 2.1.1
      common-ancestor-path: 2.0.0
      cookie: 2.0.1
      devalue: 5.9.1
      diff: 9.0.0
      dset: 3.1.4
      es-module-lexer: 2.3.2
      esbuild: 0.28.2
      find-process: 2.1.1
      flattie: 1.1.1
      fontace: 0.4.1
      get-tsconfig: 5.0.0-beta.4
      github-slugger: 2.0.0
      html-escaper: 3.0.3
      http-cache-semantics: 4.2.0
      js-yaml: 4.3.1
      jsonc-parser: 3.3.1
      magic-string: 1.2.2
      magicast: 0.5.4
      mrmime: 2.0.1
      neotraverse: 1.0.1
      obug: 2.1.4
      p-limit: 7.3.1
      p-queue: 9.3.3
      package-manager-detector: 1.6.0
      piccolore: 0.1.3
      picomatch: 4.0.7
      semver: 7.8.5
      shiki: 4.4.3
      smol-toml: 1.6.0
      svgo: 4.1.0
      tinyclip: 0.1.15
      tinyexec: 1.3.0
      tinyglobby: 0.2.15
      ultrahtml: 1.6.0
      unifont: 0.7.5
      unstorage: 1.17.5
      vite: 8.2.2(@types/node@24.10.1)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)
      vitefu: 1.1.3(vite@8.2.2(@types/node@24.10.1)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))
      xxhash-wasm: 1.1.0
      yargs-parser: 22.0.0
      zod: 4.4.3
    optionalDependencies:
      '@astrojs/markdown-remark': 7.2.4
      sharp: 0.35.3(@types/node@24.10.1)
    transitivePeerDependencies:
      - '@azure/app-configuration'
      - '@azure/cosmos'
      - '@azure/data-tables'
      - '@azure/identity'
      - '@azure/keyvault-secrets'
      - '@azure/storage-blob'
      - '@capacitor/preferences'
      - '@deno/kv'
      - '@emnapi/core'
      - '@emnapi/runtime'
      - '@netlify/blobs'
      - '@planetscale/database'
      - '@types/node'
      - '@upstash/redis'
      - '@vercel/blob'
      - '@vercel/functions'
      - '@vercel/kv'
      - '@vitejs/devtools'
      - aws4fetch
      - db0
      - idb-keyval
      - ioredis
      - jiti
      - less
      - sass
      - sass-embedded
      - stylus
      - sugarss
      - terser
      - tsx
      - uploadthing
      - yaml

  axobject-query@4.1.0: {}

  bail@2.0.2: {}

  boolbase@1.0.0: {}

  ccount@2.0.1: {}

  chalk@4.1.2:
    dependencies:
      ansi-styles: 4.3.0
      supports-color: 7.2.0

  character-entities-html4@2.1.0: {}

  character-entities-legacy@3.0.0: {}

  character-entities@2.0.2: {}

  chokidar@4.0.3:
    dependencies:
      readdirp: 4.1.2

  chokidar@5.0.0:
    dependencies:
      readdirp: 5.1.1

  ci-info@4.4.0: {}

  cliui@9.0.1:
    dependencies:
      string-width: 7.2.0
      strip-ansi: 7.1.2
      wrap-ansi: 9.0.2

  clsx@2.1.1: {}

  color-convert@2.0.1:
    dependencies:
      color-name: 1.1.4

  color-name@1.1.4: {}

  comma-separated-tokens@2.0.3: {}

  commander@11.1.0: {}

  commander@14.0.3: {}

  common-ancestor-path@2.0.0: {}

  cookie-es@1.2.3: {}

  cookie@2.0.1: {}

  crossws@0.3.5:
    dependencies:
      uncrypto: 0.1.3

  css-select@6.0.0:
    dependencies:
      boolbase: 1.0.0
      css-what: 7.0.0
      domhandler: 5.0.3
      domutils: 3.2.2
      nth-check: 2.1.1

  css-tree@2.2.1:
    dependencies:
      mdn-data: 2.0.28
      source-map-js: 1.2.1

  css-tree@3.1.0:
    dependencies:
      mdn-data: 2.12.2
      source-map-js: 1.2.1

  css-what@7.0.0: {}

  cssesc@3.0.0: {}

  csso@5.0.5:
    dependencies:
      css-tree: 2.2.1

  debug@4.4.3:
    dependencies:
      ms: 2.1.3

  decode-named-character-reference@1.3.0:
    dependencies:
      character-entities: 2.0.2

  defu@6.1.7: {}

  dequal@2.0.3: {}

  destr@2.0.5: {}

  detect-libc@2.1.2: {}

  devalue@5.9.1: {}

  devlop@1.1.0:
    dependencies:
      dequal: 2.0.3

  diff@9.0.0: {}

  dom-serializer@2.0.0:
    dependencies:
      domelementtype: 2.3.0
      domhandler: 5.0.3
      entities: 4.5.0

  domelementtype@2.3.0: {}

  domhandler@5.0.3:
    dependencies:
      domelementtype: 2.3.0

  domutils@3.2.2:
    dependencies:
      dom-serializer: 2.0.0
      domelementtype: 2.3.0
      domhandler: 5.0.3

  dset@3.1.4: {}

  emmet@2.4.11:
    dependencies:
      '@emmetio/abbreviation': 2.3.3
      '@emmetio/css-abbreviation': 2.1.8

  emoji-regex@10.6.0: {}

  enhanced-resolve@5.24.5:
    dependencies:
      graceful-fs: 4.2.11
      tapable: 2.3.3

  entities@4.5.0: {}

  entities@6.0.1: {}

  es-module-lexer@2.3.2: {}

  esbuild@0.28.2:
    optionalDependencies:
      '@esbuild/aix-ppc64': 0.28.2
      '@esbuild/android-arm': 0.28.2
      '@esbuild/android-arm64': 0.28.2
      '@esbuild/android-x64': 0.28.2
      '@esbuild/darwin-arm64': 0.28.2
      '@esbuild/darwin-x64': 0.28.2
      '@esbuild/freebsd-arm64': 0.28.2
      '@esbuild/freebsd-x64': 0.28.2
      '@esbuild/linux-arm': 0.28.2
      '@esbuild/linux-arm64': 0.28.2
      '@esbuild/linux-ia32': 0.28.2
      '@esbuild/linux-loong64': 0.28.2
      '@esbuild/linux-mips64el': 0.28.2
      '@esbuild/linux-ppc64': 0.28.2
      '@esbuild/linux-riscv64': 0.28.2
      '@esbuild/linux-s390x': 0.28.2
      '@esbuild/linux-x64': 0.28.2
      '@esbuild/netbsd-arm64': 0.28.2
      '@esbuild/netbsd-x64': 0.28.2
      '@esbuild/openbsd-arm64': 0.28.2
      '@esbuild/openbsd-x64': 0.28.2
      '@esbuild/openharmony-arm64': 0.28.2
      '@esbuild/sunos-x64': 0.28.2
      '@esbuild/win32-arm64': 0.28.2
      '@esbuild/win32-ia32': 0.28.2
      '@esbuild/win32-x64': 0.28.2

  escalade@3.2.0: {}

  escape-string-regexp@5.0.0: {}

  eventemitter3@5.0.4: {}

  extend@3.0.2: {}

  fast-deep-equal@3.1.3: {}

  fast-string-truncated-width@3.0.3: {}

  fast-string-width@3.0.2:
    dependencies:
      fast-string-truncated-width: 3.0.3

  fast-uri@3.1.0: {}

  fast-wrap-ansi@0.2.2:
    dependencies:
      fast-string-width: 3.0.2

  fast-xml-builder@1.3.1:
    dependencies:
      path-expression-matcher: 1.6.2
      xml-naming: 0.3.0

  fast-xml-parser@5.11.0:
    dependencies:
      '@nodable/entities': 3.0.0
      fast-xml-builder: 1.3.1
      is-unsafe: 2.0.2
      path-expression-matcher: 1.6.2
      strnum: 2.4.2
      xml-naming: 0.3.0

  fdir@6.5.0(picomatch@4.0.7):
    optionalDependencies:
      picomatch: 4.0.7

  find-process@2.1.1:
    dependencies:
      chalk: 4.1.2
      commander: 14.0.3
      loglevel: 1.9.2

  flattie@1.1.1: {}

  fontace@0.4.1:
    dependencies:
      fontkitten: 1.0.3

  fontkitten@1.0.0:
    dependencies:
      tiny-inflate: 1.0.3

  fontkitten@1.0.3:
    dependencies:
      tiny-inflate: 1.0.3

  fsevents@2.3.3:
    optional: true

  get-caller-file@2.0.5: {}

  get-east-asian-width@1.4.0: {}

  get-east-asian-width@1.6.0: {}

  get-tsconfig@5.0.0-beta.4:
    dependencies:
      resolve-pkg-maps: 1.0.0

  github-slugger@2.0.0: {}

  graceful-fs@4.2.11: {}

  h3@1.15.11:
    dependencies:
      cookie-es: 1.2.3
      crossws: 0.3.5
      defu: 6.1.7
      destr: 2.0.5
      iron-webcrypto: 1.2.1
      node-mock-http: 1.0.4
      radix3: 1.1.2
      ufo: 1.6.4
      uncrypto: 0.1.3

  has-flag@4.0.0: {}

  hast-util-from-html@2.0.3:
    dependencies:
      '@types/hast': 3.0.5
      devlop: 1.1.0
      hast-util-from-parse5: 8.0.3
      parse5: 7.3.0
      vfile: 6.0.3
      vfile-message: 4.0.3

  hast-util-from-parse5@8.0.3:
    dependencies:
      '@types/hast': 3.0.5
      '@types/unist': 3.0.3
      devlop: 1.1.0
      hastscript: 9.0.1
      property-information: 7.1.0
      vfile: 6.0.3
      vfile-location: 5.0.3
      web-namespaces: 2.0.1

  hast-util-heading-rank@3.0.0:
    dependencies:
      '@types/hast': 3.0.5

  hast-util-is-element@3.0.0:
    dependencies:
      '@types/hast': 3.0.5

  hast-util-parse-selector@4.0.0:
    dependencies:
      '@types/hast': 3.0.5

  hast-util-raw@9.1.0:
    dependencies:
      '@types/hast': 3.0.5
      '@types/unist': 3.0.3
      '@ungap/structured-clone': 1.3.0
      hast-util-from-parse5: 8.0.3
      hast-util-to-parse5: 8.0.1
      html-void-elements: 3.0.0
      mdast-util-to-hast: 13.2.1
      parse5: 7.3.0
      unist-util-position: 5.0.0
      unist-util-visit: 5.1.0
      vfile: 6.0.3
      web-namespaces: 2.0.1
      zwitch: 2.0.4

  hast-util-to-html@9.0.5:
    dependencies:
      '@types/hast': 3.0.5
      '@types/unist': 3.0.3
      ccount: 2.0.1
      comma-separated-tokens: 2.0.3
      hast-util-whitespace: 3.0.0
      html-void-elements: 3.0.0
      mdast-util-to-hast: 13.2.1
      property-information: 7.1.0
      space-separated-tokens: 2.0.2
      stringify-entities: 4.0.4
      zwitch: 2.0.4

  hast-util-to-parse5@8.0.1:
    dependencies:
      '@types/hast': 3.0.5
      comma-separated-tokens: 2.0.3
      devlop: 1.1.0
      property-information: 7.1.0
      space-separated-tokens: 2.0.2
      web-namespaces: 2.0.1
      zwitch: 2.0.4

  hast-util-to-string@3.0.1:
    dependencies:
      '@types/hast': 3.0.5

  hast-util-to-text@4.0.2:
    dependencies:
      '@types/hast': 3.0.5
      '@types/unist': 3.0.3
      hast-util-is-element: 3.0.0
      unist-util-find-after: 5.0.0

  hast-util-whitespace@3.0.0:
    dependencies:
      '@types/hast': 3.0.5

  hastscript@9.0.1:
    dependencies:
      '@types/hast': 3.0.5
      comma-separated-tokens: 2.0.3
      hast-util-parse-selector: 4.0.0
      property-information: 7.1.0
      space-separated-tokens: 2.0.2

  html-escaper@3.0.3: {}

  html-void-elements@3.0.0: {}

  http-cache-semantics@4.2.0: {}

  iron-webcrypto@1.2.1: {}

  is-docker@4.0.0: {}

  is-plain-obj@4.1.0: {}

  is-unsafe@2.0.2: {}

  jiti@2.7.0: {}

  js-yaml@4.3.1:
    dependencies:
      argparse: 2.0.1

  json-schema-traverse@1.0.0: {}

  jsonc-parser@2.3.1: {}

  jsonc-parser@3.3.1: {}

  kleur@4.1.5: {}

  lightningcss-android-arm64@1.32.0:
    optional: true

  lightningcss-android-arm64@1.33.0:
    optional: true

  lightningcss-darwin-arm64@1.32.0:
    optional: true

  lightningcss-darwin-arm64@1.33.0:
    optional: true

  lightningcss-darwin-x64@1.32.0:
    optional: true

  lightningcss-darwin-x64@1.33.0:
    optional: true

  lightningcss-freebsd-x64@1.32.0:
    optional: true

  lightningcss-freebsd-x64@1.33.0:
    optional: true

  lightningcss-linux-arm-gnueabihf@1.32.0:
    optional: true

  lightningcss-linux-arm-gnueabihf@1.33.0:
    optional: true

  lightningcss-linux-arm64-gnu@1.32.0:
    optional: true

  lightningcss-linux-arm64-gnu@1.33.0:
    optional: true

  lightningcss-linux-arm64-musl@1.32.0:
    optional: true

  lightningcss-linux-arm64-musl@1.33.0:
    optional: true

  lightningcss-linux-x64-gnu@1.32.0:
    optional: true

  lightningcss-linux-x64-gnu@1.33.0:
    optional: true

  lightningcss-linux-x64-musl@1.32.0:
    optional: true

  lightningcss-linux-x64-musl@1.33.0:
    optional: true

  lightningcss-win32-arm64-msvc@1.32.0:
    optional: true

  lightningcss-win32-arm64-msvc@1.33.0:
    optional: true

  lightningcss-win32-x64-msvc@1.32.0:
    optional: true

  lightningcss-win32-x64-msvc@1.33.0:
    optional: true

  lightningcss@1.32.0:
    dependencies:
      detect-libc: 2.1.2
    optionalDependencies:
      lightningcss-android-arm64: 1.32.0
      lightningcss-darwin-arm64: 1.32.0
      lightningcss-darwin-x64: 1.32.0
      lightningcss-freebsd-x64: 1.32.0
      lightningcss-linux-arm-gnueabihf: 1.32.0
      lightningcss-linux-arm64-gnu: 1.32.0
      lightningcss-linux-arm64-musl: 1.32.0
      lightningcss-linux-x64-gnu: 1.32.0
      lightningcss-linux-x64-musl: 1.32.0
      lightningcss-win32-arm64-msvc: 1.32.0
      lightningcss-win32-x64-msvc: 1.32.0

  lightningcss@1.33.0:
    dependencies:
      detect-libc: 2.1.2
    optionalDependencies:
      lightningcss-android-arm64: 1.33.0
      lightningcss-darwin-arm64: 1.33.0
      lightningcss-darwin-x64: 1.33.0
      lightningcss-freebsd-x64: 1.33.0
      lightningcss-linux-arm-gnueabihf: 1.33.0
      lightningcss-linux-arm64-gnu: 1.33.0
      lightningcss-linux-arm64-musl: 1.33.0
      lightningcss-linux-x64-gnu: 1.33.0
      lightningcss-linux-x64-musl: 1.33.0
      lightningcss-win32-arm64-msvc: 1.33.0
      lightningcss-win32-x64-msvc: 1.33.0

  loglevel@1.9.2: {}

  longest-streak@3.1.0: {}

  lru-cache@11.5.2: {}

  magic-string@0.30.21:
    dependencies:
      '@jridgewell/sourcemap-codec': 1.5.5

  magic-string@1.2.2:
    dependencies:
      '@jridgewell/sourcemap-codec': 1.5.5

  magicast@0.5.4:
    dependencies:
      '@babel/parser': 7.29.8
      '@babel/types': 7.29.8
      source-map-js: 1.2.1

  markdown-table@3.0.4: {}

  mdast-util-definitions@6.0.0:
    dependencies:
      '@types/mdast': 4.0.4
      '@types/unist': 3.0.3
      unist-util-visit: 5.1.0

  mdast-util-find-and-replace@3.0.2:
    dependencies:
      '@types/mdast': 4.0.4
      escape-string-regexp: 5.0.0
      unist-util-is: 6.0.1
      unist-util-visit-parents: 6.0.2

  mdast-util-from-markdown@2.0.3:
    dependencies:
      '@types/mdast': 4.0.4
      '@types/unist': 3.0.3
      decode-named-character-reference: 1.3.0
      devlop: 1.1.0
      mdast-util-to-string: 4.0.0
      micromark: 4.0.2
      micromark-util-decode-numeric-character-reference: 2.0.2
      micromark-util-decode-string: 2.0.1
      micromark-util-normalize-identifier: 2.0.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2
      unist-util-stringify-position: 4.0.0
    transitivePeerDependencies:
      - supports-color

  mdast-util-gfm-autolink-literal@2.0.1:
    dependencies:
      '@types/mdast': 4.0.4
      ccount: 2.0.1
      devlop: 1.1.0
      mdast-util-find-and-replace: 3.0.2
      micromark-util-character: 2.1.1

  mdast-util-gfm-footnote@2.1.0:
    dependencies:
      '@types/mdast': 4.0.4
      devlop: 1.1.0
      mdast-util-from-markdown: 2.0.3
      mdast-util-to-markdown: 2.1.2
      micromark-util-normalize-identifier: 2.0.1
    transitivePeerDependencies:
      - supports-color

  mdast-util-gfm-strikethrough@2.0.0:
    dependencies:
      '@types/mdast': 4.0.4
      mdast-util-from-markdown: 2.0.3
      mdast-util-to-markdown: 2.1.2
    transitivePeerDependencies:
      - supports-color

  mdast-util-gfm-table@2.0.0:
    dependencies:
      '@types/mdast': 4.0.4
      devlop: 1.1.0
      markdown-table: 3.0.4
      mdast-util-from-markdown: 2.0.3
      mdast-util-to-markdown: 2.1.2
    transitivePeerDependencies:
      - supports-color

  mdast-util-gfm-task-list-item@2.0.0:
    dependencies:
      '@types/mdast': 4.0.4
      devlop: 1.1.0
      mdast-util-from-markdown: 2.0.3
      mdast-util-to-markdown: 2.1.2
    transitivePeerDependencies:
      - supports-color

  mdast-util-gfm@3.1.0:
    dependencies:
      mdast-util-from-markdown: 2.0.3
      mdast-util-gfm-autolink-literal: 2.0.1
      mdast-util-gfm-footnote: 2.1.0
      mdast-util-gfm-strikethrough: 2.0.0
      mdast-util-gfm-table: 2.0.0
      mdast-util-gfm-task-list-item: 2.0.0
      mdast-util-to-markdown: 2.1.2
    transitivePeerDependencies:
      - supports-color

  mdast-util-phrasing@4.1.0:
    dependencies:
      '@types/mdast': 4.0.4
      unist-util-is: 6.0.1

  mdast-util-to-hast@13.2.1:
    dependencies:
      '@types/hast': 3.0.5
      '@types/mdast': 4.0.4
      '@ungap/structured-clone': 1.3.0
      devlop: 1.1.0
      micromark-util-sanitize-uri: 2.0.1
      trim-lines: 3.0.1
      unist-util-position: 5.0.0
      unist-util-visit: 5.0.0
      vfile: 6.0.3

  mdast-util-to-markdown@2.1.2:
    dependencies:
      '@types/mdast': 4.0.4
      '@types/unist': 3.0.3
      longest-streak: 3.1.0
      mdast-util-phrasing: 4.1.0
      mdast-util-to-string: 4.0.0
      micromark-util-classify-character: 2.0.1
      micromark-util-decode-string: 2.0.1
      unist-util-visit: 5.1.0
      zwitch: 2.0.4

  mdast-util-to-string@4.0.0:
    dependencies:
      '@types/mdast': 4.0.4

  mdn-data@2.0.28: {}

  mdn-data@2.12.2: {}

  micromark-core-commonmark@2.0.3:
    dependencies:
      decode-named-character-reference: 1.3.0
      devlop: 1.1.0
      micromark-factory-destination: 2.0.1
      micromark-factory-label: 2.0.1
      micromark-factory-space: 2.0.1
      micromark-factory-title: 2.0.1
      micromark-factory-whitespace: 2.0.1
      micromark-util-character: 2.1.1
      micromark-util-chunked: 2.0.1
      micromark-util-classify-character: 2.0.1
      micromark-util-html-tag-name: 2.0.1
      micromark-util-normalize-identifier: 2.0.1
      micromark-util-resolve-all: 2.0.1
      micromark-util-subtokenize: 2.1.0
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-extension-gfm-autolink-literal@2.1.0:
    dependencies:
      micromark-util-character: 2.1.1
      micromark-util-sanitize-uri: 2.0.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-extension-gfm-footnote@2.1.0:
    dependencies:
      devlop: 1.1.0
      micromark-core-commonmark: 2.0.3
      micromark-factory-space: 2.0.1
      micromark-util-character: 2.1.1
      micromark-util-normalize-identifier: 2.0.1
      micromark-util-sanitize-uri: 2.0.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-extension-gfm-strikethrough@2.1.0:
    dependencies:
      devlop: 1.1.0
      micromark-util-chunked: 2.0.1
      micromark-util-classify-character: 2.0.1
      micromark-util-resolve-all: 2.0.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-extension-gfm-table@2.1.1:
    dependencies:
      devlop: 1.1.0
      micromark-factory-space: 2.0.1
      micromark-util-character: 2.1.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-extension-gfm-tagfilter@2.0.0:
    dependencies:
      micromark-util-types: 2.0.2

  micromark-extension-gfm-task-list-item@2.1.0:
    dependencies:
      devlop: 1.1.0
      micromark-factory-space: 2.0.1
      micromark-util-character: 2.1.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-extension-gfm@3.0.0:
    dependencies:
      micromark-extension-gfm-autolink-literal: 2.1.0
      micromark-extension-gfm-footnote: 2.1.0
      micromark-extension-gfm-strikethrough: 2.1.0
      micromark-extension-gfm-table: 2.1.1
      micromark-extension-gfm-tagfilter: 2.0.0
      micromark-extension-gfm-task-list-item: 2.1.0
      micromark-util-combine-extensions: 2.0.1
      micromark-util-types: 2.0.2

  micromark-factory-destination@2.0.1:
    dependencies:
      micromark-util-character: 2.1.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-factory-label@2.0.1:
    dependencies:
      devlop: 1.1.0
      micromark-util-character: 2.1.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-factory-space@2.0.1:
    dependencies:
      micromark-util-character: 2.1.1
      micromark-util-types: 2.0.2

  micromark-factory-title@2.0.1:
    dependencies:
      micromark-factory-space: 2.0.1
      micromark-util-character: 2.1.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-factory-whitespace@2.0.1:
    dependencies:
      micromark-factory-space: 2.0.1
      micromark-util-character: 2.1.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-util-character@2.1.1:
    dependencies:
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-util-chunked@2.0.1:
    dependencies:
      micromark-util-symbol: 2.0.1

  micromark-util-classify-character@2.0.1:
    dependencies:
      micromark-util-character: 2.1.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-util-combine-extensions@2.0.1:
    dependencies:
      micromark-util-chunked: 2.0.1
      micromark-util-types: 2.0.2

  micromark-util-decode-numeric-character-reference@2.0.2:
    dependencies:
      micromark-util-symbol: 2.0.1

  micromark-util-decode-string@2.0.1:
    dependencies:
      decode-named-character-reference: 1.3.0
      micromark-util-character: 2.1.1
      micromark-util-decode-numeric-character-reference: 2.0.2
      micromark-util-symbol: 2.0.1

  micromark-util-encode@2.0.1: {}

  micromark-util-html-tag-name@2.0.1: {}

  micromark-util-normalize-identifier@2.0.1:
    dependencies:
      micromark-util-symbol: 2.0.1

  micromark-util-resolve-all@2.0.1:
    dependencies:
      micromark-util-types: 2.0.2

  micromark-util-sanitize-uri@2.0.1:
    dependencies:
      micromark-util-character: 2.1.1
      micromark-util-encode: 2.0.1
      micromark-util-symbol: 2.0.1

  micromark-util-subtokenize@2.1.0:
    dependencies:
      devlop: 1.1.0
      micromark-util-chunked: 2.0.1
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2

  micromark-util-symbol@2.0.1: {}

  micromark-util-types@2.0.2: {}

  micromark@4.0.2:
    dependencies:
      '@types/debug': 4.1.13
      debug: 4.4.3
      decode-named-character-reference: 1.3.0
      devlop: 1.1.0
      micromark-core-commonmark: 2.0.3
      micromark-factory-space: 2.0.1
      micromark-util-character: 2.1.1
      micromark-util-chunked: 2.0.1
      micromark-util-combine-extensions: 2.0.1
      micromark-util-decode-numeric-character-reference: 2.0.2
      micromark-util-encode: 2.0.1
      micromark-util-normalize-identifier: 2.0.1
      micromark-util-resolve-all: 2.0.1
      micromark-util-sanitize-uri: 2.0.1
      micromark-util-subtokenize: 2.1.0
      micromark-util-symbol: 2.0.1
      micromark-util-types: 2.0.2
    transitivePeerDependencies:
      - supports-color

  mrmime@2.0.1: {}

  ms@2.1.3: {}

  muggle-string@0.4.1: {}

  nanoid@3.3.18: {}

  neotraverse@1.0.1: {}

  nlcst-to-string@4.0.0:
    dependencies:
      '@types/nlcst': 2.0.3

  node-fetch-native@1.6.7: {}

  node-mock-http@1.0.4: {}

  normalize-path@3.0.0: {}

  nth-check@2.1.1:
    dependencies:
      boolbase: 1.0.0

  obug@2.1.4: {}

  ofetch@1.5.1:
    dependencies:
      destr: 2.0.5
      node-fetch-native: 1.6.7
      ufo: 1.6.4

  ohash@2.0.11: {}

  oniguruma-parser@0.12.2: {}

  oniguruma-to-es@4.3.6:
    dependencies:
      oniguruma-parser: 0.12.2
      regex: 6.1.0
      regex-recursion: 6.0.2

  p-limit@7.3.1:
    dependencies:
      yocto-queue: 1.2.2

  p-queue@9.3.3:
    dependencies:
      eventemitter3: 5.0.4
      p-timeout: 7.0.1

  p-timeout@7.0.1: {}

  package-manager-detector@1.6.0: {}

  parse-latin@7.0.0:
    dependencies:
      '@types/nlcst': 2.0.3
      '@types/unist': 3.0.3
      nlcst-to-string: 4.0.0
      unist-util-modify-children: 4.0.0
      unist-util-visit-children: 3.0.0
      vfile: 6.0.3

  parse5@7.3.0:
    dependencies:
      entities: 6.0.1

  path-browserify@1.0.1: {}

  path-expression-matcher@1.6.2: {}

  piccolore@0.1.3: {}

  picocolors@1.1.1: {}

  picomatch@2.3.1: {}

  picomatch@4.0.7: {}

  postcss-selector-parser@6.0.10:
    dependencies:
      cssesc: 3.0.0
      util-deprecate: 1.0.2

  postcss@8.5.26:
    dependencies:
      nanoid: 3.3.18
      picocolors: 1.1.1
      source-map-js: 1.2.1

  prettier@3.9.6: {}

  prismjs@1.30.0: {}

  process-ancestry@0.1.0: {}

  property-information@7.1.0: {}

  radix3@1.1.2: {}

  readdirp@4.1.2: {}

  readdirp@5.1.1: {}

  regex-recursion@6.0.2:
    dependencies:
      regex-utilities: 2.3.0

  regex-utilities@2.3.0: {}

  regex@6.1.0:
    dependencies:
      regex-utilities: 2.3.0

  rehype-autolink-headings@7.1.0:
    dependencies:
      '@types/hast': 3.0.5
      '@ungap/structured-clone': 1.3.0
      hast-util-heading-rank: 3.0.0
      hast-util-is-element: 3.0.0
      unified: 11.0.5
      unist-util-visit: 5.0.0

  rehype-raw@7.0.0:
    dependencies:
      '@types/hast': 3.0.5
      hast-util-raw: 9.1.0
      vfile: 6.0.3

  rehype-slug@6.0.0:
    dependencies:
      '@types/hast': 3.0.5
      github-slugger: 2.0.0
      hast-util-heading-rank: 3.0.0
      hast-util-to-string: 3.0.1
      unist-util-visit: 5.1.0

  rehype-stringify@10.0.1:
    dependencies:
      '@types/hast': 3.0.5
      hast-util-to-html: 9.0.5
      unified: 11.0.5

  remark-gfm@4.0.1:
    dependencies:
      '@types/mdast': 4.0.4
      mdast-util-gfm: 3.1.0
      micromark-extension-gfm: 3.0.0
      remark-parse: 11.0.0
      remark-stringify: 11.0.0
      unified: 11.0.5
    transitivePeerDependencies:
      - supports-color

  remark-parse@11.0.0:
    dependencies:
      '@types/mdast': 4.0.4
      mdast-util-from-markdown: 2.0.3
      micromark-util-types: 2.0.2
      unified: 11.0.5
    transitivePeerDependencies:
      - supports-color

  remark-rehype@11.1.2:
    dependencies:
      '@types/hast': 3.0.5
      '@types/mdast': 4.0.4
      mdast-util-to-hast: 13.2.1
      unified: 11.0.5
      vfile: 6.0.3

  remark-smartypants@3.0.3:
    dependencies:
      retext: 9.0.0
      retext-smartypants: 6.2.0
      unified: 11.0.5
      unist-util-visit: 5.1.0

  remark-stringify@11.0.0:
    dependencies:
      '@types/mdast': 4.0.4
      mdast-util-to-markdown: 2.1.2
      unified: 11.0.5

  request-light@0.5.8: {}

  request-light@0.7.0: {}

  require-from-string@2.0.2: {}

  resolve-pkg-maps@1.0.0: {}

  retext-latin@4.0.0:
    dependencies:
      '@types/nlcst': 2.0.3
      parse-latin: 7.0.0
      unified: 11.0.5

  retext-smartypants@6.2.0:
    dependencies:
      '@types/nlcst': 2.0.3
      nlcst-to-string: 4.0.0
      unist-util-visit: 5.1.0

  retext-stringify@4.0.0:
    dependencies:
      '@types/nlcst': 2.0.3
      nlcst-to-string: 4.0.0
      unified: 11.0.5

  retext@9.0.0:
    dependencies:
      '@types/nlcst': 2.0.3
      retext-latin: 4.0.0
      retext-stringify: 4.0.0
      unified: 11.0.5

  rolldown@1.2.5:
    dependencies:
      '@oxc-project/types': 0.146.0
      '@rolldown/pluginutils': 1.0.1
    optionalDependencies:
      '@rolldown/binding-android-arm-eabi': 1.2.5
      '@rolldown/binding-android-arm64': 1.2.5
      '@rolldown/binding-darwin-arm64': 1.2.5
      '@rolldown/binding-darwin-x64': 1.2.5
      '@rolldown/binding-freebsd-x64': 1.2.5
      '@rolldown/binding-linux-arm-gnueabihf': 1.2.5
      '@rolldown/binding-linux-arm64-gnu': 1.2.5
      '@rolldown/binding-linux-arm64-musl': 1.2.5
      '@rolldown/binding-linux-ppc64-gnu': 1.2.5
      '@rolldown/binding-linux-s390x-gnu': 1.2.5
      '@rolldown/binding-linux-x64-gnu': 1.2.5
      '@rolldown/binding-linux-x64-musl': 1.2.5
      '@rolldown/binding-openharmony-arm64': 1.2.5
      '@rolldown/binding-win32-arm64-msvc': 1.2.5
      '@rolldown/binding-win32-x64-msvc': 1.2.5

  satteri@0.10.5:
    dependencies:
      '@types/estree-jsx': 1.0.5
      '@types/hast': 3.0.5
      '@types/mdast': 4.0.4
      '@types/unist': 3.0.3
    optionalDependencies:
      '@bruits/satteri-darwin-arm64': 0.10.5
      '@bruits/satteri-darwin-x64': 0.10.5
      '@bruits/satteri-linux-arm64-gnu': 0.10.5
      '@bruits/satteri-linux-arm64-musl': 0.10.5
      '@bruits/satteri-linux-x64-gnu': 0.10.5
      '@bruits/satteri-linux-x64-musl': 0.10.5
      '@bruits/satteri-wasm32-wasi': 0.10.5
      '@bruits/satteri-win32-arm64-msvc': 0.10.5
      '@bruits/satteri-win32-x64-msvc': 0.10.5

  sax@1.6.1: {}

  semver@7.7.3: {}

  semver@7.8.5: {}

  sharp@0.35.3(@types/node@24.10.1):
    dependencies:
      '@img/colour': 1.1.0
      detect-libc: 2.1.2
      semver: 7.8.5
    optionalDependencies:
      '@img/sharp-darwin-arm64': 0.35.3
      '@img/sharp-darwin-x64': 0.35.3
      '@img/sharp-freebsd-wasm32': 0.35.3
      '@img/sharp-libvips-darwin-arm64': 1.3.2
      '@img/sharp-libvips-darwin-x64': 1.3.2
      '@img/sharp-libvips-linux-arm': 1.3.2
      '@img/sharp-libvips-linux-arm64': 1.3.2
      '@img/sharp-libvips-linux-ppc64': 1.3.2
      '@img/sharp-libvips-linux-riscv64': 1.3.2
      '@img/sharp-libvips-linux-s390x': 1.3.2
      '@img/sharp-libvips-linux-x64': 1.3.2
      '@img/sharp-libvips-linuxmusl-arm64': 1.3.2
      '@img/sharp-libvips-linuxmusl-x64': 1.3.2
      '@img/sharp-linux-arm': 0.35.3
      '@img/sharp-linux-arm64': 0.35.3
      '@img/sharp-linux-ppc64': 0.35.3
      '@img/sharp-linux-riscv64': 0.35.3
      '@img/sharp-linux-s390x': 0.35.3
      '@img/sharp-linux-x64': 0.35.3
      '@img/sharp-linuxmusl-arm64': 0.35.3
      '@img/sharp-linuxmusl-x64': 0.35.3
      '@img/sharp-webcontainers-wasm32': 0.35.3
      '@img/sharp-win32-arm64': 0.35.3
      '@img/sharp-win32-ia32': 0.35.3
      '@img/sharp-win32-x64': 0.35.3
      '@types/node': 24.10.1

  shiki@4.4.3:
    dependencies:
      '@shikijs/core': 4.4.3
      '@shikijs/engine-javascript': 4.4.3
      '@shikijs/engine-oniguruma': 4.4.3
      '@shikijs/langs': 4.4.3
      '@shikijs/themes': 4.4.3
      '@shikijs/types': 4.4.3
      '@shikijs/vscode-textmate': 10.0.2
      '@types/hast': 3.0.5

  sisteransi@1.0.5: {}

  sitemap@9.0.1:
    dependencies:
      '@types/node': 24.10.1
      '@types/sax': 1.2.7
      arg: 5.0.2
      sax: 1.6.1

  smol-toml@1.6.0: {}

  source-map-js@1.2.1: {}

  space-separated-tokens@2.0.2: {}

  stream-replace-string@2.0.0: {}

  string-width@7.2.0:
    dependencies:
      emoji-regex: 10.6.0
      get-east-asian-width: 1.4.0
      strip-ansi: 7.1.2

  string-width@8.2.2:
    dependencies:
      get-east-asian-width: 1.6.0
      strip-ansi: 7.1.2

  stringify-entities@4.0.4:
    dependencies:
      character-entities-html4: 2.1.0
      character-entities-legacy: 3.0.0

  strip-ansi@7.1.2:
    dependencies:
      ansi-regex: 6.2.2

  strnum@2.4.2:
    dependencies:
      anynum: 1.0.1

  supports-color@7.2.0:
    dependencies:
      has-flag: 4.0.0

  svgo@4.1.0:
    dependencies:
      commander: 11.1.0
      css-select: 6.0.0
      css-tree: 3.1.0
      css-what: 7.0.0
      csso: 5.0.5
      picocolors: 1.1.1
      sax: 1.6.1

  tailwindcss@4.3.3: {}

  tapable@2.3.3: {}

  tiny-inflate@1.0.3: {}

  tinyclip@0.1.15: {}

  tinyexec@1.3.0: {}

  tinyglobby@0.2.15:
    dependencies:
      fdir: 6.5.0(picomatch@4.0.7)
      picomatch: 4.0.7

  tinyglobby@0.2.17:
    dependencies:
      fdir: 6.5.0(picomatch@4.0.7)
      picomatch: 4.0.7

  trim-lines@3.0.1: {}

  trough@2.2.0: {}

  tslib@2.8.1:
    optional: true

  typesafe-path@0.2.2: {}

  typescript-auto-import-cache@0.3.6:
    dependencies:
      semver: 7.7.3

  typescript@6.0.3: {}

  ufo@1.6.4: {}

  ultrahtml@1.6.0: {}

  uncrypto@0.1.3: {}

  undici-types@7.16.0: {}

  undici@8.10.0: {}

  unified@11.0.5:
    dependencies:
      '@types/unist': 3.0.3
      bail: 2.0.2
      devlop: 1.1.0
      extend: 3.0.2
      is-plain-obj: 4.1.0
      trough: 2.2.0
      vfile: 6.0.3

  unifont@0.7.5:
    dependencies:
      css-tree: 3.1.0
      ohash: 2.0.11
      undici: 8.10.0

  unist-util-find-after@5.0.0:
    dependencies:
      '@types/unist': 3.0.3
      unist-util-is: 6.0.1

  unist-util-is@6.0.1:
    dependencies:
      '@types/unist': 3.0.3

  unist-util-modify-children@4.0.0:
    dependencies:
      '@types/unist': 3.0.3
      array-iterate: 2.0.1

  unist-util-position@5.0.0:
    dependencies:
      '@types/unist': 3.0.3

  unist-util-remove-position@5.0.0:
    dependencies:
      '@types/unist': 3.0.3
      unist-util-visit: 5.1.0

  unist-util-stringify-position@4.0.0:
    dependencies:
      '@types/unist': 3.0.3

  unist-util-visit-children@3.0.0:
    dependencies:
      '@types/unist': 3.0.3

  unist-util-visit-parents@6.0.2:
    dependencies:
      '@types/unist': 3.0.3
      unist-util-is: 6.0.1

  unist-util-visit@5.0.0:
    dependencies:
      '@types/unist': 3.0.3
      unist-util-is: 6.0.1
      unist-util-visit-parents: 6.0.2

  unist-util-visit@5.1.0:
    dependencies:
      '@types/unist': 3.0.3
      unist-util-is: 6.0.1
      unist-util-visit-parents: 6.0.2

  unstorage@1.17.5:
    dependencies:
      anymatch: 3.1.3
      chokidar: 5.0.0
      destr: 2.0.5
      h3: 1.15.11
      lru-cache: 11.5.2
      node-fetch-native: 1.6.7
      ofetch: 1.5.1
      ufo: 1.6.4

  util-deprecate@1.0.2: {}

  vfile-location@5.0.3:
    dependencies:
      '@types/unist': 3.0.3
      vfile: 6.0.3

  vfile-message@4.0.3:
    dependencies:
      '@types/unist': 3.0.3
      unist-util-stringify-position: 4.0.0

  vfile@6.0.3:
    dependencies:
      '@types/unist': 3.0.3
      vfile-message: 4.0.3

  vite@8.2.2(@types/node@24.10.1)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0):
    dependencies:
      lightningcss: 1.33.0
      picomatch: 4.0.7
      postcss: 8.5.26
      rolldown: 1.2.5
      tinyglobby: 0.2.17
    optionalDependencies:
      '@types/node': 24.10.1
      esbuild: 0.28.2
      fsevents: 2.3.3
      jiti: 2.7.0
      yaml: 2.9.0

  vitefu@1.1.3(vite@8.2.2(@types/node@24.10.1)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)):
    optionalDependencies:
      vite: 8.2.2(@types/node@24.10.1)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)

  volar-service-css@0.0.71(@volar/language-service@2.4.28):
    dependencies:
      vscode-css-languageservice: 6.3.9
      vscode-languageserver-textdocument: 1.0.12
      vscode-uri: 3.1.0
    optionalDependencies:
      '@volar/language-service': 2.4.28

  volar-service-emmet@0.0.71(@volar/language-service@2.4.28):
    dependencies:
      '@emmetio/css-parser': 0.4.1
      '@emmetio/html-matcher': 1.3.0
      '@vscode/emmet-helper': 2.11.0
      vscode-uri: 3.1.0
    optionalDependencies:
      '@volar/language-service': 2.4.28

  volar-service-html@0.0.71(@volar/language-service@2.4.28):
    dependencies:
      vscode-html-languageservice: 5.6.2
      vscode-languageserver-textdocument: 1.0.12
      vscode-uri: 3.1.0
    optionalDependencies:
      '@volar/language-service': 2.4.28

  volar-service-prettier@0.0.71(@volar/language-service@2.4.28)(prettier@3.9.6):
    dependencies:
      vscode-uri: 3.1.0
    optionalDependencies:
      '@volar/language-service': 2.4.28
      prettier: 3.9.6

  volar-service-typescript-twoslash-queries@0.0.71(@volar/language-service@2.4.28):
    dependencies:
      vscode-uri: 3.1.0
    optionalDependencies:
      '@volar/language-service': 2.4.28

  volar-service-typescript@0.0.71(@volar/language-service@2.4.28):
    dependencies:
      path-browserify: 1.0.1
      semver: 7.7.3
      typescript-auto-import-cache: 0.3.6
      vscode-languageserver-textdocument: 1.0.12
      vscode-nls: 5.2.0
      vscode-uri: 3.1.0
    optionalDependencies:
      '@volar/language-service': 2.4.28

  volar-service-yaml@0.0.71(@volar/language-service@2.4.28):
    dependencies:
      vscode-uri: 3.1.0
      yaml-language-server: 1.23.0
    optionalDependencies:
      '@volar/language-service': 2.4.28

  vscode-css-languageservice@6.3.9:
    dependencies:
      '@vscode/l10n': 0.0.18
      vscode-languageserver-textdocument: 1.0.12
      vscode-languageserver-types: 3.17.5
      vscode-uri: 3.1.0

  vscode-html-languageservice@5.6.2:
    dependencies:
      '@vscode/l10n': 0.0.18
      vscode-languageserver-textdocument: 1.0.12
      vscode-languageserver-types: 3.17.5
      vscode-uri: 3.1.0

  vscode-json-languageservice@4.1.8:
    dependencies:
      jsonc-parser: 3.3.1
      vscode-languageserver-textdocument: 1.0.12
      vscode-languageserver-types: 3.17.5
      vscode-nls: 5.2.0
      vscode-uri: 3.1.0

  vscode-jsonrpc@8.2.0: {}

  vscode-languageserver-protocol@3.17.5:
    dependencies:
      vscode-jsonrpc: 8.2.0
      vscode-languageserver-types: 3.17.5

  vscode-languageserver-textdocument@1.0.12: {}

  vscode-languageserver-types@3.17.5: {}

  vscode-languageserver@9.0.1:
    dependencies:
      vscode-languageserver-protocol: 3.17.5

  vscode-nls@5.2.0: {}

  vscode-uri@3.1.0: {}

  web-namespaces@2.0.1: {}

  wrap-ansi@9.0.2:
    dependencies:
      ansi-styles: 6.2.3
      string-width: 7.2.0
      strip-ansi: 7.1.2

  xml-naming@0.3.0: {}

  xxhash-wasm@1.1.0: {}

  y18n@5.0.8: {}

  yaml-language-server@1.23.0:
    dependencies:
      '@vscode/l10n': 0.0.18
      ajv: 8.17.1
      ajv-draft-04: 1.0.0(ajv@8.17.1)
      ajv-i18n: 4.2.0(ajv@8.17.1)
      prettier: 3.9.6
      request-light: 0.5.8
      vscode-json-languageservice: 4.1.8
      vscode-languageserver: 9.0.1
      vscode-languageserver-textdocument: 1.0.12
      vscode-languageserver-types: 3.17.5
      vscode-uri: 3.1.0
      yaml: 2.8.3

  yaml@2.8.3: {}

  yaml@2.9.0: {}

  yargs-parser@22.0.0: {}

  yargs@18.1.0:
    dependencies:
      cliui: 9.0.1
      escalade: 3.2.0
      get-caller-file: 2.0.5
      string-width: 8.2.2
      y18n: 5.0.8
      yargs-parser: 22.0.0

  yocto-queue@1.2.2: {}

  zod@4.4.3: {}

  zwitch@2.0.4: {}

---

## File: tsconfig.json

{
  "extends": "astro/tsconfigs/strict",
  "include": [".astro/types.d.ts", "**/*"],
  "exclude": ["dist"],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@components/*": ["src/components/*"],
      "@assets/*": ["src/assets/*"],
      "@layouts/*": ["src/layouts/*"],
      "@collections/*": ["src/collections/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}

---

## File: public/robots.txt

User-agent: *
Allow: /

Sitemap: https://yansongda.cn/sitemap-index.xml

---

## File: src/collections/experiences.json

[
  {
    "dates": "2018-07 ~ 至今",
    "role": "应用研发总监",
    "company": "某通讯公司",
    "description": "略。不是不想写，是保密协议不允许，懂的都懂 🤐"
  },
  {
    "dates": "2016-09 ~ 2018-06",
    "role": "技术负责人",
    "company": "某电力物联网公司",
    "description": "从 0 到 1 重新造数据采集方案：定制 DTU + 固件一条龙，微信小程序一鱼两吃（运维端管数据、用户端看数据），数据全部塞进自建 MongoDB 集群；后来又怒肝 v2 版本硬件和数据采集软件，成功点亮 demo —— 老板看了直呼内行。"
  },
  {
    "dates": "2015-09 ~ 2016-09",
    "role": "技术负责人",
    "company": "某电力物联网公司",
    "description": "刚毕业就一头扎进物联网数据采集硬件的深水区。本着「打不过就加入、比不过就超越」的原则，研究出了比母公司还好的 Modbus TCP 方案，服务器和终端硬件成本直接砍一刀 —— 毕业即爽文男主，剧本拿好。"
  }
]

---

## File: src/collections/menu.json

[
  {
    "name": "Home",
    "url": "/"
  },
  {
    "name": "文章",
    "url": "/posts"
  },
  {
    "name": "项目",
    "url": "/projects"
  },
  {
    "name": "关于我",
    "url": "/about"
  }
]

---

## File: src/collections/open-source.json

[
  {
    "name": "pay",
    "description": "可能是我用过的最优雅的 Alipay/WeChat/Douyin/Unipay/江苏银行 的支付 SDK 扩展包了",
    "url": "https://github.com/yansongda/pay",
    "stars": 5365,
    "language": "PHP"
  },
  {
    "name": "opencode-stats-engine",
    "description": "OpenCode 事件溯源统计引擎：监听事件、持久化到本地 SQLite，提供统计面板、REST API 与 SSE 实时更新",
    "url": "https://github.com/yansongda/opencode-stats-engine",
    "stars": 2,
    "language": "TypeScript"
  },
  {
    "name": "docker-compose-LNMP",
    "description": "docker-compose with latest php-fpm, nginx, redis, memcached, mariadb",
    "url": "https://github.com/yansongda/docker-compose-LNMP",
    "stars": 37,
    "language": "Docker"
  },
  {
    "name": "python-aliyun-iot-device",
    "description": "非官方，阿里云 IOT 套件设备端 Python 开发 SDK",
    "url": "https://github.com/yansongda/python-aliyun-iot-device",
    "stars": 9,
    "language": "Python"
  },
  {
    "name": "application",
    "description": "自己的应用服务，由 Rust 强力驱动。目前提供微信小程序与华为原生云服务",
    "url": "https://github.com/yansongda/application",
    "stars": 2,
    "language": "Rust"
  }
]

---

## File: src/collections/projects.json

[
  {
    "name": "Pay",
    "description": "可能是我用过的最优雅的 Alipay/WeChat/Douyin/Unipay/江苏银行 的支付 SDK 扩展包了",
    "url": "https://pay.yansongda.cn"
  },
  {
    "name": "artful",
    "description": "Api RequesT Framework U Like - 你喜欢的 API 请求框架",
    "url": "https://artful.yansongda.cn"
  },
  {
    "name": "rs-application",
    "description": "自己的应用服务，由 Rust 强力驱动。目前提供微信小程序与华为原生云服务。",
    "url": "https://github.com/yansongda/rs-application"
  },
  {
    "name": "laravel-pay",
    "description": "可能是我用过的最优雅的 Alipay/WeChat/Douyin/Unipay/江苏银行 的 laravel 支付扩展包了",
    "url": "https://github.com/yansongda/laravel-pay"
  },
  {
    "name": "docker-php",
    "description": "PHP 的 Docker 基础镜像，包含 amd64, arm64 等版本",
    "url": "https://github.com/yansongda/docker-php"
  }
]

---

## File: src/collections/skills.json

[
  {
    "category": "语言",
    "emoji": "💬",
    "note": "吃饭的家伙，一个都不能少",
    "skills": [
      { "name": "PHP", "note": "十年老伙计，靠它吃饭" },
      { "name": "Rust", "note": "新欢，正在热恋期，请勿打扰" },
      { "name": "Python", "note": "写写脚本摸摸鱼" },
      { "name": "JavaScript", "note": "前端半吊子必备" },
      { "name": "TypeScript", "note": "给 JS 戴上安全帽" }
    ]
  },
  {
    "category": "框架",
    "emoji": "🧱",
    "note": "造轮子专业户",
    "skills": [
      { "name": "Hyperf", "note": "协程真香，性能拉满" },
      { "name": "Salvo", "note": "Rust 界的颜值担当" },
      { "name": "Laravel", "note": "PHP 里的老牌优雅" },
      { "name": "Symfony", "note": "优雅但有点重" }
    ]
  },
  {
    "category": "数据与中间件",
    "emoji": "🗄️",
    "note": "数据猛男，掉坑无数",
    "skills": [
      { "name": "MySQL", "note": "老搭档" },
      { "name": "MongoDB", "note": "自建过集群，掉过坑" },
      { "name": "Redis", "note": "缓存届顶流" },
      { "name": "Elasticsearch", "note": "搜啥都快" }
    ]
  },
  {
    "category": "运维与部署",
    "emoji": "🚀",
    "note": "一把梭，全都要",
    "skills": [
      { "name": "Docker", "note": "打包狂魔，万物皆可容器" },
      { "name": "Nginx", "note": "反向代理一把好手" },
      { "name": "Linux", "note": "服务器上的第二个家" }
    ]
  },
  {
    "category": "正在深入",
    "emoji": "🦀",
    "note": "头铁勇士，越陷越深",
    "wide": true,
    "skills": [
      { "name": "Rust", "note": "学 Rust，掉头发，涨工资（大概）" }
    ]
  }
]

---

## File: src/posts/2012-06-08-in-those-years-we-struggled-together.md

[Binary file]

---

## File: src/posts/2012-06-08-transient-eternal.md

[Binary file]

---

## File: src/posts/2012-06-12-three-things-and-three-problems.md

[Binary file]

---

## File: src/posts/2012-06-30-new-employees-must-look-believe-think-act-and-act.md

[Binary file]

---

## File: src/posts/2012-07-11-in-the-end-we-all-understand.md

[Binary file]

---

## File: src/posts/2012-07-18-do-not-know-their-own-interests-how-should-the-road-go.md

[Binary file]

---

## File: src/posts/2012-07-22-four-years-in-college-should-be-spent-1.md

[Binary file]

---

## File: src/posts/2012-07-22-four-years-in-college-should-be-spent-2.md

[Binary file]

---

## File: src/posts/2012-07-22-four-years-in-college-should-be-spent-3.md

---
title: 大学四年应该这样度过（三）
date: 2012-07-22
categories:
  - college
  - reading
---

## 培养兴趣：开拓视野，立定志向

孔子说：“知之者不如好之者，好之者不如乐之者。”我在“给中国学生的第三封信”中曾深入论述了快乐和兴趣是一个人成功的关键。如果你对某个领域充满激情，你就有可能在该领域中发挥自己所有的潜力，甚至为它而废寝忘食。这时候，你已经不是为了成功而学习，而是为了“享受”而学习了。在“第三封信”中，我也曾谈到我自己是如何在大学期间放弃了我不感兴趣的法律专业而进入我所热爱的计算机专业学习的。

有些同学问我，如何像我一样能找到自己的兴趣呢？我觉得，首先要客观地评估和寻找自己的兴趣所在：不要把社会、家人或朋友认可和看重的事当作自己的爱好；不要以为有趣的事就是自己的兴趣所在，而是要亲身体验它并用自己的头脑做出判断；不要以为有兴趣的事情就可以成为自己的职业，例如，喜欢玩网络游戏并不代表你会喜欢或有能力开发网络游戏；不要以为有兴趣就意味着自己有这方面的天赋，不过，你可以尽量寻找天赋和兴趣的最佳结合点，例如，如果你对数学有天赋但又喜欢计算机专业，那么你完全可以做计算机理论方面的研究工作。

最好的寻找兴趣点的方法是开拓自己的视野，接触众多的领域。唯有接触你才能尝试，唯有尝试你才能找到自己的最爱。而大学正是这样一个可以让你接触并尝试众多领域的独一无二的场所。因此，大学生应当更好地把握在校时间，充分利用学校的资源，通过使用图书馆资源、旁听课程、搜索网络、听讲座、打工、参加社团活动、与朋友交流、使用电子邮件和电子论坛等不同方式接触更多的领域、更多的工作类型和更多的专家学者。当年，如果我只是乖乖地到法律系上课，而不去尝试旁听计算机系的课程，我就不会去计算机中心打工，也不去找计算机系的助教切磋，就更不会发现自己对计算机的浓厚兴趣。

通过开拓视野和接触尝试，如果你发现了自己真正的兴趣爱好，这时就可以去尝试转系的可能性、尝试课外学习、选修或旁听相关课程；你也可以去找一些打工或假期实习的机会，进一步理解相关行业的工作性质；或者，努力去考自己感兴趣专业的研究生，重新进行一次专业选择。其实，本科读什么专业并不能完全决定毕业后的工作方向，正如我所强调的那样，大学期间的学习过程培养的是你的学习能力，只要具备了这种能力，即使从事的是全新的工作，你也能在边做边学的过程中获取足够的知识和经验。

除了“选你所爱”，大家也不妨试试“爱你所选”。有些同学后悔自己在入学时选错了专业，以至于对所学的专业缺乏兴趣，没有学习动力；有些同学则因为追寻兴趣而“走火入魔”，毕业后才发现荒废了本专业的课程；另一些同学因为在学习上遇到了困难或对本专业抱有偏见，就以兴趣为借口，不愿意面对自己的专业。这些做法都是不正确的。在大学中，转系可能并不容易，所以，大家首先应尽力试着把本专业读好，并在学习过程中逐渐培养自己对本专业的兴趣。此外，一个专业里可能有很多不同的领域，也许你对专业里的某一个领域会有兴趣。现在，有很多专业发展了交叉学科，两个专业的结合往往是新的增长点。因此，只要多接触、多尝试，你也许就会碰到自己真正感兴趣的方向。“数字笔”的发明人王坚博士在微软亚洲研究院负责用户界面的研究，可是谁又能想到他从本科到博士所学的都是心理学专业，而用户界面又正是计算机和心理学专业的最佳结合点。另一方面，就算你毕业后要从事其他的行业，你依然可以把自己的专业读好，这同样能成为你在新行业中的优势。例如，有一位同学不喜欢读工科，想毕业后进入服务业发展，我就建议他先把工科读好，将来可以在服务业中以精通技术作为自己的特长。

人生的路很长，每个人都可以有很多不同的兴趣爱好。在追寻兴趣之外，更重要的是要找寻自己终身不变的志向。有一本书的作者曾访问了几百个成功者，问他们有哪件事是他们今天已经懂得，但在年轻时却留下了遗憾的事情。在受访者的回答中，最多的一种是：“希望在年轻时就有前辈告诉我、鼓励我去追寻自己的理想和志向。”相比之下，兴趣固然关键，但志向更为重要。例如，我的志向是“使影响力最大化”，多年以来，我有许多兴趣爱好，如语音识别、对弈软件、多媒体、研究到开发的转换、管理学、满足用户的需求、演讲和写作、帮助中国学生等等，兴趣可以改变，但我的志向是始终不渝的。因此，大家不必把某种兴趣当作自己最后的目标，也不必把任何一种兴趣的发展道路完全切断，在志向的指引下，不同的兴趣完全可以平行发展，实在必要时再做出最佳的抉择。志向就像罗盘，兴趣就像风帆，两者相辅相成、缺一不可，它们可以让你驶向理想的港湾。

## 积极主动：果断负责，创造机遇

创立“开复学生网”时，我的初衷是“帮助学生帮助自己”。但让我很惊讶的是，更多的学生希望我直接帮他们做出决定，甚至仅在简短的几句自我介绍后就直接对我说：“只有你能告诉我，我该怎么做”。难道一个陌生人会比你更知道自己该怎么做吗？我慢慢认识到，这种被动的思维方式是从小在中国的教育环境中培养出来的。被动的人总是习惯性地认为他们现在的境况是他人和环境造成的，如果别人不指点，环境不改变，自己就只有消极地生活下去。持有这种态度的人，事业还没有开始，自己就已经被击败，我从来没见过这样消极的人可以取得持续的成功。

从大学的第一天开始，你就必须从被动转向主动，你必须成为自己未来的主人，你必须积极地管理自己的学业和将来的事业，理由很简单：因为没有人比你更在乎你自己的工作与生活。“让大学生活对自己有价值”是你的责任。许多同学到了大四才开始做人生和职业规划，而一个主动的学生应该从进入大学时就开始规划自己的未来。 　　积极主动的第一步是要有积极的态度。大家可以用我在“第三封信”里推荐的方法，积极规划自己的人生目标，追寻兴趣并尝试新的知识和领域。纳粹德国某集中营的一位幸存者维克托·弗兰克尔曾说过：“在任何特定的环境中，人们还有一种最后的自由，就是选择自己的态度。”

积极主动的第二步是对自己的一切负责，勇敢面对人生。不要把不确定的或困难的事情一味搁置起来。比如说，有些同学认为英语重要，但学校不考试就不学英语；或者，有些同学觉得自己需要参加社团磨练人际关系，但是因为害羞就不积极报名。但是，我们必须认识到，不去解决也是一种解决，不做决定也是一个决定，这样的解决和决定将使你面前的机会丧失殆尽。对于这种消极、胆怯的作风，你终有一天会付出代价的。

积极主动的第三步是要做好充分的准备：事事用心，事事尽力，不要等机遇上门；要把握住机遇，创造机遇。中国科技大学校长朱清时院士在大三时被分配到青海做铸造工人。但他不像其他同学那样放弃学习，整天打扑克、喝酒。他依然终日钻研数理化和英语。六年后，中国科学院要在青海做一个重要的项目，这时朱校长就脱颖而出，开始了他辉煌的事业。很多人可能说他运气好，被分配到缺乏人才的青海，才有这机会。但是，如果他没有努力学习，也无法抓住这个机遇。所以，做好充分的准备，当机遇来临时，你才能抓住它。

积极主动的第四步是“以终为始”，积极地规划大学四年。任何规划都将成为你某个阶段的终点，也将成为你下一个阶段的起点，而你的志向和兴趣将为你提供方向和动力。如果不知道自己的志向和兴趣，你应该马上做一个发掘志向和兴趣的计划；如果不知道毕业后要做什么，你应该马上制定一个尝试新领域的计划；如果不知道自己最欠缺什么，你应该马上写一份简历，找你的老师、朋友打分，或自己审阅，看看哪里需要改进；如果毕业后想出国读博士，你应该想想如何让自己在申请出国前有具体的研究经验和学术论文；如果毕业后想进入某个公司工作，你应该收集该公司的招聘广告，以便和你自己的履历对比，看自己还欠缺哪些经验。只要认真制定、管理、评估和调整自己的人生规划，你就会离你自己的目标越来越近。

---

摘自：我学网

---

## File: src/posts/2012-07-22-four-years-in-college-should-be-spent-4.md

---
title: 大学四年应该这样度过（四）
date: 2012-07-22
categories:
  - college
  - reading
---

## 为人处事：培养友情，参与群体

很多大学生入校时都是第一次离开父母，离开自己生长的环境。进入校园开始集体生活后，如何与同学、朋友以及社团的同事相处就成为了大学生学习内容的一部分。大学是大家最后一次可以在相对宽松的环境中学习、培养、训练如何与人相处的机会。在未来，人们在社会里、在工作中与人相处的能力会变得越来越重要，甚至超过了工作本身。所以，大学生要好好把握机会，培养自己的交流意识和团队精神。

“人际交往能力不够强，人际圈子不够广，但又没有什么特长可以引起大家的注意，在社团里也不知道怎么和其他人有效地建立联系。”这是一些大学生在人际交往方面经常遇到的困惑。对于如何在大学期间提高人际交往能力，我的建议是：

* 第一，以诚待人，以责人之心责己、以恕己之心恕人。对别人要抱着诚挚、宽容的胸襟，对自己要怀着自我批评、有过必改的态度。与人交往时，你怎样对待别人，别人也会怎样对待你。这就好比照镜子一样，你自己的表情和态度，可以从他人对你流露出的表情和态度中一览无遗。你若以诚待人，别人也会以诚待你。你若敌视别人，别人也会敌视你。最真挚的友情和最难解的仇恨都是由这种“反射”原理逐步造成的。因此，当你想修正别人时，你应该先修正自己。你想别人怎么对你，你就应该怎么对人。你想他人理解你，你就要首先理解他人。

* 第二，培养真正的友情。如果能做到第一点，很多大学时的朋友就会成为你一辈子的知己。在一起求学和寻求自身发展的道路上，这样的友谊弥足珍贵。交朋友时，不要只去找与你性情相近或只会附和你的人做朋友。好朋友有很多种：乐观的朋友、智慧的朋友、脚踏实地的朋友、幽默风趣的朋友、激励你上进的朋友、提升你能力的朋友、帮你了解自己的朋友、对你说实话的朋友等等。此外，大学时谈恋爱也可以教你如何照顾别人，增进同理心和自控力，但恋爱这件事要一切随缘，不必为了谈恋爱而谈恋爱。

* 第三，学习团队精神和沟通能力。社团是微观的社会，参与社团是步入社会前最好的磨练。在社团中，可以培养团队合作的能力和领导才能，也可以发挥你的专业特长。但更重要的是，你要做一个诚心诚意的服务者和志愿者，或在担任学生工作时主动扮演同学和老师之间沟通桥梁的角色，并以此锻炼自己的沟通能力，为同学和老师服务。这样的学习过程也不会很轻松，挫折是肯定有的，但是不要灰心，大学社团里的人际交往是一种不用“付学费”的学习，犯了错误也可以重头来过。

* 第四，从周围的人身上学习。在班级里、社团中，多观察周围的同学，特别是那些你觉得交往能力和沟通能力特别强的同学，看他们是如何与人相处的。比如，看他们如何处理交往中的冲突、如何说服他人和影响他人、如何发挥自己的合作和协调能力、如何表达对他人的尊重和真诚、如何表示赞许或反对，如何在不冒犯他人的情况下充分展示个性等等。通过观察和模仿，你渐渐地会发现，自己的人际交往能力会有意想不到的改进。在学校里，每一个朋友都可以成为你的良师，他们的热心、幽默、机智、博学、正直、沟通、礼貌等品德都可以成为你的学习对象。当然，你也应当慷慨地帮助每一个朋友，试着做他们的良师和模范。

* 第五，提高自身修养和人格魅力。如果觉得没有特长、没有爱好可能会成为自己人际交往能力提高的一个障碍，那么，你可以有意识地去选择和培养一些兴趣爱好。共同的兴趣和爱好也是你与朋友建立深厚感情的途径之一。很多在事业上有所建树的人都不是只会闭门苦读的书呆子，他们大多都有自己的兴趣和爱好。我在微软亚洲研究院的同事中就有绘画、桥牌和体育运动方面的高手。业余爱好不仅是人际交往的一种方式，还可以让大家发掘出自己在读书以外的潜能。例如，体育锻炼既可以发挥你的运动潜能，也可以培养你的团队合作精神。如果真的没有什么兴趣爱好，那么，多读些好书丰富自己的知识也可以改进自己的人际交往能力，因为没有什么比智慧和渊博更能体现一个人的人格魅力了。

所以，学会与人相处，这也是大学中的一门“必修课”。

## 对大学生们的期望

踏入大学校门时，你还是一个忙碌的、青涩的、被动的、为分数读书的、被家庭呵护着的中学毕业生。

就读大学时，你应当掌握七项学习，学好自修之道、基础知识、实践贯通、培养兴趣、积极主动、掌控时间、为人处事。

经过大学四年，你会从思考中确立自我，从学习中寻求真理，从独立中体验自主，从计划中把握时间，从表达中锻炼口才，从交友中品味成熟，从实践中赢得价值，从兴趣中攫取快乐，从追求中获得力量。

离开大学时，只要做到了这些，你最大的收获将是“对什么都可以拥有的自信和渴望”。你就能成为一个有潜力、有思想、有价值、有前途的中国未来的主人翁。

所以，大学四年应该这么度过。

---

摘自：我学网

---

## File: src/posts/2012-07-29-how-to-learn-c-language.md

---
title: 怎样学好C语言
date: 2012-07-29
categories:
  - reading
---

> C语言其实说难不难，说不难也难。就拿 我来说，高中时，看了几本书，大一在图书馆借了几本真题，二级就过了。虽然不能 说是高手，但很多编程问题还是能够独立解决的。但，同时，语言是一门很深奥的东东，它会给你意想不到的“惊喜”。

我相信，很多coder会有以下的感觉：编程编到一定的时候，发现能力到了瓶颈，既不深，也不扎实，半吊子。比如：你长期地使用Java和.NET ，这些有虚拟机的语言对于开发便利是便利，但是对于程序员来说可能并不太好，原因有两个：

* 虚拟机屏蔽了操作系统的系统调用，以及很多底层机制。
* 大量的封装好的类库也屏蔽了很多实现细节。

一段时间后，你会发现你知其然，不知所以然。我以前在CSDN上写过一篇《Java NIO类库Selector机制解析（[上](http://blog.csdn.net/haoel/archive/2008/03/27/2224055.aspx)，[下](http://blog.csdn.net/haoel/archive/2008/03/27/2224069.aspx)，[续](http://blog.csdn.net/haoel/archive/2008/05/04/2379586.aspx)）》，在那篇文章中我说提到过（有讥讽的语气）Java的程序员不懂底层实现，所以很难把技术学得更扎实。此时，一部分程序员会不自然地想学学底层的技术，很自然的，C语言就被提了上来。

下面是我给这位朋友的一些建议：

* 鼓励并为你叫好。我鼓励你想要去学C语言的想法和精神，很多人都觉得C语言好学，其实并不然。（你可以看看[《C语言的迷题》](http://yanda.net.cn/index.php/articles/174)）现在的这个社会更多地去关注那些时髦的技术，而忽略了这个流行了40+年的C语言。一门技术如果能够流行40多年，这才是你需要去关注和学习的技术，而不是那些刚出来的技术（[过度炒作的技术](http://coolshell.cn/articles/3609.html)，[Windows编程史](http://coolshell.cn/articles/3008.html)）。这才是踏踏实实的精神。
* 不要找借口。这一条路走下来并不容易，不要给自己找借口。我最不喜欢听到的就是“很忙，没有时间”这样的借口。我以前在银行做项目，早9点到晚10点，周一到周六，我一样可以每天抽1个小时来看书和专研，一年下来也能精读5、6本书。我现在的工作项目和招聘任务很紧张，刚生的小孩只有自己和老婆两人带，还需要准备讲课，但是我还是能够找到时间看文章写文章维护酷壳。所以，我可以告诉你，“时间就像乳沟，只要你肯挤，就一定会有”。
* 学好C语言和系统编程。我认为，学好编程有四个方面：语言、算法和数据结构、系统调用和设计。
    * 语言。我可以告诉你C语言有两大主题你要好好学，一个是内存管理，一个是指针！这个世界上90%以上的C/C++出的严重性错误全是和这两个有关。不要看谭浩强的那本书，那本是本烂书。推荐这本书给你[《C程序设计语言（第2版·新版）](http://product.china-pub.com/14975&ref=browse)》
    * 算法和数据结构。我认为，用C语言实现算法和数据结构莫过于最爽的事情。推荐你看这本书——算法:[C语言实现(第1～4部分)基础知识、数据结构、排序及搜索(原书第3版)](http://product.china-pub.com/192975&ref=browse)，还有那本经典的[《算法导论》](http://product.china-pub.com/31701)
    * 系统编程。Windows下推荐两本书——[《Windows 程序设计》](http://product.china-pub.com/52880)和[《Windows核心编程》](http://product.china-pub.com/209058)，Unix/Linux下推荐两本书——[《Unix高级环境编程》](http://product.china-pub.com/30181)和[《Unix网络编程卷1，套接字》](http://product.china-pub.com/196770)、[《Unix网络编程卷2，进程间通信》](http://product.china-pub.com/196859)尤其是《Unix网络编程》这本书，一通百通，无论Windows还是Unix/Linux，都是一样的。
    * 系统设计。关于设计方面，我全力推荐[《Unix编程艺术》](http://product.china-pub.com/197413)，看完以后，你就明白什么是真正的编程文化了。然后，当你看到Windows的Fans的某些言论时，你就知道什么叫一笑了之了。

如果你能在2-3年内精读完这些书，并全部融会贯通，那么你就明白什么是一览众山小的感觉了！我足足花了5年时间才算是真正全部读完这些书的。最后，祝你好运！努力！

——-更新——-

我想，这篇文章主要想告诉大家这么几件事：

* 编程编到一定时候，你就需要了解底层系统的机制，否则，知其然不知所以然。
* 我没有否定非C的程序员的逻辑，真正的逻辑是——如果你想要了解底层机制，请学习C语言和操作系统。
* 40多年的Unix/C影响深远。包括影响了Windows。如果你想一通百通，一定要了解Unix。那是计算机文化真正的根。
* 不要肤浅地去思考问题。比如，不要以为一个DBA就不会考虑数据库引擎的内存页面的问题。也不要以为Web程序员就不需要了解后台的服务器和脚本的运行性能以及TCP/IP的问题。

**高手往往都是有很强的系统的基础知识的，表面的东西永远是肤浅的。**

--- 

部分内容摘自：酷壳网

作者：陈皓 版权归原作者所有

---

## File: src/posts/2012-08-03-interview-70-asked-classic-answer.md

[Binary file]

---

## File: src/posts/2012-08-17-successful-interview-sharing.md

[Binary file]

---

## File: src/posts/2012-08-19-yu-minhong-living-on-the-idea.md

---
title: 俞敏洪：活到点子上
date: 2012-08-19
categories:
  - reading
---

> 什么叫活到点子上？就是觉得一辈子没有白活，幸福指数很高，心灵很充实，回头看自己的人生道路没有太多的遗憾，尤其是没有太多的悔恨，如果让你再重新过一辈子，你还是愿意这样生活，这就是活到点子上。

哪些人活到了点子上？当官的是不是活到了点子上？有钱的是不是活到了点子上？有名气的人是不是活到点子上？也许是，也许不是。这真是各人饮水，冷暖自知，别人还真说不出来。不过，对下面几个问题的回答可以用来判断一个人是不是活到了点子上：你喜欢自己正在做的事情吗？你想到正在做的事情会充满热情吗？你周围有朋友赞赏你正在做的事情吗？（注意，不是羡慕，是赞赏，羡慕可能是因为你做的事情能够带来钱或名声，赞赏是因为你做的事情有意义）你做的事情能够给心灵带来充实吗？你有真正爱的人和爱你的人吗？如果你对这些问题的回答是肯定的，那说明你活到点子上了。

按照上面的标准，我发现很多有权、有钱、有名气的人并没有活到点子上，因为这些人通常想得到更大的权、更多的钱、更炫的名，并为此而苦不堪言。权、钱、名气成了他们人生沉重的负担，这些看上去耀目的负担压得他们喘不过气来。毕竟，面对权、钱、名时，能够处置坦然、得失自如的人并不多。尽管权、钱、名在大部分人眼中是好东西，但一定不是活到点子上的必要条件。

为了讲清楚什么叫活到点子上，我给大家讲两个故事。我的一个朋友有很强的经商能力，他如果做房地产生意的话，一定能够取得成功。但他梦想的生活是草原、天空和马。于是，在捞到第一桶金后，他立刻停止了商场的搏击，到内蒙古买了一片连绵起伏的草原，然后盖起一个很美的小度假村，养了十几匹好马。每当春天来临，他就去自己的草场，过起海子想要的典型生活：“做一个幸福的人，喂马，劈柴……”小度假村每年能够给他带来一些收入，去掉运营成本后还能剩下十几万，用来作为家庭的花销。他找了一个自己深爱的女人，女人也非常喜欢这种生活方式，所以两人在草原上流连忘返。第二个故事是关于一本书，叫《背包十年》，是一个叫小鹏的人的自述。小鹏是一个不喜欢工作但喜欢旅游的人，他最长的工作时间也就是三个月，每次工作只是为了给旅游筹资。只要拿到工资，他就立刻加入驴友的队伍，并以这样的方式走遍了世界各地。他的文字和摄影作品被一些国家的旅游局看上，他们给他提供资助，使他成了职业的旅行家。就这样，他圆了自己一辈子旅游的梦想。他有没有一个喜欢的女人我不知道，但我相信他一定有爱他的人与他同行。

讲完以上两个故事，我就可以来做一下总结了。一个活到点子上的人大概需要三个要素：第一，有一个自己真心真意喜欢的事情，而且这个事情能带来经济收入。当然，如果你是富家子弟，经济收入可以免谈，但其他人就没法免俗了。比如说我的朋友喜欢草原，但同时还得靠度假村获得一定的经济收入，否则就活不下去；小鹏如果没有获得资助，也无法以职业旅行家的身份旅行下去。人毕竟不能不食人间烟火。如果不是出于喜欢，那做任何事都会觉得痛苦。第二，对于财富、名望、权力没有过分的兴趣，更愿意追求内心的充实和满足。对财富欲望大的人往往烦恼无限多，也就不可能活到点子上。钱对于生活是必要的，但钱一定不能成为生命的唯一目标。第三，有一个特别值得你一心一意爱的人和你同行。这个人不是你的父母，不是你的朋友，而是你的爱人。人心之所以会“撒野”，常常是因为找不到自己的另一半。如果你真的找到了一个自己无比喜欢的人，你就会和她/他一心一意地经营生活。这时候，就算再平淡的生活也充满了欢乐。

有一个你喜欢并且能带来经济收益的事情；对财富没有太多的贪欲，把更多的精力放在追求内心充实上；有一个你深爱并且愿意一直陪着你的人。具备这三个要素，你就算真正活到了点子上。我把这个观点放到微博上，后面跟了几万条评论，大部分人说这三个要素看上去简单，实际上太难做到了。这表明大部分人都没有活到点子上。其实，能做到三个要素中的任何一个，生命就会减少很多遗憾了。

---

摘自：互联网

---

## File: src/posts/2012-08-21-tsinghua-universitys-reminder-to-college-students.md

[Binary file]

---

## File: src/posts/2012-08-27-attitude-to-technology.md

[Binary file]

---

## File: src/posts/2012-08-29-the-programmer-leveling-raiders.md

[Binary file]

---

## File: src/posts/2012-10-11-how-to-recruit-outstanding-software-engineers.md

---
title: 如何招聘到优秀的软件工程师
date: 2012-10-11
categories:
  - reading
---

在科技行业快速发展的过程中，市场对优秀工程师的需求越来越旺盛，这也导致了工程师的紧缺。美国科技博客VentureBeat本周刊登了科技行业招聘者Megan Hopkins的文章，谈论了如何在这样激烈的人才大战中招聘到心仪的目标。

以下为文章全文：

近期，我的公司VigLink的所有人共同给我们的一名工程师制作了生日贺卡。这听起来像是标准的办公室文化，但这名工程师实际上并不在办公室中。他在国家的另一端，目前还没有开始给我们工作，甚至在未来2个月内也不会开始给我们工作。

我们不是为生日而疯狂，而是为优秀的工程师而疯狂。

尽管许多雇主在招聘周期的最后阶段都会发出邀请信，但实际上科技行业招聘并没有保障，任何时候都有可能出现各种变数。对于这名工程师，许多其他公司也采取各种方法与他接触。在两个月时间内，我一直与这名工程师保持联系，并令他满意。我研究了多方面问题，甚至包括了解本地学校，帮助他的子女入学。

近年来，科技行业招聘正变得越来越无情。如果你想要成功，那么就需要知道如何参与竞争。我在这一行业已工作了7年多时间。在VigLink，我们建立了世界级的工程团队。

以下是在招聘“全明星”级别工程人才时需要牢记的注意事项：

1. 如果希望签下一名候选者，那么提醒他关注长远的职业成功

  尽管搬家费等福利看起来很好，但这些福利不会在几个月到几年之后仍带来吸引力。因此，招聘者应当避免短期的激励，而是专注于长期发展。

2. 不要仅仅因为候选者表示同意，就假定他们会来你的公司工作

  直到候选者最终出现在你的公司，并开始工作，否则没有任何事情是确定的。即便如此，其他公司和招聘人员也很可能联系你的候选者，了解他们在新公司工作的情况。如果他们发现候选者心存不满，那么将会趁虚而入。

3. 在行业内结交朋友

  有一句老话这样说：“接近你的朋友，更要接近你的敌人。”这句话也适用于科技行业招聘。如果竞争对手不了解你，认为你是一个不讲情面的威胁，那么他们将会说你和你公司的坏话。如果保持友善，那么竞争对手在挖人时将会心存愧疚。

4. 注意保密

  尽管你会想要谈论正在尝试招聘的候选者，但需要注意，避免向其他公司的“朋友”或中介机构提到候选者姓名，除非你已经做出了最终决定。市场对某些技能的需求非常旺盛，而你也没有办法阻止竞争对手抢夺你心仪的对象。

5. 如果你决定不招聘某一候选者，那么推荐他们去其他创业公司

  这种情况往往是由于候选者不适合你的公司，而并不意味着他们在其他地方没有竞争力。分享候选者是在行业内获得盟友、建立声望的好方法。

6. 尽管我总是建议你公平竞争，但要知道其他人可能会采用肮脏的伎俩

  例如，有的招聘人员会“不经意地”透露，一名候选者正在考虑他的提议，但实际情况可能并非如此。如果这样做，那么候选者当前的雇主可能会受到影响，使得候选者的工作出现不稳定。

总而言之，不同的招聘情况将存在不同的挑战。不过，在成功吸引优秀工程师前来工作之后，你会感觉到所做的一切都是值得的。

---

>部分内容摘自：新浪记事

---

## File: src/posts/2012-10-19-reading-three-books-professional-finance-and-biography.md

---
title: 周鸿祎：读三种书–专业、财经与传记
date: 2012-10-19
categories:
  - reading
---

我年轻时比较喜欢读书，看古典文学。现在工作太忙，读书就比较功利，都是管理、经营上的书，而且读得也很快，一周能看两本。当然网络时代如微博信息传递更快，但信息不等于智慧，好的杂志报纸毕竟是作家写出来的，还是书里有智慧。

**读三种书：专业、财经与传记**

我读三方面书，第一是专业书籍，你在这个专业需要保持持续不断的学习，特别是技术领域互联网变化非常快，编程语言数百种各种各样新的系统层出不穷，读专业的书是在巩固自己的基础。

第二是财经书籍，我更多的时间在做公司，国内高水平财经书籍比较少，所以我读国外翻译的比较多，像《定位》、《营销债》、《柔道战略》、《创新者的解决方案》、《创新者的疑惑》等等。国内的喜欢读吴晓波写的《大败局》、《激荡三十年》。《大败局》那本书非常好，以史为鉴，很多失败的教训让我学到不少东西。

第三我喜欢读名人传记，读国外名人传记有一个好处，这些书一般不会为尊者讳，所呈现的是一个很真实的企业家，他的优点、缺点、苦恼以及一些个性上的问题，看这种读物有助于个人励志，觉得我不是那么差，我有机会去努力。

《马云的内部讲话》也很好，非常真实，不是一个神话的马云，没有任何粉饰，值得创业者研究学习。也很佩服这种内部真实经验的分享。现在成功学的书我建议大家不要读，我也看过两本，看着有道理但生活中不会用。

**看毛选：谁是朋友敌人？**

偶尔翻一下毛选觉得收益很大《毛泽东选集》第一卷开篇第一句话：“谁是我们的朋友，谁是我们的敌人，这个问题是革命的首要问题。”我想换一种说法，对于做互联网产品的人来说，“谁是我们的用户，谁是我们的竞争对手，这个问题是从事互联网的首要问题。”我经常鼓励员工多看长征，能从中得到很大的鼓舞，大家想象一下，那样的队伍要钱没钱，要枪没枪，破破烂烂，单靠一个理想从弱小走到强大，所以对我们是一个鼓励。

**看乔布斯：他就是一本书**

我读过能找到的几乎所有乔布斯传记，比我更熟悉苹果历史的中国人恐怕也不多。乔布斯本人就是一本很厚的书，不是赶时髦的畅销读物，更非成功学，值得经常读反复读深入思考带着问题去读，你的经验阅历越多读的感受就越多。

我是做互联网产品出身的，所以我研究乔布斯时，可能比其他人更有体会。我自己有很多经验，当然也有很多失败，这对我研究乔布斯有很大帮助。如果一个人从来没有做过企业，或者说从来没有做过产品，去读乔布斯的书，可能就像一个没有武功的人去读一本武林秘籍。

**推荐书籍：以小博大只能靠颠覆**

我给大家推荐两本书：一本叫《柔道战略》，讲的是找对方最薄弱的环节，以小博大。另一本叫《颠覆式创新》，讲的是怎样改变游戏规则。一只大鳄鱼，你要打败它，在水里抱着鳄鱼打，肯定打不过。但是，你把鳄鱼引到树上，猴子都能把它收拾了。互联网上，小公司打败大公司，改良没有出路，只能靠颠覆。

我还推荐业内业外人士都读一读克里斯·安德森的著作《免费：商业的未来》，该书主题：“免费就是这样一种商业模式，它所代表的正是数字化网络时代的商业未来。”(@闫嵩达注：这正是360推出免费杀毒的根本动因。)

---

>摘自：网易

---

## File: src/posts/2012-11-02-how-to-lead-smart-people.md

[Binary file]

---

## File: src/posts/2013-05-19-thinking-that-you-are-in-a-group-in-fact-you-are-wasting-your-youth.md

[Binary file]

---

## File: src/posts/2013-06-24-how-to-operate-wechat-media-platform-accounts.md

---
title: 如何运营微信公众账号
date: 2013-06-24
categories:
  - wechat
  - reading
---

我说：个人觉得微信公众平台最重要的一点就是：用心！用心对待每一个订阅者！

经常有很多朋友和学员在微信公众号留言，问我一些微信运营的经验心得，今天我花点时间，将自已做微信公众账号运营的心得总结了一些，供朋友们参考和指点。

* 明确每一次沟通、互动、推送的对象是谁，读者对这个人越了解，信任度就越高，包括他的公司职位、姓名、联系方式。

* 简单就是力量，不要把自己的微信公众账号变成万能的功能应用，可以免费听音乐、机器人，这些功能只会淡化企业核心价值，请删掉这些功能，简单就是力量。

* 微信营运的目的是维护顾客关系，用99%的时间培养顾客的信任感。不要老想着促销，一月拿出29天的时间培养顾客，1天的时间促销可能更有效。请暂时忘记销售。

* 微信营销没有任何营销秘诀，拼的是投入和执行力，想不投入就想获取大量粉丝是不可能的，不要只盯着3个月获取90万粉丝的案例，先想想人家投入了多少资金，投入了多少人力，如果你不想投入太多资金，你可以选择投入时间，再加上执行力到位，你的目标一样可以实现。

* 不要忙于每一天推送大量的内容给潜在顾客，创造可以跟读者沟通的话题，你要知道所有价值都来自沟通，推送再好的内容，不如跟读者认真细致的沟通一次。

* 想和读者创造更多的沟通机会，就要问读者更多的问题。问一问读者喜欢什么时间接收内容，希望读者多提意见等。

* 不要被那些3个月100万粉丝的案例冲昏了头脑，粉丝再多，如果不能转化成价值，依然毫无用处。我们需要的粉丝是那些目标粉丝，粉丝的质量比粉丝的数量更重要。

* 发布文章不一定要长篇大论，最好能引发读者的思考，一般篇幅在三五百字左右。

* 关注竞争对手的微信，如果你关注了50个竞争对手的微信，就会有50个账号在教你怎样做好微信营销。你要做的就是优化他们所有的方法。记住：竞争对手是最好的老师。

* 新手开始学习玩微信，从关注优质的微信开始学习，记住那些优秀玩家的方法，最好每天都能拿笔记下来，自已对比一下哪些地方可以做得更好，更有利于自已以后的运营。

* 认真分析自已的行业，是否需要用微信公众平台，其实很多中小企业和个体老板，只要利用微信朋友圈就可以做生意，比如理发店、美容店、餐饮店、快餐店等等。具体分析请看我写的淘宝卖家如何做好微信营销。

* 怎样创作内容，内容一定要原创吗，不一定，如果你不想打造行业第一领袖的地位，内容不一定要原创，可是你一定要做一件事情，就是要加入自已的观点！

* 我们尊重顾客，可是千万不要讨好顾客，取消关注的迟早会取消关注，只要你一直提供价值，留下的总会留下来。

* 微信营销要靠渠道，拥有渠道的好处就是，每一天你都能获得稳定的粉丝，而不是一天进500粉丝，再过3天就没有粉丝关注。

* 做微信营销是做个人微信还是做微信公众账号，我想这两个并不矛盾。可以兼顾运营，如果你本人运作1到2个人的店面的话，建议用个人微信进行运作，如果是大店的话，一定要用上公众账号。

* 不要被微信营销案例冲昏头脑，那些100万的粉丝案例不真实，那些很真实的案例，你需要分析一下，他们投入了多少人力和物力，现在的营销案例忽悠人的多，自已认真去做好自已的微信运营。

* 做微信营销见效很慢，粉丝沉淀就要花很多时间，通常需要3个月沉淀的时间，才能收到一些效果和利润，最重要的就是一直坚持下去。

* 要想在很短时间里获取大量的粉丝，必须靠媒体。请记住：成功靠媒体。当然，要结合自身的实际情况选择合适的媒体，是纸媒还是网络媒体或者广播电视媒体。

* 坚持很重要。你写一篇文章，读者不一定认可你，可是当你写到50篇至100篇的时侯读者一定会认可你，所以坚持最重要。

* 重视互动。因为它不像微博，可以吸引大量的人转发和评论，只有通过与顾客的沟通来取得顾客的信任。

* 在准备营销产品之前，做好整个产品营销策划，推送的内容最重要，因为内容会直接影响读者的购买，内容预热是最好的方法。

* 现在大家有一个误区，希望一切都通过微信营销来实现，最终要顾客购买产品之前，不要忘了让顾客拔打订购电话，人与人交流最能解决购买当中的疑问。

* 做微信营销，最好结合腾讯的其他产品一起使用，如QQ和QQ空间一起使用，达到的营销效果更好，因为未来的移动互联网营销将会是走向人脉关系链的营销。

* 做微信营销就等于在做一本行业精刊，关键在内容的质量。高质量的内容会得到众多人的分享，会形成病毒营销。小而美的内容策略。

* 微信的功能本身已经固定了的，真正能使微信营销发挥作用的是使用微信营销后面的那个人。

* 有人问：微信是不是营销工具？我说，你认为是就是，你认为不是就不是，一把刀你用它来杀人它就是杀人工具，你弃之不用就是一块破铁。不要与人争论，腾讯心知肚明。

* 很多草根想按微博大号再玩微信，想弄个微信大号，这样的做法行不通，除非你能在很短的时间里获得大量的粉丝，并且是正规的操作，不正规的操作很容易被腾讯封掉，微信营销更适合企业。

* 做好精准的关键词回复功能，这样能指导读者，通过什么样的方式更了解你本人和你的企业，获得读者的信任。

* 针对微信的认证对提升企业的信任度很重要，所以想尽一切方法早一点通过微信认证，微信认证的条件是：500的粉丝量和一个微博认证。

* 千万不要一个人坐在家里学习微信营销，要经常去一些微信营销的qq群，看一看大家都在聊什么，在这些群里你能学到很多东西。

* 推送，不一定要每一次都推送文章，推广一些小的知识和技巧，也是很好的方法，只要能帮助到潜在顾客和读者都可以。我最近订阅了一个心理学习的微信账号，每一次都推送一条跟微博一样的内容给我，我很喜欢，因为信息量小，不会影响我的生活，并且可以学到新的知识，我很喜欢这样的公众账号。

* 我见到很多人，经常用微信向自已的朋友推销产品，这是错误的做法。这么做可能会让你失去这个朋友，如果你想利用微信做生意，请重新申请一个账号，用来销售产品，千万不要向自已的朋友推销产品，这样会让朋友感到你这个人太没有人情味，太功利什么都跟着利益跑，很多朋友都会离你而去。

* 微信的内容，选择合适的图片很重要，经常去和自已相关的微博里获取一些行业里的图片，做微信营销要重视细节。

* 推送内容，晚上推送内容最好，因为这些时间读者有足够的时间来阅读，白天推送内容，适合做产品的促销，当时顾客可以订购产品，带来产品真正的销售。

* 企业先学好服务500、1000个微信客户，用户多少不代表营销能力，仅仅是一个数量，用户的互动价值才是微信营销的核心，多创造和读者沟通的话题，让整个公众账号活跃起来。

* 水不流动就变成的死水，公众账号没有活跃度就是一个死号，没有任何价值。

---

## File: src/posts/2013-08-09-detailed-php-ini-configuration-file-in-Chinese.md

[Binary file]

---

## File: src/posts/2013-10-09-php-parses-json-and-xml.md

---
title: PHP 解析 JSON 与 XML 数据
date: 2013-10-09
categories:
  - php
---

与大多数流行的 Web 服务如 twitter 通过开放 API 来提供数据一样，它总是能够知道如何解析 API 数据的各种传送格式，包括 JSON，XML 等等。

PHP解析JSON数据

```php
$json_string = '{"id":1,"name":"foo","email":"foo@foobar.com","interest":["wordpress","php"]} ';

$obj=json_decode($json_string);

echo $obj->name; //prints foo
echo $obj->interest[1]; //prints php
```

PHP解析XML 数据

```php
$xml_string = "<?xml?version='1.0'?><users><user id='398'><name>Foo</name><email>foo@bar.com</name></user><user id='867'><name>Foobar</name><email>foobar@foo.com</name></user></users>";

//load the xml string using simplexml
$xml = simplexml_load_string($xml_string);
 
//loop through the each node of user
foreach ($xml->users as $user)
{
    //access attribute
    echo $user['id'];

    //subnodes are accessed by -> operator
    echo $user->name;
    echo $user->email;
}
```

---

## File: src/posts/2013-12-20-ubuntu-commonly-used-commands.md

---
title: Ubuntu 常用命令大全
date: 2013-12-20
categories:
  - wiki
  - linux
  - ubuntu
---

最近搞了一台VPS，用起来很爽啊。受益匪浅！

## 软件

查看软件xxx安装内容

`dpkg -L xxx`

查找软件

`apt-cache search 正则表达式`

查找文件属于哪个包

`dpkg -S filename apt-file search filename`

查询软件xxx依赖哪些包

`apt-cache depends xxx`

查询软件xxx被哪些包依赖

`apt-cache rdepends xxx`

增加一个光盘源

`sudo apt-cdrom add`

系统升级

`sudo apt-get update`
`sudo apt-get upgrade`
`sudo apt-get dist-upgrade`

清除所以删除包的残余配置文件

`dpkg -l |grep ^rc|awk ‘{print $2}’ |tr [””n”] [” “]|sudo xargs dpkg -P –`

编译时缺少h文件的自动处理

`sudo auto-apt run ./configure`

查看安装软件时下载包的临时存放目录

`ls /var/cache/apt/archives`

备份当前系统安装的所有包的列表

`dpkg –get-selections | grep -v deinstall > ~/somefile`

从上面备份的安装包的列表文件恢复所有包

`dpkg –set-selections < ~/somefile sudo dselect`

清理旧版本的软件缓存

`sudo apt-get autoclean`

清理所有软件缓存

`sudo apt-get clean`

删除系统不再使用的孤立软件

`sudo apt-get autoremove`

查看包在服务器上面的地址

`apt-get -qq –print-uris install ssh | cut -d”’ -f2`


## 系统

查看内核

`uname -a`

查看Ubuntu版本

`cat /etc/issue`

查看内核加载的模块

`lsmod`

查看PCI设备

`lspci`

查看USB设备

`lsusb`

查看网卡状态

`sudo ethtool eth0`

查看CPU信息

`cat /proc/cpuinfo`

显示当前硬件信息

`lshw`


## 硬盘

查看硬盘的分区

`sudo fdisk -l`

查看IDE硬盘信息

`sudo hdparm -i /dev/hda`

查看STAT硬盘信息

`sudo hdparm -I /dev/sda`

`sudo apt-get install blktool`
`sudo blktool /dev/sda id`

查看硬盘剩余空间

`df -h`
`df -H`

查看目录占用空间

`du -hs 目录名`

优盘没法卸载

`sync fuser -km /media/usbdisk`


## 内存

查看当前的内存使用情况

`free -m`


## 进程

查看当前有哪些进程

`ps -A`

中止一个进程

`kill 进程号(就是ps -A中的第一列的数字) `

`killall 进程名`

强制中止一个进程(在上面进程中止不成功的时候使用)

`kill -9 进程号`
`killall -9 进程名`

查看当前进程的实时状况

`top`

查看进程打开的文件

`lsof -p`

ADSL 配置 ADSL

`sudo pppoeconf`

ADSL手工拨号

`sudo pon dsl-provider`

激活 ADSL

`sudo /etc/ppp/pppoe_on_boot`

断开 ADSL

`sudo poff`

查看拨号日志

`sudo plog`


## 网络

根据IP查网卡地址

`arping IP地址`

查看当前IP地址

`ifconfig eth0 |awk '/inet/ {split($2,x,":");print x[2]}'`

查看当前监听80端口的程序

`lsof -i :80`

查看当前网卡的物理地址

`arp -a | awk '{print $4}' ifconfig eth0 | head -1 | awk '{print $5}'`

立即让网络支持nat

`sudo echo 1 > /proc/sys/net/ipv4/ip_forward`
`sudo iptables -t nat -I POSTROUTING -j MASQUERADE`

查看路由信息

`netstat -rn sudo route -n`

手工增加删除一条路由

`sudo route add -net 192.168.0.0 netmask 255.255.255.0 gw 172.16.0.1`
`sudo route del -net 192.168.0.0 netmask 255.255.255.0 gw 172.16.0.1`

修改网卡MAC地址的方法

`sudo ifconfig eth0 down #关闭网卡`
`sudo ifconfig eth0 hw ether 00:AA:BB:CC:DD:EE #然后改地址`
`sudo ifconfig eth0 up #然后启动网卡`

统计当前IP连接的个数

`netstat -na|grep ESTABLISHED|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -r -n`

`netstat -na|grep SYN|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -r -n`


## 服务

添加一个服务

`sudo update-rc.d 服务名 defaults 99`

删除一个服务

`sudo update-rc.d 服务名 remove`

临时重启一个服务

`/etc/init.d/服务名 restart`

临时关闭一个服务

`/etc/init.d/服务名 stop`

临时启动一个服务

`/etc/init.d/服务名 start`


## 设置

配置默认Java使用哪个

`sudo update-alternatives –config java`

修改用户资料

`sudo chfn userid`

给apt设置代理

`export http_proxy=http://xx.xx.xx.xx:xxx`

修改系统登录信息

`sudo vim /etc/motd`


## 中文

转换文件名由GBK为UTF8

`sudo apt-get install convmv convmv -r -f cp936 -t utf8 –notest –nosmart *`

批量转换src目录下的所有文件内容由GBK到UTF8

`find src -type d -exec mkdir -p utf8/{} “; find src -type f -exec iconv -f GBK -t UTF-8 {} -o utf8/{} “; mv utf8/* src rm -fr utf8`

转换文件内容由GBK到UTF8

`iconv -f gbk -t utf8 $i > newfile`


控制台下显示中文

`sudo apt-get install zhcon 使用时，输入zhcon即可`


## 文件

快速查找某个文件

`whereis filename`
`find 目录 -name 文件名`

查看文件类型

`file filename`

显示xxx文件倒数6行的内容

`tail -n 6 xxx`

让tail不停地读地最新的内容

`tail -n 10 -f /var/log/apache2/access.log`

查看文件中间的第五行（含）到第10行（含）的内容

`sed -n '5,10p' /var/log/apache2/access.log`

查找包含xxx字符串的文件

`grep -l -r xxx .`

查找关于xxx的命令

`apropos xxx man -k xxx`

将本地文件拷贝到服务器上

`scp -rp /path/filenameusername@remoteIP:/path`

将远程文件从服务器下载到本地

`scp -rp username@remoteIP:/path/filename/path`

查看某个文件被哪些应用程序读写

`lsof 文件名`

把所有文件的后辍由rm改为rmvb

`rename 's/.rm$/.rmvb/' *`

把所有文件名中的大写改为小写

`rename 'tr/A-Z/a-z/' *`

统计当前文件个数

`ls /usr/bin|wc -w`

统计当前目录个数

`ls -l /usr/bin|grep ^d|wc -l`

显示当前目录下2006-01-01的文件名

`ls -l |grep 2006-01-01 |awk `{print $8}``


## 压缩与解压缩

解压缩 xxx.tar.gz

`tar -zxvf xxx.tar.gz`

解压缩 xxx.tar.bz2

`tar -jxvf xxx.tar.bz2`

压缩aaa bbb目录为xxx.tar.gz

`tar -zcvf xxx.tar.gz aaa bbb`

压缩aaa bbb目录为xxx.tar.bz2

`tar -jcvf xxx.tar.bz2 aaa bbb`

解压缩 RAR 文件

```shell
sudo apt-get install rar unrar
sudo ln -f /usr/bin/rar /usr/bin/unrar
unrar x aaaa.rar
```

解压缩 ZIP 文件

```shell
sudo apt-get install zip unzip
sudo ln -f /usr/bin/zip /usr/bin/unzip
unzip x aaaa.zip
```


## 日期和时间

设置日期

`date -s mm/dd/yy`

设置时间

`date -s HH:MM`

将时间写入CMOS

`hwclock –systohc`

读取CMOS时间

`hwclock –hctosys`

从服务器上同步时间

`sudo ntpdate time.nist.gov`

`sudo ntpdate time.windows.com`


## 数据库

mysql的数据库存放在地方

`/var/lib/mysql`

从mysql中导出和导入数据

`mysqldump 数据库名 > 文件名 #导出数据库`

```shell
mysqladmin create 数据库名 #建立数据库
mysql 数据库名 < 文件名 #导入数据库
```

---

## File: src/posts/2014-02-04-how-to-write-a-good-PRD.md

[Binary file]

---

## File: src/posts/2014-07-30-how-is-the-code-farmer-made-1.md

---
title: 码农是如何炼成的（1）
date: 2014-07-30
categories:
  - reading
---

有很多朋友问我学编程需要看什么书，需要学什么语言，需要进行专业培训不等等，其实在我看来每个人都是可以成为码农的，当然除了有毅力够专注以外，还有许多东西可以说。

如何成为一个合格的码农？是参加培训还是自学？



我觉得自学或者参加培训都可以，但是请记住：

- 请以一个完美主义者要求自己的代码，代码不是写得越多越好，但是要反复斟酌和修改。

  通常在很多时候我们先关注的是实现某个功能，如果你能在完成功能后再回过头去进行代码检测和优化，尝试其他路径和方法不仅可以对程序进行升级也是对自己进行提升。

- 务必多思考，思考的时间可以在吃饭时，也可以在坐车时，睡觉前思考也相当不错，有时候解决不了的问题在梦中反而会灵光一闪。

- 多看些别人的代码，虽然亲手实践的作用是最重要的，但好的代码能使人更快的进步，记得早年程序员招聘时有一个必考项目就是给你看一段代码，让你说出运行结果，如果你无法看懂和理解，通常是会挂掉的。

至于学什么语言，并不是特别重要，因为我们接触的都是高级语言，语法和函数其实就是英语，核心是能够清楚解决问题的路径和逻辑，那么基本是一通百通，我最早是学 C++ 的，后来 windows 出来后学了 VB，进入互联网后最快上手的是 ASP ，因为和 VB 非常接近，08年为了玩 discuz 转 PHP，也只用了三个晚上看了些基本语法就开搞了。所以有啥机会就学啥，不用太 care 语言本身的。

码农需要具备什么样的基本素质？

很多朋友以为做码农必须是计算机系出来的，其实就我身边那些技术牛逼的哥们学什么的都有，最少的反而是计算机系出来的，为什么？国内很多计算机系培养的学生都是不动脑筋，只会依样画葫芦的，除了码字的速度更快以外，光会写不会想，在其他方面很难有长进，也就是说他们只会种地，不知道怎么种水果蔬菜。

我认为码农学习一门语言以外，最好是熟悉行业服务的业务专家，所有的程序一定是为解决某个行业问题开发的，因此如果你了解业务流程，那么在编程的时候逻辑会更加清晰，也能够写出更加优美高效的代码。而这些通常是需要在日常生活中观察、体验和积累的。

事实上很多时候一些接地气的应用也都是在行业专家指点下产生的，比如我们常用的打车应用，就是在一些有想法的出租车司机捣鼓出来的雏形下产生的。

---

>摘自：@ZTalk青龙老贼

---

## File: src/posts/2014-07-30-how-is-the-code-farmer-made-2.md

[Binary file]

---

## File: src/posts/2014-07-30-how-is-the-code-farmer-made-3.md

---
title: 码农是如何炼成的（3）
date: 2014-07-30
categories:
  - reading
---

作为若干个中小型公司的产品技术负责人，我也面试过不少应届大学生，筛选简历的时候我并不 care 他是什么大学的（当然221工程的一般也很少会来投），我只看他掌握了什么，参与了什么，然后会在面试的时候问他在开发中学习了什么。当然那些标注X鸟培训的一律不要。



我对国内大部分大学计算机系的教学都不满意，学校会教学生使用C，使用sql，使用java，甚至也有教 PHP、Ruby 等，但我想问问，有哪个学校真正把为什么要做软件，软件主要解决什么问题，什么样的软件才是合格的软件讲清楚的？

我面试过的学生里，没有一个能说明白这个事。可以想像，做一件事，连这件事的目标，做事的方法都不甚明了的话，光去学习如果使用工具又有什么意义？

另外就是对软件工程的轻视，如果说开发语言是解决软件的零件问题，那软件工程就是如何把这些零件给拼装起来的流水线，它设计的好坏直接决定了最后拼装的速度与效果。大学虽然都会开这门课，但实际作用实在是不敢恭维，有些老师自己都不理解也讲不清楚。

但是这些的重要性甚至超过了数据结构，编译原理等课程，同时这也造成了一些非常奇怪的现象，比如这几年移动互联网火热，移动端的工程师工资水涨船高，比之前做B/S的贵好多，但实际上移动端的技术含量真的有那么高吗？

一个 B/S 的码农，如果前后端都做的话，类似我这样的，需要掌握的技术至少有：

一门高级语言（C#、java、php等）,SQL，XML，WebService/WCF，Javascript(JQuery)，CSS，HTML，还不算可能使用的大量第三方框架，JS框架和浏览器兼容性等附加问题。我想大部分做移动端开发的工程师都不具备上述技能吧。

回过头来说说软件设计，会写代码的并不一定就会设计，世界上可能有天才，只写个半年程序就能做系统架构，但我肯定不是这一类的，相信大部分人也不达不到这样，系统架构不仅是技术级的，更重要的是业务级的，软件设计至少要具备：

1. 对业务有强大的理解与整合能力，能深刻把握需求文字中的重点与非重点，对其中相似的业务进行抽象与剥离，对流程中的敏感点（如权限）有很强的把握能力。

2. 对技术有充分的认知与储备。认知我就不说了看悟性，说下储备，世界上技术太多，谁也不可能把所有技术学完，所以在遇到新技术时适当接触一下，当某一天可能需要时，大脑里有个印象，可以再刨出来仔细研究。

3. 强大的编程功底。不得不说中国的软件开发模式很悲哀，经常见到项目负责人被下面的程序员忽悠到死的事。你要求他两天内完成，对方非要说得做一周，你如果不懂，真是一点脾气都没有，但更重要的作用在设计系统数据结构与接口时更好地对工作量进行预估。

但事实上大部分人即便知道这些也最终没能去做架构设计，原因很简单，大部分人受不了写代码的枯燥，做一段时间就跳槽换岗或者混日子。最终只有少部分人是认真用心的写代码，几年下来，自然就掌握了很多设计思路。

虽然被人称作码农，但别真把自己当埋头码代码的农民，用心写代码和用手写代码不是一回事。

---

>摘自：@ZTalk青龙老贼

---

## File: src/posts/2014-07-30-how-is-the-code-farmer-made-4.md

---
title: 码农是如何炼成的（4）
date: 2014-07-30
categories:
  - reading
---


经常有人在后台问为什么只有php的教程，有没有java的，有没有.net的，对于这类问题我实在不知道怎么回答。

* 一是我确实不会这些语言，写不了这类语言的教程；

* 二是在我看来如果你是会java或者.net的，完全可以通过我教程提供的源码以及注解，用自己熟悉的语言来实现功能。



但事实上他们依然写不出来，这是为什么呢？

以前的公司里有个程序员工作大概四五年了，但是开发水平一直很差，曾经有一次我让他做一个新功能，事先还特地很详细的给他讲了整个业务逻辑，给了他两天的时间，结果这哥们通宵不睡觉还是没捣鼓出来，要知道我自己做最多几个小时就完事了……

原因很简单，这哥们只会重复机械的写代码，没有用心去理解里面的业务和逻辑，一旦让他做新的东西就傻眼了。

在第一章里我就说过，对于应用软件程序员来说，基本上只会跟高级编程语言打交道，所以无论是java，还是.net，或者是php，都没有太大区别，甚至你学两年java，再转去php也是很快的。

因为我们需要学习和掌握的是编程思想，但实际上很多人只关注语言和工具，忘记了核心。思想这东西有点抽象，如何在实际中去掌握呢？具体一点说可以这样划分：

1. 片断代码的实现能力，这是基础。比如说对于一张表的查询新增更新删除，对于一个数组的遍历排序等，都属于一个片断代码，这部分跟以前读书背公式一样是死的，很容易掌握的，正常人写上十次八次的过程，应该没有不熟练的。

2. 复杂问题的分解能力。这个是基于1的基础上的，任何一个复杂问题都是由若干个简单问题组合而成，当你掌握了这其中所有简单问题的处理方式后，所需要的就是去体会如何把这些简单问题串联起来解决一个复杂问题。

3. 场景的复制能力。当你掌握了一个复杂问题的解决方案后，可以尝试将其往相似的场景复制。这个过程可能开头比较艰难，但只要你有这个意识，并且不断去尝试，可能经过三个月才勉强成功了三次，我相信从第四次开始你就会感到轻松随意了。简单一点说，这其实是个举一反三的过程。

有了上面三个能力后，用什么语言对你来说就完全不是问题了。所有语言的基本逻辑一定是一样的，区别无非在语法与函数的调用上，而这些东西都可以通过搜索引擎解决。

像我自己开始学 php 代码时，第一天就写了不到10行代码，其余时间全花在了百度上，而后三天就完成了 Discuz 整个模板和后台的个性改造。

事实上我写的微信教程也一直是遵循这个路线在给大家指导的，从简单的文字回复、图文消息回复，到后面通讯录、播放器等完整产品的开发，就是让大家体会从片断代码、简单问题到复杂问题的过程。

至于在我教程基础上开发出类似校讯通这类产品的朋友，恭喜你已经到了第三个境界，你是真心在学习，也真的掌握了编程的核心思想。

跳出编程来看我们平时的生活和工作，这样的过程和方法也是通用的，再复杂的东西也是由一个个细小的部件组成，从了解到理解再到分解最后解决，这个过程是非常有趣的，当你完成这个过程，你会发现。

真正有价值的是你的思想，这部分任何工具都帮不上忙的。

---

>摘自：@ZTalk青龙老贼

---

## File: src/posts/2014-07-30-how-is-the-code-farmer-made-5.md

[Binary file]

---

## File: src/posts/2014-07-30-how-is-the-code-farmer-made-6.md

---
title: 码农是如何炼成的（6）
date: 2014-07-30
categories:
  - reading
---

这一章开始说编码的事，我是一个完美主义者，对代码有一定程度上的洁癖，所以大家可以看到我写的教程非常的整齐。



有人说我生活上能做到不邋里邋遢就不错了，代码上哪可能做得更好？ 但如果想成为一个好的码农，对代码的完美主义情结是你在工作初期最有能力做到的一件事。

而当这件事养成习惯后，不仅不会因为保持“整洁”而浪费时间，反而会在后期的维护中给自己带来极大的便利。

我们可以从下面一些细节开始做起：

程序代码中请尽可能放弃拼音。只要你愿意查，一定能查到英文，请保证每个英文单词拼写正确，用英文的好处在于你真的不能保证每个看你代码的人都懂拼音，而英文是通用的。

慎用简写，简写最好有个约定表。只用大家都明白的，不明白的请尽可能不要简写，我们命名的目的是为了容易懂，你非要整出一个PCO，ICD之类的东西，我保证过了两周后你自己都看不懂。

保证每一个单词的大小写，每一个空行回车，甚至每一个空格都是统一的。说起来容易做起来难，但真习惯了也不是那么的难。相信我，你今后的程序人生会从这一点点小的改变中受益无穷。

多做几次代码重构。这 是码农完美主义者修养中最核心的一环。代码重构不仅仅会使你的代码变得更优雅，更易读，后期更易修改，在我看来，其最最重要的作用在于能够比你再多写三倍 的代码，更能提高你的编码水平。在时间条件的允许下，如果能将一份代码重新编写（比较夸张的重构）三次，你几乎能得到近10倍于代码本身水平的提高。

重构的实际效果可能很多人会有质疑，我现在的水平也很难从原理上解释清楚为何会有这么惊人的效果，恩，可能与古人所说的”温故而知新”有异曲同工之处吧。

以我自己的实际经验来看，重构的感觉就是你在觉得代码有一点点不顺眼或者进行了一些可以合并的复制粘贴时，需要想办法去进行的优化，另外你可能会掌握一些新的技巧，这些技巧是可以在重构中实践的。

当然完美主义者的修炼不仅仅会体现在我上面的说的地方，而是一种实实在在把每一件手上的事都做到极致的精神，想成为一个牛逼的码农，先把自己能做到的尽可能做好，就算不是为了公司，也是为了自己。

---

>摘自：@ZTalk青龙老贼

---

## File: src/posts/2014-10-13-php-uses-curl-to-access-https-and-returns-no-result.md

---
title: php 使用 curl 访问 https 返回无结果的问题
date: 2014-10-13
categories: 
  - php
  - holes
---

最近在开发一套自己的微信公众平台SDK ，目的就是为了让自己以后管理更方便。

但在创建菜单时却遇到了问题——使用curl返回无结果！以前的代码如下：

```php
$jsonmenu = urldecode(json_encode($menu));
$url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$this->getToken();

$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$jsonmenu);
$resultj = curl_exec($ch);

curl_close($ch);
```

想来想去，感觉没有什么错的，于是网上查找问题，结果网上也很少有这方面的解答。最后还是回归到了PHP的开发手册。在手册上发现了这样一句话：



在想是不是这个的原因呢？因为毕竟上面写了SSL认证是开启的。于是，更改之后代码变成了：

```php
$jsonmenu = urldecode(json_encode($menu));
$url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$this->getToken();

$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //不验证证书
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //不验证证书
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$jsonmenu);
$resultj = curl_exec($ch);
```

随后，echo 出 $resultj，成功返回数据。

问题解决！

如果有遇到相同问题的朋友们，希望能帮到你们！

---

## File: src/posts/2014-12-08-php-programmers-technical-growth-plan.md

[Binary file]

---

## File: src/posts/2015-01-10-easy-to-confuse-the-four-php-functions-strstr-strrchr-substr-stristr.md

---
title: 容易混淆的四个php函数 strstr strrchr substr stristr
date: 2015-01-10
categories:
  - php
  - wiki
  - thinking
---

`strstr`,`strrchr`,`substr`,`stristr` 这四个字符串操作函数特别让人容易混淆，我经常用的是`substr`,`strstr`，基本上能满足我对字符串的操作。

下面举一些例子，做个笔记，以后不要弄混了。

## strstr 和 strcchr 的区别

`strstr` 显示第一次找到的要查找的字符串，以及后面的字符串。

`strrchr` 显示最后一次找到的要查找的字符串，以及后面的字符串。

```php

$email = 'yansongda@yanda.net.cn@test.com';
 
$domain = strstr($email, '@');
echo "strstr 测试结果 $domain"; // @yanda.net.cn@test.com
 
$domain = strrchr($email, '@');
echo "strrchr 测试结果 $domain"; // @test.com

```

## strstr 和 stristr 的区别

`strstr` 是大小写敏感的。

`stristr` 是大小写不敏感的。

```php

$email = 'yansongDa@yanda.net.cn';
 
$domain = strstr($email, 'd');
echo "strstr 测试结果 $domain"; // da.net.cn
 
$domain = stristr($email, 'd');
echo "stristr 测试结果 $domain"; // Da@yanda.net.cn
```


## strstr 和 substr 的区别

`strstr` 是匹配后截取。

`substr` 是不匹配，根据起始位置，进行截取。

```php
$email = 'yansongDa@yanda.net.cn';
 
$domain = strstr($email, 'd');
echo "strstr 测试结果 $domain"; // da.net.cn
 
$domain = substr($email,-7);
echo "substr 测试结果 $domain";// .net.cn
```


**把这个几个字符串截取函数搞明白了，在开发时可以省不少事。**

---
摘自：互联网

---

## File: src/posts/2015-06-15-mobile-phishing-attack.md

---
title: 移动端钓鱼攻击
date: 2015-06-15
categories: 
  - mobile
  - reading
---

今天，在微博上看了一篇《微信和淘宝到底是谁封谁》的文章，我觉得文章中逻辑错乱，所以，我发了一篇关于这篇文章逻辑问题的长微博。后面，我被原博 主冷嘲热讽了一番，说是什么鸡汤啊，什么我与某某之流的人在一起混淆视听啊，等等。并且也有一些网友找我讨论一下相关的钓鱼式攻击的技术问题。所以，我想 写下这篇纯技术文章，因为我对那些商业利益上的东西不关心，所以，只谈技术，这样最简单。

**首先说明一下，我个人不是一个安全专家，也不是一个移动开发专家，按道理来说，这篇文章不应该我来写，但是我就试一试，请原谅我的无知，也期待抛砖引玉了，希望安全的同学斧正。**

关于钓鱼式攻击，其实是通过一种社会工程学的方式来愚弄用户的攻击式，攻击者通常会模仿一个用户信任的网站来偷取用户的机密信息，比如用户密码或是 信用卡。一般来说，攻击者会通过邮件和实时通信工具完成，给被攻击者发送一个高仿的网站，然后让用户看不出来与正统网站的差别，然后收集用户的机密数据。

## 移动端钓鱼攻击点分析

因为钓鱼式攻击并不新鲜，所以我这里只讲移动方面的。

在移动端，这个事情会更容易干，因为移动端有如下特点：

- 移动端的UI只能有一个应用占据整个屏幕，你只能看到一个应用，而且用户屏幕小，能显示的信息有限，比如浏览器里的网址是显示不全的。这会给钓鱼攻击有很多可乘之机。

- 移动端的平台有其安全的设计。每个应用都是隔离开的，一个应用无法获取另一个应用的数据。而且应用的下载基本上来说都是来自合法的地方。比如 iOS的设备通过App Store下载，每个程序都有自己的签名保证不会被篡改。而且移动端的的应用有各种权限配置，这样也能很大程度提高安全性。

- 移动端的APP有些有些是收费的，所以自然会有盗版需求，虽然在平台上做了一些安全设计，但是并不完美。用户可以越狱，可以root。这给恶意软件有了可乘之机。

下面我们来分析下移动端的用户操作，我们重点关注用户控制权的切换过程（因为这是攻击点）

在移动设备上，基本上来说，用户的控制切换有四种：

- 从一个APP切到另一个APP，也就是我们所谓的唤出APP。

- 从一个APP唤出一个Web，常见为一个嵌入式的WebView或是一个浏览器

- 从一个Web唤出一个APP，这需要浏览器支持一些非标准的HTTP协议，比如skype://之类的。

- 从一个Web到另一个Web，这和Web上的方式差不多。

基本上来说，**黑客的攻击从来都是找这样的转换环节来做文章的，并且需要一个用户非常熟悉的场景（这样用户才会放松警惕）。**

通过观察移动APP的特性，我们可以知道，当用户控制切换时，有下面的这些特性：

- 到另一个APP时，需要用户登录（如果登录的session过期了）

- 当支付的时候，需要用户输入支付信息（信用卡信息、支持密码）

那么用户在移动APP上经常做的事是什么？

- 社交分享：分享到微博，分享到微信等等，分享的时候，可能需要你输入用户名和口令。

- 应用内购：一般来说APP会有两种，一种免费的，一种是收费的，大量的用户都是下载免费的，然后通过什么“开通更多关卡”、“去广告”、“买道具”之类的东西，让用户输入支付信息。Apple的支付的时候也会要用户输入Apple ID的密码。

- 点击链接：有时候，我们收到短信，或是二维码，或是一个微信微博，会让我们去点击一个网站链接，这个网站链接要么就是打开一个网页，要么就是启动应用，要么就是跳转到应用市场去下载应用（如果你没安装）。

所以，一个好的钓鱼式攻击一定会从这些地方入手，然后高仿UI以及交互流程，这个交互流程和用户日常操作的完全一样，让用户无法察觉。任何方式的钓鱼攻击简单来说，会有两种：

- 一种是直接攻击：你下载了一个恶意的APP，或是打开了一个恶意的冒牌APP。

- 一种是中间人攻击：用户控制权转换时的两端都是正规应用，但是中间的过程不是正常的。

## 攻击方式

下面是一些常见的攻击方式：

- 从一个应用唤起另一个应用的方式

- 直接攻击

  当你点击一个社交分享按钮，或是一个支付按钮的时候。就会转到一个页面，这个页面需要你输入用户机密信息（密码或是支付信息），然后再唤起真正的APP。

  一个有恶意的APP可能会让你放松警惕，因为，这个你在安装这个APP的时候，你会发现这个APP根本不需要任何的权限（Android上的），甚 至连网络访问的权限都不要，因为在Android下，App可以通过别的组件访问互联网，比如：恶意应用可能创建一个MediaPlayer Object，然后就可以通过这个对象访问一个URL然后把偷到的信息发送出去。

  你的手机要被安装一个恶意的应用并不难，同样通过社工的方式，比如：盗版，色情，伪装成客服等等通过人性的弱点让你去一些非受信的市场上安装。 iOS设备上的应用也可以不用通过App Store安装（通过itms-services协议，可以通过safari浏览器直接在IOS设备上安装应用程序）。

  还有，人们都是贪小便宜的人，所以，会到某些地方买一些便宜的手机（比如淘宝），现在的高仿手机，翻新的二手手机对于一般人甚至安全专家来说完全没 有识别能力。这些手机中有很大可能藏有恶意程序。你千万不要以为你格式化手机就OK了。今天（2015年4月14日）早上CCTV2台的“第一时间”就说 了一个案例，你可以看看。另外，你可以看看相关的新闻。（另外，你把你的旧手机卖了也要小心，因为你的数据就在里面，旧手机已经成了一个灰色产业链）

  另外，Apple的App需要有一个review过程，这个过程对大众是神秘的，但我觉得应该会包括安全方面的review。不过，这个审核过程可 能也有空子可以钻。比如：在review的时候，这个应用完全正常，但在用户使用的时候，会自己从网站下载一些自己的配置文件而改变行为（更为直接的就是 访问外部网页时在审核时和在用户应用时可能完全不一样，Apple应该完全没有能力审核应用要访问的外部站点）

- 中间人攻击

  我们知道，一个APP唤起另一个APP好多都是用url-scheme的，也就是某种协议，审核这样的协议非常简单，所以如果有恶意的东西在里面基 本上很容易看到。但是，如果某些APP并没有注册自己的url-scheme，或是没有被安装，反而，另一个有恶意的APP注册了这个scheme，那 么，就会导致恶意的APP被唤起来了 **（这就是我为什么在我的微博中说，如果用户没有安装淘宝的客户端，那么，让微信唤起淘宝的客户端时，有可能是另一个有恶意的APP。但是很多人不懂这个事。在iOS下，两个APP通讯正确的做法是“钥匙串机制”）。**

  当然如果有两个应用被注册了同一个scheme，那么，iOS和Android会给出一个选择，让用户来选（注：iOS的系统有可能会直接跳某个 App 上去，不同版本的跳规则不明确，可以认为是随机跳转）。于是乎，恶意的APP就要努力的让自己比正规的APP看起来更像个正规的APP就可以了。

  在Android平台上，这个事可能更变态，只要恶意的应用有两个权限，一个是随手机操作系统在后台启动，一个是task list（然而这两个权限都是一般权限）。这样一来，当你进行两个APP切换时，恶意程序可以通过task list权限监控到，然后自己马上先于正规的app出现，等到收集完用户数据后简单的退出就好了。这个方式只需要你的程序能在10ms以内反应过来（最佳 是5ms左右），人的肉眼根本看不出来。（在iOS设备下，除了jail break后的iPhone可以这么干，正常的都iPhone还没有找到这样的攻击方式）

- 在一个应用内内嵌Web的方式

  这种方式更容易攻击了，现在很多很多应用都是内嵌的Web的形式，你完全不知道打开的网页的网站是什么，因为这些内嵌的WebView你连地址都看 不见。而且无论是iOS或Android，其WebView都可以执行任何的Javascript代码，就算显示URL，URL也可能是被混乱过的，你也 看不全，你也很容易上当。当然，那些使用带SSL证书的支持HTTPS的网站（尤其是EV证书）可以在地址栏上显示一个绿色的标记表示你访问的就是正确网 址，但是并不是所有的浏览器都会这样，比如iPhone的Safari并没有这个提示，所以，你一定要用Chrome。

  更狠的是就算你打开的是一个正确的URL，你依然可能被中间人攻击。尤其是这个网站使用了明文的HTTP协议，而你又喜欢蹭那些免费的WiFi，于 是很容易给把服务器返回给你的网页中做修改，比如，修改网页中login表单或是支付表单提交的网站（想想天朝的网络运营商给你访问的正常的网页弹广告这 事吧）

  关于DNS劫持，有些人觉得这事可能遇不上，因为这是一个全网的问题，如果你有这样的想法你就错了。还是那样，你爱占便宜，蹭上那些没有密码的 WiFi，你完不知道，你连上去的那个WiFi会设置什么样的DNS服务器，你输入了www.taobao.com，但你打开的网站根本就是不是淘定，而 是一个钓鱼网站。你会知道你打开的是错的了么？基本不可能。所以，安全点的网站都是要用HTTPS，但是还是那句话，iPhone的Safari并不会提 示你打开网站的SSL证书合不合法（事实上，在手机上的很多浏览器都不会这提示，只有Chrome会）。

  关于攻击的方式我不想讲太多，还有很多高级+猥琐的方式我也不是完全知道，知道了我也不说，不然，教人犯罪了。

  关于从Web端唤起APP是和，APP唤醒APP的攻击方式基本一样。我就不说了。

## 怎么防范钓鱼式攻击

首先，我们要知道，钓鱼式攻击是一件非常难搞的事。要搞定这个事，一般来说需要四个方面：立法层面、用户培训层面、宣传层面、与技术保全措施层面。

- 教育方面

  打击网钓的策略之一，是试着培养人们识别网钓，并教导怎样处理这些问题。只需要稍稍修改人们浏览习惯的方式，很多问题都可以避免。随着人们越来越认识到网钓者所使用的社会工程学技俩，传统的网钓欺诈技术可能在未来过时。

  * 对别人发来的链接要小心，尤其是让你输入机密信息的链接要小心检查。
  * 到正规的地方买手机，不要贪图小便宜。旧手机在卖前要“物理删除”数据。
  * 不要对手机越狱，不要root。
  * 不要从非信任的地方下载软件。
  * 要小心免费的WiFi。
  * 输入机密数据的时候一定要小心检查。
  * 多依赖一些不同的安全体系，比如：网上支付不要只依赖支付宝，尽量使用信用卡（信用卡千万不要设密码），这样就算是被钓鱼了，你还有一个银行安全的缓冲地带——可以不承认交易。
  * 现在使用手机的频率越来越高，所以，我非常建议你使用更为安全的iPhone手机，一定要打开“查找我的iPhone”功能，然后设上开机密码。iPhone手机可以做到手机丢失了别人都无法使用，包括刷机都刷不了（iOS7以上版本）

  对于一些关键网站，开启两步验证，这样就算你的用户名和密码被钓走了，还有一个动态手机口令做为登录的关卡。

- 技术方面

  * 利用SSL证书来保证从浏览器到网站的访问是现在采用比较多的方式，也是在理论上可行的方式。现代的浏览器都会在URL上放上一个锁的标志，对于EV证书，你会看到浏览器的URL是绿色的（很容易分辨）
  * 另外，像firefox浏览器有一个petname的插件，你可以为你常上的网站设置一些标签。这样，当你打开钓鱼网站的时候，你会发现这些标签没有显示出来，那就有问题了。
  * 关于SSL的CA认证机构，你需要管理好你浏览的那些根证书，有些根证书你需要删掉。
  * 还有一种打击网钓的流行作法是保持一份已知的网钓网站名单，并随时更新。比如PhishTank，以及中国防钓鱼网站联盟。
  * 增加式登录方式。这种方式被美国银行采用，就是说，你可以上传一个你自己知道的图片，而当你打开登录页面里时，输入了自己的用户名后，你会看到你设置的这个图片被显示出来。如果没有或是显示错了，表示你打开的是钓鱼网站。
  * 两步验证，通过用户自设密码+手机动态口令登录（好些网站都在使用Google Authenticator的方式，这有点像公司VPN的动态口令）。

  上述都是PC Web上的防范，然而我们的手机移动端做的并不够好，移动端的安全还是要加油。

- 安全风控方面

  **什么叫安全风控，说白了就是拿钱出来赔偿给被骗的用户，大家相信我，这个事情在基本上所有的公司都会做的，** 也就是说，无论你怎么做安全也无法保证绝对的安全，你只能缓解或是降低用户被骗的数量或概率。所以，几乎所有的公司都会有一笔钱专门用来赔偿。

  在西方国家，用户体验很好，我说一个故事，我有一个妹妹在英国，有一天她到ATM上取钱，取完钱后忘了把卡取出，结果后面的人把她的卡里的钱取走 了，于是她报了警，等警察做完笔录后，她给银行的客服打了个电话说明了情况，本想冻结银行卡的，但是银行方面二话不说就赔偿了她所有的损失。为什么英国的 巴克莱银行这么痛快，是因为他们有风控基金，专门用来处理这样的事的。

  在中国，其实银行和一些大的公司都有这笔安全风控基金，但是，要你非常坚持不懈地申诉，他们才会赔给你，而且还不是全部。要全部的话，我估计你要做一个“刁民”，否则欺负你，没道理。

## 关于微信和淘宝

微信和淘宝到底是谁先屏蔽谁我并不关心，这里面的商业利益我也不关心，微信是不是支持卖东西我也不关心。我关心的是寒冬文章中所说的微信上有淘宝钓鱼的安全问题。

从技术上来说，我觉得要微信和淘宝一起干这事，单方都不行，需要两边的安全专家一起讨论（如果需要，我可以帮你们约）。我这里给一个可能很不成熟的方案，算是抛砖引玉（我不考虑你们之间的商业竞争，我只从用户的角度出发，客户第一）：

>我觉得，从业务上来说，淘宝可以在微信上有一个官方的商城。而淘宝的商家，需要取得微信的认证后入住，才能分享相关的商品或店家链接，对此，商家入住，我觉得可通过微信的服务账号与淘宝的商家后台集成可以做到。

>然后，商家也好，买家也好，他们分享商品只能通过微信官方的商城或是商家的服务账号分享出去，而分享出去的商品信息可以是一个比较 unique的形式（比如有一个不能伪造的官方认证的标签），而用户的支付可以通过内置的微信支付也可以通过内置的支付宝（通过唤起App并不是一个好的 方式，还是应该你们在服务端进行相互的通信）。

>然后微信和淘宝双方通过宣传手段告诉全社会，微信里的商品什么才是正规的，才不是钓鱼的，并给教育用户更为安全地使用手机。

P.S. 我虽然这么说，但从我个人来说，我非常理解微信为了让用户有很好的体验而不让微信成为一个四处都是营销商品的地方。所以，我从个人来说，希望微信不要成为 一个商家的营销地。另外，我也知道阿里对移动端的看重，所以，上述的方案虽然对用户体验和安全都比较好，但是从目前商业利益的情况看来基本无法实现。不过 我这里也只是抛砖引玉了。

面对安全和用户这两个事，你们两个中国最大的互联网公司，应该带头做好榜样，你们都是不缺钱的公司，应该更多的承担起社会的责任， 真正为用户做点什么，而不是整天想着流量入口，互相屏蔽，互相指责，想着自己能有多少用户，这TMD太LOW了，和你们的地位完全不符。所以，从站在用户 的角度上来说，我希望微信和淘宝都能站在用户的角度上思考问题，一起合作来真正的为用户更好的服务。


---

摘自： [酷 壳 – CoolShell.cn](http://coolshell.cn/)

---

## File: src/posts/2015-07-22-php-compile-dont-know-how-to-define-struct-flock-on-this-system.md

---
title: php编译 Don’t know how to define struct flock on this system 解决办法
date: 2015-07-22
categories: 
  - centos
  - php
  - linux
---

在对 php 进行编译安装的过程中出现如下错误：checking for known struct flock definition... configure: error: Don't know how to define struct flock on this system, set --enable-opcache=no

现将解决办法记录

## 报错信息

>checking for known struct flock definition... configure: error: Don't know how to define struct flock on this system, set --enable-opcache=no

## 平台介绍

```shell
OS Version: CentOS release 7.1
Nginx Version: nginx version: nginx/1.4.3
PHP Version: PHP 5.5.26(fpm-fcgi)
```

## 解决办法

```shell
vim /etc/ld.so.conf.d/local.conf # 编辑库文件

/usr/local/lib # 添加该行

:wq # 保存退出

ldconfig -v # 使之生效
```

---

## File: src/posts/2015-08-16-thinkphp-3-2-session-authentication-analysis-and-repair-about-auth-class.md

[Binary file]

---

## File: src/posts/2015-09-03-phpmailer-used-in-thinkphp.md

---
title: 最新 phpmailer 的使用与和 thinkphp 的整合
date: 2015-09-03
categories:
  - thinkphp
  - php
---

## 一、说明

- 基于最新版phpmailer，现在版本为：5.2.10。最新版本请云传送至：http://sourceforge.net/projects/phpmailer/

- 最近开发项目管理系统时，研究而来。

- 写这篇博客的原因是因为发现网上关于phpmailer的文档要么很老，要么不能使用，要么copy，要么不精简。


## 二、单独使用

### 1、安装

首先去上面网址下载phpmailer，下载完成后，解压，拷贝class.phpmailer.php 和 class.smtp.php 两个文件出来。

### 2、整合

将两个文件放入网站根目录下，并新建一个php文件，其代码如下：

```php
<?php

header("Content-type: text/html;charset=utf-8");

require 'class.phpmailer.php';
require 'class.smtp.php';

$body = "<b>哈哈哈哈测试发送成功a </b>";
 
$mail = new PHPMailer();

$mail->Charset = 'utf-8';
$mail->isSMTP(); //开启smtp
$mail->Host = 'smtp.exmail.qq.com'; //设置smtp地址
$mail->Port = '465'; //设置smtp端口
$mail->SMTPSecure = 'ssl'; //加密
$mail->SMTPAuth = true;  //smtp认证开启
$mail->Username = 'system@yanda.net.cn';  //发送者邮件地址
$mail->Password = '123456798'; //密码
$mail->isHTML(); //邮件正文使用html
$mail->addAddress('admin@yanda.net.cn'); //添加接受者
$mail->addAttachment('D:\myweb\www\resume.html', '简历.zip'); //如果没有附件需求，删除该行即可
$mail->setFrom('system@yanda.net.cn');  //设置发送者，一般和username相同
$mail->Subject = '测试phpmailer发邮件';  //邮件主题
$mail->Body = $body; //邮件正文

if(!$mail->Send()) {
    echo "Mailer Error: " . $mail->ErrorInfo;
} else {
    echo "Message has been sent";
}
```

以上代码是最精简的 phpmailer 使用代码。每行代码已经在后面进行了相应的注释，同学们可以直接进行查看其作用。如果还是不知道的话，可以直接留言。

### 3、本地测试如下

发送成功



## 三、与thinkphp的整合

我们知道thinkphp3.2.3版本是带有命名空间的，所以，与TP的整合如下：

1. 为了命名统一规范，我们先将class.phpmailer.php 和 class.smtp.php重命名为PHPMailer.class.php 和 SMPT.class.php。

2. 将这两个文件放入 Application\Common\Lib\Mail 中。

同时在phpmailer.class.php的最上方增加以下代码：

```php

namespace Common\Lib\Mail;

use Common\Lib\Mail\SMTP;
use \Exception;
```

文件看起来像这样：

```php
<?php

namespace Common\Lib\Mail;

use Common\Lib\Mail\SMTP;
use \Exception;
 
……
```

再在 SMPT.class.php 文件的上方加入下面的代码

```php

namespace Common\Lib\Mail;

use \Exception;

```

以上代码的作用是定义文件类的命名空间。加入

`use \Exception;`

是因为两个类中均使用了 php 的自带的 Exception。网上有些代码不能使用的原因就是因为这个。

3. 以上两个文件处理完成之后，我们重新在Mail目录下新建一个文件 mail.class.php 整合整个 phpmailer 类，使其当做 mail 入口类：

```php
<?php

namespace Common\Lib\Mail; 

use Common\Lib\Mail\PHPMailer;

class mail { 

    public function send($to, $subject, $body) {
        $mail = new PHPMailer();

        $mail->isSMTP();
        $mail->Host = C('MAIL_HOST');
        $mail->Port = C('MAIL_PORT');
        $mail->SMTPSecure = 'ssl';
        $mail->SMTPAuth = true;
        $mail->Username = C('MAIL_USERNAME');
        $mail->Password = C('MAIL_PASSWORD');
            $mail->isHTML();
        $mail->addAddress($to);
        $mail->setFrom(C('MAIL_USERNAME'), 'noreply');
        $mail->Subject = $subject;
        $mail->Body = $body;

        if(!$mail->Send()) {
            return array('code'=>0,'msg'=>$mail->ErrorInfo);
        } else {
            return array('code'=>1);
        }
    }
}
```

其中的C函数我想大家不会陌生吧，所以在此就不多说啦。

4. 使用

接下来，我们就可以直接在 Controller 中使用了：

```php
<?php 

namespace Home\Controller;

use Think\Controller;
use Common\Lib\Mail\mail;
 
class ReminderController extends Controller
{
    public function mail(){
        $mail = new mail();
        $body = '<h1>提醒日程</h1>';
        $m = $mail->send('admin@yanda.net.cn', '今日日程', $body);
        if ( $m['code'] == 1 ) {
            echo "success";
        } else {
            echo $m['msg'];
        }
    }
}
```

当然，我们也可以在function.php中写成一个全局函数，具体的实现方法大家可以自己实现哦。当然，如果有什么不明白的还是可以留言的。

---

## File: src/posts/2016-08-31-centos-pptp-vpn-firewalld-or-iptables.md

---
title: Centos 7 搭建 PPTP VPN 服务器（firewalld + iptables 方案）
date: 2016-08-31
categories:
  - centos
  - vpn
  - linux
---

工作原因，好长时间没写博客了。

最近买了台国外的服务器。。此处省略原因。

发个文记录下遇到的坑。

## 一、系统信息

```shell
[root@server etc]# uname -a
Linux server 3.10.0-327.28.3.el7.x86_64 #1 SMP Thu Aug 18 19:05:49 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
```

## 二、安装 ppp pptpd 服务

`yum -y install ppp pptpd`

如果提示 pptpd 没有安装包。那么请

`wget http://dl.fedoraproject.org/pub/epel/7/x86_64/p/pptpd-1.4.0-2.el7.x86_64.rpm &amp;&amp; yum localinstall pptpd-1.4.0-2.el7.x86_64.rpm`

## 三、配置 ppp 配置文件

这一步主要是修改为 Google 的 DNS 方便翻过去

### 1、编辑 options.pptpd 文件
`vim /etc/ppp/options.pptpd`

### 2、找到 ms-dns

```shell
# ms-dns 10.0.0.1
# ms-dns 10.0.0.2
```

### 3、修改 ms-dns

```shell
ms-dns 8.8.8.8
ms-dns 8.8.6.6
```

## 四、配置 ppp 账号文件

### 1、编辑 chap-secrets 文件

`vim /etc/ppp/chap-secrets`

### 2、设置 VPN账号 + 服务类型 + VPN密码 + IP

`yansongda pptpd 123456 *`

以上含义为：

- vpn 账号：yansongda
- vpn 类型：pptpd
- vpn 密码：123456

可连接此 vpn 账号的 IP 地址：*（所有IP）

## 五、配置 pptpd

### 1、编辑 pptpd.conf 文件

`vim /etc/pptpd.conf`

### 2、找到 localip

```shell
# (Recommended)
#localip 192.168.0.1
#remoteip 192.168.0.234-238，192.168.0.245
# or
#localip 192.168.0.234-238，192.168.0.245
#remoteip 192.168.1.234-238，192.168.1.245
```

### 3、修改 localip

```shell
# (Recommended)
localip 192.168.0.1
remoteip 192.168.0.234-238，192.168.0.245
# or
#localip 192.168.0.234-238，192.168.0.245
#remoteip 192.168.1.234-238，192.168.1.245
```

此处请注意，如果您现有局域网的 IP 地址是 192.168.0.1 网段的，请膝盖 localip 和 remoteip 的网段。比如修改为：

```shell
# (Recommended)
localip 192.168.8.1
remoteip 192.168.8.234-238，192.168.8.245
# or
#localip 192.168.0.234-238，192.168.0.245
#remoteip 192.168.1.234-238，192.168.1.245
```

## 六、配置内核转发

### 1、编辑 sysctl.conf 文件

`vim /etc/sysctl.conf`

### 2、修改里面的内容为：

`net.ipv4.ip_forward=1`

### 3、生效

`sysctl -p`

## 七、配置防火墙

### 1、firewalld 防火墙

```shell
firewall-cmd --add-interface=eth0 #此处请将 eth0 更换为服务器外网网卡号
firewall-cmd --add-port=1723/tcp --permanent
firewall-cmd --add-masquerade --permanent
firewall-cmd --reload
 
systemctl restart firewalld
```

### 2、iptables 防火墙

```shell
iptables -P INPUT ACCEPT     # 改成 ACCEPT 标示接收一切请求
iptables -F                     # 清空默认所有规则
iptables -X                     # 清空自定义所有规则
iptables -Z                     # 计数器置0
 
iptables -A INPUT -i lo -j ACCEPT                                 # 允许127.0.0.1访问本地服务
iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT         # 允许访问外部服务
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT         # 允许 ping
iptables -A INPUT -p tcp --dport 22 -j ACCEPT  
iptables -A INPUT -p tcp --dport 1723 -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE #此处请将 eth0 更换为服务器外网网卡号
 
service iptables save
systemctl restart  iptables
```

### 3、坑（ firewall 防火墙）

**如果客户端连接出现 619 或者 “GRE” 之类的错误，但是将 firewalld 防火墙禁用掉后，又可以正常连接，那么请尝试**

```shell
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p gre -j ACCEPT
firewall-cmd --reload
```

## 八、启动所有服务

```shell
systemctl restart firewalld #systemctl restart  iptables
systemctl restart pptpd
```

### 九、在客户端使用账号密码连接 VPN 服务

至此，基于 xl2tpd 的 VPN 服务搭建完毕。

---

## File: src/posts/2016-11-15-centos-l2tp-vpn-firewalld.md

[Binary file]

---

## File: src/posts/2017-12-30-maybe-the-best-alipay-wechat-sdk.md

[Binary file]

---

## File: src/posts/2017-12-30-maybe-the-best-laravel-alipay-wechat-sdk.md

---
title: 可能是我用过的最优雅的 Alipay 和 WeChat 的 laravel 支付扩展包了
date: 2017-12-30
categories:
  - alipay
  - wechat
  - php
  - laravel
---

该文档为 v2.x 版本，如果您想找 v1.x 版本文档，请点击[https://github.com/yansongda/laravel-pay/tree/v1.0.3](https://github.com/yansongda/laravel-pay/tree/v1.0.3)

## 运行环境

- php >= 7.0
- composer
- laravel || lumen >= 5.1

## 安装

```shell
$ composer require yansongda/laravel-pay
```

### 添加 service provider（optional. if laravel < 5.5 || lumen）

```php
// laravel < 5.5
Yansongda\LaravelPay\PayServiceProvider::class,

// lumen
$app->register(Yansongda\LaravelPay\PayServiceProvider::class);
```

### 添加 alias（optional. if laravel < 5.5）

```php
'Pay' => Yansongda\LaravelPay\Facades\Pay::class,
```

### 配置文件

```shell
$ php artisan vendor:publish --provider="Yansongda\\LaravelPay\\PayServiceProvider" --tag=laravel-pay
```

**lumen 用户请手动复制**

随后，请在 `config` 文件夹中完善配置信息。 

## 使用方法

### 支付宝
```php
use Pay;

$order = [
    'out_trade_no' => time(),
    'total_amount' => '1',
    'subject' => 'test subject - 测试',
];

return Pay::alipay()->web($order);

// 下面这个方法也可以
// return Pay::web($order);
```

### 微信
```php
use Pay;

$order = [
    'out_trade_no' => time(),
    'body' => 'subject-测试',
    'total_fee'      => '1',
    'openid' => 'onkVf1FjWS5SBIixxxxxxxxx',
];

$result = Pay::wechat()->mp($order);

```

具体使用说明请传送至 [https://github.com/yansongda/pay](https://github.com/yansongda/pay)

## License

MIT

---

## File: src/posts/2018-01-15-laravel-notification-wechat-template.md

---
title: 基于 laravel 的微信模板消息通知系统
date: 2018-01-15
categories:
  - laravel
  - wechat
  - php
---

不知道大家有没有基于 laravel 的消息通知开发过微信的模板消息通知，我反正是开发过多次了，以前开发总是写在 app 目录下，然后又一坨都写在自定义的 WechatChannel 里面，看这心里总是不舒服。多次之后，就有了这个……

## 运行环境
- PHP 5.6+
- composer

## 安装
1. composer  
`composer require yansongda/larvel-notification-wechat`

2. 注册 serviceprovider （ < laravel 5.5 ）  
`Yansongda\LaravelNotificationWechat\WechatServiceProvider::class`

## 使用
### 例子
```php
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Yansongda\LaravelNotificationWechat\WechatChannel;
use Yansongda\LaravelNotificationWechat\WechatMessage;

class WechatNotification extends Notification
{
    use Queueable;

    public function __construct()
    {
        //
    }

    public function via($notifiable)
    {
        return [WechatChannel::class];
    }

    public function toWechat($notifiable)
    {
        $accessToken = "n2McCJoqWKRi7hJbKFOqftgtU_EX6u2ZOvIi1lpx0fZJ3YW5Oo4iIPZEpi0ecct2lHMagK84xGF5rEm_DSMKrZFfCEZiYw1yZN3nZXzFSlHM-y88sIi5-dYeeCWx9S1iHXWaAJAMCB";

        $data = [
            'first' => 'Test First',
            'keyword1' => 'keyword1',
            'keyword2' => 'keyword2',
            'keyword3' => ['keyword3', '#000000'],
            'remark' => ['Test remark', '#fdfdfd'],
        ];

        return WechatMessage::create($accessToken)
            ->to('oeTKvwYyc3PPAo3As3VRUBGppC0s')
            ->template("0qUpCTpgeYMFbjEKQ4W_D3ZNx5zUzQIfgasgqYX53mg")
            ->url('http://github.com/yansongda')
            ->data($data);
    }
}
```

### 支持的 WechatMessage 方法
- `to(string $openid)`: 设置模板消息接收人的 openID
- `template(string $templateID)`: 设置模板消息的模板 ID
- `url(string $url)`: 设置点击模板消息后跳转 url，选填
- `miniprogram(string $appid, string $pagepath)`: 设置点击模板消息后跳转的小程序，选填
- `data(array $data)`: 设置模板消息数据

### 关于微信 AccessToken
微信发送模板消息时需要传递 accesstoken ，这里有三种方法去处理，方便与您现有的微信开发框架所集成。

- 直接传递 accesstoken 值到 `WechatMessage::create($accesstoken)` 方法中，如上例所示；
- 传递一个 `Yansongda\LaravelNotificatinoWechat\Contracts\AccessTokenInterface` 类到 `WechatMessage::create($CredentialClass)` 方法；
- 直接在 config 文件夹中的 services.php 中添加 `'wechat' => ['appid' => 'xxx', 'appsecret' => 'xxx']`，系统将自动获取 accesstoken 并缓存，缓存的 key 为 `wechatAccessToken您的APPID` 您可以直接通过 laravel 的 Cache Facade 获取缓存的 accesstoken，当然，最保险的方案是通过 `(new Yansongda\LaravelNotificationWechat\Credential($appid, $appsecret))->getAccessToken()` 去获取 accesstoken。

具体可查看源码。

### 说明
1. 如果 `miniprogram` 与 `url` 同时存在，则优先使用小程序跳转，详情请参考[官方文档](https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277)
2. `data()`方法接收一个数组，其 `key` 为模板消息中的关键字，`value` 可以为字符串或数组。如果为字符串，则默认颜色为 `#173177`；如果为数组，则第一个参数为显示的数据，第二个参数为字体颜色

## 代码贡献
**_欢迎 Fork 并提交 PR！_**

## LICENSE
MIT

---

## File: src/posts/2018-03-15-mongodb-sharding-clustering-share-about-chosing-sharding-key.md

[Binary file]

---

## File: src/posts/2018-04-07-multi-user-multi-application-api-authentication-based-on-access-token-laravel-development-package.md

---
title: 基于 access_token 的多用户多应用 API 认证 laravel 开发包
date: 2018-04-07
categories:
  - php
  - laravel
---


当看到 Laravel-API 时，您可能在想：「不是有官方的 Passport 吗，干嘛又重复造轮子？」是的，对于中大型，且需要有 `OAuth` 授权的应用来说， Passport 的确是一个很好的选择。

**但是，对于我们经常开发的中小型应用呢？我们大部分时候可能只是需要提供一个对外服务的 API 接口而已，像是类似于微信开发、支付宝开发那样，给一组 APPID/appsecret 就开始提供纯粹的 API 服务，所以像 Passport 这样的重量级选手，可能就不是更好的选择了。**

您可能又会说：「我可以使用 Passport 的 密码授权令牌 啊！」是的，您可以使用，但是，看到 `client_id`/`client_secret`/`username`/`password` 您作何感想？

您可能又又会说：「我可以使用 Passport 的 `客户端凭据授权令牌`啊！」是的，您也可以使用，但是：

- `client_id` 是有序整数
- 还需要通过额外的 `$request` 信息，再去重新相关获取授权信息
- ...

这些您能忍？

反正我是不能忍，所以，弄了这个轮子。

Github: [https://github.com/yansongda/laravel-api](https://github.com/yansongda/laravel-api)

## 运行环境

- php >= 5.6
- composer
- laravel >= 5.1

## 特点

- 简答、易懂、快速
- 专门为 laravel 打造
- 使用自带的认证驱动模式
- 多用户多应用 access_token 模式（类似支付宝/微信公众平台认证模式）

## 安装

```shell
$ composer require yansongda/laravel-api
```

### 添加 ServiceProvider（optional. if laravel < 5.5）

```php
// laravel < 5.5
Yansongda\LaravelApi\ApiServiceProvider::class,
```


## 使用方法

1. 更改认证驱动

    在 config/auth.php 中，更改 `guards.api.driver` 为 **api**

2. 在 UserModel 中添加 trait
    
    在 `config(auth.provider.xx.model)` 的类中，添加 `use Yansongda\LaravelApi\Models\Traits\HasApiApps`

3. 运行数据迁移

    `php artian migrate`

4. 开始使用吧


### 添加 App 与 accessToken

```php
use Yansongda\LaravelApi\Api;

$app = Api::createApp(User::find(1), '备注可选');

$access_token = Api::generateAccessToken($app);
```

### 客户端使用

#### 获取 access_token

```shell
curl --data "app_id=f748864cb16db706be1e408cb49771a3&app_secret=ce57ec31a9f4f37dfbf810c2e4ea79f0" "http://api.dev/api/token"
# {"code":0,"message":"success","data":{"user_id":1,"app_id":"f748864cb16db706be1e408cb49771a3","access_token":"3857d7d56f4ffe1ab57b8a8f292b85fa","expired_in":7200}}
```

#### 使用

有两种方式可以使用

- url 带上 `access_token` 参数进行认证.
    
    例如： `https://api.dev/?access_token=3857d7d56f4ffe1ab57b8a8f292b85fa`

- header 上进行认证

    例如：`Authorization: Bearer 3857d7d56f4ffe1ab57b8a8f292b85fa`


### 服务端认证

只需要在增加 `'auth:api'` 的 middleware 即可，增加后，`$request->user()/$request->user` 即为认证用户，`$request->app` 即为认证的 app_id

```php
use Illuminate\Http\Request;

Route::middleware('auth:api')->get('user', function(Request $request) {
    dd($request->user());
    // $request->user 获取 user_id
});
Route::middleware('auth:api')->get('app', function(Request $request) {
    dd($request->app); // 获取 app_id
});
```


## 其它

### access_token 有效时间

access_token 有效时间默认为 `7200` 秒，当然，您可以自由设置该值：

```php
// 在 AppServiceProvider 的 register 方法中增加

use Yansongda\LaravelApi\Api;

Api::$ttl = 7200;
// Api::setTtl(7200);
```

### 授权 token 路由

默认情况下，token 的授权通过自带的 `'api/token'` 路由进行 `post` 授权的，如果您想重写 token 的授权方式，您需要首先：

```php
// 在 AppServiceProvider 的 register 方法中增加

use Yansongda\LaravelApi\Api;

Api::$enableRoute = false;
// Api::enableRoute(false);
```

### 授权 token 路由前缀

默认情况下，自带的路由前缀为 `api`，如果您想更换为其它，请：

```php
// 在 AppServiceProvider 的 register 方法中增加

use Yansongda\LaravelApi\Api;

Api::$routePrefix = 'api';
// Api::setRoutePrefix(’api‘);
```

### 授权 token 路由其它

- 命名为: api.token
- middleware: api

## 异常

- AccessTokenNotProvidedException
    
    当客户端没有提供 access_token 时，抛出 `AccessTokenNotProvidedException` 异常，如果不进行任何额外的操作，默认将返回 `{"code":1,"message":"AccessToken Is Not Provided"}`

- InvalidAccessTokenException
    
    当客户端提供了无效的 access_token 时，抛出 `InvalidAccessTokenException` 异常，如果不进行任何额外的操作，默认将返回 `{"code":2,"message":"AccessToken Is Invalid"}`

- AccessTokenExpiredException

    当客户端提供的 access_token 已过期时，抛出 `AccessTokenExpiredException` 异常，如果不进行任何额外的操作，默认将返回 `{"code":3,"message":"AccessToken Is Expired"}`

- GenerateAccessTokenException

    当服务端生成 access_token 失败时，抛出 `GenerateAccessTokenException` 异常，如果不进行任何额外的操作，默认将返回 `{"code":4,"message":"xxxx"}`

- InvalidAppException

    当客户端提供了错误的 app_id 或 app_secret 时，抛出 `InvalidAppException` 异常，如果不进行任何额外的操作，默认将返回 `{"code":5,"message":"Invalid App Info"}`

- CreateAppException

    当服务端生成 app 失败时，抛出 `CreateAppException` 异常，如果不进行任何额外的操作，默认将返回 `{"code":6,"message":"xxxx"}`


_以上异常如果不想使用默认的信息，均可自行捕获更改相关信息_

## License

MIT

---

## File: src/posts/2018-05-17-use-of-deployer.md

[Binary file]

---

## File: src/posts/2019-05-11-nginx-request-processing-flow.md

---
title: Nginx 请求处理流程
date: 2019-05-11
categories: 
  - nginx
  - wiki
---

## Nginx 11 个处理阶段

### 1、NGX_HTTP_POST_READ_PHASE

接收到完整的HTTP头部后处理的阶段，它位于uri重写之前，实际上很少有模块会注册在该阶段，默认的情况下，该阶段被跳过。

### 2、NGX_HTTP_SERVER_REWRITE_PHASE

URI与location匹配前，修改URI的阶段，用于重定向，也就是该阶段执行处于server块内，location块外的重写指令，在读取请求头的过程中nginx会根据host及端口找到对应的虚拟主机配置。

### 3、NGX_HTTP_FIND_CONFIG_PHASE

根据URI寻找匹配的location块配置项阶段，该阶段使用重写之后的uri来查找对应的location，值得注意的是该阶段可能会被执行多次，因为也可能有location级别的重写指令。

### 4、NGX_HTTP_REWRITE_PHASE

上一阶段找到location块后再修改URI，location级别的uri重写阶段，该阶段执行location基本的重写指令，也可能会被执行多次。

### 5、NGX_HTTP_POST_REWRITE_PHASE

防止重写URL后导致的死循环，location级别重写的后一阶段，用来检查上阶段是否有uri重写，并根据结果跳转到合适的阶段。

### 6、NGX_HTTP_PREACCESS_PHASE

下一阶段之前的准备，访问权限控制的前一阶段，该阶段在权限控制阶段之前，一般也用于访问控制，比如限制访问频率，链接数等。

### 7、NGX_HTTP_ACCESS_PHASE

让HTTP模块判断是否允许这个请求进入Nginx服务器，访问权限控制阶段，比如基于ip黑白名单的权限控制，基于用户名密码的权限控制等。

### 8、NGX_HTTP_POST_ACCESS_PHASE

访问权限控制的后一阶段，该阶段根据权限控制阶段的执行结果进行相应处理，向用户发送拒绝服务的错误码，用来响应上一阶段的拒绝。

### 9、NGX_HTTP_TRY_FILES_PHASE

为访问静态文件资源而设置，try_files指令的处理阶段，如果没有配置try_files指令，则该阶段被跳过。

### 10、NGX_HTTP_CONTENT_PHASE

处理HTTP请求内容的阶段，大部分HTTP模块介入这个阶段，内容生成阶段，该阶段产生响应，并发送到客户端。

### 11、NGX_HTTP_LOG_PHASE

处理完请求后的日志记录阶段，该阶段记录访问日志。


以上 11 个阶段中，HTTP无法介入的阶段有 4 个：

- 3、NGX_HTTP_FIND_CONFIG_PHASE

- 5、NGX_HTTP_POST_REWRITE_PHASE

- 8、NGX_HTTP_POST_ACCESS_PHASE

- 9、NGX_HTTP_TRY_FILES_PHASE

剩余的7个阶段，HTTP模块均能介入，每个阶段可介入模块的个数也是没有限制的，多个HTTP模块可同时介入同一阶段并作用于同一请求。


## Nginx lua 处理阶段

### 1、init_by_lua

在nginx重新加载配置文件时，运行里面lua脚本，常用于全局变量的申请。（例如：lua_shared_dict共享内存的申请，只有当nginx重起后，共享内存数据才清空，这常用于统计。）

### 2、set_by_lua

流程分支处理判断变量初始化（设置一个变量，常用与计算一个逻辑，然后返回结果，该阶段不能运行Output API、Control API、Subrequest API、Cosocket API）

### 3、rewrite_by_lua

转发、重定向、缓存等功能 (例如特定请求代理到外网，在access阶段前运行，主要用于rewrite)

### 4、access_by_lua

IP准入、接口权限等情况集中处理(例如配合iptable完成简单防火墙，主要用于访问控制，能收集到大部分变量，类似status需要在log阶段才有。这条指令运行于nginx access阶段的末尾，因此总是在 allow 和 deny 这样的指令之后运行，虽然它们同属 access 阶段。）

### 5、content_by_lua

内容生成，阶段是所有请求处理阶段中最为重要的一个，运行在这个阶段的配置指令一般都肩负着生成内容（content）并输出HTTP响应。

### 6、header_filter_by_lua

应答HTTP过滤处理，一般只用于设置Cookie和Headers等，该阶段不能运行Output API、Control API、Subrequest API、Cosocket API(例如添加头部信息)。

### 7、body_filter_by_lua

应答BODY过滤处理(例如完成应答内容统一成大写)（一般会在一次请求中被调用多次, 因为这是实现基于 HTTP 1.1 chunked 编码的所谓“流式输出”的，该阶段不能运行Output API、Control API、Subrequest API、Cosocket API）

### 8、log_by_lua

会话完成后本地异步完成日志记录(日志可以记录在本地，还可以同步到其他机器)（该阶段总是运行在请求结束的时候，用于请求的后续操作，如在共享内存中进行统计数据,如果要高精确的数据统计，应该使用body_filter_by_lua，该阶段不能运行Output API、Control API、Subrequest API、Cosocket API）


##  lua 与 Nginx 运行阶段对应

### 1、init_by_lua

运行在 initialization Phase；

### 2、set_by_lua

运行在rewrite 阶段；

set 指令来自 ngx_rewrite 模块，运行于 rewrite 阶段；

### 3、rewrite_by_lua

指令来自 ngx_lua 模块，运行于 rewrite 阶段的末尾

### 4、access_by_lua

指令同样来自 ngx_lua 模块，运行于 access 阶段的末尾；

deny 指令来自 ngx_access 模块，运行于 access 阶段；

### 5、content_by_lua

指令来自 ngx_lua 模块，运行于 content 阶段；

不要将它和其它的内容处理指令在同一个location内使用如proxy_pass；

echo 指令则来自 ngx_echo 模块，运行在 content 阶段；

### 6、header_filter_by_lua

运行于 content 阶段，output-header-filter 一般用来设置cookie和headers；

### 7、body_filter_by_lua

运行于 content 阶段；

### 8、log_by_lua

运行在Log Phase 阶段；


---

来源：https://juejin.im/post/5bf671a4e51d4546d60a9bd1

---

## File: src/posts/2024-02-24-new-computer-or-os-setup.md

---
title: 新电脑/系统我的 Setup
date: 2024-02-24
categories: 
  - macos
  - setup
---

## 浏览器：Safari

系统自带，通过它来 [下载 Chrome 浏览器](https://www.google.com/intl/zh-CN/chrome/)

## 浏览器：Chrome

登录 Google 帐号，以便同步浏览器内容及设置 

## 整理程序坞

首先，将不常用的、系统自带的 App 全部移到一个文件夹里去，让世界变得清爽起来。

## 邮箱

登录邮箱，及时收取、查看邮件

## Source Code Pro

[下载](https://github.com/adobe-fonts/source-code-pro/releases) TTF 类型后，进行安装

## Terminal

选择自带 Pro 的 profile 为默认

### 配置

- 字体：`Source Code Pro, 常规，14`，同时放大 terminal 到合适的大小
- 文本：平滑文本
- 文本：「褐色」文本
- 文本：「蓝色」粗体文本
- 光标：竖条
- 光标：闪动光标

### OhMyZsh

```shell
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
```

执行此命令后，会先自动安装 develop tools，完毕后，再次执行上述命令，随后，`vim .zshrc` 找到 `plugins=(git)` 启用插件：`git z zsh-syntax-highlighting zsh-autosuggestions`

#### Plugins: zsh-autosuggestions

```shell
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
```

#### Plugins: zsh-completions

```shell
git clone https://github.com/zsh-users/zsh-completions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-completions
```

#### Plugins: zsh-syntax-highlighting

```shell
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting 
```

### Alias: git

```shell
alias gs="git switch"
alias glog="git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
alias glu="git pull upstream"
```

### History

https://github.com/atuinsh/atuin

```shell
bash <(curl https://raw.githubusercontent.com/atuinsh/atuin/main/install.sh)
```

### Doggo

https://github.com/mr-karan/doggo

```shell
sudo mkdir -p /usr/local/bin/
curl -sS https://raw.githubusercontent.com/mr-karan/doggo/main/install.sh | sh
```

### node

https://github.com/nvm-sh/nvm

```shell
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
nvm install --lts
corepack enable pnpm
```

### Rust

```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

## Git

从家庭存储里下载以下文件，并放到桌面：

- gitconfig.bak
- gitignore_global.bak

执行以下命令：

```shell
mv ~/Desktop/gitconfig.bak ~/.gitconfig
mv ~/Desktop/gitignore_global.bak ~/.gitignore_global
```

## SSH

从家庭存储里下载以下文件，并放到桌面：

- config.bak
- id_rsa.bak
- id_rsa.pub
- work_rsa.bak
- work_rsa.pub
- private.gpg.asc
- public.gpg.asc

执行以下命令：

```shell
mkdir -p ~/.ssh/
mv ~/Desktop/config.bak ~/.ssh/config
mv ~/Desktop/id_rsa.bak ~/.ssh/id_rsa
mv ~/Desktop/id_rsa.pub ~/.ssh/
mv ~/Desktop/work_rsa.bak ~/.ssh/work_rsa
mv ~/Desktop/work_rsa.pub ~/.ssh/
mv ~/Desktop/private.gpg.asc ~/.ssh/
mv ~/Desktop/public.gpg.asc ~/.ssh/
chmod 600 ~/.ssh/id_rsa
chmod 600 ~/.ssh/work_rsa
```

## 通讯软件

- [钉钉](https://page.dingtalk.com/wow/z/dingtalk/simple/ddhomedownload#/)
- [飞书](https://www.feishu.cn/download)
- [企业微信](https://work.weixin.qq.com/#indexDownload)
- [微信](https://weixin.qq.com/)
- [腾讯会议](https://meeting.tencent.com/download/)

## 开发工具

- [PHPStorm](https://www.jetbrains.com/phpstorm/download/#section=mac)
  - 字体：SourceCodePro, 16, 1.2 
- [RustRover](https://www.jetbrains.com/rust/download/?section=mac)
  - 字体：SourceCodePro, 16, 1.2 
- [DataGrip](https://www.jetbrains.com/datagrip/download/#section=mac) 同步 github 数据源
  - 字体：SourceCodePro, 16, 1.2 
- [VSCode](https://code.visualstudio.com/) 登录 Microsoft 帐号同步设置
- [Docker](https://docs.docker.com/desktop/install/mac-install/)
- [Wireshark](https://www.wireshark.org/download.html)
- [Filezilla](https://filezilla-project.org/download.php?type=client)
- [TunnelBlick](https://tunnelblick.net/downloads.html)

## 知识管理

- [Obsidian](https://obsidian.md/) 同步 github
- [WPS](https://platform.wps.cn/)

## 娱乐

- [网易云音乐](https://music.163.com/)
- [IINA](https://iina.io/) / [VLC](https://www.videolan.org/)

--- METRICS ---
- Files Extracted: 61
- Estimated Token Budget: ~122978 tokens
- Recency Window: Active (< 180 days)
- Canonical Reference: https://codewiki.google/github.com/yansongda/pay
