json5-manifest-sync 0.1.4 → 0.2.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/CHANGELOG.md +8 -3
- package/README.md +12 -8
- package/dist/json5-manifest-sync.d.ts +7 -10
- package/dist/json5-manifest-sync.js +49 -30
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
-
## [0.
|
|
5
|
+
## [0.2.0] - 2026-05-06
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- The default blank-comment mode is now `preserve` instead of the previous placeholder-generating behavior. Existing users who want generated blank `//` lines must now pass `--blank-comments=fill`.
|
|
6
10
|
|
|
7
11
|
### Changed
|
|
8
12
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
13
|
+
- Replaced the old blank-comment toggle with `--blank-comments=preserve|fill|remove`.
|
|
14
|
+
- Changed the default blank-comment mode to `preserve` so sync no longer introduces placeholder `//` lines unless requested.
|
|
15
|
+
- Added `--warn-blank-comments` to warn after sync when blank `//` placeholders remain.
|
|
11
16
|
|
|
12
17
|
## [0.1.3] - 2026-02-27
|
|
13
18
|
|
package/README.md
CHANGED
|
@@ -49,14 +49,16 @@ When values like `version`, `scripts`, or dependency versions change in `package
|
|
|
49
49
|
- Skips paths ignored by your root `.gitignore`
|
|
50
50
|
- For each matching `package.json5`, rewrites values from canonical `package.json` (including `version`, scripts, dependencies, and other manifest fields)
|
|
51
51
|
- Preserves/migrates mapped `//` comments for keys and supported array items
|
|
52
|
-
-
|
|
52
|
+
- Supports three blank-comment modes: `preserve`, `fill`, and `remove`
|
|
53
53
|
- Writes stable JSON5 formatting with trailing commas for cleaner diffs
|
|
54
54
|
|
|
55
55
|
### Current limitations
|
|
56
56
|
|
|
57
57
|
- Per-item comment preservation is most reliable for arrays of strings.
|
|
58
|
-
- Arrays of objects or numbers still serialize correctly, but item-level comments may be dropped
|
|
59
|
-
-
|
|
58
|
+
- Arrays of objects or numbers still serialize correctly, but item-level comments may be dropped.
|
|
59
|
+
- Use `--blank-comments=preserve` to keep existing blank `//` lines without adding new ones.
|
|
60
|
+
- Use `--blank-comments=fill` to add blank `//` placeholders where comments are omitted.
|
|
61
|
+
- Use `--blank-comments=remove` to strip blank `//` lines from the output.
|
|
60
62
|
|
|
61
63
|
Repository: https://github.com/BBaysinger/json5-manifest-sync
|
|
62
64
|
|
|
@@ -125,13 +127,15 @@ For the current full output style, see this repo's live example: [`package.json5
|
|
|
125
127
|
|
|
126
128
|
### Options
|
|
127
129
|
|
|
128
|
-
By default, the tool
|
|
130
|
+
By default, the tool runs with `--blank-comments=preserve`.
|
|
129
131
|
|
|
130
|
-
|
|
131
|
-
- `--empty-comment=false`
|
|
132
|
-
- env var: `SYNC_JSON5_ADD_EMPTY_COMMENT=false`
|
|
132
|
+
Choose a blank-comment mode with one of the following:
|
|
133
133
|
|
|
134
|
-
|
|
134
|
+
- `--blank-comments=preserve`
|
|
135
|
+
- `--blank-comments=fill`
|
|
136
|
+
- `--blank-comments=remove`
|
|
137
|
+
|
|
138
|
+
To warn after sync when blank `//` placeholders remain, add `--warn-blank-comments`. That warning applies to `preserve` and `fill`; `remove` strips those lines.
|
|
135
139
|
|
|
136
140
|
### Formatting note
|
|
137
141
|
|
|
@@ -26,21 +26,18 @@
|
|
|
26
26
|
* - Array item comment mapping is primarily intended for arrays of strings; arrays of
|
|
27
27
|
* objects/numbers will serialize correctly but per-item comment preservation is limited.
|
|
28
28
|
*/
|
|
29
|
+
export type BlankCommentMode = "preserve" | "fill" | "remove";
|
|
29
30
|
export type SyncOptions = {
|
|
30
31
|
/**
|
|
31
|
-
*
|
|
32
|
-
* preceding comment captured from the existing JSON5. This helps visually
|
|
33
|
-
* separate entries like:
|
|
32
|
+
* Controls how blank comment lines (`//`) are handled.
|
|
34
33
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
34
|
+
* - `preserve`: keep existing blank comment lines, but do not add new ones
|
|
35
|
+
* - `fill`: keep existing blank comment lines and add them where comments are omitted
|
|
36
|
+
* - `remove`: remove blank comment lines from the output
|
|
38
37
|
*
|
|
39
|
-
* Defaults to
|
|
40
|
-
* `--remove-empty-comments` or the environment variable
|
|
41
|
-
* `SYNC_JSON5_ADD_EMPTY_COMMENT=false`.
|
|
38
|
+
* Defaults to `preserve`.
|
|
42
39
|
*/
|
|
43
|
-
|
|
40
|
+
blankCommentMode?: BlankCommentMode;
|
|
44
41
|
};
|
|
45
42
|
/**
|
|
46
43
|
* Synchronizes a JSON5 file with its canonical JSON source while preserving formatting.
|
|
@@ -4,6 +4,32 @@ import path from "path";
|
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
import { sync as globSync } from "glob";
|
|
6
6
|
import ignore from "ignore";
|
|
7
|
+
function isBlankCommentLine(line) {
|
|
8
|
+
return /^\s*\/\/\s*$/.test(line);
|
|
9
|
+
}
|
|
10
|
+
function normalizePrecedingComments(preceding, blankCommentMode) {
|
|
11
|
+
const comments = preceding ?? [];
|
|
12
|
+
if (blankCommentMode !== "remove") {
|
|
13
|
+
return comments;
|
|
14
|
+
}
|
|
15
|
+
return comments.filter((line) => !isBlankCommentLine(line));
|
|
16
|
+
}
|
|
17
|
+
function collectBlankCommentLineNumbers(raw) {
|
|
18
|
+
return raw
|
|
19
|
+
.split("\n")
|
|
20
|
+
.map((line, index) => ({ line, lineNumber: index + 1 }))
|
|
21
|
+
.filter(({ line }) => isBlankCommentLine(line))
|
|
22
|
+
.map(({ lineNumber }) => lineNumber);
|
|
23
|
+
}
|
|
24
|
+
function warnAboutBlankComments(filePath, blankCommentLines) {
|
|
25
|
+
if (blankCommentLines.length === 0) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const preview = blankCommentLines.slice(0, 8).join(", ");
|
|
29
|
+
const remainder = blankCommentLines.length > 8 ? ", ..." : "";
|
|
30
|
+
const plural = blankCommentLines.length === 1 ? "placeholder" : "placeholders";
|
|
31
|
+
console.warn(`[warn:blank-comments] ${path.basename(filePath)} contains ${blankCommentLines.length} blank comment ${plural} at line${blankCommentLines.length === 1 ? "" : "s"} ${preview}${remainder}. Fill them in with real notes, or rerun with --blank-comments=remove if you do not want placeholders.`);
|
|
32
|
+
}
|
|
7
33
|
/**
|
|
8
34
|
* Quotes an object key for consistent JSON5 formatting.
|
|
9
35
|
* Always returns a quoted key to maintain consistency across all properties.
|
|
@@ -202,12 +228,10 @@ function generateScriptComment() {
|
|
|
202
228
|
* @param source - Parsed JSON object from the canonical package.json
|
|
203
229
|
* @returns The updated JSON5 content as a formatted string
|
|
204
230
|
*/
|
|
205
|
-
export function syncJson5(raw, source, options = {
|
|
231
|
+
export function syncJson5(raw, source, options = { blankCommentMode: "preserve" }) {
|
|
206
232
|
const lines = raw.split("\n");
|
|
207
233
|
const comments = buildCommentMap(lines);
|
|
208
|
-
const
|
|
209
|
-
? options.addEmptyCommentIfMissing
|
|
210
|
-
: true;
|
|
234
|
+
const blankCommentMode = options.blankCommentMode ?? "preserve";
|
|
211
235
|
/**
|
|
212
236
|
* Recursively writes an object in normalized JSON5 style with mapped comments.
|
|
213
237
|
*
|
|
@@ -230,13 +254,14 @@ export function syncJson5(raw, source, options = { addEmptyCommentIfMissing: tru
|
|
|
230
254
|
const val = obj[key];
|
|
231
255
|
const comma = ","; // Always add trailing comma for version control benefits
|
|
232
256
|
const commentInfo = comments[fullPath];
|
|
257
|
+
const precedingComments = normalizePrecedingComments(commentInfo?.preceding, blankCommentMode);
|
|
233
258
|
// Add any preceding comments above this key
|
|
234
|
-
if (
|
|
235
|
-
for (const c of
|
|
259
|
+
if (precedingComments.length > 0) {
|
|
260
|
+
for (const c of precedingComments) {
|
|
236
261
|
result.push(indent(c, level));
|
|
237
262
|
}
|
|
238
263
|
}
|
|
239
|
-
else if (
|
|
264
|
+
else if (blankCommentMode === "fill" &&
|
|
240
265
|
!comments.hasOwnProperty(fullPath)) {
|
|
241
266
|
// No preceding comment captured — optionally add a blank one for spacing
|
|
242
267
|
// Applies to any section, not just scripts
|
|
@@ -265,13 +290,14 @@ export function syncJson5(raw, source, options = { addEmptyCommentIfMissing: tru
|
|
|
265
290
|
for (let j = 0; j < val.length; j++) {
|
|
266
291
|
const itemPath = [...path, key, j.toString()].join(".");
|
|
267
292
|
const itemCommentInfo = comments[itemPath];
|
|
293
|
+
const itemPrecedingComments = normalizePrecedingComments(itemCommentInfo?.preceding, blankCommentMode);
|
|
268
294
|
// Add preceding comments for this array item
|
|
269
|
-
if (
|
|
270
|
-
for (const c of
|
|
295
|
+
if (itemPrecedingComments.length > 0) {
|
|
296
|
+
for (const c of itemPrecedingComments) {
|
|
271
297
|
result.push(indent(c, level + indentSize));
|
|
272
298
|
}
|
|
273
299
|
}
|
|
274
|
-
else if (
|
|
300
|
+
else if (blankCommentMode === "fill" &&
|
|
275
301
|
!comments.hasOwnProperty(itemPath)) {
|
|
276
302
|
const autoComment = generateScriptComment();
|
|
277
303
|
result.push(indent(autoComment, level + indentSize));
|
|
@@ -329,29 +355,19 @@ export function runCli(args = process.argv.slice(2)) {
|
|
|
329
355
|
ignore: ["**/node_modules/**"],
|
|
330
356
|
absolute: true,
|
|
331
357
|
});
|
|
332
|
-
// Parse
|
|
333
|
-
let
|
|
334
|
-
|
|
335
|
-
if (typeof process.env.SYNC_JSON5_ADD_EMPTY_COMMENT === "string" &&
|
|
336
|
-
process.env.SYNC_JSON5_ADD_EMPTY_COMMENT.toLowerCase() === "false") {
|
|
337
|
-
addEmptyCommentIfMissing = false;
|
|
338
|
-
}
|
|
339
|
-
// CLI toggles: --remove-empty-comments, --remove-blank-comments
|
|
358
|
+
// Parse CLI flags for options
|
|
359
|
+
let blankCommentMode = "preserve";
|
|
360
|
+
let warnOnBlankComments = false;
|
|
340
361
|
for (const arg of args) {
|
|
341
|
-
if (arg
|
|
342
|
-
arg === "--remove-empty-comments" ||
|
|
343
|
-
arg === "--remove-blank-comment" ||
|
|
344
|
-
arg === "--remove-blank-comments" ||
|
|
345
|
-
arg === "--no-empty-comment" ||
|
|
346
|
-
arg === "--no-empty-comments") {
|
|
347
|
-
addEmptyCommentIfMissing = false;
|
|
348
|
-
}
|
|
349
|
-
else if (arg.startsWith("--empty-comment=")) {
|
|
362
|
+
if (arg.startsWith("--blank-comments=")) {
|
|
350
363
|
const v = arg.split("=", 2)[1]?.toLowerCase();
|
|
351
|
-
if (v === "
|
|
352
|
-
|
|
364
|
+
if (v === "preserve" || v === "fill" || v === "remove") {
|
|
365
|
+
blankCommentMode = v;
|
|
353
366
|
}
|
|
354
367
|
}
|
|
368
|
+
else if (arg === "--warn-blank-comments") {
|
|
369
|
+
warnOnBlankComments = true;
|
|
370
|
+
}
|
|
355
371
|
}
|
|
356
372
|
// Process each package.json to sync with its package.json5 counterpart
|
|
357
373
|
for (const packageJsonPath of packageJsonPaths) {
|
|
@@ -369,11 +385,14 @@ export function runCli(args = process.argv.slice(2)) {
|
|
|
369
385
|
const rawJson5 = fs.readFileSync(json5Path, "utf8");
|
|
370
386
|
const sourceJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
371
387
|
const updated = syncJson5(rawJson5, sourceJson, {
|
|
372
|
-
|
|
388
|
+
blankCommentMode,
|
|
373
389
|
});
|
|
374
390
|
// Write the synchronized result
|
|
375
391
|
fs.writeFileSync(json5Path, updated);
|
|
376
392
|
console.info(`✅ Synced ${relPath} → ${path.basename(json5Path)}`);
|
|
393
|
+
if (warnOnBlankComments && blankCommentMode !== "remove") {
|
|
394
|
+
warnAboutBlankComments(json5Path, collectBlankCommentLineNumbers(updated));
|
|
395
|
+
}
|
|
377
396
|
}
|
|
378
397
|
}
|
|
379
398
|
/**
|