Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,11 @@ import { DotFormFileEditorComponent } from './dot-form-file-editor.component';

import { DotFileFieldUploadService } from '../../services/upload-file/upload-file.service';

// monacoMock doesn't expose `getLanguages`, which getInfoByLang / the velocity
// registration call. Provide a no-op so the component's Monaco hooks don't throw.
// It also doesn't expose `MarkerSeverity`, which #hasErrorSeverityMarker relies on to
// monacoMock doesn't expose `MarkerSeverity`, which #hasErrorSeverityMarker relies on to
// tell a real syntax error apart from an informational hint/warning marker.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(global as any).monaco = {
...monacoMock,
languages: { ...monacoMock.languages, getLanguages: () => [] },
MarkerSeverity: { Hint: 1, Info: 2, Warning: 4, Error: 8 }
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,12 @@ import { debounceTime, distinctUntilChanged, filter } from 'rxjs/operators';
import {
DotMessagePipe,
DotFieldValidationMessageComponent,
DotFieldRequiredDirective
DotFieldRequiredDirective,
ensureDotVelocityLanguageRegistered
} from '@dotcms/ui';

import { FormFileEditorStore } from './store/form-file-editor.store';

import { dotVelocityLanguageDefinition } from '../../../../custom-languages/velocity-monaco-language';
import { AvailableLanguageMonaco } from '../../../../models/dot-edit-content-field.constant';
import { UPLOAD_TYPE, UploadedFile } from '../../../../models/dot-edit-content-file.model';

type DialogProps = {
Expand Down Expand Up @@ -427,10 +426,9 @@ export class DotFormFileEditorComponent implements OnInit {
onEditorInit(editor: monaco.editor.IStandaloneCodeEditor) {
this.#editorRef = editor;

// Monaco is now loaded. Register the custom Velocity language so .vtl files get
// proper highlighting (its Monarch tokens — keyword.velocity, variable.velocity,
// … — are coloured by the default `vs` theme).
this.#registerVelocityLanguage();
// Monaco is now loaded. Register the shared Velocity language so .vtl files
// highlight the same way here as in every other dotCMS editor.
ensureDotVelocityLanguageRegistered();

// initLoad ran in ngOnInit before Monaco's language registry existed, so the
// detected language fell back to 'text'. Re-detect it (also fixes the upload
Expand All @@ -446,33 +444,4 @@ export class DotFormFileEditorComponent implements OnInit {
monaco.editor.setModelLanguage(model, this.store.file().language);
}
}

/**
* Registers the custom Velocity Monarch language with Monaco, once. Mirrors
* `DotEditContentMonacoEditorControlComponent` so .vtl files highlight the same
* way here. Idempotent: skips registration when another editor already added it.
*/
#registerVelocityLanguage(): void {
if (typeof monaco === 'undefined') {
return;
}

const alreadyRegistered = monaco.languages
.getLanguages()
.some((lang) => lang.id === AvailableLanguageMonaco.Velocity);

if (alreadyRegistered) {
return;
}

monaco.languages.register({
id: AvailableLanguageMonaco.Velocity,
extensions: ['.vtl'],
mimetypes: ['text/x-velocity']
});
monaco.languages.setMonarchTokensProvider(
AvailableLanguageMonaco.Velocity,
dotVelocityLanguageDefinition
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,14 @@ describe('DotEditContentMonacoEditorControlComponent', () => {
expect(component.$monacoOptions()).toEqual(expectedOptions);
});

it('should register Velocity language when Monaco is loaded', () => {
const registerSpy = vi.spyOn(component, 'registerVelocityLanguage');
it('should register the shared Velocity grammar under the id this field uses', () => {
const registerSpy = vi.spyOn(monacoMock.languages, 'register');

spectator.detectChanges();
expect(registerSpy).toHaveBeenCalled();

expect(registerSpy).toHaveBeenCalledWith(
expect.objectContaining({ id: AvailableLanguageMonaco.Velocity })
);
});

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import { ControlContainer, FormControl, ReactiveFormsModule } from '@angular/for
import { PaginatorModule } from 'primeng/paginator';

import { DotCMSContentTypeField } from '@dotcms/dotcms-models';
import { ensureDotVelocityLanguageRegistered } from '@dotcms/ui';

import { dotVelocityLanguageDefinition } from '../../custom-languages/velocity-monaco-language';
import {
isHtml,
isJavascript,
Expand All @@ -37,15 +37,6 @@ import {
} from '../../models/dot-edit-content-field.constant';
import { getFieldVariablesParsed, stringToJson } from '../../utils/functions.util';

interface WindowWithMonaco extends Window {
monaco?: {
languages: {
register: (language: { id: string }) => void;
setMonarchTokensProvider: (id: string, provider: unknown) => void;
};
};
}

/**
* DotEditContentMonacoEditorControl is an Angular component utilizing Monaco Editor.
* It provides a code editing experience with syntax highlighting and advanced features,
Expand Down Expand Up @@ -234,23 +225,11 @@ export class DotEditContentMonacoEditorControlComponent implements OnDestroy {
}

/**
* Registers the Velocity language for the Monaco editor.
* Registers the Velocity language for the Monaco editor: the shared grammar from `@dotcms/ui`,
* under the `velocity` id this field's detection and forced language use.
*/
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
);
} else {
console.warn('Monaco is not available globally');
}
});
this.#ngZone.runOutsideAngular(() => ensureDotVelocityLanguageRegistered());
}

private readonly languageDetectors = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
DotMessageService
} from '@dotcms/data-access';
import { ComponentStatus } from '@dotcms/dotcms-models';
import { DotClipboardUtil } from '@dotcms/ui';
import { DOT_VELOCITY_LANGUAGE_ID, DotClipboardUtil } from '@dotcms/ui';

import { DotVelocityPlaygroundPageComponent } from './dot-velocity-playground-page.component';
import { DotVelocityPlaygroundStore } from './store/dot-velocity-playground.store';
Expand Down Expand Up @@ -225,7 +225,7 @@ describe('DotVelocityPlaygroundPageComponent', () => {
describe('editor options computed signal', () => {
it('exposes velocity language and wrap=on when wrapCode is true', () => {
setup({ wrapCode: vi.fn().mockReturnValue(true) });
expect(spectator.component.$editorOptions().language).toBe('velocity-playground');
expect(spectator.component.$editorOptions().language).toBe(DOT_VELOCITY_LANGUAGE_ID);
expect(spectator.component.$editorOptions().wordWrap).toBe('on');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ import { ComponentStatus } from '@dotcms/dotcms-models';
import {
DOT_MONACO_BASE_OPTIONS,
DOT_MONACO_RAW_OPTIONS,
DOT_VELOCITY_LANGUAGE_ID,
DotClipboardUtil,
DotEmptyContainerComponent,
DotMessagePipe,
DotMonacoRunShortcutEditor,
DotSpinnerComponent,
ensureDotVelocityLanguageRegistered,
getDotMonacoRunShortcutLabel,
PrincipalConfiguration,
registerDotMonacoRunShortcut
Expand All @@ -51,10 +53,6 @@ import {
getDownloadParams,
VELOCITY_HELP_EXAMPLES
} from '../dot-velocity-playground.utils';
import {
ensureVelocityLanguageRegistered,
VELOCITY_LANGUAGE_ID
} from '../monaco/register-velocity';

@Component({
selector: 'dot-velocity-playground-page',
Expand Down Expand Up @@ -104,7 +102,7 @@ export class DotVelocityPlaygroundPageComponent {
// 3. Computed signals — $ prefix
readonly $editorOptions = computed(() => ({
...DOT_MONACO_BASE_OPTIONS,
language: VELOCITY_LANGUAGE_ID,
language: DOT_VELOCITY_LANGUAGE_ID,
wordWrap: this.store.wrapCode() ? 'on' : 'off'
}));

Expand Down Expand Up @@ -182,7 +180,7 @@ export class DotVelocityPlaygroundPageComponent {
filter((isLoaded) => isLoaded),
take(1)
)
.subscribe(() => ensureVelocityLanguageRegistered());
.subscribe(() => ensureDotVelocityLanguageRegistered());
}

// 6. Public methods
Expand All @@ -193,7 +191,7 @@ export class DotVelocityPlaygroundPageComponent {
* @param editor the Monaco editor instance emitted by `ngx-monaco-editor`
*/
onEditorInit(editor: DotMonacoRunShortcutEditor): void {
ensureVelocityLanguageRegistered();
ensureDotVelocityLanguageRegistered();
registerDotMonacoRunShortcut(editor, () => this.onRun(), {
label: this.#messageService.get('velocityPlayground.action.run')
});
Expand Down
Loading
Loading