poops 1.2.4 → 1.4.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 +220 -20
- package/lib/copy.js +1 -1
- package/lib/markup/collections.js +10 -9
- package/lib/markup/engines/liquid.js +23 -10
- package/lib/markup/engines/nunjucks.js +30 -9
- package/lib/markup/helpers.js +31 -0
- package/lib/markup/indexer.js +152 -0
- package/lib/markup/renderer.js +68 -0
- package/lib/markups.js +153 -47
- package/lib/styles.js +31 -5
- package/lib/utils/helpers.js +30 -0
- package/package.json +3 -1
- package/poops.js +17 -6
package/lib/utils/helpers.js
CHANGED
|
@@ -181,3 +181,33 @@ export function doesFileBelongToPath(filePath, configPaths) {
|
|
|
181
181
|
}
|
|
182
182
|
return false
|
|
183
183
|
}
|
|
184
|
+
|
|
185
|
+
// Derive the watch list from every task's `in` path when watch is `true`.
|
|
186
|
+
// File entries (scripts/styles/reactor) resolve to their parent dir so sibling
|
|
187
|
+
// imports still retrigger a rebuild; dir entries (markup/copy/images) are
|
|
188
|
+
// watched as-is. Imports that reach outside a task's own dir aren't covered —
|
|
189
|
+
// use an explicit `watch` array for that. includePaths is skipped on purpose:
|
|
190
|
+
// it defaults to node_modules, which must never be watched.
|
|
191
|
+
export function deriveWatchDirs(config) {
|
|
192
|
+
const paths = []
|
|
193
|
+
const collect = (task) => {
|
|
194
|
+
if (!task) return
|
|
195
|
+
for (const entry of [].concat(task)) {
|
|
196
|
+
if (!entry || typeof entry !== 'object') continue
|
|
197
|
+
if (entry.in) paths.push(...(Array.isArray(entry.in) ? entry.in : [entry.in]))
|
|
198
|
+
if (entry.component) paths.push(entry.component) // reactor source component
|
|
199
|
+
const tokenPaths = entry.options && entry.options.tokenPaths
|
|
200
|
+
if (tokenPaths) paths.push(...[].concat(tokenPaths))
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
collect(config.scripts)
|
|
204
|
+
collect(config.styles)
|
|
205
|
+
collect(config.reactor)
|
|
206
|
+
collect(config.markup)
|
|
207
|
+
collect(config.copy)
|
|
208
|
+
collect(config.images)
|
|
209
|
+
// ponytail: extname()-based dir/file split misreads dot-named dirs (rare);
|
|
210
|
+
// the escape hatch is an explicit watch array.
|
|
211
|
+
return [...new Set(paths.map((p) => (path.extname(p) ? path.dirname(p) : p)))]
|
|
212
|
+
.filter((p) => p && p !== '.')
|
|
213
|
+
}
|
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.
|
|
4
|
+
"version": "1.4.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "poops.js",
|
|
@@ -62,6 +62,8 @@
|
|
|
62
62
|
"liquidjs": "^10.24.0",
|
|
63
63
|
"livereload": "^0.9.3",
|
|
64
64
|
"marked": "^9.0.3",
|
|
65
|
+
"marked-github-alerts": "^1.0.1",
|
|
66
|
+
"marked-github-emoji": "^1.0.2",
|
|
65
67
|
"nunjucks": "^3.2.4",
|
|
66
68
|
"portscanner": "^2.2.0",
|
|
67
69
|
"printstyle": "^1.0.0",
|
package/poops.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import chokidar from 'chokidar'
|
|
4
4
|
import connect from 'connect'
|
|
5
5
|
import Copy from './lib/copy.js'
|
|
6
|
-
import { pathExists, doesFileBelongToPath } from './lib/utils/helpers.js'
|
|
6
|
+
import { pathExists, doesFileBelongToPath, pathContainsPathSegment, deriveWatchDirs } from './lib/utils/helpers.js'
|
|
7
7
|
import http from 'node:http'
|
|
8
8
|
import os from 'node:os'
|
|
9
9
|
import fs from 'node:fs'
|
|
@@ -85,8 +85,6 @@ function setupLiveReloadServer(config) {
|
|
|
85
85
|
function setupWatchers(config, modules) {
|
|
86
86
|
if (!config.watch) return
|
|
87
87
|
|
|
88
|
-
// TODO: think about watching the updates of the config file itself, we can reload the config and recompile everything.
|
|
89
|
-
// TODO: ability to automatically create a watch list of directories if watch is set to true. The list will be generated from the `in` property of each task.
|
|
90
88
|
// awaitWriteFinish: wait for saves to finish writing before recompiling, so a
|
|
91
89
|
// mid-write (truncated/partial) file is never read. Fixes intermittent broken
|
|
92
90
|
// builds on editor save. Bump thresholds if slow disks flake.
|
|
@@ -95,8 +93,19 @@ function setupWatchers(config, modules) {
|
|
|
95
93
|
// rebuilds. 'add' also covers genuinely new files (e.g. a new markup page).
|
|
96
94
|
// Rebuild branches shared by change/add/deletion: a deletion needs the same
|
|
97
95
|
// rebuilds (a deleted-but-still-imported file must surface the error).
|
|
96
|
+
// Scripts/styles outputs can land inside a watched dir (e.g. a Shopify
|
|
97
|
+
// theme's assets/): the compiler's own write must not retrigger that
|
|
98
|
+
// compiler, or watch loops forever. Zones are the dirs the compilers write
|
|
99
|
+
// into; only their own extensions are skipped there, so e.g. a hand-edited
|
|
100
|
+
// .liquid asset in the same dir still rebuilds markup.
|
|
101
|
+
const outputZones = [config.scripts, config.styles].flat()
|
|
102
|
+
.filter((entry) => entry && entry.out)
|
|
103
|
+
.map((entry) => (path.extname(entry.out) ? path.dirname(entry.out) : entry.out))
|
|
104
|
+
.filter((zone) => zone && zone !== '.')
|
|
105
|
+
const isBuildOutput = (file) => outputZones.some((zone) => pathContainsPathSegment(file, zone))
|
|
106
|
+
|
|
98
107
|
const rebuild = (file) => {
|
|
99
|
-
if (/(\.m?jsx?|\.tsx?)$/i.test(file)) {
|
|
108
|
+
if (/(\.m?jsx?|\.tsx?)$/i.test(file) && !isBuildOutput(file)) {
|
|
100
109
|
modules.scripts.compile().catch(err => console.error(err))
|
|
101
110
|
|
|
102
111
|
if (modules.reactor.belongsToReactor(file)) {
|
|
@@ -108,7 +117,7 @@ function setupWatchers(config, modules) {
|
|
|
108
117
|
}).catch(err => console.error(err))
|
|
109
118
|
}
|
|
110
119
|
}
|
|
111
|
-
if (/(\.sass|\.scss|\.css)$/i.test(file)) {
|
|
120
|
+
if (/(\.sass|\.scss|\.css)$/i.test(file) && !isBuildOutput(file)) {
|
|
112
121
|
modules.styles.compile().then(() => modules.postcss.compile()).catch(err => console.error(err))
|
|
113
122
|
}
|
|
114
123
|
if (/(\.html|\.xml|\.rss|\.atom|\.njk|\.liquid|\.md)$/i.test(file)) {
|
|
@@ -240,7 +249,9 @@ if (!pathExists(configPath)) {
|
|
|
240
249
|
// Load poops.json
|
|
241
250
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'))
|
|
242
251
|
|
|
243
|
-
if (config.watch) {
|
|
252
|
+
if (config.watch === true) {
|
|
253
|
+
config.watch = deriveWatchDirs(config)
|
|
254
|
+
} else if (config.watch) {
|
|
244
255
|
config.watch = Array.isArray(config.watch) ? config.watch : [config.watch]
|
|
245
256
|
}
|
|
246
257
|
|