const parse = require ( 'json-to-ast' ) ; export interface JsonPropertyLocation { path : string ; line : number ; value : any ; column : number ; } type JsonAst = JsonAstLiteral | JsonAstObject | JsonAstArray ; interface JsonAstLocation { start : { line : number ; column : number ; offset : number ; } ; end : { line : number ; column : number ; offset : number ; } ; source : null | string ; } interface JsonAstIdentifier { type : 'Identifier' ; value : string ; raw : string ; loc : JsonAstLocation ; } interface JsonAstObjectProperty { type : 'Property' ; key : JsonAstIdentifier ; value : JsonAst ; loc : JsonAstLocation ; } interface JsonAstLiteral { type : 'Literal' ; value : string | number | boolean | any ; raw : string ; loc : JsonAstLocation ; } interface JsonAstObject { type : 'Object' ; children : Array < JsonAstObjectProperty > ; loc : JsonAstLocation ; } interface JsonAstArray { type : 'Array' ; children : Array < JsonAst > ; loc : JsonAstLocation ; } function jsonToPropertyPaths ( ast , previousPath = [ ] ) { let children = [ ] ; if ( ast . type === 'Literal' ) { return [ { value : ast . value , path : previousPath . join ( '.' ) , line : ast . loc . start . line , column : ast . loc . start . column } , ] ; } else if ( ast . type === 'Array' ) { children = ast . children . map ( ( value , idx ) => jsonToPropertyPaths ( value , previousPath . slice ( ) . concat ( [ String ( idx ) ] ) ) ) ; } else if ( ast . type === 'Object' ) { children = ast . children . map ( property => { const path = property . key . value . replace ( '.' , '\\.' ) ; return jsonToPropertyPaths ( property . value , previousPath . slice ( ) . concat ( [ path ] ) ) ; } ) ; } return children . reduce ( ( a , b ) => a . concat ( b ) , [ ] ) ; } export function parseJson ( formattedJson ) { const parsedJson = parse ( formattedJson ) as JsonAst ; return jsonToPropertyPaths ( parsedJson , [ ] ) ; } export function literalsMappedByLines ( formattedJson ) { try { const parsedJson = parse ( formattedJson ) as JsonAst ; const literals = jsonToPropertyPaths ( parsedJson , [ ] ) ; const lines = [ ] ; for ( const literal of literals ) { lines [ literal . line - 1 ] = literal ; } return lines ; } catch ( error ) { return undefined ; } }