Skip to content

Commit 316c671

Browse files
committed
Add stringify function (convert js object to java properties string)
1 parent da3b66a commit 316c671

2 files changed

Lines changed: 56 additions & 8 deletions

File tree

src/java-props.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {convertLine, LineReader} from './utils';
1+
import {decodeLine, encodeLine, LineReader} from './utils';
22

33
export interface Properties {
44
[key: string]: string;
@@ -45,13 +45,24 @@ export function parse(str: string): Properties {
4545
valueStart++;
4646
}
4747

48-
const key = convertLine(line.substring(0, keyLen));
49-
const value = convertLine(line.substring(valueStart));
48+
const key = decodeLine(line.substring(0, keyLen));
49+
const value = decodeLine(line.substring(valueStart));
5050
result[key] = value;
5151
}
5252
return result;
5353
}
5454

55+
export function stringify(props: Properties): string { // TODO: Add unit-tests
56+
let str = '';
57+
for (const key in props) {
58+
if (Object.prototype.hasOwnProperty.call(props, key)) {
59+
const value = props[key];
60+
str += encodeLine(key, true) + ': ' + encodeLine(value) + '\n';
61+
}
62+
}
63+
return str;
64+
}
65+
5566
export default {
5667
parse,
5768
};

src/utils.ts

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
const CONVERT_RXP = /(?:\\u(.{0,4})|\\(.?))/g;
2-
const UNICODE_RXP = /^[0-9a-fA-F]{4}$/;
1+
const DECODE_PATTERN = /(?:\\u(.{0,4})|\\(.?))/g;
2+
const UNICODE_PATTERN = /^[0-9a-fA-F]{4}$/;
33

4-
export function convertLine(line: string): string {
5-
return line.replace(CONVERT_RXP, (_, unicode, char) => {
4+
const ENCODE_PATTERN = /(?:[\u0000-\u001F\\\u007F-\uFFFF])/g;
5+
const ENCODE_KEY_PATTERN = /(?:[\u0000-\u0020!#:=\\\u007F-\uFFFF])/g; // ENCODE_PATTERN with separators + comments
6+
7+
export function decodeLine(line: string): string {
8+
return line.replace(DECODE_PATTERN, (_, unicode, char) => {
69
if (unicode !== undefined) {
7-
if (!unicode.match(UNICODE_RXP)) {
10+
if (!unicode.match(UNICODE_PATTERN)) {
811
throw new Error('Malformed \\uxxxx encoding.');
912
}
1013
const charVal = parseInt(unicode, 16);
@@ -23,6 +26,40 @@ export function convertLine(line: string): string {
2326
});
2427
}
2528

29+
export function encodeLine(line: string, isKey?: boolean): string {
30+
line = line.replace(isKey ? ENCODE_KEY_PATTERN : ENCODE_PATTERN, (c) => {
31+
if (c === '\t') {
32+
return '\\t';
33+
} else if (c === '\r') {
34+
return '\\r';
35+
} else if (c === '\n') {
36+
return '\\n';
37+
} else if (c === '\f') {
38+
return '\\f';
39+
} else if (c >= ' ' && c <= '~') {
40+
return '\\' + c;
41+
} else {
42+
const code = c.charCodeAt(0);
43+
if (code < 16) return '\\u000' + code.toString(16).toUpperCase();
44+
if (code < 256) return '\\u00' + code.toString(16).toUpperCase();
45+
if (code < 4096) return '\\u0' + code.toString(16).toUpperCase();
46+
return '\\u' + code.toString(16).toUpperCase();
47+
}
48+
});
49+
if (!isKey) {
50+
const c = line.charAt(0);
51+
if (c === ' ' || c === '\t' || c === '\f') {
52+
line = '\\' + line;
53+
}
54+
}
55+
return line;
56+
}
57+
58+
/**
59+
* @deprecated Use {@link #decodeLine}.
60+
*/
61+
export const convertLine = decodeLine;
62+
2663
export class LineReader {
2764
private readonly str: string;
2865
private readonly strLen: number;

0 commit comments

Comments
 (0)