Yaavi 1 year ago
commit
3109cec10b

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+node_modules/
+
+.DS_Store

+ 148 - 0
README.md

@@ -0,0 +1,148 @@
+# 中国节假日
+
+本项目提供了一系列用于管理和查询中国节假日、调休日、工作日及二十四节气的函数。通过使用这些函数,用户可以方便地检查指定日期的状态,获取日期范围内的节假日或工作日,并查找特定的工作日。此外,项目还支持查询二十四节气的日期,帮助用户了解中国传统节气的时间安排。
+
+支持 2004年 至 2024年,包括 2020年 的春节延长。
+
+## 节假日模块
+
+### `isWorkday` 检查某个日期是否为工作日
+
+```js
+console.log(isWorkday('2023-01-01')); // false
+```
+
+### `isHoliday` 检查某个日期是否为节假日
+
+```js
+console.log(isHoliday('2023-01-01')); // true
+```
+
+### `isInLieu` 检查某个日期是否为调休日(in lieu day)
+
+在中国的节假日安排中,调休日是为了连休假期或补班而调整的工作日或休息日。例如,当某个法定假日与周末相连时,可能会将某个周末调整为工作日,或者将某个工作日调整为休息日,以便连休更多天。
+
+```js
+// 检查 2024-05-02 返回 `true` 则表示是一个调休日。
+console.log(isInLieu('2024-05-02')); // true
+
+// 检查 2024-05-01 返回 `false` 则表示不是一个调休日。
+console.log(isInLieu('2024-05-01')); // false
+```
+
+
+### `getDayDetail` 检查指定日期是否是工作日
+
+函数用于检查指定日期是否是工作日,并返回一个是否工作日的布尔值和日期的详情。
+
+1. 如果指定日期是工作日,则返回 true 和工作日名称,如果是被调休的工作日,返回 true 和节假日详情。
+2. 如果是节假日,则返回 false 和节假日详情。
+
+```js
+// 示例用法
+
+// 正常工作日 周五
+console.log(getDayDetail('2024-02-02')); // {"work":true,"name":"Friday"}
+// 节假日 周末
+console.log(getDayDetail('2024-02-03')); // {"work":false,"name":"Saturday"}
+// 调休需要上班
+console.log(getDayDetail('2024-02-04')); // {"work":true,"name":"Spring Festival,春节,3"}
+// 节假日 春节
+console.log(getDayDetail('2024-02-17')); // {"work":false,"name":"Spring Festival,春节,3"}
+```
+
+### `getHolidays` 获取指定日期范围内的所有节假日
+
+接收起始日期和结束日期,并可选地决定是否包括周末。如果包括周末,则函数会返回包括周末在内的所有节假日;否则,只返回工作日的节假日。
+
+> tip: 即使不包括周末,周末的节假日仍然会被返回
+
+```js
+// 示例用法
+const start = '2024-04-26';
+const end = '2024-05-06';
+
+// 获取从 2024-05-01 到 2024-05-10 的所有节假日,包括周末
+const holidaysIncludingWeekends = getHolidays(start, end, true);
+console.log('Holidays including weekends:', holidaysIncludingWeekends.map(d => d.format('YYYY-MM-DD')));
+
+// 获取从 2024-05-01 到 2024-05-10 的节假日,不包括周末
+const holidaysExcludingWeekends = getHolidays(start, end, false);
+console.log('Holidays excluding weekends:', holidaysExcludingWeekends.map(d => d.format('YYYY-MM-DD')));
+```
+
+
+### `getWorkdays` 取指定日期范围内的工作日列表
+
+接收起始日期和结束日期,并可选地决定是否包括周末。如果包括周末,则函数会返回包括周末在内的所有工作日;否则,只返回周一到周五的工作日。
+
+```js
+// 示例用法
+const start = '2024-04-26';
+const end = '2024-05-06';
+
+// 获取从 2024-05-01 到 2024-05-10 的所有工作日,包括周末
+const workdaysIncludingWeekends = getWorkdays(start, end, true);
+console.log('Workdays including weekends:', workdaysIncludingWeekends.map(d => d.format('YYYY-MM-DD')));
+
+// 获取从 2024-05-01 到 2024-05-10 的工作日,不包括周末
+const workdaysExcludingWeekends = getWorkdays(start, end, false);
+console.log('Workdays excluding weekends:', workdaysExcludingWeekends.map(d => d.format('YYYY-MM-DD')));
+```
+
+### `findWorkday` 查找工作日
+
+查找从今天开始 未来的第 {deltaDays} 个工作日。
+
+```js
+// 查找从今天开始 未来的第 {deltaDays} 个工作日
+// 如果 deltaDays 为 0,首先检查当前日期是否为工作日。如果是,则直接返回当前日期。
+// 如果当前日期不是工作日,会查找下一个工作日。
+const currentWorkday = findWorkday(0);
+console.log(currentWorkday.format('YYYY-MM-DD'));
+
+// 查找从今天开始未来的第一个工作日
+const nextWorkday = findWorkday(1);
+console.log(nextWorkday.format('YYYY-MM-DD'));
+
+// 查找从今天开始之前的前一个工作日
+const previousWorkday = findWorkday(-1);
+console.log(previousWorkday.format('YYYY-MM-DD'));
+
+// 可以传第二个参数 查找具体日期的上下工作日
+// 查找从 2024-05-18 开始,未来的第二个工作日
+const secondNextWorkday = findWorkday(2, '2024-05-18');
+console.log(secondNextWorkday.format('YYYY-MM-DD'));
+```
+
+## 节气模块
+
+### 获取 24 节气的日期
+
+```js
+import { getSolarTerms } from "china-days";
+
+/** 获取范围内 节气日期数组 */
+const solarTerms = getSolarTerms("2024-05-01", "2024-05-20");
+solarTerms.forEach(({ date, term, name }) => {
+  console.log(`${name}: ${dayjs(date).format("YYYY-MM-DD")}, ${term}`);
+});
+
+/* 获取当天 节气 */
+const solarTerms = getSolarTerms("2024-05-20");
+console.log(solarTerms[0]);
+```
+
+## 辅助函数
+
+### `getDates` 获取两个日期之间的所有日期
+
+包括起始日期和结束日期,返回 Dayjs 对象数组。
+
+
+## 贡献代码
+
+1. Fork + Clone 项目到本地
+2. 修改 [节假日定义][src/holidays/generate.ts]
+3. 执行命令 `npm run generate` 自动生成 [常量文件][src/holidays/constants.ts]
+4. 提交PR

+ 12 - 0
index.html

@@ -0,0 +1,12 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
+    <title>Vite + TS</title>
+  </head>
+  <body>
+    <!-- <script type="module" src="./solar_terms/index.ts"></script> -->
+    <script type="module" src="./src/holidays/index.ts"></script>
+  </body>
+</html>

+ 2219 - 0
package-lock.json

@@ -0,0 +1,2219 @@
+{
+  "name": "china-days",
+  "version": "1.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "china-days",
+      "version": "1.0.0",
+      "license": "MIT",
+      "dependencies": {
+        "dayjs": "^1.11.11",
+        "serve": "^14.2.3",
+        "typescript": "^5.4.5",
+        "vite": "^5.2.11"
+      }
+    },
+    "node_modules/@adobe/css-tools": {
+      "version": "4.3.3",
+      "resolved": "http://127.0.0.1:4873/@adobe/css-tools/-/css-tools-4.3.3.tgz",
+      "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==",
+      "peer": true
+    },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
+      "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
+      "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
+      "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
+      "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
+      "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
+      "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
+      "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
+      "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
+      "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
+      "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
+      "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
+      "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
+      "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
+      "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
+      "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
+      "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
+      "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
+      "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
+      "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
+      "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
+      "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
+      "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
+      "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.5",
+      "resolved": "http://127.0.0.1:4873/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+      "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/set-array": "^1.2.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "http://127.0.0.1:4873/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.2.1",
+      "resolved": "http://127.0.0.1:4873/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+      "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/source-map": {
+      "version": "0.3.6",
+      "resolved": "http://127.0.0.1:4873/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+      "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.15",
+      "resolved": "http://127.0.0.1:4873/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+      "peer": true
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.25",
+      "resolved": "http://127.0.0.1:4873/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+      "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "node_modules/@rollup/rollup-android-arm-eabi": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz",
+      "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-android-arm64": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz",
+      "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-darwin-arm64": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz",
+      "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-darwin-x64": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz",
+      "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz",
+      "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz",
+      "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz",
+      "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-linux-arm64-musl": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz",
+      "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz",
+      "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz",
+      "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz",
+      "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-linux-x64-gnu": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz",
+      "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-linux-x64-musl": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz",
+      "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz",
+      "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz",
+      "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==",
+      "optional": true
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz",
+      "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==",
+      "optional": true
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.5",
+      "resolved": "http://127.0.0.1:4873/@types/estree/-/estree-1.0.5.tgz",
+      "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
+    },
+    "node_modules/@types/node": {
+      "version": "20.12.12",
+      "resolved": "http://127.0.0.1:4873/@types/node/-/node-20.12.12.tgz",
+      "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==",
+      "peer": true,
+      "dependencies": {
+        "undici-types": "~5.26.4"
+      }
+    },
+    "node_modules/@zeit/schemas": {
+      "version": "2.36.0",
+      "resolved": "http://127.0.0.1:4873/@zeit/schemas/-/schemas-2.36.0.tgz",
+      "integrity": "sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg=="
+    },
+    "node_modules/accepts": {
+      "version": "1.3.8",
+      "resolved": "http://127.0.0.1:4873/accepts/-/accepts-1.3.8.tgz",
+      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+      "dependencies": {
+        "mime-types": "~2.1.34",
+        "negotiator": "0.6.3"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.11.3",
+      "resolved": "http://127.0.0.1:4873/acorn/-/acorn-8.11.3.tgz",
+      "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
+      "peer": true,
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "8.12.0",
+      "resolved": "http://127.0.0.1:4873/ajv/-/ajv-8.12.0.tgz",
+      "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ansi-align": {
+      "version": "3.0.1",
+      "resolved": "http://127.0.0.1:4873/ansi-align/-/ansi-align-3.0.1.tgz",
+      "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+      "dependencies": {
+        "string-width": "^4.1.0"
+      }
+    },
+    "node_modules/ansi-align/node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "http://127.0.0.1:4873/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ansi-align/node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "http://127.0.0.1:4873/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+    },
+    "node_modules/ansi-align/node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "http://127.0.0.1:4873/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ansi-align/node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "http://127.0.0.1:4873/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ansi-regex": {
+      "version": "6.0.1",
+      "resolved": "http://127.0.0.1:4873/ansi-regex/-/ansi-regex-6.0.1.tgz",
+      "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "6.2.1",
+      "resolved": "http://127.0.0.1:4873/ansi-styles/-/ansi-styles-6.2.1.tgz",
+      "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/anymatch": {
+      "version": "3.1.3",
+      "resolved": "http://127.0.0.1:4873/anymatch/-/anymatch-3.1.3.tgz",
+      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+      "peer": true,
+      "dependencies": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/arch": {
+      "version": "2.2.0",
+      "resolved": "http://127.0.0.1:4873/arch/-/arch-2.2.0.tgz",
+      "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/arg": {
+      "version": "5.0.2",
+      "resolved": "http://127.0.0.1:4873/arg/-/arg-5.0.2.tgz",
+      "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "http://127.0.0.1:4873/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+    },
+    "node_modules/binary-extensions": {
+      "version": "2.3.0",
+      "resolved": "http://127.0.0.1:4873/binary-extensions/-/binary-extensions-2.3.0.tgz",
+      "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/boxen": {
+      "version": "7.0.0",
+      "resolved": "http://127.0.0.1:4873/boxen/-/boxen-7.0.0.tgz",
+      "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==",
+      "dependencies": {
+        "ansi-align": "^3.0.1",
+        "camelcase": "^7.0.0",
+        "chalk": "^5.0.1",
+        "cli-boxes": "^3.0.0",
+        "string-width": "^5.1.2",
+        "type-fest": "^2.13.0",
+        "widest-line": "^4.0.1",
+        "wrap-ansi": "^8.0.1"
+      },
+      "engines": {
+        "node": ">=14.16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "http://127.0.0.1:4873/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.2",
+      "resolved": "http://127.0.0.1:4873/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "peer": true,
+      "dependencies": {
+        "fill-range": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "http://127.0.0.1:4873/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+      "peer": true
+    },
+    "node_modules/bytes": {
+      "version": "3.0.0",
+      "resolved": "http://127.0.0.1:4873/bytes/-/bytes-3.0.0.tgz",
+      "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/camelcase": {
+      "version": "7.0.1",
+      "resolved": "http://127.0.0.1:4873/camelcase/-/camelcase-7.0.1.tgz",
+      "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==",
+      "engines": {
+        "node": ">=14.16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/chalk": {
+      "version": "5.0.1",
+      "resolved": "http://127.0.0.1:4873/chalk/-/chalk-5.0.1.tgz",
+      "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==",
+      "engines": {
+        "node": "^12.17.0 || ^14.13 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/chalk-template": {
+      "version": "0.4.0",
+      "resolved": "http://127.0.0.1:4873/chalk-template/-/chalk-template-0.4.0.tgz",
+      "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==",
+      "dependencies": {
+        "chalk": "^4.1.2"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk-template?sponsor=1"
+      }
+    },
+    "node_modules/chalk-template/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "http://127.0.0.1:4873/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/chalk-template/node_modules/chalk": {
+      "version": "4.1.2",
+      "resolved": "http://127.0.0.1:4873/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "3.6.0",
+      "resolved": "http://127.0.0.1:4873/chokidar/-/chokidar-3.6.0.tgz",
+      "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+      "peer": true,
+      "dependencies": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      },
+      "engines": {
+        "node": ">= 8.10.0"
+      },
+      "funding": {
+        "url": "https://paulmillr.com/funding/"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/cli-boxes": {
+      "version": "3.0.0",
+      "resolved": "http://127.0.0.1:4873/cli-boxes/-/cli-boxes-3.0.0.tgz",
+      "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/clipboardy": {
+      "version": "3.0.0",
+      "resolved": "http://127.0.0.1:4873/clipboardy/-/clipboardy-3.0.0.tgz",
+      "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==",
+      "dependencies": {
+        "arch": "^2.2.0",
+        "execa": "^5.1.1",
+        "is-wsl": "^2.2.0"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "http://127.0.0.1:4873/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "http://127.0.0.1:4873/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+    },
+    "node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "http://127.0.0.1:4873/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "peer": true
+    },
+    "node_modules/compressible": {
+      "version": "2.0.18",
+      "resolved": "http://127.0.0.1:4873/compressible/-/compressible-2.0.18.tgz",
+      "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+      "dependencies": {
+        "mime-db": ">= 1.43.0 < 2"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/compression": {
+      "version": "1.7.4",
+      "resolved": "http://127.0.0.1:4873/compression/-/compression-1.7.4.tgz",
+      "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+      "dependencies": {
+        "accepts": "~1.3.5",
+        "bytes": "3.0.0",
+        "compressible": "~2.0.16",
+        "debug": "2.6.9",
+        "on-headers": "~1.0.2",
+        "safe-buffer": "5.1.2",
+        "vary": "~1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "http://127.0.0.1:4873/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+    },
+    "node_modules/content-disposition": {
+      "version": "0.5.2",
+      "resolved": "http://127.0.0.1:4873/content-disposition/-/content-disposition-0.5.2.tgz",
+      "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/copy-anything": {
+      "version": "2.0.6",
+      "resolved": "http://127.0.0.1:4873/copy-anything/-/copy-anything-2.0.6.tgz",
+      "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==",
+      "peer": true,
+      "dependencies": {
+        "is-what": "^3.14.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.3",
+      "resolved": "http://127.0.0.1:4873/cross-spawn/-/cross-spawn-7.0.3.tgz",
+      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/dayjs": {
+      "version": "1.11.11",
+      "resolved": "http://127.0.0.1:4873/dayjs/-/dayjs-1.11.11.tgz",
+      "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg=="
+    },
+    "node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "http://127.0.0.1:4873/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/deep-extend": {
+      "version": "0.6.0",
+      "resolved": "http://127.0.0.1:4873/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/detect-libc": {
+      "version": "1.0.3",
+      "resolved": "http://127.0.0.1:4873/detect-libc/-/detect-libc-1.0.3.tgz",
+      "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
+      "peer": true,
+      "bin": {
+        "detect-libc": "bin/detect-libc.js"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/eastasianwidth": {
+      "version": "0.2.0",
+      "resolved": "http://127.0.0.1:4873/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+      "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
+    },
+    "node_modules/emoji-regex": {
+      "version": "9.2.2",
+      "resolved": "http://127.0.0.1:4873/emoji-regex/-/emoji-regex-9.2.2.tgz",
+      "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+    },
+    "node_modules/errno": {
+      "version": "0.1.8",
+      "resolved": "http://127.0.0.1:4873/errno/-/errno-0.1.8.tgz",
+      "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
+      "optional": true,
+      "peer": true,
+      "dependencies": {
+        "prr": "~1.0.1"
+      },
+      "bin": {
+        "errno": "cli.js"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.20.2",
+      "resolved": "http://127.0.0.1:4873/esbuild/-/esbuild-0.20.2.tgz",
+      "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.20.2",
+        "@esbuild/android-arm": "0.20.2",
+        "@esbuild/android-arm64": "0.20.2",
+        "@esbuild/android-x64": "0.20.2",
+        "@esbuild/darwin-arm64": "0.20.2",
+        "@esbuild/darwin-x64": "0.20.2",
+        "@esbuild/freebsd-arm64": "0.20.2",
+        "@esbuild/freebsd-x64": "0.20.2",
+        "@esbuild/linux-arm": "0.20.2",
+        "@esbuild/linux-arm64": "0.20.2",
+        "@esbuild/linux-ia32": "0.20.2",
+        "@esbuild/linux-loong64": "0.20.2",
+        "@esbuild/linux-mips64el": "0.20.2",
+        "@esbuild/linux-ppc64": "0.20.2",
+        "@esbuild/linux-riscv64": "0.20.2",
+        "@esbuild/linux-s390x": "0.20.2",
+        "@esbuild/linux-x64": "0.20.2",
+        "@esbuild/netbsd-x64": "0.20.2",
+        "@esbuild/openbsd-x64": "0.20.2",
+        "@esbuild/sunos-x64": "0.20.2",
+        "@esbuild/win32-arm64": "0.20.2",
+        "@esbuild/win32-ia32": "0.20.2",
+        "@esbuild/win32-x64": "0.20.2"
+      }
+    },
+    "node_modules/execa": {
+      "version": "5.1.1",
+      "resolved": "http://127.0.0.1:4873/execa/-/execa-5.1.1.tgz",
+      "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+      "dependencies": {
+        "cross-spawn": "^7.0.3",
+        "get-stream": "^6.0.0",
+        "human-signals": "^2.1.0",
+        "is-stream": "^2.0.0",
+        "merge-stream": "^2.0.0",
+        "npm-run-path": "^4.0.1",
+        "onetime": "^5.1.2",
+        "signal-exit": "^3.0.3",
+        "strip-final-newline": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sindresorhus/execa?sponsor=1"
+      }
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "http://127.0.0.1:4873/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+    },
+    "node_modules/fast-url-parser": {
+      "version": "1.1.3",
+      "resolved": "http://127.0.0.1:4873/fast-url-parser/-/fast-url-parser-1.1.3.tgz",
+      "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==",
+      "dependencies": {
+        "punycode": "^1.3.2"
+      }
+    },
+    "node_modules/fill-range": {
+      "version": "7.0.1",
+      "resolved": "http://127.0.0.1:4873/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "peer": true,
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "http://127.0.0.1:4873/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+      "peer": true
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "http://127.0.0.1:4873/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "optional": true,
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/get-stream": {
+      "version": "6.0.1",
+      "resolved": "http://127.0.0.1:4873/get-stream/-/get-stream-6.0.1.tgz",
+      "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/glob": {
+      "version": "7.2.3",
+      "resolved": "http://127.0.0.1:4873/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "peer": true,
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "http://127.0.0.1:4873/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "peer": true,
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "http://127.0.0.1:4873/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "optional": true,
+      "peer": true
+    },
+    "node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "http://127.0.0.1:4873/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/human-signals": {
+      "version": "2.1.0",
+      "resolved": "http://127.0.0.1:4873/human-signals/-/human-signals-2.1.0.tgz",
+      "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+      "engines": {
+        "node": ">=10.17.0"
+      }
+    },
+    "node_modules/iconv-lite": {
+      "version": "0.6.3",
+      "resolved": "http://127.0.0.1:4873/iconv-lite/-/iconv-lite-0.6.3.tgz",
+      "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+      "optional": true,
+      "peer": true,
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/image-size": {
+      "version": "0.5.5",
+      "resolved": "http://127.0.0.1:4873/image-size/-/image-size-0.5.5.tgz",
+      "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==",
+      "optional": true,
+      "peer": true,
+      "bin": {
+        "image-size": "bin/image-size.js"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/immutable": {
+      "version": "4.3.6",
+      "resolved": "http://127.0.0.1:4873/immutable/-/immutable-4.3.6.tgz",
+      "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==",
+      "peer": true
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "http://127.0.0.1:4873/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+      "peer": true,
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "http://127.0.0.1:4873/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "peer": true
+    },
+    "node_modules/ini": {
+      "version": "1.3.8",
+      "resolved": "http://127.0.0.1:4873/ini/-/ini-1.3.8.tgz",
+      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
+    },
+    "node_modules/is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "http://127.0.0.1:4873/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "peer": true,
+      "dependencies": {
+        "binary-extensions": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-docker": {
+      "version": "2.2.1",
+      "resolved": "http://127.0.0.1:4873/is-docker/-/is-docker-2.2.1.tgz",
+      "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+      "bin": {
+        "is-docker": "cli.js"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "http://127.0.0.1:4873/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "http://127.0.0.1:4873/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "http://127.0.0.1:4873/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "peer": true,
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "http://127.0.0.1:4873/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/is-port-reachable": {
+      "version": "4.0.0",
+      "resolved": "http://127.0.0.1:4873/is-port-reachable/-/is-port-reachable-4.0.0.tgz",
+      "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==",
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-stream": {
+      "version": "2.0.1",
+      "resolved": "http://127.0.0.1:4873/is-stream/-/is-stream-2.0.1.tgz",
+      "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-what": {
+      "version": "3.14.1",
+      "resolved": "http://127.0.0.1:4873/is-what/-/is-what-3.14.1.tgz",
+      "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==",
+      "peer": true
+    },
+    "node_modules/is-wsl": {
+      "version": "2.2.0",
+      "resolved": "http://127.0.0.1:4873/is-wsl/-/is-wsl-2.2.0.tgz",
+      "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+      "dependencies": {
+        "is-docker": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "http://127.0.0.1:4873/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "1.0.0",
+      "resolved": "http://127.0.0.1:4873/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+    },
+    "node_modules/less": {
+      "version": "4.2.0",
+      "resolved": "http://127.0.0.1:4873/less/-/less-4.2.0.tgz",
+      "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==",
+      "peer": true,
+      "dependencies": {
+        "copy-anything": "^2.0.1",
+        "parse-node-version": "^1.0.1",
+        "tslib": "^2.3.0"
+      },
+      "bin": {
+        "lessc": "bin/lessc"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "optionalDependencies": {
+        "errno": "^0.1.1",
+        "graceful-fs": "^4.1.2",
+        "image-size": "~0.5.0",
+        "make-dir": "^2.1.0",
+        "mime": "^1.4.1",
+        "needle": "^3.1.0",
+        "source-map": "~0.6.0"
+      }
+    },
+    "node_modules/lightningcss": {
+      "version": "1.24.1",
+      "resolved": "http://127.0.0.1:4873/lightningcss/-/lightningcss-1.24.1.tgz",
+      "integrity": "sha512-kUpHOLiH5GB0ERSv4pxqlL0RYKnOXtgGtVe7shDGfhS0AZ4D1ouKFYAcLcZhql8aMspDNzaUCumGHZ78tb2fTg==",
+      "peer": true,
+      "dependencies": {
+        "detect-libc": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      },
+      "optionalDependencies": {
+        "lightningcss-darwin-arm64": "1.24.1",
+        "lightningcss-darwin-x64": "1.24.1",
+        "lightningcss-freebsd-x64": "1.24.1",
+        "lightningcss-linux-arm-gnueabihf": "1.24.1",
+        "lightningcss-linux-arm64-gnu": "1.24.1",
+        "lightningcss-linux-arm64-musl": "1.24.1",
+        "lightningcss-linux-x64-gnu": "1.24.1",
+        "lightningcss-linux-x64-musl": "1.24.1",
+        "lightningcss-win32-x64-msvc": "1.24.1"
+      }
+    },
+    "node_modules/lightningcss-darwin-arm64": {
+      "version": "1.24.1",
+      "resolved": "http://127.0.0.1:4873/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.24.1.tgz",
+      "integrity": "sha512-1jQ12jBy+AE/73uGQWGSafK5GoWgmSiIQOGhSEXiFJSZxzV+OXIx+a9h2EYHxdJfX864M+2TAxWPWb0Vv+8y4w==",
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-darwin-x64": {
+      "version": "1.24.1",
+      "resolved": "http://127.0.0.1:4873/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.24.1.tgz",
+      "integrity": "sha512-R4R1d7VVdq2mG4igMU+Di8GPf0b64ZLnYVkubYnGG0Qxq1KaXQtAzcLI43EkpnoWvB/kUg8JKCWH4S13NfiLcQ==",
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-freebsd-x64": {
+      "version": "1.24.1",
+      "resolved": "http://127.0.0.1:4873/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.24.1.tgz",
+      "integrity": "sha512-z6NberUUw5ALES6Ixn2shmjRRrM1cmEn1ZQPiM5IrZ6xHHL5a1lPin9pRv+w6eWfcrEo+qGG6R9XfJrpuY3e4g==",
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-linux-arm-gnueabihf": {
+      "version": "1.24.1",
+      "resolved": "http://127.0.0.1:4873/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.24.1.tgz",
+      "integrity": "sha512-NLQLnBQW/0sSg74qLNI8F8QKQXkNg4/ukSTa+XhtkO7v3BnK19TS1MfCbDHt+TTdSgNEBv0tubRuapcKho2EWw==",
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-linux-arm64-gnu": {
+      "version": "1.24.1",
+      "resolved": "http://127.0.0.1:4873/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.24.1.tgz",
+      "integrity": "sha512-AQxWU8c9E9JAjAi4Qw9CvX2tDIPjgzCTrZCSXKELfs4mCwzxRkHh2RCxX8sFK19RyJoJAjA/Kw8+LMNRHS5qEg==",
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-linux-arm64-musl": {
+      "version": "1.24.1",
+      "resolved": "http://127.0.0.1:4873/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.24.1.tgz",
+      "integrity": "sha512-JCgH/SrNrhqsguUA0uJUM1PvN5+dVuzPIlXcoWDHSv2OU/BWlj2dUYr3XNzEw748SmNZPfl2NjQrAdzaPOn1lA==",
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-linux-x64-gnu": {
+      "version": "1.24.1",
+      "resolved": "http://127.0.0.1:4873/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.24.1.tgz",
+      "integrity": "sha512-TYdEsC63bHV0h47aNRGN3RiK7aIeco3/keN4NkoSQ5T8xk09KHuBdySltWAvKLgT8JvR+ayzq8ZHnL1wKWY0rw==",
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-linux-x64-musl": {
+      "version": "1.24.1",
+      "resolved": "http://127.0.0.1:4873/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.24.1.tgz",
+      "integrity": "sha512-HLfzVik3RToot6pQ2Rgc3JhfZkGi01hFetHt40HrUMoeKitLoqUUT5owM6yTZPTytTUW9ukLBJ1pc3XNMSvlLw==",
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-win32-x64-msvc": {
+      "version": "1.24.1",
+      "resolved": "http://127.0.0.1:4873/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.24.1.tgz",
+      "integrity": "sha512-joEupPjYJ7PjZtDsS5lzALtlAudAbgIBMGJPNeFe5HfdmJXFd13ECmEM+5rXNxYVMRHua2w8132R6ab5Z6K9Ow==",
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/make-dir": {
+      "version": "2.1.0",
+      "resolved": "http://127.0.0.1:4873/make-dir/-/make-dir-2.1.0.tgz",
+      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "optional": true,
+      "peer": true,
+      "dependencies": {
+        "pify": "^4.0.1",
+        "semver": "^5.6.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/merge-stream": {
+      "version": "2.0.0",
+      "resolved": "http://127.0.0.1:4873/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+    },
+    "node_modules/mime": {
+      "version": "1.6.0",
+      "resolved": "http://127.0.0.1:4873/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "optional": true,
+      "peer": true,
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "http://127.0.0.1:4873/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "http://127.0.0.1:4873/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "http://127.0.0.1:4873/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "http://127.0.0.1:4873/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "resolved": "http://127.0.0.1:4873/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "http://127.0.0.1:4873/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.7",
+      "resolved": "http://127.0.0.1:4873/nanoid/-/nanoid-3.3.7.tgz",
+      "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/needle": {
+      "version": "3.3.1",
+      "resolved": "http://127.0.0.1:4873/needle/-/needle-3.3.1.tgz",
+      "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==",
+      "optional": true,
+      "peer": true,
+      "dependencies": {
+        "iconv-lite": "^0.6.3",
+        "sax": "^1.2.4"
+      },
+      "bin": {
+        "needle": "bin/needle"
+      },
+      "engines": {
+        "node": ">= 4.4.x"
+      }
+    },
+    "node_modules/negotiator": {
+      "version": "0.6.3",
+      "resolved": "http://127.0.0.1:4873/negotiator/-/negotiator-0.6.3.tgz",
+      "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/normalize-path": {
+      "version": "3.0.0",
+      "resolved": "http://127.0.0.1:4873/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/npm-run-path": {
+      "version": "4.0.1",
+      "resolved": "http://127.0.0.1:4873/npm-run-path/-/npm-run-path-4.0.1.tgz",
+      "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+      "dependencies": {
+        "path-key": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/on-headers": {
+      "version": "1.0.2",
+      "resolved": "http://127.0.0.1:4873/on-headers/-/on-headers-1.0.2.tgz",
+      "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "http://127.0.0.1:4873/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "peer": true,
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/onetime": {
+      "version": "5.1.2",
+      "resolved": "http://127.0.0.1:4873/onetime/-/onetime-5.1.2.tgz",
+      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+      "dependencies": {
+        "mimic-fn": "^2.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/parse-node-version": {
+      "version": "1.0.1",
+      "resolved": "http://127.0.0.1:4873/parse-node-version/-/parse-node-version-1.0.1.tgz",
+      "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "http://127.0.0.1:4873/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-is-inside": {
+      "version": "1.0.2",
+      "resolved": "http://127.0.0.1:4873/path-is-inside/-/path-is-inside-1.0.2.tgz",
+      "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w=="
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "http://127.0.0.1:4873/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-to-regexp": {
+      "version": "2.2.1",
+      "resolved": "http://127.0.0.1:4873/path-to-regexp/-/path-to-regexp-2.2.1.tgz",
+      "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ=="
+    },
+    "node_modules/picocolors": {
+      "version": "1.0.1",
+      "resolved": "http://127.0.0.1:4873/picocolors/-/picocolors-1.0.1.tgz",
+      "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew=="
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "http://127.0.0.1:4873/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "peer": true,
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/pify": {
+      "version": "4.0.1",
+      "resolved": "http://127.0.0.1:4873/pify/-/pify-4.0.1.tgz",
+      "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.4.38",
+      "resolved": "http://127.0.0.1:4873/postcss/-/postcss-8.4.38.tgz",
+      "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "nanoid": "^3.3.7",
+        "picocolors": "^1.0.0",
+        "source-map-js": "^1.2.0"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/prr": {
+      "version": "1.0.1",
+      "resolved": "http://127.0.0.1:4873/prr/-/prr-1.0.1.tgz",
+      "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
+      "optional": true,
+      "peer": true
+    },
+    "node_modules/punycode": {
+      "version": "1.4.1",
+      "resolved": "http://127.0.0.1:4873/punycode/-/punycode-1.4.1.tgz",
+      "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="
+    },
+    "node_modules/range-parser": {
+      "version": "1.2.0",
+      "resolved": "http://127.0.0.1:4873/range-parser/-/range-parser-1.2.0.tgz",
+      "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/rc": {
+      "version": "1.2.8",
+      "resolved": "http://127.0.0.1:4873/rc/-/rc-1.2.8.tgz",
+      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+      "dependencies": {
+        "deep-extend": "^0.6.0",
+        "ini": "~1.3.0",
+        "minimist": "^1.2.0",
+        "strip-json-comments": "~2.0.1"
+      },
+      "bin": {
+        "rc": "cli.js"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "3.6.0",
+      "resolved": "http://127.0.0.1:4873/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "peer": true,
+      "dependencies": {
+        "picomatch": "^2.2.1"
+      },
+      "engines": {
+        "node": ">=8.10.0"
+      }
+    },
+    "node_modules/registry-auth-token": {
+      "version": "3.3.2",
+      "resolved": "http://127.0.0.1:4873/registry-auth-token/-/registry-auth-token-3.3.2.tgz",
+      "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==",
+      "dependencies": {
+        "rc": "^1.1.6",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "node_modules/registry-url": {
+      "version": "3.1.0",
+      "resolved": "http://127.0.0.1:4873/registry-url/-/registry-url-3.1.0.tgz",
+      "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==",
+      "dependencies": {
+        "rc": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/require-from-string": {
+      "version": "2.0.2",
+      "resolved": "http://127.0.0.1:4873/require-from-string/-/require-from-string-2.0.2.tgz",
+      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/rollup": {
+      "version": "4.17.2",
+      "resolved": "http://127.0.0.1:4873/rollup/-/rollup-4.17.2.tgz",
+      "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==",
+      "dependencies": {
+        "@types/estree": "1.0.5"
+      },
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=18.0.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.17.2",
+        "@rollup/rollup-android-arm64": "4.17.2",
+        "@rollup/rollup-darwin-arm64": "4.17.2",
+        "@rollup/rollup-darwin-x64": "4.17.2",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.17.2",
+        "@rollup/rollup-linux-arm-musleabihf": "4.17.2",
+        "@rollup/rollup-linux-arm64-gnu": "4.17.2",
+        "@rollup/rollup-linux-arm64-musl": "4.17.2",
+        "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2",
+        "@rollup/rollup-linux-riscv64-gnu": "4.17.2",
+        "@rollup/rollup-linux-s390x-gnu": "4.17.2",
+        "@rollup/rollup-linux-x64-gnu": "4.17.2",
+        "@rollup/rollup-linux-x64-musl": "4.17.2",
+        "@rollup/rollup-win32-arm64-msvc": "4.17.2",
+        "@rollup/rollup-win32-ia32-msvc": "4.17.2",
+        "@rollup/rollup-win32-x64-msvc": "4.17.2",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "http://127.0.0.1:4873/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+    },
+    "node_modules/safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "http://127.0.0.1:4873/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "optional": true,
+      "peer": true
+    },
+    "node_modules/sass": {
+      "version": "1.77.1",
+      "resolved": "http://127.0.0.1:4873/sass/-/sass-1.77.1.tgz",
+      "integrity": "sha512-OMEyfirt9XEfyvocduUIOlUSkWOXS/LAt6oblR/ISXCTukyavjex+zQNm51pPCOiFKY1QpWvEH1EeCkgyV3I6w==",
+      "peer": true,
+      "dependencies": {
+        "chokidar": ">=3.0.0 <4.0.0",
+        "immutable": "^4.0.0",
+        "source-map-js": ">=0.6.2 <2.0.0"
+      },
+      "bin": {
+        "sass": "sass.js"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      }
+    },
+    "node_modules/sax": {
+      "version": "1.3.0",
+      "resolved": "http://127.0.0.1:4873/sax/-/sax-1.3.0.tgz",
+      "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==",
+      "peer": true
+    },
+    "node_modules/semver": {
+      "version": "5.7.2",
+      "resolved": "http://127.0.0.1:4873/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+      "optional": true,
+      "peer": true,
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/serve": {
+      "version": "14.2.3",
+      "resolved": "http://127.0.0.1:4873/serve/-/serve-14.2.3.tgz",
+      "integrity": "sha512-VqUFMC7K3LDGeGnJM9h56D3XGKb6KGgOw0cVNtA26yYXHCcpxf3xwCTUaQoWlVS7i8Jdh3GjQkOB23qsXyjoyQ==",
+      "dependencies": {
+        "@zeit/schemas": "2.36.0",
+        "ajv": "8.12.0",
+        "arg": "5.0.2",
+        "boxen": "7.0.0",
+        "chalk": "5.0.1",
+        "chalk-template": "0.4.0",
+        "clipboardy": "3.0.0",
+        "compression": "1.7.4",
+        "is-port-reachable": "4.0.0",
+        "serve-handler": "6.1.5",
+        "update-check": "1.5.4"
+      },
+      "bin": {
+        "serve": "build/main.js"
+      },
+      "engines": {
+        "node": ">= 14"
+      }
+    },
+    "node_modules/serve-handler": {
+      "version": "6.1.5",
+      "resolved": "http://127.0.0.1:4873/serve-handler/-/serve-handler-6.1.5.tgz",
+      "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==",
+      "dependencies": {
+        "bytes": "3.0.0",
+        "content-disposition": "0.5.2",
+        "fast-url-parser": "1.1.3",
+        "mime-types": "2.1.18",
+        "minimatch": "3.1.2",
+        "path-is-inside": "1.0.2",
+        "path-to-regexp": "2.2.1",
+        "range-parser": "1.2.0"
+      }
+    },
+    "node_modules/serve-handler/node_modules/mime-db": {
+      "version": "1.33.0",
+      "resolved": "http://127.0.0.1:4873/mime-db/-/mime-db-1.33.0.tgz",
+      "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/serve-handler/node_modules/mime-types": {
+      "version": "2.1.18",
+      "resolved": "http://127.0.0.1:4873/mime-types/-/mime-types-2.1.18.tgz",
+      "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
+      "dependencies": {
+        "mime-db": "~1.33.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "http://127.0.0.1:4873/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "http://127.0.0.1:4873/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/signal-exit": {
+      "version": "3.0.7",
+      "resolved": "http://127.0.0.1:4873/signal-exit/-/signal-exit-3.0.7.tgz",
+      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "http://127.0.0.1:4873/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.0",
+      "resolved": "http://127.0.0.1:4873/source-map-js/-/source-map-js-1.2.0.tgz",
+      "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-support": {
+      "version": "0.5.21",
+      "resolved": "http://127.0.0.1:4873/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "peer": true,
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "node_modules/string-width": {
+      "version": "5.1.2",
+      "resolved": "http://127.0.0.1:4873/string-width/-/string-width-5.1.2.tgz",
+      "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+      "dependencies": {
+        "eastasianwidth": "^0.2.0",
+        "emoji-regex": "^9.2.2",
+        "strip-ansi": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/strip-ansi": {
+      "version": "7.1.0",
+      "resolved": "http://127.0.0.1:4873/strip-ansi/-/strip-ansi-7.1.0.tgz",
+      "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+      "dependencies": {
+        "ansi-regex": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+      }
+    },
+    "node_modules/strip-final-newline": {
+      "version": "2.0.0",
+      "resolved": "http://127.0.0.1:4873/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+      "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "http://127.0.0.1:4873/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/stylus": {
+      "version": "0.63.0",
+      "resolved": "http://127.0.0.1:4873/stylus/-/stylus-0.63.0.tgz",
+      "integrity": "sha512-OMlgrTCPzE/ibtRMoeLVhOY0RcNuNWh0rhAVqeKnk/QwcuUKQbnqhZ1kg2vzD8VU/6h3FoPTq4RJPHgLBvX6Bw==",
+      "peer": true,
+      "dependencies": {
+        "@adobe/css-tools": "~4.3.3",
+        "debug": "^4.3.2",
+        "glob": "^7.1.6",
+        "sax": "~1.3.0",
+        "source-map": "^0.7.3"
+      },
+      "bin": {
+        "stylus": "bin/stylus"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://opencollective.com/stylus"
+      }
+    },
+    "node_modules/stylus/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "http://127.0.0.1:4873/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "peer": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      }
+    },
+    "node_modules/stylus/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "http://127.0.0.1:4873/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "peer": true
+    },
+    "node_modules/stylus/node_modules/source-map": {
+      "version": "0.7.4",
+      "resolved": "http://127.0.0.1:4873/source-map/-/source-map-0.7.4.tgz",
+      "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
+      "peer": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/sugarss": {
+      "version": "4.0.1",
+      "resolved": "http://127.0.0.1:4873/sugarss/-/sugarss-4.0.1.tgz",
+      "integrity": "sha512-WCjS5NfuVJjkQzK10s8WOBY+hhDxxNt/N6ZaGwxFZ+wN3/lKKFSaaKUNecULcTTvE4urLcKaZFQD8vO0mOZujw==",
+      "peer": true,
+      "engines": {
+        "node": ">=12.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/postcss/"
+      },
+      "peerDependencies": {
+        "postcss": "^8.3.3"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "http://127.0.0.1:4873/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/terser": {
+      "version": "5.31.0",
+      "resolved": "http://127.0.0.1:4873/terser/-/terser-5.31.0.tgz",
+      "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/source-map": "^0.3.3",
+        "acorn": "^8.8.2",
+        "commander": "^2.20.0",
+        "source-map-support": "~0.5.20"
+      },
+      "bin": {
+        "terser": "bin/terser"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "http://127.0.0.1:4873/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "peer": true,
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/tslib": {
+      "version": "2.6.2",
+      "resolved": "http://127.0.0.1:4873/tslib/-/tslib-2.6.2.tgz",
+      "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+      "peer": true
+    },
+    "node_modules/type-fest": {
+      "version": "2.19.0",
+      "resolved": "http://127.0.0.1:4873/type-fest/-/type-fest-2.19.0.tgz",
+      "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
+      "engines": {
+        "node": ">=12.20"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "5.4.5",
+      "resolved": "http://127.0.0.1:4873/typescript/-/typescript-5.4.5.tgz",
+      "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/undici-types": {
+      "version": "5.26.5",
+      "resolved": "http://127.0.0.1:4873/undici-types/-/undici-types-5.26.5.tgz",
+      "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+      "peer": true
+    },
+    "node_modules/update-check": {
+      "version": "1.5.4",
+      "resolved": "http://127.0.0.1:4873/update-check/-/update-check-1.5.4.tgz",
+      "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==",
+      "dependencies": {
+        "registry-auth-token": "3.3.2",
+        "registry-url": "3.1.0"
+      }
+    },
+    "node_modules/uri-js": {
+      "version": "4.4.1",
+      "resolved": "http://127.0.0.1:4873/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "node_modules/uri-js/node_modules/punycode": {
+      "version": "2.3.1",
+      "resolved": "http://127.0.0.1:4873/punycode/-/punycode-2.3.1.tgz",
+      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/vary": {
+      "version": "1.1.2",
+      "resolved": "http://127.0.0.1:4873/vary/-/vary-1.1.2.tgz",
+      "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/vite": {
+      "version": "5.2.11",
+      "resolved": "http://127.0.0.1:4873/vite/-/vite-5.2.11.tgz",
+      "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==",
+      "dependencies": {
+        "esbuild": "^0.20.1",
+        "postcss": "^8.4.38",
+        "rollup": "^4.13.0"
+      },
+      "bin": {
+        "vite": "bin/vite.js"
+      },
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/vitejs/vite?sponsor=1"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      },
+      "peerDependencies": {
+        "@types/node": "^18.0.0 || >=20.0.0",
+        "less": "*",
+        "lightningcss": "^1.21.0",
+        "sass": "*",
+        "stylus": "*",
+        "sugarss": "*",
+        "terser": "^5.4.0"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "resolved": "http://127.0.0.1:4873/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/widest-line": {
+      "version": "4.0.1",
+      "resolved": "http://127.0.0.1:4873/widest-line/-/widest-line-4.0.1.tgz",
+      "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==",
+      "dependencies": {
+        "string-width": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/wrap-ansi": {
+      "version": "8.1.0",
+      "resolved": "http://127.0.0.1:4873/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+      "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+      "dependencies": {
+        "ansi-styles": "^6.1.0",
+        "string-width": "^5.0.1",
+        "strip-ansi": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "http://127.0.0.1:4873/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+      "peer": true
+    }
+  }
+}

+ 25 - 0
package.json

@@ -0,0 +1,25 @@
+{
+  "name": "china-days",
+  "version": "1.0.0",
+  "description": "中国日期的TS库,含有节假日、调休日、24节气等。",
+  "main": "index.ts",
+  "scripts": {
+    "dev": "vite",
+    "build": "tsc && vite build",
+    "preview": "vite preview"
+  },
+  "keywords": [
+    "中国日期",
+    "节假日",
+    "调休",
+    "24节气"
+  ],
+  "author": "Yaavi",
+  "license": "MIT",
+  "dependencies": {
+    "dayjs": "^1.11.11",
+    "serve": "^14.2.3",
+    "typescript": "^5.4.5",
+    "vite": "^5.2.11"
+  }
+}

+ 0 - 0
scripts/init.js


+ 116 - 0
src/holidays/arrangement.ts

@@ -0,0 +1,116 @@
+import dayjs from 'dayjs';
+
+export enum Holiday {
+  NewYearsDay = "New Year's Day,元旦,1",
+  SpringFestival = "Spring Festival,春节,3",
+  TombSweepingDay = "Tomb-sweeping Day,清明,1",
+  LabourDay = "Labour Day,劳动节,1",
+  DragonBoatFestival = "Dragon Boat Festival,端午,1",
+  NationalDay = "National Day,国庆节,3",
+  MidAutumnFestival = "Mid-autumn Festival,中秋,1",
+
+  /** special holidays */
+  AntiFascist70thDay = "Anti-Fascist 70th Day,中国人民抗日战争暨世界反法西斯战争胜利70周年纪念日,1",
+}
+
+interface DayDetails {
+  year?: number;
+  month?: number;
+  day?: number;
+  holiday?: Holiday;
+  dayType?: DayType;
+}
+
+enum DayType {
+  Workday = 1,
+  Holiday = 2,
+  InLieu = 3,
+}
+
+const dayDetails: DayDetails = {};
+
+const holidays: Record<string, Holiday> = {};
+const workdays: Record<string, Holiday> = {};
+const inLieuDays: Record<string, Holiday> = {};
+
+const yearAt = (year: number) => {
+  dayDetails.year = year;
+  return arrangement;
+}
+
+const mark = (holiday: Holiday) => {
+  dayDetails.holiday = holiday;
+  return arrangement;
+}
+
+/* 存储 */
+const save = (month: number, day: number, dayType: DayType) => {
+  if (!dayDetails.year) {
+    throw new Error("should set year before saving holiday");
+  }
+  if (!dayDetails.holiday) {
+    throw new Error("should set holiday before saving holiday");
+  }
+  dayDetails.dayType = dayType;
+  const date = dayjs(`${dayDetails.year}-${month}-${day}`);
+  if (dayType === DayType.Holiday) {
+    holidays[date.format('YYYY-MM-DD')] = dayDetails.holiday;
+  } else if (dayType === DayType.Workday) {
+    workdays[date.format('YYYY-MM-DD')] = dayDetails.holiday;
+  } else if (dayType === DayType.InLieu) {
+    inLieuDays[date.format('YYYY-MM-DD')] = dayDetails.holiday;
+  }
+  dayDetails.month = month;
+  dayDetails.day = day;
+  return arrangement;
+}
+
+/* 添加日期 */
+const to = (month: number, day: number) => {
+  if (!dayDetails.year || !dayDetails.month || !dayDetails.day) {
+    throw new Error("should set year/month/day before saving holiday range");
+  }
+  const startDate = dayjs(`${dayDetails.year}-${dayDetails.month}-${dayDetails.day}`);
+  const endDate = dayjs(`${dayDetails.year}-${month}-${day}`);
+  if (endDate.isBefore(startDate) || endDate.isSame(startDate)) {
+    throw new Error("end date should be after start date");
+  }
+  const diffDays = endDate.diff(startDate, 'day');
+  for (let i = 1; i <= diffDays; i++) {
+    const theDate = startDate.add(i, 'day');
+    if (dayDetails.dayType === DayType.Holiday) {
+      holidays[theDate.format('YYYY-MM-DD')] = dayDetails.holiday as Holiday;
+    } else if (dayDetails.dayType === DayType.Workday) {
+      workdays[theDate.format('YYYY-MM-DD')] = dayDetails.holiday as Holiday;
+    } else if (dayDetails.dayType === DayType.InLieu) {
+      inLieuDays[theDate.format('YYYY-MM-DD')] = dayDetails.holiday as Holiday;
+    }
+  }
+  return arrangement;
+}
+
+const arrangement = {
+  yearAt,
+  to,
+
+  work: (month: number, day: number) => save(month, day, DayType.Workday),
+  rest: (month: number, day: number) => save(month, day, DayType.Holiday),
+  inLieu: (month: number, day: number) => save(month, day, DayType.InLieu),
+  
+  // Special holiday markers
+  nyd: () => mark(Holiday.NewYearsDay),
+  sf: () => mark(Holiday.SpringFestival),
+  tsd: () => mark(Holiday.TombSweepingDay),
+  ld: () => mark(Holiday.LabourDay),
+  dbf: () => mark(Holiday.DragonBoatFestival),
+  nd: () => mark(Holiday.NationalDay),
+  maf: () => mark(Holiday.MidAutumnFestival),
+  afd: () => mark(Holiday.AntiFascist70thDay),
+};
+
+export {
+  arrangement,
+  holidays,
+  workdays,
+  inLieuDays
+}

+ 0 - 0
src/holidays/constants.ts


+ 474 - 0
src/holidays/generate.ts

@@ -0,0 +1,474 @@
+import { arrangement } from "./arrangement"
+
+const generate = () => {
+  /**
+   * 2024
+   * https://www.gov.cn/zhengce/content/202310/content_6911527.htm
+   * 一、元旦:1月1日放假,与周末连休。
+   * 二、春节:2月10日至17日放假调休,共8天。2月4日(星期日)、2月18日(星期日)上班。
+   * 三、清明节:4月4日至6日放假调休,共3天。4月7日(星期日)上班。
+   * 四、劳动节:5月1日至5日放假调休,共5天。4月28日(星期日)、5月11日(星期六)上班。
+   * 五、端午节:6月10日放假,与周末连休。
+   * 六、中秋节:9月15日至17日放假调休,共3天。9月14日(星期六)上班。
+   * 七、国庆节:10月1日至7日放假调休,共7天。9月29日(星期日)、10月12日(星期六)上班。
+   */
+  arrangement.yearAt(2024)
+    .nyd().rest(1, 1)
+    .sf().rest(2, 10).to(2, 17).work(2, 4).work(2, 18).inLieu(2, 15).to(2, 16)
+    .tsd().rest(4, 4).to(4, 6).work(4, 7).inLieu(4, 5)
+    .ld().rest(5, 1).to(5, 5).work(4, 28).work(5, 11).inLieu(5, 2).to(5, 3)
+    .dbf().rest(6, 10)
+    .maf().rest(9, 15).to(9, 17).work(9, 14).inLieu(9, 16)
+    .nd().rest(10, 1).to(10, 7).work(9, 29).work(10, 12).inLieu(10, 4).inLieu(10, 7)
+  
+  /**
+  * 2023
+  * http://www.gov.cn/zhengce/content/2022-12/08/content_5730844.htm
+  * 一、元旦:2022年12月31日至2023年1月2日放假调休,共3天。
+  * 二、春节:1月21日至27日放假调休,共7天。1月28日(星期六)、1月29日(星期日)上班。
+  * 三、清明节:4月5日放假,共1天。
+  * 四、劳动节:4月29日至5月3日放假调休,共5天。4月23日(星期日)、5月6日(星期六)上班。
+  * 五、端午节:6月22日至24日放假调休,共3天。6月25日(星期日)上班。
+  * 六、中秋节、国庆节:9月29日至10月6日放假调休,共8天。10月7日(星期六)、10月8日(星期日)上班。
+  */
+  arrangement.yearAt(2023)
+    .nyd().rest(1, 1).to(1, 2)
+    .sf().rest(1, 21).to(1, 27).work(1, 28).to(1, 29).inLieu(1, 26).to(1, 27)
+    .tsd().rest(4, 5)
+    .ld().rest(4, 29).to(5, 3).work(4, 23).work(5, 6).inLieu(5, 2).to(5, 3)
+    .dbf().rest(6, 22).to(6, 24).work(6, 25).inLieu(6, 23)
+    .maf().rest(9, 29)
+    .nd().rest(9, 30).to(10, 6).work(10, 7).to(10, 8).inLieu(10, 5).to(10, 6)
+  
+  /**
+  * 2022
+  * http://www.gov.cn/zhengce/content/2021-10/25/content_5644835.htm
+  * 一、元旦:2022年1月1日至3日放假,共3天。
+  * 二、春节:1月31日至2月6日放假调休,共7天。1月29日(星期六)、1月30日(星期日)上班。
+  * 三、清明节:4月3日至5日放假调休,共3天。4月2日(星期六)上班。
+  * 四、劳动节:4月30日至5月4日放假调休,共5天。4月24日(星期日)、5月7日(星期六)上班。
+  * 五、端午节:6月3日至5日放假,共3天。
+  * 六、中秋节:9月10日至12日放假,共3天。
+  * 七、国庆节:10月1日至7日放假调休,共7天。10月8日(星期六)、10月9日(星期日)上班。
+  */
+  arrangement.yearAt(2022)
+    .nyd().rest(1, 1).to(1, 3)
+    .sf().rest(1, 31).to(2, 6).work(1, 29).work(1, 30).inLieu(2, 3).to(2, 4)
+    .tsd().rest(4, 3).to(4, 5).work(4, 2).inLieu(4, 4)
+    .ld().rest(4, 30).to(5, 4).work(4, 24).work(5, 7).inLieu(5, 3).to(5, 4)
+    .dbf().rest(6, 3).to(6, 5)
+    .maf().rest(9, 10).to(9, 12)
+    .nd().rest(10, 1).to(10, 7).work(10, 8).work(10, 9).inLieu(10, 6).to(10, 7)
+    .nyd().rest(12, 31)
+  
+  /**
+  * 2021
+  * http://www.gov.cn/zhengce/content/2020-11/25/content_5564127.htm
+  * 一、元旦:2021年1月1日至3日放假,共3天。
+  * 二、春节:2月11日至17日放假调休,共7天。2月7日(星期日)、2月20日(星期六)上班。
+  * 三、清明节:4月3日至5日放假调休,共3天。
+  * 四、劳动节:5月1日至5日放假调休,共5天。4月25日(星期日)、5月8日(星期六)上班。
+  * 五、端午节:6月12日至14日放假,共3天。
+  * 六、中秋节:9月19日至21日放假调休,共3天。9月18日(星期六)上班。
+  * 七、国庆节:10月1日至7日放假调休,共7天。9月26日(星期日)、10月9日(星期六)上班。
+  */
+  arrangement.yearAt(2021)
+    .nyd().rest(1, 1).to(1, 3)
+    .sf().rest(2, 11).to(2, 17).work(2, 7).work(2, 20).inLieu(2, 16).to(2, 17)
+    .tsd().rest(4, 3).to(4, 5)
+    .ld().rest(5, 1).to(5, 5).work(4, 25).work(5, 8).inLieu(5, 4).to(5, 5)
+    .dbf().rest(6, 12).to(6, 14)
+    .maf().rest(9, 19).to(9, 21).work(9, 18).inLieu(9, 20)
+    .nd().rest(10, 1).to(10, 7).work(9, 26).work(10, 9).inLieu(10, 6).to(10, 7)
+  
+  /**
+  * 2020
+  * http://www.gov.cn/zhengce/content/2019-11/21/content_5454164.htm
+  * 一、元旦:2020年1月1日放假,共1天。
+  * 二、春节:1月24日至30日放假调休,共7天。1月19日(星期日)、2月1日(星期六)上班。
+  * 三、清明节:4月4日至6日放假调休,共3天。
+  * 四、劳动节:5月1日至5日放假调休,共5天。4月26日(星期日)、5月9日(星期六)上班。
+  * 五、端午节:6月25日至27日放假调休,共3天。6月28日(星期日)上班。
+  * 六、国庆节、中秋节:10月1日至8日放假调休,共8天。9月27日(星期日)、10月10日(星期六)上班。
+  * 
+  * http://www.gov.cn/zhengce/content/2020-01/27/content_5472352.htm
+  * 延长2020年春节假期至2月2日(农历正月初九,星期日),2月3日(星期一)起正常上班。
+  */
+  arrangement.yearAt(2020)
+    .nyd().rest(1, 1)
+    .sf().rest(1, 24).to(2, 2).work(1, 19).inLieu(1, 29)
+    .tsd().rest(4, 4).to(4, 6)
+    .ld().rest(5, 1).to(5, 5).work(4, 26).work(5, 9).inLieu(5, 4).to(5, 5)
+    .dbf().rest(6, 25).to(6, 27).work(6, 28).inLieu(6, 26)
+    .nd().rest(10, 1).to(10, 8).work(9, 27).work(10, 10).inLieu(10, 7).to(10, 8)
+  
+  /**
+  * 2019
+  * http://www.gov.cn/xinwen/2018-12/06/content_5346287.htm
+  * 一、元旦:12月30日至1月1日放假,共3天。 12月29日(星期六)上班。
+  * 二、春节:2月4日至10日放假调休,共7天。2月2日(星期六)、2月3日(星期天)上班。
+  * 三、清明节:4月5日放假,与周末连休。
+  * 四、劳动节:5月1日放假,共1天。
+  * 五、端午节:6月7日放假,与周末连休。
+  * 六、中秋节:9月13日放假,与周末连休。
+  * 七、国庆节:10月1日至7日放假调休,共7天。9月29日(星期天)、10月12日(周六)上班。
+  * http://www.gov.cn/zhengce/content/2019-03/22/content_5375877.htm
+  * 经国务院批准,现将调整2019年劳动节放假安排通知如下。
+  * 2019年5月1日至4日放假调休,共4天。4月28日(星期日)、5月5日(星期日)上班。
+  */
+  arrangement.yearAt(2019)
+    .nyd().rest(1, 1)
+    .sf().rest(2, 4).to(2, 10).work(2, 2).to(2, 3).inLieu(2, 4).inLieu(2, 8)
+    .tsd().rest(4, 5).to(4, 7)
+    .ld().rest(5, 1).to(5, 4).work(4, 28).work(5, 5).inLieu(5, 2).inLieu(5, 3)
+    .dbf().rest(6, 7).to(6, 9)
+    .maf().rest(9, 13).to(9, 15)
+    .nd().rest(10, 1).to(10, 7).work(9, 29).work(10, 12).inLieu(10, 4).inLieu(10, 7)
+  
+  /**
+  * 2018
+  * http://www.gov.cn/zhengce/content/2017-11/30/content_5243579.htm
+  * 一、元旦:1月1日放假,与周末连休。
+  * 二、春节:2月15日至21日放假调休,共7天。2月11日(星期日)、2月24日(星期六)上班。
+  * 三、清明节:4月5日至7日放假调休,共3天。4月8日(星期日)上班。
+  * 四、劳动节:4月29日至5月1日放假调休,共3天。4月28日(星期六)上班。
+  * 五、端午节:6月18日放假,与周末连休。
+  * 六、中秋节:9月24日放假,与周末连休。
+  * 七、国庆节:10月1日至7日放假调休,共7天。9月29日(星期六)、9月30日(星期日)上班。
+  */
+  arrangement.yearAt(2018)
+    .nyd().rest(1, 1)
+    .sf().rest(2, 15).to(2, 21).work(2, 11).work(2, 24).inLieu(2, 19).to(2, 21)
+    .tsd().rest(4, 5).to(4, 7).work(4, 8).inLieu(4, 6)
+    .ld().rest(4, 29).to(5, 1).work(4, 28).inLieu(4, 30)
+    .dbf().rest(6, 18)
+    .nd().rest(10, 1).to(10, 7).work(9, 29).to(9, 30).inLieu(10, 4).to(10, 5)
+    .maf().rest(9, 24)
+    .nyd().rest(12, 30).to(12, 31).work(12, 29).inLieu(12, 31)
+  
+  /**
+  * 2017
+  * http://www.gov.cn/zhengce/content/2016-12/01/content_5141603.htm
+  * 一、元旦:1月1日放假,1月2日(星期一)补休。
+  * 二、春节:1月27日至2月2日放假调休,共7天。1月22日(星期日)、2月4日(星期六)上班。
+  * 三、清明节:4月2日至4日放假调休,共3天。4月1日(星期六)上班。
+  * 四、劳动节:5月1日放假,与周末连休。
+  * 五、端午节:5月28日至30日放假调休,共3天。5月27日(星期六)上班。
+  * 六、中秋节、国庆节:10月1日至8日放假调休,共8天。9月30日(星期六)上班。
+  */
+  arrangement.yearAt(2017)
+    .nyd().rest(1, 1).to(1, 2)
+    .sf().rest(1, 27).to(2, 2).work(1, 22).work(2, 4).inLieu(2, 1).to(2, 2)
+    .tsd().rest(4, 2).to(4, 4).work(4, 1).inLieu(4, 3)
+    .ld().rest(5, 1)
+    .dbf().rest(5, 28).to(5, 30).work(5, 27).inLieu(5, 29)
+    .nd().rest(10, 1).to(10, 8).work(9, 30).inLieu(10, 6)
+    .maf().rest(10, 4)  // 国庆中秋相连,经查证10月4日为中秋
+  
+  /**
+  * 2016
+  * http://www.gov.cn/zhengce/content/2015-12/10/content_10394.htm
+  * 一、元旦:1月1日放假,与周末连休。
+  * 二、春节:2月7日至13日放假调休,共7天。2月6日(星期六)、2月14日(星期日)上班。
+  * 三、清明节:4月4日放假,与周末连休。
+  * 四、劳动节:5月1日放假,5月2日(星期一)补休。
+  * 五、端午节:6月9日至11日放假调休,共3天。6月12日(星期日)上班。
+  * 六、中秋节:9月15日至17日放假调休,共3天。9月18日(星期日)上班。
+  * 七、国庆节:10月1日至7日放假调休,共7天。10月8日(星期六)、10月9日(星期日)上班。
+  */
+  arrangement.yearAt(2016)
+    .nyd().rest(1, 1)
+    .sf().rest(2, 7).to(2, 13).work(2, 6).work(2, 14).inLieu(2, 11).to(2, 12)
+    .tsd().rest(4, 4)
+    .ld().rest(5, 1).to(5, 2)
+    .dbf().rest(6, 9).to(6, 11).work(6, 12).inLieu(6, 10)
+    .maf().rest(9, 15).to(9, 17).work(9, 18).inLieu(9, 16)
+    .nd().rest(10, 1).to(10, 7).work(10, 8).to(10, 9).inLieu(10, 6).to(10, 7)
+  
+  /**
+  * 2015
+  * http://www.gov.cn/zhengce/content/2014-12/16/content_9302.htm
+  * 一、元旦:1月1日至3日放假调休,共3天。1月4日(星期日)上班。
+  * 二、春节:2月18日至24日放假调休,共7天。2月15日(星期日)、2月28日(星期六)上班。
+  * 三、清明节:4月5日放假,4月6日(星期一)补休。
+  * 四、劳动节:5月1日放假,与周末连休。
+  * 五、端午节:6月20日放假,6月22日(星期一)补休。
+  * 六、中秋节:9月27日放假。
+  * 七、国庆节:10月1日至7日放假调休,共7天。10月10日(星期六)上班。
+  * 
+  *   注意:参见《国务院关于中国人民抗日战争暨世界反法西斯战争胜利70周年纪念日调休放假的通知》
+  *   http://www.gov.cn/zhengce/content/2015-05/13/content_9742.htm
+  *   额外的放假安排如下:
+  *   9月3日至5日调休放假,共3天。其中9月3日(星期四)放假,9月4日(星期五)调休,9月6日(星期日)上班。
+  */
+  arrangement.yearAt(2015)
+    .nyd().rest(1, 1).to(1, 3).work(1, 4).inLieu(1, 2)
+    .sf().rest(2, 18).to(2, 24).work(2, 15).work(2, 28).inLieu(2, 23).to(2, 24)
+    .tsd().rest(4, 5).to(4, 6)
+    .ld().rest(5, 1)
+    .dbf().rest(6, 20).rest(6, 22)
+    .maf().rest(9, 27)
+    .nd().rest(10, 1).to(10, 7).work(10, 10).inLieu(10, 7)
+    .afd().rest(9, 3).to(9, 4).work(9, 6).inLieu(9, 4)
+  
+  /**
+  * 2014
+  * http://www.gov.cn/zwgk/2013-12/11/content_2546204.htm
+  * 一、元旦:1月1日放假1天。
+  * 二、春节:1月31日至2月6日放假调休,共7天。1月26日(星期日)、2月8日(星期六)上班。
+  * 三、清明节:4月5日放假,4月7日(星期一)补休。
+  * 四、劳动节:5月1日至3日放假调休,共3天。5月4日(星期日)上班。
+  * 五、端午节:6月2日放假,与周末连休。
+  * 六、中秋节:9月8日放假,与周末连休。
+  * 七、国庆节:10月1日至7日放假调休,共7天。9月28日(星期日)、10月11日(星期六)上班。
+  */
+  arrangement.yearAt(2014)
+    .nyd().rest(1, 1)
+    .sf().rest(1, 31).to(2, 6).work(1, 26).work(2, 8).inLieu(2, 5).to(2, 6)
+    .tsd().rest(4, 5).to(4, 7)
+    .ld().rest(5, 1).to(5, 3).work(5, 4).inLieu(5, 2)
+    .dbf().rest(6, 2)
+    .maf().rest(9, 8)
+    .nd().rest(10, 1).to(10, 7).work(9, 28).work(10, 11).inLieu(10, 6).to(10, 7)
+  
+  /**
+  * 2013
+  * http://www.gov.cn/zwgk/2012-12/10/content_2286598.htm
+  * 一、元旦:1月1日至3日放假调休,共3天。1月5日(星期六)、1月6日(星期日)上班。
+  * 二、春节:2月9日至15日放假调休,共7天。2月16日(星期六)、2月17日(星期日)上班。
+  * 三、清明节:4月4日至6日放假调休,共3天。4月7日(星期日)上班。
+  * 四、劳动节:4月29日至5月1日放假调休,共3天。4月27日(星期六)、4月28日(星期日)上班。
+  * 五、端午节:6月10日至12日放假调休,共3天。6月8日(星期六)、6月9日(星期日)上班。
+  * 六、中秋节:9月19日至21日放假调休,共3天。9月22日(星期日)上班。
+  * 七、国庆节:10月1日至7日放假调休,共7天。9月29日(星期日)、10月12日(星期六)上班。
+  */
+  arrangement.yearAt(2013)
+    .nyd().rest(1, 1).to(1, 3).work(1, 5).to(1, 6).inLieu(1, 2).to(1, 3)
+    .sf().rest(2, 9).to(2, 15).work(2, 16).to(2, 17).inLieu(2, 14).to(2, 15)
+    .tsd().rest(4, 4).to(4, 6).work(4, 7).inLieu(4, 5)
+    .ld().rest(4, 29).to(5, 1).work(4, 27).to(4, 28).inLieu(4, 29).to(4, 30)
+    .dbf().rest(6, 10).to(6, 12).work(6, 8).to(6, 9).inLieu(6, 10).to(6, 11)
+    .maf().rest(9, 19).to(9, 21).work(9, 22).inLieu(9, 20)
+    .nd().rest(10, 1).to(10, 7).work(9, 29).work(10, 12).inLieu(10, 4).inLieu(10, 7)
+  
+  /**
+  * 2012
+  * http://www.gov.cn/zwgk/2011-12/06/content_2012097.htm
+  * 一、元旦:2012年1月1日至3日放假调休,共3天。2011年12月31日(星期六)上班。
+  * 二、春节:1月22日至28日放假调休,共7天。1月21日(星期六)、1月29日(星期日)上班。
+  * 三、清明节:4月2日至4日放假调休,共3天。3月31日(星期六)、4月1日(星期日)上班。
+  * 四、劳动节:4月29日至5月1日放假调休,共3天。4月28日(星期六)上班。
+  * 五、端午节:6月22日至24日放假公休,共3天。
+  * 六、中秋节、国庆节:9月30日至10月7日放假调休,共8天。9月29日(星期六)上班。
+  * 
+  *   注意:今年元旦特殊处理,去年上班 Σ( ° △ °|||)︴
+  */
+  arrangement.yearAt(2012)
+    .nyd().rest(1, 1).to(1, 3).inLieu(1, 3)
+    .sf().rest(1, 22).to(1, 28).work(1, 21).work(1, 29).inLieu(1, 26).to(1, 27)
+    .tsd().rest(4, 2).to(4, 4).work(3, 31).work(4, 1).inLieu(4, 2).to(4, 3)
+    .ld().rest(4, 29).to(5, 1).work(4, 28).inLieu(4, 30)
+    .dbf().rest(6, 22).rest(6, 24)
+    .maf().rest(9, 30)
+    .nd().rest(10, 1).to(10, 7).work(9, 29).inLieu(10, 5)
+  
+  /**
+  * 2011
+  * http://www.gov.cn/zwgk/2010-12/10/content_1762643.htm
+  * 一、元旦:1月1日至3日放假公休,共3天。
+  * 二、春节:2月2日(农历除夕)至8日放假调休,共7天。1月30日(星期日)、2月12日(星期六)上班。
+  * 三、清明节:4月3日至5日放假调休,共3天。4月2日(星期六)上班。
+  * 四、劳动节:4月30日至5月2日放假公休,共3天。
+  * 五、端午节:6月4日至6日放假公休,共3天。
+  * 六、中秋节:9月10日至12日放假公休,共3天。
+  * 七、国庆节:10月1日至7日放假调休,共7天。10月8日(星期六)、10月9日(星期日)上班。
+  * 
+  *  注意:明年元旦特殊处理,放到今年上班了 Σ( ° △ °|||)︴
+  */
+  arrangement.yearAt(2011)
+    .nyd().rest(1, 1).to(1, 3)
+    .sf().rest(2, 2).to(2, 8).work(1, 30).work(2, 12).inLieu(2, 7).to(2, 8)
+    .tsd().rest(4, 3).to(4, 5).work(4, 2).inLieu(4, 4)
+    .ld().rest(4, 30).to(5, 2)
+    .dbf().rest(6, 4).rest(6, 6)
+    .maf().rest(9, 10).to(9, 12)
+    .nd().rest(10, 1).to(10, 7).work(10, 8).to(10, 9).inLieu(10, 6).to(10, 7)
+    .nyd().work(12, 31)
+  
+  /**
+  * 2010
+  * http://www.gov.cn/zwgk/2009-12/08/content_1482691.htm
+  * 一、元旦:1月1日至3日放假公休,共3天。
+  * 二、春节:2月13日至19日放假调休,共7天。2月20日(星期六)、21日(星期日)上班。
+  * 三、清明节:4月3日至5日放假公休,共3天。
+  * 四、劳动节:5月1日至3日放假公休,共3天。
+  * 五、端午节:6月14日至16日放假调休,共3天。6月12日(星期六)、13日(星期日)上班。
+  * 六、中秋节:9月22日至24日放假调休,共3天。9月19日(星期日)、25日(星期六)上班。
+  * 七、国庆节:10月1日至7日放假调休,共7天。9月26日(星期日)、10月9日(星期六)上班。
+  */
+  arrangement.yearAt(2010)
+    .nyd().rest(1, 1).to(1, 3)
+    .sf().rest(2, 13).to(2, 19).work(2, 20).to(2, 21).inLieu(2, 18).to(2, 19)
+    .tsd().rest(4, 3).to(4, 5)
+    .ld().rest(5, 1).to(5, 3)
+    .dbf().rest(6, 14).to(6, 16).work(6, 12).to(6, 13).inLieu(6, 14).to(6, 15)
+    .maf().rest(9, 22).to(9, 24).work(9, 19).work(9, 25).inLieu(9, 23).to(9, 24)
+    .nd().rest(10, 1).to(10, 7).work(9, 26).work(10, 9).inLieu(10, 6).to(10, 7)
+  
+  /**
+  * 2009
+  *  http://www.gov.cn/zwgk/2008-12/10/content_1174014.htm
+  * 一、元旦:1月1日至3日放假,共3天。
+  * 其中,1月1日(星期四、新年)为法定节假日,1月3日(星期六)为公休日。
+  * 1月4日(星期日)公休日调至1月2日(星期五)。
+  * 1月4日(星期日)上班。
+  * 二、春节:1月25日至31日放假,共7天。
+  * 其中,1月25日(星期日、农历除夕)、1月26日(星期一、农历正月初一)、1月27日(星期二、农历正月初二)为法定节假日,1月31日(星期六)照常公休;1月25日(星期日)公休日调至1月28日(星期三),1月24日(星期六)、2月1
+  * 日(星期日)两个公休日调至1月29日(星期四)、1月30日(星期五)。
+  * 1月24日(星期六)、2月1日(星期日)上班。
+  * 三、清明节:4月4日至6日放假,共3天。
+  * 其中,4月4日(星期六、农历清明当日)为法定节假日,4月5日(星期日)照常公休。
+  * 4月4日(星期六)公休日调至4月6日(星期一)。
+  * 四、劳动节:5月1日至3日放假,共3天。
+  * 其中,5月1日(星期五、“五一”国际劳动节)为法定节假日,5月2日(星期六)、5月3日(星期日)照常公休。
+  * 五、端午节:5月28日至30日放假,共3天。
+  * 其中,5月28日(星期四、农历端午当日)为法定节假日,5月30日(星期六)照常公休;5月31日(星期日)公休日调至5月29日(星期五)。
+  * 5月31日(星期日)上班。
+  * 六、国庆节、中秋节:10月1日至8日放假,共8天。
+  * 其中,10月1日(星期四)、10月2日(星期五)、10月3日(星期六)为国庆节法定节假日,10月4日(星期日)照常公休;10月3日(星期六)公休日及中秋节分别调至10月5日(星期一)、10月6日(星期二),9月27日(星期日)、10
+  * 月10日(星期六)公休日调至10月7日(星期三)、10月8日(星期四)。
+  * 9月27日(星期日)、10月10日(星期六)上班。
+  */
+  arrangement.yearAt(2009)
+    .nyd().rest(1, 1).to(1, 3).work(1, 4).inLieu(1, 2)
+    .sf().rest(1, 25).to(1, 31).work(1, 24).work(2, 1).inLieu(1, 29).to(1, 30)
+    .tsd().rest(4, 4).to(4, 6)
+    .ld().rest(5, 1).to(5, 3)
+    .dbf().rest(5, 28).to(5, 30).work(5, 31).inLieu(5, 29)
+    .nd().rest(10, 1).to(10, 8).work(9, 27).work(10, 10).inLieu(10, 7).to(10, 8)
+    .maf().rest(10, 3)  // 国庆中秋相连,经查证10月3日为中秋
+  
+  /**
+  * 2008
+  *  http://www.gov.cn/zwgk/2007-12/18/content_837184.htm
+  * 一、元旦:2007年12月30日—2008年1月1日放假,共3天。
+  * 其中,1月1日(星期二)为法定节假日,12月30日(星期日)为公休日,12月29日(星期六)公休日调至12月31日(星期一),12月29日(星期六)上班。
+  * 二、春节:2月6日—12日(农历除夕至正月初六)放假,共7天。
+  * 其中,2月6日(除夕)、2月7日(春节)、2月8日(正月初二)为法定节假日,2月9日(星期六)、2月10日(星期日)照常公休,2月2日(星期六)、2月3日(星期日)两个公休日调至2月11日(星期一)、2月12日(星期二),2月2
+  * 日(星期六)、2月3日(星期日)上班。
+  * 三、清明节:4月4日—6日放假,共3天。
+  * 其中,4月4日(清明节)为法定节假日,4月5日(星期六)、4月6日(星期日)照常公休。
+  * 四、“五一”国际劳动节:5月1日—3日放假,共3天。
+  * 其中,5月1日为法定节假日,5月3日(星期六)为公休日,5月4日(星期日)公休日调至5月2日(星期五),5月4日(星期日)上班。
+  * 五、端午节:6月7日—9日放假,共3天。
+  * 其中,6月7日(星期六)照常公休,6月8日(农历五月初五,端午节)为法定节假日,6月8日(星期日)公休日调至6月9日(星期一)。
+  * 六、中秋节:9月13日—15日放假,共3天。
+  * 其中,9月13日(星期六)为公休日,9月14日(农历八月十五,中秋节)为法定节假日,9月14日(星期日)公休日调至9月15日(星期一)。
+  * 七、国庆节:9月29日—10月5日放假,共7天。
+  * 其中,10月1日、2日、3日为法定节假日,9月27日(星期六)、9月28日(星期日)两个公休日调至9月29日(星期一)、30日(星期二),10月4日(星期六)、5日(星期日)照常公休。
+  * 
+  *   注意:今年元旦假期,去年年尾要上班。
+  */
+  arrangement.yearAt(2008)
+    .nyd().rest(1, 1)
+    .sf().rest(2, 6).to(2, 12).work(2, 2).to(2, 3).inLieu(2, 11).to(2, 12)
+    .tsd().rest(4, 4).to(4, 6)
+    .ld().rest(5, 1).to(5, 3).work(5, 4).inLieu(5, 2)
+    .dbf().rest(6, 7).to(6, 9)
+    .maf().rest(9, 13).to(9, 15)
+    .nd().rest(9, 29).to(10, 5).work(9, 27).to(9, 28).inLieu(9, 29).to(9, 30)
+  
+  /**
+  * 2007
+  *  http://www.gov.cn/fwxx/sh/2006-12/18/content_471877.htm
+  * 一、元旦: 1月1日-3日放假,共三天。
+  * 其中1月1日为法定假日,将2006年12月30日(星期六)、31日(星期日)两个公休日分别调至2007年1月2日、3日,2006年12月30日(星期六)、12月31日(星期日)上班。
+  * 二、春节:2月18日—24日(即农历初一至初七)放假,共7天。
+  * 其中18日、19日、20日为法定假日,将17日(星期六)、18日(星期日)、25日(星期日)三个公休日分别调至21日(星期三)、22日(星期四)、23日(星期五);24日(星期六)照常公休,17日、25日上班。
+  * 三、“五一”:5月1日—7日放假,共7天。
+  * 其中,1日、2日、3日为法定假日,将4月28日(星期六)、29日(星期日)两个公休日调至5月4日(星期五)、7日(星期一);5月5日(星期六)、6日(星期日)照常公休,4月28日、29日上班。
+  * 四、“十一”:10月1日—7日放假,共7天。
+  * 其中,1日、2日、3日为法定假日,将9月29日(星期六)、30日(星期日)两个公休日调至10月4日(星期四)、5日(星期五);10月6日(星期六)、7日(星期日)照常公休,9月29日、30日上班。
+  * 
+  *   注意:明年元旦假期,今年年尾会放假。今年元旦假期,去年年尾要上班。
+  */
+  arrangement.yearAt(2007)
+    .nyd().rest(1, 1).to(1, 3).inLieu(1, 2).to(1, 3)
+    .sf().rest(2, 18).to(2, 24).work(2, 17).work(2, 25).inLieu(2, 22).to(2, 23)
+    .ld().rest(5, 1).to(5, 7).work(4, 28).to(4, 29).inLieu(5, 4).inLieu(5, 7)
+    .nd().rest(10, 1).to(10, 7).work(9, 29).to(9, 30).inLieu(10, 4).to(10, 5)
+    .nyd().rest(12, 30).to(12, 31).work(12, 29).inLieu(12, 31)
+  
+  /**
+  * 2006
+  *  http://www.gov.cn/jrzg/2005-12/22/content_133837.htm
+  * 一、元旦:1月1日—3日放假,共3天。
+  * 其中1月1日为法定假日,将12月31日(星期六)、1月1日(星期日)两个公休日调至1月2日(星期一)、3日(星期二),12月31日(星期六)上班。
+  * 二、春节:1月29日—2月4日(即农历大年初一至初七)放假,共7天。
+  * 其中,29日、30日、31日为法定假日,将1月28日(星期六)、29日(星期日)、2月5日(星期日)三个公休日调至2月1日(星期三)、2日(星期四)、3日(星期五),2月4日(星期六)照常公休,1月28日、2月5日上班。
+  * 三、“五一”:5月1日—7日放假,共7天。
+  * 其中,1日、2日、3日为法定假日,将4月29日(星期六)、30日(星期日)两个公休日调至5月4日(星期四)、5日(星期五),5月6日(星期六)、7日(星期日)照常公休,4月29日、30日上班。
+  * 四、“十一”:10月1日—7日放假,共7天。
+  * 其中,1日、2日、3日为法定假日,将9月30日(星期六)、10月1日(星期日)、8日(星期日)三个公休日调至10月4日(星期三)、5日(星期四)、6日(星期五),10月7日(星期六)照常公休,9月30日、10月8日上班。
+  * 
+  *   注意:明年元旦假期,今年年尾要上班。今年元旦假期,去年年尾要上班。
+  */
+  arrangement.yearAt(2006)
+    .nyd().rest(1, 1).to(1, 3)
+    .sf().rest(1, 29).to(2, 4).work(1, 28).work(2, 5).inLieu(2, 2).to(2, 3)
+    .ld().rest(5, 1).to(5, 7).work(4, 29).to(4, 30).inLieu(5, 4).to(5, 5)
+    .nd().rest(10, 1).to(10, 7).work(9, 30).work(10, 8).inLieu(10, 5).to(10, 6)
+    .nyd().work(12, 30).to(12, 31)
+  
+  /**
+  * 2005
+  * https://zhidao.baidu.com/question/2299098.html
+  * 国务院办公厅近日发出通知,2005年元旦、春节、“五一”、“十一”放假调休日期具体安排如下:
+  * 一、元旦:1月1日~3日放假,共3天。其中1月1日为法定假日,将1月1日(星期六)公休日调至1月3日(星期一),1月2日(星期日)照常公休。
+  * 二、春节:2月9日~15日(农历大年初一至初七)放假,共7天。其中,9日、10日、11日为法定假日,
+  * 2月12日(星期六)、13日(星期日)照常公休,将2月5日(星期六)、6日(星期日)两个公休日调至2月14日(星期一)、15日(星期二),
+  * 2月5日、6日上班。
+  * 三、“五一”:5月1日~7日放假,共7天。其中,1日、2日、3日为法定假日,将4月30日(星期六)、5月1日(星期日)、8日(星期日)三个公休日
+  * 调至5月4日(星期三)、5日(星期四)、6日(星期五),5月7日(星期六)照常公休,4月30日、5月8日上班。
+  * 四、“十一”:10月1日~7日放假,共7天。其中,1日、2日、3日为法定假日,将10月1日(星期六)、2日(星期日)两个公休日
+  * 调至10月4日(星期二)、5日(星期三),10月8日(星期六)、9日(星期日)两个公休日调至10月6日(星期四)、7日(星期五),10月8日、9日上班。
+  */
+  arrangement.yearAt(2005)
+    .nyd().rest(1, 1).to(1, 3)
+    .sf().rest(2, 9).to(2, 15).work(2, 5).to(2, 6).inLieu(2, 14).to(2, 15)
+    .ld().rest(5, 1).to(5, 7).work(4, 30).work(5, 8).inLieu(5, 5).to(5, 6)
+    .nd().rest(10, 1).to(10, 7).work(10, 8).to(10, 9).inLieu(10, 6).to(10, 7)
+  
+  /**
+  * 2004
+  *  https://zh.wikisource.org/zh-hans/国务院办公厅关于2004年部分节假日安排的通知
+  *  各省、自治区、直辖市人民政府,国务院各部委、各直属机构:
+  *    为便于各地区、各部门及早合理安排节假日旅游、交通运输、生产经营等有关工作,经国务院批准,现将2004年
+  *  元旦、春节、“五一”、“十一”放假调休日期具体安排通知如下:
+  *  一、元旦:1月1日放假。
+  *  二、春节:1月22日———28日(即农历大年初一至初七)放假,共7天。
+  *    其中,22日、23日、24日为法定假日,1月25日(星期日)照常公休,将1月17日(星期六)、18日(星期日)、24日(星期六)三个公休日
+  *    调至1月26日(星期一)、27日(星期二)、28日(星期三),1月17日、18日上班。
+  *  三、“五一”:5月1日———7日放假,共7天。
+  *    其中,1日、2日、3日为法定假日,将5月1日(星期六)、2日(星期日)两个公休日调至5月4日(星期二)、5日(星期三),
+  *    5月8日(星期六)、5月9日(星期日)两个公休日调至5月6日(星期四)、7日(星期五),5月8日、9日上班。
+  *  四、“十一”:10月1日———7日放假,共7天。
+  *    其中,1日、2日、3日为法定假日,将10月2日(星期六)、3日(星期日)两个公休日调至10月4日(星期一)、5日(星期二),
+  *    10月9日(星期六)、10日(星期日)两个公休日调至10月6日(星期三)、7日(星期四),10月9日、10日上班。
+  */
+  arrangement.yearAt(2004)
+    .nyd().rest(1, 1)
+    .sf().rest(1, 22).to(1, 28).work(1, 17).to(1, 18).inLieu(1, 27).to(1, 28)
+    .ld().rest(5, 1).to(5, 7).work(5, 8).to(5, 9).inLieu(5, 6).to(5, 7)
+    .nd().rest(10, 1).to(10, 7).work(10, 9).to(10, 10).inLieu(10, 6).to(10, 7)
+  
+  /**
+  * 注:2003年及以前的安排就很凌乱了(其实06/07两年也是叫“部分节假日安排”)
+  * 假如之后想要加的话可以参考以下地址:
+  * 2003: https://zh.wikisource.org/zh-hans/国务院办公厅关于2003年部分节假日休息安排的通知
+  * 2002: https://zh.wikisource.org/zh-hans/国务院办公厅关于2002年部分节假日休息安排的通知
+  * 2001: https://zh.wikisource.org/zh-hans/国务院办公厅关于2001年春节、“五一”、“十一”放假安排的通知
+  */
+}
+
+export default generate

+ 146 - 0
src/holidays/index.ts

@@ -0,0 +1,146 @@
+import dayjs, { Dayjs } from 'dayjs';
+import { holidays, workdays, inLieuDays } from './arrangement';
+import generate from './generate'
+
+generate()
+
+interface Holidays {
+  [key: string]: string;
+}
+
+interface DayDetails {
+  year: number | null;
+  month: number | null;
+  day: number | null;
+  holiday: string | null;
+  dayType: DayType | null;
+}
+
+enum DayType {
+  Holiday,
+  Workday,
+  InLieu
+}
+
+const _wrapDate = (date: dayjs.ConfigType): Dayjs => {
+  return dayjs(date);
+}
+
+const _validateDate = (...dates: dayjs.ConfigType[]): Dayjs | Dayjs[] => {
+  if (dates.length !== 1) {
+    return dates.map(date => _validateDate(date)) as Dayjs[];
+  }
+  const date = _wrapDate(dates[0]);
+  if (!date.isValid()) {
+    throw new Error(`unsupported type ${typeof date}, expected type is Date or Dayjs`);
+  }
+  const allHolidays = Object.keys(holidays).sort()
+  const minYear = dayjs(allHolidays[0]).year();
+  const maxYear = dayjs(allHolidays.slice(-1)[0]).year();
+  if (!(minYear <= date.year() && date.year() <= maxYear)) {
+    throw new Error(`no available data for year ${date.year()}, only year between [${minYear}, ${maxYear}] supported`);
+  }
+  return date;
+}
+
+/** 是否节假日 */
+const isHoliday = (date: dayjs.ConfigType): boolean => {
+  return !isWorkday(date);
+}
+
+/** 是否工作日 */
+const isWorkday = (date: dayjs.ConfigType): boolean => {
+  const validDate = _validateDate(date) as Dayjs;
+  const weekday = validDate.day();
+  const formattedDate = validDate.format('YYYY-MM-DD');
+
+  return !!(workdays[formattedDate] || (weekday >= 1 && weekday <= 5 && !holidays[formattedDate]));
+}
+
+/** 是否调休日 - 是节假日,但后续有需要补班 */
+const isInLieu = (date: dayjs.ConfigType): boolean => {
+  date = _validateDate(date) as Dayjs;
+  return !!inLieuDays[date.format('YYYY-MM-DD')];
+}
+
+/** 获取工作日详情 */
+const getDayDetail = (date: dayjs.ConfigType): { work: boolean, name: string } => {
+  date = _validateDate(date) as Dayjs;
+  if (workdays[date.format('YYYY-MM-DD')]) {
+    return {
+      work: true,
+      name: workdays[date.format('YYYY-MM-DD')]
+    }
+  } else if (holidays[date.format('YYYY-MM-DD')]) {
+    return {
+      work: false,
+      name: holidays[date.format('YYYY-MM-DD')]
+    }
+  } else {
+    const weekday = date.day();
+    return {
+      work: weekday !== 0 && weekday !== 6,
+      name: date.format('dddd')
+    }
+  }
+}
+
+const getDates = (start: dayjs.ConfigType, end: dayjs.ConfigType): Dayjs[] => {
+  start = _wrapDate(start);
+  end = _wrapDate(end);
+  const deltaDays = end.diff(start, 'day');
+  return Array.from({ length: deltaDays + 1 }, (_, i) => start.add(i, 'day'));
+}
+
+/** 获取节假日 */
+const getHolidays = (start: dayjs.ConfigType, end: dayjs.ConfigType, includeWeekends: boolean = true): Dayjs[] => {
+  start = _validateDate(start) as Dayjs;
+  end = _validateDate(end) as Dayjs;
+  if (includeWeekends) {
+    return getDates(start, end).filter(isHoliday);
+  }
+  return getDates(start, end).filter(date => holidays[date.format('YYYY-MM-DD')]);
+}
+
+/** 获取工作日 */
+const getWorkdays = (start: dayjs.ConfigType, end: dayjs.ConfigType, includeWeekends: boolean = true): Dayjs[] => {
+  start = _validateDate(start) as Dayjs;
+  end = _validateDate(end) as Dayjs;
+  if (includeWeekends) {
+    return getDates(start, end).filter(isWorkday);
+  }
+  return getDates(start, end).filter(date => isWorkday(date) && date.day() >= 1 && date.day() <= 5);
+}
+
+/* 查找从 date 开始 第 n 个工作日, 0 为当天 */
+const findWorkday = (deltaDays: number = 0, date: dayjs.ConfigType = dayjs()): Dayjs => {
+  date = _wrapDate(date);
+
+  if (deltaDays === 0) {
+    if (isWorkday(date)) {
+      return date;
+    }
+    deltaDays = 1;
+  }
+
+  const sign = deltaDays > 0 ? 1 : -1;
+  let daysToAdd = Math.abs(deltaDays);
+
+  while (daysToAdd > 0) {
+    date = date.add(sign, 'day');
+    if (isWorkday(date)) {
+      daysToAdd--;
+    }
+  }
+
+  return date;
+}
+
+export default {
+  isInLieu,
+  getDayDetail,
+  getDates,
+  getHolidays,
+  getWorkdays,
+  findWorkday,
+}

+ 0 - 0
src/index.ts


+ 41 - 0
src/solar_terms/README.md

@@ -0,0 +1,41 @@
+# 关于节气计算 
+
+
+### 二十四节气的计算公式
+
+通用寿星公式:
+\[ 日期 = [Y \times D + C] - L \]
+
+其中:
+- \[ \] 表示取整数部分
+- Y 表示年份的后两位数字
+- D 表示固定的常数 0.2422(代表地球绕太阳公转的平均速度)
+- C 表示每个节气的常数,通常分为 20 世纪和 21 世纪不同的值
+- L 表示闰年修正值,等于年份后两位数字除以 4 的整数部分。对于小寒、大寒、立春、雨水,这个修正值为 (Y-1)/4
+
+### C 值的来源
+
+每个节气都有一个对应的 C 值,这个 C 值是通过长时间的天文观测和计算得出的。不同的节气在不同的世纪有不同的 C 值,以适应地球公转轨道的微小变化。这些 C 值被分为 20 世纪和 21 世纪的值。
+
+以下是部分 C 值的示例:
+- 立春 (the_beginning_of_spring): 20 世纪的 C 值是 4.6295, 21 世纪的 C 值是 3.87
+- 雨水 (rain_water): 20 世纪的 C 值是 19.4599, 21 世纪的 C 值是 18.73
+- 惊蛰 (the_waking_of_insects): 20 世纪的 C 值是 6.3926, 21 世纪的 C 值是 5.63
+
+### 计算 C 值的公式举例
+
+例如,计算 2024 年立春的日期:
+\[ Y = 24 \](2024 年的后两位)
+\[ D = 0.2422 \]
+\[ C = 3.87 \](21 世纪的立春 C 值)
+
+计算公式为:
+\[ 日期 = [24 \times 0.2422 + 3.87] - \left\lfloor \frac{24}{4} \right\rfloor \]
+\[ 日期 = [24 \times 0.2422 + 3.87] - 6 \]
+\[ 日期 = [9.0028 + 3.87] - 6 \]
+\[ 日期 = [12.8728] - 6 \]
+\[ 日期 = 12 - 6 = 6 \]
+
+因此,2024 年立春的日期为 2 月 6 日。
+
+通过这些计算公式和 C 值,我们可以确定每年的二十四节气的具体日期。这些 C 值和计算方法是基于多年的天文观测和计算得出的,已经在实践中得到了验证和使用。

+ 126 - 0
src/solar_terms/constants.ts

@@ -0,0 +1,126 @@
+// Define the type for all solar terms
+export type SolarTermKey =
+  | "the_beginning_of_spring"
+  | "rain_water"
+  | "the_waking_of_insects"
+  | "the_spring_equinox"
+  | "pure_brightness"
+  | "grain_rain"
+  | "the_beginning_of_summer"
+  | "lesser_fullness_of_grain"
+  | "grain_in_beard"
+  | "the_summer_solstice"
+  | "lesser_heat"
+  | "greater_heat"
+  | "the_beginning_of_autumn"
+  | "the_end_of_heat"
+  | "white_dew"
+  | "the_autumn_equinox"
+  | "code_dew"
+  | "frost_descent"
+  | "the_beginning_of_winter"
+  | "lesser_snow"
+  | "greater_snow"
+  | "the_winter_solstice"
+  | "lesser_cold"
+  | "greater_cold";
+
+/**
+ * 计算节气用的 C 值
+ * 2000年的小寒、大寒、立春、雨水按照20世纪的C值来算
+ * 节气: [20世纪值, 21世纪值]
+ * */
+export const SOLAR_TERMS_C_NUMS = {
+  the_beginning_of_spring: [4.6295, 3.87],
+  rain_water: [19.4599, 18.73],
+  the_waking_of_insects: [6.3926, 5.63],
+  the_spring_equinox: [21.4155, 20.646],
+  pure_brightness: [5.59, 4.81],
+  grain_rain: [20.888, 20.1],
+  the_beginning_of_summer: [6.318, 5.52],
+  lesser_fullness_of_grain: [21.86, 21.04],
+  grain_in_beard: [6.5, 5.678],
+  the_summer_solstice: [22.2, 21.37],
+  lesser_heat: [7.928, 7.108],
+  greater_heat: [23.65, 22.83],
+  the_beginning_of_autumn: [28.35, 7.5],
+  the_end_of_heat: [23.95, 23.13],
+  white_dew: [8.44, 7.646],
+  the_autumn_equinox: [23.822, 23.042],
+  code_dew: [9.098, 8.318],
+  frost_descent: [24.218, 23.438],
+  the_beginning_of_winter: [8.218, 7.438],
+  lesser_snow: [23.08, 22.36],
+  greater_snow: [7.9, 7.18],
+  the_winter_solstice: [22.6, 21.94],
+  lesser_cold: [6.11, 5.4055],
+  greater_cold: [20.84, 20.12],
+};
+
+/** 月份和节气对应关系 */
+export const SOLAR_TERMS_MONTH = {
+  1: ["lesser_cold", "greater_cold"],
+  2: ["the_beginning_of_spring", "rain_water"],
+  3: ["the_waking_of_insects", "the_spring_equinox"],
+  4: ["pure_brightness", "grain_rain"],
+  5: ["the_beginning_of_summer", "lesser_fullness_of_grain"],
+  6: ["grain_in_beard", "the_summer_solstice"],
+  7: ["lesser_heat", "greater_heat"],
+  8: ["the_beginning_of_autumn", "the_end_of_heat"],
+  9: ["white_dew", "the_autumn_equinox"],
+  10: ["code_dew", "frost_descent"],
+  11: ["the_beginning_of_winter", "lesser_snow"],
+  12: ["greater_snow", "the_winter_solstice"],
+};
+
+export const SOLAR_TERMS_DELTA = {
+  "2026_rain_water": -1,
+  "2084_the_spring_equinox": 1,
+  "1911_the_beginning_of_summer": 1,
+  "2008_lesser_fullness_of_grain": 1,
+  "1902_grain_in_beard": 1,
+  "1928_the_summer_solstice": 1,
+  "1925_lesser_heat": 1,
+  "2016_lesser_heat": 1,
+  "1922_greater_heat": 1,
+  "2002_the_beginning_of_autumn": 1,
+  "1927_white_dew": 1,
+  "1942_the_autumn_equinox": 1,
+  "2089_frost_descent": 1,
+  "2089_the_beginning_of_winter": 1,
+  "1978_lesser_snow": 1,
+  "1954_greater_snow": 1,
+  "1918_the_winter_solstice": -1,
+  "2021_the_winter_solstice": -1,
+  "1982_lesser_cold": 1,
+  "2019_lesser_cold": -1,
+  "2000_greater_cold": 1,
+  "2082_greater_cold": 1,
+};
+
+export const SOLAR_TERMS = {
+  lesser_cold: "小寒",
+  greater_cold: "大寒",
+  the_beginning_of_spring: "立春",
+  rain_water: "雨水",
+  the_waking_of_insects: "惊蛰",
+  the_spring_equinox: "春分",
+  pure_brightness: "清明",
+  grain_rain: "谷雨",
+  the_beginning_of_summer: "立夏",
+  lesser_fullness_of_grain: "小满",
+  grain_in_beard: "芒种",
+  the_summer_solstice: "夏至",
+  lesser_heat: "小暑",
+  greater_heat: "大暑",
+  the_beginning_of_autumn: "立秋",
+  the_end_of_heat: "处暑",
+  white_dew: "白露",
+  the_autumn_equinox: "秋分",
+  code_dew: "寒露",
+  frost_descent: "霜降",
+  the_beginning_of_winter: "立冬",
+  lesser_snow: "小雪",
+  greater_snow: "大雪",
+  the_winter_solstice: "冬至",
+};

+ 92 - 0
src/solar_terms/index.ts

@@ -0,0 +1,92 @@
+import dayjs from "dayjs";
+import {
+  SOLAR_TERMS_C_NUMS,
+  SOLAR_TERMS_DELTA,
+  SOLAR_TERMS_MONTH,
+  SOLAR_TERMS,
+  type SolarTermKey,
+} from "./constants";
+
+// wrapDate to the start of the day
+const wrapDate = (date: dayjs.ConfigType): dayjs.Dayjs => {
+  return dayjs(date).startOf("day");
+};
+
+/* Get solar term date => 获取节气日期 */
+const getSolarTermDate = (
+  year: number,
+  month: number,
+  term: SolarTermKey
+): dayjs.Dayjs => {
+  const century = year >= 2000 ? 21 : 20;
+  const Y = year % 100;
+  const D = 0.2422;
+  const C = SOLAR_TERMS_C_NUMS[term][century === 21 ? 1 : 0];
+  let L = Math.floor(Y / 4);
+
+  if (
+    [
+      "lesser_cold",
+      "greater_cold",
+      "the_beginning_of_spring",
+      "rain_water",
+    ].includes(term)
+  ) {
+    L = Math.floor((Y - 1) / 4);
+  }
+
+  let day = Math.floor(Y * D + C) - L;
+  const delta = SOLAR_TERMS_DELTA[`${year}_${term}`];
+  if (delta) {
+    day += delta;
+  }
+
+  return dayjs(`${year}-${month}-${day}`);
+};
+
+export interface SolarTerm {
+  date: Date;
+  term: SolarTermKey;
+  name: string;
+};
+
+/**
+ * Get solar terms => 获取范围日期内的节气
+ * @param start 开始日期
+ * @param end 不传只查当天
+ * @returns Array of solar terms => 节气数组
+ */
+export const getSolarTerms = (
+  start: dayjs.ConfigType,
+  end?: dayjs.ConfigType
+): SolarTerm[] => {
+  const result: SolarTerm[] = [];
+  let current = wrapDate(start);
+  const endDate = wrapDate(end || start);
+
+  while (current.isBefore(endDate) || current.isSame(endDate)) {
+    const year = current.year();
+    const month = current.month() + 1;
+
+    SOLAR_TERMS_MONTH[month].forEach((term: SolarTermKey) => {
+      const solarTermDate = getSolarTermDate(year, month, term);
+      if (
+        (solarTermDate?.isBefore(endDate) || solarTermDate?.isSame(endDate)) &&
+        (solarTermDate?.isAfter(current) || solarTermDate?.isSame(current))
+      ) {
+        result.push({
+          date: solarTermDate.toDate(),
+          term,
+          name: SOLAR_TERMS[term],
+        });
+      }
+    });
+
+    /* 处理下个日期 */
+    month === 12
+      ? (current = current.add(1, "year").startOf("year"))
+      : (current = current.add(1, "month").startOf("month"));
+  }
+
+  return result;
+};

+ 4 - 0
vite.config.ts

@@ -0,0 +1,4 @@
+import { defineConfig } from 'vite'
+
+// https://vitejs.dev/config/
+export default defineConfig({})