code-scope-highlighter 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "root": true,
3
+ "parser": "@typescript-eslint/parser",
4
+ "parserOptions": {
5
+ "ecmaVersion": 6,
6
+ "sourceType": "module"
7
+ },
8
+ "plugins": [
9
+ "@typescript-eslint"
10
+ ],
11
+ "rules": {
12
+ "@typescript-eslint/naming-convention": [
13
+ "warn",
14
+ {
15
+ "selector": "import",
16
+ "format": [ "camelCase", "PascalCase" ]
17
+ }
18
+ ],
19
+ "@typescript-eslint/semi": "warn",
20
+ "curly": "warn",
21
+ "eqeqeq": "warn",
22
+ "no-throw-literal": "warn",
23
+ "semi": "off"
24
+ },
25
+ "ignorePatterns": [
26
+ "out",
27
+ "dist",
28
+ "**/*.d.ts"
29
+ ]
30
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ // See http://go.microsoft.com/fwlink/?LinkId=827846
3
+ // for the documentation about the extensions.json format
4
+ "recommendations": ["dbaeumer.vscode-eslint", "connor4312.esbuild-problem-matchers", "ms-vscode.extension-test-runner"]
5
+ }
@@ -0,0 +1,21 @@
1
+ // A launch configuration that compiles the extension and then opens it inside a new window
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ {
6
+ "version": "0.2.0",
7
+ "configurations": [
8
+ {
9
+ "name": "Run Extension",
10
+ "type": "extensionHost",
11
+ "request": "launch",
12
+ "args": [
13
+ "--disable-extensions",
14
+ "--extensionDevelopmentPath=${workspaceFolder}"
15
+ ],
16
+ "outFiles": [
17
+ "${workspaceFolder}/dist/**/*.js"
18
+ ],
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,13 @@
1
+ // Place your settings in this file to overwrite default and user settings.
2
+ {
3
+ "files.exclude": {
4
+ "out": false, // set this to true to hide the "out" folder with the compiled JS files
5
+ "dist": false // set this to true to hide the "dist" folder with the compiled JS files
6
+ },
7
+ "search.exclude": {
8
+ "out": true, // set this to false to include "out" folder in search results
9
+ "dist": true // set this to false to include "dist" folder in search results
10
+ },
11
+ // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
12
+ "typescript.tsc.autoDetect": "off"
13
+ }
@@ -0,0 +1,6 @@
1
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
2
+ // for the documentation about the tasks.json format
3
+ {
4
+ "version": "2.0.0",
5
+ "tasks": []
6
+ }
@@ -0,0 +1,5 @@
1
+ import { defineConfig } from '@vscode/test-cli';
2
+
3
+ export default defineConfig({
4
+ files: 'out/test/**/*.test.js',
5
+ });
package/.vscodeignore ADDED
@@ -0,0 +1,14 @@
1
+ .vscode/**
2
+ .vscode-test/**
3
+ out/**
4
+ node_modules/**
5
+ src/**
6
+ .gitignore
7
+ .yarnrc
8
+ esbuild.js
9
+ vsc-extension-quickstart.md
10
+ **/tsconfig.json
11
+ **/.eslintrc.json
12
+ **/*.map
13
+ **/*.ts
14
+ **/.vscode-test.*
package/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Scope Highlighter Change Log
2
+
3
+ ## v0.0.1 - 2024-07-03
4
+
5
+ - Initial release
package/LICENSE.md ADDED
@@ -0,0 +1,24 @@
1
+ ---
2
+ title: License
3
+ description: MIT License for Code Highlighter
4
+ ---
5
+
6
+ # 📄 License – Code Highlighter
7
+
8
+ This project is open-source and freely available under the terms below.
9
+
10
+ ---
11
+
12
+ ## MIT License
13
+
14
+ Copyright (c) {new Date().getFullYear()} [Jose Valdivia](https://github.com/joseavr)
15
+
16
+ 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:
17
+
18
+ > The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
19
+
20
+ **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.
21
+
22
+ ---
23
+
24
+ _Originally published at [github.com/joseavr/code-highlighter](https://github.com/joseavr/code-highlighter)_
package/README.md ADDED
@@ -0,0 +1,90 @@
1
+ <p align="center">
2
+ <img src="./code-scope-highlighter.gif" alt=" Language" />
3
+ </p>
4
+
5
+ <p align="center">
6
+ <img src="https://img.shields.io/github/languages/top/lamula21/scope-highlighter" alt=" Language" />
7
+ <img src="https://img.shields.io/github/stars/lamula21/scope-highlighter" alt=" Stars" />
8
+ <img src="https://img.shields.io/github/issues-pr/lamula21/scope-highlighter" alt=" Pull Requests" />
9
+ <img src="https://img.shields.io/github/issues/lamula21/scope-highlighter" alt=" Issues" />
10
+ <img src="https://img.shields.io/github/contributors/lamula21/scope-highlighter" alt=" Contributors" />
11
+ </p>
12
+
13
+
14
+ # Code Highlighter - A Highlighter Extension for Better Readability
15
+
16
+ A customizable scope highlighter, inspired by Dr Racket IDE.
17
+
18
+ ## ✨ Features
19
+ - **Universal highlighting:** ScopeHighlighter works on any language!
20
+ - **Dynamic Highlighting:** Instantly see the scope of matching brackets with vibrant colors.
21
+ - **HTML Tag Support:** Highlight nested HTML tags with intelligent cursor positioning:
22
+ - Place cursor on `<` of start tag to highlight: start tag + content + end tag
23
+ - Place cursor on `>` of any tag to highlight: content inside the tag
24
+ - **Customizable Colors:** Personalize your highlight colors for brackets, braces, and parentheses.
25
+ - **Flexible Modes:** Choose from "near", "always", or "never" highlight modes to suit your coding style.
26
+ - **(Soon) Language Specific Settings:** Enable or disable highlighting for specific programming languages.
27
+
28
+ ## 🌟 Why ScopeHighlighter?
29
+ - **Boost Productivity:** Quickly understand the structure of your code, making it easier to debug and develop.
30
+ - **Enhanced Readability:** No more squinting at matching brackets; ScopeHighlighter makes it clear and straightforward.
31
+ - **Seamless Integration:** Works effortlessly and fast within the VS Code ecosystem, either on desktop or the browser, thanks to the bundler `esbuild`.
32
+
33
+ ## ⚙️ Extension Settings
34
+
35
+ The following settings are configured for the scope-highlighter extension:
36
+
37
+ ### `codeScopeHighlighter.matchBrackets` - Match Brackets
38
+
39
+ For color picker: https://vuetifyjs.com/en/components/color-pickers/
40
+
41
+ - **Default**: `near`
42
+ - **Description**: Choose when the scope highlight should be active:
43
+ - `near` for when the cursor is near the bracket,
44
+ - `always` to always highlight,
45
+ - `never` to never highlight.
46
+
47
+ ### `codeScopeHighlighter.scopeColor` - Scope Color
48
+ - **Default**: `#4d4d4d30`
49
+ - **Description**: Color for highlighting the entire scope of matching brackets. (Hex format)
50
+
51
+ ### `codeScopeHighlighter.bracketColor` - Bracket Color
52
+ - **Default**: `#4d4d4d30`
53
+ - **Description**: Color for highlighting the matching brackets. (Hex format)
54
+
55
+ ## 🎯 HTML Tag Highlighting
56
+
57
+ The extension now supports HTML tag highlighting with intelligent cursor positioning:
58
+
59
+ ### How it works:
60
+ - **Cursor on `<` of start tag:** Highlights the entire tag including start tag, content, and end tag
61
+ - **Cursor on `>` of any tag:** Highlights only the content inside the tag (excluding the end tag's opening bracket)
62
+ - **Cursor inside tag content:** Highlights the content and end tag
63
+
64
+ ### Example:
65
+ ```html
66
+ <div class="container">
67
+ <h1>Hello World</h1>
68
+ <p>This is a <strong>test</strong> paragraph.</p>
69
+ </div>
70
+ ```
71
+
72
+ - Place cursor on `<` of `<div>` → highlights entire div block
73
+ - Place cursor on `>` of `<div>` → highlights content inside div
74
+ - Place cursor on `<` of `<h1>` → highlights h1 tag and content
75
+ - Place cursor on `>` of `</h1>` → highlights h1 content only
76
+
77
+ ## 🗺️ Roadmap
78
+
79
+ - [x] **HTML support:** Implement highlighting for nested html tags.
80
+ - [ ] **Language Specific Settings:** Implement highlighting for specific programming languages.
81
+ - [ ] **Bracket Specific Settings:** Implement highlighting for specific matching bracket symbols.
82
+
83
+
84
+ ## 📄 License
85
+
86
+ This project is licensed under the **MIT** - see the [MIT](https://github.com/xavimondev/easyreadme/blob/main/LICENSE) file for details.
87
+
88
+ ## For Devs
89
+
90
+ Start Debugging right away with `F5` or Command Pallete `Debug: Start Debugging`
Binary file
Binary file
Binary file
@@ -0,0 +1,3 @@
1
+ <div>
2
+ <span>test</span>
3
+ </div>
package/esbuild.js ADDED
@@ -0,0 +1,56 @@
1
+ const esbuild = require("esbuild");
2
+
3
+ const production = process.argv.includes('--production');
4
+ const watch = process.argv.includes('--watch');
5
+
6
+ /**
7
+ * @type {import('esbuild').Plugin}
8
+ */
9
+ const esbuildProblemMatcherPlugin = {
10
+ name: 'esbuild-problem-matcher',
11
+
12
+ setup(build) {
13
+ build.onStart(() => {
14
+ console.log('[watch] build started');
15
+ });
16
+ build.onEnd((result) => {
17
+ result.errors.forEach(({ text, location }) => {
18
+ console.error(`✘ [ERROR] ${text}`);
19
+ console.error(` ${location.file}:${location.line}:${location.column}:`);
20
+ });
21
+ console.log('[watch] build finished');
22
+ });
23
+ },
24
+ };
25
+
26
+ async function main() {
27
+ const ctx = await esbuild.context({
28
+ entryPoints: [
29
+ 'src/extension.ts'
30
+ ],
31
+ bundle: true,
32
+ format: 'cjs',
33
+ minify: production,
34
+ sourcemap: !production,
35
+ sourcesContent: false,
36
+ platform: 'node',
37
+ outfile: 'dist/extension.js',
38
+ external: ['vscode'],
39
+ logLevel: 'silent',
40
+ plugins: [
41
+ /* add to the end of plugins array */
42
+ esbuildProblemMatcherPlugin,
43
+ ],
44
+ });
45
+ if (watch) {
46
+ await ctx.watch();
47
+ } else {
48
+ await ctx.rebuild();
49
+ await ctx.dispose();
50
+ }
51
+ }
52
+
53
+ main().catch(e => {
54
+ console.error(e);
55
+ process.exit(1);
56
+ });
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "code-scope-highlighter",
3
+ "publisher": "joseavr",
4
+ "displayName": "Code Highlighter",
5
+ "description": "Highlight the scope of matching brackets with customizable colors and flexible highlight modes.",
6
+ "repository": "https://github.com/joseavr/code-highlighter",
7
+ "icon": "code-scope-highlighter-logo.webp",
8
+ "license": "MIT",
9
+ "version": "1.1.0",
10
+ "engines": {
11
+ "vscode": "^1.90.0"
12
+ },
13
+ "categories": [
14
+ "Other"
15
+ ],
16
+ "activationEvents": [
17
+ "*"
18
+ ],
19
+ "main": "./dist/extension.js",
20
+ "contributes": {
21
+ "commands": [
22
+ {
23
+ "command": "scope-highlighter.helloWorld",
24
+ "title": "Hello World"
25
+ }
26
+ ],
27
+ "configuration": {
28
+ "type": "object",
29
+ "title": "Scope Highlighter",
30
+ "properties": {
31
+ "codeScopeHighlighter.scopeColor": {
32
+ "type": "string",
33
+ "description": "Color for highlighting the entire scope of matching brackets. (Hex format)",
34
+ "default": "#4d4d4d89"
35
+ },
36
+ "codeScopeHighlighter.bracketColor": {
37
+ "type": "string",
38
+ "description": "Color for highlighting the matching brackets. (Hex format)",
39
+ "default": "#4d4d4d89"
40
+ },
41
+ "codeScopeHighlighter.matchBrackets": {
42
+ "type": "string",
43
+ "enum": [
44
+ "near",
45
+ "always",
46
+ "never"
47
+ ],
48
+ "default": "near",
49
+ "description": "Choose when the scope highlight should be active: 'near' for when the cursor is near the bracket, 'always' to always highlight, and 'never' to never highlight."
50
+ }
51
+ }
52
+ }
53
+ },
54
+ "devDependencies": {
55
+ "@types/vscode": "^1.90.0",
56
+ "@types/mocha": "^10.0.7",
57
+ "@types/node": "20.x",
58
+ "@typescript-eslint/eslint-plugin": "^7.14.1",
59
+ "@typescript-eslint/parser": "^7.11.0",
60
+ "eslint": "^8.57.0",
61
+ "esbuild": "^0.21.5",
62
+ "npm-run-all": "^4.1.5",
63
+ "typescript": "^5.4.5",
64
+ "@vscode/test-cli": "^0.0.9",
65
+ "@vscode/test-electron": "^2.4.0"
66
+ },
67
+ "scripts": {
68
+ "package": "pnpm run check-types && pnpm run lint && node esbuild.js --production",
69
+ "prepublish": "pnpm run package",
70
+ "watch": "npm-run-all -p watch:*",
71
+ "watch:esbuild": "node esbuild.js --watch",
72
+ "watch:tsc": "tsc --noEmit --watch --project tsconfig.json",
73
+ "compile": "pnpm run check-types && pnpm run lint && node esbuild.js",
74
+ "compile-tests": "tsc -p . --outDir out",
75
+ "test": "vscode-test",
76
+ "watch-tests": "tsc -p . -w --outDir out",
77
+ "pretest": "pnpm run compile-tests && pnpm run compile && pnpm run lint",
78
+ "check-types": "tsc --noEmit",
79
+ "lint": "eslint src --ext ts"
80
+ }
81
+ }
@@ -0,0 +1,2 @@
1
+ onlyBuiltDependencies:
2
+ - esbuild
@@ -0,0 +1,61 @@
1
+ import * as vscode from "vscode"
2
+ import { Highlighter } from "./highlighter"
3
+
4
+ export class Controller {
5
+ private highlighter: Highlighter
6
+ private _disposable: vscode.Disposable
7
+
8
+ constructor(highlighter: Highlighter) {
9
+ this.highlighter = highlighter
10
+
11
+ const subscriptions: vscode.Disposable[] = []
12
+ vscode.window.onDidChangeTextEditorSelection(
13
+ this._onEvent,
14
+ this,
15
+ subscriptions
16
+ )
17
+ vscode.window.onDidChangeActiveTextEditor(
18
+ this._onChangeEditor,
19
+ this,
20
+ subscriptions
21
+ )
22
+ vscode.workspace.onDidChangeConfiguration(
23
+ this._onUpdateSettings,
24
+ this,
25
+ subscriptions
26
+ )
27
+
28
+ this._onEvent()
29
+
30
+ this._disposable = vscode.Disposable.from.apply(
31
+ vscode.Disposable,
32
+ subscriptions
33
+ )
34
+
35
+ this.highlighter.updateConfig()
36
+ this.highlighter.onChange()
37
+ }
38
+
39
+ dispose(): void {
40
+ this._disposable.dispose()
41
+ }
42
+
43
+ private _onUpdateSettings(
44
+ configuration: vscode.ConfigurationChangeEvent
45
+ ): void {
46
+ if (configuration.affectsConfiguration("codeScopeHighlighter")) {
47
+ this.highlighter.updateConfig()
48
+ }
49
+ }
50
+
51
+ private _onChangeEditor(): void {
52
+ this.highlighter.updateConfig()
53
+ this.highlighter.onChange()
54
+ }
55
+
56
+ private _onEvent(e?: vscode.TextEditorSelectionChangeEvent): void {
57
+ if (e && e.textEditor === vscode.window.activeTextEditor) {
58
+ this.highlighter.onChange()
59
+ }
60
+ }
61
+ }
@@ -0,0 +1,11 @@
1
+ import * as vscode from "vscode"
2
+ import { Highlighter } from "./highlighter"
3
+ import { Controller } from "./controller"
4
+
5
+ export function activate(context: vscode.ExtensionContext) {
6
+ const highligher = new Highlighter()
7
+ const controller = new Controller(highligher)
8
+
9
+ context.subscriptions.push(highligher)
10
+ context.subscriptions.push(controller)
11
+ }
@@ -0,0 +1,129 @@
1
+ import * as vscode from "vscode"
2
+ import util from "./util"
3
+ import { HighlighterMode, MatchingBracket } from "./types"
4
+
5
+ class Highlighter {
6
+ scoperRangeDecorationType: vscode.TextEditorDecorationType
7
+ scoperEndDecorationType: vscode.TextEditorDecorationType
8
+ userConfigHighlightingMode: HighlighterMode
9
+
10
+ constructor() {
11
+ this.scoperRangeDecorationType = util.setRangeStyle()
12
+ this.scoperEndDecorationType = util.setEndStyle()
13
+ this.userConfigHighlightingMode = vscode.workspace
14
+ .getConfiguration("codeScopeHighlighter")
15
+ .get<HighlighterMode>("matchBrackets", HighlighterMode.Near)
16
+ }
17
+
18
+ updateConfig() {
19
+ if (vscode.window.activeTextEditor) {
20
+ vscode.window.activeTextEditor.setDecorations(
21
+ this.scoperRangeDecorationType,
22
+ []
23
+ )
24
+ vscode.window.activeTextEditor.setDecorations(
25
+ this.scoperEndDecorationType,
26
+ []
27
+ )
28
+ }
29
+ this.scoperRangeDecorationType.dispose()
30
+ this.scoperEndDecorationType.dispose()
31
+
32
+ this.scoperRangeDecorationType = util.setRangeStyle()
33
+ this.scoperEndDecorationType = util.setEndStyle()
34
+
35
+ util.updateConfig()
36
+ }
37
+
38
+ onChange() {
39
+ this.scoperRangeDecorationType.dispose()
40
+ this.scoperEndDecorationType.dispose()
41
+
42
+ this.scoperRangeDecorationType = util.setRangeStyle()
43
+ this.scoperEndDecorationType = util.setEndStyle()
44
+
45
+ const editor = vscode.window.activeTextEditor
46
+
47
+ if (!editor) {
48
+ return
49
+ }
50
+
51
+ const offset = editor.document.offsetAt(editor.selection.active)
52
+ const text = editor.document.getText()
53
+
54
+ let backwardResult: MatchingBracket
55
+ let forwardResult: MatchingBracket
56
+
57
+ // ^: cursor position
58
+ // (...)
59
+ // ^
60
+ if (util.isCloseBracket(text.charAt(offset - 1))) {
61
+ backwardResult = util.findLeftBracket(text, offset - 2)
62
+ forwardResult = util.findRightBracket(text, offset - 1)
63
+ }
64
+
65
+ // (...)
66
+ // ^
67
+ else if (util.isOpenBracket(text.charAt(offset))) {
68
+ backwardResult = util.findLeftBracket(text, offset)
69
+ forwardResult = util.findRightBracket(text, offset + 1)
70
+ }
71
+
72
+ // (.)
73
+ // ^
74
+ else {
75
+ backwardResult = util.findLeftBracket(text, offset - 1)
76
+ forwardResult = util.findRightBracket(text, offset)
77
+ }
78
+
79
+ const shouldHighlight = util.shouldHighlight(
80
+ this.userConfigHighlightingMode,
81
+ offset,
82
+ backwardResult,
83
+ forwardResult
84
+ )
85
+
86
+ // set up the decoratiosn to highlight the scope and matching brackets
87
+ if (
88
+ util.isMatchingBracket(backwardResult.bracket, forwardResult.bracket) &&
89
+ shouldHighlight
90
+ ) {
91
+ let start =
92
+ backwardResult.offset < text.length
93
+ ? backwardResult.offset + 1
94
+ : backwardResult.offset
95
+ let end = forwardResult.offset
96
+
97
+ const start_decoration = new vscode.Range(
98
+ editor.document.positionAt(start - 1),
99
+ editor.document.positionAt(start)
100
+ )
101
+ const range_decoration = new vscode.Range(
102
+ editor.document.positionAt(start),
103
+ editor.document.positionAt(end)
104
+ )
105
+ const end_decoration = new vscode.Range(
106
+ editor.document.positionAt(end),
107
+ editor.document.positionAt(end + 1)
108
+ )
109
+
110
+ var rangeDecorations = []
111
+ var endDecorations = []
112
+
113
+ rangeDecorations.push(range_decoration)
114
+ editor.setDecorations(this.scoperRangeDecorationType, rangeDecorations)
115
+
116
+ endDecorations.push(start_decoration)
117
+ endDecorations.push(end_decoration)
118
+ editor.setDecorations(this.scoperEndDecorationType, endDecorations)
119
+ }
120
+ }
121
+
122
+ dispose(): void {
123
+ this.scoperRangeDecorationType.dispose()
124
+ this.scoperEndDecorationType.dispose()
125
+ }
126
+ }
127
+
128
+ const highlighter = new Highlighter()
129
+ export { highlighter, Highlighter }
@@ -0,0 +1,15 @@
1
+ import * as assert from 'assert';
2
+
3
+ // You can import and use all API from the 'vscode' module
4
+ // as well as import your extension to test it
5
+ import * as vscode from 'vscode';
6
+ // import * as myExtension from '../../extension';
7
+
8
+ suite('Extension Test Suite', () => {
9
+ vscode.window.showInformationMessage('Start all tests.');
10
+
11
+ test('Sample test', () => {
12
+ assert.strictEqual(-1, [1, 2, 3].indexOf(5));
13
+ assert.strictEqual(-1, [1, 2, 3].indexOf(0));
14
+ });
15
+ });
package/src/types.ts ADDED
@@ -0,0 +1,12 @@
1
+ export interface MatchingBracket {
2
+ bracket: string
3
+ offset: number
4
+ }
5
+
6
+ export enum HighlighterMode {
7
+ Near = "near",
8
+ Always = "always",
9
+ Never = "never",
10
+ }
11
+
12
+ export type BracketStringType = "parentheses" | "braces" | "squareBrackets"
package/src/util.ts ADDED
@@ -0,0 +1,148 @@
1
+ import * as vscode from "vscode"
2
+ import { HighlighterMode, MatchingBracket } from "./types"
3
+
4
+ let openingBrackets = ""
5
+ let closingBrackets = ""
6
+
7
+ function updateConfig() {
8
+ const activeEditor = vscode.window.activeTextEditor
9
+
10
+ if (activeEditor) {
11
+ openingBrackets = "({["
12
+ closingBrackets = ")}]"
13
+ }
14
+ }
15
+
16
+ function isMatchingBracket(open: string, close: string) {
17
+ switch (open) {
18
+ case "(":
19
+ return close === ")"
20
+ case "{":
21
+ return close === "}"
22
+ case "[":
23
+ return close === "]"
24
+ default:
25
+ return false
26
+ }
27
+ }
28
+
29
+ function isOpenBracket(char: string) {
30
+ return openingBrackets.includes(char)
31
+ }
32
+
33
+ function isCloseBracket(char: string) {
34
+ return closingBrackets.includes(char)
35
+ }
36
+
37
+ // Finds to the left the nearest open bracket using a stack.
38
+ // Starting from the cursor position (index) to the beginning of the (text)
39
+ function findLeftBracket(text: string, index: number): MatchingBracket {
40
+ const bracketStack = []
41
+ let offset = 0
42
+ let bracket = ""
43
+
44
+ for (let i = index; i >= 0; i--) {
45
+ let char = text.charAt(i)
46
+ if (isOpenBracket(char)) {
47
+ if (bracketStack.length === 0) {
48
+ bracket = char
49
+ offset = i
50
+ break
51
+ } else {
52
+ let top = bracketStack.pop()!
53
+ if (!isMatchingBracket(char, top)) {
54
+ throw "Unmatched bracket pair"
55
+ }
56
+ }
57
+ } else if (isCloseBracket(char)) {
58
+ bracketStack.push(char)
59
+ }
60
+ }
61
+
62
+ return { bracket, offset }
63
+ }
64
+
65
+ // Finds to the right the nearest open bracket using a stack.
66
+ // Starting from the cursor position (index) to the end of the (text)
67
+ function findRightBracket(text: string, index: number): MatchingBracket {
68
+ const bracketStack = []
69
+ let offset = text.length
70
+ let bracket = ""
71
+ for (let i = index; i < text.length; i++) {
72
+ let char = text.charAt(i)
73
+ if (isCloseBracket(char)) {
74
+ if (bracketStack.length === 0) {
75
+ offset = i
76
+ bracket = char
77
+ break
78
+ } else {
79
+ let top = bracketStack.pop()!
80
+ if (!isMatchingBracket(top, char)) {
81
+ throw "Unmatched bracket pair"
82
+ }
83
+ }
84
+ } else if (isOpenBracket(char)) {
85
+ bracketStack.push(char)
86
+ }
87
+ }
88
+
89
+ return { bracket, offset }
90
+ }
91
+
92
+ function shouldHighlight(
93
+ highlighterMode: HighlighterMode,
94
+ offset: number,
95
+ leftMatchingBracket: { offset: number; bracket: string },
96
+ rightMatchingBracket: { offset: number; bracket: string }
97
+ ): boolean {
98
+ switch (highlighterMode) {
99
+ // highlight only when the cursor is next to the matching bracket
100
+ case HighlighterMode.Near:
101
+ return (
102
+ offset === leftMatchingBracket.offset ||
103
+ offset === rightMatchingBracket.offset + 1
104
+ )
105
+ case HighlighterMode.Always:
106
+ return true
107
+ case HighlighterMode.Never:
108
+ return false
109
+ default:
110
+ return false // fallback for any unexpected values
111
+ }
112
+ }
113
+
114
+ function setRangeStyle() {
115
+ return vscode.window.createTextEditorDecorationType({
116
+ light: {
117
+ backgroundColor: "#4d4d4d30"
118
+ },
119
+ dark: {
120
+ backgroundColor:
121
+ vscode.workspace.getConfiguration("codeScopeHighlighter").scopeColor,
122
+ },
123
+ })
124
+ }
125
+
126
+ function setEndStyle() {
127
+ return vscode.window.createTextEditorDecorationType({
128
+ light: {
129
+ backgroundColor: "#4d4d4d30"
130
+ },
131
+ dark: {
132
+ backgroundColor:
133
+ vscode.workspace.getConfiguration("codeScopeHighlighter").bracketColor,
134
+ },
135
+ })
136
+ }
137
+
138
+ export default {
139
+ updateConfig,
140
+ isMatchingBracket,
141
+ isOpenBracket,
142
+ isCloseBracket,
143
+ findLeftBracket,
144
+ findRightBracket,
145
+ shouldHighlight,
146
+ setRangeStyle,
147
+ setEndStyle,
148
+ }
@@ -0,0 +1,38 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>HTML Highlighting Test</title>
7
+ </head>
8
+ <body>
9
+ <div class="container">
10
+ <header>
11
+ <h1>Welcome to HTML Highlighting</h1>
12
+ <nav>
13
+ <ul>
14
+ <li><a href="#home">Home</a></li>
15
+ <li><a href="#about">About</a></li>
16
+ <li><a href="#contact">Contact</a></li>
17
+ </ul>
18
+ </nav>
19
+ </header>
20
+
21
+ <main>
22
+ <section>
23
+ <h2>Features</h2>
24
+ <p>This extension now supports <strong>HTML tag highlighting</strong> with intelligent cursor positioning.</p>
25
+ <ul>
26
+ <li>Place cursor on <code>&lt;</code> to highlight entire tag</li>
27
+ <li>Place cursor on <code>&gt;</code> to highlight content only</li>
28
+ <li>Works with nested tags</li>
29
+ </ul>
30
+ </section>
31
+ </main>
32
+
33
+ <footer>
34
+ <p>&copy; 2024 HTML Highlighter</p>
35
+ </footer>
36
+ </div>
37
+ </body>
38
+ </html>
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "Node16",
4
+ "target": "ES2022",
5
+ "lib": [
6
+ "ES2022"
7
+ ],
8
+ "sourceMap": true,
9
+ "rootDir": "src",
10
+ "strict": true /* enable all strict type-checking options */
11
+ /* Additional Checks */
12
+ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
13
+ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
14
+ // "noUnusedParameters": true, /* Report errors on unused parameters. */
15
+ }
16
+ }