Skip to content

Commit 45187b1

Browse files
committed
feat: switch to jju for automatic file generation
1 parent 7d8dd51 commit 45187b1

File tree

5 files changed

+91
-54
lines changed

5 files changed

+91
-54
lines changed

codify.json5

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@
66
}
77
},
88
{
9-
"type": "macports"
9+
type: "macports"
1010
},
1111
// This is a test comment
1212
{
13-
"type": "pnpm",
14-
"globalEnvNodeVersion": null
13+
type: "pnpm",
14+
globalEnvNodeVersion: null,
1515
},
16+
/*
17+
This is my multi-line comment
18+
*/
1619
{
17-
"type": "homebrew"
20+
type: "homebrew"
1821
}
1922
]

package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
"semver": "^7.5.4",
3434
"supports-color": "^9.4.0",
3535
"json5": "^2.2.3",
36-
"@mischnic/json-sourcemap": "^0.1.1"
36+
"@mischnic/json-sourcemap": "^0.1.1",
37+
"jju": "^1.4.0"
3738
},
3839
"description": "Codify allows users to configure settings, install new packages, and automate their systems using code instead of the GUI. Get set up on a new laptop in one click, maintain a Codify file within your project so anyone can get started and never lose your cool apps or favourite settings again.",
3940
"devDependencies": {
@@ -48,6 +49,7 @@
4849
"@types/react": "^18.3.1",
4950
"@types/semver": "^7.5.4",
5051
"@types/strip-ansi": "^5.2.1",
52+
"@types/jju": "^1.4.5",
5153
"@typescript-eslint/eslint-plugin": "^8.16.0",
5254
"@types/json5": "^2.2.0",
5355
"codify-plugin-lib": "^1.0.151",

src/utils/file-modification-calculator.test.ts

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ describe('File modification calculator tests', () => {
5454
resource: modifiedResource,
5555
}], match)
5656

57-
console.log(result)
57+
console.log(result.newFile)
5858
console.log(result.diff)
5959
})
6060

@@ -230,9 +230,9 @@ describe('File modification calculator tests', () => {
230230
' "default": "latest"\n' +
231231
' }\n' +
232232
' },\n' +
233-
' {\n' +
233+
' { \n' +
234234
' "type": "resource1",\n' +
235-
' "param2": ["a","b","c","d"]\n' +
235+
' "param2": ["a", "b", "c", "d"]\n' +
236236
' }\n' +
237237
']',)
238238
console.log(result)
@@ -311,7 +311,7 @@ describe('File modification calculator tests', () => {
311311
' "type": "resource1",\n' +
312312
' "param2": ["a", "b", "c"]\n' +
313313
' },\n' +
314-
' {\n' +
314+
' { \n' +
315315
' "type": "resource2",\n' +
316316
' "param1": false,\n' +
317317
' "param3": "this is another string"\n' +
@@ -367,12 +367,7 @@ describe('File modification calculator tests', () => {
367367
' },\n' +
368368
' {\n' +
369369
' "type": "resource1",\n' +
370-
' "param2": [\n' +
371-
' "a",\n' +
372-
' "b",\n' +
373-
' "c",\n' +
374-
' "d"\n' +
375-
' ]\n' +
370+
' "param2": ["a", "b", "c", "d"],\n' +
376371
' }\n' +
377372
']')
378373
console.log(result)
@@ -426,21 +421,11 @@ describe('File modification calculator tests', () => {
426421
' },\n' +
427422
' {\n' +
428423
' "type": "resource1",\n' +
429-
' "param2": [\n' +
430-
' "a",\n' +
431-
' "b",\n' +
432-
' "c",\n' +
433-
' "d"\n' +
434-
' ]\n' +
424+
' "param2": ["a", "b", "c", "d"],\n' +
435425
' },\n' +
436426
' {\n' +
437427
' "type": "resource2",\n' +
438-
' "param2": [\n' +
439-
' "a",\n' +
440-
' "b",\n' +
441-
' "c",\n' +
442-
' "d"\n' +
443-
' ]\n' +
428+
' "param2": ["a", "b", "c", "d"],\n' +
444429
' }\n' +
445430
']',)
446431
console.log(result)
@@ -517,6 +502,60 @@ describe('File modification calculator tests', () => {
517502
)
518503
})
519504

505+
it('Can handle comments inside a .json5 file', async () => {
506+
const existingFile =
507+
`[
508+
// I am a comment
509+
/*
510+
I am a multi-line comment
511+
*/
512+
{
513+
"type": "jenv",
514+
"add": [
515+
"system",
516+
"11",
517+
"17", // Line comment
518+
"17.0.12", // Line comment
519+
"openjdk64-11.0.24",
520+
"openjdk64-17.0.12"
521+
],
522+
"global": "17"
523+
}
524+
]
525+
`
526+
generateTestFile(existingFile, '/codify.json5');
527+
528+
const project = await CodifyParser.parse('/codify.json5')
529+
project.resourceConfigs.forEach((r) => {
530+
r.attachResourceInfo(generateResourceInfo(r.type, []))
531+
});
532+
533+
const modifiedResource = new ResourceConfig({
534+
"type": "jenv",
535+
"add": [
536+
"system",
537+
"11",
538+
"11.0",
539+
"11.0.24",
540+
"17",
541+
"17.0.12",
542+
"openjdk64-11.0.24",
543+
"openjdk64-17.0.12"
544+
],
545+
"global": "17"
546+
})
547+
modifiedResource.attachResourceInfo(generateResourceInfo('jenv'))
548+
549+
const calculator = new FileModificationCalculator(project);
550+
const result = await calculator.calculate([{
551+
modification: ModificationType.INSERT_OR_UPDATE,
552+
resource: modifiedResource,
553+
}], match)
554+
555+
console.log(result.newFile);
556+
console.log(result.diff)
557+
})
558+
520559
afterEach(() => {
521560
vi.resetAllMocks();
522561
})

src/utils/file-modification-calculator.ts

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ResourceConfig } from '../entities/resource-config.js';
22

33
import * as jsonSourceMap from 'json-source-map';
4+
import jju from 'jju'
45

56
import { FileType, InMemoryFile } from '../parser/entities.js';
67
import { SourceMap, SourceMapCache } from '../parser/source-maps.js';
@@ -80,8 +81,7 @@ export class FileModificationCalculator {
8081
}
8182

8283
// Update an existing resource
83-
newFile = this.remove(newFile, this.sourceMap, sourceIndex, isOnly);
84-
newFile = this.update(newFile, modified.resource, existing, this.sourceMap, sourceIndex, isOnly);
84+
newFile = this.update(newFile, modified.resource, existing, sourceIndex);
8585
}
8686

8787
// Insert new resources
@@ -143,9 +143,11 @@ export class FileModificationCalculator {
143143
): string {
144144
let result = file;
145145

146+
const fileStyle = jju.analyze(file);
147+
146148
for (const newResource of resources.reverse()) {
147149
const sortedResource = { ...newResource.core(true), ...this.sortKeys(newResource.parameters) }
148-
let content = JSON.stringify(sortedResource, null, 2);
150+
let content = jju.stringify(sortedResource, fileStyle as any);
149151

150152
content = content.split(/\n/).map((l) => `${this.indentString}${l}`).join('\n')
151153
content = `,\n${content}`;
@@ -162,11 +164,6 @@ export class FileModificationCalculator {
162164
sourceIndex: number,
163165
isOnly: boolean,
164166
): string {
165-
// The element being removed is the only element left,
166-
if (isOnly) {
167-
return '[]';
168-
}
169-
170167
const isLast = sourceIndex === this.totalConfigLength - 1;
171168
const isFirst = sourceIndex === 0;
172169

@@ -192,32 +189,15 @@ export class FileModificationCalculator {
192189
file: string,
193190
resource: ResourceConfig,
194191
existing: ResourceConfig,
195-
sourceMap: SourceMap,
196192
sourceIndex: number,
197-
isOnly: boolean,
198193
): string {
199194
// Updates: for now let's remove and re-add the entire object. Only two formatting availalbe either same line or multi-line
200195
const { value, valueEnd } = this.sourceMap.lookup(`/${sourceIndex}`)!;
201-
const isSameLine = value.line === valueEnd.line;
202196
const isFirst = sourceIndex === 0;
203-
204-
// We try to start deleting from the previous element to the next element if possible. This covers any spaces as well.
205-
const start = !isFirst ? this.sourceMap.lookup(`/${sourceIndex - 1}`)?.valueEnd : this.sourceMap.lookup(`/${sourceIndex}`)?.value;
206-
207197
const sortedResource = this.sortKeys(resource.raw, existing.raw);
208198

209-
let content = isSameLine
210-
? JSON.stringify(sortedResource, null, 1).replaceAll('\n', '').replaceAll(/}$/g, ' }')
211-
: JSON.stringify(sortedResource, null, this.indentString);
212-
content = this.updateParamsToOnelineIfNeeded(content, sourceMap, sourceIndex);
213-
214-
content = content.split(/\n/).map((l) => `${this.indentString}${l}`).join('\n');
215-
if (isOnly) {
216-
return `[\n${content}\n]`;
217-
}
218-
content = isFirst ? `\n${content},` : `,\n${content}`
219-
220-
return this.splice(file, start?.position!, 0, content);
199+
let content = jju.update(file.slice(value.position, valueEnd.position), sortedResource)
200+
return this.splice(file, value?.position!, valueEnd.position - value.position, content);
221201
}
222202

223203
/** Attempt to make arrays and objects oneliners if they were before. It does this by creating a new source map */

0 commit comments

Comments
 (0)