Commit 8df2811c authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch '333930-renamed-editor-lite' into 'master'

Renamed EditorLite to SourceEditor

See merge request gitlab-org/gitlab!64302
parents a16e12d9 849b4aac
<script> <script>
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { initEditorLite } from '~/blob/utils'; import { initSourceEditor } from '~/blob/utils';
import { SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance/constants'; import { SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance/constants';
import eventHub from './eventhub'; import eventHub from './eventhub';
...@@ -36,7 +36,7 @@ export default { ...@@ -36,7 +36,7 @@ export default {
}, },
}, },
mounted() { mounted() {
this.editor = initEditorLite({ this.editor = initSourceEditor({
el: this.$refs.editor, el: this.$refs.editor,
blobPath: this.fileName, blobPath: this.fileName,
blobContent: this.value, blobContent: this.value,
......
import Editor from '~/editor/editor_lite'; import Editor from '~/editor/source_editor';
export function initEditorLite({ el, ...args }) { export function initSourceEditor({ el, ...args }) {
const editor = new Editor({ const editor = new Editor({
scrollbar: { scrollbar: {
alwaysConsumeMouseWheel: false, alwaysConsumeMouseWheel: false,
......
import $ from 'jquery'; import $ from 'jquery';
import EditorLite from '~/editor/editor_lite'; import { FileTemplateExtension } from '~/editor/extensions/source_editor_file_template_ext';
import { FileTemplateExtension } from '~/editor/extensions/editor_file_template_ext'; import SourceEditor from '~/editor/source_editor';
import createFlash from '~/flash'; import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { addEditorMarkdownListeners } from '~/lib/utils/text_markdown'; import { addEditorMarkdownListeners } from '~/lib/utils/text_markdown';
...@@ -16,7 +16,7 @@ export default class EditBlob { ...@@ -16,7 +16,7 @@ export default class EditBlob {
this.configureMonacoEditor(); this.configureMonacoEditor();
if (this.options.isMarkdown) { if (this.options.isMarkdown) {
import('~/editor/extensions/editor_markdown_ext') import('~/editor/extensions/source_editor_markdown_ext')
.then(({ EditorMarkdownExtension: MarkdownExtension } = {}) => { .then(({ EditorMarkdownExtension: MarkdownExtension } = {}) => {
this.editor.use(new MarkdownExtension()); this.editor.use(new MarkdownExtension());
addEditorMarkdownListeners(this.editor); addEditorMarkdownListeners(this.editor);
...@@ -40,7 +40,7 @@ export default class EditBlob { ...@@ -40,7 +40,7 @@ export default class EditBlob {
const fileContentEl = document.getElementById('file-content'); const fileContentEl = document.getElementById('file-content');
const form = document.querySelector('.js-edit-blob-form'); const form = document.querySelector('.js-edit-blob-form');
const rootEditor = new EditorLite(); const rootEditor = new SourceEditor();
this.editor = rootEditor.createInstance({ this.editor = rootEditor.createInstance({
el: editorEl, el: editorEl,
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import { GlButton, GlFormCheckbox, GlIcon, GlLink, GlAlert } from '@gitlab/ui'; import { GlButton, GlFormCheckbox, GlIcon, GlLink, GlAlert } from '@gitlab/ui';
import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue'; import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue';
import lintCiMutation from '~/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql'; import lintCiMutation from '~/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql';
import EditorLite from '~/vue_shared/components/editor_lite.vue'; import SourceEditor from '~/vue_shared/components/source_editor.vue';
export default { export default {
components: { components: {
...@@ -12,7 +12,7 @@ export default { ...@@ -12,7 +12,7 @@ export default {
GlLink, GlLink,
GlAlert, GlAlert,
CiLintResults, CiLintResults,
EditorLite, SourceEditor,
}, },
props: { props: {
endpoint: { endpoint: {
...@@ -93,7 +93,7 @@ export default { ...@@ -93,7 +93,7 @@ export default {
<div class="js-file-title file-title clearfix"> <div class="js-file-title file-title clearfix">
{{ __('Contents of .gitlab-ci.yml') }} {{ __('Contents of .gitlab-ci.yml') }}
</div> </div>
<editor-lite v-model="content" file-name="*.yml" /> <source-editor v-model="content" file-name="*.yml" />
</div> </div>
</div> </div>
......
import { __ } from '~/locale'; import { __ } from '~/locale';
export const EDITOR_LITE_INSTANCE_ERROR_NO_EL = __( export const SOURCE_EDITOR_INSTANCE_ERROR_NO_EL = __(
'"el" parameter is required for createInstance()', '"el" parameter is required for createInstance()',
); );
...@@ -8,7 +8,7 @@ export const URI_PREFIX = 'gitlab'; ...@@ -8,7 +8,7 @@ export const URI_PREFIX = 'gitlab';
export const CONTENT_UPDATE_DEBOUNCE = 250; export const CONTENT_UPDATE_DEBOUNCE = 250;
export const ERROR_INSTANCE_REQUIRED_FOR_EXTENSION = __( export const ERROR_INSTANCE_REQUIRED_FOR_EXTENSION = __(
'Editor Lite instance is required to set up an extension.', 'Source Editor instance is required to set up an extension.',
); );
export const EDITOR_READY_EVENT = 'editor-ready'; export const EDITOR_READY_EVENT = 'editor-ready';
......
import Api from '~/api'; import Api from '~/api';
import { registerSchema } from '~/ide/utils'; import { registerSchema } from '~/ide/utils';
import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '../constants'; import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '../constants';
import { EditorLiteExtension } from './editor_lite_extension_base'; import { SourceEditorExtension } from './source_editor_extension_base';
export class CiSchemaExtension extends EditorLiteExtension { export class CiSchemaExtension extends SourceEditorExtension {
/** /**
* Registers a syntax schema to the editor based on project * Registers a syntax schema to the editor based on project
* identifier and commit. * identifier and commit.
......
...@@ -16,15 +16,15 @@ const createAnchor = (href) => { ...@@ -16,15 +16,15 @@ const createAnchor = (href) => {
return fragment; return fragment;
}; };
export class EditorLiteExtension { export class SourceEditorExtension {
constructor({ instance, ...options } = {}) { constructor({ instance, ...options } = {}) {
if (instance) { if (instance) {
Object.assign(instance, options); Object.assign(instance, options);
EditorLiteExtension.highlightLines(instance); SourceEditorExtension.highlightLines(instance);
if (instance.getEditorType && instance.getEditorType() === EDITOR_TYPE_CODE) { if (instance.getEditorType && instance.getEditorType() === EDITOR_TYPE_CODE) {
EditorLiteExtension.setupLineLinking(instance); SourceEditorExtension.setupLineLinking(instance);
} }
EditorLiteExtension.deferRerender(instance); SourceEditorExtension.deferRerender(instance);
} else if (Object.entries(options).length) { } else if (Object.entries(options).length) {
throw new Error(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION); throw new Error(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION);
} }
...@@ -79,7 +79,7 @@ export class EditorLiteExtension { ...@@ -79,7 +79,7 @@ export class EditorLiteExtension {
} }
static setupLineLinking(instance) { static setupLineLinking(instance) {
instance.onMouseMove(EditorLiteExtension.onMouseMoveHandler); instance.onMouseMove(SourceEditorExtension.onMouseMoveHandler);
instance.onMouseDown((e) => { instance.onMouseDown((e) => {
const isCorrectAnchor = e.target.element.classList.contains('link-anchor'); const isCorrectAnchor = e.target.element.classList.contains('link-anchor');
if (!isCorrectAnchor) { if (!isCorrectAnchor) {
......
import { Position } from 'monaco-editor'; import { Position } from 'monaco-editor';
import { EditorLiteExtension } from './editor_lite_extension_base'; import { SourceEditorExtension } from './source_editor_extension_base';
export class FileTemplateExtension extends EditorLiteExtension { export class FileTemplateExtension extends SourceEditorExtension {
navigateFileStart() { navigateFileStart() {
this.setPosition(new Position(1, 1)); this.setPosition(new Position(1, 1));
} }
......
import { EditorLiteExtension } from './editor_lite_extension_base'; import { SourceEditorExtension } from './source_editor_extension_base';
export class EditorMarkdownExtension extends EditorLiteExtension { export class EditorMarkdownExtension extends SourceEditorExtension {
getSelectedText(selection = this.getSelection()) { getSelectedText(selection = this.getSelection()) {
const { startLineNumber, endLineNumber, startColumn, endColumn } = selection; const { startLineNumber, endLineNumber, startColumn, endColumn } = selection;
const valArray = this.getValue().split('\n'); const valArray = this.getValue().split('\n');
......
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { KeyCode, KeyMod, Range } from 'monaco-editor'; import { KeyCode, KeyMod, Range } from 'monaco-editor';
import { EDITOR_TYPE_DIFF } from '~/editor/constants'; import { EDITOR_TYPE_DIFF } from '~/editor/constants';
import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base'; import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
import Disposable from '~/ide/lib/common/disposable'; import Disposable from '~/ide/lib/common/disposable';
import { editorOptions } from '~/ide/lib/editor_options'; import { editorOptions } from '~/ide/lib/editor_options';
import keymap from '~/ide/lib/keymap.json'; import keymap from '~/ide/lib/keymap.json';
...@@ -12,7 +12,7 @@ const isDiffEditorType = (instance) => { ...@@ -12,7 +12,7 @@ const isDiffEditorType = (instance) => {
export const UPDATE_DIMENSIONS_DELAY = 200; export const UPDATE_DIMENSIONS_DELAY = 200;
export class EditorWebIdeExtension extends EditorLiteExtension { export class EditorWebIdeExtension extends SourceEditorExtension {
constructor({ instance, modelManager, ...options } = {}) { constructor({ instance, modelManager, ...options } = {}) {
super({ super({
instance, instance,
......
...@@ -6,23 +6,23 @@ import { registerLanguages } from '~/ide/utils'; ...@@ -6,23 +6,23 @@ import { registerLanguages } from '~/ide/utils';
import { joinPaths } from '~/lib/utils/url_utility'; import { joinPaths } from '~/lib/utils/url_utility';
import { uuids } from '~/lib/utils/uuids'; import { uuids } from '~/lib/utils/uuids';
import { import {
EDITOR_LITE_INSTANCE_ERROR_NO_EL, SOURCE_EDITOR_INSTANCE_ERROR_NO_EL,
URI_PREFIX, URI_PREFIX,
EDITOR_READY_EVENT, EDITOR_READY_EVENT,
EDITOR_TYPE_DIFF, EDITOR_TYPE_DIFF,
} from './constants'; } from './constants';
import { clearDomElement } from './utils'; import { clearDomElement } from './utils';
export default class EditorLite { export default class SourceEditor {
constructor(options = {}) { constructor(options = {}) {
this.instances = []; this.instances = [];
this.options = { this.options = {
extraEditorClassName: 'gl-editor-lite', extraEditorClassName: 'gl-source-editor',
...defaultEditorOptions, ...defaultEditorOptions,
...options, ...options,
}; };
EditorLite.setupMonacoTheme(); SourceEditor.setupMonacoTheme();
registerLanguages(...languages); registerLanguages(...languages);
} }
...@@ -56,7 +56,7 @@ export default class EditorLite { ...@@ -56,7 +56,7 @@ export default class EditorLite {
extensionsArray.forEach((ext) => { extensionsArray.forEach((ext) => {
const prefix = ext.includes('/') ? '' : 'editor/'; const prefix = ext.includes('/') ? '' : 'editor/';
const trimmedExt = ext.replace(/^\//, '').trim(); const trimmedExt = ext.replace(/^\//, '').trim();
EditorLite.pushToImportsArray(promises, `~/${prefix}${trimmedExt}`); SourceEditor.pushToImportsArray(promises, `~/${prefix}${trimmedExt}`);
}); });
return Promise.all(promises); return Promise.all(promises);
...@@ -77,7 +77,7 @@ export default class EditorLite { ...@@ -77,7 +77,7 @@ export default class EditorLite {
static prepareInstance(el) { static prepareInstance(el) {
if (!el) { if (!el) {
throw new Error(EDITOR_LITE_INSTANCE_ERROR_NO_EL); throw new Error(SOURCE_EDITOR_INSTANCE_ERROR_NO_EL);
} }
clearDomElement(el); clearDomElement(el);
...@@ -88,7 +88,7 @@ export default class EditorLite { ...@@ -88,7 +88,7 @@ export default class EditorLite {
} }
static manageDefaultExtensions(instance, el, extensions) { static manageDefaultExtensions(instance, el, extensions) {
EditorLite.loadExtensions(extensions, instance) SourceEditor.loadExtensions(extensions, instance)
.then((modules) => { .then((modules) => {
if (modules) { if (modules) {
modules.forEach((module) => { modules.forEach((module) => {
...@@ -126,7 +126,7 @@ export default class EditorLite { ...@@ -126,7 +126,7 @@ export default class EditorLite {
const diffModel = { const diffModel = {
original: monacoEditor.createModel( original: monacoEditor.createModel(
blobOriginalContent, blobOriginalContent,
EditorLite.getModelLanguage(model.uri.path), SourceEditor.getModelLanguage(model.uri.path),
), ),
modified: model, modified: model,
}; };
...@@ -135,18 +135,18 @@ export default class EditorLite { ...@@ -135,18 +135,18 @@ export default class EditorLite {
} }
static convertMonacoToELInstance = (inst) => { static convertMonacoToELInstance = (inst) => {
const editorLiteInstanceAPI = { const sourceEditorInstanceAPI = {
updateModelLanguage: (path) => { updateModelLanguage: (path) => {
return EditorLite.instanceUpdateLanguage(inst, path); return SourceEditor.instanceUpdateLanguage(inst, path);
}, },
use: (exts = []) => { use: (exts = []) => {
return EditorLite.instanceApplyExtension(inst, exts); return SourceEditor.instanceApplyExtension(inst, exts);
}, },
}; };
const handler = { const handler = {
get(target, prop, receiver) { get(target, prop, receiver) {
if (Reflect.has(editorLiteInstanceAPI, prop)) { if (Reflect.has(sourceEditorInstanceAPI, prop)) {
return editorLiteInstanceAPI[prop]; return sourceEditorInstanceAPI[prop];
} }
return Reflect.get(target, prop, receiver); return Reflect.get(target, prop, receiver);
}, },
...@@ -155,7 +155,7 @@ export default class EditorLite { ...@@ -155,7 +155,7 @@ export default class EditorLite {
}; };
static instanceUpdateLanguage(inst, path) { static instanceUpdateLanguage(inst, path) {
const lang = EditorLite.getModelLanguage(path); const lang = SourceEditor.getModelLanguage(path);
const model = inst.getModel(); const model = inst.getModel();
return monacoEditor.setModelLanguage(model, lang); return monacoEditor.setModelLanguage(model, lang);
} }
...@@ -163,7 +163,7 @@ export default class EditorLite { ...@@ -163,7 +163,7 @@ export default class EditorLite {
static instanceApplyExtension(inst, exts = []) { static instanceApplyExtension(inst, exts = []) {
const extensions = [].concat(exts); const extensions = [].concat(exts);
extensions.forEach((extension) => { extensions.forEach((extension) => {
EditorLite.mixIntoInstance(extension, inst); SourceEditor.mixIntoInstance(extension, inst);
}); });
return inst; return inst;
} }
...@@ -210,10 +210,10 @@ export default class EditorLite { ...@@ -210,10 +210,10 @@ export default class EditorLite {
isDiff = false, isDiff = false,
...instanceOptions ...instanceOptions
} = {}) { } = {}) {
EditorLite.prepareInstance(el); SourceEditor.prepareInstance(el);
const createEditorFn = isDiff ? 'createDiffEditor' : 'create'; const createEditorFn = isDiff ? 'createDiffEditor' : 'create';
const instance = EditorLite.convertMonacoToELInstance( const instance = SourceEditor.convertMonacoToELInstance(
monacoEditor[createEditorFn].call(this, el, { monacoEditor[createEditorFn].call(this, el, {
...this.options, ...this.options,
...instanceOptions, ...instanceOptions,
...@@ -222,7 +222,7 @@ export default class EditorLite { ...@@ -222,7 +222,7 @@ export default class EditorLite {
let model; let model;
if (instanceOptions.model !== null) { if (instanceOptions.model !== null) {
model = EditorLite.createEditorModel({ model = SourceEditor.createEditorModel({
blobGlobalId, blobGlobalId,
blobOriginalContent, blobOriginalContent,
blobPath, blobPath,
...@@ -233,11 +233,11 @@ export default class EditorLite { ...@@ -233,11 +233,11 @@ export default class EditorLite {
} }
instance.onDidDispose(() => { instance.onDidDispose(() => {
EditorLite.instanceRemoveFromRegistry(this, instance); SourceEditor.instanceRemoveFromRegistry(this, instance);
EditorLite.instanceDisposeModels(this, instance, model); SourceEditor.instanceDisposeModels(this, instance, model);
}); });
EditorLite.manageDefaultExtensions(instance, el, extensions); SourceEditor.manageDefaultExtensions(instance, el, extensions);
this.instances.push(instance); this.instances.push(instance);
return instance; return instance;
......
...@@ -6,8 +6,8 @@ import { ...@@ -6,8 +6,8 @@ import {
EDITOR_CODE_INSTANCE_FN, EDITOR_CODE_INSTANCE_FN,
EDITOR_DIFF_INSTANCE_FN, EDITOR_DIFF_INSTANCE_FN,
} from '~/editor/constants'; } from '~/editor/constants';
import EditorLite from '~/editor/editor_lite'; import { EditorWebIdeExtension } from '~/editor/extensions/source_editor_webide_ext';
import { EditorWebIdeExtension } from '~/editor/extensions/editor_lite_webide_ext'; import SourceEditor from '~/editor/source_editor';
import createFlash from '~/flash'; import createFlash from '~/flash';
import ModelManager from '~/ide/lib/common/model_manager'; import ModelManager from '~/ide/lib/common/model_manager';
import { defaultDiffEditorOptions, defaultEditorOptions } from '~/ide/lib/editor_options'; import { defaultDiffEditorOptions, defaultEditorOptions } from '~/ide/lib/editor_options';
...@@ -216,7 +216,7 @@ export default { ...@@ -216,7 +216,7 @@ export default {
}, },
mounted() { mounted() {
if (!this.globalEditor) { if (!this.globalEditor) {
this.globalEditor = new EditorLite(); this.globalEditor = new SourceEditor();
} }
this.initEditor(); this.initEditor();
......
...@@ -50,13 +50,13 @@ export default { ...@@ -50,13 +50,13 @@ export default {
methods: { methods: {
...mapActions(['setFileResolveMode', 'setPromptConfirmationState', 'updateFile']), ...mapActions(['setFileResolveMode', 'setPromptConfirmationState', 'updateFile']),
loadEditor() { loadEditor() {
const EditorPromise = import(/* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite'); const EditorPromise = import(/* webpackChunkName: 'SourceEditor' */ '~/editor/source_editor');
const DataPromise = axios.get(this.file.content_path); const DataPromise = axios.get(this.file.content_path);
Promise.all([EditorPromise, DataPromise]) Promise.all([EditorPromise, DataPromise])
.then( .then(
([ ([
{ default: EditorLite }, { default: SourceEditor },
{ {
data: { content, new_path: path }, data: { content, new_path: path },
}, },
...@@ -66,7 +66,7 @@ export default { ...@@ -66,7 +66,7 @@ export default {
this.originalContent = content; this.originalContent = content;
this.fileLoaded = true; this.fileLoaded = true;
this.editor = new EditorLite().createInstance({ this.editor = new SourceEditor().createInstance({
el: contentEl, el: contentEl,
blobPath: path, blobPath: path,
blobContent: content, blobContent: content,
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
import { GlIcon } from '@gitlab/ui'; import { GlIcon } from '@gitlab/ui';
import { uniqueId } from 'lodash'; import { uniqueId } from 'lodash';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import EditorLite from '~/vue_shared/components/editor_lite.vue'; import SourceEditor from '~/vue_shared/components/source_editor.vue';
export default { export default {
i18n: { i18n: {
viewOnlyMessage: s__('Pipelines|Merged YAML is view only'), viewOnlyMessage: s__('Pipelines|Merged YAML is view only'),
}, },
components: { components: {
EditorLite, SourceEditor,
GlIcon, GlIcon,
}, },
inject: ['ciConfigPath'], inject: ['ciConfigPath'],
...@@ -41,7 +41,7 @@ export default { ...@@ -41,7 +41,7 @@ export default {
{{ $options.i18n.viewOnlyMessage }} {{ $options.i18n.viewOnlyMessage }}
</div> </div>
<div class="gl-mt-3 gl-border-solid gl-border-gray-100 gl-border-1"> <div class="gl-mt-3 gl-border-solid gl-border-gray-100 gl-border-1">
<editor-lite <source-editor
ref="editor" ref="editor"
:value="mergedYaml" :value="mergedYaml"
:file-name="ciConfigPath" :file-name="ciConfigPath"
......
<script> <script>
import { EDITOR_READY_EVENT } from '~/editor/constants'; import { EDITOR_READY_EVENT } from '~/editor/constants';
import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext'; import { CiSchemaExtension } from '~/editor/extensions/source_editor_ci_schema_ext';
import EditorLite from '~/vue_shared/components/editor_lite.vue'; import SourceEditor from '~/vue_shared/components/source_editor.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import getCommitSha from '../../graphql/queries/client/commit_sha.graphql'; import getCommitSha from '../../graphql/queries/client/commit_sha.graphql';
export default { export default {
components: { components: {
EditorLite, SourceEditor,
}, },
mixins: [glFeatureFlagMixin()], mixins: [glFeatureFlagMixin()],
inject: ['ciConfigPath', 'projectPath', 'projectNamespace', 'defaultBranch'], inject: ['ciConfigPath', 'projectPath', 'projectNamespace', 'defaultBranch'],
...@@ -44,7 +44,7 @@ export default { ...@@ -44,7 +44,7 @@ export default {
</script> </script>
<template> <template>
<div class="gl-border-solid gl-border-gray-100 gl-border-1"> <div class="gl-border-solid gl-border-gray-100 gl-border-1">
<editor-lite <source-editor
ref="editor" ref="editor"
:file-name="ciConfigPath" :file-name="ciConfigPath"
v-bind="$attrs" v-bind="$attrs"
......
...@@ -6,13 +6,13 @@ import axios from '~/lib/utils/axios_utils'; ...@@ -6,13 +6,13 @@ import axios from '~/lib/utils/axios_utils';
import { getBaseURL, joinPaths } from '~/lib/utils/url_utility'; import { getBaseURL, joinPaths } from '~/lib/utils/url_utility';
import { sprintf } from '~/locale'; import { sprintf } from '~/locale';
import { SNIPPET_BLOB_CONTENT_FETCH_ERROR } from '~/snippets/constants'; import { SNIPPET_BLOB_CONTENT_FETCH_ERROR } from '~/snippets/constants';
import EditorLite from '~/vue_shared/components/editor_lite.vue'; import SourceEditor from '~/vue_shared/components/source_editor.vue';
export default { export default {
components: { components: {
BlobHeaderEdit, BlobHeaderEdit,
GlLoadingIcon, GlLoadingIcon,
EditorLite, SourceEditor,
}, },
inheritAttrs: false, inheritAttrs: false,
props: { props: {
...@@ -85,7 +85,7 @@ export default { ...@@ -85,7 +85,7 @@ export default {
size="lg" size="lg"
class="loading-animation prepend-top-20 gl-mb-6" class="loading-animation prepend-top-20 gl-mb-6"
/> />
<editor-lite <source-editor
v-else v-else
:value="blob.content" :value="blob.content"
:file-global-id="blob.id" :file-global-id="blob.id"
......
...@@ -9,8 +9,8 @@ export default { ...@@ -9,8 +9,8 @@ export default {
name: 'SimpleViewer', name: 'SimpleViewer',
components: { components: {
GlIcon, GlIcon,
EditorLite: () => SourceEditor: () =>
import(/* webpackChunkName: 'EditorLite' */ '~/vue_shared/components/editor_lite.vue'), import(/* webpackChunkName: 'SourceEditor' */ '~/vue_shared/components/source_editor.vue'),
}, },
mixins: [ViewerMixin, glFeatureFlagsMixin()], mixins: [ViewerMixin, glFeatureFlagsMixin()],
inject: ['blobHash'], inject: ['blobHash'],
...@@ -53,7 +53,7 @@ export default { ...@@ -53,7 +53,7 @@ export default {
</script> </script>
<template> <template>
<div> <div>
<editor-lite <source-editor
v-if="isRawContent && refactorBlobViewerEnabled" v-if="isRawContent && refactorBlobViewerEnabled"
:value="content" :value="content"
:file-name="fileName" :file-name="fileName"
......
<script> <script>
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { CONTENT_UPDATE_DEBOUNCE, EDITOR_READY_EVENT } from '~/editor/constants'; import { CONTENT_UPDATE_DEBOUNCE, EDITOR_READY_EVENT } from '~/editor/constants';
import Editor from '~/editor/editor_lite'; import Editor from '~/editor/source_editor';
function initEditorLite({ el, ...args }) { function initSourceEditor({ el, ...args }) {
const editor = new Editor({ const editor = new Editor({
scrollbar: { scrollbar: {
alwaysConsumeMouseWheel: false, alwaysConsumeMouseWheel: false,
...@@ -64,7 +64,7 @@ export default { ...@@ -64,7 +64,7 @@ export default {
}, },
}, },
mounted() { mounted() {
this.editor = initEditorLite({ this.editor = initSourceEditor({
el: this.$refs.editor, el: this.$refs.editor,
blobPath: this.fileName, blobPath: this.fileName,
blobContent: this.value, blobContent: this.value,
...@@ -93,7 +93,7 @@ export default { ...@@ -93,7 +93,7 @@ export default {
</script> </script>
<template> <template>
<div <div
:id="`editor-lite-${fileGlobalId}`" :id="`source-editor-${fileGlobalId}`"
ref="editor" ref="editor"
data-editor-loading data-editor-loading
@[$options.readyEvent]="$emit($options.readyEvent)" @[$options.readyEvent]="$emit($options.readyEvent)"
......
...@@ -69,5 +69,5 @@ ...@@ -69,5 +69,5 @@
@import 'framework/system_messages'; @import 'framework/system_messages';
@import 'framework/spinner'; @import 'framework/spinner';
@import 'framework/card'; @import 'framework/card';
@import 'framework/editor-lite'; @import 'framework/source_editor';
@import 'framework/diffs'; @import 'framework/diffs';
...@@ -21,11 +21,11 @@ ...@@ -21,11 +21,11 @@
} }
} }
[id^='editor-lite-'] { [id^='source-editor-'] {
height: 500px; height: 500px;
} }
.monaco-editor.gl-editor-lite { .monaco-editor.gl-source-editor {
.margin-view-overlays { .margin-view-overlays {
.line-numbers { .line-numbers {
@include gl-display-flex; @include gl-display-flex;
......
...@@ -95,7 +95,7 @@ How we implement [keyboard shortcuts](keyboard_shortcuts.md) that can be customi ...@@ -95,7 +95,7 @@ How we implement [keyboard shortcuts](keyboard_shortcuts.md) that can be customi
## Editors ## Editors
GitLab text editing experiences are provided by the [Source Editor](editor_lite.md) and GitLab text editing experiences are provided by the [Source Editor](source_editor.md) and
the [Content Editor](content_editor.md). the [Content Editor](content_editor.md).
## Frontend FAQ ## Frontend FAQ
......
...@@ -4,9 +4,9 @@ group: Editor ...@@ -4,9 +4,9 @@ group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---
# Editor Lite **(FREE)** # Source Editor **(FREE)**
**Editor Lite** provides the editing experience at GitLab. This thin wrapper around **Source Editor** provides the editing experience at GitLab. This thin wrapper around
[the Monaco editor](https://microsoft.github.io/monaco-editor/) provides necessary [the Monaco editor](https://microsoft.github.io/monaco-editor/) provides necessary
helpers and abstractions, and extends Monaco [using extensions](#extensions). Multiple helpers and abstractions, and extends Monaco [using extensions](#extensions). Multiple
GitLab features use it, including: GitLab features use it, including:
...@@ -17,22 +17,22 @@ GitLab features use it, including: ...@@ -17,22 +17,22 @@ GitLab features use it, including:
- [Web Editor](../../user/project/repository/web_editor.md) - [Web Editor](../../user/project/repository/web_editor.md)
- [Security Policies](../../user/application_security/threat_monitoring/index.md) - [Security Policies](../../user/application_security/threat_monitoring/index.md)
## How to use Editor Lite ## How to use Source Editor
Editor Lite is framework-agnostic and can be used in any application, including both Source Editor is framework-agnostic and can be used in any application, including both
Rails and Vue. To help with integration, we have the dedicated `<editor-lite>` Rails and Vue. To help with integration, we have the dedicated `<source-editor>`
Vue component, but the integration of Editor Lite is generally straightforward: Vue component, but the integration of Source Editor is generally straightforward:
1. Import Editor Lite: 1. Import Source Editor:
```javascript ```javascript
import EditorLite from '~/editor/editor_lite'; import SourceEditor from '~/editor/source_editor';
``` ```
1. Initialize global editor for the view: 1. Initialize global editor for the view:
```javascript ```javascript
const editor = new EditorLite({ const editor = new SourceEditor({
// Editor Options. // Editor Options.
// The list of all accepted options can be found at // The list of all accepted options can be found at
// https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.editoroption.html // https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.editoroption.html
...@@ -43,11 +43,11 @@ Vue component, but the integration of Editor Lite is generally straightforward: ...@@ -43,11 +43,11 @@ Vue component, but the integration of Editor Lite is generally straightforward:
```javascript ```javascript
editor.createInstance({ editor.createInstance({
// Editor Lite configuration options. // Source Editor configuration options.
}) })
``` ```
An instance of Editor Lite accepts the following configuration options: An instance of Source Editor accepts the following configuration options:
| Option | Required? | Description | | Option | Required? | Description |
| -------------- | ------- | ---- | | -------------- | ------- | ---- |
...@@ -74,12 +74,12 @@ with additional functions on the instance level: ...@@ -74,12 +74,12 @@ with additional functions on the instance level:
1. Editor's loading state. 1. Editor's loading state.
The loading state is built in to Editor Lite, making spinners and loaders The loading state is built in to Source Editor, making spinners and loaders
rarely needed in HTML. To benefit the built-in loading state, set the `data-editor-loading` rarely needed in HTML. To benefit the built-in loading state, set the `data-editor-loading`
property on the HTML element that should contain the editor. When bootstrapping, property on the HTML element that should contain the editor. When bootstrapping,
Editor Lite shows the loader automatically. Source Editor shows the loader automatically.
![Editor Lite: loading state](img/editor_lite_loading.png) ![Source Editor: loading state](img/editor_lite_loading.png)
1. Update syntax highlighting if the filename changes. 1. Update syntax highlighting if the filename changes.
...@@ -104,21 +104,21 @@ with additional functions on the instance level: ...@@ -104,21 +104,21 @@ with additional functions on the instance level:
1. Performance 1. Performance
Even though Editor Lite itself is extremely slim, it still depends on Monaco editor, Even though Source Editor itself is extremely slim, it still depends on Monaco editor,
which adds weight. Every time you add Editor Lite to a view, the JavaScript bundle's which adds weight. Every time you add Source Editor to a view, the JavaScript bundle's
size significantly increases, affecting your view's loading performance. We recommend size significantly increases, affecting your view's loading performance. We recommend
you import the editor on demand if either: you import the editor on demand if either:
- You're uncertain if the view needs the editor. - You're uncertain if the view needs the editor.
- The editor is a secondary element of the view. - The editor is a secondary element of the view.
Loading Editor Lite on demand is handled like loading any other module: Loading Source Editor on demand is handled like loading any other module:
```javascript ```javascript
someActionFunction() { someActionFunction() {
import(/* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite'). import(/* webpackChunkName: 'SourceEditor' */ '~/editor/source_editor').
then(({ default: EditorLite }) => { then(({ default: SourceEditor }) => {
const editor = new EditorLite(); const editor = new SourceEditor();
... ...
}); });
... ...
...@@ -127,28 +127,28 @@ with additional functions on the instance level: ...@@ -127,28 +127,28 @@ with additional functions on the instance level:
## Extensions ## Extensions
Editor Lite provides a universal, extensible editing tool to the whole product, Source Editor provides a universal, extensible editing tool to the whole product,
and doesn't depend on any particular group. Even though the Editor Lite's core is owned by and doesn't depend on any particular group. Even though the Source Editor's core is owned by
[Create::Editor FE Team](https://about.gitlab.com/handbook/engineering/development/dev/create-editor/), [Create::Editor FE Team](https://about.gitlab.com/handbook/engineering/development/dev/create-editor/),
any group can own the extensions—the main functional elements. The goal of any group can own the extensions—the main functional elements. The goal of
Editor Lite extensions is to keep the editor's core slim and stable. Any Source Editor extensions is to keep the editor's core slim and stable. Any
needed features can be added as extensions to this core. Any group can needed features can be added as extensions to this core. Any group can
build and own new editing features without worrying about changes to Editor Lite build and own new editing features without worrying about changes to Source Editor
breaking or overriding them. breaking or overriding them.
You can depend on other modules in your extensions. This organization helps keep You can depend on other modules in your extensions. This organization helps keep
the size of Editor Lite's core at bay by importing dependencies only when needed. the size of Source Editor's core at bay by importing dependencies only when needed.
Structurally, the complete implementation of Editor Lite can be presented as this diagram: Structurally, the complete implementation of Source Editor can be presented as this diagram:
```mermaid ```mermaid
graph TD; graph TD;
B[Extension 1]---A[Editor Lite] B[Extension 1]---A[Source Editor]
C[Extension 2]---A[Editor Lite] C[Extension 2]---A[Source Editor]
D[Extension 3]---A[Editor Lite] D[Extension 3]---A[Source Editor]
E[...]---A[Editor Lite] E[...]---A[Source Editor]
F[Extension N]---A[Editor Lite] F[Extension N]---A[Source Editor]
A[Editor Lite]---Z[Monaco] A[Source Editor]---Z[Monaco]
``` ```
An extension is an ES6 module that exports a JavaScript object: An extension is an ES6 module that exports a JavaScript object:
...@@ -164,19 +164,19 @@ export default { ...@@ -164,19 +164,19 @@ export default {
``` ```
In the extension's functions, `this` refers to the current Editor Lite instance. In the extension's functions, `this` refers to the current Source Editor instance.
Using `this`, you get access to the complete instance's API, such as the Using `this`, you get access to the complete instance's API, such as the
`setPosition()` method in this particular case. `setPosition()` method in this particular case.
### Using an existing extension ### Using an existing extension
Adding an extension to Editor Lite's instance requires the following steps: Adding an extension to Source Editor's instance requires the following steps:
```javascript ```javascript
import EditorLite from '~/editor/editor_lite'; import SourceEditor from '~/editor/source_editor';
import MyExtension from '~/my_extension'; import MyExtension from '~/my_extension';
const editor = new EditorLite().createInstance({ const editor = new SourceEditor().createInstance({
... ...
}); });
editor.use(MyExtension); editor.use(MyExtension);
...@@ -184,10 +184,10 @@ editor.use(MyExtension); ...@@ -184,10 +184,10 @@ editor.use(MyExtension);
### Creating an extension ### Creating an extension
Let's create our first Editor Lite extension. Extensions are Let's create our first Source Editor extension. Extensions are
[ES6 modules](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/) exporting a [ES6 modules](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/) exporting a
basic `Object`, used to extend Editor Lite's features. As a test, let's basic `Object`, used to extend Source Editor's features. As a test, let's
create an extension that extends Editor Lite with a new function that, when called, create an extension that extends Source Editor with a new function that, when called,
outputs the editor's content in `alert`. outputs the editor's content in `alert`.
`~/my_folder/my_fancy_extension.js:` `~/my_folder/my_fancy_extension.js:`
...@@ -210,10 +210,10 @@ Now let's use our extension: ...@@ -210,10 +210,10 @@ Now let's use our extension:
`~/my_folder/component_bundle.js`: `~/my_folder/component_bundle.js`:
```javascript ```javascript
import EditorLite from '~/editor/editor_lite'; import SourceEditor from '~/editor/source_editor';
import MyFancyExtension from './my_fancy_extension'; import MyFancyExtension from './my_fancy_extension';
const editor = new EditorLite().createInstance({ const editor = new SourceEditor().createInstance({
... ...
}); });
editor.use(MyFancyExtension); editor.use(MyFancyExtension);
...@@ -223,32 +223,32 @@ someButton.addEventListener('click', () => { ...@@ -223,32 +223,32 @@ someButton.addEventListener('click', () => {
}); });
``` ```
First of all, we import Editor Lite and our new extension. Then we create the First of all, we import Source Editor and our new extension. Then we create the
editor and its instance. By default Editor Lite has no `throwContentAtMe` method. editor and its instance. By default Source Editor has no `throwContentAtMe` method.
But the `editor.use(MyFancyExtension)` line brings that method to our instance. But the `editor.use(MyFancyExtension)` line brings that method to our instance.
After that, we can use it any time we need it. In this case, we call it when some After that, we can use it any time we need it. In this case, we call it when some
theoretical button has been clicked. theoretical button has been clicked.
This script would result in an alert containing the editor's content when `someButton` is clicked. This script would result in an alert containing the editor's content when `someButton` is clicked.
![Editor Lite new extension's result](img/editor_lite_create_ext.png) ![Source Editor new extension's result](img/editor_lite_create_ext.png)
### Tips ### Tips
1. Performance 1. Performance
Just like Editor Lite itself, any extension can be loaded on demand to not harm Just like Source Editor itself, any extension can be loaded on demand to not harm
loading performance of the views: loading performance of the views:
```javascript ```javascript
const EditorPromise = import( const EditorPromise = import(
/* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite' /* webpackChunkName: 'SourceEditor' */ '~/editor/source_editor'
); );
const MarkdownExtensionPromise = import('~/editor/editor_markdown_ext'); const MarkdownExtensionPromise = import('~/editor/source_editor_markdown_ext');
Promise.all([EditorPromise, MarkdownExtensionPromise]) Promise.all([EditorPromise, MarkdownExtensionPromise])
.then(([{ default: EditorLite }, { default: MarkdownExtension }]) => { .then(([{ default: SourceEditor }, { default: MarkdownExtension }]) => {
const editor = new EditorLite().createInstance({ const editor = new SourceEditor().createInstance({
... ...
}); });
editor.use(MarkdownExtension); editor.use(MarkdownExtension);
......
<script> <script>
import EditorLite from '~/vue_shared/components/editor_lite.vue'; import SourceEditor from '~/vue_shared/components/source_editor.vue';
export default { export default {
components: { components: {
EditorLite, SourceEditor,
}, },
props: { props: {
value: { value: {
...@@ -44,5 +44,10 @@ export default { ...@@ -44,5 +44,10 @@ export default {
</script> </script>
<template> <template>
<editor-lite :value="value" file-name="*.yaml" :editor-options="editorOptions" @input="onInput" /> <source-editor
:value="value"
file-name="*.yaml"
:editor-options="editorOptions"
@input="onInput"
/>
</template> </template>
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import PolicyYamlEditor from 'ee/threat_monitoring/components/policy_yaml_editor.vue'; import PolicyYamlEditor from 'ee/threat_monitoring/components/policy_yaml_editor.vue';
import EditorLite from '~/vue_shared/components/editor_lite.vue'; import SourceEditor from '~/vue_shared/components/source_editor.vue';
describe('PolicyYamlEditor component', () => { describe('PolicyYamlEditor component', () => {
let wrapper; let wrapper;
const findEditor = () => wrapper.findComponent(EditorLite); const findEditor = () => wrapper.findComponent(SourceEditor);
const factory = ({ propsData } = {}) => { const factory = ({ propsData } = {}) => {
wrapper = shallowMount(PolicyYamlEditor, { wrapper = shallowMount(PolicyYamlEditor, {
...@@ -14,7 +14,7 @@ describe('PolicyYamlEditor component', () => { ...@@ -14,7 +14,7 @@ describe('PolicyYamlEditor component', () => {
...propsData, ...propsData,
}, },
stubs: { stubs: {
EditorLite, SourceEditor,
}, },
}); });
}; };
......
...@@ -11737,9 +11737,6 @@ msgstr "" ...@@ -11737,9 +11737,6 @@ msgstr ""
msgid "Editing" msgid "Editing"
msgstr "" msgstr ""
msgid "Editor Lite instance is required to set up an extension."
msgstr ""
msgid "Elapsed time" msgid "Elapsed time"
msgstr "" msgstr ""
...@@ -30552,6 +30549,9 @@ msgstr "" ...@@ -30552,6 +30549,9 @@ msgstr ""
msgid "Source Branch" msgid "Source Branch"
msgstr "" msgstr ""
msgid "Source Editor instance is required to set up an extension."
msgstr ""
msgid "Source IP" msgid "Source IP"
msgstr "" msgstr ""
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Merge request > User resolves conflicts', :js do RSpec.describe 'Merge request > User resolves conflicts', :js do
include Spec::Support::Helpers::Features::EditorLiteSpecHelpers include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:user) { project.creator } let(:user) { project.creator }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Pipeline Editor', :js do RSpec.describe 'Pipeline Editor', :js do
include Spec::Support::Helpers::Features::EditorLiteSpecHelpers include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:user) { create(:user) } let(:user) { create(:user) }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'CI Lint', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297782' do RSpec.describe 'CI Lint', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297782' do
include Spec::Support::Helpers::Features::EditorLiteSpecHelpers include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:user) { create(:user) } let(:user) { create(:user) }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', :js do RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', :js do
include Spec::Support::Helpers::Features::EditorLiteSpecHelpers include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
before do before do
project = create(:project, :repository) project = create(:project, :repository)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Files > User wants to add a .gitignore file', :js do RSpec.describe 'Projects > Files > User wants to add a .gitignore file', :js do
include Spec::Support::Helpers::Features::EditorLiteSpecHelpers include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
before do before do
project = create(:project, :repository) project = create(:project, :repository)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js do RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js do
include Spec::Support::Helpers::Features::EditorLiteSpecHelpers include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
let(:params) { {} } let(:params) { {} }
let(:filename) { '.gitlab-ci.yml' } let(:filename) { '.gitlab-ci.yml' }
......
...@@ -3,7 +3,7 @@ import { nextTick } from 'vue'; ...@@ -3,7 +3,7 @@ import { nextTick } from 'vue';
import BlobEditContent from '~/blob/components/blob_edit_content.vue'; import BlobEditContent from '~/blob/components/blob_edit_content.vue';
import * as utils from '~/blob/utils'; import * as utils from '~/blob/utils';
jest.mock('~/editor/editor_lite'); jest.mock('~/editor/source_editor');
describe('Blob Header Editing', () => { describe('Blob Header Editing', () => {
let wrapper; let wrapper;
...@@ -26,7 +26,7 @@ describe('Blob Header Editing', () => { ...@@ -26,7 +26,7 @@ describe('Blob Header Editing', () => {
} }
beforeEach(() => { beforeEach(() => {
jest.spyOn(utils, 'initEditorLite').mockImplementation(() => ({ jest.spyOn(utils, 'initSourceEditor').mockImplementation(() => ({
onDidChangeModelContent, onDidChangeModelContent,
updateModelLanguage, updateModelLanguage,
getValue, getValue,
...@@ -68,9 +68,9 @@ describe('Blob Header Editing', () => { ...@@ -68,9 +68,9 @@ describe('Blob Header Editing', () => {
expect(wrapper.find('#editor').exists()).toBe(true); expect(wrapper.find('#editor').exists()).toBe(true);
}); });
it('initialises Editor Lite', () => { it('initialises Source Editor', () => {
const el = wrapper.find({ ref: 'editor' }).element; const el = wrapper.find({ ref: 'editor' }).element;
expect(utils.initEditorLite).toHaveBeenCalledWith({ expect(utils.initSourceEditor).toHaveBeenCalledWith({
el, el,
blobPath: fileName, blobPath: fileName,
blobGlobalId: fileGlobalId, blobGlobalId: fileGlobalId,
......
import * as utils from '~/blob/utils'; import * as utils from '~/blob/utils';
import Editor from '~/editor/editor_lite'; import Editor from '~/editor/source_editor';
jest.mock('~/editor/editor_lite'); jest.mock('~/editor/source_editor');
describe('Blob utilities', () => { describe('Blob utilities', () => {
describe('initEditorLite', () => { describe('initSourceEditor', () => {
let editorEl; let editorEl;
const blobPath = 'foo.txt'; const blobPath = 'foo.txt';
const blobContent = 'Foo bar'; const blobContent = 'Foo bar';
...@@ -15,8 +15,8 @@ describe('Blob utilities', () => { ...@@ -15,8 +15,8 @@ describe('Blob utilities', () => {
}); });
describe('Monaco editor', () => { describe('Monaco editor', () => {
it('initializes the Editor Lite', () => { it('initializes the Source Editor', () => {
utils.initEditorLite({ el: editorEl }); utils.initSourceEditor({ el: editorEl });
expect(Editor).toHaveBeenCalledWith({ expect(Editor).toHaveBeenCalledWith({
scrollbar: { scrollbar: {
alwaysConsumeMouseWheel: false, alwaysConsumeMouseWheel: false,
...@@ -34,7 +34,7 @@ describe('Blob utilities', () => { ...@@ -34,7 +34,7 @@ describe('Blob utilities', () => {
expect(Editor.prototype.createInstance).not.toHaveBeenCalled(); expect(Editor.prototype.createInstance).not.toHaveBeenCalled();
utils.initEditorLite(params); utils.initSourceEditor(params);
expect(Editor.prototype.createInstance).toHaveBeenCalledWith(params); expect(Editor.prototype.createInstance).toHaveBeenCalledWith(params);
}, },
......
...@@ -3,21 +3,21 @@ import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; ...@@ -3,21 +3,21 @@ import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import blobBundle from '~/blob_edit/blob_bundle'; import blobBundle from '~/blob_edit/blob_bundle';
import EditorLite from '~/blob_edit/edit_blob'; import SourceEditor from '~/blob_edit/edit_blob';
jest.mock('~/blob_edit/edit_blob'); jest.mock('~/blob_edit/edit_blob');
describe('BlobBundle', () => { describe('BlobBundle', () => {
it('does not load EditorLite by default', () => { it('does not load SourceEditor by default', () => {
blobBundle(); blobBundle();
expect(EditorLite).not.toHaveBeenCalled(); expect(SourceEditor).not.toHaveBeenCalled();
}); });
it('loads EditorLite for the edit screen', async () => { it('loads SourceEditor for the edit screen', async () => {
setFixtures(`<div class="js-edit-blob-form"></div>`); setFixtures(`<div class="js-edit-blob-form"></div>`);
blobBundle(); blobBundle();
await waitForPromises(); await waitForPromises();
expect(EditorLite).toHaveBeenCalled(); expect(SourceEditor).toHaveBeenCalled();
}); });
describe('No Suggest Popover', () => { describe('No Suggest Popover', () => {
......
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import EditBlob from '~/blob_edit/edit_blob'; import EditBlob from '~/blob_edit/edit_blob';
import EditorLite from '~/editor/editor_lite'; import { FileTemplateExtension } from '~/editor/extensions/source_editor_file_template_ext';
import { FileTemplateExtension } from '~/editor/extensions/editor_file_template_ext'; import { EditorMarkdownExtension } from '~/editor/extensions/source_editor_markdown_ext';
import { EditorMarkdownExtension } from '~/editor/extensions/editor_markdown_ext'; import SourceEditor from '~/editor/source_editor';
jest.mock('~/editor/editor_lite'); jest.mock('~/editor/source_editor');
jest.mock('~/editor/extensions/editor_markdown_ext'); jest.mock('~/editor/extensions/source_editor_markdown_ext');
jest.mock('~/editor/extensions/editor_file_template_ext'); jest.mock('~/editor/extensions/source_editor_file_template_ext');
describe('Blob Editing', () => { describe('Blob Editing', () => {
const useMock = jest.fn(); const useMock = jest.fn();
...@@ -24,7 +24,7 @@ describe('Blob Editing', () => { ...@@ -24,7 +24,7 @@ describe('Blob Editing', () => {
<textarea id="file-content"></textarea> <textarea id="file-content"></textarea>
</form> </form>
`); `);
jest.spyOn(EditorLite.prototype, 'createInstance').mockReturnValue(mockInstance); jest.spyOn(SourceEditor.prototype, 'createInstance').mockReturnValue(mockInstance);
}); });
afterEach(() => { afterEach(() => {
EditorMarkdownExtension.mockClear(); EditorMarkdownExtension.mockClear();
......
...@@ -4,7 +4,7 @@ import waitForPromises from 'helpers/wait_for_promises'; ...@@ -4,7 +4,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import CiLint from '~/ci_lint/components/ci_lint.vue'; import CiLint from '~/ci_lint/components/ci_lint.vue';
import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue'; import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue';
import lintCIMutation from '~/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql'; import lintCIMutation from '~/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql';
import EditorLite from '~/vue_shared/components/editor_lite.vue'; import SourceEditor from '~/vue_shared/components/source_editor.vue';
import { mockLintDataValid } from '../mock_data'; import { mockLintDataValid } from '../mock_data';
describe('CI Lint', () => { describe('CI Lint', () => {
...@@ -35,7 +35,7 @@ describe('CI Lint', () => { ...@@ -35,7 +35,7 @@ describe('CI Lint', () => {
}); });
}; };
const findEditor = () => wrapper.find(EditorLite); const findEditor = () => wrapper.find(SourceEditor);
const findAlert = () => wrapper.find(GlAlert); const findAlert = () => wrapper.find(GlAlert);
const findCiLintResults = () => wrapper.find(CiLintResults); const findCiLintResults = () => wrapper.find(CiLintResults);
const findValidateBtn = () => wrapper.find('[data-testid="ci-lint-validate"]'); const findValidateBtn = () => wrapper.find('[data-testid="ci-lint-validate"]');
......
import { languages } from 'monaco-editor'; import { languages } from 'monaco-editor';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '~/editor/constants'; import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '~/editor/constants';
import EditorLite from '~/editor/editor_lite'; import { CiSchemaExtension } from '~/editor/extensions/source_editor_ci_schema_ext';
import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext'; import SourceEditor from '~/editor/source_editor';
const mockRef = 'AABBCCDD'; const mockRef = 'AABBCCDD';
...@@ -17,7 +17,7 @@ describe('~/editor/editor_ci_config_ext', () => { ...@@ -17,7 +17,7 @@ describe('~/editor/editor_ci_config_ext', () => {
const createMockEditor = ({ blobPath = defaultBlobPath } = {}) => { const createMockEditor = ({ blobPath = defaultBlobPath } = {}) => {
setFixtures('<div id="editor"></div>'); setFixtures('<div id="editor"></div>');
editorEl = document.getElementById('editor'); editorEl = document.getElementById('editor');
editor = new EditorLite(); editor = new SourceEditor();
instance = editor.createInstance({ instance = editor.createInstance({
el: editorEl, el: editorEl,
blobPath, blobPath,
......
...@@ -5,7 +5,7 @@ import { ...@@ -5,7 +5,7 @@ import {
EDITOR_TYPE_CODE, EDITOR_TYPE_CODE,
EDITOR_TYPE_DIFF, EDITOR_TYPE_DIFF,
} from '~/editor/constants'; } from '~/editor/constants';
import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base'; import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
jest.mock('~/helpers/startup_css_helper', () => { jest.mock('~/helpers/startup_css_helper', () => {
return { return {
...@@ -22,7 +22,7 @@ jest.mock('~/helpers/startup_css_helper', () => { ...@@ -22,7 +22,7 @@ jest.mock('~/helpers/startup_css_helper', () => {
}; };
}); });
describe('The basis for an Editor Lite extension', () => { describe('The basis for an Source Editor extension', () => {
const defaultLine = 3; const defaultLine = 3;
let ext; let ext;
let event; let event;
...@@ -63,7 +63,7 @@ describe('The basis for an Editor Lite extension', () => { ...@@ -63,7 +63,7 @@ describe('The basis for an Editor Lite extension', () => {
const instance = { const instance = {
layout: jest.fn(), layout: jest.fn(),
}; };
ext = new EditorLiteExtension({ instance }); ext = new SourceEditorExtension({ instance });
expect(instance.layout).not.toHaveBeenCalled(); expect(instance.layout).not.toHaveBeenCalled();
// We're waiting for the waitForCSSLoaded mock to kick in // We're waiting for the waitForCSSLoaded mock to kick in
...@@ -79,7 +79,7 @@ describe('The basis for an Editor Lite extension', () => { ...@@ -79,7 +79,7 @@ describe('The basis for an Editor Lite extension', () => {
${'does not fail if both instance and the options are omitted'} | ${undefined} | ${undefined} ${'does not fail if both instance and the options are omitted'} | ${undefined} | ${undefined}
${'throws if only options are passed'} | ${undefined} | ${defaultOptions} ${'throws if only options are passed'} | ${undefined} | ${defaultOptions}
`('$description', ({ instance, options } = {}) => { `('$description', ({ instance, options } = {}) => {
EditorLiteExtension.deferRerender = jest.fn(); SourceEditorExtension.deferRerender = jest.fn();
const originalInstance = { ...instance }; const originalInstance = { ...instance };
if (instance) { if (instance) {
...@@ -88,54 +88,54 @@ describe('The basis for an Editor Lite extension', () => { ...@@ -88,54 +88,54 @@ describe('The basis for an Editor Lite extension', () => {
expect(instance[prop]).toBeUndefined(); expect(instance[prop]).toBeUndefined();
}); });
// Both instance and options are passed // Both instance and options are passed
ext = new EditorLiteExtension({ instance, ...options }); ext = new SourceEditorExtension({ instance, ...options });
Object.entries(options).forEach(([prop, value]) => { Object.entries(options).forEach(([prop, value]) => {
expect(ext[prop]).toBeUndefined(); expect(ext[prop]).toBeUndefined();
expect(instance[prop]).toBe(value); expect(instance[prop]).toBe(value);
}); });
} else { } else {
ext = new EditorLiteExtension({ instance }); ext = new SourceEditorExtension({ instance });
expect(instance).toEqual(originalInstance); expect(instance).toEqual(originalInstance);
} }
} else if (options) { } else if (options) {
// Options are passed without instance // Options are passed without instance
expect(() => { expect(() => {
ext = new EditorLiteExtension({ ...options }); ext = new SourceEditorExtension({ ...options });
}).toThrow(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION); }).toThrow(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION);
} else { } else {
// Neither options nor instance are passed // Neither options nor instance are passed
expect(() => { expect(() => {
ext = new EditorLiteExtension(); ext = new SourceEditorExtension();
}).not.toThrow(); }).not.toThrow();
} }
}); });
it('initializes the line highlighting', () => { it('initializes the line highlighting', () => {
EditorLiteExtension.deferRerender = jest.fn(); SourceEditorExtension.deferRerender = jest.fn();
const spy = jest.spyOn(EditorLiteExtension, 'highlightLines'); const spy = jest.spyOn(SourceEditorExtension, 'highlightLines');
ext = new EditorLiteExtension({ instance: {} }); ext = new SourceEditorExtension({ instance: {} });
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
it('sets up the line linking for code instance', () => { it('sets up the line linking for code instance', () => {
EditorLiteExtension.deferRerender = jest.fn(); SourceEditorExtension.deferRerender = jest.fn();
const spy = jest.spyOn(EditorLiteExtension, 'setupLineLinking'); const spy = jest.spyOn(SourceEditorExtension, 'setupLineLinking');
const instance = { const instance = {
getEditorType: jest.fn().mockReturnValue(EDITOR_TYPE_CODE), getEditorType: jest.fn().mockReturnValue(EDITOR_TYPE_CODE),
onMouseMove: jest.fn(), onMouseMove: jest.fn(),
onMouseDown: jest.fn(), onMouseDown: jest.fn(),
}; };
ext = new EditorLiteExtension({ instance }); ext = new SourceEditorExtension({ instance });
expect(spy).toHaveBeenCalledWith(instance); expect(spy).toHaveBeenCalledWith(instance);
}); });
it('does not set up the line linking for diff instance', () => { it('does not set up the line linking for diff instance', () => {
EditorLiteExtension.deferRerender = jest.fn(); SourceEditorExtension.deferRerender = jest.fn();
const spy = jest.spyOn(EditorLiteExtension, 'setupLineLinking'); const spy = jest.spyOn(SourceEditorExtension, 'setupLineLinking');
const instance = { const instance = {
getEditorType: jest.fn().mockReturnValue(EDITOR_TYPE_DIFF), getEditorType: jest.fn().mockReturnValue(EDITOR_TYPE_DIFF),
}; };
ext = new EditorLiteExtension({ instance }); ext = new SourceEditorExtension({ instance });
expect(spy).not.toHaveBeenCalled(); expect(spy).not.toHaveBeenCalled();
}); });
}); });
...@@ -172,7 +172,7 @@ describe('The basis for an Editor Lite extension', () => { ...@@ -172,7 +172,7 @@ describe('The basis for an Editor Lite extension', () => {
${'does not highlight if hash is incomplete 2'} | ${'#L-'} | ${false} | ${null} ${'does not highlight if hash is incomplete 2'} | ${'#L-'} | ${false} | ${null}
`('$desc', ({ hash, shouldReveal, expectedRange } = {}) => { `('$desc', ({ hash, shouldReveal, expectedRange } = {}) => {
window.location.hash = hash; window.location.hash = hash;
EditorLiteExtension.highlightLines(instance); SourceEditorExtension.highlightLines(instance);
if (!shouldReveal) { if (!shouldReveal) {
expect(revealSpy).not.toHaveBeenCalled(); expect(revealSpy).not.toHaveBeenCalled();
expect(decorationsSpy).not.toHaveBeenCalled(); expect(decorationsSpy).not.toHaveBeenCalled();
...@@ -194,7 +194,7 @@ describe('The basis for an Editor Lite extension', () => { ...@@ -194,7 +194,7 @@ describe('The basis for an Editor Lite extension', () => {
decorationsSpy.mockReturnValue('foo'); decorationsSpy.mockReturnValue('foo');
window.location.hash = '#L10'; window.location.hash = '#L10';
expect(instance.lineDecorations).toBeUndefined(); expect(instance.lineDecorations).toBeUndefined();
EditorLiteExtension.highlightLines(instance); SourceEditorExtension.highlightLines(instance);
expect(instance.lineDecorations).toBe('foo'); expect(instance.lineDecorations).toBe('foo');
}); });
}); });
...@@ -208,7 +208,7 @@ describe('The basis for an Editor Lite extension', () => { ...@@ -208,7 +208,7 @@ describe('The basis for an Editor Lite extension', () => {
}; };
beforeEach(() => { beforeEach(() => {
EditorLiteExtension.onMouseMoveHandler(event); // generate the anchor SourceEditorExtension.onMouseMoveHandler(event); // generate the anchor
}); });
it.each` it.each`
...@@ -216,7 +216,7 @@ describe('The basis for an Editor Lite extension', () => { ...@@ -216,7 +216,7 @@ describe('The basis for an Editor Lite extension', () => {
${'onMouseMove'} | ${instance.onMouseMove} ${'onMouseMove'} | ${instance.onMouseMove}
${'onMouseDown'} | ${instance.onMouseDown} ${'onMouseDown'} | ${instance.onMouseDown}
`('sets up the $desc listener', ({ spy } = {}) => { `('sets up the $desc listener', ({ spy } = {}) => {
EditorLiteExtension.setupLineLinking(instance); SourceEditorExtension.setupLineLinking(instance);
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
...@@ -230,7 +230,7 @@ describe('The basis for an Editor Lite extension', () => { ...@@ -230,7 +230,7 @@ describe('The basis for an Editor Lite extension', () => {
fn(event); fn(event);
}); });
EditorLiteExtension.setupLineLinking(instance); SourceEditorExtension.setupLineLinking(instance);
if (shouldRemove) { if (shouldRemove) {
expect(instance.deltaDecorations).toHaveBeenCalledWith(instance.lineDecorations, []); expect(instance.deltaDecorations).toHaveBeenCalledWith(instance.lineDecorations, []);
} else { } else {
...@@ -241,7 +241,7 @@ describe('The basis for an Editor Lite extension', () => { ...@@ -241,7 +241,7 @@ describe('The basis for an Editor Lite extension', () => {
describe('onMouseMoveHandler', () => { describe('onMouseMoveHandler', () => {
it('stops propagation for contextmenu event on the generated anchor', () => { it('stops propagation for contextmenu event on the generated anchor', () => {
EditorLiteExtension.onMouseMoveHandler(event); SourceEditorExtension.onMouseMoveHandler(event);
const anchor = findLine(defaultLine).querySelector('a'); const anchor = findLine(defaultLine).querySelector('a');
const contextMenuEvent = new Event('contextmenu'); const contextMenuEvent = new Event('contextmenu');
...@@ -253,27 +253,27 @@ describe('The basis for an Editor Lite extension', () => { ...@@ -253,27 +253,27 @@ describe('The basis for an Editor Lite extension', () => {
it('creates an anchor if it does not exist yet', () => { it('creates an anchor if it does not exist yet', () => {
expect(findLine(defaultLine).querySelector('a')).toBe(null); expect(findLine(defaultLine).querySelector('a')).toBe(null);
EditorLiteExtension.onMouseMoveHandler(event); SourceEditorExtension.onMouseMoveHandler(event);
expect(findLine(defaultLine).querySelector('a')).not.toBe(null); expect(findLine(defaultLine).querySelector('a')).not.toBe(null);
}); });
it('does not create a new anchor if it exists', () => { it('does not create a new anchor if it exists', () => {
EditorLiteExtension.onMouseMoveHandler(event); SourceEditorExtension.onMouseMoveHandler(event);
expect(findLine(defaultLine).querySelector('a')).not.toBe(null); expect(findLine(defaultLine).querySelector('a')).not.toBe(null);
EditorLiteExtension.createAnchor = jest.fn(); SourceEditorExtension.createAnchor = jest.fn();
EditorLiteExtension.onMouseMoveHandler(event); SourceEditorExtension.onMouseMoveHandler(event);
expect(EditorLiteExtension.createAnchor).not.toHaveBeenCalled(); expect(SourceEditorExtension.createAnchor).not.toHaveBeenCalled();
expect(findLine(defaultLine).querySelectorAll('a')).toHaveLength(1); expect(findLine(defaultLine).querySelectorAll('a')).toHaveLength(1);
}); });
it('does not create a link if the event is triggered on a wrong node', () => { it('does not create a link if the event is triggered on a wrong node', () => {
setFixtures('<div class="wrong-class">3</div>'); setFixtures('<div class="wrong-class">3</div>');
EditorLiteExtension.createAnchor = jest.fn(); SourceEditorExtension.createAnchor = jest.fn();
const wrongEvent = generateEventMock({ el: document.querySelector('.wrong-class') }); const wrongEvent = generateEventMock({ el: document.querySelector('.wrong-class') });
EditorLiteExtension.onMouseMoveHandler(wrongEvent); SourceEditorExtension.onMouseMoveHandler(wrongEvent);
expect(EditorLiteExtension.createAnchor).not.toHaveBeenCalled(); expect(SourceEditorExtension.createAnchor).not.toHaveBeenCalled();
}); });
}); });
}); });
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
import { editor as monacoEditor, languages as monacoLanguages } from 'monaco-editor'; import { editor as monacoEditor, languages as monacoLanguages } from 'monaco-editor';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import { import {
EDITOR_LITE_INSTANCE_ERROR_NO_EL, SOURCE_EDITOR_INSTANCE_ERROR_NO_EL,
URI_PREFIX, URI_PREFIX,
EDITOR_READY_EVENT, EDITOR_READY_EVENT,
} from '~/editor/constants'; } from '~/editor/constants';
import EditorLite from '~/editor/editor_lite'; import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base'; import SourceEditor from '~/editor/source_editor';
import { DEFAULT_THEME, themes } from '~/ide/lib/themes'; import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
import { joinPaths } from '~/lib/utils/url_utility'; import { joinPaths } from '~/lib/utils/url_utility';
...@@ -25,7 +25,7 @@ describe('Base editor', () => { ...@@ -25,7 +25,7 @@ describe('Base editor', () => {
setFixtures('<div id="editor" data-editor-loading></div>'); setFixtures('<div id="editor" data-editor-loading></div>');
editorEl = document.getElementById('editor'); editorEl = document.getElementById('editor');
defaultArguments = { el: editorEl, blobPath, blobContent, blobGlobalId }; defaultArguments = { el: editorEl, blobPath, blobContent, blobGlobalId };
editor = new EditorLite(); editor = new SourceEditor();
}); });
afterEach(() => { afterEach(() => {
...@@ -49,7 +49,7 @@ describe('Base editor', () => { ...@@ -49,7 +49,7 @@ describe('Base editor', () => {
expect(editorEl.dataset.editorLoading).toBeUndefined(); expect(editorEl.dataset.editorLoading).toBeUndefined();
}); });
describe('instance of the Editor Lite', () => { describe('instance of the Source Editor', () => {
let modelSpy; let modelSpy;
let instanceSpy; let instanceSpy;
const setModel = jest.fn(); const setModel = jest.fn();
...@@ -58,7 +58,7 @@ describe('Base editor', () => { ...@@ -58,7 +58,7 @@ describe('Base editor', () => {
modelSpy = jest.spyOn(monacoEditor, 'createModel').mockImplementation(() => res); modelSpy = jest.spyOn(monacoEditor, 'createModel').mockImplementation(() => res);
}; };
const mockDecorateInstance = (decorations = {}) => { const mockDecorateInstance = (decorations = {}) => {
jest.spyOn(EditorLite, 'convertMonacoToELInstance').mockImplementation((inst) => { jest.spyOn(SourceEditor, 'convertMonacoToELInstance').mockImplementation((inst) => {
return Object.assign(inst, decorations); return Object.assign(inst, decorations);
}); });
}; };
...@@ -76,11 +76,11 @@ describe('Base editor', () => { ...@@ -76,11 +76,11 @@ describe('Base editor', () => {
mockDecorateInstance(); mockDecorateInstance();
expect(() => { expect(() => {
editor.createInstance(); editor.createInstance();
}).toThrow(EDITOR_LITE_INSTANCE_ERROR_NO_EL); }).toThrow(SOURCE_EDITOR_INSTANCE_ERROR_NO_EL);
expect(modelSpy).not.toHaveBeenCalled(); expect(modelSpy).not.toHaveBeenCalled();
expect(instanceSpy).not.toHaveBeenCalled(); expect(instanceSpy).not.toHaveBeenCalled();
expect(EditorLite.convertMonacoToELInstance).not.toHaveBeenCalled(); expect(SourceEditor.convertMonacoToELInstance).not.toHaveBeenCalled();
}); });
it('creates model to be supplied to Monaco editor', () => { it('creates model to be supplied to Monaco editor', () => {
...@@ -261,7 +261,7 @@ describe('Base editor', () => { ...@@ -261,7 +261,7 @@ describe('Base editor', () => {
blobPath, blobPath,
}; };
editor = new EditorLite(); editor = new SourceEditor();
instanceSpy = jest.spyOn(monacoEditor, 'create'); instanceSpy = jest.spyOn(monacoEditor, 'create');
}); });
...@@ -304,7 +304,7 @@ describe('Base editor', () => { ...@@ -304,7 +304,7 @@ describe('Base editor', () => {
}); });
it('shares global editor options among all instances', () => { it('shares global editor options among all instances', () => {
editor = new EditorLite({ editor = new SourceEditor({
readOnly: true, readOnly: true,
}); });
...@@ -316,7 +316,7 @@ describe('Base editor', () => { ...@@ -316,7 +316,7 @@ describe('Base editor', () => {
}); });
it('allows overriding editor options on the instance level', () => { it('allows overriding editor options on the instance level', () => {
editor = new EditorLite({ editor = new SourceEditor({
readOnly: true, readOnly: true,
}); });
inst1 = editor.createInstance({ inst1 = editor.createInstance({
...@@ -410,7 +410,7 @@ describe('Base editor', () => { ...@@ -410,7 +410,7 @@ describe('Base editor', () => {
return WithStaticMethod.computeBoo(this.base); return WithStaticMethod.computeBoo(this.base);
} }
} }
class WithStaticMethodExtended extends EditorLiteExtension { class WithStaticMethodExtended extends SourceEditorExtension {
static computeBoo(a) { static computeBoo(a) {
return a + 1; return a + 1;
} }
...@@ -546,7 +546,7 @@ describe('Base editor', () => { ...@@ -546,7 +546,7 @@ describe('Base editor', () => {
beforeEach(() => { beforeEach(() => {
editorExtensionSpy = jest editorExtensionSpy = jest
.spyOn(EditorLite, 'pushToImportsArray') .spyOn(SourceEditor, 'pushToImportsArray')
.mockImplementation((arr) => { .mockImplementation((arr) => {
arr.push( arr.push(
Promise.resolve({ Promise.resolve({
...@@ -593,7 +593,7 @@ describe('Base editor', () => { ...@@ -593,7 +593,7 @@ describe('Base editor', () => {
const useSpy = jest.fn().mockImplementation(() => { const useSpy = jest.fn().mockImplementation(() => {
calls.push('use'); calls.push('use');
}); });
jest.spyOn(EditorLite, 'convertMonacoToELInstance').mockImplementation((inst) => { jest.spyOn(SourceEditor, 'convertMonacoToELInstance').mockImplementation((inst) => {
const decoratedInstance = inst; const decoratedInstance = inst;
decoratedInstance.use = useSpy; decoratedInstance.use = useSpy;
return decoratedInstance; return decoratedInstance;
...@@ -664,7 +664,7 @@ describe('Base editor', () => { ...@@ -664,7 +664,7 @@ describe('Base editor', () => {
it('sets default syntax highlighting theme', () => { it('sets default syntax highlighting theme', () => {
const expectedTheme = themes.find((t) => t.name === DEFAULT_THEME); const expectedTheme = themes.find((t) => t.name === DEFAULT_THEME);
editor = new EditorLite(); editor = new SourceEditor();
expect(themeDefineSpy).toHaveBeenCalledWith(DEFAULT_THEME, expectedTheme.data); expect(themeDefineSpy).toHaveBeenCalledWith(DEFAULT_THEME, expectedTheme.data);
expect(themeSetSpy).toHaveBeenCalledWith(DEFAULT_THEME); expect(themeSetSpy).toHaveBeenCalledWith(DEFAULT_THEME);
...@@ -676,7 +676,7 @@ describe('Base editor', () => { ...@@ -676,7 +676,7 @@ describe('Base editor', () => {
expect(expectedTheme.name).not.toBe(DEFAULT_THEME); expect(expectedTheme.name).not.toBe(DEFAULT_THEME);
window.gon.user_color_scheme = expectedTheme.name; window.gon.user_color_scheme = expectedTheme.name;
editor = new EditorLite(); editor = new SourceEditor();
expect(themeDefineSpy).toHaveBeenCalledWith(expectedTheme.name, expectedTheme.data); expect(themeDefineSpy).toHaveBeenCalledWith(expectedTheme.name, expectedTheme.data);
expect(themeSetSpy).toHaveBeenCalledWith(expectedTheme.name); expect(themeSetSpy).toHaveBeenCalledWith(expectedTheme.name);
...@@ -687,7 +687,7 @@ describe('Base editor', () => { ...@@ -687,7 +687,7 @@ describe('Base editor', () => {
const nonExistentTheme = { name }; const nonExistentTheme = { name };
window.gon.user_color_scheme = nonExistentTheme.name; window.gon.user_color_scheme = nonExistentTheme.name;
editor = new EditorLite(); editor = new SourceEditor();
expect(themeDefineSpy).not.toHaveBeenCalled(); expect(themeDefineSpy).not.toHaveBeenCalled();
expect(themeSetSpy).toHaveBeenCalledWith(DEFAULT_THEME); expect(themeSetSpy).toHaveBeenCalledWith(DEFAULT_THEME);
......
import { Range, Position } from 'monaco-editor'; import { Range, Position } from 'monaco-editor';
import EditorLite from '~/editor/editor_lite'; import { EditorMarkdownExtension } from '~/editor/extensions/source_editor_markdown_ext';
import { EditorMarkdownExtension } from '~/editor/extensions/editor_markdown_ext'; import SourceEditor from '~/editor/source_editor';
describe('Markdown Extension for Editor Lite', () => { describe('Markdown Extension for Source Editor', () => {
let editor; let editor;
let instance; let instance;
let editorEl; let editorEl;
...@@ -25,7 +25,7 @@ describe('Markdown Extension for Editor Lite', () => { ...@@ -25,7 +25,7 @@ describe('Markdown Extension for Editor Lite', () => {
beforeEach(() => { beforeEach(() => {
setFixtures('<div id="editor" data-editor-loading></div>'); setFixtures('<div id="editor" data-editor-loading></div>');
editorEl = document.getElementById('editor'); editorEl = document.getElementById('editor');
editor = new EditorLite(); editor = new SourceEditor();
instance = editor.createInstance({ instance = editor.createInstance({
el: editorEl, el: editorEl,
blobPath: filePath, blobPath: filePath,
......
...@@ -8,8 +8,8 @@ import waitForPromises from 'helpers/wait_for_promises'; ...@@ -8,8 +8,8 @@ import waitForPromises from 'helpers/wait_for_promises';
import waitUsingRealTimer from 'helpers/wait_using_real_timer'; import waitUsingRealTimer from 'helpers/wait_using_real_timer';
import { exampleConfigs, exampleFiles } from 'jest/ide/lib/editorconfig/mock_data'; import { exampleConfigs, exampleFiles } from 'jest/ide/lib/editorconfig/mock_data';
import { EDITOR_CODE_INSTANCE_FN, EDITOR_DIFF_INSTANCE_FN } from '~/editor/constants'; import { EDITOR_CODE_INSTANCE_FN, EDITOR_DIFF_INSTANCE_FN } from '~/editor/constants';
import EditorLite from '~/editor/editor_lite'; import { EditorWebIdeExtension } from '~/editor/extensions/source_editor_webide_ext';
import { EditorWebIdeExtension } from '~/editor/extensions/editor_lite_webide_ext'; import SourceEditor from '~/editor/source_editor';
import RepoEditor from '~/ide/components/repo_editor.vue'; import RepoEditor from '~/ide/components/repo_editor.vue';
import { import {
leftSidebarViews, leftSidebarViews,
...@@ -123,8 +123,8 @@ describe('RepoEditor', () => { ...@@ -123,8 +123,8 @@ describe('RepoEditor', () => {
const findPreviewTab = () => wrapper.find('[data-testid="preview-tab"]'); const findPreviewTab = () => wrapper.find('[data-testid="preview-tab"]');
beforeEach(() => { beforeEach(() => {
createInstanceSpy = jest.spyOn(EditorLite.prototype, EDITOR_CODE_INSTANCE_FN); createInstanceSpy = jest.spyOn(SourceEditor.prototype, EDITOR_CODE_INSTANCE_FN);
createDiffInstanceSpy = jest.spyOn(EditorLite.prototype, EDITOR_DIFF_INSTANCE_FN); createDiffInstanceSpy = jest.spyOn(SourceEditor.prototype, EDITOR_DIFF_INSTANCE_FN);
createModelSpy = jest.spyOn(monacoEditor, 'createModel'); createModelSpy = jest.spyOn(monacoEditor, 'createModel');
jest.spyOn(service, 'getFileData').mockResolvedValue(); jest.spyOn(service, 'getFileData').mockResolvedValue();
jest.spyOn(service, 'getRawFileData').mockResolvedValue(); jest.spyOn(service, 'getRawFileData').mockResolvedValue();
...@@ -252,7 +252,7 @@ describe('RepoEditor', () => { ...@@ -252,7 +252,7 @@ describe('RepoEditor', () => {
); );
it('installs the WebIDE extension', async () => { it('installs the WebIDE extension', async () => {
const extensionSpy = jest.spyOn(EditorLite, 'instanceApplyExtension'); const extensionSpy = jest.spyOn(SourceEditor, 'instanceApplyExtension');
await createComponent(); await createComponent();
expect(extensionSpy).toHaveBeenCalled(); expect(extensionSpy).toHaveBeenCalled();
Reflect.ownKeys(EditorWebIdeExtension.prototype) Reflect.ownKeys(EditorWebIdeExtension.prototype)
......
...@@ -300,7 +300,7 @@ describe('init markdown', () => { ...@@ -300,7 +300,7 @@ describe('init markdown', () => {
}); });
}); });
describe('Editor Lite', () => { describe('Source Editor', () => {
let editor; let editor;
beforeEach(() => { beforeEach(() => {
......
...@@ -8,7 +8,7 @@ import { mockLintResponse, mockCiConfigPath } from '../../mock_data'; ...@@ -8,7 +8,7 @@ import { mockLintResponse, mockCiConfigPath } from '../../mock_data';
describe('Text editor component', () => { describe('Text editor component', () => {
let wrapper; let wrapper;
const MockEditorLite = { const MockSourceEditor = {
template: '<div/>', template: '<div/>',
props: ['value', 'fileName', 'editorOptions'], props: ['value', 'fileName', 'editorOptions'],
mounted() { mounted() {
...@@ -26,13 +26,13 @@ describe('Text editor component', () => { ...@@ -26,13 +26,13 @@ describe('Text editor component', () => {
ciConfigPath: mockCiConfigPath, ciConfigPath: mockCiConfigPath,
}, },
stubs: { stubs: {
EditorLite: MockEditorLite, SourceEditor: MockSourceEditor,
}, },
}); });
}; };
const findIcon = () => wrapper.findComponent(GlIcon); const findIcon = () => wrapper.findComponent(GlIcon);
const findEditor = () => wrapper.findComponent(MockEditorLite); const findEditor = () => wrapper.findComponent(MockSourceEditor);
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { EDITOR_READY_EVENT } from '~/editor/constants'; import { EDITOR_READY_EVENT } from '~/editor/constants';
import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base'; import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
import TextEditor from '~/pipeline_editor/components/editor/text_editor.vue'; import TextEditor from '~/pipeline_editor/components/editor/text_editor.vue';
import { import {
mockCiConfigPath, mockCiConfigPath,
...@@ -19,7 +19,7 @@ describe('Pipeline Editor | Text editor component', () => { ...@@ -19,7 +19,7 @@ describe('Pipeline Editor | Text editor component', () => {
let mockUse; let mockUse;
let mockRegisterCiSchema; let mockRegisterCiSchema;
const MockEditorLite = { const MockSourceEditor = {
template: '<div/>', template: '<div/>',
props: ['value', 'fileName'], props: ['value', 'fileName'],
mounted() { mounted() {
...@@ -55,15 +55,15 @@ describe('Pipeline Editor | Text editor component', () => { ...@@ -55,15 +55,15 @@ describe('Pipeline Editor | Text editor component', () => {
[EDITOR_READY_EVENT]: editorReadyListener, [EDITOR_READY_EVENT]: editorReadyListener,
}, },
stubs: { stubs: {
EditorLite: MockEditorLite, SourceEditor: MockSourceEditor,
}, },
}); });
}; };
const findEditor = () => wrapper.findComponent(MockEditorLite); const findEditor = () => wrapper.findComponent(MockSourceEditor);
beforeEach(() => { beforeEach(() => {
EditorLiteExtension.deferRerender = jest.fn(); SourceEditorExtension.deferRerender = jest.fn();
}); });
afterEach(() => { afterEach(() => {
......
...@@ -6,7 +6,7 @@ import EditorTab from '~/pipeline_editor/components/ui/editor_tab.vue'; ...@@ -6,7 +6,7 @@ import EditorTab from '~/pipeline_editor/components/ui/editor_tab.vue';
const mockContent1 = 'MOCK CONTENT 1'; const mockContent1 = 'MOCK CONTENT 1';
const mockContent2 = 'MOCK CONTENT 2'; const mockContent2 = 'MOCK CONTENT 2';
const MockEditorLite = { const MockSourceEditor = {
template: '<div>EDITOR</div>', template: '<div>EDITOR</div>',
}; };
...@@ -48,12 +48,12 @@ describe('~/pipeline_editor/components/ui/editor_tab.vue', () => { ...@@ -48,12 +48,12 @@ describe('~/pipeline_editor/components/ui/editor_tab.vue', () => {
wrapper = mount(EditorTab, { wrapper = mount(EditorTab, {
propsData: props, propsData: props,
slots: { slots: {
default: MockEditorLite, default: MockSourceEditor,
}, },
}); });
}; };
const findSlotComponent = () => wrapper.findComponent(MockEditorLite); const findSlotComponent = () => wrapper.findComponent(MockSourceEditor);
const findAlert = () => wrapper.findComponent(GlAlert); const findAlert = () => wrapper.findComponent(GlAlert);
beforeEach(() => { beforeEach(() => {
......
...@@ -25,7 +25,7 @@ import { ...@@ -25,7 +25,7 @@ import {
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(VueApollo); localVue.use(VueApollo);
const MockEditorLite = { const MockSourceEditor = {
template: '<div/>', template: '<div/>',
}; };
...@@ -55,7 +55,7 @@ describe('Pipeline editor app component', () => { ...@@ -55,7 +55,7 @@ describe('Pipeline editor app component', () => {
PipelineEditorHome, PipelineEditorHome,
PipelineEditorTabs, PipelineEditorTabs,
PipelineEditorMessages, PipelineEditorMessages,
EditorLite: MockEditorLite, SourceEditor: MockSourceEditor,
PipelineEditorEmptyState, PipelineEditorEmptyState,
}, },
mocks: { mocks: {
......
...@@ -13,7 +13,7 @@ exports[`Snippet Blob Edit component with loaded blob matches snapshot 1`] = ` ...@@ -13,7 +13,7 @@ exports[`Snippet Blob Edit component with loaded blob matches snapshot 1`] = `
value="foo/bar/test.md" value="foo/bar/test.md"
/> />
<editor-lite-stub <source-editor-stub
editoroptions="[object Object]" editoroptions="[object Object]"
fileglobalid="blob_local_7" fileglobalid="blob_local_7"
filename="foo/bar/test.md" filename="foo/bar/test.md"
......
...@@ -8,7 +8,7 @@ import createFlash from '~/flash'; ...@@ -8,7 +8,7 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility'; import { joinPaths } from '~/lib/utils/url_utility';
import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue'; import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue';
import EditorLite from '~/vue_shared/components/editor_lite.vue'; import SourceEditor from '~/vue_shared/components/source_editor.vue';
jest.mock('~/flash'); jest.mock('~/flash');
...@@ -48,7 +48,7 @@ describe('Snippet Blob Edit component', () => { ...@@ -48,7 +48,7 @@ describe('Snippet Blob Edit component', () => {
const findLoadingIcon = () => wrapper.find(GlLoadingIcon); const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findHeader = () => wrapper.find(BlobHeaderEdit); const findHeader = () => wrapper.find(BlobHeaderEdit);
const findContent = () => wrapper.find(EditorLite); const findContent = () => wrapper.find(SourceEditor);
const getLastUpdatedArgs = () => { const getLastUpdatedArgs = () => {
const event = wrapper.emitted()['blob-updated']; const event = wrapper.emitted()['blob-updated'];
......
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Editor Lite component rendering matches the snapshot 1`] = ` exports[`Source Editor component rendering matches the snapshot 1`] = `
<div <div
data-editor-loading="" data-editor-loading=""
id="editor-lite-snippet_777" id="source-editor-snippet_777"
> >
<pre <pre
class="editor-loading-content" class="editor-loading-content"
......
...@@ -2,7 +2,7 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -2,7 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import { HIGHLIGHT_CLASS_NAME } from '~/vue_shared/components/blob_viewers/constants'; import { HIGHLIGHT_CLASS_NAME } from '~/vue_shared/components/blob_viewers/constants';
import SimpleViewer from '~/vue_shared/components/blob_viewers/simple_viewer.vue'; import SimpleViewer from '~/vue_shared/components/blob_viewers/simple_viewer.vue';
import EditorLite from '~/vue_shared/components/editor_lite.vue'; import SourceEditor from '~/vue_shared/components/source_editor.vue';
describe('Blob Simple Viewer component', () => { describe('Blob Simple Viewer component', () => {
let wrapper; let wrapper;
...@@ -96,7 +96,7 @@ describe('Blob Simple Viewer component', () => { ...@@ -96,7 +96,7 @@ describe('Blob Simple Viewer component', () => {
}); });
describe('Vue refactoring to use Source Editor', () => { describe('Vue refactoring to use Source Editor', () => {
const findEditorLite = () => wrapper.find(EditorLite); const findSourceEditor = () => wrapper.find(SourceEditor);
it.each` it.each`
doesRender | condition | isRawContent | isRefactorFlagEnabled doesRender | condition | isRawContent | isRefactorFlagEnabled
...@@ -105,19 +105,19 @@ describe('Blob Simple Viewer component', () => { ...@@ -105,19 +105,19 @@ describe('Blob Simple Viewer component', () => {
${'Does not'} | ${'both, the FF and rawContent are not specified'} | ${false} | ${false} ${'Does not'} | ${'both, the FF and rawContent are not specified'} | ${false} | ${false}
${'Does'} | ${'both, the FF and rawContent are specified'} | ${true} | ${true} ${'Does'} | ${'both, the FF and rawContent are specified'} | ${true} | ${true}
`( `(
'$doesRender render Editor Lite component in readonly mode when $condition', '$doesRender render Source Editor component in readonly mode when $condition',
async ({ isRawContent, isRefactorFlagEnabled } = {}) => { async ({ isRawContent, isRefactorFlagEnabled } = {}) => {
createComponent('raw content', isRawContent, isRefactorFlagEnabled); createComponent('raw content', isRawContent, isRefactorFlagEnabled);
await waitForPromises(); await waitForPromises();
if (isRawContent && isRefactorFlagEnabled) { if (isRawContent && isRefactorFlagEnabled) {
expect(findEditorLite().exists()).toBe(true); expect(findSourceEditor().exists()).toBe(true);
expect(findEditorLite().props('value')).toBe('raw content'); expect(findSourceEditor().props('value')).toBe('raw content');
expect(findEditorLite().props('fileName')).toBe('test.js'); expect(findSourceEditor().props('fileName')).toBe('test.js');
expect(findEditorLite().props('editorOptions')).toEqual({ readOnly: true }); expect(findSourceEditor().props('editorOptions')).toEqual({ readOnly: true });
} else { } else {
expect(findEditorLite().exists()).toBe(false); expect(findSourceEditor().exists()).toBe(false);
} }
}, },
); );
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import { EDITOR_READY_EVENT } from '~/editor/constants'; import { EDITOR_READY_EVENT } from '~/editor/constants';
import Editor from '~/editor/editor_lite'; import Editor from '~/editor/source_editor';
import EditorLite from '~/vue_shared/components/editor_lite.vue'; import SourceEditor from '~/vue_shared/components/source_editor.vue';
jest.mock('~/editor/editor_lite'); jest.mock('~/editor/source_editor');
describe('Editor Lite component', () => { describe('Source Editor component', () => {
let wrapper; let wrapper;
let mockInstance; let mockInstance;
...@@ -30,7 +30,7 @@ describe('Editor Lite component', () => { ...@@ -30,7 +30,7 @@ describe('Editor Lite component', () => {
}; };
}); });
function createComponent(props = {}) { function createComponent(props = {}) {
wrapper = shallowMount(EditorLite, { wrapper = shallowMount(SourceEditor, {
propsData: { propsData: {
value, value,
fileName, fileName,
...@@ -73,10 +73,10 @@ describe('Editor Lite component', () => { ...@@ -73,10 +73,10 @@ describe('Editor Lite component', () => {
createComponent({ value: undefined }); createComponent({ value: undefined });
expect(spy).not.toHaveBeenCalled(); expect(spy).not.toHaveBeenCalled();
expect(wrapper.find('[id^="editor-lite-"]').exists()).toBe(true); expect(wrapper.find('[id^="source-editor-"]').exists()).toBe(true);
}); });
it('initialises Editor Lite instance', () => { it('initialises Source Editor instance', () => {
const el = wrapper.find({ ref: 'editor' }).element; const el = wrapper.find({ ref: 'editor' }).element;
expect(createInstanceMock).toHaveBeenCalledWith({ expect(createInstanceMock).toHaveBeenCalledWith({
el, el,
...@@ -111,7 +111,7 @@ describe('Editor Lite component', () => { ...@@ -111,7 +111,7 @@ describe('Editor Lite component', () => {
expect(wrapper.emitted().input).toEqual([[value]]); expect(wrapper.emitted().input).toEqual([[value]]);
}); });
it('emits EDITOR_READY_EVENT event when the Editor Lite is ready', async () => { it('emits EDITOR_READY_EVENT event when the Source Editor is ready', async () => {
const el = wrapper.find({ ref: 'editor' }).element; const el = wrapper.find({ ref: 'editor' }).element;
expect(wrapper.emitted()[EDITOR_READY_EVENT]).toBeUndefined(); expect(wrapper.emitted()[EDITOR_READY_EVENT]).toBeUndefined();
......
# frozen_string_literal: true # frozen_string_literal: true
# These helpers help you interact within the Editor Lite (single-file editor, snippets, etc.). # These helpers help you interact within the Source Editor (single-file editor, snippets, etc.).
# #
module Spec module Spec
module Support module Support
module Helpers module Helpers
module Features module Features
module EditorLiteSpecHelpers module SourceEditorSpecHelpers
include ActionView::Helpers::JavaScriptHelper include ActionView::Helpers::JavaScriptHelper
def editor_set_value(value) def editor_set_value(value)
......
# frozen_string_literal: true # frozen_string_literal: true
# These helpers help you interact within the Editor Lite (single-file editor, snippets, etc.). # These helpers help you interact within the Source Editor (single-file editor, snippets, etc.).
# #
module Spec module Spec
module Support module Support
...@@ -8,7 +8,7 @@ module Spec ...@@ -8,7 +8,7 @@ module Spec
module Features module Features
module SnippetSpecHelpers module SnippetSpecHelpers
include ActionView::Helpers::JavaScriptHelper include ActionView::Helpers::JavaScriptHelper
include Spec::Support::Helpers::Features::EditorLiteSpecHelpers include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
def snippet_description_locator def snippet_description_locator
'snippet-description' 'snippet-description'
...@@ -31,7 +31,7 @@ module Spec ...@@ -31,7 +31,7 @@ module Spec
end end
def snippet_get_first_blob_value def snippet_get_first_blob_value
page.find('.gl-editor-lite', match: :first) page.find('.gl-source-editor', match: :first)
end end
def snippet_description_value def snippet_description_value
...@@ -53,7 +53,7 @@ module Spec ...@@ -53,7 +53,7 @@ module Spec
end end
def snippet_fill_in_content(value) def snippet_fill_in_content(value)
page.within('.gl-editor-lite') do page.within('.gl-source-editor') do
el = find('.inputarea') el = find('.inputarea')
el.send_keys value el.send_keys value
end end
......
# frozen_string_literal: true # frozen_string_literal: true
# These helpers help you interact within the Editor Lite (single-file editor, snippets, etc.). # These helpers help you interact within the Source Editor (single-file editor, snippets, etc.).
# #
module Spec module Spec
module Support module Support
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment