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

feat: add support for nonce in Fela renderer #25992

Merged
merged 1 commit into from
Dec 20, 2022
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/fluentui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,17 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### BREAKING CHANGES
- `createFelaRenderer` is now a function @layershifter ([#25992](https://github.com/microsoft/fluentui/pull/25992))

### Fixes
- `Carousel` fix for FZ - Adding data-is-visible prop #25973 @kolaps33 ([#25973](https://github.com/microsoft/fluentui/pull/25973))
- Fix `Dropdown` allowing interaction with selected items when disabled @chpalac ([#25954](https://github.com/microsoft/fluentui/pull/25954))
- Fix `Button` styles for `disabledFocusable` when `text` @chpalac ([#26012](https://github.com/microsoft/fluentui/pull/26012))

### Features
- `nonce` can be configured for Fela renderer @layershifter ([#25992](https://github.com/microsoft/fluentui/pull/25992))

<!--------------------------------[ v0.65.0 ]------------------------------- -->
## [v0.65.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-northstar_v0.65.0) (2022-10-31)
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-northstar_v0.64.0..@fluentui/react-northstar_v0.65.0)
Expand Down
2 changes: 1 addition & 1 deletion packages/fluentui/docs/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const themes = {
};

function useRendererFactory(): CreateRenderer {
const rendererFactory = localStorage.fluentRenderer === 'emotion' ? createEmotionRenderer() : createFelaRenderer;
const rendererFactory = localStorage.fluentRenderer === 'emotion' ? createEmotionRenderer() : createFelaRenderer();

React.useEffect(() => {
(window as any).setFluentRenderer = (rendererName: 'fela' | 'emotion') => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ import { createFelaRenderer } from '@fluentui/react-northstar-fela-renderer';
import { CreateRenderer } from '@fluentui/react-northstar-styles-renderer';
import * as React from 'react';

export const RendererContext = React.createContext<CreateRenderer>(createFelaRenderer);
export const RendererContext = React.createContext<CreateRenderer>(createFelaRenderer());
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,22 @@
"@fluentui/styles": "^0.65.0",
"css-in-js-utils": "^3.0.0",
"fela": "^10.6.1",
"fela-dom": "^11.7.0",
"fela-plugin-embedded": "^10.6.1",
"fela-plugin-fallback-value": "^10.6.1",
"fela-plugin-placeholder-prefixer": "^10.6.1",
"fela-plugin-rtl": "^10.6.1",
"fela-tools": "^10.6.1",
"fela-utils": "^10.6.1",
"fela-utils": "^11.7.0",
"inline-style-expand-shorthand": "^1.2.0",
"lodash": "^4.17.15",
"react-fela": "^10.6.1",
"stylis": "^3.5.4"
},
"devDependencies": {
"@fluentui/eslint-plugin": "*",
"@fluentui/scripts": "^1.0.0",
"lerna-alias": "^3.0.3-0"
"lerna-alias": "^3.0.3-0",
"react-fela": "^10.6.1"
},
"files": [
"dist"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { render, rehydrate } from 'fela-dom';
import * as React from 'react';

import { FelaRenderer } from './types';

// Copied from https://github.com/robinweser/fela/blob/master/packages/fela-bindings/src/RendererProviderFactory.js

function hasDOM(renderer: FelaRenderer, targetDocument: Document | undefined) {
// ensure we're on a browser by using document since window is defined in e.g. React Native
// see https://github.com/robinweser/fela/issues/736
if (typeof document === 'undefined') {
return false;
}

const doc = targetDocument || document;

return renderer && doc && doc.createElement;
}

function hasServerRenderedStyle(targetDocument = document) {
return targetDocument.querySelectorAll('[data-fela-type]').length > 0;
}

type RendererProviderProps = {
renderer: FelaRenderer;
rehydrate?: boolean;
targetDocument?: Document;
};

// Typings provided by "fela" package are outdated, this overrides provides proper definition
declare module 'fela-dom' {
function render(renderer: FelaRenderer, targetDocument?: Document): void;
function rehydrate(renderer: FelaRenderer, targetDocument?: Document): void;
}

export class RendererProvider extends React.Component<RendererProviderProps, Record<string, unknown>> {
constructor(props: RendererProviderProps) {
super(props);
this._renderStyle();
}

componentDidUpdate(prevProps: RendererProviderProps) {
if (prevProps.renderer !== this.props.renderer) {
// add warning that renderer is changed
this._renderStyle();
}
}

_renderStyle() {
const { renderer, rehydrate: shouldRehydrate, targetDocument } = this.props;

if (hasDOM(renderer, targetDocument)) {
if (shouldRehydrate && hasServerRenderedStyle(targetDocument)) {
rehydrate(renderer, targetDocument);
} else {
render(renderer, targetDocument);
}
}
}

render() {
return <>{this.props.children}</>;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import felaPluginFallbackValue from 'fela-plugin-fallback-value';
import felaPluginPlaceholderPrefixer from 'fela-plugin-placeholder-prefixer';
import felaPluginRtl from 'fela-plugin-rtl';
import * as React from 'react';
import { RendererProvider } from 'react-fela';

import { felaDisableAnimationsPlugin } from './felaDisableAnimationsPlugin';
import { felaExpandCssShorthandsPlugin } from './felaExpandCssShorthandsPlugin';
Expand All @@ -14,7 +13,8 @@ import { felaInvokeKeyframesPlugin } from './felaInvokeKeyframesPlugin';
import { felaPerformanceEnhancer } from './felaPerformanceEnhancer';
import { felaSanitizeCssPlugin } from './felaSanitizeCssPlugin';
import { felaStylisEnhancer } from './felaStylisEnhancer';
import { FelaRendererParam } from './types';
import { RendererProvider } from './RendererProvider';
import { FelaRenderer, FelaRendererParam } from './types';

let felaDevMode = false;

Expand Down Expand Up @@ -92,58 +92,72 @@ const rendererConfig = {
],
};

export const createFelaRenderer: CreateRenderer = () => {
const felaRenderer = createRenderer(rendererConfig) as IRenderer & {
listeners: [];
nodes: Record<string, HTMLStyleElement>;
updateSubscription: Function | undefined;
};
let usedRenderers: number = 0;

// rehydration disabled to avoid leaking styles between renderers
// https://github.com/rofrischmann/fela/blob/master/docs/api/fela-dom/rehydrate.md
const Provider: Renderer['Provider'] = props => (
<RendererProvider renderer={felaRenderer} {...{ rehydrate: false, targetDocument: props.target }}>
{props.children}
</RendererProvider>
);

return {
registerUsage: () => {
usedRenderers += 1;
},
unregisterUsage: () => {
usedRenderers -= 1;

if (usedRenderers === 0) {
felaRenderer.listeners = [];
felaRenderer.nodes = {};
felaRenderer.updateSubscription = undefined;
}
},

renderFont: font => {
felaRenderer.renderFont(font.name, font.paths, font.props);
},
renderGlobal: felaRenderer.renderStatic,
renderRule: (styles, param) => {
const felaParam: FelaRendererParam = {
...param,
theme: { direction: param.direction },
};
export type CreateFelaRendererOptions = {
nonce?: string;
};

return felaRenderer.renderRule(() => (styles as unknown) as IStyle, felaParam);
},
export function createFelaRenderer(options: CreateFelaRendererOptions = {}): CreateRenderer {
const { nonce } = options;

// getOriginalRenderer() is implemented only for tests to be compatible with jest-react-fela expectations.
getOriginalRenderer: (): IRenderer => {
if (process.env.NODE_ENV !== 'test') {
throw new Error('This method implements private API and can be used only in tests');
}
return () => {
const felaRenderer = createRenderer(rendererConfig) as FelaRenderer & {
listeners: [];
nodes: Record<string, HTMLStyleElement>;
updateSubscription: Function | undefined;
};
let usedRenderers: number = 0;

return felaRenderer;
},
if (nonce) {
felaRenderer.styleNodeAttributes = {
nonce,
};
}

// rehydration disabled to avoid leaking styles between renderers
// https://github.com/rofrischmann/fela/blob/master/docs/api/fela-dom/rehydrate.md
const Provider: Renderer['Provider'] = props => (
<RendererProvider renderer={felaRenderer} rehydrate={false} targetDocument={props.target}>
{props.children}
</RendererProvider>
);

Provider,
return {
registerUsage: () => {
usedRenderers += 1;
},
unregisterUsage: () => {
usedRenderers -= 1;

if (usedRenderers === 0) {
felaRenderer.listeners = [];
felaRenderer.nodes = {};
felaRenderer.updateSubscription = undefined;
}
},

renderFont: font => {
felaRenderer.renderFont(font.name, font.paths, font.props);
},
renderGlobal: felaRenderer.renderStatic,
renderRule: (styles, param) => {
const felaParam: FelaRendererParam = {
...param,
theme: { direction: param.direction },
};

return felaRenderer.renderRule(() => (styles as unknown) as IStyle, felaParam);
},

// getOriginalRenderer() is implemented only for tests to be compatible with jest-react-fela expectations.
getOriginalRenderer: (): IRenderer => {
if (process.env.NODE_ENV !== 'test') {
throw new Error('This method implements private API and can be used only in tests');
}

return felaRenderer;
},

Provider,
};
};
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export type FelaRenderer = IRenderer & {
media?: string,
support?: string,
): string;

styleNodeAttributes: Record<string, string | number | boolean>;
};

export type FelaRendererChange = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { FelaComponent, RendererProvider, ThemeProvider } from 'react-fela';

const felaRenderer = (createFelaRenderer() as any).getOriginalRenderer();
const felaRenderer = (createFelaRenderer()() as any).getOriginalRenderer();

function createSnapshot(component: JSX.Element, theme = {}) {
const div = document.createElement('div');
Expand Down
Loading