coralite-scripts 0.35.0 → 0.36.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
@@ -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
- │ ├── scss/ # SCSS/Sass/CSS styles
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
- type: 'scss', // can be 'scss', 'sass', or 'css'
39
- input: 'src/scss'
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
- // Optional: copy static assets from other packages
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`, `src/scss`, `public`, and `src/components`. |
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/scss/style.scss`, and import it into an HTML page via `<link rel="stylesheet" href="/css/style.css">`.
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 buildSass from '../libs/build-sass.js'
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
- if (config.styles.type === 'sass' || config.styles.type === 'scss') {
153
- const results = await buildSass({
154
- input: config.styles.input,
155
- output: join(config.output, 'assets', 'css'),
156
- options: config.sassOptions,
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
- for (let i = 0; i < results.length; i++) {
161
- const result = results[i]
162
+ for (let i = 0; i < results.length; i++) {
163
+ const result = results[i]
162
164
 
163
- if (options.verbose) {
164
- process.stdout.write(toTime() + toMS(result.duration) + dash + result.output + '\n')
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,CA6HhC;0CAvIsC,mBAAmB"}
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"}
@@ -12,17 +12,14 @@ export type CoraliteScriptBaseConfig = {
12
12
  port: number;
13
13
  };
14
14
  styles?: {
15
- type: "css" | "sass" | "scss";
16
- input: string;
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;QAA2C,IAAI,EAApC,KAAK,GAAG,MAAM,GAAG,MAAM;QACR,KAAK,EAApB,MAAM;KACjB;;;;kBAAW,QAAQ,OAAO,CAAC;;;;iBAChB,OAAO,SAAS,EAAE,cAAc,EAAE;;;;WAClC,YAAY,GAAG,aAAa;;mCAI7B,wBAAwB,GAAG,cAAc;;;;;UAKxC,OAAO;;;;YACP,OAAO;;;;cACP,OAAO;;6BAxBK,MAAM;oCADC,gBAAgB"}
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 sass configuration
64
- if (options.styles && typeof options.styles !== 'object') {
65
- throw new Error('Configuration "styles" must be an object')
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
- if (options.styles?.input && typeof options.styles.input !== 'string') {
69
- throw new Error('Configuration "styles.input" must be a string')
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
- if (options.styles?.type) {
73
- const type = options.styles.type
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 buildSass from './build-sass.js'
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 Sass is configured and add its input directory to watchPath for file changes.
200
- if (config.styles) {
201
- if (config.styles.input) {
202
- if (!existsSync(config.styles.input)) {
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
- if (config.styles.type === 'sass' || config.styles.type === 'scss') {
216
- const start = process.hrtime()
209
+ app.use('/assets/css', express.static(join(config.output, 'assets', 'css'), {
210
+ cacheControl: false
211
+ }))
217
212
 
218
- // rebuild CSS and send notification
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
- let dash = colours.gray(' ')
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
- for (let i = 0; i < results.length; i++) {
228
- const result = results[i]
223
+ const dash = colours.gray(' ')
229
224
 
230
- process.stdout.write(toTime() + colours.bgGreen(' Compiled SASS ') + dash + toMS(result.duration) + dash + result.input + '\n')
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
- await buildCSS({
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 sassChanges = changes.filter(p => p.endsWith('.scss') || p.endsWith('.sass'))
478
- const cssChanges = changes.filter(p => p.endsWith('.css'))
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 SASS changes - rebuild all SASS files once
512
- if (sassChanges.length > 0) {
513
- const results = await buildSass({
514
- input: config.styles.input,
515
- options: config.sassOptions,
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 CSS ') + dash + toMS(result.duration) + dash + result.input + '\n')
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
- || sassChanges.length > 0
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.35.0",
3
+ "version": "0.36.0",
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.35.0"
64
+ "coralite": "0.36.0"
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 {'css' | 'sass' | 'scss'} styles.type - The style processing type to use for styling files.
13
- * @property {string} styles.input - The path to the main stylesheet file to process.
14
- * @property {Options<'async'>} [sassOptions] - Additional options passed to the Sass compiler.
15
- * @property {import('postcss').AcceptedPlugin[]} [cssPlugins] - Postcss plugins.
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
@@ -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