Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ jobs:
timeout-minutes: 30

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- uses: denoland/setup-deno@v2
with:
deno-version: canary
- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: "22.x"
node-version: "24.x"
registry-url: "https://registry.npmjs.org"

- name: build
Expand All @@ -53,8 +53,6 @@ jobs:
run: deno run -A jsr:@david/publish-on-tag@0.2.0
- name: npm publish
if: startsWith(github.ref, 'refs/tags/')
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
cd npm
npm publish --provenance --access public
npm publish --access public
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 52 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,19 @@ npm install jsonc-morph
## Example

```ts
import { parse } from "@david/jsonc-morph";
import { parse, parseToValue } from "@david/jsonc-morph";

// parse directly to a plain JavaScript value
const config = parseToValue(`{
// database settings
"host": "localhost",
"port": 5432
}`);

console.log(config.host); // "localhost"
console.log(config.port); // 5432

// parse to a CST for programmatic editing
const root = parse(`{
// 1
"data" /* 2 */: 123 // 3
Expand Down Expand Up @@ -56,3 +67,43 @@ assertEquals(
} // 4`,
);
```

## Options and strict parsing

By default, `parse` and `parseToValue` allow more than just JSONC (comments,
trailing commas, single-quoted strings, hexadecimal numbers, etc.). You can
customize this behaviour by passing options:

```ts
import { parse, parseToValue } from "@david/jsonc-morph";

// Disable specific extensions
const root = parse(text, {
allowComments: false, // Reject // and /* */ comments
allowTrailingCommas: false, // Reject trailing commas in arrays/objects
allowSingleQuotedStrings: false, // Reject 'single quoted' strings
allowHexadecimalNumbers: false, // Reject 0xFF style numbers
allowUnaryPlusNumbers: false, // Reject +42 style numbers
allowMissingCommas: false, // Reject missing commas between elements
allowLooseObjectPropertyNames: false, // Reject unquoted property names
});

// parseToValue accepts the same options
const value = parseToValue(text, { allowComments: false });
```

For strict JSON parsing (only allow JSON), use `parseStrict` or
`parseToValueStrict`:

```ts
import { parseStrict, parseToValueStrict } from "@david/jsonc-morph";

// All extensions disabled by default
const root = parseStrict('{"name": "test"}');

// Selectively enable specific extensions
const rootWithComments = parseStrict(text, { allowComments: true });

// Same for parseToValueStrict
const value = parseToValueStrict('{"name": "test"}');
```
66 changes: 66 additions & 0 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,69 @@ export {
StringLit,
WordLit,
} from "./lib/rs_lib.js";

import {
type JsonValue,
parse,
parseToValue,
type RootNode,
} from "./lib/rs_lib.js";

/** Options for strict JSON parsing (all JSONC extensions disabled by default). */
export interface ParseStrictOptions {
/** Allow comments (defaults to `false` in strict mode). */
allowComments?: boolean;
/** Allow trailing commas (defaults to `false` in strict mode). */
allowTrailingCommas?: boolean;
/** Allow loose object property names (defaults to `false` in strict mode). */
allowLooseObjectPropertyNames?: boolean;
/** Allow missing commas (defaults to `false` in strict mode). */
allowMissingCommas?: boolean;
/** Allow single-quoted strings (defaults to `false` in strict mode). */
allowSingleQuotedStrings?: boolean;
/** Allow hexadecimal numbers (defaults to `false` in strict mode). */
allowHexadecimalNumbers?: boolean;
/** Allow unary plus on numbers (defaults to `false` in strict mode). */
allowUnaryPlusNumbers?: boolean;
}

const STRICT_DEFAULTS: Required<ParseStrictOptions> = {
allowComments: false,
allowTrailingCommas: false,
allowLooseObjectPropertyNames: false,
allowMissingCommas: false,
allowSingleQuotedStrings: false,
allowHexadecimalNumbers: false,
allowUnaryPlusNumbers: false,
};

/**
* Parses a strict JSON string into a concrete syntax tree.
* By default, all JSONC extensions are disabled (no comments, no trailing commas, etc.).
* You can selectively enable extensions by setting options to `true`.
* @param text - The JSON text to parse
* @param options - Optional parsing options (all default to `false`)
* @returns The root node of the parsed CST
*/
export function parseStrict(
text: string,
options?: ParseStrictOptions,
): RootNode {
return parse(text, { ...STRICT_DEFAULTS, ...options });
}

/**
* Parses a strict JSON string directly to a JavaScript value.
* By default, all JSONC extensions are disabled (no comments, no trailing commas, etc.).
* You can selectively enable extensions by setting options to `true`.
* @param text - The JSON text to parse
* @param options - Optional parsing options (all default to `false`)
* @returns The plain JavaScript value (object, array, string, number, boolean, or null)
* @throws If the text cannot be parsed or converted
*/
export function parseToValueStrict(
text: string,
options?: ParseStrictOptions,
): JsonValue {
return parseToValue(text, { ...STRICT_DEFAULTS, ...options });
}
Loading