UNPKG

jsharmony-cms-sdk-next

Version:
694 lines (650 loc) 24 kB
/*! Copyright 2024 apHarmony This file is part of jsHarmony. jsHarmony is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. jsHarmony is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this package. If not, see <http://www.gnu.org/licenses/>. */ import { GetServerSidePropsResult } from 'next'; import { Metadata } from 'next'; import { NextRequest } from 'next/server'; import { NextResponse } from 'next/server'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ResolvingMetadata } from 'next'; import { ValidationMap } from 'react'; import { WeakValidationMap } from 'react'; /** * JshCms - renders head, editor, script, style, footer tags, and a container for JshCmsContentArea tags * @remarks * * @example * ``` * <JshCms jshCmsPage={jshCmsPage} jshCmsConfig={JshCmsConfig}> * <h1 cms-title="true">{jshCmsPage.title||'Title'}</h1> * <JshCmsContentArea cms-content="body">Page Content</JshCmsContentArea> * </JshCms> * ``` * @public */ export declare function JshCms(props: JshCmsProps): React_2.JSX.Element; /** * @public */ export declare interface JshCmsConfig { /** URL to published CMS content files */ contentUrl?: string; /** Path to redirect listing JSON file (relative to contentUrl) */ redirectListingPath?: string | null; /** Default Directory Document (e.g. index.html) */ defaultDocument?: string; /** The CMS Server URLs that will be enabled for Page Editing (set to '*' to enable any remote CMS) * - Used by jshCmsPage.editorScriptPath, and the getEditorScriptPath function * - NOT used by jsHarmonyCmsEditor.js - the launcher instead uses accessKeys for validating the remote CMS */ cmsServerUrls?: string[]; /** Cache duration (seconds) */ cacheDuration?: number; } /** * JshCmsContentArea - Render content area. * @remarks * React function component for rendering content area content and associated portals for child component rendering. * * @example * ``` * <JshCmsContentArea cms-content="body" jshCmsPage={jshCmsPage}> * Optional Default Body Content * </JshCmsContentArea> * ``` * @public */ export declare function JshCmsContentArea(props: JshCmsContentAreaProps): React_2.JSX.Element; /** * @public */ export declare interface JshCmsContentAreaProps { jshCmsPage?: JshCmsPage; jshCmsContentComponents?: JshCmsContentComponent<any>[]; ['cms-content']: string; [key: string]: any; } /** * JshCmsContentComponent - Content Component. * @public */ export declare interface JshCmsContentComponent<P = {}> { (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null; propTypes?: WeakValidationMap<P> | undefined; contextTypes?: ValidationMap<any> | undefined; defaultProps?: Partial<P> | undefined; displayName?: string | undefined; jshCmsComponentConfig?: JshCmsContentComponentConfig | undefined; } /** * JshCmsContentComponent - Content Component. * @public */ export declare class JshCmsContentComponent<P = {}> implements JshCmsContentComponent<P> { static extractChildrenAsReactElements(container: Element): ReactElement[]; } /** * JshCmsContentComponent - Content Component Config. * @public */ export declare interface JshCmsContentComponentConfig { selector: string; onBeforeRender?: (componentContainer: Element, contentComponentProps: JshCmsContentComponentProps | null) => void; onRender?: (componentContainer: Element, contentComponentProps: JshCmsContentComponentProps | null) => void; render?: (componentContainer: Element, contentComponentProps: JshCmsContentComponentProps | null) => JshCmsContentComponentRender | undefined; } /** * JshCmsContentComponentInstance - Content Component Instance. * @public */ export declare interface JshCmsContentComponentInstance { container: Element; element: ReactElement; key: string; } /** * @public */ export declare interface JshCmsContentComponentProps { data: unknown; properties: unknown; isInEditor: boolean; isInPageEditor: boolean; isInComponentEditor: boolean; isItemPreview: boolean; isGridRowPreview: boolean; } /** * JshCmsContentComponentInstance - Content Component Render Parameters. * @public */ export declare interface JshCmsContentComponentRender { container?: Element; element: ReactElement; key?: string; } /** * @internal */ export declare const JshCmsContext: React_2.Context<JshCmsContextData>; /** * @public */ export declare interface JshCmsContextData { jshCmsConfig: JshCmsConfig | undefined; jshCmsPage: JshCmsPage | undefined; } /** * JshCmsEditor - render editor support script when page is loaded in the CMS editor. * @remarks * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed. * Note: CMS was designed to support additional head tags. Next.js takes full control of the head, so these must be placed elsewhere. * * @example * ``` * <JshCmsEditor jshCmsPage={jshCmsPage} /> * ``` * @public */ export declare function JshCmsEditor(props: JshCmsElementProps): React_2.JSX.Element; /** * @public */ export declare interface JshCmsElementProps { jshCmsPage?: JshCmsPage; [key: string]: any; } /** * JshCsFooter - render additional footer tags (if any). * @remarks * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed. * * @example * ``` * <JshCmsFooter jshCmsPage={jshCmsPage} /> * ``` * @public */ export declare function JshCmsFooter(props: JshCmsElementProps): React_2.JSX.Element; /** * JshCmsHead - render additional head tags (if any). Note that this feature in particular is questionable with the Next.js head management, and since raw text must have a container, it is rendered in a div. * @remarks * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed. * Note: CMS was designed to support additional head tags. Next.js takes full control of the head, so these must be placed elsewhere. * * @example * ``` * <JshCmsHead jshCmsPage={jshCmsPage} /> * ``` * @public */ export declare function JshCmsHead(props: JshCmsElementProps): React_2.JSX.Element; /** * @public */ export declare interface JshCmsMetadataProps { params: { [key: string]: string[] | string | undefined; }; } /** * @public */ export declare interface JshCmsPage { content: { [areaId: string]: string; }; css: string; /** If page was opened from a CMS Editor in config.cmsServerUrls, the HTML script to launch the Editor */ editorScriptPath: string | null; footer: string; header: string; /** Whether the page was opened from the CMS Editor */ isInEditor: boolean; js: string; page_template_id: string; properties: { [propName: string]: any; }; seo: { canonical_url: string; keywords: string; metadesc: string; /** Title for HEAD */ title: string; }; /** Title for Page Body Content */ title: string; /** Whether the page was Not Found (page data will return empty) */ notFound: boolean; } /** * @public */ export declare class JshCmsPage implements JshCmsPage { /** * getEmptyPage - An empty JshCmsPage object, for blank editors or initializing useState * @param pageTemplateId - page template id for newly created pages * @public */ static getEmptyPage(pageTemplateId: string): JshCmsPage; /** * getNotFoundPage - An empty JshCmsPage object, with the notFound flag set * @param pageTemplateId - page template id for newly created pages * @public */ static getNotFoundPage(pageTemplateId: string): JshCmsPage; /** * getPage - Get CMS Page Data * @param pathname - Root-relative Page URL * @param params - Page load parameters * @param config - Configuration parameters * @public */ static getPage(pathname: string[] | string | undefined, params: { [key: string]: string[] | string | undefined; }, config: JshCmsPageRequest): Promise<JshCmsPage>; /** * getMetadata - provides a basic version of a Next.js metadata function that provides CMS SEO data. * * @remarks * If you application has additional metadata needs, you may wish to copy this function into your generateMetadata function. * {@link https://nextjs.org/docs/app/api-reference/functions/generate-metadata} * * @param props - params from the incoming request * @param parent - metadata from previous functions * @param config - CMS configuration parameters * @public */ static getMetadata({ params }: JshCmsMetadataProps, // eslint-disable-line @typescript-eslint/no-unused-vars parent: ResolvingMetadata, config: JshCmsPageRequest): Promise<Metadata>; /** * getEditorScriptPath - Generate script for CMS Editor * @remarks * - The provided url is validated against cmsServerUrls * - If the CMS Server is not found in cmsServerUrls, an empty element will be returned * * @param cmsServerUrl - URL from jshcms_url parameter * @param cmsServerUrls - list of allowed CMS editor servers * @returns path to the editor script * * @public */ static getEditorScriptPath(cmsServerUrl: string, cmsServerUrls: string[]): string | null; /** * getStandalonePage [Main Entry Point] - Get CMS Page Data for Standalone Integration * @remarks * if page is opened from CMS Editor or Not Found, an empty JshCmsPage Object will be returned * * @param pathname - Root relative path being requested * @param params - Request url parameters * @param config - CMS Configuration parameters * @returns JshCmsPage Object, with set properties: isInEditor, editorScriptPath, notFound * @public */ static getStandalonePage(pathname: string[] | string | undefined, params: { [key: string]: string[] | string | undefined; }, config: JshCmsPageRequest): Promise<JshCmsPage>; /** * getPath - Transform a page url into cms content file path * @param contentUrl - CMS content export folder * @param pathname - Root relative path being requested * @returns normalized path * @public */ static getPath(contentUrl: string, pathname: string): string; /** * getPathVariations - creations variations of a cms content path to try, e.g. as provided and with index.html * @param pathname - Root relative path being requested * @param defaultDocument - default document if not in url, e.g. 'index.html' * @returns list of paths to try * @public */ static getPathVariations(pathname: string, defaultDocument: string): string[]; /** * resolvePath - Convert URL to CMS Content Paths * @param contentUrl - CMS content URL * @param pathname - Root relative path being requested * @param defaultDocument - default document if not in url, e.g. 'index.html' * @returns list of paths to try * @public */ static resolvePath(contentUrl: string, pathname: string, defaultDocument: string): string[]; } /** * JshCmsPageComponent - Page Component. * @public */ export declare function JshCmsPageComponent(props: JshCmsPageComponentProps): React_2.JSX.Element; /** * @public */ export declare interface JshCmsPageComponentProps { componentId: string; [key: string]: any; } /** * JshCmsPageConfig - render config settings as a script tag * @remarks * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed. * Note: CMS was designed to support additional head tags. Next.js takes full control of the head, so these must be placed elsewhere. * * @example * ``` <JshCmsPageConfig cms-template="Two Column Page Template" config={{ "content_elements": { "left": { "title": "Left" }, "right": { "title": "Right" } } }} /> * ``` * @public */ export declare function JshCmsPageConfig(props: JshCmsPageConfigProps): React_2.JSX.Element | undefined; /** * @public */ export declare interface JshCmsPageConfigDefinition { title?: string; /** * Each editable content area has one entry in * content_elements. If no content areas are defined, * a default content area named "body" will be added. */ content_elements?: { [content_area_name: string]: { title?: string; editor_toolbar?: { /** Dock position for the Editor Menu and Toolbar. Defaults to 'auto'. */ dock?: 'auto' | 'bottom' | 'top_offset' | 'top'; /** Whether to display the editor menu. Defaults to true. */ show_menu?: boolean; /** Whether to display the editor toolbar. Defaults to true. */ show_toolbar?: boolean; }; /** Editable area type. Defaults to 'htmleditor' */ type?: 'htmleditor' | 'text'; }; }; /** * Default value for each content area. If omitted, * the HTML content will be used. */ default_content?: { [content_area_name: string]: string; }; /** Page Properties fields */ properties?: { fields: unknown[]; }; options?: { /** If set to false, no cms-title element required on the page. Defaults to true. */ title_element_required?: boolean; /** Page toolbar dock position. Defaults to 'top_offset'. */ dock?: 'bottom' | 'top_offset' | 'top'; }; /** SYSTEM - Hard-coded content element content. */ content?: { [content_area_name: string]: string | { title?: string; }; }; } /** * @public */ export declare interface JshCmsPageConfigProps { config?: JshCmsPageConfigDefinition; } /** * @public */ export declare interface JshCmsPageRequest { /** CMS content URL */ contentUrl: string; /** default document if not in url, e.g. 'index.html' */ defaultDocument: string; /** valid CMS server URLs */ cmsServerUrls: string[]; /** cache duration in seconds */ cacheDuration: number; } /** * @public */ export declare interface JshCmsProps { jshCmsConfig: JshCmsConfig; jshCmsPage?: JshCmsPage; children?: React_2.ReactNode; } /** * @public */ export declare function JshCmsProvider(props: JshCmsProviderProps): React_2.JSX.Element; /** * @public */ export declare interface JshCmsProviderProps { jshCmsConfig?: JshCmsConfig; jshCmsPage?: JshCmsPage; children?: React_2.ReactNode; } /** * A redirect loaded from the CMS data file * @public */ export declare interface JshCmsRedirect { redirect_key: number; redirect_url: string; /** 'BEGINS'|'BEGINSICASE'|'EXACT'|'EXACTICASE'|'REGEX'|'REGEXICASE' */ redirect_url_type: string; redirect_dest: string; /** '301'|'302'|'PASSTHRU' */ redirect_http_code: string; } /** * Resolved redirect result * @public */ export declare interface JshCmsRoute { /** '301'|'302'|'PASSTHRU' */ http_code: string; url: string; } /** * @public */ export declare class JshCmsRouter { /** URL to published CMS content files */ contentUrl: string; /** Path to redirect listing JSON file (relative to contentUrl) */ redirectListingPath: string | null; /** The CMS Server URLs that will be enabled for Page Editing (set to '*' to enable any remote CMS) * - Used by jshCmsPage.editorScriptPath, and the getEditorScriptPath function * - NOT used by jsHarmonyCmsEditor.js - the launcher instead uses accessKeys for validating the remote CMS */ cmsServerUrls: string[]; /** Default Directory Document (e.g. index.html) */ defaultDocument: string; /** Cache duration (seconds) */ cacheDuration: number; constructor(config: JshCmsConfig); /** getConfig - Get the current config */ getConfig(): JshCmsConfig; /** getRedirectListingPath - Get the configured path for the redirect listing file */ getRedirectListingPath(): string | undefined; /** * getRedirectData - Get CMS Redirect Data * @param origin - http origin * @returns Redirects */ getRedirectData(origin: string): Promise<JshCmsRedirect[]>; /** * getRedirect - Lookup the redirect for a request, if any * @param request - Request object providing target path and origin * @returns Appropriate redirect, if one was found */ getRedirect(request: NextRequest): Promise<JshCmsRoute | undefined>; /** * processJshCmsRedirects - Execute the redirect for a request, if any * @param request - Request object providing target path and origin * @returns Appropriate response, if one was found */ processRedirects(request: NextRequest): Promise<NextResponse | undefined>; /** *hasPage - Check if a page object file exists to decide if a route is available. * @param pathname - target path */ hasPage(pathname: string): Promise<boolean>; /** * getStandalonePage [Main Entry Point] - Get CMS Page Data for Standalone Integration * @remarks * if page is opened from CMS Editor or Not Found, an empty Page Object will be returned * * @param pathname - Root relative path being requested * @param params - Request url parameters * @returns Page Object, with filled properties: isInEditor, editorScriptPath, notFound */ getStandalonePage(pathname: string[] | string | undefined, params: { [key: string]: string[] | string | undefined; }): Promise<JshCmsPage>; /** * getEmptyPage - An empty Page object, for blank editors or initializing useState * @param pageTemplateId - page template id for newly created pages */ getEmptyPage(pageTemplateId: string): JshCmsPage; /** * getMetadata - provides a basic version of a Next.js metadata function that provides CMS SEO data. * @remarks * If you application has additional metadata needs, you may wish to copy the base function into your generateMetadata function. * {@link https://nextjs.org/docs/app/api-reference/functions/generate-metadata} */ getMetadata({ params }: JshCmsMetadataProps, parent: ResolvingMetadata): Promise<Metadata>; /** *getPage - Returns a Page object for a specified path * @param pathname - Root relative path being requested * @param params - Request url parameters * @returns Page Object, with filled properties: isInEditor, editorScriptPath, notFound */ getPage(pathname: string[] | string | undefined, params: { [key: string]: string[] | string | undefined; }): Promise<JshCmsPage>; /** *serve [Main Entry Point] - Serves CMS content for a target URL * @remarks * if page is opened from CMS Editor or Not Found, an empty Page Object will be returned * * @param pathname - Root relative path being requested * @param params - Request url parameters * @returns Page Object, with filled properties: isInEditor, editorScriptPath, notFound */ serve(pathname: string[] | string | undefined, params: { [key: string]: string[] | string | undefined; }): Promise<GetServerSidePropsResult<{ jshCmsPage: JshCmsPage; }>>; /** * loadRedirectData - Load and parse the redirects file * @param redirectListingPath - Path to exported CMS redirects * @returns List of redirects * @public */ loadRedirectData(redirectListingPath: string, origin: string): Promise<JshCmsRedirect[]>; /** * processRoute - Provides simple handling of redirects in Next.js, replace as needed. * @param route - Path and code of a found redirect * @param requestUrl - Original request url * @returns Response, if a valid redirect was provided. * @public */ static processRoute(route: JshCmsRoute, requestUrl: URL | string | undefined): NextResponse | undefined; /** * matchRedirect - Check if URL matches redirects and return first match * @param redirects - Array of CMS Redirects * @param urlpath - Target URL path * @public */ static matchRedirect(redirects: JshCmsRedirect[], urlpath: string): JshCmsRoute | undefined; /** * getRedirectBase - Looks up matching redirect, if any. * @param pathname - target path * @param contentUrl - URL to content files * @param redirectListingPath - Path to exported CMS redirects * @returns path and code if found */ private getRedirectBase; /** * hasPageBase - Check if a page object file exists to decide if a route is available. * @param pathname - target url path name * @param contentUrl - URL to CMS content files * @param defaultDocument - default document if not in url, e.g. 'index.html' */ private hasPageBase; } /** * JshCmsScript - render additional javascript (if any) as a script tag * @remarks * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed. * Note: CMS was designed to support additional head tags. Next.js takes full control of the head, so these must be placed elsewhere. * * @example * ``` * <JshCmsScript jshCmsPage={jshCmsPage} /> * ``` * @public */ export declare function JshCmsScript(props: JshCmsElementProps): React_2.JSX.Element; /** * JshCmsStyle - render additional css (if any) as a style tag * @remarks * Simple React function component for conditionally including tags in pages. These are trivial and can be replaced with custom code as needed. * Note: CMS was designed to support additional head tags. Next.js takes full control of the head, so these must be placed elsewhere. * * @example * ``` * <JshCmsStyle jshCmsPage={jshCmsPage} /> * ``` * @public */ export declare function JshCmsStyle(props: JshCmsElementProps): React_2.JSX.Element; /** * @internal */ export declare interface notifyUpdateProps { element: HTMLElement; componentId: string; contentAreaName: string; data?: unknown; properties?: unknown; isItemPreview?: boolean; isGridRowPreview?: boolean; content?: string; } /** * @public */ export declare const useJshCms: () => JshCmsContextData; /** * @public */ export declare function useJshCmsPageComponentData<T>(props: { jshCmsPage?: JshCmsPage; componentId: string; contentAreaName?: string; }): { componentData: (T | null); }; export { }