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
7aa8ff9b
Commit
7aa8ff9b
authored
Jan 24, 2022
by
Janis Altherr
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Handle path not found without throwing, accept array as path
Changelog: changed
parent
5a5cc407
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
117 additions
and
79 deletions
+117
-79
app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js
...s/javascripts/editor/extensions/source_editor_yaml_ext.js
+56
-38
spec/frontend/editor/source_editor_yaml_ext_spec.js
spec/frontend/editor/source_editor_yaml_ext_spec.js
+61
-41
No files found.
app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js
View file @
7aa8ff9b
...
@@ -19,33 +19,6 @@ export class YamlEditorExtension {
...
@@ -19,33 +19,6 @@ export class YamlEditorExtension {
return
'
YamlEditor
'
;
return
'
YamlEditor
'
;
}
}
/**
* Extends the source editor with capabilities for yaml files.
*
* @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
* @param {YamlEditorExtensionOptions} setupOptions
*/
onSetup
(
instance
,
setupOptions
=
{})
{
const
{
enableComments
=
false
,
highlightPath
=
null
,
model
=
null
}
=
setupOptions
;
this
.
enableComments
=
enableComments
;
this
.
highlightPath
=
highlightPath
;
this
.
model
=
model
;
if
(
model
)
{
this
.
initFromModel
(
instance
,
model
);
}
instance
.
onDidChangeModelContent
(()
=>
instance
.
onUpdate
());
}
initFromModel
(
instance
,
model
)
{
const
doc
=
new
Document
(
model
);
if
(
this
.
enableComments
)
{
YamlEditorExtension
.
transformComments
(
doc
);
}
instance
.
setValue
(
doc
.
toString
());
}
/**
/**
* @private
* @private
* This wraps long comments to a maximum line length of 80 chars.
* This wraps long comments to a maximum line length of 80 chars.
...
@@ -164,10 +137,10 @@ export class YamlEditorExtension {
...
@@ -164,10 +137,10 @@ export class YamlEditorExtension {
if
(
!
path
)
throw
Error
(
`No path provided.`
);
if
(
!
path
)
throw
Error
(
`No path provided.`
);
const
blob
=
instance
.
getValue
();
const
blob
=
instance
.
getValue
();
const
doc
=
parseDocument
(
blob
);
const
doc
=
parseDocument
(
blob
);
const
pathArray
=
toPath
(
path
);
const
pathArray
=
Array
.
isArray
(
path
)
?
path
:
toPath
(
path
);
if
(
!
doc
.
getIn
(
pathArray
))
{
if
(
!
doc
.
getIn
(
pathArray
))
{
throw
Error
(
`The node
${
path
}
could not be found inside the document.`
)
;
return
[
null
,
null
]
;
}
}
const
parentNode
=
doc
.
getIn
(
pathArray
.
slice
(
0
,
pathArray
.
length
-
1
));
const
parentNode
=
doc
.
getIn
(
pathArray
.
slice
(
0
,
pathArray
.
length
-
1
));
...
@@ -190,6 +163,33 @@ export class YamlEditorExtension {
...
@@ -190,6 +163,33 @@ export class YamlEditorExtension {
return
[
startLine
,
endLine
];
return
[
startLine
,
endLine
];
}
}
/**
* Extends the source editor with capabilities for yaml files.
*
* @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
* @param {YamlEditorExtensionOptions} setupOptions
*/
onSetup
(
instance
,
setupOptions
=
{})
{
const
{
enableComments
=
false
,
highlightPath
=
null
,
model
=
null
}
=
setupOptions
;
this
.
enableComments
=
enableComments
;
this
.
highlightPath
=
highlightPath
;
this
.
model
=
model
;
if
(
model
)
{
this
.
initFromModel
(
instance
,
model
);
}
instance
.
onDidChangeModelContent
(()
=>
instance
.
onUpdate
());
}
initFromModel
(
instance
,
model
)
{
const
doc
=
new
Document
(
model
);
if
(
this
.
enableComments
)
{
YamlEditorExtension
.
transformComments
(
doc
);
}
instance
.
setValue
(
doc
.
toString
());
}
setDoc
(
instance
,
doc
)
{
setDoc
(
instance
,
doc
)
{
if
(
this
.
enableComments
)
{
if
(
this
.
enableComments
)
{
YamlEditorExtension
.
transformComments
(
doc
);
YamlEditorExtension
.
transformComments
(
doc
);
...
@@ -202,18 +202,31 @@ export class YamlEditorExtension {
...
@@ -202,18 +202,31 @@ export class YamlEditorExtension {
}
}
}
}
highlight
(
instance
,
path
)
{
highlight
(
instance
,
path
,
keepOnNotFound
=
false
)
{
// IMPORTANT
// IMPORTANT
// removeHighlight and highlightLines both come from
// removeHighlight and highlightLines both come from
// SourceEditorExtension. So it has to be installed prior to this extension
// SourceEditorExtension. So it has to be installed prior to this extension
if
(
this
.
highlightPath
===
path
)
return
;
if
(
this
.
highlightPath
===
path
)
return
;
if
(
!
path
)
{
if
(
!
path
||
!
path
.
length
)
{
instance
.
removeHighlights
();
instance
.
removeHighlights
();
}
else
{
this
.
highlightPath
=
null
;
const
res
=
YamlEditorExtension
.
locate
(
instance
,
path
);
return
;
instance
.
highlightLines
(
res
);
}
}
this
.
highlightPath
=
path
||
null
;
const
[
startLine
,
endLine
]
=
YamlEditorExtension
.
locate
(
instance
,
path
);
if
(
startLine
===
null
)
{
// Path could not be found.
if
(
!
keepOnNotFound
)
{
instance
.
removeHighlights
();
this
.
highlightPath
=
null
;
}
return
;
}
instance
.
highlightLines
([
startLine
,
endLine
]);
this
.
highlightPath
=
path
;
}
}
provides
()
{
provides
()
{
...
@@ -283,18 +296,23 @@ export class YamlEditorExtension {
...
@@ -283,18 +296,23 @@ export class YamlEditorExtension {
* Add a line highlight style to the node specified by the path.
* Add a line highlight style to the node specified by the path.
*
*
* @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
* @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
* @param {string|null|false} path A path to a node of the Editor's value,
* @param {string|(string|number)[]|null|false} path A path to a node
* of the Editor's
* value,
* e.g. `"foo.bar[0]"`. If the value is falsy, this will remove all
* e.g. `"foo.bar[0]"`. If the value is falsy, this will remove all
* highlights.
* highlights.
* @param {boolean} [keepOnNotFound=false] If the passed path cannot
* be located, keep the previous highlight state
*/
*/
highlight
:
(
instance
,
path
)
=>
this
.
highlight
(
instance
,
path
),
highlight
:
(
instance
,
path
,
keepOnNotFound
)
=>
this
.
highlight
(
instance
,
path
,
keepOnNotFound
),
/**
/**
* Return the line numbers of a certain node identified by `path` within
* Return the line numbers of a certain node identified by `path` within
* the yaml.
* the yaml.
*
*
* @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
* @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
* @param {string} path A path to a node, eg. `foo.bar[0]`
* @param {string|(string|number)[]} path A path to a node, eg.
* `foo.bar[0]`
* @returns {number[]} Array following the schema `[firstLine, lastLine]`
* @returns {number[]} Array following the schema `[firstLine, lastLine]`
* (both inclusive)
* (both inclusive)
*
*
...
...
spec/frontend/editor/source_editor_yaml_ext_spec.js
View file @
7aa8ff9b
...
@@ -353,58 +353,78 @@ foo:
...
@@ -353,58 +353,78 @@ foo:
});
});
describe
(
'
highlight
'
,
()
=>
{
describe
(
'
highlight
'
,
()
=>
{
const
highlightPathOnSetup
=
'
abc
'
;
const
value
=
`foo:
const
value
=
`foo:
bar:
bar:
- baz
- baz
- boo
- boo
abc: def
abc: def
`
;
`
;
let
instance
;
let
instance
;
let
highlightLinesSpy
;
let
highlightLinesSpy
;
let
removeHighlightsSpy
;
let
removeHighlightsSpy
;
beforeEach
(()
=>
{
instance
=
getEditorInstanceWithExtension
({
highlightPath
:
highlightPathOnSetup
},
{
value
});
highlightLinesSpy
=
jest
.
fn
();
removeHighlightsSpy
=
jest
.
fn
();
spyOnApi
(
baseExtension
,
{
highlightLines
:
highlightLinesSpy
,
removeHighlights
:
removeHighlightsSpy
,
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
jest
.
clearAllMocks
();
jest
.
clearAllMocks
();
});
});
it
(
'
saves the highlighted path in highlightPath
'
,
()
=>
{
it
.
each
`
const
path
=
'
foo.bar
'
;
highlightPathOnSetup | path | keepOnNotFound | expectHighlightLinesToBeCalled | withLines | expectRemoveHighlightsToBeCalled | storedHighlightPath
instance
.
highlight
(
path
);
${
null
}
|
${
undefined
}
|
${
false
}
|
${
false
}
|
${
undefined
}
|
${
true
}
|
${
null
}
expect
(
yamlExtension
.
obj
.
highlightPath
).
toEqual
(
path
);
${
'
abc
'
}
|
${
'
abc
'
}
|
${
undefined
}
|
${
false
}
|
${
undefined
}
|
${
false
}
|
${
'
abc
'
}
});
${
null
}
|
${
null
}
|
${
false
}
|
${
false
}
|
${
undefined
}
|
${
false
}
|
${
null
}
${
null
}
|
${
''
}
|
${
false
}
|
${
false
}
|
${
undefined
}
|
${
true
}
|
${
null
}
it
(
'
calls highlightLines with a number of lines
'
,
()
=>
{
${
null
}
|
${
''
}
|
${
true
}
|
${
false
}
|
${
undefined
}
|
${
true
}
|
${
null
}
const
path
=
'
foo.bar
'
;
${
'
abc
'
}
|
${
''
}
|
${
false
}
|
${
false
}
|
${
undefined
}
|
${
true
}
|
${
null
}
instance
.
highlight
(
path
);
${
'
abc
'
}
|
${
'
foo.bar
'
}
|
${
false
}
|
${
true
}
|
${[
2
,
4
]}
|
${
false
}
|
${
'
foo.bar
'
}
expect
(
highlightLinesSpy
).
toHaveBeenCalledWith
(
instance
,
[
2
,
4
]);
${
'
abc
'
}
|
${[
'
foo
'
,
'
bar
'
]}
|
${
false
}
|
${
true
}
|
${[
2
,
4
]}
|
${
false
}
|
${[
'
foo
'
,
'
bar
'
]}
});
${
'
abc
'
}
|
${
'
invalid
'
}
|
${
true
}
|
${
false
}
|
${
undefined
}
|
${
false
}
|
${
'
abc
'
}
${
'
abc
'
}
|
${
'
invalid
'
}
|
${
false
}
|
${
false
}
|
${
undefined
}
|
${
true
}
|
${
null
}
it
(
'
calls removeHighlights if path is null
'
,
()
=>
{
${
'
abc
'
}
|
${
'
invalid
'
}
|
${
undefined
}
|
${
false
}
|
${
undefined
}
|
${
true
}
|
${
null
}
instance
.
highlight
(
null
);
${
'
abc
'
}
|
${[
'
invalid
'
]}
|
${
undefined
}
|
${
false
}
|
${
undefined
}
|
${
true
}
|
${
null
}
expect
(
removeHighlightsSpy
).
toHaveBeenCalledWith
(
instance
);
${
'
abc
'
}
|
${[
'
invalid
'
]}
|
${
true
}
|
${
false
}
|
${
undefined
}
|
${
false
}
|
${
'
abc
'
}
expect
(
highlightLinesSpy
).
not
.
toHaveBeenCalled
();
${
'
abc
'
}
|
${[]}
|
${
true
}
|
${
false
}
|
${
undefined
}
|
${
true
}
|
${
null
}
expect
(
yamlExtension
.
obj
.
highlightPath
).
toBeNull
();
${
'
abc
'
}
|
${[]}
|
${
false
}
|
${
false
}
|
${
undefined
}
|
${
true
}
|
${
null
}
});
`
(
'
returns correct result for highlightPathOnSetup=$highlightPathOnSetup, path=$path
'
+
it
(
'
throws an error if path is invalid and does not change the highlighted path
'
,
()
=>
{
'
and keepOnNotFound=$keepOnNotFound
'
,
expect
(()
=>
instance
.
highlight
(
'
invalidPath[0]
'
)).
toThrow
(
({
'
The node invalidPath[0] could not be found inside the document.
'
,
highlightPathOnSetup
,
);
path
,
expect
(
yamlExtension
.
obj
.
highlightPath
).
toEqual
(
highlightPathOnSetup
);
keepOnNotFound
,
expect
(
highlightLinesSpy
).
not
.
toHaveBeenCalled
();
expectHighlightLinesToBeCalled
,
expect
(
removeHighlightsSpy
).
not
.
toHaveBeenCalled
();
withLines
,
});
expectRemoveHighlightsToBeCalled
,
storedHighlightPath
,
})
=>
{
instance
=
getEditorInstanceWithExtension
(
{
highlightPath
:
highlightPathOnSetup
},
{
value
},
);
highlightLinesSpy
=
jest
.
fn
();
removeHighlightsSpy
=
jest
.
fn
();
spyOnApi
(
baseExtension
,
{
highlightLines
:
highlightLinesSpy
,
removeHighlights
:
removeHighlightsSpy
,
});
instance
.
highlight
(
path
,
keepOnNotFound
);
if
(
expectHighlightLinesToBeCalled
)
{
expect
(
highlightLinesSpy
).
toHaveBeenCalledWith
(
instance
,
withLines
);
}
else
{
expect
(
highlightLinesSpy
).
not
.
toHaveBeenCalled
();
}
if
(
expectRemoveHighlightsToBeCalled
)
{
expect
(
removeHighlightsSpy
).
toHaveBeenCalled
();
}
else
{
expect
(
removeHighlightsSpy
).
not
.
toHaveBeenCalled
();
}
expect
(
yamlExtension
.
obj
.
highlightPath
).
toEqual
(
storedHighlightPath
);
},
);
});
});
describe
(
'
locate
'
,
()
=>
{
describe
(
'
locate
'
,
()
=>
{
...
@@ -446,10 +466,10 @@ foo:
...
@@ -446,10 +466,10 @@ foo:
expect
(
instance
.
locate
(
path
)).
toEqual
(
expected
);
expect
(
instance
.
locate
(
path
)).
toEqual
(
expected
);
});
});
it
(
'
throws an error
if a path cannot be found inside the yaml
'
,
()
=>
{
it
(
'
returns [null, null]
if a path cannot be found inside the yaml
'
,
()
=>
{
const
path
=
'
baz[8]
'
;
const
path
=
'
baz[8]
'
;
const
instance
=
getEditorInstanceWithExtension
(
options
);
const
instance
=
getEditorInstanceWithExtension
(
options
);
expect
(
()
=>
instance
.
locate
(
path
)).
toThrow
(
);
expect
(
instance
.
locate
(
path
)).
toEqual
([
null
,
null
]
);
});
});
it
(
'
returns the expected line numbers for a path to an array entry inside the yaml
'
,
()
=>
{
it
(
'
returns the expected line numbers for a path to an array entry inside the yaml
'
,
()
=>
{
...
...
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