<!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"> <html style="color: green"> <style> body { padding: 10px; } </style> <!-- this is a comment --> <head> <title>HTML Example</title> </head> <body> The indentation tries to be <em>somewhat &quot;do what I mean&quot;</em>... but might not match your style. </body> </html> </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>