UNPKG

bsl

Version:

基于React的框架和UI组件

182 lines (159 loc) 5.28 kB
import { defaultSelectorHandlers } from './generate'; import { hashString } from './util'; import type { RenderFunction, Extension, CSSProperties } from './type'; /* @flow */ import { injectAndGetClassName, reset, resetInjectedStyle, startBuffering, flushToString, flushToStyleTag, addRenderedClassNames, getRenderedClassNames, getBufferedStyles, } from './inject'; /* :: import type { SelectorHandler } from './generate.js'; */ const unminifiedHashFn = (str: string, key: string) => `${key}_${hashString(str)}`; // StyleSheet.create is in a hot path so we want to keep as much logic out of it // as possible. So, we figure out which hash function to use once, and only // switch it out via minify() as necessary. // // This is in an exported function to make it easier to test. export const initialHashFn = () => process.env.NODE_ENV === 'production' ? hashString : unminifiedHashFn; let hashFn = initialHashFn(); const StyleSheet = { create<T>(sheetDefinition: Record<keyof T, CSSProperties>): Record<keyof T, string> { const keys = Object.keys(sheetDefinition); const recordCls: Record<string, string> = {}; for (let i = 0; i < keys.length; i += 1) { const key = keys[i]; const val = sheetDefinition[key as keyof T]; const stringVal = JSON.stringify(val); const item = { _len: stringVal.length, _name: hashFn(stringVal, key), _definition: val, }; recordCls[key] = injectAndGetClassName([item], defaultSelectorHandlers); } return recordCls as Record<keyof T, string>; }, rehydrate(renderedClassNames /* : string[] */ =[]) { addRenderedClassNames(renderedClassNames); }, }; /** * Utilities for using Aphrodite server-side. * * This can be minified out in client-only bundles by replacing `typeof window` * with `"object"`, e.g. via Webpack's DefinePlugin: * * new webpack.DefinePlugin({ * "typeof window": JSON.stringify("object") * }) */ const StyleSheetServer = typeof window !== 'undefined' ? null : { renderStatic(renderFunc: RenderFunction) { reset(); startBuffering(); const html = renderFunc(); const cssContent = flushToString(); return { html: html, css: { content: cssContent, renderedClassNames: getRenderedClassNames(), }, }; }, }; /** * Utilities for using Aphrodite in tests. * * Not meant to be used in production. */ const StyleSheetTestUtils = process.env.NODE_ENV === 'production' ? null : { /** * Prevent styles from being injected into the DOM. * * This is useful in situations where you'd like to test rendering UI * components which use Aphrodite without any of the side-effects of * Aphrodite happening. Particularly useful for testing the output of * components when you have no DOM, e.g. testing in Node without a fake DOM. * * Should be paired with a subsequent call to * clearBufferAndResumeStyleInjection. */ suppressStyleInjection() { reset(); startBuffering(); }, /** * Opposite method of preventStyleInject. */ clearBufferAndResumeStyleInjection() { reset(); }, /** * Returns a string of buffered styles which have not been flushed * * @returns {string} Buffer of styles which have not yet been flushed. */ getBufferedStyles() { return getBufferedStyles(); } }; /** * Generate the Aphrodite API exports, with given `selectorHandlers` and * `useImportant` state. */ export default function makeExports(selectorHandlers = defaultSelectorHandlers) { return { StyleSheet: { ...StyleSheet, /** * Returns a version of the exports of Aphrodite (i.e. an object * with `css` and `StyleSheet` properties) which have some * extensions included. * * @param {Array.<Object>} extensions: An array of extensions to * add to this instance of Aphrodite. Each object should have a * single property on it, defining which kind of extension to * add. * @param {SelectorHandler} [extensions[].selectorHandler]: A * selector handler extension. See `defaultSelectorHandlers` in * generate.js. * * @returns {Object} An object containing the exports of the new * instance of Aphrodite. */ extend(extensions: Extension[]) { const extensionSelectorHandlers = extensions // Pull out extensions with a selectorHandler property .map(extension => extension.selectorHandler) // Remove nulls (i.e. extensions without a selectorHandler property). .filter(handler => handler); return makeExports(selectorHandlers.concat(extensionSelectorHandlers)); }, }, StyleSheetServer, StyleSheetTestUtils, minify(shouldMinify: boolean) { hashFn = shouldMinify ? hashString : unminifiedHashFn; }, flushToStyleTag, injectAndGetClassName, defaultSelectorHandlers, reset, resetInjectedStyle, }; }