@kaspersky/dev-tools
Version:
Development tools and configs for Babel, ESLint and TypeScript
210 lines (186 loc) • 6.74 kB
JavaScript
const { extractArgValue, isFormExcludet, isFromAlreadyMigrated, migrationList, message } = require('./helpers')
const predefinedIndentBeforeCssClasses = {
'indent-checkbox': 101,
'indent-toggle': 102,
'indent-label': 103
}
const indentCssClasses = [
'indent-1',
'indent-2',
'indent-3',
'indent-top-1',
'indent-top-2',
'indent-top-3',
'indent-both-1',
'indent-both-2',
'indent-both-3',
'indent-bottom-1',
'indent-bottom-2',
'indent-bottom-3',
'indent-top-negative-1',
'indent-top-negative-2',
'indent-top-negative-3',
'indent-bottom-negative-1',
'indent-bottom-negative-2',
'indent-bottom-negative-3',
...Object.keys(predefinedIndentBeforeCssClasses)
]
const typesWithSubElements = [
...['control-group', 20],
...['data-table', 31]
]
const filterIndentCSSClasses = (classesString) => {
return typeof classesString === 'string' && classesString
? classesString
.split(' ')
.filter(className => !indentCssClasses.some(indent => indent === className))
.join(' ')
: ''
}
const parseValueFromClassName = ({ customCssClasses, subString }) => {
return customCssClasses
? parseInt((customCssClasses
.split(' ')
.map(cssClass => {
return Object.keys(predefinedIndentBeforeCssClasses).some(key => key === cssClass)
? `indent-${predefinedIndentBeforeCssClasses[cssClass]}`
: cssClass
})
.find(cssClass => cssClass.replace(/-\d+/, '') === subString) || '')
.replace(/^\D+/g, '')
) || 0
: 0
}
const createReplaceCssClassesWithOffsets = (customClassFunction) => {
const resolveOffsets = ({
indent = 0,
offsetBottom = 0,
offsetTop = 0,
offsetAfter = 0,
customClass: customCssClasses
}) => {
const valuesFromClassName = customCssClasses
? {
cssClassLeft: parseValueFromClassName({ customCssClasses, subString: 'indent' }),
cssClassTop: parseValueFromClassName({ customCssClasses, subString: 'indent-top' }),
cssClassTopNegative: parseValueFromClassName({ customCssClasses, subString: 'indent-top-negative' }),
cssClassBottom: parseValueFromClassName({ customCssClasses, subString: 'indent-bottom' }),
cssClassBottomNegative: parseValueFromClassName({ customCssClasses, subString: 'indent-bottom-negative' }),
cssClassBoth: parseValueFromClassName({ customCssClasses, subString: 'indent-both' })
}
: {}
return {
indent:
indent ||
valuesFromClassName.cssClassLeft ||
valuesFromClassName.cssClassBoth ||
0,
offsetBottom:
offsetBottom ||
valuesFromClassName.cssClassBottom ||
(valuesFromClassName.cssClassBottomNegative ? -valuesFromClassName.cssClassBottomNegative : 0) ||
0,
offsetTop:
offsetTop ||
valuesFromClassName.cssClassTop ||
(valuesFromClassName.cssClassTopNegative ? -valuesFromClassName.cssClassTopNegative : 0) ||
0,
offsetAfter:
offsetAfter ||
valuesFromClassName.cssClassBoth ||
0,
customClass: customClassFunction(customCssClasses, filterIndentCSSClasses)
}
}
const updateProductSectionElement = el => {
return {
...el,
style: el.style && {
...el.style,
...resolveOffsets(el.style)
},
elements: Array.isArray(el.elements) && typesWithSubElements.includes(el.type)
? el.elements.map(updateProductSectionElement)
: el.elements
}
}
const updateBuilderSectionElement = el => {
if (!el || !el.state) {
return el
}
const elements = el.state.elements
return {
...el,
state: {
...el.state,
style: el.state.style && {
...el.state.style,
...resolveOffsets(el.state.style)
},
elements: Array.isArray(elements) && typesWithSubElements.includes(el.type)
? elements.map(updateBuilderSectionElement)
: elements
}
}
}
const replaceCssClassesWithOffsetsFunc = async ({ fs, path }) => {
const UI_FORMS_PATH = path.join('./client/ui/')
const FILE_EXT = '.json'
const specificFormArray = extractArgValue('--only') || []
const excludeArray = extractArgValue('--exclude')
return new Promise((resolve) => {
const formNames = fs.readdirSync(UI_FORMS_PATH)
.filter(file => path.extname(file) === FILE_EXT)
const resolvedFormNames = specificFormArray.length
? formNames.filter(file => specificFormArray.includes(file.replace(FILE_EXT, '')))
: formNames
// eslint-disable-next-line no-console
console.log(`${message.startingPatchOffsets} ${UI_FORMS_PATH}
`)
resolvedFormNames.forEach(file => {
if (isFormExcludet({ file, excludeArray })) {
// eslint-disable-next-line no-console
console.log(`${message.skipped} ${file}`)
return
}
// eslint-disable-next-line no-console
console.log(`${message.reading} ${file}`)
const json = JSON.parse(fs.readFileSync(`${UI_FORMS_PATH}${file}`))
if (isFromAlreadyMigrated(json, migrationList.offsets)) {
// eslint-disable-next-line no-console
console.log(`${message.alreadyMigrated} ${file}`)
return
}
const currentMigrationInfo = json.state.migrationInfo || []
const migrationSet = new Set([...currentMigrationInfo, migrationList.offsets])
const updatedJSON = {
...json,
state: {
...json.state,
migrationInfo: [...migrationSet]
},
elements: json.elements.map(updateBuilderSectionElement),
json: {
...json.json,
elements: json.json.elements.map(updateProductSectionElement)
}
}
if (Object.keys(updatedJSON).length) {
fs.writeFileSync(`${UI_FORMS_PATH}${file}`, JSON.stringify(updatedJSON, null, 2), { encoding: 'utf-8' })
// eslint-disable-next-line no-console
console.log(`${message.updated} ${file}`)
}
})
// eslint-disable-next-line no-console
console.log(message.donePatchOffsets)
resolve()
})
}
return replaceCssClassesWithOffsetsFunc
}
const replaceCssClassesWithOffsets = createReplaceCssClassesWithOffsets((customCssClasses, filterFunction) => customCssClasses && filterFunction(customCssClasses))
const replaceCssClassesWithOffsetsAndSaveCssClasses = createReplaceCssClassesWithOffsets((customCssClasses, filterFunction) => customCssClasses && customCssClasses)
module.exports = {
replaceCssClassesWithOffsets,
replaceCssClassesWithOffsetsAndSaveCssClasses
}