├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── completions.json
├── grammars
└── angularjs.cson
├── keymaps
└── angularjs.cson
├── lib
├── angularjs.coffee
└── provider.coffee
├── package.json
├── screenshots
├── autocompletes.gif
└── snippets.gif
├── snippets
├── html-templates.cson
└── js-templates.cson
├── spec
└── grammar-spec.coffee
└── styles
└── angularjs.less
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | npm-debug.log
3 | node_modules
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ### 0.5.3 (2018-01-16)
2 | * disable autocompletion in JavaScript with whitespaces - [#83](https://github.com/angular-ui/AngularJS-Atom/issues/83)
3 | * support a snippets for $timeout - [#79](https://github.com/angular-ui/AngularJS-Atom/issues/79)
4 |
5 | ### 0.5.2 (2018-01-05)
6 | * disable autocompletion in JavaScript with comma and so on - [#83](https://github.com/angular-ui/AngularJS-Atom/issues/83)
7 |
8 | ### 0.5.1 (2017-12-03)
9 | * fix Uncaught TypeError: Cannot read property 'toLowerCase' of undefined - [#82](https://github.com/angular-ui/AngularJS-Atom/issues/82)
10 | * support autocompletions with prefix started with $
11 |
12 | ### 0.5.0 (2017-12-02)
13 | * use autocomplete-plus for autocompletion.
14 | * older autocompletion doesn't work with latest Atom.
15 |
16 | ### 0.4.0 (2017-02-04)
17 | * fix deprecated selector since Atom v1.13.0 - [#68](https://github.com/angular-ui/AngularJS-Atom/issues/68)
18 | * add new attributes of angularjs
19 |
20 | ### 0.3.5 (2016-07-27)
21 | * change syntax names to compatable with themes - [#50](https://github.com/angular-ui/AngularJS-Atom/issues/50)
22 | * fix a ng-model-options syntax highlight bug - [#58](https://github.com/angular-ui/AngularJS-Atom/issues/58)
23 | * add syntax highlight for ng-required -
24 | [#59](https://github.com/angular-ui/AngularJS-Atom/pull/59)
25 | * support jsp files - [#55](https://github.com/angular-ui/AngularJS-Atom/pull/55)
26 |
27 | ### 0.3.4 (2016-01-18)
28 | * bug fixes -
29 | [#46](https://github.com/angular-ui/AngularJS-Atom/pull/46),
30 | [#52](https://github.com/angular-ui/AngularJS-Atom/pull/52)
31 | * add syntax highlight for ng-template -
32 | [#51](https://github.com/angular-ui/AngularJS-Atom/pull/51)
33 | * support [language-javascript-semantic](https://atom.io/packages/language-javascript-semantic) -
34 | [#53](https://github.com/angular-ui/AngularJS-Atom/pull/53)
35 |
36 | ### 0.3.3 (2015-10-14)
37 | * rollback fixing emmet's tab autocompletion
38 |
39 | ### 0.3.1 (2015-10-10)
40 |
41 | * support normailzed angular's tags and attributes
42 | (e.g data-ng-if, x-ng-if)(#44)
43 |
44 | #### Bug fixes
45 | * fix confict with emmet's tab autocompletion(#19)
46 | * fix wrong syntax highlight(#42, #43)
47 |
48 | ### 0.3.0 (2015-05-23)
49 |
50 | #### Bug fixes
51 | * fix Atom update problem that Atom doen't update
52 | v0.2.0 and still use v0.1.0.(#39)
53 | * fix syntax highlight error for ng-options(#20)
54 |
55 | ### 0.2.0 (2015-02-08)
56 |
57 | #### Features
58 | * upgrade to be compatible with atom v1.0 API.
59 | please see [Upgrading your package to 1.0 APIs]
60 | (https://atom.io/docs/latest/upgrading/upgrading-your-package) for more details.
61 |
62 | #### Bug fixes
63 | * fix syntax highlight error for angular directives
64 |
65 | ### 0.1.0 (2015-01-02)
66 |
67 | #### Features
68 | * add directives and functions for angular v1.3.x
69 | * add syntax highlight for angular directives
70 | (closes [#13](https://github.com/angular-ui/AngularJS-Atom/issues/13))
71 | * add syntax highlight for angular expressions
72 | (closes [#18](https://github.com/angular-ui/AngularJS-Atom/issues/18))
73 |
74 | ### 0.0.5 (2014-09-08)
75 |
76 | #### Bug fixes
77 | * remove activation message useless
78 | (closes [#16](https://github.com/angular-ui/AngularJS-Atom/issues/16))
79 | * remove semicolon in snippets to allow chaining
80 | (closes [#4](https://github.com/angular-ui/AngularJS-Atom/issues/4))
81 | * fix error in javascript snippets
82 | (closes [#11](https://github.com/angular-ui/AngularJS-Atom/issues/11),
83 | thanks to @alepop )
84 |
85 | ### 0.0.4 (2014-03-03)
86 | merge [atom-angularjs](https://github.com/outsideris/atom-angularjs) package,
87 | thanks to @btesser
88 |
89 | #### Features
90 | * support autocompletes in html and javascript
91 | * support snippets in html and javascript
92 |
93 | ### 0.0.3 (2014-03-01)
94 |
95 | #### Bug fixes
96 | * Issue [#2](https://github.com/angular-ui/AngularJS-Atom/pull/2) :
97 | Improvements to Atom conversion thanks to @stevehansell
98 | - Replaced $TM_JAVASCRIPT_TERMINATOR with semi-colons
99 | - Removed escaping on $s in the snippet body
100 | - Inserted a comma into '.text.html, .meta.tag': to fix the html snippets
101 |
102 | ### 0.0.2 (2014-02-28)
103 | Updated assets: Add more assets, e.g. keymaps, menus, for more flexibility/options.
104 |
105 | ### 0.0.1 (2014-02-28)
106 | Initial conversion of textmate version
107 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2015 The AngularUI Team, JeongHoon Byun
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AngularJS v1.x support in Atom
2 |
3 | Adds syntax highlighting and snippets to AngularJS v1.x in Atom.
4 |
5 | Originally [converted](http://atom.io/docs/latest/converting-a-text-mate-bundle)
6 | from the [AngularJS TextMate bundle](https://github.com/angular-ui/AngularJs.tmbundle).
7 |
8 | Contributions are greatly appreciated. Please fork this repository and open a
9 | pull request to add snippets, make grammar tweaks, etc.
10 |
11 | ## Supported features
12 |
13 | ### Autocompletes
14 |
15 | You can use autocompletes for directives in HTML and
16 | angular.js's variables and function in JavaScript.
17 | See [settings](https://github.com/angular-ui/AngularJS-Atom/blob/master/settings/)
18 | for more details.
19 |
20 | 
21 |
22 | If you type some prefix and press Tab or Enter,
23 | you can use autocompletes in below.
24 |
25 | #### HTML
26 | ```
27 | ng-app
28 | ng-bind
29 | ng-bind-html
30 | ng-bind-template
31 | ng-blur
32 | ng-change
33 | ng-checked
34 | ng-class
35 | ng-class-even
36 | ng-class-odd
37 | ng-click
38 | ng-cloak
39 | ng-controller
40 | ng-copy
41 | ng-csp
42 | ng-cut
43 | ng-dblclick
44 | ng-disabled
45 | ng-focus
46 | ng-form
47 | ng-hide
48 | ng-href
49 | ng-if
50 | ng-include
51 | ng-init
52 | ng-jq
53 | ng-keydown
54 | ng-keypress
55 | ng-keyup
56 | ng-list
57 | ng-model
58 | ng-model-options
59 | ng-mousedown
60 | ng-mouseenter
61 | ng-mouseleave
62 | ng-mousemove
63 | ng-mouseover
64 | ng-mouseup
65 | ng-non-bindable
66 | ng-open
67 | ng-pluralize
68 | ng-show
69 | ng-transclude
70 | ng-view
71 | ng-messages
72 | ng-message
73 | ng-messages-include
74 | ng-swipe-left
75 | ng-swipe-righ
76 | ng-dirty
77 | ng-false-value
78 | ng-invalid
79 | ng-maxlength
80 | ng-minlength
81 | ng-message-exp
82 | ng-options
83 | ng-paste
84 | ng-pattern
85 | ng-pristine
86 | ng-readonly
87 | ng-required
88 | ng-repeat
89 | ng-repeat-start
90 | ng-repeat-end
91 | ng-selected
92 | ng-src
93 | ng-srcset
94 | ng-style
95 | ng-submit
96 | ng-switch
97 | ng-switch-when
98 | ng-switch-default
99 | ng-trim
100 | ng-true-value
101 | ng-valid
102 | ng-value
103 | ```
104 |
105 | #### JavaScript
106 |
107 | ```
108 | angular
109 | bind
110 | bootstrap
111 | copy
112 | element
113 | equals
114 | extend
115 | forEach
116 | fromJson
117 | identity
118 | injector
119 | isArray
120 | isDate
121 | isDefined
122 | isElement
123 | isFunction
124 | isNumber
125 | isObject
126 | isString
127 | isUndefined
128 | lowercase
129 | module
130 | noop
131 | reloadWithDebugInfo
132 | toJson
133 | uppercase
134 | $anchorScroll
135 | $animate
136 | $cacheFactory
137 | $compile
138 | $controller
139 | $document
140 | $exceptionHandler
141 | $filter
142 | $http
143 | $httpBackend
144 | $interpolate
145 | $interval
146 | $locale
147 | $location
148 | $log
149 | $parse
150 | $q
151 | $rootElement
152 | $rootScope
153 | $sce
154 | $sceDelegate
155 | $templateCache
156 | $templateRequest
157 | $timeout
158 | $window
159 | $animateProvider
160 | $compileProvider
161 | $controllerProvider
162 | $filterProvider
163 | $httpProvider
164 | $interpolateProvider
165 | $locationProvider
166 | $logProvider
167 | $parseProvider
168 | $rootScopeProvider
169 | $sceDelegateProvider
170 | $sceProvider
171 | $injector
172 | $provide
173 | $ariaProvider
174 | $aria
175 | $cookieStore
176 | $cookies
177 | mock
178 | $exceptionHandlerProvider
179 | TzDate
180 | dump
181 | inject
182 | $resource
183 | $routeProvider
184 | $route
185 | $routeParams
186 | $sanitize
187 | $swipe
188 | controller
189 | $scope
190 | service
191 | factory
192 | provider
193 | ngResource
194 | defer
195 | config
196 | when
197 | otherwise
198 | directive
199 | run
200 | filter
201 | ```
202 |
203 | ### Snippets
204 |
205 | You can use snippets in HTML and JavaScript.
206 | See [snippets](https://github.com/angular-ui/AngularJS-Atom/tree/master/snippets)
207 | for more details.
208 |
209 | 
210 |
211 | If you type prefix and press `tab`,
212 | It will be replaced by snippet for it.
213 |
214 | #### HTML
215 |
216 | ##### ngindex
217 | ```
218 |
219 |
220 |
221 |
222 |
223 | $2
224 |
225 |
226 | ```
227 |
228 | ##### ngsa
229 | ```
230 |
231 | ```
232 |
233 | ##### ngst
234 | ```
235 |
238 | ```
239 |
240 | ##### nginc
241 | ```
242 |
243 | ```
244 |
245 | ##### ngplural
246 | ```
247 |
248 | ```
249 |
250 | ##### ngswitch
251 | ```
252 | $2
253 | ```
254 |
255 | ##### ngtmpl
256 | ```
257 |
258 | ```
259 |
260 | ##### ngview
261 | ```
262 |
263 | ```
264 |
265 | #### JavaScript
266 |
267 | ##### ngm
268 | ```
269 | angular.module('$1', [$2])$3
270 | ```
271 |
272 | ##### ngma
273 | ```
274 | var $1 = angular.module('$2', [$3])$4
275 | ```
276 |
277 | ##### ngmc
278 | ```
279 | var $1 = angular.module('$2', [$3], function($4) {
280 | $5
281 | })$6
282 | ```
283 |
284 | ##### ngmfa
285 | ```
286 | factory('$1', function($2) {
287 | $3
288 | })$4
289 | ```
290 |
291 | ##### ngmfi
292 | ```
293 | filter('$1', function($2) {
294 | return function (input, $3) {
295 | $4
296 | };
297 | })$5
298 | ```
299 |
300 | ##### ngms
301 | ```
302 | service('$1', function($2) {
303 | $3
304 | })$4
305 | ```
306 |
307 | ##### ngro
308 | ```
309 | $routeProvider.otherwise({redirectTo: '$1' });
310 | ```
311 |
312 | ##### ngrw
313 | ```
314 | $routeProvider.when('$1', {templateUrl: '$2', controller: '$3'});
315 | ```
316 |
317 | ##### ngrwr
318 | ```
319 | $routeProvider.when('$1', {templateUrl: '$2', controller: '$3', resolve: {$4} });
320 | ```
321 |
322 | ##### ngfor
323 | ```
324 | angular.forEach($1, function(value, key) {
325 | $2
326 | });
327 | ```
328 |
329 | ##### ngdl
330 | ```
331 | .directive('$1', function($2) {
332 | $3
333 | return function(scope, element, attrs) {
334 | $4
335 | }
336 | })$5
337 | ```
338 |
339 | ##### ngdlf
340 | ```
341 | function (scope, element, attrs) {
342 | $1
343 | }
344 | ```
345 |
346 | ##### ngdc
347 | ```
348 | .directive('$1', function factory($2) {
349 | var directiveDefinitionObject = {
350 | $3
351 | compile: function compile(tElement, tAttrs, transclude) {
352 | $4
353 | return function (scope, element, attrs) {
354 | $5
355 | }
356 | }
357 | };
358 | return directiveDefinitionObject;
359 | })$6
360 | ```
361 |
362 | ##### ngdcf
363 | ```
364 | function compile(tElement, tAttrs, transclude) {
365 | $1
366 | return function (scope, element, attrs) {
367 | $2
368 | }
369 | }$3
370 | ```
371 |
372 | ##### ngb
373 | ```
374 | $scope.$broadcast('$1', $2);
375 | ```
376 |
377 | ##### nge
378 | ```
379 | $scope.$emit('', );
380 | ```
381 |
382 | ##### ngf
383 | ```
384 | $scope.$1 = function($2) {
385 | $3
386 | };
387 | ```
388 |
389 | ##### ngcp
390 | ```
391 | $1Ctrl.prototype.$2 = function $2($3) {
392 | $4
393 | };
394 | ```
395 |
396 | ##### ngon
397 | ```
398 | $scope.$on('$1', function(event, $2) {
399 | $3
400 | });
401 | ```
402 |
403 | ##### ngv
404 | ```
405 | $scope.$1 = $2;
406 | ```
407 |
408 | ##### ngw
409 | ```
410 | $scope.$watch('$1', function(newValue, oldValue) {
411 | $2
412 | });
413 | ```
414 |
415 | #### ngto
416 | ```
417 | $timeout(function() {
418 | $2
419 | }, $1)
420 | ```
421 |
422 | ##### ngc
423 | ```
424 | var $1 = function($scope, $2) {
425 | $3
426 | }
427 | ```
428 |
429 | ##### ngc$
430 | ```
431 | $1Ctrl.$inject = [$scope, '$2'];
432 | function $1Ctrl($scope, $2) {
433 | $4
434 | }
435 | angular.module($3).controller('$1Ctrl', $1Ctrl);
436 | ```
437 |
438 | ##### ngdoc
439 | ```
440 | /**
441 | * @ngdoc ${1:function}
442 | * @name $2
443 | * @description
444 | * $3
445 | *
446 | */
447 | ```
448 |
449 | ##### nghttp
450 | ```
451 | $http({method: '${1:GET}', url: '$2'})
452 | .success(function(data, status, headers, config) {
453 | $3
454 | })
455 | .error(function(data, status, headers, config) {
456 | $4
457 | });
458 | ```
459 |
460 | ##### ngcopy
461 | ```
462 | angular.copy(${1:source} ${2:, ${3:destination}})
463 | ```
464 |
465 | ##### ngel
466 | ```
467 | angular.element(${1:element});
468 | ```
469 |
470 | ##### ngeq
471 | ```
472 | angular.equals(${1:object1}, ${2:object2});
473 | ```
474 |
475 | ##### ngext
476 | ```
477 | angular.extend(${1:destinationObject}, ${2:sourceObject})
478 | ```
479 |
480 | ##### ngisa
481 | ```
482 | angular.isArray(${1:value})
483 | ```
484 |
485 | ##### ngisd
486 | ```
487 | angular.isDefined(${1:value})
488 | ```
489 |
490 | ##### ngisf
491 | ```
492 | angular.isFunction(${1:value})
493 | ```
494 |
495 | ##### ngisn
496 | ```
497 | angular.isNumber(${1:value})
498 | ```
499 |
500 | ##### ngiso
501 | ```
502 | angular.isObject(${1:value})
503 | ```
504 |
505 | ##### ngiss
506 | ```
507 | angular.isString(${1:value})
508 | ```
509 |
510 |
511 | ##### nglo
512 | ```
513 | angular.lowercase(${1:string});
514 | ```
515 |
516 | ##### ngup
517 | ```
518 | angular.uppercase(${1:string});
519 | ```
520 |
521 | ## FAQ
522 |
523 | #### Can't I use autocompletion with tab when I installed emmet plugin
524 |
525 | See [emmet's document](https://github.com/emmetio/emmet-atom#tab-key)
526 |
527 | In your `keymap.cson`, add the following code.
528 |
529 | ```
530 | 'atom-text-editor[data-grammar="text html angular"]:not([mini])':
531 | 'tab': 'emmet:expand-abbreviation-with-tab'
532 | ```
533 |
--------------------------------------------------------------------------------
/completions.json:
--------------------------------------------------------------------------------
1 | {
2 | "directives": [
3 | "ng-app",
4 | "ng-bind",
5 | "ng-bind-html",
6 | "ng-bind-template",
7 | "ng-blur",
8 | "ng-change",
9 | "ng-checked",
10 | "ng-class",
11 | "ng-class-even",
12 | "ng-class-odd",
13 | "ng-click",
14 | "ng-cloak",
15 | "ng-controller",
16 | "ng-copy",
17 | "ng-csp",
18 | "ng-cut",
19 | "ng-dblclick",
20 | "ng-disabled",
21 | "ng-focus",
22 | "ng-form",
23 | "ng-hide",
24 | "ng-href",
25 | "ng-if",
26 | "ng-include",
27 | "ng-init",
28 | "ng-jq",
29 | "ng-keydown",
30 | "ng-keypress",
31 | "ng-keyup",
32 | "ng-list",
33 | "ng-model",
34 | "ng-model-options",
35 | "ng-mousedown",
36 | "ng-mouseenter",
37 | "ng-mouseleave",
38 | "ng-mousemove",
39 | "ng-mouseover",
40 | "ng-mouseup",
41 | "ng-non-bindable",
42 | "ng-open",
43 | "ng-pluralize",
44 | "ng-show",
45 | "ng-transclude",
46 | "ng-view",
47 | "ng-messages",
48 | "ng-message",
49 | "ng-messages-include",
50 | "ng-swipe-left",
51 | "ng-swipe-right"
52 | ],
53 | "attributes": [
54 | "ng-dirty",
55 | "ng-false-value",
56 | "ng-invalid",
57 | "ng-maxlength",
58 | "ng-minlength",
59 | "ng-message-exp",
60 | "ng-options",
61 | "ng-paste",
62 | "ng-pattern",
63 | "ng-pristine",
64 | "ng-readonly",
65 | "ng-required",
66 | "ng-repeat",
67 | "ng-repeat-start",
68 | "ng-repeat-end",
69 | "ng-selected",
70 | "ng-src",
71 | "ng-srcset",
72 | "ng-style",
73 | "ng-submit",
74 | "ng-switch",
75 | "ng-switch-when",
76 | "ng-switch-default",
77 | "ng-trim",
78 | "ng-true-value",
79 | "ng-valid",
80 | "ng-value"
81 | ],
82 | "javascript": [
83 | "angular",
84 | "bind",
85 | "bootstrap",
86 | "copy",
87 | "element",
88 | "equals",
89 | "extend",
90 | "forEach",
91 | "fromJson",
92 | "identity",
93 | "injector",
94 | "isArray",
95 | "isDate",
96 | "isDefined",
97 | "isElement",
98 | "isFunction",
99 | "isNumber",
100 | "isObject",
101 | "isString",
102 | "isUndefined",
103 | "lowercase",
104 | "module",
105 | "noop",
106 | "reloadWithDebugInfo",
107 | "toJson",
108 | "uppercase",
109 |
110 | "$anchorScroll",
111 | "$animate",
112 | "$cacheFactory",
113 | "$compile",
114 | "$controller",
115 | "$document",
116 | "$exceptionHandler",
117 | "$filter",
118 | "$http",
119 | "$httpBackend",
120 | "$interpolate",
121 | "$interval",
122 | "$locale",
123 | "$location",
124 | "$log",
125 | "$parse",
126 | "$q",
127 | "$rootElement",
128 | "$rootScope",
129 | "$sce",
130 | "$sceDelegate",
131 | "$templateCache",
132 | "$templateRequest",
133 | "$timeout",
134 | "$window",
135 | "$animateProvider",
136 | "$compileProvider",
137 | "$controllerProvider",
138 | "$filterProvider",
139 | "$httpProvider",
140 | "$interpolateProvider",
141 | "$locationProvider",
142 | "$logProvider",
143 | "$parseProvider",
144 | "$rootScopeProvider",
145 | "$sceDelegateProvider",
146 | "$sceProvider",
147 | "$injector",
148 | "$provide",
149 | "$ariaProvider",
150 | "$aria",
151 | "$cookieStore",
152 | "$cookies",
153 |
154 | "mock",
155 | "$exceptionHandlerProvider",
156 | "TzDate",
157 | "dump",
158 | "inject",
159 | "$resource",
160 | "$routeProvider",
161 | "$route",
162 | "$routeParams",
163 | "$sanitize",
164 | "$swipe",
165 | "controller",
166 | "$scope",
167 | "service",
168 | "factory",
169 | "provider",
170 | "ngResource",
171 | "defer",
172 | "config",
173 | "when",
174 | "otherwise",
175 | "directive",
176 | "run",
177 | "filter"
178 | ]
179 | }
180 |
--------------------------------------------------------------------------------
/grammars/angularjs.cson:
--------------------------------------------------------------------------------
1 | 'scopeName': 'text.html.angular'
2 | 'name': 'HTML (Angular)'
3 | 'fileTypes': [
4 | 'htm'
5 | 'html'
6 | 'shtml'
7 | 'tmpl'
8 | 'tpl'
9 | 'xhtml'
10 | 'jsp'
11 | ]
12 | 'patterns': [
13 | {
14 | 'begin': '(?)((?i:(data-|x-)?ng(-|_|:)(form|include|pluralize|transclude|view|messages|message))\\b)'
15 | 'beginCaptures':
16 | '1':
17 | 'name': 'punctuation.definition.tag.begin.html'
18 | '2':
19 | 'name': 'entity.name.tag.block.any.html.angular'
20 | 'end': '(>)'
21 | 'endCaptures':
22 | '1':
23 | 'name': 'punctuation.definition.tag.end.html'
24 | 'name': 'meta.tag.block.any.html'
25 | }
26 | {
27 | 'begin': '(?)((?i:' +
28 | 'address|article|aside|applet|' +
29 | 'blockquote|center|' +
30 | 'dir|div|dl|dt|dd|' +
31 | 'fieldset|footer|form|frame|frameset|' +
32 | 'header|hr|h1|h2|h3|h4|h5|h6|' +
33 | 'iframe|' +
34 | 'menu|nav|noframes|' +
35 | 'object|ol|' +
36 | 'p|pre|' +
37 | 'section|ul' +
38 | ')\\b)'
39 | 'beginCaptures':
40 | '1':
41 | 'name': 'punctuation.definition.tag.begin.html'
42 | '2':
43 | 'name': 'entity.name.tag.block.any.html'
44 | 'end': '(>)'
45 | 'endCaptures':
46 | '1':
47 | 'name': 'punctuation.definition.tag.end.html'
48 | 'name': 'meta.tag.block.any.html'
49 | 'patterns': [
50 | { 'include': '#angular-directive-attribute' }
51 | { 'include': '#tag-stuff' }
52 | ]
53 | }
54 | {
55 | 'begin': '(?)((?i:'+
56 | 'a|a|abbr|acronym|area|' +
57 | 'b|base|basefont|bdo|big|body|br|button|' +
58 | 'caption|cite|code|col|colgroup|' +
59 | 'del|dfn|' +
60 | 'em|font|' +
61 | 'head|html|' +
62 | 'i|img|input|ins|isindex|' +
63 | 'kbd|' +
64 | 'label|legend|li|link|' +
65 | 'map|meta|' +
66 | 'noscript|' +
67 | 'optgroup|option|' +
68 | 'param|q|' +
69 | 's|samp|script|select|small|span|strike|strong|style|sub|sup|' +
70 | 'table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|' +
71 | 'u|var' +
72 | ')\\b)'
73 | 'beginCaptures':
74 | '1':
75 | 'name': 'punctuation.definition.tag.begin.html'
76 | '2':
77 | 'name': 'entity.name.tag.inline.any.html'
78 | 'end': '((?: ?/)?>)'
79 | 'endCaptures':
80 | '1':
81 | 'name': 'punctuation.definition.tag.end.html'
82 | 'name': 'meta.tag.inline.any.html'
83 | 'patterns': [
84 | { 'include': '#angular-directive-attribute' }
85 | { 'include': '#tag-stuff' }
86 | ]
87 | }
88 | {
89 | 'begin': '(?:^\\s+)?(<)((?i:script))\\b(?=[^>]*\\btype\\s*=\\s*[\'"]?text/ng-template[\'"]?)(?![^>]*/>)'
90 | 'beginCaptures':
91 | '1':
92 | 'name': 'punctuation.definition.tag.html'
93 | '2':
94 | 'name': 'entity.name.tag.script.html'
95 | 'end': '(?<=(script|SCRIPT))(>)(?:\\s*\\n)?'
96 | 'endCaptures':
97 | '2':
98 | 'name': 'punctuation.definition.tag.html'
99 | 'contentName': 'text.embedded.html'
100 | 'patterns': [
101 | {
102 | 'include': '#tag-stuff'
103 | }
104 | {
105 | 'begin': '(?)'
106 | 'captures':
107 | '1':
108 | 'name': 'punctuation.definition.tag.html'
109 | '2':
110 | 'name': 'entity.name.tag.script.html'
111 | 'end': '()((?i:script))'
112 | 'patterns': [
113 | {
114 | 'include': 'text.html.angular'
115 | }
116 | ]
117 | }
118 | ]
119 | }
120 | { 'include': '#angular-expressions' }
121 | { 'include': 'text.html.basic' }
122 | ]
123 | 'repository':
124 | 'angular-expressions':
125 | 'begin': '(\\{\\{)'
126 | 'beginCaptures':
127 | '1':
128 | 'name': 'punctuation.definition.block.begin.angular'
129 | 'end': '(\\}\\})'
130 | 'endCaptures':
131 | '1':
132 | 'name': 'punctuation.definition.block.end.angular'
133 | 'name': 'meta.tag.template.angular'
134 | 'patterns':[
135 | { 'include': 'source.js' }
136 | ]
137 | 'angular-directive-attribute':
138 | 'begin': '\\b((?i:(data-|x-)?ng(-|_|:)(' +
139 | 'animate-children|app|' +
140 | 'bind|bind-html|bind-template|blur|' +
141 | 'change|checked|class|class-even|class-odd|click|cloak|controller|copy|csp|cut|' +
142 | 'dblclick|disabled|' +
143 | 'focus|form|' +
144 | 'hide|href|' +
145 | 'if|include|init|' +
146 | 'jq|' +
147 | 'keydown|keypress|keyup|' +
148 | 'list|' +
149 | 'messages|message|model-options|maxlength|minlength|model|mousedown|mouseenter|mouseleave|mousemove|mouseover|mouseup|' +
150 | 'non-bindable|' +
151 | 'open|options|' +
152 | 'paste|pattern|pluralize|' +
153 | 'readonly|repeat-start|repeat-end|repeat|required|' +
154 | 'selected|show|src|srcset|style|strict-di|submit|switch-when|switch-default|switch|' +
155 | 'transclude|' +
156 | 'value|' +
157 | 'swipe-left|swipe-right|view|' +
158 | ')))\\b\\s*(=?)'
159 | 'beginCaptures':
160 | '1':
161 | 'name': 'support.other.attribute-name.html.angular'
162 | 'end': '(?<=\'|")|(?=\\s|>)'
163 | 'name': 'meta.attribute.html.angular'
164 | 'patterns': [
165 | {
166 | 'begin': '"'
167 | 'beginCaptures':
168 | '0':
169 | 'name': 'punctuation.definition.string.begin.html.angular'
170 | 'end': '"'
171 | 'endCaptures':
172 | '0':
173 | 'name': 'punctuation.definition.string.end.html.angular'
174 | 'name': 'string.quoted.double.html.angular'
175 | 'patterns': [
176 | { 'include': '#angular-expressions' }
177 | ]
178 | }
179 | {
180 | 'begin': '\''
181 | 'beginCaptures':
182 | '0':
183 | 'name': 'punctuation.definition.string.begin.html.angular'
184 | 'end': '\''
185 | 'endCaptures':
186 | '0':
187 | 'name': 'punctuation.definition.string.end.html.angular'
188 | 'name': 'string.quoted.single.html.angular'
189 | 'patterns': [
190 | { 'include': '#angular-expressions' }
191 | ]
192 | }
193 | ]
194 | 'embedded-code':
195 | 'patterns': [
196 | {
197 | 'include': '#smarty'
198 | }
199 | {
200 | 'include': '#python'
201 | }
202 | ]
203 | 'entities':
204 | 'patterns': [
205 | {
206 | 'captures':
207 | '1':
208 | 'name': 'punctuation.definition.entity.html'
209 | '3':
210 | 'name': 'punctuation.definition.entity.html'
211 | 'match': '(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)'
212 | 'name': 'constant.character.entity.html'
213 | }
214 | {
215 | 'match': '&'
216 | 'name': 'invalid.illegal.bad-ampersand.html'
217 | }
218 | ]
219 | 'python':
220 | 'begin': '(?:^\\s*)<\\?python(?!.*\\?>)'
221 | 'end': '\\?>(?:\\s*$\\n)?'
222 | 'name': 'source.python.embedded.html'
223 | 'patterns': [
224 | {
225 | 'include': 'source.python'
226 | }
227 | ]
228 | 'smarty':
229 | 'patterns': [
230 | {
231 | 'begin': '(\\{(literal)\\})'
232 | 'captures':
233 | '1':
234 | 'name': 'source.smarty.embedded.html'
235 | '2':
236 | 'name': 'support.function.built-in.smarty'
237 | 'end': '(\\{/(literal)\\})'
238 | }
239 | {
240 | 'begin': '{{|{'
241 | 'disabled': 1
242 | 'end': '}}|}'
243 | 'name': 'source.smarty.embedded.html'
244 | 'patterns': [
245 | {
246 | 'include': 'source.smarty'
247 | }
248 | ]
249 | }
250 | ]
251 | 'string-double-quoted':
252 | 'begin': '"'
253 | 'beginCaptures':
254 | '0':
255 | 'name': 'punctuation.definition.string.begin.html'
256 | 'end': '"'
257 | 'endCaptures':
258 | '0':
259 | 'name': 'punctuation.definition.string.end.html'
260 | 'name': 'string.quoted.double.html'
261 | 'patterns': [
262 | {
263 | 'include': '#embedded-code'
264 | }
265 | {
266 | 'include': '#entities'
267 | }
268 | ]
269 | 'string-single-quoted':
270 | 'begin': '\''
271 | 'beginCaptures':
272 | '0':
273 | 'name': 'punctuation.definition.string.begin.html'
274 | 'end': '\''
275 | 'endCaptures':
276 | '0':
277 | 'name': 'punctuation.definition.string.end.html'
278 | 'name': 'string.quoted.single.html'
279 | 'patterns': [
280 | {
281 | 'include': '#embedded-code'
282 | }
283 | {
284 | 'include': '#entities'
285 | }
286 | ]
287 | 'tag-generic-attribute':
288 | 'match': '(?<=[^=])\\b([a-zA-Z0-9:-]+)'
289 | 'name': 'entity.other.attribute-name.html'
290 | 'tag-id-attribute':
291 | 'begin': '\\b(id)\\b\\s*(=)'
292 | 'captures':
293 | '1':
294 | 'name': 'entity.other.attribute-name.id.html'
295 | '2':
296 | 'name': 'punctuation.separator.key-value.html'
297 | 'end': '(?<=\'|")|(?=\\s|>)'
298 | 'name': 'meta.attribute-with-value.id.html'
299 | 'patterns': [
300 | {
301 | 'begin': '"'
302 | 'beginCaptures':
303 | '0':
304 | 'name': 'punctuation.definition.string.begin.html'
305 | 'contentName': 'meta.toc-list.id.html'
306 | 'end': '"'
307 | 'endCaptures':
308 | '0':
309 | 'name': 'punctuation.definition.string.end.html'
310 | 'name': 'string.quoted.double.html'
311 | 'patterns': [
312 | {
313 | 'include': '#embedded-code'
314 | }
315 | {
316 | 'include': '#entities'
317 | }
318 | ]
319 | }
320 | {
321 | 'begin': '\''
322 | 'beginCaptures':
323 | '0':
324 | 'name': 'punctuation.definition.string.begin.html'
325 | 'contentName': 'meta.toc-list.id.html'
326 | 'end': '\''
327 | 'endCaptures':
328 | '0':
329 | 'name': 'punctuation.definition.string.end.html'
330 | 'name': 'string.quoted.single.html'
331 | 'patterns': [
332 | {
333 | 'include': '#embedded-code'
334 | }
335 | {
336 | 'include': '#entities'
337 | }
338 | ]
339 | }
340 | {
341 | 'include': '#unquoted-attribute'
342 | }
343 | ]
344 | 'tag-stuff':
345 | 'patterns': [
346 | {
347 | 'include': '#tag-id-attribute'
348 | }
349 | {
350 | 'include': '#tag-generic-attribute'
351 | }
352 | {
353 | 'include': '#string-double-quoted'
354 | }
355 | {
356 | 'include': '#string-single-quoted'
357 | }
358 | {
359 | 'include': '#embedded-code'
360 | }
361 | {
362 | 'include': '#unquoted-attribute'
363 | }
364 | ]
365 | 'unquoted-attribute':
366 | 'match': '(?<==)(?:[^\\s<>/\'"]|/(?!>))+'
367 | 'name': 'string.unquoted.html'
368 |
--------------------------------------------------------------------------------
/keymaps/angularjs.cson:
--------------------------------------------------------------------------------
1 | # Keybindings require three things to be fully defined: A selector that is
2 | # matched against the focused element, the keystroke and the command to
3 | # execute.
4 | #
5 | # Below is a basic keybinding which registers on all platforms by applying to
6 | # the root workspace element.
7 |
8 | # For more detailed documentation see
9 | # https://atom.io/docs/latest/advanced/keymaps
10 | #'.workspace':
11 | # 'ctrl-alt-o': 'angularjs:toggle'
12 |
--------------------------------------------------------------------------------
/lib/angularjs.coffee:
--------------------------------------------------------------------------------
1 | provider = require './provider'
2 |
3 | module.exports =
4 | activate: ->
5 |
6 | getProvider: -> provider
7 |
--------------------------------------------------------------------------------
/lib/provider.coffee:
--------------------------------------------------------------------------------
1 | # ref https://github.com/atom/autocomplete-html/blob/master/lib/provider.coffee
2 |
3 | COMPLETIONS = require '../completions.json'
4 |
5 | attributePattern = /\s+([a-zA-Z][-a-zA-Z]*)\s*=\s*$/
6 |
7 | module.exports =
8 | selector: '.source.js, .text.html'
9 | disableForSelector: '.source.js .comment, .text.html .comment'
10 | filterSuggestions: true
11 | completions: COMPLETIONS
12 |
13 | getSuggestions: (request) ->
14 | if @isJavaScript(request) and not @isIgnoreInJavaScript(request)
15 | @getJavascriptCompletions(request)
16 | else if @isHtml(request)
17 | if @isAttributeStart(request)
18 | @getAttributeNameCompletions(request)
19 | else if @isTagStart(request)
20 | @getTagNameCompletions(request)
21 | else
22 | []
23 |
24 | isJavaScript: ({ scopeDescriptor }) ->
25 | for scope in scopeDescriptor.getScopesArray()
26 | return true if scope.startsWith('source') and scope.endsWith('.js')
27 | return false
28 |
29 | isIgnoreInJavaScript: ({ scopeDescriptor, prefix }) ->
30 | scopes = scopeDescriptor.getScopesArray()
31 | return true if scopes.indexOf('punctuation.terminator.statement.js') isnt -1 or
32 | scopes.indexOf('keyword.operator.assignment.js') isnt -1 or
33 | scopes.indexOf('meta.delimiter.object.comma.js') isnt -1 or
34 | scopes.indexOf('keyword.operator.comparison.js') isnt -1 or
35 | scopes.indexOf('keyword.operator.ternary.js') isnt -1 or
36 | scopes.indexOf('keyword.operator.js') isnt -1 or
37 | scopes.indexOf('string.quoted.template.js') isnt -1 or
38 | prefix.trim() is ''
39 | return false
40 |
41 | isHtml: ({ scopeDescriptor }) ->
42 | for scope in scopeDescriptor.getScopesArray()
43 | return true if scope.endsWith('.html')
44 | return false
45 |
46 | isAttributeStart: ({prefix, scopeDescriptor, bufferPosition, editor}) ->
47 | scopes = scopeDescriptor.getScopesArray()
48 | return @hasTagScope(scopes) if not @getPreviousAttribute(editor, bufferPosition) and prefix and not prefix.trim()
49 |
50 | previousBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - 1)]
51 | previousScopes = editor.scopeDescriptorForBufferPosition(previousBufferPosition)
52 | previousScopesArray = previousScopes.getScopesArray()
53 |
54 | return true if previousScopesArray.indexOf('entity.other.attribute-name.html') isnt -1
55 | return false unless @hasTagScope(scopes)
56 |
57 | # autocomplete here:
58 | # not here: |
59 | scopes.indexOf('punctuation.definition.tag.end.html') isnt -1 and
60 | previousScopesArray.indexOf('punctuation.definition.tag.end.html') is -1
61 |
62 | isTagStart: ({ prefix, scopeDescriptor, bufferPosition, editor }) ->
63 | return @hasTagScope(scopeDescriptor.getScopesArray()) if prefix.trim() and prefix.indexOf('<') is -1
64 |
65 | # autocomplete-plus's default prefix setting does not capture <. Manually check for it.
66 | prefix = editor.getTextInRange([[bufferPosition.row, bufferPosition.column - 1], bufferPosition])
67 |
68 | scopes = scopeDescriptor.getScopesArray()
69 |
70 | # Don't autocomplete in embedded languages
71 | prefix is '<' and scopes[0] is 'text.html.basic' and scopes.length is 1
72 |
73 | hasTagScope: (scopes) ->
74 | for scope in scopes
75 | return true if scope.startsWith('meta.tag.') and scope.endsWith('.html')
76 | return false
77 |
78 | hasStringScope: (scopes) ->
79 | scopes.indexOf('string.quoted.double.html') isnt -1 or
80 | scopes.indexOf('string.quoted.single.html') isnt -1
81 |
82 | getAttributeNameCompletions: ({prefix, editor, bufferPosition}) ->
83 | completions = []
84 | cantidates = @completions.directives.concat @completions.attributes
85 | for idx, attribute of cantidates when not prefix.trim() or firstCharsEqual(attribute, prefix)
86 | completions.push({ text: attribute, type: 'attribute' })
87 | completions
88 |
89 | getTagNameCompletions: ({ prefix, editor, bufferPosition }) ->
90 | # autocomplete-plus's default prefix setting does not capture <. Manually check for it.
91 | ignorePrefix = editor.getTextInRange([[bufferPosition.row, bufferPosition.column - 1], bufferPosition]) is '<'
92 |
93 | completions = []
94 | for idx, tag of @completions.directives when ignorePrefix or firstCharsEqual(tag, prefix)
95 | completions.push({ text: tag, type: 'tag' })
96 | completions
97 |
98 | getJavascriptCompletions: ({ prefix, editor, bufferPosition }) ->
99 | completions = []
100 | prefix = @getPrefix(editor, bufferPosition)
101 | for idx, tag of @completions.javascript
102 | completions.push({ text: tag, type: 'angularjs', replacementPrefix: prefix })
103 | completions
104 |
105 | getPreviousAttribute: (editor, bufferPosition) ->
106 | # Remove everything until the opening quote (if we're in a string)
107 | quoteIndex = bufferPosition.column - 1 # Don't start at the end of the line
108 | while quoteIndex
109 | scopes = editor.scopeDescriptorForBufferPosition([bufferPosition.row, quoteIndex])
110 | scopesArray = scopes.getScopesArray()
111 | break if not @hasStringScope(scopesArray) or scopesArray.indexOf('punctuation.definition.string.begin.html') isnt -1
112 | quoteIndex--
113 |
114 | attributePattern.exec(editor.getTextInRange([[bufferPosition.row, 0], [bufferPosition.row, quoteIndex]]))?[1]
115 |
116 | getPrefix: (editor, bufferPosition) ->
117 | # Whatever your prefix regex might be
118 | regex = /\$?[\w0-9_-]+$/
119 |
120 | # Get the text for the line up to the triggered buffer position
121 | line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition])
122 |
123 | # Match the regex to the line, and return the match
124 | line.match(regex)?[0] or ''
125 |
126 | firstCharsEqual = (str1, str2) ->
127 | str1[0].toLowerCase() is str2[0].toLowerCase()
128 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angularjs",
3 | "version": "0.5.3",
4 | "main": "./lib/angularjs",
5 | "description": "An AngularJS package for Atom",
6 | "keywords": [
7 | "angular",
8 | "angularjs",
9 | "javascript",
10 | "frontend"
11 | ],
12 | "repository": "https://github.com/angular-ui/AngularJS-Atom",
13 | "readmeFilename": "README.md",
14 | "license": "MIT",
15 | "engines": {
16 | "atom": ">=0.174.0 <2.0.0"
17 | },
18 | "providedServices": {
19 | "autocomplete.provider": {
20 | "versions": {
21 | "2.0.0": "getProvider"
22 | }
23 | }
24 | },
25 | "dependencies": {}
26 | }
27 |
--------------------------------------------------------------------------------
/screenshots/autocompletes.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angular-ui/AngularJS-Atom/052c02c8e5936ec6e7ec8a0db617ea773a670077/screenshots/autocompletes.gif
--------------------------------------------------------------------------------
/screenshots/snippets.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angular-ui/AngularJS-Atom/052c02c8e5936ec6e7ec8a0db617ea773a670077/screenshots/snippets.gif
--------------------------------------------------------------------------------
/snippets/html-templates.cson:
--------------------------------------------------------------------------------
1 | ".text.html:not(.meta.tag)":
2 | "angular scaffold":
3 | "prefix": "ngindex"
4 | "body": """
5 |
6 |
7 |
8 |
9 |
10 | $2
11 |
12 |
13 | """
14 | "angular.js from CDN":
15 | "prefix": "ngsa"
16 | "body": """
17 |
18 | """
19 | "ngTemplate script tag":
20 | "prefix": "ngst"
21 | "body": """
22 |
25 | """
26 | "ngInclude":
27 | "prefix": "nginc"
28 | "body": """
29 |
30 | """
31 | "ngPluralize":
32 | "prefix": "ngplural"
33 | "body": """
34 |
35 | """
36 | "ngSwitch":
37 | "prefix": "ngswitch"
38 | "body": """
39 | $2
40 | """
41 | "script template":
42 | "prefix": "ngtmpl"
43 | "body": """
44 |
45 | """
46 | "ngView":
47 | "prefix": "ngview"
48 | "body": """
49 |
50 | """
51 |
--------------------------------------------------------------------------------
/snippets/js-templates.cson:
--------------------------------------------------------------------------------
1 | ".source.js, .source.js-semantic":
2 | "module":
3 | "prefix": "ngm"
4 | "body": "angular.module('$1', [$2])$3"
5 | "module as variable":
6 | "prefix": "ngma"
7 | "body": "var $1 = angular.module('$2', [$3])$4"
8 | "module with config":
9 | "prefix": "ngmc"
10 | "body": """
11 | var $1 = angular.module('$2', [$3], function($4) {
12 | $5
13 | })$6
14 | """
15 | "module factory":
16 | "prefix": "ngmfa"
17 | "body": """
18 | factory('$1', function($2) {
19 | $3
20 | })$4
21 | """
22 | "module filter":
23 | "prefix": "ngmfi"
24 | "body": """
25 | filter('$1', function($2) {
26 | return function (input, $3) {
27 | $4
28 | };
29 | })$5
30 | """
31 | "module service":
32 | "prefix": "ngms"
33 | "body": """
34 | service('$1', function($2) {
35 | $3
36 | })$4
37 | """
38 | "$routeProvider.otherwise":
39 | "prefix": "ngro"
40 | "body": """
41 | $routeProvider.otherwise({redirectTo: '$1' })
42 | """
43 | "$routeProvider.when":
44 | "prefix": "ngrw"
45 | "body": """
46 | $routeProvider.when('$1', {templateUrl: '$2', controller: '$3'})
47 | """
48 | "$routeProvider.when with resolve":
49 | "prefix": "ngrwr"
50 | "body": """
51 | $routeProvider.when('$1', {
52 | templateUrl: '$2',
53 | controller: '$3'${4:,
54 | resolve: {
55 | $5
56 | }}
57 | })
58 | """
59 | "angular forEach":
60 | "prefix": "ngfor"
61 | "body": """
62 | angular.forEach($1, function(value, key) {
63 | $2
64 | })
65 | """
66 | "directive include link function":
67 | "prefix": "ngdl"
68 | "body": """
69 | .directive('$1', function($2) {
70 | $3
71 | return function(scope, element, attrs) {
72 | $4
73 | }
74 | })$5
75 | """
76 | "linking func of directive":
77 | "prefix": "ngdlf"
78 | "body": """
79 | function (scope, element, attrs) {
80 | $1
81 | }
82 | """
83 | "directive include compile function":
84 | "prefix": "ngdc"
85 | "body": """
86 | .directive('$1', function factory($2) {
87 | var directiveDefinitionObject = {
88 | $3
89 | compile: function compile(tElement, tAttrs, transclude) {
90 | $4
91 | return function (scope, element, attrs) {
92 | $5
93 | }
94 | }
95 | };
96 | return directiveDefinitionObject;
97 | })$6
98 | """
99 | "compile function":
100 | "prefix": "ngdcf"
101 | "body": """
102 | function compile(tElement, tAttrs, transclude) {
103 | $1
104 | return function (scope, element, attrs) {
105 | $2
106 | }
107 | }$3
108 | """
109 | "$scope.$broadcast":
110 | "prefix": "ngb"
111 | "body": """
112 | $scope.$broadcast('$1', $2)
113 | """
114 | "$scope.$emit":
115 | "prefix": "nge"
116 | "body": """
117 | $scope.$emit('', )
118 | """
119 | "function inside $scope":
120 | "prefix": "ngf"
121 | "body": """
122 | $scope.$1 = function($2) {
123 | $3
124 | };
125 | """
126 | "controller prototype method":
127 | "prefix": "ngcp"
128 | "body": """
129 | $1Ctrl.prototype.$2 = function $2($3) {
130 | $4
131 | };
132 | """
133 | "$scope.$on":
134 | "prefix": "ngon"
135 | "body": """
136 | $scope.$on('$1', function(event, $2) {
137 | $3
138 | })
139 | """
140 | "variable inside $scope":
141 | "prefix": "ngv"
142 | "body": """
143 | $scope.$1 = $2;
144 | """
145 | "$scope.$watch":
146 | "prefix": "ngw"
147 | "body": """
148 | $scope.$watch('$1', function(newValue, oldValue) {
149 | $2
150 | })
151 | """
152 | "$timeout":
153 | "prefix": "ngto"
154 | "body": """
155 | $timeout(function() {
156 | $2
157 | }, $1)
158 | """
159 | "controller":
160 | "prefix": "ngc"
161 | "body": """
162 | var $1 = function($scope, $2) {
163 | $3
164 | };
165 | """
166 | "controller $inject Syntax":
167 | "prefix": "ngc$"
168 | "body": """
169 | $1Ctrl.$inject = ['$scope', '$2'];
170 | function $1Ctrl($scope, $2) {
171 | $4
172 | }
173 | angular.module($3).controller('$1Ctrl', $1Ctrl)
174 | """
175 | "ngdocs comment":
176 | "prefix": "ngdoc"
177 | "body": """
178 | /**
179 | * @ngdoc ${1:function}
180 | * @name $2
181 | * @description
182 | * $3
183 | *
184 | */
185 | """
186 | "$http":
187 | "prefix": "nghttp"
188 | "body": """
189 | $http({method: '${1:GET}', url: '$2'})
190 | .then(function successCallback(data, status, headers, config) {
191 | $3
192 | },
193 | function errorCallback(data, status, headers, config) {
194 | $4
195 | });
196 | """
197 | "copy":
198 | "prefix": "ngcopy"
199 | "body": """
200 | angular.copy(${1:source} ${2:, ${3:destination}})
201 | """
202 | "element":
203 | "prefix": 'ngel'
204 | "body": "angular.element(${1:element})$2"
205 | "equals":
206 | "prefix": "ngeq"
207 | "body": "angular.equals(${1:object1}, ${2:object2})"
208 | "extend":
209 | "prefix": "ngext"
210 | "body": "angular.extend(${1:destinationObject}, ${2:sourceObject})$3"
211 | "isArray":
212 | "prefix": "ngisa"
213 | "body": "angular.isArray(${1:value})"
214 | "isDefined":
215 | "prefix": "ngisd"
216 | "body": "angular.isDefined(${1:value})"
217 | "isFunction":
218 | "prefix": "ngisf"
219 | "body": "angular.isFunction(${1:value})"
220 | "isNumber":
221 | "prefix": "ngisn"
222 | "body": "angular.isNumber(${1:value})"
223 | "isObject":
224 | "prefix": "ngiso"
225 | "body": "angular.isObject(${1:value})"
226 | "isString":
227 | "prefix": "ngiss"
228 | "body": "angular.isString(${1:value})"
229 | "lowercase":
230 | "prefix": "nglo"
231 | "body": "angular.lowercase(${1:string})$2"
232 | "uppercase":
233 | "prefix": "ngup"
234 | "body": "angular.uppercase(${1:string})$2"
235 |
--------------------------------------------------------------------------------
/spec/grammar-spec.coffee:
--------------------------------------------------------------------------------
1 | describe 'directive grammar', ->
2 | grammar = null
3 |
4 | beforeEach ->
5 | waitsForPromise ->
6 | atom.packages.activatePackage('angularjs')
7 |
8 | runs ->
9 | grammar = atom.grammars.grammarForScopeName('text.html.angular')
10 |
11 | it 'parses the grammar', ->
12 | expect(grammar).toBeTruthy()
13 | expect(grammar.scopeName).toBe 'text.html.angular'
14 |
15 | describe 'directive attributes', ->
16 | it 'tokenizes ng-repeat attribute inside HTML', ->
17 | lines = grammar.tokenizeLines '''
18 | {{availability}}
19 | '''
20 |
21 | expect(lines[0][3]).toEqual value: 'ng-repeat', scopes: ['text.html.angular', 'meta.tag.block.any.html', 'meta.attribute.html.angular', 'support.other.attribute-name.html.angular']
22 |
23 | it 'tokenizes ng-src and ng-click attributes inside HTML', ->
24 | lines = grammar.tokenizeLines '''
25 |
26 |
27 |
28 | '''
29 |
30 | expect(lines[0][3]).toEqual value: 'ng-repeat', scopes: ['text.html.angular', 'meta.tag.inline.any.html', 'meta.attribute.html.angular', 'support.other.attribute-name.html.angular']
31 | expect(lines[1][4]).toEqual value: 'ng-src', scopes: ['text.html.angular', 'meta.tag.inline.any.html', 'meta.attribute.html.angular', 'support.other.attribute-name.html.angular']
32 | expect(lines[1][12]).toEqual value: 'ng-click', scopes: ['text.html.angular', 'meta.tag.inline.any.html', 'meta.attribute.html.angular', 'support.other.attribute-name.html.angular']
33 |
34 | it 'tokenizes ng-view attribute without value inside HTML', ->
35 | lines = grammar.tokenizeLines '''
36 |
37 | '''
38 |
39 | expect(lines[0][3]).toEqual value: 'ng-view', scopes: ['text.html.angular', 'meta.tag.block.any.html', 'meta.attribute.html.angular', 'support.other.attribute-name.html.angular']
40 |
41 | it 'tokenizes capitalized ng-repeat attribute inside HTML', ->
42 | lines = grammar.tokenizeLines '''
43 | {{availability}}
44 | '''
45 |
46 | expect(lines[0][3]).toEqual value: 'NG-REPEAT', scopes: ['text.html.angular', 'meta.tag.block.any.html', 'meta.attribute.html.angular', 'support.other.attribute-name.html.angular']
47 |
48 | it 'tokenizes ng-repeat-start and ng-repeat-end attribute', ->
49 | lines = grammar.tokenizeLines '''
50 |
51 |
52 | '''
53 |
54 | expect(lines[0][3]).toEqual value: 'ng-repeat-start', scopes: ['text.html.angular', 'meta.tag.block.any.html', 'meta.attribute.html.angular', 'support.other.attribute-name.html.angular']
55 | expect(lines[1][3]).toEqual value: 'ng-repeat-end', scopes: ['text.html.angular', 'meta.tag.block.any.html', 'meta.attribute.html.angular', 'support.other.attribute-name.html.angular']
56 |
57 | it 'tokenizes ng-controller attribute in body tag', ->
58 | lines = grammar.tokenizeLines '''
59 |
60 | '''
61 |
62 | expect(lines[0][3]).toEqual value: 'ng-controller', scopes: ['text.html.angular', 'meta.tag.inline.any.html', 'meta.attribute.html.angular', 'support.other.attribute-name.html.angular']
63 |
64 | it 'tokenizes ng-s attribute', ->
65 | lines = grammar.tokenizeLines '''
66 |