import defaultStyles from '@-ui/styles'
function unique(...args: any[]): any[] {
const seen = {},
out: any[] = []
for (let i = 0; i < args.length; i++) {
for (let j = 0; j < args[i].length; j++) {
const value = args[i][j]
if (seen[value] === true) continue
seen[value] = true
out.push(value)
}
}
return out
}
export interface StylesResult {
css: string
names: string[]
}
export interface CreateStylesOptions {
clearCache?: boolean
}
export const createStylesFromCache = (
styles = defaultStyles,
options: CreateStylesOptions = {}
): StylesResult => {
// createStylesFromCache() is unsafe in asynchronous render environments
const {clearCache = true} = options,
{dash} = styles,
styleCache = dash.stylisCache
let css = ''
const names = unique(
Object.keys(styles.dash.variablesCache),
Object.keys(dash.globalCache),
Object.keys(dash.insertCache)
)
for (let i = 0; i < names.length; i++) css += styleCache[names[i]]
if (clearCache) dash.clear()
return {names, css}
}
export const createStyleTagFromCache = (
styles = defaultStyles,
options: CreateStylesOptions = {}
): string => {
// createStyleTagFromCache() is unsafe in asynchronous render environments
const {css, names} = createStylesFromCache(styles, options)
const nonceString = styles.dash.sheet.nonce
? ` nonce="${styles.dash.sheet.nonce}"`
: ''
return (
``
)
}
export interface WriteStylesOptions {
name?: string
hash?: (string: string) => string
clearCache?: boolean
}
export interface WriteStylesResult {
filename: string
name: string
path: string
styles: string
}
export const writeStylesFromCache = async (
outputPath = '',
styles = defaultStyles,
options?: WriteStylesOptions
): Promise => {
// requiring in here prevents webpack errors in stuff like Next.js apps
// eslint-disable-next-line @typescript-eslint/no-var-requires
const fs = require('fs')
// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require('path')
styles = styles || defaultStyles
// eslint-disable-next-line
let {name, hash = styles.dash.hash, clearCache = true} = options || {}
const stylesString = createStylesFromCache(styles, {clearCache}).css
name = `${name || styles.dash.key + '-' + hash(stylesString) + '.css'}`
const filename = path.join(outputPath, name)
await fs.promises.writeFile(filename, stylesString)
return {filename, name, path: outputPath, styles: stylesString}
}
export const createStylesFromString = (
string: string,
styles = defaultStyles,
options: CreateStylesOptions = {}
): StylesResult => {
const {clearCache = true} = options
const {dash} = styles
const styleCache = dash.stylisCache
let css = ''
const names = unique(
Object.keys(styles.dash.variablesCache),
Object.keys(styles.dash.globalCache)
)
let i = 0
for (; i < names.length; i++) css += styleCache[names[i]]
const replacer = `${styles.dash.key}-`
const classRe = new RegExp(
`[='"\\s](${styles.dash.key}-[A-Za-z0-9_-]+)[\\s'">]`,
'g'
)
const seen = {}
let result: RegExpMatchArray | null
while ((result = classRe.exec(string)) !== null) {
const name = result[1].slice(replacer.length)
const style = styleCache[name]
if (style && seen[name] === void 0) {
css += style
names.push(name)
seen[name] = true
}
}
if (clearCache) dash.clear()
return {names, css}
}
export const createStyleTagFromString = (
string: string,
styles = defaultStyles,
options: CreateStylesOptions = {}
): string => {
const {css, names} = createStylesFromString(string, styles, options)
const nonceString = styles.dash.sheet.nonce
? ` nonce="${styles.dash.sheet.nonce}"`
: ''
return (
``
)
}
export const writeStylesFromString = async (
string: string,
outputPath = '',
styles = defaultStyles,
options?: WriteStylesOptions
): Promise => {
// requiring in here prevents webpack errors in stuff like Next.js apps
// eslint-disable-next-line @typescript-eslint/no-var-requires
const fs = require('fs')
// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require('path')
styles = styles || defaultStyles
// eslint-disable-next-line
let {name, hash = styles.dash.hash, clearCache = true} = options || {}
const stylesString = createStylesFromString(string, styles, {clearCache}).css
name = `${name || styles.dash.key + '-' + hash(stylesString) + '.css'}`
const filename = path.join(outputPath, name)
await fs.promises.writeFile(filename, stylesString)
return {filename, name, path: outputPath, styles: stylesString}
}