Skip to content

Commit

Permalink
Merge pull request #126 from bem/browser
Browse files Browse the repository at this point in the history
Themekit in browser
  • Loading branch information
Nnigmat authored Jun 23, 2021
2 parents 628f719 + 6fc8c4d commit 3118e00
Show file tree
Hide file tree
Showing 17 changed files with 218 additions and 447 deletions.
24 changes: 21 additions & 3 deletions src/cli/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { Command, flags } from '@oclif/command'
import { watch } from 'chokidar'
import chalk from 'chalk'

import { Config } from '../core/config'
import { loadConfig } from '../core/config'
import { build } from '../core/build'
import { loadTheme } from '../core/loadTheme'
import { debounce, flatten } from '../core/utils'
import { buildFiles } from '../core/buildFiles'
import { Platforms } from '../core/types'
import { Data, Platforms } from '../core/types'
import { loadData } from '../core/loadData'

type Flags = {
config: string
Expand Down Expand Up @@ -49,7 +51,13 @@ export default class Build extends Command {
outputs: flags.output,
})

const result = await this.build(config)
const data = await this.loadData(config)

if (!data) {
return
}

const result = await this.build(data)

if (!result) {
return
Expand Down Expand Up @@ -93,7 +101,17 @@ export default class Build extends Command {
}
}

private async build(config: any) {
private async loadData(config: Config): Promise<Data | undefined> {
try {
return await loadData(config)
} catch (error) {
console.log('\r')
console.log(error)
console.log(`\n>---------------- ${chalk.red('Data loading failed')} -----------------<`)
}
}

private async build(config: any): Promise<Platforms | undefined> {
console.log(`>---------------- ${chalk.yellow('Build started')} ----------------<`)
try {
const result = await build(config)
Expand Down
92 changes: 49 additions & 43 deletions src/core/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,12 @@ import cssColorFn from 'css-color-function'
import { Api, InternalApi } from '../index'
import { createStyleDictionaryConfig } from './style-dictionary-config'
import { variablesWithPrefix } from './variablesWithPrefix'
import { loadMappers } from './mappers'
import { loadTheme } from './loadTheme'
import { dedupeProps } from './dedupe-props'
import { loadSources } from './load-sources'
import { Config } from './config'
import { isColor } from './utils'
import { enhanceWhitepaperConfig } from './enhance-whitepaper-config'
import { replaceAliasToVariable } from './replace-alias-to-variable'
import { deprecate } from './deprecate'
import { Platforms } from './types'
import { performActions } from './perfomActions'
import { Platforms, Data } from './types'

const context = new Map()

Expand Down Expand Up @@ -74,6 +69,32 @@ Api.registerTransform({
},
})

Api.registerFormat({
name: 'json/extended',
formatter(dictionary) {
const result: Record<string, any> = {}
console.log(dictionary)
for (const prop of dictionary.allProperties) {
result[prop.name] = {
name: prop.name,
value: prop.value,
rawValue: prop.original.value,
path: prop.path,
comment: prop.comment,
}
}
return JSON.stringify(result, null, 2)
},
})

Api.registerTransform({
name: 'json/extended/mapper',
type: 'name',
transformer: (prop) => {
return context.get('mapper')[prop.name] || prop.name
},
})

Api.registerFilter({
name: 'whitepaper/color',
matcher: (prop) => {
Expand Down Expand Up @@ -108,24 +129,13 @@ Api.registerAction({
if (key === 'value') {
let convertedValue = value

const colorRe = /color\(.+\)/g
const colorRe = /color\((?!{).+\)/g
let executed
while ((executed = colorRe.exec(convertedValue)) !== null) {
convertedValue = convertedValue.replace(executed[0], cssColorFn.convert(executed[0]))
}

return {
original: value,
value: convertedValue,
}
}

// If the value has "value" key, spread the original and converted values
if (value.value) {
return {
...value,
...value.value,
}
return convertedValue
}

return value
Expand All @@ -140,32 +150,28 @@ Api.registerPreset({
actions: ['process-color'],
})

export async function build(config: Config): Promise<Platforms> {
export async function build(data: Data): Promise<Platforms> {
let result = {}

for (const entry in config.entry) {
const theme = await loadTheme(config.entry[entry])
for (const platform of theme.platforms) {
// TODO: Load sources in themes?
const sources = await loadSources(theme.sources, platform)

// TODO: Load mappers in themes?
context.set('mapper', await loadMappers(theme.mappers))
context.set('whitepaper', enhanceWhitepaperConfig(theme.whitepaper, platform))

const StyleDictionary = InternalApi.extend(
createStyleDictionaryConfig({
platform: platform,
sources: sources,
entry: entry,
output: config.output,
}),
)

StyleDictionary.properties = dedupeProps(StyleDictionary.properties)
result = { ...result, ...StyleDictionary.buildAllPlatforms() }
}
}
data.forEach((el: any) => {
const { sources, mapper, whitepaper, platform, entry, output, properties } = el

context.set('mapper', mapper)
context.set('whitepaper', whitepaper)

const StyleDictionary = InternalApi.extend(
createStyleDictionaryConfig({
platform,
sources,
entry,
output,
properties,
}),
)

StyleDictionary.properties = dedupeProps(StyleDictionary.properties)
result = { ...result, ...StyleDictionary.buildAllPlatforms() }
})

return performActions(result)
}
2 changes: 1 addition & 1 deletion src/core/enhance-whitepaper-config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type WhitepaperConfig = Record<string, string>
import { WhitepaperConfig } from './types'

export function enhanceWhitepaperConfig(
config: WhitepaperConfig,
Expand Down
26 changes: 26 additions & 0 deletions src/core/loadData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Config } from './config'
import { enhanceWhitepaperConfig } from './enhance-whitepaper-config'
import { loadSources } from './load-sources'
import { loadTheme } from './loadTheme'
import { loadMappers } from './mappers'
import { Data } from './types'

export async function loadData(config: Config): Promise<Data> {
const result = []

for (const entry in config.entry) {
const theme = await loadTheme(config.entry[entry])
for (const platform of theme.platforms) {
result.push({
sources: await loadSources(theme.sources, platform),
mapper: await loadMappers(theme.mappers),
whitepaper: enhanceWhitepaperConfig(theme.whitepaper, platform),
output: config.output,
entry,
platform,
})
}
}

return result
}
3 changes: 2 additions & 1 deletion src/core/mappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { readJSON, readFileSync } from 'fs-extra'
import YAML from 'yaml'

import { normalizePaths } from './utils'
import { Mapper } from './types'

export async function loadMappers(paths: string[]): Promise<any> {
export async function loadMappers(paths: string[]): Promise<Mapper> {
const result = {}
for (const file of await glob(normalizePaths(paths))) {
if (/\.ya?ml$/.test(file)) {
Expand Down
27 changes: 27 additions & 0 deletions src/core/parseContent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import YAML from 'yaml'

type Format = 'json' | 'yaml' | 'yml'

/**
* Parse content by format.
*
* @param content - Raw content
* @param format - Parsing format
*/
export function parseContent(content: string, format: Format): any {
switch (format) {
case 'json':
try {
return JSON.parse(content)
} catch (_e) {
return content
}
case 'yml':
case 'yaml':
return YAML.parse(content)
default:
throw new Error(
`Unexpected format "${format}" for parsing, please choose json or yaml format.`,
)
}
}
15 changes: 12 additions & 3 deletions src/core/style-dictionary-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ type Options = {
entry: string
platform: string
output: Record<string, Platform>
properties: object
}

export function createStyleDictionaryConfig({ sources, entry, platform, output }: Options): Config {
export function createStyleDictionaryConfig({
sources,
entry,
platform,
output,
properties,
}: Options): Config {
const platforms = Object.entries<Platform>(output)
// prettier-ignore
.reduce<Record<string, Platform>>((acc, [key, value]) => {
Expand Down Expand Up @@ -41,8 +48,10 @@ export function createStyleDictionaryConfig({ sources, entry, platform, output }
return acc
}, {})

// To work in browser we should pass `properties` and set `include` to []
return {
include: sources,
platforms: platforms,
include: properties ? [] : sources,
platforms,
properties,
}
}
29 changes: 29 additions & 0 deletions src/core/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Platforms as PlatformsTypes } from './platforms'
import { Platform as SDPlatform } from '../vendors/style-dictionary'

export type File = {
context: any
destination: string
Expand All @@ -23,3 +26,29 @@ export type Platform = {
}

export type Platforms = Record<string, Platform>

export type WhitepaperConfig = Record<string, string>

export type Mapper = Record<string, string>

export type BaseData = {
mapper: Mapper
whitepaper: WhitepaperConfig
output: Record<string, SDPlatform>
entry: string
platform: PlatformsTypes
}

export type NodeData = Array<
BaseData & {
sources: string[]
}
>

export type BrowserData = Array<
BaseData & {
properties: object
}
>

export type Data = NodeData | BrowserData
26 changes: 14 additions & 12 deletions src/core/yaml-interop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,18 @@ class YamlParseError extends Error {
/**
* Patched native `require` for importing module with `yaml` extensions.
*/
Module.prototype.require = new Proxy(Module.prototype.require, {
apply(target, thisArg, args) {
if (/\.ya?ml$/.test(args[0])) {
const file = readFileSync(args[0], 'utf8')
try {
return YAML.parse(file, { prettyErrors: true })
} catch (error) {
throw new YamlParseError(args[0], file, error.message, error.linePos)
if (typeof window === 'undefined') {
Module.prototype.require = new Proxy(Module.prototype.require, {
apply(target, thisArg, args) {
if (/\.ya?ml$/.test(args[0])) {
const file = readFileSync(args[0], 'utf8')
try {
return YAML.parse(file, { prettyErrors: true })
} catch (error) {
throw new YamlParseError(args[0], file, error.message, error.linePos)
}
}
}
return Reflect.apply(target, thisArg, args)
},
})
return Reflect.apply(target, thisArg, args)
},
})
}
1 change: 1 addition & 0 deletions src/vendors/style-dictionary/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type Platform = {
export type Config = {
include: string[]
platforms: Record<string, Platform>
properties: object
}

export type InjectedTransformer = {
Expand Down
6 changes: 5 additions & 1 deletion src/vendors/style-dictionary/lib/buildFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@
*/

var path = require('path'),
fs = require('fs-extra'),
chalk = require('chalk'),
filterProperties = require('./filterProperties'),
GroupMessages = require('./utils/groupMessages');

let fs
if (typeof window === 'undefined') {
fs = require('fs-extra')
}

/**
* Takes the style property object and a format and returns a
* string that can be written to a file.
Expand Down
5 changes: 4 additions & 1 deletion src/vendors/style-dictionary/lib/cleanDir.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
*/

var path = require('path'),
fs = require('fs-extra'),
chalk = require('chalk');

let fs
if (typeof window === 'undefined') {
require('fs-extra')
}

/**
* Takes the style property object and a format and returns a
Expand Down
Loading

0 comments on commit 3118e00

Please sign in to comment.