Compare commits

...

3 Commits

Author SHA1 Message Date
eps1lon
027534e673 Add experimental_ prefix to renderToMarkup 2024-08-12 18:38:44 +02:00
eps1lon
f23fc95209 Allow nightly releases of react-markup 2024-08-12 18:35:33 +02:00
eps1lon
07b977b734 react-html -> react-markup 2024-08-05 15:41:54 +02:00
24 changed files with 96 additions and 81 deletions

View File

@@ -9,7 +9,7 @@
import type {Thenable} from 'shared/ReactTypes';
export * from 'react-html/src/ReactHTMLLegacyClientStreamConfig.js';
export * from 'react-markup/src/ReactMarkupLegacyClientStreamConfig.js';
export * from 'react-client/src/ReactClientConsoleConfigPlain';
export type ModuleLoading = null;

View File

@@ -1,7 +0,0 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-html.production.js');
} else {
module.exports = require('./cjs/react-html.development.js');
}

View File

@@ -1,7 +0,0 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-html.react-server.production.js');
} else {
module.exports = require('./cjs/react-html.react-server.development.js');
}

View File

@@ -1,23 +1,23 @@
# `react-html`
# `react-markup`
This package provides the ability to render standalone HTML from Server Components for use in embedded contexts such as e-mails and RSS/Atom feeds. It cannot use Client Components and does not hydrate. It is intended to be paired with the generic React package, which is shipped as `react` to npm.
## Installation
```sh
npm install react react-html
npm install react react-markup
```
## Usage
```js
import { renderToMarkup } from 'react-html';
import { experimental_renderToMarkup } from 'react-markup';
import EmailTemplate from './my-email-template-component.js'
async function action(email, name) {
"use server";
// ... in your server, e.g. a Server Action...
const htmlString = await renderToMarkup(<EmailTemplate name={name} />);
const htmlString = await experimental_renderToMarkup(<EmailTemplate name={name} />);
// ... send e-mail using some e-mail provider
await sendEmail({ to: email, contentType: 'text/html', body: htmlString });
}
@@ -27,6 +27,6 @@ Note that this is an async function that needs to be awaited - unlike the legacy
## API
### `react-html`
### `react-markup`
See https://react.dev/reference/react-html
See https://react.dev/reference/react-markup

View File

@@ -0,0 +1,10 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
export {renderToMarkup as experimental_renderToMarkup} from './src/ReactMarkupClient';

View File

@@ -7,4 +7,4 @@
* @flow
*/
export * from './src/ReactHTMLClient';
export {};

7
packages/react-markup/npm/index.js vendored Normal file
View File

@@ -0,0 +1,7 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-markup.production.js');
} else {
module.exports = require('./cjs/react-markup.development.js');
}

View File

@@ -0,0 +1,7 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-markup.react-server.production.js');
} else {
module.exports = require('./cjs/react-markup.react-server.development.js');
}

View File

@@ -1,13 +1,12 @@
{
"name": "react-html",
"name": "react-markup",
"version": "19.0.0",
"private": true,
"description": "React package generating embedded HTML markup such as e-mails using Server Components.",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/facebook/react.git",
"directory": "packages/react-html"
"directory": "packages/react-markup"
},
"keywords": [
"react"
@@ -24,12 +23,12 @@
"LICENSE",
"README.md",
"index.js",
"react-html.react-server.js",
"react-markup.react-server.js",
"cjs/"
],
"exports": {
".": {
"react-server": "./react-html.react-server.js",
"react-server": "./react-markup.react-server.js",
"default": "./index.js"
},
"./src/*": "./src/*",

View File

@@ -7,4 +7,4 @@
* @flow
*/
export * from './src/ReactHTMLServer';
export * from './src/ReactMarkupServer';

View File

@@ -23,7 +23,7 @@ import {
createResumableState,
createRenderState,
createRootFormatContext,
} from './ReactFizzConfigHTML';
} from './ReactFizzConfigMarkup';
type MarkupOptions = {
identifierPrefix?: string,

View File

@@ -8,4 +8,4 @@
*/
// eslint-disable-next-line react-internal/prod-error-codes
throw new Error('react-html should not get built in stable');
throw new Error('react-markup should not get built in stable');

View File

@@ -41,7 +41,7 @@ import {
createResumableState,
createRenderState,
createRootFormatContext,
} from './ReactFizzConfigHTML';
} from './ReactFizzConfigMarkup';
type ReactMarkupNodeList =
// This is the intersection of ReactNodeList and ReactClientValue minus

View File

@@ -8,4 +8,4 @@
*/
// eslint-disable-next-line react-internal/prod-error-codes
throw new Error('react-html should not get built in stable');
throw new Error('react-markup should not get built in stable');

View File

@@ -10,7 +10,7 @@
'use strict';
let React;
let ReactHTML;
let ReactMarkup;
function normalizeCodeLocInfo(str) {
return (
@@ -24,18 +24,18 @@ function normalizeCodeLocInfo(str) {
if (!__EXPERIMENTAL__) {
it('should not be built in stable', () => {
try {
require('react-html');
require('react-markup');
} catch (x) {
return;
}
throw new Error('Expected react-html not to exist in stable.');
throw new Error('Expected react-markup not to exist in stable.');
});
} else {
describe('ReactHTML', () => {
describe('ReactMarkup', () => {
beforeEach(() => {
jest.resetModules();
React = require('react');
ReactHTML = require('react-html');
ReactMarkup = require('react-markup');
});
it('should be able to render a simple component', async () => {
@@ -43,7 +43,7 @@ if (!__EXPERIMENTAL__) {
return <div>hello world</div>;
}
const html = await ReactHTML.renderToMarkup(<Component />);
const html = await ReactMarkup.experimental_renderToMarkup(<Component />);
expect(html).toBe('<div>hello world</div>');
});
@@ -52,14 +52,14 @@ if (!__EXPERIMENTAL__) {
return <div>{'hello '.repeat(200)}world</div>;
}
const html = await ReactHTML.renderToMarkup(
const html = await ReactMarkup.experimental_renderToMarkup(
React.createElement(Component),
);
expect(html).toBe('<div>' + ('hello '.repeat(200) + 'world') + '</div>');
});
it('should prefix html tags with a doctype', async () => {
const html = await ReactHTML.renderToMarkup(
const html = await ReactMarkup.experimental_renderToMarkup(
<html>
<body>hello</body>
</html>,
@@ -76,7 +76,7 @@ if (!__EXPERIMENTAL__) {
}
await expect(async () => {
await ReactHTML.renderToMarkup(<Component />);
await ReactMarkup.experimental_renderToMarkup(<Component />);
}).rejects.toThrow();
});
@@ -87,7 +87,7 @@ if (!__EXPERIMENTAL__) {
}
await expect(async () => {
await ReactHTML.renderToMarkup(<Component />);
await ReactMarkup.experimental_renderToMarkup(<Component />);
}).rejects.toThrow();
});
@@ -100,7 +100,7 @@ if (!__EXPERIMENTAL__) {
}
await expect(async () => {
await ReactHTML.renderToMarkup(<Component />);
await ReactMarkup.experimental_renderToMarkup(<Component />);
}).rejects.toThrow();
});
@@ -142,7 +142,7 @@ if (!__EXPERIMENTAL__) {
);
}
const html = await ReactHTML.renderToMarkup(<Component />);
const html = await ReactMarkup.experimental_renderToMarkup(<Component />);
const container = document.createElement('div');
container.innerHTML = html;
@@ -176,7 +176,7 @@ if (!__EXPERIMENTAL__) {
);
}
const html = await ReactHTML.renderToMarkup(<Component />);
const html = await ReactMarkup.experimental_renderToMarkup(<Component />);
expect(html).toBe('<div>01</div>');
});
@@ -199,7 +199,7 @@ if (!__EXPERIMENTAL__) {
}
await expect(async () => {
await ReactHTML.renderToMarkup(
await ReactMarkup.experimental_renderToMarkup(
<div>
<Foo />
</div>,

View File

@@ -13,7 +13,7 @@ global.TextDecoder = require('util').TextDecoder;
global.TextEncoder = require('util').TextEncoder;
let React;
let ReactHTML;
let ReactMarkup;
function normalizeCodeLocInfo(str) {
return (
@@ -27,34 +27,34 @@ function normalizeCodeLocInfo(str) {
if (!__EXPERIMENTAL__) {
it('should not be built in stable', () => {
try {
require('react-html');
require('react-markup');
} catch (x) {
return;
}
throw new Error('Expected react-html not to exist in stable.');
throw new Error('Expected react-markup not to exist in stable.');
});
} else {
describe('ReactHTML', () => {
describe('ReactMarkup', () => {
beforeEach(() => {
jest.resetModules();
// We run in the react-server condition.
jest.mock('react', () => require('react/react.react-server'));
if (__EXPERIMENTAL__) {
jest.mock('react-html', () =>
require('react-html/react-html.react-server'),
jest.mock('react-markup', () =>
require('react-markup/react-markup.react-server'),
);
}
React = require('react');
if (__EXPERIMENTAL__) {
ReactHTML = require('react-html');
ReactMarkup = require('react-markup');
} else {
try {
require('react-html/react-html.react-server');
require('react-markup/react-markup.react-server');
} catch (x) {
return;
}
throw new Error('Expected react-html not to exist in stable.');
throw new Error('Expected react-markup not to exist in stable.');
}
});
@@ -64,7 +64,7 @@ if (!__EXPERIMENTAL__) {
return React.createElement('div', null, 'hello world');
}
const html = await ReactHTML.renderToMarkup(
const html = await ReactMarkup.experimental_renderToMarkup(
React.createElement(Component),
);
expect(html).toBe('<div>hello world</div>');
@@ -76,14 +76,14 @@ if (!__EXPERIMENTAL__) {
return React.createElement('div', null, 'hello '.repeat(200) + 'world');
}
const html = await ReactHTML.renderToMarkup(
const html = await ReactMarkup.experimental_renderToMarkup(
React.createElement(Component),
);
expect(html).toBe('<div>' + ('hello '.repeat(200) + 'world') + '</div>');
});
it('should prefix html tags with a doctype', async () => {
const html = await ReactHTML.renderToMarkup(
const html = await ReactMarkup.experimental_renderToMarkup(
// We can't use JSX because that's client-JSX in our tests.
React.createElement(
'html',
@@ -104,7 +104,9 @@ if (!__EXPERIMENTAL__) {
}
await expect(async () => {
await ReactHTML.renderToMarkup(React.createElement(Component));
await ReactMarkup.experimental_renderToMarkup(
React.createElement(Component),
);
}).rejects.toThrow();
});
@@ -116,7 +118,9 @@ if (!__EXPERIMENTAL__) {
}
await expect(async () => {
await ReactHTML.renderToMarkup(React.createElement(Component));
await ReactMarkup.experimental_renderToMarkup(
React.createElement(Component),
);
}).rejects.toThrow();
});
@@ -130,7 +134,9 @@ if (!__EXPERIMENTAL__) {
}
await expect(async () => {
await ReactHTML.renderToMarkup(React.createElement(Component));
await ReactMarkup.experimental_renderToMarkup(
React.createElement(Component),
);
}).rejects.toThrow();
});
@@ -173,7 +179,7 @@ if (!__EXPERIMENTAL__) {
);
}
const html = await ReactHTML.renderToMarkup(
const html = await ReactMarkup.experimental_renderToMarkup(
React.createElement(Component),
);
const container = document.createElement('div');
@@ -204,7 +210,7 @@ if (!__EXPERIMENTAL__) {
return React.createElement('div', null, a, b);
}
const html = await ReactHTML.renderToMarkup(
const html = await ReactMarkup.experimental_renderToMarkup(
React.createElement(Component),
);
expect(html).toBe('<div>00</div>');
@@ -225,7 +231,7 @@ if (!__EXPERIMENTAL__) {
}
await expect(async () => {
await ReactHTML.renderToMarkup(
await ReactMarkup.experimental_renderToMarkup(
React.createElement('div', null, React.createElement(Foo)),
{
onError(error, errorInfo) {

View File

@@ -13,4 +13,4 @@ export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM';
export * from 'react-client/src/ReactClientConsoleConfigBrowser';
// eslint-disable-next-line react-internal/prod-error-codes
throw new Error('Fiber is not used in react-html');
throw new Error('Fiber is not used in react-markup');

View File

@@ -8,7 +8,7 @@
*/
import type {Request} from 'react-server/src/ReactFizzServer';
export * from 'react-html/src/ReactFizzConfigHTML.js';
export * from 'react-markup/src/ReactFizzConfigMarkup.js';
export * from 'react-client/src/ReactClientConsoleConfigPlain';

View File

@@ -516,7 +516,7 @@
"528": "Expected <link> not to update to be updated to a stylesheet with precedence. Check the `rel`, `href`, and `precedence` props of this component. Alternatively, check whether two different <link> components render in the same slot or share the same key.%s",
"529": "Expected stylesheet with precedence to not be updated to a different kind of <link>. Check the `rel`, `href`, and `precedence` props of this component. Alternatively, check whether two different <link> components render in the same slot or share the same key.%s",
"530": "The render was aborted by the server with a promise.",
"531": "react-html is not supported outside a React Server Components environment.",
"531": "react-markup is not supported outside a React Server Components environment.",
"532": "Attempted to render a Client Component from renderToMarkup. This is not supported since it will never hydrate. Only render Server Components with renderToMarkup.",
"533": "Attempted to render a Server Action from renderToMarkup. This is not supported since it varies by version of the app. Use a fixed URL for any forms instead.",
"534": "renderToMarkup should not have emitted Client References. This is a bug in React.",
@@ -527,4 +527,4 @@
"539": "Binary RSC chunks cannot be encoded as strings. This is a bug in the wiring of the React streams.",
"540": "String chunks need to be passed in their original shape. Not split into smaller string chunks. This is a bug in the wiring of the React streams.",
"541": "Compared context values must be arrays"
}
}

View File

@@ -367,10 +367,10 @@ const bundles = [
{
bundleTypes: __EXPERIMENTAL__ ? [NODE_DEV, NODE_PROD] : [],
moduleType: RENDERER,
entry: 'react-html/src/ReactHTMLServer.js',
name: 'react-html.react-server',
entry: 'react-markup/src/ReactMarkupServer.js',
name: 'react-markup.react-server',
condition: 'react-server',
global: 'ReactHTML',
global: 'ReactMarkup',
minifyWithProdErrorCodes: false,
wrapWithModuleBoundaries: false,
externals: ['react'],
@@ -380,9 +380,9 @@ const bundles = [
{
bundleTypes: __EXPERIMENTAL__ ? [NODE_DEV, NODE_PROD] : [],
moduleType: RENDERER,
entry: 'react-html/src/ReactHTMLClient.js',
name: 'react-html',
global: 'ReactHTML',
entry: 'react-markup/src/ReactMarkupClient.js',
name: 'react-markup',
global: 'ReactMarkup',
minifyWithProdErrorCodes: false,
wrapWithModuleBoundaries: false,
externals: ['react'],

View File

@@ -65,8 +65,8 @@ const forks = Object.freeze({
if (entry === 'react/src/ReactServer.js') {
return './packages/react/src/ReactSharedInternalsServer.js';
}
if (entry === 'react-html/src/ReactHTMLServer.js') {
// Inside the ReactHTMLServer render we don't refer to any shared internals
if (entry === 'react-markup/src/ReactMarkupServer.js') {
// Inside the ReactMarkupServer render we don't refer to any shared internals
// but instead use our own internal copy of the state because you cannot use
// any of this state from a component anyway. E.g. you can't use a client hook.
return './packages/react/src/ReactSharedInternalsClient.js';
@@ -100,8 +100,8 @@ const forks = Object.freeze({
entry === 'react-dom/src/ReactDOMFB.js' ||
entry === 'react-dom/src/ReactDOMTestingFB.js' ||
entry === 'react-dom/src/ReactDOMServer.js' ||
entry === 'react-html/src/ReactHTMLClient.js' ||
entry === 'react-html/src/ReactHTMLServer.js'
entry === 'react-markup/src/ReactMarkupClient.js' ||
entry === 'react-markup/src/ReactMarkupServer.js'
) {
if (
bundleType === FB_WWW_DEV ||

View File

@@ -444,14 +444,14 @@ module.exports = [
{
shortName: 'markup',
entryPoints: [
'react-html/src/ReactHTMLClient.js', // react-html
'react-html/src/ReactHTMLServer.js', // react-html/react-html.react-server
'react-markup/src/ReactMarkupClient.js', // react-markup
'react-markup/src/ReactMarkupServer.js', // react-markup/react-markup.react-server
],
paths: [
'react-dom',
'react-dom/src/ReactDOMReactServer.js',
'react-dom-bindings',
'react-html',
'react-markup',
'shared/ReactDOMSharedInternals',
],
isFlowTyped: true,