diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-11 00:09:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-11 00:09:47 +0300 |
commit | 7b2f94166965e60329129e5a919e2c3d88f23c7a (patch) | |
tree | 8fa395403cbffd6138b36bf36430e243f3f07f85 /app/assets/javascripts/editor | |
parent | 6fd750c19206412cfc52b49a70b56147d839c52f (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/editor')
3 files changed, 142 insertions, 5 deletions
diff --git a/app/assets/javascripts/editor/constants.js b/app/assets/javascripts/editor/constants.js index d40d19000fb..d44bfdfb966 100644 --- a/app/assets/javascripts/editor/constants.js +++ b/app/assets/javascripts/editor/constants.js @@ -1,15 +1,15 @@ import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; -import { __ } from '~/locale'; +import { s__ } from '~/locale'; -export const SOURCE_EDITOR_INSTANCE_ERROR_NO_EL = __( - '"el" parameter is required for createInstance()', +export const SOURCE_EDITOR_INSTANCE_ERROR_NO_EL = s__( + 'SourceEditor|"el" parameter is required for createInstance()', ); export const URI_PREFIX = 'gitlab'; export const CONTENT_UPDATE_DEBOUNCE = DEFAULT_DEBOUNCE_AND_THROTTLE_MS; -export const ERROR_INSTANCE_REQUIRED_FOR_EXTENSION = __( - 'Source Editor instance is required to set up an extension.', +export const ERROR_INSTANCE_REQUIRED_FOR_EXTENSION = s__( + 'SourceEditor|Source Editor instance is required to set up an extension.', ); export const EDITOR_READY_EVENT = 'editor-ready'; @@ -20,6 +20,10 @@ export const EDITOR_TYPE_DIFF = 'vs.editor.IDiffEditor'; export const EDITOR_CODE_INSTANCE_FN = 'createInstance'; export const EDITOR_DIFF_INSTANCE_FN = 'createDiffInstance'; +export const EDITOR_EXTENSION_DEFINITION_ERROR = s__( + 'SourceEditor|Extension definition should be either a class or a function', +); + // // EXTENSIONS' CONSTANTS // diff --git a/app/assets/javascripts/editor/extensions/example_source_editor_extension.js b/app/assets/javascripts/editor/extensions/example_source_editor_extension.js new file mode 100644 index 00000000000..119a2aea9eb --- /dev/null +++ b/app/assets/javascripts/editor/extensions/example_source_editor_extension.js @@ -0,0 +1,116 @@ +// THIS IS AN EXAMPLE +// +// This file contains a basic documented example of the Source Editor extensions' +// API for your convenience. You can copy/paste it into your own file +// and adjust as you see fit +// + +export class MyFancyExtension { + /** + * THE LIFE-CYCLE CALLBACKS + */ + + /** + * Is called before the extension gets used by an instance, + * Use `onSetup` to setup Monaco directly: + * actions, keystrokes, update options, etc. + * Is called only once before the extension gets registered + * + * @param { Object } [setupOptions] The setupOptions object + * @param { Object } [instance] The Source Editor instance + */ + // eslint-disable-next-line class-methods-use-this,no-unused-vars + onSetup(setupOptions, instance) {} + + /** + * The first thing called after the extension is + * registered and used by an instance. + * Is called every time the extension is applied + * + * @param { Object } [instance] The Source Editor instance + */ + // eslint-disable-next-line class-methods-use-this,no-unused-vars + onUse(instance) {} + + /** + * Is called before un-using an extension. Can be used for time-critical + * actions like cleanup, reverting visual changes, and other user-facing + * updates. + * + * @param { Object } [instance] The Source Editor instance + */ + // eslint-disable-next-line class-methods-use-this,no-unused-vars + onBeforeUnuse(instance) {} + + /** + * Is called right after an extension is removed from an instance (un-used) + * Can be used for non time-critical tasks like cleanup on the Monaco level + * (removing actions, keystrokes, etc.). + * onUnuse() will be executed during the browser's idle period + * (https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback) + * + * @param { Object } [instance] The Source Editor instance + */ + // eslint-disable-next-line class-methods-use-this,no-unused-vars + onUnuse(instance) {} + + /** + * The public API of the extension: these are the methods that will be exposed + * to the end user + * @returns {Object} + */ + provides() { + return { + basic: () => { + // The most basic method not depending on anything + // Use: instance.basic(); + // eslint-disable-next-line @gitlab/require-i18n-strings + return 'Foo Bar'; + }, + basicWithProp: () => { + // The methods with access to the props of the extension. + // The props can be either hardcoded (for example in `onSetup`), or + // can be dynamically passed as part of `setupOptions` object when + // using the extension. + // Use: instance.use({ definition: MyFancyExtension, setupOptions: { foo: 'bar' }}); + return this.foo; + }, + basicWithPropsAsList: (prop1, prop2) => { + // Just a simple method with local props + // The props are passed as usually. + // Use: instance.basicWithPropsAsList(prop1, prop2); + // eslint-disable-next-line @gitlab/require-i18n-strings + return `The prop1 is ${prop1}; the prop2 is ${prop2}`; + }, + basicWithInstance: (instance) => { + // The method accessing the instance methods: either own or provided + // by previously-registered extensions + // `instance` is always supplied to all methods in provides() as THE LAST + // argument. + // You don't need to explicitly pass instance to this method: + // Use: instance.basicWithInstance(); + // eslint-disable-next-line @gitlab/require-i18n-strings + return `We have access to the whole Instance! ${instance.alpha()}`; + }, + advancedWithInstanceAndProps: ({ author, book } = {}, firstname, lastname, instance) => { + // Advanced method where + // { author, book } — are the props passed as an object + // prop1, prop2 — are the props passed as simple list + // instance — is automatically supplied, no need to pass it to + // the method explicitly + // Use: instance.advancedWithInstanceAndProps( + // { + // author: 'Franz Kafka', + // book: 'The Transformation' + // }, + // 'Franz', + // 'Kafka' + // ); + return ` +The author is ${author}; the book is ${book} +The author's name is ${firstname}; the last name is ${lastname} +We have access to the whole Instance! For example, 'instance.alpha()': ${instance.alpha()}`; + }, + }; + } +} diff --git a/app/assets/javascripts/editor/source_editor_extension.js b/app/assets/javascripts/editor/source_editor_extension.js new file mode 100644 index 00000000000..664bcabcf45 --- /dev/null +++ b/app/assets/javascripts/editor/source_editor_extension.js @@ -0,0 +1,17 @@ +import { EDITOR_EXTENSION_DEFINITION_ERROR } from './constants'; + +export default class EditorExtension { + constructor({ definition, setupOptions } = {}) { + if (typeof definition !== 'function') { + throw new Error(EDITOR_EXTENSION_DEFINITION_ERROR); + } + this.name = definition.name; // both class- and fn-based extensions have a name + this.setupOptions = setupOptions; + // eslint-disable-next-line new-cap + this.obj = new definition(); + } + + get api() { + return this.obj.provides(); + } +} |