Skip to content

Commit

Permalink
[emmet] Support all the features (#8155)
Browse files Browse the repository at this point in the history
* [emmet] Support all the features

* Fix TSLint errors

* [emmet] Fix problem with CSS `url()` without quotes

* [emmet] Do not save files without a name

* [emmet] Clarifying the method name

* [emmet] Add Promise error handler

* [emmet] Correct support for paths

* Fix TSLint errors

* Space before the closing bracket.

* More guidelines

* [emmet] Add class BasicEmmetEditorAction

* Fix bad copyright statement
  • Loading branch information
mrmlnc authored and egamma committed Jun 27, 2016
1 parent 845e94c commit 2a15286
Show file tree
Hide file tree
Showing 21 changed files with 735 additions and 132 deletions.
39 changes: 39 additions & 0 deletions src/vs/workbench/parts/emmet/node/actions/balance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

'use strict';

import nls = require('vs/nls');
import {BasicEmmetEditorAction} from '../emmetEditorAction';

import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
import {IEditorActionDescriptorData, ICommonCodeEditor} from 'vs/editor/common/editorCommon';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';

class BalanceInwardAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.balanceInward';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'balance_inward');
}
}

class BalanceOutwardAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.balanceOutward';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'balance_outward');
}
}

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(BalanceInwardAction,
BalanceInwardAction.ID,
nls.localize('balanceInward', "Emmet: Balance (inward)"), void 0, 'Emmet: Balance (inward)'));

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(BalanceOutwardAction,
BalanceOutwardAction.ID,
nls.localize('balanceOutward', "Emmet: Balance (outward)"), void 0, 'Emmet: Balance (outward)'));
120 changes: 120 additions & 0 deletions src/vs/workbench/parts/emmet/node/actions/base64.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

'use strict';

import nls = require('vs/nls');

import * as Paths from 'vs/base/common/paths';
import {fileExists} from 'vs/base/node/pfs';
import {createPath} from '../fileAccessor';
import {EmmetEditorAction} from '../emmetActions';
import {Action} from 'vs/base/common/actions';

import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
import {IEditorActionDescriptorData, ICommonCodeEditor} from 'vs/editor/common/editorCommon';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import {IQuickOpenService, IInputOptions} from 'vs/workbench/services/quickopen/common/quickOpenService';
import {IMessageService, Severity} from 'vs/platform/message/common/message';

class EncodeDecodeDataUrlAction extends EmmetEditorAction {

static ID = 'editor.emmet.action.encodeDecodeDataUrl';
private imageFilePath: string = null;

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor,
@IConfigurationService configurationService: IConfigurationService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IMessageService private messageService: IMessageService) {
super(descriptor, editor, configurationService);
}

public runEmmetAction(_module) {
const currentLine = this.editorAccessor.getCurrentLine();
if (!this.isDataURI(currentLine)) {
this.encodeDecode(_module);
return;
}

let options: IInputOptions = {
prompt: nls.localize('enterImagePath', "Enter path to file (absolute or relative)"),
placeHolder: nls.localize('path', "Path to file")
};

const quickPromise = this.quickOpenService.input(options)
.then(path => {
if (!this.isValidInput(path)) {
quickPromise.cancel();
}

this.imageFilePath = path;

const fullpath = createPath(this.editorAccessor.getFilePath(), path);
return fileExists(fullpath);
})
.then(status => {
if (!status) {
this.encodeDecode(_module, this.imageFilePath);
return;
}

const message = nls.localize('warnEscalation', "File **{0}** already exists. Do you want to overwrite the existing file?", this.imageFilePath);
const actions = [
new Action('cancel', nls.localize('cancel', "Cancel"), '', true),
new Action('ok', nls.localize('ok', "OK"), '', true, () => {
this.encodeDecode(_module, this.imageFilePath);
return null;
})
];
this.messageService.show(Severity.Warning, { message, actions });
});
}

public encodeDecode(_module: any, filepath?: string) {
this.editorAccessor.prompt = (): string => {
return filepath;
};

if (!_module.run('encode_decode_data_url', this.editorAccessor)) {
this.editorAccessor.noExpansionOccurred();
}
}

private isValidInput(input: any): boolean {
if (input === undefined) {
return false;
}

// Validate all segments of path without absolute and empty segments
// Valid: `images/test.png`, `./test.png`, `../images/test.png`, `\images\test.png`
let isValidFilePath = true;
const filePathSegments = Paths.normalize(input).split('/').filter(segment => {
return segment.length !== 0 && segment !== '..';
});

for (let i = 0; i < filePathSegments.length; i++) {
if (!Paths.isValidBasename(filePathSegments[i])) {
isValidFilePath = false;
break;
}
}

if (!isValidFilePath) {
const message = nls.localize('invalidFileNameError', "The name **{0}** is not valid as a file or folder name. Please choose a different name.", input);
this.messageService.show(Severity.Error, message);
return false;
}

return true;
}

private isDataURI(data: string): boolean {
return /(?:src=|url\()['"]?data:/.test(data);
}
}

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(EncodeDecodeDataUrlAction,
EncodeDecodeDataUrlAction.ID,
nls.localize('encodeDecodeDataUrl', "Emmet: Encode\\Decode data:URL image"), void 0, 'Emmet: Encode\\Decode data:URL image'));
39 changes: 39 additions & 0 deletions src/vs/workbench/parts/emmet/node/actions/editPoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

'use strict';

import nls = require('vs/nls');
import {BasicEmmetEditorAction} from '../emmetEditorAction';

import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
import {IEditorActionDescriptorData, ICommonCodeEditor} from 'vs/editor/common/editorCommon';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';

class PreviousEditPointAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.previousEditPoint';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'prev_edit_point');
}
}

class NextEditPointAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.nextEditPoint';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'next_edit_point');
}
}

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(PreviousEditPointAction,
PreviousEditPointAction.ID,
nls.localize('previousEditPoint', "Emmet: Previous Edit Point"), void 0, 'Emmet: Previous Edit Point'));

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(NextEditPointAction,
NextEditPointAction.ID,
nls.localize('nextEditPoint', "Emmet: Next Edit Point"), void 0, 'Emmet: Next Edit Point'));
26 changes: 26 additions & 0 deletions src/vs/workbench/parts/emmet/node/actions/evaluateMath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

'use strict';

import nls = require('vs/nls');
import {BasicEmmetEditorAction} from '../emmetEditorAction';

import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
import {IEditorActionDescriptorData, ICommonCodeEditor} from 'vs/editor/common/editorCommon';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';

class EvaluateMathAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.evaluateMath';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'evaluate_math_expression');
}
}

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(EvaluateMathAction,
EvaluateMathAction.ID,
nls.localize('evaluateMathExpression', "Emmet: Evaluate Math Expression"), void 0, 'Emmet: Evaluate Math Expression'));
45 changes: 45 additions & 0 deletions src/vs/workbench/parts/emmet/node/actions/expandAbbreviation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

'use strict';

import nls = require('vs/nls');
import {BasicEmmetEditorAction} from '../emmetEditorAction';

import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
import {IEditorActionDescriptorData, ICommonCodeEditor} from 'vs/editor/common/editorCommon';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';

import editorCommon = require('vs/editor/common/editorCommon');
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
import {KeyCode} from 'vs/base/common/keyCodes';
import {KbExpr} from 'vs/platform/keybinding/common/keybindingService';

class ExpandAbbreviationAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.expandAbbreviation';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'expand_abbreviation');
}
}

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(ExpandAbbreviationAction,
ExpandAbbreviationAction.ID,
nls.localize('expandAbbreviationAction', "Emmet: Expand Abbreviation"), void 0, 'Emmet: Expand Abbreviation'));


KeybindingsRegistry.registerCommandRule({
id: ExpandAbbreviationAction.ID,
weight: KeybindingsRegistry.WEIGHT.editorContrib(),
when: KbExpr.and(
KbExpr.has(editorCommon.KEYBINDING_CONTEXT_EDITOR_TEXT_FOCUS),
KbExpr.not(editorCommon.KEYBINDING_CONTEXT_EDITOR_HAS_NON_EMPTY_SELECTION),
KbExpr.not(editorCommon.KEYBINDING_CONTEXT_EDITOR_HAS_MULTIPLE_SELECTIONS),
KbExpr.not(editorCommon.KEYBINDING_CONTEXT_EDITOR_TAB_MOVES_FOCUS),
KbExpr.has('config.emmet.triggerExpansionOnTab')
),
primary: KeyCode.Tab
});
91 changes: 91 additions & 0 deletions src/vs/workbench/parts/emmet/node/actions/incrementDecrement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

'use strict';

import nls = require('vs/nls');
import {BasicEmmetEditorAction} from '../emmetEditorAction';

import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
import {IEditorActionDescriptorData, ICommonCodeEditor} from 'vs/editor/common/editorCommon';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';

class IncrementNumberByOneTenthAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.incrementNumberByOneTenth';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'increment_number_by_01');
}
}

class IncrementNumberByOneAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.incrementNumberByOne';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'increment_number_by_1');
}
}

class IncrementNumberByTenAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.incrementNumberByTen';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'increment_number_by_10');
}
}

class DecrementNumberByOneTenthAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.decrementNumberByOneTenth';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'decrement_number_by_01');
}
}

class DecrementNumberByOneAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.decrementNumberByOne';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'decrement_number_by_1');
}
}

class DecrementNumberByTenAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.decrementNumberByTen';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'decrement_number_by_10');
}
}

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(IncrementNumberByOneTenthAction,
IncrementNumberByOneTenthAction.ID,
nls.localize('incrementNumberByOneTenth', "Emmet: Increment by 0.1"), void 0, 'Emmet: Increment by 0.1'));

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(DecrementNumberByOneTenthAction,
DecrementNumberByOneTenthAction.ID,
nls.localize('decrementNumberByOneTenth', "Emmet: Decrement by 0.1"), void 0, 'Emmet: Decrement by 0.1'));

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(IncrementNumberByOneAction,
IncrementNumberByOneAction.ID,
nls.localize('incrementNumberByOne', "Emmet: Increment by 1"), void 0, 'Emmet: Increment by 1'));

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(DecrementNumberByOneAction,
DecrementNumberByOneAction.ID,
nls.localize('decrementNumberByOne', "Emmet: Decrement by 1"), void 0, 'Emmet: Decrement by 1'));

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(IncrementNumberByTenAction,
IncrementNumberByTenAction.ID,
nls.localize('incrementNumberByTen', "Emmet: Increment by 10"), void 0, 'Emmet: Increment by 10'));

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(DecrementNumberByTenAction,
DecrementNumberByTenAction.ID,
nls.localize('decrementNumberByTen', "Emmet: Decrement by 10"), void 0, 'Emmet: Decrement by 10'));
26 changes: 26 additions & 0 deletions src/vs/workbench/parts/emmet/node/actions/matchingPair.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

'use strict';

import nls = require('vs/nls');
import {BasicEmmetEditorAction} from '../emmetEditorAction';

import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
import {IEditorActionDescriptorData, ICommonCodeEditor} from 'vs/editor/common/editorCommon';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';

class GoToMatchingPairAction extends BasicEmmetEditorAction {

static ID = 'editor.emmet.action.matchingPair';

constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor, @IConfigurationService configurationService: IConfigurationService) {
super(descriptor, editor, configurationService, 'matching_pair');
}
}

CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(GoToMatchingPairAction,
GoToMatchingPairAction.ID,
nls.localize('matchingPair', "Emmet: Go to Matching Pair"), void 0, 'Emmet: Go to Matching Pair'));
Loading

0 comments on commit 2a15286

Please sign in to comment.