├── .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 | ![](https://raw.github.com/angular-ui/AngularJS-Atom/master/screenshots/autocompletes.gif) 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 | ![](https://raw.github.com/angular-ui/AngularJS-Atom/master/screenshots/snippets.gif) 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': '()' 21 | 'endCaptures': 22 | '1': 23 | 'name': 'punctuation.definition.tag.end.html' 24 | 'name': 'meta.tag.block.any.html' 25 | } 26 | { 27 | 'begin': '()' 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': '()' 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': '(?<=)(?:\\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': '()' 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 |