mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-09-10 14:11:42 +00:00
AAE-37906 Extract rich text parsing service (#11164)
* AAE-37906 Extract rich text parsing service * AAE-37906 Add unit tests * AAE-37906 Remove unused import * AAE-37906 Fix units
This commit is contained in:
@@ -18,12 +18,14 @@
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DisplayRichTextWidgetComponent } from './display-rich-text.widget';
|
||||
import { DisplayRichTextWidgetComponent, RICH_TEXT_PARSER_TOKEN } from './display-rich-text.widget';
|
||||
import { RichTextParserService } from '../../../services/rich-text-parser.service';
|
||||
|
||||
describe('DisplayRichTextWidgetComponent', () => {
|
||||
let widget: DisplayRichTextWidgetComponent;
|
||||
let fixture: ComponentFixture<DisplayRichTextWidgetComponent>;
|
||||
let debugEl: DebugElement;
|
||||
let mockRichTextParserService: jasmine.SpyObj<RichTextParserService>;
|
||||
|
||||
const cssSelector = {
|
||||
parsedHTML: '.adf-display-rich-text-widget-parsed-html'
|
||||
@@ -79,8 +81,14 @@ describe('DisplayRichTextWidgetComponent', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
mockRichTextParserService = jasmine.createSpyObj('RichTextParserService', ['parse']);
|
||||
mockRichTextParserService.parse.and.returnValue(
|
||||
'<h1>Editor.js</h1><p class="ce-tune-alignment--left">Display some <font color="#ff1300">formatted</font> <mark class="cdx-marker">text</mark></p>'
|
||||
);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [DisplayRichTextWidgetComponent]
|
||||
imports: [DisplayRichTextWidgetComponent],
|
||||
providers: [{ provide: RICH_TEXT_PARSER_TOKEN, useValue: mockRichTextParserService }]
|
||||
});
|
||||
fixture = TestBed.createComponent(DisplayRichTextWidgetComponent);
|
||||
widget = fixture.componentInstance;
|
||||
@@ -88,6 +96,13 @@ describe('DisplayRichTextWidgetComponent', () => {
|
||||
widget.field = fakeFormField;
|
||||
});
|
||||
|
||||
it('should call RichTextParserService.parse() method', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(mockRichTextParserService.parse).toHaveBeenCalledWith(fakeFormField.value);
|
||||
expect(mockRichTextParserService.parse).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should parse editorjs data to html', async () => {
|
||||
const expectedHtml =
|
||||
'<h1>Editor.js</h1><p class="ce-tune-alignment--left">Display some <font color="#ff1300">formatted</font> <mark class="cdx-marker">text</mark></p>';
|
||||
|
@@ -17,10 +17,14 @@
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
import { Component, OnInit, SecurityContext, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, inject, InjectionToken, OnInit, SecurityContext, ViewEncapsulation } from '@angular/core';
|
||||
import { WidgetComponent, FormService } from '@alfresco/adf-core';
|
||||
import edjsHTML from 'editorjs-html';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { RichTextParserService } from '../../../services/rich-text-parser.service';
|
||||
|
||||
export const RICH_TEXT_PARSER_TOKEN = new InjectionToken<RichTextParserService>('RichTextParserService', {
|
||||
factory: () => new RichTextParserService()
|
||||
});
|
||||
|
||||
@Component({
|
||||
selector: 'display-rich-text',
|
||||
@@ -40,39 +44,22 @@ import { DomSanitizer } from '@angular/platform-browser';
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class DisplayRichTextWidgetComponent extends WidgetComponent implements OnInit {
|
||||
parsedHTML: any;
|
||||
parsedHTML: string | Error;
|
||||
|
||||
private static readonly CUSTOM_PARSER = {
|
||||
header: (block: any): string => {
|
||||
const paragraphAlign = block.data.alignment || block.data.align || block.tunes?.anyTuneName?.alignment;
|
||||
if (typeof paragraphAlign !== 'undefined' && ['left', 'right', 'center'].includes(paragraphAlign)) {
|
||||
return `<h${block.data.level} class="ce-tune-alignment--${paragraphAlign}">${block.data.text}</h${block.data.level}>`;
|
||||
} else {
|
||||
return `<h${block.data.level}>${block.data.text}</h${block.data.level}>`;
|
||||
}
|
||||
},
|
||||
paragraph: (block: any): string => {
|
||||
const paragraphAlign = block.data.alignment || block.data.align || block.tunes?.anyTuneName?.alignment;
|
||||
private readonly richTextParserService = inject(RICH_TEXT_PARSER_TOKEN);
|
||||
private readonly sanitizer = inject(DomSanitizer);
|
||||
|
||||
if (typeof paragraphAlign !== 'undefined' && ['left', 'right', 'center', 'justify'].includes(paragraphAlign)) {
|
||||
return `<p class="ce-tune-alignment--${paragraphAlign}">${block.data.text}</p>`;
|
||||
} else {
|
||||
return `<p>${block.data.text}</p>`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
constructor(public formService: FormService, private readonly sanitizer: DomSanitizer) {
|
||||
constructor(formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.parsedHTML = edjsHTML(DisplayRichTextWidgetComponent.CUSTOM_PARSER, { strict: true }).parse(this.field.value);
|
||||
this.parsedHTML = this.richTextParserService.parse(this.field.value);
|
||||
|
||||
if (!(this.parsedHTML instanceof Error)) {
|
||||
this.sanitizeHtmlContent();
|
||||
} else {
|
||||
if (this.parsedHTML instanceof Error) {
|
||||
throw this.parsedHTML;
|
||||
} else {
|
||||
this.sanitizeHtmlContent();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,32 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { RichTextParserService } from './rich-text-parser.service';
|
||||
|
||||
describe('RichTextParserService', () => {
|
||||
it('should test CUSTOM_PARSER.header method works correctly', () => {
|
||||
const block = { data: { text: 'Test Header', level: 2, alignment: 'center' } };
|
||||
const result = (RichTextParserService as any).CUSTOM_PARSER.header(block);
|
||||
expect(result).toBe('<h2 class="ce-tune-alignment--center">Test Header</h2>');
|
||||
});
|
||||
|
||||
it('should test CUSTOM_PARSER.paragraph method works correctly', () => {
|
||||
const block = { data: { text: 'Test paragraph text', alignment: 'justify' } };
|
||||
const result = (RichTextParserService as any).CUSTOM_PARSER.paragraph(block);
|
||||
expect(result).toBe('<p class="ce-tune-alignment--justify">Test paragraph text</p>');
|
||||
});
|
||||
});
|
@@ -0,0 +1,56 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import edjsHTML from 'editorjs-html';
|
||||
|
||||
export interface OutputData {
|
||||
version?: string;
|
||||
time?: number;
|
||||
blocks: any[];
|
||||
}
|
||||
|
||||
export class RichTextParserService {
|
||||
private static readonly CUSTOM_PARSER = {
|
||||
header: (block: any): string => {
|
||||
if (!block.data || !block.data.text || !block.data.level) {
|
||||
return '';
|
||||
}
|
||||
const paragraphAlign = block.data.alignment || block.data.align || block.tunes?.anyTuneName?.alignment;
|
||||
if (typeof paragraphAlign !== 'undefined' && ['left', 'right', 'center'].includes(paragraphAlign)) {
|
||||
return `<h${block.data.level} class="ce-tune-alignment--${paragraphAlign}">${block.data.text}</h${block.data.level}>`;
|
||||
} else {
|
||||
return `<h${block.data.level}>${block.data.text}</h${block.data.level}>`;
|
||||
}
|
||||
},
|
||||
paragraph: (block: any): string => {
|
||||
if (!block.data || !block.data.text) {
|
||||
return '';
|
||||
}
|
||||
const paragraphAlign = block.data.alignment || block.data.align || block.tunes?.anyTuneName?.alignment;
|
||||
|
||||
if (typeof paragraphAlign !== 'undefined' && ['left', 'right', 'center', 'justify'].includes(paragraphAlign)) {
|
||||
return `<p class="ce-tune-alignment--${paragraphAlign}">${block.data.text}</p>`;
|
||||
} else {
|
||||
return `<p>${block.data.text}</p>`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
parse(richText: OutputData): string | Error {
|
||||
return edjsHTML(RichTextParserService.CUSTOM_PARSER, { strict: true }).parse(richText);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user