Skip to content

Commit

Permalink
feat: added json key order linter
Browse files Browse the repository at this point in the history
  • Loading branch information
PKulkoRaccoonGang committed Nov 12, 2024
1 parent b4d560b commit 40ff25a
Show file tree
Hide file tree
Showing 120 changed files with 10,967 additions and 5,381 deletions.
193 changes: 193 additions & 0 deletions json-key-order-linter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
const fs = require('fs');
const path = require('path');
const chalk = require('chalk');

const folderPath = 'tokens/';

const KEY_ORDERS = {
main: ['$type', '$value', '$description', 'outputReferences', 'modify', 'source'],
value: ['behavior', 'delay', 'duration', 'property', 'timing-function'],
modify: ['type', 'toReplace', 'replaceWith'],
};

const shouldFix = process.argv.includes('--fix');
let warningsCount = 0;
let processedFileCount = 0;

/**
* Reorders the keys in an object based on a specified key order.
* @param {Object} obj - The object to reorder.
* @param {string[]} desiredKeyOrder - The desired order for the keys.
* @returns {Object} - An object containing the reordered object and
* a flag indicating if the key order was mismatched and mismatched keys.
*/
function reorderObjectKeys(obj, desiredKeyOrder) {
const reorderedObject = {};
const originalKeyList = Object.keys(obj);
let isKeyOrderMismatched = false;
const mismatchedKeysList = [];

desiredKeyOrder.forEach((key) => {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
reorderedObject[key] = obj[key];
}
});

originalKeyList.forEach((key) => {
if (!Object.prototype.hasOwnProperty.call(reorderedObject, key)) {
reorderedObject[key] = obj[key];
}
});

if (JSON.stringify(originalKeyList) !== JSON.stringify(Object.keys(reorderedObject))) {
isKeyOrderMismatched = true;
mismatchedKeysList.push(...originalKeyList.filter((key, index) => key !== Object.keys(reorderedObject)[index]));
}

return { reorderedObject, isKeyOrderMismatched, mismatchedKeys: mismatchedKeysList };
}

/**
* Recursively reorders keys in JSON data based on specified key orders for nested objects.
* @param {*} data - The JSON data (object, array, or primitive) to process.
* @param {string} currentPath - The path to the current data within the JSON structure.
* @returns {Object} - An object containing the reordered data and
* a flag indicating if any key order mismatches were found.
*/
function reorderKeysInJson(data, currentPath = '') {
if (Array.isArray(data)) {
return data.map((item, index) => reorderKeysInJson(item, `${currentPath}[${index}]`));
}
if (typeof data === 'object' && data !== null) {
const {
reorderedObject: reorderedData, isKeyOrderMismatched: mainMismatch, mismatchedKeys: mainMismatchedKeys,
} = reorderObjectKeys(data, KEY_ORDERS.main);
let hasAnyKeyOrderMismatch = mainMismatch;
const mismatches = mainMismatch ? { [currentPath]: mainMismatchedKeys } : {};

if (
Object.prototype.hasOwnProperty.call(reorderedData, '$value')
&& typeof reorderedData.$value === 'object'
&& reorderedData.$value !== null
) {
if (Object.values(reorderedData.$value).every((item) => typeof item === 'object' && item !== null)) {
Object.keys(reorderedData.$value).forEach((key) => {
const {
reorderedObject, isKeyOrderMismatched, mismatchedKeys: valueMismatchedKeys,
} = reorderObjectKeys(reorderedData.$value[key], KEY_ORDERS.value);
reorderedData.$value[key] = reorderedObject;
if (isKeyOrderMismatched) {
hasAnyKeyOrderMismatch = true;
mismatches[`${currentPath}.$value.${key}`] = valueMismatchedKeys;
}
});
} else {
const {
reordered: reorderedValue, isKeyOrderMismatched, mismatchedKeys: valueMismatchedKeys,
} = reorderObjectKeys(reorderedData.$value, KEY_ORDERS.value);
reorderedData.$value = reorderedValue;
if (isKeyOrderMismatched) {
hasAnyKeyOrderMismatch = true;
mismatches[`${currentPath}.$value`] = valueMismatchedKeys;
}
}
}

if (Array.isArray(reorderedData.modify)) {
reorderedData.modify = reorderedData.modify.map((item, index) => {
if (typeof item === 'object' && item !== null) {
const {
reorderedObject,
isKeyOrderMismatched, mismatchedKeys: modifyMismatchedKeys,
} = reorderObjectKeys(item, KEY_ORDERS.modify);
if (isKeyOrderMismatched) {
hasAnyKeyOrderMismatch = true;
mismatches[`${currentPath}.modify[${index}]`] = modifyMismatchedKeys;
}
return reorderedObject;
}
return item;
});
}

Object.keys(reorderedData).forEach((key) => {
const result = reorderKeysInJson(reorderedData[key], `${currentPath}.${key}`);
reorderedData[key] = result.reorderedData || result;
if (result.isKeyOrderMismatched) {
Object.assign(mismatches, result.mismatches);
hasAnyKeyOrderMismatch = true;
}
});

return {
reorderedData,
isKeyOrderMismatched: hasAnyKeyOrderMismatch,
mismatches,
};
}
return {
reorderedData: data,
isKeyOrderMismatched: false,
mismatches: {},
};
}

/**
* Processes all JSON files in a given directory path, reordering keys in each file based on predefined key orders.
* @param {string} directoryPath - The path of the directory containing JSON files.
*/
function processJsonFilesInDirectory(directoryPath) {
fs.readdirSync(directoryPath).forEach((fileName) => {
const filePath = path.join(directoryPath, fileName);
const fileStats = fs.statSync(filePath);

if (fileStats.isDirectory()) {
processJsonFilesInDirectory(filePath);
} else if (fileStats.isFile() && path.extname(fileName) === '.json') {
try {
let fileContent = fs.readFileSync(filePath, 'utf-8');
const jsonData = JSON.parse(fileContent);

const { reorderedData, isKeyOrderMismatched, mismatches } = reorderKeysInJson(jsonData);

if (isKeyOrderMismatched) {
warningsCount++;
if (shouldFix) {
fs.writeFileSync(filePath, JSON.stringify(reorderedData, null, 2), 'utf-8');
} else {
console.warn(chalk.yellow(`Warning: Key order mismatch in ${filePath}.`));

Check warning on line 158 in json-key-order-linter.js

View workflow job for this annotation

GitHub Actions / tests

Unexpected console statement
console.warn(chalk.red('Mismatched keys by path:'));

Check warning on line 159 in json-key-order-linter.js

View workflow job for this annotation

GitHub Actions / tests

Unexpected console statement
Object.entries(mismatches).forEach(([keyPath, keys]) => {
console.warn(chalk.cyan(` Path: ${keyPath.slice(1)}`));

Check warning on line 161 in json-key-order-linter.js

View workflow job for this annotation

GitHub Actions / tests

Unexpected console statement
console.warn(chalk.magenta(` Mismatched keys: ${keys.join(', ')}`));

Check warning on line 162 in json-key-order-linter.js

View workflow job for this annotation

GitHub Actions / tests

Unexpected console statement
console.warn();

Check warning on line 163 in json-key-order-linter.js

View workflow job for this annotation

GitHub Actions / tests

Unexpected console statement
});
}
}

if (!fileContent.endsWith('\n')) {
fileContent += '\n';
fs.writeFileSync(filePath, fileContent, 'utf-8');
}

processedFileCount++;
} catch (error) {
console.error(chalk.red(`Error processing file ${filePath}:`), error);

Check warning on line 175 in json-key-order-linter.js

View workflow job for this annotation

GitHub Actions / tests

Unexpected console statement
}
}
});
}

processJsonFilesInDirectory(folderPath);

let statusMessage;

if (shouldFix) {
statusMessage = chalk.green(`Processed ${processedFileCount} files. ${warningsCount} files were updated.`);
} else if (warningsCount > 0) {
statusMessage = chalk.yellow(`Processed ${processedFileCount} files. ${warningsCount} files have key order mismatches.`);
} else {
statusMessage = chalk.green(`Processed ${processedFileCount} files. All files are in correct order.`);
}

console.log(statusMessage);

Check warning on line 193 in json-key-order-linter.js

View workflow job for this annotation

GitHub Actions / tests

Unexpected console statement
134 changes: 49 additions & 85 deletions styles/css/core/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
--pgn-elevation-zindex-600: 600; /* z-index of level 600. */
--pgn-elevation-zindex-400: 400; /* z-index of level 400. */
--pgn-elevation-zindex-200: 200; /* z-index of level 200. */
--pgn-elevation-zindex-0: 0; /* z-index of level 0. */
--pgn-elevation-zindex-0-is-key-order-mismatched: false; /* z-index of level 0. */
--pgn-elevation-zindex-0-reordered-data: 0; /* z-index of level 0. */
--pgn-elevation-tooltip-zindex: 1070;
--pgn-elevation-sheet-zindex-main: 1032;
--pgn-elevation-sheet-zindex-backdrop: 1031;
Expand All @@ -30,76 +31,46 @@
--pgn-elevation-modal-zindex: 1050;
--pgn-elevation-modal-backdrop-zindex: 1040;
--pgn-elevation-dropdown-zindex: 1000;
--pgn-transition-collapse-width-behavior: normal; /* Collapse transition for width that takes 350ms */
--pgn-transition-collapse-width-delay: 0s; /* Collapse transition for width that takes 350ms */
--pgn-transition-collapse-width-timing-function: ease; /* Collapse transition for width that takes 350ms */
--pgn-transition-collapse-width-duration: 0.35s; /* Collapse transition for width that takes 350ms */
--pgn-transition-collapse-width-property: width; /* Collapse transition for width that takes 350ms */
--pgn-transition-collapse-height-behavior: normal; /* Collapse transition for height that takes 350ms */
--pgn-transition-collapse-height-delay: 0s; /* Collapse transition for height that takes 350ms */
--pgn-transition-collapse-height-timing-function: ease; /* Collapse transition for height that takes 350ms */
--pgn-transition-collapse-height-duration: 0.35s; /* Collapse transition for height that takes 350ms */
--pgn-transition-collapse-height-property: height; /* Collapse transition for height that takes 350ms */
--pgn-transition-fade-behavior: normal; /* Opacity transition that takes 150ms */
--pgn-transition-fade-delay: 0s; /* Opacity transition that takes 150ms */
--pgn-transition-fade-timing-function: linear; /* Opacity transition that takes 150ms */
--pgn-transition-fade-duration: 0.15s; /* Opacity transition that takes 150ms */
--pgn-transition-fade-property: opacity; /* Opacity transition that takes 150ms */
--pgn-transition-base-behavior: normal; /* Generic transition for any property change */
--pgn-transition-base-delay: 0s; /* Generic transition for any property change */
--pgn-transition-base-timing-function: ease-in-out; /* Generic transition for any property change */
--pgn-transition-base-duration: 0.2s; /* Generic transition for any property change */
--pgn-transition-base-property: all; /* Generic transition for any property change */
--pgn-transition-progress-bar-transition-behavior: normal;
--pgn-transition-progress-bar-transition-delay: 0s;
--pgn-transition-progress-bar-transition-timing-function: ease;
--pgn-transition-progress-bar-transition-duration: 0.6s;
--pgn-transition-progress-bar-transition-property: width;
--pgn-transition-progress-bar-animation-timing-iteration-count: infinite;
--pgn-transition-progress-bar-animation-timing-delay: 0s;
--pgn-transition-progress-bar-animation-timing-timing-function: linear;
--pgn-transition-progress-bar-animation-timing-duration: 1s;
--pgn-transition-form-control-3-behavior: normal;
--pgn-transition-form-control-3-delay: 0s;
--pgn-transition-form-control-3-timing-function: ease-in-out;
--pgn-transition-form-control-3-duration: 0.15s;
--pgn-transition-form-control-3-property: box-shadow;
--pgn-transition-form-control-2-behavior: normal;
--pgn-transition-form-control-2-delay: 0s;
--pgn-transition-form-control-2-timing-function: ease-in-out;
--pgn-transition-form-control-2-duration: 0.15s;
--pgn-transition-form-control-2-property: border-color;
--pgn-transition-form-control-1-behavior: normal;
--pgn-transition-form-control-1-delay: 0s;
--pgn-transition-form-control-1-timing-function: ease-in-out;
--pgn-transition-form-control-1-duration: 0.15s;
--pgn-transition-form-control-1-property: background-color;
--pgn-transition-form-input-2-behavior: normal;
--pgn-transition-form-input-2-delay: 0s;
--pgn-transition-form-input-2-timing-function: ease-in-out;
--pgn-transition-form-input-2-duration: 0.15s;
--pgn-transition-form-input-2-property: box-shadow;
--pgn-transition-form-input-1-behavior: normal;
--pgn-transition-form-input-1-delay: 0s;
--pgn-transition-form-input-1-timing-function: ease-in-out;
--pgn-transition-form-input-1-duration: 0.15s;
--pgn-transition-form-input-1-property: border-color;
--pgn-transition-carousel-control-behavior: normal;
--pgn-transition-carousel-control-delay: 0ms;
--pgn-transition-carousel-control-timing-function: ease;
--pgn-transition-carousel-control-duration: 0.15s;
--pgn-transition-carousel-control-property: opacity;
--pgn-transition-carousel-indicator-behavior: normal;
--pgn-transition-carousel-indicator-delay: 0ms;
--pgn-transition-carousel-indicator-timing-function: ease;
--pgn-transition-carousel-indicator-duration: var(--pgn-transition-carousel-duration);
--pgn-transition-carousel-indicator-property: opacity;
--pgn-transition-collapse-width-is-key-order-mismatched: false; /* Collapse transition for width that takes 350ms */
--pgn-transition-collapse-height-is-key-order-mismatched: false; /* Collapse transition for height that takes 350ms */
--pgn-transition-fade-is-key-order-mismatched: false; /* Opacity transition that takes 150ms */
--pgn-transition-base-is-key-order-mismatched: false; /* Generic transition for any property change */
--pgn-transition-progress-bar-transition-is-key-order-mismatched: false;
--pgn-transition-progress-bar-animation-timing-is-key-order-mismatched: false;
--pgn-transition-form-control-3-is-key-order-mismatched: false;
--pgn-transition-form-control-3-reordered-data-timing-function: ease-in-out;
--pgn-transition-form-control-3-reordered-data-property: box-shadow;
--pgn-transition-form-control-3-reordered-data-duration: 0.15s;
--pgn-transition-form-control-3-reordered-data-delay: 0s;
--pgn-transition-form-control-3-reordered-data-behavior: normal;
--pgn-transition-form-control-2-is-key-order-mismatched: false;
--pgn-transition-form-control-2-reordered-data-timing-function: ease-in-out;
--pgn-transition-form-control-2-reordered-data-property: border-color;
--pgn-transition-form-control-2-reordered-data-duration: 0.15s;
--pgn-transition-form-control-2-reordered-data-delay: 0s;
--pgn-transition-form-control-2-reordered-data-behavior: normal;
--pgn-transition-form-control-1-is-key-order-mismatched: false;
--pgn-transition-form-control-1-reordered-data-timing-function: ease-in-out;
--pgn-transition-form-control-1-reordered-data-property: background-color;
--pgn-transition-form-control-1-reordered-data-duration: 0.15s;
--pgn-transition-form-control-1-reordered-data-delay: 0s;
--pgn-transition-form-control-1-reordered-data-behavior: normal;
--pgn-transition-form-input-2-is-key-order-mismatched: false;
--pgn-transition-form-input-2-reordered-data-timing-function: ease-in-out;
--pgn-transition-form-input-2-reordered-data-property: box-shadow;
--pgn-transition-form-input-2-reordered-data-duration: 0.15s;
--pgn-transition-form-input-2-reordered-data-delay: 0s;
--pgn-transition-form-input-2-reordered-data-behavior: normal;
--pgn-transition-form-input-1-is-key-order-mismatched: false;
--pgn-transition-form-input-1-reordered-data-timing-function: ease-in-out;
--pgn-transition-form-input-1-reordered-data-property: border-color;
--pgn-transition-form-input-1-reordered-data-duration: 0.15s;
--pgn-transition-form-input-1-reordered-data-delay: 0s;
--pgn-transition-form-input-1-reordered-data-behavior: normal;
--pgn-transition-carousel-control-is-key-order-mismatched: false;
--pgn-transition-carousel-indicator-is-key-order-mismatched: false;
--pgn-transition-carousel-duration: 0.6s;
--pgn-transition-carousel-base-behavior: normal;
--pgn-transition-carousel-base-delay: 0ms;
--pgn-transition-carousel-base-timing-function: ease-in-out;
--pgn-transition-carousel-base-duration: var(--pgn-transition-carousel-duration);
--pgn-transition-carousel-base-property: transform;
--pgn-transition-carousel-base-is-key-order-mismatched: false;
--pgn-transition-btn: none;
--pgn-transition-badge: none;
--pgn-typography-print-page-size: a3;
Expand Down Expand Up @@ -147,10 +118,10 @@
--pgn-typography-font-size-sm: 87.5%; /* Small font size. */
--pgn-typography-font-size-lg: calc(var(--pgn-typography-font-size-base) * 1.25); /* Lead text font size. */
--pgn-typography-font-size-base: 1.125rem; /* Base font size. */
--pgn-typography-font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; /* Monospace font family. */
--pgn-typography-font-family-monospace-is-key-order-mismatched: false; /* Monospace font family. */
--pgn-typography-font-family-serif: serif; /* Serif font family. */
--pgn-typography-font-family-sans-serif: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; /* Sans-serif font family. */
--pgn-typography-font-family-base: var(--pgn-typography-font-family-sans-serif); /* Basic font family. */
--pgn-typography-font-family-sans-serif-is-key-order-mismatched: false; /* Sans-serif font family. */
--pgn-typography-font-family-base-is-key-order-mismatched: false; /* Basic font family. */
--pgn-typography-blockquote-font-size: calc(var(--pgn-typography-font-size-base) * 1.25);
--pgn-typography-blockquote-small-font-size: var(--pgn-typography-font-size-sm);
--pgn-typography-dt-font-weight: var(--pgn-typography-font-weight-bold);
Expand Down Expand Up @@ -316,11 +287,9 @@
--pgn-spacing-nav-link-padding-y: 0.5rem;
--pgn-spacing-modal-dialog-margin: 1.5rem;
--pgn-spacing-modal-header-padding-y: 1rem;
--pgn-spacing-modal-header-padding-base-y: var(--pgn-spacing-modal-header-padding-y);
--pgn-spacing-modal-header-padding-base-x: 1.5rem;
--pgn-spacing-modal-header-padding-base-is-key-order-mismatched: false;
--pgn-spacing-modal-footer-padding-y: 1rem;
--pgn-spacing-modal-footer-padding-base-y: var(--pgn-spacing-modal-footer-padding-y);
--pgn-spacing-modal-footer-padding-base-x: 1.5rem;
--pgn-spacing-modal-footer-padding-base-is-key-order-mismatched: false;
--pgn-spacing-modal-inner-padding-bottom: 0.7rem;
--pgn-spacing-modal-inner-padding-base: 1.5rem;
--pgn-spacing-menu-item-icon-margin-right: var(--pgn-spacing-menu-item-icon-margin-left);
Expand All @@ -334,10 +303,7 @@
--pgn-spacing-form-control-select-feedback-tooltip-padding-x: 0.5rem;
--pgn-spacing-form-control-select-feedback-tooltip-padding-y: 0.25rem;
--pgn-spacing-form-control-select-feedback-margin-top: var(--pgn-spacing-form-text-margin-top);
--pgn-spacing-form-control-select-feedback-icon-position-offset-y: 0;
--pgn-spacing-form-control-select-feedback-icon-position-offset-x: calc(var(--pgn-spacing-form-control-select-padding-x-base) + var(--pgn-spacing-form-control-select-indicator-padding));
--pgn-spacing-form-control-select-feedback-icon-position-position-x: right;
--pgn-spacing-form-control-select-feedback-icon-position-position-y: center;
--pgn-spacing-form-control-select-feedback-icon-position-is-key-order-mismatched: false;
--pgn-spacing-form-control-select-feedback-icon-padding-right: calc((1em + 2 * var(--pgn-spacing-form-control-select-padding-y-base)) * 3 / 4 + var(--pgn-spacing-form-control-select-padding-x-base) + var(--pgn-spacing-form-control-select-indicator-padding));
--pgn-spacing-form-control-select-indicator-padding: 1rem;
--pgn-spacing-form-control-select-padding-x-lg: var(--pgn-spacing-form-input-padding-x-lg);
Expand Down Expand Up @@ -366,16 +332,14 @@
--pgn-spacing-dropzone-padding: 1.5rem;
--pgn-spacing-dropdown-close-container-top: 0.625rem;
--pgn-spacing-dropdown-divider-margin-y: calc(var(--pgn-spacing-spacer-base) / 2);
--pgn-spacing-dropdown-padding-header-y: 0.5rem;
--pgn-spacing-dropdown-padding-header-x: var(--pgn-spacing-dropdown-padding-x-item);
--pgn-spacing-dropdown-padding-header-is-key-order-mismatched: false;
--pgn-spacing-dropdown-padding-y-item: 0.25rem;
--pgn-spacing-dropdown-padding-y-base: 0.5rem;
--pgn-spacing-dropdown-padding-x-item: 1rem;
--pgn-spacing-dropdown-padding-x-base: 0rem;
--pgn-spacing-dropdown-spacer: 0.125rem;
--pgn-spacing-data-table-footer-position: center;
--pgn-spacing-data-table-padding-cell-y: 0.75rem;
--pgn-spacing-data-table-padding-cell-x: 0.5rem;
--pgn-spacing-data-table-padding-cell-is-key-order-mismatched: false;
--pgn-spacing-data-table-padding-small: 0.5rem;
--pgn-spacing-data-table-padding-y: 0.75rem;
--pgn-spacing-data-table-padding-x: 0.75rem;
Expand Down
Loading

0 comments on commit 40ff25a

Please sign in to comment.