Skip to content

Commit

Permalink
feat(edit-content) fix tests and lint
Browse files Browse the repository at this point in the history
  • Loading branch information
oidacra committed Oct 23, 2024
1 parent e94fa66 commit 5aeb6ac
Show file tree
Hide file tree
Showing 6 changed files with 271 additions and 199 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { WYSIWYG_MOCK } from '../../mocks/dot-edit-content-wysiwyg-field.mock';

describe('DotWysiwygMonacoComponent', () => {
let spectator: Spectator<DotWysiwygMonacoComponent>;
let component: DotWysiwygMonacoComponent;

const createComponent = createComponentFactory({
component: DotWysiwygMonacoComponent,
Expand All @@ -37,24 +38,27 @@ describe('DotWysiwygMonacoComponent', () => {
field: WYSIWYG_MOCK
} as unknown
});
});

it('should set default language', () => {
expect(spectator.component.$language()).toBe(DEFAULT_MONACO_LANGUAGE);
component = spectator.component;
});

it('should set custom language', () => {
const customLanguage = 'javascript';
spectator.setInput('language', customLanguage);
expect(spectator.component.$language()).toBe(customLanguage);
it('should set default language', () => {
expect(component.$language()).toBe(DEFAULT_MONACO_LANGUAGE);
});

it('should generate correct Monaco options', () => {
it('should generate correct Monaco options', async () => {
const expectedOptions = {
...DEFAULT_WYSIWYG_FIELD_MONACO_CONFIG,
language: DEFAULT_MONACO_LANGUAGE
language: 'plaintext' // due the auto detect language is plaintext
};
expect(spectator.component.$monacoOptions()).toEqual(expectedOptions);

// Wait for any potential asynchronous operations to complete
await spectator.fixture.whenStable();

// Force change detection
spectator.detectChanges();

expect(component.$monacoOptions()).toEqual(expectedOptions);
});

it('should parse custom props from field variables', () => {
Expand All @@ -73,8 +77,15 @@ describe('DotWysiwygMonacoComponent', () => {
const expectedOptions = {
...DEFAULT_WYSIWYG_FIELD_MONACO_CONFIG,
...customProps,
language: DEFAULT_MONACO_LANGUAGE
language: 'plaintext' // due the auto detect language is plaintext
};
expect(spectator.component.$monacoOptions()).toEqual(expectedOptions);
expect(component.$monacoOptions()).toEqual(expectedOptions);
});

it('should register Velocity language when Monaco is loaded', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const registerSpy = jest.spyOn(component as any, 'registerVelocityLanguage');
component.ngOnInit();
expect(registerSpy).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -73,33 +73,6 @@ export class DotWysiwygMonacoComponent implements OnDestroy, OnInit {
#ngZone: NgZone = inject(NgZone);
#destroyRef = inject(DestroyRef);

ngOnInit() {
this.#monacoLoaderService.isMonacoLoaded$
.pipe(takeUntilDestroyed(this.#destroyRef))
.subscribe((isLoaded) => {
if (isLoaded) {
this.registerVelocityLanguage();
}
});
}
private registerVelocityLanguage() {
this.#ngZone.runOutsideAngular(() => {
const windowWithMonaco = window as WindowWithMonaco;
if (windowWithMonaco.monaco) {
windowWithMonaco.monaco.languages.register({
id: AvailableLanguageMonaco.Velocity
});
windowWithMonaco.monaco.languages.setMonarchTokensProvider(
AvailableLanguageMonaco.Velocity,
dotVelocityLanguageDefinition
);
console.warn('Velocity language registered successfully');
} else {
console.warn('Monaco is not available globally');
}
});
}

/**
* Holds a reference to the MonacoEditorComponent.
*/
Expand Down Expand Up @@ -143,32 +116,29 @@ export class DotWysiwygMonacoComponent implements OnDestroy, OnInit {
};
});

/**
* A signal that holds the current language of the Monaco editor.
* It starts with the default language, which is 'plaintext'.
*/
$language = signal<string>(DEFAULT_MONACO_LANGUAGE);

private readonly languageDetectors = {
[AvailableLanguageMonaco.Velocity]: isVelocity,
[AvailableLanguageMonaco.Javascript]: isJavascript,
[AvailableLanguageMonaco.Html]: isHtml,
[AvailableLanguageMonaco.Markdown]: isMarkdown
};

/**
* Detects the language of the content in the Monaco editor and sets the appropriate language.
* A disposable reference that manages the lifecycle of content change listeners.
* It starts as null and can be assigned a disposable object that will be used
* to clean up event listeners or other resources related to content changes.
*
* @type {monaco.IDisposable | null}
*/
private detectLanguage() {
const content = this.#editor.getValue().trim();

if (!content) {
this.setLanguage(AvailableLanguageMonaco.PlainText);

return;
}

const detectedLanguage = Object.entries(this.languageDetectors).find(([, detector]) =>
detector(content)
)?.[0] as AvailableLanguageMonaco;
#contentChangeDisposable: monaco.IDisposable | null = null;

this.setLanguage(detectedLanguage || AvailableLanguageMonaco.PlainText);
ngOnInit() {
this.#monacoLoaderService.isMonacoLoaded$
.pipe(takeUntilDestroyed(this.#destroyRef))
.subscribe((isLoaded) => {
if (isLoaded) {
this.registerVelocityLanguage();
}
});
}

/**
Expand All @@ -191,15 +161,6 @@ export class DotWysiwygMonacoComponent implements OnDestroy, OnInit {
}
}

/**
* A disposable reference that manages the lifecycle of content change listeners.
* It starts as null and can be assigned a disposable object that will be used
* to clean up event listeners or other resources related to content changes.
*
* @type {monaco.IDisposable | null}
*/
#contentChangeDisposable: monaco.IDisposable | null = null;

/**
* Initializes the editor by setting up the editor reference,
* processing the editor content, and setting up a listener for content changes.
Expand All @@ -213,19 +174,6 @@ export class DotWysiwygMonacoComponent implements OnDestroy, OnInit {
this.setupContentChangeListener();
}

private processEditorContent() {
if (this.#editor) {
const currentContent = this.#editor.getValue();

const processedContent = this.removeWysiwygComment(currentContent);
if (currentContent !== processedContent) {
this.#editor.setValue(processedContent);
}

this.detectLanguage();
}
}

ngOnDestroy() {
try {
if (this.#contentChangeDisposable) {
Expand All @@ -245,6 +193,19 @@ export class DotWysiwygMonacoComponent implements OnDestroy, OnInit {
}
}

private processEditorContent() {
if (this.#editor) {
const currentContent = this.#editor.getValue();

const processedContent = this.removeWysiwygComment(currentContent);
if (currentContent !== processedContent) {
this.#editor.setValue(processedContent);
}

this.detectLanguage();
}
}

private removeEditor() {
this.#editor.dispose();
this.#editor = null;
Expand Down Expand Up @@ -281,4 +242,51 @@ export class DotWysiwygMonacoComponent implements OnDestroy, OnInit {
private setLanguage(language: string) {
this.$language.set(language);
}

/**
* Registers the Velocity language for the Monaco editor.
*/
private registerVelocityLanguage() {
this.#ngZone.runOutsideAngular(() => {
const windowWithMonaco = window as WindowWithMonaco;
if (windowWithMonaco.monaco) {
windowWithMonaco.monaco.languages.register({
id: AvailableLanguageMonaco.Velocity
});
windowWithMonaco.monaco.languages.setMonarchTokensProvider(
AvailableLanguageMonaco.Velocity,
dotVelocityLanguageDefinition
);
console.warn('Velocity language registered successfully');
} else {
console.warn('Monaco is not available globally');
}
});
}

private readonly languageDetectors = {
[AvailableLanguageMonaco.Velocity]: isVelocity,
[AvailableLanguageMonaco.Javascript]: isJavascript,
[AvailableLanguageMonaco.Html]: isHtml,
[AvailableLanguageMonaco.Markdown]: isMarkdown
};

/**
* Detects the language of the content in the Monaco editor and sets the appropriate language.
*/
private detectLanguage() {
const content = this.#editor.getValue().trim();

if (!content) {
this.setLanguage(AvailableLanguageMonaco.PlainText);

return;
}

const detectedLanguage = Object.entries(this.languageDetectors).find(([, detector]) =>
detector(content)
)?.[0] as AvailableLanguageMonaco;

this.setLanguage(detectedLanguage || AvailableLanguageMonaco.PlainText);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
top: 50%;
transform: translateY(-50%);
pointer-events: none;
color: $color-palette-primary-500;
}

::ng-deep {
Expand Down
Loading

0 comments on commit 5aeb6ac

Please sign in to comment.