blogger-plugin 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/constants.cjs +28 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.mjs +25 -0
- package/dist/constants.mjs.map +1 -0
- package/dist/index.cjs +0 -1
- package/dist/index.d.cts +1 -2
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +1 -0
- package/dist/tailwind.cjs +64 -0
- package/dist/tailwind.cjs.map +1 -0
- package/dist/tailwind.mjs +59 -0
- package/dist/tailwind.mjs.map +1 -0
- package/dist/utils.cjs +167 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.mjs +161 -0
- package/dist/utils.mjs.map +1 -0
- package/dist/vite.cjs +263 -583
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +9 -7
- package/dist/vite.d.mts +13 -0
- package/dist/vite.mjs +289 -0
- package/dist/vite.mjs.map +1 -0
- package/package.json +15 -12
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -1
- package/dist/index.js.map +0 -1
- package/dist/vite.d.ts +0 -11
- package/dist/vite.js +0 -612
- package/dist/vite.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ A plugin that allows you to use modern frontend frameworks inside a Blogger temp
|
|
|
7
7
|
- ✅ Supports **all major frontend frameworks** supported by Vite — including **React, Vue, Svelte, Solid**, and more.
|
|
8
8
|
- 🔄 Enables **local development** by proxying unhandled requests to a Blogger blog.
|
|
9
9
|
- 🧩 Works seamlessly with Vite’s dev server and build system.
|
|
10
|
+
- 🎨 Automatic **Tailwind CSS** support — Extracts classes from proxied content during development.
|
|
10
11
|
|
|
11
12
|
## 📦 Installation
|
|
12
13
|
|
|
@@ -105,6 +106,26 @@ The `blogger()` plugin accepts the following options:
|
|
|
105
106
|
| `styles` | `string[]` | `undefined` | Custom CSS file paths to inject into the template. Useful for global stylesheets or critical CSS. |
|
|
106
107
|
| `template` | `string` | Auto-detected | Path to your Blogger XML template file. If not specified, the plugin will search for: `{index\|template\|theme}.xml`, `src/{index\|template\|theme}.xml` |
|
|
107
108
|
|
|
109
|
+
### Tailwind CSS Support
|
|
110
|
+
|
|
111
|
+
The plugin **automatically detects and supports Tailwind CSS**. When Tailwind is configured in your project, the plugin:
|
|
112
|
+
|
|
113
|
+
1. **During development:** Extracts Tailwind classes from the HTML content of your proxied Blogger blog as you navigate and preview pages, caching them in `.tailwind-classes.json`
|
|
114
|
+
2. **During build:** Extracts Tailwind classes **only from your template XML** file to ensure all classes used in your template are included in the production CSS
|
|
115
|
+
3. **Optimizes compilation** by providing Tailwind with the discovered classes
|
|
116
|
+
|
|
117
|
+
To use Tailwind CSS with the blogger-plugin:
|
|
118
|
+
|
|
119
|
+
1. **Install Tailwind CSS** and configure it as usual in your project
|
|
120
|
+
2. The plugin will **automatically detect** your Tailwind setup — no additional configuration needed!
|
|
121
|
+
3. **During development:** Navigate through your blog preview to allow Tailwind to extract classes from your blog's HTML
|
|
122
|
+
4. **During build:** Make sure your template XML includes all the Tailwind classes you're using, as only the template is scanned for production
|
|
123
|
+
|
|
124
|
+
The plugin gathers Tailwind classes from your proxied blog during development and from your template during the build for complete coverage in production.
|
|
125
|
+
|
|
126
|
+
> [!TIP]
|
|
127
|
+
> Add `.tailwind-classes.json` to your `.gitignore` — it's a generated cache file that will be recreated during development and build.
|
|
128
|
+
|
|
108
129
|
### Example with All Options
|
|
109
130
|
|
|
110
131
|
```ts
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.__toESM = __toESM;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let vite = require("vite");
|
|
3
|
+
//#region src/constants.ts
|
|
4
|
+
const DEFAULT_MODULES = [
|
|
5
|
+
"src/index.tsx",
|
|
6
|
+
"src/index.ts",
|
|
7
|
+
"src/index.jsx",
|
|
8
|
+
"src/index.js",
|
|
9
|
+
"src/main.tsx",
|
|
10
|
+
"src/main.ts",
|
|
11
|
+
"src/main.jsx",
|
|
12
|
+
"src/main.js"
|
|
13
|
+
];
|
|
14
|
+
const DEFAULT_TEMPLATES = [
|
|
15
|
+
"index.xml",
|
|
16
|
+
"template.xml",
|
|
17
|
+
"theme.xml",
|
|
18
|
+
"src/index.xml",
|
|
19
|
+
"src/template.xml",
|
|
20
|
+
"src/theme.xml"
|
|
21
|
+
];
|
|
22
|
+
const VITE_BUNDLER_KEY = Number(vite.version.split(".")[0]) >= 8 ? "rolldownOptions" : "rollupOptions";
|
|
23
|
+
//#endregion
|
|
24
|
+
exports.DEFAULT_MODULES = DEFAULT_MODULES;
|
|
25
|
+
exports.DEFAULT_TEMPLATES = DEFAULT_TEMPLATES;
|
|
26
|
+
exports.VITE_BUNDLER_KEY = VITE_BUNDLER_KEY;
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=constants.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.cjs","names":["viteVersion"],"sources":["../src/constants.ts"],"sourcesContent":["import { version as viteVersion } from 'vite';\n\nexport const DEFAULT_MODULES = [\n 'src/index.tsx',\n 'src/index.ts',\n 'src/index.jsx',\n 'src/index.js',\n 'src/main.tsx',\n 'src/main.ts',\n 'src/main.jsx',\n 'src/main.js',\n] as const;\n\nexport const DEFAULT_TEMPLATES = ['index.xml', 'template.xml', 'theme.xml', 'src/index.xml', 'src/template.xml', 'src/theme.xml'] as const;\n\nexport const VITE_MAJOR = Number(viteVersion.split('.')[0]);\nexport const VITE_BUNDLER_KEY = (VITE_MAJOR >= 8 ? 'rolldownOptions' : 'rollupOptions') as 'rollupOptions';\n"],"mappings":";;;AAEA,MAAa,kBAAkB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,MAAa,oBAAoB;CAAC;CAAa;CAAgB;CAAa;CAAiB;CAAoB;CAAgB;AAGjI,MAAa,mBADa,OAAOA,KAAAA,QAAY,MAAM,IAAI,CAAC,GACvB,IAAc,IAAI,oBAAoB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { version } from "vite";
|
|
2
|
+
//#region src/constants.ts
|
|
3
|
+
const DEFAULT_MODULES = [
|
|
4
|
+
"src/index.tsx",
|
|
5
|
+
"src/index.ts",
|
|
6
|
+
"src/index.jsx",
|
|
7
|
+
"src/index.js",
|
|
8
|
+
"src/main.tsx",
|
|
9
|
+
"src/main.ts",
|
|
10
|
+
"src/main.jsx",
|
|
11
|
+
"src/main.js"
|
|
12
|
+
];
|
|
13
|
+
const DEFAULT_TEMPLATES = [
|
|
14
|
+
"index.xml",
|
|
15
|
+
"template.xml",
|
|
16
|
+
"theme.xml",
|
|
17
|
+
"src/index.xml",
|
|
18
|
+
"src/template.xml",
|
|
19
|
+
"src/theme.xml"
|
|
20
|
+
];
|
|
21
|
+
const VITE_BUNDLER_KEY = Number(version.split(".")[0]) >= 8 ? "rolldownOptions" : "rollupOptions";
|
|
22
|
+
//#endregion
|
|
23
|
+
export { DEFAULT_MODULES, DEFAULT_TEMPLATES, VITE_BUNDLER_KEY };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=constants.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.mjs","names":["viteVersion"],"sources":["../src/constants.ts"],"sourcesContent":["import { version as viteVersion } from 'vite';\n\nexport const DEFAULT_MODULES = [\n 'src/index.tsx',\n 'src/index.ts',\n 'src/index.jsx',\n 'src/index.js',\n 'src/main.tsx',\n 'src/main.ts',\n 'src/main.jsx',\n 'src/main.js',\n] as const;\n\nexport const DEFAULT_TEMPLATES = ['index.xml', 'template.xml', 'theme.xml', 'src/index.xml', 'src/template.xml', 'src/theme.xml'] as const;\n\nexport const VITE_MAJOR = Number(viteVersion.split('.')[0]);\nexport const VITE_BUNDLER_KEY = (VITE_MAJOR >= 8 ? 'rolldownOptions' : 'rollupOptions') as 'rollupOptions';\n"],"mappings":";;AAEA,MAAa,kBAAkB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,MAAa,oBAAoB;CAAC;CAAa;CAAgB;CAAa;CAAiB;CAAoB;CAAgB;AAGjI,MAAa,mBADa,OAAOA,QAAY,MAAM,IAAI,CAAC,GACvB,IAAc,IAAI,oBAAoB"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.cts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { }
|
|
1
|
+
export { };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let node_fs = require("node:fs");
|
|
3
|
+
node_fs = require_runtime.__toESM(node_fs, 1);
|
|
4
|
+
let node_path = require("node:path");
|
|
5
|
+
node_path = require_runtime.__toESM(node_path, 1);
|
|
6
|
+
let tailwindcss_iso = require("tailwindcss-iso");
|
|
7
|
+
//#region src/tailwind.ts
|
|
8
|
+
const TAILWIND_CACHE_FILE = ".tailwind-classes.json";
|
|
9
|
+
function readFileContent(file) {
|
|
10
|
+
if (!node_fs.existsSync(file)) return null;
|
|
11
|
+
return node_fs.readFileSync(file, "utf-8");
|
|
12
|
+
}
|
|
13
|
+
function writeFileContent(file, content) {
|
|
14
|
+
const dirname = node_path.dirname(file);
|
|
15
|
+
if (!node_fs.existsSync(dirname)) node_fs.mkdirSync(dirname, { recursive: true });
|
|
16
|
+
const current = readFileContent(file);
|
|
17
|
+
if (current === null || content !== current) {
|
|
18
|
+
node_fs.writeFileSync(file, content, "utf8");
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
function removeFile(file) {
|
|
24
|
+
if (!node_fs.existsSync(file)) return false;
|
|
25
|
+
node_fs.rmSync(file);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
function getTailwindCacheFile(root) {
|
|
29
|
+
return node_path.resolve(root, TAILWIND_CACHE_FILE);
|
|
30
|
+
}
|
|
31
|
+
function readTailwindCache(root) {
|
|
32
|
+
const content = readFileContent(getTailwindCacheFile(root));
|
|
33
|
+
if (!content) return null;
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(content);
|
|
36
|
+
} catch (_unused) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function writeTailwindCache(root, classes) {
|
|
41
|
+
const file = getTailwindCacheFile(root);
|
|
42
|
+
const content = JSON.stringify(classes, null, 2);
|
|
43
|
+
return {
|
|
44
|
+
updated: writeFileContent(file, content),
|
|
45
|
+
content
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function clearTailwindCache(root) {
|
|
49
|
+
writeTailwindCache(root, []);
|
|
50
|
+
}
|
|
51
|
+
function removeTailwindCache(root) {
|
|
52
|
+
removeFile(getTailwindCacheFile(root));
|
|
53
|
+
}
|
|
54
|
+
async function updateTailwindCache(root, content) {
|
|
55
|
+
var _readTailwindCache;
|
|
56
|
+
const classes = await (0, tailwindcss_iso.getTailwindClasses)({ content });
|
|
57
|
+
writeTailwindCache(root, [...new Set([...(_readTailwindCache = readTailwindCache(root)) !== null && _readTailwindCache !== void 0 ? _readTailwindCache : [], ...classes])]);
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
exports.clearTailwindCache = clearTailwindCache;
|
|
61
|
+
exports.removeTailwindCache = removeTailwindCache;
|
|
62
|
+
exports.updateTailwindCache = updateTailwindCache;
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=tailwind.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tailwind.cjs","names":["fs","path"],"sources":["../src/tailwind.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { getTailwindClasses } from 'tailwindcss-iso';\n\nconst TAILWIND_CACHE_FILE = '.tailwind-classes.json';\n\nfunction readFileContent(file: string): string | null {\n if (!fs.existsSync(file)) {\n return null;\n }\n return fs.readFileSync(file, 'utf-8');\n}\n\nfunction writeFileContent(file: string, content: string): boolean {\n const dirname = path.dirname(file);\n\n if (!fs.existsSync(dirname)) {\n fs.mkdirSync(dirname, { recursive: true });\n }\n\n const current = readFileContent(file);\n if (current === null || content !== current) {\n fs.writeFileSync(file, content, 'utf8');\n return true;\n }\n\n return false;\n}\n\nfunction removeFile(file: string): boolean {\n if (!fs.existsSync(file)) {\n return false;\n }\n fs.rmSync(file);\n return true;\n}\n\nfunction getTailwindCacheFile(root: string): string {\n return path.resolve(root, TAILWIND_CACHE_FILE);\n}\n\nexport function readTailwindCache(root: string): string[] | null {\n const content = readFileContent(getTailwindCacheFile(root));\n if (!content) {\n return null;\n }\n try {\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\nexport function writeTailwindCache(root: string, classes: string[]): { updated: boolean; content: string } {\n const file = getTailwindCacheFile(root);\n const content = JSON.stringify(classes, null, 2);\n const updated = writeFileContent(file, content);\n return { updated, content };\n}\n\nexport function clearTailwindCache(root: string): void {\n writeTailwindCache(root, []);\n}\n\nexport function removeTailwindCache(root: string): void {\n removeFile(getTailwindCacheFile(root));\n}\n\nexport async function updateTailwindCache(root: string, content: string): Promise<void> {\n const classes = (await getTailwindClasses({\n content,\n })) as string[];\n\n writeTailwindCache(root, [...new Set([...(readTailwindCache(root) ?? []), ...classes])]);\n}\n"],"mappings":";;;;;;;AAIA,MAAM,sBAAsB;AAE5B,SAAS,gBAAgB,MAA6B;AACpD,KAAI,CAACA,QAAG,WAAW,KAAK,CACtB,QAAO;AAET,QAAOA,QAAG,aAAa,MAAM,QAAQ;;AAGvC,SAAS,iBAAiB,MAAc,SAA0B;CAChE,MAAM,UAAUC,UAAK,QAAQ,KAAK;AAElC,KAAI,CAACD,QAAG,WAAW,QAAQ,CACzB,SAAG,UAAU,SAAS,EAAE,WAAW,MAAM,CAAC;CAG5C,MAAM,UAAU,gBAAgB,KAAK;AACrC,KAAI,YAAY,QAAQ,YAAY,SAAS;AAC3C,UAAG,cAAc,MAAM,SAAS,OAAO;AACvC,SAAO;;AAGT,QAAO;;AAGT,SAAS,WAAW,MAAuB;AACzC,KAAI,CAACA,QAAG,WAAW,KAAK,CACtB,QAAO;AAET,SAAG,OAAO,KAAK;AACf,QAAO;;AAGT,SAAS,qBAAqB,MAAsB;AAClD,QAAOC,UAAK,QAAQ,MAAM,oBAAoB;;AAGhD,SAAgB,kBAAkB,MAA+B;CAC/D,MAAM,UAAU,gBAAgB,qBAAqB,KAAK,CAAC;AAC3D,KAAI,CAAC,QACH,QAAO;AAET,KAAI;AACF,SAAO,KAAK,MAAM,QAAQ;mBACpB;AACN,SAAO;;;AAIX,SAAgB,mBAAmB,MAAc,SAA0D;CACzG,MAAM,OAAO,qBAAqB,KAAK;CACvC,MAAM,UAAU,KAAK,UAAU,SAAS,MAAM,EAAE;AAEhD,QAAO;EAAE,SADO,iBAAiB,MAAM,QACvB;EAAE;EAAS;;AAG7B,SAAgB,mBAAmB,MAAoB;AACrD,oBAAmB,MAAM,EAAE,CAAC;;AAG9B,SAAgB,oBAAoB,MAAoB;AACtD,YAAW,qBAAqB,KAAK,CAAC;;AAGxC,eAAsB,oBAAoB,MAAc,SAAgC;;CACtF,MAAM,UAAW,OAAA,GAAA,gBAAA,oBAAyB,EACxC,SACD,CAAC;AAEF,oBAAmB,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAA,qBAAI,kBAAkB,KAAK,MAAA,QAAA,uBAAA,KAAA,IAAA,qBAAI,EAAE,EAAG,GAAG,QAAQ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { getTailwindClasses } from "tailwindcss-iso";
|
|
4
|
+
//#region src/tailwind.ts
|
|
5
|
+
const TAILWIND_CACHE_FILE = ".tailwind-classes.json";
|
|
6
|
+
function readFileContent(file) {
|
|
7
|
+
if (!fs.existsSync(file)) return null;
|
|
8
|
+
return fs.readFileSync(file, "utf-8");
|
|
9
|
+
}
|
|
10
|
+
function writeFileContent(file, content) {
|
|
11
|
+
const dirname = path.dirname(file);
|
|
12
|
+
if (!fs.existsSync(dirname)) fs.mkdirSync(dirname, { recursive: true });
|
|
13
|
+
const current = readFileContent(file);
|
|
14
|
+
if (current === null || content !== current) {
|
|
15
|
+
fs.writeFileSync(file, content, "utf8");
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
function removeFile(file) {
|
|
21
|
+
if (!fs.existsSync(file)) return false;
|
|
22
|
+
fs.rmSync(file);
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
function getTailwindCacheFile(root) {
|
|
26
|
+
return path.resolve(root, TAILWIND_CACHE_FILE);
|
|
27
|
+
}
|
|
28
|
+
function readTailwindCache(root) {
|
|
29
|
+
const content = readFileContent(getTailwindCacheFile(root));
|
|
30
|
+
if (!content) return null;
|
|
31
|
+
try {
|
|
32
|
+
return JSON.parse(content);
|
|
33
|
+
} catch (_unused) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function writeTailwindCache(root, classes) {
|
|
38
|
+
const file = getTailwindCacheFile(root);
|
|
39
|
+
const content = JSON.stringify(classes, null, 2);
|
|
40
|
+
return {
|
|
41
|
+
updated: writeFileContent(file, content),
|
|
42
|
+
content
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function clearTailwindCache(root) {
|
|
46
|
+
writeTailwindCache(root, []);
|
|
47
|
+
}
|
|
48
|
+
function removeTailwindCache(root) {
|
|
49
|
+
removeFile(getTailwindCacheFile(root));
|
|
50
|
+
}
|
|
51
|
+
async function updateTailwindCache(root, content) {
|
|
52
|
+
var _readTailwindCache;
|
|
53
|
+
const classes = await getTailwindClasses({ content });
|
|
54
|
+
writeTailwindCache(root, [...new Set([...(_readTailwindCache = readTailwindCache(root)) !== null && _readTailwindCache !== void 0 ? _readTailwindCache : [], ...classes])]);
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { clearTailwindCache, removeTailwindCache, updateTailwindCache };
|
|
58
|
+
|
|
59
|
+
//# sourceMappingURL=tailwind.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tailwind.mjs","names":[],"sources":["../src/tailwind.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { getTailwindClasses } from 'tailwindcss-iso';\n\nconst TAILWIND_CACHE_FILE = '.tailwind-classes.json';\n\nfunction readFileContent(file: string): string | null {\n if (!fs.existsSync(file)) {\n return null;\n }\n return fs.readFileSync(file, 'utf-8');\n}\n\nfunction writeFileContent(file: string, content: string): boolean {\n const dirname = path.dirname(file);\n\n if (!fs.existsSync(dirname)) {\n fs.mkdirSync(dirname, { recursive: true });\n }\n\n const current = readFileContent(file);\n if (current === null || content !== current) {\n fs.writeFileSync(file, content, 'utf8');\n return true;\n }\n\n return false;\n}\n\nfunction removeFile(file: string): boolean {\n if (!fs.existsSync(file)) {\n return false;\n }\n fs.rmSync(file);\n return true;\n}\n\nfunction getTailwindCacheFile(root: string): string {\n return path.resolve(root, TAILWIND_CACHE_FILE);\n}\n\nexport function readTailwindCache(root: string): string[] | null {\n const content = readFileContent(getTailwindCacheFile(root));\n if (!content) {\n return null;\n }\n try {\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\nexport function writeTailwindCache(root: string, classes: string[]): { updated: boolean; content: string } {\n const file = getTailwindCacheFile(root);\n const content = JSON.stringify(classes, null, 2);\n const updated = writeFileContent(file, content);\n return { updated, content };\n}\n\nexport function clearTailwindCache(root: string): void {\n writeTailwindCache(root, []);\n}\n\nexport function removeTailwindCache(root: string): void {\n removeFile(getTailwindCacheFile(root));\n}\n\nexport async function updateTailwindCache(root: string, content: string): Promise<void> {\n const classes = (await getTailwindClasses({\n content,\n })) as string[];\n\n writeTailwindCache(root, [...new Set([...(readTailwindCache(root) ?? []), ...classes])]);\n}\n"],"mappings":";;;;AAIA,MAAM,sBAAsB;AAE5B,SAAS,gBAAgB,MAA6B;AACpD,KAAI,CAAC,GAAG,WAAW,KAAK,CACtB,QAAO;AAET,QAAO,GAAG,aAAa,MAAM,QAAQ;;AAGvC,SAAS,iBAAiB,MAAc,SAA0B;CAChE,MAAM,UAAU,KAAK,QAAQ,KAAK;AAElC,KAAI,CAAC,GAAG,WAAW,QAAQ,CACzB,IAAG,UAAU,SAAS,EAAE,WAAW,MAAM,CAAC;CAG5C,MAAM,UAAU,gBAAgB,KAAK;AACrC,KAAI,YAAY,QAAQ,YAAY,SAAS;AAC3C,KAAG,cAAc,MAAM,SAAS,OAAO;AACvC,SAAO;;AAGT,QAAO;;AAGT,SAAS,WAAW,MAAuB;AACzC,KAAI,CAAC,GAAG,WAAW,KAAK,CACtB,QAAO;AAET,IAAG,OAAO,KAAK;AACf,QAAO;;AAGT,SAAS,qBAAqB,MAAsB;AAClD,QAAO,KAAK,QAAQ,MAAM,oBAAoB;;AAGhD,SAAgB,kBAAkB,MAA+B;CAC/D,MAAM,UAAU,gBAAgB,qBAAqB,KAAK,CAAC;AAC3D,KAAI,CAAC,QACH,QAAO;AAET,KAAI;AACF,SAAO,KAAK,MAAM,QAAQ;mBACpB;AACN,SAAO;;;AAIX,SAAgB,mBAAmB,MAAc,SAA0D;CACzG,MAAM,OAAO,qBAAqB,KAAK;CACvC,MAAM,UAAU,KAAK,UAAU,SAAS,MAAM,EAAE;AAEhD,QAAO;EAAE,SADO,iBAAiB,MAAM,QACvB;EAAE;EAAS;;AAG7B,SAAgB,mBAAmB,MAAoB;AACrD,oBAAmB,MAAM,EAAE,CAAC;;AAG9B,SAAgB,oBAAoB,MAAoB;AACtD,YAAW,qBAAqB,KAAK,CAAC;;AAGxC,eAAsB,oBAAoB,MAAc,SAAgC;;CACtF,MAAM,UAAW,MAAM,mBAAmB,EACxC,SACD,CAAC;AAEF,oBAAmB,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAA,qBAAI,kBAAkB,KAAK,MAAA,QAAA,uBAAA,KAAA,IAAA,qBAAI,EAAE,EAAG,GAAG,QAAQ,CAAC,CAAC,CAAC"}
|
package/dist/utils.cjs
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
//#region src/utils.ts
|
|
2
|
+
function escapeHtml(str) {
|
|
3
|
+
if (str === "") return "";
|
|
4
|
+
return str.replace(/[&<>"'`]/g, (ch) => {
|
|
5
|
+
switch (ch) {
|
|
6
|
+
case "&": return "&";
|
|
7
|
+
case "<": return "<";
|
|
8
|
+
case ">": return ">";
|
|
9
|
+
case "\"": return """;
|
|
10
|
+
case "'": return "'";
|
|
11
|
+
case "`": return "`";
|
|
12
|
+
default: return ch;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function escapeRegex(str) {
|
|
17
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
18
|
+
}
|
|
19
|
+
function toWebHeaders(httpHeaders) {
|
|
20
|
+
const headers = new Headers();
|
|
21
|
+
for (const [name, value] of Object.entries(httpHeaders)) if (Array.isArray(value)) for (const item of value) headers.append(name, item);
|
|
22
|
+
else headers.set(name, String(value !== null && value !== void 0 ? value : ""));
|
|
23
|
+
return headers;
|
|
24
|
+
}
|
|
25
|
+
const BLOGGER_PLUGIN_HEAD_COMMENT_REGEX = /(<!--blogger-plugin:head:begin-->)([\s\S]*?)(<!--blogger-plugin:head:end-->)/;
|
|
26
|
+
const BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX = /(<b:comment><!--blogger-plugin:head:begin--><\/b:comment>)([\s\S]*?)(<b:comment><!--blogger-plugin:head:end--><\/b:comment>)/;
|
|
27
|
+
function replaceBloggerPluginHeadComment(input, replacement, bcomment = false) {
|
|
28
|
+
if (bcomment) return input.replace(BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX, (_, start, _content, end) => `${start}${replacement}${end}`);
|
|
29
|
+
return input.replace(BLOGGER_PLUGIN_HEAD_COMMENT_REGEX, (_, start, _content, end) => `${start}${replacement}${end}`);
|
|
30
|
+
}
|
|
31
|
+
function getBloggerPluginHeadComment(input, bcomment = false) {
|
|
32
|
+
var _input$match$2, _input$match2;
|
|
33
|
+
if (bcomment) {
|
|
34
|
+
var _input$match$, _input$match;
|
|
35
|
+
return (_input$match$ = (_input$match = input.match(BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX)) === null || _input$match === void 0 ? void 0 : _input$match[2]) !== null && _input$match$ !== void 0 ? _input$match$ : null;
|
|
36
|
+
}
|
|
37
|
+
return (_input$match$2 = (_input$match2 = input.match(BLOGGER_PLUGIN_HEAD_COMMENT_REGEX)) === null || _input$match2 === void 0 ? void 0 : _input$match2[2]) !== null && _input$match$2 !== void 0 ? _input$match$2 : null;
|
|
38
|
+
}
|
|
39
|
+
function replaceHost(input, oldHost, newHost, newProtocol) {
|
|
40
|
+
return input.replace(new RegExp(`(https?:)?(\\/\\/|\\\\/\\\\/)${escapeRegex(oldHost)}`, "g"), (_, protocol, slash) => `${protocol ? newProtocol !== null && newProtocol !== void 0 ? newProtocol : protocol : ""}${slash !== null && slash !== void 0 ? slash : ""}${newHost}`);
|
|
41
|
+
}
|
|
42
|
+
function getRequestUrl(req) {
|
|
43
|
+
const xForwardedProtoHeader = req.headers["x-forwarded-proto"];
|
|
44
|
+
const xForwardedHostHeader = req.headers["x-forwarded-host"];
|
|
45
|
+
const hostHeader = req.headers.host;
|
|
46
|
+
const protocol = Array.isArray(xForwardedProtoHeader) ? xForwardedProtoHeader[0] : xForwardedProtoHeader !== null && xForwardedProtoHeader !== void 0 ? xForwardedProtoHeader : req.socket && "encrypted" in req.socket && req.socket.encrypted ? "https" : "http";
|
|
47
|
+
const host = Array.isArray(xForwardedHostHeader) ? xForwardedHostHeader[0] : xForwardedHostHeader !== null && xForwardedHostHeader !== void 0 ? xForwardedHostHeader : hostHeader;
|
|
48
|
+
if (host && req.originalUrl) return new URL(`${protocol}://${host}${req.originalUrl}`);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const TAILWIND_PLUGIN_NAMES = new Set(["@tailwindcss/vite:scan"]);
|
|
52
|
+
function isTailwindPlugin(plugin) {
|
|
53
|
+
return TAILWIND_PLUGIN_NAMES.has(plugin.name);
|
|
54
|
+
}
|
|
55
|
+
function errorHtml(reqUrl) {
|
|
56
|
+
return `<!DOCTYPE html>
|
|
57
|
+
<html>
|
|
58
|
+
|
|
59
|
+
<head>
|
|
60
|
+
<meta charset='UTF-8'/>
|
|
61
|
+
<meta content='width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=5, user-scalable=yes' name='viewport'/>
|
|
62
|
+
<title>500 Internal Server Error</title>
|
|
63
|
+
<link rel='icon' href='data:,' />
|
|
64
|
+
<style>
|
|
65
|
+
*, ::before, ::after {
|
|
66
|
+
box-sizing: border-box;
|
|
67
|
+
}
|
|
68
|
+
body {
|
|
69
|
+
min-height: 100svh;
|
|
70
|
+
display: flex;
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
align-items: center;
|
|
73
|
+
justify-content: center;
|
|
74
|
+
margin: 0;
|
|
75
|
+
padding: 20px;
|
|
76
|
+
background-color: #f5f5f5;
|
|
77
|
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", Segoe UI Symbol, "Noto Color Emoji";
|
|
78
|
+
}
|
|
79
|
+
.card {
|
|
80
|
+
padding: 24px;
|
|
81
|
+
background-color: #ffffff;
|
|
82
|
+
border: 1px solid #e5e5e5;
|
|
83
|
+
max-width: 448px;
|
|
84
|
+
border-radius: 14px;
|
|
85
|
+
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
|
|
86
|
+
display: flex;
|
|
87
|
+
flex-direction: column;
|
|
88
|
+
gap: 24px;
|
|
89
|
+
}
|
|
90
|
+
.card-content {
|
|
91
|
+
display: flex;
|
|
92
|
+
flex-direction: column;
|
|
93
|
+
gap: 6px;
|
|
94
|
+
}
|
|
95
|
+
.card-title {
|
|
96
|
+
font-weight: 600;
|
|
97
|
+
}
|
|
98
|
+
.card-description {
|
|
99
|
+
font-size: 14px;
|
|
100
|
+
opacity: 0.85;
|
|
101
|
+
}
|
|
102
|
+
.card-footer {
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
105
|
+
}
|
|
106
|
+
.button {
|
|
107
|
+
display: inline-flex;
|
|
108
|
+
white-space: nowrap;
|
|
109
|
+
align-items: center;
|
|
110
|
+
justify-content: center;
|
|
111
|
+
gap: 8px;
|
|
112
|
+
padding: 8px 16px;
|
|
113
|
+
font-weight: 500;
|
|
114
|
+
background-color: #171717;
|
|
115
|
+
outline: none;
|
|
116
|
+
border: none;
|
|
117
|
+
color: #ffffff;
|
|
118
|
+
border-radius: 8px;
|
|
119
|
+
min-height: 36px;
|
|
120
|
+
}
|
|
121
|
+
.button:hover {
|
|
122
|
+
opacity: 0.9;
|
|
123
|
+
}
|
|
124
|
+
.button svg {
|
|
125
|
+
wiheadersdth: 16px;
|
|
126
|
+
height: 16px;
|
|
127
|
+
flex-shrink: 0;
|
|
128
|
+
}
|
|
129
|
+
.card-footer .button {
|
|
130
|
+
flex-grow: 1;
|
|
131
|
+
}
|
|
132
|
+
</style>
|
|
133
|
+
</head>
|
|
134
|
+
|
|
135
|
+
<body>
|
|
136
|
+
<div class='card'>
|
|
137
|
+
<div class='card-content'>
|
|
138
|
+
<div class='card-title'>500 Internal Server Error</div>
|
|
139
|
+
<div class='card-description'>Failed to fetch: ${escapeHtml(reqUrl)}</div>
|
|
140
|
+
</div>
|
|
141
|
+
<div class='card-footer'>
|
|
142
|
+
<button class='button' type='button'>
|
|
143
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-refresh-ccw" aria-hidden="true"><path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path><path d="M3 3v5h5"></path><path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16"></path><path d="M16 16h5v5"></path></svg>
|
|
144
|
+
Reload
|
|
145
|
+
</button>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
<script>
|
|
149
|
+
const button = document.getElementsByTagName('button')[0];
|
|
150
|
+
button.addEventListener('click', () => {
|
|
151
|
+
window.location.reload();
|
|
152
|
+
});
|
|
153
|
+
<\/script>
|
|
154
|
+
</body>
|
|
155
|
+
|
|
156
|
+
</html>`;
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
exports.errorHtml = errorHtml;
|
|
160
|
+
exports.getBloggerPluginHeadComment = getBloggerPluginHeadComment;
|
|
161
|
+
exports.getRequestUrl = getRequestUrl;
|
|
162
|
+
exports.isTailwindPlugin = isTailwindPlugin;
|
|
163
|
+
exports.replaceBloggerPluginHeadComment = replaceBloggerPluginHeadComment;
|
|
164
|
+
exports.replaceHost = replaceHost;
|
|
165
|
+
exports.toWebHeaders = toWebHeaders;
|
|
166
|
+
|
|
167
|
+
//# sourceMappingURL=utils.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.cjs","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import type { IncomingHttpHeaders, OutgoingHttpHeaders } from 'node:http';\nimport type { Connect } from 'vite';\n\nexport function escapeHtml(str: string) {\n if (str === '') return '';\n return str.replace(/[&<>\"'`]/g, (ch) => {\n switch (ch) {\n case '&':\n return '&';\n case '<':\n return '<';\n case '>':\n return '>';\n case '\"':\n return '"';\n case \"'\":\n return ''';\n case '`':\n return '`';\n default:\n return ch;\n }\n });\n}\n\nexport function escapeRegex(str: string) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function toWebHeaders(httpHeaders: IncomingHttpHeaders | OutgoingHttpHeaders): Headers {\n const headers = new Headers();\n for (const [name, value] of Object.entries(httpHeaders)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n headers.append(name, item);\n }\n } else {\n headers.set(name, String(value ?? ''));\n }\n }\n return headers;\n}\n\nexport const BLOGGER_PLUGIN_HEAD_COMMENT_REGEX = /(<!--blogger-plugin:head:begin-->)([\\s\\S]*?)(<!--blogger-plugin:head:end-->)/;\n\nexport const BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX =\n /(<b:comment><!--blogger-plugin:head:begin--><\\/b:comment>)([\\s\\S]*?)(<b:comment><!--blogger-plugin:head:end--><\\/b:comment>)/;\n\nexport function replaceBloggerPluginHeadComment(input: string, replacement: string, bcomment = false) {\n if (bcomment) {\n return input.replace(BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX, (_, start: string, _content: string, end: string) => `${start}${replacement}${end}`);\n }\n return input.replace(BLOGGER_PLUGIN_HEAD_COMMENT_REGEX, (_, start: string, _content: string, end: string) => `${start}${replacement}${end}`);\n}\n\nexport function getBloggerPluginHeadComment(input: string, bcomment = false) {\n if (bcomment) {\n return input.match(BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX)?.[2] ?? null;\n }\n return input.match(BLOGGER_PLUGIN_HEAD_COMMENT_REGEX)?.[2] ?? null;\n}\n\nexport function replaceHost(input: string, oldHost: string, newHost: string, newProtocol?: string) {\n return input.replace(\n new RegExp(`(https?:)?(\\\\/\\\\/|\\\\\\\\/\\\\\\\\/)${escapeRegex(oldHost)}`, 'g'),\n (_, protocol, slash) => `${protocol ? (newProtocol ?? protocol) : ''}${slash ?? ''}${newHost}`,\n );\n}\n\nexport function getRequestUrl(req: Connect.IncomingMessage): URL | null {\n const xForwardedProtoHeader = req.headers['x-forwarded-proto'];\n const xForwardedHostHeader = req.headers['x-forwarded-host'];\n const hostHeader = req.headers.host;\n\n const protocol = Array.isArray(xForwardedProtoHeader)\n ? xForwardedProtoHeader[0]\n : (xForwardedProtoHeader ?? (req.socket && 'encrypted' in req.socket && req.socket.encrypted ? 'https' : 'http'));\n const host = Array.isArray(xForwardedHostHeader) ? xForwardedHostHeader[0] : (xForwardedHostHeader ?? hostHeader);\n\n if (host && req.originalUrl) {\n return new URL(`${protocol}://${host}${req.originalUrl}`);\n }\n\n return null;\n}\n\nexport function isBloggerPath(path: string) {\n return (\n path === '/' ||\n path === '/search' ||\n /^\\/search\\/label(\\/[^/]+)?\\/?$/.test(path) ||\n /^p\\/.+\\.html$/.test(path) ||\n /^\\/\\d{4}\\/\\d{2}(\\/?|\\/[^/\\s]+\\.html)$/.test(path)\n );\n}\n\nconst TAILWIND_PLUGIN_NAMES = new Set(['@tailwindcss/vite:scan']);\n\nexport function isTailwindPlugin(plugin: { name: string }): boolean {\n return TAILWIND_PLUGIN_NAMES.has(plugin.name);\n}\n\nexport function errorHtml(reqUrl: string) {\n return `<!DOCTYPE html>\n<html>\n\n<head>\n <meta charset='UTF-8'/>\n <meta content='width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=5, user-scalable=yes' name='viewport'/>\n <title>500 Internal Server Error</title>\n <link rel='icon' href='data:,' />\n <style>\n *, ::before, ::after {\n box-sizing: border-box;\n }\n body {\n min-height: 100svh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n margin: 0;\n padding: 20px;\n background-color: #f5f5f5;\n font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", Segoe UI Symbol, \"Noto Color Emoji\";\n }\n .card {\n padding: 24px;\n background-color: #ffffff;\n border: 1px solid #e5e5e5;\n max-width: 448px;\n border-radius: 14px;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);\n display: flex;\n flex-direction: column;\n gap: 24px;\n }\n .card-content {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .card-title {\n font-weight: 600;\n }\n .card-description {\n font-size: 14px;\n opacity: 0.85;\n }\n .card-footer {\n display: flex;\n align-items: center;\n }\n .button {\n display: inline-flex;\n white-space: nowrap;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 8px 16px;\n font-weight: 500;\n background-color: #171717;\n outline: none;\n border: none;\n color: #ffffff;\n border-radius: 8px;\n min-height: 36px;\n }\n .button:hover {\n opacity: 0.9;\n }\n .button svg {\n wiheadersdth: 16px;\n height: 16px;\n flex-shrink: 0;\n }\n .card-footer .button {\n flex-grow: 1;\n }\n </style>\n</head>\n\n<body>\n <div class='card'>\n <div class='card-content'>\n <div class='card-title'>500 Internal Server Error</div>\n <div class='card-description'>Failed to fetch: ${escapeHtml(reqUrl)}</div>\n </div>\n <div class='card-footer'>\n <button class='button' type='button'>\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-refresh-ccw\" aria-hidden=\"true\"><path d=\"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\"></path><path d=\"M3 3v5h5\"></path><path d=\"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16\"></path><path d=\"M16 16h5v5\"></path></svg>\n Reload\n </button>\n </div>\n </div>\n <script>\n const button = document.getElementsByTagName('button')[0];\n button.addEventListener('click', () => {\n window.location.reload();\n });\n </script>\n</body>\n\n</html>`;\n}\n"],"mappings":";AAGA,SAAgB,WAAW,KAAa;AACtC,KAAI,QAAQ,GAAI,QAAO;AACvB,QAAO,IAAI,QAAQ,cAAc,OAAO;AACtC,UAAQ,IAAR;GACE,KAAK,IACH,QAAO;GACT,KAAK,IACH,QAAO;GACT,KAAK,IACH,QAAO;GACT,KAAK,KACH,QAAO;GACT,KAAK,IACH,QAAO;GACT,KAAK,IACH,QAAO;GACT,QACE,QAAO;;GAEX;;AAGJ,SAAgB,YAAY,KAAa;AACvC,QAAO,IAAI,QAAQ,uBAAuB,OAAO;;AAGnD,SAAgB,aAAa,aAAiE;CAC5F,MAAM,UAAU,IAAI,SAAS;AAC7B,MAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,YAAY,CACrD,KAAI,MAAM,QAAQ,MAAM,CACtB,MAAK,MAAM,QAAQ,MACjB,SAAQ,OAAO,MAAM,KAAK;KAG5B,SAAQ,IAAI,MAAM,OAAO,UAAA,QAAA,UAAA,KAAA,IAAA,QAAS,GAAG,CAAC;AAG1C,QAAO;;AAGT,MAAa,oCAAoC;AAEjD,MAAa,qCACX;AAEF,SAAgB,gCAAgC,OAAe,aAAqB,WAAW,OAAO;AACpG,KAAI,SACF,QAAO,MAAM,QAAQ,qCAAqC,GAAG,OAAe,UAAkB,QAAgB,GAAG,QAAQ,cAAc,MAAM;AAE/I,QAAO,MAAM,QAAQ,oCAAoC,GAAG,OAAe,UAAkB,QAAgB,GAAG,QAAQ,cAAc,MAAM;;AAG9I,SAAgB,4BAA4B,OAAe,WAAW,OAAO;;AAC3E,KAAI,UAAU;;AACZ,UAAA,iBAAA,eAAO,MAAM,MAAM,mCAAmC,MAAA,QAAA,iBAAA,KAAA,IAAA,KAAA,IAAA,aAAG,QAAA,QAAA,kBAAA,KAAA,IAAA,gBAAM;;AAEjE,SAAA,kBAAA,gBAAO,MAAM,MAAM,kCAAkC,MAAA,QAAA,kBAAA,KAAA,IAAA,KAAA,IAAA,cAAG,QAAA,QAAA,mBAAA,KAAA,IAAA,iBAAM;;AAGhE,SAAgB,YAAY,OAAe,SAAiB,SAAiB,aAAsB;AACjG,QAAO,MAAM,QACX,IAAI,OAAO,gCAAgC,YAAY,QAAQ,IAAI,IAAI,GACtE,GAAG,UAAU,UAAU,GAAG,WAAY,gBAAA,QAAA,gBAAA,KAAA,IAAA,cAAe,WAAY,KAAK,UAAA,QAAA,UAAA,KAAA,IAAA,QAAS,KAAK,UACtF;;AAGH,SAAgB,cAAc,KAA0C;CACtE,MAAM,wBAAwB,IAAI,QAAQ;CAC1C,MAAM,uBAAuB,IAAI,QAAQ;CACzC,MAAM,aAAa,IAAI,QAAQ;CAE/B,MAAM,WAAW,MAAM,QAAQ,sBAAsB,GACjD,sBAAsB,KACrB,0BAAA,QAAA,0BAAA,KAAA,IAAA,wBAA0B,IAAI,UAAU,eAAe,IAAI,UAAU,IAAI,OAAO,YAAY,UAAU;CAC3G,MAAM,OAAO,MAAM,QAAQ,qBAAqB,GAAG,qBAAqB,KAAM,yBAAA,QAAA,yBAAA,KAAA,IAAA,uBAAwB;AAEtG,KAAI,QAAQ,IAAI,YACd,QAAO,IAAI,IAAI,GAAG,SAAS,KAAK,OAAO,IAAI,cAAc;AAG3D,QAAO;;AAaT,MAAM,wBAAwB,IAAI,IAAI,CAAC,yBAAyB,CAAC;AAEjE,SAAgB,iBAAiB,QAAmC;AAClE,QAAO,sBAAsB,IAAI,OAAO,KAAK;;AAG/C,SAAgB,UAAU,QAAgB;AACxC,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uDAmF8C,WAAW,OAAO,CAAC"}
|
package/dist/utils.mjs
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
//#region src/utils.ts
|
|
2
|
+
function escapeHtml(str) {
|
|
3
|
+
if (str === "") return "";
|
|
4
|
+
return str.replace(/[&<>"'`]/g, (ch) => {
|
|
5
|
+
switch (ch) {
|
|
6
|
+
case "&": return "&";
|
|
7
|
+
case "<": return "<";
|
|
8
|
+
case ">": return ">";
|
|
9
|
+
case "\"": return """;
|
|
10
|
+
case "'": return "'";
|
|
11
|
+
case "`": return "`";
|
|
12
|
+
default: return ch;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function escapeRegex(str) {
|
|
17
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
18
|
+
}
|
|
19
|
+
function toWebHeaders(httpHeaders) {
|
|
20
|
+
const headers = new Headers();
|
|
21
|
+
for (const [name, value] of Object.entries(httpHeaders)) if (Array.isArray(value)) for (const item of value) headers.append(name, item);
|
|
22
|
+
else headers.set(name, String(value !== null && value !== void 0 ? value : ""));
|
|
23
|
+
return headers;
|
|
24
|
+
}
|
|
25
|
+
const BLOGGER_PLUGIN_HEAD_COMMENT_REGEX = /(<!--blogger-plugin:head:begin-->)([\s\S]*?)(<!--blogger-plugin:head:end-->)/;
|
|
26
|
+
const BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX = /(<b:comment><!--blogger-plugin:head:begin--><\/b:comment>)([\s\S]*?)(<b:comment><!--blogger-plugin:head:end--><\/b:comment>)/;
|
|
27
|
+
function replaceBloggerPluginHeadComment(input, replacement, bcomment = false) {
|
|
28
|
+
if (bcomment) return input.replace(BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX, (_, start, _content, end) => `${start}${replacement}${end}`);
|
|
29
|
+
return input.replace(BLOGGER_PLUGIN_HEAD_COMMENT_REGEX, (_, start, _content, end) => `${start}${replacement}${end}`);
|
|
30
|
+
}
|
|
31
|
+
function getBloggerPluginHeadComment(input, bcomment = false) {
|
|
32
|
+
var _input$match$2, _input$match2;
|
|
33
|
+
if (bcomment) {
|
|
34
|
+
var _input$match$, _input$match;
|
|
35
|
+
return (_input$match$ = (_input$match = input.match(BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX)) === null || _input$match === void 0 ? void 0 : _input$match[2]) !== null && _input$match$ !== void 0 ? _input$match$ : null;
|
|
36
|
+
}
|
|
37
|
+
return (_input$match$2 = (_input$match2 = input.match(BLOGGER_PLUGIN_HEAD_COMMENT_REGEX)) === null || _input$match2 === void 0 ? void 0 : _input$match2[2]) !== null && _input$match$2 !== void 0 ? _input$match$2 : null;
|
|
38
|
+
}
|
|
39
|
+
function replaceHost(input, oldHost, newHost, newProtocol) {
|
|
40
|
+
return input.replace(new RegExp(`(https?:)?(\\/\\/|\\\\/\\\\/)${escapeRegex(oldHost)}`, "g"), (_, protocol, slash) => `${protocol ? newProtocol !== null && newProtocol !== void 0 ? newProtocol : protocol : ""}${slash !== null && slash !== void 0 ? slash : ""}${newHost}`);
|
|
41
|
+
}
|
|
42
|
+
function getRequestUrl(req) {
|
|
43
|
+
const xForwardedProtoHeader = req.headers["x-forwarded-proto"];
|
|
44
|
+
const xForwardedHostHeader = req.headers["x-forwarded-host"];
|
|
45
|
+
const hostHeader = req.headers.host;
|
|
46
|
+
const protocol = Array.isArray(xForwardedProtoHeader) ? xForwardedProtoHeader[0] : xForwardedProtoHeader !== null && xForwardedProtoHeader !== void 0 ? xForwardedProtoHeader : req.socket && "encrypted" in req.socket && req.socket.encrypted ? "https" : "http";
|
|
47
|
+
const host = Array.isArray(xForwardedHostHeader) ? xForwardedHostHeader[0] : xForwardedHostHeader !== null && xForwardedHostHeader !== void 0 ? xForwardedHostHeader : hostHeader;
|
|
48
|
+
if (host && req.originalUrl) return new URL(`${protocol}://${host}${req.originalUrl}`);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const TAILWIND_PLUGIN_NAMES = new Set(["@tailwindcss/vite:scan"]);
|
|
52
|
+
function isTailwindPlugin(plugin) {
|
|
53
|
+
return TAILWIND_PLUGIN_NAMES.has(plugin.name);
|
|
54
|
+
}
|
|
55
|
+
function errorHtml(reqUrl) {
|
|
56
|
+
return `<!DOCTYPE html>
|
|
57
|
+
<html>
|
|
58
|
+
|
|
59
|
+
<head>
|
|
60
|
+
<meta charset='UTF-8'/>
|
|
61
|
+
<meta content='width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=5, user-scalable=yes' name='viewport'/>
|
|
62
|
+
<title>500 Internal Server Error</title>
|
|
63
|
+
<link rel='icon' href='data:,' />
|
|
64
|
+
<style>
|
|
65
|
+
*, ::before, ::after {
|
|
66
|
+
box-sizing: border-box;
|
|
67
|
+
}
|
|
68
|
+
body {
|
|
69
|
+
min-height: 100svh;
|
|
70
|
+
display: flex;
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
align-items: center;
|
|
73
|
+
justify-content: center;
|
|
74
|
+
margin: 0;
|
|
75
|
+
padding: 20px;
|
|
76
|
+
background-color: #f5f5f5;
|
|
77
|
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", Segoe UI Symbol, "Noto Color Emoji";
|
|
78
|
+
}
|
|
79
|
+
.card {
|
|
80
|
+
padding: 24px;
|
|
81
|
+
background-color: #ffffff;
|
|
82
|
+
border: 1px solid #e5e5e5;
|
|
83
|
+
max-width: 448px;
|
|
84
|
+
border-radius: 14px;
|
|
85
|
+
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
|
|
86
|
+
display: flex;
|
|
87
|
+
flex-direction: column;
|
|
88
|
+
gap: 24px;
|
|
89
|
+
}
|
|
90
|
+
.card-content {
|
|
91
|
+
display: flex;
|
|
92
|
+
flex-direction: column;
|
|
93
|
+
gap: 6px;
|
|
94
|
+
}
|
|
95
|
+
.card-title {
|
|
96
|
+
font-weight: 600;
|
|
97
|
+
}
|
|
98
|
+
.card-description {
|
|
99
|
+
font-size: 14px;
|
|
100
|
+
opacity: 0.85;
|
|
101
|
+
}
|
|
102
|
+
.card-footer {
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
105
|
+
}
|
|
106
|
+
.button {
|
|
107
|
+
display: inline-flex;
|
|
108
|
+
white-space: nowrap;
|
|
109
|
+
align-items: center;
|
|
110
|
+
justify-content: center;
|
|
111
|
+
gap: 8px;
|
|
112
|
+
padding: 8px 16px;
|
|
113
|
+
font-weight: 500;
|
|
114
|
+
background-color: #171717;
|
|
115
|
+
outline: none;
|
|
116
|
+
border: none;
|
|
117
|
+
color: #ffffff;
|
|
118
|
+
border-radius: 8px;
|
|
119
|
+
min-height: 36px;
|
|
120
|
+
}
|
|
121
|
+
.button:hover {
|
|
122
|
+
opacity: 0.9;
|
|
123
|
+
}
|
|
124
|
+
.button svg {
|
|
125
|
+
wiheadersdth: 16px;
|
|
126
|
+
height: 16px;
|
|
127
|
+
flex-shrink: 0;
|
|
128
|
+
}
|
|
129
|
+
.card-footer .button {
|
|
130
|
+
flex-grow: 1;
|
|
131
|
+
}
|
|
132
|
+
</style>
|
|
133
|
+
</head>
|
|
134
|
+
|
|
135
|
+
<body>
|
|
136
|
+
<div class='card'>
|
|
137
|
+
<div class='card-content'>
|
|
138
|
+
<div class='card-title'>500 Internal Server Error</div>
|
|
139
|
+
<div class='card-description'>Failed to fetch: ${escapeHtml(reqUrl)}</div>
|
|
140
|
+
</div>
|
|
141
|
+
<div class='card-footer'>
|
|
142
|
+
<button class='button' type='button'>
|
|
143
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-refresh-ccw" aria-hidden="true"><path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path><path d="M3 3v5h5"></path><path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16"></path><path d="M16 16h5v5"></path></svg>
|
|
144
|
+
Reload
|
|
145
|
+
</button>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
<script>
|
|
149
|
+
const button = document.getElementsByTagName('button')[0];
|
|
150
|
+
button.addEventListener('click', () => {
|
|
151
|
+
window.location.reload();
|
|
152
|
+
});
|
|
153
|
+
<\/script>
|
|
154
|
+
</body>
|
|
155
|
+
|
|
156
|
+
</html>`;
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
export { errorHtml, getBloggerPluginHeadComment, getRequestUrl, isTailwindPlugin, replaceBloggerPluginHeadComment, replaceHost, toWebHeaders };
|
|
160
|
+
|
|
161
|
+
//# sourceMappingURL=utils.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.mjs","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import type { IncomingHttpHeaders, OutgoingHttpHeaders } from 'node:http';\nimport type { Connect } from 'vite';\n\nexport function escapeHtml(str: string) {\n if (str === '') return '';\n return str.replace(/[&<>\"'`]/g, (ch) => {\n switch (ch) {\n case '&':\n return '&';\n case '<':\n return '<';\n case '>':\n return '>';\n case '\"':\n return '"';\n case \"'\":\n return ''';\n case '`':\n return '`';\n default:\n return ch;\n }\n });\n}\n\nexport function escapeRegex(str: string) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function toWebHeaders(httpHeaders: IncomingHttpHeaders | OutgoingHttpHeaders): Headers {\n const headers = new Headers();\n for (const [name, value] of Object.entries(httpHeaders)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n headers.append(name, item);\n }\n } else {\n headers.set(name, String(value ?? ''));\n }\n }\n return headers;\n}\n\nexport const BLOGGER_PLUGIN_HEAD_COMMENT_REGEX = /(<!--blogger-plugin:head:begin-->)([\\s\\S]*?)(<!--blogger-plugin:head:end-->)/;\n\nexport const BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX =\n /(<b:comment><!--blogger-plugin:head:begin--><\\/b:comment>)([\\s\\S]*?)(<b:comment><!--blogger-plugin:head:end--><\\/b:comment>)/;\n\nexport function replaceBloggerPluginHeadComment(input: string, replacement: string, bcomment = false) {\n if (bcomment) {\n return input.replace(BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX, (_, start: string, _content: string, end: string) => `${start}${replacement}${end}`);\n }\n return input.replace(BLOGGER_PLUGIN_HEAD_COMMENT_REGEX, (_, start: string, _content: string, end: string) => `${start}${replacement}${end}`);\n}\n\nexport function getBloggerPluginHeadComment(input: string, bcomment = false) {\n if (bcomment) {\n return input.match(BLOGGER_PLUGIN_HEAD_BCOMMENT_REGEX)?.[2] ?? null;\n }\n return input.match(BLOGGER_PLUGIN_HEAD_COMMENT_REGEX)?.[2] ?? null;\n}\n\nexport function replaceHost(input: string, oldHost: string, newHost: string, newProtocol?: string) {\n return input.replace(\n new RegExp(`(https?:)?(\\\\/\\\\/|\\\\\\\\/\\\\\\\\/)${escapeRegex(oldHost)}`, 'g'),\n (_, protocol, slash) => `${protocol ? (newProtocol ?? protocol) : ''}${slash ?? ''}${newHost}`,\n );\n}\n\nexport function getRequestUrl(req: Connect.IncomingMessage): URL | null {\n const xForwardedProtoHeader = req.headers['x-forwarded-proto'];\n const xForwardedHostHeader = req.headers['x-forwarded-host'];\n const hostHeader = req.headers.host;\n\n const protocol = Array.isArray(xForwardedProtoHeader)\n ? xForwardedProtoHeader[0]\n : (xForwardedProtoHeader ?? (req.socket && 'encrypted' in req.socket && req.socket.encrypted ? 'https' : 'http'));\n const host = Array.isArray(xForwardedHostHeader) ? xForwardedHostHeader[0] : (xForwardedHostHeader ?? hostHeader);\n\n if (host && req.originalUrl) {\n return new URL(`${protocol}://${host}${req.originalUrl}`);\n }\n\n return null;\n}\n\nexport function isBloggerPath(path: string) {\n return (\n path === '/' ||\n path === '/search' ||\n /^\\/search\\/label(\\/[^/]+)?\\/?$/.test(path) ||\n /^p\\/.+\\.html$/.test(path) ||\n /^\\/\\d{4}\\/\\d{2}(\\/?|\\/[^/\\s]+\\.html)$/.test(path)\n );\n}\n\nconst TAILWIND_PLUGIN_NAMES = new Set(['@tailwindcss/vite:scan']);\n\nexport function isTailwindPlugin(plugin: { name: string }): boolean {\n return TAILWIND_PLUGIN_NAMES.has(plugin.name);\n}\n\nexport function errorHtml(reqUrl: string) {\n return `<!DOCTYPE html>\n<html>\n\n<head>\n <meta charset='UTF-8'/>\n <meta content='width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=5, user-scalable=yes' name='viewport'/>\n <title>500 Internal Server Error</title>\n <link rel='icon' href='data:,' />\n <style>\n *, ::before, ::after {\n box-sizing: border-box;\n }\n body {\n min-height: 100svh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n margin: 0;\n padding: 20px;\n background-color: #f5f5f5;\n font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", Segoe UI Symbol, \"Noto Color Emoji\";\n }\n .card {\n padding: 24px;\n background-color: #ffffff;\n border: 1px solid #e5e5e5;\n max-width: 448px;\n border-radius: 14px;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);\n display: flex;\n flex-direction: column;\n gap: 24px;\n }\n .card-content {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .card-title {\n font-weight: 600;\n }\n .card-description {\n font-size: 14px;\n opacity: 0.85;\n }\n .card-footer {\n display: flex;\n align-items: center;\n }\n .button {\n display: inline-flex;\n white-space: nowrap;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 8px 16px;\n font-weight: 500;\n background-color: #171717;\n outline: none;\n border: none;\n color: #ffffff;\n border-radius: 8px;\n min-height: 36px;\n }\n .button:hover {\n opacity: 0.9;\n }\n .button svg {\n wiheadersdth: 16px;\n height: 16px;\n flex-shrink: 0;\n }\n .card-footer .button {\n flex-grow: 1;\n }\n </style>\n</head>\n\n<body>\n <div class='card'>\n <div class='card-content'>\n <div class='card-title'>500 Internal Server Error</div>\n <div class='card-description'>Failed to fetch: ${escapeHtml(reqUrl)}</div>\n </div>\n <div class='card-footer'>\n <button class='button' type='button'>\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-refresh-ccw\" aria-hidden=\"true\"><path d=\"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\"></path><path d=\"M3 3v5h5\"></path><path d=\"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16\"></path><path d=\"M16 16h5v5\"></path></svg>\n Reload\n </button>\n </div>\n </div>\n <script>\n const button = document.getElementsByTagName('button')[0];\n button.addEventListener('click', () => {\n window.location.reload();\n });\n </script>\n</body>\n\n</html>`;\n}\n"],"mappings":";AAGA,SAAgB,WAAW,KAAa;AACtC,KAAI,QAAQ,GAAI,QAAO;AACvB,QAAO,IAAI,QAAQ,cAAc,OAAO;AACtC,UAAQ,IAAR;GACE,KAAK,IACH,QAAO;GACT,KAAK,IACH,QAAO;GACT,KAAK,IACH,QAAO;GACT,KAAK,KACH,QAAO;GACT,KAAK,IACH,QAAO;GACT,KAAK,IACH,QAAO;GACT,QACE,QAAO;;GAEX;;AAGJ,SAAgB,YAAY,KAAa;AACvC,QAAO,IAAI,QAAQ,uBAAuB,OAAO;;AAGnD,SAAgB,aAAa,aAAiE;CAC5F,MAAM,UAAU,IAAI,SAAS;AAC7B,MAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,YAAY,CACrD,KAAI,MAAM,QAAQ,MAAM,CACtB,MAAK,MAAM,QAAQ,MACjB,SAAQ,OAAO,MAAM,KAAK;KAG5B,SAAQ,IAAI,MAAM,OAAO,UAAA,QAAA,UAAA,KAAA,IAAA,QAAS,GAAG,CAAC;AAG1C,QAAO;;AAGT,MAAa,oCAAoC;AAEjD,MAAa,qCACX;AAEF,SAAgB,gCAAgC,OAAe,aAAqB,WAAW,OAAO;AACpG,KAAI,SACF,QAAO,MAAM,QAAQ,qCAAqC,GAAG,OAAe,UAAkB,QAAgB,GAAG,QAAQ,cAAc,MAAM;AAE/I,QAAO,MAAM,QAAQ,oCAAoC,GAAG,OAAe,UAAkB,QAAgB,GAAG,QAAQ,cAAc,MAAM;;AAG9I,SAAgB,4BAA4B,OAAe,WAAW,OAAO;;AAC3E,KAAI,UAAU;;AACZ,UAAA,iBAAA,eAAO,MAAM,MAAM,mCAAmC,MAAA,QAAA,iBAAA,KAAA,IAAA,KAAA,IAAA,aAAG,QAAA,QAAA,kBAAA,KAAA,IAAA,gBAAM;;AAEjE,SAAA,kBAAA,gBAAO,MAAM,MAAM,kCAAkC,MAAA,QAAA,kBAAA,KAAA,IAAA,KAAA,IAAA,cAAG,QAAA,QAAA,mBAAA,KAAA,IAAA,iBAAM;;AAGhE,SAAgB,YAAY,OAAe,SAAiB,SAAiB,aAAsB;AACjG,QAAO,MAAM,QACX,IAAI,OAAO,gCAAgC,YAAY,QAAQ,IAAI,IAAI,GACtE,GAAG,UAAU,UAAU,GAAG,WAAY,gBAAA,QAAA,gBAAA,KAAA,IAAA,cAAe,WAAY,KAAK,UAAA,QAAA,UAAA,KAAA,IAAA,QAAS,KAAK,UACtF;;AAGH,SAAgB,cAAc,KAA0C;CACtE,MAAM,wBAAwB,IAAI,QAAQ;CAC1C,MAAM,uBAAuB,IAAI,QAAQ;CACzC,MAAM,aAAa,IAAI,QAAQ;CAE/B,MAAM,WAAW,MAAM,QAAQ,sBAAsB,GACjD,sBAAsB,KACrB,0BAAA,QAAA,0BAAA,KAAA,IAAA,wBAA0B,IAAI,UAAU,eAAe,IAAI,UAAU,IAAI,OAAO,YAAY,UAAU;CAC3G,MAAM,OAAO,MAAM,QAAQ,qBAAqB,GAAG,qBAAqB,KAAM,yBAAA,QAAA,yBAAA,KAAA,IAAA,uBAAwB;AAEtG,KAAI,QAAQ,IAAI,YACd,QAAO,IAAI,IAAI,GAAG,SAAS,KAAK,OAAO,IAAI,cAAc;AAG3D,QAAO;;AAaT,MAAM,wBAAwB,IAAI,IAAI,CAAC,yBAAyB,CAAC;AAEjE,SAAgB,iBAAiB,QAAmC;AAClE,QAAO,sBAAsB,IAAI,OAAO,KAAK;;AAG/C,SAAgB,UAAU,QAAgB;AACxC,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uDAmF8C,WAAW,OAAO,CAAC"}
|