├── .eslintignore ├── spec ├── fixtures │ ├── dira │ │ └── dira.1 │ │ │ └── dira.2 │ │ │ ├── .babelrc │ │ │ ├── good.js │ │ │ ├── react.js │ │ │ ├── react.jsx │ │ │ ├── bad.js │ │ │ └── ignored.js │ ├── projectRoot │ │ ├── test.js │ │ ├── src │ │ │ ├── a.min.js │ │ │ ├── test.es │ │ │ ├── test.es6 │ │ │ ├── test.js │ │ │ ├── test.jsx │ │ │ └── test.babel │ │ └── .languagebabel │ ├── grammar │ │ ├── babel-sublime │ │ │ ├── js-template-strings.js │ │ │ ├── js-class.js │ │ │ ├── jsx-features.jsx │ │ │ ├── js-symbols.js │ │ │ └── jsx-text.jsx │ │ ├── flow-predicates.js │ │ ├── css.js │ │ ├── private-fields.js │ │ └── declare.js │ └── dirb │ │ └── good.js ├── .eslintrc ├── default-config.js ├── grammar-spec.coffee ├── create-tag-grammar-spec.js └── auto-indent-spec.coffee ├── .gitignore ├── grammars ├── Embedded Babel Language.json ├── ttl-26d12b471f2035277d061587e2033f31d73aaf261c3f4b1e48d5e0c0ad2087f8.json └── Babel Regex.json ├── src ├── .babelrc ├── .languagebabel └── create-ttl-grammar.js ├── .eslintrc ├── .gitattributes ├── appveyor.yml ├── .travis.yml ├── LICENSE.md ├── settings └── language-babel.json ├── lib ├── auto-complete-emmet-css.js ├── transpiler-task.coffee ├── did-insert-text.coffee ├── main.coffee ├── auto-complete-jsx.coffee ├── auto-complete-styled-components.coffee └── completions-jsx.coffee ├── styles └── language-babel.less ├── coffeelint.json └── package.json /.eslintignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | spec/fixtures 3 | -------------------------------------------------------------------------------- /spec/fixtures/dira/dira.1/dira.2/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /spec/fixtures/projectRoot/test.js: -------------------------------------------------------------------------------- 1 | let x = "simple test"; -------------------------------------------------------------------------------- /spec/fixtures/projectRoot/src/a.min.js: -------------------------------------------------------------------------------- 1 | let x="simple test" 2 | -------------------------------------------------------------------------------- /spec/fixtures/projectRoot/src/test.es: -------------------------------------------------------------------------------- 1 | let x="simple test" 2 | -------------------------------------------------------------------------------- /spec/fixtures/projectRoot/src/test.es6: -------------------------------------------------------------------------------- 1 | let x="simple test" 2 | -------------------------------------------------------------------------------- /spec/fixtures/projectRoot/src/test.js: -------------------------------------------------------------------------------- 1 | let x="simple test" 2 | -------------------------------------------------------------------------------- /spec/fixtures/projectRoot/src/test.jsx: -------------------------------------------------------------------------------- 1 | let x="simple test" 2 | -------------------------------------------------------------------------------- /spec/fixtures/projectRoot/src/test.babel: -------------------------------------------------------------------------------- 1 | let x="simple test" 2 | -------------------------------------------------------------------------------- /spec/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "atomtest": true, 4 | "jasmine": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | babel-source 5 | babel-target 6 | thumbs.db 7 | /testJs/ 8 | package-lock.json 9 | -------------------------------------------------------------------------------- /grammars/Embedded Babel Language.json: -------------------------------------------------------------------------------- 1 | { 2 | "scopeName": "source.embedded.js.jsx", 3 | "injectionSelector": "source.embedded.jsx", 4 | "patterns": [ 5 | { 6 | "include": "source.js.jsx" 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /src/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "node5" 4 | ], 5 | "plugins": [ 6 | "transform-class-properties", 7 | "syntax-class-properties", 8 | "transform-decorators-legacy" 9 | ], 10 | "sourceMaps": "inline" 11 | } 12 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": "eslint:recommended", 4 | "env": { 5 | "browser": true, 6 | "node": true, 7 | "es6": true 8 | }, 9 | "rules": { 10 | "indent": ["error", 2], 11 | "semi": ["error", "always"] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /grammars/ttl-26d12b471f2035277d061587e2033f31d73aaf261c3f4b1e48d5e0c0ad2087f8.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "language-babel-extension", 3 | "comment": "Auto generated Tag Extensions for language-babel", 4 | "comment": "Please do not edit this file directly", 5 | "scopeName": "languagebabel.ttlextension", 6 | "fileTypes": [], 7 | "patterns": [ 8 | 9 | ] 10 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /spec/default-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | allowLocalOverride: false, 3 | babelMapsAddUrl: true, 4 | babelMapsPath: "", 5 | babelSourcePath: "", 6 | babelTranspilePath: "", 7 | createMap: false, 8 | createTargetDirectories: false, 9 | createTranspiledCode: true, 10 | disableWhenNoBabelrcFileInPath: false, 11 | keepFileExtension: false, 12 | suppressSourcePathMessages: false, 13 | suppressTranspileOnSaveMessages: false, 14 | transpileOnSave: true, 15 | autoIndentJSX: true 16 | }; 17 | -------------------------------------------------------------------------------- /src/.languagebabel: -------------------------------------------------------------------------------- 1 | { 2 | "babelSourcePath": "src", 3 | "babelMapsAddUrl": false, 4 | "babelTranspilePath": "lib", 5 | "createMap": false, 6 | "createTranspiledCode": true, 7 | "disableWhenNoBabelrcFileInPath": true, 8 | "projectRoot": false, 9 | "suppressSourcePathMessages": true, 10 | "suppressTranspileOnSaveMessages": false, 11 | "transpileOnSave": true 12 | } 13 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | platform: x64 4 | 5 | branches: 6 | only: 7 | - master 8 | 9 | clone_depth: 10 10 | 11 | skip_tags: true 12 | 13 | environment: 14 | APM_TEST_PACKAGES: 15 | 16 | matrix: 17 | - ATOM_CHANNEL: stable 18 | - ATOM_CHANNEL: beta 19 | 20 | install: 21 | - ps: Install-Product node 5 22 | 23 | build_script: 24 | - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/atom/ci/master/build-package.ps1')) 25 | 26 | test: off 27 | deploy: off 28 | -------------------------------------------------------------------------------- /spec/fixtures/projectRoot/.languagebabel: -------------------------------------------------------------------------------- 1 | { 2 | "babelMapsPath": "", 3 | "babelMapsAddUrl": false, 4 | "babelSourcePath": "src", 5 | "babelTranspilePath": "", 6 | "createMap": false, 7 | "createTargetDirectories": true, 8 | "createTranspiledCode": true, 9 | "disableWhenNoBabelrcFileInPath": false, 10 | "projectRoot": true, 11 | "suppressSourcePathMessages": true, 12 | "suppressTranspileOnSaveMessages": true, 13 | "transpileOnSave": true 14 | } 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | notifications: 2 | email: 3 | on_success: never 4 | on_failure: change 5 | 6 | script: 'curl -s https://raw.githubusercontent.com/atom/ci/master/build-package.sh | sh' 7 | 8 | git: 9 | depth: 10 10 | 11 | sudo: false 12 | 13 | matrix: 14 | include: 15 | - os: osx 16 | env: ATOM_CHANNEL=stable 17 | # - os: linux 18 | # dist: trusty 19 | # env: ATOM_CHANNEL=stable 20 | - os: osx 21 | env: ATOM_CHANNEL=beta 22 | # - os: linux 23 | # dist: trusty 24 | # env: ATOM_CHANNEL=beta 25 | 26 | branches: 27 | only: 28 | - master 29 | 30 | addons: 31 | apt: 32 | packages: 33 | - libstdc++6 34 | -------------------------------------------------------------------------------- /spec/fixtures/grammar/babel-sublime/js-template-strings.js: -------------------------------------------------------------------------------- 1 | // SYNTAX TEST "source.js.jsx" 2 | 3 | return `another template ${aa}` 4 | // <- keyword.control.flow.js 5 | // <- keyword.control.flow.js 6 | //^^^^ keyword.control.flow.js 7 | // ^^^^^^^^ ^^^^^^^^ ^^^^^^ string.quasi.js 8 | // ^ punctuation.definition.quasi.begin.js 9 | // ^^^^^^^^ ^^^^^^^^ ^^^^^^ string.quoted.template.js 10 | // ^^^^^ entity.quasi.element.js 11 | // ^^ punctuation.quasi.element.begin.js 12 | // ^^ variable.other.readwrite.js 13 | // ^ punctuation.quasi.element.end.js 14 | // ^ punctuation.definition.quasi.end.js 15 | 16 | // >> only:source.js.jsx 17 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Graham Clark 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /spec/fixtures/dira/dira.1/dira.2/good.js: -------------------------------------------------------------------------------- 1 | var QuadraticCalculator = React.createClass({ 2 | getInitialState: function() { 3 | console.log("test") 4 | return { 5 | a: 1, 6 | b: 3, 7 | c: -4 8 | }; 9 | }, 10 | 11 | /** 12 | * This function will be re-bound in render multiple times. Each .bind() will 13 | * create a new function that calls this with the appropriate key as well as 14 | * the event. The key is the key in the state object that the value should be 15 | * mapped from. 16 | */ 17 | handleInputChange: function(key, event) { 18 | var partialState = {}; 19 | partialState[key] = parseFloat(event.target.value); 20 | this.setState(partialState); 21 | }, 22 | 23 | render: function() { 24 | var a = this.state.a; 25 | var b = this.state.b; 26 | var c = this.state.c; 27 | var root = Math.sqrt(Math.pow(b, 2) - 4 * a * c); 28 | var denominator = 2 * a; 29 | var x1 = (-b + root) / denominator; 30 | var x2 = (-b - root) / denominator; 31 | return true; 32 | } 33 | }); 34 | 35 | React.render( 36 | document.getElementById('container') 37 | ); 38 | -------------------------------------------------------------------------------- /spec/fixtures/dira/dira.1/dira.2/react.js: -------------------------------------------------------------------------------- 1 | var QuadraticCalculator = React.createClass({ 2 | getInitialState: function () { 3 | console.log("test"); 4 | return { 5 | a: 1, 6 | b: 3, 7 | c: -4 8 | }; 9 | }, 10 | 11 | /** 12 | * This function will be re-bound in render multiple times. Each .bind() will 13 | * create a new function that calls this with the appropriate key as well as 14 | * the event. The key is the key in the state object that the value should be 15 | * mapped from. 16 | */ 17 | handleInputChange: function (key, event) { 18 | var partialState = {}; 19 | partialState[key] = parseFloat(event.target.value); 20 | this.setState(partialState); 21 | }, 22 | 23 | render: function () { 24 | var a = this.state.a; 25 | var b = this.state.b; 26 | var c = this.state.c; 27 | var root = Math.sqrt(Math.pow(b, 2) - 4 * a * c); 28 | var denominator = 2 * a; 29 | var x1 = (-b + root) / denominator; 30 | var x2 = (-b - root) / denominator; 31 | return; 32 | false; 33 | } 34 | }); 35 | 36 | React.render(document.getElementById('container')); 37 | -------------------------------------------------------------------------------- /spec/fixtures/dira/dira.1/dira.2/react.jsx: -------------------------------------------------------------------------------- 1 | var QuadraticCalculator = React.createClass({ 2 | getInitialState: function() { 3 | console.log("test") 4 | return { 5 | a: 1, 6 | b: 3, 7 | c: -4 8 | }; 9 | }, 10 | 11 | /** 12 | * This function will be re-bound in render multiple times. Each .bind() will 13 | * create a new function that calls this with the appropriate key as well as 14 | * the event. The key is the key in the state object that the value should be 15 | * mapped from. 16 | */ 17 | handleInputChange: function(key, event) { 18 | var partialState = {}; 19 | partialState[key] = parseFloat(event.target.value); 20 | this.setState(partialState); 21 | }, 22 | 23 | render: function() { 24 | var a = this.state.a; 25 | var b = this.state.b; 26 | var c = this.state.c; 27 | var root = Math.sqrt(Math.pow(b, 2) - 4 * a * c); 28 | var denominator = 2 * a; 29 | var x1 = (-b + root) / denominator; 30 | var x2 = (-b - root) / denominator; 31 | return 32 | false; 33 | } 34 | }); 35 | 36 | React.render( 37 | document.getElementById('container') 38 | ); 39 | -------------------------------------------------------------------------------- /spec/fixtures/dira/dira.1/dira.2/bad.js: -------------------------------------------------------------------------------- 1 | var QuadraticCalculator = React.createClass({ 2 | getInitialState: function() { 3 | console.log("test") 4 | return { 5 | a: 1, 6 | b: 3, 7 | c: -4 8 | }; 9 | }, 10 | 11 | /** 12 | * This function will be re-bound in render multiple times. Each .bind() will 13 | * create a new function that calls this with the appropriate key as well as 14 | * the event. The key is the key in the state object that the value should be 15 | * mapped from. 16 | */ 17 | handleInputChange: function(key, event) { 18 | var partialState = {}; 19 | partialState[key] = parseFloat(event.target.value); 20 | this.setState(partialState); 21 | }, 22 | 23 | render: function() { 24 | var a = this.state.a; 25 | var b = this.state.b; 26 | var c = this.state.c; 27 | var root = Math.sqrt(Math.pow(b, 2) - 4 * a * c); 28 | var denominator = 2 * a; 29 | var x1 = (-b + root) / denominator; 30 | var x2 = (-b - root) / denominator; 31 | return { // ill formed object 32 | }); 33 | 34 | React.render( 35 | document.getElementById('container') 36 | ); 37 | 38 | this is an error 39 | -------------------------------------------------------------------------------- /settings/language-babel.json: -------------------------------------------------------------------------------- 1 | { 2 | ".source.js.jsx": { 3 | "editor": { 4 | "commentStart": "// ", 5 | "foldEndPattern": "^\\s*\\}|^\\s*\\]|^\\s*\\)", 6 | "increaseIndentPattern": "{[^}\"']*$|\\[[^\\]\"']*$|\\([^)\"']*$|^\\s*<[a-zA-Z][^/]*$|^\\s*>$", 7 | "decreaseIndentPattern": "^\\s*(\\s*/[*].*[*]/\\s*)*[}\\])]|^\\s*()", 8 | "nonWordCharacters": "/\\()\"':,.;<>~!@#%^&*|+=[]{}`?-…" 9 | } 10 | }, 11 | ".source.inside-js.css.styled": { 12 | "editor": { 13 | "commentStart": "${'' /* ", 14 | "commentEnd": " */}" 15 | } 16 | }, 17 | ".entity.quasi.element.js": { 18 | "editor": { 19 | "commentStart": "// " 20 | }, 21 | "autocomplete": { 22 | "symbols": { 23 | "": { 24 | "selector": ".source", 25 | "typePriority": 1 26 | } 27 | } 28 | } 29 | }, 30 | ".meta.tag.jsx": { 31 | "editor": { 32 | "commentStart": "{/* ", 33 | "commentEnd": " */}", 34 | "increaseIndentPattern": "{[^}\"']*$|\\[[^\\]\"']*$|\\([^)\"']*$|<[a-zA-Z][^/]*$|^\\s*>$", 35 | "decreaseIndentPattern": "^\\s*(\\s*/[*].*[*]/\\s*)*[}\\])]|^\\s*()" 36 | } 37 | }, 38 | ".JSXAttrs": { 39 | "editor": { 40 | "commentStart": "// " 41 | } 42 | }, 43 | ".JSXNested": { 44 | "editor": { 45 | "commentStart": "{/* ", 46 | "commentEnd": " */}" 47 | } 48 | }, 49 | ".graphql": { 50 | "editor": { 51 | "commentStart": "# " 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /spec/fixtures/dirb/good.js: -------------------------------------------------------------------------------- 1 | var QuadraticCalculator = React.createClass({ 2 | getInitialState: function() { 3 | console.log("test") 4 | return { 5 | a: 1, 6 | b: 3, 7 | c: -4 8 | }; 9 | }, 10 | 11 | /** 12 | * This function will be re-bound in render multiple times. Each .bind() will 13 | * create a new function that calls this with the appropriate key as well as 14 | * the event. The key is the key in the state object that the value should be 15 | * mapped from. 16 | */ 17 | handleInputChange: function(key, event) { 18 | var partialState = {}; 19 | partialState[key] = parseFloat(event.target.value); 20 | this.setState(partialState); 21 | }, 22 | 23 | render: function() { 24 | var a = this.state.a; 25 | var b = this.state.b; 26 | var c = this.state.c; 27 | var root = Math.sqrt(Math.pow(b, 2) - 4 * a * c); 28 | var denominator = 2 * a; 29 | var x1 = (-b + root) / denominator; 30 | var x2 = (-b - root) / denominator; 31 | return ( 32 |
33 | 34 | ax2 + bx + c = 0 35 | 36 |

Solve for x:

37 |

38 | 41 |
42 | 45 |
46 | 49 |
50 | x: {x1}, {x2} 51 |

52 |
53 | ); 54 | } 55 | }); 56 | 57 | React.render( 58 | , 59 | document.getElementById('container') 60 | ); 61 | -------------------------------------------------------------------------------- /spec/fixtures/dira/dira.1/dira.2/ignored.js: -------------------------------------------------------------------------------- 1 | var QuadraticCalculator = React.createClass({ 2 | getInitialState: function() { 3 | console.log("test") 4 | return { 5 | a: 1, 6 | b: 3, 7 | c: -4 8 | }; 9 | }, 10 | 11 | /** 12 | * This function will be re-bound in render multiple times. Each .bind() will 13 | * create a new function that calls this with the appropriate key as well as 14 | * the event. The key is the key in the state object that the value should be 15 | * mapped from. 16 | */ 17 | handleInputChange: function(key, event) { 18 | var partialState = {}; 19 | partialState[key] = parseFloat(event.target.value); 20 | this.setState(partialState); 21 | }, 22 | 23 | render: function() { 24 | var a = this.state.a; 25 | var b = this.state.b; 26 | var c = this.state.c; 27 | var root = Math.sqrt(Math.pow(b, 2) - 4 * a * c); 28 | var denominator = 2 * a; 29 | var x1 = (-b + root) / denominator; 30 | var x2 = (-b - root) / denominator; 31 | return ( 32 |
33 | 34 | ax2 + bx + c = 0 35 | 36 |

Solve for x:

37 |

38 | 41 |
42 | 45 |
46 | 49 |
50 | x: {x1}, {x2} 51 |

52 |
53 | ); 54 | } 55 | }); 56 | 57 | React.render( 58 | , 59 | document.getElementById('container') 60 | ); 61 | -------------------------------------------------------------------------------- /lib/auto-complete-emmet-css.js: -------------------------------------------------------------------------------- 1 | /*global atom*/ 2 | "use babel"; 3 | 4 | module.exports = { 5 | selector: '.source.inside-js.css.styled, .source.css.styled', 6 | disableForSelector: 7 | '.source.inside-js.css.styled .comment, .source.inside-js.css.styled .string, .source.inside-js.css.styled .entity.quasi.element.js, .source.css.styled .comment, .source.css.styled .string, .source.css.styled .entity.quasi.element.js', 8 | 9 | filterSuggestions: false, 10 | inclusionPriority: 10000, 11 | excludeLowerPriority: false, 12 | suggestionPriority: 100, 13 | 14 | getSuggestions({editor, bufferPosition}) { 15 | if (atom.config.get('language-babel.emmetCSSAutocomplete')) { 16 | const prefix = this.getPrefix(editor, bufferPosition); 17 | return this.emmetSuggestion(prefix); 18 | } 19 | return null; 20 | }, 21 | 22 | getPrefix(editor, bufferPosition) { 23 | const regex = /(^|;)(?:\s*)([\w\s0-9+-:@!#]+)$/g; 24 | const line = editor.getTextInRange([ 25 | [bufferPosition.row, 0], 26 | bufferPosition 27 | ]); 28 | const match = regex.exec(line); 29 | return match ? match[2] : ''; 30 | }, 31 | 32 | emmetSuggestion(prefix) { 33 | const completion = []; 34 | try { 35 | // Expensive dependency: use a lazy require. 36 | const {expand} = require('@emmetio/expand-abbreviation'); 37 | const emmetAbbreviation = expand(prefix, { 38 | syntax: 'css', 39 | field: (index, placeholder) => 40 | `\${${index}${placeholder ? ':' + placeholder : ''}}` 41 | }); 42 | const emmetDisplayText = 43 | emmetAbbreviation.length > 28 44 | ? emmetAbbreviation.substr(0, 25) + '...' 45 | : emmetAbbreviation; 46 | completion.push({ 47 | type: 'snippet', 48 | snippet: emmetAbbreviation, 49 | displayText: emmetDisplayText, 50 | leftLabel: 'emmet', 51 | description: 'language-babel emmet', 52 | descriptionMoreURL: 'https://docs.emmet.io/cheat-sheet/', 53 | replacementPrefix: prefix 54 | }); 55 | } catch (err) { 56 | } 57 | return completion; 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /spec/grammar-spec.coffee: -------------------------------------------------------------------------------- 1 | path = require 'path' 2 | grammarTest = require 'atom-grammar-test' 3 | 4 | describe 'Grammar', -> 5 | beforeEach -> 6 | waitsForPromise -> 7 | atom.packages.activatePackage('language-babel') 8 | waitsForPromise -> 9 | atom.packages.activatePackage('language-todo') 10 | waitsForPromise -> 11 | atom.packages.activatePackage('language-hyperlink') 12 | waitsForPromise -> 13 | atom.packages.activatePackage('language-mustache') 14 | waitsForPromise -> 15 | atom.packages.activatePackage('language-html') 16 | 17 | # test private class fields and methods 18 | grammarTest path.join(__dirname, 'fixtures/grammar/private-fields.js') 19 | 20 | # babel-sublime test files 21 | grammarTest path.join(__dirname, 'fixtures/grammar/babel-sublime/flow.js') 22 | grammarTest path.join(__dirname, 'fixtures/grammar/babel-sublime/js-class.js') 23 | grammarTest path.join(__dirname, 'fixtures/grammar/babel-sublime/js-functions.js') 24 | grammarTest path.join(__dirname, 'fixtures/grammar/babel-sublime/js-symbols.js') 25 | grammarTest path.join(__dirname, 'fixtures/grammar/babel-sublime/js-template-strings.js') 26 | grammarTest path.join(__dirname, 'fixtures/grammar/babel-sublime/jsx-attributes.jsx') 27 | grammarTest path.join(__dirname, 'fixtures/grammar/babel-sublime/jsx-es6.jsx') 28 | grammarTest path.join(__dirname, 'fixtures/grammar/babel-sublime/jsx-features.jsx') 29 | grammarTest path.join(__dirname, 'fixtures/grammar/babel-sublime/jsx-full-react-class.jsx') 30 | grammarTest path.join(__dirname, 'fixtures/grammar/babel-sublime/jsx-text.jsx') 31 | 32 | # flow declaration file 33 | grammarTest path.join(__dirname, 'fixtures/grammar/declare.js') 34 | 35 | # grammar test large files 36 | grammarTest path.join(__dirname, 'fixtures/grammar/large files/browser-polyfill.js') 37 | grammarTest path.join(__dirname, 'fixtures/grammar/large files/jquery-2.1.4.js') 38 | grammarTest path.join(__dirname, 'fixtures/grammar/large files/bundle.js') 39 | grammarTest path.join(__dirname, 'fixtures/grammar/large files/jquery-2.1.4.min.js') 40 | 41 | # # es2015 check 42 | grammarTest path.join(__dirname, 'fixtures/grammar/everythingJs/es2015-module.js') 43 | 44 | # todo,jsdoc,... 45 | grammarTest path.join(__dirname, 'fixtures/grammar/doc-keywords.js') 46 | 47 | # flow predicates... 48 | grammarTest path.join(__dirname, 'fixtures/grammar/flow-predicates.js') 49 | 50 | # issues raised 51 | grammarTest path.join(__dirname, 'fixtures/grammar/issues.js') 52 | 53 | # misc Tests 54 | grammarTest path.join(__dirname, 'fixtures/grammar/misc.js') 55 | grammarTest path.join(__dirname, 'fixtures/grammar/es6module.js') 56 | 57 | # graphql test 58 | grammarTest path.join(__dirname, 'fixtures/grammar/graphql.js') 59 | -------------------------------------------------------------------------------- /styles/language-babel.less: -------------------------------------------------------------------------------- 1 | // You can provide styles for the language-babel package here. 2 | 3 | @import "ui-variables"; 4 | 5 | // Config ----------------------------------- 6 | @syntax-hue: 220; 7 | @syntax-saturation: 24%; 8 | @syntax-brightness: 20%; 9 | 10 | // Base colors ----------------------------------- 11 | @syntax-base-accent-color: hsl(@syntax-hue, 100%, 66% ); 12 | @syntax-base-background-color: hsv(@syntax-hue, @syntax-saturation, @syntax-brightness); 13 | @syntax-base-text-color: @light-gray; 14 | @syntax-base-guide-color: fade(@syntax-base-text-color, 15%); 15 | 16 | 17 | // Colors: Mix Base16 Tomorrow with Theme hue ----------------------------------- 18 | @syntax-mix-base: hsl(@syntax-hue, 100%, 66%); 19 | @syntax-mix-grey: 12%; 20 | @syntax-mix-color: 0%; 21 | 22 | @very-light-gray: mix( @syntax-mix-base, hsl(0,0%,84%), @syntax-mix-grey); 23 | @light-gray: mix( @syntax-mix-base, hsl(0,0%,72%), @syntax-mix-grey); 24 | @gray: mix( @syntax-mix-base, hsl(0,0%,54%), @syntax-mix-grey); 25 | @dark-gray: mix( @syntax-mix-base, hsl(0,0%,36%), @syntax-mix-grey); 26 | @very-dark-gray: mix( @syntax-mix-base, hsl(0,0%,18%), @syntax-mix-grey); 27 | 28 | @cyan: mix( @syntax-mix-base, #57B6C2, @syntax-mix-color); 29 | @blue: mix( @syntax-mix-base, #61AEEF, @syntax-mix-color); 30 | @purple: mix( @syntax-mix-base, #C679DD, @syntax-mix-color); 31 | @green: mix( @syntax-mix-base, #97C378, @syntax-mix-color); 32 | @red: mix( @syntax-mix-base, #DF6A73, @syntax-mix-color); 33 | @dark-red: mix( @syntax-mix-base, #BE4F44, @syntax-mix-color); 34 | @orange: mix( @syntax-mix-base, #D29B67, @syntax-mix-color); 35 | @light-orange: mix( @syntax-mix-base, #E5C17C, @syntax-mix-color); 36 | @bright-orange: mix( @syntax-mix-base, #FF8000, @syntax-mix-color); 37 | 38 | atom-text-editor { 39 | .syntax--source.syntax--js.syntax--jsx { 40 | .syntax--graphql { 41 | .syntax--alias { 42 | font-style: italic 43 | } 44 | .syntax--support.syntax--type.syntax--builtin { 45 | -webkit-filter: brightness(80%); 46 | } 47 | } 48 | .syntax--jsx { 49 | .syntax--entity { 50 | &.syntax--other { 51 | &.syntax--attribute-name { 52 | font-style: italic // color: @cyan; 53 | } 54 | } 55 | } 56 | .syntax--constant.syntax--character.syntax--entity { 57 | font-style: italic 58 | } 59 | } 60 | } 61 | .syntax--constant.syntax--numeric.syntax--bigint { 62 | font-style: italic 63 | } 64 | .syntax--source.syntax--css.syntax--styled { 65 | .syntax--support.syntax--type.syntax--property-name.syntax--unknown { 66 | -webkit-filter: brightness(75%); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /coffeelint.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrow_spacing": { 3 | "level": "ignore" 4 | }, 5 | "braces_spacing": { 6 | "level": "ignore", 7 | "spaces": 0, 8 | "empty_object_spaces": 0 9 | }, 10 | "camel_case_classes": { 11 | "level": "error" 12 | }, 13 | "coffeescript_error": { 14 | "level": "error" 15 | }, 16 | "colon_assignment_spacing": { 17 | "level": "ignore", 18 | "spacing": { 19 | "left": 0, 20 | "right": 0 21 | } 22 | }, 23 | "cyclomatic_complexity": { 24 | "level": "ignore", 25 | "value": 10 26 | }, 27 | "duplicate_key": { 28 | "level": "error" 29 | }, 30 | "empty_constructor_needs_parens": { 31 | "level": "ignore" 32 | }, 33 | "ensure_comprehensions": { 34 | "level": "warn" 35 | }, 36 | "eol_last": { 37 | "level": "ignore" 38 | }, 39 | "indentation": { 40 | "value": 2, 41 | "level": "error" 42 | }, 43 | "line_endings": { 44 | "level": "ignore", 45 | "value": "unix" 46 | }, 47 | "max_line_length": { 48 | "value": 200, 49 | "level": "warn", 50 | "limitComments": true 51 | }, 52 | "missing_fat_arrows": { 53 | "level": "ignore", 54 | "is_strict": false 55 | }, 56 | "newlines_after_classes": { 57 | "value": 3, 58 | "level": "ignore" 59 | }, 60 | "no_backticks": { 61 | "level": "error" 62 | }, 63 | "no_debugger": { 64 | "level": "warn", 65 | "console": false 66 | }, 67 | "no_empty_functions": { 68 | "level": "ignore" 69 | }, 70 | "no_empty_param_list": { 71 | "level": "ignore" 72 | }, 73 | "no_implicit_braces": { 74 | "level": "ignore", 75 | "strict": true 76 | }, 77 | "no_implicit_parens": { 78 | "level": "ignore", 79 | "strict": true 80 | }, 81 | "no_interpolation_in_single_quotes": { 82 | "level": "ignore" 83 | }, 84 | "no_nested_string_interpolation": { 85 | "level": "warn" 86 | }, 87 | "no_plusplus": { 88 | "level": "ignore" 89 | }, 90 | "no_private_function_fat_arrows": { 91 | "level": "warn" 92 | }, 93 | "no_stand_alone_at": { 94 | "level": "ignore" 95 | }, 96 | "no_tabs": { 97 | "level": "error" 98 | }, 99 | "no_this": { 100 | "level": "ignore" 101 | }, 102 | "no_throwing_strings": { 103 | "level": "error" 104 | }, 105 | "no_trailing_semicolons": { 106 | "level": "error" 107 | }, 108 | "no_trailing_whitespace": { 109 | "level": "ignore", 110 | "allowed_in_comments": false, 111 | "allowed_in_empty_lines": true 112 | }, 113 | "no_unnecessary_double_quotes": { 114 | "level": "ignore" 115 | }, 116 | "no_unnecessary_fat_arrows": { 117 | "level": "warn" 118 | }, 119 | "non_empty_constructor_needs_parens": { 120 | "level": "ignore" 121 | }, 122 | "prefer_english_operator": { 123 | "level": "ignore", 124 | "doubleNotLevel": "ignore" 125 | }, 126 | "space_operators": { 127 | "level": "ignore" 128 | }, 129 | "spacing_after_comma": { 130 | "level": "ignore" 131 | }, 132 | "transform_messes_up_line_numbers": { 133 | "level": "warn" 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /lib/transpiler-task.coffee: -------------------------------------------------------------------------------- 1 | fs = require 'fs-plus' 2 | path = require 'path' 3 | 4 | # recurse directories to root looking for babel core 5 | # or provide our own 6 | requireBabelCore = (dir) -> 7 | if dir != path.dirname(dir) 8 | if babelCore = resolveBabelCore(dir) then return babelCore 9 | else return requireBabelCore(path.dirname(dir)) 10 | return resolveBabelCore('..') # return language-babel's copy of babel-core 11 | 12 | # resolve a babel core in the dir 13 | resolveBabelCore = (dir) -> 14 | try 15 | projectBabelCore = path.normalize( path.join( dir, '/node_modules/@babel/core')) 16 | babel = require projectBabelCore 17 | catch 18 | try 19 | projectBabelCore = path.normalize( path.join( dir, '/node_modules/babel-core')) 20 | babel = require projectBabelCore 21 | catch 22 | return false 23 | 'babel': babel 24 | 'projectBabelCore': projectBabelCore 25 | 26 | # language-babel transpiles run here. 27 | # This runs as a separate task so that transpiles can have their own environment. 28 | module.exports = (projectPath) -> 29 | callback = @async() #async task 30 | process.chdir(projectPath) 31 | 32 | { babel, projectBabelCore } = requireBabelCore(projectPath) 33 | babelCoreUsed = "Using babel-core at\n#{require.resolve projectBabelCore}" 34 | 35 | process.on 'message', (mObj) -> 36 | if mObj.command is 'transpile' 37 | try 38 | babel.transformFile mObj.pathTo.sourceFile, mObj.babelOptions, (err,result) => 39 | # fiddly formating a return 40 | msgRet = {} 41 | msgRet.reqId = mObj.reqId # send back to reqId 42 | if err 43 | msgRet.err = {} 44 | if err.loc then msgRet.err.loc = err.loc 45 | if err.codeFrame 46 | msgRet.err.codeFrame = err.codeFrame 47 | else msgRet.err.codeFrame = "" 48 | msgRet.err.message = err.message 49 | if result 50 | msgRet.result = result 51 | msgRet.result.ast = null; # ast seems to create a JSON circular ref on emit 52 | msgRet.babelVersion = babel.version 53 | msgRet.babelCoreUsed = babelCoreUsed 54 | emit "transpile:#{mObj.reqId}", msgRet 55 | # if this file transpilation isn't in a Atom project folder then term this task 56 | # as this is normally an Ad-hoc file transpile. 57 | if not mObj.pathTo.sourceFileInProject 58 | callback() 59 | catch err 60 | msgRet = {} 61 | msgRet.reqId = mObj.reqId # send back to reqId 62 | msgRet.err = {} 63 | msgRet.err.message = err.message 64 | msgRet.err.stack = err.stack 65 | msgRet.babelCoreUsed = babelCoreUsed 66 | emit "transpile:#{mObj.reqId}", msgRet 67 | callback() 68 | 69 | # used for preview 70 | if mObj.command is 'transpileCode' 71 | try 72 | msgRet = babel.transform mObj.code, mObj.babelOptions 73 | # fiddly formating a return 74 | msgRet.babelVersion = babel.version 75 | msgRet.babelCoreUsed = babelCoreUsed 76 | emit "transpile:#{mObj.reqId}", msgRet 77 | # if this file transpilation isn't in a Atom project folder then term this task 78 | # as this is normally an Ad-hoc file transpile. 79 | if not mObj.pathTo.sourceFileInProject 80 | callback() 81 | catch err 82 | msgRet = {} 83 | msgRet.reqId = mObj.reqId # send back to reqId 84 | msgRet.err = {} 85 | msgRet.err.message = err.message 86 | msgRet.err.stack = err.stack 87 | msgRet.babelVersion = babel.version 88 | msgRet.babelCoreUsed = babelCoreUsed 89 | emit "transpile:#{mObj.reqId}", msgRet 90 | callback() 91 | 92 | #stop issued stop process 93 | if mObj.command is 'stop' 94 | callback() 95 | -------------------------------------------------------------------------------- /spec/fixtures/grammar/flow-predicates.js: -------------------------------------------------------------------------------- 1 | // SYNTAX TEST "source.js.jsx" 2 | 3 | // Predicates 4 | 5 | declare function f(x: mixed): boolean %checks (x !== null); 6 | // <- keyword.other.declare.flowtype 7 | // <- keyword.other.declare.flowtype 8 | //^^^^^ keyword.other.declare.flowtype 9 | // ^^^^^^^^ ^^^^ ^^^^^^^ ^^^^^^^ ^^^^^^^ ^^ ^^^ ^^^^^ meta.function.js 10 | // ^^^^^^^^ storage.type.function.js 11 | // ^ entity.name.function.js 12 | // ^ punctuation.definition.parameters.begin.js 13 | // ^ ^ ^ ^ meta.brace.round.js 14 | // ^^ ^^^^^ meta.function.parameters.js 15 | // ^ ^ variable.other.readwrite.js 16 | // ^ ^ punctuation.type.flowtype 17 | // ^^^^^ ^^^^^^^ support.type.builtin.primitive.flowtype 18 | // ^ punctuation.definition.parameters.end.js 19 | // ^^^^^^^ entity.name.function.predicate.flowtype 20 | // ^^^ keyword.operator.comparison.js 21 | // ^^^^ constant.language.null.js 22 | // ^ punctuation.terminator.statement.js 23 | function f7(x: mixed): %checks { return x !== null } 24 | // <- meta.function.js storage.type.function.js 25 | // <- meta.function.js storage.type.function.js 26 | //^^^^^^ ^^^^^ ^^^^^^^ ^^^^^^^ ^ ^^^^^^ ^ ^^^ ^^^^ ^ meta.function.js 27 | //^^^^^^ storage.type.function.js 28 | // ^^ entity.name.function.js 29 | // ^ punctuation.definition.parameters.begin.js 30 | // ^ ^ meta.brace.round.js 31 | // ^^ ^^^^^ meta.function.parameters.js 32 | // ^ ^ variable.other.readwrite.js 33 | // ^ ^ punctuation.type.flowtype 34 | // ^^^^^ support.type.builtin.primitive.flowtype 35 | // ^ punctuation.definition.parameters.end.js 36 | // ^^^^^^^ entity.name.function.predicate.flowtype 37 | // ^ ^ meta.brace.curly.js 38 | // ^^^^^^ keyword.control.flow.js 39 | // ^^^ keyword.operator.comparison.js 40 | // ^^^^ constant.language.null.js 41 | var a1 = (x: mixed): %checks => x !== null 42 | // <- storage.type.js 43 | // <- storage.type.js 44 | //^ storage.type.js 45 | // ^^ ^ ^^^ ^^^^^^^ ^^^^^^^ ^^ meta.function.arrow.js 46 | // ^^ entity.name.function.js 47 | // ^ keyword.operator.assignment.js 48 | // ^ punctuation.definition.parameters.begin.js 49 | // ^ ^ meta.brace.round.js 50 | // ^^ ^^^^^ meta.function.parameters.js 51 | // ^ ^ variable.other.readwrite.js 52 | // ^ ^ punctuation.type.flowtype 53 | // ^^^^^ support.type.builtin.primitive.flowtype 54 | // ^ punctuation.definition.parameters.end.js 55 | // ^^^^^^^ entity.name.function.predicate.flowtype 56 | // ^^ storage.type.function.arrow.js 57 | // ^^^ keyword.operator.comparison.js 58 | // ^^^^ constant.language.null.js 59 | 60 | 61 | // >> only:(source.js.jsx) 62 | -------------------------------------------------------------------------------- /lib/did-insert-text.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | class DidInsertText 3 | constructor: (@editor) -> 4 | @adviseBefore(@editor, 'insertText', @insertText) 5 | 6 | # patched TextEditor::insertText 7 | insertText: (text, options) => 8 | return true if @editor.hasMultipleCursors() # for time being 9 | 10 | if ( text is "\n") 11 | if !@insertNewlineBetweenJSXTags() then return false 12 | if !@insertNewlineAfterBacktick() then return false 13 | else if ( text is "`") 14 | if !@insertBackTick() then return false 15 | true 16 | 17 | # check bracket-matcher package config to determine backtick insertion 18 | bracketMatcherBackticks: () -> 19 | return atom.packages.isPackageActive("bracket-matcher") and 20 | atom.config.get("bracket-matcher.autocompleteBrackets") and 21 | "``" in atom.config.get("bracket-matcher.autocompleteCharacters") 22 | 23 | # if a newLine is entered between a JSX tag open and close marked_
_
24 | # then add another newLine and reposition cursor 25 | insertNewlineBetweenJSXTags: () -> 26 | cursorBufferPosition = @editor.getCursorBufferPosition() 27 | return true unless cursorBufferPosition.column > 0 28 | return true unless 'JSXEndTagStart' is @editor.scopeDescriptorForBufferPosition(cursorBufferPosition).getScopesArray().slice(-1).toString() 29 | cursorBufferPosition.column-- 30 | return true unless 'JSXStartTagEnd' is @editor.scopeDescriptorForBufferPosition(cursorBufferPosition).getScopesArray().slice(-1).toString() 31 | indentLength = @editor.indentationForBufferRow(cursorBufferPosition.row) 32 | @editor.insertText("\n\n") 33 | @editor.setIndentationForBufferRow cursorBufferPosition.row+1, indentLength+1, { preserveLeadingWhitespace: false } 34 | @editor.setIndentationForBufferRow cursorBufferPosition.row+2, indentLength, { preserveLeadingWhitespace: false } 35 | @editor.moveUp() 36 | @editor.moveToEndOfLine() 37 | false 38 | 39 | # if a newline is entered after the opening backtick 40 | # indent cursor and add a closing backtick 41 | insertNewlineAfterBacktick: () -> 42 | cursorBufferPosition = @editor.getCursorBufferPosition() 43 | return true unless cursorBufferPosition.column > 0 44 | betweenBackTicks = 'punctuation.definition.quasi.end.js' is @editor.scopeDescriptorForBufferPosition(cursorBufferPosition).getScopesArray().slice(-1).toString() 45 | cursorBufferPosition.column-- 46 | return true unless 'punctuation.definition.quasi.begin.js' is @editor.scopeDescriptorForBufferPosition(cursorBufferPosition).getScopesArray().slice(-1).toString() 47 | indentLength = @editor.indentationForBufferRow(cursorBufferPosition.row) 48 | return true unless @bracketMatcherBackticks() 49 | if (betweenBackTicks) 50 | @editor.insertText("\n\n") 51 | @editor.setIndentationForBufferRow cursorBufferPosition.row+1, indentLength+1, { preserveLeadingWhitespace: false } 52 | @editor.setIndentationForBufferRow cursorBufferPosition.row+2, indentLength, { preserveLeadingWhitespace: false } 53 | @editor.moveUp() 54 | @editor.moveToEndOfLine() 55 | else 56 | @editor.insertText("\n\t") 57 | @editor.setIndentationForBufferRow cursorBufferPosition.row+1, indentLength+1, { preserveLeadingWhitespace: false } 58 | false 59 | 60 | # the atom bracket matcher doesn't currently ( v1.15) add a closing backtick when the opening 61 | # backtick appears after a word character as is the case in a tagname`` sequence 62 | # this remedies that 63 | insertBackTick: () -> 64 | return true unless @bracketMatcherBackticks() 65 | cursorBufferPosition = @editor.getCursorBufferPosition() 66 | return true if 'punctuation.definition.quasi.begin.js' is @editor.scopeDescriptorForBufferPosition(cursorBufferPosition).getScopesArray().slice(-1).toString() 67 | selectedText = @editor.getSelectedText() 68 | cursorPosition = @editor.getCursorBufferPosition() 69 | @editor.insertText("`" + selectedText + "`") 70 | @editor.setCursorBufferPosition(cursorPosition) 71 | @editor.moveRight() 72 | false 73 | 74 | 75 | # from https://github.com/atom/underscore-plus/blob/master/src/underscore-plus.coffee 76 | adviseBefore: (object, methodName, advice) -> 77 | original = object[methodName] 78 | object[methodName] = (args...) -> 79 | unless advice.apply(this, args) == false 80 | original.apply(this, args) 81 | -------------------------------------------------------------------------------- /grammars/Babel Regex.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Regular Expressions (Babel)", 3 | "scopeName": "source.regexp.babel", 4 | "fileTypes": [], 5 | "patterns": [ 6 | { "include": "#anchor"}, 7 | { "include": "#backref"}, 8 | { "include": "#quantifier"}, 9 | { "include": "#operator"}, 10 | { "include": "#group-assertion"}, 11 | { "include": "#group-definition"}, 12 | { "include": "#character-class-definition" }, 13 | { "include": "#character-class" } 14 | ], 15 | "repository": { 16 | "character-class-definition": { 17 | "patterns": [{ 18 | "name": "constant.other.character-class.set.regexp", 19 | "begin": "(\\[)(\\^)?", 20 | "end": "(\\])", 21 | "beginCaptures": { 22 | "1": { "name": "punctuation.definition.character-class.regexp" }, 23 | "2": { "name": "keyword.operator.negation.regexp" } 24 | }, 25 | "endCaptures": { 26 | "1": { 27 | "name": "punctuation.definition.character-class.regexp" 28 | } 29 | }, 30 | "patterns": 31 | [ 32 | { 33 | "name": "constant.other.character-class.range.regexp", 34 | "match": "((\\\\[wWsSdD]|\\.)|(\\\\([trnvf0]|c[A-Z]|x[\\da-fA-F]{2}|u[\\da-fA-F]{4}|u\\{[\\da-fA-F]+\\}|.)|([^\\]\\s])))(\\-)((\\\\[wWsSdD]|\\.)|(\\\\([trnvf0]|c[A-Z]|x[\\da-fA-F]{2}|u[\\da-fA-F]{4}|u\\{[\\da-fA-F]+\\}|.)|([^\\]\\s])))", 35 | "captures": 36 | { 37 | "2": { "name": "constant.character.escape.backslash.regexp" }, 38 | "3": { "name": "constant.character.escape.backslash.regexp" }, 39 | "5": { "name": "constant.character.regexp" }, 40 | "6": { "name": "punctuation.definition.range.regexp" }, 41 | "8": { "name": "constant.character.escape.backslash.regexp" }, 42 | "9": { "name": "constant.character.escape.backslash.regexp" }, 43 | "11": { "name": "constant.character.regexp" } 44 | } 45 | }, 46 | { "include": "#character-class" } 47 | ] 48 | }] 49 | }, 50 | "group-assertion": { 51 | "patterns": [{ 52 | "begin": "(\\()((\\?=)|(\\?!))", 53 | "end": "(\\))", 54 | "name": "meta.group.assertion.regexp", 55 | "endCaptures": { 56 | "1": { 57 | "name": "punctuation.definition.group.regexp" 58 | } 59 | }, 60 | "beginCaptures": { 61 | "1": { "name": "punctuation.definition.group.regexp" }, 62 | "2": { "name": "punctuation.definition.group.assertion.regexp" }, 63 | "3": { "name": "meta.assertion.look-ahead.regexp" }, 64 | "4": { "name": "meta.assertion.negative-look-ahead.regexp" } 65 | }, 66 | "patterns": [{ 67 | "include": "$self" 68 | }] 69 | }] 70 | }, 71 | "anchor": { 72 | "patterns": [{ 73 | "name": "keyword.control.anchor.regexp", 74 | "match": "\\\\[bB]|\\^|\\$" 75 | }] 76 | }, 77 | "operator": { 78 | "patterns": [{ 79 | "name": "keyword.operator.or.regexp", 80 | "match": "\\|" 81 | }] 82 | }, 83 | "group-definition": { 84 | "patterns": [{ 85 | "begin": "(\\()((\\?:))?", 86 | "end": "(\\))", 87 | "name": "meta.group.regexp", 88 | "endCaptures": { 89 | "1": { "name": "punctuation.definition.group.regexp" } 90 | }, 91 | "beginCaptures": { 92 | "1": { "name": "punctuation.definition.group.regexp" }, 93 | "3": { "name": "punctuation.definition.group.capture.regexp" }, 94 | "5": { "name": "punctuation.definition.group.capture.regexp" }, 95 | "6": { "name": "punctuation.definition.group.no-capture.regexp" } 96 | }, 97 | "patterns": [{ 98 | "include": "$self" 99 | }] 100 | }] 101 | }, 102 | "quantifier": { 103 | "patterns": [{ 104 | "name": "keyword.operator.quantifier.regexp", 105 | "match": "(\\?|\\*\\??|\\+\\??)|\\{(\\d+,\\d+|\\d+,|\\d+)\\}" 106 | }] 107 | }, 108 | "backref": { 109 | "patterns": [{ 110 | "name": "keyword.other.back-reference.regexp", 111 | "match": "\\\\[1-9][0-9]*" 112 | }] 113 | }, 114 | "character-class": { 115 | "patterns": [{ 116 | "name": "constant.character.escape.backslash.regexp", 117 | "match": "\\\\[wWsSdD]" 118 | }, { 119 | "match": "(\\\\([trnvf0\\\\]|c[A-Z]|x[\\da-fA-F]{2}|u[\\da-fA-F]{4}|u\\{[\\da-fA-F]+\\}|.))", 120 | "captures": { 121 | "1": { "name": "constant.character.escape.backslash.regexp" } 122 | } 123 | }] 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "language-babel", 3 | "main": "./lib/main", 4 | "version": "2.85.0", 5 | "description": "JavaScript ES201x, React JSX, Flow and GraphQL Grammar. Babel Transpiler", 6 | "keywords": [ 7 | "react", 8 | "flow", 9 | "graphql", 10 | "es6", 11 | "jsx", 12 | "javascript", 13 | "es7", 14 | "esnext", 15 | "es2015", 16 | "es2016", 17 | "es2017", 18 | "relay", 19 | "apollo" 20 | ], 21 | "activationCommands": [], 22 | "repository": "https://github.com/gandm/language-babel", 23 | "license": "MIT", 24 | "engines": { 25 | "atom": "^1.15.0" 26 | }, 27 | "providedServices": { 28 | "autocomplete.provider": { 29 | "versions": { 30 | "2.0.0": "autoCompleteProvider" 31 | } 32 | }, 33 | "preview.provider": { 34 | "versions": { 35 | "0.1.0": "provide" 36 | } 37 | } 38 | }, 39 | "dependencies": { 40 | "@emmetio/expand-abbreviation": "^0.5.8", 41 | "babel-core": "^6.26.0", 42 | "fs-plus": "^3.0.0", 43 | "fuzzaldrin": "^2.1.0", 44 | "jjv": "^1.0.2", 45 | "js-yaml": "^3.10.0", 46 | "path-is-inside": "^1.0.1", 47 | "strip-json-comments": "^2.0.1" 48 | }, 49 | "devDependencies": { 50 | "atom-grammar-test": "<1.0.0", 51 | "babel-eslint": "^6.1.2", 52 | "babel-plugin-syntax-class-properties": "^6.13.0", 53 | "babel-plugin-transform-class-properties": "^6.11.5", 54 | "babel-plugin-transform-decorators-legacy": "^1.3.4", 55 | "babel-preset-node5": "^11.1.0", 56 | "chai": "^3.0.0", 57 | "core-decorators": "^0.12.3", 58 | "eslint": "^3.6.0", 59 | "temp": "^0.8.3" 60 | }, 61 | "configSchema": { 62 | "autoIndentJSX": { 63 | "title": "Auto Indent JSX", 64 | "description": "Auto Indent JSX using default or eslintrc rules", 65 | "type": "boolean", 66 | "default": false, 67 | "order": 10 68 | }, 69 | "taggedTemplateGrammar": { 70 | "title": "JavaScript Tagged Template Literal Grammar Extensions", 71 | "description": "Enter a list of comma separated tagged template literals/regex in the form tagname:scope.name.of.grammar", 72 | "type": "array", 73 | "default": [], 74 | "items": { 75 | "type": "string" 76 | }, 77 | "order": 20 78 | }, 79 | "emmetCSSAutocomplete": { 80 | "title": "Styled-Components Auto-Complete method", 81 | "description": "Use Emmet to auto-complete in addition to the default CSS completion", 82 | "type": "boolean", 83 | "default": false, 84 | "order": 25 85 | }, 86 | "allowLocalOverride": { 87 | "description": "Allow .languagebabel files to overide the settings below. Useful for project based configurations.", 88 | "type": "boolean", 89 | "default": false, 90 | "order": 30 91 | }, 92 | "transpileOnSave": { 93 | "description": "Check source code validity on file save. Use \"Create Transpiled Code\" option below to save file.", 94 | "type": "boolean", 95 | "default": false, 96 | "order": 40 97 | }, 98 | "createTranspiledCode": { 99 | "description": "Save transpiled code to Babel Transpile Path below.", 100 | "type": "boolean", 101 | "default": false, 102 | "order": 50 103 | }, 104 | "disableWhenNoBabelrcFileInPath": { 105 | "description": "Suppress transpile when no .babelrc file is in source file path.", 106 | "type": "boolean", 107 | "default": true, 108 | "order": 60 109 | }, 110 | "suppressTranspileOnSaveMessages": { 111 | "description": "Suppress non-error notification messages on each save.", 112 | "type": "boolean", 113 | "default": true, 114 | "order": 70 115 | }, 116 | "suppressSourcePathMessages": { 117 | "description": "Suppress messages about file not being inside Babel Source Path.", 118 | "type": "boolean", 119 | "default": true, 120 | "order": 75 121 | }, 122 | "createMap": { 123 | "description": "Create separate map file.", 124 | "type": "boolean", 125 | "default": false, 126 | "order": 80 127 | }, 128 | "babelMapsAddUrl": { 129 | "description": "Append map file name to transpiled output if \"Create separate map file\" is set.", 130 | "type": "boolean", 131 | "default": true, 132 | "order": 90 133 | }, 134 | "babelSourcePath": { 135 | "description": "Babel Source Root based on Project root.", 136 | "type": "string", 137 | "default": "", 138 | "order": 100 139 | }, 140 | "babelTranspilePath": { 141 | "description": "Babel Transpile Root based on Project root.", 142 | "type": "string", 143 | "default": "", 144 | "order": 120 145 | }, 146 | "babelMapsPath": { 147 | "description": "Babel Maps Root based on Project root.", 148 | "type": "string", 149 | "default": "", 150 | "order": 130 151 | }, 152 | "createTargetDirectories": { 153 | "description": "Create transpile output target directories.", 154 | "type": "boolean", 155 | "default": true, 156 | "order": 140 157 | }, 158 | "keepFileExtension": { 159 | "description": "Source filename extension becomes target filename extension.", 160 | "type": "boolean", 161 | "default": false, 162 | "order": 150 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /spec/create-tag-grammar-spec.js: -------------------------------------------------------------------------------- 1 | /*global atom*/ 2 | var temp = require('temp'); 3 | var path = require('path'); 4 | var CreateTtlGrammar = require('../lib/create-ttl-grammar'); 5 | 6 | temp.track(); 7 | 8 | describe('Create Ttl Grammar', () => { 9 | var ttlGrammar = null; 10 | 11 | beforeEach(() => { 12 | temp.cleanup(); 13 | waitsForPromise(() => { 14 | return atom.packages.activatePackage('language-babel'); 15 | }); 16 | 17 | return runs(() => { 18 | ttlGrammar = new CreateTtlGrammar(); 19 | 20 | }); 21 | }); 22 | 23 | afterEach(() => { 24 | ttlGrammar.destroy(); 25 | ttlGrammar = null; 26 | }); 27 | 28 | describe('::getTtlConfig', () => { 29 | return it( 30 | 'should return an array containing the tagged template extensions configuration', 31 | () => { 32 | return expect(ttlGrammar.getTtlConfig()).toEqual([]); 33 | } 34 | ); 35 | }); 36 | 37 | describe('::generateTtlSHA256', () => { 38 | return it( 39 | 'should return SHA256 hash some text', 40 | () => { 41 | return expect(ttlGrammar.generateTtlSHA256('The Quick Fox')).toEqual('4af51dbb709ee9d85987ca5982e322ee2ec4d72ae8c92f11c5728813277e6b33'); 42 | } 43 | ); 44 | }); 45 | 46 | describe('::makeTtlGrammarFilename', () => { 47 | return it( 48 | 'should return a string prefixed with ttl-', 49 | () => { 50 | expect(ttlGrammar.makeTtlGrammarFilename('filename')).toEqual('ttl-filename.json'); 51 | } 52 | ); 53 | }); 54 | 55 | describe('::getGrammarPath', () => { 56 | return it( 57 | 'should return an absolute path where the language-babel grammar files are', 58 | () => { 59 | expect(path.isAbsolute(ttlGrammar.getGrammarPath())).toEqual(true); 60 | } 61 | ); 62 | }); 63 | 64 | describe('::makeTtlGrammarFilenameAbsoulute', () => { 65 | return it( 66 | 'should return an absolute path with a filename ', 67 | () => { 68 | expect(path.isAbsolute(ttlGrammar.makeTtlGrammarFilenameAbsoulute('someFile'))).toEqual(true); 69 | } 70 | ); 71 | }); 72 | 73 | describe('::getGrammarFiles', () => { 74 | return it( 75 | 'should return a list of all language-babel grammar files including Babel Language.json', 76 | () => { 77 | waitsForPromise(() => { 78 | return ttlGrammar.getGrammarFiles().then( (grammarFiles) => { 79 | expect(grammarFiles).toContain('Babel Language.json'); 80 | }); 81 | }); 82 | } 83 | ); 84 | }); 85 | 86 | describe('::getTtlGrammarFiles', () => { 87 | return it( 88 | 'should return a list of language-babel grammar with a ttl- prefix', 89 | () => { 90 | waitsForPromise(() => { 91 | return ttlGrammar.getTtlGrammarFiles().then( (grammarFiles) => { 92 | expect(grammarFiles).toMatch(/^ttl-/); 93 | }); 94 | }); 95 | } 96 | ); 97 | }); 98 | 99 | describe('::doesGrammarFileExist', () => { 100 | return it( 101 | 'checks if a grammar file exists', 102 | () => { 103 | waitsForPromise(() => { 104 | return ttlGrammar.doesGrammarFileExist('Babel Language.json').catch( (rejVal) => { 105 | expect(rejVal).toEqual(true); 106 | }); 107 | }); 108 | } 109 | ); 110 | }); 111 | 112 | describe('::removeTtlLanguageFiles', () => { 113 | return it( 114 | 'should remove any files ttl-hashedvalue.json', 115 | () => { 116 | var tempGrammarDir = temp.mkdirSync(); 117 | temp.open('ttl-a.json'); 118 | temp.open('ttl-b.json'); 119 | temp.open('ttl-c.json'); 120 | 121 | spyOn(ttlGrammar, 'getGrammarPath').andReturn(tempGrammarDir); 122 | 123 | waitsForPromise( () => { 124 | return ttlGrammar.removeTtlLanguageFiles() 125 | // Previous fs.unlink's queue a delete in Node so delay check 126 | .then( () => setTimeout(()=>void(0) ,1000) ) 127 | .then( () => ttlGrammar.getTtlGrammarFiles() ) 128 | .then( (ttlFiles) => expect(ttlFiles).toEqual([]) ); 129 | }); 130 | }); 131 | }); 132 | 133 | describe('::createGrammarPatterns', () => { 134 | return it( 135 | 'should generate an error when a badly formatted ttl config is entered', 136 | () => { 137 | expect(() => ttlGrammar.createGrammarPatterns('/* test */:trailing.dot.#include')).toThrow(); 138 | } 139 | ); 140 | }); 141 | 142 | describe('::onigurumaCheck', () => { 143 | return it( 144 | 'should return true on a valid regex', 145 | () => { 146 | let ret = ttlGrammar.onigurumaCheck('(?<=\\{)'); 147 | expect(ret).toBe(true); 148 | } 149 | ); 150 | }); 151 | 152 | describe('::onigurumaCheck', () => { 153 | return it( 154 | 'should throw on a invalid regex', 155 | () => { 156 | expect(() => {ttlGrammar.onigurumaCheck('(?<=\\s*\\{)');}).toThrow(); 157 | } 158 | ); 159 | }); 160 | 161 | // Ensure we finish off by creating a valid ttl file 162 | describe('::createGrammar', () => { 163 | return it( 164 | 'should create a valid ttl grammar file based upon some defined config', 165 | () => { 166 | var tempGrammarDir = temp.mkdirSync(); 167 | 168 | spyOn(ttlGrammar, 'getGrammarPath').andReturn(tempGrammarDir); 169 | spyOn(ttlGrammar, 'getTtlConfig').andReturn(['"(?:css\\.(?:[a-z])+)":source.css','/* @html */:text.html.basic','sql:source.sql']); 170 | 171 | const grammarText = ttlGrammar.createGrammarText(); 172 | const hash = ttlGrammar.generateTtlSHA256(grammarText); 173 | const ttlFilename = ttlGrammar.makeTtlGrammarFilename(hash); 174 | const ttlFilenameAbsolute = ttlGrammar.makeTtlGrammarFilenameAbsoulute(ttlFilename); 175 | waitsForPromise(() => { 176 | return ttlGrammar.createGrammar({ttlFilename, ttlFilenameAbsolute, grammarText }).then( (val) => { 177 | expect(val).toEqual('ttl-21a776c6bf96514f8dd8ffa557f23132510ace330d988f695538558900eeebe9.json'); 178 | }); 179 | }); 180 | } 181 | ); 182 | }); 183 | 184 | }); 185 | -------------------------------------------------------------------------------- /lib/main.coffee: -------------------------------------------------------------------------------- 1 | {CompositeDisposable} = require 'atom' 2 | autoCompleteJSX = require './auto-complete-jsx' 3 | autoCompleteStyledComponents = require './auto-complete-styled-components' 4 | autoCompeteEmmetCSS = require './auto-complete-emmet-css' 5 | AutoIndent = require './auto-indent' 6 | ttlGrammar = require './create-ttl-grammar' 7 | 8 | INTERFILESAVETIME = 1000 9 | LB = 'language-babel' 10 | observeStatusBarGrammarNameTimer = null 11 | observeStatusBarGrammarNameTimerCalled = 0 12 | 13 | module.exports = 14 | activate: (state) -> 15 | # run observeStatusBarGrammarName until Atom has created the Status Bar Grammar Name DOM node 16 | observeStatusBarGrammarNameTimer = setInterval(@observeStatusBarGrammarName.bind(@), 1000) 17 | autoCompleteStyledComponents.loadProperties() 18 | @transpiler ?= new (require './transpiler') 19 | @ttlGrammar = new ttlGrammar(true) 20 | # track any file save events and transpile if babel 21 | @disposable = new CompositeDisposable 22 | @textEditors = {} 23 | @fileSaveTimes = {} 24 | 25 | @disposable.add atom.packages.onDidActivatePackage @isPackageCompatible 26 | 27 | @disposable.add atom.project.onDidChangePaths => 28 | @transpiler.stopUnusedTasks() 29 | 30 | @disposable.add atom.workspace.observeTextEditors (textEditor) => 31 | @textEditors[textEditor.id] = new CompositeDisposable 32 | 33 | @textEditors[textEditor.id].add textEditor.observeGrammar (grammar) => 34 | # Instantiate indentor for language-babel files 35 | if textEditor.getGrammar().packageName is LB 36 | @textEditors[textEditor.id]?.autoIndent = new AutoIndent(textEditor) 37 | else 38 | @textEditors[textEditor.id]?.autoIndent?.destroy() 39 | delete @textEditors[textEditor.id]?.autoIndent? 40 | 41 | @textEditors[textEditor.id].add textEditor.onDidSave (event) => 42 | if textEditor.getGrammar().packageName is LB 43 | filePath = textEditor.getPath() 44 | lastSaveTime = @fileSaveTimes[filePath] ? 0 45 | @fileSaveTimes[filePath] = Date.now() 46 | if (lastSaveTime < (@fileSaveTimes[filePath] - INTERFILESAVETIME)) 47 | @transpiler.transpile(filePath, textEditor) 48 | 49 | @textEditors[textEditor.id].add textEditor.onDidDestroy () => 50 | @textEditors[textEditor.id]?.autoIndent?.destroy() 51 | delete @textEditors[textEditor.id]?.autoIndent? 52 | filePath = textEditor.getPath() 53 | if @fileSaveTimes[filePath]? then delete @fileSaveTimes[filePath] 54 | @textEditors[textEditor.id].dispose() 55 | delete @textEditors[textEditor.id] 56 | 57 | deactivate: -> 58 | @disposable.dispose() 59 | for id, disposeable of @textEditors 60 | if @textEditors[id].autoIndent? 61 | @textEditors[id].autoIndent.destroy() 62 | delete @textEditors[id].autoIndent 63 | disposeable.dispose() 64 | @transpiler.stopAllTranspilerTask() 65 | @transpiler.disposables.dispose() 66 | @ttlGrammar.destroy() 67 | @mutateStatusGrammarNameObserver?.disconnet() 68 | 69 | # warns if an activated package is on the incompatible list 70 | isPackageCompatible: (activatedPackage) -> 71 | incompatiblePackages = { 72 | 'source-preview-babel': 73 | "Both vie to preview the same file." 74 | 'source-preview-react': 75 | "Both vie to preview the same file." 76 | 'react': 77 | "The Atom community package 'react' (not to be confused 78 | \nwith Facebook React) monkey patches the atom methods 79 | \nthat provide autoindent features for JSX. 80 | \nAs it detects JSX scopes without regard to the grammar being used, 81 | \nit tries to auto indent JSX that is highlighted by language-babel. 82 | \nAs language-babel also attempts to do auto indentation using 83 | \nstandard atom API's, this creates a potential conflict." 84 | } 85 | 86 | for incompatiblePackage, reason of incompatiblePackages 87 | if activatedPackage.name is incompatiblePackage 88 | atom.notifications.addInfo 'Incompatible Package Detected', 89 | dismissable: true 90 | detail: "language-babel has detected the presence of an 91 | incompatible Atom package named '#{activatedPackage.name}'. 92 | \n \nIt is recommended that you disable either '#{activatedPackage.name}' or language-babel 93 | \n \nReason:\n \n#{reason}" 94 | 95 | # autocomplete-plus providers 96 | autoCompleteProvider: -> 97 | [autoCompleteJSX, autoCompleteStyledComponents, autoCompeteEmmetCSS] 98 | 99 | # preview tranpile provider 100 | provide:-> 101 | @transpiler 102 | 103 | 104 | # Kludge to change the grammar name in the status bar from Babel ES6 JavaScipt to Babel 105 | # The grammar name still remains the same for compatibilty with other packages such as atom-beautify 106 | # but is more meaningful and shorter on the status bar. 107 | observeStatusBarGrammarName: -> 108 | # select the target node 109 | target = document.getElementsByTagName('grammar-selector-status'); 110 | 111 | # only run this for so many cycles without getting a valid dom node 112 | if ++observeStatusBarGrammarNameTimerCalled > 60 113 | clearInterval(observeStatusBarGrammarNameTimer) 114 | observeStatusBarGrammarNameTimerCalled = 0 115 | 116 | # only expect a single child (grammar name) for this DOM Node 117 | if target.length is 1 118 | target = target[0].childNodes?[0] 119 | 120 | if target 121 | # don't run again as we are now observing 122 | clearInterval(observeStatusBarGrammarNameTimer) 123 | 124 | @mutateStatusBarGrammarName(target) 125 | 126 | # create an observer instance 127 | mutateStatusGrammarNameObserver = new MutationObserver (mutations) => 128 | mutations.forEach (mutation) => 129 | @mutateStatusBarGrammarName(mutation.target) 130 | 131 | # configuration of the observer: 132 | config = { attributes: true, childList: false, characterData: false } 133 | 134 | # pass in the target node, as well as the observer options 135 | mutateStatusGrammarNameObserver.observe(target, config); 136 | 137 | 138 | # change name in status bar 139 | mutateStatusBarGrammarName: (elem) -> 140 | if elem?.innerHTML is 'Babel ES6 JavaScript' 141 | elem.innerHTML = 'Babel' 142 | -------------------------------------------------------------------------------- /lib/auto-complete-jsx.coffee: -------------------------------------------------------------------------------- 1 | {Range, Point} = require "atom" 2 | {filter, score} = require "fuzzaldrin" 3 | 4 | # tags we are interested in are marked by the grammar 5 | JSXSTARTTAGEND = 0 6 | JSXENDTAGSTART = 1 7 | JSXTAG = 2 8 | JSXATTRIBUTE = 3 9 | # regex to search for tag open/close tag and close tag 10 | JSXREGEXP = /(?:(<)|(<\/))([$_A-Za-z](?:[$._:\-a-zA-Z0-9])*)|(?:(\/>)|(>))|(<\s*>)/g 11 | TAGREGEXP = /<([$_a-zA-Z][$._:\-a-zA-Z0-9]*)($|\s|\/>|>)/g 12 | COMPLETIONS = require "./completions-jsx" 13 | REACTURL = "http://facebook.github.io/react/docs/tags-and-attributes.html" 14 | 15 | module.exports = 16 | selector: ".meta.tag.jsx" 17 | inclusionPriority: 10000 18 | excludeLowerPriority: false 19 | 20 | 21 | getSuggestions: (opts) -> 22 | {editor, bufferPosition, scopeDescriptor, prefix} = opts 23 | 24 | jsxTag = @getTriggerTag editor, bufferPosition 25 | return if not jsxTag? 26 | 27 | # build autocomplete list 28 | suggestions = [] 29 | 30 | if jsxTag is JSXSTARTTAGEND 31 | startOfJSX = @getStartOfJSX editor, bufferPosition 32 | jsxRange = new Range(startOfJSX, bufferPosition) 33 | tagNameStack = @buildTagStack(editor, jsxRange) 34 | while ( tagName = tagNameStack.pop())? 35 | suggestions.push 36 | snippet: "$1" 37 | type: "tag" 38 | description: "language-babel tag closer" 39 | 40 | else if jsxTag is JSXENDTAGSTART 41 | startOfJSX = @getStartOfJSX editor, bufferPosition 42 | jsxRange = new Range(startOfJSX, bufferPosition) 43 | tagNameStack = @buildTagStack(editor, jsxRange) 44 | while ( tagName = tagNameStack.pop())? 45 | suggestions.push 46 | snippet: "#{tagName}>" 47 | type: "tag" 48 | description: "language-babel tag closer" 49 | 50 | else if jsxTag is JSXTAG 51 | return if not /^[a-z]/g.exec(prefix) 52 | htmlElements = filter(COMPLETIONS.htmlElements, prefix, {key: "name"}) 53 | for htmlElement in htmlElements 54 | if score(htmlElement.name, prefix) < 0.07 then continue 55 | suggestions.push 56 | snippet: htmlElement.name 57 | type: "tag" 58 | description: "language-babel JSX supported elements" 59 | descriptionMoreURL: REACTURL 60 | 61 | else if jsxTag is JSXATTRIBUTE 62 | tagName = @getThisTagName editor, bufferPosition 63 | return if not tagName? 64 | for elementObj in COMPLETIONS.htmlElements 65 | if elementObj.name is tagName then break 66 | attributes = elementObj.attributes.concat COMPLETIONS.globalAttributes 67 | attributes = attributes.concat COMPLETIONS.events 68 | filteredAttributes = filter(attributes, prefix, {key: "name"}) 69 | for attribute in filteredAttributes 70 | if score(attribute.name, prefix) < 0.07 then continue 71 | suggestions.push 72 | snippet: attribute.name 73 | type: "attribute" 74 | rightLabel: "<#{tagName}>" 75 | description: "language-babel JSXsupported attributes/events" 76 | descriptionMoreURL: REACTURL 77 | 78 | else return 79 | suggestions 80 | 81 | # get tagname for this attribute 82 | getThisTagName: ( editor, bufferPosition) -> 83 | row = bufferPosition.row 84 | column = null 85 | while row >= 0 86 | rowText = editor.lineTextForBufferRow(row) 87 | if not column? 88 | rowText = rowText.substr 0, column = bufferPosition.column 89 | matches = [] 90 | while (( match = TAGREGEXP.exec(rowText)) isnt null ) 91 | # save this match if it a valid tag 92 | scopes = editor.scopeDescriptorForBufferPosition([row, match.index+1]).getScopesArray() 93 | if "entity.name.tag.open.jsx" in scopes then matches.push match[1] 94 | # return the tag that is the last one found 95 | if matches.length 96 | return matches.pop() 97 | else row-- 98 | 99 | 100 | getTriggerTag: (editor, bufferPosition) -> 101 | # JSX tag scopes we are interested in may already closed once typed 102 | # so we have to backtrack by one char to see if they were typed 103 | column = bufferPosition.column-1 104 | if column >= 0 105 | scopes = editor.scopeDescriptorForBufferPosition([bufferPosition.row, column]).getScopesArray() 106 | if "entity.other.attribute-name.jsx" in scopes then return JSXATTRIBUTE 107 | if "entity.name.tag.open.jsx" in scopes then return JSXTAG 108 | if "JSXStartTagEnd" in scopes then return JSXSTARTTAGEND 109 | if "JSXEndTagStart" in scopes then return JSXENDTAGSTART 110 | 111 | 112 | # find beggining of JSX in buffer and return Point 113 | getStartOfJSX: (editor, bufferPosition) -> 114 | row = bufferPosition.row 115 | # find previous start of row that has no jsx tag 116 | while row >= 0 117 | break if "meta.tag.jsx" not in editor.scopeDescriptorForBufferPosition([row, 0]).getScopesArray() 118 | row-- 119 | if row < 0 then row = 0 120 | # maybe jsx appaears later in row 121 | columnLen = editor.lineTextForBufferRow(row).length 122 | column = 0 123 | while column < columnLen 124 | break if "meta.tag.jsx" in editor.scopeDescriptorForBufferPosition([row, column]).getScopesArray() 125 | column++ 126 | # adjust row column if jsx not in this row at all 127 | if column is columnLen 128 | row++ 129 | column = 0 130 | new Point(row, column) 131 | 132 | # build stack of tagnames opened but not closed in Range 133 | buildTagStack: (editor, range) -> 134 | tagNameStack = [] 135 | row = range.start.row 136 | while row <= range.end.row 137 | line = editor.lineTextForBufferRow row 138 | if row is range.end.row 139 | line = line.substr 0, range.end.column 140 | while (( match = JSXREGEXP.exec(line)) isnt null ) 141 | matchColumn = match.index 142 | matchPointStart = new Point(row, matchColumn) 143 | matchPointEnd = new Point(row, matchColumn + match[0].length - 1) 144 | matchRange = new Range(matchPointStart, matchPointEnd) 145 | if range.intersectsWith(matchRange) 146 | scopes = editor.scopeDescriptorForBufferPosition([row, match.index]).getScopesArray() 147 | continue if "punctuation.definition.tag.jsx" not in scopes 148 | #check capture groups 149 | if match[1]? # tags starting 156 | tagNameStack.pop() 157 | else if match[6]? # tag fragment stating <> 158 | tagNameStack.push "" 159 | 160 | row++ 161 | tagNameStack 162 | -------------------------------------------------------------------------------- /spec/fixtures/grammar/babel-sublime/js-class.js: -------------------------------------------------------------------------------- 1 | // SYNTAX TEST "source.js.jsx" 2 | 3 | class MyClass { 4 | // <- meta.class.js storage.type.class.js 5 | // <- meta.class.js storage.type.class.js 6 | //^^^ meta.class.js 7 | //^^^ storage.type.class.js 8 | // ^^^^^^^ entity.name.class.js 9 | // ^ punctuation.section.class.begin.js 10 | regularMethod() {} 11 | //^^^^^^^^^^^^^^^ ^^ meta.class.body.js 12 | //^^^^^^^^^^^^^^^ ^^ meta.function.method.js 13 | //^^^^^^^^^^^^^ entity.name.function.method.js 14 | // ^ punctuation.definition.parameters.begin.js 15 | // ^^ meta.brace.round.js 16 | // ^ punctuation.definition.parameters.end.js 17 | // ^^ meta.brace.curly.js 18 | *generatorMethod() {} 19 | //^^^^^^^^^^^^^^^^^^ ^^ meta.class.body.js 20 | //^^^^^^^^^^^^^^^^^^ ^^ meta.function.method.js 21 | //^ keyword.generator.asterisk.js 22 | // ^^^^^^^^^^^^^^^ entity.name.function.method.js 23 | // ^ punctuation.definition.parameters.begin.js 24 | // ^^ meta.brace.round.js 25 | // ^ punctuation.definition.parameters.end.js 26 | // ^^ meta.brace.curly.js 27 | static staticRegularMethod() {} 28 | //^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ ^^ meta.class.body.js 29 | //^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ ^^ meta.function.method.js 30 | //^^^^^^ storage.modifier.js 31 | // ^^^^^^^^^^^^^^^^^^^ entity.name.function.method.js 32 | // ^ punctuation.definition.parameters.begin.js 33 | // ^^ meta.brace.round.js 34 | // ^ punctuation.definition.parameters.end.js 35 | // ^^ meta.brace.curly.js 36 | static get staticGetterMethod() {} 37 | //^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^ ^^ meta.class.body.js 38 | //^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^ ^^ meta.accessor.js 39 | //^^^^^^ storage.modifier.js 40 | // ^^^ storage.type.accessor.js 41 | // ^^^^^^^^^^^^^^^^^^ entity.name.function.accessor.js 42 | // ^ punctuation.definition.parameters.begin.js 43 | // ^^ meta.brace.round.js 44 | // ^ punctuation.definition.parameters.end.js 45 | // ^^ meta.brace.curly.js 46 | static set staticSetterMethod(arg) {} 47 | //^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^ meta.class.body.js 48 | //^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^ meta.accessor.js 49 | //^^^^^^ storage.modifier.js 50 | // ^^^ storage.type.accessor.js 51 | // ^^^^^^^^^^^^^^^^^^ entity.name.function.accessor.js 52 | // ^ punctuation.definition.parameters.begin.js 53 | // ^ ^ meta.brace.round.js 54 | // ^^^ meta.function.parameters.js 55 | // ^^^ variable.other.readwrite.js 56 | // ^ punctuation.definition.parameters.end.js 57 | // ^^ meta.brace.curly.js 58 | static *staticGeneratorMethod() {} 59 | //^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^ meta.class.body.js 60 | //^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^ meta.function.method.js 61 | //^^^^^^ storage.modifier.js 62 | // ^ keyword.generator.asterisk.js 63 | // ^^^^^^^^^^^^^^^^^^^^^ entity.name.function.method.js 64 | // ^ punctuation.definition.parameters.begin.js 65 | // ^^ meta.brace.round.js 66 | // ^ punctuation.definition.parameters.end.js 67 | // ^^ meta.brace.curly.js 68 | static async staticAsyncMethod() {} 69 | //^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^ meta.class.body.js 70 | //^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^ meta.function.method.js 71 | //^^^^^^ storage.modifier.js 72 | // ^^^^^ storage.type.js 73 | // ^^^^^^^^^^^^^^^^^ entity.name.function.method.js 74 | // ^ punctuation.definition.parameters.begin.js 75 | // ^^ meta.brace.round.js 76 | // ^ punctuation.definition.parameters.end.js 77 | // ^^ meta.brace.curly.js 78 | async asyncMethod() {} 79 | //^^^^^ ^^^^^^^^^^^^^ ^^ meta.class.body.js 80 | //^^^^^ ^^^^^^^^^^^^^ ^^ meta.function.method.js 81 | //^^^^^ storage.type.js 82 | // ^^^^^^^^^^^ entity.name.function.method.js 83 | // ^ punctuation.definition.parameters.begin.js 84 | // ^^ meta.brace.round.js 85 | // ^ punctuation.definition.parameters.end.js 86 | // ^^ meta.brace.curly.js 87 | [computedMethod()]() {} 88 | //^^^^^^^^^^^^^^^^^^^^ ^^ meta.class.body.js 89 | //^^^^^^^^^^^^^^^^^^^^ ^^ meta.function.method.js 90 | //^ ^ meta.brace.square.js 91 | // ^^^^^^^^^^^^^^^^ meta.function-call.without-arguments.js 92 | // ^^^^^^^^^^^^^^ entity.name.function.js 93 | // ^^ ^^ meta.brace.round.js 94 | // ^ punctuation.definition.parameters.begin.js 95 | // ^ punctuation.definition.parameters.end.js 96 | // ^^ meta.brace.curly.js 97 | ["computedString"]() {} 98 | //^^^^^^^^^^^^^^^^^^^^ ^^ meta.class.body.js 99 | //^^^^^^^^^^^^^^^^^^^^ ^^ meta.function.method.js 100 | //^ ^ meta.brace.square.js 101 | // ^^^^^^^^^^^^^^^^ string.quoted.double.js 102 | // ^ punctuation.definition.string.begin.js 103 | // ^ punctuation.definition.string.end.js 104 | // ^ punctuation.definition.parameters.begin.js 105 | // ^^ meta.brace.round.js 106 | // ^ punctuation.definition.parameters.end.js 107 | // ^^ meta.brace.curly.js 108 | ["computed" + "String"]() {} 109 | //^^^^^^^^^^^ ^ ^^^^^^^^^^^ ^^ meta.class.body.js 110 | //^^^^^^^^^^^ ^ ^^^^^^^^^^^ ^^ meta.function.method.js 111 | //^ ^ meta.brace.square.js 112 | // ^^^^^^^^^^ ^^^^^^^^ string.quoted.double.js 113 | // ^ ^ punctuation.definition.string.begin.js 114 | // ^ ^ punctuation.definition.string.end.js 115 | // ^ keyword.operator.arithmetic.js 116 | // ^ punctuation.definition.parameters.begin.js 117 | // ^^ meta.brace.round.js 118 | // ^ punctuation.definition.parameters.end.js 119 | // ^^ meta.brace.curly.js 120 | *[Symbol.iterator]() {} 121 | //^^^^^^^^^^^^^^^^^^^^ ^^ meta.class.body.js 122 | //^^^^^^^^^^^^^^^^^^^^ ^^ meta.function.method.js 123 | //^ keyword.generator.asterisk.js 124 | // ^ ^ meta.brace.square.js 125 | // ^^^^^^ support.class.builtin.js 126 | // ^ keyword.operator.accessor.js 127 | // ^^^^^^^^ meta.property.object.js 128 | // ^^^^^^^^ variable.other.property.js 129 | // ^ punctuation.definition.parameters.begin.js 130 | // ^^ meta.brace.round.js 131 | // ^ punctuation.definition.parameters.end.js 132 | // ^^ meta.brace.curly.js 133 | } 134 | // <- punctuation.section.class.end.js 135 | 136 | 137 | // >> only:(source.js.jsx) 138 | -------------------------------------------------------------------------------- /spec/fixtures/grammar/babel-sublime/jsx-features.jsx: -------------------------------------------------------------------------------- 1 | // SYNTAX TEST "source.js.jsx" 2 | 3 | // JSX Fragements 4 | 5 | <> 6 | // <- meta.tag.jsx punctuation.definition.tag.jsx 7 | // <- meta.tag.jsx punctuation.definition.tag.jsx JSXAttrs JSXStartTagEnd 8 | Some fragment 9 | //^^^^ ^^^^^^^^ meta.tag.jsx 10 | //^^^^ ^^^^^^^^ JSXAttrs 11 | //^^^^ ^^^^^^^^ JSXNested 12 |
<>Some frag
13 | //^^^^^^^^^^^ ^^^^^^^^^^^^^ meta.tag.jsx 14 | //^^^^^^^^^^^ ^^^^^^^^^^^^^ JSXAttrs 15 | //^^^^^^^^^^^ ^^^^^^^^^^^^^ JSXNested 16 | //^ ^^^ ^^^^^ ^ punctuation.definition.tag.jsx 17 | // ^^^ entity.name.tag.open.jsx 18 | // ^ ^ JSXStartTagEnd 19 | // ^^ ^^ JSXEndTagStart 20 | // ^^^ entity.name.tag.close.jsx 21 | 22 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 23 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 24 | //^ meta.tag.jsx 25 | //^ punctuation.definition.tag.jsx 26 | 27 | // tight greater-/less-than operations. 28 | 29 | for (var i=1; i 111 | // <- meta.tag.jsx punctuation.definition.tag.jsx 112 | // <- meta.tag.jsx entity.name.tag.open.jsx 113 | //^^ ^^ ^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^ meta.tag.jsx 114 | // ^ punctuation.definition.tag.jsx 115 | //^^ entity.name.tag.open.jsx 116 | // ^^ ^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^ JSXAttrs 117 | // ^^ ^^^^^^^ ^^ comment.block.js 118 | // ^^ ^^ punctuation.definition.comment.js 119 | // ^^^^^^^ entity.other.attribute-name.jsx 120 | // ^ keyword.operator.assignment.jsx 121 | // ^^^^^^^^^^^^^^ meta.embedded.expression.js 122 | // ^ punctuation.section.embedded.begin.jsx 123 | // ^^^^ variable.language.this.js 124 | // ^ keyword.operator.accessor.js 125 | // ^^^^^^^ meta.property.object.js 126 | // ^^^^^^^ variable.other.property.js 127 | // ^ punctuation.section.embedded.end.jsx 128 | // ^ JSXStartTagEnd 129 | 130 | //^^^^^^^^^^^^^^^^^^^^^^^ ^^ meta.tag.jsx 131 | //^^^^^^^^^^^^^^^^^^^^^^^ ^^ JSXAttrs 132 | //^^^^^^^^^^^^^^^^^^^^^^^ ^^ JSXNested 133 | //^ ^^ punctuation.definition.tag.jsx 134 | // ^^^^^^^^^^^^^^^^^^^^^^ entity.name.tag.open.jsx 135 | // ^^^^^^^^^^^^^^^^^^^^^^ support.class.component.open.jsx 136 | 170 | // ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.tag.jsx 171 | // ^^^^^^^^^^^^^^^^^^^^^^^^^ JSXAttrs 172 | // ^^^^^^^^^^^^^^^^^^^^^^^^^ JSXNested 173 | // ^^^^^^^^^ entity.other.attribute-name.jsx 174 | // ^ keyword.operator.assignment.jsx 175 | // ^^^^^^^^^^^^^^ string.quoted.single.js 176 | // ^ punctuation.definition.string.begin.jsx 177 | // ^ punctuation.definition.string.end.jsx 178 | // ^ punctuation.definition.tag.jsx 179 | // ^ JSXStartTagEnd 180 | 181 | //^^^^^^^^^^^^^^^^^^^^ meta.tag.jsx 182 | //^^^^^^^^^^^^^^^^^^^^ JSXAttrs 183 | //^^^^^^^^^^^^^^^^^^^^ JSXNested 184 | //^^ ^ punctuation.definition.tag.jsx 185 | //^^ JSXEndTagStart 186 | // ^^^^^^^^^^^^^^^^^ entity.name.tag.close.jsx 187 | // ^^^^^^^^^^^^^^^^^ support.class.component.close.jsx 188 | 189 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 190 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 191 | //^^^^ meta.tag.jsx 192 | // ^ punctuation.definition.tag.jsx 193 | //^^^ entity.name.tag.close.jsx 194 | 195 | 196 | 197 | // >> only:(source.js.jsx) 198 | -------------------------------------------------------------------------------- /lib/auto-complete-styled-components.coffee: -------------------------------------------------------------------------------- 1 | # This code was based upon https://github.com/atom/autocomplete-css but has been modified to allow it to be used 2 | # for styled-componenets. The completions.json file used to auto complete is a copy of the one used by the atom 3 | # package. That package, provided as an Atom base package, has tools to update the completions.json file from the web. 4 | # See that package for more info and just copy the completions.json to this files directory when a refresh is needed. 5 | 6 | fs = require 'fs' 7 | path = require 'path' 8 | 9 | firstInlinePropertyNameWithColonPattern = /{\s*(\S+)\s*:/ # .example { display: } 10 | inlinePropertyNameWithColonPattern = /(?:;.+?)*;\s*(\S+)\s*:/ # .example { display: block; float: left; color: } (match the last one) 11 | propertyNameWithColonPattern = /^\s*(\S+)\s*:/ # display: 12 | propertyNamePrefixPattern = /[a-zA-Z]+[-a-zA-Z]*$/ 13 | pesudoSelectorPrefixPattern = /:(:)?([a-z]+[a-z-]*)?$/ 14 | tagSelectorPrefixPattern = /(^|\s|,)([a-z]+)?$/ 15 | importantPrefixPattern = /(![a-z]+)$/ 16 | cssDocsURL = "https://developer.mozilla.org/en-US/docs/Web/CSS" 17 | 18 | module.exports = 19 | selector: '.source.inside-js.css.styled, .source.css.styled' 20 | disableForSelector: ".source.inside-js.css.styled .comment, .source.inside-js.css.styled .string, .source.inside-js.css.styled .entity.quasi.element.js, .source.css.styled .comment, .source.css.styled .string, .source.css.styled .entity.quasi.element.js" 21 | 22 | filterSuggestions: true 23 | inclusionPriority: 10000 24 | excludeLowerPriority: false 25 | suggestionPriority: 90 26 | 27 | getSuggestions: (request) -> 28 | completions = null 29 | scopes = request.scopeDescriptor.getScopesArray() 30 | 31 | if @isCompletingValue(request) 32 | completions = @getPropertyValueCompletions(request) 33 | else if @isCompletingPseudoSelector(request) 34 | completions = @getPseudoSelectorCompletions(request) 35 | else 36 | if @isCompletingName(request) 37 | completions = @getPropertyNameCompletions(request) 38 | else if @isCompletingNameOrTag(request) 39 | completions = @getPropertyNameCompletions(request) 40 | .concat(@getTagCompletions(request)) 41 | 42 | return completions 43 | 44 | onDidInsertSuggestion: ({editor, suggestion}) -> 45 | setTimeout(@triggerAutocomplete.bind(this, editor), 1) if suggestion.type is 'property' 46 | 47 | triggerAutocomplete: (editor) -> 48 | atom.commands.dispatch(atom.views.getView(editor), 'autocomplete-plus:activate', {activatedManually: false}) 49 | 50 | loadProperties: -> 51 | @properties = {} 52 | fs.readFile path.resolve(__dirname, 'completions.json'), (error, content) => 53 | {@pseudoSelectors, @properties, @tags} = JSON.parse(content) unless error? 54 | 55 | return 56 | 57 | isCompletingValue: ({scopeDescriptor, bufferPosition, prefix, editor}) -> 58 | scopes = scopeDescriptor.getScopesArray() 59 | 60 | beforePrefixBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - prefix.length - 1)] 61 | beforePrefixScopes = editor.scopeDescriptorForBufferPosition(beforePrefixBufferPosition) 62 | beforePrefixScopesArray = beforePrefixScopes.getScopesArray() 63 | 64 | return (hasScope(scopes, 'meta.property-values.css')) or 65 | (hasScope(beforePrefixScopesArray , 'meta.property-values.css')) 66 | 67 | isCompletingName: ({scopeDescriptor, bufferPosition, editor}) -> 68 | scope = scopeDescriptor.getScopesArray().slice(-1) 69 | prefix = @getPropertyNamePrefix(bufferPosition, editor) 70 | return @isPropertyNamePrefix(prefix) and (scope[0] is 'meta.property-list.css') 71 | 72 | isCompletingNameOrTag: ({scopeDescriptor, bufferPosition, editor}) -> 73 | scope = scopeDescriptor.getScopesArray().slice(-1) 74 | prefix = @getPropertyNamePrefix(bufferPosition, editor) 75 | return @isPropertyNamePrefix(prefix) and 76 | ((scope[0] is 'meta.property-list.css') or 77 | (scope[0] is 'source.css.styled') or 78 | (scope[0] is 'entity.name.tag.css') or 79 | (scope[0] is 'source.inside-js.css.styled')) 80 | 81 | isCompletingPseudoSelector: ({editor, scopeDescriptor, bufferPosition}) -> 82 | scope = scopeDescriptor.getScopesArray().slice(-1) 83 | return ( ( scope[0] is 'constant.language.pseudo.prefixed.css') or 84 | ( scope[0] is 'keyword.operator.pseudo.css') ) 85 | 86 | isPropertyValuePrefix: (prefix) -> 87 | prefix = prefix.trim() 88 | prefix.length > 0 and prefix isnt ':' 89 | 90 | isPropertyNamePrefix: (prefix) -> 91 | return false unless prefix? 92 | prefix = prefix.trim() 93 | prefix.match(/^[a-zA-Z-]+$/) 94 | 95 | getImportantPrefix: (editor, bufferPosition) -> 96 | line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition]) 97 | importantPrefixPattern.exec(line)?[1] 98 | 99 | getPreviousPropertyName: (bufferPosition, editor) -> 100 | {row} = bufferPosition 101 | while row >= 0 102 | line = editor.lineTextForBufferRow(row) 103 | propertyName = inlinePropertyNameWithColonPattern.exec(line)?[1] 104 | propertyName ?= firstInlinePropertyNameWithColonPattern.exec(line)?[1] 105 | propertyName ?= propertyNameWithColonPattern.exec(line)?[1] 106 | return propertyName if propertyName 107 | row-- 108 | return 109 | 110 | getPropertyValueCompletions: ({bufferPosition, editor, prefix, scopeDescriptor}) -> 111 | property = @getPreviousPropertyName(bufferPosition, editor) 112 | values = @properties[property]?.values 113 | return null unless values? 114 | 115 | scopes = scopeDescriptor.getScopesArray() 116 | addSemicolon = not lineEndsWithSemicolon(bufferPosition, editor) 117 | 118 | completions = [] 119 | if @isPropertyValuePrefix(prefix) 120 | for value in values when firstCharsEqual(value, prefix) 121 | completions.push(@buildPropertyValueCompletion(value, property, addSemicolon)) 122 | else 123 | for value in values 124 | completions.push(@buildPropertyValueCompletion(value, property, addSemicolon)) 125 | 126 | if importantPrefix = @getImportantPrefix(editor, bufferPosition) 127 | completions.push 128 | type: 'keyword' 129 | text: '!important' 130 | displayText: '!important' 131 | replacementPrefix: importantPrefix 132 | description: "Forces this property to override any other declaration of the same property. Use with caution." 133 | descriptionMoreURL: "#{cssDocsURL}/Specificity#The_!important_exception" 134 | 135 | completions 136 | 137 | buildPropertyValueCompletion: (value, propertyName, addSemicolon) -> 138 | text = value 139 | text += ';' if addSemicolon 140 | text = makeSnippet(text) 141 | 142 | { 143 | type: 'value' 144 | snippet: text 145 | displayText: value 146 | description: "#{value} value for the #{propertyName} property" 147 | descriptionMoreURL: "#{cssDocsURL}/#{propertyName}#Values" 148 | } 149 | 150 | getPropertyNamePrefix: (bufferPosition, editor) -> 151 | line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition]) 152 | propertyNamePrefixPattern.exec(line)?[0] 153 | 154 | getPropertyNameCompletions: ({bufferPosition, editor, scopeDescriptor, activatedManually}) -> 155 | scopes = scopeDescriptor.getScopesArray() 156 | line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition]) 157 | 158 | prefix = @getPropertyNamePrefix(bufferPosition, editor) 159 | return [] unless activatedManually or prefix 160 | 161 | completions = [] 162 | for property, options of @properties when not prefix or firstCharsEqual(property, prefix) 163 | completions.push(@buildPropertyNameCompletion(property, prefix, options)) 164 | completions 165 | 166 | buildPropertyNameCompletion: (propertyName, prefix, {description}) -> 167 | type: 'property' 168 | text: "#{propertyName}: " 169 | displayText: propertyName 170 | replacementPrefix: prefix 171 | description: description 172 | descriptionMoreURL: "#{cssDocsURL}/#{propertyName}" 173 | 174 | getPseudoSelectorPrefix: (editor, bufferPosition) -> 175 | line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition]) 176 | line.match(pesudoSelectorPrefixPattern)?[0] 177 | 178 | getPseudoSelectorCompletions: ({bufferPosition, editor}) -> 179 | prefix = @getPseudoSelectorPrefix(editor, bufferPosition) 180 | return null unless prefix 181 | 182 | completions = [] 183 | for pseudoSelector, options of @pseudoSelectors when firstCharsEqual(pseudoSelector, prefix) 184 | completions.push(@buildPseudoSelectorCompletion(pseudoSelector, prefix, options)) 185 | completions 186 | 187 | buildPseudoSelectorCompletion: (pseudoSelector, prefix, {argument, description}) -> 188 | completion = 189 | type: 'pseudo-selector' 190 | replacementPrefix: prefix 191 | description: description 192 | descriptionMoreURL: "#{cssDocsURL}/#{pseudoSelector}" 193 | 194 | if argument? 195 | completion.snippet = "#{pseudoSelector}(${1:#{argument}})" 196 | else 197 | completion.text = pseudoSelector 198 | completion 199 | 200 | getTagSelectorPrefix: (editor, bufferPosition) -> 201 | line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition]) 202 | tagSelectorPrefixPattern.exec(line)?[2] 203 | 204 | getTagCompletions: ({bufferPosition, editor, prefix}) -> 205 | completions = [] 206 | if prefix 207 | for tag in @tags when firstCharsEqual(tag, prefix) 208 | completions.push(@buildTagCompletion(tag)) 209 | completions 210 | 211 | buildTagCompletion: (tag) -> 212 | type: 'tag' 213 | text: tag 214 | description: "Selector for <#{tag}> elements" 215 | 216 | lineEndsWithSemicolon = (bufferPosition, editor) -> 217 | {row} = bufferPosition 218 | line = editor.lineTextForBufferRow(row) 219 | /;\s*$/.test(line) 220 | 221 | hasScope = (scopesArray, scope) -> 222 | scopesArray.indexOf(scope) isnt -1 223 | 224 | firstCharsEqual = (str1, str2) -> 225 | str1[0].toLowerCase() is str2[0].toLowerCase() 226 | 227 | # looks at a string and replaces consecutive () with incrementing snippet positions ($n) 228 | # It also adds a trailing $n at end of text 229 | # e.g translate() becomes translate($1)$2 230 | makeSnippet = (text) -> 231 | snippetNumber = 0 232 | while text.includes('()') 233 | text = text.replace('()', "($#{++snippetNumber})") 234 | text = text + "$#{++snippetNumber}" 235 | return text 236 | -------------------------------------------------------------------------------- /src/create-ttl-grammar.js: -------------------------------------------------------------------------------- 1 | /*global atom*/ 2 | const crypto = require('crypto'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const CompositeDisposable = require('atom').CompositeDisposable; 6 | 7 | // This Class is repsonsible for creating a new Tagged Template grammar 8 | // on detection of a changed Tagged Template Configuration in the package settings 9 | module.exports = 10 | class CreateTtlGrammar { 11 | 12 | disposable = new CompositeDisposable(); 13 | configChangedTimer= null; 14 | TTL_GRAMMAR_NAME = 'language-babel-extension'; 15 | TTL_SCOPENAME = `languagebabel.ttlextension`; 16 | 17 | constructor(observeConfig = false) { 18 | if (observeConfig) { 19 | // look for changes in tagged template handlers 20 | this.disposable.add(atom.config.observe('language-babel.taggedTemplateGrammar', this.observeTtlConfig.bind(this, 10000))); 21 | } 22 | } 23 | 24 | destroy() { 25 | this.disposable.dispose(); 26 | } 27 | 28 | // add new grammars to registry 29 | addGrammars(filename) { 30 | return new Promise((resolve, reject) => { 31 | atom.grammars.loadGrammar(filename, (err) => { 32 | if (err) { 33 | reject(new Error(`Unable to add Grammar to registry\n${filename}`)); 34 | } 35 | else resolve(); 36 | }); 37 | }); 38 | 39 | } 40 | 41 | // Check if the grammar exists under this SHA256 file name 42 | // If not then remove all ttl grammars and create a new one 43 | // This returns a Promise that resolves with a ttl filename 44 | // if a new grammar was created or rejects if a problem. 45 | createGrammar({ttlFilename, ttlFilenameAbsolute, grammarText}) { 46 | return new Promise((resolve, reject) => { 47 | this.doesGrammarFileExist(ttlFilename) 48 | .then((ifFileExists) => { 49 | if (ifFileExists) { 50 | resolve(); 51 | } 52 | else { 53 | this.removeGrammars(); 54 | this.removeTtlLanguageFiles() 55 | .then(() => this.createGrammarFile(ttlFilenameAbsolute, grammarText)) 56 | .then(() => this.addGrammars(ttlFilenameAbsolute)) 57 | .then(() => { 58 | atom.notifications.addInfo('language-babel', {detail: `Grammar created at \n${ttlFilenameAbsolute}`,dismissable: true}); 59 | resolve(ttlFilename); 60 | }) 61 | .catch((err) => { 62 | atom.notifications.addWarning('language-babel', {detail: `${err.message}`,dismissable: true}); 63 | reject(err); 64 | }); 65 | } 66 | }); 67 | }); 68 | } 69 | 70 | // write the ttl grammar file for this config 71 | createGrammarFile(filename,text) { 72 | return new Promise((resolve, reject) => { 73 | fs.writeFile(filename, text, (err) => { 74 | if (err) reject(new Error(err)); 75 | else resolve(); 76 | }); 77 | }); 78 | } 79 | 80 | // create a Grammar file's JSON text 81 | createGrammarText() { 82 | return `{ 83 | "name": "${this.TTL_GRAMMAR_NAME}", 84 | "comment": "Auto generated Tag Extensions for language-babel", 85 | "comment": "Please do not edit this file directly", 86 | "scopeName": "${this.TTL_SCOPENAME}", 87 | "fileTypes": [], 88 | "patterns": [ 89 | ${this.getTtlConfig().map((ttlString) => (this.createGrammarPatterns(ttlString)))} 90 | ] 91 | }`; 92 | } 93 | 94 | // Create a grammar's pattern derived from a the tagged template string 95 | // in the form matchString:includeScope 96 | createGrammarPatterns(ttlString) { 97 | let lastColonIndex = ttlString.lastIndexOf(':'); 98 | let matchString = ttlString.substring(0, lastColonIndex); 99 | let includeScope = ttlString.substring(lastColonIndex+1); 100 | const isValidIncludeScope = /^([a-zA-Z]\w*\.?)*(\w#([a-zA-Z]\w*\.?)*)?\w$/.test(includeScope); 101 | const isQuotedMatchString = /^\".*\"$/.test(matchString); 102 | 103 | if (matchString.length < 1 || !isValidIncludeScope) { 104 | throw new Error(`Error in the Tagged Template Grammar String ${ttlString}`); 105 | } 106 | 107 | if ( isQuotedMatchString ) { 108 | // Found a possible regexp in the form "regex" so strip the " 109 | matchString = matchString.substring(1, matchString.length -1); 110 | try { 111 | this.onigurumaCheck(matchString); 112 | matchString = matchString.replace(/\\/g,"\\\\"); // \ to \\ 113 | matchString = matchString.replace(/\\\\["]/g,"\\\\\\\""); // \\" to \\ 114 | } 115 | catch (err) { 116 | throw new Error(`You entered an badly formed RegExp in the Tagged Template Grammar settings.\n${matchString}\n${err}`); 117 | } 118 | } 119 | else if ( /"/g.test(matchString)) { 120 | throw new Error(`Bad literal string in the Tagged Template Grammar settings.\n${matchString}`); 121 | } 122 | else { 123 | // User entered a literal string which may contain chars that a special inside a regex. 124 | // Escape any special chars e.g. '/** @html */' -> '\/\*\* @html \*\/' 125 | // The string stored by Atom in the config has the \\ already escaped. 126 | const escapeStringRegExp = /[|{}()[\]^$+*?.]/g; 127 | const preEscapedSlash = /\\/g; 128 | matchString = matchString.replace(preEscapedSlash, '\\\\\\\\'); 129 | matchString = matchString.replace(escapeStringRegExp, '\\\\$&'); 130 | } 131 | 132 | return `{ 133 | "contentName": "${includeScope.match(/^[^#]*/)[0]}", 134 | "begin": "\\\\s*+(${matchString})\\\\s*(\`)", 135 | "beginCaptures": { 136 | "1": { "name": "entity.name.tag.js" }, 137 | "2": { "name": "punctuation.definition.quasi.begin.js" } 138 | }, 139 | "end": "\\\\s*(?<=[^\\\\\\\\]\\\\\\\\\\\\\\\\|[^\\\\\\\\]|^\\\\\\\\\\\\\\\\|^)((\`))", 140 | "endCaptures": { 141 | "1": { "name": "punctuation.definition.quasi.end.js" } 142 | }, 143 | "patterns": [ 144 | { "include": "source.js.jsx#literal-quasi-embedded" }, 145 | { "include": "${includeScope}" } 146 | ] 147 | }`; 148 | } 149 | 150 | // checks a ttl grammar filename exists 151 | // returns a Promise that resolves to true if ttlFileName exists 152 | doesGrammarFileExist(ttlFilename) { 153 | return new Promise((resolve) => { 154 | fs.access(this.makeTtlGrammarFilenameAbsoulute(ttlFilename), (fs.constants || fs).R_OK, (err) => { 155 | err ? resolve(false): resolve(true); 156 | }); 157 | }); 158 | } 159 | 160 | // get full path to the language-babel grammar file dir 161 | getGrammarPath() { 162 | return path.normalize( 163 | path.resolve(atom.packages.loadedPackages['language-babel'].path, './grammars') 164 | ); 165 | } 166 | 167 | // get an array of all language-babel grammar files 168 | getGrammarFiles() { 169 | return new Promise((resolve,reject) => { 170 | fs.readdir(this.getGrammarPath(),(err, data) => { 171 | if (err) reject(new Error(err)); 172 | else { 173 | resolve(data); 174 | } 175 | }); 176 | }); 177 | } 178 | 179 | // read configurations for tagged templates 180 | getTtlConfig() { 181 | return atom.config.get('language-babel').taggedTemplateGrammar; 182 | } 183 | 184 | // get an array of grammar tagged template extension filenames 185 | getTtlGrammarFiles() { 186 | return this.getGrammarFiles().then(dirFiles => dirFiles.filter(function(filename) { 187 | return /^ttl-/.test(filename); 188 | })); 189 | } 190 | 191 | // generate a SHA256 for some text 192 | generateTtlSHA256(stringToHash) { 193 | let hash = crypto.createHash('sha256'); 194 | hash.update(stringToHash); 195 | return hash.digest('hex'); 196 | } 197 | 198 | // tagged template filename 199 | makeTtlGrammarFilename(hashString) { 200 | return `ttl-${hashString}.json`; 201 | } 202 | 203 | // get a fully qualified filename 204 | makeTtlGrammarFilenameAbsoulute(ttlFilename) { 205 | return path.resolve(this.getGrammarPath(), ttlFilename); 206 | } 207 | 208 | 209 | // observe changes in the taggedTemplateGrammar config which take place 210 | // because observed config changes are fired as a user types them inside 211 | // settings we need to delay processing the array strings, until last char 212 | // entered was setTimeout seconds ago. parse tagged template configuration 213 | // and then create grammar and generate a SHA256 hash from the grammar 214 | observeTtlConfig(timeout) { 215 | if (this.configChangedTimer) clearTimeout(this.configChangedTimer); 216 | this.configChangedTimer = setTimeout(() => { 217 | try { 218 | const grammarText = this.createGrammarText(); 219 | const hash = this.generateTtlSHA256(grammarText); 220 | const ttlFilename = this.makeTtlGrammarFilename(hash); 221 | const ttlFilenameAbsolute = this.makeTtlGrammarFilenameAbsoulute(ttlFilename); 222 | this.createGrammar({ttlFilename, ttlFilenameAbsolute, grammarText}); 223 | } 224 | catch(err) { 225 | atom.notifications.addWarning('language-babel', {detail: `${err.message}`,dismissable: true}); 226 | } 227 | }, timeout); 228 | } 229 | 230 | // validate a regex with a Oniguruma. This will throw if it fails the checks 231 | // This will return true if the check passes or false if no oniguruma was found 232 | onigurumaCheck(regex) { 233 | let isRegexValid = false; 234 | // We need to call oniguruma's constructor via this convoluted method as I can't include 235 | // the github/atom/node-oniguruma package as npm on Windows get node-gyp errors unless a 236 | // user has installed a compiler. Find Atom's Oniguruma and call the constructor. 237 | if (typeof atom.grammars.grammars === "object") { 238 | atom.grammars.grammars.every((obj) => { 239 | if (obj.name === "Babel ES6 JavaScript") { 240 | let ref, ref1, ref2; 241 | if ((ref = obj.firstLineRegex) != null) { 242 | if ((ref1 = ref.scanner) != null) { 243 | if ((ref2 = ref1.__proto__) != null) { 244 | if (typeof ref2.constructor === "function") { 245 | // now call new obj.firstLineRegex.scanner.__proto__.constructor([onigString]); 246 | // to validate the regex 247 | new ref2.constructor([regex]); 248 | isRegexValid = true; 249 | } 250 | } 251 | } 252 | } 253 | return false; 254 | } 255 | else return true; 256 | }); 257 | } 258 | return isRegexValid; 259 | } 260 | 261 | // Remove grammars before upodating 262 | removeGrammars() { 263 | atom.grammars.removeGrammarForScopeName(this.TTL_SCOPENAME); 264 | } 265 | 266 | // remove all language files in tagged template GrammarFiles array 267 | removeTtlLanguageFiles() { 268 | return this.getTtlGrammarFiles().then((ttlGrammarFiles) => { 269 | for (let ttlGrammarFilename of ttlGrammarFiles) { 270 | let ttlGrammarFileAbsoulte = this.makeTtlGrammarFilenameAbsoulute(ttlGrammarFilename); 271 | fs.unlink(ttlGrammarFileAbsoulte); 272 | } 273 | }); 274 | 275 | } 276 | }; 277 | -------------------------------------------------------------------------------- /spec/fixtures/grammar/css.js: -------------------------------------------------------------------------------- 1 | styled.div` 2 | 3 | div > .className + #idName 4 | /* psedo selectors */ 5 | p::after p::backdrop p::before p::first-letter p::first-line p::selection 6 | p:any-link p:before p:checked p:current p:default p:dir p:disabled p:drop 7 | p:empty p:enabled 8 | p:first p:first-child p:first-letter p:first-line p:first-of-type p:focus 9 | p:fullscreen p:hover p:in-range p:indeterminate p:invalid p:last-child 10 | p:last-of-type p:left p:link p:only-child p:only-of-type p:optional 11 | p:out-of-range p:read-only p:read-write p:required p:right p:root p:scope 12 | p:target p:unresolved p:valid p:visited 13 | 14 | /* functions */ 15 | p:lang(en) p:lang("en") 16 | p:not(html) p:has(html) p:matches(p,a) p:nth-child(1n+1) p:nth-last-child(1) p:nth-last-of-type(2n) p:nth-of-type(odd) 17 | [attr][attr=aaa][attr~="_blank" i][attr|="_blank"][attr$="_blank"][attr*="_blank"] 18 | { 19 | color: red; 20 | } 21 | 22 | border: 23 | /* numeric values */ 24 | -1, +1, -1 -0.e10 1.0001 16/9 25 | /* units */ 26 | 1turn 1rad 1grad 1deg 1kHz 1Hz 1vw 1vmin 1vmax 1vh 1rem 1q 1px 1pt 1pc 1mozmm 1mm 1in 1ex 1em 1cm 1ch 27 | /* hex */ 28 | #fff #ffffffff 29 | /* unit after interpolation close */ 30 | ${props.something?1:2}px; 31 | /* css properties */ 32 | invalid-or-unknown-name:; 33 | --custom-name:; 34 | additive-symbols: top yyyyyy; 35 | all:; 36 | animation:; 37 | animation-delay:; 38 | animation-direction:; 39 | animation-duration:; 40 | animation-fill-mode:; 41 | animation-iteration-count:; 42 | animation-name:; 43 | animation-play-state:; 44 | animation-timing-function:; 45 | appearance:; 46 | backface-visibility:; 47 | background:; 48 | background-attachment:; 49 | background-blend-mode:; 50 | background-clip:; 51 | background-color:; 52 | background-image:; 53 | background-origin:; 54 | background-position:; 55 | background-repeat:; 56 | background-size:; 57 | bleed:; 58 | block-size:; 59 | border:; 60 | border-block-end:; 61 | border-block-end-color:; 62 | border-block-end-style:; 63 | border-block-end-width:; 64 | border-block-start:; 65 | border-block-start-color:; 66 | border-block-start-style:; 67 | border-block-start-width:; 68 | border-bottom:; 69 | border-bottom-color:; 70 | border-bottom-left-radius:; 71 | border-bottom-right-radius:; 72 | border-bottom-style:; 73 | border-bottom-width:; 74 | border-collapse:; 75 | border-color:; 76 | border-image:; 77 | border-image-outset:; 78 | border-image-repeat:; 79 | border-image-slice:; 80 | border-image-source:; 81 | border-image-width:; 82 | border-inline-end:; 83 | border-inline-end-color:; 84 | border-inline-end-style:; 85 | border-inline-end-width:; 86 | border-inline-start:; 87 | border-inline-start-color:; 88 | border-inline-start-style:; 89 | border-inline-start-width:; 90 | border-left:; 91 | border-left-color:; 92 | border-left-style:; 93 | border-left-width:; 94 | border-radius:; 95 | border-right:; 96 | border-right-color:; 97 | border-right-style:; 98 | border-right-width:; 99 | border-spacing:; 100 | border-style:; 101 | border-top:; 102 | border-top-color:; 103 | border-top-left-radius:; 104 | border-top-right-radius:; 105 | border-top-style:; 106 | border-top-width:; 107 | border-width:; 108 | bottom:; 109 | box-decoration-break:; 110 | box-shadow:; 111 | box-sizing:; 112 | break-after:; 113 | break-before:; 114 | break-inside:; 115 | caption-side:; 116 | clear:; 117 | clip-path:; 118 | column-count:; 119 | column-fill:; 120 | column-gap:; 121 | column-rule:; 122 | column-rule-color:; 123 | column-rule-style:; 124 | column-rule-width:; 125 | column-span:; 126 | column-width:; 127 | columns:; 128 | content:; 129 | counter-increment:; 130 | counter-reset:; 131 | cursor:; 132 | direction:; 133 | display:; 134 | empty-cells:; 135 | fallback:; 136 | filter:; 137 | float:; 138 | font:; 139 | flex:; 140 | flex-basis:; 141 | flex-direction:; 142 | flex-flow:; 143 | flex-grow:; 144 | flex-shrink:; 145 | flex-wrap:; 146 | font-family:; 147 | font-feature-settings:; 148 | font-kerning:; 149 | font-language-override:; 150 | font-size:; 151 | font-size-adjust:; 152 | font-stretch:; 153 | font-style:; 154 | font-synthesis:; 155 | font-variant:; 156 | font-variant-alternates:; 157 | font-variant-caps:; 158 | font-variant-east-asian:; 159 | font-variant-ligatures:; 160 | font-variant-numeric:; 161 | font-variant-position:; 162 | font-weight:; 163 | grid:; 164 | grid-area:; 165 | grid-auto-columns:; 166 | grid-auto-flow:; 167 | grid-auto-rows:; 168 | grid-column:; 169 | grid-column-end:; 170 | grid-column-gap:; 171 | grid-column-start:; 172 | grid-gap:; 173 | grid-row:; 174 | grid-row-end:; 175 | grid-row-gap:; 176 | grid-row-start:; 177 | grid-template:; 178 | grid-template-areas:; 179 | grid-template-columns:; 180 | grid-template-rows:; 181 | image-orientation:; 182 | image-rendering:; 183 | image-resolution:; 184 | height:; 185 | hyphens:; 186 | inline-size:; 187 | isolation:; 188 | justify-content:; 189 | left:; 190 | letter-spacing:; 191 | line-break:; 192 | line-height:; 193 | list-style:; 194 | list-style-image:; 195 | list-style-position:; 196 | list-style-type:; 197 | margin:; 198 | margin-block-end:; 199 | margin-block-start:; 200 | margin-bottom:; 201 | margin-inline-end:; 202 | margin-inline-start:; 203 | margin-left:; 204 | margin-right:; 205 | margin-top:; 206 | marks:; 207 | mask:; 208 | mask-clip:; 209 | mask-composite:; 210 | mask-image:; 211 | mask-mode:; 212 | mask-origin:; 213 | mask-position:; 214 | mask-repeat:; 215 | mask-size:; 216 | mask-type:; 217 | max-block-size:; 218 | max-height:; 219 | max-inline-size:; 220 | max-width:; 221 | max-zoom:; 222 | min-block-size:; 223 | min-height:; 224 | min-inline-size:; 225 | min-width:; 226 | min-zoom:; 227 | mix-blend-mode:; 228 | nav-up:; 229 | nav-right:; 230 | nav-left:; 231 | nav-index:; 232 | nav-down:; 233 | negative:; 234 | object-fit:; 235 | object-position:; 236 | offset-block-end:; 237 | offset-block-start:; 238 | offset-inline-end:; 239 | offset-inline-start:; 240 | opacity:; 241 | order:; 242 | orientation:; 243 | orphans:; 244 | outline:; 245 | outline-color:; 246 | outline-offset:; 247 | outline-style:; 248 | outline-width:; 249 | overflow:; 250 | overflow-wrap:; 251 | overflow-x:; 252 | overflow-y:; 253 | pad:; 254 | padding:; 255 | padding-block-end:; 256 | padding-block-start:; 257 | padding-bottom:; 258 | padding-inline-end:; 259 | padding-inline-start:; 260 | padding-left:; 261 | padding-right:; 262 | padding-top:; 263 | page-break-after:; 264 | page-break-before:; 265 | page-break-inside:; 266 | perspective:; 267 | perspective-origin:; 268 | pointer-events:; 269 | position:; 270 | quotes:; 271 | prefix:; 272 | range:; 273 | resize:; 274 | revert:; 275 | right:; 276 | ruby-align:; 277 | ruby-merge:; 278 | ruby-position:; 279 | scroll-behavior:; 280 | scroll-snap-coordinate:; 281 | scroll-snap-destination:; 282 | scroll-snap-type:; 283 | shape-image-threshold:; 284 | shape-margin:; 285 | shape-outside:; 286 | size:; 287 | speak-as:; 288 | src:; 289 | suffix:; 290 | symbols:; 291 | system:; 292 | tab-size:; 293 | table-layout:; 294 | text-align:; 295 | text-align-last:; 296 | text-combine-upright:; 297 | text-decoration:; 298 | text-decoration-color:; 299 | text-decoration-line:; 300 | text-decoration-style:; 301 | text-emphasis:; 302 | text-emphasis-color:; 303 | text-emphasis-position:; 304 | text-emphasis-style:; 305 | text-indent:; 306 | text-justify:; 307 | text-orientation:; 308 | text-overflow:; 309 | text-rendering:; 310 | text-size-adjust:; 311 | text-shadow:; 312 | text-transform:; 313 | text-underline-position:; 314 | top:; 315 | touch-action:; 316 | transform:; 317 | transform-box:; 318 | transform-origin:; 319 | transform-style:; 320 | transition:; 321 | transition-delay:; 322 | transition-duration:; 323 | transition-property:; 324 | transition-timing-function:; 325 | unicode-bidi:; 326 | unicode-range:; 327 | user-zoom:; 328 | vertical-align:; 329 | visibility:; 330 | volume:; 331 | white-space:; 332 | widows:; 333 | width:; 334 | will-change:; 335 | word-break:; 336 | word-spacing:; 337 | word-wrap:; 338 | writing-mode:; 339 | z-index:; 340 | zoom:; 341 | 342 | color: 343 | /* css functions */ 344 | annotation() 345 | blur() 346 | attr() 347 | brightness() 348 | calc() 349 | character-variant() 350 | circle() 351 | contrast() 352 | cross-fade() 353 | cubic-bezier() 354 | drop-shadow() 355 | element() 356 | ellipse() 357 | fit-content() 358 | format() 359 | grayscale() 360 | hsl() 361 | hsla() 362 | hue-rotate() 363 | image() 364 | image-set() 365 | inset() 366 | invert() 367 | linear-gradient() 368 | local() 369 | matrix() 370 | matrix3d() 371 | minmax() 372 | opacity() 373 | ornaments() 374 | perspective() 375 | polygon() 376 | radial-gradient() 377 | rect() 378 | repeat() 379 | repeating-linear-gradient() 380 | repeating-radial-gradient() 381 | rgb() 382 | rgba() 383 | rotate() 384 | rotate3d() 385 | rotateX() 386 | rotateY() 387 | rotateZ() 388 | saturate() 389 | scale() 390 | scale3d() 391 | scaleX() 392 | scaleY() 393 | scaleZ() 394 | sepia() 395 | skew() 396 | skewX() 397 | skewY() 398 | steps() 399 | stylistic() 400 | styleset() 401 | swash() 402 | symbols() 403 | translate() 404 | translate3d() 405 | translateX() 406 | translateY() 407 | translateZ() 408 | url() 409 | var(); 410 | 411 | 412 | @media print { 413 | body { font-size: 10pt } 414 | } 415 | @media screen { 416 | body { font-size: 13px } 417 | } 418 | @media screen, print { 419 | body { line-height: 1.2 } 420 | } 421 | @media only screen 422 | and ( device-aspect-ratio: 480px) 423 | and ( max-device-width: 480px) 424 | and ( max-device-width: 480px) 425 | and (-webkit-min-device-pixel-ratio: 2) { 426 | body { line-height: 1.4 } 427 | } 428 | @font-face { 429 | font-family: MyHelvetica; 430 | src: local("Helvetica Neue Bold"), 431 | local("HelveticaNeue-Bold"), 432 | url(MgOpenModernaBold.ttf); 433 | font-weight: bold; 434 | font-family: Goudy Bookletter 1911, sans-serif; 435 | font-family: Red/Black, sans-serif; 436 | font-family: "Lucida" Grande, sans-serif; 437 | font-family: Ahem!, sans-serif; 438 | font-family: test@foo, sans-serif; 439 | font-family: #POUND, sans-serif; 440 | font-family: Hawaii 5-0, sans-serif; 441 | } 442 | @font-feature-values Font Two { 443 | @swash { 444 | color: 4; 445 | } 446 | } 447 | @charset "UTF-8"; /* Set the encoding of the style sheet to Unicode UTF-8 */ 448 | @charset 'iso-859-15'; /* Set the encoding of the style sheet to Latin-9 (Western European languages, with euro sign) */ 449 | @charset "UTF-8"; /* Invalid, there is a character (a space) before the at-rule */ 450 | @charset UTF-8; /* Invalid, without ' or ", the charset is not a CSS */ 451 | @counter-style circled-alpha { 452 | system: fixed; 453 | symbols: Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ; 454 | suffix: " "; 455 | } 456 | @import url("fineprint.css") print; 457 | @import url("bluish.css") projection, tv; 458 | @import 'custom.css'; 459 | @import url("chrome://communicator/skin/"); 460 | @import "common.css" screen, projection; 461 | @import url('landscape.css') screen and (orientation:landscape); 462 | 463 | @keyframes important1 { 464 | from { margin-top: 50px; } 465 | 50% { margin-top: 150px !important; } /* ignored */ 466 | to { margin-top: 100px; } 467 | } 468 | 469 | @keyframes important2 { 470 | from { margin-top: 50px; 471 | margin-bottom: 100px; } 472 | to { margin-top: 150px !important; /* ignored */ 473 | margin-bottom: 50px; } 474 | } 475 | /* Default namespace */ 476 | @namespace url(XML-namespace-URL); 477 | @namespace "XML-namespace-URL"; 478 | 479 | /* Prefixed namespace */ 480 | @namespace prefix url(XML-namespace-URL); 481 | @namespace prefix "XML-namespace-URL"; 482 | @page { margin: 2cm } /* All margins set to 2cm */ 483 | 484 | @page :first { 485 | margin-top: 10cm /* Top margin on first page 10cm */ 486 | } 487 | 488 | @supports ( transform-style: preserve ) or ( -moz-transform-style: preserve ) or 489 | ( -o-transform-style: preserve ) or ( -webkit-transform-style: preserve ) { 490 | margin: 1px; 491 | } 492 | @viewport { 493 | min-width: 640px; 494 | max-width: 800px; 495 | } 496 | @viewport { 497 | zoom: 0.75; 498 | min-zoom: 0.5; 499 | max-zoom: 0.9; 500 | } 501 | @viewport { 502 | orientation: landscape; 503 | } 504 | ` 505 | -------------------------------------------------------------------------------- /spec/auto-indent-spec.coffee: -------------------------------------------------------------------------------- 1 | # Tests for Auto Indenting JSX 2 | 3 | {Range, Point} = require 'atom' 4 | fs = require 'fs-plus' 5 | path = require 'path' 6 | AutoIndent = require '../lib/auto-indent' 7 | 8 | describe 'auto-indent', -> 9 | [autoIndent, editor, notifications, sourceCode, sourceCodeRange, indentJSXRange] = [] 10 | 11 | beforeEach -> 12 | waitsForPromise -> 13 | atom.packages.activatePackage('language-babel') 14 | 15 | beforeEach -> 16 | waitsForPromise -> 17 | atom.workspace.open('non-existent.js').then (o) -> editor = o 18 | 19 | runs -> 20 | autoIndent = new AutoIndent(editor) 21 | notifications = atom.notifications 22 | 23 | 24 | # :: constructor 25 | describe '::constructor', -> 26 | it ' should setup some valid indentation defaults', -> 27 | expectedResult = 28 | jsxIndent: [1,1] 29 | jsxIndentProps: [1,1] 30 | jsxClosingBracketLocation: [ 1, { selfClosing: 'tag-aligned', nonEmpty: 'tag-aligned'} ] 31 | expect(autoIndent.eslintIndentOptions).toEqual(expectedResult) 32 | 33 | # ::getEslintrcFilename 34 | describe '::getEslintrcFilename', -> 35 | it 'returns a correct project path for the source file', -> 36 | expect(path.dirname(autoIndent.getEslintrcFilename())).toEqual(path.dirname(editor.getPath())) 37 | 38 | it 'returns a .eslintrc file name', -> 39 | expect(path.basename(autoIndent.getEslintrcFilename())).toEqual('.eslintrc') 40 | 41 | # ::readEslintrcOptions 42 | describe '::readEslintrcOptions', -> 43 | it 'returns an empty object on a missing .eslintrc', -> 44 | expect(autoIndent.readEslintrcOptions('.missing')).toEqual({}) 45 | 46 | it 'returns an empty Object and a notification message on bad eslint', -> 47 | spyOn(fs, 'isFileSync').andReturn(true) 48 | spyOn(fs, 'readFileSync').andReturn('{') 49 | spyOn(notifications, 'addError').andCallThrough() 50 | obj = autoIndent.readEslintrcOptions() 51 | expect(notifications.addError).toHaveBeenCalled() 52 | expect(obj).toEqual({}) 53 | 54 | it 'returns an empty Object when attempting to read something other than a file', -> 55 | spyOn(fs, 'isFileSync').andReturn(false) 56 | spyOn(fs, 'readFileSync') 57 | spyOn(notifications, 'addError').andCallThrough() 58 | obj = autoIndent.readEslintrcOptions() 59 | expect(fs.readFileSync).not.toHaveBeenCalled() 60 | expect(notifications.addError).not.toHaveBeenCalled() 61 | expect(obj).toEqual({}) 62 | 63 | it 'returns an empty Object when eslint with no rules is read', -> 64 | spyOn(fs, 'isFileSync').andReturn(true) 65 | spyOn(fs, 'readFileSync').andReturn('{}') 66 | spyOn(notifications, 'addError').andCallThrough() 67 | obj = autoIndent.readEslintrcOptions() 68 | expect(notifications.addError).not.toHaveBeenCalled() 69 | expect(obj).toEqual({}) 70 | 71 | # ::translateIndentOptions 72 | describe '::translateIndentOptions', -> 73 | it 'should return expected defaults when no object is input', -> 74 | result = autoIndent.translateIndentOptions() 75 | expectedResult = 76 | jsxIndent: [1,1] 77 | jsxIndentProps: [1,1] 78 | jsxClosingBracketLocation: [ 1, { selfClosing: 'tag-aligned', nonEmpty: 'tag-aligned'} ] 79 | expect(result).toEqual(expectedResult) 80 | 81 | it 'should return expected defaults when no valid object is input', -> 82 | result = autoIndent.translateIndentOptions({}) 83 | expectedResult = 84 | jsxIndent: [1,1] 85 | jsxIndentProps: [1,1] 86 | jsxClosingBracketLocation: [ 1, { selfClosing: 'tag-aligned', nonEmpty: 'tag-aligned'} ] 87 | expect(result).toEqual(expectedResult) 88 | 89 | it 'should return two tab markers for jsx and props when an indent of 4 spaces is found', -> 90 | rules = 91 | "indent": [1, 4] 92 | result = autoIndent.translateIndentOptions(rules) 93 | expectedResult = 94 | jsxIndent: [1,2] 95 | jsxIndentProps: [1,2] 96 | jsxClosingBracketLocation: [ 1, { selfClosing: 'tag-aligned', nonEmpty: 'tag-aligned'} ] 97 | expect(result).toEqual(expectedResult) 98 | 99 | it 'should return one tab markers for jsx and props when an indent "tab" is found', -> 100 | rules = 101 | "indent": [1, "tab"] 102 | result = autoIndent.translateIndentOptions(rules) 103 | expectedResult = 104 | jsxIndent: [1,1] 105 | jsxIndentProps: [1,1] 106 | jsxClosingBracketLocation: [ 1, { selfClosing: 'tag-aligned', nonEmpty: 'tag-aligned'} ] 107 | expect(result).toEqual(expectedResult) 108 | 109 | it 'should return jsxIndent of 2 tabs and jsxIndentProps of 3', -> 110 | rules = 111 | "indent": [1, 6] 112 | "react/jsx-indent": ["warn", 4] 113 | result = autoIndent.translateIndentOptions(rules) 114 | expectedResult = 115 | jsxIndent: ['warn', 2] 116 | jsxIndentProps: [1, 3] 117 | jsxClosingBracketLocation: [ 1, { selfClosing: 'tag-aligned', nonEmpty: 'tag-aligned'} ] 118 | expect(result).toEqual(expectedResult) 119 | 120 | it 'should return jsxIndent of 2 tabs and jsxIndentProps of 2', -> 121 | rules = 122 | "indent": [1, 6] 123 | "react/jsx-indent": ["warn", 4] 124 | "react/jsx-indent-props": [2, 4] 125 | result = autoIndent.translateIndentOptions(rules) 126 | expectedResult = 127 | jsxIndent: ['warn', 2] 128 | jsxIndentProps: [2, 2] 129 | jsxClosingBracketLocation: [ 1, { selfClosing: 'tag-aligned', nonEmpty: 'tag-aligned'} ] 130 | expect(result).toEqual(expectedResult) 131 | 132 | it 'should return jsxIndent of 2 tabs and jsxIndentProps of 2, line-aligned', -> 133 | rules = 134 | "indent": [1, 6] 135 | "react/jsx-indent": ["warn", 4] 136 | "react/jsx-indent-props": [2, 4] 137 | 'react/jsx-closing-bracket-location': [1, 'line-aligned'] 138 | result = autoIndent.translateIndentOptions(rules) 139 | expectedResult = 140 | jsxIndent: ['warn', 2] 141 | jsxIndentProps: [2, 2] 142 | jsxClosingBracketLocation: [ 1, { selfClosing: 'line-aligned', nonEmpty: 'line-aligned'} ] 143 | expect(result).toEqual(expectedResult) 144 | 145 | it 'should return jsxIndent of 2 tabs and jsxIndentProps of 2, line-aligned and props-aligned', -> 146 | rules = 147 | "indent": [1, 6] 148 | "react/jsx-indent": ["warn", 4] 149 | "react/jsx-indent-props": [2, 4] 150 | "react/jsx-closing-bracket-location": [ 1, 151 | "nonEmpty": "props-aligned", 152 | "selfClosing": "line-aligned" 153 | ] 154 | result = autoIndent.translateIndentOptions(rules) 155 | expectedResult = 156 | jsxIndent: ['warn', 2] 157 | jsxIndentProps: [2, 2] 158 | jsxClosingBracketLocation: [ 1, { selfClosing: 'line-aligned', nonEmpty: 'props-aligned'} ] 159 | expect(result).toEqual(expectedResult) 160 | 161 | #: indentJSX 162 | describe '::indentJSX', -> 163 | 164 | beforeEach -> 165 | sourceCode = """ 166 |
167 | {this._renderPlaceholder()} 168 |
173 |
179 | {this._renderPlaceholder()} 180 | 183 |
184 | { // tests inline JSX 185 | trainerProfile.backgroundImageLink 186 | ? 187 | : 188 | } 189 | { 190 | cond ? 191 | : 192 | 193 | } 194 |
195 |
196 | 197 | """ 198 | editor.insertText(sourceCode) 199 | sourceCodeRange = new Range(new Point(0,0), new Point(31,0)) 200 | indentJSXRange = new Range(new Point(0,0), new Point(30,1)) 201 | 202 | it 'should indent JSX according to eslint rules', -> 203 | indentedCode = """ 204 |
205 | {this._renderPlaceholder()} 206 |
211 |
217 | {this._renderPlaceholder()} 218 | 221 |
222 | { // tests inline JSX 223 | trainerProfile.backgroundImageLink 224 | ? 225 | : 226 | } 227 | { 228 | cond ? 229 | : 230 | 231 | } 232 |
233 |
234 | 235 | """ 236 | # remember this is tabs based on atom default 237 | autoIndent.eslintIndentOptions = 238 | jsxIndent: [1, 1] 239 | jsxIndentProps: [1, 1] 240 | jsxClosingBracketLocation: [ 1, 241 | selfClosing: 'tag-aligned' 242 | nonEmpty: 'tag-aligned' ] 243 | autoIndent.autoJsx = true 244 | autoIndent.indentJSX(indentJSXRange) 245 | expect(editor.getTextInBufferRange(sourceCodeRange)).toEqual(indentedCode) 246 | 247 | it 'should indent JSX according to eslint rules and tag closing alignment', -> 248 | indentedCode = """ 249 |
250 | {this._renderPlaceholder()} 251 |
256 |
262 | {this._renderPlaceholder()} 263 | 266 |
267 | { // tests inline JSX 268 | trainerProfile.backgroundImageLink 269 | ? 270 | : 271 | } 272 | { 273 | cond ? 274 | : 275 | 276 | } 277 |
278 |
279 | 280 | """ 281 | # remember this is tabs based on atom default 282 | autoIndent.eslintIndentOptions = 283 | jsxIndent: [1, 2] 284 | jsxIndentProps: [1, 2] 285 | jsxClosingBracketLocation: [ 1, 286 | selfClosing: 'props-aligned' 287 | nonEmpty: 'props-aligned' ] 288 | autoIndent.autoJsx = true 289 | autoIndent.indentJSX(indentJSXRange) 290 | expect(editor.getTextInBufferRange(sourceCodeRange)).toEqual(indentedCode) 291 | 292 | # test insert newline between opening closing JSX tags 293 | describe 'insert-nl-jsx', -> 294 | 295 | it 'should insert two new lines and position cursor between JSX tags', -> 296 | # remember this is tabs based on atom default 297 | autoIndent.eslintIndentOptions = 298 | jsxIndent: [1, 1] 299 | jsxIndentProps: [1, 1] 300 | jsxClosingBracketLocation: [ 1, 301 | selfClosing: 'tabs-aligned' 302 | nonEmpty: 'tabs-aligned' ] 303 | autoIndent.autoJsx = true 304 | editor.insertText('
') 305 | editor.setCursorBufferPosition([0,5]) 306 | editor.insertText('\n') 307 | 308 | expect(editor.getTextInBufferRange([[0,0],[0,5]])).toEqual("
") 309 | expect(editor.getTextInBufferRange([[1,0],[1,2]])).toEqual(" ") 310 | expect(editor.getTextInBufferRange([[2,0],[2,6]])).toEqual("
") 311 | expect(editor.getCursorBufferPosition()).toEqual([1,2]) 312 | -------------------------------------------------------------------------------- /spec/fixtures/grammar/private-fields.js: -------------------------------------------------------------------------------- 1 | // SYNTAX TEST "source.js.jsx" 2 | class Point { 3 | // <- meta.class.js storage.type.class.js 4 | // <- meta.class.js storage.type.class.js 5 | //^^^ meta.class.js 6 | //^^^ storage.type.class.js 7 | // ^^^^^ entity.name.class.js 8 | // ^ punctuation.section.class.begin.js 9 | #x 10 | //^^ meta.class.body.js 11 | //^ keyword.operator.private.js 12 | // ^ variable.other.readwrite.js 13 | #y 14 | //^^ meta.class.body.js 15 | //^ keyword.operator.private.js 16 | // ^ variable.other.readwrite.js 17 | #x = 0,#y = 0 18 | //^^ ^ ^^^^ ^ ^ meta.class.body.js 19 | //^ ^ keyword.operator.private.js 20 | // ^ ^ variable.other.readwrite.js 21 | // ^ ^ keyword.operator.assignment.js 22 | // ^ ^ constant.numeric.js 23 | // ^ meta.delimiter.comma.js 24 | static x = 1, #y, [a] 25 | //^^^^^^ ^ ^ ^^ ^^^ ^^^ meta.class.body.js 26 | //^^^^^^ storage.modifier.js 27 | // ^ ^ ^ variable.other.readwrite.js 28 | // ^ keyword.operator.assignment.js 29 | // ^ constant.numeric.js 30 | // ^ ^ meta.delimiter.comma.js 31 | // ^ keyword.operator.private.js 32 | // ^ ^ meta.brace.square.js 33 | z, #w = 2, [b] 34 | //^^ ^^ ^ ^^ ^^^ meta.class.body.js 35 | //^ ^ ^ variable.other.readwrite.js 36 | // ^ ^ meta.delimiter.comma.js 37 | // ^ keyword.operator.private.js 38 | // ^ keyword.operator.assignment.js 39 | // ^ constant.numeric.js 40 | // ^ ^ meta.brace.square.js 41 | get #x() { return #xValue } 42 | //^^^ ^^^^ ^ ^^^^^^ ^^^^^^^ ^ meta.class.body.js 43 | //^^^ ^^^^ ^ ^^^^^^ ^^^^^^^ ^ meta.accessor.js 44 | //^^^ storage.type.accessor.js 45 | // ^ ^ keyword.operator.private.js 46 | // ^ entity.name.function.accessor.js 47 | // ^ punctuation.definition.parameters.begin.js 48 | // ^^ meta.brace.round.js 49 | // ^ punctuation.definition.parameters.end.js 50 | // ^ ^ meta.brace.curly.js 51 | // ^^^^^^ keyword.control.flow.js 52 | // ^^^^^^ variable.other.readwrite.js 53 | set #x(value) { 54 | //^^^ ^^^^^^^^^ ^ meta.class.body.js 55 | //^^^ ^^^^^^^^^ ^ meta.accessor.js 56 | //^^^ storage.type.accessor.js 57 | // ^ keyword.operator.private.js 58 | // ^ entity.name.function.accessor.js 59 | // ^ punctuation.definition.parameters.begin.js 60 | // ^ ^ meta.brace.round.js 61 | // ^^^^^ meta.function.parameters.js 62 | // ^^^^^ variable.other.readwrite.js 63 | // ^ punctuation.definition.parameters.end.js 64 | // ^ meta.brace.curly.js 65 | this.#xValue = value 66 | // ^^^^^^^^^^^^ ^ ^^^^^ meta.class.body.js 67 | // ^^^^^^^^^^^^ ^ ^^^^^ meta.accessor.js 68 | // ^^^^ variable.language.this.js 69 | // ^ keyword.operator.accessor.js 70 | // ^^^^^^^ meta.property.object.js 71 | // ^ keyword.operator.private.js 72 | // ^^^^^^ variable.other.property.js 73 | // ^ keyword.operator.assignment.js 74 | // ^^^^^ variable.other.readwrite.js 75 | window.requestAnimationFrame(this.#render.bind(this)) 76 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.class.body.js 77 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.accessor.js 78 | // ^^^^^^ support.type.object.dom.js 79 | // ^ ^ ^ keyword.operator.accessor.js 80 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.method-call.with-arguments.js 81 | // ^^^^^^^^^^^^^^^^^^^^^ ^^^^ entity.name.function.js 82 | // ^ ^ ^^ meta.brace.round.js 83 | // ^^^^ ^^^^ variable.language.this.js 84 | // ^^^^^^^ meta.property.object.js 85 | // ^ keyword.operator.private.js 86 | // ^^^^^^ variable.other.property.js 87 | } 88 | //^ meta.class.body.js 89 | //^ meta.accessor.js 90 | //^ meta.brace.curly.js 91 | #clicked() { 92 | //^^^^^^^^^^ ^ meta.class.body.js 93 | //^^^^^^^^^^ ^ meta.function.method.js 94 | //^ keyword.operator.private.js 95 | // ^^^^^^^ entity.name.function.method.js 96 | // ^ punctuation.definition.parameters.begin.js 97 | // ^^ meta.brace.round.js 98 | // ^ punctuation.definition.parameters.end.js 99 | // ^ meta.brace.curly.js 100 | this.#x++ 101 | // ^^^^^^^^^ meta.class.body.js 102 | // ^^^^^^^^^ meta.function.method.js 103 | // ^^^^ variable.language.this.js 104 | // ^ keyword.operator.accessor.js 105 | // ^^ meta.property.object.js 106 | // ^ keyword.operator.private.js 107 | // ^ variable.other.property.js 108 | // ^^ keyword.operator.arithmetic.js 109 | } 110 | //^ meta.class.body.js 111 | //^ meta.function.method.js 112 | //^ meta.brace.curly.js 113 | constructor() { 114 | //^^^^^^^^^^^^^ ^ meta.class.body.js 115 | //^^^^^^^^^^^^^ ^ meta.function.method.js 116 | //^^^^^^^^^^^ entity.name.function.method.js 117 | // ^ punctuation.definition.parameters.begin.js 118 | // ^^ meta.brace.round.js 119 | // ^ punctuation.definition.parameters.end.js 120 | // ^ meta.brace.curly.js 121 | super() 122 | // ^^^^^^^ meta.class.body.js 123 | // ^^^^^^^ meta.function.method.js 124 | // ^^^^^^^ meta.function-call.without-arguments.js 125 | // ^^^^^ entity.name.function.js 126 | // ^^ meta.brace.round.js 127 | this.onclick = this.#clicked.bind(this) 128 | // ^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^ meta.class.body.js 129 | // ^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^ meta.function.method.js 130 | // ^^^^ ^^^^ ^^^^ variable.language.this.js 131 | // ^ ^ ^ keyword.operator.accessor.js 132 | // ^^^^^^^ ^^^^^^^^ meta.property.object.js 133 | // ^^^^^^^ ^^^^^^^ variable.other.property.js 134 | // ^ keyword.operator.assignment.js 135 | // ^ keyword.operator.private.js 136 | // ^^^^^^^^^^ meta.method-call.with-arguments.js 137 | // ^^^^ entity.name.function.js 138 | // ^ ^ meta.brace.round.js 139 | #x = +x 140 | // ^^ ^ ^^ meta.class.body.js 141 | // ^^ ^ ^^ meta.function.method.js 142 | // ^ keyword.operator.private.js 143 | // ^ ^ variable.other.readwrite.js 144 | // ^ keyword.operator.assignment.js 145 | // ^ keyword.operator.arithmetic.js 146 | #y = +y 147 | // ^^ ^ ^^ meta.class.body.js 148 | // ^^ ^ ^^ meta.function.method.js 149 | // ^ keyword.operator.private.js 150 | // ^ ^ variable.other.readwrite.js 151 | // ^ keyword.operator.assignment.js 152 | // ^ keyword.operator.arithmetic.js 153 | } 154 | //^ meta.class.body.js 155 | //^ meta.function.method.js 156 | //^ meta.brace.curly.js 157 | connectedCallback() { this.#render() } 158 | //^^^^^^^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^ ^ meta.class.body.js 159 | //^^^^^^^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^ ^ meta.function.method.js 160 | //^^^^^^^^^^^^^^^^^ entity.name.function.method.js 161 | // ^ punctuation.definition.parameters.begin.js 162 | // ^^ ^^ meta.brace.round.js 163 | // ^ punctuation.definition.parameters.end.js 164 | // ^ ^ meta.brace.curly.js 165 | // ^^^^ variable.language.this.js 166 | // ^ keyword.operator.accessor.js 167 | // ^^^^^^^^^ meta.method-call.without-arguments.js 168 | // ^ keyword.operator.private.js 169 | // ^^^^^^ entity.name.function.js 170 | #render() { 171 | //^^^^^^^^^ ^ meta.class.body.js 172 | //^^^^^^^^^ ^ meta.function.method.js 173 | //^ keyword.operator.private.js 174 | // ^^^^^^ entity.name.function.method.js 175 | // ^ punctuation.definition.parameters.begin.js 176 | // ^^ meta.brace.round.js 177 | // ^ punctuation.definition.parameters.end.js 178 | // ^ meta.brace.curly.js 179 | this.textContent = this.#x.toString() 180 | // ^^^^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^ meta.class.body.js 181 | // ^^^^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^ meta.function.method.js 182 | // ^^^^ ^^^^ variable.language.this.js 183 | // ^ ^ ^ keyword.operator.accessor.js 184 | // ^^^^^^^^^^^ ^^ meta.property.object.js 185 | // ^^^^^^^^^^^ ^ variable.other.property.js 186 | // ^ keyword.operator.assignment.js 187 | // ^ keyword.operator.private.js 188 | // ^^^^^^^^^^ meta.method-call.without-arguments.js 189 | // ^^^^^^^^ entity.name.function.js 190 | // ^^ meta.brace.round.js 191 | } 192 | //^ meta.class.body.js 193 | //^ meta.function.method.js 194 | //^ meta.brace.curly.js 195 | get x() { return #x } 196 | //^^^ ^^^ ^ ^^^^^^ ^^ ^ meta.class.body.js 197 | //^^^ ^^^ ^ ^^^^^^ ^^ ^ meta.accessor.js 198 | //^^^ storage.type.accessor.js 199 | // ^ entity.name.function.accessor.js 200 | // ^ punctuation.definition.parameters.begin.js 201 | // ^^ meta.brace.round.js 202 | // ^ punctuation.definition.parameters.end.js 203 | // ^ ^ meta.brace.curly.js 204 | // ^^^^^^ keyword.control.flow.js 205 | // ^ keyword.operator.private.js 206 | // ^ variable.other.readwrite.js 207 | set x(value) { #x = +value } 208 | //^^^ ^^^^^^^^ ^ ^^ ^ ^^^^^^ ^ meta.class.body.js 209 | //^^^ ^^^^^^^^ ^ ^^ ^ ^^^^^^ ^ meta.accessor.js 210 | //^^^ storage.type.accessor.js 211 | // ^ entity.name.function.accessor.js 212 | // ^ punctuation.definition.parameters.begin.js 213 | // ^ ^ meta.brace.round.js 214 | // ^^^^^ meta.function.parameters.js 215 | // ^^^^^ ^ ^^^^^ variable.other.readwrite.js 216 | // ^ punctuation.definition.parameters.end.js 217 | // ^ ^ meta.brace.curly.js 218 | // ^ keyword.operator.private.js 219 | // ^ keyword.operator.assignment.js 220 | // ^ keyword.operator.arithmetic.js 221 | get y() { return #y } 222 | //^^^ ^^^ ^ ^^^^^^ ^^ ^ meta.class.body.js 223 | //^^^ ^^^ ^ ^^^^^^ ^^ ^ meta.accessor.js 224 | //^^^ storage.type.accessor.js 225 | // ^ entity.name.function.accessor.js 226 | // ^ punctuation.definition.parameters.begin.js 227 | // ^^ meta.brace.round.js 228 | // ^ punctuation.definition.parameters.end.js 229 | // ^ ^ meta.brace.curly.js 230 | // ^^^^^^ keyword.control.flow.js 231 | // ^ keyword.operator.private.js 232 | // ^ variable.other.readwrite.js 233 | set y(value) { #y = +value } 234 | //^^^ ^^^^^^^^ ^ ^^ ^ ^^^^^^ ^ meta.class.body.js 235 | //^^^ ^^^^^^^^ ^ ^^ ^ ^^^^^^ ^ meta.accessor.js 236 | //^^^ storage.type.accessor.js 237 | // ^ entity.name.function.accessor.js 238 | // ^ punctuation.definition.parameters.begin.js 239 | // ^ ^ meta.brace.round.js 240 | // ^^^^^ meta.function.parameters.js 241 | // ^^^^^ ^ ^^^^^ variable.other.readwrite.js 242 | // ^ punctuation.definition.parameters.end.js 243 | // ^ ^ meta.brace.curly.js 244 | // ^ keyword.operator.private.js 245 | // ^ keyword.operator.assignment.js 246 | // ^ keyword.operator.arithmetic.js 247 | equals(p) { return #x === p.#x && #y === p.#y } 248 | //^^^^^^^^^ ^ ^^^^^^ ^^ ^^^ ^^^^ ^^ ^^ ^^^ ^^^^ ^ meta.class.body.js 249 | //^^^^^^^^^ ^ ^^^^^^ ^^ ^^^ ^^^^ ^^ ^^ ^^^ ^^^^ ^ meta.function.method.js 250 | //^^^^^^ entity.name.function.method.js 251 | // ^ punctuation.definition.parameters.begin.js 252 | // ^ ^ meta.brace.round.js 253 | // ^ meta.function.parameters.js 254 | // ^ ^ ^ variable.other.readwrite.js 255 | // ^ punctuation.definition.parameters.end.js 256 | // ^ ^ meta.brace.curly.js 257 | // ^^^^^^ keyword.control.flow.js 258 | // ^ ^ ^ ^ keyword.operator.private.js 259 | // ^^^ ^^^ keyword.operator.comparison.js 260 | // ^ ^ variable.other.object.js 261 | // ^ ^ keyword.operator.accessor.js 262 | // ^^ ^^ meta.property.object.js 263 | // ^ ^ variable.other.property.js 264 | // ^^ keyword.operator.logical.js 265 | toString() { return `Point<${ #x },${ #y }>` } 266 | //^^^^^^^^^^ ^ ^^^^^^ ^^^^^^^^^ ^^ ^^^^ ^^ ^^^ ^ meta.class.body.js 267 | //^^^^^^^^^^ ^ ^^^^^^ ^^^^^^^^^ ^^ ^^^^ ^^ ^^^ ^ meta.function.method.js 268 | //^^^^^^^^ entity.name.function.method.js 269 | // ^ punctuation.definition.parameters.begin.js 270 | // ^^ meta.brace.round.js 271 | // ^ punctuation.definition.parameters.end.js 272 | // ^ ^ meta.brace.curly.js 273 | // ^^^^^^ keyword.control.flow.js 274 | // ^^^^^^^^^ ^^ ^^^^ ^^ ^^^ string.quasi.js 275 | // ^^^^^^^^^ ^^ ^^^^ ^^ ^^^ string.quoted.template.js 276 | // ^ punctuation.definition.quasi.begin.js 277 | // ^^ ^^ ^ ^^ ^^ ^ entity.quasi.element.js 278 | // ^^ ^^ punctuation.quasi.element.begin.js 279 | // ^ ^ keyword.operator.private.js 280 | // ^ ^ variable.other.readwrite.js 281 | // ^ ^ punctuation.quasi.element.end.js 282 | // ^ punctuation.definition.quasi.end.js 283 | } 284 | // <- punctuation.section.class.end.js 285 | 286 | // >> only:(source.js.jsx) 287 | -------------------------------------------------------------------------------- /lib/completions-jsx.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | 3 | events: [ 4 | { name: 'onCopy' } 5 | { name: 'onCut' } 6 | { name: 'onPaste' } 7 | { name: 'onCompositionEnd' } 8 | { name: 'onCompositionStart' } 9 | { name: 'onCompositionUpdate' } 10 | { name: 'onKeyDown' } 11 | { name: 'onKeyPress' } 12 | { name: 'onKeyUp' } 13 | { name: 'onFocus' } 14 | { name: 'onBlur' } 15 | { name: 'onChange' } 16 | { name: 'onInput' } 17 | { name: 'onSubmit' } 18 | { name: 'onClick' } 19 | { name: 'onContextMenu' } 20 | { name: 'onDoubleClick' } 21 | { name: 'onDrag' } 22 | { name: 'onDragEnd' } 23 | { name: 'onDragEnter' } 24 | { name: 'onDragExit' } 25 | { name: 'onDragLeave' } 26 | { name: 'onDragOver' } 27 | { name: 'onDragStart' } 28 | { name: 'onDrop' } 29 | { name: 'onMouseDown' } 30 | { name: 'onMouseEnter' } 31 | { name: 'onMouseLeave' } 32 | { name: 'onMouseMove' } 33 | { name: 'onMouseOut' } 34 | { name: 'onMouseOver' } 35 | { name: 'onMouseUp' } 36 | { name: 'onSelect' } 37 | { name: 'onTouchCancel' } 38 | { name: 'onTouchEnd' } 39 | { name: 'onTouchMove' } 40 | { name: 'onTouchStart' } 41 | { name: 'onScroll' } 42 | { name: 'onWheel' } 43 | { name: 'onAbort' } 44 | { name: 'onCanPlay' } 45 | { name: 'onCanPlayThrough' } 46 | { name: 'onDurationChange' } 47 | { name: 'onEmptied' } 48 | { name: 'onEncrypted' } 49 | { name: 'onEnded' } 50 | { name: 'onError' } 51 | { name: 'onLoadedData' } 52 | { name: 'onLoadedMetadata' } 53 | { name: 'onLoadStart' } 54 | { name: 'onPause' } 55 | { name: 'onPlay' } 56 | { name: 'onPlaying' } 57 | { name: 'onProgress' } 58 | { name: 'onRateChange' } 59 | { name: 'onSeeked' } 60 | { name: 'onSeeking' } 61 | { name: 'onStalled' } 62 | { name: 'onSuspend' } 63 | { name: 'onTimeUpdate' } 64 | { name: 'onVolumeChange' } 65 | { name: 'onWaiting' } 66 | ] 67 | 68 | globalAttributes: [ 69 | { name: 'className'} 70 | { name: 'class'} 71 | { name: 'id'} 72 | { name: 'itemProp'} 73 | { name: 'itemScope'} 74 | { name: 'itemType'} 75 | { name: 'itemID'} 76 | { name: 'dangerouslySetInnerHTML'} 77 | { name: 'data-'} 78 | { name: 'aria-'} 79 | { name: 'style'} 80 | { name: 'accessKey'} 81 | { name: 'contentEditable'} 82 | { name: 'contextMenu'} 83 | { name: 'dir'} 84 | { name: 'draggable'} 85 | { name: 'hidden'} 86 | { name: 'lang'} 87 | { name: 'spellCheck'} 88 | { name: 'tabIndex'} 89 | { name: 'title'} 90 | ] 91 | 92 | htmlElements: [ 93 | { name: 'a' 94 | attributes: [ 95 | { name: 'href'} 96 | { name: 'target'} 97 | { name: 'download'} 98 | { name: 'rel'} 99 | { name: 'hrefLang'} 100 | { name: 'type'} 101 | ]} 102 | { name: 'abbr' 103 | attributes: []} 104 | { name: 'address' 105 | attributes: []} 106 | { name: 'area' 107 | attributes: [ 108 | { name: 'alt'} 109 | { name: 'coords'} 110 | { name: 'href'} 111 | { name: 'hrefLang'} 112 | { name: 'media'} 113 | { name: 'rel'} 114 | { name: 'shape'} 115 | { name: 'target'} 116 | { name: 'type'} 117 | ]} 118 | { name: 'article' 119 | attributes: []} 120 | { name: 'aside' 121 | attributes: []} 122 | { name: 'audio' 123 | attributes: [ 124 | { name: 'autoPlay'} 125 | { name: 'controls'} 126 | { name: 'crossOrigin'} 127 | { name: 'loop'} 128 | { name: 'mediaGroup'} 129 | { name: 'muted'} 130 | { name: 'preload'} 131 | { name: 'src'} 132 | ]} 133 | { name: 'b' 134 | attributes: []} 135 | { name: 'base' 136 | attributes: [ 137 | { name: 'href'} 138 | { name: 'target'} 139 | ]} 140 | { name: 'bdi' 141 | attributes: []} 142 | { name: 'bdo' 143 | attributes: []} 144 | { name: 'big' 145 | attributes: []} 146 | { name: 'blockquote' 147 | attributes: []} 148 | { name: 'body' 149 | attributes: []} 150 | { name: 'br' 151 | attributes: []} 152 | { name: 'button' 153 | attributes: [ 154 | { name: 'autoFocus'} 155 | { name: 'disabled'} 156 | { name: 'form'} 157 | { name: 'formAction'} 158 | { name: 'formEncType'} 159 | { name: 'formMethod'} 160 | { name: 'formNoValidate'} 161 | { name: 'formTarget'} 162 | { name: 'name'} 163 | { name: 'type'} 164 | { name: 'value'} 165 | ]} 166 | { name: 'canvas' 167 | attributes: [ 168 | { name: 'height'} 169 | { name: 'width'} 170 | ]} 171 | { name: 'caption' 172 | attributes: []} 173 | { name: 'cite' 174 | attributes: []} 175 | { name: 'code' 176 | attributes: []} 177 | { name: 'col' 178 | attributes: [ 179 | { name: 'span'} 180 | ]} 181 | { name: 'colgroup' 182 | attributes: [ 183 | { name: 'span'} 184 | ]} 185 | { name: 'data' 186 | attributes: []} 187 | { name: 'datalist' 188 | attributes: []} 189 | { name: 'dd' 190 | attributes: []} 191 | { name: 'del' 192 | attributes: [ 193 | { name: 'dateTime'} 194 | ]} 195 | { name: 'details' 196 | attributes: [ 197 | { name: 'open'} 198 | ]} 199 | { name: 'dfn' 200 | attributes: [ 201 | { name: 'open'} 202 | ]} 203 | { name: 'dialog' 204 | attributes: []} 205 | { name: 'div' 206 | attributes: []} 207 | { name: 'dl' 208 | attributes: []} 209 | { name: 'dt' 210 | attributes: []} 211 | { name: 'em' 212 | attributes: []} 213 | { name: 'embed' 214 | attributes: [ 215 | { name: 'height'} 216 | { name: 'src'} 217 | { name: 'type'} 218 | { name: 'width'} 219 | ]} 220 | { name: 'fieldset' 221 | attributes: [ 222 | { name: 'disabled'} 223 | { name: 'form'} 224 | { name: 'name'} 225 | ]} 226 | { name: 'figcaption' 227 | attributes: []} 228 | { name: 'figure' 229 | attributes: []} 230 | { name: 'footer' 231 | attributes: []} 232 | { name: 'form' 233 | attributes: [ 234 | { name: 'acceptCharset'} 235 | { name: 'action'} 236 | { name: 'autoComplete'} 237 | { name: 'encType'} 238 | { name: 'method'} 239 | { name: 'name'} 240 | { name: 'noValidate'} 241 | { name: 'target'} 242 | ]} 243 | { name: 'h1' 244 | attributes: []} 245 | { name: 'h2' 246 | attributes: []} 247 | { name: 'h3' 248 | attributes: []} 249 | { name: 'h4' 250 | attributes: []} 251 | { name: 'h5' 252 | attributes: []} 253 | { name: 'h6' 254 | attributes: []} 255 | { name: 'head' 256 | attributes: []} 257 | { name: 'header' 258 | attributes: []} 259 | { name: 'hr' 260 | attributes: []} 261 | { name: 'html' 262 | attributes: [ 263 | { name: 'manifest'} 264 | { name: 'lang'} 265 | ]} 266 | { name: 'i' 267 | attributes: []} 268 | { name: 'iframe' 269 | attributes: [ 270 | { name: 'height'} 271 | { name: 'name'} 272 | { name: 'sandbox'} 273 | { name: 'seamless'} 274 | { name: 'src'} 275 | { name: 'srcDoc'} 276 | { name: 'width'} 277 | ]} 278 | { name: 'img' 279 | attributes: [ 280 | { name: 'alt'} 281 | { name: 'height'} 282 | { name: 'src'} 283 | { name: 'usemap'} 284 | { name: 'width'} 285 | ]} 286 | { name: 'input' 287 | attributes: [ 288 | { name: 'accept'} 289 | { name: 'alt'} 290 | { name: 'autoComplete'} 291 | { name: 'autoFocus'} 292 | { name: 'checked'} 293 | { name: 'disabled'} 294 | { name: 'form'} 295 | { name: 'formAction'} 296 | { name: 'formEncType'} 297 | { name: 'formMethod'} 298 | { name: 'formNoValidate'} 299 | { name: 'formTarget'} 300 | { name: 'height'} 301 | { name: 'list'} 302 | { name: 'max'} 303 | { name: 'maxLength'} 304 | { name: 'min'} 305 | { name: 'multiple'} 306 | { name: 'name'} 307 | { name: 'pattern'} 308 | { name: 'placeholder'} 309 | { name: 'readOnly'} 310 | { name: 'required'} 311 | { name: 'size'} 312 | { name: 'src'} 313 | { name: 'step'} 314 | { name: 'type'} 315 | { name: 'value'} 316 | { name: 'width'} 317 | ]} 318 | { name: 'ins' 319 | attributes: [ 320 | { name: 'dateTime'} 321 | ]} 322 | { name: 'kbd' 323 | attributes: []} 324 | { name: 'keygen' 325 | attributes: [ 326 | { name: 'autoFocus'} 327 | { name: 'challenge'} 328 | { name: 'disabled'} 329 | { name: 'form'} 330 | { name: 'keyType'} 331 | { name: 'name'} 332 | ]} 333 | { name: 'label' 334 | attributes: [ 335 | { name: 'htmlFor'} 336 | { name: 'form'} 337 | ]} 338 | { name: 'legend' 339 | attributes: [ 340 | { name: 'value'} 341 | ]} 342 | { name: 'li' 343 | attributes: []} 344 | { name: 'link' 345 | attributes: [ 346 | { name: 'disabled'} 347 | { name: 'href'} 348 | { name: 'hrefLang'} 349 | { name: 'media'} 350 | { name: 'rel'} 351 | { name: 'sizes'} 352 | { name: 'type'} 353 | ]} 354 | { name: 'main' 355 | attributes: []} 356 | { name: 'map' 357 | attributes: [ 358 | { name: 'name'} 359 | ]} 360 | { name: 'mark' 361 | attributes: []} 362 | { name: 'menu' 363 | attributes: [ 364 | { name: 'label'} 365 | { name: 'type'} 366 | ]} 367 | { name: 'menuitem' 368 | attributes: []} 369 | { name: 'meta' 370 | attributes: [ 371 | { name: 'charset'} 372 | { name: 'content'} 373 | { name: 'httpEquiv'} 374 | { name: 'name'} 375 | ]} 376 | { name: 'meter' 377 | attributes: []} 378 | { name: 'nav' 379 | attributes: []} 380 | { name: 'noscript' 381 | attributes: []} 382 | { name: 'object' 383 | attributes: [ 384 | { name: 'data'} 385 | { name: 'form'} 386 | { name: 'height'} 387 | { name: 'name'} 388 | { name: 'type'} 389 | { name: 'usemap'} 390 | { name: 'width'} 391 | ]} 392 | { name: 'ol' 393 | attributes: [ 394 | { name: 'start'} 395 | { name: 'type'} 396 | ]} 397 | { name: 'optgroup' 398 | attributes: [ 399 | { name: 'disabled'} 400 | { name: 'label'} 401 | ]} 402 | { name: 'option' 403 | attributes: [ 404 | { name: 'disabled'} 405 | { name: 'label'} 406 | { name: 'selected'} 407 | { name: 'value'} 408 | ]} 409 | { name: 'output' 410 | attributes: [ 411 | { name: 'htmlFor'} 412 | { name: 'form'} 413 | { name: 'name'} 414 | ]} 415 | { name: 'p' 416 | attributes: []} 417 | { name: 'param' 418 | attributes: [ 419 | { name: 'name'} 420 | { name: 'value'} 421 | ]} 422 | { name: 'picture' 423 | attributes: []} 424 | { name: 'pre' 425 | attributes: []} 426 | { name: 'progress' 427 | attributes: [ 428 | { name: 'form'} 429 | { name: 'max'} 430 | { name: 'value'} 431 | ]} 432 | { name: 'q' 433 | attributes: []} 434 | { name: 'rp' 435 | attributes: []} 436 | { name: 'rt' 437 | attributes: []} 438 | { name: 'ruby' 439 | attributes: []} 440 | { name: 's' 441 | attributes: []} 442 | { name: 'samp' 443 | attributes: []} 444 | { name: 'script' 445 | attributes: [ 446 | { name: 'async'} 447 | { name: 'charSet'} 448 | { name: 'defer'} 449 | { name: 'src'} 450 | { name: 'type'} 451 | ]} 452 | { name: 'section' 453 | attributes: []} 454 | { name: 'select' 455 | attributes: [ 456 | { name: 'autoFocus'} 457 | { name: 'disabled'} 458 | { name: 'form'} 459 | { name: 'multiple'} 460 | { name: 'name'} 461 | { name: 'required'} 462 | { name: 'size'} 463 | ]} 464 | { name: 'small' 465 | attributes: []} 466 | { name: 'source' 467 | attributes: [ 468 | { name: 'media'} 469 | { name: 'src'} 470 | { name: 'type'} 471 | ]} 472 | { name: 'span' 473 | attributes: []} 474 | { name: 'strong' 475 | attributes: []} 476 | { name: 'style' 477 | attributes: [ 478 | { name: 'disabled'} 479 | { name: 'media'} 480 | { name: 'scoped'} 481 | { name: 'type'} 482 | ]} 483 | { name: 'sub' 484 | attributes: []} 485 | { name: 'summary' 486 | attributes: []} 487 | { name: 'sup' 488 | attributes: []} 489 | { name: 'table' 490 | attributes: []} 491 | { name: 'tbody' 492 | attributes: []} 493 | { name: 'td' 494 | attributes: [ 495 | { name: 'colSpan'} 496 | { name: 'headers'} 497 | { name: 'rowSpan'} 498 | ]} 499 | { name: 'textarea' 500 | attributes: [ 501 | { name: 'autoFocus'} 502 | { name: 'cols'} 503 | { name: 'disabled'} 504 | { name: 'form'} 505 | { name: 'label'} 506 | { name: 'maxLength'} 507 | { name: 'name'} 508 | { name: 'placeholder'} 509 | { name: 'readonly'} 510 | { name: 'required'} 511 | { name: 'rows'} 512 | { name: 'wrap'} 513 | ]} 514 | { name: 'tfoot' 515 | attributes: []} 516 | { name: 'th' 517 | attributes: [ 518 | { name: 'colSpan'} 519 | { name: 'headers'} 520 | { name: 'rowSpan'} 521 | { name: 'scope'} 522 | ]} 523 | { name: 'thead' 524 | attributes: []} 525 | { name: 'time' 526 | attributes: [ 527 | { name: 'dateTime'} 528 | ]} 529 | { name: 'title' 530 | attributes: []} 531 | { name: 'tr' 532 | attributes: []} 533 | { name: 'track' 534 | attributes: [ 535 | { name: 'default'} 536 | { name: 'label'} 537 | { name: 'src'} 538 | ]} 539 | { name: 'u' 540 | attributes: []} 541 | { name: 'ul' 542 | attributes: []} 543 | { name: 'var' 544 | attributes: []} 545 | { name: 'video' 546 | attributes: [ 547 | { name: 'autoPlay'} 548 | { name: 'controls'} 549 | { name: 'height'} 550 | { name: 'loop'} 551 | { name: 'mediaGroup'} 552 | { name: 'muted'} 553 | { name: 'poster'} 554 | { name: 'preload'} 555 | { name: 'src'} 556 | { name: 'width'} 557 | ]} 558 | { name: 'wbr' 559 | attributes: []} 560 | # svg elements 561 | { name: 'circle' 562 | attributes: [ 563 | { name: 'cx'} 564 | { name: 'cy'} 565 | { name: 'r'} 566 | { name: 'stroke'} 567 | { name: 'strokeWidth'} 568 | { name: 'fill'} 569 | ]} 570 | { name: 'clipPath' 571 | attributes: [ 572 | { name: 'clipPath'} 573 | ]} 574 | { name: 'defs' 575 | attributes: []} 576 | { name: 'ellipse' 577 | attributes: [ 578 | { name: 'cx'} 579 | { name: 'cy'} 580 | { name: 'rx'} 581 | { name: 'ry'} 582 | ]} 583 | { name: 'g' 584 | attributes: [ 585 | { name: 'fill'} 586 | { name: 'opacity'} 587 | ]} 588 | { name: 'line' 589 | attributes: [ 590 | { name: 'x1'} 591 | { name: 'x2'} 592 | { name: 'y1'} 593 | { name: 'y2'} 594 | ]} 595 | { name: 'linearGradient' 596 | attributes: [ 597 | { name: 'x1'} 598 | { name: 'x2'} 599 | { name: 'y1'} 600 | { name: 'y2'} 601 | { name: 'spreadMethod'} 602 | { name: 'xlinkHref'} 603 | ]} 604 | { name: 'mask' 605 | attributes: [ 606 | { name: 'mashUnits'} 607 | { name: 'x'} 608 | { name: 'y'} 609 | { name: 'width'} 610 | { name: 'height'} 611 | ]} 612 | { name: 'path' 613 | attributes: [ 614 | { name: 'd'} 615 | { name: 'transform'} 616 | ]} 617 | { name: 'pattern' 618 | attributes: [ 619 | { name: 'patternContentUnits'} 620 | { name: 'x'} 621 | { name: 'y'} 622 | { name: 'width'} 623 | { name: 'height'} 624 | { name: 'viewBox'} 625 | { name: 'xlinkHref'} 626 | ]} 627 | { name: 'polygon' 628 | attributes: [ 629 | { name: 'points'} 630 | ]} 631 | { name: 'polyline' 632 | attributes: [ 633 | { name: 'points'} 634 | ]} 635 | { name: 'radialGradient' 636 | attributes: [ 637 | { name: 'gradientUnits'} 638 | { name: 'gradientTransform'} 639 | { name: 'cx'} 640 | { name: 'cy'} 641 | { name: 'r'} 642 | { name: 'fx'} 643 | { name: 'fy'} 644 | { name: 'spreadMethod'} 645 | { name: 'xlinkHref'} 646 | ]} 647 | { name: 'rect' 648 | attributes: [ 649 | { name: 'x'} 650 | { name: 'y'} 651 | { name: 'rx'} 652 | { name: 'ry'} 653 | { name: 'width'} 654 | { name: 'height'} 655 | ]} 656 | { name: 'stop' 657 | attributes: [ 658 | { name: 'offset'} 659 | { name: 'stopColor'} 660 | { name: 'stopOpacity'} 661 | ]} 662 | { name: 'svg' 663 | attributes: [ 664 | { name: 'x'} 665 | { name: 'y'} 666 | { name: 'width'} 667 | { name: 'height'} 668 | { name: 'viewBox'} 669 | { name: 'preserveAspectRatio'} 670 | { name: 'zoomAndPan'} 671 | ]} 672 | { name: 'text' 673 | attributes: [ 674 | { name: 'x'} 675 | { name: 'y'} 676 | { name: 'dx'} 677 | { name: 'dy'} 678 | { name: 'rotate'} 679 | { name: 'textLength'} 680 | { name: 'lengthAdjust'} 681 | ]} 682 | { name: 'tspan' 683 | attributes: [ 684 | { name: 'x'} 685 | { name: 'y'} 686 | { name: 'dx'} 687 | { name: 'dy'} 688 | { name: 'rotate'} 689 | { name: 'textLength'} 690 | { name: 'lengthAdjust'} 691 | { name: 'xlinkHref'} 692 | ]} 693 | ] 694 | -------------------------------------------------------------------------------- /spec/fixtures/grammar/babel-sublime/js-symbols.js: -------------------------------------------------------------------------------- 1 | // SYNTAX TEST "source.js.jsx" 2 | 3 | A = function() {} 4 | // <- meta.function.js entity.name.function.js 5 | //^ ^^^^^^^^^^ ^^ meta.function.js 6 | //^ keyword.operator.assignment.js 7 | // ^^^^^^^^ storage.type.function.js 8 | // ^ punctuation.definition.parameters.begin.js 9 | // ^^ meta.brace.round.js 10 | // ^ punctuation.definition.parameters.end.js 11 | // ^^ meta.brace.curly.js 12 | B = function(z) {} 13 | // <- meta.function.js entity.name.function.js 14 | //^ ^^^^^^^^^^^ ^^ meta.function.js 15 | //^ keyword.operator.assignment.js 16 | // ^^^^^^^^ storage.type.function.js 17 | // ^ punctuation.definition.parameters.begin.js 18 | // ^ ^ meta.brace.round.js 19 | // ^ meta.function.parameters.js 20 | // ^ variable.other.readwrite.js 21 | // ^ punctuation.definition.parameters.end.js 22 | // ^^ meta.brace.curly.js 23 | C = function c() {} 24 | // <- meta.function.js entity.name.function.js 25 | //^ ^^^^^^^^ ^^^ ^^ meta.function.js 26 | // ^ entity.name.function.js 27 | //^ keyword.operator.assignment.js 28 | // ^^^^^^^^ storage.type.function.js 29 | // ^ punctuation.definition.parameters.begin.js 30 | // ^^ meta.brace.round.js 31 | // ^ punctuation.definition.parameters.end.js 32 | // ^^ meta.brace.curly.js 33 | D = function d(z) {} 34 | // <- meta.function.js entity.name.function.js 35 | //^ ^^^^^^^^ ^^^^ ^^ meta.function.js 36 | // ^ entity.name.function.js 37 | //^ keyword.operator.assignment.js 38 | // ^^^^^^^^ storage.type.function.js 39 | // ^ punctuation.definition.parameters.begin.js 40 | // ^ ^ meta.brace.round.js 41 | // ^ meta.function.parameters.js 42 | // ^ variable.other.readwrite.js 43 | // ^ punctuation.definition.parameters.end.js 44 | // ^^ meta.brace.curly.js 45 | E = () => {} 46 | // <- meta.function.arrow.js entity.name.function.js 47 | //^ ^^ ^^ ^^ meta.function.arrow.js 48 | //^ keyword.operator.assignment.js 49 | // ^ punctuation.definition.parameters.begin.js 50 | // ^^ meta.brace.round.js 51 | // ^ punctuation.definition.parameters.end.js 52 | // ^^ storage.type.function.arrow.js 53 | // ^^ meta.brace.curly.js 54 | F = (z) => {} 55 | // <- meta.function.arrow.js entity.name.function.js 56 | //^ ^^^ ^^ ^^ meta.function.arrow.js 57 | //^ keyword.operator.assignment.js 58 | // ^ punctuation.definition.parameters.begin.js 59 | // ^ ^ meta.brace.round.js 60 | // ^ meta.function.parameters.js 61 | // ^ variable.other.readwrite.js 62 | // ^ punctuation.definition.parameters.end.js 63 | // ^^ storage.type.function.arrow.js 64 | // ^^ meta.brace.curly.js 65 | G = z => {} 66 | // <- meta.function.arrow.js entity.name.function.js 67 | //^ ^ ^^ meta.function.arrow.js 68 | //^ keyword.operator.assignment.js 69 | // ^ variable.other.readwrite.js 70 | // ^^ storage.type.function.arrow.js 71 | // ^^ meta.brace.curly.js 72 | function() {} 73 | // <- meta.function.js storage.type.function.js 74 | // <- meta.function.js storage.type.function.js 75 | //^^^^^^^^ ^^ meta.function.js 76 | //^^^^^^ storage.type.function.js 77 | // ^ punctuation.definition.parameters.begin.js 78 | // ^^ meta.brace.round.js 79 | // ^ punctuation.definition.parameters.end.js 80 | // ^^ meta.brace.curly.js 81 | function(z) {} 82 | // <- meta.function.js storage.type.function.js 83 | // <- meta.function.js storage.type.function.js 84 | //^^^^^^^^^ ^^ meta.function.js 85 | //^^^^^^ storage.type.function.js 86 | // ^ punctuation.definition.parameters.begin.js 87 | // ^ ^ meta.brace.round.js 88 | // ^ meta.function.parameters.js 89 | // ^ variable.other.readwrite.js 90 | // ^ punctuation.definition.parameters.end.js 91 | // ^^ meta.brace.curly.js 92 | function H() {} 93 | // <- meta.function.js storage.type.function.js 94 | // <- meta.function.js storage.type.function.js 95 | //^^^^^^ ^^^ ^^ meta.function.js 96 | //^^^^^^ storage.type.function.js 97 | // ^ entity.name.function.js 98 | // ^ punctuation.definition.parameters.begin.js 99 | // ^^ meta.brace.round.js 100 | // ^ punctuation.definition.parameters.end.js 101 | // ^^ meta.brace.curly.js 102 | function I(z) {} 103 | // <- meta.function.js storage.type.function.js 104 | // <- meta.function.js storage.type.function.js 105 | //^^^^^^ ^^^^ ^^ meta.function.js 106 | //^^^^^^ storage.type.function.js 107 | // ^ entity.name.function.js 108 | // ^ punctuation.definition.parameters.begin.js 109 | // ^ ^ meta.brace.round.js 110 | // ^ meta.function.parameters.js 111 | // ^ variable.other.readwrite.js 112 | // ^ punctuation.definition.parameters.end.js 113 | // ^^ meta.brace.curly.js 114 | () => {} 115 | // <- meta.function.arrow.js punctuation.definition.parameters.begin.js meta.brace.round.js 116 | // <- meta.function.arrow.js meta.brace.round.js punctuation.definition.parameters.end.js 117 | // ^^ ^^ meta.function.arrow.js 118 | // ^^ storage.type.function.arrow.js 119 | // ^^ meta.brace.curly.js 120 | (z) => {} 121 | // <- meta.function.arrow.js punctuation.definition.parameters.begin.js meta.brace.round.js 122 | // <- meta.function.arrow.js meta.function.parameters.js variable.other.readwrite.js 123 | //^ ^^ ^^ meta.function.arrow.js 124 | //^ meta.brace.round.js 125 | //^ punctuation.definition.parameters.end.js 126 | // ^^ storage.type.function.arrow.js 127 | // ^^ meta.brace.curly.js 128 | J.prototype.j = () => {} 129 | // <- meta.prototype.function.arrow.js entity.name.class.js 130 | // <- meta.prototype.function.arrow.js keyword.operator.accessor.js 131 | //^^^^^^^^^^^ ^ ^^ ^^ ^^ meta.prototype.function.arrow.js 132 | // ^ keyword.operator.accessor.js 133 | //^^^^^^^^^ variable.language.prototype.js 134 | // ^ entity.name.function.js 135 | // ^ keyword.operator.assignment.js 136 | // ^ punctuation.definition.parameters.begin.js 137 | // ^^ meta.brace.round.js 138 | // ^ punctuation.definition.parameters.end.js 139 | // ^^ storage.type.function.arrow.js 140 | // ^^ meta.brace.curly.js 141 | K.prototype.k = (z) => {} 142 | // <- meta.prototype.function.arrow.js entity.name.class.js 143 | // <- meta.prototype.function.arrow.js keyword.operator.accessor.js 144 | //^^^^^^^^^^^ ^ ^^^ ^^ ^^ meta.prototype.function.arrow.js 145 | // ^ keyword.operator.accessor.js 146 | //^^^^^^^^^ variable.language.prototype.js 147 | // ^ entity.name.function.js 148 | // ^ keyword.operator.assignment.js 149 | // ^ punctuation.definition.parameters.begin.js 150 | // ^ ^ meta.brace.round.js 151 | // ^ meta.function.parameters.js 152 | // ^ variable.other.readwrite.js 153 | // ^ punctuation.definition.parameters.end.js 154 | // ^^ storage.type.function.arrow.js 155 | // ^^ meta.brace.curly.js 156 | L.prototype.l = z => {} 157 | // <- meta.prototype.function.arrow.js entity.name.class.js 158 | // <- meta.prototype.function.arrow.js keyword.operator.accessor.js 159 | //^^^^^^^^^^^ ^ ^ ^^ meta.prototype.function.arrow.js 160 | // ^ keyword.operator.accessor.js 161 | //^^^^^^^^^ variable.language.prototype.js 162 | // ^ entity.name.function.js 163 | // ^ keyword.operator.assignment.js 164 | // ^ variable.other.readwrite.js 165 | // ^^ storage.type.function.arrow.js 166 | // ^^ meta.brace.curly.js 167 | M.prototype.m = function() {} 168 | // <- meta.prototype.function.js entity.name.class.js 169 | // <- meta.prototype.function.js keyword.operator.accessor.js 170 | //^^^^^^^^^^^ ^ ^^^^^^^^^^ ^^ meta.prototype.function.js 171 | // ^ keyword.operator.accessor.js 172 | //^^^^^^^^^ variable.language.prototype.js 173 | // ^ entity.name.function.js 174 | // ^ keyword.operator.assignment.js 175 | // ^^^^^^^^ storage.type.function.js 176 | // ^ punctuation.definition.parameters.begin.js 177 | // ^^ meta.brace.round.js 178 | // ^ punctuation.definition.parameters.end.js 179 | // ^^ meta.brace.curly.js 180 | N.prototype.n = function(z) {} 181 | // <- meta.prototype.function.js entity.name.class.js 182 | // <- meta.prototype.function.js keyword.operator.accessor.js 183 | //^^^^^^^^^^^ ^ ^^^^^^^^^^^ ^^ meta.prototype.function.js 184 | // ^ keyword.operator.accessor.js 185 | //^^^^^^^^^ variable.language.prototype.js 186 | // ^ entity.name.function.js 187 | // ^ keyword.operator.assignment.js 188 | // ^^^^^^^^ storage.type.function.js 189 | // ^ punctuation.definition.parameters.begin.js 190 | // ^ ^ meta.brace.round.js 191 | // ^ meta.function.parameters.js 192 | // ^ variable.other.readwrite.js 193 | // ^ punctuation.definition.parameters.end.js 194 | // ^^ meta.brace.curly.js 195 | O.prototype.o = function oo() {} 196 | // <- meta.prototype.function.js entity.name.class.js 197 | // <- meta.prototype.function.js keyword.operator.accessor.js 198 | //^^^^^^^^^^^ ^ ^^^^^^^^ ^^^^ ^^ meta.prototype.function.js 199 | // ^ keyword.operator.accessor.js 200 | //^^^^^^^^^ variable.language.prototype.js 201 | // ^ ^^ entity.name.function.js 202 | // ^ keyword.operator.assignment.js 203 | // ^^^^^^^^ storage.type.function.js 204 | // ^ punctuation.definition.parameters.begin.js 205 | // ^^ meta.brace.round.js 206 | // ^ punctuation.definition.parameters.end.js 207 | // ^^ meta.brace.curly.js 208 | P.prototype.p = function pp(z) {} 209 | // <- meta.prototype.function.js entity.name.class.js 210 | // <- meta.prototype.function.js keyword.operator.accessor.js 211 | //^^^^^^^^^^^ ^ ^^^^^^^^ ^^^^^ ^^ meta.prototype.function.js 212 | // ^ keyword.operator.accessor.js 213 | //^^^^^^^^^ variable.language.prototype.js 214 | // ^ ^^ entity.name.function.js 215 | // ^ keyword.operator.assignment.js 216 | // ^^^^^^^^ storage.type.function.js 217 | // ^ punctuation.definition.parameters.begin.js 218 | // ^ ^ meta.brace.round.js 219 | // ^ meta.function.parameters.js 220 | // ^ variable.other.readwrite.js 221 | // ^ punctuation.definition.parameters.end.js 222 | // ^^ meta.brace.curly.js 223 | Q.q = () => {} 224 | // <- meta.function.static.arrow.js entity.name.class.js 225 | // <- meta.function.static.arrow.js keyword.operator.accessor.js 226 | //^ ^ ^^ ^^ ^^ meta.function.static.arrow.js 227 | //^ entity.name.function.js 228 | // ^ keyword.operator.assignment.js 229 | // ^ punctuation.definition.parameters.begin.js 230 | // ^^ meta.brace.round.js 231 | // ^ punctuation.definition.parameters.end.js 232 | // ^^ storage.type.function.arrow.js 233 | // ^^ meta.brace.curly.js 234 | R.r = (z) => {} 235 | // <- meta.function.static.arrow.js entity.name.class.js 236 | // <- meta.function.static.arrow.js keyword.operator.accessor.js 237 | //^ ^ ^^^ ^^ ^^ meta.function.static.arrow.js 238 | //^ entity.name.function.js 239 | // ^ keyword.operator.assignment.js 240 | // ^ punctuation.definition.parameters.begin.js 241 | // ^ ^ meta.brace.round.js 242 | // ^ meta.function.parameters.js 243 | // ^ variable.other.readwrite.js 244 | // ^ punctuation.definition.parameters.end.js 245 | // ^^ storage.type.function.arrow.js 246 | // ^^ meta.brace.curly.js 247 | S.s = z => {} 248 | // <- meta.function.static.arrow.js entity.name.class.js 249 | // <- meta.function.static.arrow.js keyword.operator.accessor.js 250 | //^ ^ ^ ^^ meta.function.static.arrow.js 251 | //^ entity.name.function.js 252 | // ^ keyword.operator.assignment.js 253 | // ^ variable.other.readwrite.js 254 | // ^^ storage.type.function.arrow.js 255 | // ^^ meta.brace.curly.js 256 | T.t = function() {} 257 | // <- meta.function.static.js entity.name.class.js 258 | // <- meta.function.static.js keyword.operator.accessor.js 259 | //^ ^ ^^^^^^^^^^ ^^ meta.function.static.js 260 | //^ entity.name.function.js 261 | // ^ keyword.operator.assignment.js 262 | // ^^^^^^^^ storage.type.function.js 263 | // ^ punctuation.definition.parameters.begin.js 264 | // ^^ meta.brace.round.js 265 | // ^ punctuation.definition.parameters.end.js 266 | // ^^ meta.brace.curly.js 267 | U.u = function(z) {} 268 | // <- meta.function.static.js entity.name.class.js 269 | // <- meta.function.static.js keyword.operator.accessor.js 270 | //^ ^ ^^^^^^^^^^^ ^^ meta.function.static.js 271 | //^ entity.name.function.js 272 | // ^ keyword.operator.assignment.js 273 | // ^^^^^^^^ storage.type.function.js 274 | // ^ punctuation.definition.parameters.begin.js 275 | // ^ ^ meta.brace.round.js 276 | // ^ meta.function.parameters.js 277 | // ^ variable.other.readwrite.js 278 | // ^ punctuation.definition.parameters.end.js 279 | // ^^ meta.brace.curly.js 280 | V.v = function vv() {} 281 | // <- meta.function.static.js entity.name.class.js 282 | // <- meta.function.static.js keyword.operator.accessor.js 283 | //^ ^ ^^^^^^^^ ^^^^ ^^ meta.function.static.js 284 | //^ ^^ entity.name.function.js 285 | // ^ keyword.operator.assignment.js 286 | // ^^^^^^^^ storage.type.function.js 287 | // ^ punctuation.definition.parameters.begin.js 288 | // ^^ meta.brace.round.js 289 | // ^ punctuation.definition.parameters.end.js 290 | // ^^ meta.brace.curly.js 291 | W.w = function ww(z) {} 292 | // <- meta.function.static.js entity.name.class.js 293 | // <- meta.function.static.js keyword.operator.accessor.js 294 | //^ ^ ^^^^^^^^ ^^^^^ ^^ meta.function.static.js 295 | //^ ^^ entity.name.function.js 296 | // ^ keyword.operator.assignment.js 297 | // ^^^^^^^^ storage.type.function.js 298 | // ^ punctuation.definition.parameters.begin.js 299 | // ^ ^ meta.brace.round.js 300 | // ^ meta.function.parameters.js 301 | // ^ variable.other.readwrite.js 302 | // ^ punctuation.definition.parameters.end.js 303 | // ^^ meta.brace.curly.js 304 | 305 | class X extends XX {} 306 | // <- meta.class.js storage.type.class.js 307 | // <- meta.class.js storage.type.class.js 308 | //^^^ meta.class.js 309 | //^^^ storage.type.class.js 310 | // ^ ^^ entity.name.class.js 311 | // ^^^^^^^ meta.class.extends.js 312 | // ^^^^^^^ storage.type.extends.js 313 | // ^ punctuation.section.class.begin.js 314 | // ^ punctuation.section.class.end.js 315 | class Y {} 316 | // <- meta.class.js storage.type.class.js 317 | // <- meta.class.js storage.type.class.js 318 | //^^^ meta.class.js 319 | //^^^ storage.type.class.js 320 | // ^ entity.name.class.js 321 | // ^ punctuation.section.class.begin.js 322 | // ^ punctuation.section.class.end.js 323 | 324 | 325 | // >> only:(source.js.jsx) 326 | -------------------------------------------------------------------------------- /spec/fixtures/grammar/babel-sublime/jsx-text.jsx: -------------------------------------------------------------------------------- 1 | // SYNTAX TEST "source.js.jsx" 2 |
3 | // <- meta.tag.jsx punctuation.definition.tag.jsx 4 | // <- meta.tag.jsx entity.name.tag.open.jsx 5 | //^^^ meta.tag.jsx 6 | // ^ punctuation.definition.tag.jsx 7 | //^^ entity.name.tag.open.jsx 8 | // ^ JSXAttrs 9 | // ^ JSXStartTagEnd 10 | {'it\'s with text inside'} 11 | //^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ meta.tag.jsx 12 | //^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXAttrs 13 | //^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXNested 14 | //^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ meta.embedded.expression.js 15 | //^ punctuation.section.embedded.begin.jsx 16 | // ^^^^^^ ^^^^ ^^^^ ^^^^^^^ string.quoted.single.js 17 | // ^ punctuation.definition.string.begin.jsx 18 | // ^ punctuation.definition.string.end.jsx 19 | // ^ punctuation.section.embedded.end.jsx 20 |
21 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 22 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 23 | //^^^^ meta.tag.jsx 24 | // ^ punctuation.definition.tag.jsx 25 | //^^^ entity.name.tag.close.jsx 26 | 27 |
{'it\'s with text inside'}
28 | // <- meta.tag.jsx punctuation.definition.tag.jsx 29 | // <- meta.tag.jsx entity.name.tag.open.jsx 30 | //^^^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^^^ meta.tag.jsx 31 | // ^ ^^ ^ punctuation.definition.tag.jsx 32 | //^^ entity.name.tag.open.jsx 33 | // ^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^^^ JSXAttrs 34 | // ^ JSXStartTagEnd 35 | // ^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXNested 36 | // ^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ meta.embedded.expression.js 37 | // ^ punctuation.section.embedded.begin.jsx 38 | // ^^^^^^ ^^^^ ^^^^ ^^^^^^^ string.quoted.single.js 39 | // ^ punctuation.definition.string.begin.jsx 40 | // ^ punctuation.definition.string.end.jsx 41 | // ^ punctuation.section.embedded.end.jsx 42 | // ^^ JSXEndTagStart 43 | // ^^^ entity.name.tag.close.jsx 44 | 45 |
51 | //^^^^^^^^ meta.tag.jsx 52 | //^^^^^^^^ JSXAttrs 53 | //^^^^ entity.other.attribute-name.jsx 54 | // ^ keyword.operator.assignment.jsx 55 | // ^^ string.quoted.single.js 56 | // ^ punctuation.definition.string.begin.jsx 57 | // ^ punctuation.definition.string.end.jsx 58 | // ^ punctuation.definition.tag.jsx 59 | // ^ JSXStartTagEnd 60 | {'it\'s with text inside'} 61 | //^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ meta.tag.jsx 62 | //^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXAttrs 63 | //^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXNested 64 | //^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ meta.embedded.expression.js 65 | //^ punctuation.section.embedded.begin.jsx 66 | // ^^^^^^ ^^^^ ^^^^ ^^^^^^^ string.quoted.single.js 67 | // ^ punctuation.definition.string.begin.jsx 68 | // ^ punctuation.definition.string.end.jsx 69 | // ^ punctuation.section.embedded.end.jsx 70 |
71 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 72 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 73 | //^^^^ meta.tag.jsx 74 | // ^ punctuation.definition.tag.jsx 75 | //^^^ entity.name.tag.close.jsx 76 | 77 |
{'it\'s with text inside'}
78 | // <- meta.tag.jsx punctuation.definition.tag.jsx 79 | // <- meta.tag.jsx entity.name.tag.open.jsx 80 | //^^ ^^^^^^^^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^^^ meta.tag.jsx 81 | // ^ ^^ ^ punctuation.definition.tag.jsx 82 | //^^ entity.name.tag.open.jsx 83 | // ^^^^^^^^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^^^ JSXAttrs 84 | // ^^^^ entity.other.attribute-name.jsx 85 | // ^ keyword.operator.assignment.jsx 86 | // ^^ string.quoted.double.js 87 | // ^ ^ punctuation.definition.string.begin.jsx 88 | // ^ ^ punctuation.definition.string.end.jsx 89 | // ^ JSXStartTagEnd 90 | // ^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXNested 91 | // ^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ meta.embedded.expression.js 92 | // ^ punctuation.section.embedded.begin.jsx 93 | // ^^^^^^ ^^^^ ^^^^ ^^^^^^^ string.quoted.single.js 94 | // ^ punctuation.section.embedded.end.jsx 95 | // ^^ JSXEndTagStart 96 | // ^^^ entity.name.tag.close.jsx 97 |
103 | //^^^^^^^^ meta.tag.jsx 104 | //^^^^^^^^ JSXAttrs 105 | //^^^^ entity.other.attribute-name.jsx 106 | // ^ keyword.operator.assignment.jsx 107 | // ^^ string.quoted.double.js 108 | // ^ punctuation.definition.string.begin.jsx 109 | // ^ punctuation.definition.string.end.jsx 110 | // ^ punctuation.definition.tag.jsx 111 | // ^ JSXStartTagEnd 112 | {"it's with text inside"} 113 | //^^^^^^ ^^^^ ^^^^ ^^^^^^^^ meta.tag.jsx 114 | //^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXAttrs 115 | //^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXNested 116 | //^^^^^^ ^^^^ ^^^^ ^^^^^^^^ meta.embedded.expression.js 117 | //^ punctuation.section.embedded.begin.jsx 118 | // ^^^^^ ^^^^ ^^^^ ^^^^^^^ string.quoted.double.js 119 | // ^ punctuation.definition.string.begin.jsx 120 | // ^ punctuation.definition.string.end.jsx 121 | // ^ punctuation.section.embedded.end.jsx 122 |
123 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 124 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 125 | //^^^^ meta.tag.jsx 126 | // ^ punctuation.definition.tag.jsx 127 | //^^^ entity.name.tag.close.jsx 128 | 129 |
{"it's with text inside"}
130 | // <- meta.tag.jsx punctuation.definition.tag.jsx 131 | // <- meta.tag.jsx entity.name.tag.open.jsx 132 | //^^ ^^^^^^^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^^^ meta.tag.jsx 133 | // ^ ^^ ^ punctuation.definition.tag.jsx 134 | //^^ entity.name.tag.open.jsx 135 | // ^^^^^^^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^^^ JSXAttrs 136 | // ^^^^ entity.other.attribute-name.jsx 137 | // ^ keyword.operator.assignment.jsx 138 | // ^^ ^^^^^^ ^^^^ ^^^^ ^^^^^^^^ meta.embedded.expression.js 139 | // ^ ^ punctuation.section.embedded.begin.jsx 140 | // ^ ^ punctuation.section.embedded.end.jsx 141 | // ^ JSXStartTagEnd 142 | // ^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXNested 143 | // ^^^^^ ^^^^ ^^^^ ^^^^^^^ string.quoted.double.js 144 | // ^ punctuation.definition.string.begin.jsx 145 | // ^ punctuation.definition.string.end.jsx 146 | // ^^ JSXEndTagStart 147 | // ^^^ entity.name.tag.close.jsx 148 |
154 | //^^^^^^^^ meta.tag.jsx 155 | //^^^^^^^^ JSXAttrs 156 | //^^^^ entity.other.attribute-name.jsx 157 | // ^ keyword.operator.assignment.jsx 158 | // ^^ meta.embedded.expression.js 159 | // ^ punctuation.section.embedded.begin.jsx 160 | // ^ punctuation.section.embedded.end.jsx 161 | // ^ punctuation.definition.tag.jsx 162 | // ^ JSXStartTagEnd 163 | {"it's with text inside"} 164 | //^^^^^^ ^^^^ ^^^^ ^^^^^^^^ meta.tag.jsx 165 | //^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXAttrs 166 | //^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXNested 167 | //^^^^^^ ^^^^ ^^^^ ^^^^^^^^ meta.embedded.expression.js 168 | //^ punctuation.section.embedded.begin.jsx 169 | // ^^^^^ ^^^^ ^^^^ ^^^^^^^ string.quoted.double.js 170 | // ^ punctuation.definition.string.begin.jsx 171 | // ^ punctuation.definition.string.end.jsx 172 | // ^ punctuation.section.embedded.end.jsx 173 |
174 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 175 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 176 | //^^^^ meta.tag.jsx 177 | // ^ punctuation.definition.tag.jsx 178 | //^^^ entity.name.tag.close.jsx 179 | 180 |
181 | // <- meta.tag.jsx punctuation.definition.tag.jsx 182 | // <- meta.tag.jsx entity.name.tag.open.jsx 183 | //^^^ meta.tag.jsx 184 | // ^ punctuation.definition.tag.jsx 185 | //^^ entity.name.tag.open.jsx 186 | // ^ JSXAttrs 187 | // ^ JSXStartTagEnd 188 | it's with text inside 189 | //^^^^ ^^^^ ^^^^ ^^^^^^ meta.tag.jsx 190 | //^^^^ ^^^^ ^^^^ ^^^^^^ JSXAttrs 191 | //^^^^ ^^^^ ^^^^ ^^^^^^ JSXNested 192 |
193 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 194 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 195 | //^^^^ meta.tag.jsx 196 | // ^ punctuation.definition.tag.jsx 197 | //^^^ entity.name.tag.close.jsx 198 | 199 |
it's with text inside
200 | // <- meta.tag.jsx punctuation.definition.tag.jsx 201 | // <- meta.tag.jsx entity.name.tag.open.jsx 202 | //^^^^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^ meta.tag.jsx 203 | // ^ ^^ ^ punctuation.definition.tag.jsx 204 | //^^ entity.name.tag.open.jsx 205 | // ^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXAttrs 206 | // ^ JSXStartTagEnd 207 | // ^^^^ ^^^^ ^^^^ ^^^^^^ JSXNested 208 | // ^^ JSXEndTagStart 209 | // ^^^ entity.name.tag.close.jsx 210 | 211 |
217 | //^^^^^^^^ meta.tag.jsx 218 | //^^^^^^^^ JSXAttrs 219 | //^^^^ entity.other.attribute-name.jsx 220 | // ^ keyword.operator.assignment.jsx 221 | // ^^ string.quoted.single.js 222 | // ^ punctuation.definition.string.begin.jsx 223 | // ^ punctuation.definition.string.end.jsx 224 | // ^ punctuation.definition.tag.jsx 225 | // ^ JSXStartTagEnd 226 | it's with text inside 227 | //^^^^ ^^^^ ^^^^ ^^^^^^ meta.tag.jsx 228 | //^^^^ ^^^^ ^^^^ ^^^^^^ JSXAttrs 229 | //^^^^ ^^^^ ^^^^ ^^^^^^ JSXNested 230 |
231 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 232 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 233 | //^^^^ meta.tag.jsx 234 | // ^ punctuation.definition.tag.jsx 235 | //^^^ entity.name.tag.close.jsx 236 | 237 |
it's with text inside
238 | // <- meta.tag.jsx punctuation.definition.tag.jsx 239 | // <- meta.tag.jsx entity.name.tag.open.jsx 240 | //^^ ^^^^^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^ meta.tag.jsx 241 | // ^ ^^ ^ punctuation.definition.tag.jsx 242 | //^^ entity.name.tag.open.jsx 243 | // ^^^^^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXAttrs 244 | // ^^^^ entity.other.attribute-name.jsx 245 | // ^ keyword.operator.assignment.jsx 246 | // ^^ string.quoted.double.js 247 | // ^ punctuation.definition.string.begin.jsx 248 | // ^ punctuation.definition.string.end.jsx 249 | // ^ JSXStartTagEnd 250 | // ^^^^ ^^^^ ^^^^ ^^^^^^ JSXNested 251 | // ^^ JSXEndTagStart 252 | // ^^^ entity.name.tag.close.jsx 253 |
259 | //^^^^^^^^ meta.tag.jsx 260 | //^^^^^^^^ JSXAttrs 261 | //^^^^ entity.other.attribute-name.jsx 262 | // ^ keyword.operator.assignment.jsx 263 | // ^^ string.quoted.double.js 264 | // ^ punctuation.definition.string.begin.jsx 265 | // ^ punctuation.definition.string.end.jsx 266 | // ^ punctuation.definition.tag.jsx 267 | // ^ JSXStartTagEnd 268 | it's with text inside 269 | //^^^^ ^^^^ ^^^^ ^^^^^^ meta.tag.jsx 270 | //^^^^ ^^^^ ^^^^ ^^^^^^ JSXAttrs 271 | //^^^^ ^^^^ ^^^^ ^^^^^^ JSXNested 272 |
273 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 274 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 275 | //^^^^ meta.tag.jsx 276 | // ^ punctuation.definition.tag.jsx 277 | //^^^ entity.name.tag.close.jsx 278 | 279 |
it's with text inside
280 | // <- meta.tag.jsx punctuation.definition.tag.jsx 281 | // <- meta.tag.jsx entity.name.tag.open.jsx 282 | //^^ ^^^^^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^ meta.tag.jsx 283 | // ^ ^^ ^ punctuation.definition.tag.jsx 284 | //^^ entity.name.tag.open.jsx 285 | // ^^^^^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXAttrs 286 | // ^^^^ entity.other.attribute-name.jsx 287 | // ^ keyword.operator.assignment.jsx 288 | // ^^ meta.embedded.expression.js 289 | // ^ punctuation.section.embedded.begin.jsx 290 | // ^ punctuation.section.embedded.end.jsx 291 | // ^ JSXStartTagEnd 292 | // ^^^^ ^^^^ ^^^^ ^^^^^^ JSXNested 293 | // ^^ JSXEndTagStart 294 | // ^^^ entity.name.tag.close.jsx 295 |
301 | //^^^^^^^^ meta.tag.jsx 302 | //^^^^^^^^ JSXAttrs 303 | //^^^^ entity.other.attribute-name.jsx 304 | // ^ keyword.operator.assignment.jsx 305 | // ^^ meta.embedded.expression.js 306 | // ^ punctuation.section.embedded.begin.jsx 307 | // ^ punctuation.section.embedded.end.jsx 308 | // ^ punctuation.definition.tag.jsx 309 | // ^ JSXStartTagEnd 310 | it's with text inside 311 | //^^^^ ^^^^ ^^^^ ^^^^^^ meta.tag.jsx 312 | //^^^^ ^^^^ ^^^^ ^^^^^^ JSXAttrs 313 | //^^^^ ^^^^ ^^^^ ^^^^^^ JSXNested 314 |
315 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 316 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXEndTagStart 317 | //^^^^ meta.tag.jsx 318 | // ^ punctuation.definition.tag.jsx 319 | //^^^ entity.name.tag.close.jsx 320 | 321 |
it's with text inside
322 | // <- meta.tag.jsx punctuation.definition.tag.jsx 323 | // <- meta.tag.jsx entity.name.tag.open.jsx 324 | //^^ ^^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^ meta.tag.jsx 325 | // ^ ^^ ^ punctuation.definition.tag.jsx 326 | //^^ entity.name.tag.open.jsx 327 | // ^^^^^^^^^ ^^^^ ^^^^ ^^^^^^^^ JSXAttrs 328 | // ^^^^ entity.other.attribute-name.jsx 329 | // ^ JSXStartTagEnd 330 | // ^^^^ ^^^^ ^^^^ ^^^^^^ JSXNested 331 | // ^^ JSXEndTagStart 332 | // ^^^ entity.name.tag.close.jsx 333 | 334 |
it's with text inside
340 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXStartTagEnd 341 | // <- meta.tag.jsx JSXAttrs JSXNested 342 | //^^^ ^^^^ ^^^^ ^^^^^^^^^^^^ meta.tag.jsx 343 | //^^^ ^^^^ ^^^^ ^^^^^^^^ JSXAttrs 344 | // ^^ ^ punctuation.definition.tag.jsx 345 | //^^^ ^^^^ ^^^^ ^^^^^^ JSXNested 346 | // ^^ JSXEndTagStart 347 | // ^^^ entity.name.tag.close.jsx 348 | 349 |
it's with text inside
363 | // <- meta.tag.jsx JSXAttrs punctuation.definition.tag.jsx JSXStartTagEnd 364 | // <- meta.tag.jsx JSXAttrs JSXNested 365 | //^^^ ^^^^ ^^^^ ^^^^^^^^^^^^ meta.tag.jsx 366 | //^^^ ^^^^ ^^^^ ^^^^^^^^ JSXAttrs 367 | // ^^ ^ punctuation.definition.tag.jsx 368 | //^^^ ^^^^ ^^^^ ^^^^^^ JSXNested 369 | // ^^ JSXEndTagStart 370 | // ^^^ entity.name.tag.close.jsx 371 | -------------------------------------------------------------------------------- /spec/fixtures/grammar/declare.js: -------------------------------------------------------------------------------- 1 | // SYNTAX TEST "source.js.jsx" 2 | 3 | declare module 'a-unique-module-name' { 4 | // <- keyword.other.declare.flowtype 5 | // <- keyword.other.declare.flowtype 6 | //^^^^^ keyword.other.declare.flowtype 7 | // ^^^^^^ storage.type.module.flowtype 8 | // ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.single.js 9 | // ^ punctuation.definition.string.begin.js 10 | // ^ punctuation.definition.string.end.js 11 | // ^ punctuation.section.class.begin.js 12 | declare interface Stack {} 13 | //^^^^^^^ ^^^^^^^^^ ^^^^^^^^ ^^ meta.class.body.js 14 | //^^^^^^^ keyword.other.declare.flowtype 15 | // ^^^^^^^^^ keyword.other.interface.flowtype 16 | // ^^^^^ support.type.class.interface.js 17 | // ^ ^ punctuation.flowtype 18 | // ^ support.type.class.flowtype 19 | // ^ punctuation.section.class.begin.js 20 | // ^ punctuation.section.class.end.js 21 | declare class Response extends A mixins A,B {} 22 | //^^^^^^^ ^^^^^ ^^^^^^^^ ^^^^^^^ ^ ^^^^^^ ^^^ ^^ meta.class.body.js 23 | //^^^^^^^ keyword.other.declare.flowtype 24 | // ^^^^^ storage.type.class.flowtype 25 | // ^^^^^^^^ ^ ^ ^ entity.name.class.js 26 | // ^^^^^^^ ^^^^^^ meta.class.extends.js 27 | // ^^^^^^^ ^^^^^^ storage.type.extends.js 28 | // ^ meta.delimiter.comma.js 29 | // ^ punctuation.section.class.begin.js 30 | // ^ punctuation.section.class.end.js 31 | declare module.exports: () => Function; 32 | //^^^^^^^ ^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^ meta.class.body.js 33 | //^^^^^^^ keyword.other.declare.flowtype 34 | // ^^^^^^ ^^^^^^^ storage.type.module.flowtype 35 | // ^ keyword.operator.accessor.flowtype 36 | // ^ punctuation.type.flowtype 37 | // ^ punctuation.definition.parameters.begin.js 38 | // ^^ meta.brace.round.js 39 | // ^ punctuation.definition.parameters.end.js 40 | // ^^ storage.type.function.arrow.js 41 | // ^^^^^^^^ support.type.builtin.class.flowtype 42 | // ^ punctuation.terminator.statement.js 43 | declare type NextFunction = (error?: Object) => void 44 | //^^^^^^^ ^^^^ ^^^^^^^^^^^^ ^ ^^^^^^^^ ^^^^^^^ ^^ ^^^^ meta.class.body.js 45 | //^^^^^^^ keyword.other.declare.flowtype 46 | // ^^^^ keyword.other.typedef.flowtype 47 | // ^^^^^^^^^^^^ support.type.class.flowtype 48 | // ^ punctuation.definition.parameters.begin.js 49 | // ^ ^ meta.brace.round.js 50 | // ^^^^^^^ ^^^^^^ meta.function.parameters.js 51 | // ^^^^^ variable.other.readwrite.js 52 | // ^ keyword.operator.optional.parameter.flowtype 53 | // ^ punctuation.type.flowtype 54 | // ^^^^^^ support.type.builtin.class.flowtype 55 | // ^ punctuation.definition.parameters.end.js 56 | // ^^^^ support.type.builtin.primitive.flowtype 57 | } 58 | // <- punctuation.section.class.end.js 59 | 60 | interface Iterator { 61 | // <- keyword.other.interface.flowtype 62 | // <- keyword.other.interface.flowtype 63 | //^^^^^^^ keyword.other.interface.flowtype 64 | // ^^^^^^^^ support.type.class.interface.js 65 | // ^ ^ punctuation.flowtype 66 | // ^ support.type.class.flowtype 67 | // ^ punctuation.section.class.begin.js 68 | next(): IteratorResult 69 | // ^^^^^^^ ^^^^^^^^^^^^^^^^^ meta.class.body.js 70 | // ^^^^^^^ ^^^^^^^^^^^^^^^^^ meta.function.method.js 71 | // ^^^^ entity.name.function.method.js 72 | // ^ punctuation.definition.parameters.begin.js 73 | // ^^ meta.brace.round.js 74 | // ^ punctuation.definition.parameters.end.js 75 | // ^ punctuation.type.flowtype 76 | // ^^^^^^^^^^^^^^ ^ support.type.class.flowtype 77 | // ^ ^ punctuation.flowtype 78 | iterator(): Iterator 79 | // ^^^^^^^^^^^ ^^^^^^^^^^^ meta.class.body.js 80 | // ^^^^^^^^^^^ ^^^^^^^^^^^ meta.function.method.js 81 | // ^^^^^^^^ entity.name.function.method.js 82 | // ^ punctuation.definition.parameters.begin.js 83 | // ^^ meta.brace.round.js 84 | // ^ punctuation.definition.parameters.end.js 85 | // ^ punctuation.type.flowtype 86 | // ^^^^^^^^ ^ support.type.class.flowtype 87 | // ^ ^ punctuation.flowtype 88 | } 89 | // <- punctuation.section.class.end.js 90 | 91 | declare var NaN: number 92 | // <- keyword.other.declare.flowtype 93 | // <- keyword.other.declare.flowtype 94 | //^^^^^ keyword.other.declare.flowtype 95 | // ^^^ storage.type.js 96 | // ^^^ variable.other.readwrite.js 97 | // ^ punctuation.type.flowtype 98 | // ^^^^^^ support.type.builtin.primitive.flowtype 99 | 100 | declare var module: { 101 | // <- keyword.other.declare.flowtype 102 | // <- keyword.other.declare.flowtype 103 | //^^^^^ keyword.other.declare.flowtype 104 | // ^^^ storage.type.js 105 | // ^^^^^^ variable.other.readwrite.js 106 | // ^ punctuation.type.flowtype 107 | // ^ meta.brace.curly.open.flowtype 108 | exports: any; 109 | // ^^^^^^^ variable.other.readwrite.js 110 | // ^ punctuation.type.flowtype 111 | // ^^^ support.type.builtin.primitive.flowtype 112 | require(id: string): any; 113 | // ^^^^^^^^^^^ ^^^^^^^^ ^^^ meta.function.method.js 114 | // ^^^^^^^ entity.name.function.method.js 115 | // ^ punctuation.definition.parameters.begin.js 116 | // ^ ^ meta.brace.round.js 117 | // ^^^ ^^^^^^ meta.function.parameters.js 118 | // ^^ variable.other.readwrite.js 119 | // ^ ^ punctuation.type.flowtype 120 | // ^^^^^^ ^^^ support.type.builtin.primitive.flowtype 121 | // ^ punctuation.definition.parameters.end.js 122 | id: string; 123 | // ^^ variable.other.readwrite.js 124 | // ^ punctuation.type.flowtype 125 | // ^^^^^^ support.type.builtin.primitive.flowtype 126 | filename: string; 127 | // ^^^^^^^^ variable.other.readwrite.js 128 | // ^ punctuation.type.flowtype 129 | // ^^^^^^ support.type.builtin.primitive.flowtype 130 | loaded: boolean; 131 | // ^^^^^^ variable.other.readwrite.js 132 | // ^ punctuation.type.flowtype 133 | // ^^^^^^^ support.type.builtin.primitive.flowtype 134 | parent: any; 135 | // ^^^^^^ variable.other.readwrite.js 136 | // ^ punctuation.type.flowtype 137 | // ^^^ support.type.builtin.primitive.flowtype 138 | children: Array; 139 | // ^^^^^^^^ variable.other.readwrite.js 140 | // ^ punctuation.type.flowtype 141 | // ^^^^^ support.type.builtin.class.flowtype 142 | // ^ ^ punctuation.flowtype 143 | // ^^^ support.type.builtin.primitive.flowtype 144 | }; 145 | // <- meta.brace.curly.close.flowtype 146 | // <- punctuation.terminator.statement.js 147 | 148 | declare class Blob { 149 | // <- keyword.other.declare.flowtype 150 | // <- keyword.other.declare.flowtype 151 | //^^^^^ keyword.other.declare.flowtype 152 | // ^^^^^ storage.type.class.flowtype 153 | // ^^^^ entity.name.class.js 154 | // ^ punctuation.section.class.begin.js 155 | constructor(blobParts?: Array, options?: { 156 | // ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^ meta.class.body.js 157 | // ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^ meta.function.method.js 158 | // ^^^^^^^^^^^ entity.name.function.method.js 159 | // ^ punctuation.definition.parameters.begin.js 160 | // ^ meta.brace.round.js 161 | // ^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^ meta.function.parameters.js 162 | // ^^^^^^^^^ ^^^^^^^ variable.other.readwrite.js 163 | // ^ ^ keyword.operator.optional.parameter.flowtype 164 | // ^ ^ punctuation.type.flowtype 165 | // ^^^^^ support.type.builtin.class.flowtype 166 | // ^ ^ punctuation.flowtype 167 | // ^^^ support.type.builtin.primitive.flowtype 168 | // ^ meta.delimiter.comma.js 169 | // ^ meta.brace.curly.open.flowtype 170 | type?: string 171 | // ^^^^^^ ^^^^^^ meta.class.body.js 172 | // ^^^^^^ ^^^^^^ meta.function.method.js 173 | // ^^^^^^ ^^^^^^ meta.function.parameters.js 174 | // ^^^^ variable.other.readwrite.js 175 | // ^ keyword.operator.optional.parameter.flowtype 176 | // ^ punctuation.type.flowtype 177 | // ^^^^^^ support.type.builtin.primitive.flowtype 178 | endings?: string 179 | // ^^^^^^^^^ ^^^^^^ meta.class.body.js 180 | // ^^^^^^^^^ ^^^^^^ meta.function.method.js 181 | // ^^^^^^^^^ ^^^^^^ meta.function.parameters.js 182 | // ^^^^^^^ variable.other.readwrite.js 183 | // ^ keyword.operator.optional.parameter.flowtype 184 | // ^ punctuation.type.flowtype 185 | // ^^^^^^ support.type.builtin.primitive.flowtype 186 | }): void 187 | // ^^^ ^^^^ meta.class.body.js 188 | // ^^^ ^^^^ meta.function.method.js 189 | // ^ meta.function.parameters.js 190 | // ^ meta.brace.curly.close.flowtype 191 | // ^ punctuation.definition.parameters.end.js 192 | // ^ meta.brace.round.js 193 | // ^ punctuation.type.flowtype 194 | // ^^^^ support.type.builtin.primitive.flowtype 195 | type: string 196 | // ^^^^^ ^^^^^^ meta.class.body.js 197 | // ^^^^^ ^^^^^^ meta.function.method.js 198 | // ^^^^ variable.other.readwrite.js 199 | // ^ punctuation.type.flowtype 200 | // ^^^^^^ support.type.builtin.primitive.flowtype 201 | size: number 202 | // ^^^^^ ^^^^^^ meta.class.body.js 203 | // ^^^^^ ^^^^^^ meta.function.method.js 204 | // ^^^^ variable.other.readwrite.js 205 | // ^ punctuation.type.flowtype 206 | // ^^^^^^ support.type.builtin.primitive.flowtype 207 | slice(start?: number, end?: number, contentType?: string): Blob 208 | // ^^^^^^^^^^^^^ ^^^^^^^ ^^^^^ ^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^ ^^^^ meta.class.body.js 209 | // ^^^^^^^^^^^^^ ^^^^^^^ ^^^^^ ^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^ ^^^^ meta.function.method.js 210 | // ^^^^^ entity.name.function.method.js 211 | // ^ punctuation.definition.parameters.begin.js 212 | // ^ ^ meta.brace.round.js 213 | // ^^^^^^^ ^^^^^^^ ^^^^^ ^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^ meta.function.parameters.js 214 | // ^^^^^ ^^^ ^^^^^^^^^^^ variable.other.readwrite.js 215 | // ^ ^ ^ keyword.operator.optional.parameter.flowtype 216 | // ^ ^ ^ ^ punctuation.type.flowtype 217 | // ^^^^^^ ^^^^^^ ^^^^^^ support.type.builtin.primitive.flowtype 218 | // ^ ^ meta.delimiter.comma.js 219 | // ^ punctuation.definition.parameters.end.js 220 | // ^^^^ support.type.class.flowtype 221 | } 222 | // <- punctuation.section.class.end.js 223 | 224 | type CanvasImageSource = HTMLImageElement | number & string 225 | // <- keyword.other.typedef.flowtype 226 | // <- keyword.other.typedef.flowtype 227 | //^^ keyword.other.typedef.flowtype 228 | // ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ support.type.class.flowtype 229 | // ^ kewyword.operator.union.flowtype 230 | // ^^^^^^ ^^^^^^ support.type.builtin.primitive.flowtype 231 | // ^ kewyword.operator.intersection.flowtype 232 | 233 | type child_process$execOpts = { 234 | // <- keyword.other.typedef.flowtype 235 | // <- keyword.other.typedef.flowtype 236 | //^^ keyword.other.typedef.flowtype 237 | // ^^^^^^^^^^^^^^^^^^^^^^ support.type.primitive.flowtype 238 | // ^ meta.brace.curly.js 239 | cwd?: string 240 | //^^^ variable.other.readwrite.js 241 | // ^ keyword.operator.optional.parameter.flowtype 242 | // ^ punctuation.type.flowtype 243 | // ^^^^^^ support.type.builtin.primitive.flowtype 244 | env?: Object 245 | //^^^ variable.other.readwrite.js 246 | // ^ keyword.operator.optional.parameter.flowtype 247 | // ^ punctuation.type.flowtype 248 | // ^^^^^^ support.type.builtin.class.flowtype 249 | }; 250 | // <- meta.brace.curly.js 251 | // <- punctuation.terminator.statement.js 252 | 253 | type ReactClass = _ReactClass 254 | // <- keyword.other.typedef.flowtype 255 | // <- keyword.other.typedef.flowtype 256 | //^^ keyword.other.typedef.flowtype 257 | // ^^^^^^^^^^ ^ ^ ^ ^^^^^^^^^^^ ^ ^ ^ support.type.class.flowtype 258 | // ^ ^ ^ ^ punctuation.flowtype 259 | // ^ ^ ^ ^ ^ meta.delimiter.comma.js 260 | // ^ kewyword.operator.existential.flowtype 261 | 262 | declare function require(id: string): any; 263 | // <- keyword.other.declare.flowtype 264 | // <- keyword.other.declare.flowtype 265 | //^^^^^ keyword.other.declare.flowtype 266 | // ^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^ ^^^ meta.function.js 267 | // ^^^^^^^^ storage.type.function.js 268 | // ^^^^^^^ entity.name.function.js 269 | // ^ punctuation.definition.parameters.begin.js 270 | // ^ ^ meta.brace.round.js 271 | // ^^^ ^^^^^^ meta.function.parameters.js 272 | // ^^ variable.other.readwrite.js 273 | // ^ ^ punctuation.type.flowtype 274 | // ^^^^^^ ^^^ support.type.builtin.primitive.flowtype 275 | // ^ punctuation.definition.parameters.end.js 276 | // ^ punctuation.terminator.statement.js 277 | 278 | declare var foo: ( 279 | // <- keyword.other.declare.flowtype 280 | // <- keyword.other.declare.flowtype 281 | //^^^^^ keyword.other.declare.flowtype 282 | // ^^^ storage.type.js 283 | // ^^^ storage.type.function.js 284 | // ^ punctuation.type.flowtype 285 | // ^ punctuation.definition.parameters.begin.js 286 | // ^ meta.brace.round.js 287 | ((x: T) => T) & ((x: T, y: U) => U) 288 | //^^^^^^^ ^^ ^^ ^^ ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ meta.function.parameters.js 289 | //^ ^ ^ ^ ^ ^ ^ ^ meta.brace.round.js 290 | // ^ ^ ^ ^ punctuation.flowtype 291 | // ^ ^ ^ ^ ^ ^ ^ ^ support.type.class.flowtype 292 | // ^ ^ punctuation.definition.parameters.begin.js 293 | // ^ ^ ^ variable.other.readwrite.js 294 | // ^ ^ ^ punctuation.type.flowtype 295 | // ^ ^ punctuation.definition.parameters.end.js 296 | // ^^ ^^ storage.type.function.arrow.js 297 | // ^ kewyword.operator.intersection.flowtype 298 | // ^ ^ meta.delimiter.comma.js 299 | ) 300 | // <- punctuation.definition.parameters.end.js meta.brace.round.js 301 | 302 | 303 | // >> only:(source.js.jsx) 304 | --------------------------------------------------------------------------------