-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathindex.tsx
More file actions
97 lines (85 loc) · 2.79 KB
/
Copy pathindex.tsx
File metadata and controls
97 lines (85 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import Script from 'next/script';
import { QueryEngine } from '@snapwp/query';
import { TemplateFooter } from './template-footer';
import { TemplateHead } from './template-head';
import { TemplateScripts } from './template-scripts';
import type { BlockData } from '@snapwp/types';
import type { ReactNode } from 'react';
export type TemplateRendererProps = {
getTemplateData?: ( typeof QueryEngine )[ 'getTemplateData' ];
children: ( editorBlocks: BlockData[] ) => ReactNode;
params: Promise< {
uri: string[];
} >;
};
/**
* Renders a full HTML document including the head, body, and scripts.
* Combines custom styles, block content, and scripts into a complete page.
*
* @param {Object} props The props for the component.
* @param {TemplateRendererProps['getTemplateData']} props.getTemplateData A async callback to get template styles and content.
* @param {TemplateRendererProps['children']} props.children The block content to render.
* @param {TemplateRendererProps['params']} props.params The params for the component.
*
* @return A complete HTML document structure.
*/
export async function TemplateRenderer( {
getTemplateData = QueryEngine.getTemplateData,
children,
params,
}: TemplateRendererProps ): Promise< ReactNode > {
const pathname = generatePathName( await params );
const { editorBlocks, bodyClasses, stylesheets, scripts, scriptModules } =
await getTemplateData( pathname || '/' );
if ( ! editorBlocks?.length ) {
throw new Error(
'Error: Unable to render content. `editorBlocks` is not defined. This may be due to missing template data or an issue with data fetching.'
);
}
// @todo: Script modules should load before styles to handle ordering properly
return (
<>
<TemplateHead stylesheets={ stylesheets } />
<TemplateScripts
scripts={ scripts }
scriptModules={ scriptModules }
>
<main>
<div className="wp-site-blocks">
{ children( editorBlocks ) }
</div>
</main>
</TemplateScripts>
<TemplateFooter />
{ /* Hot Fix for adding classes to the body outside the root layout */ }
<Script
strategy="beforeInteractive"
dangerouslySetInnerHTML={ {
__html: `
${ JSON.stringify( bodyClasses ) }.forEach( ( c ) => {
document.body.classList.add( c );
} );
`,
} }
/>
</>
);
}
/**
* Generates the path name for the template renderer.
*
* @param {Object} params The params for the component.
* @param {string[]} params.uri The slug segments to join.
*
* @return {string} The generated path name.
*/
const generatePathName = ( params: { uri: string[] } ): string => {
if ( ! params.uri ) {
return '/';
}
const path = params.uri.join( '/' );
if ( path.length > 0 ) {
return `/${ path }`;
}
return '/';
};