diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..4ada048 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +/.github/ export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +syntax_test_* export-ignore +preview.* export-ignore diff --git a/.github/workflows/ci-syntax-tests.yml b/.github/workflows/ci-syntax-tests.yml new file mode 100644 index 0000000..e12f2b1 --- /dev/null +++ b/.github/workflows/ci-syntax-tests.yml @@ -0,0 +1,50 @@ +name: CI Syntax Tests + +on: + push: + branches: + - master + tags-ignore: + - '**' + paths: + - '.github/workflows/ci-syntax-tests.yml' + - '**.sublime-syntax' + - '**/syntax_test_*' + pull_request: + paths: + - '.github/workflows/ci-syntax-tests.yml' + - '**.sublime-syntax' + - '**/syntax_test_*' + workflow_dispatch: + +jobs: + syntax_tests: + name: Sublime Text ${{ matrix.build }} + runs-on: ubuntu-latest + timeout-minutes: 15 # default is 6 hours! + strategy: + matrix: + include: + # Stable ST4 builds + - build: 4152 + default_packages: binary + - build: 4169 + default_packages: binary + - build: 4180 + default_packages: binary + - build: 4192 + default_packages: binary + # Latest dev build (and latest available maybe unreleased syntaxes) + - build: latest + default_packages: master + steps: + - name: Checkout EJS + uses: actions/checkout@v4 + with: + path: EJS + - uses: SublimeText/syntax-test-action@v2 + with: + build: ${{ matrix.build }} + package_name: EJS + package_root: EJS + default_packages: ${{ matrix.default_packages }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..adcc1fa --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# MacOS specific ignores +.DS_Store + +# development +.sublime/ +.venv/ +.vscode/ + +# python cache files +__pycache__/ +*.pyc diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..98fccd6 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.8 \ No newline at end of file diff --git a/Default.sublime-keymap b/Default.sublime-keymap index 3a9d255..123c2e2 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -3,7 +3,7 @@ // <% %> { "keys": ["%"], "command": "insert_snippet", "args": {"contents": "%${0: }%>"}, "context": [ - { "key": "selector", "operand": "text.ejs.percentsign - source.js", "match_all": true }, + { "key": "selector", "operand": "text.html.ejs - text.html.ejs source.js", "match_all": true }, { "key": "setting.auto_match_enabled", "operand": true }, { "key": "selection_empty", "operand": true, "match_all": true }, { "key": "preceding_text", "operator": "regex_contains", "operand": "<$", "match_all": true }, @@ -13,108 +13,33 @@ // { "keys": ["?"], "command": "insert_snippet", "args": {"contents": "?${0: }?>"}, "context": [ - { "key": "selector", "operand": "text.ejs.questionmark - source.js", "match_all": true }, + { "key": "selector", "operand": "text.html.ejs.questionmark - text.html.ejs source.js", "match_all": true }, { "key": "setting.auto_match_enabled", "operand": true }, { "key": "selection_empty", "operand": true, "match_all": true }, { "key": "preceding_text", "operator": "regex_contains", "operand": "<$", "match_all": true }, - { "key": "following_text", "operator": "not_regex_contains", "operand": "^[?=_#>-]", "match_all": true } - ] - }, - // <$ $> - { "keys": ["$"], "command": "insert_snippet", "args": {"contents": "\\$${0: }\\$>"}, "context": - [ - { "key": "selector", "operand": "text.ejs.dollarsign - source.js", "match_all": true }, - { "key": "setting.auto_match_enabled", "operand": true }, - { "key": "selection_empty", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "<$", "match_all": true }, - { "key": "following_text", "operator": "not_regex_contains", "operand": "^[$=_#>-]", "match_all": true } - ] - }, - // <@ @> - { "keys": ["@"], "command": "insert_snippet", "args": {"contents": "@${0: }@>"}, "context": - [ - { "key": "selector", "operand": "text.ejs.atsign - source.js", "match_all": true }, - { "key": "setting.auto_match_enabled", "operand": true }, - { "key": "selection_empty", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "<$", "match_all": true }, - { "key": "following_text", "operator": "not_regex_contains", "operand": "^[@=_#>-]", "match_all": true } + { "key": "following_text", "operator": "not_regex_contains", "operand": "^[%=_#>-]", "match_all": true } ] }, + // Auto-indent // <% %> { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "\n\t$0\n"}, "context": [ - { "key": "selector", "operand": "text.ejs.percentsign - source.js", "match_all": true }, + { "key": "selector", "operand": "text.html.ejs", "match_all": true }, { "key": "setting.auto_indent", "operand": true }, { "key": "selection_empty", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "<%(?!%)[=_#-]?\\s*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^[_-]?%>", "match_all": true } - ] - }, - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "\n\t$0\n"}, "context": - [ - { "key": "selector", "operand": "text.ejs.percentsign punctuation.definition.js.end.ejs", "match_all": true }, - { "key": "setting.auto_indent", "operand": true }, - { "key": "selection_empty", "operand": false, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "<%(?!%)[=_#-]?\\s*$", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "<%[#=_-]?\\s*$", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*[_-]?%>", "match_all": true } ] }, // { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "\n\t$0\n"}, "context": [ - { "key": "selector", "operand": "text.ejs.questionmark - source.js", "match_all": true }, + { "key": "selector", "operand": "text.html.ejs.questionmark", "match_all": true }, { "key": "setting.auto_indent", "operand": true }, { "key": "selection_empty", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "<\\?(?!\\?)[=_#-]?\\s*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^[_-]?\\?>", "match_all": true } - ] - }, - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "\n\t$0\n"}, "context": - [ - { "key": "selector", "operand": "text.ejs.questionmark punctuation.definition.js.end.ejs", "match_all": true }, - { "key": "setting.auto_indent", "operand": true }, - { "key": "selection_empty", "operand": false, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "<\\?(?!\\?)[=_#-]?\\s*$", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "<\\?[#=_-]?\\s*$", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*[_-]?\\?>", "match_all": true } ] }, - // <$ $> - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "\n\t$0\n"}, "context": - [ - { "key": "selector", "operand": "text.ejs.dollarsign - source.js", "match_all": true }, - { "key": "setting.auto_indent", "operand": true }, - { "key": "selection_empty", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "<\\$(?!\\$)[=_#-]?\\s*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^[_-]?\\$>", "match_all": true } - ] - }, - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "\n\t$0\n"}, "context": - [ - { "key": "selector", "operand": "text.ejs.dollarsign punctuation.definition.js.end.ejs", "match_all": true }, - { "key": "setting.auto_indent", "operand": true }, - { "key": "selection_empty", "operand": false, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "<\\$(?!\\$)[=_#-]?\\s*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*[_-]?\\$>", "match_all": true } - ] - }, - // <@ @> - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "\n\t$0\n"}, "context": - [ - { "key": "selector", "operand": "text.ejs.atsign - source.js", "match_all": true }, - { "key": "setting.auto_indent", "operand": true }, - { "key": "selection_empty", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "<@(?!@)[=_#-]?\\s*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^[_-]?@>", "match_all": true } - ] - }, - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "\n\t$0\n"}, "context": - [ - { "key": "selector", "operand": "text.ejs.atsign punctuation.definition.js.end.ejs", "match_all": true }, - { "key": "setting.auto_indent", "operand": true }, - { "key": "selection_empty", "operand": false, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "<@(?!@)[=_#-]?\\s*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*[_-]?@>", "match_all": true } - ] - } ] diff --git a/Dracula EJS.YAML-tmTheme b/Dracula EJS.YAML-tmTheme deleted file mode 100644 index cc94838..0000000 --- a/Dracula EJS.YAML-tmTheme +++ /dev/null @@ -1,288 +0,0 @@ -# [PackageDev] target_format: plist, ext: tmTheme -name: Dracula - -colorSpaceName: sRGB - -settings: -- settings: - activeGuide: '#9d550fb0' - background: '#202122' - bracketContentsForeground: '#f8f8f2a5' - bracketContentsOptions: underline - bracketsForeground: '#f8f8f2a5' - bracketsOptions: underline - caret: '#f8f8f0' - findHighlight: '#effb7b' - findHighlightForeground: '#000000' - foreground: '#f8f8f0' - # invisibles: '#f8f8f259' - lineHighlight: '#33353a' - selection: '#383a40' - selectionBorder: '#222218' - tagsOptions: stippled_underline - -- name: Comment - scope: comment - settings: - fontStyle: '' - foreground: '#6272a4' - -- name: String - scope: string - settings: - foreground: '#f1fa8c' - -- name: Number - scope: constant.numeric - settings: - foreground: '#bd93f9' - -- name: Built-in constant - scope: constant.language - settings: - foreground: '#bd93f9' - -- name: User-defined constant - scope: constant.character, constant.other - settings: - foreground: '#bd93f9' - -- name: Variable - scope: variable - settings: - fontStyle: '' - -- name: Keyword - scope: keyword - (source.c keyword.operator | source.c++ keyword.operator | source.objc keyword.operator | source.objc++ keyword.operator), keyword.operator.word - settings: - foreground: '#ff79c6' - -- name: Storage - scope: storage - settings: - fontStyle: '' - foreground: '#ff79c6' - -- name: Storage type - scope: storage.type - settings: - fontStyle: italic - foreground: '#8be9fd' - -- name: Entity name - scope: entity.name - (entity.name.filename | entity.name.section | entity.name.tag | entity.name.label | entity.name.type) - settings: - fontStyle: italic - foreground: '#50fa7b' - -- name: Inherited class - scope: entity.other.inherited-class - settings: - fontStyle: italic underline - foreground: '#50fa7b' - -- name: Function argument - scope: variable.parameter - (source.c | source.c++ | source.objc | source.objc++) - settings: - fontStyle: italic - foreground: '#ffb86c' - -- name: Language variable - scope: variable.language - settings: - fontStyle: italic - foreground: '#8be9fd' - -- name: Tag name - scope: entity.name.tag - settings: - fontStyle: '' - foreground: '#ff79c6' - -- name: Tag attribute - scope: entity.other.attribute-name - settings: - fontStyle: '' - foreground: '#50fa7b' - -- name: CSS pseudo class/element - scope: (entity.other.pseudo-class | entity.other.pseudo-element) - entity.other invalid - settings: - fontStyle: '' - foreground: '#50fa7b' - -- name: Function call - scope: variable.function - settings: - foreground: '#50fa7b' - -- name: Library function - scope: support.function - settings: - fontStyle: '' - foreground: '#8be9fd' - -- name: Library constant - scope: support.constant - settings: - fontStyle: '' - foreground: '#8be9fd' - -- name: Library type/built-in classes - scope: support.type, support.class.builtin, support.class.error - settings: - fontStyle: italic - foreground: '#8be9fd' - -- name: Library variable - scope: support.other.variable - settings: - fontStyle: '' - -- name: Invalid - scope: invalid - settings: - background: '#ff79c6' - fontStyle: '' - foreground: '#f8f8f0' - -- name: Invalid deprecated - scope: invalid.deprecated - settings: - background: '#bd93f9' - foreground: '#f8f8f0' - -- name: JSON String - scope: meta.structure.dictionary.json string.quoted.double.json - settings: - foreground: '#8be9fd' - -- name: YAML String - scope: string.unquoted.yaml - settings: - foreground: '#f8f8f0' - -- name: diff.header - scope: meta.diff, meta.diff.header - settings: - foreground: '#6272a4' - -- name: diff.deleted - scope: markup.deleted - settings: - foreground: '#ff79c6' - -- name: diff.inserted - scope: markup.inserted - settings: - foreground: '#50fa7b' - -- name: diff.changed - scope: markup.changed - settings: - foreground: '#f1fa8c' - -- scope: constant.numeric.line-number.find-in-files - match - settings: - foreground: '#bd93f9' - -- scope: entity.name.filename - settings: - foreground: '#f1fa8c' - -- scope: message.error - settings: - foreground: '#ff5555' - -################################################################################ -## Not defined in Monokai -################################################################################ - -- name: Flow - scope: meta.flowtype - settings: - background: '#282c33' - -- name: Flow - scope: punctuation.separator.flowtype, punctuation.section.flowtype - settings: - fontStyle: bold - -- name: Function name - scope: entity.name.function - entity.name.function.constructor - settings: - fontStyle: '' - foreground: '#50fa7b' - -- name: String contents - scope: constant.character.escape - settings: - foreground: '#ff79c6' - -- name: JSON Punctuation - scope: punctuation.definition.string.begin.json, punctuation.definition.string.end.json - settings: - foreground: '#f8f8f0' - -- name: JSON String - scope: meta.structure.dictionary.value.json string.quoted.double.json - settings: - foreground: '#f1fa8c' - -################################################################################ -## More highlighting for Flow -################################################################################ - -- name: Flow type operator - scope: punctuation.separator.type, meta.type.object punctuation.separator.key-value - settings: - foreground: '#ff79c6' - -- name: Flow types - scope: support.type.primitive, support.type.any, support.type.mixed - settings: - fontStyle: '' - foreground: '#bd93f9' - -################################################################################ -## Make highlighting look more like babel-sublime -################################################################################ - -- name: Dot accessor - scope: punctuation.accessor - settings: - foreground: '#ff79c6' - -- name: Template string expression punctuation - scope: punctuation.section.interpolation - settings: - foreground: '#ff79c6' - -- name: Object key-value separator - scope: meta.object-literal punctuation.separator.key-value - settings: - foreground: '#bd93f9' - -- name: Constructor call - scope: meta.function-call.constructor variable.type - settings: - foreground: '#50fa7b' - -################################################################################ -## EJS fixes -################################################################################ - -- name: JS Embedded in HTML String - scope: text.html string.quoted source.js - settings: - foreground: '#f8f8f0' - -- name: JS Quoted String - scope: string.quoted.js - settings: - foreground: '#f1fa8c' - -- name: JS Template String - scope: string.interpolated.js - settings: - foreground: '#f1fa8c' diff --git a/Dracula EJS.tmTheme b/Dracula EJS.tmTheme deleted file mode 100644 index 300f887..0000000 --- a/Dracula EJS.tmTheme +++ /dev/null @@ -1,593 +0,0 @@ - - - - - colorSpaceName - sRGB - name - Dracula - settings - - - settings - - activeGuide - #9d550fb0 - background - #202122 - bracketContentsForeground - #f8f8f2a5 - bracketContentsOptions - underline - bracketsForeground - #f8f8f2a5 - bracketsOptions - underline - caret - #f8f8f0 - findHighlight - #effb7b - findHighlightForeground - #000000 - foreground - #f8f8f0 - lineHighlight - #33353a - selection - #383a40 - selectionBorder - #222218 - tagsOptions - stippled_underline - - - - name - Comment - scope - comment - settings - - fontStyle - - foreground - #6272a4 - - - - name - String - scope - string - settings - - foreground - #f1fa8c - - - - name - Number - scope - constant.numeric - settings - - foreground - #bd93f9 - - - - name - Built-in constant - scope - constant.language - settings - - foreground - #bd93f9 - - - - name - User-defined constant - scope - constant.character, constant.other - settings - - foreground - #bd93f9 - - - - name - Variable - scope - variable - settings - - fontStyle - - - - - name - Keyword - scope - keyword - (source.c keyword.operator | source.c++ keyword.operator | source.objc keyword.operator | source.objc++ keyword.operator), keyword.operator.word - settings - - foreground - #ff79c6 - - - - name - Storage - scope - storage - settings - - fontStyle - - foreground - #ff79c6 - - - - name - Storage type - scope - storage.type - settings - - fontStyle - italic - foreground - #8be9fd - - - - name - Entity name - scope - entity.name - (entity.name.filename | entity.name.section | entity.name.tag | entity.name.label | entity.name.type) - settings - - fontStyle - italic - foreground - #50fa7b - - - - name - Inherited class - scope - entity.other.inherited-class - settings - - fontStyle - italic underline - foreground - #50fa7b - - - - name - Function argument - scope - variable.parameter - (source.c | source.c++ | source.objc | source.objc++) - settings - - fontStyle - italic - foreground - #ffb86c - - - - name - Language variable - scope - variable.language - settings - - fontStyle - italic - foreground - #8be9fd - - - - name - Tag name - scope - entity.name.tag - settings - - fontStyle - - foreground - #ff79c6 - - - - name - Tag attribute - scope - entity.other.attribute-name - settings - - fontStyle - - foreground - #50fa7b - - - - name - CSS pseudo class/element - scope - (entity.other.pseudo-class | entity.other.pseudo-element) - entity.other invalid - settings - - fontStyle - - foreground - #50fa7b - - - - name - Function call - scope - variable.function - settings - - foreground - #50fa7b - - - - name - Library function - scope - support.function - settings - - fontStyle - - foreground - #8be9fd - - - - name - Library constant - scope - support.constant - settings - - fontStyle - - foreground - #8be9fd - - - - name - Library type/built-in classes - scope - support.type, support.class.builtin, support.class.error - settings - - fontStyle - italic - foreground - #8be9fd - - - - name - Library variable - scope - support.other.variable - settings - - fontStyle - - - - - name - Invalid - scope - invalid - settings - - background - #ff79c6 - fontStyle - - foreground - #f8f8f0 - - - - name - Invalid deprecated - scope - invalid.deprecated - settings - - background - #bd93f9 - foreground - #f8f8f0 - - - - name - JSON String - scope - meta.structure.dictionary.json string.quoted.double.json - settings - - foreground - #8be9fd - - - - name - YAML String - scope - string.unquoted.yaml - settings - - foreground - #f8f8f0 - - - - name - diff.header - scope - meta.diff, meta.diff.header - settings - - foreground - #6272a4 - - - - name - diff.deleted - scope - markup.deleted - settings - - foreground - #ff79c6 - - - - name - diff.inserted - scope - markup.inserted - settings - - foreground - #50fa7b - - - - name - diff.changed - scope - markup.changed - settings - - foreground - #f1fa8c - - - - scope - constant.numeric.line-number.find-in-files - match - settings - - foreground - #bd93f9 - - - - scope - entity.name.filename - settings - - foreground - #f1fa8c - - - - scope - message.error - settings - - foreground - #ff5555 - - - - name - Flow - scope - meta.flowtype - settings - - background - #282c33 - - - - name - Flow - scope - punctuation.separator.flowtype, punctuation.section.flowtype - settings - - fontStyle - bold - - - - name - Function name - scope - entity.name.function - entity.name.function.constructor - settings - - fontStyle - - foreground - #50fa7b - - - - name - String contents - scope - constant.character.escape - settings - - foreground - #ff79c6 - - - - name - JSON Punctuation - scope - punctuation.definition.string.begin.json, punctuation.definition.string.end.json - settings - - foreground - #f8f8f0 - - - - name - JSON String - scope - meta.structure.dictionary.value.json string.quoted.double.json - settings - - foreground - #f1fa8c - - - - name - Flow type operator - scope - punctuation.separator.type, meta.type.object punctuation.separator.key-value - settings - - foreground - #ff79c6 - - - - name - Flow types - scope - support.type.primitive, support.type.any, support.type.mixed - settings - - fontStyle - - foreground - #bd93f9 - - - - name - Dot accessor - scope - punctuation.accessor - settings - - foreground - #ff79c6 - - - - name - Template string expression punctuation - scope - punctuation.section.interpolation - settings - - foreground - #ff79c6 - - - - name - Object key-value separator - scope - meta.object-literal punctuation.separator.key-value - settings - - foreground - #bd93f9 - - - - name - Constructor call - scope - meta.function-call.constructor variable.type - settings - - foreground - #50fa7b - - - - name - JS Embedded in HTML String - scope - text.html string.quoted source.js - settings - - foreground - #f8f8f0 - - - - name - JS Quoted String - scope - string.quoted.js - settings - - foreground - #f1fa8c - - - - name - JS Template String - scope - string.interpolated.js - settings - - foreground - #f1fa8c - - - - - diff --git a/EJS ($).sublime-syntax b/EJS ($).sublime-syntax deleted file mode 100644 index b44d621..0000000 --- a/EJS ($).sublime-syntax +++ /dev/null @@ -1,10 +0,0 @@ -%YAML 1.2 ---- -name: EJS (<$ $>) -version: 2 -first_line_match: ^<\$ -scope: text.ejs.dollarsign -extends: Packages/EJS 2/EJS.sublime-syntax - -variables: - delimiter: '\$' diff --git a/EJS (@).sublime-syntax b/EJS (@).sublime-syntax deleted file mode 100644 index ec8409d..0000000 --- a/EJS (@).sublime-syntax +++ /dev/null @@ -1,10 +0,0 @@ -%YAML 1.2 ---- -name: EJS (<@ @>) -version: 2 -first_line_match: ^<@ -scope: text.ejs.atsign -extends: Packages/EJS 2/EJS.sublime-syntax - -variables: - delimiter: '@' diff --git a/EJS (Q) - Comments.tmPreferences b/EJS (Q) - Comments.tmPreferences new file mode 100644 index 0000000..fb97e49 --- /dev/null +++ b/EJS (Q) - Comments.tmPreferences @@ -0,0 +1,37 @@ + + + + scope + text.html.ejs.questionmark + settings + + shellVariables + + + name + TM_COMMENT_START + value + + + + name + TM_COMMENT_END + value + ]]> + + + name + TM_COMMENT_START_2 + value + + + + name + TM_COMMENT_END_2 + value + ]]> + + + + + diff --git a/EJS (Q) - Snippet Variables.tmPreferences b/EJS (Q) - Snippet Variables.tmPreferences new file mode 100644 index 0000000..935970a --- /dev/null +++ b/EJS (Q) - Snippet Variables.tmPreferences @@ -0,0 +1,32 @@ + + + + scope + text.html.ejs.questionmark + settings + + shellVariables + + + + name + TM_TEMPLATE_INDENT + value + + + + name + TM_TEMPLATE_START + value + + + + name + TM_TEMPLATE_END + value + ]]> + + + + + diff --git a/EJS (Q).sublime-syntax b/EJS (Q).sublime-syntax index a354f1f..2f6ea15 100644 --- a/EJS (Q).sublime-syntax +++ b/EJS (Q).sublime-syntax @@ -1,10 +1,41 @@ %YAML 1.2 --- +# https://github.com/mde/ejs name: EJS () +scope: text.html.ejs.questionmark version: 2 -first_line_match: ^<\? -scope: text.ejs.questionmark -extends: Packages/EJS 2/EJS.sublime-syntax + +extends: EJS.sublime-syntax variables: - delimiter: '\?' + + ejs_delimiter: '\?' + +contexts: + + style-css-content: + - meta_include_prototype: false + - match: '{{style_content_begin}}' + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 # make sure to match only once + embed: scope:source.css.embedded.html.ejs.questionmark + embed_scope: source.css.embedded.html + escape: '{{style_content_end}}' + escape_captures: + 1: source.css.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.css.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + + tag-style-attribute-double-quoted-value-content: + - include: scope:source.css.embedded.html.ejs.questionmark.double-quoted + apply_prototype: true + + tag-style-attribute-single-quoted-value-content: + - include: scope:source.css.embedded.html.ejs.questionmark.single-quoted + apply_prototype: true + + ejs-content: + - include: JavaScript (for EJS Q).sublime-syntax + apply_prototype: true diff --git a/EJS - Comments.tmPreferences b/EJS - Comments.tmPreferences new file mode 100644 index 0000000..d58da5d --- /dev/null +++ b/EJS - Comments.tmPreferences @@ -0,0 +1,37 @@ + + + + scope + text.html.ejs + settings + + shellVariables + + + name + TM_COMMENT_START + value + + + + name + TM_COMMENT_END + value + ]]> + + + name + TM_COMMENT_START_2 + value + + + + name + TM_COMMENT_END_2 + value + ]]> + + + + + diff --git a/EJS - Snippet Variables.tmPreferences b/EJS - Snippet Variables.tmPreferences new file mode 100644 index 0000000..039d2c1 --- /dev/null +++ b/EJS - Snippet Variables.tmPreferences @@ -0,0 +1,32 @@ + + + + scope + text.html.ejs + settings + + shellVariables + + + + name + TM_TEMPLATE_INDENT + value + + + + name + TM_TEMPLATE_START + value + + + + name + TM_TEMPLATE_END + value + ]]> + + + + + diff --git a/EJS.sublime-syntax b/EJS.sublime-syntax index 36defca..ecdd00a 100644 --- a/EJS.sublime-syntax +++ b/EJS.sublime-syntax @@ -1,31 +1,151 @@ %YAML 1.2 --- -name: EJS (<% %>) +# https://github.com/mde/ejs +name: EJS <% %> +scope: text.html.ejs version: 2 -file_extensions: [ejs] -first_line_match: ^<% -scope: text.ejs.percentsign + +extends: Packages/HTML/HTML.sublime-syntax + +file_extensions: + - ejs variables: - delimiter: '%' + + # HTML variables + + tag_name_start: (?:[A-Za-z]|{{ejs_tag_start}}) + + # EJS variables + + ejs_delimiter: '%' + + ejs_commet_start: '<{{ejs_delimiter}}#' + ejs_tag_start: '<{{ejs_delimiter}}(?:[=_-]|(?!{{ejs_delimiter}}[^>]))' + ejs_tag_end: '[_-]?{{ejs_delimiter}}>' contexts: - main: - - match: '' - push: Packages/HTML/HTML.sublime-syntax - with_prototype: - - match: '<{{delimiter}}#' - scope: punctuation.definition.comment.begin.ejs - push: comment - - match: '<{{delimiter}}(?!{{delimiter}})[=_-]?' - scope: keyword.operator.delimiter.ejs, punctuation.definition.js.begin.ejs - embed: scope:source.js - embed_scope: source.js.embedded.ejs - escape: '[_-]?{{delimiter}}>' - escape_captures: - 0: keyword.operator.delimiter.ejs, punctuation.definition.js.end.ejs - comment: - - meta_scope: comment.block.ejs - - match: '{{delimiter}}>' + +###[ HTML OVERRIDES ]######################################################### + + prototype: + - meta_prepend: true + - include: ejs-embedded + + tag-other: + # required until PR #3980 (ST 4175) + - match: + + + scope + text.html.ejs source.css + settings + + shellVariables + + + name + TM_COMMENT_START + value + + + + name + TM_COMMENT_END + value + ]]> + + + name + TM_COMMENT_START_2 + value + + + + name + TM_COMMENT_END_2 + value + + + + + + diff --git a/Embeddings/CSS (for EJS P).sublime-syntax b/Embeddings/CSS (for EJS P).sublime-syntax new file mode 100644 index 0000000..8f94732 --- /dev/null +++ b/Embeddings/CSS (for EJS P).sublime-syntax @@ -0,0 +1,101 @@ +%YAML 1.2 +--- +scope: source.css.embedded.html.ejs +version: 2 +hidden: true + +extends: Packages/CSS/CSS.sublime-syntax + +variables: + + # CSS variables + + ident_start: (?:{{nmstart}}|{{ejs_tag_start}}) + + # EJS variables + + ejs_delimiter: '%' + + ejs_commet_start: '<{{ejs_delimiter}}#' + ejs_tag_start: '<{{ejs_delimiter}}(?:[=_-]|(?!{{ejs_delimiter}}[^>]))' + ejs_tag_end: '[_-]?{{ejs_delimiter}}>' + +contexts: + prototype: + - meta_prepend: true + - include: ejs-embedded + + block-comment-body: + - meta_prepend: true + - meta_include_prototype: false + - include: ejs-interpolations + + string-content: + - meta_prepend: true + - include: ejs-interpolations + + at-supports-group-body: + # required until PR #3785 (ST 4157) + - meta_prepend: true + - meta_include_prototype: false + + property-list-body: + # required until PR #3785 (ST 4157) + - meta_prepend: true + - meta_include_prototype: false + + stylesheet-block-body: + # required until PR #3785 (ST 4157) + - meta_prepend: true + - meta_include_prototype: false + +###[ EJS TAGS ]############################################################### + + ejs-embedded: + - match: '{{ejs_commet_start}}' + scope: punctuation.definition.comment.begin.ejs + push: ejs-embedded-comment-body + - match: '{{ejs_tag_start}}' + scope: punctuation.section.embedded.begin.ejs + push: ejs-embedded-body + + ejs-embedded-comment-body: + - meta_include_prototype: false + - meta_scope: meta.embedded.ejs comment.block.ejs + - match: '{{ejs_tag_end}}' + scope: punctuation.definition.comment.end.ejs + pop: 1 + + ejs-embedded-body: + - meta_include_prototype: false + - meta_scope: meta.embedded.ejs + - meta_content_scope: source.js.embedded.ejs + - match: '{{ejs_tag_end}}' + scope: punctuation.section.embedded.end.ejs + pop: 1 + - include: ejs-content + + ejs-interpolations: + - match: '{{ejs_commet_start}}' + scope: punctuation.definition.comment.begin.ejs + push: ejs-interpolation-comment-body + - match: '{{ejs_tag_start}}' + scope: punctuation.section.embedded.begin.ejs + push: ejs-interpolation-body + + ejs-interpolation-comment-body: + - clear_scopes: 1 + - meta_include_prototype: false + - meta_scope: meta.embedded.ejs comment.block.ejs + - include: ejs-embedded-comment-body + + ejs-interpolation-body: + - clear_scopes: 1 + - meta_include_prototype: false + - meta_scope: meta.embedded.ejs + - meta_content_scope: source.js.embedded.ejs + - include: ejs-embedded-body + + ejs-content: + - include: JavaScript (for CSS EJS P).sublime-syntax + apply_prototype: true diff --git a/Embeddings/CSS (for EJS Q double-quoted).sublime-syntax b/Embeddings/CSS (for EJS Q double-quoted).sublime-syntax new file mode 100644 index 0000000..637cf22 --- /dev/null +++ b/Embeddings/CSS (for EJS Q double-quoted).sublime-syntax @@ -0,0 +1,9 @@ +%YAML 1.2 +--- +scope: source.css.embedded.html.ejs.questionmark.double-quoted +version: 2 +hidden: true + +extends: + - CSS (for EJS P double-quoted).sublime-syntax + - CSS (for EJS Q).sublime-syntax diff --git a/Embeddings/CSS (for EJS Q single-quoted).sublime-syntax b/Embeddings/CSS (for EJS Q single-quoted).sublime-syntax new file mode 100644 index 0000000..107e263 --- /dev/null +++ b/Embeddings/CSS (for EJS Q single-quoted).sublime-syntax @@ -0,0 +1,9 @@ +%YAML 1.2 +--- +scope: source.css.embedded.html.ejs.questionmark.single-quoted +version: 2 +hidden: true + +extends: + - CSS (for EJS P single-quoted).sublime-syntax + - CSS (for EJS Q).sublime-syntax diff --git a/Embeddings/CSS (for EJS Q) - Comments.tmPreferences b/Embeddings/CSS (for EJS Q) - Comments.tmPreferences new file mode 100644 index 0000000..24367f3 --- /dev/null +++ b/Embeddings/CSS (for EJS Q) - Comments.tmPreferences @@ -0,0 +1,37 @@ + + + + scope + text.html.ejs.questionmark source.css + settings + + shellVariables + + + name + TM_COMMENT_START + value + + + + name + TM_COMMENT_END + value + ]]> + + + name + TM_COMMENT_START_2 + value + + + + name + TM_COMMENT_END_2 + value + + + + + + diff --git a/Embeddings/CSS (for EJS Q).sublime-syntax b/Embeddings/CSS (for EJS Q).sublime-syntax new file mode 100644 index 0000000..09a4b9f --- /dev/null +++ b/Embeddings/CSS (for EJS Q).sublime-syntax @@ -0,0 +1,19 @@ +%YAML 1.2 +--- +scope: source.css.embedded.html.ejs.questionmark +version: 2 +hidden: true + +extends: CSS (for EJS P).sublime-syntax + +variables: + + # EJS variables + + ejs_delimiter: '\?' + +contexts: + + ejs-content: + - include: JavaScript (for CSS EJS Q).sublime-syntax + apply_prototype: true diff --git a/Embeddings/JavaScript (for CSS EJS P).sublime-syntax b/Embeddings/JavaScript (for CSS EJS P).sublime-syntax new file mode 100644 index 0000000..58e9d76 --- /dev/null +++ b/Embeddings/JavaScript (for CSS EJS P).sublime-syntax @@ -0,0 +1,36 @@ +%YAML 1.2 +--- +scope: source.js.embedded.css.ejs +version: 2 +hidden: true + +extends: Packages/JavaScript/JavaScript.sublime-syntax + +variables: + + # EJS variables + + ejs_delimiter: '%' + + ejs_commet_start: '<{{ejs_delimiter}}#' + ejs_tag_start: '<{{ejs_delimiter}}(?:[=_-]|(?!{{ejs_delimiter}}[^>]))' + ejs_tag_end: '[_-]?{{ejs_delimiter}}>' + +contexts: + + prototype: + - meta_prepend: true + - match: (?={{ejs_tag_end}}) + pop: 1 + + main: + - include: script + + script: + - meta_prepend: true + - match: \} + scope: punctuation.section.block.end.js + - match: \] + scope: punctuation.section.brackets.end.js + - match: \) + scope: punctuation.section.group.end.js diff --git a/Embeddings/JavaScript (for CSS EJS Q).sublime-syntax b/Embeddings/JavaScript (for CSS EJS Q).sublime-syntax new file mode 100644 index 0000000..ceef8e7 --- /dev/null +++ b/Embeddings/JavaScript (for CSS EJS Q).sublime-syntax @@ -0,0 +1,13 @@ +%YAML 1.2 +--- +scope: source.js.embedded.css.ejs.questionmark +version: 2 +hidden: true + +extends: JavaScript (for CSS EJS P).sublime-syntax + +variables: + + # EJS variables + + ejs_delimiter: '\?' diff --git a/Embeddings/JavaScript (for EJS P).sublime-syntax b/Embeddings/JavaScript (for EJS P).sublime-syntax new file mode 100644 index 0000000..b719a92 --- /dev/null +++ b/Embeddings/JavaScript (for EJS P).sublime-syntax @@ -0,0 +1,75 @@ +%YAML 1.2 +--- +scope: source.js.embedded.html.ejs +version: 2 +hidden: true + +extends: Packages/JavaScript/JavaScript.sublime-syntax + +variables: + + # EJS variables + + ejs_delimiter: '%' + + ejs_commet_start: '<{{ejs_delimiter}}#' + ejs_tag_start: '<{{ejs_delimiter}}(?:[=_-]|(?!{{ejs_delimiter}}[^>]))' + ejs_tag_end: '[_-]?{{ejs_delimiter}}>' + +contexts: + + main: + - include: script + + script: + - meta_prepend: true + - match: \} + scope: punctuation.section.block.end.js + - match: \] + scope: punctuation.section.brackets.end.js + - match: \) + scope: punctuation.section.group.end.js + + statements: + # if in nested context, push nested HTML syntax + - meta_prepend: true + - include: nested-ejs + + statement: + - meta_prepend: true + - match: (?={{ejs_tag_end}}) + pop: 1 + + expression-begin: + # if in nested context, push nested HTML syntax + - meta_prepend: true + - include: nested-ejs + + expression-end: + - meta_prepend: true + - match: (?={{ejs_tag_end}}) + pop: 1 + + string-content: + # if in nested context, push nested HTML syntax + - meta_prepend: true + - include: nested-ejs + + nested-ejs: + - match: '{{ejs_tag_end}}' + scope: punctuation.section.embedded.end.ejs + push: nested-ejs-body + + nested-ejs-body: + - clear_scopes: true + - meta_include_prototype: false + - meta_scope: text.html.ejs.percentsign meta.embedded.ejs + - meta_content_scope: source.js.embedded.ejs + - match: '{{ejs_tag_start}}' + scope: punctuation.section.embedded.begin.ejs + pop: 1 + - include: ejs-content + + ejs-content: + - include: EJS.sublime-syntax + apply_prototype: true diff --git a/Embeddings/JavaScript (for EJS Q).sublime-syntax b/Embeddings/JavaScript (for EJS Q).sublime-syntax new file mode 100644 index 0000000..61a5391 --- /dev/null +++ b/Embeddings/JavaScript (for EJS Q).sublime-syntax @@ -0,0 +1,19 @@ +%YAML 1.2 +--- +scope: source.js.embedded.html.ejs.questionmark +version: 2 +hidden: true + +extends: JavaScript (for EJS P).sublime-syntax + +variables: + + # EJS variables + + ejs_delimiter: '\?' + +contexts: + + ejs-content: + - include: EJS (Q).sublime-syntax + apply_prototype: true diff --git a/LICENSE.txt b/LICENSE similarity index 100% rename from LICENSE.txt rename to LICENSE diff --git a/README.md b/README.md index f9856ef..97b5d25 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,33 @@ -# EJS 2 +# EJS -[EJS](http://ejs.co/) syntax definition for Sublime Text 3 & 4. Includes EJS tag autocompletion and snippets. +[EJS](http://ejs.co/) syntax definition for Sublime Text based on its HTML, CSS and JavaScript syntax definitions. + +Supported template tag variants are: `<% %>`. ``. + +![preview](preview.png) ## Installation -Use [Package Control](https://packagecontrol.io/docs/usage) to install [**EJS 2**](https://packagecontrol.io/packages/EJS%202). +### Package Control + +The easiest way to install is using [Package Control](https://packagecontrol.io). It's listed as `EJS`. + +1. Open `Command Palette` using ctrl+shift+P or menu item `Tools → Command Palette...` +2. Choose `Package Control: Install Package` +3. Find `EJS` and hit Enter + +### Manual Install + +1. Download appropriate [EJS.sublime-package](https://github.com/SublimeText/EJS/releases) for your Sublime Text build. +2. Copy it into _Installed Packages_ directory + +> [!NOTE] +> +> To find _Installed Packages_... +> +> 1. call _Menu > Preferences > Browse Packages.._ +> 2. Navigate to parent folder + ### Setting the default syntax @@ -17,27 +40,45 @@ To open files with a different extension as EJS, or to use delimiters other than 3. Then select: `Syntax` → `Open all with current extension as...` → `EJS 2` → `EJS ()` 4. Repeat for each extension you want to open as EJS -This package includes syntax definitions for the following additional delimiters: ``, `<$ $>`, `<@ @>`. +## Snippets -### Color Scheme +In the HTML scope: -`EJS 2` comes with the `Dracula EJS` color scheme, which is a modified/updated version of [zertosh](https://github.com/zertosh)’s old dracula theme. You can select it from: `Preferences` → `Color Scheme`. ++ `if`+`TAB` - Inserts EJS `if` statement ++ `for`+`TAB` - Inserts EJS `for` loop -[`Oceanic Next`](https://github.com/voronianski/oceanic-next-color-scheme) is also a good color scheme for EJS that works right out of the box. +## Troubleshooting -If you'd prefer to use a different color scheme, you may need to add lines like [these](https://github.com/nwoltman/sublime-ejs/blob/a7cceaf26f3c3dd0ea4d64f9303c95d632f9d9e4/Dracula%20EJS.YAML-tmTheme#L273-L286) to make the highlighting more compatible with EJS. +### §1 Syntax Definition Parse Errors -#### Preview (with *Dracula EJS*) +EJS extends Sublime Text's HTML, CSS and JavaScript syntax definition. -![](example.png) +If EJS syntax highlighting doesn't work +and console displays syntax errors in _Vue Component.sublime-syntax_, +please make sure to remove any out-dated syntax override. -### Snippets +Steps: -In the HTML scope: +1. call _Menu > Preferences > Browse Packages.._ +2. Look for _HTML_, _CSS_ or _JavaScript_ folder +3. Remove them or at least delete any syntax definition in it. -+ `if`+`TAB` - Inserts EJS `if` statement -+ `for`+`TAB` - Inserts EJS `for` loop +### §2 Scripts are not correctly highlighted + +EJS relies on JavaScript (`source.js`) +to scope script blocks and inline scripts. + +Make sure to remove related out-dated syntax packages, +which don't meet least compatibility requirements. + +They can be identified by calling +e.g. `sublime.find_syntax_by_scope("source.js")` in ST's console. + +Known candidates are: + +- [JavaScriptNext - ES6 Syntax](https://packagecontrol.io/packages/JavaScriptNext%20-%20ES6%20Syntax) +- [Naomi](https://github.com/borela/naomi) ## Contributing -Most problems are best addressed by opening an [issue](https://github.com/nwoltman/sublime-ejs/issues). +Most problems are best addressed by opening an [issue](https://github.com/SublimeText/EJS/issues). diff --git a/example.png b/example.png deleted file mode 100644 index 1d076d9..0000000 Binary files a/example.png and /dev/null differ diff --git a/preview.ejs b/preview.ejs new file mode 100644 index 0000000..1081d0f --- /dev/null +++ b/preview.ejs @@ -0,0 +1,27 @@ + + + + <%= locals.title %> + + <%# Styles %> + + <% + const styles = locals styles; + const stylesLength = styles ? styles.length : 0; + for (let i = 0; i < stylesLength; i++) { -%> + + <% } + -%> + + + + <%- include('body') -%> + <%- include core/footer %> + + + + diff --git a/preview.png b/preview.png new file mode 100644 index 0000000..196a4bf Binary files /dev/null and b/preview.png differ diff --git a/snippets/ejs-for-loop ($).sublime-snippet b/snippets/ejs-for-loop ($).sublime-snippet deleted file mode 100644 index ed004d8..0000000 --- a/snippets/ejs-for-loop ($).sublime-snippet +++ /dev/null @@ -1,10 +0,0 @@ - - - $2 -<\$ } -\$>$0 -]]> - for - text.ejs.dollarsign - source.js - <$ for (...) { -$> - diff --git a/snippets/ejs-for-loop (@).sublime-snippet b/snippets/ejs-for-loop (@).sublime-snippet deleted file mode 100644 index 4badd96..0000000 --- a/snippets/ejs-for-loop (@).sublime-snippet +++ /dev/null @@ -1,10 +0,0 @@ - - - $2 -<@ } -@>$0 -]]> - for - text.ejs.atsign - source.js - <@ for (...) { -@> - diff --git a/snippets/ejs-for-loop (Q).sublime-snippet b/snippets/ejs-for-loop (Q).sublime-snippet deleted file mode 100644 index e437988..0000000 --- a/snippets/ejs-for-loop (Q).sublime-snippet +++ /dev/null @@ -1,10 +0,0 @@ - - - $2 -$0 -]]> - for - text.ejs.questionmark - source.js - <? for (...) { -?> - diff --git a/snippets/ejs-for-loop.sublime-snippet b/snippets/ejs-for-loop.sublime-snippet index 3902dfd..6183b78 100644 --- a/snippets/ejs-for-loop.sublime-snippet +++ b/snippets/ejs-for-loop.sublime-snippet @@ -1,10 +1,10 @@ +${TM_TEMPLATE_START} for (var i = 0; i < ${1:length}; i++) { -${TM_TEMPLATE_END} $2 -<% } -%>$0 +${TM_TEMPLATE_START} } -${TM_TEMPLATE_END}$0 ]]> for - text.ejs.percentsign - source.js - <% for (...) { -%> + text.html.ejs - text.html.ejs source.js + <% for (...) { -%> diff --git a/snippets/ejs-if-else ($).sublime-snippet b/snippets/ejs-if-else ($).sublime-snippet deleted file mode 100644 index e3f8c37..0000000 --- a/snippets/ejs-if-else ($).sublime-snippet +++ /dev/null @@ -1,12 +0,0 @@ - - - $3${1: -<\$ \} else { -\$> - $4} -<\$ } -\$>$0 -]]> - if - text.ejs.dollarsign - source.js - <$ if () { $> <$ } else { $> - diff --git a/snippets/ejs-if-else (@).sublime-snippet b/snippets/ejs-if-else (@).sublime-snippet deleted file mode 100644 index baf78c1..0000000 --- a/snippets/ejs-if-else (@).sublime-snippet +++ /dev/null @@ -1,12 +0,0 @@ - - - $3${1: -<@ \} else { -@> - $4} -<@ } -@>$0 -]]> - if - text.ejs.atsign - source.js - <@ if () { @> <@ } else { @> - diff --git a/snippets/ejs-if-else (Q).sublime-snippet b/snippets/ejs-if-else (Q).sublime-snippet deleted file mode 100644 index 941a074..0000000 --- a/snippets/ejs-if-else (Q).sublime-snippet +++ /dev/null @@ -1,12 +0,0 @@ - - - $3${1: - - $4} -$0 -]]> - if - text.ejs.questionmark - source.js - <? if () { ?> <? } else { ?> - diff --git a/snippets/ejs-if-else.sublime-snippet b/snippets/ejs-if-else.sublime-snippet index 6a12634..6f73ccb 100644 --- a/snippets/ejs-if-else.sublime-snippet +++ b/snippets/ejs-if-else.sublime-snippet @@ -1,12 +1,12 @@ +${TM_TEMPLATE_START} if (${2:condition}) { -${TM_TEMPLATE_END} $3${1: -<% \} else { -%> +${TM_TEMPLATE_START} \} else { -${TM_TEMPLATE_END} $4} -<% } -%>$0 +${TM_TEMPLATE_START} } -${TM_TEMPLATE_END}$0 ]]> if - text.ejs.percentsign - source.js + text.html.ejs - text.html.ejs source.js <% if () { %> <% } else { %> diff --git a/tests/syntax_test_percent.ejs b/tests/syntax_test_percent.ejs new file mode 100644 index 0000000..d80f8dc --- /dev/null +++ b/tests/syntax_test_percent.ejs @@ -0,0 +1,285 @@ +/*SYNTAX TEST "EJS.sublime-syntax" */ + + <%#%> +/* ^^^^^ text.html - text.html text.html - source */ +/* ^^^^^ meta.embedded.ejs comment.block.ejs - meta.embedded meta.embedded */ +/* ^^^ punctuation.definition.comment.begin.ejs */ +/* ^^ punctuation.definition.comment.end.ejs */ + + <%# Comment tag, no execution, no output %> +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.ejs */ +/* ^^^ punctuation.definition.comment.begin.ejs */ +/* ^^ punctuation.definition.comment.end.ejs */ + + <%%> +/* ^^^^ text.html - text.html text.html - source */ +/* ^^^^ meta.embedded.ejs - meta.embedded meta.embedded */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^ punctuation.section.embedded.end.ejs */ + + <% "'Scriptlet' tag, for control-flow, no output" %> +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^ punctuation.section.embedded.end.ejs */ + <%_ " 'Whitespace Slurping' Scriptlet tag, strips all whitespace before it" _%> +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^ punctuation.section.embedded.end.ejs */ + <%= " Outputs the value into the template (escaped)" %> +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^ punctuation.section.embedded.end.ejs */ + + <%- " Outputs the unescaped value into the template" -%> +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^ punctuation.section.embedded.end.ejs */ + + <%% Literal tags %%> +/* ^^^^^^^^^^^^^^^^^^^^ - meta.embedded - punctuation */ + +<% if (user) { %> +/*^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* <- punctuation.section.embedded.begin.ejs */ +/*^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^^^^^^^^^^ meta.conditional.js */ +/* ^^ keyword.control.conditional.if.js */ +/* ^^^^^^ meta.group.js */ +/* ^ punctuation.section.group.begin.js */ +/* ^^^^ variable.other.readwrite.js */ +/* ^ punctuation.section.group.end.js */ +/* ^^ meta.block.js */ +/* ^ punctuation.section.block.begin.js */ +/* ^^ punctuation.section.embedded.end.ejs */ + +

<%= user.name %>

+/*^^^^ meta.tag.block.any.html */ +/*^ punctuation.definition.tag.begin.html */ +/* ^^ entity.name.tag.block.any.html */ +/* ^ punctuation.definition.tag.end.html */ +/* ^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^^ variable.other.readwrite.js */ +/* ^ punctuation.accessor.js */ +/* ^^^^ meta.property.object.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^^^^^ meta.tag.block.any.html */ +/* ^^ punctuation.definition.tag.begin.html */ +/* ^^ entity.name.tag.block.any.html */ +/* ^ punctuation.definition.tag.end.html */ + + ="class-<% name() %>" /> +/* ^^^^^^^^^^ meta.attribute-with-value.html entity.other.attribute-name.html meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^ variable.other */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^^^^^^^ meta.attribute-with-value.html meta.string.html string.quoted.double.html */ +/* ^^^^^^^^^^^^ meta.attribute-with-value.html meta.string.html meta.embedded.ejs */ +/* ^ meta.attribute-with-value.html meta.string.html string.quoted.double.html */ + + <<%tag%> <%attr%>=<%value%>> +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.tag.other.html */ +/*^ punctuation.definition.tag.begin.html */ +/* ^^^^^^^ entity.name.tag.other.html meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^ source.js.embedded.ejs variable.other.readwrite.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^^^^^^^^^^^^^^^^^^ meta.attribute-with-value.html */ +/* ^^^^^^^^ entity.other.attribute-name.html meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^ source.js.embedded.ejs variable.other.readwrite.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^ punctuation.separator.key-value.html */ +/* ^^^^^^^^^ meta.string.html meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^ source.js.embedded.ejs variable.other.readwrite.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^ punctuation.definition.tag.end.html */ + +<% } %> +/*^^^^^ meta.embedded.ejs */ +/* <- punctuation.section.embedded.begin.ejs */ +/*^^^ source.js.embedded.ejs */ +/* ^ punctuation.section.block.end.js */ +/* ^^ punctuation.section.embedded.end.ejs */ + +<% console.log("%> any text <%"); %> +/*^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* <- punctuation.section.embedded.begin.ejs */ +/*^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^^^^^ support.type.object.console.js */ +/* ^ punctuation.accessor.js */ +/* ^^^ meta.function-call support.function.console.js */ +/* ^^ meta.function-call meta.group.js */ +/* ^ punctuation.section.group.begin.js */ +/* ^ meta.string.js string.quoted.double.js punctuation.definition.string.begin.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^^^^^^^^ meta.tag.inline.any.html */ +/* ^ punctuation.definition.tag.begin.html */ +/* ^^^^^^ entity.name.tag.inline.any.html */ +/* ^ punctuation.definition.tag.end.html */ +/* ^^^^^^^^^ meta.tag.inline.any.html */ +/* ^^ punctuation.definition.tag.begin.html */ +/* ^^^^^^ entity.name.tag.inline.any.html */ +/* ^ punctuation.definition.tag.end.html */ +/* ^^^^^^^^ meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^ source.js.embedded.ejs */ +/* ^^ meta.function-call meta.group.js */ +/* ^ meta.string.js string.quoted.double.js punctuation.definition.string.end.js */ +/* ^ punctuation.section.group.end.js */ +/* ^ punctuation.terminator.statement.js */ +/* ^^ punctuation.section.embedded.end.ejs */ + + +/*<- meta.tag.style.end.html punctuation.definition.tag.begin.html */ +/*^^^^^^ meta.tag.style.end.html */ +/* <- punctuation.definition.tag.begin.html */ +/*^^^^^ entity.name.tag.style.html */ +/* ^ punctuation.definition.tag.end.html */ + +
"> +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.tag.block.any.html */ +/*^^ entity.name.tag.block.any.html */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.attribute-with-value.style.html */ +/* ^^^^^ entity.other.attribute-name.style.html */ +/* ^ punctuation.separator.key-value.html */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.html */ +/* ^ string.quoted.double.html punctuation.definition.string.begin.html */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.css.embedded.html */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^^^^^^ meta.brackets.js */ +/* ^ punctuation.section.brackets.begin.js */ +/* ^^^^^^ meta.string.js string.quoted.double.js */ +/* ^ punctuation.section.brackets.end.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^ string.quoted.double.html punctuation.definition.string.end.html */ +/* ^ punctuation.definition.tag.end.html */ diff --git a/tests/syntax_test_questionmark.ejs b/tests/syntax_test_questionmark.ejs new file mode 100644 index 0000000..403c404 --- /dev/null +++ b/tests/syntax_test_questionmark.ejs @@ -0,0 +1,284 @@ +/* SYNTAX TEST "EJS (Q).sublime-syntax" */ + + +/* ^^^^^ text.html - text.html text.html - source */ +/* ^^^^^ meta.embedded.ejs comment.block.ejs - meta.embedded meta.embedded */ +/* ^^^ punctuation.definition.comment.begin.ejs */ +/* ^^ punctuation.definition.comment.end.ejs */ + + +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.ejs */ +/* ^^^ punctuation.definition.comment.begin.ejs */ +/* ^^ punctuation.definition.comment.end.ejs */ + + +/* ^^^^ text.html - text.html text.html - source */ +/* ^^^^ meta.embedded.ejs - meta.embedded meta.embedded */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^ punctuation.section.embedded.end.ejs */ + + +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^ punctuation.section.embedded.end.ejs */ + +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^ punctuation.section.embedded.end.ejs */ + +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^ punctuation.section.embedded.end.ejs */ + + +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^ punctuation.section.embedded.end.ejs */ + + +/* ^^^^^^^^^^^^^^^^^^^^ - meta.embedded - punctuation */ + + +/*^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* <- punctuation.section.embedded.begin.ejs */ +/*^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^^^^^^^^^^ meta.conditional.js */ +/* ^^ keyword.control.conditional.if.js */ +/* ^^^^^^ meta.group.js */ +/* ^ punctuation.section.group.begin.js */ +/* ^^^^ variable.other.readwrite.js */ +/* ^ punctuation.section.group.end.js */ +/* ^^ meta.block.js */ +/* ^ punctuation.section.block.begin.js */ +/* ^^ punctuation.section.embedded.end.ejs */ + +

+/*^^^^ meta.tag.block.any.html */ +/*^ punctuation.definition.tag.begin.html */ +/* ^^ entity.name.tag.block.any.html */ +/* ^ punctuation.definition.tag.end.html */ +/* ^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^^ variable.other.readwrite.js */ +/* ^ punctuation.accessor.js */ +/* ^^^^ meta.property.object.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^^^^^ meta.tag.block.any.html */ +/* ^^ punctuation.definition.tag.begin.html */ +/* ^^ entity.name.tag.block.any.html */ +/* ^ punctuation.definition.tag.end.html */ + + ="class-" /> +/* ^^^^^^^^^^ meta.attribute-with-value.html entity.other.attribute-name.html meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^ variable.other */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^^^^^^^ meta.attribute-with-value.html meta.string.html string.quoted.double.html */ +/* ^^^^^^^^^^^^ meta.attribute-with-value.html meta.string.html meta.embedded.ejs */ +/* ^ meta.attribute-with-value.html meta.string.html string.quoted.double.html */ + + < => +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.tag.other.html */ +/*^ punctuation.definition.tag.begin.html */ +/* ^^^^^^^ entity.name.tag.other.html meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^ source.js.embedded.ejs variable.other.readwrite.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^^^^^^^^^^^^^^^^^^ meta.attribute-with-value.html */ +/* ^^^^^^^^ entity.other.attribute-name.html meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^ source.js.embedded.ejs variable.other.readwrite.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^ punctuation.separator.key-value.html */ +/* ^^^^^^^^^ meta.string.html meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^ source.js.embedded.ejs variable.other.readwrite.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^ punctuation.definition.tag.end.html */ + + +/*^^^^^ meta.embedded.ejs */ +/* <- punctuation.section.embedded.begin.ejs */ +/*^^^ source.js.embedded.ejs */ +/* ^ punctuation.section.block.end.js */ +/* ^^ punctuation.section.embedded.end.ejs */ + + any text +/*^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* <- punctuation.section.embedded.begin.ejs */ +/*^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^^^^^ support.type.object.console.js */ +/* ^ punctuation.accessor.js */ +/* ^^^ meta.function-call support.function.console.js */ +/* ^^ meta.function-call meta.group.js */ +/* ^ punctuation.section.group.begin.js */ +/* ^ meta.string.js string.quoted.double.js punctuation.definition.string.begin.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^^^^^^^^ meta.tag.inline.any.html */ +/* ^ punctuation.definition.tag.begin.html */ +/* ^^^^^^ entity.name.tag.inline.any.html */ +/* ^ punctuation.definition.tag.end.html */ +/* ^^^^^^^^^ meta.tag.inline.any.html */ +/* ^^ punctuation.definition.tag.begin.html */ +/* ^^^^^^ entity.name.tag.inline.any.html */ +/* ^ punctuation.definition.tag.end.html */ +/* ^^^^^^^^ meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^ source.js.embedded.ejs */ +/* ^^ meta.function-call meta.group.js */ +/* ^ meta.string.js string.quoted.double.js punctuation.definition.string.end.js */ +/* ^ punctuation.section.group.end.js */ +/* ^ punctuation.terminator.statement.js */ +/* ^^ punctuation.section.embedded.end.ejs */ + + +/* <- meta.tag.style.end.html punctuation.definition.tag.begin.html */ +/*^^^^^^ meta.tag.style.end.html */ +/*^^^^^ entity.name.tag.style.html */ +/* ^ punctuation.definition.tag.end.html */ + +
"> +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.tag.block.any.html */ +/*^^ entity.name.tag.block.any.html */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.attribute-with-value.style.html */ +/* ^^^^^ entity.other.attribute-name.style.html */ +/* ^ punctuation.separator.key-value.html */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.html */ +/* ^ string.quoted.double.html punctuation.definition.string.begin.html */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.css.embedded.html */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.embedded.ejs */ +/* ^^ punctuation.section.embedded.begin.ejs */ +/* ^^^^^^^^^^^^^^^^^^^^^^ source.js.embedded.ejs */ +/* ^^^^^^^^ meta.brackets.js */ +/* ^ punctuation.section.brackets.begin.js */ +/* ^^^^^^ meta.string.js string.quoted.double.js */ +/* ^ punctuation.section.brackets.end.js */ +/* ^^ punctuation.section.embedded.end.ejs */ +/* ^ string.quoted.double.html punctuation.definition.string.end.html */ +/* ^ punctuation.definition.tag.end.html */