Skip to content

Commit

Permalink
fix: cases where jsonString endswith incomplete \u escape sequence
Browse files Browse the repository at this point in the history
chore: add publish workflow and `jsr` configurations
  • Loading branch information
CNSeniorious000 committed May 14, 2024
1 parent 86f5289 commit 7d4444c
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 5 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: publish

on: [push, workflow_dispatch]

jobs:
jsr:
runs-on: ubuntu-latest

permissions:
contents: read
id-token: write

steps:
- uses: actions/checkout@v4

- name: Publish package
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
npx jsr publish --allow-slow-types
else
npx jsr publish --allow-slow-types --dry-run
fi
npm:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "22.x"
registry-url: "https://registry.npmjs.org"

- run: |
npm install
npm run build
- env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
npm publish --provenance --access public
else
npm publish --provenance --access public --dry-run
fi
11 changes: 11 additions & 0 deletions jsr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "@promplate/partial-json",
"version": "0.1.7",
"exports": {
".": "./src/index.ts",
"./options": "./src/options.ts"
},
"publish": {
"include": ["src", "README.md", "LICENSE", "jsr.json"]
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "partial-json",
"version": "0.1.6",
"version": "0.1.7",
"description": "Parse partial JSON generated by LLM",
"keywords": [
"JSON",
Expand Down
12 changes: 8 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ class PartialJSON extends Error { }

class MalformedJSON extends Error { }

/** Partial JSON parser
/**
* Parse incomplete JSON
* @param {string} jsonString Partial JSON to be parsed
* @param {number} allowPartial Specify what kind of partialness is allowed during JSON parsing
* @param {number} allowPartial Specify what types are allowed to be partial, see {@link Allow} for details
* @returns The parsed JSON
* @throws {PartialJSON} If the JSON is incomplete (related to the `allow` parameter)
* @throws {MalformedJSON} If the JSON is malformed
*/
const parseJSON = (jsonString: string, allowPartial: number = Allow.ALL) => {
function parseJSON(jsonString: string, allowPartial: number = Allow.ALL): any {
if (typeof jsonString !== "string") {
throw new TypeError(`expecting str, got ${typeof jsonString}`);
}
Expand Down Expand Up @@ -83,7 +87,7 @@ const _parseJSON = (jsonString: string, allow: number) => {
return JSON.parse(jsonString.substring(start, index - Number(escape)) + '"');
} catch (e) {
// SyntaxError: Invalid escape sequence
return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("\\", Math.max(0, index - 5))) + '"');
return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("\\")) + '"');
}
}
markPartialJSON("Unterminated string literal");
Expand Down
62 changes: 62 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,53 @@
/**
* Sometimes you don't allow every type to be partially parsed.
* For example, you may not want a partial number because it may increase its size gradually before it's complete.
* In this case, you can use the `Allow` object to control what types you allow to be partially parsed.
* @module
*/

/**
* allow partial strings like `"hello \u12` to be parsed as `"hello "`
*/
export const STR = 0b000000001;

/**
* allow partial numbers like `123.` to be parsed as `123`
*/
export const NUM = 0b000000010;

/**
* allow partial arrays like `[1, 2,` to be parsed as `[1, 2]`
*/
export const ARR = 0b000000100;

/**
* allow partial objects like `{"a": 1, "b":` to be parsed as `{"a": 1}`
*/
export const OBJ = 0b000001000;

/**
* allow `nu` to be parsed as `null`
*/
export const NULL = 0b000010000;

/**
* allow `tr` to be parsed as `true`, and `fa` to be parsed as `false`
*/
export const BOOL = 0b000100000;

/**
* allow `Na` to be parsed as `NaN`
*/
export const NAN = 0b001000000;

/**
* allow `Inf` to be parsed as `Infinity`
*/
export const INFINITY = 0b010000000;

/**
* allow `-Inf` to be parsed as `-Infinity`
*/
export const _INFINITY = 0b100000000;

export const INF = INFINITY | _INFINITY;
Expand All @@ -14,6 +56,26 @@ export const ATOM = STR | NUM | SPECIAL;
export const COLLECTION = ARR | OBJ;
export const ALL = ATOM | COLLECTION;

/**
* Control what types you allow to be partially parsed.
* The default is to allow all types to be partially parsed, which in most casees is the best option.
* @example
* If you don't want to allow partial objects, you can use the following code:
* ```ts
* import { Allow, parse } from "partial-json";
* parse(`[{"a": 1, "b": 2}, {"a": 3,`, Allow.ARR); // [ { a: 1, b: 2 } ]
* ```
* Or you can use `~` to disallow a type:
* ```ts
* parse(`[{"a": 1, "b": 2}, {"a": 3,`, ~Allow.OBJ); // [ { a: 1, b: 2 } ]
* ```
* @example
* If you don't want to allow partial strings, you can use the following code:
* ```ts
* import { Allow, parse } from "partial-json";
* parse(`["complete string", "incompl`, ~Allow.STR); // [ 'complete string' ]
* ```
*/
export const Allow = { STR, NUM, ARR, OBJ, NULL, BOOL, NAN, INFINITY, _INFINITY, INF, SPECIAL, ATOM, COLLECTION, ALL };

export default Allow;
1 change: 1 addition & 0 deletions tests/examples.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { test, expect } from "vitest";

test("str", () => {
expect(parse('"', STR)).toBe("");
expect(parse('" \\x12', STR)).toBe(" ");
expect(() => parse('"', ~STR)).toThrow(PartialJSON);
});

Expand Down

1 comment on commit 7d4444c

@vercel
Copy link

@vercel vercel bot commented on 7d4444c May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.