* Format JSON literals like object literals
Following up on commit a42db30 (https://github.com/prettier/prettier/issues/2173),
this change makes it so that literals in JSON files are formatted as
they would be in an object literal. This normalizes trailing zeroes,
exponential notation, unnecessarily escaped characters, etc.
It works by using babylon to parse literals as expressions, and putting
the result in the AST instead of a `json-literal` node. Since JSON
string literals have to be double-quoted, there's a new
`__prettier__isJson` flag on each node, which is used by the printer to
force double-quotes.
* json: Check options.parser when formatting StringLiteral
This is instead of having a custom AST property. See
https://github.com/prettier/prettier/pull/2181#discussion_r122578251
* multiparser: Use babylon.parseExpression
See https://github.com/prettier/prettier/pull/2181#discussion_r122578354
* json: Don't split result AST node into two
See https://github.com/prettier/prettier/pull/2181#discussion_r122578499
* json: Don't use babylon parser to build expression nodes
See https://github.com/prettier/prettier/pull/2181#discussion_r122579052
* Revert "multiparser: Use babylon.parseExpression"
This reverts commit 3d7a4362880d39fac0cea88b5d0186a29538cf6f.
* Remove unused parameter from babylon parser
* json: Remove unused constructorTypes
82 lines
2.0 KiB
JavaScript
82 lines
2.0 KiB
JavaScript
"use strict";
|
|
|
|
const createError = require("./parser-create-error");
|
|
|
|
function parse(text) {
|
|
const jsonToAst = require("json-to-ast");
|
|
try {
|
|
const ast = jsonToAst(text);
|
|
return toBabylon(ast);
|
|
} catch (err) {
|
|
const firstNewlineIndex = err.message.indexOf("\n");
|
|
const firstLine = err.message.slice(0, firstNewlineIndex);
|
|
const lastSpaceIndex = firstLine.lastIndexOf(" ");
|
|
const message = firstLine.slice(0, lastSpaceIndex);
|
|
const locString = firstLine.slice(lastSpaceIndex + 1);
|
|
const lineCol = locString.split(":").map(Number);
|
|
|
|
throw createError("(json-to-ast) " + message, {
|
|
start: {
|
|
line: lineCol[0],
|
|
column: lineCol[1]
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function toBabylon(node) {
|
|
const typeMap = {
|
|
object: "ObjectExpression",
|
|
property: "ObjectProperty",
|
|
identifier: "json-identifier",
|
|
array: "ArrayExpression"
|
|
};
|
|
|
|
const result = {
|
|
type: typeMap[node.type],
|
|
start: node.loc.start.offset,
|
|
end: node.loc.end.offset,
|
|
loc: node.loc
|
|
};
|
|
|
|
switch (node.type) {
|
|
case "object":
|
|
return Object.assign(result, {
|
|
properties: node.children.map(toBabylon)
|
|
});
|
|
case "property":
|
|
return Object.assign(result, {
|
|
key: toBabylon(node.key),
|
|
value: toBabylon(node.value)
|
|
});
|
|
case "identifier":
|
|
return Object.assign(result, {
|
|
value: node.value
|
|
});
|
|
case "array":
|
|
return Object.assign(result, {
|
|
elements: node.children.map(toBabylon)
|
|
});
|
|
case "literal": {
|
|
const constructorTypes = {
|
|
String: "StringLiteral",
|
|
Number: "NumericLiteral",
|
|
Boolean: "BooleanLiteral"
|
|
};
|
|
|
|
const value = JSON.parse(node.rawValue);
|
|
const type = value === null
|
|
? "NullLiteral"
|
|
: constructorTypes[value.constructor.name];
|
|
|
|
return Object.assign(result, {
|
|
type: type,
|
|
value: value,
|
|
extra: { raw: node.rawValue }
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = parse;
|