<!doctype html>
<html>
<head>
	<title>Emmet for CodeMirror 5</title>
	<link rel="stylesheet" href="./node_modules/codemirror/lib/codemirror.css" />
	<link rel="stylesheet" href="./node_modules/codemirror/addon/hint/show-hint.css" />

	<script src="./node_modules/codemirror/lib/codemirror.js"></script>
	<script src="./node_modules/codemirror/mode/xml/xml.js"></script>
	<script src="./node_modules/codemirror/mode/css/css.js"></script>
	<script src="./node_modules/codemirror/mode/htmlmixed/htmlmixed.js"></script>
	<script src="./node_modules/codemirror/addon/hint/show-hint.js"></script>
	<script src="./dist/emmet-codemirror-plugin.js"></script>

	<style>
	.CodeMirror {
		border: 1px solid black;
	}

	.cm-delimit {
		color: #fa4;
	}

	/* Add subtle visual clue for marked Emmet abbreviation */
	.emmet-abbreviation {
		border-bottom: 1px dotted green;
	}

	/* Emmet completions styling */
	.emmet-label {
		display: inline-block;
		min-width: 100px;
	}

	.emmet-preview {
		margin-left: 15px;
		opacity: 0.6;
		display: inline-block;
		max-width: 300px;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.emmet-preview__expand {
		display: block;
		margin-left: 0;
		max-width: 400px;
		max-height: 5.5em;
		white-space: pre;
	}

	.emmet-open-tag,
	.emmet-close-tag {
		border-bottom: 1px dotted red;
	}
	</style>
</head>
<body>
	<h1>Emmet for CodeMirror 5</h1>

	<form><textarea id="code" name="code">
&lt;html style="color: green"&gt;
  &lt;style&gt;
    body {
	  padding: 10px;
	}
  &lt;/style&gt;
  &lt;!-- this is a comment --&gt;
  &lt;head&gt;
    &lt;title&gt;HTML Example&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    The indentation tries to be &lt;em&gt;somewhat &amp;quot;do what
    I mean&amp;quot;&lt;/em&gt;... but might not match your style.
  &lt;/body&gt;
&lt;/html&gt;
	</textarea></form>

	<script>
		var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
			mode : "text/html",
			lineNumbers : true,
			markTagPairs: true,
			autoRenameTags: true,
			extraKeys: {
				'Ctrl-Space': 'autocomplete',
				'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 syntaxes 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'
				}
			}
		});

		// Add completions provider for CodeMirror’s `show-hint` addon
		CodeMirror.registerGlobalHelper('hint', 'emmet', function(mode, editor) {
			// Tell `show-hint` module that current helper will provide completions
			return !!editor.getEmmetAbbreviation();
		}, function(editor, options) {
			// Activate auto-popup, if disabled (see below)
			const marker = editor.findEmmetMarker();
			if (!marker) {
				return;
			}

			clearTimeout(marker.popupDisableTimer);
			marker.autoPopupDisabled = false;

			const completions = editor.getEmmetCompletions();
			return completions && {
				from: completions.from,
				to: completions.to,
				// Transform Emmet completions to ones that supported by `show-hint`
				list: completions.list.map(function(completion) {
					return {
						from: completion.range.from,
						to: completion.range.to,
						render: function(elt) {
							var content = document.createDocumentFragment();
							var label = document.createElement('span');
							label.className = 'emmet-label';

							var preview = document.createElement('span');
							preview.className = 'emmet-preview';

							content.appendChild(label);
							content.appendChild(preview);

							if (completion.type === 'expanded-abbreviation') {
								// It’s an expanded abbreviation completion:
								// render preview for it
								label.className += ' emmet-label__expand';
								label.textContent = 'Expand abbreviation';

								preview.className += ' emmet-preview__expand';
								// Replace tab with a few spaces so preview would take
								// lesser space
								preview.textContent = completion.preview.replace(/\t/g, '  ');
							} else {
								// A regular snippet: render completion abbreviation
								// and its preview
								label.textContent = completion.label;
								preview.textContent = completion.preview;
							}

							elt.appendChild(content);
						},
						hint: function() {
							// Use completions’ `insert()` method to properly
							// insert Emmet completion
							completion.insert();
						}
					};
				})
			};
		});

		// Automatically display Emmet completions when cursor enters abbreviation
		// marker if `markEmmetAbbreviation` option was enabled (true by default)
		editor.on('cursorActivity', function() {
			if (editor.getOption('markEmmetAbbreviation')) {
				const marker = editor.findEmmetMarker();
				if (marker && !marker.autoPopupDisabled) {
					editor.showHint({ completeSingle: false });
				}
			}
		});

		// Automatic popup with expanded Emmet abbreviation might be very annoying
		// since almost any latin word can be Emmet abbreviation.
		// So when user hides completion popup with Escape key, we should mark
		// Emmet abbreviation marker under cursor as one that shouldn’t receive
		// automatic completion popup.
		// Since CodeMirror API does not allow us (easily) to detect if completion
		// popup was hidden because of user interaction (Esc key) or because it
		// must recalculate completions on user typing, we will use a timer hack
		editor.on('startCompletion', function() {
			var marker = editor.findEmmetMarker();
			if (marker) {
				clearTimeout(marker.popupDisableTimer);
				marker.popupDisableTimer = null;
			}
		});
		editor.on('endCompletion', function() {
			var marker = editor.findEmmetMarker();
			if (marker) {
				clearTimeout(marker.popupDisableTimer);
				marker.popupDisableTimer = setTimeout(function() {
					marker.autoPopupDisabled = true;
				}, 30);
			}
		});
	</script>
</body>
</html>