projen 0.103.3 → 0.103.5
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/.jsii +11700 -6065
- package/lib/ai-instructions.js +2 -2
- package/lib/awscdk/auto-discover.js +6 -6
- package/lib/awscdk/awscdk-app-java.js +1 -1
- package/lib/awscdk/awscdk-app-py.js +1 -1
- package/lib/awscdk/awscdk-app-ts.js +1 -1
- package/lib/awscdk/awscdk-construct.js +1 -1
- package/lib/awscdk/awscdk-deps-java.js +1 -1
- package/lib/awscdk/awscdk-deps-js.js +1 -1
- package/lib/awscdk/awscdk-deps-py.js +1 -1
- package/lib/awscdk/awscdk-deps.js +1 -1
- package/lib/awscdk/cdk-config.js +3 -3
- package/lib/awscdk/cdk-tasks.js +1 -1
- package/lib/awscdk/integration-test.js +1 -1
- package/lib/awscdk/lambda-extension.js +1 -1
- package/lib/awscdk/lambda-function.js +2 -2
- package/lib/build/build-workflow.js +1 -1
- package/lib/cdk/auto-discover-base.js +2 -2
- package/lib/cdk/construct-lib.js +1 -1
- package/lib/cdk/integration-test-base.js +1 -1
- package/lib/cdk/jsii-build.js +1 -1
- package/lib/cdk/jsii-docgen.js +1 -1
- package/lib/cdk/jsii-project.js +1 -1
- package/lib/cdk8s/auto-discover.js +2 -2
- package/lib/cdk8s/cdk8s-app-py.js +1 -1
- package/lib/cdk8s/cdk8s-app-ts.js +1 -1
- package/lib/cdk8s/cdk8s-construct.js +1 -1
- package/lib/cdk8s/cdk8s-deps-py.js +1 -1
- package/lib/cdk8s/cdk8s-deps.js +1 -1
- package/lib/cdk8s/integration-test.js +1 -1
- package/lib/cdktf/cdktf-construct.js +1 -1
- package/lib/cdktn/cdktn-app-ts.js +1 -1
- package/lib/cdktn/cdktn-config.js +1 -1
- package/lib/cdktn/cdktn-construct.js +1 -1
- package/lib/cdktn/cdktn-deps.js +1 -1
- package/lib/cdktn/cdktn-tasks.js +1 -1
- package/lib/circleci/circleci.js +1 -1
- package/lib/component.js +2 -2
- package/lib/dependencies.js +1 -1
- package/lib/dev-env.js +1 -1
- package/lib/docker-compose/docker-compose-service.js +1 -1
- package/lib/docker-compose/docker-compose.js +1 -1
- package/lib/file.js +1 -1
- package/lib/gitattributes.js +1 -1
- package/lib/github/actions-provider.js +1 -1
- package/lib/github/auto-approve.js +1 -1
- package/lib/github/auto-merge.js +1 -1
- package/lib/github/auto-queue.js +1 -1
- package/lib/github/dependabot.js +1 -1
- package/lib/github/dependency-review.js +1 -1
- package/lib/github/github-credentials.js +1 -1
- package/lib/github/github-project.js +1 -1
- package/lib/github/github.js +1 -1
- package/lib/github/merge-queue.js +1 -1
- package/lib/github/mergify.js +1 -1
- package/lib/github/pr-template.js +1 -1
- package/lib/github/pull-request-backport.js +1 -1
- package/lib/github/pull-request-lint.js +1 -1
- package/lib/github/stale.js +1 -1
- package/lib/github/task-workflow-job.js +1 -1
- package/lib/github/task-workflow.js +1 -1
- package/lib/github/workflow-actions.js +1 -1
- package/lib/github/workflow-jobs.js +1 -1
- package/lib/github/workflow-steps.js +1 -1
- package/lib/github/workflows.js +1 -1
- package/lib/gitlab/configuration.js +1 -1
- package/lib/gitlab/gitlab-configuration.js +1 -1
- package/lib/gitlab/nested-configuration.js +1 -1
- package/lib/gitpod.js +1 -1
- package/lib/ignore-file.js +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +4 -2
- package/lib/ini.js +1 -1
- package/lib/java/java-project.js +1 -1
- package/lib/java/junit.js +1 -1
- package/lib/java/maven-compile.js +1 -1
- package/lib/java/maven-packaging.js +1 -1
- package/lib/java/maven-sample.js +1 -1
- package/lib/java/pom.js +2 -2
- package/lib/java/projenrc.js +1 -1
- package/lib/javascript/biome/biome.js +1 -1
- package/lib/javascript/bundler.js +1 -1
- package/lib/javascript/eslint.js +1 -1
- package/lib/javascript/index.d.ts +2 -0
- package/lib/javascript/index.js +3 -1
- package/lib/javascript/jest.js +4 -4
- package/lib/javascript/license-checker.js +1 -1
- package/lib/javascript/node-config-file.d.ts +39 -0
- package/lib/javascript/node-config-file.js +44 -0
- package/lib/javascript/node-config.d.ts +1150 -0
- package/lib/javascript/node-config.js +266 -0
- package/lib/javascript/node-package.js +1 -1
- package/lib/javascript/node-project.js +1 -1
- package/lib/javascript/npm-config.js +1 -1
- package/lib/javascript/pnpm-workspace-config.js +2 -2
- package/lib/javascript/pnpm-workspace.js +1 -1
- package/lib/javascript/prettier.js +1 -1
- package/lib/javascript/projenrc.js +1 -1
- package/lib/javascript/typescript-config.js +2 -2
- package/lib/javascript/upgrade-dependencies.js +2 -2
- package/lib/javascript/yarnrc.js +1 -1
- package/lib/json-patch.js +1 -1
- package/lib/json.js +1 -1
- package/lib/license.js +1 -1
- package/lib/logger.js +1 -1
- package/lib/makefile.js +1 -1
- package/lib/object-file.js +1 -1
- package/lib/project-build.js +1 -1
- package/lib/project-tree.js +1 -1
- package/lib/project.js +1 -1
- package/lib/projects.js +1 -1
- package/lib/projenrc-json.js +1 -1
- package/lib/projenrc.js +1 -1
- package/lib/properties-file.d.ts +50 -0
- package/lib/properties-file.js +77 -0
- package/lib/python/pip.js +1 -1
- package/lib/python/poetry.js +2 -2
- package/lib/python/projenrc.js +1 -1
- package/lib/python/pyproject-toml-file.js +1 -1
- package/lib/python/pytest-sample.js +1 -1
- package/lib/python/pytest.js +1 -1
- package/lib/python/python-project.js +1 -1
- package/lib/python/python-sample.js +1 -1
- package/lib/python/requirements-file.js +1 -1
- package/lib/python/setuppy.js +1 -1
- package/lib/python/setuptools.js +1 -1
- package/lib/python/uv-config.js +1 -1
- package/lib/python/uv.js +1 -1
- package/lib/python/venv.js +1 -1
- package/lib/readme.js +1 -1
- package/lib/release/publisher.js +1 -1
- package/lib/release/release-trigger.js +1 -1
- package/lib/release/release.js +1 -1
- package/lib/renovatebot.js +1 -1
- package/lib/run-task.cjs +6 -2
- package/lib/sample-file.js +2 -2
- package/lib/script-runner.js +1 -1
- package/lib/sonarqube/index.d.ts +4 -0
- package/lib/sonarqube/index.js +21 -0
- package/lib/sonarqube/javascript.d.ts +35 -0
- package/lib/sonarqube/javascript.js +57 -0
- package/lib/sonarqube/rust.d.ts +37 -0
- package/lib/sonarqube/rust.js +58 -0
- package/lib/sonarqube/sonarqube.d.ts +439 -0
- package/lib/sonarqube/sonarqube.js +184 -0
- package/lib/sonarqube/typescript.d.ts +36 -0
- package/lib/sonarqube/typescript.js +61 -0
- package/lib/source-code.js +1 -1
- package/lib/task-shell.js +1 -1
- package/lib/task.js +1 -1
- package/lib/tasks.js +1 -1
- package/lib/testing.js +1 -1
- package/lib/textfile.js +1 -1
- package/lib/toml.js +1 -1
- package/lib/typescript/projenrc-ts.js +1 -1
- package/lib/typescript/projenrc.js +1 -1
- package/lib/typescript/typescript-runner.js +1 -1
- package/lib/typescript/typescript-typedoc.js +1 -1
- package/lib/typescript/typescript.js +5 -5
- package/lib/util.d.ts +9 -0
- package/lib/util.js +39 -1
- package/lib/version.js +2 -2
- package/lib/vscode/devcontainer.js +1 -1
- package/lib/vscode/extensions.js +1 -1
- package/lib/vscode/launch-config.js +1 -1
- package/lib/vscode/settings.js +1 -1
- package/lib/vscode/vscode.js +1 -1
- package/lib/web/next.js +3 -3
- package/lib/web/postcss.js +1 -1
- package/lib/web/react.js +3 -3
- package/lib/web/tailwind.js +1 -1
- package/lib/xmlfile.js +1 -1
- package/lib/yaml.js +1 -1
- package/node_modules/properties-file/LICENSE +21 -0
- package/node_modules/properties-file/README.md +253 -0
- package/node_modules/properties-file/dist/cjs/bundler/bun.d.ts +10 -0
- package/node_modules/properties-file/dist/cjs/bundler/bun.js +1 -0
- package/node_modules/properties-file/dist/cjs/bundler/esbuild.d.ts +11 -0
- package/node_modules/properties-file/dist/cjs/bundler/esbuild.js +1 -0
- package/node_modules/properties-file/dist/cjs/bundler/rollup.d.ts +11 -0
- package/node_modules/properties-file/dist/cjs/bundler/rollup.js +1 -0
- package/node_modules/properties-file/dist/cjs/bundler/webpack.d.ts +12 -0
- package/node_modules/properties-file/dist/cjs/bundler/webpack.js +1 -0
- package/node_modules/properties-file/dist/cjs/characters.d.ts +32 -0
- package/node_modules/properties-file/dist/cjs/characters.js +1 -0
- package/node_modules/properties-file/dist/cjs/editor/index.d.ts +181 -0
- package/node_modules/properties-file/dist/cjs/editor/index.js +1 -0
- package/node_modules/properties-file/dist/cjs/escape/index.d.ts +18 -0
- package/node_modules/properties-file/dist/cjs/escape/index.js +1 -0
- package/node_modules/properties-file/dist/cjs/index.d.ts +25 -0
- package/node_modules/properties-file/dist/cjs/index.js +1 -0
- package/node_modules/properties-file/dist/cjs/package.json +1 -0
- package/node_modules/properties-file/dist/cjs/parser/index.d.ts +3 -0
- package/node_modules/properties-file/dist/cjs/parser/index.js +1 -0
- package/node_modules/properties-file/dist/cjs/parser/nodes.d.ts +154 -0
- package/node_modules/properties-file/dist/cjs/parser/nodes.js +1 -0
- package/node_modules/properties-file/dist/cjs/parser/normalize.d.ts +12 -0
- package/node_modules/properties-file/dist/cjs/parser/normalize.js +1 -0
- package/node_modules/properties-file/dist/cjs/parser/parse.d.ts +23 -0
- package/node_modules/properties-file/dist/cjs/parser/parse.js +1 -0
- package/node_modules/properties-file/dist/cjs/parser/properties.d.ts +93 -0
- package/node_modules/properties-file/dist/cjs/parser/properties.js +1 -0
- package/node_modules/properties-file/dist/cjs/properties-file.d.ts +8 -0
- package/node_modules/properties-file/dist/cjs/unescape/index.d.ts +14 -0
- package/node_modules/properties-file/dist/cjs/unescape/index.js +1 -0
- package/node_modules/properties-file/dist/esm/bundler/bun.d.ts +10 -0
- package/node_modules/properties-file/dist/esm/bundler/bun.js +1 -0
- package/node_modules/properties-file/dist/esm/bundler/esbuild.d.ts +11 -0
- package/node_modules/properties-file/dist/esm/bundler/esbuild.js +1 -0
- package/node_modules/properties-file/dist/esm/bundler/rollup.d.ts +11 -0
- package/node_modules/properties-file/dist/esm/bundler/rollup.js +1 -0
- package/node_modules/properties-file/dist/esm/bundler/webpack.d.ts +12 -0
- package/node_modules/properties-file/dist/esm/bundler/webpack.js +1 -0
- package/node_modules/properties-file/dist/esm/characters.d.ts +32 -0
- package/node_modules/properties-file/dist/esm/characters.js +1 -0
- package/node_modules/properties-file/dist/esm/editor/index.d.ts +181 -0
- package/node_modules/properties-file/dist/esm/editor/index.js +1 -0
- package/node_modules/properties-file/dist/esm/escape/index.d.ts +18 -0
- package/node_modules/properties-file/dist/esm/escape/index.js +1 -0
- package/node_modules/properties-file/dist/esm/index.d.ts +25 -0
- package/node_modules/properties-file/dist/esm/index.js +1 -0
- package/node_modules/properties-file/dist/esm/parser/index.d.ts +3 -0
- package/node_modules/properties-file/dist/esm/parser/index.js +1 -0
- package/node_modules/properties-file/dist/esm/parser/nodes.d.ts +154 -0
- package/node_modules/properties-file/dist/esm/parser/nodes.js +1 -0
- package/node_modules/properties-file/dist/esm/parser/normalize.d.ts +12 -0
- package/node_modules/properties-file/dist/esm/parser/normalize.js +1 -0
- package/node_modules/properties-file/dist/esm/parser/parse.d.ts +23 -0
- package/node_modules/properties-file/dist/esm/parser/parse.js +1 -0
- package/node_modules/properties-file/dist/esm/parser/properties.d.ts +93 -0
- package/node_modules/properties-file/dist/esm/parser/properties.js +1 -0
- package/node_modules/properties-file/dist/esm/properties-file.d.ts +8 -0
- package/node_modules/properties-file/dist/esm/unescape/index.d.ts +14 -0
- package/node_modules/properties-file/dist/esm/unescape/index.js +1 -0
- package/node_modules/properties-file/package.json +190 -0
- package/package.json +6 -2
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# properties-file
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://www.npmjs.com/package/properties-file)
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
`.properties` file parser, editor, formatter and bundler integrations.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
> Doing a major version update? Check our [migration guides](./docs/migration/README.md).
|
|
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 library written entirely in TypeScript that exactly reproduces the [Properties Java implementation](/assets/java-implementation.md).
|
|
24
|
+
- Works for both Node.js applications and browsers that support at least [ES5](https://www.w3schools.com/js/js_es5.asp).
|
|
25
|
+
- Flexible, tree-shakable APIs — import only what you need, and your bundler will exclude the rest:
|
|
26
|
+
- `getProperties` converts `.properties` content to a key-value pair object.
|
|
27
|
+
- `Properties` provides lossless parsing with a full data model — every element (properties, comments, blank lines, whitespace, duplicate keys) is preserved and can be round-tripped exactly or normalized via `format()` options.
|
|
28
|
+
- `PropertiesEditor` enables insertion, edition, and removal of entries while preserving formatting.
|
|
29
|
+
- `escapeKey` and `escapeValue` convert any content to `.properties` compatible format.
|
|
30
|
+
- Bundler integrations for Webpack, Rollup/Vite, esbuild, and Bun to import `.properties` files directly. See [BUNDLER.md](./docs/BUNDLER.md).
|
|
31
|
+
- **Tiny with 0 dependencies** — `getProperties` is only 970 B min+gzip.
|
|
32
|
+
- **Runs everywhere** — compiled to ES5, works in any browser and on Node.js all the way back to v0.4.0 (2011, the first stable release with ES5 support). [Verified via Docker](./tests/node-compat/).
|
|
33
|
+
- **100% test coverage** based on the output from a Java implementation.
|
|
34
|
+
- Active maintenance (many popular `.properties` packages have been inactive for years). See our [detailed comparison](./docs/COMPARISON.md) with other packages.
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
We have put a lot of effort into incorporating [TSDoc](https://tsdoc.org/) into all our APIs. If you are unsure about how to use certain APIs provided in our examples, please check directly in your IDE.
|
|
39
|
+
|
|
40
|
+
### `getProperties` (converting `.properties` to an object)
|
|
41
|
+
|
|
42
|
+
The most common use case for `.properties` files is for Node.js applications that need to read the file's content into a simple key-value pair object. Here is how this can be done with a single API call:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { readFileSync } from 'node:fs'
|
|
46
|
+
import { getProperties } from 'properties-file'
|
|
47
|
+
|
|
48
|
+
console.log(getProperties(readFileSync('hello-world.properties')))
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Output:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
{ hello: 'hello', world: 'world' }
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### `Properties` (lossless parsing with full data model)
|
|
58
|
+
|
|
59
|
+
The `Properties` class parses a `.properties` file into a lossless data model where every element — properties, comments, blank lines — is preserved in order. This is useful when you need to inspect, analyze, or transform `.properties` files while retaining their exact structure.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { readFileSync } from 'node:fs'
|
|
63
|
+
import { PropertiesNodeType, Properties } from 'properties-file/parser'
|
|
64
|
+
|
|
65
|
+
const properties = new Properties(readFileSync('example.properties'))
|
|
66
|
+
|
|
67
|
+
// Access all nodes in file order (properties, comments, blank lines).
|
|
68
|
+
for (const node of properties.nodes) {
|
|
69
|
+
switch (node.type) {
|
|
70
|
+
case PropertiesNodeType.PROPERTY:
|
|
71
|
+
console.log(`${node.key} = ${node.value}`)
|
|
72
|
+
break
|
|
73
|
+
case PropertiesNodeType.COMMENT:
|
|
74
|
+
console.log(`Comment: ${node.delimiter}${node.body}`)
|
|
75
|
+
break
|
|
76
|
+
case PropertiesNodeType.BLANK:
|
|
77
|
+
console.log('(blank line)')
|
|
78
|
+
break
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Get a simple key-value object (last-wins for duplicate keys).
|
|
83
|
+
console.log(properties.toObject())
|
|
84
|
+
|
|
85
|
+
// Lossless round-trip: format() reproduces the exact original content.
|
|
86
|
+
console.log(properties.format() === readFileSync('example.properties', 'utf8')) // true
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### Finding key collisions
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { Properties } from 'properties-file/parser'
|
|
93
|
+
|
|
94
|
+
const properties = new Properties(
|
|
95
|
+
'hello = hello1\nworld = world1\nworld = world2\nhello = hello2\nworld = world3'
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
const collisions = properties.getKeyCollisions()
|
|
99
|
+
collisions.forEach((collision) => {
|
|
100
|
+
const lines = collision.nodes.map((node) => node.startingLineNumber)
|
|
101
|
+
console.log(`Key '${collision.key}' appears on lines ${lines.join(', ')}`)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Outputs:
|
|
106
|
+
*
|
|
107
|
+
* Key 'hello' appears on lines 1, 4
|
|
108
|
+
* Key 'world' appears on lines 2, 3, 5
|
|
109
|
+
*/
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### Normalizing output
|
|
113
|
+
|
|
114
|
+
Passing options to `format()` produces a normalized version of the file with granular control over formatting:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import { Properties } from 'properties-file/parser'
|
|
118
|
+
|
|
119
|
+
const properties = new Properties('# comment\n\n key : value\n key : updated')
|
|
120
|
+
|
|
121
|
+
console.log(
|
|
122
|
+
properties.format({
|
|
123
|
+
removeComments: true, // Strip all comments
|
|
124
|
+
removeBlankLines: true, // Strip all blank lines
|
|
125
|
+
removeLeadingWhitespace: true, // Strip indentation
|
|
126
|
+
deduplicateKeys: true, // Keep only last occurrence
|
|
127
|
+
separatorChar: '=', // Standardize separator
|
|
128
|
+
separatorLeading: ' ', // Space before =
|
|
129
|
+
separatorTrailing: ' ', // Space after =
|
|
130
|
+
})
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Outputs:
|
|
135
|
+
*
|
|
136
|
+
* key = updated
|
|
137
|
+
*/
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `PropertiesEditor` (editing `.properties` content)
|
|
141
|
+
|
|
142
|
+
The `PropertiesEditor` extends `Properties` with methods to insert, update, delete, and upsert entries while preserving formatting.
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import { PropertiesEditor } from 'properties-file/editor'
|
|
146
|
+
|
|
147
|
+
const properties = new PropertiesEditor('hello = hello\n# This is a comment\nworld = world')
|
|
148
|
+
|
|
149
|
+
properties.insertComment('This is a multiline\ncomment before `newKey3`')
|
|
150
|
+
properties.insert('newKey3', 'This is my third key')
|
|
151
|
+
|
|
152
|
+
properties.insert('newKey1', 'This is my first new key', {
|
|
153
|
+
referenceKey: 'newKey3',
|
|
154
|
+
position: 'before',
|
|
155
|
+
comment: 'Below are the new keys being edited',
|
|
156
|
+
commentDelimiter: '!',
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
properties.insert('newKey2', 'hello', {
|
|
160
|
+
referenceKey: 'newKey1',
|
|
161
|
+
position: 'after',
|
|
162
|
+
escapeUnicode: true,
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
properties.delete('hello')
|
|
166
|
+
properties.update('world', {
|
|
167
|
+
newValue: 'new world',
|
|
168
|
+
})
|
|
169
|
+
console.log(properties.format())
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Outputs:
|
|
173
|
+
*
|
|
174
|
+
* # This is a comment
|
|
175
|
+
* world = new world
|
|
176
|
+
* ! Below are the new keys being edited
|
|
177
|
+
* newKey1 = This is my first new key
|
|
178
|
+
* newKey2 = hello
|
|
179
|
+
* # This is a multiline
|
|
180
|
+
* # comment before `newKey3`
|
|
181
|
+
* newKey3 = This is my third key
|
|
182
|
+
*/
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The editor also provides `upsert` (update or insert) and `deleteAll` (remove all occurrences of a duplicate key). Check your IDE for all available methods and options via TSDoc.
|
|
186
|
+
|
|
187
|
+
### Bundler Integrations
|
|
188
|
+
|
|
189
|
+
If you would like to import `.properties` directly using `import`, this package provides integrations for all major bundlers: **Webpack/Rspack**, **Rollup/Vite/Rolldown**, **esbuild**, and **Bun**.
|
|
190
|
+
|
|
191
|
+
See [BUNDLER.md](./docs/BUNDLER.md) for setup instructions and examples.
|
|
192
|
+
|
|
193
|
+
By adding these configurations you should now be able to import directly `.properties` files just like this:
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { properties as helloWorld } from './hello-world.properties'
|
|
197
|
+
|
|
198
|
+
console.dir(helloWorld)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Output:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{ "hello": "world" }
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Why another `.properties` file package?
|
|
208
|
+
|
|
209
|
+
There are over 20 similar packages available, but most are abandoned, incomplete, or not compliant with the Java specification. See our [detailed comparison](./docs/COMPARISON.md) for benchmarks, compliance tests, and a feature matrix against the top 5 packages. The short version:
|
|
210
|
+
|
|
211
|
+
- **100% Java spec compliance** — the only package (alongside `properties-parser`) to pass all test cases.
|
|
212
|
+
- **3–7x faster** than alternatives on a 10,000-entry file.
|
|
213
|
+
- **Lossless data model** — no other package preserves comments, blank lines, whitespace, and duplicate keys for round-trip editing.
|
|
214
|
+
|
|
215
|
+
Unfortunately, the `.properties` file specification is not well-documented. One reason for this is that it was originally used in Java to store configurations. Today, most applications handle this using JSON, YAML, or other modern formats because these formats are more flexible.
|
|
216
|
+
|
|
217
|
+
### So why `.properties` files?
|
|
218
|
+
|
|
219
|
+
While many options exist today to handle configurations, `.properties` files remain one of the best options 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):
|
|
220
|
+
|
|
221
|
+
| File format | Key/value based | Supports inline comments | Built for localization | Good linguistic tools support |
|
|
222
|
+
| ------------- | ---------------- | ------------------------ | ---------------------- | ----------------------------- |
|
|
223
|
+
| `.properties` | Yes | Yes | Yes (Resource Bundles) | Yes |
|
|
224
|
+
| `JSON` | No (can do more) | No (requires JSON5) | No | Depends on the schema |
|
|
225
|
+
| `YAML` | No (can do more) | Yes | No | Depends on the schema |
|
|
226
|
+
|
|
227
|
+
Having good JavaScript/TypeScript support for `.properties` files offers more internationalization (i18n) options.
|
|
228
|
+
|
|
229
|
+
### How does this package work?
|
|
230
|
+
|
|
231
|
+
Our goal is to offer parity with the Java implementation, which is the closest thing to a specification for `.properties` files. The package provides two parsing paths:
|
|
232
|
+
|
|
233
|
+
1. **`getProperties`** — a fast, functional parser optimized for the common case of converting `.properties` content to a key-value object. Uses `charCodeAt`-based scanning with zero-copy optimizations.
|
|
234
|
+
|
|
235
|
+
2. **`Properties`** — a lossless parser that produces an ordered array of typed nodes (`PropertyNode`, `CommentNode`, `BlankLineNode`). Every element in the file is preserved, enabling exact round-trip reconstruction via `format()` and flexible normalization by passing options to `format()`.
|
|
236
|
+
|
|
237
|
+
Both parsers are fully compliant with the Java `Properties` specification and produce identical key-value output. Just like Java, if a Unicode-escaped character (`\u`) is malformed, an error will be thrown.
|
|
238
|
+
|
|
239
|
+
## Contributing
|
|
240
|
+
|
|
241
|
+
See [CONTRIBUTING.md](./docs/CONTRIBUTING.md) for project principles, architecture, code style, and development commands.
|
|
242
|
+
|
|
243
|
+
## Additional references
|
|
244
|
+
|
|
245
|
+
- Java [Test Sandbox](https://codehs.com/sandbox/id/java-main-FObePj)
|
|
246
|
+
- Java's `Properties` class [documentation](https://docs.oracle.com/javase/9/docs/api/java/util/Properties.html)
|
|
247
|
+
- Java's `PropertyResourceBundle` [documentation](https://docs.oracle.com/javase/9/docs/api/java/util/PropertyResourceBundle.html)
|
|
248
|
+
- Java's Internationalization [Guide](https://docs.oracle.com/en/java/javase/18/intl/internationalization-overview.html)
|
|
249
|
+
- Wikipedia's .properties [page](https://en.wikipedia.org/wiki/.properties)
|
|
250
|
+
|
|
251
|
+
### Special mention
|
|
252
|
+
|
|
253
|
+
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.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BunPlugin } from 'bun';
|
|
2
|
+
/**
|
|
3
|
+
* Bun plugin for `.properties` files. Works with both `Bun.plugin` (runtime) and `Bun.build`
|
|
4
|
+
* (build-time).
|
|
5
|
+
*/
|
|
6
|
+
declare const bunPlugin: BunPlugin;
|
|
7
|
+
export default bunPlugin;
|
|
8
|
+
|
|
9
|
+
// Enables type recognition for direct `.properties` file imports.
|
|
10
|
+
import '../properties-file.d.ts'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"default",{enumerable:!0,get:function(){return _default}});var _nodefs=require("node:fs"),_index=require("../index.js"),bunPlugin={name:"properties-file",setup:function(e){e.onLoad({filter:/\.properties$/},function(e){var r=e.path;return{exports:{properties:(0,_index.getProperties)((0,_nodefs.readFileSync)(r,"utf8"))},loader:"object"}})}},_default=bunPlugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Plugin } from 'esbuild';
|
|
2
|
+
/**
|
|
3
|
+
* esbuild plugin for `.properties` files.
|
|
4
|
+
*
|
|
5
|
+
* @returns An esbuild plugin that transforms `.properties` imports into JavaScript modules.
|
|
6
|
+
*/
|
|
7
|
+
declare const esbuildPlugin: () => Plugin;
|
|
8
|
+
export default esbuildPlugin;
|
|
9
|
+
|
|
10
|
+
// Enables type recognition for direct `.properties` file imports.
|
|
11
|
+
import '../properties-file.d.ts'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"default",{enumerable:!0,get:function(){return _default}});var _nodefs=require("node:fs"),_index=require("../index.js"),esbuildPlugin=function(){return{name:"properties-file",setup:function(e){e.onLoad({filter:/\.properties$/},function(e){var t=e.path;return{contents:"export const properties = ".concat(JSON.stringify((0,_index.getProperties)((0,_nodefs.readFileSync)(t,"utf8"))),";"),loader:"js"}})}}},_default=esbuildPlugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Plugin } from 'rollup';
|
|
2
|
+
/**
|
|
3
|
+
* Rollup plugin for `.properties` files. Also compatible with Vite and Rolldown.
|
|
4
|
+
*
|
|
5
|
+
* @returns A Rollup plugin that transforms `.properties` imports into JavaScript modules.
|
|
6
|
+
*/
|
|
7
|
+
declare const rollupPlugin: () => Plugin;
|
|
8
|
+
export default rollupPlugin;
|
|
9
|
+
|
|
10
|
+
// Enables type recognition for direct `.properties` file imports.
|
|
11
|
+
import '../properties-file.d.ts'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"default",{enumerable:!0,get:function(){return _default}});var _index=require("../index.js"),PROPERTIES_EXTENSION=".properties",rollupPlugin=function(){return{name:"properties-file",transform:function(e,r){return-1===r.indexOf(PROPERTIES_EXTENSION,r.length-PROPERTIES_EXTENSION.length)?null:{code:"export const properties = ".concat(JSON.stringify((0,_index.getProperties)(e)),";"),map:null}}}},_default=rollupPlugin;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webpack file loader for `.properties` files. Also compatible with Rspack.
|
|
3
|
+
*
|
|
4
|
+
* @param content - The content of a `.properties` file.
|
|
5
|
+
*
|
|
6
|
+
* @returns A CommonJS module string exporting the parsed key-value pairs.
|
|
7
|
+
*/
|
|
8
|
+
declare const webpackLoader: (content: string) => string;
|
|
9
|
+
export default webpackLoader;
|
|
10
|
+
|
|
11
|
+
// Enables type recognition for direct `.properties` file imports.
|
|
12
|
+
import '../properties-file.d.ts'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"default",{enumerable:!0,get:function(){return _default}});var _index=require("../index.js"),webpackLoader=function(e){return"exports.properties = ".concat(JSON.stringify((0,_index.getProperties)(e)),";")},_default=webpackLoader;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Tab character code. */
|
|
2
|
+
export declare const CH_TAB = 9;
|
|
3
|
+
/** Line feed character code. */
|
|
4
|
+
export declare const CH_LF = 10;
|
|
5
|
+
/** Form feed character code. */
|
|
6
|
+
export declare const CH_FF = 12;
|
|
7
|
+
/** Carriage return character code. */
|
|
8
|
+
export declare const CH_CR = 13;
|
|
9
|
+
/** Space character code. */
|
|
10
|
+
export declare const CH_SPACE = 32;
|
|
11
|
+
/** Exclamation mark character code (comment delimiter). */
|
|
12
|
+
export declare const CH_BANG = 33;
|
|
13
|
+
/** Hash character code (comment delimiter). */
|
|
14
|
+
export declare const CH_HASH = 35;
|
|
15
|
+
/** Colon character code (separator). */
|
|
16
|
+
export declare const CH_COLON = 58;
|
|
17
|
+
/** Equals character code (separator). */
|
|
18
|
+
export declare const CH_EQUALS = 61;
|
|
19
|
+
/** Backslash character code (escape / continuation). */
|
|
20
|
+
export declare const CH_BACKSLASH = 92;
|
|
21
|
+
/** Lowercase 'f' character code (formfeed escape). */
|
|
22
|
+
export declare const CH_LOWER_F = 102;
|
|
23
|
+
/** Lowercase 'n' character code (newline escape). */
|
|
24
|
+
export declare const CH_LOWER_N = 110;
|
|
25
|
+
/** Lowercase 'r' character code (carriage return escape). */
|
|
26
|
+
export declare const CH_LOWER_R = 114;
|
|
27
|
+
/** Lowercase 't' character code (tab escape). */
|
|
28
|
+
export declare const CH_LOWER_T = 116;
|
|
29
|
+
/** Lowercase 'u' character code (unicode escape). */
|
|
30
|
+
export declare const CH_LOWER_U = 117;
|
|
31
|
+
/** Byte Order Mark character code. */
|
|
32
|
+
export declare const CH_BOM = 65279;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";function _export(_,C){for(var e in C)Object.defineProperty(_,e,{enumerable:!0,get:Object.getOwnPropertyDescriptor(C,e).get})}Object.defineProperty(exports,"__esModule",{value:!0}),_export(exports,{get CH_BACKSLASH(){return CH_BACKSLASH},get CH_BANG(){return CH_BANG},get CH_BOM(){return CH_BOM},get CH_COLON(){return CH_COLON},get CH_CR(){return CH_CR},get CH_EQUALS(){return CH_EQUALS},get CH_FF(){return CH_FF},get CH_HASH(){return CH_HASH},get CH_LF(){return CH_LF},get CH_LOWER_F(){return CH_LOWER_F},get CH_LOWER_N(){return CH_LOWER_N},get CH_LOWER_R(){return CH_LOWER_R},get CH_LOWER_T(){return CH_LOWER_T},get CH_LOWER_U(){return CH_LOWER_U},get CH_SPACE(){return CH_SPACE},get CH_TAB(){return CH_TAB}});var CH_TAB=9,CH_LF=10,CH_FF=12,CH_CR=13,CH_SPACE=32,CH_BANG=33,CH_HASH=35,CH_COLON=58,CH_EQUALS=61,CH_BACKSLASH=92,CH_LOWER_F=102,CH_LOWER_N=110,CH_LOWER_R=114,CH_LOWER_T=116,CH_LOWER_U=117,CH_BOM=65279;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { Properties } from '../parser/properties.js';
|
|
2
|
+
import type { PropertyNode } from '../parser/nodes.js';
|
|
3
|
+
/** Characters that can be used as key-value pair separators. */
|
|
4
|
+
export type KeyValuePairSeparator = '=' | ':' | ' ';
|
|
5
|
+
/** Characters that can be used as comment delimiters. */
|
|
6
|
+
export type CommentDelimiter = '#' | '!';
|
|
7
|
+
/** Options for {@link PropertiesEditor.insert}. */
|
|
8
|
+
export type InsertOptions = {
|
|
9
|
+
/**
|
|
10
|
+
* Insert relative to this key (last occurrence). If the key is not found,
|
|
11
|
+
* the property is appended at the end.
|
|
12
|
+
*/
|
|
13
|
+
referenceKey?: string;
|
|
14
|
+
/** Position relative to the reference key. Default: `'after'`. */
|
|
15
|
+
position?: 'before' | 'after';
|
|
16
|
+
/** If `true`, escape non-ASCII characters as `\\uXXXX` sequences. Default: `false`. */
|
|
17
|
+
escapeUnicode?: boolean;
|
|
18
|
+
/** Separator character to use between key and value. Default: `'='`. */
|
|
19
|
+
separator?: KeyValuePairSeparator;
|
|
20
|
+
/**
|
|
21
|
+
* Comment text to prepend before the property. Supports multi-line: newlines
|
|
22
|
+
* in the string create separate comment nodes. Empty lines within the text
|
|
23
|
+
* become blank line nodes.
|
|
24
|
+
*/
|
|
25
|
+
comment?: string;
|
|
26
|
+
/** Delimiter character for the comment. Default: `'#'`. */
|
|
27
|
+
commentDelimiter?: CommentDelimiter;
|
|
28
|
+
};
|
|
29
|
+
/** Options for {@link PropertiesEditor.insertComment}. */
|
|
30
|
+
export type InsertCommentOptions = {
|
|
31
|
+
/**
|
|
32
|
+
* Insert relative to this key (last occurrence). If the key is not found,
|
|
33
|
+
* the comment is appended at the end.
|
|
34
|
+
*/
|
|
35
|
+
referenceKey?: string;
|
|
36
|
+
/** Position relative to the reference key. Default: `'after'`. */
|
|
37
|
+
position?: 'before' | 'after';
|
|
38
|
+
/** Delimiter character for the comment. Default: `'#'`. */
|
|
39
|
+
commentDelimiter?: CommentDelimiter;
|
|
40
|
+
};
|
|
41
|
+
/** Options for {@link PropertiesEditor.insertBlankLine}. */
|
|
42
|
+
export type InsertBlankLineOptions = {
|
|
43
|
+
/**
|
|
44
|
+
* Insert relative to this key (last occurrence). If the key is not found,
|
|
45
|
+
* the blank line is appended at the end.
|
|
46
|
+
*/
|
|
47
|
+
referenceKey?: string;
|
|
48
|
+
/** Position relative to the reference key. Default: `'after'`. */
|
|
49
|
+
position?: 'before' | 'after';
|
|
50
|
+
};
|
|
51
|
+
/** Options for {@link PropertiesEditor.update}. */
|
|
52
|
+
export type UpdateOptions = {
|
|
53
|
+
/** Replacement value. When not set, the original value is preserved. */
|
|
54
|
+
newValue?: string;
|
|
55
|
+
/** Replacement key (rename). When not set, the original key is preserved. */
|
|
56
|
+
newKey?: string;
|
|
57
|
+
/** If `true`, escape non-ASCII characters as `\\uXXXX` sequences. Default: `false`. */
|
|
58
|
+
escapeUnicode?: boolean;
|
|
59
|
+
/** New separator character. When not set, the original separator is preserved. */
|
|
60
|
+
separator?: KeyValuePairSeparator;
|
|
61
|
+
/**
|
|
62
|
+
* Replacement comment text. When set, all comment and blank line nodes immediately
|
|
63
|
+
* preceding the property (up to the previous property) are removed and replaced
|
|
64
|
+
* with the new comment. Supports multi-line via newlines in the string.
|
|
65
|
+
*/
|
|
66
|
+
newComment?: string;
|
|
67
|
+
/** Delimiter character for the new comment. Default: `'#'`. */
|
|
68
|
+
commentDelimiter?: CommentDelimiter;
|
|
69
|
+
};
|
|
70
|
+
/** Options for {@link PropertiesEditor.upsert}. */
|
|
71
|
+
export type UpsertOptions = {
|
|
72
|
+
/** If `true`, escape non-ASCII characters as `\\uXXXX` sequences. Default: `false`. */
|
|
73
|
+
escapeUnicode?: boolean;
|
|
74
|
+
/** Separator character. Default: `'='`. */
|
|
75
|
+
separator?: KeyValuePairSeparator;
|
|
76
|
+
/**
|
|
77
|
+
* Comment text. When inserting a new property, this is prepended as a comment.
|
|
78
|
+
* When updating an existing property, this replaces the leading comment nodes.
|
|
79
|
+
*/
|
|
80
|
+
comment?: string;
|
|
81
|
+
/** Delimiter character for the comment. Default: `'#'`. */
|
|
82
|
+
commentDelimiter?: CommentDelimiter;
|
|
83
|
+
};
|
|
84
|
+
/** Options for {@link PropertiesEditor.delete}. */
|
|
85
|
+
export type DeleteOptions = {
|
|
86
|
+
/**
|
|
87
|
+
* If `false`, only the property node itself is removed. If `true` (default),
|
|
88
|
+
* all comment and blank line nodes immediately preceding the property (up to
|
|
89
|
+
* the previous property) are also removed.
|
|
90
|
+
*/
|
|
91
|
+
deleteLeadingNodes?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Which occurrence of the key to delete when duplicates exist.
|
|
94
|
+
* - `'last'` (default) — deletes the last occurrence (the effective value in
|
|
95
|
+
* Java's last-wins semantics).
|
|
96
|
+
* - `'first'` — deletes the first occurrence. Useful for cleaning up duplicate
|
|
97
|
+
* keys while keeping the effective value.
|
|
98
|
+
*/
|
|
99
|
+
occurrence?: 'first' | 'last';
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* An editor for `.properties` files that extends the lossless {@link Properties}
|
|
103
|
+
* parser with insert, update, delete, and upsert operations.
|
|
104
|
+
*/
|
|
105
|
+
export declare class PropertiesEditor extends Properties {
|
|
106
|
+
/**
|
|
107
|
+
* Find the first property node with the given key.
|
|
108
|
+
*
|
|
109
|
+
* @param key - The unescaped key to search for.
|
|
110
|
+
*
|
|
111
|
+
* @returns The matching node and its index in `this.nodes`, or `undefined`.
|
|
112
|
+
*/
|
|
113
|
+
private findFirstProperty;
|
|
114
|
+
/**
|
|
115
|
+
* Find the last property node with the given key.
|
|
116
|
+
*
|
|
117
|
+
* @param key - The unescaped key to search for.
|
|
118
|
+
*
|
|
119
|
+
* @returns The matching node and its index in `this.nodes`, or `undefined`.
|
|
120
|
+
*/
|
|
121
|
+
private findLastProperty;
|
|
122
|
+
/**
|
|
123
|
+
* Insert a new property.
|
|
124
|
+
*
|
|
125
|
+
* @param key - The unescaped key.
|
|
126
|
+
* @param value - The unescaped value.
|
|
127
|
+
* @param options - Insert options.
|
|
128
|
+
*/
|
|
129
|
+
insert(key: string, value: string, options?: InsertOptions): void;
|
|
130
|
+
/**
|
|
131
|
+
* Insert a comment.
|
|
132
|
+
*
|
|
133
|
+
* @param comment - The comment text (may contain newlines).
|
|
134
|
+
* @param options - Insert comment options.
|
|
135
|
+
*/
|
|
136
|
+
insertComment(comment: string, options?: InsertCommentOptions): void;
|
|
137
|
+
/**
|
|
138
|
+
* Insert a blank line.
|
|
139
|
+
*
|
|
140
|
+
* @param options - Insert blank line options.
|
|
141
|
+
*/
|
|
142
|
+
insertBlankLine(options?: InsertBlankLineOptions): void;
|
|
143
|
+
/**
|
|
144
|
+
* Update an existing property.
|
|
145
|
+
*
|
|
146
|
+
* @param key - The unescaped key to update (uses last occurrence).
|
|
147
|
+
* @param options - Update options.
|
|
148
|
+
*
|
|
149
|
+
* @returns `true` if the property was found and updated, `false` otherwise.
|
|
150
|
+
*/
|
|
151
|
+
update(key: string, options: UpdateOptions): boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Update a property if it exists, or insert it if it doesn't.
|
|
154
|
+
*
|
|
155
|
+
* @param key - The unescaped key.
|
|
156
|
+
* @param value - The unescaped value.
|
|
157
|
+
* @param options - Upsert options.
|
|
158
|
+
*/
|
|
159
|
+
upsert(key: string, value: string, options?: UpsertOptions): void;
|
|
160
|
+
/**
|
|
161
|
+
* Delete an occurrence of a property.
|
|
162
|
+
*
|
|
163
|
+
* By default, deletes the last occurrence (the effective value in Java's last-wins
|
|
164
|
+
* semantics). Use `{ occurrence: 'first' }` to delete the first occurrence instead,
|
|
165
|
+
* which is useful for cleaning up duplicate keys while keeping the effective value.
|
|
166
|
+
*
|
|
167
|
+
* @param key - The unescaped key to delete.
|
|
168
|
+
* @param options - Delete options.
|
|
169
|
+
*
|
|
170
|
+
* @returns The deleted {@link PropertyNode}, or `undefined` if the key was not found.
|
|
171
|
+
*/
|
|
172
|
+
delete(key: string, options?: DeleteOptions): PropertyNode | undefined;
|
|
173
|
+
/**
|
|
174
|
+
* Delete all occurrences of a key.
|
|
175
|
+
*
|
|
176
|
+
* @param key - The unescaped key to delete.
|
|
177
|
+
*
|
|
178
|
+
* @returns An array of the deleted {@link PropertyNode} instances.
|
|
179
|
+
*/
|
|
180
|
+
deleteAll(key: string): PropertyNode[];
|
|
181
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"PropertiesEditor",{enumerable:!0,get:function(){return PropertiesEditor}});var _index=require("../escape/index.js"),_properties=require("../parser/properties.js");function _instanceof(e,r){return null!=r&&"undefined"!=typeof Symbol&&r[Symbol.hasInstance]?!!r[Symbol.hasInstance](e):e instanceof r}function _array_like_to_array(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,n=new Array(r);t<r;t++)n[t]=e[t];return n}function _array_without_holes(e){if(Array.isArray(e))return _array_like_to_array(e)}function _assert_this_initialized(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function _call_super(e,r,t){return r=_get_prototype_of(r),_possible_constructor_return(e,_is_native_reflect_construct()?Reflect.construct(r,t||[],_get_prototype_of(e).constructor):r.apply(e,t))}function _class_call_check(e,r){if(!_instanceof(e,r))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,r){for(var t=0;t<r.length;t++){var n=r[t];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function _create_class(e,r,t){return r&&_defineProperties(e.prototype,r),t&&_defineProperties(e,t),e}function _get_prototype_of(e){return _get_prototype_of=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},_get_prototype_of(e)}function _inherits(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(r&&r.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),r&&_set_prototype_of(e,r)}function _is_native_reflect_construct(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(_is_native_reflect_construct=function(){return!!e})()}function _iterable_to_array(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function _non_iterable_spread(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _possible_constructor_return(e,r){return!r||"object"!==_type_of(r)&&"function"!=typeof r?_assert_this_initialized(e):r}function _set_prototype_of(e,r){return _set_prototype_of=Object.setPrototypeOf||function(e,r){return e.__proto__=r,e},_set_prototype_of(e,r)}function _to_consumable_array(e){return _array_without_holes(e)||_iterable_to_array(e)||_unsupported_iterable_to_array(e)||_non_iterable_spread()}function _type_of(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e}function _unsupported_iterable_to_array(e,r){if(e){if("string"==typeof e)return _array_like_to_array(e,r);var t=Object.prototype.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(t):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_array_like_to_array(e,r):void 0}}var DEFAULT_SEPARATOR="=",DEFAULT_COMMENT_DELIMITER="#",REGEX_NEWLINE=/\r\n|\r|\n/,buildPropertyNode=function(e,r,t,n){var o,i=!0===t.escapeUnicode,a=(0,_index.escapeKey)(e,i),s=(0,_index.escapeValue)(r,i),l=" "===t.separator?void 0:null!==(o=t.separator)&&void 0!==o?o:DEFAULT_SEPARATOR,c=l?" ":"",u=l?"".concat(" ").concat(l).concat(c):" ",p="".concat(a).concat(u).concat(s).split(REGEX_NEWLINE);return{type:"property",rawLines:p,leadingWhitespace:"",key:e,escapedKey:a,separatorLeading:" ",separatorChar:l,separatorTrailing:c,value:r,escapedValue:s,startingLineNumber:n,endingLineNumber:n+p.length-1}},buildCommentNodes=function(e,r,t){return e.split(REGEX_NEWLINE).map(function(e,n){return""===e?{type:"blank",rawLine:"",lineNumber:t+n}:{type:"comment",rawLine:"".concat(r," ").concat(e),leadingWhitespace:"",delimiter:r,body:" ".concat(e),lineNumber:t+n}})},recalculateLineNumbers=function(e){for(var r=1,t=0;t<e.length;t++){var n=e[t];if("property"===n.type){var o=n.rawLines.length;e[t]={type:"property",rawLines:n.rawLines,leadingWhitespace:n.leadingWhitespace,key:n.key,escapedKey:n.escapedKey,separatorLeading:n.separatorLeading,separatorChar:n.separatorChar,separatorTrailing:n.separatorTrailing,value:n.value,escapedValue:n.escapedValue,startingLineNumber:r,endingLineNumber:r+o-1},r+=o}else"comment"===n.type?(e[t]={type:"comment",rawLine:n.rawLine,leadingWhitespace:n.leadingWhitespace,delimiter:n.delimiter,body:n.body,lineNumber:r},r++):(e[t]={type:"blank",rawLine:n.rawLine,lineNumber:r},r++)}},PropertiesEditor=function(){function e(){return _class_call_check(this,e),_call_super(this,e,arguments)}return _inherits(e,_properties.Properties),_create_class(e,[{key:"findFirstProperty",value:function(e){for(var r=0;r<this.nodes.length;r++){var t=this.nodes[r];if("property"===t.type&&t.key===e)return{index:r,node:t}}}},{key:"findLastProperty",value:function(e){for(var r=this.nodes.length-1;r>=0;r--){var t=this.nodes[r];if("property"===t.type&&t.key===e)return{index:r,node:t}}}},{key:"insert",value:function(e,r,t){var n,o,i=[];if(void 0!==(null==t?void 0:t.comment)){var a,s=null!==(o=t.commentDelimiter)&&void 0!==o?o:DEFAULT_COMMENT_DELIMITER;(a=i).push.apply(a,_to_consumable_array(buildCommentNodes(t.comment,s,0)))}if(i.push(buildPropertyNode(e,r,{escapeUnicode:null==t?void 0:t.escapeUnicode,separator:null==t?void 0:t.separator},0)),null==t?void 0:t.referenceKey){var l=this.findLastProperty(t.referenceKey);if(void 0!==l){var c,u="before"===t.position?l.index:l.index+1;return(c=this.nodes).splice.apply(c,[u,0].concat(_to_consumable_array(i))),void recalculateLineNumbers(this.nodes)}}(n=this.nodes).push.apply(n,_to_consumable_array(i)),recalculateLineNumbers(this.nodes)}},{key:"insertComment",value:function(e,r){var t,n,o=null!==(n=null==r?void 0:r.commentDelimiter)&&void 0!==n?n:DEFAULT_COMMENT_DELIMITER,i=buildCommentNodes(e,o,0);if(null==r?void 0:r.referenceKey){var a=this.findLastProperty(r.referenceKey);if(void 0!==a){var s,l="before"===r.position?a.index:a.index+1;return(s=this.nodes).splice.apply(s,[l,0].concat(_to_consumable_array(i))),void recalculateLineNumbers(this.nodes)}}(t=this.nodes).push.apply(t,_to_consumable_array(i)),recalculateLineNumbers(this.nodes)}},{key:"insertBlankLine",value:function(e){var r={type:"blank",rawLine:"",lineNumber:0};if(null==e?void 0:e.referenceKey){var t=this.findLastProperty(e.referenceKey);if(void 0!==t){var n="before"===e.position?t.index:t.index+1;return this.nodes.splice(n,0,r),void recalculateLineNumbers(this.nodes)}}this.nodes.push(r),recalculateLineNumbers(this.nodes)}},{key:"update",value:function(e,r){var t,n,o,i=this.findLastProperty(e);if(void 0===i)return!1;var a=i.index,s=i.node,l=null!==(t=r.newKey)&&void 0!==t?t:s.key,c=null!==(n=r.newValue)&&void 0!==n?n:s.value,u=!0===r.escapeUnicode,p=u?(0,_index.escapeKey)(l,!0):void 0!==r.newKey?(0,_index.escapeKey)(l):s.escapedKey,d=u?(0,_index.escapeValue)(c,!0):void 0!==r.newValue?(0,_index.escapeValue)(c):s.escapedValue,_=r.separator?" "===r.separator?void 0:r.separator:s.separatorChar,y=r.separator?" ":s.separatorLeading,f=r.separator?_?" ":"":s.separatorTrailing,m=_?"".concat(y).concat(_).concat(f):y,v="".concat(p).concat(m).concat(d).split(REGEX_NEWLINE),h={type:"property",rawLines:v,leadingWhitespace:s.leadingWhitespace,key:l,escapedKey:p,separatorLeading:y,separatorChar:_,separatorTrailing:f,value:c,escapedValue:d,startingLineNumber:s.startingLineNumber,endingLineNumber:s.startingLineNumber+v.length-1};if(void 0!==r.newComment){for(var b,L=a,g=a-1;g>=0&&"property"!==this.nodes[g].type;g--)L=g;var E=null!==(o=r.commentDelimiter)&&void 0!==o?o:DEFAULT_COMMENT_DELIMITER,N=buildCommentNodes(r.newComment,E,0);(b=this.nodes).splice.apply(b,[L,a-L+1].concat(_to_consumable_array(N),[h]))}else this.nodes[a]=h;return recalculateLineNumbers(this.nodes),!0}},{key:"upsert",value:function(e,r,t){void 0!==this.findLastProperty(e)?this.update(e,{newValue:r,escapeUnicode:null==t?void 0:t.escapeUnicode,separator:null==t?void 0:t.separator,newComment:null==t?void 0:t.comment,commentDelimiter:null==t?void 0:t.commentDelimiter}):this.insert(e,r,t)}},{key:"delete",value:function(e,r){var t="first"===(null==r?void 0:r.occurrence)?this.findFirstProperty(e):this.findLastProperty(e);if(void 0!==t){var n=t.index,o=t.node;if(!1!==(null==r?void 0:r.deleteLeadingNodes)){for(var i=n,a=n-1;a>=0&&"property"!==this.nodes[a].type;a--)i=a;this.nodes.splice(i,n-i+1)}else this.nodes.splice(n,1);return recalculateLineNumbers(this.nodes),o}}},{key:"deleteAll",value:function(e){for(var r=[],t=this.nodes.length-1;t>=0;t--){var n=this.nodes[t];"property"===n.type&&n.key===e&&(this.nodes.splice(t,1),r.push(n))}return r.length>0&&recalculateLineNumbers(this.nodes),r.reverse()}}]),e}();
|
|
@@ -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
|
+
* @returns 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
|
+
* @returns The escaped value.
|
|
17
|
+
*/
|
|
18
|
+
export declare const escapeValue: (unescapedValue: string, escapeUnicode?: boolean) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";function _export(e,t){for(var r in t)Object.defineProperty(e,r,{enumerable:!0,get:Object.getOwnPropertyDescriptor(t,r).get})}Object.defineProperty(exports,"__esModule",{value:!0}),_export(exports,{get escapeKey(){return escapeKey},get escapeValue(){return escapeValue}});var escapeKey=function(e){return escapeContent(e,!0,arguments.length>1&&void 0!==arguments[1]&&arguments[1])},escapeValue=function(e){return escapeContent(e,!1,arguments.length>1&&void 0!==arguments[1]&&arguments[1])},REGEX_ESCAPE_NO_UNICODE=/[\s!#:=\\]/g,REGEX_ESCAPE_UNICODE=/[\s!#:=\\\u0000-\u001F\u007F-\uFFFF]/g,escapeContent=function(e,t,r){var n=r?REGEX_ESCAPE_UNICODE:REGEX_ESCAPE_NO_UNICODE;return n.lastIndex=0,e.replace(n,function(e,r){switch(e){case" ":return t||0===r?"\\ ":" ";case"\\":return"\\\\";case"\f":return"\\f";case"\n":return"\\n";case"\r":return"\\r";case"\t":return"\\t";case"=":case":":case"#":case"!":return"\\".concat(e);default:return"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)}})};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A key-value pair object.
|
|
3
|
+
*/
|
|
4
|
+
export type KeyValuePairObject = Record<string, string>;
|
|
5
|
+
/**
|
|
6
|
+
* Converts the content of a `.properties` file to a key-value pair object.
|
|
7
|
+
*
|
|
8
|
+
* This is a self-contained, zero-dependency parser optimized for minimal
|
|
9
|
+
* bundle size. It implements the Java `java.util.Properties` specification:
|
|
10
|
+
*
|
|
11
|
+
* - BOM detection and skipping
|
|
12
|
+
* - Comment lines (`#` or `!`)
|
|
13
|
+
* - Line continuations (trailing odd backslash)
|
|
14
|
+
* - Key-value separator detection (`=`, `:`, or whitespace)
|
|
15
|
+
* - Escape sequence processing (`\\n`, `\\t`, `\\r`, `\\f`, `\\\\`, `\\uXXXX`)
|
|
16
|
+
* - Last-value-wins semantics for duplicate keys
|
|
17
|
+
*
|
|
18
|
+
* @param content - The content of a `.properties` file.
|
|
19
|
+
*
|
|
20
|
+
* @returns A key/value object representing the content of a `.properties` file.
|
|
21
|
+
*/
|
|
22
|
+
export declare const getProperties: (content: string | Buffer) => KeyValuePairObject;
|
|
23
|
+
|
|
24
|
+
// Enables type recognition for direct `.properties` file imports.
|
|
25
|
+
import './properties-file.d.ts'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"getProperties",{enumerable:!0,get:function(){return q}});var _=function(e){return e>=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1},S=function(e){if(-1===e.indexOf("\\"))return e;for(var r=e.length,a="",t=0,c=0;c<r;)if(92===e.charCodeAt(c)){if(c>t&&(a+=e.slice(t,c)),++c>=r){a+="\\",t=c;break}switch(e.charCodeAt(c)){case 110:a+="\n",c++;break;case 116:a+="\t",c++;break;case 114:a+="\r",c++;break;case 102:a+="\f",c++;break;case 117:if(c+4>=r)throw new Error("malformed escaped unicode characters '".concat(e.slice(c-1,c+5),"'"));var o=_(e.charCodeAt(c+1)),i=_(e.charCodeAt(c+2)),n=_(e.charCodeAt(c+3)),f=_(e.charCodeAt(c+4));if(o<0||i<0||n<0||f<0)throw new Error("malformed escaped unicode characters '".concat(e.slice(c-1,c+5),"'"));a+=String.fromCharCode(o<<12|i<<8|n<<4|f),c+=5;break;default:a+=e.charAt(c),c++}t=c}else c++;return t<r&&(a+=e.slice(t,r)),a},H=function(e,r,a){for(;r<a;){var t=e.charCodeAt(r);if(32!==t&&9!==t&&12!==t)break;r++}return r},q=function(e){for(var r="string"==typeof e?e:e.toString(),a={},t=(r.length>0&&65279===r.charCodeAt(0)?r.slice(1):r).split(/\r\n|\r|\n/),c=t.length,o=0;o<c;){var i=t[o],n=i.length,f=H(i,0,n);if(f>=n)o++;else{var s=i.charCodeAt(f);if(35!==s&&33!==s){for(var d=0,l=n-1;l>=0&&92===i.charCodeAt(l);l--)d++;var h=d%2==1,v=void 0,u=void 0;if(h){var C=(f>0?i.slice(f):i).slice(0,-1),A=[C];for(u=-1!==C.indexOf("\\");h&&o+1<c;){var b=t[++o],g=b.length,p=H(b,0,g);d=0;for(var k=g-1;k>=p&&92===b.charCodeAt(k);k--)d++;var _=(h=d%2==1)?b.slice(p,g-1):b.slice(p);!u&&-1!==_.indexOf("\\")&&(u=!0),A.push(_)}v=A.join("")}else u=-1!==(v=f>0?i.slice(f):i).indexOf("\\");for(var m=v.length,x=0,O=!1;x<m;){var w=v.charCodeAt(x);if(92!==w){if(!O&&(61===w||58===w||32===w||9===w||12===w))break;O=!1,x++}else O=!O,x++}var j=x;if(j<m){var y=v.charCodeAt(j);(32===y||9===y||12===y)&&((j=H(v,j,m))<m&&(y=v.charCodeAt(j))),j<m&&(61===y||58===y)&&(j++,j=H(v,j,m))}var P=v.slice(0,x),q=v.slice(j);a[u?S(P):P]=u?S(q):q,o++}else o++}}return a};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "type": "commonjs" }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";function _export(e,r){for(var t in r)Object.defineProperty(e,t,{enumerable:!0,get:Object.getOwnPropertyDescriptor(r,t).get})}Object.defineProperty(exports,"__esModule",{value:!0}),_export(exports,{get Properties(){return _properties.Properties},get PropertiesNodeType(){return _nodes.PropertiesNodeType}});var _properties=require("./properties.js"),_nodes=require("./nodes.js");
|