vite-plugin-unit 0.0.5 → 2.0.0

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 CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  A vite plugin to enable you build websites in units using alpine.js
6
6
 
7
+ Check out the [create-unit](https://github.com/henryhale/create-unit) library for details.
8
+
7
9
  ## installation
8
10
 
9
11
  ```sh
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * vite-plugin-unit
3
- * @description A vite plugin to enable you build websites in units using alpine.js
3
+ * @description A vite plugin to enable you build websites in units.
4
4
  * @author Henry Hale
5
5
  * @license MIT
6
6
  * @url https://github.com/henryhale/vite-plugin-unit
package/dist/index.js CHANGED
@@ -1,18 +1,18 @@
1
1
  /**
2
2
  * vite-plugin-unit
3
- * @description A vite plugin to enable you build websites in units using alpine.js
3
+ * @description A vite plugin to enable you build websites in units.
4
4
  * @author Henry Hale
5
5
  * @license MIT
6
6
  * @url https://github.com/henryhale/vite-plugin-unit
7
7
  */
8
+ import { log } from "node:console";
8
9
  import { existsSync, readFileSync } from "node:fs";
10
+ import { cp, mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
9
11
  import { dirname, extname, join, resolve } from "node:path";
10
- import { cp, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
11
- import { log } from "node:console";
12
12
  const defaultOptions = {
13
13
  pages: "pages/",
14
14
  template: "template.html",
15
- slot: "#slot#"
15
+ slot: "<slot></slot>"
16
16
  };
17
17
  export default function plugin(options = {}) {
18
18
  const opt = Object.assign({}, defaultOptions, options);
@@ -23,9 +23,17 @@ export default function plugin(options = {}) {
23
23
  // source code folder
24
24
  const srcDir = "src/";
25
25
  // intermediate output folder for unit.js
26
- const outputDir = "./.unit/";
27
- // regexp to match single html tag
26
+ const outputDir = ".unit/";
27
+ // regexp to match single html tag with attributes
28
28
  const htmlRegex = /<(.+?) ([/]?|.+?)>/g;
29
+ // import statements
30
+ const importRegex = /import (.+?) from "(.+?)"(.+?)/g;
31
+ // html tag regexp
32
+ const tagRegex = /<(.+?)>/;
33
+ // regexp to match attributes in html tag
34
+ const attrRegex = /(\w+(?:-\w+)*)\s*=\s*["']([^"']+)["']/g;
35
+ // regexp to match placeholders like {text}
36
+ const valueRegex = /{(\w*)}/g;
29
37
  // mapping file path to thier contents
30
38
  const pathToCode = new Map();
31
39
  // function that compiles .unit files
@@ -33,9 +41,19 @@ export default function plugin(options = {}) {
33
41
  let filePath = null;
34
42
  let content = null;
35
43
  const nameToPath = new Map();
44
+ // create a key-value object from attributes of an html tag
45
+ function mapAttributes(attr = "") {
46
+ const map = {};
47
+ let match = attrRegex.exec(attr);
48
+ while (match !== null) {
49
+ map[match[1]] = match[2];
50
+ match = attrRegex.exec(attr);
51
+ }
52
+ return map;
53
+ }
36
54
  // remove all import statements while saving the import names & content
37
55
  return (code
38
- .replace(/import (.+?) from "(.+?)"(.+?)/g, (_, importName, importPath) => {
56
+ .replace(importRegex, (_, importName, importPath) => {
39
57
  filePath = join(dirname(file), importPath);
40
58
  nameToPath.set(importName, filePath);
41
59
  if (!pathToCode.has(filePath)) {
@@ -45,12 +63,29 @@ export default function plugin(options = {}) {
45
63
  return "";
46
64
  })
47
65
  // replace every html tag matching an import name
48
- .replace(htmlRegex, (match, tag, attr = "") => {
66
+ .replace(htmlRegex, (match, tag, attr) => {
49
67
  const path = nameToPath.get(tag);
50
68
  if (path) {
69
+ // get rid of trailing forward slash
51
70
  if (attr.endsWith("/"))
52
71
  attr = attr.slice(0, -1);
53
- return pathToCode.get(path).replace(/<(.+?)>/, (m) => m.slice(0, -1) + " " + attr + ">");
72
+ const map = mapAttributes(attr);
73
+ return (pathToCode
74
+ .get(path)
75
+ ?.replace(valueRegex, (m, key) => {
76
+ const value = map[key];
77
+ if (value) {
78
+ delete map[key];
79
+ return value;
80
+ }
81
+ return m;
82
+ })
83
+ .replace(tagRegex, (m) => {
84
+ const others = Object.entries(map).reduce((r, [k, v]) => {
85
+ return `${r + k}=${/'/.test(v) ? `"${v}"` : `'${v}'`}`;
86
+ }, "");
87
+ return `${m.slice(0, -1)} ${others}>`;
88
+ }) ?? "");
54
89
  }
55
90
  return match;
56
91
  })
@@ -88,7 +123,9 @@ export default function plugin(options = {}) {
88
123
  async function respond(file) {
89
124
  res.statusCode = 200;
90
125
  res.setHeader("Content-Type", "text/html");
91
- const contents = await readFile(join(config.root, opt.template), { encoding: "utf-8" });
126
+ const contents = await readFile(join(config.root, opt.template), {
127
+ encoding: "utf-8"
128
+ });
92
129
  pathToCode.clear();
93
130
  const compiled = compile(file, await readFile(file, { encoding: "utf-8" }));
94
131
  res.end(contents.replace(opt.slot, compiled));
@@ -109,7 +146,7 @@ export default function plugin(options = {}) {
109
146
  }
110
147
  // try checking if the requested asset exists in the `src` folder
111
148
  if (filePath.lastIndexOf(".") > -1) {
112
- filePath = join(config.root, req.url);
149
+ filePath = join(config.root, req.url || "");
113
150
  if (existsSync(filePath)) {
114
151
  // direct the file path relative to the `src` folder
115
152
  req.url = filePath;
@@ -157,7 +194,9 @@ export default function plugin(options = {}) {
157
194
  * Grab the template file
158
195
  */
159
196
  const templateFile = join(outputDir, opt.template);
160
- const template = await readFile(templateFile, { encoding: "utf-8" });
197
+ const template = await readFile(templateFile, {
198
+ encoding: "utf-8"
199
+ });
161
200
  /**
162
201
  * Capture the pages
163
202
  */
@@ -176,11 +215,18 @@ export default function plugin(options = {}) {
176
215
  else {
177
216
  // ...
178
217
  }
179
- const fileContent = await readFile(filePath, { encoding: "utf-8" });
218
+ const fileContent = await readFile(filePath, {
219
+ encoding: "utf-8"
220
+ });
180
221
  const compiledPage = compile(filePath, fileContent);
181
222
  const result = template.replace(opt.slot, compiledPage);
182
223
  log("build: ", page);
183
- return await writeFile(join(outputDir, page.replace(ext, ".html")), result);
224
+ const fullPath = join(outputDir, page.replace(ext, ".html"));
225
+ const dirPath = dirname(fullPath);
226
+ if (!existsSync(dirPath)) {
227
+ await mkdir(dirPath, { recursive: true });
228
+ }
229
+ return await writeFile(fullPath, result);
184
230
  }
185
231
  /**
186
232
  * Clear the input files
@@ -210,7 +256,7 @@ export default function plugin(options = {}) {
210
256
  /**
211
257
  * Copy the entire unit dist folder to the root of the project
212
258
  */
213
- await cp(outputDir + "dist", distFolder, { recursive: true });
259
+ await cp(`${outputDir}dist`, distFolder, { recursive: true });
214
260
  // await new Promise((res) => setTimeout(res, 5000));
215
261
  /**
216
262
  * Delete the entire unit output folder
package/package.json CHANGED
@@ -1,72 +1,60 @@
1
1
  {
2
- "name": "vite-plugin-unit",
3
- "version": "0.0.5",
4
- "description": "A vite plugin to enable you build websites in units using alpine.js",
5
- "main": "./dist/index.js",
6
- "module": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "files": [
9
- "./dist/",
10
- "./LICENSE.md",
11
- "./README.md",
12
- "./package.json"
13
- ],
14
- "repository": {
15
- "type": "git",
16
- "url": "git+https://github.com/henryhale/vite-plugin-unit.git"
17
- },
18
- "keywords": [
19
- "vite",
20
- "alpine",
21
- "ui",
22
- "browser"
23
- ],
24
- "author": {
25
- "name": "Henry Hale",
26
- "url": "https://github.com/henryhale"
27
- },
28
- "license": "MIT",
29
- "bugs": {
30
- "url": "https://github.com/henryhale/vite-plugin-unit/issues"
31
- },
32
- "homepage": "https://github.com/henryhale/vite-plugin-unit#readme",
33
- "type": "module",
34
- "scripts": {
35
- "build": "tsc -b",
36
- "dev": "tsc -w",
37
- "lint": "eslint --cache --ext .ts source/ && prettier -c source/",
38
- "lint:fix": "eslint --cache --ext .ts source/ --fix && prettier -c -w source/",
39
- "prepack": "pnpm build",
40
- "prepare": "husky install",
41
- "release": "release-it",
42
- "test": "echo \"Error: no test specified\""
43
- },
44
- "engines": {
45
- "node": ">=18",
46
- "pnpm": ">=8"
47
- },
48
- "lint-staged": {
49
- "*.ts": "pnpm lint:fix"
50
- },
51
- "prettier": {
52
- "printWidth": 120,
53
- "tabWidth": 4,
54
- "semi": true,
55
- "singleQuote": false,
56
- "trailingComma": "none"
57
- },
58
- "devDependencies": {
59
- "@release-it/conventional-changelog": "^8.0.1",
60
- "@types/node": "^20.10.6",
61
- "@typescript-eslint/eslint-plugin": "^6.16.0",
62
- "@typescript-eslint/parser": "^6.16.0",
63
- "eslint": "^8.56.0",
64
- "eslint-plugin-prettier": "^5.1.2",
65
- "husky": "^8.0.3",
66
- "lint-staged": "^15.2.0",
67
- "prettier": "^3.1.1",
68
- "release-it": "^17.0.1",
69
- "typescript": "^5.3.3",
70
- "vite": "^5.0.11"
71
- }
2
+ "name": "vite-plugin-unit",
3
+ "version": "2.0.0",
4
+ "description": "A vite plugin to enable you build websites in units.",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "./dist/",
10
+ "./LICENSE.md",
11
+ "./README.md",
12
+ "./package.json"
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/henryhale/vite-plugin-unit.git"
17
+ },
18
+ "keywords": [
19
+ "vite",
20
+ "static",
21
+ "site",
22
+ "static site generator",
23
+ "ui",
24
+ "website",
25
+ "browser"
26
+ ],
27
+ "author": {
28
+ "name": "Henry Hale",
29
+ "url": "https://github.com/henryhale"
30
+ },
31
+ "license": "MIT",
32
+ "bugs": {
33
+ "url": "https://github.com/henryhale/vite-plugin-unit/issues"
34
+ },
35
+ "homepage": "https://github.com/henryhale/vite-plugin-unit#readme",
36
+ "type": "module",
37
+ "scripts": {
38
+ "build": "tsc -b",
39
+ "dev": "tsc -w",
40
+ "lint": "biome check",
41
+ "lint:fix": "biome check --fix",
42
+ "prepack": "pnpm build",
43
+ "prepare": "husky || true",
44
+ "release": "release-it",
45
+ "test": "echo \"Error: no test specified\""
46
+ },
47
+ "lint-staged": {
48
+ "*.ts": "pnpm lint:fix"
49
+ },
50
+ "devDependencies": {
51
+ "@biomejs/biome": "^2.4.10",
52
+ "@release-it/conventional-changelog": "^10.0.6",
53
+ "@types/node": "^25.5.2",
54
+ "husky": "^9.1.7",
55
+ "lint-staged": "^16.4.0",
56
+ "release-it": "^19.2.4",
57
+ "typescript": "^6.0.2",
58
+ "vite": "^8.0.3"
59
+ }
72
60
  }