quick-json5 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +66 -0
  3. package/dist/exports/Exports.d.ts +6 -0
  4. package/dist/exports/Exports.d.ts.map +1 -0
  5. package/dist/exports/Exports.js +6 -0
  6. package/dist/exports/Exports.js.map +1 -0
  7. package/dist/json/JsonEncoder.d.ts +3 -0
  8. package/dist/json/JsonEncoder.d.ts.map +1 -0
  9. package/dist/json/JsonEncoder.js +147 -0
  10. package/dist/json/JsonEncoder.js.map +1 -0
  11. package/dist/json/JsonParser.d.ts +3 -0
  12. package/dist/json/JsonParser.d.ts.map +1 -0
  13. package/dist/json/JsonParser.js +378 -0
  14. package/dist/json/JsonParser.js.map +1 -0
  15. package/dist/json5/Json5Encoder.d.ts +3 -0
  16. package/dist/json5/Json5Encoder.d.ts.map +1 -0
  17. package/dist/json5/Json5Encoder.js +155 -0
  18. package/dist/json5/Json5Encoder.js.map +1 -0
  19. package/dist/json5/Json5Parser.d.ts +3 -0
  20. package/dist/json5/Json5Parser.d.ts.map +1 -0
  21. package/dist/json5/Json5Parser.js +781 -0
  22. package/dist/json5/Json5Parser.js.map +1 -0
  23. package/dist/tests/Json5EncoderTest.d.ts +2 -0
  24. package/dist/tests/Json5EncoderTest.d.ts.map +1 -0
  25. package/dist/tests/Json5EncoderTest.js +44 -0
  26. package/dist/tests/Json5EncoderTest.js.map +1 -0
  27. package/dist/tests/Json5ParserTests.d.ts +3 -0
  28. package/dist/tests/Json5ParserTests.d.ts.map +1 -0
  29. package/dist/tests/Json5ParserTests.js +211 -0
  30. package/dist/tests/Json5ParserTests.js.map +1 -0
  31. package/dist/tests/JsonEncoderTests.d.ts +2 -0
  32. package/dist/tests/JsonEncoderTests.d.ts.map +1 -0
  33. package/dist/tests/JsonEncoderTests.js +44 -0
  34. package/dist/tests/JsonEncoderTests.js.map +1 -0
  35. package/dist/tests/JsonParserTests.d.ts +3 -0
  36. package/dist/tests/JsonParserTests.d.ts.map +1 -0
  37. package/dist/tests/JsonParserTests.js +140 -0
  38. package/dist/tests/JsonParserTests.js.map +1 -0
  39. package/dist/tests/Test.d.ts +2 -0
  40. package/dist/tests/Test.d.ts.map +1 -0
  41. package/dist/tests/Test.js +9 -0
  42. package/dist/tests/Test.js.map +1 -0
  43. package/dist/types/Types.d.ts +8 -0
  44. package/dist/types/Types.d.ts.map +1 -0
  45. package/dist/types/Types.js +2 -0
  46. package/dist/types/Types.js.map +1 -0
  47. package/dist/unused/Unused.d.ts +2 -0
  48. package/dist/unused/Unused.d.ts.map +1 -0
  49. package/dist/unused/Unused.js +47 -0
  50. package/dist/unused/Unused.js.map +1 -0
  51. package/dist/utilities/JsonParseError.d.ts +7 -0
  52. package/dist/utilities/JsonParseError.d.ts.map +1 -0
  53. package/dist/utilities/JsonParseError.js +10 -0
  54. package/dist/utilities/JsonParseError.js.map +1 -0
  55. package/dist/utilities/ObjectUtilities.d.ts +2 -0
  56. package/dist/utilities/ObjectUtilities.d.ts.map +1 -0
  57. package/dist/utilities/ObjectUtilities.js +142 -0
  58. package/dist/utilities/ObjectUtilities.js.map +1 -0
  59. package/dist/utilities/TypedArray.d.ts +4 -0
  60. package/dist/utilities/TypedArray.d.ts.map +1 -0
  61. package/dist/utilities/TypedArray.js +2 -0
  62. package/dist/utilities/TypedArray.js.map +1 -0
  63. package/dist/utilities/Utilities.d.ts +17 -0
  64. package/dist/utilities/Utilities.d.ts.map +1 -0
  65. package/dist/utilities/Utilities.js +97 -0
  66. package/dist/utilities/Utilities.js.map +1 -0
  67. package/package.json +38 -0
  68. package/src/exports/Exports.ts +7 -0
  69. package/src/json/JsonEncoder.ts +180 -0
  70. package/src/json/JsonParser.ts +491 -0
  71. package/src/json5/Json5Encoder.ts +189 -0
  72. package/src/json5/Json5Parser.ts +959 -0
  73. package/src/tests/Json5EncoderTest.ts +51 -0
  74. package/src/tests/Json5ParserTests.ts +237 -0
  75. package/src/tests/JsonEncoderTests.ts +51 -0
  76. package/src/tests/JsonParserTests.ts +159 -0
  77. package/src/tests/Test.ts +13 -0
  78. package/src/types/Types.ts +9 -0
  79. package/src/unused/Unused.ts +51 -0
  80. package/src/utilities/JsonParseError.ts +7 -0
  81. package/src/utilities/ObjectUtilities.ts +184 -0
  82. package/src/utilities/TypedArray.ts +39 -0
  83. package/src/utilities/Utilities.ts +130 -0
  84. package/tsconfig.json +55 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Types.js","sourceRoot":"","sources":["../../src/types/Types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Unused.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Unused.d.ts","sourceRoot":"","sources":["../../src/unused/Unused.ts"],"names":[],"mappings":""}
@@ -0,0 +1,47 @@
1
+ const whitespaceCharactersCharCodesSet = new Set([
2
+ // White space characters:
3
+ 0x0009, // Horizontal tab
4
+ 0x000A, // Line feed
5
+ 0x000B, // Vertical tab
6
+ 0x000C, // Form feed
7
+ 0x000D, // Carriage return
8
+ 0x0020, // Space
9
+ 0x00A0, // Non-breaking space
10
+ 0x2028, // Line separator
11
+ 0x2029, // Paragraph separator
12
+ 0xFEFF, // Byte order mark
13
+ // Unicode extended "Space Separator" category
14
+ 0x0020, // Space (SP) - already included above, but listed again in the second list
15
+ 0x00A0, // No-Break Space (NBSP) - already included above, but listed again in the second list
16
+ 0x1680, // Ogham Space Mark
17
+ 0x2000, // En Quad
18
+ 0x2001, // Em Quad
19
+ 0x2002, // En Space
20
+ 0x2003, // Em Space
21
+ 0x2004, // Three-Per-Em Space
22
+ 0x2005, // Four-Per-Em Space
23
+ 0x2006, // Six-Per-Em Space
24
+ 0x2007, // Figure Space
25
+ 0x2008, // Punctuation Space
26
+ 0x2009, // Thin Space
27
+ 0x200A, // Hair Space
28
+ 0x202F, // Narrow No-Break Space (NNBSP)
29
+ 0x205F, // Medium Mathematical Space (MMSP)
30
+ 0x3000, // Ideographic Space
31
+ ]);
32
+ export {};
33
+ // Sorted whitespace character ranges:
34
+ //
35
+ // 0x0009 - 0x000D
36
+ // 0x0020
37
+ // 0x00A0
38
+ //
39
+ // 0x1680
40
+ // 0x2000 - 0x200A
41
+ // 0x2028
42
+ // 0x2029
43
+ // 0x202F
44
+ // 0x205F
45
+ // 0x3000
46
+ // 0xFEFF
47
+ //# sourceMappingURL=Unused.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Unused.js","sourceRoot":"","sources":["../../src/unused/Unused.ts"],"names":[],"mappings":"AACA,MAAM,gCAAgC,GAAG,IAAI,GAAG,CAAC;IAChD,0BAA0B;IAC1B,MAAM,EAAE,iBAAiB;IACzB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,kBAAkB;IAC1B,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,qBAAqB;IAC7B,MAAM,EAAE,iBAAiB;IACzB,MAAM,EAAE,sBAAsB;IAC9B,MAAM,EAAE,kBAAkB;IAE1B,8CAA8C;IAC9C,MAAM,EAAE,2EAA2E;IACnF,MAAM,EAAE,sFAAsF;IAC9F,MAAM,EAAE,mBAAmB;IAC3B,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,qBAAqB;IAC7B,MAAM,EAAE,oBAAoB;IAC5B,MAAM,EAAE,mBAAmB;IAC3B,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,oBAAoB;IAC5B,MAAM,EAAE,aAAa;IACrB,MAAM,EAAE,aAAa;IACrB,MAAM,EAAE,gCAAgC;IACxC,MAAM,EAAE,mCAAmC;IAC3C,MAAM,EAAE,oBAAoB;CAC5B,CAAC,CAAA;;AAEF,sCAAsC;AACtC,EAAE;AACF,kBAAkB;AAClB,SAAS;AACT,SAAS;AACT,EAAE;AACF,SAAS;AAET,kBAAkB;AAClB,SAAS;AACT,SAAS;AACT,SAAS;AACT,SAAS;AAET,SAAS;AACT,SAAS"}
@@ -0,0 +1,7 @@
1
+ import { PositionInfo } from "./Utilities.js";
2
+ export declare class JsonParserError extends Error {
3
+ readonly message: string;
4
+ readonly positionInfo: PositionInfo;
5
+ constructor(message: string, positionInfo: PositionInfo);
6
+ }
7
+ //# sourceMappingURL=JsonParseError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonParseError.d.ts","sourceRoot":"","sources":["../../src/utilities/JsonParseError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAE5C,qBAAa,eAAgB,SAAQ,KAAK;aACb,OAAO,EAAE,MAAM;aAAkB,YAAY,EAAE,YAAY;IAAvF,YAA4B,OAAO,EAAE,MAAM,EAAkB,YAAY,EAAE,YAAY,EAEtF;CACD"}
@@ -0,0 +1,10 @@
1
+ export class JsonParserError extends Error {
2
+ message;
3
+ positionInfo;
4
+ constructor(message, positionInfo) {
5
+ super(message);
6
+ this.message = message;
7
+ this.positionInfo = positionInfo;
8
+ }
9
+ }
10
+ //# sourceMappingURL=JsonParseError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonParseError.js","sourceRoot":"","sources":["../../src/utilities/JsonParseError.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACb,OAAO;IAA0B,YAAY;IAAzE,YAA4B,OAAe,EAAkB,YAA0B;QACtF,KAAK,CAAC,OAAO,CAAC,CAAA;uBADa,OAAO;4BAA0B,YAAY;IAEzE,CAAC;CACD"}
@@ -0,0 +1,2 @@
1
+ export declare function deepEquals(obj1: unknown, obj2: unknown): boolean;
2
+ //# sourceMappingURL=ObjectUtilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectUtilities.d.ts","sourceRoot":"","sources":["../../src/utilities/ObjectUtilities.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAqLhE"}
@@ -0,0 +1,142 @@
1
+ export function deepEquals(obj1, obj2) {
2
+ if (obj1 === obj2) {
3
+ return true; // Values or references are exactly equal
4
+ }
5
+ // From this point, values are known to not be equal
6
+ // Take types
7
+ const obj1Type = typeof obj1;
8
+ const obj2Type = typeof obj2;
9
+ // `typeof obj` can be:
10
+ // "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
11
+ if (obj1Type !== obj2Type) { // If types mismatch
12
+ return false; // Includes case when one is null and the other undefined
13
+ }
14
+ // Handle NaN equality
15
+ if (obj1Type === 'number' && isNaN(obj1) && isNaN(obj2)) {
16
+ return true;
17
+ }
18
+ if (obj1Type !== 'object') { // If both are not objects (we know they have the same type at this point)
19
+ // Return false, since values are not equal, and types other then "object" need to have
20
+ // full equality to return true.
21
+ return false;
22
+ }
23
+ // Get object type tags for both
24
+ const obj1Tag = toString.call(obj1);
25
+ const obj2Tag = toString.call(obj2);
26
+ if (obj1Tag !== obj2Tag) {
27
+ return false;
28
+ }
29
+ switch (obj1Tag) {
30
+ case '[object Array]': {
31
+ const arr1 = obj1;
32
+ const arr2 = obj2;
33
+ if (arr1.length !== arr2.length) {
34
+ return false;
35
+ }
36
+ for (let i = 0; i < arr1.length; i++) {
37
+ if (!deepEquals(arr1[i], arr2[i])) {
38
+ return false;
39
+ }
40
+ }
41
+ return true;
42
+ }
43
+ case '[object Map]': {
44
+ const map1 = obj1;
45
+ const map2 = obj2;
46
+ if (map1.size !== map1.size) {
47
+ return false;
48
+ }
49
+ for (const [key, value] of map1) {
50
+ if (!map2.has(key)) {
51
+ return false;
52
+ }
53
+ if (!deepEquals(value, map2.get(key))) {
54
+ return false;
55
+ }
56
+ }
57
+ return true;
58
+ }
59
+ case '[object Set]': {
60
+ const set1 = obj1;
61
+ const set2 = obj2;
62
+ if (set1.size !== set2.size) {
63
+ return false;
64
+ }
65
+ for (const element of set1) {
66
+ if (!set2.has(element)) {
67
+ return false;
68
+ }
69
+ }
70
+ return true;
71
+ }
72
+ case '[object Int8Array]':
73
+ case '[object Uint8Array]':
74
+ case '[object Uint8ClampedArray]':
75
+ case '[object Int16Array]':
76
+ case '[object Uint16Array]':
77
+ case '[object Int32Array]':
78
+ case '[object Uint32Array]':
79
+ case '[object BigInt64Array]':
80
+ case '[object BigUint64Array]':
81
+ case '[object Float32Array]':
82
+ case '[object Float64Array]': {
83
+ const arr1 = obj1;
84
+ const arr2 = obj2;
85
+ if (arr1.length !== arr2.length) {
86
+ return false;
87
+ }
88
+ for (let i = 0; i < arr1.length; i++) {
89
+ if (arr1[i] !== arr2[i]) {
90
+ return false;
91
+ }
92
+ }
93
+ return true;
94
+ }
95
+ case '[object ArrayBuffer]': {
96
+ const arr1 = obj1;
97
+ const arr2 = obj2;
98
+ return deepEquals(new Uint8Array(arr1), new Uint8Array(arr2));
99
+ }
100
+ case '[object DataView]': {
101
+ const dataView1 = obj1;
102
+ const dataView2 = obj2;
103
+ if (dataView1.byteOffset !== dataView2.byteOffset) {
104
+ return false;
105
+ }
106
+ if (dataView1.byteLength !== dataView2.byteLength) {
107
+ return false;
108
+ }
109
+ return deepEquals(dataView1.buffer, dataView2.buffer);
110
+ }
111
+ case '[object Date]': {
112
+ const date1 = obj1;
113
+ const date2 = obj2;
114
+ return date1.getTime() === date2.getTime();
115
+ }
116
+ case '[object RegExp]': {
117
+ const regExp1 = obj1;
118
+ const regExp2 = obj2;
119
+ return regExp1.source === regExp2.source && regExp1.flags === regExp2.flags;
120
+ }
121
+ default: {
122
+ // Compare own properties using Reflect.ownKeys to include Symbols and non-enumerable
123
+ const obj1Keys = Reflect.ownKeys(obj1);
124
+ const obj2Keys = Reflect.ownKeys(obj2);
125
+ if (obj1Keys.length !== obj2Keys.length) {
126
+ return false;
127
+ }
128
+ for (const key of obj1Keys) {
129
+ if (!Reflect.has(obj2, key)) { // Reflect.has checks own and inherited, sufficient here
130
+ return false;
131
+ }
132
+ const val1 = Reflect.get(obj1, key);
133
+ const val2 = Reflect.get(obj2, key);
134
+ if (!deepEquals(val1, val2)) {
135
+ return false;
136
+ }
137
+ }
138
+ return true;
139
+ }
140
+ }
141
+ }
142
+ //# sourceMappingURL=ObjectUtilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectUtilities.js","sourceRoot":"","sources":["../../src/utilities/ObjectUtilities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | BigInt64Array | BigUint64Array | Float32Array | Float64Array;
2
+ export type TypedArrayConstructor = Int8ArrayConstructor | Uint8ArrayConstructor | Uint8ClampedArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | BigInt64ArrayConstructor | BigUint64ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor;
3
+ export type TypedArrayToConstructor<T extends TypedArray> = T extends Int8Array ? Int8ArrayConstructor : T extends Uint8Array ? Uint8ArrayConstructor : T extends Uint8ClampedArray ? Uint8ClampedArrayConstructor : T extends Int16Array ? Int16ArrayConstructor : T extends Uint16Array ? Uint16ArrayConstructor : T extends Int32Array ? Int32ArrayConstructor : T extends Uint32Array ? Uint32ArrayConstructor : T extends BigInt64Array ? BigInt64ArrayConstructor : T extends BigUint64Array ? BigUint64ArrayConstructor : T extends Float32Array ? Float32ArrayConstructor : T extends Float64Array ? Float64ArrayConstructor : never;
4
+ //# sourceMappingURL=TypedArray.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TypedArray.d.ts","sourceRoot":"","sources":["../../src/utilities/TypedArray.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GACrB,SAAS,GACT,UAAU,GACV,iBAAiB,GACjB,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,GACX,aAAa,GACb,cAAc,GACd,YAAY,GACZ,YAAY,CAAA;AAEb,MAAM,MAAM,qBAAqB,GAChC,oBAAoB,GACpB,qBAAqB,GACrB,4BAA4B,GAC5B,qBAAqB,GACrB,sBAAsB,GACtB,qBAAqB,GACrB,sBAAsB,GACtB,wBAAwB,GACxB,yBAAyB,GACzB,uBAAuB,GACvB,uBAAuB,CAAA;AAExB,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,UAAU,IACvD,CAAC,SAAS,SAAS,GAAG,oBAAoB,GAC1C,CAAC,SAAS,UAAU,GAAG,qBAAqB,GAC5C,CAAC,SAAS,iBAAiB,GAAG,4BAA4B,GAC1D,CAAC,SAAS,UAAU,GAAG,qBAAqB,GAC5C,CAAC,SAAS,WAAW,GAAG,sBAAsB,GAC9C,CAAC,SAAS,UAAU,GAAG,qBAAqB,GAC5C,CAAC,SAAS,WAAW,GAAG,sBAAsB,GAC9C,CAAC,SAAS,aAAa,GAAG,wBAAwB,GAClD,CAAC,SAAS,cAAc,GAAG,yBAAyB,GACpD,CAAC,SAAS,YAAY,GAAG,uBAAuB,GAChD,CAAC,SAAS,YAAY,GAAG,uBAAuB,GAChD,KAAK,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=TypedArray.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TypedArray.js","sourceRoot":"","sources":["../../src/utilities/TypedArray.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ export declare function charCodeToHex(charcode: number): string;
2
+ export declare function hexCharCodeToNumber(charCode: number): number;
3
+ export declare const positivePowersOf10: Float64Array<ArrayBuffer>;
4
+ export declare function offsetToLineAndColumnNumber(text: string, charOffset: number): LineAndColumnNumber;
5
+ export declare function getPositionInfo(text: string, charOffset: number): PositionInfo;
6
+ export declare function clip(num: number, min: number, max: number): number;
7
+ export interface LineAndColumnNumber {
8
+ lineNumber: number;
9
+ columnNumber: number;
10
+ }
11
+ export interface PositionInfo {
12
+ charOffset: number;
13
+ lineNumber: number;
14
+ columnNumber: number;
15
+ positionString: string;
16
+ }
17
+ //# sourceMappingURL=Utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Utilities.d.ts","sourceRoot":"","sources":["../../src/utilities/Utilities.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAsBtD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,UAUnD;AAED,eAAO,MAAM,kBAAkB,2BAI7B,CAAA;AAOF,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB,CAyCjG;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,CAa9E;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAUzD;AAED,MAAM,WAAW,mBAAmB;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,YAAY;IAC5B,UAAU,EAAE,MAAM,CAAA;IAElB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IAEpB,cAAc,EAAE,MAAM,CAAA;CACtB"}
@@ -0,0 +1,97 @@
1
+ export function charCodeToHex(charcode) {
2
+ function digitToCharCode(digit) {
3
+ if (digit < 10) {
4
+ return 48 + digit; // 48 is '0'
5
+ }
6
+ else {
7
+ return 65 + digit - 10; // 65 is 'A'
8
+ }
9
+ }
10
+ // Digit 1 (Least significant)
11
+ const charCode1 = digitToCharCode(charcode & 0xF);
12
+ // Digit 2
13
+ const charCode2 = digitToCharCode((charcode >>> 4) & 0xF);
14
+ // Digit 3
15
+ const charCode3 = digitToCharCode((charcode >>> 8) & 0xF);
16
+ // Digit 4 (Most significant)
17
+ const charCode4 = digitToCharCode((charcode >>> 12) & 0xF);
18
+ return String.fromCharCode(charCode4, charCode3, charCode2, charCode1);
19
+ }
20
+ export function hexCharCodeToNumber(charCode) {
21
+ if (charCode >= 48 && charCode <= 57) { // '0'..'9'
22
+ return charCode - 48;
23
+ }
24
+ if (charCode >= 65 && charCode <= 70) { // 'A'..'F'
25
+ return charCode - 65 + 10;
26
+ }
27
+ else if (charCode >= 97 && charCode <= 102) { // 'a'..'f'
28
+ return charCode - 97 + 10;
29
+ }
30
+ else {
31
+ throw new Error(`Invalid hexadecimal character: ${String.fromCharCode(charCode)}`);
32
+ }
33
+ }
34
+ export const positivePowersOf10 = new Float64Array([
35
+ 1e+00, 1e+01, 1e+02, 1e+03, 1e+04, 1e+05, 1e+06, 1e+07, 1e+08, 1e+09,
36
+ 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19,
37
+ 1e+20, 1e+21, 1e+22
38
+ ]);
39
+ // Converts a character offset in a string to a (line number, column) pair.
40
+ //
41
+ // Line and column numbers are 1-based.
42
+ // Handles standard Unix (`\n`) and Windows (`\r\n`) line endings efficiently
43
+ // by searching for the `\n` character.
44
+ export function offsetToLineAndColumnNumber(text, charOffset) {
45
+ // Handle the edge case of offset 0 quickly
46
+ if (charOffset === 0) {
47
+ return { lineNumber: 1, columnNumber: 1 };
48
+ }
49
+ if (charOffset > text.length) {
50
+ throw new Error(`Character offset is larger than string length.`);
51
+ }
52
+ // Initialize line number and the position of the last line break found
53
+ let lineNumber = 1;
54
+ let lastLineBreakPosition = -1;
55
+ let searchPosition = 0; // Position to start the next search from
56
+ // Efficiently find line breaks using indexOf.
57
+ // We only need to search up to the target offset.
58
+ while (searchPosition < charOffset) {
59
+ const lineBreakPosition = text.indexOf('\n', searchPosition);
60
+ // If no more line breaks are found, or the next one is at or after the offset,
61
+ // the target offset is on the current line.
62
+ if (lineBreakPosition === -1 || lineBreakPosition >= charOffset) {
63
+ break;
64
+ }
65
+ // Found a line break before the offset.
66
+ // Increment line number and update the position of the last line break.
67
+ lineNumber++;
68
+ lastLineBreakPosition = lineBreakPosition;
69
+ // Start the next search immediately after the found line break.
70
+ searchPosition = lineBreakPosition + 1;
71
+ }
72
+ // Calculate the column number: it's the offset relative to the start of the current line.
73
+ // The start of the current line is the character immediately after the last line break,
74
+ // or the beginning of the string if no line breaks were found before the offset.
75
+ const columnNumber = charOffset - (lastLineBreakPosition + 1) + 1;
76
+ return { lineNumber, columnNumber };
77
+ }
78
+ export function getPositionInfo(text, charOffset) {
79
+ charOffset = clip(charOffset, 0, text.length - 1);
80
+ const { lineNumber, columnNumber } = offsetToLineAndColumnNumber(text, charOffset);
81
+ return {
82
+ charOffset,
83
+ lineNumber,
84
+ columnNumber,
85
+ positionString: `position ${charOffset} (line ${lineNumber}, column ${columnNumber})`
86
+ };
87
+ }
88
+ export function clip(num, min, max) {
89
+ if (num < min) {
90
+ return min;
91
+ }
92
+ if (num > max) {
93
+ return max;
94
+ }
95
+ return num;
96
+ }
97
+ //# sourceMappingURL=Utilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Utilities.js","sourceRoot":"","sources":["../../src/utilities/Utilities.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "quick-json5",
3
+ "version": "0.1.0",
4
+ "description": "Fast JSON5 parser and serializer.",
5
+ "author": "Rotem Dan",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "json5",
9
+ "json"
10
+ ],
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/rotemdan/quick-json5"
14
+ },
15
+ "bugs": {
16
+ "url": "https://github.com/rotemdan/quick-json5/issues"
17
+ },
18
+ "engines": {
19
+ "node": ">=18"
20
+ },
21
+ "private": false,
22
+ "main": "./dist/exports/Exports.js",
23
+ "type": "module",
24
+ "files": [
25
+ "dist",
26
+ "src",
27
+ "tsconfig.json",
28
+ "LICENSE.md",
29
+ "README.md"
30
+ ],
31
+ "scripts": {
32
+ "test": "node dist/tests/Test.js"
33
+ },
34
+ "dependencies": {},
35
+ "devDependencies": {
36
+ "@types/node": "~26.1.1"
37
+ }
38
+ }
@@ -0,0 +1,7 @@
1
+ export * from '../json5/Json5Encoder.js'
2
+ export * from '../json5/Json5Parser.js'
3
+
4
+ export * from '../json/JsonEncoder.js'
5
+ export * from '../json/JsonParser.js'
6
+
7
+ export * from '../types/Types.js'
@@ -0,0 +1,180 @@
1
+ import { JsonReplacerFunction, JsonReplacerType } from '../types/Types.js'
2
+ import { charCodeToHex } from '../utilities/Utilities.js'
3
+
4
+ export function stringifyJSON(obj: any, replacer?: JsonReplacerType, space = 0) {
5
+ let replacerFunc: JsonReplacerFunction | undefined
6
+
7
+ if (replacer != null) {
8
+ if (Array.isArray(replacer)) {
9
+ const replacerSet = new Set()
10
+
11
+ for (const key of replacer) {
12
+ replacerSet.add(String(key))
13
+ }
14
+
15
+ replacerFunc = (key, value) => {
16
+ if (replacerSet.has(key)) {
17
+ return value
18
+ }
19
+ }
20
+ } else if (typeof replacer === 'function') {
21
+ replacerFunc = replacer
22
+ } else {
23
+ throw new TypeError('Invalid replacer argument.')
24
+ }
25
+ }
26
+
27
+ const baseIndentString = ' '.repeat(space)
28
+
29
+ let currentIndentLevel = 0
30
+
31
+ function getIndentString() {
32
+ if (space === 0) {
33
+ return ''
34
+ }
35
+
36
+ const spaces = baseIndentString.repeat(currentIndentLevel)
37
+
38
+ return `\n${spaces}`
39
+ }
40
+
41
+ function encode(obj: any) {
42
+ if (obj === undefined) {
43
+ return ''
44
+ }
45
+
46
+ const typeofObj = typeof obj
47
+
48
+ if (obj === null || typeofObj === 'boolean') {
49
+ return String(obj)
50
+ }
51
+
52
+ if (typeofObj === 'number') {
53
+ if (isNaN(obj) || obj === Infinity || obj === -Infinity) {
54
+ throw new Error(`NaN and Infinity can't be encoded in JSON`)
55
+ }
56
+
57
+ return String(obj)
58
+ }
59
+
60
+ if (typeofObj === 'string') {
61
+ return `"${escapeStringIfNeeded(obj)}"`
62
+ }
63
+
64
+ if (typeof obj !== 'object') {
65
+ throw new Error(`Type '${typeof obj}' cannot be encoded in JSON`)
66
+ }
67
+
68
+ if (typeof obj.toJSON === 'function') {
69
+ return obj.toJSON()
70
+ }
71
+
72
+ if (Array.isArray(obj)) {
73
+ let str = '['
74
+ let isFirstElement = true
75
+
76
+ for (let i = 0; i < obj.length; i++) {
77
+ const element = obj[i]
78
+
79
+ if (element === undefined) {
80
+ continue
81
+ }
82
+
83
+ currentIndentLevel += 1
84
+
85
+ const saparatingComma = isFirstElement === true ? '' : ','
86
+ const indentString = getIndentString()
87
+
88
+ const encodedElement = encode(element)
89
+
90
+ str += `${saparatingComma}${indentString}${encodedElement}`
91
+
92
+ currentIndentLevel -= 1
93
+
94
+ isFirstElement = false
95
+ }
96
+
97
+ str += `${getIndentString()}]`
98
+
99
+ return str
100
+ } else {
101
+ let str = '{'
102
+ let isFirstEntry = true
103
+
104
+ for (const key in obj) {
105
+ let value = obj[key]
106
+
107
+ if (replacerFunc !== undefined) {
108
+ value = replacerFunc(key, value)
109
+ }
110
+
111
+ if (value === undefined) {
112
+ continue
113
+ }
114
+
115
+ currentIndentLevel += 1
116
+
117
+ const saparatingComma = isFirstEntry === true ? '' : ','
118
+ const indentString = getIndentString()
119
+ const escapedKey = escapeStringIfNeeded(key)
120
+ const spaceAfterColons = space > 0 ? ' ' : ''
121
+
122
+ const encodedValue = encode(value)
123
+
124
+ str += `${saparatingComma}${indentString}"${escapedKey}":${spaceAfterColons}${encodedValue}`
125
+
126
+ currentIndentLevel -= 1
127
+
128
+ isFirstEntry = false
129
+ }
130
+
131
+ str += `${getIndentString()}}`
132
+
133
+ return str
134
+ }
135
+ }
136
+
137
+ return encode(obj)
138
+ }
139
+
140
+ function escapeStringIfNeeded(str: string): string {
141
+ if (!/["\\\x00-\x1F]/.test(str)) {
142
+ return str
143
+ } else {
144
+ return escapeString(str)
145
+ }
146
+ }
147
+
148
+ function escapeString(str: string): string {
149
+ let escapedStr = ''
150
+
151
+ for (let i = 0; i < str.length; i++) {
152
+ const charCode = str.charCodeAt(i)
153
+
154
+ if (charCode >= 32) {
155
+ if (charCode === 34) { // '"'
156
+ escapedStr += '\\"'
157
+ } else if (charCode === 92) { // '\\'
158
+ escapedStr += '\\\\'
159
+ } else {
160
+ escapedStr += String.fromCharCode(charCode)
161
+ }
162
+ } else {
163
+ if (charCode === 10) { // '\n'
164
+ escapedStr += '\\n'
165
+ } else if (charCode === 13) { // '\r'
166
+ escapedStr += '\\r'
167
+ } else if (charCode === 9) { // '\t'
168
+ escapedStr += '\\t'
169
+ } else if (charCode === 12) { // '\f'
170
+ escapedStr += '\\f'
171
+ } else if (charCode === 8) { // '\b'
172
+ escapedStr += '\\b'
173
+ } else {
174
+ escapedStr += `\\u${charCodeToHex(charCode)}`
175
+ }
176
+ }
177
+ }
178
+
179
+ return escapedStr
180
+ }