2 * @fileoverview Rule to require object keys to be sorted
3 * @author Toru Nagashima
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 const astUtils = require("./utils/ast-utils"),
13 naturalCompare = require("natural-compare");
15 //------------------------------------------------------------------------------
17 //------------------------------------------------------------------------------
20 * Gets the property name of the given `Property` node.
22 * - If the property's key is an `Identifier` node, this returns the key's name
23 * whether it's a computed property or not.
24 * - If the property has a static name, this returns the static name.
25 * - Otherwise, this returns null.
26 * @param {ASTNode} node The `Property` node to get.
27 * @returns {string|null} The property name or null.
30 function getPropertyName(node) {
31 const staticName = astUtils.getStaticPropertyName(node);
33 if (staticName !== null) {
37 return node.key.name || null;
41 * Functions which check that the given 2 names are in specific order.
43 * Postfix `I` is meant insensitive.
44 * Postfix `N` is meant natual.
47 const isValidOrders = {
52 return a.toLowerCase() <= b.toLowerCase();
55 return naturalCompare(a, b) <= 0;
58 return naturalCompare(a.toLowerCase(), b.toLowerCase()) <= 0;
61 return isValidOrders.asc(b, a);
64 return isValidOrders.ascI(b, a);
67 return isValidOrders.ascN(b, a);
70 return isValidOrders.ascIN(b, a);
74 //------------------------------------------------------------------------------
76 //------------------------------------------------------------------------------
83 description: "require object keys to be sorted",
84 category: "Stylistic Issues",
86 url: "https://eslint.org/docs/rules/sort-keys"
110 additionalProperties: false
118 const order = context.options[0] || "asc";
119 const options = context.options[1];
120 const insensitive = options && options.caseSensitive === false;
121 const natual = options && options.natural;
122 const minKeys = options && options.minKeys;
123 const isValidOrder = isValidOrders[
124 order + (insensitive ? "I" : "") + (natual ? "N" : "")
127 // The stack to save the previous property's name for each object literals.
131 ObjectExpression(node) {
135 numKeys: node.properties.length
139 "ObjectExpression:exit"() {
143 SpreadElement(node) {
144 if (node.parent.type === "ObjectExpression") {
145 stack.prevName = null;
150 if (node.parent.type === "ObjectPattern") {
154 const prevName = stack.prevName;
155 const numKeys = stack.numKeys;
156 const thisName = getPropertyName(node);
158 if (thisName !== null) {
159 stack.prevName = thisName;
162 if (prevName === null || thisName === null || numKeys < minKeys) {
166 if (!isValidOrder(prevName, thisName)) {
170 message: "Expected object keys to be in {{natual}}{{insensitive}}{{order}}ending order. '{{thisName}}' should be before '{{prevName}}'.",
175 insensitive: insensitive ? "insensitive " : "",
176 natual: natual ? "natural " : ""