Skip to content

Commit

Permalink
fix(plugin-runtime): Document.tsx should work normal with title tag r…
Browse files Browse the repository at this point in the history
…ender (#4961)
  • Loading branch information
fireairforce authored Nov 24, 2023
1 parent ce201bb commit ecc57b6
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 7 deletions.
6 changes: 6 additions & 0 deletions .changeset/chilled-swans-eat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@modern-js/runtime': patch
---

fix(plugin-runtime): `Document.tsx` should work fine when user config `html.title` or `html.titleByEntries`
fix(plugin-runtime): `Document.tsx` 正常工作当用户配置 `html.title` or `html.titleByEntries` 的时候
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type DocumentStructureContextProps = {
hasSetLinks?: boolean;
hasSetBody?: boolean;
hasSetRoot?: boolean;
hasSetTitle?: boolean;
docChild?: ReactNode;
};

Expand All @@ -16,4 +17,5 @@ export const DocumentStructureContext =
hasSetBody: false,
hasSetRoot: false,
hasSetLinks: false,
hasSetTitle: false,
});
14 changes: 9 additions & 5 deletions packages/runtime/plugin-runtime/src/document/Head.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,34 @@ import React, { useContext } from 'react';
import { DocumentStructureContext } from './DocumentStructureContext';
import { Scripts } from './Scripts';
import { Links } from './Links';
import { Title } from './Title';
import {
DOCUMENT_META_PLACEHOLDER,
HEAD_PARTICALS_SEPARATOR,
TOP_PARTICALS_SEPARATOR,
} from './constants';

export function Head(props: { children?: any }) {
const { hasSetScripts, hasSetLinks } = useContext(DocumentStructureContext);
const { hasSetScripts, hasSetLinks, hasSetTitle } = useContext(
DocumentStructureContext,
);
const { children, ...rest } = props;
// todo: verify the children
return (
<head {...rest}>
{/* configuration by config.output.meta */}
{`${TOP_PARTICALS_SEPARATOR}`}
{`${DOCUMENT_META_PLACEHOLDER}`}
{TOP_PARTICALS_SEPARATOR}
{DOCUMENT_META_PLACEHOLDER}
{!hasSetTitle && <Title />}
{!hasSetLinks && <Links />}
{/* Scripts must have as default. If not, place in Head */}
{!hasSetScripts && <Scripts />}
{`${HEAD_PARTICALS_SEPARATOR}`}
{HEAD_PARTICALS_SEPARATOR}
{children}
</head>
);
}

export function DefaultHead() {
return <head>{`${DOCUMENT_META_PLACEHOLDER}`}</head>;
return <head>{DOCUMENT_META_PLACEHOLDER}</head>;
}
2 changes: 2 additions & 0 deletions packages/runtime/plugin-runtime/src/document/Html.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export function Html(props: { children: any[] }) {
const hasSetLinks = Boolean(findTargetElement('Links', children));
const hasSetBody = Boolean(findTargetChild('Body', children));
const hasSetRoot = Boolean(findTargetElement('Root', children));
const hasSetTitle = Boolean(findTargetElement('title', children));
const notMissMustChild = [
hasSetHead,
hasSetBody,
Expand Down Expand Up @@ -96,6 +97,7 @@ export function Html(props: { children: any[] }) {
hasSetLinks,
hasSetRoot,
hasSetBody,
hasSetTitle,
docChild: children,
}}
>
Expand Down
5 changes: 5 additions & 0 deletions packages/runtime/plugin-runtime/src/document/Title.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { DOCUMENT_TITLE_PLACEHOLDER } from './constants';

export function Title() {
return <title>{DOCUMENT_TITLE_PLACEHOLDER}</title>;
}
11 changes: 10 additions & 1 deletion packages/runtime/plugin-runtime/src/document/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
DOCUMENT_COMMENT_PLACEHOLDER_END,
DOCUMENT_STYLE_PLACEHOLDER_START,
DOCUMENT_STYLE_PLACEHOLDER_END,
DOCUMENT_TITLE_PLACEHOLDER,
TOP_PARTICALS_SEPARATOR,
HEAD_PARTICALS_SEPARATOR,
BODY_PARTICALS_SEPARATOR,
Expand Down Expand Up @@ -224,6 +225,13 @@ export const documentPlugin = (): CliPlugin<AppTools> => ({
.join(''),
].join('');

const titles = [
templateParameters.title,
htmlWebpackPlugin.tags.headTags
.filter((item: any) => item.tagName === 'title')
.join(''),
].join('');

// if the Document.tsx has a functional script, replace to convert it
if (
html.includes(DOCUMENT_SCRIPT_PLACEHOLDER_START) &&
Expand Down Expand Up @@ -281,7 +289,8 @@ export const documentPlugin = (): CliPlugin<AppTools> => ({
.replace(
DOCUMENT_SSRDATASCRIPT_PLACEHOLDER,
PLACEHOLDER_REPLACER_MAP[DOCUMENT_SSRDATASCRIPT_PLACEHOLDER],
);
)
.replace(DOCUMENT_TITLE_PLACEHOLDER, titles);
return finalHtml;
};
};
Expand Down
1 change: 1 addition & 0 deletions packages/runtime/plugin-runtime/src/document/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { HTML_CHUNKSMAP_SEPARATOR } from '@modern-js/utils/universal/constants';

export const DOC_EXT = ['jsx', 'tsx', 'ts', 'js'];
export const DOCUMENT_META_PLACEHOLDER = encodeURIComponent('<%= meta %>');
export const DOCUMENT_TITLE_PLACEHOLDER = encodeURIComponent('<%= title %>');
export const HTML_SEPARATOR = '<!--<?- html ?>-->';
export const HEAD_PARTICALS_SEPARATOR = encodeURIComponent(
'<!--<?- partials.head ?>-->',
Expand Down
27 changes: 26 additions & 1 deletion packages/runtime/plugin-runtime/tests/document/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('plugin-document', () => {
);
const docHtml = ReactDomServer.renderToString(document);
expect(docHtml).toEqual(
`<html><head>%3C!--%3C%3F-%20partials.top%20%3F%3E--%3E<!-- -->%3C%25%3D%20meta%20%25%3E<!-- -->%3C!--%20chunk%20links%20placeholder%20--%3E<!-- -->%3C!--%20chunk%20scripts%20placeholder%20--%3E<!-- -->%3C!--%3C%3F-%20partials.head%20%3F%3E--%3E</head><body><div id="root">%3C!--%3C%3F-%20html%20%3F%3E--%3E</div>%3C!--%3C%3F-%20partials.body%20%3F%3E--%3E<!-- -->%3C!--%3C%3F-%20chunksMap.js%20%3F%3E--%3E<!-- -->%3C!--%3C%3F-%20SSRDataScript%20%3F%3E--%3E</body></html>`,
`<html><head>%3C!--%3C%3F-%20partials.top%20%3F%3E--%3E<!-- -->%3C%25%3D%20meta%20%25%3E<title>%3C%25%3D%20title%20%25%3E</title>%3C!--%20chunk%20links%20placeholder%20--%3E<!-- -->%3C!--%20chunk%20scripts%20placeholder%20--%3E<!-- -->%3C!--%3C%3F-%20partials.head%20%3F%3E--%3E</head><body><div id=\"root\">%3C!--%3C%3F-%20html%20%3F%3E--%3E</div>%3C!--%3C%3F-%20partials.body%20%3F%3E--%3E<!-- -->%3C!--%3C%3F-%20chunksMap.js%20%3F%3E--%3E<!-- -->%3C!--%3C%3F-%20SSRDataScript%20%3F%3E--%3E</body></html>`,
);
});

Expand Down Expand Up @@ -92,4 +92,29 @@ describe('plugin-document', () => {

expect(docHtml.includes(`<h1>title: </h1><div id="abc">`)).toBeTruthy();
});

it('should render title successful', () => {
const document = (
<DocumentContext.Provider
value={{
templateParams: {
title: 'aaaa',
},
}}
>
<Html>
<Head></Head>
<Body>
<Root rootId="abc"></Root>
<Scripts></Scripts>
</Body>
</Html>
</DocumentContext.Provider>
);
const docHtml = ReactDomServer.renderToString(document);

expect(
docHtml.includes(`<title>%3C%25%3D%20title%20%25%3E</title>`),
).toBeTruthy();
});
});
1 change: 1 addition & 0 deletions tests/integration/app-document/modern.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default applyBaseConfig({
},
html: {
favicon: './static/a.icon',
title: 'test-title',
},
plugins: [routerPlugin(), tmpTest()],
});
8 changes: 8 additions & 0 deletions tests/integration/app-document/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ describe('test dev and build', () => {
),
).toBe(true);
});

test('should has title in Head', async () => {
const htmlWithDoc = fs.readFileSync(
path.join(appDir, 'dist', 'html/sub/index.html'),
'utf-8',
);
expect(htmlWithDoc.includes('<title>test-title</title>')).toBe(true);
});
});

describe('test dev', () => {
Expand Down

0 comments on commit ecc57b6

Please sign in to comment.