-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow additional handlers for special selectors to be added. (#95)
Summary: This adds the ability for users of Aphrodite to add extensions which support other special selectors. This should let people add extensions to write global styles or many other not-terribly-well-supported use cases until we have better solutions. This adds docs on how to use the extensions, and adds a bunch of jsdocs to make things clear in the code. Test Plan: - `npm run test`
- Loading branch information
Showing
8 changed files
with
451 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import {mapObj, hashObject} from './util'; | ||
import { | ||
injectAndGetClassName, | ||
reset, startBuffering, flushToString, | ||
addRenderedClassNames, getRenderedClassNames, | ||
} from './inject'; | ||
|
||
const StyleSheet = { | ||
create(sheetDefinition) { | ||
return mapObj(sheetDefinition, ([key, val]) => { | ||
return [key, { | ||
// TODO(emily): Make a 'production' mode which doesn't prepend | ||
// the class name here, to make the generated CSS smaller. | ||
_name: `${key}_${hashObject(val)}`, | ||
_definition: val | ||
}]; | ||
}); | ||
}, | ||
|
||
rehydrate(renderedClassNames=[]) { | ||
addRenderedClassNames(renderedClassNames); | ||
}, | ||
}; | ||
|
||
/** | ||
* Utilities for using Aphrodite server-side. | ||
*/ | ||
const StyleSheetServer = { | ||
renderStatic(renderFunc) { | ||
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 = { | ||
/** | ||
* 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(); | ||
}, | ||
}; | ||
|
||
/** | ||
* Generate the Aphrodite API exports, with given `selectorHandlers` and | ||
* `useImportant` state. | ||
*/ | ||
const makeExports = (useImportant, selectorHandlers) => { | ||
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) { | ||
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( | ||
useImportant, | ||
selectorHandlers.concat(extensionSelectorHandlers) | ||
); | ||
}, | ||
}, | ||
|
||
StyleSheetServer, | ||
StyleSheetTestUtils, | ||
|
||
css(...styleDefinitions) { | ||
return injectAndGetClassName( | ||
useImportant, styleDefinitions, selectorHandlers); | ||
}, | ||
}; | ||
}; | ||
|
||
module.exports = makeExports; |
Oops, something went wrong.