-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2766 from epam/mergeFigmaVariablesScript
Add merge figma variables script
- Loading branch information
Showing
6 changed files
with
200 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { runTask } from '../utils/taskUtils'; | ||
import { taskConfig } from '../tasks/mergeFigmaVariables/main'; | ||
|
||
runTask(taskConfig); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import { ITaskConfig, TTaskParams } from '../../utils/taskUtils'; | ||
import { readFigmaVarCollection, writeFileSync } from '../themeTokensGen/utils/fileUtils'; | ||
import { IFigmaVarCollection, IFigmaVarRaw } from '../themeTokensGen/types/sourceTypes'; | ||
import isEqual from 'react-fast-compare'; | ||
import deepmerge from 'deepmerge'; | ||
|
||
const ARGS = { | ||
// source collection JSON (UX designers should provide it) | ||
BASE_JSON: '--base', | ||
CHANGED_JSON: '--changed', | ||
NEW_JSON: '--new', | ||
// output folder for SCSS mixins | ||
OUT: '--out', | ||
}; | ||
|
||
interface DiffElement { | ||
type: 'added' | 'modified'; | ||
name: string; | ||
diff: any; | ||
} | ||
|
||
export const taskConfig: ITaskConfig = { | ||
main, | ||
cliArgs: { | ||
[ARGS.BASE_JSON]: { format: 'NameValue', required: true }, | ||
[ARGS.CHANGED_JSON]: { format: 'NameValue', required: true }, | ||
[ARGS.NEW_JSON]: { format: 'NameValue', required: true }, | ||
[ARGS.OUT]: { format: 'NameValue', required: true }, | ||
}, | ||
}; | ||
|
||
async function main(params: TTaskParams) { | ||
const { | ||
[ARGS.BASE_JSON]: { value: baseJsonPath }, | ||
[ARGS.CHANGED_JSON]: { value: changedJsonPath }, | ||
[ARGS.NEW_JSON]: { value: newVersionJsomPath }, | ||
[ARGS.OUT]: { value: outPath }, | ||
} = params.cliArgs; | ||
|
||
const baseJson = readFigmaVarCollection(baseJsonPath!); | ||
const changedJson = readFigmaVarCollection(changedJsonPath!); | ||
const newVersionJson = readFigmaVarCollection(newVersionJsomPath!); | ||
|
||
const diff = calculateDiff(baseJson, changedJson); | ||
writeFileSync(`${outPath}/diff.json`, JSON.stringify(diff, null, 2)); | ||
|
||
const { newJson, warnings } = applyChanges(newVersionJson, diff); | ||
writeFileSync(`${outPath}/newTheme.json`, JSON.stringify(newJson, null, 2)); | ||
writeFileSync(`${outPath}/warnings.json`, JSON.stringify(warnings, null, 2)); | ||
} | ||
|
||
function calculateDiff(oldData: IFigmaVarCollection, newData: IFigmaVarCollection): Record<string, DiffElement> { | ||
const changes: Record<string, DiffElement> = {}; | ||
|
||
for (const newItem of newData.variables) { | ||
const oldItem = oldData.variables.find((item) => item.id === newItem.id); | ||
|
||
if (!oldItem) { | ||
changes[newItem.id] = { type: 'added', name: newItem.name, diff: newItem }; | ||
} else { | ||
const diff: DiffElement = { type: 'modified', name: newItem.name, diff: {} as IFigmaVarRaw }; | ||
|
||
Object.keys(newItem).forEach((key) => { | ||
const typedKey = key as keyof IFigmaVarRaw; | ||
|
||
if (typedKey === 'valuesByMode') { | ||
Object.keys(newItem.valuesByMode).forEach((mode) => { | ||
if (!isEqual(newItem.valuesByMode[mode], oldItem.valuesByMode[mode])) { | ||
diff.diff.valuesByMode = { ...diff.diff.valuesByMode || {}, [mode]: newItem.valuesByMode[mode] }; | ||
} | ||
}); | ||
} else if (typedKey === 'resolvedValuesByMode') { | ||
Object.keys(newItem.resolvedValuesByMode).forEach((mode) => { | ||
if (!isEqual(newItem.resolvedValuesByMode[mode], oldItem.resolvedValuesByMode[mode])) { | ||
diff.diff.resolvedValuesByMode = { ...diff.diff.resolvedValuesByMode || {}, [mode]: newItem.resolvedValuesByMode[mode] }; | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
if (Object.keys(diff.diff).length > 0) { | ||
changes[newItem.id] = diff; | ||
} | ||
} | ||
} | ||
|
||
if (!isEqual(oldData.modes, newData.modes)) { | ||
changes['modes'] = { type: 'modified', name: 'modes', diff: { modes: newData.modes } }; | ||
} | ||
|
||
return changes; | ||
} | ||
|
||
function applyChanges(data: IFigmaVarCollection, changes: Record<string, DiffElement>): { newJson: IFigmaVarCollection, warnings: string[] } { | ||
const newJson: IFigmaVarCollection = { ...data }; | ||
const warningsList: string[] = []; | ||
|
||
if (changes['modes']) { | ||
if (!Object.keys(data.modes).some((mode) => Object.keys(newJson.modes).includes(mode))) { | ||
console.error('There is no the same theme_id(mods array) in the new json to apply changes. Check the ids of themes, probably it is needed to change them manually'); | ||
throw new Error('There is no the same theme id(mods array) in the new json to apply changes. Check the ids of themes, probably it is needed to change them manually'); | ||
} | ||
|
||
newJson.modes = changes['modes'].diff.modes; | ||
} | ||
|
||
newJson.variables = newJson.variables.map((item) => { | ||
const change = changes[item.id]; | ||
if (change && change.type === 'modified') { | ||
return deepmerge(item, change.diff); | ||
} | ||
return item; | ||
}); | ||
|
||
Object.keys(changes).forEach((id) => { | ||
const change = changes[id]; | ||
if (change.type === 'added' && !newJson.variables.find((item) => item.id === id)) { | ||
newJson.variables.push(changes[id].diff as IFigmaVarRaw); | ||
newJson.variableIds.push(id); | ||
} | ||
|
||
if (change.type === 'modified' && id !== 'modes' && !newJson.variables.find((item) => item.id === id)) { | ||
warningsList.push(`Variable with id: '${id}' and name: '${change.name}' was changed and not found in new version JSON. Probably it was removed, please check changelog.`); | ||
} | ||
}); | ||
|
||
return { newJson: newJson, warnings: warningsList }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7057,7 +7057,7 @@ deep-is@^0.1.3, deep-is@~0.1.3: | |
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" | ||
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== | ||
|
||
deepmerge@^4.2.2: | ||
deepmerge@4.3.1, deepmerge@^4.2.2: | ||
version "4.3.1" | ||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" | ||
integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== | ||
|
@@ -16381,7 +16381,16 @@ string-natural-compare@^3.0.1: | |
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" | ||
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== | ||
|
||
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: | ||
"string-width-cjs@npm:string-width@^4.2.0": | ||
version "4.2.3" | ||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" | ||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== | ||
dependencies: | ||
emoji-regex "^8.0.0" | ||
is-fullwidth-code-point "^3.0.0" | ||
strip-ansi "^6.0.1" | ||
|
||
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: | ||
version "4.2.3" | ||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" | ||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== | ||
|
@@ -16505,7 +16514,14 @@ stringify-object@^3.3.0: | |
is-obj "^1.0.1" | ||
is-regexp "^1.0.0" | ||
|
||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", [email protected], strip-ansi@^6.0.0, strip-ansi@^6.0.1: | ||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1": | ||
version "6.0.1" | ||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" | ||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== | ||
dependencies: | ||
ansi-regex "^5.0.1" | ||
|
||
[email protected], strip-ansi@^6.0.0, strip-ansi@^6.0.1: | ||
version "6.0.1" | ||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" | ||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== | ||
|
@@ -18402,7 +18418,7 @@ [email protected]: | |
"@types/trusted-types" "^2.0.2" | ||
workbox-core "6.6.1" | ||
|
||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: | ||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": | ||
version "7.0.0" | ||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" | ||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== | ||
|
@@ -18420,6 +18436,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: | |
string-width "^4.1.0" | ||
strip-ansi "^6.0.0" | ||
|
||
wrap-ansi@^7.0.0: | ||
version "7.0.0" | ||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" | ||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== | ||
dependencies: | ||
ansi-styles "^4.0.0" | ||
string-width "^4.1.0" | ||
strip-ansi "^6.0.0" | ||
|
||
wrap-ansi@^8.1.0: | ||
version "8.1.0" | ||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" | ||
|