├── .gitignore
├── .travis.yml
├── LICENSE.txt
├── README.md
├── generate-menu.js
├── keymaps
└── emmet.cson
├── lib
├── editor-proxy.coffee
├── emmet.coffee
├── interactive.js
└── prompt.coffee
├── menus
└── emmet.json
├── package.json
├── spec
├── emmet-spec.coffee
└── fixtures
│ ├── abbreviation
│ ├── after
│ │ ├── anchor-class-expand.html
│ │ ├── css-abbrv.css
│ │ ├── header-expand.html
│ │ ├── html-abbrv.html
│ │ ├── multi-line.html
│ │ ├── php-in-html.php
│ │ ├── sass-test.sass
│ │ └── vanilla-php.php
│ └── before
│ │ ├── anchor-class-expand.html
│ │ ├── css-abbrv.css
│ │ ├── header-expand.html
│ │ ├── html-abbrv.html
│ │ ├── multi-line.html
│ │ ├── php-in-html.php
│ │ ├── sass-test.sass
│ │ └── vanilla-php.php
│ ├── balance
│ └── sample.html
│ ├── edit-points
│ └── edit-points.html
│ ├── encode-decode-data-url
│ ├── after
│ │ └── encode-decode-data-url.css
│ ├── barrel.png
│ └── before
│ │ └── encode-decode-data-url.css
│ ├── evaluate-math-expression
│ └── evaluate-math-expression.html
│ ├── increment-decrement-numbers
│ └── increment-decrement-numbers.css
│ ├── merge-lines
│ ├── after
│ │ └── merge-lines.html
│ └── before
│ │ └── merge-lines.html
│ ├── reflect-css-value
│ ├── after
│ │ └── reflect-css-value.css
│ └── before
│ │ └── reflect-css-value.css
│ ├── remove-tag
│ ├── after
│ │ ├── remove-tag-once.html
│ │ └── remove-tag-twice.html
│ └── before
│ │ └── remove-tag.html
│ ├── select-item
│ ├── select-item.css
│ └── select-item.html
│ ├── split-join-tag
│ └── split-join-tag.html
│ ├── tabbing.html
│ ├── update-image-size
│ ├── after
│ │ ├── update-image-size.css
│ │ └── update-image-size.html
│ ├── before
│ │ ├── update-image-size.css
│ │ └── update-image-size.html
│ └── raptor_dunk.jpg
│ ├── update-tag
│ ├── after
│ │ └── update-tag.html
│ └── before
│ │ └── update-tag.html
│ └── wrap-with-abbreviation
│ ├── after
│ └── wrap-with-abbreviation.html
│ └── before
│ └── wrap-with-abbreviation.html
└── styles
└── emmet.less
/.gitignore:
--------------------------------------------------------------------------------
1 | lib-cov
2 | *.seed
3 | *.log
4 | *.csv
5 | *.dat
6 | *.out
7 | *.pid
8 | *.gz
9 |
10 | pids
11 | logs
12 | results
13 |
14 | node_modules/
15 | npm-debug.log
16 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | script: 'curl -s -H "Authorization: token $ATOM_ACCESS_TOKEN" -H "Accept: application/vnd.github.v3.raw"
3 | https://api.github.com/repos/atom/apm/contents/script/build-package | sh'
4 | env:
5 | global:
6 | secure: LrQO6c1B6B/6cAAf2qLc8qE+En43+m2yu+y5jghl2QEk3GCxUFrt25QLpbC0Uo2EPaERVt5E60pMcerjSyF0mQCeM8z5zjd+LxQJDruiJ6I9KDhSynGWEgcf6uYZmOyTiNyj8EzS7AHm5Ap3weHxsfi+TfhjNzL15PEFAOomjIY=
7 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Garen J. Torikian
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Emmet plugin Atom editor
2 |
3 | [Emmet](http://emmet.io) support for [Atom](http://atom.io).
4 |
5 | ## Installation
6 |
7 | * In Atom, open *Preferences* (*Settings* on Windows)
8 | * Go to *Install* section
9 | * Search for `Emmet` package. Once it found, click `Install` button to install package.
10 |
11 | ### Manual installation
12 |
13 | You can install the latest Emmet version manually from console:
14 |
15 | ```bash
16 | cd ~/.atom/packages
17 | git clone https://github.com/emmetio/emmet-atom
18 | cd emmet-atom
19 | npm install
20 | ```
21 |
22 | Then restart Atom editor.
23 |
24 | ## Features:
25 |
26 | * Expand abbreviations by Tab key.
27 | * Multiple cursor support: most [Emmet actions](http://docs.emmet.io/actions/) like Expand Abbreviation, Wrap with Abbreviation, Update Tag can run in multi-cursor mode.
28 | * Interactive actions (Interactive Expand Abbreviation, Wrap With Abbreviation, Update Tag) allows you to preview result real-time as you type.
29 | * Better tabstops in generated content: when abbreviation expanded, hit Tab key to quickly traverse between important code points.
30 | * [Emmet v1.1 core](http://emmet.io/blog/beta-v1-1/).
31 |
32 | Please report any problems at [issue tracker](https://github.com/emmetio/emmet-atom/issues).
33 |
34 | ## Tab key
35 |
36 | Currently, Emmet expands abbreviations by Tab key only for HTML, CSS, Sass/SCSS and LESS syntaxes. Tab handler scope is limited because it overrides default snippets.
37 |
38 | If you want to make Emmet expand abbreviations with Tab key for other syntaxes, you can do the following:
39 |
40 | 1. Use *Open Your Keymap* menu item to open your custom `keymap.cson` file.
41 | 2. Add the following section into it:
42 |
43 | ```coffee
44 | 'atom-text-editor[data-grammar="YOUR GRAMMAR HERE"]:not([mini])':
45 | 'tab': 'emmet:expand-abbreviation-with-tab'
46 | ```
47 |
48 | Replace `YOUR GRAMMAR HERE` with actual grammar attribute value. The easiest way to get grammar name of currently opened editor is to open DevTools and find corresponding `` element: it will contain `data-grammar` attribute with value you need. For example, for HTML syntax it’s a `text html basic`.
49 |
50 | You can add as many sections as you like for different syntaxes. Note that default snippets will no longer work, but you can add [your own snippets in Emmet](http://docs.emmet.io/customization/).
51 |
52 | ## Default Keybindings
53 |
54 | You can change these in Preferences > Keybindings.
55 |
56 | Command | Darwin | Linux/Windows
57 | ------- | ------ | -------------
58 | Expand Abbreviation | tab or shift + ⌘ + e | tab or ctrl + e
59 | Expand Abbreviation (interactive) | alt + ⌘ + enter | ctrl + alt + enter
60 | Wrap with Abbreviation | ctrl + w | ctrl + alt + w
61 | Balance (outward) | ctrl + d | ctrl + shift + e
62 | Balance (inward) | alt + d | ctrl + shift + 0
63 | Go to Matching Pair | ctrl + alt + j | ctrl + alt + j
64 | Next Edit Point | ctrl + → | ctrl + alt + →
65 | Previous Edit Point | ctrl + ← | ctrl + alt + ←
66 | Select Next Item | ctrl + shift + → | ctrl + shift + .
67 | Select Previous Item | ctrl + shift + ← | ctrl + shift + ,
68 | Toggle Comment | ⌘ + / | ctrl + shift + /
69 | Split/Join Tag | shift + ⌘ + j | ctrl + shift + `
70 | Remove Tag | ⌘ + ' | ctrl + shift + ;
71 | Evaluate Math Expression | shift + ⌘ + y | ctrl + shift + y
72 | Increment Number by 0.1 | ctrl + alt + ↑ | alt + ↑
73 | Decrement Number by 0.1 | ctrl + alt + ↓ | alt + ↓
74 | Increment Number by 1 | ctrl + alt + ⌘ + ↑ | ctrl + ↑
75 | Decrement Number by 1 | ctrl + alt + ⌘ + ↓ | ctrl + ↓
76 | Increment Number by 10 | ctrl + alt + ⌘ + shift + ↑ | shift + alt + ↑
77 | Decrement Number by 10 | ctrl + alt + ⌘ + shift + ↓ | shift + alt + ↓
78 | Reflect CSS value | shift + ⌘ + r | ctrl + shift + r
79 | Update Image Size | ctrl + i | ctrl + u
80 | Encode/Decode image to data:URL | ctrl + shift + i | ctrl + '
81 | Update Tag | ctrl + shift + u | ctrl + shift + '
82 | Merge Lines | shift + ⌘ + m | ctrl + shift + m
83 |
84 | All actions and their keyboard shortcuts are available under Packages > Emmet menu item.
85 |
86 | ## Extensions support
87 |
88 | You can easily [extend](http://docs.emmet.io/customization/) Emmet with new actions and filters or customize existing ones. In Preferences > Emmet, set Extensions path to folder with Emmet extensions. By default, it’s `~/emmet`, e.g. `emmet` folder in your system HOME folder.
89 |
--------------------------------------------------------------------------------
/generate-menu.js:
--------------------------------------------------------------------------------
1 | // Generates Atom menu file from Emmet action list
2 | var fs = require('fs');
3 | var path = require('path');
4 | var actions = require('emmet/lib/action/main');
5 |
6 | function generateMenu(menu) {
7 | return menu.map(function(item) {
8 | if (item.type == 'action') {
9 | return {
10 | label: item.label,
11 | command: 'emmet:' + item.name.replace(/_/g, '-')
12 | };
13 | }
14 |
15 | if (item.type == 'submenu') {
16 | return {
17 | label: item.name,
18 | submenu: generateMenu(item.items)
19 | };
20 | }
21 | });
22 | }
23 |
24 | var menu = {
25 | 'menu': [{
26 | label: 'Packages',
27 | submenu: [{
28 | label: 'Emmet',
29 | submenu: generateMenu(actions.getMenu()).concat([{
30 | label: 'Interactive Expand Abbreviation',
31 | command: 'emmet:interactive-expand-abbreviation'
32 | }])
33 | }]
34 | }]
35 | };
36 |
37 | var menuFile = path.join(__dirname, 'menus', 'emmet.json');
38 | fs.writeFileSync(menuFile, JSON.stringify(menu, null, '\t'), {encoding: 'utf8'});
39 |
40 | console.log('Menu file "%s" generated successfully', menuFile);
--------------------------------------------------------------------------------
/keymaps/emmet.cson:
--------------------------------------------------------------------------------
1 | 'atom-text-editor:not([mini])':
2 | 'ctrl-e': 'emmet:expand-abbreviation'
3 | 'ctrl-shift-e': 'emmet:balance-outward'
4 | 'ctrl-shift-0': 'emmet:balance-inward'
5 | 'ctrl-alt-j': 'emmet:matching-pair'
6 | 'ctrl-alt-right': 'emmet:next-edit-point'
7 | 'ctrl-alt-left': 'emmet:prev-edit-point'
8 | 'ctrl-shift-`': 'emmet:split-join-tag'
9 | 'ctrl-shift-;': 'emmet:remove-tag'
10 | 'ctrl-shift-y': 'emmet:evaluate-math-expression'
11 | 'alt-up': 'emmet:increment-number-by-01'
12 | 'alt-down': 'emmet:decrement-number-by-01'
13 | 'ctrl-up': 'emmet:increment-number-by-1'
14 | 'ctrl-down': 'emmet:decrement-number-by-1'
15 | 'alt-shift-up': 'emmet:increment-number-by-10'
16 | 'alt-shift-down': 'emmet:decrement-number-by-10'
17 | 'ctrl-shift-.': 'emmet:select-next-item'
18 | 'ctrl-shift-,': 'emmet:select-previous-item'
19 | 'ctrl-shift-r': 'emmet:reflect-css-value'
20 | 'ctrl-u': 'emmet:update-image-size'
21 | "ctrl-'": 'emmet:encode-decode-data-url'
22 | "ctrl-shift-'": 'emmet:update-tag'
23 | 'ctrl-shift-m': 'emmet:merge-lines'
24 | 'ctrl-alt-w': 'emmet:wrap-with-abbreviation'
25 | 'ctrl-alt-enter': 'emmet:interactive-expand-abbreviation'
26 |
27 | 'atom-pane atom-text-editor:not([mini])':
28 | 'ctrl-shift-/': 'emmet:toggle-comment'
29 |
30 | # Override Enter key for specific syntaxes only
31 | 'atom-pane atom-text-editor[data-grammar~="html"]:not([mini]):not(.autocomplete-active), atom-pane atom-text-editor[data-grammar~="xml"]:not([mini]):not(.autocomplete-active)':
32 | 'enter': 'emmet:insert-formatted-line-break-only'
33 |
34 | # language-specific Tab triggers
35 | # you can add more triggers by changing `grammar` attribute values
36 | 'atom-text-editor[data-grammar="text html basic"]:not([mini]), atom-text-editor[data-grammar~="angular"]:not([mini]), atom-text-editor[data-grammar~="erb"]:not([mini]), atom-text-editor[data-grammar~="jade"]:not([mini]), atom-text-editor[data-grammar~="css"]:not([mini]), atom-text-editor[data-grammar~="stylus"]:not([mini]), atom-text-editor[data-grammar~="sass"]:not([mini]), atom-text-editor[data-grammar~="scss"]:not([mini])':
37 | 'tab': 'emmet:expand-abbreviation-with-tab'
38 |
39 | '.platform-darwin atom-text-editor:not([mini])':
40 | 'cmd-shift-e': 'emmet:expand-abbreviation'
41 | 'ctrl-d': 'emmet:balance-outward'
42 | 'alt-d': 'emmet:balance-inward'
43 | 'ctrl-right': 'emmet:next-edit-point'
44 | 'ctrl-left': 'emmet:prev-edit-point'
45 | "cmd-shift-j": 'emmet:split-join-tag'
46 | "cmd-'": 'emmet:remove-tag'
47 | 'cmd-shift-y': 'emmet:evaluate-math-expression'
48 | 'ctrl-alt-up': 'emmet:increment-number-by-01'
49 | 'ctrl-alt-down': 'emmet:decrement-number-by-01'
50 | 'ctrl-alt-cmd-up': 'emmet:increment-number-by-1'
51 | 'ctrl-alt-cmd-down': 'emmet:decrement-number-by-1'
52 | 'ctrl-alt-cmd-shift-up': 'emmet:increment-number-by-10'
53 | 'ctrl-alt-cmd-shift-down': 'emmet:decrement-number-by-10'
54 | 'ctrl-shift-right': 'emmet:select-next-item'
55 | 'ctrl-shift-left': 'emmet:select-previous-item'
56 | 'cmd-shift-r': 'emmet:reflect-css-value'
57 | 'ctrl-i': 'emmet:update-image-size'
58 | "ctrl-shift-i": 'emmet:encode-decode-data-url'
59 | 'ctrl-shift-u': 'emmet:update-tag'
60 | 'cmd-shift-m': 'emmet:merge-lines'
61 | 'ctrl-w': 'emmet:wrap-with-abbreviation'
62 | 'alt-cmd-enter': 'emmet:interactive-expand-abbreviation'
63 |
64 | '.platform-darwin atom-pane atom-text-editor:not([mini])':
65 | 'cmd-/': 'emmet:toggle-comment'
66 |
--------------------------------------------------------------------------------
/lib/editor-proxy.coffee:
--------------------------------------------------------------------------------
1 | {Point, Range} = require 'atom'
2 | path = require 'path'
3 |
4 | emmet = require 'emmet'
5 | utils = require 'emmet/lib/utils/common'
6 | tabStops = require 'emmet/lib/assets/tabStops'
7 | resources = require 'emmet/lib/assets/resources'
8 | editorUtils = require 'emmet/lib/utils/editor'
9 | actionUtils = require 'emmet/lib/utils/action'
10 |
11 | insertSnippet = (snippet, editor) ->
12 | atom.packages.getLoadedPackage('snippets')?.mainModule?.insert(snippet, editor)
13 |
14 | # Fetch expansions and assign to editor
15 | editor.snippetExpansion = atom.packages.getLoadedPackage('snippets')?.mainModule?.getExpansions(editor)[0]
16 |
17 | visualize = (str) ->
18 | str
19 | .replace(/\t/g, '\\t')
20 | .replace(/\n/g, '\\n')
21 | .replace(/\s/g, '\\s')
22 |
23 | # Normalizes text before it goes to editor: replaces indentation
24 | # and newlines with ones used in editor
25 | # @param {String} text Text to normalize
26 | # @param {Editor} editor Brackets editor instance
27 | # @return {String}
28 | normalize = (text, editor) ->
29 | editorUtils.normalize text,
30 | indentation: editor.getTabText(),
31 | newline: '\n'
32 |
33 | # Proprocess text data that should be used as snippet content
34 | # Currently, Atom’s snippets implementation has the following issues:
35 | # * multiple $0 are not treated as distinct final tabstops
36 | preprocessSnippet = (value) ->
37 | order = []
38 |
39 | tabstopOptions =
40 | tabstop: (data) ->
41 | group = parseInt(data.group, 10)
42 | if group is 0
43 | order.push(-1)
44 | group = order.length
45 | else
46 | order.push(group) if order.indexOf(group) is -1
47 | group = order.indexOf(group) + 1
48 |
49 | placeholder = data.placeholder or ''
50 | if placeholder
51 | # recursively update nested tabstops
52 | placeholder = tabStops.processText(placeholder, tabstopOptions)
53 |
54 | if placeholder then "${#{group}:#{placeholder}}" else "${#{group}}"
55 |
56 | escape: (ch) ->
57 | if ch == '$' then '\\$' else ch
58 |
59 | tabStops.processText(value, tabstopOptions)
60 |
61 | module.exports =
62 | setup: (@editor, @selectionIndex=0) ->
63 | buf = @editor.getBuffer()
64 | bufRanges = @editor.getSelectedBufferRanges()
65 | @_selection =
66 | index: 0
67 | saved: new Array(bufRanges.length)
68 | bufferRanges: bufRanges
69 | indexRanges: bufRanges.map (range) ->
70 | start: buf.characterIndexForPosition(range.start)
71 | end: buf.characterIndexForPosition(range.end)
72 |
73 | # Executes given function for every selection
74 | exec: (fn) ->
75 | ix = @_selection.bufferRanges.length - 1
76 | @_selection.saved = []
77 | success = true
78 | while ix >= 0
79 | @_selection.index = ix
80 | if fn(@_selection.index) is false
81 | success = false
82 | break
83 | ix--
84 |
85 | if success and @_selection.saved.length > 1
86 | @_setSelectedBufferRanges(@_selection.saved)
87 |
88 | _setSelectedBufferRanges: (sels) ->
89 | filteredSels = sels.filter (s) -> !!s
90 | if filteredSels.length
91 | @editor.setSelectedBufferRanges(filteredSels)
92 |
93 | _saveSelection: (delta) ->
94 | @_selection.saved[@_selection.index] = @editor.getSelectedBufferRange()
95 | if delta
96 | i = @_selection.index
97 | delta = Point.fromObject([delta, 0])
98 | while ++i < @_selection.saved.length
99 | range = @_selection.saved[i]
100 | if range
101 | @_selection.saved[i] = new Range(range.start.translate(delta), range.end.translate(delta))
102 |
103 | selectionList: ->
104 | @_selection.indexRanges
105 |
106 | # Returns the current caret position.
107 | getCaretPos: ->
108 | @getSelectionRange().start
109 |
110 | # Sets the current caret position.
111 | setCaretPos: (pos) ->
112 | @createSelection(pos)
113 |
114 | # Fetches the character indexes of the selected text.
115 | # Returns an {Object} with `start` and `end` properties.
116 | getSelectionRange: ->
117 | @_selection.indexRanges[@_selection.index]
118 |
119 | getSelectionBufferRange: ->
120 | @_selection.bufferRanges[@_selection.index]
121 |
122 | # Creates a selection from the `start` to `end` character indexes.
123 | #
124 | # If `end` is ommited, this method should place a caret at the `start` index.
125 | #
126 | # start - A {Number} representing the starting character index
127 | # end - A {Number} representing the ending character index
128 | createSelection: (start, end=start) ->
129 | sels = @_selection.bufferRanges
130 | buf = @editor.getBuffer()
131 | sels[@_selection.index] = new Range(buf.positionForCharacterIndex(start), buf.positionForCharacterIndex(end))
132 | @_setSelectedBufferRanges(sels)
133 |
134 | # Returns the currently selected text.
135 | getSelection: ->
136 | @editor.getTextInBufferRange(@getSelectionBufferRange())
137 |
138 | # Fetches the current line's start and end indexes.
139 | #
140 | # Returns an {Object} with `start` and `end` properties
141 | getCurrentLineRange: ->
142 | sel = @getSelectionBufferRange()
143 | row = sel.getRows()[0]
144 | lineLength = @editor.lineTextForBufferRow(row).length
145 | index = @editor.getBuffer().characterIndexForPosition({row: row, column: 0})
146 | return {
147 | start: index
148 | end: index + lineLength
149 | }
150 |
151 | # Returns the current line.
152 | getCurrentLine: ->
153 | sel = @getSelectionBufferRange()
154 | row = sel.getRows()[0]
155 | return @editor.lineTextForBufferRow(row)
156 |
157 | # Returns the editor content.
158 | getContent: ->
159 | return @editor.getText()
160 |
161 | # Replace the editor's content (or part of it, if using `start` to
162 | # `end` index).
163 | #
164 | # If `value` contains `caret_placeholder`, the editor puts a caret into
165 | # this position. If you skip the `start` and `end` arguments, the whole target's
166 | # content is replaced with `value`.
167 | #
168 | # If you pass just the `start` argument, the `value` is placed at the `start` string
169 | # index of thr current content.
170 | #
171 | # If you pass both `start` and `end` arguments, the corresponding substring of
172 | # the current target's content is replaced with `value`.
173 | #
174 | # value - A {String} of content you want to paste
175 | # start - The optional start index {Number} of the editor's content
176 | # end - The optional end index {Number} of the editor's content
177 | # noIdent - An optional {Boolean} which, if `true`, does not attempt to auto indent `value`
178 | replaceContent: (value, start, end, noIndent) ->
179 | unless end?
180 | end = unless start? then @getContent().length else start
181 | start = 0 unless start?
182 |
183 | value = normalize(value, @editor)
184 | buf = @editor.getBuffer()
185 | changeRange = new Range(
186 | Point.fromObject(buf.positionForCharacterIndex(start)),
187 | Point.fromObject(buf.positionForCharacterIndex(end))
188 | )
189 |
190 | oldValue = @editor.getTextInBufferRange(changeRange)
191 | buf.setTextInRange(changeRange, '')
192 | # Before inserting snippet we have to reset all available selections
193 | # to insert snippent right in required place. Otherwise snippet
194 | # will be inserted for each selection in editor
195 |
196 | # Right after that we should save first available selection as buffer range
197 | caret = buf.positionForCharacterIndex(start)
198 | @editor.setSelectedBufferRange(new Range(caret, caret))
199 | insertSnippet preprocessSnippet(value), @editor
200 | @_saveSelection(utils.splitByLines(value).length - utils.splitByLines(oldValue).length)
201 | value
202 |
203 | getGrammar: ->
204 | @editor.getGrammar().scopeName.toLowerCase()
205 |
206 | # Returns the editor's syntax mode.
207 | getSyntax: ->
208 | scope = @getCurrentScope().join(' ')
209 | return 'xsl' if ~scope.indexOf('xsl')
210 | return 'jsx' if not /\bstring\b/.test(scope) && /\bsource\.(js|ts)x?\b/.test(scope)
211 |
212 | sourceSyntax = scope.match(/\bsource\.([\w\-]+)/)?[0]
213 |
214 | if not /\bstring\b/.test(scope) && sourceSyntax && resources.hasSyntax(sourceSyntax)
215 | syntax = sourceSyntax;
216 | else
217 | # probe syntax based on current selector
218 | m = scope.match(/\b(source|text)\.[\w\-\.]+/)
219 | syntax = m?[0].split('.').reduceRight (result, token) ->
220 | result or (token if resources.hasSyntax token)
221 | , null
222 |
223 | actionUtils.detectSyntax(@, syntax or 'html')
224 |
225 | getCurrentScope: ->
226 | range = @_selection.bufferRanges[@_selection.index]
227 | @editor.scopeDescriptorForBufferPosition(range.start).getScopesArray()
228 |
229 | # Returns the current output profile name
230 | #
231 | # See emmet.setupProfile for more information.
232 | getProfileName: ->
233 | return if @getCurrentScope().some((scope) -> /\bstring\.quoted\b/.test scope) then 'line' else actionUtils.detectProfile(@)
234 |
235 | # Returns the current editor's file path
236 | getFilePath: ->
237 | # is there a better way to get this?
238 | @editor.buffer.file.path
239 |
--------------------------------------------------------------------------------
/lib/emmet.coffee:
--------------------------------------------------------------------------------
1 | path = require 'path'
2 | fs = require 'fs'
3 | {CompositeDisposable} = require 'atom'
4 |
5 | emmet = require 'emmet'
6 | emmetActions = require 'emmet/lib/action/main'
7 | resources = require 'emmet/lib/assets/resources'
8 |
9 | editorProxy = require './editor-proxy'
10 | # interactive = require './interactive'
11 |
12 | singleSelectionActions = [
13 | 'prev_edit_point', 'next_edit_point', 'merge_lines',
14 | 'reflect_css_value', 'select_next_item', 'select_previous_item',
15 | 'wrap_with_abbreviation', 'update_tag'
16 | ]
17 |
18 | toggleCommentSyntaxes = ['html', 'css', 'less', 'scss']
19 |
20 | for k, v of atom.config.get 'emmet.stylus'
21 | emmet.preferences.set('stylus.' + k, v);
22 |
23 | getUserHome = () ->
24 | if process.platform is 'win32'
25 | return process.env.USERPROFILE
26 |
27 | process.env.HOME
28 |
29 | isValidTabContext = () ->
30 | if editorProxy.getGrammar() is 'html'
31 | # HTML may contain embedded grammars
32 | scopes = editorProxy.getCurrentScope()
33 | contains = (regexp) -> scopes.filter((s) -> regexp.test s).length
34 |
35 | if contains /\.js\.embedded\./
36 | # in JS, allow Tab expander only inside string
37 | return contains /^string\./
38 |
39 | return true
40 |
41 |
42 | # Emmet action decorator: creates a command function
43 | # for Atom and executes Emmet action as single
44 | # undo command
45 | # @param {Object} action Action to perform
46 | # @return {Function}
47 | actionDecorator = (action) ->
48 | (evt) ->
49 | editorProxy.setup @getModel()
50 | editorProxy.editor.transact =>
51 | runAction action, evt
52 |
53 | # Same as `actionDecorator()` but executes action
54 | # with multiple selections
55 | # @param {Object} action Action to perform
56 | # @return {Function}
57 | multiSelectionActionDecorator = (action) ->
58 | (evt) ->
59 | editorProxy.setup(@getModel())
60 | editorProxy.editor.transact =>
61 | editorProxy.exec (i) ->
62 | runAction action, evt
63 | return false if evt.keyBindingAborted
64 |
65 | runAction = (action, evt) ->
66 | syntax = editorProxy.getSyntax()
67 | if action is 'expand_abbreviation_with_tab'
68 | # do not handle Tab key if:
69 | # -1. syntax is unknown- (no longer valid, defined by keymap selector)
70 | # 2. there’s a selection (user wants to indent it)
71 | # 3. has expanded snippet (e.g. has tabstops)
72 | activeEditor = editorProxy.editor;
73 | if not isValidTabContext() or not activeEditor.getLastSelection().isEmpty()
74 | return evt.abortKeyBinding()
75 | if activeEditor.snippetExpansion
76 | # in case of snippet expansion: expand abbreviation if we currently on last
77 | # tabstop
78 | se = activeEditor.snippetExpansion
79 | if se.tabStopIndex + 1 >= se.tabStopMarkers.length
80 | se.destroy()
81 | else
82 | return evt.abortKeyBinding()
83 |
84 | if action is 'toggle_comment' and (toggleCommentSyntaxes.indexOf(syntax) is -1 or not atom.config.get 'emmet.useEmmetComments')
85 | return evt.abortKeyBinding()
86 |
87 | if action is 'insert_formatted_line_break_only'
88 | if not atom.config.get 'emmet.formatLineBreaks'
89 | return evt.abortKeyBinding()
90 |
91 | result = emmet.run action, editorProxy
92 | return if not result then evt.abortKeyBinding() else true
93 |
94 | emmet.run action, editorProxy
95 |
96 | atomActionName = (name) ->
97 | 'emmet:' + name.replace(/_/g, '-')
98 |
99 | registerInteractiveActions = (actions) ->
100 | for name in ['wrap_with_abbreviation', 'update_tag', 'interactive_expand_abbreviation']
101 | do (name) ->
102 | atomAction = atomActionName name
103 | actions[atomAction] = (evt) ->
104 | editorProxy.setup(@getModel())
105 | interactive = require './interactive'
106 | interactive.run(name, editorProxy)
107 |
108 | loadExtensions = () ->
109 | extPath = atom.config.get 'emmet.extensionsPath'
110 | console.log 'Loading Emmet extensions from', extPath
111 | return unless extPath
112 |
113 | if extPath[0] is '~'
114 | extPath = getUserHome() + extPath.substr 1
115 |
116 | if fs.existsSync extPath
117 | emmet.resetUserData()
118 | files = fs.readdirSync extPath
119 | files = files
120 | .map((item) -> path.join extPath, item)
121 | .filter((file) -> not fs.statSync(file).isDirectory())
122 |
123 | emmet.loadExtensions(files)
124 | else
125 | console.warn 'Emmet: no such extension folder:', extPath
126 |
127 | module.exports =
128 | config:
129 | extensionsPath:
130 | type: 'string'
131 | default: '~/emmet'
132 | formatLineBreaks:
133 | type: 'boolean'
134 | default: true
135 | useEmmetComments:
136 | type: 'boolean'
137 | default: false
138 | description: 'disable to use atom native commenting system'
139 |
140 | activate: (@state) ->
141 | @subscriptions = new CompositeDisposable
142 | unless @actions
143 | @subscriptions.add atom.config.observe 'emmet.extensionsPath', loadExtensions
144 | @actions = {}
145 | registerInteractiveActions @actions
146 | for action in emmetActions.getList()
147 | atomAction = atomActionName action.name
148 | if @actions[atomAction]?
149 | continue
150 | cmd = if singleSelectionActions.indexOf(action.name) isnt -1 then actionDecorator(action.name) else multiSelectionActionDecorator(action.name)
151 | @actions[atomAction] = cmd
152 |
153 | @subscriptions.add atom.commands.add 'atom-text-editor', @actions
154 |
155 | deactivate: ->
156 | atom.config.transact => @subscriptions.dispose()
157 |
--------------------------------------------------------------------------------
/lib/interactive.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition of interactive functions: the function
3 | * that require additional dialog prompt and update
4 | * editor content when user types data in prompt
5 | */
6 | var utils = require('emmet/lib/utils/common');
7 | var editorUtils = require('emmet/lib/utils/editor');
8 | var actionUtils = require('emmet/lib/utils/action');
9 |
10 | var range = require('emmet/lib/assets/range');
11 | var htmlMatcher = require('emmet/lib/assets/htmlMatcher');
12 | var parser = require('emmet/lib/parser/abbreviation');
13 | var updateTag = require('emmet/lib/action/updateTag');
14 |
15 | var atom = require('atom');
16 | var PromptView = require('./prompt');
17 | var Point = atom.Point;
18 | var Range = atom.Range;
19 | var prompt = new PromptView();
20 |
21 | /**
22 | * Caches wrapping context for current selection in editor
23 | * @param {IEmmetEditor} editor
24 | * @param {Object} info Current editor info (content, syntax, etc.)
25 | * @return {Object}
26 | */
27 | function selectionContext(editor, info) {
28 | info = info || editorUtils.outputInfo(editor);
29 | return editor.selectionList().map(function(sel, i) {
30 | var r = range(sel);
31 | var tag = htmlMatcher.tag(info.content, r.start);
32 | if (!r.length() && tag) {
33 | // no selection, use tag pair
34 | r = utils.narrowToNonSpace(info.content, tag.range);
35 | }
36 |
37 | var out = {
38 | selection: r,
39 | tag: tag,
40 | caret: r.start,
41 | syntax: info.syntax,
42 | profile: info.profile || null,
43 | counter: i + 1,
44 | contextNode: actionUtils.captureContext(editor, r.start)
45 | };
46 |
47 | if (r.length()) {
48 | var pasted = utils.escapeText(r.substring(info.content));
49 | out.pastedContent = editorUtils.unindent(editor, pasted);
50 | }
51 |
52 | return out;
53 | });
54 | }
55 |
56 | function updateFinalCarets(selCtx, fromIndex, delta) {
57 | if (!delta) {
58 | return;
59 | }
60 |
61 | var offset = new Point(delta, 0);
62 | for (var i = fromIndex + 1, il = selCtx.length; i < il; i++) {
63 | selCtx[i].finalCaret = selCtx[i].finalCaret.translate(offset);
64 | }
65 | }
66 |
67 | /**
68 | * Returns current caret position for given editor
69 | * @param {Editor} editor Atom editor instance
70 | * @return {Number} Character index in editor
71 | */
72 | function getCaret(editor) {
73 | // we can’t use default `getCursor()` method because it returns
74 | // the most recent (e.g. the latest) caret, but we need the first one
75 | return editor.getSelectedBufferRanges()[0].start;
76 | }
77 |
78 | function lineDelta(prev, cur) {
79 | return utils.splitByLines(cur).length - utils.splitByLines(prev).length;
80 | }
81 |
82 | function setFinalCarets(selCtx, editor) {
83 | if (selCtx && selCtx.length > 1) {
84 | editor.setSelectedBufferRanges(selCtx.map(function(ctx) {
85 | return new Range(ctx.finalCaret, ctx.finalCaret);
86 | }));
87 | }
88 | }
89 |
90 | module.exports = {
91 | run: function(cmd, editor) {
92 | if (cmd === 'wrap_with_abbreviation') {
93 | return this.wrapWithAbbreviation(editor);
94 | }
95 |
96 | if (cmd === 'update_tag') {
97 | return this.updateTag(editor);
98 | }
99 |
100 | if (cmd === 'interactive_expand_abbreviation') {
101 | return this.expandAbbreviation(editor);
102 | }
103 | },
104 |
105 | expandAbbreviation: function(editor) {
106 | var info = editorUtils.outputInfo(editor);
107 | var selCtx = editor.selectionList().map(function(sel, i) {
108 | editor._selection.index = i;
109 | var r = range(sel);
110 | return {
111 | selection: r,
112 | selectedText: r.substring(info.content),
113 | caret: r.start,
114 | syntax: info.syntax,
115 | profile: info.profile || null,
116 | counter: i + 1,
117 | contextNode: actionUtils.captureContext(editor, r.start)
118 | };
119 | });
120 |
121 | return this.wrapWithAbbreviation(editor, selCtx);
122 | },
123 |
124 | wrapWithAbbreviation: function(editor, selCtx) {
125 | selCtx = selCtx || selectionContext(editor);
126 |
127 | // show prompt dialog that will wrap each selection
128 | // on user typing
129 | prompt.show({
130 | label: 'Enter Abbreviation',
131 | editor: editor.editor,
132 | editorView: editor.editorView,
133 | update: function(abbr) {
134 | var result, replaced;
135 | for (var i = selCtx.length - 1, ctx; i >= 0; i--) {
136 | ctx = selCtx[i];
137 | result = '';
138 | try {
139 | if (abbr) {
140 | result = parser.expand(abbr, ctx);
141 | } else {
142 | result = ctx.pastedContent;
143 | }
144 | } catch (e) {
145 | console.error(e);
146 | result = ctx.pastedContent;
147 | }
148 |
149 | editor._selection.index = i;
150 | replaced = editor.replaceContent(result, ctx.selection.start, ctx.selection.end);
151 | ctx.finalCaret = getCaret(editor.editor);
152 | updateFinalCarets(selCtx, i, lineDelta(ctx.selectedText, replaced));
153 | }
154 | },
155 | confirm: function() {
156 | setFinalCarets(selCtx, editor.editor);
157 | }
158 | });
159 | },
160 |
161 | updateTag: function(editor) {
162 | var info = editorUtils.outputInfo(editor);
163 | var selCtx = selectionContext(editor, info);
164 |
165 | // show prompt dialog that will update each
166 | // tag from selection
167 | prompt.show({
168 | label: 'Enter Abbreviation',
169 | editor: editor.editor,
170 | editorView: editor.editorView,
171 | update: function(abbr) {
172 | var tag, replaced, delta;
173 | for (var i = selCtx.length - 1, ctx; i >= 0; i--) {
174 | ctx = selCtx[i];
175 | tag = null;
176 |
177 | try {
178 | tag = updateTag.getUpdatedTag(abbr, {match: ctx.tag}, info.content, {
179 | counter: ctx.counter
180 | });
181 | } catch (e) {
182 | console.error(e);
183 | }
184 |
185 | if (!tag) {
186 | continue;
187 | }
188 |
189 | replaced = [{
190 | start: ctx.tag.open.range.start,
191 | end: ctx.tag.open.range.end,
192 | content: tag.source
193 | }];
194 |
195 | if (tag.name() != ctx.tag.name && ctx.tag.close) {
196 | replaced.unshift({
197 | start: ctx.tag.close.range.start,
198 | end: ctx.tag.close.range.end,
199 | content: '' + tag.name() + '>'
200 | });
201 | }
202 |
203 | replaced.forEach(function(data) {
204 | editor.replaceContent(data.content, data.start, data.end);
205 | ctx.finalCaret = editor.editor.getBuffer().positionForCharacterIndex(data.start);
206 | });
207 | }
208 |
209 | },
210 | confirm: function() {
211 | setFinalCarets(selCtx, editor.editor);
212 | }
213 | });
214 | }
215 | };
--------------------------------------------------------------------------------
/lib/prompt.coffee:
--------------------------------------------------------------------------------
1 | {$, TextEditorView, View} = require 'atom-space-pen-views'
2 | noop = ->
3 |
4 | method = (delegate, method) ->
5 | delegate?[method]?.bind(delegate) or noop
6 |
7 | module.exports =
8 | class PromptView extends View
9 | @attach: -> new PromptView
10 |
11 | @content: ->
12 | @div class: 'emmet-prompt tool-panel panel-bottom', =>
13 | # @label class: 'emmet-prompt__label', outlet: 'label'
14 | @div class: 'emmet-prompt__input', =>
15 | @subview 'panelInput', new TextEditorView(mini: true)
16 |
17 | initialize: () ->
18 | @panelEditor = @panelInput.getModel()
19 | @panelEditor.onDidStopChanging =>
20 | return unless @attached
21 | @handleUpdate @panelEditor.getText()
22 | atom.commands.add @panelInput.element, 'core:confirm', => @confirm()
23 | atom.commands.add @panelInput.element, 'core:cancel', => @cancel()
24 |
25 | show: (@delegate={}) ->
26 | @editor = @delegate.editor
27 | @editorView = @delegate.editorView
28 | # @panelInput.setPlaceholderText @delegate.label or 'Enter abbreviation'
29 | @panelInput.element.setAttribute 'placeholder', @delegate.label or 'Enter abbreviation'
30 | @updated = no
31 |
32 | @attach()
33 | text = @panelEditor.getText()
34 | if text
35 | @panelEditor.selectAll()
36 | @handleUpdate text
37 |
38 | undo: ->
39 | @editor.undo() if @updated
40 |
41 | handleUpdate: (text) ->
42 | @undo()
43 | @updated = yes
44 | @editor.transact =>
45 | method(@delegate, 'update')(text)
46 |
47 | confirm: ->
48 | @handleUpdate @panelEditor.getText()
49 | @trigger 'confirm'
50 | method(@delegate, 'confirm')()
51 | @detach()
52 |
53 | cancel: ->
54 | @undo()
55 | @trigger 'cancel'
56 | method(@delegate, 'cancel')()
57 | @detach()
58 |
59 | detach: ->
60 | return unless @hasParent()
61 | @detaching = true
62 | @prevPane?.activate()
63 |
64 | super
65 | @detaching = false
66 | @attached = false
67 |
68 | @trigger 'detach'
69 | method(@delegate, 'hide')()
70 |
71 | attach: ->
72 | @attached = true
73 | @prevPane = atom.workspace.getActivePane()
74 | atom.workspace.addBottomPanel(item: this, visible: true)
75 | @panelInput.focus()
76 | @trigger 'attach'
77 | method(@delegate, 'show')()
78 |
--------------------------------------------------------------------------------
/menus/emmet.json:
--------------------------------------------------------------------------------
1 | {
2 | "menu": [
3 | {
4 | "label": "Packages",
5 | "submenu": [
6 | {
7 | "label": "Emmet",
8 | "submenu": [
9 | {
10 | "label": "Encode\\Decode data:URL image",
11 | "command": "emmet:encode-decode-data-url"
12 | },
13 | {
14 | "label": "Previous Edit Point",
15 | "command": "emmet:prev-edit-point"
16 | },
17 | {
18 | "label": "Next Edit Point",
19 | "command": "emmet:next-edit-point"
20 | },
21 | {
22 | "label": "Numbers",
23 | "submenu": [
24 | {
25 | "label": "Evaluate Math Expression",
26 | "command": "emmet:evaluate-math-expression"
27 | },
28 | {
29 | "label": "Increment number by 1",
30 | "command": "emmet:increment-number-by-1"
31 | },
32 | {
33 | "label": "Decrement number by 1",
34 | "command": "emmet:decrement-number-by-1"
35 | },
36 | {
37 | "label": "Increment number by 10",
38 | "command": "emmet:increment-number-by-10"
39 | },
40 | {
41 | "label": "Decrement number by 10",
42 | "command": "emmet:decrement-number-by-10"
43 | },
44 | {
45 | "label": "Increment number by 0.1",
46 | "command": "emmet:increment-number-by-01"
47 | },
48 | {
49 | "label": "Decrement number by 0.1",
50 | "command": "emmet:decrement-number-by-01"
51 | }
52 | ]
53 | },
54 | {
55 | "label": "Expand Abbreviation",
56 | "command": "emmet:expand-abbreviation"
57 | },
58 | {
59 | "label": "Balance (inward)",
60 | "command": "emmet:balance-inward"
61 | },
62 | {
63 | "label": "Balance (outward)",
64 | "command": "emmet:balance-outward"
65 | },
66 | {
67 | "label": "HTML",
68 | "submenu": [
69 | {
70 | "label": "Go To Matching Tag Pair",
71 | "command": "emmet:matching-pair"
72 | },
73 | {
74 | "label": "Remove Tag",
75 | "command": "emmet:remove-tag"
76 | },
77 | {
78 | "label": "Split\\Join Tag Declaration",
79 | "command": "emmet:split-join-tag"
80 | },
81 | {
82 | "label": "Update Tag",
83 | "command": "emmet:update-tag"
84 | }
85 | ]
86 | },
87 | {
88 | "label": "Merge Lines",
89 | "command": "emmet:merge-lines"
90 | },
91 | {
92 | "label": "CSS",
93 | "submenu": [
94 | {
95 | "label": "Reflect Value",
96 | "command": "emmet:reflect-css-value"
97 | }
98 | ]
99 | },
100 | {
101 | "label": "Select Next Item",
102 | "command": "emmet:select-next-item"
103 | },
104 | {
105 | "label": "Select Previous Item",
106 | "command": "emmet:select-previous-item"
107 | },
108 | {
109 | "label": "Toggle Comment",
110 | "command": "emmet:toggle-comment"
111 | },
112 | {
113 | "label": "Update Image Size",
114 | "command": "emmet:update-image-size"
115 | },
116 | {
117 | "label": "Wrap With Abbreviation",
118 | "command": "emmet:wrap-with-abbreviation"
119 | },
120 | {
121 | "label": "Interactive Expand Abbreviation",
122 | "command": "emmet:interactive-expand-abbreviation"
123 | }
124 | ]
125 | }
126 | ]
127 | }
128 | ]
129 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "emmet",
3 | "description": "Emmet – the essential tool for web developers",
4 | "main": "./lib/emmet",
5 | "version": "2.4.3",
6 | "dependencies": {
7 | "emmet": "^1.3.2",
8 | "atom-space-pen-views": "^2.0.3"
9 | },
10 | "license": "MIT",
11 | "repository": "https://github.com/emmetio/emmet-atom",
12 | "engines": {
13 | "atom": "*"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/spec/emmet-spec.coffee:
--------------------------------------------------------------------------------
1 | Path = require "path"
2 | Fs = require "fs"
3 |
4 | readFile = (path) ->
5 | Fs.readFileSync(Path.join(__dirname, "./fixtures/", path), "utf8")
6 |
7 | describe "Emmet", ->
8 | [editor, editorElement] = []
9 |
10 | console.log atom.keymaps.onDidMatchBinding (event) ->
11 | console.log 'Matched keybinding', event
12 |
13 |
14 | simulateTabKeyEvent = () ->
15 | event = keydownEvent("tab", {target: editorElement})
16 | atom.keymaps.handleKeyboardEvent(event.originalEvent)
17 |
18 | beforeEach ->
19 | waitsForPromise ->
20 | atom.workspace.open("tabbing.html")
21 |
22 | waitsForPromise ->
23 | atom.packages.activatePackage("emmet")
24 |
25 | waitsForPromise ->
26 | atom.packages.activatePackage("snippets") # to intentionally disrupt tab expansion
27 |
28 | waitsForPromise ->
29 | atom.packages.activatePackage("language-css", sync: true)
30 |
31 | waitsForPromise ->
32 | atom.packages.activatePackage("language-sass", sync: true)
33 |
34 | waitsForPromise ->
35 | atom.packages.activatePackage("language-php", sync: true)
36 |
37 | waitsForPromise ->
38 | atom.packages.activatePackage("language-html", sync: true)
39 |
40 | runs ->
41 | # make sure emitter is initiated to properly deactivate package
42 | atom.packages.getLoadedPackage('snippets')?.mainModule?.getEmitter()
43 | editor = atom.workspace.getActiveTextEditor()
44 | editorElement = atom.views.getView(editor)
45 |
46 | describe "tabbing", ->
47 | beforeEach ->
48 | atom.workspace.open('tabbing.html')
49 | editor.setCursorScreenPosition([1, 4])
50 |
51 | it "moves the cursor along", ->
52 | simulateTabKeyEvent()
53 | cursorPos = editor.getCursorScreenPosition()
54 | expect(cursorPos.column).toBe 6
55 |
56 | describe "emmet:expand-abbreviation", ->
57 | expansion = null
58 |
59 | describe "for normal HTML", ->
60 | beforeEach ->
61 | editor.setText readFile "abbreviation/before/html-abbrv.html"
62 | editor.moveToEndOfLine()
63 |
64 | expansion = readFile "abbreviation/after/html-abbrv.html"
65 |
66 | it "expands HTML abbreviations via commands", ->
67 | atom.commands.dispatch editorElement, "emmet:expand-abbreviation"
68 | expect(editor.getText()).toBe expansion
69 |
70 | it "expands HTML abbreviations via keybindings", ->
71 | event = keydownEvent('e', shiftKey: true, metaKey: true, target: editorElement)
72 | atom.keymaps.handleKeyboardEvent(event.originalEvent)
73 | expect(editor.getText()).toBe expansion
74 |
75 | it "expands HTML abbreviations via Tab", ->
76 | console.log atom.keymaps.findKeyBindings keystrokes: 'tab'
77 | simulateTabKeyEvent()
78 | expect(editor.getText()).toBe expansion
79 |
80 | # describe "for HTML with attributes", ->
81 | # beforeEach ->
82 | # workspaceView.openSync(Path.join(__dirname, './fixtures/abbreviation/before/anchor-class-expand.html'))
83 | # editorView = workspaceView.getActiveView()
84 | # editor = editorView.getEditor()
85 | # editSession = workspaceView.getActivePaneItem()
86 | # editSession.moveCursorToEndOfLine()
87 |
88 | # expansion = Fs.readFileSync(Path.join(__dirname, './fixtures/abbreviation/after/anchor-class-expand.html'), "utf8")
89 |
90 | # it "expands HTML abbreviations via commands", ->
91 | # editorView.trigger "emmet:expand-abbreviation"
92 | # expect(editorView.getText()).toBe expansion
93 | # cursorPos = editor.getCursorScreenPosition()
94 | # expect(cursorPos.column).toBe 9
95 |
96 | # it "expands HTML abbreviations via keybindings", ->
97 | # editorView.trigger keydownEvent('e', shiftKey: true, metaKey: true, target: editor[0])
98 | # expect(editor.getText()).toBe expansion
99 | # cursorPos = editor.getCursorScreenPosition()
100 | # expect(cursorPos.column).toBe 9
101 |
102 | # it "expands HTML abbreviations via Tab", ->
103 | # editorView.trigger keydownEvent('tab', target: editor[0])
104 | # expect(editor.getText()).toBe expansion
105 | # cursorPos = editor.getCursorScreenPosition()
106 | # expect(cursorPos.column).toBe 9
107 |
108 | # # headers seem to be a special case: http://git.io/7XeBKQ
109 | # describe "for headers in HTML", ->
110 | # beforeEach ->
111 | # workspaceView.openSync(Path.join(__dirname, './fixtures/abbreviation/before/header-expand.html'))
112 | # editorView = workspaceView.getActiveView()
113 | # editor = editorView.getEditor()
114 | # editSession = workspaceView.getActivePaneItem()
115 | # editSession.moveCursorToEndOfLine()
116 |
117 | # expansion = Fs.readFileSync(Path.join(__dirname, './fixtures/abbreviation/after/header-expand.html'), "utf8")
118 |
119 | # it "expands HTML abbreviations via commands", ->
120 | # editorView.trigger "emmet:expand-abbreviation"
121 | # expect(editorView.getText()).toBe expansion
122 |
123 | # it "expands HTML abbreviations via keybindings", ->
124 | # editorView.trigger keydownEvent('e', shiftKey: true, metaKey: true, target: editor[0])
125 | # expect(editorView.getText()).toBe expansion
126 |
127 | # it "expands HTML abbreviations via Tab", ->
128 | # editorView.trigger keydownEvent('tab', target: editor[0])
129 | # expect(editorView.getText()).toBe expansion
130 |
131 | # describe "for CSS", ->
132 | # beforeEach ->
133 | # workspaceView.openSync(Path.join(__dirname, './fixtures/abbreviation/before/css-abbrv.css'))
134 | # editorView = workspaceView.getActiveView()
135 | # editor = editorView.getEditor()
136 | # editSession = workspaceView.getActivePaneItem()
137 | # editSession.moveCursorToEndOfLine()
138 |
139 | # expansion = Fs.readFileSync(Path.join(__dirname, './fixtures/abbreviation/after/css-abbrv.css'), "utf8")
140 |
141 | # it "expands CSS abbreviations via commands", ->
142 | # editorView.trigger "emmet:expand-abbreviation"
143 | # expect(editor.getText()).toBe expansion
144 |
145 | # it "expands CSS abbreviations via keybindings", ->
146 | # editorView.trigger keydownEvent('e', shiftKey: true, metaKey: true, target: editor[0])
147 | # expect(editor.getText()).toBe expansion
148 |
149 | # it "expands CSS abbreviations via tab", ->
150 | # editorView.trigger keydownEvent('tab', target: editor[0])
151 | # expect(editor.getText()).toBe expansion
152 |
153 | # describe "for PHP", ->
154 | # describe "for PHP with HTML", ->
155 | # beforeEach ->
156 | # workspaceView.openSync(Path.join(__dirname, './fixtures/abbreviation/before/php-in-html.php'))
157 | # editorView = workspaceView.getActiveView()
158 | # editor = editorView.getEditor()
159 | # editSession = workspaceView.getActivePaneItem()
160 | # editSession.setCursorBufferPosition([6, 5])
161 |
162 | # expansion = Fs.readFileSync(Path.join(__dirname, './fixtures/abbreviation/after/php-in-html.php'), "utf8")
163 |
164 | # it "expands abbreviations via commands", ->
165 | # editorView.trigger "emmet:expand-abbreviation"
166 | # expect(editor.getText()).toBe expansion
167 |
168 | # it "expands abbreviations via keybindings", ->
169 | # editorView.trigger keydownEvent('e', shiftKey: true, metaKey: true, target: editor[0])
170 | # expect(editor.getText()).toBe expansion
171 |
172 | # it "expands abbreviations via tab", ->
173 | # editorView.trigger keydownEvent('tab', target: editor[0])
174 | # expect(editor.getText()).toBe expansion
175 |
176 | # # fdescribe "for vanilla PHP", ->
177 | # # beforeEach ->
178 | # # workspaceView.openSync(Path.join(__dirname, './fixtures/abbreviation/before/vanilla-php.php'))
179 | # # editorView = workspaceView.getActiveView()
180 | # # editor = editorView.getEditor()
181 | # # editSession = workspaceView.getActivePaneItem()
182 | # # editSession.setCursorBufferPosition([1, 3])
183 | # #
184 | # # expansion = Fs.readFileSync(Path.join(__dirname, './fixtures/abbreviation/after/vanilla-php.php'), "utf8")
185 | # #
186 | # # it "expands abbreviations via commands", ->
187 | # # editorView.trigger "emmet:expand-abbreviation"
188 | # # expect(editor.getText()).toBe expansion
189 | # #
190 | # # it "expands abbreviations via keybindings", ->
191 | # # editorView.trigger keydownEvent('e', shiftKey: true, metaKey: true, target: editor[0])
192 | # # expect(editor.getText()).toBe expansion
193 | # #
194 | # # it "expands abbreviations via tab", ->
195 | # # editorView.trigger keydownEvent('tab', target: editor[0])
196 | # # expect(editor.getText()).toBe expansion
197 |
198 | # describe "for SASS", ->
199 | # beforeEach ->
200 | # workspaceView.openSync(Path.join(__dirname, './fixtures/abbreviation/before/sass-test.sass'))
201 | # editorView = workspaceView.getActiveView()
202 | # editor = editorView.getEditor()
203 | # editSession = workspaceView.getActivePaneItem()
204 | # editSession.moveCursorToEndOfLine()
205 |
206 | # expansion = Fs.readFileSync(Path.join(__dirname, './fixtures/abbreviation/after/sass-test.sass'), "utf8")
207 |
208 | # it "expands abbreviations via commands", ->
209 | # editorView.trigger "emmet:expand-abbreviation"
210 | # expect(editor.getText()).toBe expansion
211 |
212 | # it "expands abbreviations via keybindings", ->
213 | # editorView.trigger keydownEvent('e', shiftKey: true, metaKey: true, target: editor[0])
214 | # expect(editor.getText()).toBe expansion
215 |
216 | # it "expands abbreviations via tab", ->
217 | # editorView.trigger keydownEvent('tab', target: editor[0])
218 | # expect(editor.getText()).toBe expansion
219 |
220 | # describe "for multiple cursors", ->
221 | # beforeEach ->
222 | # workspaceView.openSync(Path.join(__dirname, './fixtures/abbreviation/before/multi-line.html'))
223 | # editorView = workspaceView.getActiveView()
224 | # editor = editorView.getEditor()
225 | # editSession = workspaceView.getActivePaneItem()
226 |
227 | # editor.addCursorAtBufferPosition([0, 9])
228 | # editor.addCursorAtBufferPosition([1, 9])
229 | # editor.addCursorAtBufferPosition([2, 9])
230 |
231 | # expansion = Fs.readFileSync(Path.join(__dirname, './fixtures/abbreviation/after/multi-line.html'), "utf8")
232 |
233 | # it "expands HTML abbreviations via commands", ->
234 | # editorView.trigger "emmet:expand-abbreviation"
235 | # expect(editorView.getText()).toBe expansion
236 |
237 | # # it "expands HTML abbreviations via keybindings", ->
238 | # # editorView.trigger keydownEvent('e', shiftKey: true, metaKey: true, target: editor[0])
239 | # # expect(editor.getText()).toBe expansion
240 | # #
241 | # # it "expands HTML abbreviations via Tab", ->
242 | # # editorView.trigger keydownEvent('tab', target: editor[0])
243 | # # expect(editor.getText()).toBe expansion
244 |
245 | # describe "emmet:balance", ->
246 | # beforeEach ->
247 | # workspaceView.openSync(Path.join(__dirname, './fixtures/balance/sample.html'))
248 | # editorView = workspaceView.getActiveView()
249 | # editor = editorView.getEditor()
250 | # editSession = workspaceView.getActivePaneItem()
251 |
252 | # describe "for balance-outward", ->
253 | # beforeEach ->
254 | # editSession.setCursorBufferPosition([3, 23])
255 |
256 | # it "matches pairs outwards via commands", ->
257 | # expect(editor.getSelection().getBufferRange()).toEqual [[3, 23], [3, 23]]
258 | # editorView.trigger "emmet:balance-outward"
259 | # expect(editor.getSelection().getBufferRange()).toEqual [[3, 11], [3, 38]]
260 | # editorView.trigger "emmet:balance-outward"
261 | # expect(editor.getSelection().getBufferRange()).toEqual [[3, 8], [3, 42]]
262 | # editorView.trigger "emmet:balance-outward"
263 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 29], [4, 4]]
264 |
265 | # it "matches pairs outwards via keybindings", ->
266 | # expect(editor.getSelection().getBufferRange()).toEqual [[3, 23], [3, 23]]
267 | # editorView.trigger keydownEvent('d', ctrlKey: true, target: editor[0])
268 | # expect(editor.getSelection().getBufferRange()).toEqual [[3, 11], [3, 38]]
269 | # editorView.trigger keydownEvent('d', ctrlKey: true, target: editor[0])
270 | # expect(editor.getSelection().getBufferRange()).toEqual [[3, 8], [3, 42]]
271 | # editorView.trigger keydownEvent('d', ctrlKey: true, target: editor[0])
272 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 29], [4, 4]]
273 |
274 | # describe "for balance-inward", ->
275 | # beforeEach ->
276 | # editSession.setCursorBufferPosition([1, 4])
277 |
278 | # it "matches pairs inwards via commands", ->
279 | # editorView.trigger "emmet:balance-inward"
280 | # expect(editor.getSelection().getBufferRange()).toEqual [[0, 15], [5, 0]]
281 | # editorView.trigger "emmet:balance-inward"
282 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 4], [4, 14]]
283 | # editorView.trigger "emmet:balance-inward"
284 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 29], [4, 4]]
285 | # editorView.trigger "emmet:balance-inward"
286 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 8], [2, 33]]
287 |
288 | # it "matches pairs inwards via keybindings", ->
289 | # editorView.trigger keydownEvent('d', altKey: true, target: editor[0])
290 | # expect(editor.getSelection().getBufferRange()).toEqual [[0, 15], [5, 0]]
291 | # editorView.trigger keydownEvent('d', altKey: true, target: editor[0])
292 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 4], [4, 14]]
293 | # editorView.trigger keydownEvent('d', altKey: true, target: editor[0])
294 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 29], [4, 4]]
295 | # editorView.trigger keydownEvent('d', altKey: true, target: editor[0])
296 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 8], [2, 33]]
297 |
298 | # describe "for go-to match-pair", ->
299 | # it "goes to the match-pair via commands", ->
300 | # editSession.setCursorBufferPosition([4, 10])
301 | # editorView.trigger "emmet:matching-pair"
302 | # expect(editor.getCursor().getBufferPosition()).toEqual [1, 4]
303 |
304 | # editSession.setCursorBufferPosition([5, 5])
305 | # editorView.trigger "emmet:matching-pair"
306 | # expect(editor.getCursor().getBufferPosition()).toEqual [0, 0]
307 |
308 | # it "goes to the match-pair via keybindings", ->
309 | # editSession.setCursorBufferPosition([4, 10])
310 | # editorView.trigger keydownEvent('j', ctrlKey: true, altKey: true, target: editor[0])
311 | # expect(editor.getCursor().getBufferPosition()).toEqual [1, 4]
312 |
313 | # editSession.setCursorBufferPosition([5, 5])
314 | # editorView.trigger keydownEvent('j', ctrlKey: true, altKey: true, target: editor[0])
315 | # expect(editor.getCursor().getBufferPosition()).toEqual [0, 0]
316 |
317 | # describe "emmet:edit-point", ->
318 | # beforeEach ->
319 | # workspaceView.openSync(Path.join(__dirname, './fixtures/edit-points/edit-points.html'))
320 | # editorView = workspaceView.getActiveView()
321 | # editor = editorView.getEditor()
322 | # editSession = workspaceView.getActivePaneItem()
323 |
324 | # describe "for next-edit-point", ->
325 | # beforeEach ->
326 | # editSession.setCursorBufferPosition([0, 0])
327 |
328 | # it "finds the next-edit-point via commands", ->
329 | # editorView.trigger "emmet:next-edit-point"
330 | # expect(editor.getCursor().getBufferPosition()).toEqual [1, 8]
331 | # editorView.trigger "emmet:next-edit-point"
332 | # expect(editor.getCursor().getBufferPosition()).toEqual [1, 17]
333 | # editorView.trigger "emmet:next-edit-point"
334 | # expect(editor.getCursor().getBufferPosition()).toEqual [1, 19]
335 |
336 | # it "finds the next-edit-point via keybindings", ->
337 | # editorView.trigger keydownEvent('.', ctrlKey: true, altKey:true, target: editor[0])
338 | # expect(editor.getCursor().getBufferPosition()).toEqual [1, 8]
339 | # editorView.trigger keydownEvent('.', ctrlKey: true, altKey:true, target: editor[0])
340 | # expect(editor.getCursor().getBufferPosition()).toEqual [1, 17]
341 | # editorView.trigger keydownEvent('.', ctrlKey: true, altKey:true, target: editor[0])
342 | # expect(editor.getCursor().getBufferPosition()).toEqual [1, 19]
343 |
344 | # describe "for prev-edit-point", ->
345 | # beforeEach ->
346 | # editSession.setCursorBufferPosition([9, 15])
347 |
348 | # it "finds the prev-edit-point via commands", ->
349 | # editorView.trigger "emmet:prev-edit-point"
350 | # expect(editor.getCursor().getBufferPosition()).toEqual [2, 23]
351 | # editorView.trigger "emmet:prev-edit-point"
352 | # expect(editor.getCursor().getBufferPosition()).toEqual [2, 19]
353 | # editorView.trigger "emmet:prev-edit-point"
354 | # expect(editor.getCursor().getBufferPosition()).toEqual [2, 17]
355 |
356 | # it "finds the prev-edit-point via keybindings", ->
357 | # editorView.trigger keydownEvent(',', ctrlKey: true, altKey:true, target: editor[0])
358 | # expect(editor.getCursor().getBufferPosition()).toEqual [2, 23]
359 | # editorView.trigger keydownEvent(',', ctrlKey: true, altKey:true, target: editor[0])
360 | # expect(editor.getCursor().getBufferPosition()).toEqual [2, 19]
361 | # editorView.trigger keydownEvent(',', ctrlKey: true, altKey:true, target: editor[0])
362 | # expect(editor.getCursor().getBufferPosition()).toEqual [2, 17]
363 |
364 | # describe "emmet:split-join-tag", ->
365 | # beforeEach ->
366 | # workspaceView.openSync(Path.join(__dirname, './fixtures/split-join-tag/split-join-tag.html'))
367 | # editorView = workspaceView.getActiveView()
368 | # editor = editorView.getEditor()
369 | # editSession = workspaceView.getActivePaneItem()
370 |
371 | # describe "for split-join-tag", ->
372 | # beforeEach ->
373 | # editSession.setCursorBufferPosition([1, 10])
374 |
375 | # it "calls split-join-tag via commands", ->
376 | # editorView.trigger "emmet:split-join-tag"
377 | # expect(editor.lineForBufferRow(0)).toBe ""
378 | # editorView.trigger "emmet:split-join-tag"
379 | # expect(editor.lineForBufferRow(0)).toBe ""
380 | # editorView.trigger "emmet:split-join-tag"
381 | # expect(editor.lineForBufferRow(0)).toBe ""
382 |
383 | # it "calls split-join-tag via keybindings", ->
384 | # editorView.trigger keydownEvent('j', shiftKey: true, metaKey: true, target: editor[0])
385 | # expect(editor.lineForBufferRow(0)).toBe ""
386 | # editorView.trigger keydownEvent('j', shiftKey: true, metaKey: true, target: editor[0])
387 | # expect(editor.lineForBufferRow(0)).toBe ""
388 | # editorView.trigger keydownEvent('j', shiftKey: true, metaKey: true, target: editor[0])
389 | # expect(editor.lineForBufferRow(0)).toBe ""
390 |
391 | # describe "emmet:remove-tag", ->
392 | # onceRemoved = twiceRemoved = null
393 |
394 | # beforeEach ->
395 | # workspaceView.openSync(Path.join(__dirname, './fixtures/remove-tag/before/remove-tag.html'))
396 | # editorView = workspaceView.getActiveView()
397 | # editor = editorView.getEditor()
398 | # editSession = workspaceView.getActivePaneItem()
399 |
400 | # onceRemoved = Fs.readFileSync(Path.join(__dirname, './fixtures/remove-tag/after/remove-tag-once.html'), "utf8")
401 | # twiceRemoved = Fs.readFileSync(Path.join(__dirname, './fixtures/remove-tag/after/remove-tag-twice.html'), "utf8")
402 |
403 | # editSession.setCursorBufferPosition([1, 10])
404 |
405 | # it "calls remove-tag via commands", ->
406 | # editorView.trigger "emmet:remove-tag"
407 | # expect(editor.getText()).toBe onceRemoved
408 | # editorView.trigger "emmet:remove-tag"
409 | # expect(editor.getText()).toBe twiceRemoved
410 |
411 | # it "calls remove-tag via keybindings", ->
412 | # editorView.trigger keydownEvent('\'', metaKey: true, target: editor[0])
413 | # expect(editor.getText()).toBe onceRemoved
414 | # editorView.trigger keydownEvent('\'', metaKey: true, target: editor[0])
415 | # expect(editor.getText()).toBe twiceRemoved
416 |
417 | # describe "emmet:evaluate-math-expression", ->
418 | # beforeEach ->
419 | # workspaceView.openSync(Path.join(__dirname, './fixtures/evaluate-math-expression/evaluate-math-expression.html'))
420 | # editorView = workspaceView.getActiveView()
421 | # editor = editorView.getEditor()
422 | # editSession = workspaceView.getActivePaneItem()
423 |
424 | # describe "for evaluate-math-expression", ->
425 | # it "calls evaluate-math-expression via commands", ->
426 | # editSession.setCursorBufferPosition([0, 3])
427 | # editorView.trigger "emmet:evaluate-math-expression"
428 | # editSession.setCursorBufferPosition([0, 7])
429 | # editorView.trigger "emmet:evaluate-math-expression"
430 | # editSession.setCursorBufferPosition([0, 12])
431 | # editorView.trigger "emmet:evaluate-math-expression"
432 | # expect(editor.getText()).toBe "12 3 90\n"
433 |
434 | # it "calls evaluate-math-expression via keybindings", ->
435 | # editSession.setCursorBufferPosition([0, 3])
436 | # editorView.trigger keydownEvent('y', shiftKey: true, metaKey: true, target: editor[0])
437 | # editSession.setCursorBufferPosition([0, 7])
438 | # editorView.trigger keydownEvent('y', shiftKey: true, metaKey: true, target: editor[0])
439 | # editSession.setCursorBufferPosition([0, 12])
440 | # editorView.trigger keydownEvent('y', shiftKey: true, metaKey: true, target: editor[0])
441 | # expect(editor.getText()).toBe "12 3 90\n"
442 |
443 | # describe "emmet increment/decrement numbers", ->
444 | # beforeEach ->
445 | # workspaceView.openSync(Path.join(__dirname, './fixtures/increment-decrement-numbers/increment-decrement-numbers.css'))
446 | # editorView = workspaceView.getActiveView()
447 | # editor = editorView.getEditor()
448 | # editSession = workspaceView.getActivePaneItem()
449 |
450 | # describe "for incrementing", ->
451 | # describe "increment by 01", ->
452 | # beforeEach ->
453 | # editSession.setCursorBufferPosition([1, 18])
454 |
455 | # it "increments via commands", ->
456 | # editorView.trigger "emmet:increment-number-by-01"
457 | # editorView.trigger "emmet:increment-number-by-01"
458 | # expect(editor.lineForBufferRow(1)).toMatch(/1\.9/)
459 | # editorView.trigger "emmet:increment-number-by-01"
460 | # editorView.trigger "emmet:increment-number-by-01"
461 | # expect(editor.lineForBufferRow(1)).toMatch(/2\.1/)
462 |
463 | # it "increments via keybindings", ->
464 | # editorView.trigger keydownEvent('up', ctrlKey: true, altKey: true, target: editor[0])
465 | # editorView.trigger keydownEvent('up', ctrlKey: true, altKey: true, target: editor[0])
466 | # expect(editor.lineForBufferRow(1)).toMatch(/1\.9/)
467 | # editorView.trigger keydownEvent('up', ctrlKey: true, altKey: true, target: editor[0])
468 | # editorView.trigger keydownEvent('up', ctrlKey: true, altKey: true, target: editor[0])
469 | # expect(editor.lineForBufferRow(1)).toMatch(/2\.1/)
470 |
471 | # describe "increment by 1", ->
472 | # beforeEach ->
473 | # editSession.setCursorBufferPosition([2, 13])
474 |
475 | # it "increments via commands", ->
476 | # editorView.trigger "emmet:increment-number-by-1"
477 | # editorView.trigger "emmet:increment-number-by-1"
478 | # expect(editor.lineForBufferRow(2)).toMatch(/12/)
479 | # for i in [0..12] by 1
480 | # editorView.trigger "emmet:increment-number-by-1"
481 | # expect(editor.lineForBufferRow(2)).toMatch(/25/)
482 |
483 | # it "increments via keybindings", ->
484 | # editorView.trigger keydownEvent('up', ctrlKey: true, altKey: true, metaKey:true, target: editor[0])
485 | # editorView.trigger keydownEvent('up', ctrlKey: true, altKey: true, metaKey:true, target: editor[0])
486 | # expect(editor.lineForBufferRow(2)).toMatch(/12/)
487 | # for i in [0..12] by 1
488 | # editorView.trigger keydownEvent('up', ctrlKey: true, altKey: true, metaKey:true, target: editor[0])
489 | # expect(editor.lineForBufferRow(2)).toMatch(/25/)
490 |
491 | # describe "increment by 10", ->
492 | # beforeEach ->
493 | # editSession.setCursorBufferPosition([3, 12])
494 |
495 | # it "increments via commands", ->
496 | # editorView.trigger "emmet:increment-number-by-10"
497 | # editorView.trigger "emmet:increment-number-by-10"
498 | # expect(editor.lineForBufferRow(3)).toMatch(/120/)
499 |
500 | # it "increments via keybindings", ->
501 | # editorView.trigger keydownEvent('up', ctrlKey: true, altKey: true, metaKey: true, shiftKey: true, target: editor[0])
502 | # editorView.trigger keydownEvent('up', ctrlKey: true, altKey: true, metaKey: true, shiftKey: true, target: editor[0])
503 | # expect(editor.lineForBufferRow(3)).toMatch(/120/)
504 |
505 | # describe "for decrementing", ->
506 | # describe "decrement by 01", ->
507 | # beforeEach ->
508 | # editSession.setCursorBufferPosition([1, 18])
509 |
510 | # it "decrements via commands", ->
511 | # editorView.trigger "emmet:decrement-number-by-01"
512 | # editorView.trigger "emmet:decrement-number-by-01"
513 | # expect(editor.lineForBufferRow(1)).toMatch(/1\.5/)
514 | # for i in [0..20] by 1
515 | # editorView.trigger "emmet:decrement-number-by-01"
516 | # expect(editor.lineForBufferRow(1)).toMatch(/\-0\.6/)
517 |
518 | # it "decrements via keybindings", ->
519 | # editorView.trigger keydownEvent('down', ctrlKey: true, altKey: true, target: editor[0])
520 | # editorView.trigger keydownEvent('down', ctrlKey: true, altKey: true, target: editor[0])
521 | # expect(editor.lineForBufferRow(1)).toMatch(/1\.5/)
522 | # for i in [0..20] by 1
523 | # editorView.trigger keydownEvent('down', ctrlKey: true, altKey: true, target: editor[0])
524 | # expect(editor.lineForBufferRow(1)).toMatch(/\-0\.6/)
525 |
526 | # describe "decrement by 1", ->
527 | # beforeEach ->
528 | # editSession.setCursorBufferPosition([2, 13])
529 |
530 | # it "decrements via commands", ->
531 | # editorView.trigger "emmet:decrement-number-by-1"
532 | # editorView.trigger "emmet:decrement-number-by-1"
533 | # expect(editor.lineForBufferRow(2)).toMatch(/8/)
534 | # for i in [0..12] by 1
535 | # editorView.trigger "emmet:decrement-number-by-1"
536 | # expect(editor.lineForBufferRow(2)).toMatch(/\-5/)
537 |
538 | # it "decrements via keybindings", ->
539 | # editorView.trigger keydownEvent('down', ctrlKey: true, altKey: true, metaKey:true, target: editor[0])
540 | # editorView.trigger keydownEvent('down', ctrlKey: true, altKey: true, metaKey:true, target: editor[0])
541 | # expect(editor.lineForBufferRow(2)).toMatch(/8/)
542 | # for i in [0..12] by 1
543 | # editorView.trigger keydownEvent('down', ctrlKey: true, altKey: true, metaKey:true, target: editor[0])
544 | # expect(editor.lineForBufferRow(2)).toMatch(/\-5/)
545 |
546 | # describe "decrement by 10", ->
547 | # beforeEach ->
548 | # editSession.setCursorBufferPosition([3, 12])
549 |
550 | # it "decrements via commands", ->
551 | # editorView.trigger "emmet:decrement-number-by-10"
552 | # editorView.trigger "emmet:decrement-number-by-10"
553 | # expect(editor.lineForBufferRow(3)).toMatch(/80/)
554 |
555 | # it "decrements via keybindings", ->
556 | # editorView.trigger keydownEvent('down', ctrlKey: true, altKey: true, metaKey: true, shiftKey: true, target: editor[0])
557 | # editorView.trigger keydownEvent('down', ctrlKey: true, altKey: true, metaKey: true, shiftKey: true, target: editor[0])
558 | # expect(editor.lineForBufferRow(3)).toMatch(/80/)
559 |
560 | # describe "emmet select items", ->
561 | # describe "for HTML", ->
562 | # beforeEach ->
563 | # workspaceView.openSync(Path.join(__dirname, './fixtures/select-item/select-item.html'))
564 | # editorView = workspaceView.getActiveView()
565 | # editor = editorView.getEditor()
566 | # editSession = workspaceView.getActivePaneItem()
567 |
568 | # describe "selecting next item", ->
569 | # beforeEach ->
570 | # editSession.setCursorBufferPosition([0, 0])
571 |
572 | # it "selects next items via commands", ->
573 | # editorView.trigger "emmet:select-next-item"
574 | # expect(editor.getSelection().getBufferRange()).toEqual [[0, 1], [0, 8]]
575 | # editorView.trigger "emmet:select-next-item"
576 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 5], [1, 6]]
577 | # editorView.trigger "emmet:select-next-item"
578 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 5], [2, 8]]
579 | # editorView.trigger "emmet:select-next-item"
580 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 9], [2, 28]]
581 | # editorView.trigger "emmet:select-next-item"
582 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 16], [2, 27]]
583 | # editorView.trigger "emmet:select-next-item"
584 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 16], [2, 20]]
585 | # editorView.trigger "emmet:select-next-item"
586 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 21], [2, 27]]
587 |
588 | # it "selects next items via keybindings", ->
589 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
590 | # expect(editor.getSelection().getBufferRange()).toEqual [[0, 1], [0, 8]]
591 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
592 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 5], [1, 6]]
593 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
594 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 5], [2, 8]]
595 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
596 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 9], [2, 28]]
597 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
598 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 16], [2, 27]]
599 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
600 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 16], [2, 20]]
601 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
602 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 21], [2, 27]]
603 |
604 | # describe "selecting previous item", ->
605 | # beforeEach ->
606 | # editSession.setCursorBufferPosition([2, 21])
607 |
608 | # it "selects previous items via commands", ->
609 | # editorView.trigger "emmet:select-previous-item"
610 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 16], [2, 20]]
611 | # editorView.trigger "emmet:select-previous-item"
612 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 16], [2, 27]]
613 | # editorView.trigger "emmet:select-previous-item"
614 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 9], [2, 28]]
615 | # editorView.trigger "emmet:select-previous-item"
616 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 5], [2, 8]]
617 | # editorView.trigger "emmet:select-previous-item"
618 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 5], [1, 6]]
619 | # editorView.trigger "emmet:select-previous-item"
620 | # expect(editor.getSelection().getBufferRange()).toEqual [[0, 1], [0, 8]]
621 |
622 | # it "selects previous items via keybindings", ->
623 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
624 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 16], [2, 20]]
625 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
626 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 16], [2, 27]]
627 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
628 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 9], [2, 28]]
629 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
630 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 5], [2, 8]]
631 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
632 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 5], [1, 6]]
633 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
634 | # expect(editor.getSelection().getBufferRange()).toEqual [[0, 1], [0, 8]]
635 |
636 | # describe "for CSS", ->
637 | # beforeEach ->
638 | # workspaceView.openSync(Path.join(__dirname, './fixtures/select-item/select-item.css'))
639 | # editorView = workspaceView.getActiveView()
640 | # editor = editorView.getEditor()
641 | # editSession = workspaceView.getActivePaneItem()
642 |
643 | # describe "selecting next item", ->
644 | # beforeEach ->
645 | # editSession.setCursorBufferPosition([0, 0])
646 |
647 | # it "selects next items via commands", ->
648 | # editorView.trigger "emmet:select-next-item"
649 | # expect(editor.getSelection().getBufferRange()).toEqual [[0, 0], [0, 4]]
650 | # editorView.trigger "emmet:select-next-item"
651 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 4], [1, 28]]
652 | # editorView.trigger "emmet:select-next-item"
653 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 12], [1, 27]]
654 | # editorView.trigger "emmet:select-next-item"
655 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 12], [1, 15]]
656 | # editorView.trigger "emmet:select-next-item"
657 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 16], [1, 21]]
658 | # editorView.trigger "emmet:select-next-item"
659 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 22], [1, 27]]
660 | # editorView.trigger "emmet:select-next-item"
661 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 4], [2, 46]]
662 |
663 | # it "selects next items via keybindings", ->
664 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
665 | # expect(editor.getSelection().getBufferRange()).toEqual [[0, 0], [0, 4]]
666 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
667 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 4], [1, 28]]
668 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
669 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 12], [1, 27]]
670 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
671 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 12], [1, 15]]
672 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
673 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 16], [1, 21]]
674 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
675 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 22], [1, 27]]
676 | # editorView.trigger keydownEvent('.', altKey: true, metaKey: true, target: editor[0])
677 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 4], [2, 46]]
678 |
679 | # describe "selecting previous item", ->
680 | # beforeEach ->
681 | # editSession.setCursorBufferPosition([2, 4])
682 |
683 | # it "selects previous items via commands", ->
684 | # editorView.trigger "emmet:select-previous-item"
685 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 4], [2, 46]]
686 | # editorView.trigger "emmet:select-previous-item"
687 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 22], [1, 27]]
688 | # editorView.trigger "emmet:select-previous-item"
689 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 16], [1, 21]]
690 | # editorView.trigger "emmet:select-previous-item"
691 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 12], [1, 15]]
692 | # editorView.trigger "emmet:select-previous-item"
693 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 12], [1, 27]]
694 | # editorView.trigger "emmet:select-previous-item"
695 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 4], [1, 28]]
696 |
697 | # it "selects previous items via keybindings", ->
698 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
699 | # expect(editor.getSelection().getBufferRange()).toEqual [[2, 4], [2, 46]]
700 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
701 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 22], [1, 27]]
702 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
703 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 16], [1, 21]]
704 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
705 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 12], [1, 15]]
706 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
707 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 12], [1, 27]]
708 | # editorView.trigger keydownEvent(',', altKey: true, metaKey: true, target: editor[0])
709 | # expect(editor.getSelection().getBufferRange()).toEqual [[1, 4], [1, 28]]
710 |
711 | # describe "emmet:reflect-css-value", ->
712 | # reflection = null
713 |
714 | # beforeEach ->
715 | # workspaceView.openSync(Path.join(__dirname, './fixtures/reflect-css-value/before/reflect-css-value.css'))
716 | # editorView = workspaceView.getActiveView()
717 | # editor = editorView.getEditor()
718 | # editSession = workspaceView.getActivePaneItem()
719 |
720 | # reflection = Fs.readFileSync(Path.join(__dirname, './fixtures/reflect-css-value/after/reflect-css-value.css'), "utf8")
721 |
722 | # it "reflects CSS via commands", ->
723 | # editor.setCursorBufferPosition([3, 32])
724 | # editorView.trigger "emmet:reflect-css-value"
725 | # # editor.setCursorBufferPosition([9, 16])
726 | # # editorView.trigger "emmet:reflect-css-value"
727 | # expect(editor.getText()).toBe reflection
728 |
729 | # it "reflects CSS via keybindings", ->
730 | # editor.setCursorBufferPosition([3, 32])
731 | # editorView.trigger keydownEvent('r', shiftKey: true, metaKey: true, target: editor[0])
732 | # # editor.setCursorBufferPosition([9, 16])
733 | # # editorView.trigger keydownEvent('r', shiftKey: true, metaKey: true, target: editor[0])
734 | # expect(editor.getText()).toBe reflection
735 |
736 | # # describe "emmet:encode-decode-data-url", ->
737 | # # encoded = null
738 | # # beforeEach ->
739 | # # workspaceView.openSync(Path.join(__dirname, './fixtures/encode-decode-data-url/before/encode-decode-data-url.css'))
740 | # # editorView = workspaceView.getActiveView()
741 | # # editor = editorView.getEditor()
742 | # # editSession = workspaceView.getActivePaneItem()
743 | # #
744 | # # editSession.setCursorBufferPosition([1, 22])
745 | # #
746 | # # encoded = Fs.readFileSync(Path.join(__dirname, './fixtures/encode-decode-data-url/after/encode-decode-data-url.css'), "utf8")
747 | # #
748 | # # it "encodes and decodes URL via commands", ->
749 | # # editorView.trigger "emmet:encode-decode-data-url"
750 | # # expect(editor.getText()).toBe encoded
751 | # #
752 | # # it "encodes and decodes CSS via keybindings", ->
753 | # # editorView.trigger keydownEvent('d', shiftKey: true, ctrlKey: true, target: editor[0])
754 | # # expect(editor.getText()).toBe encoded
755 |
756 | # # describe "emmet:update-image-size", ->
757 | # # updated = null
758 | # #
759 | # # describe "for HTML", ->
760 | # # beforeEach ->
761 | # # workspaceView.openSync(Path.join(__dirname, './fixtures/update-image-size/before/update-image-size.html'))
762 | # # editorView = workspaceView.getActiveView()
763 | # # editor = editorView.getEditor()
764 | # # editSession = workspaceView.getActivePaneItem()
765 | # # editSession.setCursorBufferPosition([0, 15])
766 | # #
767 | # # updated = Fs.readFileSync(Path.join(__dirname, './fixtures/update-image-size/after/update-image-size.html'), "utf8")
768 | # #
769 | # # it "updates the image via commands", ->
770 | # # editorView.trigger "emmet:update-image-size"
771 | # # expect(editor.getText()).toBe updated
772 | # #
773 | # # it "updates the image via keybindings", ->
774 | # # editorView.trigger keydownEvent('i', shiftKey: true, ctrlKey: true, target: editor[0])
775 | # # expect(editor.getText()).toBe updated
776 | # #
777 | # # describe "for CSS", ->
778 | # # beforeEach ->
779 | # # workspaceView.openSync(Path.join(__dirname, './fixtures/update-image-size/before/update-image-size.css'))
780 | # # editorView = workspaceView.getActiveView()
781 | # # editor = editorView.getEditor()
782 | # # editSession = workspaceView.getActivePaneItem()
783 | # # editSession.setCursorBufferPosition([0, 15])
784 | # #
785 | # # updated = Fs.readFileSync(Path.join(__dirname, './fixtures/update-image-size/after/update-image-size.css'), "utf8")
786 | # #
787 | # # it "updates the image via commands", ->
788 | # # editorView.trigger "emmet:update-image-size"
789 | # # expect(editor.getText()).toBe updated
790 | # #
791 | # # it "updates the image via keybindings", ->
792 | # # editorView.trigger keydownEvent('i', shiftKey: true, ctrlKey: true, target: editor[0])
793 | # # expect(editor.getText()).toBe updated
794 |
795 | # describe "emmet:update-tag", ->
796 | # updated = null
797 | # prompt = null
798 |
799 | # describe "for HTML", ->
800 | # beforeEach ->
801 | # workspaceView.openSync(Path.join(__dirname, './fixtures/update-tag/before/update-tag.html'))
802 | # editorView = workspaceView.getActiveView()
803 | # editor = editorView.getEditor()
804 | # editSession = workspaceView.getActivePaneItem()
805 | # editSession.setCursorBufferPosition([0, 11])
806 |
807 | # updated = Fs.readFileSync(Path.join(__dirname, './fixtures/update-tag/after/update-tag.html'), "utf8")
808 |
809 | # it "updates the tag via commands", ->
810 | # editorView.trigger "emmet:update-tag"
811 | # prompt = atom.workspaceView.find(".emmet-prompt").view()
812 |
813 | # prompt.panelInput.insertText(".+c2[title=Hello]")
814 | # prompt.trigger 'core:confirm'
815 |
816 | # expect(editor.getText()).toBe updated
817 |
818 | # it "updates the tag via keybindings", ->
819 | # editorView.trigger keydownEvent('u', shiftKey: true, ctrlKey: true, target: editor[0])
820 |
821 | # prompt.panelInput.insertText(".+c2[title=Hello]")
822 | # prompt.trigger 'core:confirm'
823 |
824 | # expect(editor.getText()).toBe updated
825 |
826 | # describe "emmet:wrap-with-abbreviation", ->
827 | # updated = null
828 | # prompt = null
829 |
830 | # describe "for HTML", ->
831 | # beforeEach ->
832 | # workspaceView.openSync(Path.join(__dirname, './fixtures/wrap-with-abbreviation/before/wrap-with-abbreviation.html'))
833 | # editorView = workspaceView.getActiveView()
834 | # editor = editorView.getEditor()
835 | # editSession = workspaceView.getActivePaneItem()
836 | # editSession.setCursorBufferPosition([1, 4])
837 |
838 | # updated = Fs.readFileSync(Path.join(__dirname, './fixtures/wrap-with-abbreviation/after/wrap-with-abbreviation.html'), "utf8")
839 |
840 | # it "wraps an abbreviation via commands", ->
841 | # editorView.trigger "emmet:wrap-with-abbreviation"
842 | # prompt = atom.workspaceView.find(".emmet-prompt").view()
843 |
844 | # prompt.panelInput.setText(".wrapper>h1{Title}+.content")
845 | # prompt.trigger 'core:confirm'
846 |
847 | # expect(editor.getText()).toBe updated
848 |
849 | # it "wraps an abbreviation via keybindings", ->
850 | # editorView.trigger keydownEvent('a', shiftKey: true, metaKey: true, target: editor[0])
851 | # prompt = atom.workspaceView.find(".emmet-prompt").view()
852 |
853 | # prompt.panelInput.setText(".wrapper>h1{Title}+.content")
854 | # prompt.trigger 'core:confirm'
855 |
856 | # expect(editor.getText()).toBe updated
857 |
858 | # describe "emmet:merge-lines", ->
859 | # updated = null
860 |
861 | # describe "for HTML", ->
862 | # beforeEach ->
863 | # workspaceView.openSync(Path.join(__dirname, './fixtures/merge-lines/before/merge-lines.html'))
864 | # editorView = workspaceView.getActiveView()
865 | # editor = editorView.getEditor()
866 | # editSession = workspaceView.getActivePaneItem()
867 | # editSession.setCursorBufferPosition([3, 5])
868 |
869 | # updated = Fs.readFileSync(Path.join(__dirname, './fixtures/merge-lines/after/merge-lines.html'), "utf8")
870 |
871 | # it "performs merge lines via commands", ->
872 | # editorView.trigger "emmet:merge-lines"
873 | # expect(editor.getText()).toBe updated
874 |
875 | # it "performs merge lines via keybindings", ->
876 | # editorView.trigger keydownEvent('M', shiftKey: true, metaKey: true, target: editor[0])
877 | # expect(editor.getText()).toBe updated
878 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/after/anchor-class-expand.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/after/css-abbrv.css:
--------------------------------------------------------------------------------
1 | margin: 10px;
2 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/after/header-expand.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/after/html-abbrv.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/after/multi-line.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/after/php-in-html.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | PHP Test
4 |
5 |
6 | Hello World
'; ?>
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/after/sass-test.sass:
--------------------------------------------------------------------------------
1 | margin: 10px
2 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/after/vanilla-php.php:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/before/anchor-class-expand.html:
--------------------------------------------------------------------------------
1 | a.selected
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/before/css-abbrv.css:
--------------------------------------------------------------------------------
1 | m10
2 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/before/header-expand.html:
--------------------------------------------------------------------------------
1 | h1
2 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/before/html-abbrv.html:
--------------------------------------------------------------------------------
1 | #header>ul#nav>li*4>a[href]
2 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/before/multi-line.html:
--------------------------------------------------------------------------------
1 | .selector
2 | .selector
3 | .selector
4 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/before/php-in-html.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | PHP Test
4 |
5 |
6 | Hello World'; ?>
7 | .wow
8 |
9 |
10 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/before/sass-test.sass:
--------------------------------------------------------------------------------
1 | m10
2 |
--------------------------------------------------------------------------------
/spec/fixtures/abbreviation/before/vanilla-php.php:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/spec/fixtures/balance/sample.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Document example
4 | Lorem ipsum dolor sit amet.
5 |
6 |
7 |
--------------------------------------------------------------------------------
/spec/fixtures/edit-points/edit-points.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
12 |
--------------------------------------------------------------------------------
/spec/fixtures/encode-decode-data-url/after/encode-decode-data-url.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: url(data:application/octet-stream;base64,/VBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg/Qn9AAAC/VBMVEUAAABEREBEREBEREBEREBEREBEREBEREBEREBEREBEREBEREBEREBEREBEREBEREA2cv04dP05c/05c/06dP06dP07bf07bP08bf04dP05dP06dP05df03df07Zf05dP06c/07bf0+Zf1AU2Q6bf06dP05df05dP06dP1AcP07bP05dP0udP05df04df06cv05dP02ef0AAP05cv05c/06dP05dP06dP05df05c/05dP06c/39WTtA/f04c/05dP06bv06bv06b/05c/05c/04dP0A/f39Wzn9Vzv9WDz9SUk6bP03c/06dP05c/05df04cf08Y/0+XX4+V3L9Tjv9WDr9WTz9WDv9WDv9VTz9UTz9TTz9WD79WTv9WDr9WDv9VTz9WDv9WDv9WDr9WTv9WDz9WDr9VDv9Uzz9VTv9Vzv9WDv9Vzv9VDz9WDv9VTz9WDv9VTz9WDv9Vzv9WTr9YED9Vzv9WDv9WDv9WDt0TEr9Vjn9VD39Vjz9Vjz9WTv9WDv9WTz9VUD9VTz9Wj79WDv9WDz9Vzv9WDv9Uz39VD39Vjv9Wjv9VT79AAD9Tj39WTv9VDxMRUJhRUL9Uj39VTv9Vjz9WTz9Vzv9Wjz9VVX9VTv9WDv9VT39VTz9WDv9WTv9Vjz9VTz9WDr9WDv9Vzv9WTv9WDv9WDv9VDz9WVD9VTz9VjxlUE07av1ATVD9Ujz9Vzr9WTv9WDv9WDv9WDv9VDz9Tj1BU2M6cv07bP06bv05cv1A/f39Vzv9Vjz9VD39VD39Vzz9WTr9WTv9Vzz9VzpCUl88aP06c/07bf05dP04dP04c/05cv1AW3U/UF07dv03dv05cf04cv06bP07bf06b/05c/05c/05dP05dP05df06df08eP04df06df05c/05c/07cv1AWXA9Zv05cv05dP04dP04dP06df05dP04c/07a/07av08av01df05dP05c/06b/06bv39WDv9WDv9Vjz9Vjz9/XX9AAAA/XRSTlMAAQUGAQsMAhASFRgDGgMfJk1vfv39/f39/X1uTCVY/f39WC79Wf39EP39C/39df0TAf1ZZf39/f39VCsESf39/f39/UACLf13Bx4qOUdVR0xCLw39/f39/WQvHVb9/f39s/39/f39/f39+P39/f39dgj9/f39BiP9/f39/XMYHiVOXWx6/XldSiEBOv1wISH9/f39UiIDJ1j9/fz9/f39/f39/f0c/f0reSRD/f39yD0mZ/39XAhJV3b9eW1kVUYqdv39/f1SLDIoDRwtWP39/f39/f39/RE7/f39ODVZcf39/f39/f39fRj9/f07AAAACXBIWXMAAABIAAAASABG/Ws+AAAC/UlEQVRI/WNgIA8wMjEzMRJC/WdhZWNlIf39DP39OTg5CWL9/W1g/f39/QH9/RBgcf39XP39/f39Bxb9/f39/RMQFBIWERUT/f39/f39/f1BZf05QC5jZP2r/RP9/QgE/T5//f0J/f39/f39MP0L/TImNg4e/f39/SdVNXVk/SD9/Sb9dv06ZlZ2/Qla/f11GBh0Uf1//f0Hcy0kSP1Y/f39/Whg/WBk/f39/Qn9egZG/X8ZTP39LSz9/VtZI/1n/Yj9MP39/Ts4Iv07Of39/TH9IzMwIf1n/f39Av39fXz9/f0DAv39Qf1CQv39/WEx/QMVCf0aERkV/RQnDDH9cf39EmD9ef0xDRUJ/f39/f1v/Un9Kf1p/Rn9Wf05X/1+/f09FxYTGDH9B1L9/StYFRIrAWdM/WNV/f0AZ0wXYlX9/QhnTP1jVf39CGdM/WFVD4Aj/fH9B2r9Ff39WP1/Lf0Z5WX9/f0rKv1w/TQDQ3VNbR39/f39/Sb9/Rgx/Qz9/WppbWv9SEv9/f39/f0D/Y8z/SdM/f39/SH9/VP9/f39af1n/f1D/f01e/39eQRj/X79/f39/S5e/XT9/RVDL/3x/XQRmA7q/WsB/Tz9TT39PF39Vf39/Thjev1qLP39LFr9M/3t8HH9ZmT9W/1u/mMnmLV7/V4G/f19/Q9MOXj9/f39wCn9/Qn9/Thj/Sf9/f1I/T13/QINFy9d/XL9/f1PH0/9/f0b/TL9/f1b/f39/R39MW14/SN6bQJkff0z/RkY/T94/f39/f1jZP39Yhr9ev39/f0XL1/9fv39/f39D/39/Xn9Dy/9/f16/f12ACc0/f1tZ0BZRP1jICwA/f39/ToJ/f0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTMtMDYtMTJUMTg6Mjg6MTQtMDU6MDD9Dv0wAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDEzLTA2LTEyVDE4OjI4OjE0LTA1OjAw/VNT/QAAAABJRU5E/UJg/Q==);
3 | }
4 |
--------------------------------------------------------------------------------
/spec/fixtures/encode-decode-data-url/barrel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emmetio/emmet-atom/8d5fdacfef954ec5b33866f5fac32532742f72e3/spec/fixtures/encode-decode-data-url/barrel.png
--------------------------------------------------------------------------------
/spec/fixtures/encode-decode-data-url/before/encode-decode-data-url.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: url(../barrel.png);
3 | }
4 |
--------------------------------------------------------------------------------
/spec/fixtures/evaluate-math-expression/evaluate-math-expression.html:
--------------------------------------------------------------------------------
1 | 2*6 10\3 20*4+10
2 |
--------------------------------------------------------------------------------
/spec/fixtures/increment-decrement-numbers/increment-decrement-numbers.css:
--------------------------------------------------------------------------------
1 | body {
2 | line-height: 1.7;
3 | padding: 10px;
4 | width: 100%;
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/merge-lines/after/merge-lines.html:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet.Officiis animi consequuntur iure.Ea asperiores aperiam non necessitatibus?Expedita iusto cupiditate eum esse
2 |
--------------------------------------------------------------------------------
/spec/fixtures/merge-lines/before/merge-lines.html:
--------------------------------------------------------------------------------
1 |
2 | Lorem ipsum dolor sit amet.
3 | Officiis animi consequuntur iure.
4 | Ea asperiores aperiam non necessitatibus?
5 | Expedita iusto cupiditate eum esse
6 |
7 |
--------------------------------------------------------------------------------
/spec/fixtures/reflect-css-value/after/reflect-css-value.css:
--------------------------------------------------------------------------------
1 | div {
2 | padding: 10px;
3 |
4 | -webkit-transform: rotate(50deg);
5 | -moz-transform: rotate(50deg);
6 | -ms-transform: rotate(50deg);
7 | -o-transform: rotate(50deg);
8 | transform: rotate(50deg);
9 |
10 | opacity: 0.7;
11 | filter: alpha(opacity=60);
12 | }
13 |
--------------------------------------------------------------------------------
/spec/fixtures/reflect-css-value/before/reflect-css-value.css:
--------------------------------------------------------------------------------
1 | div {
2 | padding: 10px;
3 |
4 | -webkit-transform: rotate(50deg);
5 | -moz-transform: rotate(45deg);
6 | -ms-transform: rotate(45deg);
7 | -o-transform: rotate(45deg);
8 | transform: rotate(45deg);
9 |
10 | opacity: 0.7;
11 | filter: alpha(opacity=60);
12 | }
13 |
--------------------------------------------------------------------------------
/spec/fixtures/remove-tag/after/remove-tag-once.html:
--------------------------------------------------------------------------------
1 |
2 | Title
3 | Lorem ipsum dolor sit amet.
4 | Officiis animi consequuntur iure.
5 | Ea asperiores aperiam non necessitatibus?
6 | Expedita iusto cupiditate eum esse.
7 |
8 |
--------------------------------------------------------------------------------
/spec/fixtures/remove-tag/after/remove-tag-twice.html:
--------------------------------------------------------------------------------
1 | Title
2 | Lorem ipsum dolor sit amet.
3 | Officiis animi consequuntur iure.
4 | Ea asperiores aperiam non necessitatibus?
5 | Expedita iusto cupiditate eum esse.
6 |
--------------------------------------------------------------------------------
/spec/fixtures/remove-tag/before/remove-tag.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Title
4 |
Lorem ipsum dolor sit amet.
5 |
Officiis animi consequuntur iure.
6 |
Ea asperiores aperiam non necessitatibus?
7 |
Expedita iusto cupiditate eum esse.
8 |
9 |
10 |
--------------------------------------------------------------------------------
/spec/fixtures/select-item/select-item.css:
--------------------------------------------------------------------------------
1 | body {
2 | border: 1px solid black;
3 | background: url(image.jpg) #ccc no-repeat;
4 | }
5 |
--------------------------------------------------------------------------------
/spec/fixtures/select-item/select-item.html:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/spec/fixtures/split-join-tag/split-join-tag.html:
--------------------------------------------------------------------------------
1 |
2 | Lorem ipsum dolor sit amet
3 |
4 |
--------------------------------------------------------------------------------
/spec/fixtures/tabbing.html:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/spec/fixtures/update-image-size/after/update-image-size.css:
--------------------------------------------------------------------------------
1 | .block {
2 | background: url(../raptor_dunk.jpg);
3 | width: 640px;
4 | height: 427px;
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/update-image-size/after/update-image-size.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/spec/fixtures/update-image-size/before/update-image-size.css:
--------------------------------------------------------------------------------
1 | .block {
2 | background: url(../raptor_dunk.jpg);
3 | }
4 |
--------------------------------------------------------------------------------
/spec/fixtures/update-image-size/before/update-image-size.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/spec/fixtures/update-image-size/raptor_dunk.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emmetio/emmet-atom/8d5fdacfef954ec5b33866f5fac32532742f72e3/spec/fixtures/update-image-size/raptor_dunk.jpg
--------------------------------------------------------------------------------
/spec/fixtures/update-tag/after/update-tag.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/spec/fixtures/update-tag/before/update-tag.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/spec/fixtures/wrap-with-abbreviation/after/wrap-with-abbreviation.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/spec/fixtures/wrap-with-abbreviation/before/wrap-with-abbreviation.html:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/styles/emmet.less:
--------------------------------------------------------------------------------
1 | @import 'ui-variables';
2 |
3 | .emmet-panel {
4 | position: absolute;
5 | z-index: 10;
6 | background: @pane-item-background-color;
7 | color: @text-color;
8 | padding: 5px;
9 | min-width: 200px;
10 | font-size: 12px;
11 | -webkit-box-shadow: 0 0 20px rgba(0, 0, 0, .5);
12 | box-shadow: 0 0 20px rgba(0, 0, 0, .5);
13 |
14 | &-tail {
15 | position: absolute;
16 | left: 8px;
17 | margin-top: -6px;
18 | width: 15px;
19 | height: 15px;
20 | content: '';
21 | display: inline-block;
22 | background: inherit;
23 | z-index: -1;
24 | -webkit-transform: rotate(45deg);
25 | transform: rotate(45deg);
26 | }
27 |
28 | atom-text-editor[mini] {
29 | z-index: 1;
30 | line-height: 16px;
31 | }
32 | }
33 |
34 | .emmet-prompt {
35 | min-width: -webkit-min-content;
36 | padding: 10px;
37 |
38 | /* &__label {
39 | display: inline-block;
40 | white-space: nowrap;
41 | min-width: -webkit-min-content;
42 | min-width: min-content;
43 | padding-right: 10px;
44 | margin: 0;
45 | } */
46 |
47 | &__input {
48 | flex: 1 100%;
49 | margin: 0;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------