mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-28 09:35:38 -05:00
Notebook UI - Markdown toolbar - Headings dropdown (#11049)
* Adds heading dropdown to markdown toolbar. * Added a method specific to headings that places markdown at beginning of line selected. * Rewrote comment for my new method. * Revised code to support multi select for headers, similar to how unordered list is applied. Multi-line headings can be undone if the multi lines are selected. * Modified transformText to make single-line undo operation possible with just the cursor position. * Added utility methods to help determine if the selection is a line-only or multi-line. * Building isReplaceOperation to determine when preceeding characters need to be replaced with a new MarkdownButtonType. * Updated comments. * Applied changes written by Chris. * Reverted changes to earlier stage where heading addition works just like list item additions. * getExtendedSelectedText now returns an actual value in range for MarkdownLineType.EVERY_LINE. * Added conditional so that Preview element is updated only when Preview is enabled. * Updated tests for heading toolbar: heading 1, 2 and 3. * Removed code that could not be reached. * Corrected tests for headings. * wip (cherry picked from commit 43deb9635cc0eeebaffef22d4373f1f6ad713ace) * cleanup * fix error * Fix tests * Add more testing * delete * re-add Co-authored-by: chgagnon <chgagnon@microsoft.com>
This commit is contained in:
@@ -30,8 +30,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { IEditor } from 'vs/editor/common/editorCommon';
|
||||
import { NotebookEditorStub } from 'sql/workbench/contrib/notebook/test/testCommon';
|
||||
|
||||
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
|
||||
suite('MarkdownTextTransformer', () => {
|
||||
let markdownTextTransformer: MarkdownTextTransformer;
|
||||
@@ -74,7 +73,6 @@ suite('MarkdownTextTransformer', () => {
|
||||
// Couple widget with newly created text model
|
||||
widget.setModel(textModel);
|
||||
|
||||
// let textModel = widget.getModel() as TextModel;
|
||||
assert(!isUndefinedOrNull(widget.getModel()), 'Text model is undefined');
|
||||
});
|
||||
|
||||
@@ -90,22 +88,21 @@ suite('MarkdownTextTransformer', () => {
|
||||
testWithNoSelection(MarkdownButtonType.LINK, '[]()', true);
|
||||
testWithNoSelection(MarkdownButtonType.LINK, '');
|
||||
testWithNoSelection(MarkdownButtonType.UNORDERED_LIST, '- ', true);
|
||||
testWithNoSelection(MarkdownButtonType.UNORDERED_LIST, '- ');
|
||||
testWithNoSelection(MarkdownButtonType.UNORDERED_LIST, '');
|
||||
testWithNoSelection(MarkdownButtonType.ORDERED_LIST, '1. ', true);
|
||||
testWithNoSelection(MarkdownButtonType.ORDERED_LIST, '1. ');
|
||||
testWithNoSelection(MarkdownButtonType.ORDERED_LIST, '');
|
||||
testWithNoSelection(MarkdownButtonType.IMAGE, '![]()', true);
|
||||
testWithNoSelection(MarkdownButtonType.IMAGE, '');
|
||||
testWithNoSelection(MarkdownButtonType.HEADING1, '# ', true);
|
||||
testWithNoSelection(MarkdownButtonType.HEADING1, '');
|
||||
testWithNoSelection(MarkdownButtonType.HEADING2, '## ', true);
|
||||
testWithNoSelection(MarkdownButtonType.HEADING2, '');
|
||||
testWithNoSelection(MarkdownButtonType.HEADING3, '### ', true);
|
||||
testWithNoSelection(MarkdownButtonType.HEADING3, '');
|
||||
});
|
||||
|
||||
test('Transform text with one word selected', () => {
|
||||
testWithSingleWordSelected(MarkdownButtonType.BOLD, '**WORD**');
|
||||
testWithSingleWordSelected(MarkdownButtonType.ITALIC, '_WORD_');
|
||||
testWithSingleWordSelected(MarkdownButtonType.CODE, '```\nWORD\n```');
|
||||
testWithSingleWordSelected(MarkdownButtonType.HIGHLIGHT, '<mark>WORD</mark>');
|
||||
testWithSingleWordSelected(MarkdownButtonType.LINK, '[WORD]()');
|
||||
testWithSingleWordSelected(MarkdownButtonType.UNORDERED_LIST, '- WORD');
|
||||
testWithSingleWordSelected(MarkdownButtonType.ORDERED_LIST, '1. WORD');
|
||||
testWithSingleWordSelected(MarkdownButtonType.IMAGE, '![WORD]()');
|
||||
});
|
||||
|
||||
test('Transform text with multiple words selected', () => {
|
||||
@@ -128,6 +125,9 @@ suite('MarkdownTextTransformer', () => {
|
||||
testWithMultipleLinesSelected(MarkdownButtonType.UNORDERED_LIST, '- Multi\n- Lines\n- Selected');
|
||||
testWithMultipleLinesSelected(MarkdownButtonType.ORDERED_LIST, '1. Multi\n1. Lines\n1. Selected');
|
||||
testWithMultipleLinesSelected(MarkdownButtonType.IMAGE, '![Multi\nLines\nSelected]()');
|
||||
testWithMultipleLinesSelected(MarkdownButtonType.HEADING1, '# Multi\n# Lines\n# Selected');
|
||||
testWithMultipleLinesSelected(MarkdownButtonType.HEADING2, '## Multi\n## Lines\n## Selected');
|
||||
testWithMultipleLinesSelected(MarkdownButtonType.HEADING3, '### Multi\n### Lines\n### Selected');
|
||||
});
|
||||
|
||||
test('Ensure notebook editor returns expected object', () => {
|
||||
@@ -146,16 +146,26 @@ suite('MarkdownTextTransformer', () => {
|
||||
textModel.setValue('');
|
||||
}
|
||||
markdownTextTransformer.transformText(type);
|
||||
assert.equal(textModel.getValue(), expectedValue, `${MarkdownButtonType[type]} with no selection failed`);
|
||||
assert.equal(textModel.getValue(), expectedValue, `${MarkdownButtonType[type]} with no selection failed (setValue ${setValue})`);
|
||||
}
|
||||
|
||||
function testWithSingleWordSelected(type: MarkdownButtonType, expectedValue: string): void {
|
||||
let value = 'WORD';
|
||||
textModel.setValue(value);
|
||||
widget.setSelection({ startColumn: 1, startLineNumber: 1, endColumn: 5, endLineNumber: 1 });
|
||||
|
||||
// Test transformation (adding text)
|
||||
widget.setSelection({ startColumn: 1, startLineNumber: 1, endColumn: value.length + 1, endLineNumber: 1 });
|
||||
assert.equal(textModel.getValueInRange(widget.getSelection()), value, 'Expected selection is not found');
|
||||
markdownTextTransformer.transformText(type);
|
||||
assert.equal(textModel.getValue(), expectedValue, `${MarkdownButtonType[type]} with single word selection failed`);
|
||||
const textModelValue = textModel.getValue();
|
||||
assert.equal(textModelValue, expectedValue, `${MarkdownButtonType[type]} with single word selection failed`);
|
||||
|
||||
// Test undo (removing text)
|
||||
const valueRange = getValueRange(textModel, value);
|
||||
assert.notEqual(valueRange, undefined, 'Could not find value in model after transformation');
|
||||
widget.setSelection(valueRange);
|
||||
markdownTextTransformer.transformText(type);
|
||||
assert.equal(textModel.getValue(), value, `Undo operation for ${MarkdownButtonType[type]} with single word selection failed`);
|
||||
}
|
||||
|
||||
function testWithMultipleWordsSelected(type: MarkdownButtonType, expectedValue: string): void {
|
||||
@@ -165,6 +175,13 @@ suite('MarkdownTextTransformer', () => {
|
||||
assert.equal(textModel.getValueInRange(widget.getSelection()), value, 'Expected multi-word selection is not found');
|
||||
markdownTextTransformer.transformText(type);
|
||||
assert.equal(textModel.getValue(), expectedValue, `${MarkdownButtonType[type]} with multiple word selection failed`);
|
||||
|
||||
// Test undo (removing text)
|
||||
const valueRange = getValueRange(textModel, value);
|
||||
assert.notEqual(valueRange, undefined, 'Could not find value in model after transformation');
|
||||
widget.setSelection(valueRange);
|
||||
markdownTextTransformer.transformText(type);
|
||||
assert.equal(textModel.getValue(), value, `Undo operation for ${MarkdownButtonType[type]} with multiple word selection failed`);
|
||||
}
|
||||
|
||||
function testWithMultipleLinesSelected(type: MarkdownButtonType, expectedValue: string): void {
|
||||
@@ -174,6 +191,32 @@ suite('MarkdownTextTransformer', () => {
|
||||
assert.equal(textModel.getValueInRange(widget.getSelection()), value, 'Expected multi-line selection is not found');
|
||||
markdownTextTransformer.transformText(type);
|
||||
assert.equal(textModel.getValue(), expectedValue, `${MarkdownButtonType[type]} with multiple line selection failed`);
|
||||
|
||||
// Test undo (removing text)
|
||||
let valueRange = getValueRange(textModel, 'Multi');
|
||||
// Modify the range to include all the lines
|
||||
valueRange = new Range(valueRange.startLineNumber, valueRange.startColumn, valueRange.endLineNumber + 2, 9);
|
||||
assert.notEqual(valueRange, undefined, 'Could not find value in model after transformation');
|
||||
widget.setSelection(valueRange);
|
||||
markdownTextTransformer.transformText(type);
|
||||
assert.equal(textModel.getValue(), value, `Undo operation for ${MarkdownButtonType[type]} with multiple line selection failed`);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Searches the model for the specified string value and if found returns a range for the last
|
||||
* occurence of that value.
|
||||
* @param textModel The model to search
|
||||
* @param value The value to search for
|
||||
*/
|
||||
function getValueRange(textModel: TextModel, value: string): Range | undefined {
|
||||
const linesContent = textModel.getLinesContent();
|
||||
let range = undefined;
|
||||
linesContent.forEach((line, index) => {
|
||||
const valueIndex = line.indexOf(value);
|
||||
if (valueIndex >= 0) {
|
||||
range = new Range(index + 1, valueIndex + 1, index + 1, valueIndex + value.length + 1);
|
||||
}
|
||||
});
|
||||
return range;
|
||||
}
|
||||
Reference in New Issue
Block a user