coralite-scripts 0.35.0 → 0.36.1
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 +24 -15
- package/bin/index.js +18 -32
- package/dist/libs/config.d.ts.map +1 -1
- package/dist/types/index.d.ts +7 -10
- package/dist/types/index.d.ts.map +1 -1
- package/libs/build-styles.js +93 -0
- package/libs/config.js +35 -13
- package/libs/server.js +41 -65
- package/package.json +2 -2
- package/types/index.js +5 -4
- package/libs/build-css.js +0 -67
- package/libs/build-sass.js +0 -80
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Coralite expects a standard folder layout:
|
|
|
12
12
|
my-coralite-site/
|
|
13
13
|
├── src/
|
|
14
14
|
│ ├── pages/ # Your page components (e.g., `about.html`, `index.html`)
|
|
15
|
-
│ ├──
|
|
15
|
+
│ ├── css/ # SCSS/Sass/CSS global styles
|
|
16
16
|
│ └── components/ # Reusable component files
|
|
17
17
|
├── public/ # Static assets (CSS, JS, images)
|
|
18
18
|
├── dist/ # Output directory for built site (auto-generated)
|
|
@@ -30,25 +30,33 @@ Create or update your config file with the following:
|
|
|
30
30
|
import { defineConfig } from 'coralite-scripts'
|
|
31
31
|
|
|
32
32
|
export default defineConfig({
|
|
33
|
+
// Directory configuration
|
|
33
34
|
output: 'dist',
|
|
34
35
|
public: 'public',
|
|
35
36
|
pages: 'src/pages',
|
|
36
37
|
components: 'src/components',
|
|
38
|
+
|
|
39
|
+
// Style pipeline (CSS, Sass, PostCSS)
|
|
37
40
|
styles: {
|
|
38
|
-
|
|
39
|
-
input:
|
|
41
|
+
// Array of entry points
|
|
42
|
+
input: [
|
|
43
|
+
'src/css/main.scss'
|
|
44
|
+
],
|
|
45
|
+
// Processor configurations
|
|
46
|
+
processors: {
|
|
47
|
+
scss: {
|
|
48
|
+
style: 'compressed',
|
|
49
|
+
loadPaths: ['node_modules']
|
|
50
|
+
}
|
|
51
|
+
}
|
|
40
52
|
},
|
|
41
|
-
|
|
53
|
+
|
|
54
|
+
// Plugins
|
|
55
|
+
plugins: [],
|
|
56
|
+
|
|
57
|
+
// Static Assets
|
|
42
58
|
assets: [
|
|
43
59
|
{ pkg: 'some-package', path: 'dist/asset.js', dest: 'assets/asset.js' }
|
|
44
|
-
],
|
|
45
|
-
// Optional: ignore processing elements with specific attributes
|
|
46
|
-
ignoreByAttribute: [
|
|
47
|
-
{ name: 'data-ignore', value: 'true' }
|
|
48
|
-
],
|
|
49
|
-
// Optional: skip rendering elements with specific attributes
|
|
50
|
-
skipRenderByAttribute: [
|
|
51
|
-
{ name: 'data-skip', value: 'true' }
|
|
52
60
|
]
|
|
53
61
|
})
|
|
54
62
|
```
|
|
@@ -88,7 +96,7 @@ Coralite provides real-time development workflows out of the box:
|
|
|
88
96
|
|-------|-------------|
|
|
89
97
|
| **Live Reload** | Automatically reloads browser when any `.html`, `.scss`, `.sass`, or `.css` file changes. |
|
|
90
98
|
| **Hot CSS Updates** | Sass/SCSS files are compiled instantly and injected into your page via Server-Sent Events (SSE). |
|
|
91
|
-
| **File Watching** | Monitors `src/pages`, `
|
|
99
|
+
| **File Watching** | Monitors `src/pages`, `styles.input` files, `public`, and `src/components`. |
|
|
92
100
|
| **Dev Logs** | Shows real-time build times, file changes, and status codes in terminal. |
|
|
93
101
|
|
|
94
102
|
---
|
|
@@ -97,7 +105,8 @@ Coralite provides real-time development workflows out of the box:
|
|
|
97
105
|
|
|
98
106
|
- **Routing**: `/` → `index.html`, `/about` → `about.html`
|
|
99
107
|
- **HTML Compilation**: Pages are compiled with embedded live reload scripts during development.
|
|
100
|
-
- **Sass/CSS Support**: `.scss`, `.sass`, or `.css` files are auto-compiled to CSS in `dist/css`.
|
|
108
|
+
- **Sass/CSS Support**: `.scss`, `.sass`, or `.css` files specified in `styles.input` are auto-compiled to CSS in `dist/assets/css`.
|
|
109
|
+
- **Auto-Injection**: Global styles are automatically injected as `<link>` tags into the `<head>` of every page, before component-scoped styles.
|
|
101
110
|
- **Server-Sent Events (SSE)**: Used for real-time updates without full page refresh.
|
|
102
111
|
|
|
103
112
|
> No extra tooling needed — everything is built-in!
|
|
@@ -125,7 +134,7 @@ Coralite provides real-time development workflows out of the box:
|
|
|
125
134
|
|
|
126
135
|
3. Edit the file → see auto-reload!
|
|
127
136
|
|
|
128
|
-
4. Add a new SCSS file at `src/
|
|
137
|
+
4. Add a new SCSS file at `src/css/style.scss`, add it to `styles.input` in your config, and see it automatically injected into your pages!
|
|
129
138
|
|
|
130
139
|
---
|
|
131
140
|
|
package/bin/index.js
CHANGED
|
@@ -5,10 +5,9 @@ import { Command, Argument } from 'commander'
|
|
|
5
5
|
import server from '../libs/server.js'
|
|
6
6
|
import colours from 'kleur'
|
|
7
7
|
import pkg from '../package.json' with { type: 'json' }
|
|
8
|
-
import
|
|
9
|
-
import { join, relative } from 'node:path'
|
|
8
|
+
import buildStyles from '../libs/build-styles.js'
|
|
9
|
+
import { join, relative, dirname } from 'node:path'
|
|
10
10
|
import { deleteDirectoryRecursive, copyDirectory, toMS, toTime, displayError, displayWarning, displayInfo } from '../libs/build-utils.js'
|
|
11
|
-
import buildCSS from '../libs/build-css.js'
|
|
12
11
|
import { Coralite } from 'coralite'
|
|
13
12
|
import { mkdir, writeFile } from 'node:fs/promises'
|
|
14
13
|
import ora from 'ora'
|
|
@@ -67,6 +66,10 @@ if (mode === 'dev') {
|
|
|
67
66
|
pages: config.pages,
|
|
68
67
|
plugins: config.plugins,
|
|
69
68
|
assets: config.assets,
|
|
69
|
+
externalStyles: config.styles?.input?.map(input => {
|
|
70
|
+
const ext = input.split('.').pop()
|
|
71
|
+
return '/assets/css/' + input.split('/').pop().replace(`.${ext}`, '.css')
|
|
72
|
+
}),
|
|
70
73
|
baseURL: config.baseURL,
|
|
71
74
|
output: config.output,
|
|
72
75
|
mode: 'production',
|
|
@@ -112,12 +115,13 @@ if (mode === 'dev') {
|
|
|
112
115
|
// Write ESM script assets generated during the build phase
|
|
113
116
|
if (coralite.outputFiles) {
|
|
114
117
|
const assetsDir = join(config.output, 'assets', 'js')
|
|
115
|
-
await mkdir(assetsDir, { recursive: true })
|
|
116
118
|
|
|
117
119
|
const assetWrites = Object.values(coralite.outputFiles).map(async (file) => {
|
|
118
120
|
const outFile = join(assetsDir, file.hashedPath)
|
|
121
|
+
await mkdir(dirname(outFile), { recursive: true })
|
|
119
122
|
await writeFile(outFile, file.text)
|
|
120
123
|
if (options.verbose) {
|
|
124
|
+
const dash = colours.gray(' ─ ')
|
|
121
125
|
process.stdout.write(toTime() + toMS(0) + dash + outFile + '\n')
|
|
122
126
|
}
|
|
123
127
|
})
|
|
@@ -144,40 +148,22 @@ if (mode === 'dev') {
|
|
|
144
148
|
}
|
|
145
149
|
}
|
|
146
150
|
|
|
147
|
-
if (config.styles) {
|
|
151
|
+
if (config.styles && config.styles.input) {
|
|
148
152
|
if (!options.verbose) {
|
|
149
153
|
spinner = ora('Building styles...').start()
|
|
150
154
|
}
|
|
151
155
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
start
|
|
158
|
-
})
|
|
156
|
+
const results = await buildStyles({
|
|
157
|
+
input: config.styles.input,
|
|
158
|
+
output: join(config.output, 'assets', 'css'),
|
|
159
|
+
processors: config.styles.processors
|
|
160
|
+
})
|
|
159
161
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
for (let i = 0; i < results.length; i++) {
|
|
163
|
+
const result = results[i]
|
|
162
164
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
} else if (config.styles.type === 'css') {
|
|
168
|
-
const results = await buildCSS({
|
|
169
|
-
input: config.styles.input,
|
|
170
|
-
output: join(config.output, 'assets', 'css'),
|
|
171
|
-
plugins: config.cssPlugins,
|
|
172
|
-
start
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
for (let i = 0; i < results.length; i++) {
|
|
176
|
-
const result = results[i]
|
|
177
|
-
|
|
178
|
-
if (options.verbose) {
|
|
179
|
-
process.stdout.write(toTime() + toMS(result.duration) + dash + result.output + '\n')
|
|
180
|
-
}
|
|
165
|
+
if (options.verbose) {
|
|
166
|
+
process.stdout.write(toTime() + toMS(result.duration) + dash + result.output + '\n')
|
|
181
167
|
}
|
|
182
168
|
}
|
|
183
169
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../libs/config.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,sCAzBW,oBAAoB,GAClB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../libs/config.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,sCAzBW,oBAAoB,GAClB,oBAAoB,CAmJhC;0CA7JsC,mBAAmB"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -12,17 +12,14 @@ export type CoraliteScriptBaseConfig = {
|
|
|
12
12
|
port: number;
|
|
13
13
|
};
|
|
14
14
|
styles?: {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
input?: string[];
|
|
16
|
+
processors?: {
|
|
17
|
+
scss?: Options<"async">;
|
|
18
|
+
postcss?: {
|
|
19
|
+
plugins?: import("postcss").AcceptedPlugin[];
|
|
20
|
+
};
|
|
21
|
+
};
|
|
17
22
|
};
|
|
18
|
-
/**
|
|
19
|
-
* - Additional options passed to the Sass compiler.
|
|
20
|
-
*/
|
|
21
|
-
sassOptions?: Options<"async">;
|
|
22
|
-
/**
|
|
23
|
-
* - Postcss plugins.
|
|
24
|
-
*/
|
|
25
|
-
cssPlugins?: import("postcss").AcceptedPlugin[];
|
|
26
23
|
/**
|
|
27
24
|
* - Set build mode for the coralite instance.
|
|
28
25
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../types/index.js"],"names":[],"mappings":";;;;;;YAOc,MAAM;;;;aAEjB;QAA0B,IAAI,EAAnB,MAAM;KACjB;aACA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../types/index.js"],"names":[],"mappings":";;;;;;YAOc,MAAM;;;;aAEjB;QAA0B,IAAI,EAAnB,MAAM;KACjB;aACA;QAA6B,KAAK,GAAvB,MAAM,EAAE;QACQ,UAAU,GACrC;YAAgD,IAAI,GAAzC,QAAQ,OAAO,CAAC;YACW,OAAO,GAC7C;gBAA0E,OAAO,GAAtE,OAAO,SAAS,EAAE,cAAc,EAAE;aAC7C;SAAA;KAAA;;;;WAAW,YAAY,GAAG,aAAa;;mCAI7B,wBAAwB,GAAG,cAAc;;;;;UAKxC,OAAO;;;;YACP,OAAO;;;;cACP,OAAO;;6BAzBK,MAAM;oCADC,gBAAgB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as sass from 'sass'
|
|
2
|
+
import postcss from 'postcss'
|
|
3
|
+
import fs from 'fs/promises'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} BuildStylesResult
|
|
8
|
+
* @property {string} input - The input file path
|
|
9
|
+
* @property {string} output - The output file name
|
|
10
|
+
* @property {[number, number]} duration - The build duration as high-resolution time array
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Compiles SCSS and CSS files with optional PostCSS processing
|
|
15
|
+
* @param {Object} options
|
|
16
|
+
* @param {string[]} options.input - Array of input file paths
|
|
17
|
+
* @param {string} options.output - Output directory for compiled CSS files
|
|
18
|
+
* @param {Object} [options.processors] - Processor configurations
|
|
19
|
+
* @param {import('sass').Options<'async'>} [options.processors.scss] - Sass options
|
|
20
|
+
* @param {Object} [options.processors.postcss] - PostCSS options
|
|
21
|
+
* @param {import('postcss').AcceptedPlugin[]} [options.processors.postcss.plugins] - PostCSS plugins
|
|
22
|
+
* @returns {Promise<BuildStylesResult[]>}
|
|
23
|
+
*/
|
|
24
|
+
async function buildStyles ({
|
|
25
|
+
input,
|
|
26
|
+
output,
|
|
27
|
+
processors = {}
|
|
28
|
+
}) {
|
|
29
|
+
const scssOptions = {
|
|
30
|
+
sourceMap: true,
|
|
31
|
+
loadPaths: ['node_modules'],
|
|
32
|
+
silenceDeprecations: [
|
|
33
|
+
'color-functions',
|
|
34
|
+
'import',
|
|
35
|
+
'global-builtin',
|
|
36
|
+
'elseif'
|
|
37
|
+
],
|
|
38
|
+
...processors.scss
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const postcssPlugins = processors.postcss?.plugins || []
|
|
42
|
+
|
|
43
|
+
const results = await Promise.all(input.map(async (filePath) => {
|
|
44
|
+
const fileStart = process.hrtime()
|
|
45
|
+
const ext = path.extname(filePath)
|
|
46
|
+
const fileName = path.basename(filePath, ext) + '.css'
|
|
47
|
+
const outputFile = path.join(output, fileName)
|
|
48
|
+
|
|
49
|
+
let css
|
|
50
|
+
let map
|
|
51
|
+
|
|
52
|
+
if (ext === '.scss' || ext === '.sass') {
|
|
53
|
+
const result = await sass.compileAsync(filePath, scssOptions)
|
|
54
|
+
css = result.css
|
|
55
|
+
map = result.sourceMap
|
|
56
|
+
} else if (ext === '.css') {
|
|
57
|
+
css = await fs.readFile(filePath, 'utf-8')
|
|
58
|
+
} else {
|
|
59
|
+
return null
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (postcssPlugins.length > 0) {
|
|
63
|
+
const postcssOptions = {
|
|
64
|
+
from: filePath,
|
|
65
|
+
to: outputFile,
|
|
66
|
+
map: map ? { prev: map } : true
|
|
67
|
+
}
|
|
68
|
+
const result = await postcss(postcssPlugins).process(css, postcssOptions)
|
|
69
|
+
css = result.css
|
|
70
|
+
map = result.map
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const duration = process.hrtime(fileStart)
|
|
74
|
+
|
|
75
|
+
await fs.mkdir(output, { recursive: true })
|
|
76
|
+
await fs.writeFile(outputFile, css)
|
|
77
|
+
|
|
78
|
+
if (map) {
|
|
79
|
+
const mapPath = outputFile + '.map'
|
|
80
|
+
await fs.writeFile(mapPath, typeof map === 'string' ? map : JSON.stringify(map))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
input: filePath,
|
|
85
|
+
output: fileName,
|
|
86
|
+
duration
|
|
87
|
+
}
|
|
88
|
+
}))
|
|
89
|
+
|
|
90
|
+
return results.filter(Boolean)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default buildStyles
|
package/libs/config.js
CHANGED
|
@@ -60,21 +60,43 @@ export function defineConfig (options) {
|
|
|
60
60
|
throw new Error('Configuration "server.port" must be a positive number')
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// Validate
|
|
64
|
-
if (options.styles
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
// Validate styles configuration
|
|
64
|
+
if (options.styles) {
|
|
65
|
+
if (typeof options.styles !== 'object') {
|
|
66
|
+
throw new Error('Configuration "styles" must be an object')
|
|
67
|
+
}
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
if (options.styles.input) {
|
|
70
|
+
if (typeof options.styles.input === 'string') {
|
|
71
|
+
throw new Error('Coralite Config Error: The "styles" configuration has been upgraded. "input" must now be an array, and "type" has been replaced by the "processors" object. Please update your coralite.config.js.')
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!Array.isArray(options.styles.input)) {
|
|
75
|
+
throw new Error('Configuration "styles.input" must be an array of strings')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const outputs = new Set()
|
|
79
|
+
for (const input of options.styles.input) {
|
|
80
|
+
if (typeof input !== 'string') {
|
|
81
|
+
throw new Error('Configuration "styles.input" must be an array of strings')
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const ext = input.split('.').pop()
|
|
85
|
+
const filename = input.split('/').pop().replace(`.${ext}`, '.css')
|
|
86
|
+
|
|
87
|
+
if (outputs.has(filename)) {
|
|
88
|
+
throw new Error(`Coralite Build Error: Filename collision detected in styles.input. Multiple inputs will output to "${filename}". Please rename one of the files.`)
|
|
89
|
+
}
|
|
90
|
+
outputs.add(filename)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (options.styles.type) {
|
|
95
|
+
throw new Error('Coralite Config Error: The "styles" configuration has been upgraded. "input" must now be an array, and "type" has been replaced by the "processors" object. Please update your coralite.config.js.')
|
|
96
|
+
}
|
|
71
97
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (typeof type !== 'string') {
|
|
75
|
-
throw new Error('Configuration "styles.type" must be a string')
|
|
76
|
-
} else if (type !== 'css' && type !== 'sass' && type !== 'scss') {
|
|
77
|
-
throw new Error('Configuration "styles.type" must be equal to either "css", "sass" or "scss" but found: ' + type)
|
|
98
|
+
if (options.styles.processors && typeof options.styles.processors !== 'object') {
|
|
99
|
+
throw new Error('Configuration "styles.processors" must be an object')
|
|
78
100
|
}
|
|
79
101
|
}
|
|
80
102
|
|
package/libs/server.js
CHANGED
|
@@ -2,12 +2,11 @@ import express from 'express'
|
|
|
2
2
|
import colours from 'kleur'
|
|
3
3
|
import localAccess from 'local-access'
|
|
4
4
|
import chokidar from 'chokidar'
|
|
5
|
-
import
|
|
5
|
+
import buildStyles from './build-styles.js'
|
|
6
6
|
import { displayError, displayInfo, displayWarning, displaySuccess, toCode, toMS, toTime, deleteDirectoryRecursive } from './build-utils.js'
|
|
7
|
-
import { extname, join, normalize, relative, sep } from 'path'
|
|
7
|
+
import { dirname, extname, join, normalize, relative, sep } from 'path'
|
|
8
8
|
import { access, constants, mkdir, readFile, writeFile } from 'fs/promises'
|
|
9
9
|
import Coralite from 'coralite'
|
|
10
|
-
import buildCSS from './build-css.js'
|
|
11
10
|
import { existsSync, mkdirSync } from 'fs'
|
|
12
11
|
import portfinder from 'portfinder'
|
|
13
12
|
|
|
@@ -107,6 +106,10 @@ async function server (config, options) {
|
|
|
107
106
|
pages: currentConfig.pages,
|
|
108
107
|
plugins: currentConfig.plugins,
|
|
109
108
|
assets: currentConfig.assets,
|
|
109
|
+
externalStyles: currentConfig.styles?.input?.map(input => {
|
|
110
|
+
const ext = input.split('.').pop()
|
|
111
|
+
return '/assets/css/' + input.split('/').pop().replace(`.${ext}`, '.css')
|
|
112
|
+
}),
|
|
110
113
|
baseURL: currentConfig.baseURL,
|
|
111
114
|
ignoreByAttribute: currentConfig.ignoreByAttribute,
|
|
112
115
|
skipRenderByAttribute: currentConfig.skipRenderByAttribute,
|
|
@@ -134,7 +137,8 @@ async function server (config, options) {
|
|
|
134
137
|
}
|
|
135
138
|
|
|
136
139
|
if (currentConfig.plugins) {
|
|
137
|
-
extractPluginPaths()
|
|
140
|
+
await extractPluginPaths()
|
|
141
|
+
|
|
138
142
|
for (const plugin of currentConfig.plugins) {
|
|
139
143
|
if (typeof plugin.server === 'function') {
|
|
140
144
|
await plugin.server(app, coralite)
|
|
@@ -196,50 +200,32 @@ async function server (config, options) {
|
|
|
196
200
|
// serve compiled components directory
|
|
197
201
|
app.use(express.static(config.output, staticOptions))
|
|
198
202
|
|
|
199
|
-
// check if
|
|
200
|
-
if (config.styles) {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
mkdirSync(config.styles.input)
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
watchPath.push(config.styles.input)
|
|
207
|
-
|
|
208
|
-
app.use('/assets/css', express.static(join(config.output, 'assets', 'css'), {
|
|
209
|
-
cacheControl: false
|
|
210
|
-
}))
|
|
211
|
-
} else {
|
|
212
|
-
displayError('Coralite config styles input must not be empty.')
|
|
203
|
+
// check if styles are configured and add its inputs to watchPath for file changes.
|
|
204
|
+
if (config.styles && config.styles.input) {
|
|
205
|
+
for (const input of config.styles.input) {
|
|
206
|
+
watchPath.push(dirname(input))
|
|
213
207
|
}
|
|
214
208
|
|
|
215
|
-
|
|
216
|
-
|
|
209
|
+
app.use('/assets/css', express.static(join(config.output, 'assets', 'css'), {
|
|
210
|
+
cacheControl: false
|
|
211
|
+
}))
|
|
217
212
|
|
|
218
|
-
|
|
219
|
-
const results = await buildSass({
|
|
220
|
-
...config.styles,
|
|
221
|
-
output: join(config.output, 'assets', 'css'),
|
|
222
|
-
start
|
|
223
|
-
})
|
|
213
|
+
const start = process.hrtime()
|
|
224
214
|
|
|
225
|
-
|
|
215
|
+
// rebuild CSS and send notification
|
|
216
|
+
const results = await buildStyles({
|
|
217
|
+
input: config.styles.input,
|
|
218
|
+
output: join(config.output, 'assets', 'css'),
|
|
219
|
+
processors: config.styles.processors,
|
|
220
|
+
start
|
|
221
|
+
})
|
|
226
222
|
|
|
227
|
-
|
|
228
|
-
const result = results[i]
|
|
223
|
+
const dash = colours.gray(' ─ ')
|
|
229
224
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
} else if (config.styles.type === 'css') {
|
|
233
|
-
const start = process.hrtime()
|
|
225
|
+
for (let i = 0; i < results.length; i++) {
|
|
226
|
+
const result = results[i]
|
|
234
227
|
|
|
235
|
-
|
|
236
|
-
input: config.styles.input,
|
|
237
|
-
output: join(config.output, 'assets', 'css'),
|
|
238
|
-
plugins: config.cssPlugins,
|
|
239
|
-
start
|
|
240
|
-
})
|
|
241
|
-
} else {
|
|
242
|
-
displayError('Coralite config styles type must not be empty')
|
|
228
|
+
process.stdout.write(toTime() + colours.bgGreen(' Compiled STYLES ') + dash + toMS(result.duration) + dash + result.input + '\n')
|
|
243
229
|
}
|
|
244
230
|
}
|
|
245
231
|
|
|
@@ -393,6 +379,7 @@ async function server (config, options) {
|
|
|
393
379
|
// Write ESM script assets generated during the build phase
|
|
394
380
|
if (coralite.outputFiles) {
|
|
395
381
|
const assetsDir = join(config.output, 'assets', 'js')
|
|
382
|
+
|
|
396
383
|
if (!existsSync(assetsDir)) {
|
|
397
384
|
await mkdir(assetsDir, { recursive: true })
|
|
398
385
|
}
|
|
@@ -474,8 +461,12 @@ async function server (config, options) {
|
|
|
474
461
|
// Group changes by type
|
|
475
462
|
const pagesChanges = changes.filter(p => p.startsWith(pagesPath))
|
|
476
463
|
const componentChanges = changes.filter(p => p.startsWith(componentPath))
|
|
477
|
-
const
|
|
478
|
-
|
|
464
|
+
const stylesChanges = changes.filter(p => {
|
|
465
|
+
if (!currentConfig.styles?.input) {
|
|
466
|
+
return false
|
|
467
|
+
}
|
|
468
|
+
return currentConfig.styles.input.some(input => p.startsWith(normalize(join(process.cwd(), dirname(input))))) || p.endsWith('.scss') || p.endsWith('.sass') || p.endsWith('.css')
|
|
469
|
+
})
|
|
479
470
|
const configChanges = changes.filter(p => p === configPathStr || Array.from(pluginPaths).some(pluginPath => p === pluginPath))
|
|
480
471
|
|
|
481
472
|
try {
|
|
@@ -508,39 +499,24 @@ async function server (config, options) {
|
|
|
508
499
|
await coralite.components.setItem(path)
|
|
509
500
|
}
|
|
510
501
|
|
|
511
|
-
// Handle
|
|
512
|
-
if (
|
|
513
|
-
const results = await
|
|
514
|
-
input:
|
|
515
|
-
|
|
516
|
-
output: join(config.output, 'assets', 'css'),
|
|
517
|
-
start
|
|
518
|
-
})
|
|
519
|
-
|
|
520
|
-
for (const result of results) {
|
|
521
|
-
process.stdout.write(toTime() + colours.bgGreen(' Compiled SASS ') + dash + toMS(result.duration) + dash + result.input + '\n')
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
// Handle CSS changes - rebuild all CSS files once
|
|
526
|
-
if (cssChanges.length > 0) {
|
|
527
|
-
const results = await buildCSS({
|
|
528
|
-
input: config.styles.input,
|
|
502
|
+
// Handle STYLES changes - rebuild all STYLES files once
|
|
503
|
+
if (stylesChanges.length > 0 && currentConfig.styles?.input) {
|
|
504
|
+
const results = await buildStyles({
|
|
505
|
+
input: currentConfig.styles.input,
|
|
506
|
+
processors: currentConfig.styles.processors,
|
|
529
507
|
output: join(config.output, 'assets', 'css'),
|
|
530
|
-
plugins: config.cssPlugins,
|
|
531
508
|
start
|
|
532
509
|
})
|
|
533
510
|
|
|
534
511
|
for (const result of results) {
|
|
535
|
-
process.stdout.write(toTime() + colours.bgGreen(' Compiled
|
|
512
|
+
process.stdout.write(toTime() + colours.bgGreen(' Compiled STYLES ') + dash + toMS(result.duration) + dash + result.input + '\n')
|
|
536
513
|
}
|
|
537
514
|
}
|
|
538
515
|
|
|
539
516
|
// Notify clients to reload
|
|
540
517
|
if (pagesChanges.length > 0
|
|
541
518
|
|| componentChanges.length > 0
|
|
542
|
-
||
|
|
543
|
-
|| cssChanges.length > 0
|
|
519
|
+
|| stylesChanges.length > 0
|
|
544
520
|
|| configChanges.length > 0) {
|
|
545
521
|
clients.forEach(client => {
|
|
546
522
|
client.write(`data: reload\n\n`)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coralite-scripts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.1",
|
|
4
4
|
"description": "Configuration and scripts for Create Coralite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"portfinder": "^1.0.38",
|
|
62
62
|
"postcss": "^8.5.6",
|
|
63
63
|
"sass": "^1.91.0",
|
|
64
|
-
"coralite": "0.
|
|
64
|
+
"coralite": "0.36.1"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"build": "premove dist && pnpm build-types",
|
package/types/index.js
CHANGED
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
* @property {Object} [server] - Server configuration options.
|
|
10
10
|
* @property {number} server.port - The port number on which the development server will run.
|
|
11
11
|
* @property {Object} [styles]
|
|
12
|
-
* @property {
|
|
13
|
-
* @property {
|
|
14
|
-
* @property {Options<'async'>} [
|
|
15
|
-
* @property {
|
|
12
|
+
* @property {string[]} [styles.input] - Array of inputs, mixing scss and css
|
|
13
|
+
* @property {Object} [styles.processors]
|
|
14
|
+
* @property {Options<'async'>} [styles.processors.scss] - Native Dart Sass options
|
|
15
|
+
* @property {Object} [styles.processors.postcss]
|
|
16
|
+
* @property {import('postcss').AcceptedPlugin[]} [styles.processors.postcss.plugins] - Native PostCSS plugins
|
|
16
17
|
* @property {'production' | 'development'} [mode='production'] - Set build mode for the coralite instance.
|
|
17
18
|
*/
|
|
18
19
|
|
package/libs/build-css.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import postcss from 'postcss'
|
|
2
|
-
import fs from 'fs/promises'
|
|
3
|
-
import path from 'path'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @typedef {Object} BuildCssResult
|
|
7
|
-
* @property {string} input - The input file path
|
|
8
|
-
* @property {string} output - The output file path
|
|
9
|
-
* @property {[number, number]} duration - The build duration as high-resolution time array
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Compiles SCSS files to CSS with source maps
|
|
14
|
-
* @param {Object} options
|
|
15
|
-
* @param {string} options.input - The directory containing SCSS files to compile
|
|
16
|
-
* @param {string} options.output - The output directory for compiled CSS files
|
|
17
|
-
* @param {import('postcss').AcceptedPlugin[]} [options.plugins=[]] - postcss plugins
|
|
18
|
-
* @param {[number, number]} [options.start]
|
|
19
|
-
* @returns {Promise<BuildCssResult[]>} Resolves when all files are compiled
|
|
20
|
-
*/
|
|
21
|
-
async function buildCSS ({
|
|
22
|
-
input,
|
|
23
|
-
output,
|
|
24
|
-
plugins = []
|
|
25
|
-
}) {
|
|
26
|
-
try {
|
|
27
|
-
// ensure output directory exists
|
|
28
|
-
await fs.mkdir(output, { recursive: true })
|
|
29
|
-
|
|
30
|
-
// read all files from src/scss directory
|
|
31
|
-
const cssFiles = await fs.readdir(input)
|
|
32
|
-
const filteredCssFiles = cssFiles.filter(file => file.endsWith('.css'))
|
|
33
|
-
|
|
34
|
-
const results = await Promise.all(filteredCssFiles.map(async (file) => {
|
|
35
|
-
const filePath = path.join(input, file)
|
|
36
|
-
const outputFile = path.join(output, file)
|
|
37
|
-
const css = await fs.readFile(filePath)
|
|
38
|
-
|
|
39
|
-
const fileStart = process.hrtime()
|
|
40
|
-
|
|
41
|
-
const result = await postcss(plugins).process(css, {
|
|
42
|
-
from: filePath,
|
|
43
|
-
to: outputFile
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
const duration = process.hrtime(fileStart)
|
|
47
|
-
|
|
48
|
-
await fs.writeFile(outputFile, result.css)
|
|
49
|
-
|
|
50
|
-
if (result.map) {
|
|
51
|
-
await fs.writeFile(outputFile + '.map', result.map.toString())
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
input: filePath,
|
|
56
|
-
output: outputFile,
|
|
57
|
-
duration
|
|
58
|
-
}
|
|
59
|
-
}))
|
|
60
|
-
|
|
61
|
-
return results
|
|
62
|
-
} catch (error) {
|
|
63
|
-
throw error
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export default buildCSS
|
package/libs/build-sass.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import * as sass from 'sass'
|
|
2
|
-
import fs from 'fs/promises'
|
|
3
|
-
import path from 'path'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @import {Options} from 'sass'
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @typedef {Object} BuildSassResult
|
|
11
|
-
* @property {string} input - The input file path
|
|
12
|
-
* @property {string} output - The output file path
|
|
13
|
-
* @property {[number, number]} duration - The build duration as high-resolution time array
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Compiles SCSS files to CSS with source maps
|
|
18
|
-
* @param {Object} options
|
|
19
|
-
* @param {string} options.input - The directory containing SCSS files to compile
|
|
20
|
-
* @param {string} options.output - The output directory for compiled CSS files
|
|
21
|
-
* @param {Options<'async'>} [options.options] - Sass compile options
|
|
22
|
-
* @param {[number, number]} [options.start]
|
|
23
|
-
* @returns {Promise<BuildSassResult[]>} Resolves when all files are compiled
|
|
24
|
-
*/
|
|
25
|
-
async function buildSass ({
|
|
26
|
-
input,
|
|
27
|
-
output,
|
|
28
|
-
options = {
|
|
29
|
-
sourceMap: true,
|
|
30
|
-
loadPaths: ['node_modules'],
|
|
31
|
-
silenceDeprecations: [
|
|
32
|
-
'color-functions',
|
|
33
|
-
'import',
|
|
34
|
-
'global-builtin',
|
|
35
|
-
'elseif'
|
|
36
|
-
]
|
|
37
|
-
}
|
|
38
|
-
}) {
|
|
39
|
-
try {
|
|
40
|
-
// ensure output directory exists
|
|
41
|
-
await fs.mkdir(output, { recursive: true })
|
|
42
|
-
|
|
43
|
-
// read all files from src/scss directory
|
|
44
|
-
const scssFiles = await fs.readdir(input)
|
|
45
|
-
const filteredScssFiles = scssFiles.filter(file => file.endsWith('.scss') && file[0] !== '_')
|
|
46
|
-
|
|
47
|
-
const results = await Promise.all(filteredScssFiles.map(async (file) => {
|
|
48
|
-
const filePath = path.join(input, file)
|
|
49
|
-
const outputFile = path.join(output, file.replace('.scss', '.css'))
|
|
50
|
-
|
|
51
|
-
// start duration timer.
|
|
52
|
-
const fileStart = process.hrtime()
|
|
53
|
-
|
|
54
|
-
// compile sass
|
|
55
|
-
const result = await sass.compileAsync(filePath, options)
|
|
56
|
-
|
|
57
|
-
// record duration
|
|
58
|
-
const duration = process.hrtime(fileStart)
|
|
59
|
-
|
|
60
|
-
await fs.writeFile(outputFile, result.css)
|
|
61
|
-
|
|
62
|
-
if (result.sourceMap) {
|
|
63
|
-
const sourceMapPath = outputFile + '.map'
|
|
64
|
-
await fs.writeFile(sourceMapPath, JSON.stringify(result.sourceMap))
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
input: filePath,
|
|
69
|
-
output: outputFile,
|
|
70
|
-
duration
|
|
71
|
-
}
|
|
72
|
-
}))
|
|
73
|
-
|
|
74
|
-
return results
|
|
75
|
-
} catch (error) {
|
|
76
|
-
throw error
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export default buildSass
|