├── .coffeelintignore ├── .github ├── no-response.yml └── workflows │ └── ci.yml ├── .gitignore ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE.md ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── coffeelint.json ├── grammars ├── xml.cson └── xsl.cson ├── package.json ├── settings └── language-xml.cson ├── snippets └── language-xml.cson └── spec └── xml-spec.coffee /.coffeelintignore: -------------------------------------------------------------------------------- 1 | spec/fixtures 2 | -------------------------------------------------------------------------------- /.github/no-response.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-no-response - https://github.com/probot/no-response 2 | 3 | # Number of days of inactivity before an issue is closed for lack of response 4 | daysUntilClose: 28 5 | 6 | # Label requiring a response 7 | responseRequiredLabel: more-information-needed 8 | 9 | # Comment to post when closing an issue for lack of response. Set to `false` to disable. 10 | closeComment: > 11 | This issue has been automatically closed because there has been no response 12 | to our request for more information from the original author. With only the 13 | information that is currently in the issue, we don't have enough information 14 | to take action. Please reach out if you have or find the answers we need so 15 | that we can investigate further. 16 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push] 4 | 5 | env: 6 | CI: true 7 | 8 | jobs: 9 | Test: 10 | strategy: 11 | matrix: 12 | os: [ubuntu-latest, macos-latest, windows-latest] 13 | channel: [stable, beta] 14 | runs-on: ${{ matrix.os }} 15 | steps: 16 | - uses: actions/checkout@v1 17 | - uses: UziTech/action-setup-atom@v2 18 | with: 19 | version: ${{ matrix.channel }} 20 | - name: Install dependencies 21 | run: apm install 22 | - name: Run tests 23 | run: atom --test spec 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | See the [Atom contributing guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md) 2 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | ### Prerequisites 10 | 11 | * [ ] Put an X between the brackets on this line if you have done all of the following: 12 | * Reproduced the problem in Safe Mode: http://flight-manual.atom.io/hacking-atom/sections/debugging/#using-safe-mode 13 | * Followed all applicable steps in the debugging guide: http://flight-manual.atom.io/hacking-atom/sections/debugging/ 14 | * Checked the FAQs on the message board for common solutions: https://discuss.atom.io/c/faq 15 | * Checked that your issue isn't already filed: https://github.com/issues?utf8=✓&q=is%3Aissue+user%3Aatom 16 | * Checked that there is not already an Atom package that provides the described functionality: https://atom.io/packages 17 | 18 | ### Description 19 | 20 | [Description of the issue] 21 | 22 | ### Steps to Reproduce 23 | 24 | 1. [First Step] 25 | 2. [Second Step] 26 | 3. [and so on...] 27 | 28 | **Expected behavior:** [What you expect to happen] 29 | 30 | **Actual behavior:** [What actually happens] 31 | 32 | **Reproduces how often:** [What percentage of the time does it reproduce?] 33 | 34 | ### Versions 35 | 36 | You can get this information from copy and pasting the output of `atom --version` and `apm --version` from the command line. Also, please include the OS and what version of the OS you're running. 37 | 38 | ### Additional Information 39 | 40 | Any additional information, configuration or data that might be necessary to reproduce the issue. 41 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 GitHub Inc. 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 | 22 | -------------------------------------------------------------------- 23 | 24 | This package was derived from a TextMate bundle located at 25 | https://github.com/textmate/xml.tmbundle and distributed under the following 26 | license, located in `README.mdown`: 27 | 28 | Permission to copy, use, modify, sell and distribute this 29 | software is granted. This software is provided "as is" without 30 | express or implied warranty, and with no claim as to its 31 | suitability for any purpose. 32 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Requirements 2 | 3 | * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. 4 | * All new code requires tests to ensure against regressions 5 | 6 | ### Description of the Change 7 | 8 | 13 | 14 | ### Alternate Designs 15 | 16 | 17 | 18 | ### Benefits 19 | 20 | 21 | 22 | ### Possible Drawbacks 23 | 24 | 25 | 26 | ### Applicable Issues 27 | 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##### Atom and all repositories under Atom will be archived on December 15, 2022. Learn more in our [official announcement](https://github.blog/2022-06-08-sunsetting-atom/) 2 | # XML language support in Atom 3 | [![CI](https://github.com/atom/language-xml/actions/workflows/ci.yml/badge.svg)](https://github.com/atom/language-xml/actions/workflows/ci.yml) 4 | 5 | Adds syntax highlighting and snippets to XML files in Atom. 6 | 7 | Originally [converted](http://flight-manual.atom.io/hacking-atom/sections/converting-from-textmate) from the [XML TextMate bundle](https://github.com/textmate/xml.tmbundle). 8 | 9 | Contributions are greatly appreciated. Please fork this repository and open a pull request to add snippets, make grammar tweaks, etc. 10 | -------------------------------------------------------------------------------- /coffeelint.json: -------------------------------------------------------------------------------- 1 | { 2 | "max_line_length": { 3 | "level": "ignore" 4 | }, 5 | "no_empty_param_list": { 6 | "level": "error" 7 | }, 8 | "arrow_spacing": { 9 | "level": "error" 10 | }, 11 | "no_interpolation_in_single_quotes": { 12 | "level": "error" 13 | }, 14 | "no_debugger": { 15 | "level": "error" 16 | }, 17 | "prefer_english_operator": { 18 | "level": "error" 19 | }, 20 | "colon_assignment_spacing": { 21 | "spacing": { 22 | "left": 0, 23 | "right": 1 24 | }, 25 | "level": "error" 26 | }, 27 | "braces_spacing": { 28 | "spaces": 0, 29 | "level": "error" 30 | }, 31 | "spacing_after_comma": { 32 | "level": "error" 33 | }, 34 | "no_stand_alone_at": { 35 | "level": "error" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /grammars/xml.cson: -------------------------------------------------------------------------------- 1 | 'scopeName': 'text.xml' 2 | 'name': 'XML' 3 | 'fileTypes': [ 4 | 'aiml' 5 | 'atom' 6 | 'axml' 7 | 'bpmn' 8 | 'config' 9 | 'cpt' 10 | 'csl' 11 | 'csproj' 12 | 'csproj.user' 13 | 'dae' 14 | 'dia' 15 | 'dita' 16 | 'ditamap' 17 | 'dtml' 18 | 'fodg' 19 | 'fodp' 20 | 'fods' 21 | 'fodt' 22 | 'fsproj' 23 | 'fxml' 24 | 'gir' 25 | 'glade' 26 | 'gpx' 27 | 'graphml' 28 | 'icls' 29 | 'iml' 30 | 'isml' 31 | 'jmx' 32 | 'jsp' 33 | 'kml' 34 | 'kst' 35 | 'launch' 36 | 'menu' 37 | 'mxml' 38 | 'nunit' 39 | 'nuspec' 40 | 'opml' 41 | 'owl' 42 | 'pom' 43 | 'ppj' 44 | 'proj' 45 | 'pt' 46 | 'pubxml' 47 | 'pubxml.user' 48 | 'rdf' 49 | 'rng' 50 | 'rss' 51 | 'sdf' 52 | 'shproj' 53 | 'siml' 54 | 'sld' 55 | 'storyboard' 56 | 'StyleCop' 57 | 'svg' 58 | 'targets' 59 | 'tld' 60 | 'vbox' 61 | 'vbox-prev' 62 | 'vbproj' 63 | 'vbproj.user' 64 | 'vcproj' 65 | 'vcproj.filters' 66 | 'vcxproj' 67 | 'vcxproj.filters' 68 | 'wixmsp' 69 | 'wixmst' 70 | 'wixobj' 71 | 'wixout' 72 | 'wsdl' 73 | 'wxs' 74 | 'xaml' 75 | 'xbl' 76 | 'xib' 77 | 'xlf' 78 | 'xliff' 79 | 'xml' 80 | 'xpdl' 81 | 'xsd' 82 | 'xul' 83 | 'ui' 84 | ] 85 | 'firstLineMatch': '''(?x) 86 | # XML declaration 87 | (?: 88 | ^ <\\? xml 89 | 90 | # VersionInfo 91 | \\s+ version 92 | \\s* = \\s* 93 | ([\'"]) 94 | 1 \\. [0-9]+ 95 | \\1 96 | 97 | # EncodingDecl 98 | (?: 99 | \\s+ encoding 100 | \\s* = \\s* 101 | 102 | # EncName 103 | ([\'"]) 104 | [A-Za-z] 105 | [-A-Za-z0-9._]* 106 | \\2 107 | )? 108 | 109 | # SDDecl 110 | (?: 111 | \\s+ standalone 112 | \\s* = \\s* 113 | ([\'"]) 114 | (?:yes|no) 115 | \\3 116 | )? 117 | 118 | \\s* \\?> 119 | ) 120 | | 121 | # Modeline 122 | (?i: 123 | # Emacs 124 | -\\*-(?:\\s*(?=[^:;\\s]+\\s*-\\*-)|(?:.*?[;\\s]|(?<=-\\*-))mode\\s*:\\s*) 125 | xml 126 | (?=[\\s;]|(?]?\\d+|m)?|\\sex)(?=:(?=\\s*set?\\s[^\\n:]+:)|:(?!\\s*set?\\s))(?:(?:\\s|\\s*:\\s*)\\w*(?:\\s*=(?:[^\\n\\\\\\s]|\\\\.)*)?)*[\\s:](?:filetype|ft|syntax)\\s*= 130 | xml 131 | (?=\\s|:|$) 132 | ) 133 | ''' 134 | 'patterns': [ 135 | { 136 | 'begin': '(<\\?)\\s*([-_a-zA-Z0-9]+)' 137 | 'captures': 138 | '1': 139 | 'name': 'punctuation.definition.tag.xml' 140 | '2': 141 | 'name': 'entity.name.tag.xml' 142 | 'end': '(\\?>)' 143 | 'name': 'meta.tag.preprocessor.xml' 144 | 'patterns': [ 145 | { 146 | 'match': ' ([a-zA-Z-]+)' 147 | 'name': 'entity.other.attribute-name.xml' 148 | } 149 | { 150 | 'include': '#doublequotedString' 151 | } 152 | { 153 | 'include': '#singlequotedString' 154 | } 155 | ] 156 | } 157 | { 158 | 'begin': '()' 167 | 'name': 'meta.tag.sgml.doctype.xml' 168 | 'patterns': [ 169 | { 170 | 'include': '#internalSubset' 171 | } 172 | ] 173 | } 174 | { 175 | 'include': '#comments' 176 | } 177 | { 178 | 'begin': '(<)((?:([-_a-zA-Z0-9]+)(:))?([-_a-zA-Z0-9:]+))(?=(\\s[^>]*)?>)' 179 | 'beginCaptures': 180 | '1': 181 | 'name': 'punctuation.definition.tag.xml' 182 | '2': 183 | 'name': 'entity.name.tag.xml' 184 | '3': 185 | 'name': 'entity.name.tag.namespace.xml' 186 | '4': 187 | 'name': 'punctuation.separator.namespace.xml' 188 | '5': 189 | 'name': 'entity.name.tag.localname.xml' 190 | 'end': '(>)()' 191 | 'endCaptures': 192 | '1': 193 | 'name': 'punctuation.definition.tag.xml' 194 | '2': 195 | 'name': 'punctuation.definition.tag.xml' 196 | '3': 197 | 'name': 'entity.name.tag.xml' 198 | '4': 199 | 'name': 'entity.name.tag.namespace.xml' 200 | '5': 201 | 'name': 'punctuation.separator.namespace.xml' 202 | '6': 203 | 'name': 'entity.name.tag.localname.xml' 204 | '7': 205 | 'name': 'punctuation.definition.tag.xml' 206 | 'name': 'meta.tag.no-content.xml' 207 | 'patterns': [ 208 | { 209 | 'include': '#tagStuff' 210 | } 211 | ] 212 | } 213 | { 214 | 'begin': '()' 227 | 'name': 'meta.tag.xml' 228 | 'patterns': [ 229 | { 230 | 'include': '#tagStuff' 231 | } 232 | ] 233 | } 234 | { 235 | 'include': '#entity' 236 | } 237 | { 238 | 'include': '#bare-ampersand' 239 | } 240 | { 241 | 'begin': '<%@' 242 | 'beginCaptures': 243 | '0': 244 | 'name': 'punctuation.section.embedded.begin.xml' 245 | 'end': '%>' 246 | 'endCaptures': 247 | '0': 248 | 'name': 'punctuation.section.embedded.end.xml' 249 | 'name': 'source.java-props.embedded.xml' 250 | 'patterns': [ 251 | { 252 | 'match': 'page|include|taglib' 253 | 'name': 'keyword.other.page-props.xml' 254 | } 255 | ] 256 | } 257 | { 258 | 'begin': '<%[!=]?(?!--)' 259 | 'beginCaptures': 260 | '0': 261 | 'name': 'punctuation.section.embedded.begin.xml' 262 | 'end': '(?!--)%>' 263 | 'endCaptures': 264 | '0': 265 | 'name': 'punctuation.section.embedded.end.xml' 266 | 'name': 'source.java.embedded.xml' 267 | 'patterns': [ 268 | { 269 | 'include': 'source.java' 270 | } 271 | ] 272 | } 273 | { 274 | 'begin': '' 279 | 'endCaptures': 280 | '0': 281 | 'name': 'punctuation.definition.string.end.xml' 282 | 'name': 'string.unquoted.cdata.xml' 283 | } 284 | ] 285 | 'repository': 286 | 'EntityDecl': 287 | 'begin': '()' 300 | 'patterns': [ 301 | { 302 | 'include': '#doublequotedString' 303 | } 304 | { 305 | 'include': '#singlequotedString' 306 | } 307 | ] 308 | 'bare-ampersand': 309 | 'match': '&' 310 | 'name': 'invalid.illegal.bad-ampersand.xml' 311 | 'doublequotedString': 312 | 'begin': '"' 313 | 'beginCaptures': 314 | '0': 315 | 'name': 'punctuation.definition.string.begin.xml' 316 | 'end': '"' 317 | 'endCaptures': 318 | '0': 319 | 'name': 'punctuation.definition.string.end.xml' 320 | 'name': 'string.quoted.double.xml' 321 | 'patterns': [ 322 | { 323 | 'include': '#entity' 324 | } 325 | { 326 | 'include': '#bare-ampersand' 327 | } 328 | ] 329 | 'entity': 330 | 'captures': 331 | '1': 332 | 'name': 'punctuation.definition.constant.xml' 333 | '3': 334 | 'name': 'punctuation.definition.constant.xml' 335 | 'match': '(&)([:a-zA-Z_][:a-zA-Z0-9_.-]*|#[0-9]+|#x[0-9a-fA-F]+)(;)' 336 | 'name': 'constant.character.entity.xml' 337 | 'internalSubset': 338 | 'begin': '(\\[)' 339 | 'captures': 340 | '1': 341 | 'name': 'punctuation.definition.constant.xml' 342 | 'end': '(\\])' 343 | 'name': 'meta.internalsubset.xml' 344 | 'patterns': [ 345 | { 346 | 'include': '#EntityDecl' 347 | } 348 | { 349 | 'include': '#parameterEntity' 350 | } 351 | { 352 | 'include': '#comments' 353 | } 354 | ] 355 | 'parameterEntity': 356 | 'captures': 357 | '1': 358 | 'name': 'punctuation.definition.constant.xml' 359 | '3': 360 | 'name': 'punctuation.definition.constant.xml' 361 | 'match': '(%)([:a-zA-Z_][:a-zA-Z0-9_.-]*)(;)' 362 | 'name': 'constant.character.parameter-entity.xml' 363 | 'singlequotedString': 364 | 'begin': '\'' 365 | 'beginCaptures': 366 | '0': 367 | 'name': 'punctuation.definition.string.begin.xml' 368 | 'end': '\'' 369 | 'endCaptures': 370 | '0': 371 | 'name': 'punctuation.definition.string.end.xml' 372 | 'name': 'string.quoted.single.xml' 373 | 'patterns': [ 374 | { 375 | 'include': '#entity' 376 | } 377 | { 378 | 'include': '#bare-ampersand' 379 | } 380 | ] 381 | 'tagStuff': 382 | 'patterns': [ 383 | { 384 | 'captures': 385 | '1': 386 | 'name': 'entity.other.attribute-name.namespace.xml' 387 | '2': 388 | 'name': 'entity.other.attribute-name.xml' 389 | '3': 390 | 'name': 'punctuation.separator.namespace.xml' 391 | '4': 392 | 'name': 'entity.other.attribute-name.localname.xml' 393 | 'match': '(?:^|\\s+)(?:([-\\w.]+)((:)))?([-\\w.:]+)\\s*=' 394 | } 395 | { 396 | 'include': '#doublequotedString' 397 | } 398 | { 399 | 'include': '#singlequotedString' 400 | } 401 | ] 402 | 'comments': 403 | 'patterns': [ 404 | { 405 | 'begin': '<%--' 406 | 'captures': 407 | '0': 408 | 'name': 'punctuation.definition.comment.xml' 409 | 'end': '--%>' 410 | 'name': 'comment.block.xml' 411 | } 412 | { 413 | 'begin': '' 418 | 'name': 'comment.block.xml' 419 | 'patterns': [ 420 | { 421 | 'begin': '--(?!>)' 422 | 'captures': 423 | '0': 424 | 'name': 'invalid.illegal.bad-comments-or-CDATA.xml' 425 | } 426 | ] 427 | } 428 | ] 429 | -------------------------------------------------------------------------------- /grammars/xsl.cson: -------------------------------------------------------------------------------- 1 | 'scopeName': 'text.xml.xsl' 2 | 'name': 'XSL' 3 | 'fileTypes': [ 4 | 'xsl' 5 | 'xslt' 6 | ] 7 | 'patterns': [ 8 | { 9 | 'begin': '(<)(xsl)((:))(template)' 10 | 'captures': 11 | '1': 12 | 'name': 'punctuation.definition.tag.xml' 13 | '2': 14 | 'name': 'entity.name.tag.namespace.xml' 15 | '3': 16 | 'name': 'entity.name.tag.xml' 17 | '4': 18 | 'name': 'punctuation.separator.namespace.xml' 19 | '5': 20 | 'name': 'entity.name.tag.localname.xml' 21 | 'end': '(>)' 22 | 'name': 'meta.tag.xml.template' 23 | 'patterns': [ 24 | { 25 | 'captures': 26 | '1': 27 | 'name': 'entity.other.attribute-name.namespace.xml' 28 | '2': 29 | 'name': 'entity.other.attribute-name.xml' 30 | '3': 31 | 'name': 'punctuation.separator.namespace.xml' 32 | '4': 33 | 'name': 'entity.other.attribute-name.localname.xml' 34 | 'match': ' (?:([-_a-zA-Z0-9]+)((:)))?([a-zA-Z-]+)' 35 | } 36 | { 37 | 'include': '#doublequotedString' 38 | } 39 | { 40 | 'include': '#singlequotedString' 41 | } 42 | ] 43 | } 44 | { 45 | 'include': 'text.xml' 46 | } 47 | ] 48 | 'repository': 49 | 'doublequotedString': 50 | 'begin': '"' 51 | 'beginCaptures': 52 | '0': 53 | 'name': 'punctuation.definition.string.begin.xml' 54 | 'end': '"' 55 | 'endCaptures': 56 | '0': 57 | 'name': 'punctuation.definition.string.end.xml' 58 | 'name': 'string.quoted.double.xml' 59 | 'singlequotedString': 60 | 'begin': '\'' 61 | 'beginCaptures': 62 | '0': 63 | 'name': 'punctuation.definition.string.begin.xml' 64 | 'end': '\'' 65 | 'endCaptures': 66 | '0': 67 | 'name': 'punctuation.definition.string.end.xml' 68 | 'name': 'string.quoted.single.xml' 69 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "language-xml", 3 | "version": "0.35.3", 4 | "description": "XML language support in Atom", 5 | "engines": { 6 | "atom": "*", 7 | "node": "*" 8 | }, 9 | "homepage": "http://atom.github.io/language-xml", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/atom/language-xml.git" 13 | }, 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/atom/language-xml/issues" 17 | }, 18 | "devDependencies": { 19 | "coffeelint": "^1.10.1" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /settings/language-xml.cson: -------------------------------------------------------------------------------- 1 | '.text.xml': 2 | 'editor': 3 | 'commentStart': '' 5 | 'foldEndPattern': '^\\s*(]+>|[/%]>|-->)\\s*$' 6 | 'increaseIndentPattern': '^\\s*<(([^!/?]|%)(?!.+?([/%]>|))|[%!]--\\s*$)' 7 | 'decreaseIndentPattern': '^\\s*(]+>|-->|--%>)' 8 | -------------------------------------------------------------------------------- /snippets/language-xml.cson: -------------------------------------------------------------------------------- 1 | '.text.xml': 2 | 'CDATA': 3 | 'prefix': 'cdata' 4 | 'body': '' 5 | 'XML Processing Instruction': 6 | 'prefix': 'xml' 7 | 'body': '' 8 | 'Long Attribute Tag': 9 | 'prefix': '$4\n' 11 | 'Long Tag': 12 | 'prefix': '<' 13 | 'body': '<${1:name}>$2' 14 | 'Short Tag': 15 | 'prefix': '>' 16 | 'body': '<${1:name} />' 17 | -------------------------------------------------------------------------------- /spec/xml-spec.coffee: -------------------------------------------------------------------------------- 1 | describe "XML grammar", -> 2 | grammar = null 3 | 4 | beforeEach -> 5 | waitsForPromise -> 6 | atom.packages.activatePackage("language-xml") 7 | 8 | runs -> 9 | grammar = atom.grammars.grammarForScopeName("text.xml") 10 | 11 | it "parses the grammar", -> 12 | expect(grammar).toBeTruthy() 13 | expect(grammar.scopeName).toBe "text.xml" 14 | 15 | it "tokenizes comments in internal subsets correctly", -> 16 | lines = grammar.tokenizeLines """ 17 | 19 | 20 | 21 | ]> 22 | """ 23 | 24 | expect(lines[1][1]).toEqual value: '') 30 | expect(tokens[0]).toEqual value: '') 36 | expect(tokens[0]).toEqual value: '', scopes: ['text.xml', 'comment.block.xml'] 40 | 41 | it "tokenizes empty element meta.tag.no-content.xml", -> 42 | {tokens} = grammar.tokenizeLine('') 43 | expect(tokens[0]).toEqual value: '<', scopes: ['text.xml', 'meta.tag.no-content.xml', 'punctuation.definition.tag.xml'] 44 | expect(tokens[1]).toEqual value: 'n', scopes: ['text.xml', 'meta.tag.no-content.xml', 'entity.name.tag.xml', 'entity.name.tag.localname.xml'] 45 | expect(tokens[2]).toEqual value: '>', scopes: ['text.xml', 'meta.tag.no-content.xml', 'punctuation.definition.tag.xml'] 46 | expect(tokens[3]).toEqual value: '', scopes: ['text.xml', 'meta.tag.no-content.xml', 'punctuation.definition.tag.xml'] 49 | 50 | it "tokenizes attribute-name of multi-line tag", -> 51 | linesWithIndent = grammar.tokenizeLines """ 52 | 54 | 55 | """ 56 | expect(linesWithIndent[1][1]).toEqual value: 'attrName', scopes: ['text.xml', 'meta.tag.xml', 'entity.other.attribute-name.localname.xml'] 57 | 58 | linesWithoutIndent = grammar.tokenizeLines """ 59 | 61 | 62 | """ 63 | expect(linesWithoutIndent[1][0]).toEqual value: 'attrName', scopes: ['text.xml', 'meta.tag.xml', 'entity.other.attribute-name.localname.xml'] 64 | 65 | it "tokenizes attribute-name.namespace contains period", -> 66 | lines = grammar.tokenizeLines """ 67 | 68 | 69 | """ 70 | expect(lines[0][3]).toEqual value: 'name.space', scopes: ['text.xml', 'meta.tag.xml', 'entity.other.attribute-name.namespace.xml'] 71 | 72 | it "tokenizes attribute-name.namespace contains East-Asian Kanji", -> 73 | lines = grammar.tokenizeLines """ 74 | 75 | 76 | """ 77 | expect(lines[0][3]).toEqual value: '名前空間名', scopes: ['text.xml', 'meta.tag.xml', 'entity.other.attribute-name.namespace.xml'] 78 | 79 | it "tokenizes attribute-name.localname contains period", -> 80 | lines = grammar.tokenizeLines """ 81 | 82 | 83 | """ 84 | expect(lines[0][3]).toEqual value: 'attr.name', scopes: ['text.xml', 'meta.tag.xml', 'entity.other.attribute-name.localname.xml'] 85 | 86 | it "tokenizes attribute-name.localname contains colon", -> 87 | lines = grammar.tokenizeLines """ 88 | 89 | 90 | """ 91 | expect(lines[0][5]).toEqual value: 'attr:name', scopes: ['text.xml', 'meta.tag.xml', 'entity.other.attribute-name.localname.xml'] 92 | 93 | it "tokenizes attribute-name.localname contains East-Asian Kanji", -> 94 | lines = grammar.tokenizeLines """ 95 | 96 | 97 | """ 98 | expect(lines[0][3]).toEqual value: '属性名', scopes: ['text.xml', 'meta.tag.xml', 'entity.other.attribute-name.localname.xml'] 99 | 100 | it "tokenizes attribute-name.localname when followed by spaces", -> 101 | lines = grammar.tokenizeLines """ 102 | 103 | 104 | """ 105 | expect(lines[0][3]).toEqual value: 'attrName', scopes: ['text.xml', 'meta.tag.xml', 'entity.other.attribute-name.localname.xml'] 106 | 107 | describe "firstLineMatch", -> 108 | it "recognises Emacs modelines", -> 109 | valid = """ 110 | #-*-xml-*- 111 | #-*-mode:xml-*- 112 | /* -*-xml-*- */ 113 | // -*- XML -*- 114 | /* -*- mode:xml -*- */ 115 | // -*- font:bar;mode:XML -*- 116 | // -*- font:bar;mode:XMl;foo:bar; -*- 117 | // -*-font:mode;mode:XML-*- 118 | // -*- foo:bar mode: xml bar:baz -*- 119 | " -*-foo:bar;mode:xML;bar:foo-*- "; 120 | " -*-font-mode:foo;mode:XML;foo-bar:quux-*-" 121 | "-*-font:x;foo:bar; mode : xml;bar:foo;foooooo:baaaaar;fo:ba;-*-"; 122 | "-*- font:x;foo : bar ; mode : xMl ; bar : foo ; foooooo:baaaaar;fo:ba-*-"; 123 | """ 124 | for line in valid.split /\n/ 125 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).not.toBeNull() 126 | 127 | invalid = """ 128 | /* --*XML-*- */ 129 | /* -*-- XML -*- 130 | /* -*- -- XML -*- 131 | /* -*- HXML -;- -*- 132 | // -*- iXML -*- 133 | // -*- XML; -*- 134 | // -*- xml-stuff -*- 135 | /* -*- model:xml -*- 136 | /* -*- indent-mode:xml -*- 137 | // -*- font:mode;xml -*- 138 | // -*- mode: -*- XML 139 | // -*- mode: grok-with-xml -*- 140 | // -*-font:mode;mode:xml--*- 141 | """ 142 | for line in invalid.split /\n/ 143 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).toBeNull() 144 | 145 | it "recognises Vim modelines", -> 146 | valid = """ 147 | vim: se filetype=xml: 148 | # vim: se ft=xml: 149 | # vim: set ft=xml: 150 | # vim: set filetype=XML: 151 | # vim: ft=xml 152 | # vim: syntax=xML 153 | # vim: se syntax=XML: 154 | # ex: syntax=xml 155 | # vim:ft=xml 156 | # vim600: ft=xml 157 | # vim>600: set ft=xml: 158 | # vi:noai:sw=3 ts=6 ft=xml 159 | # vi::::::::::noai:::::::::::: ft=xml 160 | # vim:ts=4:sts=4:sw=4:noexpandtab:ft=xml 161 | # vi:: noai : : : : sw =3 ts =6 ft =xml 162 | # vim: ts=4: pi sts=4: ft=xml: noexpandtab: sw=4: 163 | # vim: ts=4 sts=4: ft=xml noexpandtab: 164 | # vim:noexpandtab sts=4 ft=xml ts=4 165 | # vim:noexpandtab:ft=xml 166 | # vim:ts=4:sts=4 ft=xml:noexpandtab:\x20 167 | # vim:noexpandtab titlestring=hi\|there\\\\ ft=xml ts=4 168 | """ 169 | for line in valid.split /\n/ 170 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).not.toBeNull() 171 | 172 | invalid = """ 173 | ex: se filetype=xml: 174 | _vi: se filetype=xml: 175 | vi: se filetype=xml 176 | # vim set ft=xmlz 177 | # vim: soft=xml 178 | # vim: hairy-syntax=xml: 179 | # vim set ft=xml: 180 | # vim: setft=xml: 181 | # vim: se ft=xml backupdir=tmp 182 | # vim: set ft=xml set cmdheight=1 183 | # vim:noexpandtab sts:4 ft:xml ts:4 184 | # vim:noexpandtab titlestring=hi\\|there\\ ft=xml ts=4 185 | # vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=xml ts=4 186 | """ 187 | for line in invalid.split /\n/ 188 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).toBeNull() 189 | 190 | it "recognises a valid XML declaration", -> 191 | valid = """ 192 | 193 | 194 | 195 | 196 | 197 | """ 198 | for line in valid.split /\n/ 199 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).not.toBeNull() 200 | 201 | invalid = """ 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | """ 211 | for line in invalid.split /\n/ 212 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).toBeNull() 213 | --------------------------------------------------------------------------------