properties-file 2.1.32 → 2.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/README.md +35 -2
- package/lib/escape/index.d.ts +18 -0
- package/lib/escape/index.js +96 -0
- package/lib/property.d.ts +4 -1
- package/lib/property.js +13 -56
- package/lib/unescape/index.d.ts +11 -0
- package/lib/unescape/index.js +69 -0
- package/package.json +10 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|

|
|
7
7
|
[](https://snyk.io/test/github/Avansai/properties-file?targetFile=package.json)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
`.properties` JSON converter, file parser and Webpack loader.
|
|
10
10
|
|
|
11
11
|
## Installation 💻
|
|
12
12
|
|
|
@@ -25,6 +25,7 @@ npm install properties-file
|
|
|
25
25
|
- `propertiesToJson` allows quick conversion from `.properties` files to JSON.
|
|
26
26
|
- `getProperties` returns a `Properties` object that provides insights into parsing issues such as key collisions.
|
|
27
27
|
- `propertiesToJson` & `getProperties` also have a browser-compatible version when passing directly the content of a file using the APIs under `properties-file/content`.
|
|
28
|
+
- `escapeKey`, `escapeValue` that can allow you to convert any content to `.properties` compatible format.
|
|
28
29
|
- Out of the box Webpack loader to `import` `.properties` files directly in your application.
|
|
29
30
|
- 100% test coverage based on the output from a Java implementation.
|
|
30
31
|
- Active maintenance (many popular .properties packages have been inactive years).
|
|
@@ -35,7 +36,7 @@ We put a lot of effort into adding [TSDoc](https://tsdoc.org/) to all our APIs.
|
|
|
35
36
|
|
|
36
37
|
Both APIs (`getProperties` and `propertiesToJson`) directly under `properties-file` depend on [`fs`](https://nodejs.org/api/fs.html) which means they cannot be used by browsers. If you cannot use `fs` and already have a `.properties` file content, the same APIs are available under `properties-file/content`. Instead of taking the `filePath` as the first argument, they take `content`. The example below will use "`fs`" APIs since they are the most common use cases.
|
|
37
38
|
|
|
38
|
-
### `propertiesToJson`
|
|
39
|
+
### `propertiesToJson` (common use case)
|
|
39
40
|
|
|
40
41
|
This API is probably the most used. You have a `.properties` file that you want to open and access like a simple key/value JSON object. Here is how this can be done with a single API call:
|
|
41
42
|
|
|
@@ -61,6 +62,38 @@ import { propertiesToJson } from 'properties-file/content'
|
|
|
61
62
|
console.log(propertiesToJson(propertiesFileContent))
|
|
62
63
|
```
|
|
63
64
|
|
|
65
|
+
### `escapeKey` and `escapeValue` (converting content to `.properties` format)
|
|
66
|
+
|
|
67
|
+
> ⚠ This package does not offer full-fledged `.properties` file writer that would include a variety of options like modifying an existing file while keeping comments and line breaks intact. If you have any interest into adding this in, pull requests are welcomed!
|
|
68
|
+
|
|
69
|
+
It is possible to use this package to do basic conversion between key/value content into `.properties.` compatible format by using `escapeKey` and `escapeValue`. Here is an example of how it can be done:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import * as fs from 'node:fs'
|
|
73
|
+
import { EOL } from 'node:os'
|
|
74
|
+
import { getProperties } from 'properties-file'
|
|
75
|
+
import { escapeKey, escapeValue } from 'properties-file/escape'
|
|
76
|
+
|
|
77
|
+
const properties = getProperties('assets/tests/collisions-test.properties')
|
|
78
|
+
const newProperties: string[] = []
|
|
79
|
+
console.dir(properties)
|
|
80
|
+
|
|
81
|
+
properties.collection.forEach((property) => {
|
|
82
|
+
const value = property.value === 'world3' ? 'new world3' : property.value
|
|
83
|
+
newProperties.push(`${escapeKey(property.key)}: ${escapeValue(value)}`)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
fs.writeFileSync('myNewFile.properties', newProperties.join(EOL))
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Outputs:
|
|
90
|
+
*
|
|
91
|
+
* hello: hello2
|
|
92
|
+
* world: new world3
|
|
93
|
+
*
|
|
94
|
+
*/
|
|
95
|
+
```
|
|
96
|
+
|
|
64
97
|
### `getProperties` (advanced use case)
|
|
65
98
|
|
|
66
99
|
Java's implementation of `Properties` is quite resilient. In fact, there are only two ways an exception can be thrown:
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Escape a property key.
|
|
3
|
+
*
|
|
4
|
+
* @param unescapedKey - A property key to be escaped.
|
|
5
|
+
* @param escapeUnicode - Escape unicode characters into ISO-8859-1 compatible encoding?
|
|
6
|
+
*
|
|
7
|
+
* @return The escaped key.
|
|
8
|
+
*/
|
|
9
|
+
export declare const escapeKey: (unescapedKey: string, escapeUnicode?: boolean) => string;
|
|
10
|
+
/**
|
|
11
|
+
* Escape property value.
|
|
12
|
+
*
|
|
13
|
+
* @param unescapedValue - Property value to be escaped.
|
|
14
|
+
* @param escapeUnicode - Escape unicode characters into ISO-8859-1 compatible encoding?
|
|
15
|
+
*
|
|
16
|
+
* @return The escaped value.
|
|
17
|
+
*/
|
|
18
|
+
export declare const escapeValue: (unescapedValue: string, escapeUnicode?: boolean) => string;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.escapeValue = exports.escapeKey = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Escape a property key.
|
|
6
|
+
*
|
|
7
|
+
* @param unescapedKey - A property key to be escaped.
|
|
8
|
+
* @param escapeUnicode - Escape unicode characters into ISO-8859-1 compatible encoding?
|
|
9
|
+
*
|
|
10
|
+
* @return The escaped key.
|
|
11
|
+
*/
|
|
12
|
+
var escapeKey = function (unescapedKey, escapeUnicode) {
|
|
13
|
+
if (escapeUnicode === void 0) { escapeUnicode = false; }
|
|
14
|
+
return escapeContent(unescapedKey, true, escapeUnicode);
|
|
15
|
+
};
|
|
16
|
+
exports.escapeKey = escapeKey;
|
|
17
|
+
/**
|
|
18
|
+
* Escape property value.
|
|
19
|
+
*
|
|
20
|
+
* @param unescapedValue - Property value to be escaped.
|
|
21
|
+
* @param escapeUnicode - Escape unicode characters into ISO-8859-1 compatible encoding?
|
|
22
|
+
*
|
|
23
|
+
* @return The escaped value.
|
|
24
|
+
*/
|
|
25
|
+
var escapeValue = function (unescapedValue, escapeUnicode) {
|
|
26
|
+
if (escapeUnicode === void 0) { escapeUnicode = false; }
|
|
27
|
+
return escapeContent(unescapedValue, false, escapeUnicode);
|
|
28
|
+
};
|
|
29
|
+
exports.escapeValue = escapeValue;
|
|
30
|
+
/**
|
|
31
|
+
* Escape the content from either key or value of a property.
|
|
32
|
+
*
|
|
33
|
+
* @param unescapedContent - The content to escape.
|
|
34
|
+
* @param escapeSpace - Escape spaces?
|
|
35
|
+
* @param escapeUnicode - Escape unicode characters into ISO-8859-1 compatible encoding?
|
|
36
|
+
*
|
|
37
|
+
* @returns The unescaped content.
|
|
38
|
+
*/
|
|
39
|
+
var escapeContent = function (unescapedContent, escapeSpace, escapeUnicode) {
|
|
40
|
+
var escapedContent = '';
|
|
41
|
+
for (var character = unescapedContent[0], position = 0; position < unescapedContent.length; position++, character = unescapedContent[position]) {
|
|
42
|
+
switch (character) {
|
|
43
|
+
case ' ': {
|
|
44
|
+
// Escape space if required, or if it is first character.
|
|
45
|
+
escapedContent += escapeSpace || position === 0 ? '\\ ' : ' ';
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
// Backslash.
|
|
49
|
+
case '\\': {
|
|
50
|
+
escapedContent += '\\\\';
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case '\f': {
|
|
54
|
+
// Formfeed.
|
|
55
|
+
escapedContent += '\\f';
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
case '\n': {
|
|
59
|
+
// Newline.
|
|
60
|
+
escapedContent += '\\n';
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case '\r': {
|
|
64
|
+
// Carriage return.
|
|
65
|
+
escapedContent += '\\r';
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case '\t': {
|
|
69
|
+
// Tab.
|
|
70
|
+
escapedContent += '\\t';
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case '=':
|
|
74
|
+
case ':':
|
|
75
|
+
case '#':
|
|
76
|
+
case '!': {
|
|
77
|
+
// Escapes =, :, # and !.
|
|
78
|
+
escapedContent += "\\".concat(character);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
default: {
|
|
82
|
+
if (escapeUnicode) {
|
|
83
|
+
var codePoint = character.codePointAt(0); // Can never be `undefined`.
|
|
84
|
+
if (codePoint < 0x0020 || codePoint > 0x007e) {
|
|
85
|
+
escapedContent += "\\u".concat(codePoint.toString(16).padStart(4, '0'));
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Non-escapable characters.
|
|
90
|
+
escapedContent += character;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return escapedContent;
|
|
96
|
+
};
|
package/lib/property.d.ts
CHANGED
|
@@ -55,8 +55,11 @@ export declare class Property {
|
|
|
55
55
|
* @param startingLineNumber - The starting line number of the content being unescaped.
|
|
56
56
|
*
|
|
57
57
|
* @returns The unescaped content.
|
|
58
|
+
*
|
|
59
|
+
* @throws {@link Error}
|
|
60
|
+
* This exception is thrown if malformed escaped unicode characters are present.
|
|
58
61
|
*/
|
|
59
|
-
|
|
62
|
+
private unescapeLine;
|
|
60
63
|
/**
|
|
61
64
|
* Find the delimiting characters separating the key from the value.
|
|
62
65
|
*/
|
package/lib/property.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Property = void 0;
|
|
4
|
+
var unescape_1 = require("./unescape");
|
|
4
5
|
/**
|
|
5
6
|
* Object representing a property (key/value).
|
|
6
7
|
*/
|
|
@@ -55,18 +56,18 @@ var Property = /** @class */ (function () {
|
|
|
55
56
|
// Set key if present.
|
|
56
57
|
if (!this.hasNoKey) {
|
|
57
58
|
this.escapedKey = this.linesContent.slice(0, this.delimiterPosition);
|
|
58
|
-
this.key = this.
|
|
59
|
+
this.key = this.unescapeLine(this.escapedKey, this.startingLineNumber);
|
|
59
60
|
}
|
|
60
61
|
// Set value if present.
|
|
61
62
|
if (!this.hasNoValue) {
|
|
62
63
|
this.escapedValue = this.linesContent.slice(this.delimiterPosition + this.delimiterLength);
|
|
63
|
-
this.value = this.
|
|
64
|
+
this.value = this.unescapeLine(this.escapedValue, this.startingLineNumber);
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
else if (this.hasNoValue) {
|
|
67
68
|
// Set key if present (no delimiter).
|
|
68
69
|
this.escapedKey = this.linesContent;
|
|
69
|
-
this.key = this.
|
|
70
|
+
this.key = this.unescapeLine(this.escapedKey, this.startingLineNumber);
|
|
70
71
|
}
|
|
71
72
|
};
|
|
72
73
|
/**
|
|
@@ -76,61 +77,17 @@ var Property = /** @class */ (function () {
|
|
|
76
77
|
* @param startingLineNumber - The starting line number of the content being unescaped.
|
|
77
78
|
*
|
|
78
79
|
* @returns The unescaped content.
|
|
80
|
+
*
|
|
81
|
+
* @throws {@link Error}
|
|
82
|
+
* This exception is thrown if malformed escaped unicode characters are present.
|
|
79
83
|
*/
|
|
80
|
-
Property.prototype.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
case 'f': {
|
|
87
|
-
// Formfeed/
|
|
88
|
-
unescapedContent += '\f';
|
|
89
|
-
position++;
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
case 'n': {
|
|
93
|
-
// Newline.
|
|
94
|
-
unescapedContent += '\n';
|
|
95
|
-
position++;
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
case 'r': {
|
|
99
|
-
// Carriage return.
|
|
100
|
-
unescapedContent += '\r';
|
|
101
|
-
position++;
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
case 't': {
|
|
105
|
-
// Tab.
|
|
106
|
-
unescapedContent += '\t';
|
|
107
|
-
position++;
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
case 'u': {
|
|
111
|
-
// Unicode character.
|
|
112
|
-
var codePoint = escapedContent.slice(position + 2, position + 6);
|
|
113
|
-
if (!/[\da-f]{4}/i.test(codePoint)) {
|
|
114
|
-
// Code point can only be within Unicode's Multilingual Plane (BMP).
|
|
115
|
-
throw new Error("malformed escaped unicode characters '\\u".concat(codePoint, "' in property starting at line ").concat(startingLineNumber));
|
|
116
|
-
}
|
|
117
|
-
unescapedContent += String.fromCodePoint(Number.parseInt(codePoint, 16));
|
|
118
|
-
position += 5;
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
121
|
-
default: {
|
|
122
|
-
// Otherwise the escape character is not required.
|
|
123
|
-
unescapedContent += nextCharacter;
|
|
124
|
-
position++;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
// When there is \, simply add the character.
|
|
130
|
-
unescapedContent += character;
|
|
131
|
-
}
|
|
84
|
+
Property.prototype.unescapeLine = function (escapedContent, startingLineNumber) {
|
|
85
|
+
try {
|
|
86
|
+
return (0, unescape_1.unescapeContent)(escapedContent);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
throw new Error("".concat(error.message, " in property starting at line ").concat(startingLineNumber));
|
|
132
90
|
}
|
|
133
|
-
return unescapedContent;
|
|
134
91
|
};
|
|
135
92
|
/**
|
|
136
93
|
* Find the delimiting characters separating the key from the value.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unescape the content from either key or value of a property.
|
|
3
|
+
*
|
|
4
|
+
* @param escapedContent - The content to unescape.
|
|
5
|
+
*
|
|
6
|
+
* @returns The unescaped content.
|
|
7
|
+
*
|
|
8
|
+
* @throws {@link Error}
|
|
9
|
+
* This exception is thrown if malformed escaped unicode characters are present.
|
|
10
|
+
*/
|
|
11
|
+
export declare const unescapeContent: (escapedContent: string) => string;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.unescapeContent = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Unescape the content from either key or value of a property.
|
|
6
|
+
*
|
|
7
|
+
* @param escapedContent - The content to unescape.
|
|
8
|
+
*
|
|
9
|
+
* @returns The unescaped content.
|
|
10
|
+
*
|
|
11
|
+
* @throws {@link Error}
|
|
12
|
+
* This exception is thrown if malformed escaped unicode characters are present.
|
|
13
|
+
*/
|
|
14
|
+
var unescapeContent = function (escapedContent) {
|
|
15
|
+
var unescapedContent = '';
|
|
16
|
+
for (var character = escapedContent[0], position = 0; position < escapedContent.length; position++, character = escapedContent[position]) {
|
|
17
|
+
if (character === '\\') {
|
|
18
|
+
var nextCharacter = escapedContent[position + 1];
|
|
19
|
+
switch (nextCharacter) {
|
|
20
|
+
case 'f': {
|
|
21
|
+
// Formfeed.
|
|
22
|
+
unescapedContent += '\f';
|
|
23
|
+
position++;
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
case 'n': {
|
|
27
|
+
// Newline.
|
|
28
|
+
unescapedContent += '\n';
|
|
29
|
+
position++;
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
case 'r': {
|
|
33
|
+
// Carriage return.
|
|
34
|
+
unescapedContent += '\r';
|
|
35
|
+
position++;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
case 't': {
|
|
39
|
+
// Tab.
|
|
40
|
+
unescapedContent += '\t';
|
|
41
|
+
position++;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
case 'u': {
|
|
45
|
+
// Unicode character.
|
|
46
|
+
var codePoint = escapedContent.slice(position + 2, position + 6);
|
|
47
|
+
if (!/[\da-f]{4}/i.test(codePoint)) {
|
|
48
|
+
// Code point can only be within Unicode's Multilingual Plane (BMP).
|
|
49
|
+
throw new Error("malformed escaped unicode characters '\\u".concat(codePoint, "'"));
|
|
50
|
+
}
|
|
51
|
+
unescapedContent += String.fromCodePoint(Number.parseInt(codePoint, 16));
|
|
52
|
+
position += 5;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
default: {
|
|
56
|
+
// Otherwise the escape character is not required.
|
|
57
|
+
unescapedContent += nextCharacter;
|
|
58
|
+
position++;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// When there is \, simply add the character.
|
|
64
|
+
unescapedContent += character;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return unescapedContent;
|
|
68
|
+
};
|
|
69
|
+
exports.unescapeContent = unescapeContent;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "properties-file",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": ".properties file parser, JSON converter and Webpack loader.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
".properties",
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
"exports": {
|
|
25
25
|
".": "./lib/index.js",
|
|
26
26
|
"./content": "./lib/content/index.js",
|
|
27
|
+
"./escape": "./lib/escape/index.js",
|
|
28
|
+
"./unescape": "./lib/unescape/index.js",
|
|
27
29
|
"./webpack-loader": "./lib/loader/webpack.js"
|
|
28
30
|
},
|
|
29
31
|
"main": "lib/index.js",
|
|
@@ -33,6 +35,12 @@
|
|
|
33
35
|
"content": [
|
|
34
36
|
"lib/content/index.d.ts"
|
|
35
37
|
],
|
|
38
|
+
"escape": [
|
|
39
|
+
"lib/escape/index.d.ts"
|
|
40
|
+
],
|
|
41
|
+
"unescape": [
|
|
42
|
+
"lib/unescape/index.d.ts"
|
|
43
|
+
],
|
|
36
44
|
"webpack-loader": [
|
|
37
45
|
"lib/loader/webpack.d.ts"
|
|
38
46
|
]
|
|
@@ -44,6 +52,7 @@
|
|
|
44
52
|
"scripts": {
|
|
45
53
|
"add-import-type": "node ./src/add-import-type.mjs",
|
|
46
54
|
"build": "npm run prettier && npm run lint-fix && rm -Rf ./lib && tsc && npm run add-import-type && npm run test",
|
|
55
|
+
"ci": "npm run lint-check && rm -Rf ./lib && tsc && npm run add-import-type && npm run test",
|
|
47
56
|
"lint-check": "eslint --ext .js --ext .jsx --ext .ts --ext .tsx --ext .json .",
|
|
48
57
|
"lint-fix": "eslint --ext .js --ext .jsx --ext .ts --ext .tsx --ext .json --fix .",
|
|
49
58
|
"lint-print-config": "eslint --print-config ./eslintrc.yaml",
|