Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/general errors checks #572

Merged
merged 7 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
669 changes: 282 additions & 387 deletions .pnp.cjs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ packageExtensions:
dependencies:
pretty-format: '*'
react-dom: '*'
react-datepicker@*:
dependencies:
'@types/react-onclickoutside': '*'
swiper@*:
dependencies:
'@types/react': '*'
Expand Down
6 changes: 3 additions & 3 deletions generators/button/src/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ const command = new Command()
.name('Button styles generator')
.argument('path <string>', 'Path to save the styles')
.option('-t, --theme path <string>', 'Path to colors file')
.action((path, options) => {
.action((path: string, options: Record<string, string>) => {
assert.ok(options.theme, 'Theme colors path is required')

const colorsFile = readFileSync(join(process.cwd(), options.theme)).toString('utf-8')
const { code } = transform(colorsFile, { presets: ['env'] })

if (!code) throw Error('Could not read the file')

// eslint-disable-next-line no-eval
const colors = eval(code)
// eslint-disable-next-line no-eval, security/detect-eval-with-expression
const colors: Record<string, any> = eval(code)

const generator = new ButtonAppearanceStyleGenerator(colors)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { writeFileSync } from 'fs'
import type { ButtonColorSchemes } from '../button-generator.interfaces.js'

import { pretty } from '@atls-ui-generators/utils'
import { getStylesName } from '@atls-ui-generators/utils'
import { writeFileSync } from 'fs'

import { ButtonColorSchemes } from '../button-generator.interfaces.js'
import { pretty } from '@atls-ui-generators/utils'
import { getStylesName } from '@atls-ui-generators/utils'

const getAppearanceStylesName = (variant: string, state: string) =>
const getAppearanceStylesName = (variant: string, state: string): string =>
getStylesName('appearance', variant, state)

export class ButtonAppearanceStyleGenerator {
Expand All @@ -14,10 +14,10 @@ export class ButtonAppearanceStyleGenerator {
{ import: '{ createAppearanceStyles }', from: '@atls-ui-parts/button' },
]

#variants: string[] = []
#variants: Array<string> = []

constructor(private readonly colorSchemes: ButtonColorSchemes) {
const allVariants = Object.keys(colorSchemes).reduce<string[]>(
const allVariants = Object.keys(colorSchemes).reduce<Array<string>>(
(array, key) => (key.startsWith('button.') ? [...array, key.split('.')[1]] : array),
[]
)
Expand All @@ -27,59 +27,27 @@ export class ButtonAppearanceStyleGenerator {
this.#variants = uniqueVariants
}

private generateVariantStatefulStyles(variant: string) {
const lines: string[] = []

const allStates: string[] = Object.keys(this.colorSchemes).reduce<string[]>(
(array, key) => (key.startsWith(`button.${variant}`) ? [...array, key.split('.')[2]] : array),
[]
)

const uniqueStates = [...new Set(allStates)]

for (const state of uniqueStates) {
lines.push(`const ${getAppearanceStylesName(variant, state)} = createAppearanceStyles({
fontColor: vars.colors['button.${variant}.${state}.font'],
backgroundColor: vars.colors['button.${variant}.${state}.background'],
borderColor: vars.colors['button.${variant}.${state}.border'],
})`)
}

return lines.join('\n\n')
}

private generateVariantAppearanceStyles(
variants: string[],
state: string,
addSuffix: boolean = true
) {
const suffix = addSuffix ? state : ''
return variants
.map((variant) => `${variant}${suffix}: ${getAppearanceStylesName(variant, state)},`)
.join('\n')
}

generateAppearanceStyles() {
generateAppearanceStyles(): Record<'appearanceStyles' | 'imports' | 'statefulStyles', string> {
const statefulStyles = pretty(
this.#variants.map((variant) => this.generateVariantStatefulStyles(variant)).join('\n\n')
)

const appearanceStyles = pretty(`
export const appearanceVariant = {
${this.generateVariantAppearanceStyles(this.#variants, 'Default', false)}
}
}

export const appearanceHover = {
${this.generateVariantAppearanceStyles(this.#variants, 'Hover')}
}

export const appearancePressed = {
}
export const appearancePressed = {
${this.generateVariantAppearanceStyles(this.#variants, 'Pressed')}
}
}

export const appearanceDisabled = {
${this.generateVariantAppearanceStyles(this.#variants, 'Disabled')}
}`)
}`)

const imports = pretty(
this.requiredImports
Expand All @@ -90,12 +58,12 @@ export class ButtonAppearanceStyleGenerator {
return { statefulStyles, appearanceStyles, imports }
}

generateFile(path: string, filename = 'appearance.css.ts') {
generateFile(path: string, filename = 'appearance.css.ts'): void {
const generated = this.generateAppearanceStyles()

const code = pretty(`
${generated.imports}
${generated.statefulStyles}
${generated.imports}
${generated.statefulStyles}
${generated.appearanceStyles}
`)

Expand All @@ -105,4 +73,36 @@ export class ButtonAppearanceStyleGenerator {

writeFileSync(`${path}/${filename}`, code)
}

private generateVariantStatefulStyles(variant: string): string {
const lines: Array<string> = []

const allStates: Array<string> = Object.keys(this.colorSchemes).reduce<Array<string>>(
(array, key) => (key.startsWith(`button.${variant}`) ? [...array, key.split('.')[2]] : array),
[]
)

const uniqueStates = [...new Set(allStates)]

for (const state of uniqueStates) {
lines.push(`const ${getAppearanceStylesName(variant, state)} = createAppearanceStyles({
fontColor: vars.colors['button.${variant}.${state}.font'],
backgroundColor: vars.colors['button.${variant}.${state}.background'],
borderColor: vars.colors['button.${variant}.${state}.border'],
})`)
}

return lines.join('\n\n')
}

private generateVariantAppearanceStyles(
variants: Array<string>,
state: string,
addSuffix: boolean = true
): string {
const suffix = addSuffix ? state : ''
return variants
.map((variant) => `${variant}${suffix}: ${getAppearanceStylesName(variant, state)},`)
.join('\n')
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { readFileSync } from 'fs'
import { mkdirSync } from 'fs'
import { rmdirSync } from 'fs'
import { existsSync } from 'fs'

import { pretty } from '@atls-ui-generators/utils'
Expand Down Expand Up @@ -107,6 +108,10 @@ export const appearanceDisabled = {
lightBlueDisabled: appearanceLightBlueDisabledStyles,
}
`
afterAll(() => {
if (existsSync(`${__dirname}/generated`))
rmdirSync(`${__dirname}/generated`, { recursive: true })
})

it('should generate code for appearance styles', () => {
const generator = new ButtonAppearanceStyleGenerator(colors)
Expand All @@ -126,7 +131,9 @@ export const appearanceDisabled = {

if (!existsSync(`${__dirname}/generated`)) mkdirSync(`${__dirname}/generated`)

expect(() => generator.generateFile(`${__dirname}/generated/`)).toThrowError()
expect(() => {
generator.generateFile(`${__dirname}/generated/`)
}).toThrowError()
})

it('should generate appearance styles file', () => {
Expand Down
4 changes: 2 additions & 2 deletions generators/icons/src/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const command = new Command()
.argument('path <string>', 'Path to save icons')
.option('-i, --icons path <string>', 'Path to icons dir')
.option('-r, --replacements path <string>', 'Path to replacements file')
.action(async (path, options) => {
.action(async (path: string, options: Record<string, string>) => {
assert.ok(options.icons, 'Icons dir path is required')

const iconsPath = join(process.cwd(), options.icons)
Expand All @@ -37,7 +37,7 @@ const command = new Command()

if (!code) throw Error('Could not read the file')

// eslint-disable-next-line no-eval
// eslint-disable-next-line no-eval, security/detect-eval-with-expression
replacements = eval(code)
}

Expand Down
4 changes: 3 additions & 1 deletion generators/icons/src/get-color-replacement.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ export interface GetColorReplacementOptions {
color: string
}

export const getColorReplacement = (options: GetColorReplacementOptions) => ({
export const getColorReplacement = (
options: GetColorReplacementOptions
): Record<string, string> => ({
[options.color]: `{(vars.colors${(options.themePaths || []).reduce(
(str, prop) => `${str}.${prop}`,
''
Expand Down
36 changes: 26 additions & 10 deletions generators/icons/src/svgr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,23 @@ import parserBabel from 'prettier/parser-babel'
import parserTypescript from 'prettier/parser-typescript'

// @ts-expect-error types
const svgrTemplate = ({ template }, opts, { componentName, jsx }) => {
const svgrTemplate = ({ template }, opts, { componentName, jsx }): any => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const typeScriptTpl = template.smart({ plugins: ['typescript', 'prettier'] })

// eslint-disable-next-line
return typeScriptTpl.ast`
import React from 'react'
import { vars } from '@ui/theme'
import { IconProps } from '../icons.interfaces'
import type { IconProps } from '../icons.interfaces'

export const ${componentName} = React.memo((props: IconProps) => (
${jsx}
))
`
}

const read = (files: Array<string>) =>
const read = async (files: Array<string>): Promise<Array<{ name: string; source: string }>> =>
Promise.all(
files.map(async (iconPath) => ({
name: `${camelcase(path.basename(iconPath, path.extname(iconPath)), {
Expand All @@ -35,10 +37,14 @@ const read = (files: Array<string>) =>
}))
)

const compile = (icons: Array<{ name: string, source: string }>, replacements: Record<string, any>) =>
const compile = async (
icons: Array<{ name: string; source: string }>,
replacements: Record<string, any>
): Promise<Array<{ name: string; code: any }>> =>
Promise.all(
icons.map(async (icon) => ({
name: icon.name,
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
code: await svgr(
icon.source.replace(/mask0/g, icon.name),
{
Expand All @@ -51,28 +57,38 @@ const compile = (icons: Array<{ name: string, source: string }>, replacements: R
}))
)

const save = async (sources: Array<{ name: string }>, targetDir: string) =>
const save = async (
sources: Array<{ name: string; code?: string }>,
targetDir: string
): Promise<Array<void>> =>
Promise.all(
sources.map((source) =>
fs.writeFileAsync(
path.join(targetDir, `${source.name}.tsx`),
// @ts-ignore
format(`/* eslint-disable */\n${source.code}`, {
// @ts-expect-error
format(`/* eslint-disable */\n${source?.code || ''}`, {
...prettierConfig,
filepath: path.join(targetDir, `${source.name}.tsx`),
plugins: [parserTypescript, parserBabel, prettierPlugin],
})
))
)

const createIndex = (sources: Array<{ name: string }>, targetDir: string) =>
const createIndex = (
sources: Array<{ name: string }>,
targetDir: string
): ReturnType<typeof fs.writeFileAsync> =>
fs.writeFileAsync(
path.join(targetDir, 'index.ts'),
`${sources.map((source) => `export * from './${source.name}'`).join('\n')}\n`
)

export const build = async (iconsPath: string, targetDir: string, replacements: object) => {
const prettifyIconsPath = () => {
export const build = async (
iconsPath: string,
targetDir: string,
replacements: object
): Promise<void> => {
const prettifyIconsPath = (): string => {
const parts = iconsPath.split('')
if (parts[parts.length - 1] === '/') {
parts.pop()
Expand Down
6 changes: 3 additions & 3 deletions generators/input/src/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ const command = new Command()
.name('Input styles generator')
.argument('path <string>', 'Path to save the styles')
.option('-t, --theme path <string>', 'Path to colors file')
.action((path, options) => {
.action((path: string, options: Record<string, string>) => {
assert.ok(options.theme, 'Theme colors path is required')

const colorsFile = readFileSync(join(process.cwd(), options.theme)).toString('utf-8')
const { code } = transform(colorsFile, { presets: ['env'] })

if (!code) throw Error('Could not read the file')

// eslint-disable-next-line no-eval
const colors = eval(code)
// eslint-disable-next-line no-eval, security/detect-eval-with-expression
const colors: Record<string, any> = eval(code)

const generator = new InputAppearanceStyleGenerator(colors)

Expand Down
Loading