minimaz-cli 0.1.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/LICENSE +7 -0
- package/README.md +107 -0
- package/bin/cli.ts +80 -0
- package/dist/LICENSE +7 -0
- package/dist/README.md +103 -0
- package/dist/bin/cli.js +2 -0
- package/dist/package.json +42 -0
- package/package.json +57 -0
- package/src/commands/build.ts +176 -0
- package/src/commands/help.ts +33 -0
- package/src/commands/init.ts +56 -0
- package/src/commands/template.ts +146 -0
- package/src/templates/default/minimaz.config.json +26 -0
- package/src/templates/default/public/assets/.gitkeep +0 -0
- package/src/templates/default/public/favicon.ico +0 -0
- package/src/templates/default/src/index.html +80 -0
- package/src/templates/default/src/pages/about.html +46 -0
- package/src/templates/default/src/script.js +1 -0
- package/src/templates/default/src/style.css +99 -0
- package/src/templates/gitignore +2 -0
- package/src/templates/simple/minimaz.config.json +26 -0
- package/src/templates/simple/public/assets/.gitkeep +0 -0
- package/src/templates/simple/public/favicon.ico +0 -0
- package/src/templates/simple/src/index.html +15 -0
- package/src/templates/simple/src/pages/page.html +11 -0
- package/src/templates/simple/src/script.js +1 -0
- package/src/templates/simple/src/style.css +0 -0
- package/src/utils/functions.ts +161 -0
- package/src/utils/loadConfig.ts +61 -0
- package/src/utils/logService.ts +19 -0
- package/src/utils/postInstall.ts +16 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright (c) 2025 Hans Zeller (info@zellerindustries.com)
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Minimaz ⚡
|
|
2
|
+
|
|
3
|
+
**Minimaz** is a minimal, zero-dependency static site builder and project initializer focused on speed, simplicity, and clean output.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
* 📁 Initialize projects from global templates
|
|
8
|
+
* 🧩 Save, list, and delete custom templates
|
|
9
|
+
* 📝 Supports HTML, CSS, JS, and TypeScript (.ts → .js)
|
|
10
|
+
* 🧹 Minifies HTML, CSS, JS, and TS (compiled & minified)
|
|
11
|
+
* ⚙️ Configurable with a `minimaz.config.json` file
|
|
12
|
+
* ➕ Supports concatenation of additional scripts and styles
|
|
13
|
+
* 🪄 Optional path replacements for asset links
|
|
14
|
+
* 🪶 Lightweight and fast — ideal for small static or utility projects
|
|
15
|
+
* 🔥 Usable with `minimaz` or alias `mz`
|
|
16
|
+
* 🆕 Display version with `minimaz version`
|
|
17
|
+
|
|
18
|
+
## 📦 Installation
|
|
19
|
+
|
|
20
|
+
Run directly with `npx` without global install:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx minimaz init my-site
|
|
24
|
+
cd my-site
|
|
25
|
+
npx minimaz build
|
|
26
|
+
npx minimaz version
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or using the alias:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx mz init my-site
|
|
33
|
+
npx mz build
|
|
34
|
+
npx mz version
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 📁 Project Structure
|
|
38
|
+
|
|
39
|
+
```txt
|
|
40
|
+
my-site/
|
|
41
|
+
├── src/ # HTML, CSS, JS, TS files
|
|
42
|
+
├── public/ # Static assets (images, fonts, etc.)
|
|
43
|
+
├── dist/ # Output folder (generated)
|
|
44
|
+
├── minimaz.config.json
|
|
45
|
+
└── ...
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## ⚙️ Configuration
|
|
49
|
+
|
|
50
|
+
Customize your build using a `minimaz.config.json` file:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"src": "src",
|
|
55
|
+
"dist": "dist",
|
|
56
|
+
"public": "public",
|
|
57
|
+
"minify": {
|
|
58
|
+
"html": true,
|
|
59
|
+
"css": true,
|
|
60
|
+
"js": true,
|
|
61
|
+
"ts": true
|
|
62
|
+
},
|
|
63
|
+
"replace": {
|
|
64
|
+
"../public/": "public/"
|
|
65
|
+
},
|
|
66
|
+
"styles": [
|
|
67
|
+
"style.css",
|
|
68
|
+
"theme.css"
|
|
69
|
+
],
|
|
70
|
+
"scripts": [
|
|
71
|
+
"lib.js",
|
|
72
|
+
"script.js"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
* `styles` (optional): array of `.css` files to concatenate and minify into a single `style.css`
|
|
78
|
+
* `scripts` (optional): array of `.js` files to concatenate and minify into a single `script.js`
|
|
79
|
+
* If omitted, fallback defaults are `style.css` and `script.js`
|
|
80
|
+
|
|
81
|
+
## 🛠 Commands
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
minimaz init <project-name> # Create a new project using global templates
|
|
85
|
+
minimaz build # Build and minify the site (uses config or defaults)
|
|
86
|
+
minimaz template <path> # Save a new template from specified path (or current dir)
|
|
87
|
+
minimaz template -l # List available templates
|
|
88
|
+
minimaz template -d <name> # Delete a saved template
|
|
89
|
+
minimaz help # Show help message
|
|
90
|
+
minimaz version # Display Minimaz version
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
*All commands also work with the alias `mz`.*
|
|
94
|
+
|
|
95
|
+
## 📂 Templates
|
|
96
|
+
|
|
97
|
+
Minimaz supports global templates stored in:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
~/.minimaz/templates
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Use them to quickly initialize consistent projects across environments.
|
|
104
|
+
|
|
105
|
+
## 📄 License
|
|
106
|
+
|
|
107
|
+
MIT
|
package/bin/cli.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { fileURLToPath } from 'url'
|
|
3
|
+
import { dirname, join } from 'path'
|
|
4
|
+
import fs from 'fs-extra'
|
|
5
|
+
|
|
6
|
+
import { build } from '../src/commands/build.js'
|
|
7
|
+
import { init } from '../src/commands/init.js'
|
|
8
|
+
import { help } from '../src/commands/help.js'
|
|
9
|
+
import { template } from '../src/commands/template.js'
|
|
10
|
+
|
|
11
|
+
import { log } from '../src/utils/logService.js'
|
|
12
|
+
import { parseArgs } from '../src/utils/functions.js'
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
15
|
+
const __dirname = dirname(__filename)
|
|
16
|
+
|
|
17
|
+
// Read version from package.json dynamically
|
|
18
|
+
const pkgPath = join(__dirname, '../package.json')
|
|
19
|
+
const pkgJson = await fs.readJson(pkgPath)
|
|
20
|
+
const version = pkgJson.version as string
|
|
21
|
+
|
|
22
|
+
async function main(): Promise<void> {
|
|
23
|
+
const args = parseArgs(process.argv.slice(2))
|
|
24
|
+
const cmd = (args._[0] || '').toLowerCase()
|
|
25
|
+
|
|
26
|
+
type CommandFn = () => Promise<void> | void
|
|
27
|
+
|
|
28
|
+
const commands: Record<string, CommandFn> = {
|
|
29
|
+
// Init Command
|
|
30
|
+
init: async () => {
|
|
31
|
+
await init(args._[1] || 'minimaz-project', {
|
|
32
|
+
template: args.template || args.t || 'default'
|
|
33
|
+
})
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
// Build Command
|
|
37
|
+
build: async () => build(),
|
|
38
|
+
|
|
39
|
+
// Help Command
|
|
40
|
+
help: () => help(),
|
|
41
|
+
|
|
42
|
+
// Template Command
|
|
43
|
+
template: async () => {
|
|
44
|
+
await template(args._[1], {
|
|
45
|
+
list: args.l || args.list,
|
|
46
|
+
delete: args.d || args.delete,
|
|
47
|
+
update: args.u || args.update
|
|
48
|
+
} as any)
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
// Version
|
|
52
|
+
version: () => console.log(version),
|
|
53
|
+
|
|
54
|
+
// Aliases
|
|
55
|
+
i: () => commands.init(),
|
|
56
|
+
b: () => commands.build(),
|
|
57
|
+
h: () => commands.help(),
|
|
58
|
+
t: () => commands.template(),
|
|
59
|
+
v: () => commands.version()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
if (commands[cmd]) {
|
|
64
|
+
await commands[cmd]()
|
|
65
|
+
} else {
|
|
66
|
+
log('error', `Unknown command '${cmd}'. Use 'minimaz help' to see available commands.`)
|
|
67
|
+
commands.help()
|
|
68
|
+
}
|
|
69
|
+
} catch (e: any) {
|
|
70
|
+
log(
|
|
71
|
+
'error',
|
|
72
|
+
e instanceof Error
|
|
73
|
+
? process.env.DEBUG ? e.stack ?? e.message : e.message
|
|
74
|
+
: String(e)
|
|
75
|
+
)
|
|
76
|
+
process.exit(1)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
main()
|
package/dist/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright (c) 2025 Hans Zeller (info@zellerindustries.com)
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/dist/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Minimaz ⚡
|
|
2
|
+
|
|
3
|
+
**Minimaz** is a minimal, zero-dependency static site builder and project initializer focused on speed, simplicity, and clean output.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- 📁 Initialize projects from global templates
|
|
8
|
+
- 🧩 Save, list, and delete custom templates
|
|
9
|
+
- 📝 Supports HTML, CSS, JS, and TypeScript (.ts → .js)
|
|
10
|
+
- 🧹 Minifies HTML, CSS, JS, and TS (compiled & minified)
|
|
11
|
+
- ⚙️ Configurable with a `minimaz.config.json` file
|
|
12
|
+
- ➕ Supports concatenation of additional scripts and styles
|
|
13
|
+
- 🪄 Optional path replacements for asset links
|
|
14
|
+
- 🪶 Lightweight and fast — ideal for small static or utility projects
|
|
15
|
+
- 🔥 Usable with `minimaz` or alias `mz`
|
|
16
|
+
|
|
17
|
+
## 📦 Installation
|
|
18
|
+
|
|
19
|
+
Run directly with `npx` without global install:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx minimaz init my-site
|
|
23
|
+
cd my-site
|
|
24
|
+
npx minimaz build
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or using the alias:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx mz init my-site
|
|
31
|
+
npx mz build
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 📁 Project Structure
|
|
35
|
+
|
|
36
|
+
```txt
|
|
37
|
+
my-site/
|
|
38
|
+
├── src/ # HTML, CSS, JS, TS files
|
|
39
|
+
├── public/ # Static assets (images, fonts, etc.)
|
|
40
|
+
├── dist/ # Output folder (generated)
|
|
41
|
+
├── minimaz.config.json
|
|
42
|
+
└── ...
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## ⚙️ Configuration
|
|
46
|
+
|
|
47
|
+
Customize your build using a `minimaz.config.json` file:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"src": "src",
|
|
52
|
+
"dist": "dist",
|
|
53
|
+
"public": "public",
|
|
54
|
+
"minify": {
|
|
55
|
+
"html": true,
|
|
56
|
+
"css": true,
|
|
57
|
+
"js": true,
|
|
58
|
+
"ts": true
|
|
59
|
+
},
|
|
60
|
+
"replace": {
|
|
61
|
+
"../public/": "public/"
|
|
62
|
+
},
|
|
63
|
+
"styles": [
|
|
64
|
+
"style.css",
|
|
65
|
+
"theme.css"
|
|
66
|
+
],
|
|
67
|
+
"scripts": [
|
|
68
|
+
"lib.js",
|
|
69
|
+
"script.js"
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- `styles` (optional): array of `.css` files to concatenate and minify into a single `style.css`
|
|
75
|
+
- `scripts` (optional): array of `.js` files to concatenate and minify into a single `script.js`
|
|
76
|
+
- If omitted, fallback defaults are `style.css` and `script.js`
|
|
77
|
+
|
|
78
|
+
## 🛠 Commands
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
minimaz init <project-name> # Create a new project using global templates
|
|
82
|
+
minimaz build # Build and minify the site (uses config or defaults)
|
|
83
|
+
minimaz template <path> # Save a new template from specified path (or current dir)
|
|
84
|
+
minimaz template -l # List available templates
|
|
85
|
+
minimaz template -d <name> # Delete a saved template
|
|
86
|
+
minimaz help # Show help message
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
_All commands also work with the alias `mz`._
|
|
90
|
+
|
|
91
|
+
## 📂 Templates
|
|
92
|
+
|
|
93
|
+
Minimaz supports global templates stored in:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
~/.minimaz/templates
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Use them to quickly initialize consistent projects across environments.
|
|
100
|
+
|
|
101
|
+
## 📄 License
|
|
102
|
+
|
|
103
|
+
MIT
|
package/dist/bin/cli.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{fileURLToPath as n}from"url";import{dirname as r,join as s}from"path";import m from"fs-extra";import{build as p}from"../src/commands/build.js";import{init as c}from"../src/commands/init.js";import{help as l}from"../src/commands/help.js";import{template as d}from"../src/commands/template.js";import{log as a}from"../src/utils/logService.js";import{parseArgs as f}from"../src/utils/functions.js";const g=n(import.meta.url),u=r(g),v=s(u,"../package.json"),h=await m.readJson(v),y=h.version;async function _(){const e=f(process.argv.slice(2)),i=(e._[0]||"").toLowerCase(),o={init:async()=>{await c(e._[1]||"minimaz-project",{template:e.template||e.t||"default"})},build:async()=>p(),help:()=>l(),template:async()=>{await d(e._[1],{list:e.l||e.list,delete:e.d||e.delete,update:e.u||e.update})},version:()=>console.log(y),i:()=>o.init(),b:()=>o.build(),h:()=>o.help(),t:()=>o.template()};try{o[i]?await o[i]():(a("error",`Unknown command '${i}'. Use 'minimaz help' to see available commands.`),o.help())}catch(t){a("error",t instanceof Error?process.env.DEBUG?t.stack??t.message:t.message:String(t)),process.exit(1)}}_();
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "minimaz-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Minimal project initializer and builder CLI",
|
|
5
|
+
"author": "MrZeller",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"bin/",
|
|
10
|
+
"src/",
|
|
11
|
+
"LICENSE",
|
|
12
|
+
"README.md",
|
|
13
|
+
"package.json"
|
|
14
|
+
],
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/zeller-dev/minimaz-cli.git"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"cli",
|
|
21
|
+
"minimal",
|
|
22
|
+
"build",
|
|
23
|
+
"init",
|
|
24
|
+
"project",
|
|
25
|
+
"starter"
|
|
26
|
+
],
|
|
27
|
+
"homepage": "https://github.com/zeller-dev/minimaz-cli#readme",
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/zeller-dev/minimaz-cli/issues"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"clean-css": "^5.3.3",
|
|
33
|
+
"fs-extra": "^11.3.0",
|
|
34
|
+
"html-minifier-terser": "^7.2.0",
|
|
35
|
+
"terser": "^5.44.0"
|
|
36
|
+
},
|
|
37
|
+
"postinstall": "node ./dist/src/utils/postInstall.js",
|
|
38
|
+
"bin": {
|
|
39
|
+
"minimaz": "./bin/cli.js",
|
|
40
|
+
"mz": "./bin/cli.js"
|
|
41
|
+
}
|
|
42
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "minimaz-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Minimal project initializer and builder CLI",
|
|
5
|
+
"author": "MrZeller",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"bin/",
|
|
10
|
+
"src/",
|
|
11
|
+
"LICENSE",
|
|
12
|
+
"README.md",
|
|
13
|
+
"package.json"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"dev": "node --loader ts-node/esm bin/cli.ts",
|
|
17
|
+
"build": "node builder.js",
|
|
18
|
+
"postinstall:dev": "node --loader ts-node/esm ./src/utils/postInstall.ts",
|
|
19
|
+
"postinstall:prod": "node ./dist/src/utils/postInstall.js"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/zeller-dev/minimaz-cli.git"
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"minimaz": "./dist/bin/cli.js",
|
|
27
|
+
"mz": "./dist/bin/cli.js"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"cli",
|
|
31
|
+
"minimal",
|
|
32
|
+
"build",
|
|
33
|
+
"init",
|
|
34
|
+
"project",
|
|
35
|
+
"starter"
|
|
36
|
+
],
|
|
37
|
+
"homepage": "https://github.com/zeller-dev/minimaz-cli#readme",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/zeller-dev/minimaz-cli/issues"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"clean-css": "^5.3.3",
|
|
43
|
+
"fs-extra": "^11.3.0",
|
|
44
|
+
"html-minifier-terser": "^7.2.0",
|
|
45
|
+
"terser": "^5.44.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/clean-css": "^4.2.11",
|
|
49
|
+
"@types/fs-extra": "^11.0.4",
|
|
50
|
+
"@types/html-minifier-terser": "^7.0.2",
|
|
51
|
+
"@types/node": "^24.7.2",
|
|
52
|
+
"esbuild": "^0.25.10",
|
|
53
|
+
"ts-node": "^10.9.2",
|
|
54
|
+
"typescript": "^5.9.3"
|
|
55
|
+
},
|
|
56
|
+
"postinstall": "node ./dist/src/utils/postInstall.js"
|
|
57
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import fs from 'fs-extra'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import CleanCSS from 'clean-css'
|
|
4
|
+
import { minify as minifyHtml } from 'html-minifier-terser'
|
|
5
|
+
import { minify as minifyJs, MinifyOutput } from 'terser'
|
|
6
|
+
|
|
7
|
+
import { loadConfig } from '../utils/loadConfig.js'
|
|
8
|
+
import { log } from '../utils/logService.js'
|
|
9
|
+
import { applyReplacements, getFile } from '../utils/functions.js'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Build the project according to configuration.
|
|
13
|
+
*/
|
|
14
|
+
export async function build(): Promise<void> {
|
|
15
|
+
try {
|
|
16
|
+
const config: any = await loadConfig()
|
|
17
|
+
const distDir: string = path.resolve(process.cwd(), config.dist || 'dist')
|
|
18
|
+
|
|
19
|
+
// Remove previous dist folder and recreate it
|
|
20
|
+
await fs.remove(distDir)
|
|
21
|
+
await fs.ensureDir(distDir)
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Process a single folder
|
|
25
|
+
* @param srcPathRel Relative path of the source folder
|
|
26
|
+
* @param destName Destination folder name inside dist
|
|
27
|
+
*/
|
|
28
|
+
async function processFolder(srcPathRel: string, destName: any): Promise<void> {
|
|
29
|
+
const fullSrc: string = path.resolve(process.cwd(), srcPathRel)
|
|
30
|
+
const fullDest: string = path.join(distDir, destName)
|
|
31
|
+
|
|
32
|
+
if (!(await fs.pathExists(fullSrc))) {
|
|
33
|
+
log('warn', `Folder not found: ${srcPathRel}`)
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const cssChunks: string[] = []
|
|
38
|
+
const jsChunks: string[] = []
|
|
39
|
+
|
|
40
|
+
// Recursive walk function to process files
|
|
41
|
+
async function walk(src: string, dest: string): Promise<void> {
|
|
42
|
+
await fs.ensureDir(dest)
|
|
43
|
+
|
|
44
|
+
for (const item of await fs.readdir(src)) {
|
|
45
|
+
const srcPath: string = path.join(src, item)
|
|
46
|
+
const destPath: string = path.join(dest, item)
|
|
47
|
+
const stat: fs.Stats = await fs.stat(srcPath)
|
|
48
|
+
const ext: string = path.extname(item).toLowerCase()
|
|
49
|
+
|
|
50
|
+
if (stat.isDirectory()) {
|
|
51
|
+
await walk(srcPath, destPath)
|
|
52
|
+
continue
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
switch (ext) {
|
|
57
|
+
case '.html': {
|
|
58
|
+
let content: string = await getFile(srcPath, config.replace)
|
|
59
|
+
if (config.minify?.html) {
|
|
60
|
+
content = await minifyHtml(content, {
|
|
61
|
+
collapseWhitespace: true,
|
|
62
|
+
removeComments: true,
|
|
63
|
+
minifyJS: config.minify?.ts,
|
|
64
|
+
minifyCSS: config.minify?.css
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
await fs.outputFile(destPath, content)
|
|
68
|
+
break
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
case '.css': {
|
|
72
|
+
const content: string = await getFile(srcPath, config.replace)
|
|
73
|
+
cssChunks.push(content)
|
|
74
|
+
break
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
case '.js': {
|
|
78
|
+
const content: string = await getFile(srcPath, config.replace)
|
|
79
|
+
jsChunks.push(content)
|
|
80
|
+
break
|
|
81
|
+
}
|
|
82
|
+
/*
|
|
83
|
+
case '.ts': {
|
|
84
|
+
const result = await esbuild.build({
|
|
85
|
+
entryPoints: [srcPath],
|
|
86
|
+
bundle: false,
|
|
87
|
+
minify: !!config.minify?.ts,
|
|
88
|
+
platform: 'browser',
|
|
89
|
+
format: 'esm',
|
|
90
|
+
write: false
|
|
91
|
+
})
|
|
92
|
+
let compiled = result.outputFiles[0].text
|
|
93
|
+
compiled = applyReplacements(compiled, config.replace)
|
|
94
|
+
if (srcPathRel === config.src) jsChunks.push(compiled)
|
|
95
|
+
break
|
|
96
|
+
}
|
|
97
|
+
*/
|
|
98
|
+
default:
|
|
99
|
+
await fs.copy(srcPath, destPath)
|
|
100
|
+
break
|
|
101
|
+
}
|
|
102
|
+
} catch (error: any) {
|
|
103
|
+
log('error', `Failed to process file: ${srcPath} - ${error.message}`)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
await walk(fullSrc, fullDest)
|
|
109
|
+
|
|
110
|
+
// Merge CSS/JS only for the root source folder
|
|
111
|
+
if (srcPathRel === config.src) {
|
|
112
|
+
try {
|
|
113
|
+
if (config.styles?.length) {
|
|
114
|
+
for (const style of config.styles) {
|
|
115
|
+
const fullPath: string = path.resolve(process.cwd(), style)
|
|
116
|
+
if (await fs.pathExists(fullPath)) {
|
|
117
|
+
let css: string = await fs.readFile(fullPath, 'utf-8')
|
|
118
|
+
css = applyReplacements(css, config.replace)
|
|
119
|
+
cssChunks.push(css)
|
|
120
|
+
} else {
|
|
121
|
+
log('warn', `Style file not found: ${style}`)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (config.scripts?.length) {
|
|
127
|
+
for (const script of config.scripts) {
|
|
128
|
+
const fullPath: string = path.resolve(process.cwd(), script)
|
|
129
|
+
if (await fs.pathExists(fullPath)) {
|
|
130
|
+
let js: string = await fs.readFile(fullPath, 'utf-8')
|
|
131
|
+
js = applyReplacements(js, config.replace)
|
|
132
|
+
jsChunks.push(js)
|
|
133
|
+
} else {
|
|
134
|
+
log('warn', `Script file not found: ${script}`)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Write final CSS bundle
|
|
140
|
+
if (cssChunks.length > 0) {
|
|
141
|
+
let finalCss: string = cssChunks.join('')
|
|
142
|
+
if (config.minify?.css) finalCss = new CleanCSS().minify(finalCss).styles
|
|
143
|
+
await fs.outputFile(path.join(distDir, 'style.css'), finalCss)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Write final JS bundle
|
|
147
|
+
if (jsChunks.length > 0) {
|
|
148
|
+
let finalJs: string = jsChunks.join('')
|
|
149
|
+
if (config.minify?.js) {
|
|
150
|
+
const minified: MinifyOutput = await minifyJs(finalJs)
|
|
151
|
+
finalJs = minified.code ?? ''
|
|
152
|
+
}
|
|
153
|
+
if (finalJs) await fs.outputFile(path.join(distDir, 'script.js'), finalJs)
|
|
154
|
+
}
|
|
155
|
+
} catch (error: any) {
|
|
156
|
+
log('error', `Failed to merge CSS/JS: ${error.message}`)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
log('success', `Processed folder: ${srcPathRel} -> /${destName}`)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Process all folders defined in configuration
|
|
164
|
+
if (config.folders && Object.keys(config.folders).length > 0) {
|
|
165
|
+
for (const [srcPathRel, destName] of Object.entries(config.folders)) {
|
|
166
|
+
await processFolder(srcPathRel, destName)
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
log('warn', 'No folders defined in config. Nothing to build.')
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
log('success', `Build completed. Output saved in /${config.dist}`)
|
|
173
|
+
} catch (error: any) {
|
|
174
|
+
log('error', `Build failed: ${error.message}`)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Displays CLI usage information for Minimaz.
|
|
3
|
+
* Lists all available commands and their options.
|
|
4
|
+
*
|
|
5
|
+
* Example:
|
|
6
|
+
* minimaz init my-site -t default
|
|
7
|
+
* minimaz build
|
|
8
|
+
* minimaz template --list
|
|
9
|
+
*/
|
|
10
|
+
export function help(): void {
|
|
11
|
+
console.log([
|
|
12
|
+
'Usage:',
|
|
13
|
+
'',
|
|
14
|
+
'\tminimaz init | i <project-name>',
|
|
15
|
+
'\t\tCreate a new project (default: "minimaz-site")',
|
|
16
|
+
'\t\tOptions:',
|
|
17
|
+
'\t\t\t--template | -t <template-name>\tUse a global template (default: "default")',
|
|
18
|
+
'',
|
|
19
|
+
'\tminimaz build | b',
|
|
20
|
+
'\t\tBuild and minify files into the dist folder',
|
|
21
|
+
'',
|
|
22
|
+
'\tminimaz template | t [path]',
|
|
23
|
+
'\t\tSave current folder as a template (no path = current folder)',
|
|
24
|
+
'\t\tOptions:',
|
|
25
|
+
'\t\t\t--list | -l\tList available global templates',
|
|
26
|
+
'\t\t\t--delete | -d <template-name>\tDelete a global template',
|
|
27
|
+
'',
|
|
28
|
+
'\tminimaz help | h',
|
|
29
|
+
'\t\tShow this help message'
|
|
30
|
+
].join('\n'));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// @TODO add help for each command
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import fs from 'fs-extra'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import os from 'os'
|
|
4
|
+
import { log } from '../utils/logService.js'
|
|
5
|
+
import { createGlobalDir } from '../utils/functions.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Initializes a new Minimaz project by copying a predefined template
|
|
9
|
+
* from the user's global Minimaz directory (~/.minimaz/templates).
|
|
10
|
+
*
|
|
11
|
+
* @param projectName - The name of the project folder to create.
|
|
12
|
+
* @param options - Optional settings (e.g. { template: 'landing' }).
|
|
13
|
+
*
|
|
14
|
+
* Process:
|
|
15
|
+
* 1. Ensures the global `.minimaz` directory exists.
|
|
16
|
+
* 2. Locates the chosen template inside `.minimaz/templates`.
|
|
17
|
+
* 3. Copies the template files to the new project folder.
|
|
18
|
+
* 4. Adds `.gitignore` if available.
|
|
19
|
+
* 5. Logs actions and errors.
|
|
20
|
+
*/
|
|
21
|
+
export async function init(projectName: string, options: any = {}): Promise<void> {
|
|
22
|
+
const minimazDir: string = path.join(os.homedir(), '.minimaz')
|
|
23
|
+
|
|
24
|
+
// Step 1: Create global folder if missing
|
|
25
|
+
if (!await fs.pathExists(minimazDir)) {
|
|
26
|
+
log('info', `Global folder '${minimazDir}' not found. Creating...`)
|
|
27
|
+
await createGlobalDir()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Step 2: Determine paths
|
|
31
|
+
const templateDir: string = path.join(minimazDir, 'templates', options.template || 'default')
|
|
32
|
+
const targetDir: string = path.resolve(process.cwd(), projectName)
|
|
33
|
+
|
|
34
|
+
// Step 3: Validate template existence
|
|
35
|
+
if (!await fs.pathExists(templateDir))
|
|
36
|
+
throw new Error(`Template '${options.template}' not found.`)
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
// Step 4: Copy template files to target directory
|
|
40
|
+
await fs.copy(templateDir, targetDir)
|
|
41
|
+
|
|
42
|
+
// Step 5: Copy .gitignore if available at the parent level
|
|
43
|
+
const gitignoreSrc: string = path.join(templateDir, '..', 'gitignore')
|
|
44
|
+
const gitignoreDest: string = path.join(targetDir, '.gitignore')
|
|
45
|
+
if (await fs.pathExists(gitignoreSrc)) {
|
|
46
|
+
await fs.copy(gitignoreSrc, gitignoreDest)
|
|
47
|
+
log('info', `.gitignore added to project.`)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Step 6: Confirm success
|
|
51
|
+
log('success', `Project '${projectName}' created using template '${options.template}'.`)
|
|
52
|
+
} catch (error: any) {
|
|
53
|
+
// Step 7: Handle any failure during copy
|
|
54
|
+
throw new Error(`Failed to create project: ${error.message}`)
|
|
55
|
+
}
|
|
56
|
+
}
|