0.3.7 • Published 7 years ago

emmetio-codemirror-plugin-webextensions v0.3.7

Weekly downloads
3
License
MIT
Repository
github
Last release
7 years ago

Emmet 2 extension for CodeMirror editor

CodeMirror extension that adds Emmet support to text editor.


Extension development is sponsored by CodePen.


How to use

This extension can be installed as a regular npm module:

npm install --save @emmetio/codemirror-plugin

The package itself follows CodeMirror extension convention and simply registers new commands and some extension methods. In order to use Emmet, you should create CodeMirror instance and provide keymap with Emmet actions. Currently, this extension registers only 2 actions:

  • emmetExpandAbbreviation – expand abbreviation from current cursor position.
  • emmetInsertLineBreak – inserts formatted line break if cursor is between tags.

The package comes in to flavors: a stand-alone browser bundle and ES2015/CommonJS modules that you can use in your app.

If you’re building an app, you can use extension like this:

import CodeMirror from 'codemirror';
import emmet from '@emmetio/codemirror-plugin';

// Register extension on CodeMirror constructor
emmet(CodeMirror);

// Create editor instance and provide keymap for Emmet actions
const editor = CodeMirror.fromTextArea(document.getElementById('code'), {
	mode : "text/html",
	extraKeys: {
		'Tab': 'emmetExpandAbbreviation',
		'Enter': 'emmetInsertLineBreak'
	}
});

For a stand-alone, basic usage, simply add dist/emmet-codemirror-plugin.js file into your page:

<script src="codemirror.js"></script>
<script src="./dist/emmet-codemirror-plugin.js"></script>

<form>
	<textarea id="code" name="code"></textarea>
</form>

<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
	mode : "text/html",
	extraKeys: {
		'Tab': 'emmetExpandAbbreviation',
		'Enter': 'emmetInsertLineBreak'
	}
});
</script>

Autocomplete provider

The new Emmet 2 concept suggests that Emmet should be used as autocomplete provider: it gives user full control over Tab key, editors’ native snippets and provides real-time preview of expanded abbreviation.

CodeMirror doesn’t have native autocomplete support but provides fully optional show-hint module. To add autocomplete support into your CodeMirror instance, call .getEmmetCompletions() extension method in editor instance and use its result as a provider for autocomplete extension. This method returns object with the following properties:

  • from and to properties describe range of matched Emmet abbreviation in editor.
  • list contains list of completions with the following properties: type: type of completion item, either expanded-abbreviation or snippet. range: object with from and to properties that describe range of editor content to be replaced with current completion item. Note that for expanded-abbreviation item type this range matches full abbreviation, while for snippet type it matches only a part of abbreviation. label: completion display label. preview: preview of expanded completion item. * insert(): a method that applies current completion item to editor.

For a complete example of how to use Emmet completions with show-hint module, see example.html file.

Tag pair marking and renaming

Pass markTagPairs: true option to enable automatic HTML tag pair marking in editor: open and close tags will be marked with .emmet-open-tag and .emmet-close-tag classes respectively. If this option enabled (off by default), changing either open or close tag will automatically update the opposite part. To disable automatic renaming, pass autoRenameTags: false option:

const editor = CodeMirror.fromTextArea(document.getElementById("code"), {
	mode : "text/html",
	// Enable tag marking (off by default).
	markTagPairs: true,

	// Enable tag auto-rename (enabled by default).
	// Requires `markTagPairs` to be enabled
	autoRenameTags: true
});

Adding custom snippets

You can add custom Emmet snippets via emmet option when creating CodeMirror editor instance:

const editor = CodeMirror.fromTextArea(document.getElementById("code"), {
	mode : "text/html",
	extraKeys: {
		'Tab': 'emmetExpandAbbreviation',
		'Enter': 'emmetInsertLineBreak'
	},

	// Example of passing custom snippets to Emmet.
	// `markupSnippets` are used for markup languages like HTML, Slim, Pug etc.,
	// `stylesheetSnippets` are used for stylesheet syntaxes like CSS, LESS etc.
	// Since a single editor may contain mixed syntaxes, you should
	// explicitly separate markup and stylesheet snippets instead of passing
	// a single `snippets` property, as described in `@emmetio/expand-abbreviation`
	// module
	emmet: {
		markupSnippets: {
			foo: 'div.foo[bar=baz]'
		},
		stylesheetSnippets: {
			myp: 'my-super: property'
		}
	}
});

Note that markup and stylesheet snippet definitions are different. Markup snippets are written as Emmet abbreviations (e.g. you simply describe element name and its default attributes) while stylesheet snippets are aliases to CSS properties with optional keywords list, separated by | character. These keywords are used in abbreviation resolving process. For more examples, see @emmetio/snippets repo.

How it works

In order to provide a predictable completions list, this extension automatically marks Emmet abbreviation as a text marker when user types text in editor. This marker is automatically re-validated on change and destroyed when user edits different part of code. The marker has .emmet-abbreviation class and can be styled via CSS to give users a clue what part of text will be expanded as abbreviation. Also, this marker contains .model property with extracted and parsed abbreviation.

The main reason to use text marker is to allow user to edit entered abbreviation and maintain proper autocomplete and abbreviation expansion context. You can use .findEmmetMarker() extension method in editor instance to get abbreviation marker. It’s mostly used to automatically display autocomplete popup when cursor enters abbreviation: if there’s marker for given cursor position then there’s valid abbreviation to expand.

If you experience issues with abbreviation marker, you can disable it by passing markEmmetAbbreviation: false option when creating editor instance or by setting this option to false with editor.setOption() method.