Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
9f4ef4b5
Commit
9f4ef4b5
authored
Oct 07, 2020
by
Denys Mishunov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow using extensions from instance level
parent
b89fa5ca
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
151 additions
and
38 deletions
+151
-38
app/assets/javascripts/editor/editor_lite.js
app/assets/javascripts/editor/editor_lite.js
+37
-0
changelogs/unreleased/232503-editor-lite-extensions-on-instance.yml
.../unreleased/232503-editor-lite-extensions-on-instance.yml
+5
-0
spec/frontend/editor/editor_lite_spec.js
spec/frontend/editor/editor_lite_spec.js
+109
-38
No files found.
app/assets/javascripts/editor/editor_lite.js
View file @
9f4ef4b5
...
@@ -39,6 +39,26 @@ export default class Editor {
...
@@ -39,6 +39,26 @@ export default class Editor {
monacoEditor
.
setModelLanguage
(
model
,
id
);
monacoEditor
.
setModelLanguage
(
model
,
id
);
}
}
static
pushToImportsArray
(
arr
,
toImport
)
{
arr
.
push
(
import
(
toImport
));
}
static
loadExtensions
(
extensions
)
{
if
(
!
extensions
)
{
return
Promise
.
resolve
();
}
const
promises
=
[];
const
extensionsArray
=
typeof
extensions
===
'
string
'
?
extensions
.
split
(
'
,
'
)
:
extensions
;
extensionsArray
.
forEach
(
ext
=>
{
const
prefix
=
ext
.
indexOf
(
'
/
'
)
===
-
1
?
'
editor/
'
:
''
;
const
trimmedExt
=
ext
.
replace
(
/^
\/
/
,
''
).
trim
();
Editor
.
pushToImportsArray
(
promises
,
`~/
${
prefix
}${
trimmedExt
}
`
);
});
return
Promise
.
all
(
promises
);
}
/**
/**
* Creates a monaco instance with the given options.
* Creates a monaco instance with the given options.
*
*
...
@@ -53,6 +73,7 @@ export default class Editor {
...
@@ -53,6 +73,7 @@ export default class Editor {
blobPath
=
''
,
blobPath
=
''
,
blobContent
=
''
,
blobContent
=
''
,
blobGlobalId
=
''
,
blobGlobalId
=
''
,
extensions
=
[],
...
instanceOptions
...
instanceOptions
}
=
{})
{
}
=
{})
{
if
(
!
el
)
{
if
(
!
el
)
{
...
@@ -80,6 +101,22 @@ export default class Editor {
...
@@ -80,6 +101,22 @@ export default class Editor {
model
.
dispose
();
model
.
dispose
();
});
});
instance
.
updateModelLanguage
=
path
=>
Editor
.
updateModelLanguage
(
path
,
instance
);
instance
.
updateModelLanguage
=
path
=>
Editor
.
updateModelLanguage
(
path
,
instance
);
instance
.
use
=
args
=>
this
.
use
(
args
,
instance
);
Editor
.
loadExtensions
(
extensions
,
instance
)
.
then
(
modules
=>
{
if
(
modules
)
{
modules
.
forEach
(
module
=>
{
instance
.
use
(
module
.
default
);
});
}
})
.
catch
(
e
=>
{
throw
e
;
})
.
finally
(()
=>
{
el
.
dispatchEvent
(
new
Event
(
'
editor-ready
'
));
});
this
.
instances
.
push
(
instance
);
this
.
instances
.
push
(
instance
);
return
instance
;
return
instance
;
...
...
changelogs/unreleased/232503-editor-lite-extensions-on-instance.yml
0 → 100644
View file @
9f4ef4b5
---
title
:
Editor Lite to saupport extensions in instance constructor
merge_request
:
44723
author
:
type
:
added
spec/frontend/editor/editor_lite_spec.js
View file @
9f4ef4b5
import
{
editor
as
monacoEditor
,
languages
as
monacoLanguages
,
Uri
}
from
'
monaco-editor
'
;
import
{
editor
as
monacoEditor
,
languages
as
monacoLanguages
,
Uri
}
from
'
monaco-editor
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
Editor
from
'
~/editor/editor_lite
'
;
import
Editor
from
'
~/editor/editor_lite
'
;
import
{
DEFAULT_THEME
,
themes
}
from
'
~/ide/lib/themes
'
;
import
{
DEFAULT_THEME
,
themes
}
from
'
~/ide/lib/themes
'
;
import
{
EDITOR_LITE_INSTANCE_ERROR_NO_EL
,
URI_PREFIX
}
from
'
~/editor/constants
'
;
import
{
EDITOR_LITE_INSTANCE_ERROR_NO_EL
,
URI_PREFIX
}
from
'
~/editor/constants
'
;
...
@@ -253,55 +254,125 @@ describe('Base editor', () => {
...
@@ -253,55 +254,125 @@ describe('Base editor', () => {
const
MyExt3
=
{
const
MyExt3
=
{
foo
:
foo2
,
foo
:
foo2
,
};
};
beforeEach
(()
=>
{
instance
=
editor
.
createInstance
({
el
:
editorEl
,
blobPath
,
blobContent
});
});
it
(
'
is extensible with the extensions
'
,
()
=>
{
describe
(
'
basic functionality
'
,
()
=>
{
expect
(
instance
.
foo
).
toBeUndefined
();
beforeEach
(()
=>
{
instance
=
editor
.
createInstance
({
el
:
editorEl
,
blobPath
,
blobContent
});
});
editor
.
use
(
MyExt1
);
it
(
'
is extensible with the extensions
'
,
()
=>
{
expect
(
instance
.
foo
).
toEqual
(
foo1
);
expect
(
instance
.
foo
).
toBeUndefined
();
});
it
(
'
does not fail if no extensions supplied
'
,
()
=>
{
instance
.
use
(
MyExt1
);
const
spy
=
jest
.
spyOn
(
global
.
console
,
'
error
'
);
expect
(
instance
.
foo
).
toEqual
(
foo1
);
editor
.
use
(
);
}
);
expect
(
spy
).
not
.
toHaveBeenCalled
();
it
(
'
does not fail if no extensions supplied
'
,
()
=>
{
});
const
spy
=
jest
.
spyOn
(
global
.
console
,
'
error
'
);
instance
.
use
();
it
(
'
is extensible with multiple extensions
'
,
()
=>
{
expect
(
spy
).
not
.
toHaveBeenCalled
();
expect
(
instance
.
foo
).
toBeUndefined
();
});
expect
(
instance
.
bar
).
toBeUndefined
();
editor
.
use
([
MyExt1
,
MyExt2
]);
it
(
'
is extensible with multiple extensions
'
,
()
=>
{
expect
(
instance
.
foo
).
toBeUndefined
();
expect
(
instance
.
bar
).
toBeUndefined
();
expect
(
instance
.
foo
).
toEqual
(
foo1
);
instance
.
use
([
MyExt1
,
MyExt2
]);
expect
(
instance
.
bar
).
toEqual
(
bar
);
});
it
(
'
uses the last definition of a method in case of an overlap
'
,
()
=>
{
expect
(
instance
.
foo
).
toEqual
(
foo1
);
editor
.
use
([
MyExt1
,
MyExt2
,
MyExt3
]);
expect
(
instance
.
bar
).
toEqual
(
bar
);
expect
(
instance
).
toEqual
(
});
expect
.
objectContaining
({
foo
:
foo2
,
it
(
'
uses the last definition of a method in case of an overlap
'
,
()
=>
{
bar
,
instance
.
use
([
MyExt1
,
MyExt2
,
MyExt3
]);
}),
expect
(
instance
).
toEqual
(
);
expect
.
objectContaining
({
foo
:
foo2
,
bar
,
}),
);
});
it
(
'
correctly resolves references withing extensions
'
,
()
=>
{
const
FunctionExt
=
{
inst
()
{
return
this
;
},
mod
()
{
return
this
.
getModel
();
},
};
instance
.
use
(
FunctionExt
);
expect
(
instance
.
inst
()).
toEqual
(
editor
.
instances
[
0
]);
});
});
});
it
(
'
correctly resolves references withing extensions
'
,
()
=>
{
describe
(
'
extensions as an instance parameter
'
,
()
=>
{
const
FunctionExt
=
{
let
editorExtensionSpy
;
inst
()
{
const
instanceConstructor
=
(
extensions
=
[])
=>
{
return
this
;
return
editor
.
createInstance
({
},
el
:
editorEl
,
mod
()
{
blobPath
,
return
this
.
getModel
();
blobContent
,
},
blobGlobalId
,
extensions
,
});
};
};
editor
.
use
(
FunctionExt
);
expect
(
instance
.
inst
()).
toEqual
(
editor
.
instances
[
0
]);
beforeEach
(()
=>
{
editorExtensionSpy
=
jest
.
spyOn
(
Editor
,
'
pushToImportsArray
'
).
mockImplementation
(
arr
=>
{
arr
.
push
(
Promise
.
resolve
({
default
:
{},
}),
);
});
});
it
.
each
([
undefined
,
[],
[
''
],
''
])(
'
does not fail and makes no fetch if extensions is %s
'
,
()
=>
{
instance
=
instanceConstructor
(
null
);
expect
(
editorExtensionSpy
).
not
.
toHaveBeenCalled
();
},
);
it
.
each
`
type | value | callsCount
${
'
simple string
'
}
|
${
'
foo
'
}
|
${
1
}
${
'
combined string
'
}
|
${
'
foo, bar
'
}
|
${
2
}
${
'
array of strings
'
}
|
${[
'
foo
'
,
'
bar
'
]}
|
${
2
}
`
(
'
accepts $type as an extension parameter
'
,
({
value
,
callsCount
})
=>
{
instance
=
instanceConstructor
(
value
);
expect
(
editorExtensionSpy
).
toHaveBeenCalled
();
expect
(
editorExtensionSpy
.
mock
.
calls
).
toHaveLength
(
callsCount
);
});
it
.
each
`
desc | path | expectation
${
'
~/editor
'
}
|
${
'
foo
'
}
|
${
'
~/editor/foo
'
}
${
'
~/CUSTOM_PATH with leading slash
'
}
|
${
'
/my_custom_path/bar
'
}
|
${
'
~/my_custom_path/bar
'
}
${
'
~/CUSTOM_PATH without leading slash
'
}
|
${
'
my_custom_path/delta
'
}
|
${
'
~/my_custom_path/delta
'
}
`
(
'
fetches extensions from $desc path
'
,
({
path
,
expectation
})
=>
{
instance
=
instanceConstructor
(
path
);
expect
(
editorExtensionSpy
).
toHaveBeenCalledWith
(
expect
.
any
(
Array
),
expectation
);
});
it
(
'
emits editor-ready event after all extensions were applied
'
,
async
()
=>
{
const
calls
=
[];
const
eventSpy
=
jest
.
fn
().
mockImplementation
(()
=>
{
calls
.
push
(
'
event
'
);
});
const
useSpy
=
jest
.
spyOn
(
editor
,
'
use
'
).
mockImplementation
(()
=>
{
calls
.
push
(
'
use
'
);
});
editorEl
.
addEventListener
(
'
editor-ready
'
,
eventSpy
);
instance
=
instanceConstructor
(
'
foo, bar
'
);
await
waitForPromises
();
expect
(
useSpy
.
mock
.
calls
).
toHaveLength
(
2
);
expect
(
calls
).
toEqual
([
'
use
'
,
'
use
'
,
'
event
'
]);
});
});
});
describe
(
'
multiple instances
'
,
()
=>
{
describe
(
'
multiple instances
'
,
()
=>
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment