diff --git a/README-ru.md b/README-ru.md index b4d059e..f4ec211 100644 --- a/README-ru.md +++ b/README-ru.md @@ -43,6 +43,8 @@ interface RenderParams { icon?: Icon; // nonce to be set on the appropriate tags nonce?: string; + // base tag attributes + base?: Base; // common options // Page title @@ -85,6 +87,32 @@ interface RenderParams { } ``` +### `Base` + +Описывает тег `base`: + +```typescript +interface Base { + href?: string; + target?: HTMLBaseElement['target']; +} +``` + +Например: + +```js +renderLayout({ + title: 'Home page', + base: {target: '_top'}, +}); +``` + +Будет выглядеть следующим образом: + +```html + +``` + ### `Meta` Описывает тег `meta`: @@ -252,6 +280,7 @@ interface CommonOptions { } export interface HeadContent { + base?: Base; scripts: Script[]; helpers: RenderHelpers; links: Link[]; diff --git a/README.md b/README.md index 2f38f1c..6fb5dac 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,8 @@ interface RenderParams { icon?: Icon; // nonce to be set on the appropriate tags nonce?: string; + // base tag attributes + base?: Base; // common options // Page title @@ -85,6 +87,32 @@ interface RenderParams { } ``` +### Base + +Describes `base` tag: + +```typescript +interface Base { + href?: string; + target?: HTMLBaseElement['target']; +} +``` + +Example: + +```js +renderLayout({ + title: 'Home page', + base: {target: '_top'}, +}); +``` + +Will be rendered as: + +```html + +``` + ### Meta Describes `meta` tag: @@ -252,6 +280,7 @@ interface CommonOptions { } export interface HeadContent { + base?: Base; scripts: Script[]; helpers: RenderHelpers; links: Link[]; diff --git a/src/index.ts b/src/index.ts index b391db4..1017b0e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,6 +12,7 @@ export { } from './plugins/index.js'; export type { + Base, Plugin, Icon, Link, diff --git a/src/render.test.ts b/src/render.test.ts index 9e993aa..a8207af 100644 --- a/src/render.test.ts +++ b/src/render.test.ts @@ -16,6 +16,24 @@ test('should allow `` attributes override', () => { expect(createRenderFunction([dirPlugin()])({title: 'Foobar'})).toMatch(''); }); +test('should render `` tag with target', () => { + const html = createRenderFunction()({title: 'Foobar', base: {target: '_top'}}); + expect(html).toMatch(''); +}); + +test('should render `` tag with href and target', () => { + const html = createRenderFunction()({ + title: 'Foobar', + base: {href: 'https://example.com/', target: '_top'}, + }); + expect(html).toMatch(''); +}); + +test('should not render `` tag when base is not provided', () => { + const html = createRenderFunction()({title: 'Foobar'}); + expect(html).not.toMatch(' { expect(createRenderFunction()({title: 'Foobar'})).toMatch(/
\s*<\/div>/); expect(createRenderFunction()({title: 'Foobar', bodyContent: {root: 'content'}})).toMatch( diff --git a/src/types.ts b/src/types.ts index 191f01f..813bf31 100644 --- a/src/types.ts +++ b/src/types.ts @@ -32,6 +32,11 @@ export interface Icon { export type Meta = {name: string; content: string}; +export interface Base { + href?: string; + target?: HTMLBaseElement['target']; +} + export interface CommonOptions { title: string; lang?: string; @@ -39,6 +44,7 @@ export interface CommonOptions { } export interface HeadContent { + base?: Base; scripts: Script[]; helpers: RenderHelpers; links: Link[]; @@ -56,7 +62,7 @@ export interface BodyContent { afterRoot: string[]; } -export interface RenderContent extends HeadContent { +export interface RenderContent extends Required { htmlAttributes: Attributes; bodyContent: BodyContent; } @@ -84,6 +90,7 @@ export interface RenderParams extends Commo data?: Data; icon?: Icon; nonce?: string; + base?: Base; // content htmlAttributes?: Attributes; meta?: Meta[]; diff --git a/src/utils/generateRenderContent.ts b/src/utils/generateRenderContent.ts index e7f4c17..69e8a71 100644 --- a/src/utils/generateRenderContent.ts +++ b/src/utils/generateRenderContent.ts @@ -71,13 +71,14 @@ export function generateRenderContent( links.unshift({rel: 'icon', type: icon.type, sizes: icon.sizes, href: icon.href}); } - const {lang, isMobile, title, pluginsOptions = {}} = params; + const {lang, isMobile, title, base = {}, pluginsOptions = {}} = params; for (const plugin of plugins ?? []) { plugin.apply({ options: hasProperty(pluginsOptions, plugin.name) ? pluginsOptions[plugin.name] : undefined, renderContent: { + base, htmlAttributes, meta, links, @@ -99,6 +100,7 @@ export function generateRenderContent( } return { + base, htmlAttributes, meta, links, diff --git a/src/utils/renderHeadContent.ts b/src/utils/renderHeadContent.ts index 926760d..1a7e342 100644 --- a/src/utils/renderHeadContent.ts +++ b/src/utils/renderHeadContent.ts @@ -1,11 +1,23 @@ import type {HeadContent} from '../types.js'; export function renderHeadContent(content: HeadContent): string { - const {scripts, helpers, links, meta, styleSheets, inlineStyleSheets, inlineScripts, title} = - content; + const { + base, + scripts, + helpers, + links, + meta, + styleSheets, + inlineStyleSheets, + inlineScripts, + title, + } = content; + + const baseAttrs = base ? helpers.attrs({...base}) : ''; return ` + ${baseAttrs ? `` : ''} ${title} ${[ ...scripts.map(({src, crossOrigin}) =>