Skip to content

Commit 1601f70

Browse files
feat: add support for .properties files (#181)
* feat: add support for `.properties` files * feat: add tests
1 parent edadcc9 commit 1601f70

7 files changed

Lines changed: 100 additions & 0 deletions

File tree

.changeset/large-bees-pull.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@replexica/spec": minor
3+
"@replexica/cli": minor
4+
"replexica": minor
5+
---
6+
7+
Added support for .properties file

packages/cli/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"open": "^10.1.0",
3838
"ora": "^8.0.1",
3939
"p-limit": "^6.1.0",
40+
"properties-parser": "^0.6.0",
4041
"slugify": "^1.6.6",
4142
"typescript": "^5.4.5",
4243
"vitest": "^2.0.0",
@@ -53,6 +54,7 @@
5354
"@types/markdown-it": "^14.1.2",
5455
"@types/node": "^20.14.10",
5556
"@types/object-hash": "^3.0.6",
57+
"@types/properties-parser": "^0.3.3",
5658
"@types/xml2js": "^0.4.14",
5759
"tsup": "^8.1.0"
5860
}

packages/cli/src/workers/bucket/v2/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { rootKeyLoader } from './root-key';
1212
import { markdownLoader } from './markdown';
1313
import { xcodeLoader } from './xcode';
1414
import { androidLoader } from './android';
15+
import { propertiesLoader } from './properties';
1516

1617
// Path expansion
1718
export function expandPlaceholderedGlob(pathPattern: string, sourceLocale: string): string[] {
@@ -126,5 +127,11 @@ export function createBucketLoader(params: CreateBucketLoaderParams) {
126127
jsonLoader(),
127128
flatLoader(),
128129
);
130+
case 'properties':
131+
return composeLoaders<string, Record<string, string>>(
132+
textLoader(filepath),
133+
propertiesLoader(),
134+
flatLoader(),
135+
);
129136
}
130137
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { propertiesLoader } from './properties'; // Adjust the import path as needed
3+
4+
describe('propertiesLoader', () => {
5+
const loader = propertiesLoader();
6+
7+
const sampleProperties = `
8+
# General messages
9+
welcome.message=Welcome to our application!
10+
error.message=An error has occurred. Please try again later.
11+
12+
# User-related messages
13+
user.login=Please enter your username and password.
14+
user.username=Username
15+
user.password=Password
16+
`.trim();
17+
18+
it('should load properties correctly', async () => {
19+
const result = await loader.load(sampleProperties);
20+
expect(result).toEqual({
21+
'welcome.message': 'Welcome to our application!',
22+
'error.message': 'An error has occurred. Please try again later.',
23+
'user.login': 'Please enter your username and password.',
24+
'user.username': 'Username',
25+
'user.password': 'Password'
26+
});
27+
});
28+
29+
it('should save properties correctly', async () => {
30+
const input = {
31+
'app.name': 'My App',
32+
'app.version': '1.0.0',
33+
'user.greeting': 'Hello, {0}!'
34+
};
35+
36+
const result = await loader.save(input);
37+
expect(result).toContain('app.name=My App');
38+
expect(result).toContain('app.version=1.0.0');
39+
expect(result).toContain('user.greeting=Hello, {0}!');
40+
});
41+
42+
it('should handle empty input when loading', async () => {
43+
const result = await loader.load('');
44+
expect(result).toEqual({});
45+
});
46+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { parse, createEditor } from 'properties-parser';
2+
import { BucketLoader } from './_base';
3+
4+
export const propertiesLoader = (): BucketLoader<string, Record<string, string>> => ({
5+
async load(text: string) {
6+
return parse(text || '');
7+
},
8+
async save(payload) {
9+
const editor = createEditor();
10+
11+
// Update or add new key-value pairs
12+
for (const [key, value] of Object.entries(payload)) {
13+
editor.set(key, value);
14+
}
15+
16+
return editor.toString();
17+
}
18+
});

packages/spec/src/formats.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const bucketTypes = [
88
'yaml-root-key',
99
'xcode',
1010
'android',
11+
'properties',
1112
] as const;
1213

1314
export const bucketTypeSchema = Z.enum(bucketTypes);

pnpm-lock.yaml

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

0 commit comments

Comments
 (0)