landvex: Fixar och tester klara för alla komponenter

- Datafabrik: Dockerfile fix, agentorkestrering fungerar
- Vision: Identify-modell, FAISS, OCR alla testade
- API: Alla 7 integrationstester passerade
- Upplösare: Entitetsupplösning verifierad
This commit is contained in:
Bernt
2026-07-05 06:41:32 +00:00
parent f4f853d94b
commit aee0f09db8
19583 changed files with 1450867 additions and 1153 deletions
Generated Vendored Executable
+152
View File
@@ -0,0 +1,152 @@
#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
const pkg = require('../package.json')
const JSON5 = require('./')
const argv = parseArgs()
if (argv.version) {
version()
} else if (argv.help) {
usage()
} else {
const inFilename = argv.defaults[0]
let readStream
if (inFilename) {
readStream = fs.createReadStream(inFilename)
} else {
readStream = process.stdin
}
let json5 = ''
readStream.on('data', data => {
json5 += data
})
readStream.on('end', () => {
let space
if (argv.space === 't' || argv.space === 'tab') {
space = '\t'
} else {
space = Number(argv.space)
}
let value
try {
value = JSON5.parse(json5)
if (!argv.validate) {
const json = JSON.stringify(value, null, space)
let writeStream
// --convert is for backward compatibility with v0.5.1. If
// specified with <file> and not --out-file, then a file with
// the same name but with a .json extension will be written.
if (argv.convert && inFilename && !argv.outFile) {
const parsedFilename = path.parse(inFilename)
const outFilename = path.format(
Object.assign(
parsedFilename,
{base: path.basename(parsedFilename.base, parsedFilename.ext) + '.json'}
)
)
writeStream = fs.createWriteStream(outFilename)
} else if (argv.outFile) {
writeStream = fs.createWriteStream(argv.outFile)
} else {
writeStream = process.stdout
}
writeStream.write(json)
}
} catch (err) {
console.error(err.message)
process.exit(1)
}
})
}
function parseArgs () {
let convert
let space
let validate
let outFile
let version
let help
const defaults = []
const args = process.argv.slice(2)
for (let i = 0; i < args.length; i++) {
const arg = args[i]
switch (arg) {
case '--convert':
case '-c':
convert = true
break
case '--space':
case '-s':
space = args[++i]
break
case '--validate':
case '-v':
validate = true
break
case '--out-file':
case '-o':
outFile = args[++i]
break
case '--version':
case '-V':
version = true
break
case '--help':
case '-h':
help = true
break
default:
defaults.push(arg)
break
}
}
return {
convert,
space,
validate,
outFile,
version,
help,
defaults,
}
}
function version () {
console.log(pkg.version)
}
function usage () {
console.log(
`
Usage: json5 [options] <file>
If <file> is not provided, then STDIN is used.
Options:
-s, --space The number of spaces to indent or 't' for tabs
-o, --out-file [file] Output to the specified file, otherwise STDOUT
-v, --validate Validate JSON5 but do not output JSON
-V, --version Output the version number
-h, --help Output usage information`
)
}
+4
View File
@@ -0,0 +1,4 @@
import parse = require('./parse')
import stringify = require('./stringify')
export {parse, stringify}
+9
View File
@@ -0,0 +1,9 @@
const parse = require('./parse')
const stringify = require('./stringify')
const JSON5 = {
parse,
stringify,
}
module.exports = JSON5
+15
View File
@@ -0,0 +1,15 @@
/**
* Parses a JSON5 string, constructing the JavaScript value or object described
* by the string.
* @template T The type of the return value.
* @param text The string to parse as JSON5.
* @param reviver A function that prescribes how the value originally produced
* by parsing is transformed before being returned.
* @returns The JavaScript value converted from the JSON5 string.
*/
declare function parse<T = any>(
text: string,
reviver?: ((this: any, key: string, value: any) => any) | null,
): T
export = parse
+1114
View File
@@ -0,0 +1,1114 @@
const util = require('./util')
let source
let parseState
let stack
let pos
let line
let column
let token
let key
let root
module.exports = function parse (text, reviver) {
source = String(text)
parseState = 'start'
stack = []
pos = 0
line = 1
column = 0
token = undefined
key = undefined
root = undefined
do {
token = lex()
// This code is unreachable.
// if (!parseStates[parseState]) {
// throw invalidParseState()
// }
parseStates[parseState]()
} while (token.type !== 'eof')
if (typeof reviver === 'function') {
return internalize({'': root}, '', reviver)
}
return root
}
function internalize (holder, name, reviver) {
const value = holder[name]
if (value != null && typeof value === 'object') {
if (Array.isArray(value)) {
for (let i = 0; i < value.length; i++) {
const key = String(i)
const replacement = internalize(value, key, reviver)
if (replacement === undefined) {
delete value[key]
} else {
Object.defineProperty(value, key, {
value: replacement,
writable: true,
enumerable: true,
configurable: true,
})
}
}
} else {
for (const key in value) {
const replacement = internalize(value, key, reviver)
if (replacement === undefined) {
delete value[key]
} else {
Object.defineProperty(value, key, {
value: replacement,
writable: true,
enumerable: true,
configurable: true,
})
}
}
}
}
return reviver.call(holder, name, value)
}
let lexState
let buffer
let doubleQuote
let sign
let c
function lex () {
lexState = 'default'
buffer = ''
doubleQuote = false
sign = 1
for (;;) {
c = peek()
// This code is unreachable.
// if (!lexStates[lexState]) {
// throw invalidLexState(lexState)
// }
const token = lexStates[lexState]()
if (token) {
return token
}
}
}
function peek () {
if (source[pos]) {
return String.fromCodePoint(source.codePointAt(pos))
}
}
function read () {
const c = peek()
if (c === '\n') {
line++
column = 0
} else if (c) {
column += c.length
} else {
column++
}
if (c) {
pos += c.length
}
return c
}
const lexStates = {
default () {
switch (c) {
case '\t':
case '\v':
case '\f':
case ' ':
case '\u00A0':
case '\uFEFF':
case '\n':
case '\r':
case '\u2028':
case '\u2029':
read()
return
case '/':
read()
lexState = 'comment'
return
case undefined:
read()
return newToken('eof')
}
if (util.isSpaceSeparator(c)) {
read()
return
}
// This code is unreachable.
// if (!lexStates[parseState]) {
// throw invalidLexState(parseState)
// }
return lexStates[parseState]()
},
comment () {
switch (c) {
case '*':
read()
lexState = 'multiLineComment'
return
case '/':
read()
lexState = 'singleLineComment'
return
}
throw invalidChar(read())
},
multiLineComment () {
switch (c) {
case '*':
read()
lexState = 'multiLineCommentAsterisk'
return
case undefined:
throw invalidChar(read())
}
read()
},
multiLineCommentAsterisk () {
switch (c) {
case '*':
read()
return
case '/':
read()
lexState = 'default'
return
case undefined:
throw invalidChar(read())
}
read()
lexState = 'multiLineComment'
},
singleLineComment () {
switch (c) {
case '\n':
case '\r':
case '\u2028':
case '\u2029':
read()
lexState = 'default'
return
case undefined:
read()
return newToken('eof')
}
read()
},
value () {
switch (c) {
case '{':
case '[':
return newToken('punctuator', read())
case 'n':
read()
literal('ull')
return newToken('null', null)
case 't':
read()
literal('rue')
return newToken('boolean', true)
case 'f':
read()
literal('alse')
return newToken('boolean', false)
case '-':
case '+':
if (read() === '-') {
sign = -1
}
lexState = 'sign'
return
case '.':
buffer = read()
lexState = 'decimalPointLeading'
return
case '0':
buffer = read()
lexState = 'zero'
return
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
buffer = read()
lexState = 'decimalInteger'
return
case 'I':
read()
literal('nfinity')
return newToken('numeric', Infinity)
case 'N':
read()
literal('aN')
return newToken('numeric', NaN)
case '"':
case "'":
doubleQuote = (read() === '"')
buffer = ''
lexState = 'string'
return
}
throw invalidChar(read())
},
identifierNameStartEscape () {
if (c !== 'u') {
throw invalidChar(read())
}
read()
const u = unicodeEscape()
switch (u) {
case '$':
case '_':
break
default:
if (!util.isIdStartChar(u)) {
throw invalidIdentifier()
}
break
}
buffer += u
lexState = 'identifierName'
},
identifierName () {
switch (c) {
case '$':
case '_':
case '\u200C':
case '\u200D':
buffer += read()
return
case '\\':
read()
lexState = 'identifierNameEscape'
return
}
if (util.isIdContinueChar(c)) {
buffer += read()
return
}
return newToken('identifier', buffer)
},
identifierNameEscape () {
if (c !== 'u') {
throw invalidChar(read())
}
read()
const u = unicodeEscape()
switch (u) {
case '$':
case '_':
case '\u200C':
case '\u200D':
break
default:
if (!util.isIdContinueChar(u)) {
throw invalidIdentifier()
}
break
}
buffer += u
lexState = 'identifierName'
},
sign () {
switch (c) {
case '.':
buffer = read()
lexState = 'decimalPointLeading'
return
case '0':
buffer = read()
lexState = 'zero'
return
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
buffer = read()
lexState = 'decimalInteger'
return
case 'I':
read()
literal('nfinity')
return newToken('numeric', sign * Infinity)
case 'N':
read()
literal('aN')
return newToken('numeric', NaN)
}
throw invalidChar(read())
},
zero () {
switch (c) {
case '.':
buffer += read()
lexState = 'decimalPoint'
return
case 'e':
case 'E':
buffer += read()
lexState = 'decimalExponent'
return
case 'x':
case 'X':
buffer += read()
lexState = 'hexadecimal'
return
}
return newToken('numeric', sign * 0)
},
decimalInteger () {
switch (c) {
case '.':
buffer += read()
lexState = 'decimalPoint'
return
case 'e':
case 'E':
buffer += read()
lexState = 'decimalExponent'
return
}
if (util.isDigit(c)) {
buffer += read()
return
}
return newToken('numeric', sign * Number(buffer))
},
decimalPointLeading () {
if (util.isDigit(c)) {
buffer += read()
lexState = 'decimalFraction'
return
}
throw invalidChar(read())
},
decimalPoint () {
switch (c) {
case 'e':
case 'E':
buffer += read()
lexState = 'decimalExponent'
return
}
if (util.isDigit(c)) {
buffer += read()
lexState = 'decimalFraction'
return
}
return newToken('numeric', sign * Number(buffer))
},
decimalFraction () {
switch (c) {
case 'e':
case 'E':
buffer += read()
lexState = 'decimalExponent'
return
}
if (util.isDigit(c)) {
buffer += read()
return
}
return newToken('numeric', sign * Number(buffer))
},
decimalExponent () {
switch (c) {
case '+':
case '-':
buffer += read()
lexState = 'decimalExponentSign'
return
}
if (util.isDigit(c)) {
buffer += read()
lexState = 'decimalExponentInteger'
return
}
throw invalidChar(read())
},
decimalExponentSign () {
if (util.isDigit(c)) {
buffer += read()
lexState = 'decimalExponentInteger'
return
}
throw invalidChar(read())
},
decimalExponentInteger () {
if (util.isDigit(c)) {
buffer += read()
return
}
return newToken('numeric', sign * Number(buffer))
},
hexadecimal () {
if (util.isHexDigit(c)) {
buffer += read()
lexState = 'hexadecimalInteger'
return
}
throw invalidChar(read())
},
hexadecimalInteger () {
if (util.isHexDigit(c)) {
buffer += read()
return
}
return newToken('numeric', sign * Number(buffer))
},
string () {
switch (c) {
case '\\':
read()
buffer += escape()
return
case '"':
if (doubleQuote) {
read()
return newToken('string', buffer)
}
buffer += read()
return
case "'":
if (!doubleQuote) {
read()
return newToken('string', buffer)
}
buffer += read()
return
case '\n':
case '\r':
throw invalidChar(read())
case '\u2028':
case '\u2029':
separatorChar(c)
break
case undefined:
throw invalidChar(read())
}
buffer += read()
},
start () {
switch (c) {
case '{':
case '[':
return newToken('punctuator', read())
// This code is unreachable since the default lexState handles eof.
// case undefined:
// return newToken('eof')
}
lexState = 'value'
},
beforePropertyName () {
switch (c) {
case '$':
case '_':
buffer = read()
lexState = 'identifierName'
return
case '\\':
read()
lexState = 'identifierNameStartEscape'
return
case '}':
return newToken('punctuator', read())
case '"':
case "'":
doubleQuote = (read() === '"')
lexState = 'string'
return
}
if (util.isIdStartChar(c)) {
buffer += read()
lexState = 'identifierName'
return
}
throw invalidChar(read())
},
afterPropertyName () {
if (c === ':') {
return newToken('punctuator', read())
}
throw invalidChar(read())
},
beforePropertyValue () {
lexState = 'value'
},
afterPropertyValue () {
switch (c) {
case ',':
case '}':
return newToken('punctuator', read())
}
throw invalidChar(read())
},
beforeArrayValue () {
if (c === ']') {
return newToken('punctuator', read())
}
lexState = 'value'
},
afterArrayValue () {
switch (c) {
case ',':
case ']':
return newToken('punctuator', read())
}
throw invalidChar(read())
},
end () {
// This code is unreachable since it's handled by the default lexState.
// if (c === undefined) {
// read()
// return newToken('eof')
// }
throw invalidChar(read())
},
}
function newToken (type, value) {
return {
type,
value,
line,
column,
}
}
function literal (s) {
for (const c of s) {
const p = peek()
if (p !== c) {
throw invalidChar(read())
}
read()
}
}
function escape () {
const c = peek()
switch (c) {
case 'b':
read()
return '\b'
case 'f':
read()
return '\f'
case 'n':
read()
return '\n'
case 'r':
read()
return '\r'
case 't':
read()
return '\t'
case 'v':
read()
return '\v'
case '0':
read()
if (util.isDigit(peek())) {
throw invalidChar(read())
}
return '\0'
case 'x':
read()
return hexEscape()
case 'u':
read()
return unicodeEscape()
case '\n':
case '\u2028':
case '\u2029':
read()
return ''
case '\r':
read()
if (peek() === '\n') {
read()
}
return ''
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
throw invalidChar(read())
case undefined:
throw invalidChar(read())
}
return read()
}
function hexEscape () {
let buffer = ''
let c = peek()
if (!util.isHexDigit(c)) {
throw invalidChar(read())
}
buffer += read()
c = peek()
if (!util.isHexDigit(c)) {
throw invalidChar(read())
}
buffer += read()
return String.fromCodePoint(parseInt(buffer, 16))
}
function unicodeEscape () {
let buffer = ''
let count = 4
while (count-- > 0) {
const c = peek()
if (!util.isHexDigit(c)) {
throw invalidChar(read())
}
buffer += read()
}
return String.fromCodePoint(parseInt(buffer, 16))
}
const parseStates = {
start () {
if (token.type === 'eof') {
throw invalidEOF()
}
push()
},
beforePropertyName () {
switch (token.type) {
case 'identifier':
case 'string':
key = token.value
parseState = 'afterPropertyName'
return
case 'punctuator':
// This code is unreachable since it's handled by the lexState.
// if (token.value !== '}') {
// throw invalidToken()
// }
pop()
return
case 'eof':
throw invalidEOF()
}
// This code is unreachable since it's handled by the lexState.
// throw invalidToken()
},
afterPropertyName () {
// This code is unreachable since it's handled by the lexState.
// if (token.type !== 'punctuator' || token.value !== ':') {
// throw invalidToken()
// }
if (token.type === 'eof') {
throw invalidEOF()
}
parseState = 'beforePropertyValue'
},
beforePropertyValue () {
if (token.type === 'eof') {
throw invalidEOF()
}
push()
},
beforeArrayValue () {
if (token.type === 'eof') {
throw invalidEOF()
}
if (token.type === 'punctuator' && token.value === ']') {
pop()
return
}
push()
},
afterPropertyValue () {
// This code is unreachable since it's handled by the lexState.
// if (token.type !== 'punctuator') {
// throw invalidToken()
// }
if (token.type === 'eof') {
throw invalidEOF()
}
switch (token.value) {
case ',':
parseState = 'beforePropertyName'
return
case '}':
pop()
}
// This code is unreachable since it's handled by the lexState.
// throw invalidToken()
},
afterArrayValue () {
// This code is unreachable since it's handled by the lexState.
// if (token.type !== 'punctuator') {
// throw invalidToken()
// }
if (token.type === 'eof') {
throw invalidEOF()
}
switch (token.value) {
case ',':
parseState = 'beforeArrayValue'
return
case ']':
pop()
}
// This code is unreachable since it's handled by the lexState.
// throw invalidToken()
},
end () {
// This code is unreachable since it's handled by the lexState.
// if (token.type !== 'eof') {
// throw invalidToken()
// }
},
}
function push () {
let value
switch (token.type) {
case 'punctuator':
switch (token.value) {
case '{':
value = {}
break
case '[':
value = []
break
}
break
case 'null':
case 'boolean':
case 'numeric':
case 'string':
value = token.value
break
// This code is unreachable.
// default:
// throw invalidToken()
}
if (root === undefined) {
root = value
} else {
const parent = stack[stack.length - 1]
if (Array.isArray(parent)) {
parent.push(value)
} else {
Object.defineProperty(parent, key, {
value,
writable: true,
enumerable: true,
configurable: true,
})
}
}
if (value !== null && typeof value === 'object') {
stack.push(value)
if (Array.isArray(value)) {
parseState = 'beforeArrayValue'
} else {
parseState = 'beforePropertyName'
}
} else {
const current = stack[stack.length - 1]
if (current == null) {
parseState = 'end'
} else if (Array.isArray(current)) {
parseState = 'afterArrayValue'
} else {
parseState = 'afterPropertyValue'
}
}
}
function pop () {
stack.pop()
const current = stack[stack.length - 1]
if (current == null) {
parseState = 'end'
} else if (Array.isArray(current)) {
parseState = 'afterArrayValue'
} else {
parseState = 'afterPropertyValue'
}
}
// This code is unreachable.
// function invalidParseState () {
// return new Error(`JSON5: invalid parse state '${parseState}'`)
// }
// This code is unreachable.
// function invalidLexState (state) {
// return new Error(`JSON5: invalid lex state '${state}'`)
// }
function invalidChar (c) {
if (c === undefined) {
return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
}
return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
}
function invalidEOF () {
return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
}
// This code is unreachable.
// function invalidToken () {
// if (token.type === 'eof') {
// return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
// }
// const c = String.fromCodePoint(token.value.codePointAt(0))
// return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
// }
function invalidIdentifier () {
column -= 5
return syntaxError(`JSON5: invalid identifier character at ${line}:${column}`)
}
function separatorChar (c) {
console.warn(`JSON5: '${formatChar(c)}' in strings is not valid ECMAScript; consider escaping`)
}
function formatChar (c) {
const replacements = {
"'": "\\'",
'"': '\\"',
'\\': '\\\\',
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\v': '\\v',
'\0': '\\0',
'\u2028': '\\u2028',
'\u2029': '\\u2029',
}
if (replacements[c]) {
return replacements[c]
}
if (c < ' ') {
const hexString = c.charCodeAt(0).toString(16)
return '\\x' + ('00' + hexString).substring(hexString.length)
}
return c
}
function syntaxError (message) {
const err = new SyntaxError(message)
err.lineNumber = line
err.columnNumber = column
return err
}
+13
View File
@@ -0,0 +1,13 @@
const fs = require('fs')
const JSON5 = require('./')
// eslint-disable-next-line node/no-deprecated-api
require.extensions['.json5'] = function (module, filename) {
const content = fs.readFileSync(filename, 'utf8')
try {
module.exports = JSON5.parse(content)
} catch (err) {
err.message = filename + ': ' + err.message
throw err
}
}
+4
View File
@@ -0,0 +1,4 @@
// This file is for backward compatibility with v0.5.1.
require('./register')
console.warn("'json5/require' is deprecated. Please use 'json5/register' instead.")
+89
View File
@@ -0,0 +1,89 @@
declare type StringifyOptions = {
/**
* A function that alters the behavior of the stringification process, or an
* array of String and Number objects that serve as a allowlist for
* selecting/filtering the properties of the value object to be included in
* the JSON5 string. If this value is null or not provided, all properties
* of the object are included in the resulting JSON5 string.
*/
replacer?:
| ((this: any, key: string, value: any) => any)
| (string | number)[]
| null
/**
* A String or Number object that's used to insert white space into the
* output JSON5 string for readability purposes. If this is a Number, it
* indicates the number of space characters to use as white space; this
* number is capped at 10 (if it is greater, the value is just 10). Values
* less than 1 indicate that no space should be used. If this is a String,
* the string (or the first 10 characters of the string, if it's longer than
* that) is used as white space. If this parameter is not provided (or is
* null), no white space is used. If white space is used, trailing commas
* will be used in objects and arrays.
*/
space?: string | number | null
/**
* A String representing the quote character to use when serializing
* strings.
*/
quote?: string | null
}
/**
* Converts a JavaScript value to a JSON5 string.
* @param value The value to convert to a JSON5 string.
* @param replacer A function that alters the behavior of the stringification
* process. If this value is null or not provided, all properties of the object
* are included in the resulting JSON5 string.
* @param space A String or Number object that's used to insert white space into
* the output JSON5 string for readability purposes. If this is a Number, it
* indicates the number of space characters to use as white space; this number
* is capped at 10 (if it is greater, the value is just 10). Values less than 1
* indicate that no space should be used. If this is a String, the string (or
* the first 10 characters of the string, if it's longer than that) is used as
* white space. If this parameter is not provided (or is null), no white space
* is used. If white space is used, trailing commas will be used in objects and
* arrays.
* @returns The JSON5 string converted from the JavaScript value.
*/
declare function stringify(
value: any,
replacer?: ((this: any, key: string, value: any) => any) | null,
space?: string | number | null,
): string
/**
* Converts a JavaScript value to a JSON5 string.
* @param value The value to convert to a JSON5 string.
* @param replacer An array of String and Number objects that serve as a
* allowlist for selecting/filtering the properties of the value object to be
* included in the JSON5 string. If this value is null or not provided, all
* properties of the object are included in the resulting JSON5 string.
* @param space A String or Number object that's used to insert white space into
* the output JSON5 string for readability purposes. If this is a Number, it
* indicates the number of space characters to use as white space; this number
* is capped at 10 (if it is greater, the value is just 10). Values less than 1
* indicate that no space should be used. If this is a String, the string (or
* the first 10 characters of the string, if it's longer than that) is used as
* white space. If this parameter is not provided (or is null), no white space
* is used. If white space is used, trailing commas will be used in objects and
* arrays.
* @returns The JSON5 string converted from the JavaScript value.
*/
declare function stringify(
value: any,
replacer: (string | number)[],
space?: string | number | null,
): string
/**
* Converts a JavaScript value to a JSON5 string.
* @param value The value to convert to a JSON5 string.
* @param options An object specifying options.
* @returns The JSON5 string converted from the JavaScript value.
*/
declare function stringify(value: any, options: StringifyOptions): string
export = stringify
+261
View File
@@ -0,0 +1,261 @@
const util = require('./util')
module.exports = function stringify (value, replacer, space) {
const stack = []
let indent = ''
let propertyList
let replacerFunc
let gap = ''
let quote
if (
replacer != null &&
typeof replacer === 'object' &&
!Array.isArray(replacer)
) {
space = replacer.space
quote = replacer.quote
replacer = replacer.replacer
}
if (typeof replacer === 'function') {
replacerFunc = replacer
} else if (Array.isArray(replacer)) {
propertyList = []
for (const v of replacer) {
let item
if (typeof v === 'string') {
item = v
} else if (
typeof v === 'number' ||
v instanceof String ||
v instanceof Number
) {
item = String(v)
}
if (item !== undefined && propertyList.indexOf(item) < 0) {
propertyList.push(item)
}
}
}
if (space instanceof Number) {
space = Number(space)
} else if (space instanceof String) {
space = String(space)
}
if (typeof space === 'number') {
if (space > 0) {
space = Math.min(10, Math.floor(space))
gap = ' '.substr(0, space)
}
} else if (typeof space === 'string') {
gap = space.substr(0, 10)
}
return serializeProperty('', {'': value})
function serializeProperty (key, holder) {
let value = holder[key]
if (value != null) {
if (typeof value.toJSON5 === 'function') {
value = value.toJSON5(key)
} else if (typeof value.toJSON === 'function') {
value = value.toJSON(key)
}
}
if (replacerFunc) {
value = replacerFunc.call(holder, key, value)
}
if (value instanceof Number) {
value = Number(value)
} else if (value instanceof String) {
value = String(value)
} else if (value instanceof Boolean) {
value = value.valueOf()
}
switch (value) {
case null: return 'null'
case true: return 'true'
case false: return 'false'
}
if (typeof value === 'string') {
return quoteString(value, false)
}
if (typeof value === 'number') {
return String(value)
}
if (typeof value === 'object') {
return Array.isArray(value) ? serializeArray(value) : serializeObject(value)
}
return undefined
}
function quoteString (value) {
const quotes = {
"'": 0.1,
'"': 0.2,
}
const replacements = {
"'": "\\'",
'"': '\\"',
'\\': '\\\\',
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\v': '\\v',
'\0': '\\0',
'\u2028': '\\u2028',
'\u2029': '\\u2029',
}
let product = ''
for (let i = 0; i < value.length; i++) {
const c = value[i]
switch (c) {
case "'":
case '"':
quotes[c]++
product += c
continue
case '\0':
if (util.isDigit(value[i + 1])) {
product += '\\x00'
continue
}
}
if (replacements[c]) {
product += replacements[c]
continue
}
if (c < ' ') {
let hexString = c.charCodeAt(0).toString(16)
product += '\\x' + ('00' + hexString).substring(hexString.length)
continue
}
product += c
}
const quoteChar = quote || Object.keys(quotes).reduce((a, b) => (quotes[a] < quotes[b]) ? a : b)
product = product.replace(new RegExp(quoteChar, 'g'), replacements[quoteChar])
return quoteChar + product + quoteChar
}
function serializeObject (value) {
if (stack.indexOf(value) >= 0) {
throw TypeError('Converting circular structure to JSON5')
}
stack.push(value)
let stepback = indent
indent = indent + gap
let keys = propertyList || Object.keys(value)
let partial = []
for (const key of keys) {
const propertyString = serializeProperty(key, value)
if (propertyString !== undefined) {
let member = serializeKey(key) + ':'
if (gap !== '') {
member += ' '
}
member += propertyString
partial.push(member)
}
}
let final
if (partial.length === 0) {
final = '{}'
} else {
let properties
if (gap === '') {
properties = partial.join(',')
final = '{' + properties + '}'
} else {
let separator = ',\n' + indent
properties = partial.join(separator)
final = '{\n' + indent + properties + ',\n' + stepback + '}'
}
}
stack.pop()
indent = stepback
return final
}
function serializeKey (key) {
if (key.length === 0) {
return quoteString(key, true)
}
const firstChar = String.fromCodePoint(key.codePointAt(0))
if (!util.isIdStartChar(firstChar)) {
return quoteString(key, true)
}
for (let i = firstChar.length; i < key.length; i++) {
if (!util.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) {
return quoteString(key, true)
}
}
return key
}
function serializeArray (value) {
if (stack.indexOf(value) >= 0) {
throw TypeError('Converting circular structure to JSON5')
}
stack.push(value)
let stepback = indent
indent = indent + gap
let partial = []
for (let i = 0; i < value.length; i++) {
const propertyString = serializeProperty(String(i), value)
partial.push((propertyString !== undefined) ? propertyString : 'null')
}
let final
if (partial.length === 0) {
final = '[]'
} else {
if (gap === '') {
let properties = partial.join(',')
final = '[' + properties + ']'
} else {
let separator = ',\n' + indent
let properties = partial.join(separator)
final = '[\n' + indent + properties + ',\n' + stepback + ']'
}
}
stack.pop()
indent = stepback
return final
}
}
+3
View File
@@ -0,0 +1,3 @@
export declare const Space_Separator: RegExp
export declare const ID_Start: RegExp
export declare const ID_Continue: RegExp
File diff suppressed because one or more lines are too long
+5
View File
@@ -0,0 +1,5 @@
export declare function isSpaceSeparator(c?: string): boolean
export declare function isIdStartChar(c?: string): boolean
export declare function isIdContinueChar(c?: string): boolean
export declare function isDigit(c?: string): boolean
export declare function isHexDigit(c?: string): boolean
+35
View File
@@ -0,0 +1,35 @@
const unicode = require('../lib/unicode')
module.exports = {
isSpaceSeparator (c) {
return typeof c === 'string' && unicode.Space_Separator.test(c)
},
isIdStartChar (c) {
return typeof c === 'string' && (
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c === '$') || (c === '_') ||
unicode.ID_Start.test(c)
)
},
isIdContinueChar (c) {
return typeof c === 'string' && (
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
(c === '$') || (c === '_') ||
(c === '\u200C') || (c === '\u200D') ||
unicode.ID_Continue.test(c)
)
},
isDigit (c) {
return typeof c === 'string' && /[0-9]/.test(c)
},
isHexDigit (c) {
return typeof c === 'string' && /[0-9A-Fa-f]/.test(c)
},
}