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,184 @@
1
+ import { TypedArray } from './TypedArray.js'
2
+
3
+ export function deepEquals(obj1: unknown, obj2: unknown): boolean {
4
+ if (obj1 === obj2) {
5
+ return true // Values or references are exactly equal
6
+ }
7
+
8
+ // From this point, values are known to not be equal
9
+
10
+ // Take types
11
+ const obj1Type = typeof obj1
12
+ const obj2Type = typeof obj2
13
+
14
+ // `typeof obj` can be:
15
+ // "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
16
+
17
+ if (obj1Type !== obj2Type) { // If types mismatch
18
+ return false // Includes case when one is null and the other undefined
19
+ }
20
+
21
+ // Handle NaN equality
22
+ if (obj1Type === 'number' && isNaN(obj1 as number) && isNaN(obj2 as number)) {
23
+ return true
24
+ }
25
+
26
+ if (obj1Type !== 'object') { // If both are not objects (we know they have the same type at this point)
27
+ // Return false, since values are not equal, and types other then "object" need to have
28
+ // full equality to return true.
29
+ return false
30
+ }
31
+
32
+ // Get object type tags for both
33
+ const obj1Tag = toString.call(obj1)
34
+ const obj2Tag = toString.call(obj2)
35
+
36
+ if (obj1Tag !== obj2Tag) {
37
+ return false
38
+ }
39
+
40
+ switch (obj1Tag) {
41
+ case '[object Array]': {
42
+ const arr1 = obj1 as any[]
43
+ const arr2 = obj2 as any[]
44
+
45
+ if (arr1.length !== arr2.length) {
46
+ return false
47
+ }
48
+
49
+ for (let i = 0; i < arr1.length; i++) {
50
+ if (!deepEquals(arr1[i], arr2[i])) {
51
+ return false
52
+ }
53
+ }
54
+
55
+ return true
56
+ }
57
+
58
+ case '[object Map]': {
59
+ const map1 = obj1 as Map<any, any>
60
+ const map2 = obj2 as Map<any, any>
61
+
62
+ if (map1.size !== map1.size) {
63
+ return false
64
+ }
65
+
66
+ for (const [key, value] of map1) {
67
+ if (!map2.has(key)) {
68
+ return false
69
+ }
70
+
71
+ if (!deepEquals(value, map2.get(key))) {
72
+ return false
73
+ }
74
+ }
75
+
76
+ return true
77
+ }
78
+
79
+ case '[object Set]': {
80
+ const set1 = obj1 as Set<any>
81
+ const set2 = obj2 as Set<any>
82
+
83
+ if (set1.size !== set2.size) {
84
+ return false
85
+ }
86
+
87
+ for (const element of set1) {
88
+ if (!set2.has(element)) {
89
+ return false
90
+ }
91
+ }
92
+
93
+ return true
94
+ }
95
+
96
+ case '[object Int8Array]':
97
+ case '[object Uint8Array]':
98
+ case '[object Uint8ClampedArray]':
99
+ case '[object Int16Array]':
100
+ case '[object Uint16Array]':
101
+ case '[object Int32Array]':
102
+ case '[object Uint32Array]':
103
+ case '[object BigInt64Array]':
104
+ case '[object BigUint64Array]':
105
+ case '[object Float32Array]':
106
+ case '[object Float64Array]': {
107
+ const arr1 = obj1 as TypedArray
108
+ const arr2 = obj2 as TypedArray
109
+
110
+ if (arr1.length !== arr2.length) {
111
+ return false
112
+ }
113
+
114
+ for (let i = 0; i < arr1.length; i++) {
115
+ if (arr1[i] !== arr2[i]) {
116
+ return false
117
+ }
118
+ }
119
+
120
+ return true
121
+ }
122
+
123
+ case '[object ArrayBuffer]': {
124
+ const arr1 = obj1 as ArrayBuffer
125
+ const arr2 = obj2 as ArrayBuffer
126
+
127
+ return deepEquals(new Uint8Array(arr1), new Uint8Array(arr2))
128
+ }
129
+
130
+ case '[object DataView]': {
131
+ const dataView1 = obj1 as DataView
132
+ const dataView2 = obj2 as DataView
133
+
134
+ if (dataView1.byteOffset !== dataView2.byteOffset) {
135
+ return false
136
+ }
137
+
138
+ if (dataView1.byteLength !== dataView2.byteLength) {
139
+ return false
140
+ }
141
+
142
+ return deepEquals(dataView1.buffer, dataView2.buffer)
143
+ }
144
+
145
+ case '[object Date]': {
146
+ const date1 = obj1 as Date
147
+ const date2 = obj2 as Date
148
+
149
+ return date1.getTime() === date2.getTime()
150
+ }
151
+
152
+ case '[object RegExp]': {
153
+ const regExp1 = obj1 as RegExp
154
+ const regExp2 = obj2 as RegExp
155
+
156
+ return regExp1.source === regExp2.source && regExp1.flags === regExp2.flags
157
+ }
158
+
159
+ default: {
160
+ // Compare own properties using Reflect.ownKeys to include Symbols and non-enumerable
161
+ const obj1Keys = Reflect.ownKeys(obj1 as any)
162
+ const obj2Keys = Reflect.ownKeys(obj2 as any)
163
+
164
+ if (obj1Keys.length !== obj2Keys.length) {
165
+ return false
166
+ }
167
+
168
+ for (const key of obj1Keys) {
169
+ if (!Reflect.has(obj2 as any, key)) { // Reflect.has checks own and inherited, sufficient here
170
+ return false
171
+ }
172
+
173
+ const val1 = Reflect.get(obj1 as any, key)
174
+ const val2 = Reflect.get(obj2 as any, key)
175
+
176
+ if (!deepEquals(val1, val2)) {
177
+ return false
178
+ }
179
+ }
180
+
181
+ return true
182
+ }
183
+ }
184
+ }
@@ -0,0 +1,39 @@
1
+ export type TypedArray =
2
+ Int8Array |
3
+ Uint8Array |
4
+ Uint8ClampedArray |
5
+ Int16Array |
6
+ Uint16Array |
7
+ Int32Array |
8
+ Uint32Array |
9
+ BigInt64Array |
10
+ BigUint64Array |
11
+ Float32Array |
12
+ Float64Array
13
+
14
+ export type TypedArrayConstructor =
15
+ Int8ArrayConstructor |
16
+ Uint8ArrayConstructor |
17
+ Uint8ClampedArrayConstructor |
18
+ Int16ArrayConstructor |
19
+ Uint16ArrayConstructor |
20
+ Int32ArrayConstructor |
21
+ Uint32ArrayConstructor |
22
+ BigInt64ArrayConstructor |
23
+ BigUint64ArrayConstructor |
24
+ Float32ArrayConstructor |
25
+ Float64ArrayConstructor
26
+
27
+ export type TypedArrayToConstructor<T extends TypedArray> =
28
+ T extends Int8Array ? Int8ArrayConstructor :
29
+ T extends Uint8Array ? Uint8ArrayConstructor :
30
+ T extends Uint8ClampedArray ? Uint8ClampedArrayConstructor :
31
+ T extends Int16Array ? Int16ArrayConstructor :
32
+ T extends Uint16Array ? Uint16ArrayConstructor :
33
+ T extends Int32Array ? Int32ArrayConstructor :
34
+ T extends Uint32Array ? Uint32ArrayConstructor :
35
+ T extends BigInt64Array ? BigInt64ArrayConstructor :
36
+ T extends BigUint64Array ? BigUint64ArrayConstructor :
37
+ T extends Float32Array ? Float32ArrayConstructor :
38
+ T extends Float64Array ? Float64ArrayConstructor :
39
+ never;
@@ -0,0 +1,130 @@
1
+ export function charCodeToHex(charcode: number): string {
2
+ function digitToCharCode(digit: number) {
3
+ if (digit < 10) {
4
+ return 48 + digit // 48 is '0'
5
+ } else {
6
+ return 65 + digit - 10 // 65 is 'A'
7
+ }
8
+ }
9
+
10
+ // Digit 1 (Least significant)
11
+ const charCode1 = digitToCharCode(charcode & 0xF)
12
+
13
+ // Digit 2
14
+ const charCode2 = digitToCharCode((charcode >>> 4) & 0xF)
15
+
16
+ // Digit 3
17
+ const charCode3 = digitToCharCode((charcode >>> 8) & 0xF)
18
+
19
+ // Digit 4 (Most significant)
20
+ const charCode4 = digitToCharCode((charcode >>> 12) & 0xF)
21
+
22
+ return String.fromCharCode(charCode4, charCode3, charCode2, charCode1)
23
+ }
24
+
25
+ export function hexCharCodeToNumber(charCode: number) {
26
+ if (charCode >= 48 && charCode <= 57) { // '0'..'9'
27
+ return charCode - 48
28
+ } if (charCode >= 65 && charCode <= 70) { // 'A'..'F'
29
+ return charCode - 65 + 10
30
+ } else if (charCode >= 97 && charCode <= 102) { // 'a'..'f'
31
+ return charCode - 97 + 10
32
+ } else {
33
+ throw new Error(`Invalid hexadecimal character: ${String.fromCharCode(charCode)}`)
34
+ }
35
+ }
36
+
37
+ export const positivePowersOf10 = new Float64Array([
38
+ 1e+00, 1e+01, 1e+02, 1e+03, 1e+04, 1e+05, 1e+06, 1e+07, 1e+08, 1e+09,
39
+ 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19,
40
+ 1e+20, 1e+21, 1e+22
41
+ ])
42
+
43
+ // Converts a character offset in a string to a (line number, column) pair.
44
+ //
45
+ // Line and column numbers are 1-based.
46
+ // Handles standard Unix (`\n`) and Windows (`\r\n`) line endings efficiently
47
+ // by searching for the `\n` character.
48
+ export function offsetToLineAndColumnNumber(text: string, charOffset: number): LineAndColumnNumber {
49
+ // Handle the edge case of offset 0 quickly
50
+ if (charOffset === 0) {
51
+ return { lineNumber: 1, columnNumber: 1 }
52
+ }
53
+
54
+ if (charOffset > text.length) {
55
+ throw new Error(`Character offset is larger than string length.`)
56
+ }
57
+
58
+ // Initialize line number and the position of the last line break found
59
+ let lineNumber = 1
60
+ let lastLineBreakPosition = -1
61
+ let searchPosition = 0 // Position to start the next search from
62
+
63
+ // Efficiently find line breaks using indexOf.
64
+ // We only need to search up to the target offset.
65
+ while (searchPosition < charOffset) {
66
+ const lineBreakPosition = text.indexOf('\n', searchPosition)
67
+
68
+ // If no more line breaks are found, or the next one is at or after the offset,
69
+ // the target offset is on the current line.
70
+ if (lineBreakPosition === -1 || lineBreakPosition >= charOffset) {
71
+ break
72
+ }
73
+
74
+ // Found a line break before the offset.
75
+ // Increment line number and update the position of the last line break.
76
+ lineNumber++
77
+ lastLineBreakPosition = lineBreakPosition
78
+
79
+ // Start the next search immediately after the found line break.
80
+ searchPosition = lineBreakPosition + 1
81
+ }
82
+
83
+ // Calculate the column number: it's the offset relative to the start of the current line.
84
+ // The start of the current line is the character immediately after the last line break,
85
+ // or the beginning of the string if no line breaks were found before the offset.
86
+ const columnNumber = charOffset - (lastLineBreakPosition + 1) + 1
87
+
88
+ return { lineNumber, columnNumber }
89
+ }
90
+
91
+ export function getPositionInfo(text: string, charOffset: number): PositionInfo {
92
+ charOffset = clip(charOffset, 0, text.length - 1)
93
+
94
+ const { lineNumber, columnNumber } = offsetToLineAndColumnNumber(text, charOffset)
95
+
96
+ return {
97
+ charOffset,
98
+
99
+ lineNumber,
100
+ columnNumber,
101
+
102
+ positionString: `position ${charOffset} (line ${lineNumber}, column ${columnNumber})`
103
+ }
104
+ }
105
+
106
+ export function clip(num: number, min: number, max: number) {
107
+ if (num < min) {
108
+ return min
109
+ }
110
+
111
+ if (num > max) {
112
+ return max
113
+ }
114
+
115
+ return num
116
+ }
117
+
118
+ export interface LineAndColumnNumber {
119
+ lineNumber: number
120
+ columnNumber: number
121
+ }
122
+
123
+ export interface PositionInfo {
124
+ charOffset: number
125
+
126
+ lineNumber: number
127
+ columnNumber: number
128
+
129
+ positionString: string
130
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ // Visit https://aka.ms/tsconfig to read more about this file
3
+ "compilerOptions": {
4
+ // File Layout
5
+ "rootDir": "./src",
6
+ "outDir": "./dist",
7
+
8
+ // Environment Settings
9
+ // See also https://aka.ms/tsconfig/module
10
+ "module": "nodenext",
11
+ "target": "esnext",
12
+ "types": ["node"],
13
+ // For nodejs:
14
+ // "lib": ["esnext"],
15
+ // "types": ["node"],
16
+ // and npm install -D @types/node
17
+
18
+ // Other Outputs
19
+ "sourceMap": true,
20
+ "declaration": true,
21
+ "declarationMap": true,
22
+
23
+ // Stricter Typechecking Options
24
+ // "noUncheckedIndexedAccess": true,
25
+ // "exactOptionalPropertyTypes": true,
26
+
27
+ // Style Options
28
+ "noImplicitReturns": true,
29
+ // "noImplicitOverride": true,
30
+ // "noUnusedLocals": true,
31
+ // "noUnusedParameters": true,
32
+ // "noFallthroughCasesInSwitch": true,
33
+ // "noPropertyAccessFromIndexSignature": true,
34
+
35
+ // Recommended Options
36
+ "strict": true,
37
+ "jsx": "react-jsx",
38
+ // "verbatimModuleSyntax": true,
39
+ "isolatedModules": true,
40
+ "noUncheckedSideEffectImports": true,
41
+ "moduleDetection": "force",
42
+ "skipLibCheck": true,
43
+
44
+ // Extended options not in generated tsconfig.json
45
+ "newLine": "lf",
46
+ "forceConsistentCasingInFileNames": true,
47
+ "alwaysStrict": true,
48
+
49
+ "noImplicitThis": true,
50
+ "strictBindCallApply": true,
51
+ "strictFunctionTypes": true,
52
+
53
+ "noErrorTruncation": true,
54
+ }
55
+ }