ngx-contentful-rich-text
Version:
Angular renderer for the Contentful rich text field type
294 lines (279 loc) • 10.3 kB
JavaScript
import * as i0 from '@angular/core';
import { Component, ChangeDetectionStrategy, Injectable, Input, ComponentFactoryResolver, Directive, ViewContainerRef, NgModule } from '@angular/core';
import { MARKS, BLOCKS, INLINES } from '@contentful/rich-text-types';
import { CommonModule } from '@angular/common';
class MarkRenderer {
}
const TEXT = `<ng-container ngxMarkRendererHost [node]="node"></ng-container>`;
class DefaultMarkRendererComponent extends MarkRenderer {
constructor() {
super(...arguments);
this.MARKS = MARKS;
}
}
DefaultMarkRendererComponent.decorators = [
{ type: Component, args: [{
template: `
<ng-container [ngSwitch]="node.marks[node.markIndex].type">
<b *ngSwitchCase="MARKS.BOLD">${TEXT}</b>
<code *ngSwitchCase="MARKS.CODE">${TEXT}</code>
<i *ngSwitchCase="MARKS.ITALIC">${TEXT}</i>
<u *ngSwitchCase="MARKS.UNDERLINE">${TEXT}</u>
</ng-container>
`,
changeDetection: ChangeDetectionStrategy.OnPush
},] }
];
class NodeRenderer {
}
const CHILDREN = '<ngx-contentful-rich-text [nodes]="node.content"></ngx-contentful-rich-text>';
const DEFAULT_INLINE = '<span>type: {{ node.nodeType }} id: {{ node.data.target.sys.id }}</span>';
class DefaultNodeRendererComponent extends NodeRenderer {
constructor() {
super(...arguments);
this.BLOCKS = BLOCKS;
this.INLINES = INLINES;
}
}
DefaultNodeRendererComponent.decorators = [
{ type: Component, args: [{
template: `
<ng-container [ngSwitch]="node.nodeType">
<ng-container *ngSwitchCase="BLOCKS.DOCUMENT">${CHILDREN}</ng-container>
<div *ngSwitchCase="BLOCKS.EMBEDDED_ENTRY">${CHILDREN}</div>
<h1 *ngSwitchCase="BLOCKS.HEADING_1">${CHILDREN}</h1>
<h2 *ngSwitchCase="BLOCKS.HEADING_2">${CHILDREN}</h2>
<h3 *ngSwitchCase="BLOCKS.HEADING_3">${CHILDREN}</h3>
<h4 *ngSwitchCase="BLOCKS.HEADING_4">${CHILDREN}</h4>
<h5 *ngSwitchCase="BLOCKS.HEADING_5">${CHILDREN}</h5>
<h6 *ngSwitchCase="BLOCKS.HEADING_6">${CHILDREN}</h6>
<hr *ngSwitchCase="BLOCKS.HR" />
<li *ngSwitchCase="BLOCKS.LIST_ITEM">${CHILDREN}</li>
<ol *ngSwitchCase="BLOCKS.OL_LIST">
${CHILDREN}
</ol>
<p *ngSwitchCase="BLOCKS.PARAGRAPH">${CHILDREN}</p>
<blockquote *ngSwitchCase="BLOCKS.QUOTE">${CHILDREN}</blockquote>
<ul *ngSwitchCase="BLOCKS.UL_LIST">
${CHILDREN}
</ul>
<ng-container *ngSwitchCase="INLINES.ASSET_HYPERLINK">
${DEFAULT_INLINE}
</ng-container>
<ng-container *ngSwitchCase="INLINES.EMBEDDED_ENTRY">
${DEFAULT_INLINE}
</ng-container>
<ng-container *ngSwitchCase="INLINES.ENTRY_HYPERLINK">
${DEFAULT_INLINE}
</ng-container>
<a *ngSwitchCase="INLINES.HYPERLINK" [href]="node.data.uri">
${CHILDREN}
</a>
</ng-container>
`,
changeDetection: ChangeDetectionStrategy.OnPush
},] }
];
class RendererProviderService {
constructor() {
this.nodeRenderers = {};
this.markRenderers = {};
}
getMarkRenderer(node) {
const mark = node.marks[node.markIndex];
const resolver = this.markRenderers[mark.type];
let renderer;
try {
renderer = resolver(node);
}
catch (error) {
renderer = resolver;
}
return renderer || DefaultMarkRendererComponent;
}
getNodeRenderer(node) {
const resolver = this.nodeRenderers[node.nodeType];
let renderer;
try {
renderer = resolver(node);
}
catch (error) {
renderer = resolver;
}
return renderer || DefaultNodeRendererComponent;
}
setNodeRenderers(customRenderers) {
this.nodeRenderers = Object.assign(this.nodeRenderers, customRenderers);
}
setMarkRenderers(customRenderers) {
this.markRenderers = Object.assign(this.markRenderers, customRenderers);
}
}
RendererProviderService.ɵprov = i0.ɵɵdefineInjectable({ factory: function RendererProviderService_Factory() { return new RendererProviderService(); }, token: RendererProviderService, providedIn: "root" });
RendererProviderService.decorators = [
{ type: Injectable, args: [{
providedIn: 'root',
},] }
];
class NgxContentfulRichTextComponent {
constructor(rendererProvider) {
this.rendererProvider = rendererProvider;
}
ngOnInit() {
this.rendererProvider.setNodeRenderers(this.nodeRenderers);
this.rendererProvider.setMarkRenderers(this.markRenderers);
}
ngOnChanges(changes) {
var _a;
if ((_a = changes.document) === null || _a === void 0 ? void 0 : _a.currentValue) {
this.nodes = [changes.document.currentValue];
}
}
}
NgxContentfulRichTextComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-contentful-rich-text',
template: `
<ng-container *ngIf="nodes?.length">
<ng-container *ngFor="let node of nodes">
<ng-container
*ngIf="node.nodeType !== 'text'; else textNode"
ngxNodeRendererHost
[node]="node"
>
</ng-container>
<ng-template #textNode>
<ng-container ngxMarkRendererHost [node]="node"></ng-container>
</ng-template>
</ng-container>
</ng-container>
`,
changeDetection: ChangeDetectionStrategy.OnPush
},] }
];
NgxContentfulRichTextComponent.ctorParameters = () => [
{ type: RendererProviderService }
];
NgxContentfulRichTextComponent.propDecorators = {
document: [{ type: Input }],
nodes: [{ type: Input }],
nodeRenderers: [{ type: Input }],
markRenderers: [{ type: Input }]
};
class TextValueComponent {
}
TextValueComponent.decorators = [
{ type: Component, args: [{
template: '{{ node.value }}',
changeDetection: ChangeDetectionStrategy.OnPush
},] }
];
TextValueComponent.propDecorators = {
node: [{ type: Input }]
};
class ComponentRendererService {
constructor(componentFactoryResolver) {
this.componentFactoryResolver = componentFactoryResolver;
}
render(viewContainerRef, component, node) {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);
componentRef.instance.node = node;
componentRef.changeDetectorRef.detectChanges();
}
}
ComponentRendererService.ɵprov = i0.ɵɵdefineInjectable({ factory: function ComponentRendererService_Factory() { return new ComponentRendererService(i0.ɵɵinject(i0.ComponentFactoryResolver)); }, token: ComponentRendererService, providedIn: "root" });
ComponentRendererService.decorators = [
{ type: Injectable, args: [{
providedIn: 'root',
},] }
];
ComponentRendererService.ctorParameters = () => [
{ type: ComponentFactoryResolver }
];
class MarkRendererHostDirective {
constructor(viewContainerRef, componentRenderer, rendererProvider) {
this.viewContainerRef = viewContainerRef;
this.componentRenderer = componentRenderer;
this.rendererProvider = rendererProvider;
}
ngOnInit() {
let component;
if (isNaN(this.node.markIndex)) {
// Create new object because node object might not be extensible
this.node = Object.assign(Object.assign({}, this.node), { markIndex: 0 });
}
else {
this.node.markIndex += 1;
}
if (this.node.marks.length > this.node.markIndex) {
component = this.rendererProvider.getMarkRenderer(this.node);
}
else {
component = TextValueComponent;
}
this.componentRenderer.render(this.viewContainerRef, component, this.node);
}
}
MarkRendererHostDirective.decorators = [
{ type: Directive, args: [{
selector: '[ngxMarkRendererHost]',
},] }
];
MarkRendererHostDirective.ctorParameters = () => [
{ type: ViewContainerRef },
{ type: ComponentRendererService },
{ type: RendererProviderService }
];
MarkRendererHostDirective.propDecorators = {
node: [{ type: Input }]
};
class NodeRendererHostDirective {
constructor(viewContainerRef, componentRenderer, rendererProvider) {
this.viewContainerRef = viewContainerRef;
this.componentRenderer = componentRenderer;
this.rendererProvider = rendererProvider;
}
ngOnInit() {
const component = this.rendererProvider.getNodeRenderer(this.node);
this.componentRenderer.render(this.viewContainerRef, component, this.node);
}
}
NodeRendererHostDirective.decorators = [
{ type: Directive, args: [{
selector: '[ngxNodeRendererHost]',
},] }
];
NodeRendererHostDirective.ctorParameters = () => [
{ type: ViewContainerRef },
{ type: ComponentRendererService },
{ type: RendererProviderService }
];
NodeRendererHostDirective.propDecorators = {
node: [{ type: Input }]
};
class NgxContentfulRichTextModule {
}
NgxContentfulRichTextModule.decorators = [
{ type: NgModule, args: [{
declarations: [
DefaultMarkRendererComponent,
DefaultNodeRendererComponent,
MarkRendererHostDirective,
NgxContentfulRichTextComponent,
NodeRendererHostDirective,
TextValueComponent,
],
imports: [CommonModule],
exports: [MarkRendererHostDirective, NgxContentfulRichTextComponent],
},] }
];
/*
* Public API Surface of ngx-contentful-rich-text
*/
/**
* Generated bundle index. Do not edit.
*/
export { CHILDREN, DefaultMarkRendererComponent, DefaultNodeRendererComponent, MarkRenderer, MarkRendererHostDirective, NgxContentfulRichTextComponent, NgxContentfulRichTextModule, NodeRenderer, TEXT, RendererProviderService as ɵa, ComponentRendererService as ɵb, NodeRendererHostDirective as ɵc, TextValueComponent as ɵd };
//# sourceMappingURL=ngx-contentful-rich-text.js.map