properties-file 2.1.1 → 2.1.4
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/LICENSE +21 -21
- package/README.md +215 -215
- package/lib/content/index.d.ts +18 -18
- package/lib/content/index.js +61 -61
- package/lib/file/index.d.ts +21 -21
- package/lib/file/index.js +32 -32
- package/lib/index.d.ts +10 -10
- package/lib/index.js +12 -12
- package/lib/loader/webpack.d.ts +8 -8
- package/lib/loader/webpack.js +14 -14
- package/lib/properties-file.d.ts +7 -7
- package/lib/properties.d.ts +55 -55
- package/lib/properties.js +91 -91
- package/lib/property-line.d.ts +22 -22
- package/lib/property-line.js +48 -48
- package/lib/property.d.ts +64 -64
- package/lib/property.js +205 -205
- package/package.json +80 -80
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2022 Avansai
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Avansai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,215 +1,215 @@
|
|
|
1
|
-
# properties-file
|
|
2
|
-
|
|
3
|
-
[](https://opensource.org/licenses/MIT)
|
|
4
|
-
[](https://www.npmjs.com/package/properties-file)
|
|
5
|
-

|
|
6
|
-

|
|
7
|
-
[](https://snyk.io/test/github/Avansai/properties-file?targetFile=package.json)
|
|
8
|
-
|
|
9
|
-
.properties file parser, JSON converter and Webpack loader.
|
|
10
|
-
|
|
11
|
-
## Installation 💻
|
|
12
|
-
|
|
13
|
-
> ⚠ in June 2022 we have released version 2 of this package which is not compatible with the previous versions. Make sure to read the documentation before upgrading.
|
|
14
|
-
|
|
15
|
-
Add the package as a dependency:
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
npm install properties-file
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## What's in it for me? 🤔
|
|
22
|
-
|
|
23
|
-
- A modern TypeScript library that reproduces exactly the [Properties Java implementation](/assets/java-implementation.md).
|
|
24
|
-
- Flexible APIs:
|
|
25
|
-
- `propertiesToJson` allows quick conversion from `.properties` files to JSON.
|
|
26
|
-
- `getProperties` returns a `Properties` object that allows insights into parsing issues such as key collisions.
|
|
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
|
-
- Out of the box Webpack loader to `import` `.properties` files directly in your application.
|
|
29
|
-
- 100% test coverage based on the output from a Java implementation.
|
|
30
|
-
- Active maintenance (many popular .properties packages have been inactive years).
|
|
31
|
-
|
|
32
|
-
## Usage 🎬
|
|
33
|
-
|
|
34
|
-
We put a lot of effort into adding [TSDoc](https://tsdoc.org/) to all our APIs. Please check directly in your IDE if you are unsure how to use certain APIs provided in our examples.
|
|
35
|
-
|
|
36
|
-
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
|
-
### `propertiesToJson`
|
|
39
|
-
|
|
40
|
-
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
|
-
```ts
|
|
43
|
-
import { propertiesToJson } from 'properties-file'
|
|
44
|
-
|
|
45
|
-
console.log(propertiesToJson('hello-world.properties'))
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Output:
|
|
49
|
-
|
|
50
|
-
```js
|
|
51
|
-
{ hello: 'hello', world: 'world' }
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
If you cannot use `fs` and already have the content of a `.properties` file, your code would look like this instead:
|
|
55
|
-
|
|
56
|
-
```ts
|
|
57
|
-
import { propertiesToJson } from 'properties-file/content'
|
|
58
|
-
|
|
59
|
-
// ...some code to get the .properties file content into a variable called `propertiesFileContent`
|
|
60
|
-
|
|
61
|
-
console.log(propertiesToJson(propertiesFileContent))
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### `getProperties` (advanced use case)
|
|
65
|
-
|
|
66
|
-
Java's implementation of `Properties` is quite resilient. In fact, there are only two ways an exception can be thrown:
|
|
67
|
-
|
|
68
|
-
- The file is not found.
|
|
69
|
-
- A (`\u`) Unicode escape character is malformed.
|
|
70
|
-
|
|
71
|
-
This means that almost all files will be valid.
|
|
72
|
-
|
|
73
|
-
But what about a file that has duplicate keys? Duplicate keys have no reason to exist and they probably should have thrown errors as well but instead Java decided to simply overwrite the value with the latest occurrence in a file.
|
|
74
|
-
|
|
75
|
-
So how can we know if there were duplicate keys if we want to log some warnings? Simply by using `getProperties` which will return all the data that was used to parse the content. Here is an example on how it can be used:
|
|
76
|
-
|
|
77
|
-
```properties
|
|
78
|
-
# collisions-test.properties
|
|
79
|
-
hello: hello1
|
|
80
|
-
world: world1
|
|
81
|
-
world: world2
|
|
82
|
-
hello: hello2
|
|
83
|
-
world: world3
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
```ts
|
|
87
|
-
import { getProperties } from 'properties-file'
|
|
88
|
-
|
|
89
|
-
const properties = getProperties('assets/tests/collisions-test.properties')
|
|
90
|
-
|
|
91
|
-
properties.collection.forEach((property) => {
|
|
92
|
-
console.log(`${property.key} => '${property.value}'`)
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Outputs:
|
|
97
|
-
*
|
|
98
|
-
* hello => 'hello2'
|
|
99
|
-
* world => 'world3'
|
|
100
|
-
*
|
|
101
|
-
*/
|
|
102
|
-
|
|
103
|
-
const keyCollisions = properties.getKeyCollisions()
|
|
104
|
-
|
|
105
|
-
keyCollisions.forEach((keyCollision) => {
|
|
106
|
-
console.warn(
|
|
107
|
-
`Found a key collision for key '${
|
|
108
|
-
keyCollision.key
|
|
109
|
-
}' on lines ${keyCollision.startingLineNumbers.join(
|
|
110
|
-
', '
|
|
111
|
-
)} (will use the value at line ${keyCollision.getApplicableLineNumber()}).`
|
|
112
|
-
)
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Outputs:
|
|
117
|
-
*
|
|
118
|
-
* Found a key collision for key 'hello' on lines 1, 4 (will use the value at line 4).
|
|
119
|
-
* Found a key collision for key 'world' on lines 2, 3, 5 (will use the value at line 5).
|
|
120
|
-
*
|
|
121
|
-
*/
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Webpack File Loader
|
|
125
|
-
|
|
126
|
-
If you would like to import `.properties` directly using `import`, this package comes with its own Webpack file loader located under `properties-file/webpack-loader`. Here is an example of how to configure it:
|
|
127
|
-
|
|
128
|
-
```js
|
|
129
|
-
// webpack.config.js
|
|
130
|
-
module.exports = {
|
|
131
|
-
module: {
|
|
132
|
-
rules: [
|
|
133
|
-
{
|
|
134
|
-
test: /\.properties$/i,
|
|
135
|
-
use: [
|
|
136
|
-
{
|
|
137
|
-
loader: 'properties-file/webpack-loader',
|
|
138
|
-
},
|
|
139
|
-
],
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
|
-
},
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
As soon as you configure Webpack, the `.properties` type should be available in your IDE when using `import`. If you ever need to add it manually, you can add a `*.properties` type declaration file at the root of your application, like this:
|
|
147
|
-
|
|
148
|
-
```js
|
|
149
|
-
// properties-file.d.ts
|
|
150
|
-
declare module '*.properties' {
|
|
151
|
-
const properties: { readonly [key: string]: string };
|
|
152
|
-
export default properties;
|
|
153
|
-
}
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
By adding these configurations you should now be able to import directly `.properties` files just like this:
|
|
157
|
-
|
|
158
|
-
```ts
|
|
159
|
-
import helloWorld from './hello-world.properties'
|
|
160
|
-
|
|
161
|
-
console.dir(helloWorld)
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
Output:
|
|
165
|
-
|
|
166
|
-
```json
|
|
167
|
-
{ "hello": "world" }
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## Why another `.properties` file package?
|
|
171
|
-
|
|
172
|
-
There are probably over 20 similar packages available but:
|
|
173
|
-
|
|
174
|
-
- A lot of the most popular packages have had no activity for over 5 years.
|
|
175
|
-
- A large portion of the packages will not replicate the current Java implementation.
|
|
176
|
-
- No package offers the same capabilities as this one.
|
|
177
|
-
|
|
178
|
-
Unfortunately the `.properties` file specification is not well documented. One reason for this is that it was originally used in Java to store configurations. Most applications will handle this using JSON, YAML or other modern formats today because the formats are more flexible.
|
|
179
|
-
|
|
180
|
-
### So why `.properties` files?
|
|
181
|
-
|
|
182
|
-
While many options exists today to handle configurations, `.properties` file remain one of the best option to store localizable strings (also known as messages). On the Java side, `PropertyResourceBundle` is how most implementations handle localization today. Because of its simplicity and maturity, `.properties` files remain one of the best options today when it comes to internationalization (i18n):
|
|
183
|
-
|
|
184
|
-
| File format | Key/value based | Supports inline comments | Built for localization | Good linguistic tools support |
|
|
185
|
-
| ------------- | ---------------- | ------------------------ | ---------------------- | ----------------------------- |
|
|
186
|
-
| `.properties` | Yes | Yes | Yes (Resource Bundles) | Yes |
|
|
187
|
-
| `JSON` | No (can do more) | No (requires JSON5) | No | Depends on the schema |
|
|
188
|
-
| `YAML` | No (can do more) | Yes | No | Depends on the schema |
|
|
189
|
-
|
|
190
|
-
By having good JavaScript/TypeScript support for `.properties` files, it provides more options when it comes to i18n.
|
|
191
|
-
|
|
192
|
-
### How does this package work?
|
|
193
|
-
|
|
194
|
-
Basically our goal was to offer parity with the Java implementation, which is the closest thing to a specification `.properties` file have. Here is in a nutshell the logic behind this package:
|
|
195
|
-
|
|
196
|
-
1. Split the file content by lines (create line objects)
|
|
197
|
-
2. Create `LineObjects` by combining multi-line properties and removing trailing backslash
|
|
198
|
-
3. Create `PropertyObjects` from `LineObjects` that combined all lines of a property
|
|
199
|
-
4. Identify the key/value delimiter and populate escaped keys and values.
|
|
200
|
-
5. Unescape keys and values
|
|
201
|
-
6. Create a `PropertiesObject` that will include all `PropertyObjects` while removing collisions
|
|
202
|
-
|
|
203
|
-
Just like Java, if a Unicode escaped characters (`\u`) is malformed, it will throw an error. But of course, we do not recommend using Unicode escaped characters but rather UTF-8 encoding that supports more characters.
|
|
204
|
-
|
|
205
|
-
## Additional references
|
|
206
|
-
|
|
207
|
-
- Java [Test Sandbox](https://codehs.com/sandbox/id/java-main-kYynuh?filename=TestProperties.java)
|
|
208
|
-
- Java's `Properties` class [documentation](https://docs.oracle.com/javase/9/docs/api/java/util/Properties.html)
|
|
209
|
-
- Java's `PropertyResourceBundle` [documentation](https://docs.oracle.com/javase/9/docs/api/java/util/PropertyResourceBundle.html)
|
|
210
|
-
- Java's Internationalization [Guide](https://docs.oracle.com/en/java/javase/18/intl/internationalization-overview.html)
|
|
211
|
-
- Wikipedia's .properties [page](https://en.wikipedia.org/wiki/.properties)
|
|
212
|
-
|
|
213
|
-
### Special mention
|
|
214
|
-
|
|
215
|
-
Thanks to [@calibr](https://github.com/calibr), the creator of [properties-file version 1.0](https://github.com/calibr/properties-file), for letting us use the [https://www.npmjs.com/package/properties-file](https://www.npmjs.com/package/properties-file) package name. We hope that it will make it easier to find our package.
|
|
1
|
+
# properties-file
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://www.npmjs.com/package/properties-file)
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
[](https://snyk.io/test/github/Avansai/properties-file?targetFile=package.json)
|
|
8
|
+
|
|
9
|
+
.properties file parser, JSON converter and Webpack loader.
|
|
10
|
+
|
|
11
|
+
## Installation 💻
|
|
12
|
+
|
|
13
|
+
> ⚠ in June 2022 we have released version 2 of this package which is not compatible with the previous versions. Make sure to read the documentation before upgrading.
|
|
14
|
+
|
|
15
|
+
Add the package as a dependency:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
npm install properties-file
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## What's in it for me? 🤔
|
|
22
|
+
|
|
23
|
+
- A modern TypeScript library that reproduces exactly the [Properties Java implementation](/assets/java-implementation.md).
|
|
24
|
+
- Flexible APIs:
|
|
25
|
+
- `propertiesToJson` allows quick conversion from `.properties` files to JSON.
|
|
26
|
+
- `getProperties` returns a `Properties` object that allows insights into parsing issues such as key collisions.
|
|
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
|
+
- Out of the box Webpack loader to `import` `.properties` files directly in your application.
|
|
29
|
+
- 100% test coverage based on the output from a Java implementation.
|
|
30
|
+
- Active maintenance (many popular .properties packages have been inactive years).
|
|
31
|
+
|
|
32
|
+
## Usage 🎬
|
|
33
|
+
|
|
34
|
+
We put a lot of effort into adding [TSDoc](https://tsdoc.org/) to all our APIs. Please check directly in your IDE if you are unsure how to use certain APIs provided in our examples.
|
|
35
|
+
|
|
36
|
+
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
|
+
### `propertiesToJson`
|
|
39
|
+
|
|
40
|
+
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
|
+
```ts
|
|
43
|
+
import { propertiesToJson } from 'properties-file'
|
|
44
|
+
|
|
45
|
+
console.log(propertiesToJson('hello-world.properties'))
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Output:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
{ hello: 'hello', world: 'world' }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
If you cannot use `fs` and already have the content of a `.properties` file, your code would look like this instead:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { propertiesToJson } from 'properties-file/content'
|
|
58
|
+
|
|
59
|
+
// ...some code to get the .properties file content into a variable called `propertiesFileContent`
|
|
60
|
+
|
|
61
|
+
console.log(propertiesToJson(propertiesFileContent))
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### `getProperties` (advanced use case)
|
|
65
|
+
|
|
66
|
+
Java's implementation of `Properties` is quite resilient. In fact, there are only two ways an exception can be thrown:
|
|
67
|
+
|
|
68
|
+
- The file is not found.
|
|
69
|
+
- A (`\u`) Unicode escape character is malformed.
|
|
70
|
+
|
|
71
|
+
This means that almost all files will be valid.
|
|
72
|
+
|
|
73
|
+
But what about a file that has duplicate keys? Duplicate keys have no reason to exist and they probably should have thrown errors as well but instead Java decided to simply overwrite the value with the latest occurrence in a file.
|
|
74
|
+
|
|
75
|
+
So how can we know if there were duplicate keys if we want to log some warnings? Simply by using `getProperties` which will return all the data that was used to parse the content. Here is an example on how it can be used:
|
|
76
|
+
|
|
77
|
+
```properties
|
|
78
|
+
# collisions-test.properties
|
|
79
|
+
hello: hello1
|
|
80
|
+
world: world1
|
|
81
|
+
world: world2
|
|
82
|
+
hello: hello2
|
|
83
|
+
world: world3
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { getProperties } from 'properties-file'
|
|
88
|
+
|
|
89
|
+
const properties = getProperties('assets/tests/collisions-test.properties')
|
|
90
|
+
|
|
91
|
+
properties.collection.forEach((property) => {
|
|
92
|
+
console.log(`${property.key} => '${property.value}'`)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Outputs:
|
|
97
|
+
*
|
|
98
|
+
* hello => 'hello2'
|
|
99
|
+
* world => 'world3'
|
|
100
|
+
*
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
const keyCollisions = properties.getKeyCollisions()
|
|
104
|
+
|
|
105
|
+
keyCollisions.forEach((keyCollision) => {
|
|
106
|
+
console.warn(
|
|
107
|
+
`Found a key collision for key '${
|
|
108
|
+
keyCollision.key
|
|
109
|
+
}' on lines ${keyCollision.startingLineNumbers.join(
|
|
110
|
+
', '
|
|
111
|
+
)} (will use the value at line ${keyCollision.getApplicableLineNumber()}).`
|
|
112
|
+
)
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Outputs:
|
|
117
|
+
*
|
|
118
|
+
* Found a key collision for key 'hello' on lines 1, 4 (will use the value at line 4).
|
|
119
|
+
* Found a key collision for key 'world' on lines 2, 3, 5 (will use the value at line 5).
|
|
120
|
+
*
|
|
121
|
+
*/
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Webpack File Loader
|
|
125
|
+
|
|
126
|
+
If you would like to import `.properties` directly using `import`, this package comes with its own Webpack file loader located under `properties-file/webpack-loader`. Here is an example of how to configure it:
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
// webpack.config.js
|
|
130
|
+
module.exports = {
|
|
131
|
+
module: {
|
|
132
|
+
rules: [
|
|
133
|
+
{
|
|
134
|
+
test: /\.properties$/i,
|
|
135
|
+
use: [
|
|
136
|
+
{
|
|
137
|
+
loader: 'properties-file/webpack-loader',
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
As soon as you configure Webpack, the `.properties` type should be available in your IDE when using `import`. If you ever need to add it manually, you can add a `*.properties` type declaration file at the root of your application, like this:
|
|
147
|
+
|
|
148
|
+
```js
|
|
149
|
+
// properties-file.d.ts
|
|
150
|
+
declare module '*.properties' {
|
|
151
|
+
const properties: { readonly [key: string]: string };
|
|
152
|
+
export default properties;
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
By adding these configurations you should now be able to import directly `.properties` files just like this:
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
import helloWorld from './hello-world.properties'
|
|
160
|
+
|
|
161
|
+
console.dir(helloWorld)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Output:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{ "hello": "world" }
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Why another `.properties` file package?
|
|
171
|
+
|
|
172
|
+
There are probably over 20 similar packages available but:
|
|
173
|
+
|
|
174
|
+
- A lot of the most popular packages have had no activity for over 5 years.
|
|
175
|
+
- A large portion of the packages will not replicate the current Java implementation.
|
|
176
|
+
- No package offers the same capabilities as this one.
|
|
177
|
+
|
|
178
|
+
Unfortunately the `.properties` file specification is not well documented. One reason for this is that it was originally used in Java to store configurations. Most applications will handle this using JSON, YAML or other modern formats today because the formats are more flexible.
|
|
179
|
+
|
|
180
|
+
### So why `.properties` files?
|
|
181
|
+
|
|
182
|
+
While many options exists today to handle configurations, `.properties` file remain one of the best option to store localizable strings (also known as messages). On the Java side, `PropertyResourceBundle` is how most implementations handle localization today. Because of its simplicity and maturity, `.properties` files remain one of the best options today when it comes to internationalization (i18n):
|
|
183
|
+
|
|
184
|
+
| File format | Key/value based | Supports inline comments | Built for localization | Good linguistic tools support |
|
|
185
|
+
| ------------- | ---------------- | ------------------------ | ---------------------- | ----------------------------- |
|
|
186
|
+
| `.properties` | Yes | Yes | Yes (Resource Bundles) | Yes |
|
|
187
|
+
| `JSON` | No (can do more) | No (requires JSON5) | No | Depends on the schema |
|
|
188
|
+
| `YAML` | No (can do more) | Yes | No | Depends on the schema |
|
|
189
|
+
|
|
190
|
+
By having good JavaScript/TypeScript support for `.properties` files, it provides more options when it comes to i18n.
|
|
191
|
+
|
|
192
|
+
### How does this package work?
|
|
193
|
+
|
|
194
|
+
Basically our goal was to offer parity with the Java implementation, which is the closest thing to a specification `.properties` file have. Here is in a nutshell the logic behind this package:
|
|
195
|
+
|
|
196
|
+
1. Split the file content by lines (create line objects)
|
|
197
|
+
2. Create `LineObjects` by combining multi-line properties and removing trailing backslash
|
|
198
|
+
3. Create `PropertyObjects` from `LineObjects` that combined all lines of a property
|
|
199
|
+
4. Identify the key/value delimiter and populate escaped keys and values.
|
|
200
|
+
5. Unescape keys and values
|
|
201
|
+
6. Create a `PropertiesObject` that will include all `PropertyObjects` while removing collisions
|
|
202
|
+
|
|
203
|
+
Just like Java, if a Unicode escaped characters (`\u`) is malformed, it will throw an error. But of course, we do not recommend using Unicode escaped characters but rather UTF-8 encoding that supports more characters.
|
|
204
|
+
|
|
205
|
+
## Additional references
|
|
206
|
+
|
|
207
|
+
- Java [Test Sandbox](https://codehs.com/sandbox/id/java-main-kYynuh?filename=TestProperties.java)
|
|
208
|
+
- Java's `Properties` class [documentation](https://docs.oracle.com/javase/9/docs/api/java/util/Properties.html)
|
|
209
|
+
- Java's `PropertyResourceBundle` [documentation](https://docs.oracle.com/javase/9/docs/api/java/util/PropertyResourceBundle.html)
|
|
210
|
+
- Java's Internationalization [Guide](https://docs.oracle.com/en/java/javase/18/intl/internationalization-overview.html)
|
|
211
|
+
- Wikipedia's .properties [page](https://en.wikipedia.org/wiki/.properties)
|
|
212
|
+
|
|
213
|
+
### Special mention
|
|
214
|
+
|
|
215
|
+
Thanks to [@calibr](https://github.com/calibr), the creator of [properties-file version 1.0](https://github.com/calibr/properties-file), for letting us use the [https://www.npmjs.com/package/properties-file](https://www.npmjs.com/package/properties-file) package name. We hope that it will make it easier to find our package.
|
package/lib/content/index.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { KeyValueObject } from '../';
|
|
2
|
-
import { Properties } from '../properties';
|
|
3
|
-
/**
|
|
4
|
-
* Get a `Properties` object from the content of a `.properties` file.
|
|
5
|
-
*
|
|
6
|
-
* @param content - the content of a `.properties` file.
|
|
7
|
-
*
|
|
8
|
-
* @returns A `Properties` object representing the content of a `.properties` file.
|
|
9
|
-
*/
|
|
10
|
-
export declare function getProperties(content: string): Properties;
|
|
11
|
-
/**
|
|
12
|
-
* Converts the content of a `.properties` file to JSON.
|
|
13
|
-
*
|
|
14
|
-
* @param content - the content of a `.properties` file.
|
|
15
|
-
*
|
|
16
|
-
* @returns A (JSON) key/value object representing the content of a `.properties` file.
|
|
17
|
-
*/
|
|
18
|
-
export declare function propertiesToJson(content: string): KeyValueObject;
|
|
1
|
+
import { KeyValueObject } from '../';
|
|
2
|
+
import { Properties } from '../properties';
|
|
3
|
+
/**
|
|
4
|
+
* Get a `Properties` object from the content of a `.properties` file.
|
|
5
|
+
*
|
|
6
|
+
* @param content - the content of a `.properties` file.
|
|
7
|
+
*
|
|
8
|
+
* @returns A `Properties` object representing the content of a `.properties` file.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getProperties(content: string): Properties;
|
|
11
|
+
/**
|
|
12
|
+
* Converts the content of a `.properties` file to JSON.
|
|
13
|
+
*
|
|
14
|
+
* @param content - the content of a `.properties` file.
|
|
15
|
+
*
|
|
16
|
+
* @returns A (JSON) key/value object representing the content of a `.properties` file.
|
|
17
|
+
*/
|
|
18
|
+
export declare function propertiesToJson(content: string): KeyValueObject;
|
package/lib/content/index.js
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.propertiesToJson = exports.getProperties = void 0;
|
|
4
|
-
var properties_1 = require("../properties");
|
|
5
|
-
var property_1 = require("../property");
|
|
6
|
-
var property_line_1 = require("../property-line");
|
|
7
|
-
/**
|
|
8
|
-
* Get a `Properties` object from the content of a `.properties` file.
|
|
9
|
-
*
|
|
10
|
-
* @param content - the content of a `.properties` file.
|
|
11
|
-
*
|
|
12
|
-
* @returns A `Properties` object representing the content of a `.properties` file.
|
|
13
|
-
*/
|
|
14
|
-
function getProperties(content) {
|
|
15
|
-
// Remove BOM character if present and create an array from lines.
|
|
16
|
-
var lines = (content.codePointAt(0) === 0xfeff ? content.slice(1) : content).split(/\r?\n/);
|
|
17
|
-
/** Line number while parsing properties file content. */
|
|
18
|
-
var lineNumber = 0;
|
|
19
|
-
/** The current property object being parsed. */
|
|
20
|
-
var property;
|
|
21
|
-
/** The collection of property objects. */
|
|
22
|
-
var properties = new properties_1.Properties();
|
|
23
|
-
for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
|
|
24
|
-
var line = lines_1[_i];
|
|
25
|
-
lineNumber++;
|
|
26
|
-
var propertyLine = new property_line_1.PropertyLine(line, !!property);
|
|
27
|
-
if (!property) {
|
|
28
|
-
// Check if the line is a new property.
|
|
29
|
-
if (propertyLine.isComment || propertyLine.isBlank) {
|
|
30
|
-
continue; // Skip line if its a comment or blank.
|
|
31
|
-
}
|
|
32
|
-
// The line is a new property.
|
|
33
|
-
property = new property_1.Property(propertyLine, lineNumber);
|
|
34
|
-
if (propertyLine.continues) {
|
|
35
|
-
continue; // Continue parsing the next line.
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
// Continue parsing an existing property.
|
|
40
|
-
property.addLine(propertyLine);
|
|
41
|
-
if (propertyLine.continues) {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
// If the line does not continue, add the property to the collection.
|
|
46
|
-
property = properties.add(property);
|
|
47
|
-
}
|
|
48
|
-
return properties;
|
|
49
|
-
}
|
|
50
|
-
exports.getProperties = getProperties;
|
|
51
|
-
/**
|
|
52
|
-
* Converts the content of a `.properties` file to JSON.
|
|
53
|
-
*
|
|
54
|
-
* @param content - the content of a `.properties` file.
|
|
55
|
-
*
|
|
56
|
-
* @returns A (JSON) key/value object representing the content of a `.properties` file.
|
|
57
|
-
*/
|
|
58
|
-
function propertiesToJson(content) {
|
|
59
|
-
return getProperties(content).toJson();
|
|
60
|
-
}
|
|
61
|
-
exports.propertiesToJson = propertiesToJson;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.propertiesToJson = exports.getProperties = void 0;
|
|
4
|
+
var properties_1 = require("../properties");
|
|
5
|
+
var property_1 = require("../property");
|
|
6
|
+
var property_line_1 = require("../property-line");
|
|
7
|
+
/**
|
|
8
|
+
* Get a `Properties` object from the content of a `.properties` file.
|
|
9
|
+
*
|
|
10
|
+
* @param content - the content of a `.properties` file.
|
|
11
|
+
*
|
|
12
|
+
* @returns A `Properties` object representing the content of a `.properties` file.
|
|
13
|
+
*/
|
|
14
|
+
function getProperties(content) {
|
|
15
|
+
// Remove BOM character if present and create an array from lines.
|
|
16
|
+
var lines = (content.codePointAt(0) === 0xfeff ? content.slice(1) : content).split(/\r?\n/);
|
|
17
|
+
/** Line number while parsing properties file content. */
|
|
18
|
+
var lineNumber = 0;
|
|
19
|
+
/** The current property object being parsed. */
|
|
20
|
+
var property;
|
|
21
|
+
/** The collection of property objects. */
|
|
22
|
+
var properties = new properties_1.Properties();
|
|
23
|
+
for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
|
|
24
|
+
var line = lines_1[_i];
|
|
25
|
+
lineNumber++;
|
|
26
|
+
var propertyLine = new property_line_1.PropertyLine(line, !!property);
|
|
27
|
+
if (!property) {
|
|
28
|
+
// Check if the line is a new property.
|
|
29
|
+
if (propertyLine.isComment || propertyLine.isBlank) {
|
|
30
|
+
continue; // Skip line if its a comment or blank.
|
|
31
|
+
}
|
|
32
|
+
// The line is a new property.
|
|
33
|
+
property = new property_1.Property(propertyLine, lineNumber);
|
|
34
|
+
if (propertyLine.continues) {
|
|
35
|
+
continue; // Continue parsing the next line.
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// Continue parsing an existing property.
|
|
40
|
+
property.addLine(propertyLine);
|
|
41
|
+
if (propertyLine.continues) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// If the line does not continue, add the property to the collection.
|
|
46
|
+
property = properties.add(property);
|
|
47
|
+
}
|
|
48
|
+
return properties;
|
|
49
|
+
}
|
|
50
|
+
exports.getProperties = getProperties;
|
|
51
|
+
/**
|
|
52
|
+
* Converts the content of a `.properties` file to JSON.
|
|
53
|
+
*
|
|
54
|
+
* @param content - the content of a `.properties` file.
|
|
55
|
+
*
|
|
56
|
+
* @returns A (JSON) key/value object representing the content of a `.properties` file.
|
|
57
|
+
*/
|
|
58
|
+
function propertiesToJson(content) {
|
|
59
|
+
return getProperties(content).toJson();
|
|
60
|
+
}
|
|
61
|
+
exports.propertiesToJson = propertiesToJson;
|