Add doctype to renderToMarkup when html tags are rendered (#30122)
Stacked on top of #30121. This is the same thing we do for `renderToReadableStream` so that you don't have to manually inject it into the stream. The only reason we didn't for `renderToString` / `renderToStaticMarkup` was to preserve legacy behavior but since this is a new API we can change that. If you're rendering a partial it doesn't matter. This is likely what you'd do for RSS feeds. The question is if you can reliably rely on the doctype being used while rendering e-mails since many clients are so quirky. However, if you're careful it also doesn't hurt so it seems best to include it.
Sebastian Markbåge committed
Jun 28, 2024 at 15:35 UTC
0d1fdb5c2ebdbde03c8f6b5dcb4058dc715ffb0a
3 files changed
+27
-8
packages/react-html/src/ReactFizzConfigHTML.js
+2
-8
@@ -36,14 +36,7 @@ export const isPrimaryRenderer = false;
36
// Disable Client Hooks
37
export const supportsClientAPIs = false;
38
39
-import {
40
- stringToChunk,
41
- stringToPrecomputedChunk,
42
-} from 'react-server/src/ReactServerStreamConfig';
43
-
44
-// this chunk is empty on purpose because we do not want to emit the DOCTYPE
45
-// when markup is rendering HTML
46
-export const doctypeChunk: PrecomputedChunk = stringToPrecomputedChunk('');
39
+import {stringToChunk} from 'react-server/src/ReactServerStreamConfig';
40
41
export type {
42
RenderState,
@@ -81,6 +74,7 @@ export {
74
resetResumableState,
75
completeResumableState,
76
emitEarlyPreloads,
77
+ doctypeChunk,
78
} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
79
80
import escapeTextForBrowser from 'react-dom-bindings/src/server/escapeTextForBrowser';
packages/react-html/src/__tests__/ReactHTMLClient-test.js
+11
@@ -28,6 +28,17 @@ describe('ReactHTML', () => {
28
expect(html).toBe('<div>hello world</div>');
29
});
30
31
+ it('should prefix html tags with a doctype', async () => {
32
+ const html = await ReactHTML.renderToMarkup(
33
+ <html>
34
+ <body>hello</body>
35
+ </html>,
36
+ );
37
+ expect(html).toBe(
38
+ '<!DOCTYPE html><html><head></head><body>hello</body></html>',
39
+ );
40
+ });
41
+
42
it('should error on useState', async () => {
43
function Component() {
44
const [state] = React.useState('hello');
packages/react-html/src/__tests__/ReactHTMLServer-test.js
+14
@@ -38,6 +38,20 @@ describe('ReactHTML', () => {
38
expect(html).toBe('<div>hello world</div>');
39
});
40
41
+ it('should prefix html tags with a doctype', async () => {
42
+ const html = await ReactHTML.renderToMarkup(
43
+ // We can't use JSX because that's client-JSX in our tests.
44
+ React.createElement(
45
+ 'html',
46
+ null,
47
+ React.createElement('body', null, 'hello'),
48
+ ),
49
+ );
50
+ expect(html).toBe(
51
+ '<!DOCTYPE html><html><head></head><body>hello</body></html>',
52
+ );
53
+ });
54
+
55
it('should error on useState', async () => {
56
function Component() {
57
const [state] = React.useState('hello');