소스 편집기

소스 편집기(Source Editor)는 GitLab에서의 편집 경험을 제공합니다. 이것은 Monaco 에디터를 감싸는 얇은 래퍼로, 필요한 도우미 및 추상화를 제공하고, 확장 (확장을 사용하여 Monaco를 확장)합니다. Web IDE, CI 린터, 스니펫, 웹 에디터, 보안 정책과 같은 여러 GitLab 기능에서 사용됩니다.

소스 편집기를 사용하는 시기

사용자가 파일 내용을 편집해야 하는 경우에만 소스 편집기를 사용하십시오. 소스 코드를 표시해야 하는 경우에는 BlobContent 컴포넌트를 사용하는 것을 고려하십시오.

작업 중인 페이지가 이미 소스 편집기를로드 하는 경우에도 소스 편집기에서 읽기 전용 콘텐츠를 표시하는 것은 여전히 유효한 옵션입니다.

소스 편집기 사용 방법

소스 편집기는 프레임워크에 독립적이므로 Rails 및 뷰를 비롯한 모든 응용 프로그램에서 사용할 수 있습니다. 통합을 돕기 위해 <소스-편집기> 특화된 Vue 컴포넌트를 제공하지만, 소스 편집기의 통합은 일반적으로 직관적입니다.

  1. 소스 편집기를 가져옵니다.:

    import SourceEditor from '~/editor/source_editor';
    
  2. 뷰의 전역 편집기를 초기화합니다.:

    const editor = new SourceEditor({
      // 편집기 옵션.
      // 허용되는 모든 옵션 디렉터리은 다음에서 찾을 수 있습니다.
      // https://microsoft.github.io/monaco-editor/docs.html
    });
    
  3. 편집기의 인스턴스를 생성합니다.:

    editor.createInstance({
      // 소스 편집기 구성 옵션.
    })
    

소스 편집기의 인스턴스는 다음 구성 옵션을 수용합니다:

옵션 필요 여부 설명
el true HTML 노드: 편집기를 렌더링할 요소입니다.
blobPath false 문자열: 편집기에 렌더링할 파일의 이름으로 해당 파일에 사용할 올바른 구문 강조 표시기를 식별하는 데 사용되거나 다른 파일 유형을 나타냅니다. 실제 파일 이름이 알려지지 않거나 그 역할이 없을 때 *.js와 같은 와일드카드를 사용할 수 있습니다.
blobContent false 문자열: 편집기에 초기 내용을 렌더링합니다.
extensions false 배열: 이 인스턴스에서 사용할 확장 기능입니다.
blobGlobalId false 문자열: 자동 생성된 속성.
참고: 이 속성은 앞으로 사라질 수 있습니다. 알고 있는 경우가 아니라면 blobGlobalId를 전달하지 마십시오.
편집기 옵션 false 객체(들): 위 디렉터리에 없는 모든 속성은 특정 인스턴스에 대한 편집기 옵션으로 취급됩니다. 이 필드를 사용하여 인스턴스 수준에서 전역 편집기 옵션을 재정의합니다. 전체 편집기 옵션의 인덱스가 있습니다.

API

편집기는 인스턴스 수준에서 모나코 에디터에서 제공하는 공개 API와 동일한 공개 API를 사용하며, 다음과 같이 인스턴스 수준에서의 추가 기능도 사용합니다:

함수 인수 설명
updateModelLanguage path: 문자열 전달된 path의 확장에 따라 인스턴스의 구문 강조 표시를 업데이트합니다. 인스턴스 수준에서만 사용할 수 있습니다.
use 객체 배열 인스턴스에 적용할 확장 기능 배열입니다. 객체의 배열만 허용됩니다. 확장의 ES6 모듈은 뷰 또는 컴포넌트에서 가져와 use에 전달하기 전에 검색되고 해결되어야합니다. 인스턴스 및 전역 편집기(모든 인스턴스) 수준에서 사용할 수 있습니다.
모나코 에디터 옵션 문서 참조 기본 모나코 에디터 옵션입니다.

  1. 편집기의 로딩 상태.

    로딩 상태는 소스 편집기에 기본적으로 내장되어 있어 스피너와 로더가 거의 필요하지 않습니다. 내장된 로딩 상태를 이용하려면 편집기를 포함해야 하는 HTML 요소에 data-editor-loading 속성을 설정하면 Source 편집기가 부트스트랩 할 때 로더를 자동으로 표시합니다.

    Source Editor: 로딩 상태

  2. 파일 이름이 변경되면 구문 강조 표시를 업데이트합니다.

    // 여기서 fileNameEl은 파일 이름을 포함하는 HTML 입력 요소입니다.
    fileNameEl.addEventListener('change', () => {
      this.editor.updateModelLanguage(fileNameEl.value);
    });
    
  3. 편집기의 내용을 가져오기.

    편집기에서 모든 변경에 대한 청취기를 설정할 수 있지만, 이것은 빠르게 비용이 발생할 수 있는 작업이 될 수 있습니다. 대신 필요할 때 편집기의 내용을 가져오십시오. 예를 들어, 양식 제출시:

    form.addEventListener('submit', () => {
      my_content_variable = this.editor.getValue();
    });
    
  4. 성능

    소스 편집기 자체는 매우 가볍지만 목자코 에디터에 의존하기 때문에 크기가 커집니다. 뷰에 소스 편집기를 추가할 때마다 JavaScript 번들의 크기가 크게 증가하여 뷰의 로드 성능에 영향을 줍니다. 뷰가 편집기가 필요한지 확신이 없으면 또는 편집기가 뷰의 보조 요소인 경우에는 요구 사항에 맞게 편집기를 필요에 따라 가져오는 것을 권장합니다.

    요구 사항에 따라 소스 편집기를 필요에 따라 가져오는 것은 다른 모듈을 가져오는 것처럼 처리됩니다.:

    someActionFunction() {
      import(/* webpackChunkName: 'SourceEditor' */ '~/editor/source_editor').
        then(({ default: SourceEditor }) => {
          const editor = new SourceEditor();
          ...
        });
      ...
    }
    

확장 기능

소스 편집기는 전체 제품에 대한 범용적이고 확장 가능한 편집 도구를 제공하며 특정 그룹에 의존하지 않습니다. 소스 편집기의 핵심은 소유한 그룹의 확장 기능입니다. Create::Editor FE Team이 소유하는 소스 편집기의 핵심이지만, 필요한 기능은 핵심에 영향을받거나 덮어쓰지 않고 확장 형태로 추가할 수 있습니다. 어떤 그룹이든 변경에 대해 걱정할 필요없이 새로운 편집 기능을 빌드하고 소유할 수 있습니다.

확장 기능에서 다른 모듈에 의존할 수 있습니다. 이러한 구성은 필요할 때만 의존성을 가져오도록하여 소스 편집기의 핵심 크기를 유지하여야 합니다.

구조적으로 소스 편집기의 전체 구현은 다음과 같이 나타낼 수 있습니다:

%%{init: { "fontFamily": "GitLab Sans" }}%% graph TD; B[확장 기능 1]---A[소스 편집기] C[확장 기능 2]---A[소스 편집기] D[확장 기능 3]---A[소스 편집기] E[...]---A[소스 편집기] F[확장 기능 N]---A[소스 편집기] A[소스 편집기]---Z[모나코]

확장 기능은 JavaScript 객체를 내보내는 ES6 모듈입니다:

import { Position } from 'monaco-editor';

export default {
  navigateFileStart() {
    this.setPosition(new Position(1, 1));
  },
};

확장 기능의 함수에서 this는 현재 소스 편집기 인스턴스를 나타냅니다. 여기에서는 이 경우에 setPosition() 메소드에 액세스할 수 있습니다.

기존 확장 기능 사용

소스 편집기 인스턴스에 확장 기능을 추가하려면 다음 단계를 수행해야 합니다:

import SourceEditor from '~/editor/source_editor';
import MyExtension from '~/my_extension';

const editor = new SourceEditor().createInstance({
  ...
});
editor.use(MyExtension);

확장 생성

첫 번째 소스 에디터 확장을 만들어 봅시다. 확장은 기본 Object를 내보내는 ES6 모듈로, 소스 에디터의 기능을 확장하는 데 사용됩니다. 테스트로 호출될 때 에디터의 내용을 alert로 출력하는 새로운 기능을 추가하는 확장을 만들어 봅시다.

~/my_folder/my_fancy_extension.js:

export default {
  throwContentAtMe() {
    alert(this.getValue());
  },
};

위 코드 예제에서 this는 인스턴스를 가리킵니다. 인스턴스를 참조함으로써 우리는 getValue()와 같은 함수를 포함한 완전한 기저 Monaco 에디터 API에 액세스할 수 있습니다.

이제 확장을 사용해 봅시다.

~/my_folder/component_bundle.js:

import SourceEditor from '~/editor/source_editor';
import MyFancyExtension from './my_fancy_extension';

const editor = new SourceEditor().createInstance({
  ...
});
editor.use(MyFancyExtension);
...
someButton.addEventListener('click', () => {
  editor.throwContentAtMe();
});

먼저 Source Editor와 새로운 확장을 가져옵니다. 그런 다음에 에디터와 해당 인스턴스를 만듭니다. 기본적으로 Source Editor에는 throwContentAtMe 메서드가 없습니다. 그러나 editor.use(MyFancyExtension) 라인은 해당 메서드를 인스턴스로 가져옵니다. 그 후에는 필요할 때마다 사용할 수 있습니다. 이 경우, 이론적인 버튼이 클릭되었을 때 호출합니다.

위 스크립트는 someButton이 클릭될 때 에디터의 내용을 포함하는 경고를 결과로 표시합니다.

소스 에디터의 새로운 확장 결과

  1. 성능

    소스 에디터 그 자체와 마찬가지로 모든 확장은 보기의 로딩 성능에 영향을 미치지 않도록 필요에 따라 로드할 수 있습니다:

    const EditorPromise = import(
      /* webpackChunkName: 'SourceEditor' */ '~/editor/source_editor'
    );
    const MarkdownExtensionPromise = import('~/editor/source_editor_markdown_ext');
       
    Promise.all([EditorPromise, MarkdownExtensionPromise])
      .then(([{ default: SourceEditor }, { default: MarkdownExtension }]) => {
        const editor = new SourceEditor().createInstance({
          ...
        });
        editor.use(MarkdownExtension);
      });
    
  2. 여러 확장 사용

    use 메서드에 확장의 배열을 전달하기만 하면 됩니다:

    editor.use([FileTemplateExtension, MyFancyExtension]);