master 51a5823eea44 cached
15 files
29.3 KB
7.8k tokens
10 symbols
1 requests
Download .txt
Repository: formulahendry/vscode-auto-close-tag
Branch: master
Commit: 51a5823eea44
Files: 15
Total size: 29.3 KB

Directory structure:
gitextract_60176eh4/

├── .github/
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .travis.yml
├── .vscode/
│   ├── launch.json
│   ├── settings.json
│   └── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── src/
│   └── extension.ts
├── test/
│   ├── extension.test.ts
│   └── index.ts
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/main.yml
================================================
name: CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

  workflow_dispatch:

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        os: [macos-latest, ubuntu-latest, windows-latest]
    runs-on: ${{ matrix.os }}

    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Install Node.js
        uses: actions/setup-node@v1
        with:
          node-version: 16.x
      - run: npm install
      - run: npm run vscode:prepublish


================================================
FILE: .gitignore
================================================
out
node_modules

================================================
FILE: .travis.yml
================================================
sudo: false

os:
  - osx
  - linux

before_install:
  - if [ $TRAVIS_OS_NAME == "linux" ]; then
      export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0;
      sh -e /etc/init.d/xvfb start;
      sleep 3;
    fi

install:
  - npm install
  - npm run vscode:prepublish

script:
  - npm test --silent

================================================
FILE: .vscode/launch.json
================================================
// A launch configuration that compiles the extension and then opens it inside a new window
{
    "version": "0.1.0",
    "configurations": [
        {
            "name": "Launch Extension",
            "type": "extensionHost",
            "request": "launch",
            "runtimeExecutable": "${execPath}",
            "args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
            "stopOnEntry": false,
            "sourceMaps": true,
            "outDir": "${workspaceRoot}/out/src",
            "preLaunchTask": "npm"
        },
        {
            "name": "Launch Tests",
            "type": "extensionHost",
            "request": "launch",
            "runtimeExecutable": "${execPath}",
            "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ],
            "stopOnEntry": false,
            "sourceMaps": true,
            "outDir": "${workspaceRoot}/out/test",
            "preLaunchTask": "npm"
        }
    ]
}


================================================
FILE: .vscode/settings.json
================================================
// Place your settings in this file to overwrite default and user settings.
{
    "files.exclude": {
        "out": false // set this to true to hide the "out" folder with the compiled JS files
    },
    "search.exclude": {
        "out": true // set this to false to include "out" folder in search results
    },
    "typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version
}

================================================
FILE: .vscode/tasks.json
================================================
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
// ${fileExtname}: the current opened file's extension
// ${cwd}: the current working directory of the spawned process

// A task runner that calls a custom npm script that compiles the extension.
{
    "version": "2.0.0",

    // we want to run npm
    "command": "npm",

    // we run the custom script "compile" as defined in package.json
    "args": ["run", "compile", "--loglevel", "silent"],

    // The tsc compiler is started in watching mode
    "isWatching": true,

    // use the standard tsc in watch mode problem matcher to find compile problems in the output.
    "problemMatcher": "$tsc-watch",
    "tasks": [
        {
            "label": "npm",
            "type": "shell",
            "command": "npm",
            "args": [
                "run",
                "compile",
                "--loglevel",
                "silent"
            ],
            "isBackground": true,
            "problemMatcher": "$tsc-watch",
            "group": "build"
        }
    ]
}

================================================
FILE: .vscodeignore
================================================
.vscode/**
typings/**
out/test/**
test/**
src/**
**/*.map
.gitignore
tsconfig.json
vsc-extension-quickstart.md


================================================
FILE: CHANGELOG.md
================================================
### 0.5.15 (2023-12-09)
* [#222](https://github.com/formulahendry/vscode-auto-close-tag/pull/222): Fix for undo/redo

### 0.5.14 (2022-02-08)
* Add sponsor for Duckly

### 0.5.13 (2021-10-27)
* Update link for Tabnine

### 0.5.12 (2021-07-31)
* Support Workspace Trust and Virtual Workspaces

### 0.5.11 (2021-07-09)
* Support self-closing tags with space

### 0.5.10 (2021-01-06)
* Add sponsor for Tabnine

### 0.5.9 (2020-10-11)
* [#106](https://github.com/formulahendry/vscode-auto-close-tag/pull/106): Support for auto closing tags starting with underscore

### 0.5.8 (2020-07-03)
* [#175](https://github.com/formulahendry/vscode-auto-close-tag/pull/175): Add new setting 'Added disableOnLanguage'

### 0.5.7 (2020-04-21)
* Update support for embedded elixir
* Add support for Apple's property list type (plist)

### 0.5.6 (2018-02-17)
* Add support for embedded elixir

### 0.5.5 (2017-12-03)
* Handle void tags that are written in other case than lowercase (HTML tag names are case-insensitive)

### 0.5.4 (2017-11-30)
* Add support for CFML

### 0.5.3 (2017-11-04)
* Add support for Multi Root Workspace

### 0.5.2 (2017-10-22)
* [#65](https://github.com/formulahendry/vscode-auto-close-tag/issues/65): Enable Auto Close Tag on erb file

### 0.5.1 (2017-09-29)
* [#63](https://github.com/formulahendry/vscode-auto-close-tag/issues/63): Handle space before closing parentheses

### 0.5.0 (2017-09-08)
* Not enabled for HTML, Handlebars and Razor files, since VS Code has built-in support from v1.16

### 0.4.3 (2017-06-30)
* [#49](https://github.com/formulahendry/vscode-auto-close-tag/issues/49)

### 0.4.2 (2017-05-22)
* [#46](https://github.com/formulahendry/vscode-auto-close-tag/issues/46): Enable Auto Close Tag on Liquid

### 0.4.1 (2017-05-14)
* Enable Auto Close Tag on more template engines

### 0.4.0 (2017-05-12)
* [#26](https://github.com/formulahendry/vscode-auto-close-tag/issues/26): Enable Auto Close Tag only on a set of languages

### 0.3.12 (2017-05-02)
* Remove 'Keymaps' category per VS Code team's suggestion

### 0.3.11 (2017-04-16)
* Resolve [GitHub issue#33](https://github.com/formulahendry/vscode-auto-close-tag/issues/33): Add config entry to enable both Visual Studio and Sublime Text mode

### 0.3.10 (2017-03-10)
* Resolve [GitHub issue#30](https://github.com/formulahendry/vscode-auto-close-tag/issues/30): Should not close tag inside template literals

### 0.3.9
* Update key binding to align with Sublime Text
* Resolve [GitHub issue#23](https://github.com/formulahendry/vscode-auto-close-tag/issues/23): Tag should not be auto closed inside quotes

### 0.3.8
* Resolve [GitHub issue#20](https://github.com/formulahendry/vscode-auto-close-tag/issues/20): Fix automatic close tag after tab switch

### 0.3.7
* Resolve [GitHub issue#19](https://github.com/formulahendry/vscode-auto-close-tag/issues/19): Fix Auto Close Tag not working in HTML/XML file due to VS Code 1.8 breaking changes

### 0.3.6
* Resolve [GitHub issue#18](https://github.com/formulahendry/vscode-auto-close-tag/issues/18): Support `.` (dot) in tags

### 0.3.5
* Merge [PR #15](https://github.com/formulahendry/vscode-auto-close-tag/pull/15)
  * Avoid closing brackets duplication
  * Support `:-_` in tags

### 0.3.4
* Resolve [GitHub issue#12](https://github.com/formulahendry/vscode-auto-close-tag/issues/12): Path symbol "/" problem

### 0.3.3
* Merge [PR#11](https://github.com/formulahendry/vscode-auto-close-tag/pull/11): Remove left over console.log command

### 0.3.2
* Resolve [GitHub issue#10](https://github.com/formulahendry/vscode-auto-close-tag/issues/10): add support to close self-closing tag automatically in Sublime Text 3 mode

### 0.3.1
* Add support to close self-closing tag automatically

### 0.3.0
* Use Keyboard Shortcut or Command Palette to add close tag manually
* Add config entry to turn on/off auto close tag

### 0.2.0
* Add config entry to support auto close tag of Sublime Text 3 Mode

### 0.1.4
* Resolve [GitHub issue#5](https://github.com/formulahendry/vscode-auto-close-tag/issues/5): arrow function shouldn't trigger auto-close

### 0.1.3
* Resolve [GitHub issue#4](https://github.com/formulahendry/vscode-auto-close-tag/issues/4): providie a config entry to set the tag list that would not be auto closed

### 0.1.2
* Update README.md to clarify the configuration for `auto-close-tag.activationOnLanguage`

### 0.1.1
* Match correct opening tag in some corner cases

### 0.1.0
* Bug fixes
* Add blog info 

### 0.0.3
* Update README.md

### 0.0.2
* Add configuration to set the languages that the extension will be activated
* Add support for tag with attribute. e.g. `<a href="https://www.microsoft.com"></a>`. So `</a>` will be automatically added.
* Minor bug fix

### 0.0.1
* Initial Release

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2018 Jun Han

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Auto Close Tag

[![CI](https://github.com/formulahendry/vscode-auto-close-tag/actions/workflows/main.yml/badge.svg)](https://github.com/formulahendry/vscode-auto-close-tag/actions/workflows/main.yml)

Automatically add HTML/XML close tag, same as Visual Studio IDE or Sublime Text does.

## Book for VS Code

[《Visual Studio Code 权威指南》](https://union-click.jd.com/jdc?e=jdext-1261348777639735296-0&p=AyIGZRhbHQsWAVIaXxEyEgRdG1sRBxU3EUQDS10iXhBeGlcJDBkNXg9JHUlSSkkFSRwSBF0bWxEHFRgMXgdIMkRxFAUJD1RQZT0cBnwKDE4%2BaDpgB2ILWStbHAIQD1QaWxIBIgdUGlsRBxEEUxprJQIXNwd1g6O0yqLkB4%2B%2FjcePwitaJQIWD1cfWhwKGwVSG1wlAhoDZc31gdeauIyr%2FsOovNLYq46cqca50ytrJQEiXABPElAeEgRSG1kQCxQBUxxZHQQQA1YTXAkDIgdUGlscChECXRs1FGwSD1UbWRALFwRWK1slASJZOxoLRlUXU1NONU9QEkdXWRlJbBUDVB9TFgAVN1caWhcA):带你深入浅出 VS Code!

![Book](images/book.jpg)

## Note

From VS Code 1.16, it has [built-in close tag support](https://code.visualstudio.com/updates/v1_16#_html-close-tags) for HTML, Handlebars and Razor files. This extension is enabled for other languages like XML, PHP, Vue, JavaScript, TypeScript, JSX, TSX, GJS, GTS, and so on. It is configurable.

## Features

* Automatically add closing tag when you type in the closing bracket of the opening tag
* After closing tag is inserted, the cursor is between the opening and closing tag
* Set the tag list that would not be auto closed
* Automatically close self-closing tag
* Support auto close tag as Sublime Text 3
* Use Keyboard Shortcut or Command Palette to add close tag manually

## Usages

After typing in the closing bracket of the opening tag, the closing tag will be inserted automatically.

![Usage](images/usage.gif)

To add close tag manually, use shortcut `Alt+.` (`Command+Alt+.` for Mac), or press `F1` and then select/type `Close Tag`

![Usage](images/close-tag.gif)

## Sublime Text 3 Mode

To automatically add close tag when `</` is typed (same as Sublime Text 3 does), set the below config as `true`:
```json
{
    "auto-close-tag.SublimeText3Mode": true
}
```
The setting is `false` by default.

![Sublime Text 3](images/st3.gif)

## Configuration

Use `auto-close-tag.enableAutoCloseTag` to set whether to insert close tag automatically (it is `true` by default):
```json
{
    "auto-close-tag.enableAutoCloseTag": true
}
```

To set whether to close self-closing tag automatically (e.g. type `<br`, then type `/`, `>` will be added automatically) (it is `true` by default):
```json
{
    "auto-close-tag.enableAutoCloseSelfClosingTag": true
}
```

Whether to insert a space before the forward slash in a self-closing tag (it is `false` by default):
```json
{
    "auto-close-tag.insertSpaceBeforeSelfClosingTag": false
}
```

Add entry into `auto-close-tag.activationOnLanguage` to set the languages that the extension will be activated. Use `["*"]` to activate for all languages. Below are the default settings:
```json
{
    "auto-close-tag.activationOnLanguage": [
        "xml",
        "php",
        "blade",
        "ejs",
        "glimmer-js",
        "glimmer-ts",
        "jinja",
        "javascript",
        "javascriptreact",
        "typescript",
        "typescriptreact",
        "plaintext",
        "markdown",
        "vue",
        "liquid",
        "erb",
        "lang-cfml",
        "cfml",
        "HTML (Eex)"
    ]
}
```
**Note:** The setting should be set with language id defined in [VS Code](https://github.com/Microsoft/vscode/tree/master/extensions). Taking [javascript definition](https://github.com/Microsoft/vscode/blob/master/extensions/javascript/package.json) as an example, we need to use `javascript` for `.js` and `.es6`, use `javascriptreact` for `.jsx`. So, if you want to enable this extension on `.js` file, you need to add `javascript` in settings.json.

Alternatively you could also exlude the languages where you don't want the extension to be activated. Below is an example:
```json
{
    "auto-close-tag.disableOnLanguage": [
        "php",
        "python"
    ]
}
```

You could also set the tag list that would not be auto closed. Below are the default settings for void elements in HTML per [W3C spec](https://www.w3.org/TR/html-markup/syntax.html#syntax-elements), and you could overwrite it:
```json
{
    "auto-close-tag.excludedTags": [
        "area",
        "base",
        "br",
        "col",
        "command",
        "embed",
        "hr",
        "img",
        "input",
        "keygen",
        "link",
        "meta",
        "param",
        "source",
        "track",
        "wbr"
    ]
}
```

`auto-close-tag.fullMode`: Whether to enable both Visual Studio and Sublime Text mode. (Default is **false**)

## Change Log
See Change Log [here](CHANGELOG.md)

## Issues
Submit the [issues](https://github.com/formulahendry/vscode-auto-close-tag/issues) if you find any bug or have any suggestion.

## Contribution
Fork the [repo](https://github.com/formulahendry/vscode-auto-close-tag) and submit pull requests.

## Blog
Visit the [blog](https://blogs.msdn.microsoft.com/formulahendry) or the [post](https://blogs.msdn.microsoft.com/formulahendry/2016/06/29/auto-close-tag-for-visual-studio-code/) for more detailed info 

================================================
FILE: package.json
================================================
{
    "name": "auto-close-tag",
    "displayName": "Auto Close Tag",
    "description": "Automatically add HTML/XML close tag, same as Visual Studio IDE or Sublime Text",
    "version": "0.5.15",
    "publisher": "formulahendry",
    "icon": "images/logo.png",
    "engines": {
        "vscode": "^1.49.0"
    },
    "categories": [
        "Other",
        "Programming Languages"
    ],
    "keywords": [
        "AutoComplete",
        "close",
        "tag",
        "html",
        "xml",
        "multi-root ready"
    ],
    "bugs": {
        "url": "https://github.com/formulahendry/vscode-auto-close-tag/issues",
        "email": "formulahendry@gmail.com"
    },
    "homepage": "https://github.com/formulahendry/vscode-auto-close-tag/blob/master/README.md",
    "repository": {
        "type": "git",
        "url": "https://github.com/formulahendry/vscode-auto-close-tag.git"
    },
    "extensionKind": [
        "ui",
        "workspace"
    ],
    "activationEvents": [
        "*",
        "onCommand:auto-close-tag.closeTag"
    ],
    "main": "./out/src/extension",
    "capabilities": {
        "untrustedWorkspaces": {
            "supported": true
        },
        "virtualWorkspaces": true
    },
    "contributes": {
        "commands": [
            {
                "command": "auto-close-tag.closeTag",
                "title": "Close Tag"
            }
        ],
        "keybindings": [
            {
                "command": "auto-close-tag.closeTag",
                "key": "alt+.",
                "mac": "cmd+alt+."
            }
        ],
        "configuration": {
            "type": "object",
            "title": "Auto Close Tag configuration",
            "properties": {
                "auto-close-tag.activationOnLanguage": {
                    "type": "array",
                    "default": [
                        "xml",
                        "php",
                        "blade",
                        "ejs",
                        "glimmer-js",
                        "glimmer-ts",
                        "jinja",
                        "javascript",
                        "javascriptreact",
                        "typescript",
                        "typescriptreact",
                        "plaintext",
                        "markdown",
                        "vue",
                        "liquid",
                        "erb",
                        "lang-cfml",
                        "cfml",
                        "HTML (EEx)",
                        "HTML (Eex)",
                        "plist"
                    ],
                    "description": "Set the languages that the extension will be activated.  e.g. [\"html\",\"xml\",\"php\"]. Use [\"*\"] to activate for all languages.",
                    "scope": "resource"
                },
                "auto-close-tag.disableOnLanguage": {
                    "type": "array",
                    "default": [],
                    "description": "Set the languages where the extension will be disabled.  e.g. [\"html\",\"xml\",\"php\"].",
                    "scope": "resource"
                },
                "auto-close-tag.excludedTags": {
                    "type": "array",
                    "default": [
                        "area",
                        "base",
                        "br",
                        "col",
                        "command",
                        "embed",
                        "hr",
                        "img",
                        "input",
                        "keygen",
                        "link",
                        "meta",
                        "param",
                        "source",
                        "track",
                        "wbr"
                    ],
                    "description": "Set the tag list that would not be auto closed.",
                    "scope": "resource"
                },
                "auto-close-tag.SublimeText3Mode": {
                    "type": "boolean",
                    "default": false,
                    "description": "Auto close tag when </ is typed, same as Sublime Text 3",
                    "scope": "resource"
                },
                "auto-close-tag.enableAutoCloseTag": {
                    "type": "boolean",
                    "default": true,
                    "description": "Whether to insert close tag automatically",
                    "scope": "resource"
                },
                "auto-close-tag.enableAutoCloseSelfClosingTag": {
                    "type": "boolean",
                    "default": true,
                    "description": "Whether to close self-closing tag automatically",
                    "scope": "resource"
                },
                "auto-close-tag.insertSpaceBeforeSelfClosingTag": {
                    "type": "boolean",
                    "default": false,
                    "description": "Insert a space before the forward slash in a self-closing tag.",
                    "scope": "resource"
                },
                "auto-close-tag.fullMode": {
                    "type": "boolean",
                    "default": false,
                    "description": "Enable both Visual Studio and Sublime Text mode",
                    "scope": "resource"
                }
            }
        }
    },
    "scripts": {
        "vscode:prepublish": "tsc -p ./",
        "compile": "tsc -watch -p ./"
    },
    "devDependencies": {
        "@types/mocha": "^2.2.32",
        "@types/node": "^6.0.40",
        "@types/vscode": "^1.49.0",
        "mocha": "^2.3.3",
        "typescript": "^3.9.10"
    }
}


================================================
FILE: src/extension.ts
================================================
'use strict';
import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
    vscode.workspace.onDidChangeTextDocument(event => {
        insertAutoCloseTag(event);
    });

    let closeTag = vscode.commands.registerCommand('auto-close-tag.closeTag', () => {
        insertCloseTag();
    });

    context.subscriptions.push(closeTag);
}

// this method is called when your extension is deactivated
export function deactivate() {
}

function insertAutoCloseTag(event: vscode.TextDocumentChangeEvent): void {
    if (!event.contentChanges[0] || ( event.reason && event.reason == vscode.TextDocumentChangeReason.Undo ) || ( event.reason && event.reason == vscode.TextDocumentChangeReason.Redo ) ) {
        return;
    }
    let isRightAngleBracket = CheckRightAngleBracket(event.contentChanges[0]);
    if (!isRightAngleBracket && event.contentChanges[0].text !== "/") {
        return;
    }

    let editor = vscode.window.activeTextEditor;
    if (!editor || ( editor && event.document !== editor.document ) ) {
        return;
    }

    let config = vscode.workspace.getConfiguration('auto-close-tag', editor.document.uri);
    if (!config.get<boolean>("enableAutoCloseTag", true)) {
        return;
    }

    let languageId = editor.document.languageId;
    let languages = config.get<string[]>("activationOnLanguage", ["*"]);
    let disableOnLanguage = config.get<string[]>("disableOnLanguage", []);
    if ((languages.indexOf("*") === -1 && languages.indexOf(languageId) === -1) || disableOnLanguage.indexOf(languageId) !== -1) {
        return;
    }

    let selection = editor.selection;
    let originalPosition = selection.start.translate(0, 1);
    let excludedTags = config.get<string[]>("excludedTags", []);
    let isSublimeText3Mode = config.get<boolean>("SublimeText3Mode", false);
    let enableAutoCloseSelfClosingTag = config.get<boolean>("enableAutoCloseSelfClosingTag", true);
    let isFullMode = config.get<boolean>("fullMode");

    if ((isSublimeText3Mode || isFullMode) && event.contentChanges[0].text === "/") {
        let text = editor.document.getText(new vscode.Range(new vscode.Position(0, 0), originalPosition));
        let last2chars = "";
        if (text.length > 2) {
            last2chars = text.substr(text.length - 2);
        }
        if (last2chars === "</") {
            let closeTag = getCloseTag(text, excludedTags);
            if (closeTag) {
                let nextChar = getNextChar(editor, originalPosition);
                if (nextChar === ">") {
                    closeTag = closeTag.substr(0, closeTag.length - 1);
                }
                editor.edit((editBuilder) => {
                    editBuilder.insert(originalPosition, closeTag);
                }).then(() => {
                    if (nextChar === ">") {
                        editor.selection = moveSelectionRight(editor.selection, 1);
                    }
                });
            }
        }
    }

    if (((!isSublimeText3Mode || isFullMode) && isRightAngleBracket) ||
        (enableAutoCloseSelfClosingTag && event.contentChanges[0].text === "/")) {
        let textLine = editor.document.lineAt(selection.start);
        let text = textLine.text.substring(0, selection.start.character + 1);
        let result = /<([_a-zA-Z][a-zA-Z0-9:\-_.]*)(?:\s+[^<>]*?[^\s/<>=]+?)*?\s?(\/|>)$/.exec(text);
        if (result !== null && ((occurrenceCount(result[0], "'") % 2 === 0)
            && (occurrenceCount(result[0], "\"") % 2 === 0) && (occurrenceCount(result[0], "`") % 2 === 0))) {
            if (result[2] === ">") {
                if (excludedTags.indexOf(result[1].toLowerCase()) === -1) {
                    editor.edit((editBuilder) => {
                        editBuilder.insert(originalPosition, "</" + result[1] + ">");
                    }).then(() => {
                        editor.selection = new vscode.Selection(originalPosition, originalPosition);
                    });
                }
            } else {
                if (textLine.text.length <= selection.start.character + 1 || textLine.text[selection.start.character + 1] !== '>') { // if not typing "/" just before ">", add the ">" after "/"
                    editor.edit((editBuilder) => {
                        if (config.get<boolean>("insertSpaceBeforeSelfClosingTag")) {
                            const spacePosition = originalPosition.translate(0, -1);
                            editBuilder.insert(spacePosition, " ");
                        }
                        editBuilder.insert(originalPosition, ">");
                    })
                }
            }
        }
    }
}

function CheckRightAngleBracket(contentChange: vscode.TextDocumentContentChangeEvent): boolean {
    return contentChange.text === ">" || CheckRightAngleBracketInVSCode_1_8(contentChange);
}

function CheckRightAngleBracketInVSCode_1_8(contentChange: vscode.TextDocumentContentChangeEvent): boolean {
    return contentChange.text.endsWith(">") && contentChange.range.start.character === 0
        && contentChange.range.start.line === contentChange.range.end.line
        && !contentChange.range.end.isEqual(new vscode.Position(0, 0));
}

function insertCloseTag(): void {
    let editor = vscode.window.activeTextEditor;
    if (!editor) {
        return;
    }

    let selection = editor.selection;
    let originalPosition = selection.start;
    let config = vscode.workspace.getConfiguration('auto-close-tag', editor.document.uri);
    let excludedTags = config.get<string[]>("excludedTags", []);
    let text = editor.document.getText(new vscode.Range(new vscode.Position(0, 0), originalPosition));
    if (text.length > 2) {
        let closeTag = getCloseTag(text, excludedTags);
        if (closeTag) {
            editor.edit((editBuilder) => {
                editBuilder.insert(originalPosition, closeTag);
            });
        }
    }
}

function getNextChar(editor: vscode.TextEditor, position: vscode.Position): string {
    let nextPosition = position.translate(0, 1);
    let text = editor.document.getText(new vscode.Range(position, nextPosition));
    return text;
}

function getCloseTag(text: string, excludedTags: string[]): string {
    let regex = /<(\/?[_a-zA-Z][a-zA-Z0-9:\-_.]*)(?:\s+[^<>]*?[^\s/<>=]+?)*?\s?>/g;
    let result = null;
    let stack = [];
    while ((result = regex.exec(text)) !== null) {
        let isStartTag = result[1].substr(0, 1) !== "/";
        let tag = isStartTag ? result[1] : result[1].substr(1);
        if (excludedTags.indexOf(tag.toLowerCase()) === -1) {
            if (isStartTag) {
                stack.push(tag);
            } else if (stack.length > 0) {
                let lastTag = stack[stack.length - 1];
                if (lastTag === tag) {
                    stack.pop()
                }
            }
        }
    }
    if (stack.length > 0) {
        let closeTag = stack[stack.length - 1];
        if (text.substr(text.length - 2) === "</") {
            return closeTag + ">";
        }
        if (text.substr(text.length - 1) === "<") {
            return "/" + closeTag + ">";
        }
        return "</" + closeTag + ">";
    } else {
        return null;
    }
}

function moveSelectionRight(selection: vscode.Selection, shift: number): vscode.Selection {
    let newPosition = selection.active.translate(0, shift);
    let newSelection = new vscode.Selection(newPosition, newPosition);
    return newSelection;
}

function occurrenceCount(source: string, find: string): number {
    return source.split(find).length - 1;
}


================================================
FILE: test/extension.test.ts
================================================
//
// Note: This example test is leveraging the Mocha test framework.
// Please refer to their documentation on https://mochajs.org/ for help.
//

// The module 'assert' provides assertion methods from node
import * as assert from 'assert';

// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from 'vscode';
import * as myExtension from '../src/extension';

// Defines a Mocha test suite to group tests of similar kind together
suite("Extension Tests", () => {

    // Defines a Mocha unit test
    test("Something 1", () => {
        assert.equal(-1, [1, 2, 3].indexOf(5));
        assert.equal(-1, [1, 2, 3].indexOf(0));
    });
});

================================================
FILE: test/index.ts
================================================
//
// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
//
// This file is providing the test runner to use when running extension tests.
// By default the test runner in use is Mocha based.
//
// You can provide your own test runner if you want to override it by exporting
// a function run(testRoot: string, clb: (error:Error) => void) that the extension
// host can call to run the tests. The test runner is expected to use console.log
// to report the results back to the caller. When the tests are finished, return
// a possible error to the callback or null if none.

var testRunner = require('vscode/lib/testrunner');

// You can directly control Mocha options by uncommenting the following lines
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
testRunner.configure({
    ui: 'tdd', 		// the TDD UI is being used in extension.test.ts (suite, test, etc.)
    useColors: true // colored output from test results
});

module.exports = testRunner;

================================================
FILE: tsconfig.json
================================================
{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es6",
        "outDir": "out",
        "lib": [
            "es6"
        ],
        "sourceMap": true,
        "rootDir": "."
    },
    "exclude": [
        "node_modules",
        ".vscode-test"
    ]
}
Download .txt
gitextract_60176eh4/

├── .github/
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .travis.yml
├── .vscode/
│   ├── launch.json
│   ├── settings.json
│   └── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── src/
│   └── extension.ts
├── test/
│   ├── extension.test.ts
│   └── index.ts
└── tsconfig.json
Download .txt
SYMBOL INDEX (10 symbols across 1 files)

FILE: src/extension.ts
  function activate (line 4) | function activate(context: vscode.ExtensionContext) {
  function deactivate (line 17) | function deactivate() {
  function insertAutoCloseTag (line 20) | function insertAutoCloseTag(event: vscode.TextDocumentChangeEvent): void {
  function CheckRightAngleBracket (line 107) | function CheckRightAngleBracket(contentChange: vscode.TextDocumentConten...
  function CheckRightAngleBracketInVSCode_1_8 (line 111) | function CheckRightAngleBracketInVSCode_1_8(contentChange: vscode.TextDo...
  function insertCloseTag (line 117) | function insertCloseTag(): void {
  function getNextChar (line 138) | function getNextChar(editor: vscode.TextEditor, position: vscode.Positio...
  function getCloseTag (line 144) | function getCloseTag(text: string, excludedTags: string[]): string {
  function moveSelectionRight (line 176) | function moveSelectionRight(selection: vscode.Selection, shift: number):...
  function occurrenceCount (line 182) | function occurrenceCount(source: string, find: string): number {
Condensed preview — 15 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (32K chars).
[
  {
    "path": ".github/workflows/main.yml",
    "chars": 507,
    "preview": "name: CI\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\n  workflow_dispatch:\n\njobs:\n  b"
  },
  {
    "path": ".gitignore",
    "chars": 16,
    "preview": "out\nnode_modules"
  },
  {
    "path": ".travis.yml",
    "chars": 313,
    "preview": "sudo: false\r\n\r\nos:\r\n  - osx\r\n  - linux\r\n\r\nbefore_install:\r\n  - if [ $TRAVIS_OS_NAME == \"linux\" ]; then\r\n      export CXX"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 996,
    "preview": "// A launch configuration that compiles the extension and then opens it inside a new window\n{\n    \"version\": \"0.1.0\",\n  "
  },
  {
    "path": ".vscode/settings.json",
    "chars": 455,
    "preview": "// Place your settings in this file to overwrite default and user settings.\n{\n    \"files.exclude\": {\n        \"out\": fals"
  },
  {
    "path": ".vscode/tasks.json",
    "chars": 1241,
    "preview": "// Available variables which can be used inside of strings.\n// ${workspaceRoot}: the root folder of the team\n// ${file}:"
  },
  {
    "path": ".vscodeignore",
    "chars": 111,
    "preview": ".vscode/**\ntypings/**\nout/test/**\ntest/**\nsrc/**\n**/*.map\n.gitignore\ntsconfig.json\nvsc-extension-quickstart.md\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 4877,
    "preview": "### 0.5.15 (2023-12-09)\r\n* [#222](https://github.com/formulahendry/vscode-auto-close-tag/pull/222): Fix for undo/redo\r\n\r"
  },
  {
    "path": "LICENSE",
    "chars": 1064,
    "preview": "MIT License\n\nCopyright (c) 2018 Jun Han\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof"
  },
  {
    "path": "README.md",
    "chars": 5130,
    "preview": "# Auto Close Tag\n\n[![CI](https://github.com/formulahendry/vscode-auto-close-tag/actions/workflows/main.yml/badge.svg)](h"
  },
  {
    "path": "package.json",
    "chars": 5697,
    "preview": "{\n    \"name\": \"auto-close-tag\",\n    \"displayName\": \"Auto Close Tag\",\n    \"description\": \"Automatically add HTML/XML clos"
  },
  {
    "path": "src/extension.ts",
    "chars": 7588,
    "preview": "'use strict';\nimport * as vscode from 'vscode';\n\nexport function activate(context: vscode.ExtensionContext) {\n    vscode"
  },
  {
    "path": "test/extension.test.ts",
    "chars": 708,
    "preview": "//\n// Note: This example test is leveraging the Mocha test framework.\n// Please refer to their documentation on https://"
  },
  {
    "path": "test/index.ts",
    "chars": 1017,
    "preview": "//\n// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING\n//\n// This file is providing the test runner to u"
  },
  {
    "path": "tsconfig.json",
    "chars": 281,
    "preview": "{\n    \"compilerOptions\": {\n        \"module\": \"commonjs\",\n        \"target\": \"es6\",\n        \"outDir\": \"out\",\n        \"lib\""
  }
]

About this extraction

This page contains the full source code of the formulahendry/vscode-auto-close-tag GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 15 files (29.3 KB), approximately 7.8k tokens, and a symbol index with 10 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!