poops 1.9.2 → 1.9.4

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
@@ -110,6 +110,7 @@ or pass a custom config. This is useful when you have multiple environments:
110
110
  | `--port <number>` | `-p` | Specify the server port, overrides config |
111
111
  | `--livereload-port <number>` | `-l` | Specify the livereload port, overrides config |
112
112
  | `--base-url <path>` | `-u` | Set the base URL prefix for markup, overrides config |
113
+ | `--quiet` | `-q` | Hide the header and the server/livereload info lines |
113
114
 
114
115
  The `--base-url` flag is particularly useful for CI/CD pipelines where the deploy path may differ per environment:
115
116
 
@@ -117,6 +118,14 @@ The `--base-url` flag is particularly useful for CI/CD pipelines where the deplo
117
118
  poops --build --base-url /blog
118
119
  ```
119
120
 
121
+ The `--quiet` flag drops the `💩 Poops — vX.Y.Z` header (and its terminal bell) plus the `Local server` / `Network` / `LiveReload` lines. Handy when you run several Poops instances side by side and only want to see which one is compiling:
122
+
123
+ ```bash
124
+ poops -q & poops -q -c site/poops.json
125
+ ```
126
+
127
+ Build logs, warnings and errors are unaffected — `--quiet` only removes the banner.
128
+
120
129
  If you have installed Poops locally you can run it with `npx poops` or `npx 💩` or add a script to your `package.json`:
121
130
 
122
131
  ```json
@@ -37,5 +37,7 @@ export default async function minifyToFile({ outfilePath, loader, code, banner,
37
37
  console.error(err)
38
38
  }
39
39
 
40
- if (options.justMinified) fs.unlinkSync(outfilePath)
40
+ // The unminified file only exists on disk when a compiler wrote it there —
41
+ // watch rebuilds pass `code` in memory and there is nothing to delete.
42
+ if (options.justMinified && pathExists(outfilePath)) fs.unlinkSync(outfilePath)
41
43
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "poops",
3
3
  "description": "Straightforward, no-bullshit bundler for the web.",
4
- "version": "1.9.2",
4
+ "version": "1.9.4",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "poops.js",
package/poops.js CHANGED
@@ -30,6 +30,7 @@ const cli = new Argoyle(pkg.version)
30
30
  .option('port', { short: 'p', value: '<number>', description: 'Specify the port for the server, overrides the config file' })
31
31
  .option('livereload-port', { short: 'l', value: '<number>', description: 'Specify the port for the livereload server, overrides the config file' })
32
32
  .option('base-url', { short: 'u', value: '<path>', description: 'Set the base URL prefix for markup, overrides the config file' })
33
+ .option('quiet', { short: 'q', description: 'Hide the header and the server/livereload info lines' })
33
34
 
34
35
  let flags, positionals
35
36
  try {
@@ -44,6 +45,7 @@ const defaultConfigPath = flags.config || positionals[0] || 'poops.json'
44
45
  const overridePort = flags.port
45
46
  const overrideLivereloadPort = flags['livereload-port']
46
47
  const overrideBaseURL = flags['base-url']
48
+ const quiet = flags.quiet // hides the header and the address lines only — build logs, warnings and errors still print
47
49
 
48
50
  let configPath = path.join(cwd, defaultConfigPath)
49
51
  if (!pathExists(configPath)) configPath = path.join(cwd, '💩.json') // the canonical alternative config name
@@ -107,7 +109,7 @@ const hook = (stage) => runExec(config, cwd, stage)
107
109
  function setupLiveReloadServer(config) {
108
110
  if (!config.livereload) return
109
111
  liveReloadServer = livereload.createServer({ port: config.livereload_port })
110
- styledLog(`🔃 {dim}LiveReload :{/} ${liveReloadServer.config.port}`)
112
+ if (!quiet) styledLog(`🔃 {dim}LiveReload :{/} ${liveReloadServer.config.port}`)
111
113
  console.log()
112
114
  }
113
115
 
@@ -137,6 +139,44 @@ function setupWatchers(config, modules) {
137
139
  .filter((zone) => zone && zone !== '.')
138
140
  const isBuildOutput = (file) => outputZones.some((zone) => pathContainsPathSegment(file, zone))
139
141
 
142
+ // One chokidar event fires per written file, so a single build that writes
143
+ // several outputs into a watched dir (css + map + min.css) triggers the same
144
+ // rebuild branch once per file. The trailing debounce folds such a burst
145
+ // into one run; the window collects the paths so the handler can still
146
+ // reason per-file (the copy branch's css hot-swap vs full reload). 300ms:
147
+ // outlives the 150ms awaitWriteFinish settle between files of one burst.
148
+ const coalesce = (fn, ms = 300) => {
149
+ let timer
150
+ const files = new Set()
151
+ return (file) => {
152
+ files.add(file)
153
+ clearTimeout(timer)
154
+ timer = setTimeout(() => {
155
+ const batch = [...files]
156
+ files.clear()
157
+ fn(batch)
158
+ }, ms)
159
+ }
160
+ }
161
+
162
+ const recompileStyles = coalesce(() => {
163
+ modules.styles.compile().then(() => modules.postcss.compile())
164
+ .then(() => { hook('styles'); styleOutputs(config).forEach((out) => reload(out)) })
165
+ .catch(err => console.error(err))
166
+ })
167
+
168
+ // A copied .css (e.g. the styles compiler's own output landing in a copy
169
+ // source) stays a hot-swap; any other copied file escalates to a full
170
+ // reload — reload() itself folds the batch into one refresh.
171
+ const recopy = coalesce((batch) => {
172
+ modules.copy.execute()
173
+ .then(() => {
174
+ hook('copy')
175
+ batch.forEach((file) => reload(/\.css$/i.test(file) ? file : undefined))
176
+ })
177
+ .catch(err => console.error(err))
178
+ })
179
+
140
180
  const rebuild = (file) => {
141
181
  // Engines that keep compiled templates across compiles (nunjucks) drop
142
182
  // exactly this file's entries; shared by change/add/unlink via rebuild.
@@ -154,9 +194,7 @@ function setupWatchers(config, modules) {
154
194
  }
155
195
  }
156
196
  if (/(\.sass|\.scss|\.css)$/i.test(file) && !isBuildOutput(file)) {
157
- modules.styles.compile().then(() => modules.postcss.compile())
158
- .then(() => { hook('styles'); styleOutputs(config).forEach((out) => reload(out)) })
159
- .catch(err => console.error(err))
197
+ recompileStyles(file)
160
198
  }
161
199
  if (/(\.html|\.xml|\.rss|\.atom|\.njk|\.liquid|\.md)$/i.test(file)) {
162
200
  // Incremental: re-render only the pages whose last render touched this
@@ -187,11 +225,7 @@ function setupWatchers(config, modules) {
187
225
  .then(() => { hook('images'); hook('markup'); reload() })
188
226
  .catch(err => console.error(err))
189
227
  }
190
- // A copied .css (e.g. the styles compiler's own output landing in a copy
191
- // source) stays a hot-swap; any other copied file needs a full reload.
192
- doesFileBelongToPath(file, config.copy) && modules.copy.execute()
193
- .then(() => { hook('copy'); reload(/\.css$/i.test(file) ? file : undefined) })
194
- .catch(err => console.error(err))
228
+ doesFileBelongToPath(file, config.copy) && recopy(file)
195
229
  }
196
230
 
197
231
  // Atomic-save editors (rename-write) fire unlink+add for every save, so an
@@ -296,8 +330,10 @@ async function poops() {
296
330
  }
297
331
 
298
332
  // CLI Header
299
- const title = `💩 Poops — v${pkg.version}`
300
- styledLog(`\n{#8b4513}${title}\n${title.replace(/./g, '-')}{/}{bell}\n`)
333
+ if (!quiet) {
334
+ const title = `💩 Poops — v${pkg.version}`
335
+ styledLog(`\n{#8b4513}${title}\n${title.replace(/./g, '-')}{/}{bell}\n`)
336
+ }
301
337
 
302
338
  // Check if poops.json exists
303
339
  if (!pathExists(configPath)) {
@@ -391,9 +427,11 @@ async function startServer() {
391
427
 
392
428
  // eslint-disable-next-line @stylistic/space-before-function-paren
393
429
  http.createServer(createStaticHandler(base)).listen(parseInt(port), '0.0.0.0', async () => {
394
- console.log()
395
- styledLog(`🏠 {dim}Local server:{/} {underline|http://localhost:${port}}`)
396
- styledLog(`🛜 {dim} Network :{/} {underline|http://${getLocalIP()}:${port}}`)
430
+ if (!quiet) {
431
+ console.log()
432
+ styledLog(`🏠 {dim}Local server:{/} {underline|http://localhost:${port}}`)
433
+ styledLog(`🛜 {dim} Network :{/} {underline|http://${getLocalIP()}:${port}}`)
434
+ }
397
435
  setupLiveReloadServer(config)
398
436
  })
399
437
  }