diff --git a/.devcontainer/tools.mk b/.devcontainer/tools.mk index 4b0c4cc0..d61b1df1 100644 --- a/.devcontainer/tools.mk +++ b/.devcontainer/tools.mk @@ -5,11 +5,10 @@ ifeq ($(strip $(ARCH)),) $(error Unable to determine platform architecture) endif -HATCH_VERSION = 1.10.0 -NODE_VERSION := 18.20.2 +NODE_VERSION := 18.20.4 # The versions of Python we support -PYXX_versions := 3.8 3.9 3.10 3.11 3.12 +PYXX_versions := 3.9 3.10 3.11 3.12 PY_INTERPRETERS = # Hatch is not only used for building packages, but bootstrapping any missing @@ -17,12 +16,12 @@ PY_INTERPRETERS = HATCH ?= $(or $(shell command -v hatch), $(BIN)/hatch) $(HATCH): - curl -L --output /tmp/hatch.tar.gz https://github.com/pypa/hatch/releases/download/hatch-v$(HATCH_VERSION)/hatch-$(HATCH_VERSION)-$(ARCH)-unknown-linux-gnu.tar.gz + curl -L --output /tmp/hatch.tar.gz https://github.com/pypa/hatch/releases/latest/download/hatch-$(ARCH)-unknown-linux-gnu.tar.gz tar -xf /tmp/hatch.tar.gz -C /tmp rm /tmp/hatch.tar.gz test -d $(BIN) || mkdir -p $(BIN) - mv /tmp/hatch-$(HATCH_VERSION)-$(ARCH)-unknown-linux-gnu $(HATCH) + mv /tmp/hatch $(HATCH) $@ --version touch $@ diff --git a/.github/dependabot.yml b/.github/dependabot.yml index fa7921d5..1f3f666a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,22 +9,22 @@ updates: directory: "/" target-branch: "develop" schedule: - interval: "weekly" + interval: "monthly" - package-ecosystem: "npm" directory: "/code" target-branch: "develop" schedule: - interval: "weekly" + interval: "monthly" - package-ecosystem: "pip" directory: "/code" target-branch: "develop" schedule: - interval: "weekly" + interval: "monthly" - package-ecosystem: "pip" directory: "/lib/esbonio/tests/workspaces/demo" target-branch: "develop" schedule: - interval: "weekly" + interval: "monthly" diff --git a/.github/workflows/lsp-pr.yml b/.github/workflows/lsp-pr.yml index cd5246a2..ec546269 100644 --- a/.github/workflows/lsp-pr.yml +++ b/.github/workflows/lsp-pr.yml @@ -45,7 +45,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] os: [ubuntu-latest, windows-latest] steps: @@ -55,6 +55,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} + allow-prereleases: true - name: pip cache uses: actions/cache@v4 diff --git a/.github/workflows/lsp-release.yml b/.github/workflows/lsp-release.yml index 4190beec..5da4126f 100644 --- a/.github/workflows/lsp-release.yml +++ b/.github/workflows/lsp-release.yml @@ -121,7 +121,7 @@ jobs: - uses: 'actions/setup-python@v5' with: # This must be the minimum Python version we support - python-version: "3.8" + python-version: "3.9" - name: pip cache uses: actions/cache@v4 diff --git a/.github/workflows/sphinx-ext-pr.yml b/.github/workflows/sphinx-ext-pr.yml index e29d304f..23e402c0 100644 --- a/.github/workflows/sphinx-ext-pr.yml +++ b/.github/workflows/sphinx-ext-pr.yml @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 @@ -67,10 +67,10 @@ jobs: - run: | python --version python -m pip install --upgrade pip - python -m pip install --upgrade tox + python -m pip install --upgrade hatch name: Setup Environment - run: | cd lib/esbonio-extensions - python -m tox -e py`echo ${{ matrix.python-version }} | tr -d .` - name: Test + hatch test -i py=${{ matrix.python-version }} + name: Run Tests diff --git a/.github/workflows/vscode-pr.yml b/.github/workflows/vscode-pr.yml index bb51ddbb..3f821182 100644 --- a/.github/workflows/vscode-pr.yml +++ b/.github/workflows/vscode-pr.yml @@ -22,7 +22,7 @@ jobs: - uses: 'actions/setup-python@v5' with: # This must be the minimum Python version we support - python-version: "3.8" + python-version: "3.9" - name: Pip cache uses: actions/cache@v4 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ab3a205b..0e70a945 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,4 +1,6 @@ -exclude: '.bumpversion.cfg$' +ci: + autoupdate_schedule: quarterly + repos: - repo: https://github.com/pre-commit/pre-commit-hooks @@ -9,26 +11,41 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.2 + rev: v0.6.5 hooks: - id: ruff + name: ruff (esbonio) + args: [--fix] + files: 'lib/esbonio/.*\.py' + + - id: ruff + name: ruff (esbonio-extensions) args: [--fix] + files: 'lib/esbonio-extensions/.*\.py' - id: ruff-format + name: ruff-format (esbonio) + files: 'lib/esbonio/.*\.py' + + - id: ruff-format + name: ruff-format (esbonio-extensions) + files: 'lib/esbonio-extensions/.*\.py' - repo: https://github.com/pre-commit/mirrors-mypy - rev: 'v1.10.1' + rev: 'v1.11.2' hooks: - id: mypy name: mypy (scripts) files: 'scripts/.*\.py' + exclude: 'scripts/.*_documentation\.py' + - id: mypy name: mypy (esbonio) args: [--config,lib/esbonio/pyproject.toml] additional_dependencies: - aiosqlite - platformdirs - - pygls + - pygls>=2a0 - pytest_lsp>=0.3 - sphinx - tomli diff --git a/.vscode/settings.json b/.vscode/settings.json index 9722740e..3ecb53a9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -26,9 +26,25 @@ "**/.ipynb_checkpoints": true, "**/.coverage": true, "**/.vscode-test": true, - "**/.mypy_cache": true + "**/.mypy_cache": true, + "**/.ruff_cache": true }, "esbonio.server.showDeprecationWarnings": true, + "esbonio.sphinx.configOverrides": { + // "extensions": [ + // "sphinx.ext.autodoc", + // "sphinx.ext.intersphinx", + // "sphinx.ext.napoleon", + // "sphinx.ext.viewcode", + // "sphinx_design", + // "myst_parser", + // "cli_help", + // "collection_items", + // "domain", + // ], + // "html_theme": "alabaster", + // "html_theme_options": {}, + }, "python.testing.pytestArgs": [ "lib/esbonio/tests" ], diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d0181bd9..e6640fcd 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -24,23 +24,6 @@ "$tsc-watch" ] }, - { - "label": "Build Tests", - "type": "npm", - "script": "compile-test", - "isBackground": false, - "options": { - "cwd": "${workspaceRoot}/code" - }, - "group": "build", - "presentation": { - "panel": "dedicated", - "reveal": "never", - }, - "problemMatcher": [ - "$tsc-watch" - ] - }, { "label": "Build Docs", "type": "shell", diff --git a/code/Makefile b/code/Makefile index 923c4b37..62392432 100644 --- a/code/Makefile +++ b/code/Makefile @@ -36,15 +36,15 @@ dev-deps: node_modules/.installed bundled/libs/.installed # Ensures the latest version of esbonio from PyPi is used. release-deps: node_modules/.installed bundled/libs/.installed -test -L bundled/libs/esbonio && rm bundled/libs/esbonio - test -d bundled/libs/esbonio-*.dist-info || $(PY38) -m pip install -t ./bundled/libs --no-cache-dir --implementation py --no-deps --upgrade $(ESBONIO) + test -d bundled/libs/esbonio-*.dist-info || $(PY39) -m pip install -t ./bundled/libs --no-cache-dir --implementation py --no-deps --upgrade $(ESBONIO) requirements.txt: $(HATCH) requirements.in $(HATCH) run deps:update -bundled/libs/.installed: $(PY38) requirements.txt +bundled/libs/.installed: $(PY39) requirements.txt -test -d bundled/libs && rm -r bundled/libs - $(PY38) --version - $(PY38) -m pip install -t ./bundled/libs --no-cache-dir --implementation py --no-deps --upgrade -r ./requirements.txt + $(PY39) --version + $(PY39) -m pip install -t ./bundled/libs --no-cache-dir --implementation py --no-deps --upgrade -r ./requirements.txt touch $@ node_modules/.installed: package.json package-lock.json $(NPM) diff --git a/code/changes/785.enhancement.md b/code/changes/785.enhancement.md new file mode 100644 index 00000000..d0a1061c --- /dev/null +++ b/code/changes/785.enhancement.md @@ -0,0 +1 @@ +Expose the `esbonio.sphinx.configOverrides` option diff --git a/code/changes/858.misc.md b/code/changes/858.misc.md new file mode 100644 index 00000000..e3446f31 --- /dev/null +++ b/code/changes/858.misc.md @@ -0,0 +1 @@ +Drop support for Python 3.8 diff --git a/code/changes/859.misc.md b/code/changes/859.misc.md new file mode 100644 index 00000000..f32ba63f --- /dev/null +++ b/code/changes/859.misc.md @@ -0,0 +1 @@ +Add support for Python 3.13 diff --git a/code/changes/881.enchancement.md b/code/changes/881.enchancement.md new file mode 100644 index 00000000..b16d91bc --- /dev/null +++ b/code/changes/881.enchancement.md @@ -0,0 +1 @@ +The Sphinx Process tree view now includes details including `esbonio.sphinx.pythonCommand`, `esbonio.sphinx.buildCommand`, the current builder and output files diff --git a/code/changes/881.misc.md b/code/changes/881.misc.md new file mode 100644 index 00000000..3a74af5c --- /dev/null +++ b/code/changes/881.misc.md @@ -0,0 +1,7 @@ +**IMPORTANT!** + +The VSCode extension will no longer automatically inject the currently active Python interpreter into the configuration sent to the server. +It is now required for all users to set the `esbonio.sphinx.pythonCommand` option, either in your VSCode settings, or in your project's `pyproject.toml` file. + +This makes VSCode's behavior more predicable and brings it in line with how other editors behave. +It also encourages the sharing of project configuration settings, which is particuarly useful if you use an [environment manager](https://docs.esbon.io/en/latest/lsp/howto/use-esbonio-with.html) diff --git a/code/guides/bring-your-own-sphinx.md b/code/guides/bring-your-own-sphinx.md index b1dfd93d..dbf476ad 100644 --- a/code/guides/bring-your-own-sphinx.md +++ b/code/guides/bring-your-own-sphinx.md @@ -4,7 +4,4 @@ While the `esbonio` language server is bundled as part of the extension, it does This is because every Sphinx project is unique with its own set of dependencies and required extensions. In order to correctly understand your project `esbonio` needs to use the same Python environment that you use to build your documentation. -The Esbonio extension supports two mechanisms for selecting your Python environment. - -1. If the official Python extension is available, by default Esbonio will attempt to use the same environment you have configured for your workspace. -2. Alternatively, you can use the `esbonio.sphinx.pythonCommand` setting to override this behavior. +You can tell Esbonio which environment to use by setting the `esbonio.sphinx.pythonCommand` option. See [this guide](https://docs.esbon.io/en/latest/lsp/howto/use-esbonio-with.html) for some examples diff --git a/code/hatch.toml b/code/hatch.toml index df070ec3..c7d3c6b3 100644 --- a/code/hatch.toml +++ b/code/hatch.toml @@ -1,5 +1,5 @@ [envs.deps] -python = "3.8" +python = "3.9" dependencies = ["pip-tools"] skip-install = true diff --git a/code/package-lock.json b/code/package-lock.json index 20225905..2efed774 100644 --- a/code/package-lock.json +++ b/code/package-lock.json @@ -1,26 +1,25 @@ { "name": "esbonio", - "version": "0.94.2", + "version": "0.95.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "esbonio", - "version": "0.94.2", + "version": "0.95.1", "license": "MIT", "dependencies": { "@vscode/python-extension": "^1.0.5", - "semver": "^7.6.2", + "semver": "^7.6.3", "vscode-languageclient": "^9.0.1" }, "devDependencies": { - "@types/glob": "^8.1.0", "@types/node": "^18", - "@types/vscode": "1.78.0", - "@vscode/vsce": "^2.30.0", - "esbuild": "^0.23.0", - "ovsx": "^0.9.1", - "typescript": "^5.5.3" + "@types/vscode": "1.82.0", + "@vscode/vsce": "^3.1.0", + "esbuild": "^0.23.1", + "ovsx": "^0.9.4", + "typescript": "^5.6.2" }, "engines": { "vscode": "^1.82.0" @@ -235,13 +234,14 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", - "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" @@ -251,13 +251,14 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", - "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -267,13 +268,14 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", - "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -283,13 +285,14 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", - "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -299,13 +302,14 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -315,13 +319,14 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", - "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -331,13 +336,14 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", - "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -347,13 +353,14 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", - "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -363,13 +370,14 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", - "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -379,13 +387,14 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", - "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -395,13 +404,14 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", - "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -411,13 +421,14 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", - "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", "cpu": [ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -427,13 +438,14 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", - "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", "cpu": [ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -443,13 +455,14 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", - "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -459,13 +472,14 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", - "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -475,13 +489,14 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", - "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -491,13 +506,14 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", - "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -507,13 +523,14 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", - "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -523,13 +540,14 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", - "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -539,13 +557,14 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", - "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -555,13 +574,14 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", - "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" @@ -571,13 +591,14 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", - "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -587,13 +608,14 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", - "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -603,13 +625,14 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -618,22 +641,83 @@ "node": ">=18" } }, - "node_modules/@types/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "dependencies": { - "@types/minimatch": "^5.1.2", - "@types/node": "*" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@types/node": { "version": "18.18.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.5.tgz", @@ -641,10 +725,11 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.78.0.tgz", - "integrity": "sha512-LJZIJpPvKJ0HVQDqfOy6W4sNKUBBwyDu1Bs8chHBZOe9MNuKTJtidgZ2bqjhmmWpUb0TIIqv47BFUcVmAsgaVA==", - "dev": true + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.82.0.tgz", + "integrity": "sha512-VSHV+VnpF8DEm8LNrn8OJ8VuUNcBzN3tMvKrNpbhhfuVjFm82+6v44AbDhLvVFgCzn6vs94EJNTp7w8S6+Q1Rw==", + "dev": true, + "license": "MIT" }, "node_modules/@vscode/python-extension": { "version": "1.0.5", @@ -656,10 +741,11 @@ } }, "node_modules/@vscode/vsce": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.30.0.tgz", - "integrity": "sha512-MBYpXdCY1SCdc2u/y11kmJuSODKFyZRpeRTQq5p4rSg05QSjSy5pz6h/BGLNdSahgXfKRBATEkjAcJFdJuDz8Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.1.0.tgz", + "integrity": "sha512-fwdfp1Ol+bZtlSGkpcd/nztfo6+SVsTOMWjZ/+a88lVtUn7gXNbSu7dbniecl5mz4vINl+oaVDVtVdGbJDApmw==", "dev": true, + "license": "MIT", "dependencies": { "@azure/identity": "^4.1.0", "@vscode/vsce-sign": "^2.0.0", @@ -669,17 +755,17 @@ "cockatiel": "^3.1.2", "commander": "^6.2.1", "form-data": "^4.0.0", - "glob": "^7.0.6", + "glob": "^11.0.0", "hosted-git-info": "^4.0.2", "jsonc-parser": "^3.2.0", "leven": "^3.1.0", - "markdown-it": "^12.3.2", + "markdown-it": "^14.1.0", "mime": "^1.3.4", "minimatch": "^3.0.3", "parse-semver": "^1.1.1", "read": "^1.0.7", "semver": "^7.5.2", - "tmp": "^0.2.1", + "tmp": "^0.2.3", "typed-rest-client": "^1.8.4", "url-join": "^4.0.1", "xml2js": "^0.5.0", @@ -690,7 +776,7 @@ "vsce": "vsce" }, "engines": { - "node": ">= 16" + "node": ">= 20" }, "optionalDependencies": { "keytar": "^7.7.0" @@ -831,6 +917,53 @@ "win32" ] }, + "node_modules/@vscode/vsce/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vscode/vsce/node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/agent-base": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", @@ -887,7 +1020,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/asynckit": { "version": "0.4.0", @@ -1172,6 +1306,20 @@ "dev": true, "optional": true }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/css-select": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", @@ -1350,6 +1498,12 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -1359,6 +1513,12 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -1400,11 +1560,12 @@ } }, "node_modules/esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -1412,30 +1573,30 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" } }, "node_modules/escape-string-regexp": { @@ -1495,6 +1656,34 @@ } } }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -1519,8 +1708,9 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" }, "node_modules/function-bind": { "version": "1.1.2", @@ -1626,15 +1816,17 @@ "optional": true }, "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, @@ -1802,8 +1994,10 @@ "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -1878,6 +2072,30 @@ "dev": true, "optional": true }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", + "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -1970,12 +2188,13 @@ } }, "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, + "license": "MIT", "dependencies": { - "uc.micro": "^1.0.1" + "uc.micro": "^2.0.0" } }, "node_modules/lodash.includes": { @@ -2033,35 +2252,42 @@ } }, "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, "bin": { - "markdown-it": "bin/markdown-it.js" + "markdown-it": "bin/markdown-it.mjs" } }, "node_modules/markdown-it/node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" }, "node_modules/mime": { "version": "1.6.0", @@ -2128,6 +2354,15 @@ "dev": true, "optional": true }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -2255,10 +2490,11 @@ } }, "node_modules/ovsx": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.9.1.tgz", - "integrity": "sha512-faORiHeVdRFXVjvwjGvsGdfw49ocUZwUvjrrObZDzhlkKkrUS8L2afeXF8goeuv1YbTV8lmFfBYAt0C4FaoVuQ==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.9.4.tgz", + "integrity": "sha512-IZbOqvqcUAfT+iZahSXViE5Aaq8e5dzWnGDjZ1VGR4oA/SYKPOn5VuTPudVBDkhlLMDKRJTLkRlq924wwe6nIQ==", "dev": true, + "license": "EPL-2.0", "dependencies": { "@vscode/vsce": "^2.25.0", "commander": "^6.1.0", @@ -2275,6 +2511,105 @@ "node": ">= 16" } }, + "node_modules/ovsx/node_modules/@vscode/vsce": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.32.0.tgz", + "integrity": "sha512-3EFJfsgrSftIqt3EtdRcAygy/OJ3hstyI1cDmIgkU9CFZW5C+3djr6mfosndCUqcVYuyjmxOK1xmFp/Bq7+NIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/identity": "^4.1.0", + "@vscode/vsce-sign": "^2.0.0", + "azure-devops-node-api": "^12.5.0", + "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.9", + "cockatiel": "^3.1.2", + "commander": "^6.2.1", + "form-data": "^4.0.0", + "glob": "^7.0.6", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^12.3.2", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "semver": "^7.5.2", + "tmp": "^0.2.1", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 16" + }, + "optionalDependencies": { + "keytar": "^7.7.0" + } + }, + "node_modules/ovsx/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/ovsx/node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/ovsx/node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/ovsx/node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/ovsx/node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, "node_modules/parse-semver": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", @@ -2311,12 +2646,47 @@ "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", + "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "dev": true, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -2369,6 +2739,16 @@ "once": "^1.3.1" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.12.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", @@ -2445,21 +2825,6 @@ "dev": true, "optional": true }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -2487,9 +2852,9 @@ "dev": true }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -2521,6 +2886,27 @@ "node": ">= 0.4" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -2634,6 +3020,51 @@ "node": ">=4" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -2647,6 +3078,28 @@ "node": ">=4" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -2705,15 +3158,12 @@ } }, "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, "engines": { - "node": ">=8.17.0" + "node": ">=14.14" } }, "node_modules/tslib": { @@ -2756,10 +3206,11 @@ } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2769,10 +3220,11 @@ } }, "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" }, "node_modules/underscore": { "version": "1.13.6", @@ -2851,19 +3303,208 @@ "vscode-languageserver-types": "3.17.5" } }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "optional": true, "dependencies": { - "string-width": "^1.0.2 || 2" + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/wrappy": { @@ -3093,188 +3734,227 @@ } }, "@esbuild/aix-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", - "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", "dev": true, "optional": true }, "@esbuild/android-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", - "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", "dev": true, "optional": true }, "@esbuild/android-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", - "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", "dev": true, "optional": true }, "@esbuild/android-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", - "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", "dev": true, "optional": true }, "@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", "dev": true, "optional": true }, "@esbuild/darwin-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", - "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", "dev": true, "optional": true }, "@esbuild/freebsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", - "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", "dev": true, "optional": true }, "@esbuild/freebsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", - "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", "dev": true, "optional": true }, "@esbuild/linux-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", - "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", "dev": true, "optional": true }, "@esbuild/linux-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", - "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", "dev": true, "optional": true }, "@esbuild/linux-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", - "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", "dev": true, "optional": true }, "@esbuild/linux-loong64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", - "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", "dev": true, "optional": true }, "@esbuild/linux-mips64el": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", - "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", "dev": true, "optional": true }, "@esbuild/linux-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", - "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", "dev": true, "optional": true }, "@esbuild/linux-riscv64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", - "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", "dev": true, "optional": true }, "@esbuild/linux-s390x": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", - "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", "dev": true, "optional": true }, "@esbuild/linux-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", - "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", "dev": true, "optional": true }, "@esbuild/netbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", - "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", "dev": true, "optional": true }, "@esbuild/openbsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", - "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", "dev": true, "optional": true }, "@esbuild/openbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", - "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", "dev": true, "optional": true }, "@esbuild/sunos-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", - "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", "dev": true, "optional": true }, "@esbuild/win32-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", - "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", "dev": true, "optional": true }, "@esbuild/win32-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", - "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", "dev": true, "optional": true }, "@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", "dev": true, "optional": true }, - "@types/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "requires": { - "@types/minimatch": "^5.1.2", - "@types/node": "*" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } } }, - "@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true }, "@types/node": { "version": "18.18.5", @@ -3283,9 +3963,9 @@ "dev": true }, "@types/vscode": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.78.0.tgz", - "integrity": "sha512-LJZIJpPvKJ0HVQDqfOy6W4sNKUBBwyDu1Bs8chHBZOe9MNuKTJtidgZ2bqjhmmWpUb0TIIqv47BFUcVmAsgaVA==", + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.82.0.tgz", + "integrity": "sha512-VSHV+VnpF8DEm8LNrn8OJ8VuUNcBzN3tMvKrNpbhhfuVjFm82+6v44AbDhLvVFgCzn6vs94EJNTp7w8S6+Q1Rw==", "dev": true }, "@vscode/python-extension": { @@ -3294,9 +3974,9 @@ "integrity": "sha512-uYhXUrL/gn92mfqhjAwH2+yGOpjloBxj9ekoL4BhUsKcyJMpEg6WlNf3S3si+5x9zlbHHe7FYQNjZEbz1ymI9Q==" }, "@vscode/vsce": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.30.0.tgz", - "integrity": "sha512-MBYpXdCY1SCdc2u/y11kmJuSODKFyZRpeRTQq5p4rSg05QSjSy5pz6h/BGLNdSahgXfKRBATEkjAcJFdJuDz8Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.1.0.tgz", + "integrity": "sha512-fwdfp1Ol+bZtlSGkpcd/nztfo6+SVsTOMWjZ/+a88lVtUn7gXNbSu7dbniecl5mz4vINl+oaVDVtVdGbJDApmw==", "dev": true, "requires": { "@azure/identity": "^4.1.0", @@ -3307,23 +3987,59 @@ "cockatiel": "^3.1.2", "commander": "^6.2.1", "form-data": "^4.0.0", - "glob": "^7.0.6", + "glob": "^11.0.0", "hosted-git-info": "^4.0.2", "jsonc-parser": "^3.2.0", "keytar": "^7.7.0", "leven": "^3.1.0", - "markdown-it": "^12.3.2", + "markdown-it": "^14.1.0", "mime": "^1.3.4", "minimatch": "^3.0.3", "parse-semver": "^1.1.1", "read": "^1.0.7", "semver": "^7.5.2", - "tmp": "^0.2.1", + "tmp": "^0.2.3", "typed-rest-client": "^1.8.4", "url-join": "^4.0.1", "xml2js": "^0.5.0", "yauzl": "^2.3.1", "yazl": "^2.2.2" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "dependencies": { + "minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + } } }, "@vscode/vsce-sign": { @@ -3676,6 +4392,17 @@ "dev": true, "optional": true }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "css-select": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", @@ -3795,6 +4522,12 @@ "domhandler": "^4.2.0" } }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -3804,6 +4537,12 @@ "safe-buffer": "^5.0.1" } }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -3836,35 +4575,35 @@ "dev": true }, "esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", "dev": true, "requires": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" } }, "escape-string-regexp": { @@ -3901,6 +4640,24 @@ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true }, + "foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } + } + }, "form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -3922,7 +4679,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "function-bind": { @@ -4010,15 +4767,15 @@ "optional": true }, "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } @@ -4126,7 +4883,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "requires": { "once": "^1.3.0", @@ -4184,6 +4941,22 @@ "dev": true, "optional": true }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "jackspeak": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", + "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, "jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -4270,12 +5043,12 @@ "dev": true }, "linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, "requires": { - "uc.micro": "^1.0.1" + "uc.micro": "^2.0.0" } }, "lodash.includes": { @@ -4330,30 +5103,31 @@ } }, "markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, "requires": { "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, "dependencies": { "entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true } } }, "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "dev": true }, "mime": { @@ -4400,6 +5174,12 @@ "dev": true, "optional": true }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true + }, "mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -4506,9 +5286,9 @@ } }, "ovsx": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.9.1.tgz", - "integrity": "sha512-faORiHeVdRFXVjvwjGvsGdfw49ocUZwUvjrrObZDzhlkKkrUS8L2afeXF8goeuv1YbTV8lmFfBYAt0C4FaoVuQ==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.9.4.tgz", + "integrity": "sha512-IZbOqvqcUAfT+iZahSXViE5Aaq8e5dzWnGDjZ1VGR4oA/SYKPOn5VuTPudVBDkhlLMDKRJTLkRlq924wwe6nIQ==", "dev": true, "requires": { "@vscode/vsce": "^2.25.0", @@ -4518,8 +5298,89 @@ "leven": "^3.1.0", "semver": "^7.6.0", "tmp": "^0.2.1" + }, + "dependencies": { + "@vscode/vsce": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.32.0.tgz", + "integrity": "sha512-3EFJfsgrSftIqt3EtdRcAygy/OJ3hstyI1cDmIgkU9CFZW5C+3djr6mfosndCUqcVYuyjmxOK1xmFp/Bq7+NIg==", + "dev": true, + "requires": { + "@azure/identity": "^4.1.0", + "@vscode/vsce-sign": "^2.0.0", + "azure-devops-node-api": "^12.5.0", + "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.9", + "cockatiel": "^3.1.2", + "commander": "^6.2.1", + "form-data": "^4.0.0", + "glob": "^7.0.6", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "keytar": "^7.7.0", + "leven": "^3.1.0", + "markdown-it": "^12.3.2", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "semver": "^7.5.2", + "tmp": "^0.2.1", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + } + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true + }, + "linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "requires": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + } } }, + "package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, "parse-semver": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", @@ -4555,9 +5416,33 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, + "path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "requires": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "dependencies": { + "lru-cache": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", + "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "dev": true + } + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -4604,6 +5489,12 @@ "once": "^1.3.1" } }, + "punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true + }, "qs": { "version": "6.12.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", @@ -4669,15 +5560,6 @@ } } }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -4691,9 +5573,9 @@ "dev": true }, "semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==" + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" }, "set-blocking": { "version": "2.0.0", @@ -4716,6 +5598,21 @@ "has-property-descriptors": "^1.0.2" } }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -4790,6 +5687,40 @@ "strip-ansi": "^4.0.0" } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -4800,6 +5731,23 @@ "ansi-regex": "^3.0.0" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + } + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -4851,13 +5799,10 @@ } }, "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true }, "tslib": { "version": "2.6.2", @@ -4893,15 +5838,15 @@ } }, "typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true }, "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "dev": true }, "underscore": { @@ -4976,6 +5921,15 @@ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -4986,6 +5940,126 @@ "string-width": "^1.0.2 || 2" } }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/code/package.json b/code/package.json index 290d8097..50016384 100644 --- a/code/package.json +++ b/code/package.json @@ -31,17 +31,16 @@ ], "dependencies": { "@vscode/python-extension": "^1.0.5", - "semver": "^7.6.2", + "semver": "^7.6.3", "vscode-languageclient": "^9.0.1" }, "devDependencies": { - "@types/glob": "^8.1.0", "@types/node": "^18", - "@types/vscode": "1.78.0", - "@vscode/vsce": "^2.30.0", - "esbuild": "^0.23.0", - "ovsx": "^0.9.1", - "typescript": "^5.5.3" + "@types/vscode": "1.82.0", + "@vscode/vsce": "^3.1.0", + "esbuild": "^0.23.1", + "ovsx": "^0.9.4", + "typescript": "^5.6.2" }, "engines": { "vscode": "^1.82.0" @@ -165,6 +164,12 @@ "default": null, "description": "The sphinx-build command to use." }, + "esbonio.sphinx.configOverrides": { + "scope": "resource", + "type": "object", + "default": null, + "description": "Overrides to apply to Sphinx's configuration." + }, "esbonio.sphinx.pythonCommand": { "scope": "resource", "type": "array", @@ -433,7 +438,7 @@ "view/item/context": [ { "command": "esbonio.sphinx.restart", - "when": "view == sphinxProcesses && viewItem == process", + "when": "view == sphinxProcesses && viewItem == sphinxProcess", "group": "inline" } ] diff --git a/code/requirements.in b/code/requirements.in index 19202e2c..22ef66d5 100644 --- a/code/requirements.in +++ b/code/requirements.in @@ -1,7 +1,7 @@ # This file is used to generate requirements.txt. # # Only run the commands below to manually upgrade packages in requirements.txt: -# NOTE: Use the minimum version of Python we support when running these commands (currently 3.8) +# NOTE: Use the minimum version of Python we support when running these commands (currently 3.9) # # 1) python -m pip install pip-tools # 2) pip-compile --generate-hashes --upgrade ./requirements.in @@ -12,6 +12,6 @@ aiosqlite docutils platformdirs -pygls>=1.1.0 +pygls>=2a0 tomli websockets diff --git a/code/requirements.txt b/code/requirements.txt index 24d3a5fc..0511f3bc 100644 --- a/code/requirements.txt +++ b/code/requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # pip-compile --generate-hashes requirements.in @@ -8,119 +8,133 @@ aiosqlite==0.20.0 \ --hash=sha256:36a1deaca0cac40ebe32aac9977a6e2bbc7f5189f23f4a54d5908986729e5bd6 \ --hash=sha256:6d35c8c256637f4672f843c31021464090805bf925385ac39473fb16eaaca3d7 # via -r requirements.in -attrs==23.2.0 \ - --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \ - --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1 +attrs==24.2.0 \ + --hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \ + --hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2 # via # cattrs # lsprotocol -cattrs==23.2.3 \ - --hash=sha256:0341994d94971052e9ee70662542699a3162ea1e0c62f7ce1b4a57f563685108 \ - --hash=sha256:a934090d95abaa9e911dac357e3a8699e0b4b14f8529bcc7d2b1ad9d51672b9f +cattrs==24.1.2 \ + --hash=sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0 \ + --hash=sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85 # via # lsprotocol # pygls -docutils==0.20.1 \ - --hash=sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6 \ - --hash=sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b +docutils==0.21.2 \ + --hash=sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f \ + --hash=sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2 # via -r requirements.in -exceptiongroup==1.2.1 \ - --hash=sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad \ - --hash=sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16 +exceptiongroup==1.2.2 \ + --hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \ + --hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc # via cattrs -lsprotocol==2023.0.1 \ - --hash=sha256:c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2 \ - --hash=sha256:cc5c15130d2403c18b734304339e51242d3018a05c4f7d0f198ad6e0cd21861d +lsprotocol==2024.0.0a2 \ + --hash=sha256:65c218418b850a62fa70aed1dfe4cfae5c09ef7d3f9710060a0c0a609c1c6cb2 \ + --hash=sha256:928785ded9b3c3c044c04b36893471585476dd6df274b6d296c7910e3d284c1a # via pygls -platformdirs==4.2.2 \ - --hash=sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee \ - --hash=sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3 +platformdirs==4.3.6 \ + --hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \ + --hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb # via -r requirements.in -pygls==1.3.1 \ - --hash=sha256:140edceefa0da0e9b3c533547c892a42a7d2fd9217ae848c330c53d266a55018 \ - --hash=sha256:6e00f11efc56321bdeb6eac04f6d86131f654c7d49124344a9ebb968da3dd91e +pygls==2.0.0a1 \ + --hash=sha256:934568567502bd535146ff383b81c6811e5b4acfdc6d513cbcafe672689bdcd3 \ + --hash=sha256:acbc284440daeb5aca7f12b785d250e7a55f1e3aada57d0e22cc9efe63e47c12 # via -r requirements.in tomli==2.0.1 \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f # via -r requirements.in -typing-extensions==4.11.0 \ - --hash=sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0 \ - --hash=sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a +typing-extensions==4.12.2 \ + --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ + --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 # via # aiosqlite # cattrs -websockets==12.0 \ - --hash=sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b \ - --hash=sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6 \ - --hash=sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df \ - --hash=sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b \ - --hash=sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205 \ - --hash=sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892 \ - --hash=sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53 \ - --hash=sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2 \ - --hash=sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed \ - --hash=sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c \ - --hash=sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd \ - --hash=sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b \ - --hash=sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931 \ - --hash=sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30 \ - --hash=sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370 \ - --hash=sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be \ - --hash=sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec \ - --hash=sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf \ - --hash=sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62 \ - --hash=sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b \ - --hash=sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402 \ - --hash=sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f \ - --hash=sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123 \ - --hash=sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9 \ - --hash=sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603 \ - --hash=sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45 \ - --hash=sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558 \ - --hash=sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4 \ - --hash=sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438 \ - --hash=sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137 \ - --hash=sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480 \ - --hash=sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447 \ - --hash=sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8 \ - --hash=sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04 \ - --hash=sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c \ - --hash=sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb \ - --hash=sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967 \ - --hash=sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b \ - --hash=sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d \ - --hash=sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def \ - --hash=sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c \ - --hash=sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92 \ - --hash=sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2 \ - --hash=sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113 \ - --hash=sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b \ - --hash=sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28 \ - --hash=sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7 \ - --hash=sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d \ - --hash=sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f \ - --hash=sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468 \ - --hash=sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8 \ - --hash=sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae \ - --hash=sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611 \ - --hash=sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d \ - --hash=sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9 \ - --hash=sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca \ - --hash=sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f \ - --hash=sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2 \ - --hash=sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077 \ - --hash=sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2 \ - --hash=sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6 \ - --hash=sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374 \ - --hash=sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc \ - --hash=sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e \ - --hash=sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53 \ - --hash=sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399 \ - --hash=sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547 \ - --hash=sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3 \ - --hash=sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870 \ - --hash=sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5 \ - --hash=sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8 \ - --hash=sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7 +websockets==13.1 \ + --hash=sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a \ + --hash=sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54 \ + --hash=sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23 \ + --hash=sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7 \ + --hash=sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135 \ + --hash=sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700 \ + --hash=sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf \ + --hash=sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5 \ + --hash=sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e \ + --hash=sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c \ + --hash=sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02 \ + --hash=sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a \ + --hash=sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418 \ + --hash=sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f \ + --hash=sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3 \ + --hash=sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68 \ + --hash=sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978 \ + --hash=sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20 \ + --hash=sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295 \ + --hash=sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b \ + --hash=sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6 \ + --hash=sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb \ + --hash=sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a \ + --hash=sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa \ + --hash=sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0 \ + --hash=sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a \ + --hash=sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238 \ + --hash=sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c \ + --hash=sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084 \ + --hash=sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19 \ + --hash=sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d \ + --hash=sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7 \ + --hash=sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9 \ + --hash=sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79 \ + --hash=sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96 \ + --hash=sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6 \ + --hash=sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe \ + --hash=sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842 \ + --hash=sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa \ + --hash=sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3 \ + --hash=sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d \ + --hash=sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51 \ + --hash=sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7 \ + --hash=sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09 \ + --hash=sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096 \ + --hash=sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9 \ + --hash=sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b \ + --hash=sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5 \ + --hash=sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678 \ + --hash=sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea \ + --hash=sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d \ + --hash=sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49 \ + --hash=sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc \ + --hash=sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5 \ + --hash=sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027 \ + --hash=sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0 \ + --hash=sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878 \ + --hash=sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c \ + --hash=sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa \ + --hash=sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f \ + --hash=sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6 \ + --hash=sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2 \ + --hash=sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf \ + --hash=sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708 \ + --hash=sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6 \ + --hash=sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f \ + --hash=sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd \ + --hash=sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2 \ + --hash=sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d \ + --hash=sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7 \ + --hash=sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f \ + --hash=sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5 \ + --hash=sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6 \ + --hash=sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557 \ + --hash=sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14 \ + --hash=sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7 \ + --hash=sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd \ + --hash=sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c \ + --hash=sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17 \ + --hash=sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23 \ + --hash=sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db \ + --hash=sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6 \ + --hash=sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d \ + --hash=sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9 \ + --hash=sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee \ + --hash=sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6 # via -r requirements.in diff --git a/code/src/common/constants.ts b/code/src/common/constants.ts index 395c36d4..cf719039 100644 --- a/code/src/common/constants.ts +++ b/code/src/common/constants.ts @@ -1,5 +1,5 @@ export namespace Server { - export const REQUIRED_PYTHON = "3.8.0" + export const REQUIRED_PYTHON = "3.9.0" export const DEFAULT_SELECTOR = [ { scheme: 'file', language: 'restructuredtext' }, diff --git a/code/src/node/client.ts b/code/src/node/client.ts index 6ef3a40a..fb6f348a 100644 --- a/code/src/node/client.ts +++ b/code/src/node/client.ts @@ -338,9 +338,6 @@ export class EsbonioClient { * transport. */ private getLanguageClientOptions(config: vscode.WorkspaceConfiguration): LanguageClientOptions { - - - let documentSelector = config.get("server.documentSelector") if (!documentSelector || documentSelector.length === 0) { documentSelector = Server.DEFAULT_SELECTOR @@ -361,8 +358,7 @@ export class EsbonioClient { return result } - result.forEach(async (config, i) => { - await this.injectPython(params, i, config) + result.forEach((config) => { this.stripNulls(config) }) return result @@ -394,31 +390,6 @@ export class EsbonioClient { } } - /** - * Inject the user's configured Python interpreter into the configuration. - */ - private async injectPython(params: ConfigurationParams, index: number, config: any) { - if (params.items[index].section !== "esbonio") { - return - } - - if (config?.sphinx?.pythonCommand?.length > 0) { - return - } - - // User has not explictly configured a Python command, try and inject the - // Python interpreter they have configured for this resource. - let scopeUri: vscode.Uri | undefined - let scope = params.items[index].scopeUri - if (scope) { - scopeUri = vscode.Uri.parse(scope) - } - let python = await this.python.getCmd(scopeUri) - if (python) { - config.sphinx.pythonCommand = python - } - } - private callHandlers(method: string, params: any) { this.handlers.get(method)?.forEach(handler => { try { diff --git a/code/src/node/extension.ts b/code/src/node/extension.ts index 31d70ed3..c12262f0 100644 --- a/code/src/node/extension.ts +++ b/code/src/node/extension.ts @@ -22,7 +22,7 @@ export async function activate(context: vscode.ExtensionContext) { let previewManager = new PreviewManager(logger, context, esbonio) context.subscriptions.push(vscode.window.registerTreeDataProvider( - 'sphinxProcesses', new SphinxProcessProvider(esbonio) + 'sphinxProcesses', new SphinxProcessProvider(logger, esbonio) )); let config = vscode.workspace.getConfiguration("esbonio.server") diff --git a/code/src/node/processTreeView.ts b/code/src/node/processTreeView.ts index 3c6d0d12..4820cac6 100644 --- a/code/src/node/processTreeView.ts +++ b/code/src/node/processTreeView.ts @@ -1,5 +1,7 @@ import * as vscode from 'vscode' import { Notifications, Events } from "../common/constants"; +import { OutputChannelLogger } from '../common/log' + import { AppCreatedNotification, ClientCreatedNotification, ClientDestroyedNotification, ClientErroredNotification, EsbonioClient, SphinxClientConfig, SphinxInfo } from './client'; /** @@ -13,7 +15,7 @@ export class SphinxProcessProvider implements vscode.TreeDataProvider = new vscode.EventEmitter(); readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; - constructor(client: EsbonioClient) { + constructor(private logger: OutputChannelLogger, client: EsbonioClient) { client.addHandler( Notifications.SPHINX_CLIENT_CREATED, (params: ClientCreatedNotification) => this.clientCreated(params) @@ -52,14 +54,14 @@ export class SphinxProcessProvider implements vscode.TreeDataProvider cmd.push(`- ${c}`)) + + return { + label: element.command.join(' '), + iconPath: new vscode.ThemeIcon('console'), + tooltip: new vscode.MarkdownString(`**Sphinx Command**\n ${cmd.join('\n ')}`), + contextValue: element.kind, collapsibleState: vscode.TreeItemCollapsibleState.None } - case 'property': - return { label: 'Prop', collapsibleState: vscode.TreeItemCollapsibleState.None } + case 'python': + let pyCmd: string[] = [] + element.command.forEach(c => pyCmd.push(`- ${c}`)) + + return { + label: element.command.join(' '), + iconPath: vscode.ThemeIcon.File, + tooltip: new vscode.MarkdownString(`**Python Command**\n ${pyCmd.join('\n ')}`), + resourceUri: vscode.Uri.parse('file:///test.py'), // Needed to pull in the icon for Python + contextValue: element.kind, + collapsibleState: vscode.TreeItemCollapsibleState.None + } + + case 'directory': + return { + resourceUri: element.uri, + iconPath: vscode.ThemeIcon.Folder, + contextValue: element.kind, + collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, + } + + case 'file': + return { + resourceUri: element.uri, + iconPath: vscode.ThemeIcon.File, + contextValue: element.kind, + command: { command: 'vscode.open', title: `Open ${element.name}`, arguments: [element.uri], }, + collapsibleState: vscode.TreeItemCollapsibleState.None + } } } @@ -90,34 +140,78 @@ export class SphinxProcessProvider implements vscode.TreeDataProvider { + async getChildren(element?: ProcessTreeNode): Promise { const result: ProcessTreeNode[] = [] if (!element) { for (let process of this.sphinxClients.values()) { let cwd = process.config.cwd - let node: ProcssContainerNode = { kind: 'container', name: cwd, path: cwd } + let node: ProcessContainerNode = { kind: 'container', name: cwd, path: cwd } result.push(node) } - return Promise.resolve(result) + return result } switch (element.kind) { case 'container': for (let [id, process] of this.sphinxClients.entries()) { if (element.name === process.config.cwd) { - let node: SphinxProcessNode = { kind: 'process', id: id } + let node: SphinxProcessNode = { kind: 'sphinxProcess', id: id } result.push(node) } } break - case 'process': - case 'property': + case 'sphinxProcess': + let client = this.sphinxClients.get(element.id) + if (!client) { + break + } + + let pythonNode: PythonCommandNode = { kind: 'python', command: client.config.pythonCommand } + result.push(pythonNode) + + let commandNode: SphinxCommandNode = { kind: 'sphinxCommand', command: client.config.buildCommand } + result.push(commandNode) + + let app = client.app + if (!app) { + break + } + + let builderNode: SphinxBuilderNode = { + kind: 'sphinxBuilder', + name: app.builder_name, + uri: vscode.Uri.file(app.build_dir) + } + result.push(builderNode) + + break + + // Check the build dir for any files/directories + // TODO: Is there a way to insert VSCode's native file tree here? + // It would save having to reimplement it ourselves. + case 'sphinxBuilder': + case 'directory': + let items = await vscode.workspace.fs.readDirectory(element.uri) + for (let [name, type] of items) { + let node: FileNode | DirNode = { + kind: type === vscode.FileType.Directory ? 'directory' : 'file', + name: name, + uri: vscode.Uri.joinPath(element.uri, name) + } + result.push(node) + } + break + + // The following node types have no children + case 'sphinxCommand': + case 'python': + case 'file': } - return Promise.resolve(result) + return result } /** @@ -126,6 +220,7 @@ export class SphinxProcessProvider implements vscode.TreeDataProvider> $(GITHUB_OUTPUT) - -html-local: - sphinx-build -M html . _build $(SPHINXOPTS) - -html: $(BUILD) +html: $(HATCH) + $(HATCH) -e docs run build diff --git a/docs/conf.py b/docs/conf.py index c89a8876..988cfbec 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,6 +11,7 @@ import os import sys +sys.path.insert(0, os.path.abspath("../lib/esbonio-extensions")) sys.path.insert(0, os.path.abspath("../lib/esbonio")) sys.path.insert(0, os.path.abspath("./ext")) diff --git a/docs/index.rst b/docs/index.rst index f12f9aa9..158f28a4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -62,6 +62,7 @@ The primary goal of Esbonio is to reduce the friction that comes from trying to :hidden: Getting Started + integrating/previews Sphinx Extensions ----------------- diff --git a/docs/integrating/getting-started.rst b/docs/integrating/getting-started.rst index 959c436b..43c4fb3a 100644 --- a/docs/integrating/getting-started.rst +++ b/docs/integrating/getting-started.rst @@ -34,17 +34,3 @@ These guides will help you get ``esbonio`` setup with your editor of choice :text-align: center Using ``esbonio`` with Neovim's built in language client. - -Additional Features -=================== - -The language server provides additional notifications and commands that are not part of the LSP specification. -This means that they require additional client side integration code to be enabled. - -Theses features are not a requirement to use ``esbonio``, but they do offer some quality of life improvements. - -.. toctree:: - :maxdepth: 1 - - Sphinx Processes - Previews diff --git a/docs/integrating/previews.rst b/docs/integrating/previews.rst new file mode 100644 index 00000000..674ae43e --- /dev/null +++ b/docs/integrating/previews.rst @@ -0,0 +1,127 @@ +Live Previews +============= + +.. note:: + + Currently live previews are only implemented for builders that produce HTML output. + +``esbonio`` is able to offer a preview of your documentation that is automatically updated as you work. + +While the preview functionality tries to leverage existing LSP methods where possible, there are some features that require extra methods to enable. +This page provides all the details you will need to enable live previews in your language client of choice. + +Basic Previews +-------------- + +To trigger a preview for a file, your language client will need to invoke the following command using the :lsp:`workspace/executeCommand` request from the Language Server Protocol. + +.. esbonio:command:: esboino.server.previewFile + + Generate and open the preview for the given file. + + This command requires the following arguments + + .. code-block:: json + + [ + {"uri": "file:///path/to/file/to/preview.rst"} + ] + + The server will then look up the output file that corresponds with the given uri, if no such file exists, the server will do nothing and return a ``null`` response. + + Assuming the output file exists and your language client supports it the server will send a :lsp:`window/showDocument` request to open the resulting HTML file in your web browser. + + However, to handle the case where your client does not support :lsp:`window/showDocument` the server will also return the following object allowing you to open the corresponding uri yourself. + + .. code-block:: json + + {"uri": "http://localhost:1234/preview.html?ws=56789"} + +Implementing this single command will give you a fairly good preview experience. + +- The preview will automatically reload each time a Sphinx build completes. +- Assuming your client supports the ``selection`` field of a ``window/showDocument`` request, scrolling the preview window will automatically scroll your editor window to match. +- To preview another file, send another ``esbonio.server.previewFile`` command. Depending on your language client, you might be able to `automate this `__ + +Synchronised Scrolling +---------------------- + +However, to implement full synchronised scrolling you will need your client to send the following custom notification each time you scroll your editor. + +.. esbonio:command:: view/scroll + + Scroll the preview to reveal the given line number. + This requires the following parameters + + .. code-block:: json + + {"uri": "file:///path/to/file/to/preview.rst", "line": 10} + + Where ``line`` is the line number visible at the very top of your editor window. + The ``uri`` of the current file is also required since output files can contain the contents of one or more input files (e.g. using the ``.. include::`` directive). + +Example Implementation +----------------------- + +.. tip:: + + For a more complete example, see the preview implementation in the `Esbonio VSCode Extension `__ + + +The following is just enough configuration to enable live previews with synchronised scrolling in Neovim. +There are likely some quality of life improvements you would want to make to this, but it's enough to get something up and running. + +This example + +- Adds a ``:EsbonioPreviewFile`` command to generate the preview for the current file +- Relies on Neovim's built in :lsp:`window/showDocument` handler both to open the preview in your default web browser and synchronise the preview's scroll state with the editor. +- Sets up an autocmd for the ``WinScrolled`` event to synchronise the editor's scroll state with the preview. + +.. code-block:: lua + + require('lspconfig').esbonio.setup { + commands = { + EsbonioPreviewFile = { + preview_file, + description = 'Preview Current File', + }, + }, + } + +Where the ``preview_file`` function sends the :command:`esbonio.server.previewFile` command and sets up the ``WinScrolled`` autocommand. + +.. code-block:: lua + + function preview_file() + local params = { + command = 'esbonio.server.previewFile', + arguments = { + { uri = vim.uri_from_bufnr(0) }, + }, + } + + local clients = require('lspconfig.util').get_lsp_clients { + bufnr = vim.api.nvim_get_current_buf(), + name = 'esbonio', + } + for _, client in ipairs(clients) do + client.request('workspace/executeCommand', params, nil, 0) + end + + local augroup = vim.api.nvim_create_augroup("EsbonioSyncScroll", { clear = true }) + vim.api.nvim_create_autocmd({"WinScrolled"}, { + callback = scroll_view, group = augroup, buffer = 0 + }) + end + +And the ``scroll_view`` command sends the required ``view/scroll`` notification with the server. + +.. code-block:: lua + + function scroll_view(event) + local esbonio = vim.lsp.get_active_clients({ bufnr = 0, name = 'esbonio' })[1] + local view = vim.fn.winsaveview() + + local params = { uri = vim.uri_from_bufnr(0), line = view.topline } + esbonio.notify('view/scroll', params) + end diff --git a/docs/integrating/reference/previews.rst b/docs/integrating/reference/previews.rst deleted file mode 100644 index 9c713f2e..00000000 --- a/docs/integrating/reference/previews.rst +++ /dev/null @@ -1,48 +0,0 @@ -Previews -======== - -This page gives an overview of how the preview feature in ``esbonio`` is implemented. - - -.. figure:: /images/preview-architecture.svg - :align: center - - Architecture of the preview feature - -The diagram above shows the main components involved in implementing the preview feature. - -- On the left we have the user's text editor of choice e.g. VSCode, Vim, Emacs etc -- On the right we have the webview used to show the preview of the user's documentation. - In the case of VSCode this is probably a built-in webview, but for other editors it's most likely to be a web browser. -- In the center there is the ``esbonio`` language server itself with two additional components. - - - A HTTP server, used to serve files out of the build directory - - A WebSocket server, used for communication between the language server and the webview. - -Typical Workflow ----------------- - -At a high level the typical interaction between the components may look something like the following. - -#. The user previews a given file in their editor. -#. If it hasn't done so already, the language server creates a WebSocket server to listen for connections from a webview. -#. If it hasn't done so already, the language server creates a HTTP server and configures it to serve content out of the relevant build directory. -#. The server informs the editor the url at which the preview server can be found and the webview is opened. -#. Once the page loads in the webview, the WebSocket client embedded in the page connects to the WebSocket server running in the Language Server. - Using the Language Server as an intermediary, it's now possible for the editor and webview to communicate with each other. -#. When the user scrolls the editor, the editor informs the webview where it should scroll to (and vice versa). - -Commands --------- - -The server offers the following commands for controlling the underlying Sphinx processes. -They are invoked using an :lsp:`workspace/executeCommand` request - -.. esbonio:command:: esbonio.server.previewFile - - Preview the output for the given file. - This command accepts an object of the following form - - .. code-block:: json - - {"uri": "a0a5a856-d4ec-4c45-8461-78748ddbd06f"} diff --git a/docs/lsp/howto.rst b/docs/lsp/howto.rst index 8038bfc1..6a72dab9 100644 --- a/docs/lsp/howto.rst +++ b/docs/lsp/howto.rst @@ -9,3 +9,4 @@ This section contains a number of guides to help you get the most out of Esbonio :hidden: Migrate to v1 + Use Esbonio With... diff --git a/docs/lsp/howto/use-esbonio-with.rst b/docs/lsp/howto/use-esbonio-with.rst new file mode 100644 index 00000000..34820550 --- /dev/null +++ b/docs/lsp/howto/use-esbonio-with.rst @@ -0,0 +1,105 @@ +How To Use Esbonio With... +========================== + +There are (almost!) as many ways to manage a Python environment as there are packages on PyPi! +This guide outlines how to configure ``esbonio`` to use the right environment for your project. + +... Hatch +--------- + +If for example, you used `hatch `__ to define an environment in which you build your documentation + +.. code-block:: toml + + [tool.hatch.envs.docs] + dependencies = [ + "sphinx", + "sphinx-design", + "furo", + "myst-parser", + ] + scripts.build = "sphinx-build -M dirhtml . ./_build" + +Then you should set :esbonio:conf:`esbonio.sphinx.pythonCommand` to + +.. code-block:: toml + + [tool.esbonio.sphinx] + pythonCommand = ["hatch", "-e", "docs", "run", "python"] + +... Poetry +---------- + +Given a set of dependencies managed through `Poetry `__ + +.. code-block:: toml + + [tool.poetry.dependencies] + python = ">=3.9" + cattrs = ">=23.1.2" + lsprotocol = "2024.0.0a2" + websockets = { version = ">=11.0.3", optional = true } + + [tool.poetry.group.docs.dependencies] + myst-parser = ">=2.0" + sphinx = ">=7.1.2" + sphinx-design = ">=0.5.0" + sphinx-rtd-theme = ">=1.3.0" + +You will first need to make sure that ``poetry`` has created the environment with the required dependencies + +.. code-block:: console + + $ poetry install --with docs + +Then you should set :esbonio:conf:`esbonio.sphinx.pythonCommand` to + +.. code-block:: toml + + [tool.esbonio.sphinx] + pythonCommand = ["poetry", "run", "python"] + +... venv / virtualenv +--------------------- + +.. tip:: + + Virtual environments are not portable between machines or even Python versions, which means the best place to set the :esbonio:conf:`esbonio.sphinx.pythonCommand` option is in your language client, rather than your project's ``pyproject.toml``. + +Assuming you already have an envrionment that you use to build your documentation + +.. code-block:: console + + (venv) $ python -m pip list + Package Version Editable project location + ----------------------------- ---------- ------------------------------------------------- + ... + Sphinx 7.1.2 + sphinx_design 0.5.0 + sphinx-rtd-theme 2.0.0 + sphinxcontrib-applehelp 1.0.4 + sphinxcontrib-devhelp 1.0.2 + sphinxcontrib-htmlhelp 2.0.1 + sphinxcontrib-jquery 4.1 + sphinxcontrib-jsmath 1.0.1 + sphinxcontrib-qthelp 1.0.3 + sphinxcontrib-serializinghtml 1.1.5 + urllib3 2.1.0 + +Then you set :esbonio:conf:`esbonio.sphinx.pythonCommand` to the full path to the ``python`` executable contained in the environment (which will be slightly different depending on your operating system) + +.. tab-set:: + + .. tab-item:: Linux / macOS + + .. code-block:: toml + + [tool.esbonio.sphinx] + pythonCommand = ["/home/user/Projects/myproject/venv/bin/python"] + + .. tab-item:: Windows + + .. code-block:: toml + + [tool.esbonio.sphinx] + pythonCommand = ["C:\\Users\\user\\Projects\\myproject\\Scripts\\python.exe"] diff --git a/docs/lsp/reference/configuration.rst b/docs/lsp/reference/configuration.rst index e58cf7b8..572d4219 100644 --- a/docs/lsp/reference/configuration.rst +++ b/docs/lsp/reference/configuration.rst @@ -252,7 +252,7 @@ The following options control the creation of the Sphinx application object mana A list of environment variables to pass through to the Sphinx process. -.. esbonio:config:: sphinx.configOverrides +.. esbonio:config:: esbonio.sphinx.configOverrides :scope: project :type: object diff --git a/docs/pyproject.toml b/docs/pyproject.toml index 08f379b7..a636caea 100644 --- a/docs/pyproject.toml +++ b/docs/pyproject.toml @@ -1,2 +1,19 @@ [tool.esbonio.sphinx] -buildCommand = ["sphinx-build", "-M", "dirhtml", ".", "./_build"] +# buildCommand = ["sphinx-build", "-M", "dirhtml", ".", "./_build"] +pythonCommand = ["hatch", "-e", "docs", "run", "python"] + +[tool.hatch.envs.docs] +installer = 'uv' +skip-install = true +dependencies = [ + "aiosqlite", + "sphinx", + "sphinx-design", + "furo", + "myst-parser", + "platformdirs", + "pytest_lsp", +] + +[tool.hatch.envs.docs.scripts] +build = "sphinx-build -M dirhtml . ./_build" diff --git a/docs/requirements.txt b/docs/requirements.txt index 4b7c6be7..6d29ac8b 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -4,6 +4,7 @@ sphinx sphinx-design furo myst-parser -pytest_lsp --e lib/esbonio --e lib/esbonio-extensions[tutorial] +pytest_lsp>=1.0b0 +pygls>=2.0a0 +platformdirs +aiosqlite diff --git a/lib/esbonio-extensions/changes/656.misc.rst b/lib/esbonio-extensions/changes/656.misc.md similarity index 100% rename from lib/esbonio-extensions/changes/656.misc.rst rename to lib/esbonio-extensions/changes/656.misc.md diff --git a/lib/esbonio-extensions/changes/879.misc.md b/lib/esbonio-extensions/changes/879.misc.md new file mode 100644 index 00000000..51a41f78 --- /dev/null +++ b/lib/esbonio-extensions/changes/879.misc.md @@ -0,0 +1,3 @@ +Drop Python 3.8 support + +Remove dependency on `nbformat` diff --git a/lib/esbonio-extensions/esbonio/tutorial.py b/lib/esbonio-extensions/esbonio/tutorial.py index f28d3e6d..a7fc8b22 100644 --- a/lib/esbonio-extensions/esbonio/tutorial.py +++ b/lib/esbonio-extensions/esbonio/tutorial.py @@ -1,31 +1,72 @@ +from __future__ import annotations + +import json import pathlib import re import textwrap -from typing import Iterable -from typing import List -from typing import Optional -from typing import Set -from typing import Tuple -from typing import Union - -import nbformat -import nbformat.v4 as nbf -from docutils import nodes -from docutils import writers +import typing + +from docutils import nodes, writers from docutils.io import StringOutput from docutils.parsers.rst.directives.admonitions import BaseAdmonition from sphinx.application import Sphinx from sphinx.builders import Builder -from sphinx.util import status_iterator +from sphinx.util.display import status_iterator from sphinx.util.docutils import new_document from sphinx.util.logging import getLogger -from sphinx.util.osutil import copyfile -from sphinx.util.osutil import relative_uri +from sphinx.util.osutil import copyfile, relative_uri + +if typing.TYPE_CHECKING: + from typing import Any, Iterable, Literal, Set, Tuple, TypedDict, Union + + CellType = Literal["code", "markdown"] + + class MarkdownCell(TypedDict): + """Represents a markdown cell in a notebook""" + + cell_type: Literal["markdown"] + """The type of cell""" + + metadata: dict[str, Any] + """Metadata for the cell""" + + source: str | list[str] + """The cell's source""" + + class CodeCell(TypedDict): + """Represents a code cell in a notebook""" + + cell_type: Literal["code"] + """The type of cell""" + + execution_count: int | None + + metadata: dict[str, Any] + """Metadata for the cell""" + + source: str | list[str] + """The cell's source""" + + outputs: list[Any] + """A list of cell outputs""" + + NotebookCell = CodeCell | MarkdownCell + + class Notebook(TypedDict): + """Represents the top-level notebook structure.""" + + metadata: dict[str, Any] + + nbformat: int + + nbformat_minor: int + + cells: list[NotebookCell] + __version__ = "0.2.2" logger = getLogger(__name__) -CELL_TYPES = {"markdown": nbf.new_markdown_cell, "code": nbf.new_code_cell} REPL_PATTERN = re.compile(r"^(>>>|\.\.\.) ?", re.MULTILINE) CODE_LANGUAGES = {"default", "python", "pycon3", "pycon"} @@ -62,36 +103,40 @@ class NotebookTranslator(nodes.NodeVisitor): def __init__(self, document): super().__init__(document) - self.cells: List[nbformat.NotebookNode] = [] + self.cells: list[NotebookCell] = [] """A list of cells that have been constructed so far.""" self.section_level = 0 """Used to keep track of the nested sections.""" - self._list_styles: List[str] = [] + self._list_styles: list[str] = [] """Used to keep track of the current list style.""" - self._prefix: List[Tuple[nodes.Node, str]] = [] + self._prefix: list[Tuple[nodes.Node, str]] = [] """Used to keep track of the prefix to insert before text. e.g. ``> `` for markdown quote blocks.""" - def asnotebook(self) -> nbformat.NotebookNode: - # Trim any empty cells. - cells = [c for c in self.cells if len(c.source) > 0] + def asnotebook(self) -> Notebook: + cells: list[NotebookCell] = [] + for cell in self.cells: + # Skip empty cells + if len(cell["source"]) == 0: + continue + + if isinstance(source := cell["source"], str): + cell["source"] = source.splitlines(keepends=True) - return nbf.new_notebook(cells=cells) + cells.append(cell) + + return {"metadata": {}, "nbformat": 4, "nbformat_minor": 4, "cells": cells} def astext(self) -> str: - return nbf.writes(self.asnotebook()) + return json.dumps(self.asnotebook(), indent=2) @property - def current_cell(self) -> Optional[nbformat.NotebookNode]: + def current_cell(self) -> NotebookCell | None: """Small helper for keeping track of the cell currently under construction.""" - - if len(self.cells) == 0: - return None - - return self.cells[-1] + return self.cells[-1] if len(self.cells) > 0 else None @property def list_style(self) -> str: @@ -103,7 +148,7 @@ def prefix(self) -> str: """Return the current prefix to insert at the start of the current line.""" return "".join(item[1] for item in self._prefix) - def new_cell(self, cell_type: str, *args, **kwargs) -> nbformat.NotebookNode: + def new_cell(self, cell_type: CellType, *args, **kwargs) -> NotebookCell: """Add a new cell to the notebook. To help simplify the implementation of visitors, asking for a new ``markdown`` cell @@ -111,17 +156,31 @@ def new_cell(self, cell_type: str, *args, **kwargs) -> nbformat.NotebookNode: Parameters ---------- - cell_type: + cell_type The type of cell to create, can be either ``markdown`` or ``code`` """ if ( self.current_cell is not None - and self.current_cell.cell_type == cell_type == "markdown" + and self.current_cell["cell_type"] == cell_type == "markdown" ): return - new_cell = CELL_TYPES[cell_type](*args, **kwargs) + if cell_type == "markdown": + new_cell: MarkdownCell = { + "cell_type": "markdown", + "metadata": {}, + "source": "", + } + else: + new_cell: CodeCell = { + "cell_type": "code", + "metadata": {}, + "execution_count": None, + "source": "", + "outputs": [], + } + self.cells.append(new_cell) return new_cell @@ -140,7 +199,7 @@ def append_text(self, text: str): # If the text is just a newline on its own, include the prefix if text == "\n": - self.current_cell.source += f"\n{self.prefix}" + self.current_cell["source"] += f"\n{self.prefix}" return # Remove the final newline if it exists, we'll add it back later. @@ -153,7 +212,7 @@ def append_text(self, text: str): if final_newline: text += "\n" - self.current_cell.source += text + self.current_cell["source"] += text def push_prefix(self, node: nodes.Node, prefix: str): """Push a (node, prefix) pair onto the prefix stack.""" @@ -381,7 +440,7 @@ def depart_term(self, node): self.append_text("`: ") def visit_Text(self, node): - if self.current_cell.cell_type == "markdown": + if self.current_cell["cell_type"] == "markdown": self.append_text(node.astext()) return @@ -515,11 +574,11 @@ def process_solutions(self, doctree: nodes.document, src: str) -> None: notebook = translator.asnotebook() blocks = [] - for cell in notebook.cells: - source = cell.source + for cell in notebook["cells"]: + source = "".join(cell["source"]) # Comment out the lines containing markdown. - if cell.cell_type == "markdown": + if cell["cell_type"] == "markdown": source = textwrap.indent(source, "# ") blocks.append(source) @@ -638,16 +697,8 @@ def setup(app: Sphinx): path = "tutorial_demo" package = "esbonio" - # `files` only available in Python 3.9+ - if hasattr(importlib.resources, "files"): - demo = importlib.resources.files(package).joinpath(path) - source = pathlib.Path(demo) - - else: - # `path` deprecated in Python 3.11, so let's only rely on it when we - # have to. - with importlib.resources.path(package, path) as demo: - source = pathlib.Path(demo) + demo = importlib.resources.files(package).joinpath(path) + source = pathlib.Path(demo) destination = pathlib.Path( platformdirs.user_data_dir(appname="esbonio-tutorial", appauthor="swyddfa") diff --git a/lib/esbonio-extensions/pyproject.toml b/lib/esbonio-extensions/pyproject.toml index b4c164a9..3122e350 100644 --- a/lib/esbonio-extensions/pyproject.toml +++ b/lib/esbonio-extensions/pyproject.toml @@ -7,7 +7,7 @@ name = "esbonio-extensions" dynamic = ["version"] description = "A collection of extensions for Sphinx and the Esbonio language server" readme = "README.md" -requires-python = ">=3.8" +requires-python = ">=3.9" license = { text = "MIT" } authors = [{ name = "Alex Carney", email = "alcarneyme@gmail.com" }] classifiers = [ @@ -16,7 +16,6 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -29,7 +28,6 @@ dependencies = ["esbonio", "platformdirs", "sphinx"] [project.optional-dependencies] dev = ["black", "flake8", "pytest", "pytest-cov", "mock"] spelling = ["pyspellchecker"] -tutorial = ["nbformat"] [project.urls] "Bug Tracker" = "https://github.com/swyddfa/esbonio/issues" diff --git a/lib/esbonio-extensions/tests/data/tutorial/bare_link.ipynb b/lib/esbonio-extensions/tests/data/tutorial/bare_link.ipynb index 5e0dde6b..791c3608 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/bare_link.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/bare_link.ipynb @@ -1,16 +1,15 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "", - "metadata": {}, - "source": [ - "\n", - "Link here: [https://docs.python.org/3.7/](https://docs.python.org/3.7/)\n" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Link here: [https://docs.python.org/3.7/](https://docs.python.org/3.7/)\n" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/data/tutorial/bold.ipynb b/lib/esbonio-extensions/tests/data/tutorial/bold.ipynb index a303b30b..ea37f668 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/bold.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/bold.ipynb @@ -1,16 +1,15 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "", - "metadata": {}, - "source": [ - "\n", - "Here is some **bold** text\n" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Here is some **bold** text\n" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/data/tutorial/bullet_list.ipynb b/lib/esbonio-extensions/tests/data/tutorial/bullet_list.ipynb index a14d93e0..aa9d985e 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/bullet_list.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/bullet_list.ipynb @@ -1,23 +1,22 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "", - "metadata": {}, - "source": [ - "\n", - "- Item one\n", - " \n", - "- Item two, for reasons it has been decided to make this item much longer than\n", - " the other items to ensure that we can cover the case where the items contiain\n", - " longer content\n", - " \n", - "- Item three\n", - " " - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "- Item one\n", + " \n", + "- Item two, for reasons it has been decided to make this item much longer than\n", + " the other items to ensure that we can cover the case where the items contiain\n", + " longer content\n", + " \n", + "- Item three\n", + " " + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/data/tutorial/comment.ipynb b/lib/esbonio-extensions/tests/data/tutorial/comment.ipynb index 727339f2..d08c3c2c 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/comment.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/comment.ipynb @@ -1,16 +1,15 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "", - "metadata": {}, - "source": [ - "\n", - "And here is some normal text\n" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "And here is some normal text\n" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/data/tutorial/doctest_no_output.ipynb b/lib/esbonio-extensions/tests/data/tutorial/doctest_no_output.ipynb index 082d77d6..36b85398 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/doctest_no_output.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/doctest_no_output.ipynb @@ -1,18 +1,17 @@ { - "cells": [ - { - "cell_type": "code", - "id": "", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "l = [1,2,3]\n", - "l.append(4)" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "l = [1,2,3]\n", + "l.append(4)" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/data/tutorial/heading.ipynb b/lib/esbonio-extensions/tests/data/tutorial/heading.ipynb index 27664b2e..fb31a2b3 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/heading.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/heading.ipynb @@ -1,24 +1,23 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "", - "metadata": {}, - "source": [ - "\n", - "# Heading 1\n", - "\n", - "## Heading 2\n", - "\n", - "### Heading 3\n", - "\n", - "#### Heading 4\n", - "\n", - "##### Heading 5\n" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Heading 1\n", + "\n", + "## Heading 2\n", + "\n", + "### Heading 3\n", + "\n", + "#### Heading 4\n", + "\n", + "##### Heading 5\n" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/data/tutorial/image.ipynb b/lib/esbonio-extensions/tests/data/tutorial/image.ipynb index 3e73ca7c..ff6d85d6 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/image.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/image.ipynb @@ -1,15 +1,14 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "", - "metadata": {}, - "source": [ - "![](/path/to/image.png)" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](/path/to/image.png)" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/data/tutorial/inline_code.ipynb b/lib/esbonio-extensions/tests/data/tutorial/inline_code.ipynb index b945f2ab..b16d9e02 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/inline_code.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/inline_code.ipynb @@ -1,16 +1,15 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "", - "metadata": {}, - "source": [ - "\n", - "Here is some `inline code`\n" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Here is some `inline code`\n" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/data/tutorial/inline_link.ipynb b/lib/esbonio-extensions/tests/data/tutorial/inline_link.ipynb index 74da20e0..87c98b98 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/inline_link.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/inline_link.ipynb @@ -1,16 +1,15 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "", - "metadata": {}, - "source": [ - "\n", - "Check out the [documentation](https://docs.python.org/3.7/)\n" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Check out the [documentation](https://docs.python.org/3.7/)\n" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/data/tutorial/italic.ipynb b/lib/esbonio-extensions/tests/data/tutorial/italic.ipynb index c2222754..f55fa98d 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/italic.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/italic.ipynb @@ -1,16 +1,15 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "", - "metadata": {}, - "source": [ - "\n", - "Here is some *italic* text\n" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Here is some *italic* text\n" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/data/tutorial/note.ipynb b/lib/esbonio-extensions/tests/data/tutorial/note.ipynb index 69934d7c..30cfa7cc 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/note.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/note.ipynb @@ -1,19 +1,18 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "", - "metadata": {}, - "source": [ - "\n", - "> **Note**\n", - ">\n", - "> This is an *important* note\n", - "> \n" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "> **Note**\n", + ">\n", + "> This is an *important* note\n", + "> \n" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/data/tutorial/paragraphs.ipynb b/lib/esbonio-extensions/tests/data/tutorial/paragraphs.ipynb index 9e3933b0..85cd28a7 100644 --- a/lib/esbonio-extensions/tests/data/tutorial/paragraphs.ipynb +++ b/lib/esbonio-extensions/tests/data/tutorial/paragraphs.ipynb @@ -1,22 +1,21 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "", - "metadata": {}, - "source": [ - "\n", - "Here is an extended example that involves more text than what can fit inside a\n", - "single paragraph of text. This is to ensure that when the translator encounters\n", - "mutliple paragraphs - unlike the code blocks it does not split the paragraph\n", - "into multiple cells.\n", - "\n", - "Instead this should be combined into a single cell with the appropriate spacing\n", - "between the lines so that they are formatted accordingly.\n" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Here is an extended example that involves more text than what can fit inside a\n", + "single paragraph of text. This is to ensure that when the translator encounters\n", + "mutliple paragraphs - unlike the code blocks it does not split the paragraph\n", + "into multiple cells.\n", + "\n", + "Instead this should be combined into a single cell with the appropriate spacing\n", + "between the lines so that they are formatted accordingly.\n" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/lib/esbonio-extensions/tests/test_tutorial.py b/lib/esbonio-extensions/tests/test_tutorial.py index 9a6e7680..b7c2dc66 100644 --- a/lib/esbonio-extensions/tests/test_tutorial.py +++ b/lib/esbonio-extensions/tests/test_tutorial.py @@ -1,9 +1,8 @@ +import json import pathlib -import nbformat.v4 as nbformat -import pytest - import esbonio.tutorial as tutorial +import pytest @pytest.mark.parametrize( @@ -28,26 +27,17 @@ def test_notebook_translator(testdata, parse_rst, name): the correct sequence of notebook cells.""" rst = testdata(pathlib.Path("tutorial", name + ".rst")).decode("utf8") - json = testdata(pathlib.Path("tutorial", name + ".ipynb")).decode("utf8") - - nb = nbformat.reads(json) + ipynb = testdata(pathlib.Path("tutorial", name + ".ipynb")).decode("utf8") - # Don't worry about different minor version numbers - nb.nbformat_minor = None + expected = json.loads(ipynb) doctree = parse_rst(rst) - translator = tutorial.NotebookTranslator(doctree) doctree.walkabout(translator) - notebook = translator.asnotebook() - notebook.nbformat_minor = None - - # Don't worry about cell ids - for cell in notebook.cells: - cell.id = "" - actual = nbformat.writes(notebook) - expected = nbformat.writes(nb) + # # Don't worry about cell ids + # for cell in notebook.cells: + # cell.id = "" - assert expected == actual + assert expected == notebook diff --git a/lib/esbonio-extensions/tox.ini b/lib/esbonio-extensions/tox.ini index b8d91c6b..7ad30657 100644 --- a/lib/esbonio-extensions/tox.ini +++ b/lib/esbonio-extensions/tox.ini @@ -1,16 +1,6 @@ [tox] isolated_build = True min_version = 4 -envlist = py{38,39,310,311,312} - -[testenv] -deps = - mock - pytest - pytest-cov -extras = tutorial -commands = - pytest --cov=esbonio [testenv:pkg] description = Prepare the resources to be shipped with the package @@ -18,6 +8,7 @@ deps = build ../esbonio sphinx-design + myst-parser usedevelop = true allowlist_externals = cp diff --git a/lib/esbonio/changes/785.enhancement.md b/lib/esbonio/changes/785.enhancement.md new file mode 100644 index 00000000..90298e7a --- /dev/null +++ b/lib/esbonio/changes/785.enhancement.md @@ -0,0 +1 @@ +Re-implemented the `esbonio.sphinx.configOverrides` option diff --git a/lib/esbonio/changes/858.misc.md b/lib/esbonio/changes/858.misc.md new file mode 100644 index 00000000..e3446f31 --- /dev/null +++ b/lib/esbonio/changes/858.misc.md @@ -0,0 +1 @@ +Drop support for Python 3.8 diff --git a/lib/esbonio/changes/859.misc.md b/lib/esbonio/changes/859.misc.md new file mode 100644 index 00000000..f32ba63f --- /dev/null +++ b/lib/esbonio/changes/859.misc.md @@ -0,0 +1 @@ +Add support for Python 3.13 diff --git a/lib/esbonio/changes/866.misc.md b/lib/esbonio/changes/866.misc.md new file mode 100644 index 00000000..3d6e35f6 --- /dev/null +++ b/lib/esbonio/changes/866.misc.md @@ -0,0 +1 @@ +Drop Sphinx `5.x` support, add Sphinx `8.x` support diff --git a/lib/esbonio/changes/874.fix.md b/lib/esbonio/changes/874.fix.md new file mode 100644 index 00000000..47332719 --- /dev/null +++ b/lib/esbonio/changes/874.fix.md @@ -0,0 +1 @@ +Esbonio's preview generation should no longer conflict with extensions like `ablog` which call methods like `replac_self()` on custom doctree nodes. diff --git a/lib/esbonio/changes/882.misc.md b/lib/esbonio/changes/882.misc.md new file mode 100644 index 00000000..d89c711e --- /dev/null +++ b/lib/esbonio/changes/882.misc.md @@ -0,0 +1 @@ +Migrate to pygls v2 diff --git a/lib/esbonio/esbonio/server/_configuration.py b/lib/esbonio/esbonio/server/_configuration.py index fad620a1..e988e938 100644 --- a/lib/esbonio/esbonio/server/_configuration.py +++ b/lib/esbonio/esbonio/server/_configuration.py @@ -17,14 +17,9 @@ T = TypeVar("T") if typing.TYPE_CHECKING: + from collections.abc import Awaitable from typing import Any - from typing import Awaitable from typing import Callable - from typing import Dict - from typing import List - from typing import Optional - from typing import Set - from typing import Type from typing import Union from .server import EsbonioLanguageServer @@ -47,7 +42,7 @@ class Subscription(Generic[T]): section: str """The configuration section.""" - spec: Type[T] + spec: type[T] """The subscription's class definition.""" callback: ConfigurationCallback @@ -67,7 +62,7 @@ class ConfigChangeEvent(Generic[T]): value: T """The latest configuration value.""" - previous: Optional[T] = None + previous: T | None = None """The previous configuration value, (if any).""" @@ -90,13 +85,13 @@ def scope(self) -> str: return max([self.file_scope, self.workspace_scope], key=len) @property - def scope_path(self) -> Optional[str]: + def scope_path(self) -> str | None: """The scope uri as a path.""" uri = Uri.parse(self.scope) return uri.path @property - def scope_fs_path(self) -> Optional[str]: + def scope_fs_path(self) -> str | None: """The scope uri as an fs path.""" uri = Uri.parse(self.scope) return uri.fs_path @@ -158,16 +153,16 @@ def __init__(self, server: EsbonioLanguageServer): self.logger = server.logger.getChild("Configuration") """The logger instance to use""" - self._initialization_options: Dict[str, Any] = {} + self._initialization_options: dict[str, Any] = {} """The received initializaion options (if any)""" - self._workspace_config: Dict[str, Dict[str, Any]] = {} + self._workspace_config: dict[str, dict[str, Any]] = {} """The cached workspace configuration.""" - self._file_config: Dict[str, Dict[str, Any]] = {} + self._file_config: dict[str, dict[str, Any]] = {} """The cached configuration coming from configuration files.""" - self._subscriptions: Dict[Subscription, Any] = {} + self._subscriptions: dict[Subscription, Any] = {} """Subscriptions and their last known value""" @property @@ -203,9 +198,9 @@ def supports_workspace_config(self): def subscribe( self, section: str, - spec: Type[T], + spec: type[T], callback: ConfigurationCallback, - scope: Optional[Uri] = None, + scope: Uri | None = None, ): """Subscribe to updates to the given configuration section. @@ -276,7 +271,7 @@ def _notify_subscriptions(self, *args): exc_info=True, ) - def get(self, section: str, spec: Type[T], scope: Optional[Uri] = None) -> T: + def get(self, section: str, spec: type[T], scope: Uri | None = None) -> T: """Get the requested configuration section. Parameters @@ -325,7 +320,7 @@ def scope_for(self, uri: Uri) -> str: def _get_config( self, section: str, - spec: Type[T], + spec: type[T], context: ConfigurationContext, ) -> T: """Get the requested configuration section.""" @@ -364,11 +359,11 @@ def _get_config( ) return spec() - def _uri_to_file_scope(self, uri: Optional[Uri]) -> str: + def _uri_to_file_scope(self, uri: Uri | None) -> str: folder_uris = list(self._file_config.keys()) return _uri_to_scope(folder_uris, uri) - def _uri_to_workspace_scope(self, uri: Optional[Uri]) -> str: + def _uri_to_workspace_scope(self, uri: Uri | None) -> str: folder_uris = [f.uri for f in self.workspace.folders.values()] if (root_uri := self.workspace.root_uri) is not None: @@ -376,7 +371,7 @@ def _uri_to_workspace_scope(self, uri: Optional[Uri]) -> str: return _uri_to_scope(folder_uris, uri) - def _discover_config_files(self) -> List[pathlib.Path]: + def _discover_config_files(self) -> list[pathlib.Path]: """Scan the workspace for available configuration files.""" folder_uris = {f.uri for f in self.workspace.folders.values()} @@ -395,7 +390,7 @@ def _discover_config_files(self) -> List[pathlib.Path]: return paths - def update_file_configuration(self, paths: Optional[List[pathlib.Path]] = None): + def update_file_configuration(self, paths: list[pathlib.Path] | None = None): """Update the internal cache of configuration coming from files. Parameters @@ -446,7 +441,7 @@ async def update_workspace_configuration(self): ) try: - results = await self.server.get_configuration_async(params) + results = await self.server.workspace_configuration_async(params) except Exception: self.logger.error("Unable to get workspace configuration", exc_info=True) return @@ -466,7 +461,7 @@ async def update_workspace_configuration(self): self._notify_subscriptions() -def _uri_to_scope(known_scopes: List[str], uri: Optional[Uri]) -> str: +def _uri_to_scope(known_scopes: list[str], uri: Uri | None) -> str: """Convert the given uri to a scope or the empty string if none could be found. Parameters @@ -496,13 +491,13 @@ def _uri_to_scope(known_scopes: List[str], uri: Optional[Uri]) -> str: return sorted(candidates, key=len, reverse=True)[0] -def _merge_configs(*configs: Dict[str, Any]): +def _merge_configs(*configs: dict[str, Any]): """Recursively merge all the given configuration sources together. The last config given takes precedence. """ final = {} - all_keys: Set[str] = set() + all_keys: set[str] = set() for c in configs: all_keys.update(c.keys()) diff --git a/lib/esbonio/esbonio/server/cli.py b/lib/esbonio/esbonio/server/cli.py index 343a501f..65764d1f 100644 --- a/lib/esbonio/esbonio/server/cli.py +++ b/lib/esbonio/esbonio/server/cli.py @@ -2,9 +2,9 @@ import logging import sys import warnings +from collections.abc import Sequence from logging.handlers import MemoryHandler from typing import Optional -from typing import Sequence from pygls.protocol import default_converter diff --git a/lib/esbonio/esbonio/server/events.py b/lib/esbonio/esbonio/server/events.py index 255ee629..a2a2cae3 100644 --- a/lib/esbonio/esbonio/server/events.py +++ b/lib/esbonio/esbonio/server/events.py @@ -9,9 +9,6 @@ if typing.TYPE_CHECKING: from typing import Any - from typing import Dict - from typing import Optional - from typing import Set class EventSource: @@ -20,14 +17,14 @@ class EventSource: # TODO: It might be nice to do some fancy typing here so that type checkers # etc know which events are possible etc. - def __init__(self, logger: Optional[logging.Logger] = None): + def __init__(self, logger: logging.Logger | None = None): self.logger = logger or logging.getLogger(__name__) """The logging instance to use.""" - self.handlers: Dict[str, set] = {} + self.handlers: dict[str, set] = {} """Collection of handlers for various events.""" - self._tasks: Set[asyncio.Task] = set() + self._tasks: set[asyncio.Task] = set() """Holds tasks that are currently executing an async event handler.""" def add_listener(self, event: str, handler): diff --git a/lib/esbonio/esbonio/server/feature.py b/lib/esbonio/esbonio/server/feature.py index 78761020..1efff85f 100644 --- a/lib/esbonio/esbonio/server/feature.py +++ b/lib/esbonio/esbonio/server/feature.py @@ -12,23 +12,21 @@ if typing.TYPE_CHECKING: import re + from collections.abc import Coroutine from typing import Any - from typing import Coroutine - from typing import List from typing import Optional - from typing import Set from typing import Union from .server import EsbonioLanguageServer CompletionResult = Union[ - Optional[List[types.CompletionItem]], - Coroutine[Any, Any, Optional[List[types.CompletionItem]]], + Optional[list[types.CompletionItem]], + Coroutine[Any, Any, Optional[list[types.CompletionItem]]], ] DocumentSymbolResult = Union[ - Optional[List[types.DocumentSymbol]], - Coroutine[Any, Any, Optional[List[types.DocumentSymbol]]], + Optional[list[types.DocumentSymbol]], + Coroutine[Any, Any, Optional[list[types.DocumentSymbol]]], ] MaybeAsyncNone = Union[ @@ -37,8 +35,8 @@ ] WorkspaceSymbolResult = Union[ - Optional[List[types.WorkspaceSymbol]], - Coroutine[Any, Any, Optional[List[types.WorkspaceSymbol]]], + Optional[list[types.WorkspaceSymbol]], + Coroutine[Any, Any, Optional[list[types.WorkspaceSymbol]]], ] @@ -82,7 +80,7 @@ def document_open(self, params: types.DidOpenTextDocumentParams) -> MaybeAsyncNo def document_save(self, params: types.DidSaveTextDocumentParams) -> MaybeAsyncNone: """Called when a text document is saved.""" - completion_trigger: Optional[CompletionTrigger] = None + completion_trigger: CompletionTrigger | None = None def completion(self, context: CompletionContext) -> CompletionResult: """Called when a completion request matches one of the specified triggers.""" @@ -102,16 +100,16 @@ def workspace_symbol( class CompletionTrigger: """Define when the feature's completion method should be called.""" - patterns: List[re.Pattern] + patterns: list[re.Pattern] """A list of regular expressions to try""" - languages: Set[str] = attrs.field(factory=set) + languages: set[str] = attrs.field(factory=set) """Languages in which the completion trigger should fire. If empty, the document's language will be ignored. """ - characters: Set[str] = attrs.field(factory=set) + characters: set[str] = attrs.field(factory=set) """Characters which, when typed, should trigger a completion request. If empty, this trigger will ignore any trigger characters. @@ -124,7 +122,7 @@ def __call__( document: TextDocument, language: str, client_capabilities: types.ClientCapabilities, - ) -> Optional[CompletionContext]: + ) -> CompletionContext | None: """Determine if this completion trigger should fire. Parameters @@ -254,7 +252,7 @@ def deprecated_support(self) -> bool: ) @property - def documentation_formats(self) -> List[types.MarkupKind]: + def documentation_formats(self) -> list[types.MarkupKind]: """The list of documentation formats supported by the client.""" return get_capability( self.capabilities, @@ -291,7 +289,7 @@ def snippet_support(self) -> bool: ) @property - def supported_tags(self) -> List[types.CompletionItemTag]: + def supported_tags(self) -> list[types.CompletionItemTag]: """The list of ``CompletionItemTags`` supported by the client.""" capabilities = get_capability( self.capabilities, diff --git a/lib/esbonio/esbonio/server/features/directives/__init__.py b/lib/esbonio/esbonio/server/features/directives/__init__.py index 5d03bc22..839bb4e1 100644 --- a/lib/esbonio/esbonio/server/features/directives/__init__.py +++ b/lib/esbonio/esbonio/server/features/directives/__init__.py @@ -8,12 +8,8 @@ from esbonio import server if typing.TYPE_CHECKING: + from collections.abc import Coroutine from typing import Any - from typing import Coroutine - from typing import Dict - from typing import List - from typing import Optional - from typing import Union @attrs.define @@ -23,7 +19,7 @@ class Directive: name: str """The name of the directive, as the user would type in an rst file.""" - implementation: Optional[str] + implementation: str | None """The dotted name of the directive's implementation.""" @@ -32,9 +28,7 @@ class DirectiveProvider: def suggest_directives( self, context: server.CompletionContext - ) -> Union[ - Optional[List[Directive]], Coroutine[Any, Any, Optional[List[Directive]]] - ]: + ) -> list[Directive] | None | Coroutine[Any, Any, list[Directive] | None]: """Given a completion context, suggest directives that may be used.""" return None @@ -49,7 +43,7 @@ class DirectiveFeature(server.LanguageFeature): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self._providers: Dict[int, DirectiveProvider] = {} + self._providers: dict[int, DirectiveProvider] = {} def add_provider(self, provider: DirectiveProvider): """Register a directive provider. @@ -63,7 +57,7 @@ def add_provider(self, provider: DirectiveProvider): async def suggest_directives( self, context: server.CompletionContext - ) -> List[Directive]: + ) -> list[Directive]: """Suggest directives that may be used, given a completion context. Parameters @@ -71,11 +65,11 @@ async def suggest_directives( context The completion context. """ - items: List[Directive] = [] + items: list[Directive] = [] for provider in self._providers.values(): try: - result: Optional[List[Directive]] = None + result: list[Directive] | None = None aresult = provider.suggest_directives(context) if inspect.isawaitable(aresult): diff --git a/lib/esbonio/esbonio/server/features/directives/completion.py b/lib/esbonio/esbonio/server/features/directives/completion.py index d93c12fe..0c8a2bb1 100644 --- a/lib/esbonio/esbonio/server/features/directives/completion.py +++ b/lib/esbonio/esbonio/server/features/directives/completion.py @@ -11,9 +11,7 @@ if typing.TYPE_CHECKING: from typing import Callable - from typing import Dict from typing import Optional - from typing import Tuple from . import Directive @@ -23,7 +21,7 @@ WORD = re.compile("[a-zA-Z]+") -_DIRECTIVE_RENDERERS: Dict[Tuple[str, str], DirectiveRenderer] = {} +_DIRECTIVE_RENDERERS: dict[tuple[str, str], DirectiveRenderer] = {} """CompletionItem rendering functions for directives.""" @@ -39,7 +37,7 @@ def fn(f: DirectiveRenderer) -> DirectiveRenderer: def get_directive_renderer( language: str, insert_behavior: str -) -> Optional[DirectiveRenderer]: +) -> DirectiveRenderer | None: """Return the directive renderer to use. Parameters @@ -62,7 +60,7 @@ def get_directive_renderer( def render_rst_directive_with_insert_text( context: server.CompletionContext, directive: Directive, -) -> Optional[types.CompletionItem]: +) -> types.CompletionItem | None: """Render a ``CompletionItem`` using ``insertText`` fields. This implements the ``insert`` behavior for directives. @@ -139,7 +137,7 @@ def render_rst_directive_with_insert_text( def render_rst_directive_with_text_edit( context: server.CompletionContext, directive: Directive, -) -> Optional[types.CompletionItem]: +) -> types.CompletionItem | None: """Render a ``CompletionItem`` for a reStructuredText directive using the ``textEdit`` field. @@ -189,7 +187,7 @@ def render_rst_directive_with_text_edit( def render_myst_directive_with_text_edit( context: server.CompletionContext, directive: Directive, -) -> Optional[types.CompletionItem]: +) -> types.CompletionItem | None: """Render a ``CompletionItem`` for a MyST directive using the ``textEdit`` field. Parameters @@ -240,7 +238,7 @@ def render_myst_directive_with_text_edit( def render_myst_directive_with_insert_text( context: server.CompletionContext, directive: Directive, -) -> Optional[types.CompletionItem]: +) -> types.CompletionItem | None: """Render a ``CompletionItem`` for a MyST directive using the ``insertText`` field. Parameters diff --git a/lib/esbonio/esbonio/server/features/log.py b/lib/esbonio/esbonio/server/features/log.py index 394919e8..5b76e4b7 100644 --- a/lib/esbonio/esbonio/server/features/log.py +++ b/lib/esbonio/esbonio/server/features/log.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import enum import json import logging @@ -5,7 +7,6 @@ import textwrap from logging.handlers import MemoryHandler from typing import Any -from typing import Dict from typing import Optional import attrs @@ -35,7 +36,9 @@ def emit(self, record: logging.LogRecord) -> None: return log = self.format(record).strip() - self.server.show_message_log(log) + self.server.window_log_message( + types.LogMessageParams(message=log, type=types.MessageType.Log) + ) @attrs.define @@ -205,7 +208,7 @@ def add_logger( self.loggers[name] = dict(level=level, propagate=False, handlers=handlers) - def finish(self) -> Dict[str, Any]: + def finish(self) -> dict[str, Any]: """Return the final configuration.""" return dict( version=1, @@ -235,13 +238,13 @@ class LoggingConfig: window: bool = attrs.field(default=False) """If set, send message as a ``window/logMessage`` notification""" - config: Dict[str, LoggerConfiguration] = attrs.field(factory=dict) + config: dict[str, LoggerConfiguration] = attrs.field(factory=dict) """Configuration of individual loggers""" show_deprecation_warnings: bool = attrs.field(default=False) """Developer flag to enable deprecation warnings.""" - def to_logging_config(self, server: server.EsbonioLanguageServer) -> Dict[str, Any]: + def to_logging_config(self, server: server.EsbonioLanguageServer) -> dict[str, Any]: """Convert the user's config into a config dict that can be passed to the ``logging.config.dictConfig()`` function. diff --git a/lib/esbonio/esbonio/server/features/myst/directives.py b/lib/esbonio/esbonio/server/features/myst/directives.py index aec577ac..0f638770 100644 --- a/lib/esbonio/esbonio/server/features/myst/directives.py +++ b/lib/esbonio/esbonio/server/features/myst/directives.py @@ -1,7 +1,5 @@ from __future__ import annotations -import typing - from lsprotocol import types from esbonio import server @@ -10,10 +8,6 @@ from esbonio.server.features.directives import completion from esbonio.sphinx_agent.types import MYST_DIRECTIVE -if typing.TYPE_CHECKING: - from typing import List - from typing import Optional - class MystDirectives(server.LanguageFeature): """A frontend to directives for MyST syntax.""" @@ -46,7 +40,7 @@ def update_configuration( async def completion( self, context: server.CompletionContext - ) -> Optional[List[types.CompletionItem]]: + ) -> list[types.CompletionItem] | None: """Provide completion suggestions for directives.""" groups = context.match.groupdict() @@ -76,7 +70,7 @@ async def complete_arguments(self, context: server.CompletionContext): async def complete_directives( self, context: server.CompletionContext - ) -> Optional[List[types.CompletionItem]]: + ) -> list[types.CompletionItem] | None: """Return completion suggestions for the available directives.""" render_func = completion.get_directive_renderer( diff --git a/lib/esbonio/esbonio/server/features/myst/roles.py b/lib/esbonio/esbonio/server/features/myst/roles.py index dbc01bda..9621b654 100644 --- a/lib/esbonio/esbonio/server/features/myst/roles.py +++ b/lib/esbonio/esbonio/server/features/myst/roles.py @@ -1,7 +1,5 @@ from __future__ import annotations -import typing - from lsprotocol import types from esbonio import server @@ -9,10 +7,6 @@ from esbonio.server.features.roles import completion from esbonio.sphinx_agent.types import MYST_ROLE -if typing.TYPE_CHECKING: - from typing import List - from typing import Optional - class MystRoles(server.LanguageFeature): """A frontend to roles for MyST syntax.""" @@ -45,7 +39,7 @@ def update_configuration( async def completion( self, context: server.CompletionContext - ) -> Optional[List[types.CompletionItem]]: + ) -> list[types.CompletionItem] | None: """Provide completion suggestions for roles.""" groups = context.match.groupdict() @@ -84,7 +78,7 @@ async def complete_targets(self, context: server.CompletionContext): async def complete_roles( self, context: server.CompletionContext - ) -> Optional[List[types.CompletionItem]]: + ) -> list[types.CompletionItem] | None: """Return completion suggestions for the available roles""" render_func = completion.get_role_renderer( diff --git a/lib/esbonio/esbonio/server/features/preview_manager/__init__.py b/lib/esbonio/esbonio/server/features/preview_manager/__init__.py index 723e9bbb..1ba0ab77 100644 --- a/lib/esbonio/esbonio/server/features/preview_manager/__init__.py +++ b/lib/esbonio/esbonio/server/features/preview_manager/__init__.py @@ -1,7 +1,5 @@ from typing import Any -from typing import Dict from typing import Optional -from typing import Set from urllib.parse import urlencode from lsprotocol import types @@ -34,7 +32,7 @@ def __init__( self.sphinx.add_listener("build", self.on_build) """The sphinx manager.""" - self.built_clients: Set[str] = set() + self.built_clients: set[str] = set() """Keeps track of which clients run a build at least once.""" self.build_path: Optional[str] = None @@ -190,7 +188,7 @@ async def show_preview_uri(self) -> Optional[Uri]: server = await self.preview webview = await self.webview - query_params: Dict[str, Any] = dict(ws=webview.port) + query_params: dict[str, Any] = dict(ws=webview.port) if self.config.show_line_markers: query_params["show-markers"] = True @@ -204,7 +202,7 @@ async def show_preview_uri(self) -> Optional[Uri]: self.logger.info("Preview available at: %s", uri.as_string(encode=False)) if self.supports_show_document: - result = await self.server.show_document_async( + result = await self.server.window_show_document_async( types.ShowDocumentParams( uri=uri.as_string(encode=False), external=True, take_focus=False ) diff --git a/lib/esbonio/esbonio/server/features/preview_manager/preview.py b/lib/esbonio/esbonio/server/features/preview_manager/preview.py index 1bae234d..802a86bc 100644 --- a/lib/esbonio/esbonio/server/features/preview_manager/preview.py +++ b/lib/esbonio/esbonio/server/features/preview_manager/preview.py @@ -11,7 +11,6 @@ if typing.TYPE_CHECKING: from typing import Any - from typing import Optional from .config import PreviewConfig @@ -38,7 +37,7 @@ class RequestHandlerFactory: produce a request handler based on the current situation. """ - def __init__(self, logger: logging.Logger, build_uri: Optional[Uri] = None): + def __init__(self, logger: logging.Logger, build_uri: Uri | None = None): self.logger = logger self.build_uri = build_uri @@ -67,16 +66,16 @@ def __init__(self, logger: logging.Logger, config: PreviewConfig, executor: Any) self._handler_factory = RequestHandlerFactory(self.logger) """Factory for producing http request handlers.""" - self._startup_task: Optional[asyncio.Task] = None + self._startup_task: asyncio.Task | None = None """Task that resolves once the server is ready.""" self._executor: Any = executor """The executor in which to run the http server.""" - self._future: Optional[asyncio.Future] = None + self._future: asyncio.Future | None = None """The future representing the http server's "task".""" - self._server: Optional[HTTPServer] = None + self._server: HTTPServer | None = None """The http server itself.""" def __await__(self): diff --git a/lib/esbonio/esbonio/server/features/preview_manager/webview.py b/lib/esbonio/esbonio/server/features/preview_manager/webview.py index 78de9332..40802398 100644 --- a/lib/esbonio/esbonio/server/features/preview_manager/webview.py +++ b/lib/esbonio/esbonio/server/features/preview_manager/webview.py @@ -9,51 +9,49 @@ from lsprotocol import types from pygls.protocol import JsonRPCProtocol from pygls.protocol import default_converter -from pygls.server import Server +from pygls.server import JsonRPCServer from pygls.server import WebSocketTransportAdapter from websockets.server import serve from esbonio import server if typing.TYPE_CHECKING: - from typing import Optional - from websockets import WebSocketServer from .config import PreviewConfig -class WebviewServer(Server): +class WebviewServer(JsonRPCServer): """The webview server controlls the webpage hosting the preview. Used to implement automatic reloads and features like sync scrolling. """ - lsp: JsonRPCProtocol + protocol: JsonRPCProtocol def __init__(self, logger: logging.Logger, config: PreviewConfig, *args, **kwargs): super().__init__(JsonRPCProtocol, default_converter, *args, **kwargs) self.config = config self.logger = logger.getChild("WebviewServer") - self.lsp._send_only_body = True + self.protocol._send_only_body = True self._connected = False - self._ws_server: Optional[WebSocketServer] = None + self._ws_server: WebSocketServer | None = None - self._startup_task: Optional[asyncio.Task] = None + self._startup_task: asyncio.Task | None = None """The task that resolves once startup is complete.""" - self._server_task: Optional[asyncio.Task] = None + self._server_task: asyncio.Task | None = None """The task hosting the server itself.""" - self._editor_in_control: Optional[asyncio.Task] = None + self._editor_in_control: asyncio.Task | None = None """If set, the editor is in control and the view should not emit scroll events""" - self._view_in_control: Optional[asyncio.Task] = None + self._view_in_control: asyncio.Task | None = None """If set, the view is in control and the editor should not emit scroll events""" - self._current_uri: Optional[str] = None + self._current_uri: str | None = None """If set, indicates the current uri the editor and view are scrolling.""" def __await__(self): @@ -76,13 +74,10 @@ def connected(self) -> bool: """Indicates when we have an active connection to the client.""" return self._connected - def feature(self, feature_name: str, options=None): - return self.lsp.fm.feature(feature_name, options) - def reload(self): """Reload the current view.""" if self.connected: - self.lsp.notify("view/reload", {}) + self.protocol.notify("view/reload", {}) def scroll(self, uri: str, line: int): """Called by the editor to scroll the current webview.""" @@ -95,7 +90,7 @@ def scroll(self, uri: str, line: int): self._current_uri = uri self._editor_in_control = asyncio.create_task(self.cooldown("editor")) - self.lsp.notify("view/scroll", {"uri": uri, "line": line}) + self.protocol.notify("view/scroll", {"uri": uri, "line": line}) async def cooldown(self, name: str): """Create a cooldown.""" @@ -130,13 +125,13 @@ async def connection(websocket): loop = asyncio.get_running_loop() transport = WebSocketTransportAdapter(websocket, loop) - self.lsp.connection_made(transport) # type: ignore[arg-type] + self.protocol.connection_made(transport) # type: ignore[arg-type] self._connected = True self.logger.debug("Connected") async for message in websocket: - self.lsp._procedure_handler( - json.loads(message, object_hook=self.lsp._deserialize_message) + self.protocol._procedure_handler( + json.loads(message, object_hook=self.protocol._deserialize_message) ) self.logger.debug("Connection lost") @@ -170,7 +165,7 @@ def on_scroll(ls: WebviewServer, params): server._view_in_control = asyncio.create_task(server.cooldown("view")) - esbonio.lsp.show_document( + esbonio.window_show_document( types.ShowDocumentParams( uri=params.uri, external=False, diff --git a/lib/esbonio/esbonio/server/features/project_manager/manager.py b/lib/esbonio/esbonio/server/features/project_manager/manager.py index 052365b7..9747fffa 100644 --- a/lib/esbonio/esbonio/server/features/project_manager/manager.py +++ b/lib/esbonio/esbonio/server/features/project_manager/manager.py @@ -1,18 +1,12 @@ from __future__ import annotations import pathlib -import typing from esbonio import server from esbonio.server import Uri from .project import Project -if typing.TYPE_CHECKING: - from typing import Dict - from typing import Optional - from typing import Union - class ProjectManager(server.LanguageFeature): """Responsible for managing project instances.""" @@ -20,15 +14,15 @@ class ProjectManager(server.LanguageFeature): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.projects: Dict[str, Project] = {} + self.projects: dict[str, Project] = {} """Holds active project instances""" - def register_project(self, scope: str, dbpath: Union[str, pathlib.Path]): + def register_project(self, scope: str, dbpath: str | pathlib.Path): """Register a project.""" self.logger.debug("Registered project for scope '%s': '%s'", scope, dbpath) self.projects[scope] = Project(dbpath, self.converter) - def get_project(self, uri: Uri) -> Optional[Project]: + def get_project(self, uri: Uri) -> Project | None: """Return the project instance for the given uri, if available""" scope = self.server.configuration.scope_for(uri) diff --git a/lib/esbonio/esbonio/server/features/project_manager/project.py b/lib/esbonio/esbonio/server/features/project_manager/project.py index e06de622..d803614f 100644 --- a/lib/esbonio/esbonio/server/features/project_manager/project.py +++ b/lib/esbonio/esbonio/server/features/project_manager/project.py @@ -11,13 +11,7 @@ if typing.TYPE_CHECKING: from typing import Any - from typing import Dict - from typing import List - from typing import Optional - from typing import Tuple - from typing import Type from typing import TypeVar - from typing import Union import cattrs @@ -27,10 +21,10 @@ class Project: """Represents a documentation project.""" - def __init__(self, dbpath: Union[str, pathlib.Path], converter: cattrs.Converter): + def __init__(self, dbpath: str | pathlib.Path, converter: cattrs.Converter): self.converter = converter self.dbpath = dbpath - self._connection: Optional[aiosqlite.Connection] = None + self._connection: aiosqlite.Connection | None = None async def close(self): if self._connection is not None: @@ -42,10 +36,10 @@ async def get_db(self) -> aiosqlite.Connection: return self._connection - def load_as(self, o: str, t: Type[T]) -> T: + def load_as(self, o: str, t: type[T]) -> T: return self.converter.structure(json.loads(o), t) - async def get_src_uris(self) -> List[Uri]: + async def get_src_uris(self) -> list[Uri]: """Return all known source uris.""" db = await self.get_db() @@ -54,7 +48,7 @@ async def get_src_uris(self) -> List[Uri]: results = await cursor.fetchall() return [Uri.parse(s[0]) for s in results] - async def get_build_path(self, src_uri: Uri) -> Optional[str]: + async def get_build_path(self, src_uri: Uri) -> str | None: """Get the build path associated with the given ``src_uri``.""" db = await self.get_db() @@ -65,7 +59,7 @@ async def get_build_path(self, src_uri: Uri) -> Optional[str]: return result[0] - async def get_config_value(self, name: str) -> Optional[Any]: + async def get_config_value(self, name: str) -> Any | None: """Return the requested configuration value, if available.""" db = await self.get_db() @@ -78,7 +72,7 @@ async def get_config_value(self, name: str) -> Optional[Any]: (value,) = row return json.loads(value) - async def get_directives(self) -> List[Tuple[str, Optional[str]]]: + async def get_directives(self) -> list[tuple[str, str | None]]: """Get the directives known to Sphinx.""" db = await self.get_db() @@ -86,7 +80,7 @@ async def get_directives(self) -> List[Tuple[str, Optional[str]]]: cursor = await db.execute(query) return await cursor.fetchall() # type: ignore[return-value] - async def get_role(self, name: str) -> Optional[types.Role]: + async def get_role(self, name: str) -> types.Role | None: """Get the roles known to Sphinx.""" db = await self.get_db() @@ -96,7 +90,7 @@ async def get_role(self, name: str) -> Optional[types.Role]: return types.Role.from_db(self.load_as, *result) if result is not None else None - async def get_roles(self) -> List[Tuple[str, Optional[str]]]: + async def get_roles(self) -> list[tuple[str, str | None]]: """Get the roles known to Sphinx.""" db = await self.get_db() @@ -104,7 +98,7 @@ async def get_roles(self) -> List[Tuple[str, Optional[str]]]: cursor = await db.execute(query) return await cursor.fetchall() # type: ignore[return-value] - async def get_document_symbols(self, src_uri: Uri) -> List[types.Symbol]: + async def get_document_symbols(self, src_uri: Uri) -> list[types.Symbol]: """Get the symbols for the given file.""" db = await self.get_db() query = ( @@ -114,14 +108,14 @@ async def get_document_symbols(self, src_uri: Uri) -> List[types.Symbol]: cursor = await db.execute(query, (str(src_uri.resolve()),)) return await cursor.fetchall() # type: ignore[return-value] - async def find_symbols(self, **kwargs) -> List[types.Symbol]: + async def find_symbols(self, **kwargs) -> list[types.Symbol]: """Find symbols which match the given criteria.""" db = await self.get_db() base_query = ( "SELECT id, name, kind, detail, range, parent_id, order_id FROM symbols" ) - where: List[str] = [] - parameters: List[Any] = [] + where: list[str] = [] + parameters: list[Any] = [] for param, value in kwargs.items(): where.append(f"{param} = ?") @@ -138,7 +132,7 @@ async def find_symbols(self, **kwargs) -> List[types.Symbol]: async def get_workspace_symbols( self, query: str - ) -> List[Tuple[str, str, int, str, str, str]]: + ) -> list[tuple[str, str, int, str, str, str]]: """Return all the workspace symbols matching the given query string""" db = await self.get_db() @@ -161,11 +155,11 @@ async def get_workspace_symbols( cursor = await db.execute(sql_query, (query_str, query_str)) return await cursor.fetchall() # type: ignore[return-value] - async def get_diagnostics(self) -> Dict[Uri, List[Dict[str, Any]]]: + async def get_diagnostics(self) -> dict[Uri, list[dict[str, Any]]]: """Get diagnostics for the project.""" db = await self.get_db() cursor = await db.execute("SELECT * FROM diagnostics") - results: Dict[Uri, List[Dict[str, Any]]] = {} + results: dict[Uri, list[dict[str, Any]]] = {} for uri_str, item in await cursor.fetchall(): uri = Uri.parse(uri_str) diff --git a/lib/esbonio/esbonio/server/features/roles/__init__.py b/lib/esbonio/esbonio/server/features/roles/__init__.py index ad19eb57..58d08c56 100644 --- a/lib/esbonio/esbonio/server/features/roles/__init__.py +++ b/lib/esbonio/esbonio/server/features/roles/__init__.py @@ -9,12 +9,8 @@ from esbonio.sphinx_agent import types if typing.TYPE_CHECKING: + from collections.abc import Coroutine from typing import Any - from typing import Coroutine - from typing import Dict - from typing import List - from typing import Optional - from typing import Union from esbonio.server import Uri @@ -24,7 +20,7 @@ class RoleProvider: def get_role( self, uri: Uri, name: str - ) -> Union[Optional[types.Role], Coroutine[Any, Any, Optional[types.Role]]]: + ) -> types.Role | None | Coroutine[Any, Any, types.Role | None]: """Return the definition of the given role, if known. Parameters @@ -39,9 +35,7 @@ def get_role( def suggest_roles( self, context: server.CompletionContext - ) -> Union[ - Optional[List[types.Role]], Coroutine[Any, Any, Optional[List[types.Role]]] - ]: + ) -> list[types.Role] | None | Coroutine[Any, Any, list[types.Role] | None]: """Givem a completion context, suggest roles that may be used.""" return None @@ -51,10 +45,11 @@ class RoleTargetProvider: def suggest_targets( self, context: server.CompletionContext, **kwargs - ) -> Union[ - Optional[List[lsp.CompletionItem]], - Coroutine[Any, Any, Optional[List[lsp.CompletionItem]]], - ]: + ) -> ( + list[lsp.CompletionItem] + | None + | Coroutine[Any, Any, list[lsp.CompletionItem] | None] + ): """Givem a completion context, suggest role targets that may be used.""" return None @@ -69,8 +64,8 @@ class RolesFeature(server.LanguageFeature): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self._role_providers: Dict[int, RoleProvider] = {} - self._target_providers: Dict[str, RoleTargetProvider] = {} + self._role_providers: dict[int, RoleProvider] = {} + self._target_providers: dict[str, RoleTargetProvider] = {} def add_role_provider(self, provider: RoleProvider): """Register a role provider. @@ -100,7 +95,7 @@ def add_target_provider(self, name: str, provider: RoleTargetProvider): async def suggest_roles( self, context: server.CompletionContext - ) -> List[types.Role]: + ) -> list[types.Role]: """Suggest roles that may be used, given a completion context. Parameters @@ -108,11 +103,11 @@ async def suggest_roles( context The completion context """ - items: List[types.Role] = [] + items: list[types.Role] = [] for provider in self._role_providers.values(): try: - result: Optional[List[types.Role]] = None + result: list[types.Role] | None = None aresult = provider.suggest_roles(context) if inspect.isawaitable(aresult): @@ -126,7 +121,7 @@ async def suggest_roles( return items - async def get_role(self, uri: Uri, name: str) -> Optional[types.Role]: + async def get_role(self, uri: Uri, name: str) -> types.Role | None: """Return the definition of the given role name. Parameters @@ -139,12 +134,12 @@ async def get_role(self, uri: Uri, name: str) -> Optional[types.Role]: Returns ------- - Optional[types.Role] + types.Role | None The role's definition, if known """ for provider in self._role_providers.values(): try: - result: Optional[types.Role] = None + result: types.Role | None = None aresult = provider.get_role(uri, name) if inspect.isawaitable(aresult): @@ -160,7 +155,7 @@ async def get_role(self, uri: Uri, name: str) -> Optional[types.Role]: async def suggest_targets( self, context: server.CompletionContext, role_name: str - ) -> List[lsp.CompletionItem]: + ) -> list[lsp.CompletionItem]: """Suggest role targets that may be used, given a completion context. Parameters @@ -186,7 +181,7 @@ async def suggest_targets( continue try: - result: Optional[List[lsp.CompletionItem]] = None + result: list[lsp.CompletionItem] | None = None aresult = provider.suggest_targets(context, **spec.kwargs) if inspect.isawaitable(aresult): diff --git a/lib/esbonio/esbonio/server/features/roles/completion.py b/lib/esbonio/esbonio/server/features/roles/completion.py index 6c5db338..9b403ded 100644 --- a/lib/esbonio/esbonio/server/features/roles/completion.py +++ b/lib/esbonio/esbonio/server/features/roles/completion.py @@ -11,9 +11,7 @@ if typing.TYPE_CHECKING: from typing import Callable - from typing import Dict from typing import Optional - from typing import Tuple from esbonio.sphinx_agent.types import Role @@ -27,10 +25,10 @@ WORD = re.compile("[a-zA-Z]+") -_ROLE_RENDERERS: Dict[Tuple[str, str], RoleRenderer] = {} +_ROLE_RENDERERS: dict[tuple[str, str], RoleRenderer] = {} """CompletionItem rendering functions for roles.""" -_ROLE_TARGET_RENDERERS: Dict[Tuple[str, str], RoleTargetRenderer] = {} +_ROLE_TARGET_RENDERERS: dict[tuple[str, str], RoleTargetRenderer] = {} """CompletionItem rendering functions for role targets.""" @@ -54,7 +52,7 @@ def fn(f: RoleTargetRenderer) -> RoleTargetRenderer: return fn -def get_role_renderer(language: str, insert_behavior: str) -> Optional[RoleRenderer]: +def get_role_renderer(language: str, insert_behavior: str) -> RoleRenderer | None: """Return the role renderer to use. Parameters @@ -75,7 +73,7 @@ def get_role_renderer(language: str, insert_behavior: str) -> Optional[RoleRende def get_role_target_renderer( language: str, insert_behavior: str -) -> Optional[RoleTargetRenderer]: +) -> RoleTargetRenderer | None: """Return the role target renderer to use. Parameters @@ -97,7 +95,7 @@ def get_role_target_renderer( @role_renderer(language="rst", insert_behavior="insert") def render_rst_role_with_insert_text( context: server.CompletionContext, role: Role -) -> Optional[types.CompletionItem]: +) -> types.CompletionItem | None: """Render a ``CompletionItem`` using ``insertText``. This implements the ``insert`` insert behavior for roles. @@ -145,7 +143,7 @@ def render_rst_role_with_insert_text( @role_target_renderer(language="rst", insert_behavior="replace") def render_rst_target_with_text_edit( context: server.CompletionContext, item: types.CompletionItem -) -> Optional[types.CompletionItem]: +) -> types.CompletionItem | None: """Render a ``CompletionItem`` using ``insertText``. This implements the ``replace`` insert behavior for role targets. @@ -169,7 +167,7 @@ def render_rst_target_with_text_edit( @role_renderer(language="markdown", insert_behavior="insert") def render_myst_role_with_insert_text( context: server.CompletionContext, role: Role -) -> Optional[types.CompletionItem]: +) -> types.CompletionItem | None: """Render a ``CompletionItem`` using ``insertText``. This implements the ``insert`` insert behavior for roles. @@ -217,7 +215,7 @@ def render_myst_role_with_insert_text( @role_renderer(language="rst", insert_behavior="replace") def render_rst_role_with_text_edit( context: server.CompletionContext, role: Role -) -> Optional[types.CompletionItem]: +) -> types.CompletionItem | None: """Render a role's ``CompletionItem`` using ``textEdit``. This implements the ``replace`` insert behavior for roles. @@ -260,7 +258,7 @@ def render_rst_role_with_text_edit( @role_renderer(language="markdown", insert_behavior="replace") def render_myst_role_with_text_edit( context: server.CompletionContext, role: Role -) -> Optional[types.CompletionItem]: +) -> types.CompletionItem | None: """Render a role's ``CompletionItem`` using ``textEdit``. This implements the ``replace`` insert behavior for roles. @@ -303,7 +301,7 @@ def render_myst_role_with_text_edit( @role_target_renderer(language="markdown", insert_behavior="replace") def render_myst_target_with_text_edit( context: server.CompletionContext, item: types.CompletionItem -) -> Optional[types.CompletionItem]: +) -> types.CompletionItem | None: """Render a ``CompletionItem`` using ``textEdit``. This implements the ``replace`` insert behavior for role targets. diff --git a/lib/esbonio/esbonio/server/features/rst/directives.py b/lib/esbonio/esbonio/server/features/rst/directives.py index a125e147..be608203 100644 --- a/lib/esbonio/esbonio/server/features/rst/directives.py +++ b/lib/esbonio/esbonio/server/features/rst/directives.py @@ -1,7 +1,5 @@ from __future__ import annotations -import typing - from lsprotocol import types from esbonio import server @@ -9,10 +7,6 @@ from esbonio.server.features.directives import completion from esbonio.sphinx_agent.types import RST_DIRECTIVE -if typing.TYPE_CHECKING: - from typing import List - from typing import Optional - class RstDirectives(server.LanguageFeature): """A frontend to directives for reStructuredText syntax.""" @@ -45,7 +39,7 @@ def update_configuration( async def completion( self, context: server.CompletionContext - ) -> Optional[List[types.CompletionItem]]: + ) -> list[types.CompletionItem] | None: """Provide completion suggestions for directives.""" groups = context.match.groupdict() @@ -75,7 +69,7 @@ async def complete_arguments(self, context: server.CompletionContext): async def complete_directives( self, context: server.CompletionContext - ) -> Optional[List[types.CompletionItem]]: + ) -> list[types.CompletionItem] | None: """Return completion suggestions for the available directives.""" render_func = completion.get_directive_renderer( diff --git a/lib/esbonio/esbonio/server/features/rst/roles.py b/lib/esbonio/esbonio/server/features/rst/roles.py index 6c31d049..12bda497 100644 --- a/lib/esbonio/esbonio/server/features/rst/roles.py +++ b/lib/esbonio/esbonio/server/features/rst/roles.py @@ -1,7 +1,5 @@ from __future__ import annotations -import typing - from lsprotocol import types from esbonio import server @@ -10,10 +8,6 @@ from esbonio.sphinx_agent.types import RST_DIRECTIVE from esbonio.sphinx_agent.types import RST_ROLE -if typing.TYPE_CHECKING: - from typing import List - from typing import Optional - class RstRoles(server.LanguageFeature): """A frontend to roles for reStructuredText syntax.""" @@ -46,7 +40,7 @@ def update_configuration( async def completion( self, context: server.CompletionContext - ) -> Optional[List[types.CompletionItem]]: + ) -> list[types.CompletionItem] | None: """Provide completion suggestions for roles.""" groups = context.match.groupdict() @@ -92,7 +86,7 @@ async def completion( async def complete_targets( self, context: server.CompletionContext - ) -> Optional[List[types.CompletionItem]]: + ) -> list[types.CompletionItem] | None: """Provide completion suggestions for role targets.""" render_func = completion.get_role_target_renderer( @@ -111,7 +105,7 @@ async def complete_targets( async def complete_roles( self, context: server.CompletionContext - ) -> Optional[List[types.CompletionItem]]: + ) -> list[types.CompletionItem] | None: """Return completion suggestions for the available roles""" render_func = completion.get_role_renderer( diff --git a/lib/esbonio/esbonio/server/features/sphinx_manager/client.py b/lib/esbonio/esbonio/server/features/sphinx_manager/client.py index f83e4c8b..26d446bb 100644 --- a/lib/esbonio/esbonio/server/features/sphinx_manager/client.py +++ b/lib/esbonio/esbonio/server/features/sphinx_manager/client.py @@ -6,11 +6,8 @@ if typing.TYPE_CHECKING: import pathlib + from collections.abc import Generator from typing import Any - from typing import Dict - from typing import Generator - from typing import List - from typing import Optional from esbonio.server import Uri from esbonio.sphinx_agent import types @@ -42,8 +39,8 @@ class SphinxClient(Protocol): """Describes the API language features can use to inspect/manipulate a Sphinx application instance.""" - state: Optional[ClientState] - sphinx_info: Optional[types.SphinxInfo] + state: ClientState | None + sphinx_info: types.SphinxInfo | None @property def id(self) -> str: @@ -91,9 +88,9 @@ async def restart(self) -> SphinxClient: async def build( self, *, - filenames: Optional[List[str]] = None, + filenames: list[str] | None = None, force_all: bool = False, - content_overrides: Optional[Dict[str, str]] = None, + content_overrides: dict[str, str] | None = None, ) -> types.BuildResult: """Trigger a Sphinx build.""" ... diff --git a/lib/esbonio/esbonio/server/features/sphinx_manager/client_subprocess.py b/lib/esbonio/esbonio/server/features/sphinx_manager/client_subprocess.py index d642c68d..14c241e9 100644 --- a/lib/esbonio/esbonio/server/features/sphinx_manager/client_subprocess.py +++ b/lib/esbonio/esbonio/server/features/sphinx_manager/client_subprocess.py @@ -23,9 +23,6 @@ if typing.TYPE_CHECKING: from typing import Any - from typing import Dict - from typing import List - from typing import Optional from .client import SphinxClient from .manager import SphinxManager @@ -54,7 +51,7 @@ class SubprocessSphinxClient(JsonRPCClient): def __init__( self, config: SphinxConfig, - logger: Optional[logging.Logger] = None, + logger: logging.Logger | None = None, protocol_cls=SphinxAgentProtocol, *args, **kwargs, @@ -70,22 +67,22 @@ def __init__( self.logger = logger or logging.getLogger(__name__) """The logger instance to use.""" - self.sphinx_info: Optional[types.SphinxInfo] = None + self.sphinx_info: types.SphinxInfo | None = None """Information about the Sphinx application the client is connected to.""" - self.state: Optional[ClientState] = None + self.state: ClientState | None = None """The current state of the client.""" - self.exception: Optional[Exception] = None + self.exception: Exception | None = None """The most recently encountered exception (if any)""" self._events = EventSource(self.logger) """The sphinx client can emit events.""" - self._startup_task: Optional[asyncio.Task] = None + self._startup_task: asyncio.Task | None = None """The startup task.""" - self._stderr_forwarder: Optional[asyncio.Task] = None + self._stderr_forwarder: asyncio.Task | None = None """A task that forwards the server's stderr to the test process.""" def __repr__(self): @@ -214,6 +211,7 @@ async def start(self) -> SphinxClient: params = types.CreateApplicationParams( command=self.config.build_command, + config_overrides=self.config.config_overrides, ) self.sphinx_info = await self.protocol.send_request_async( "sphinx/createApp", params @@ -254,9 +252,9 @@ async def stop(self): async def build( self, *, - filenames: Optional[List[str]] = None, + filenames: list[str] | None = None, force_all: bool = False, - content_overrides: Optional[Dict[str, str]] = None, + content_overrides: dict[str, str] | None = None, ) -> types.BuildResult: """Trigger a Sphinx build.""" @@ -334,7 +332,7 @@ def _on_progress(params): return client -def get_sphinx_env(config: SphinxConfig) -> Dict[str, str]: +def get_sphinx_env(config: SphinxConfig) -> dict[str, str]: """Return the set of environment variables to use with the Sphinx process.""" env = { diff --git a/lib/esbonio/esbonio/server/features/sphinx_manager/config.py b/lib/esbonio/esbonio/server/features/sphinx_manager/config.py index 53e0c48f..ba3e975c 100644 --- a/lib/esbonio/esbonio/server/features/sphinx_manager/config.py +++ b/lib/esbonio/esbonio/server/features/sphinx_manager/config.py @@ -1,8 +1,10 @@ +from __future__ import annotations + import hashlib import importlib.util import logging import pathlib -from typing import List +from typing import Any from typing import Optional import attrs @@ -45,19 +47,22 @@ class SphinxConfig: enable_dev_tools: bool = attrs.field(default=False) """Flag to enable dev tools.""" - python_command: List[str] = attrs.field(factory=list) + python_command: list[str] = attrs.field(factory=list) """The command to use when launching the python interpreter.""" - build_command: List[str] = attrs.field(factory=list) + build_command: list[str] = attrs.field(factory=list) """The sphinx-build command to use.""" - env_passthrough: List[str] = attrs.field(factory=list) + config_overrides: dict[str, Any] = attrs.field(factory=dict) + """Overrides to apply to Sphinx's configuration.""" + + env_passthrough: list[str] = attrs.field(factory=list) """List of environment variables to pass through to the Sphinx subprocess""" cwd: str = attrs.field(default="${scopeFsPath}") """The working directory to use.""" - python_path: List[pathlib.Path] = attrs.field(factory=list) + python_path: list[pathlib.Path] = attrs.field(factory=list) """The value of ``PYTHONPATH`` to use when injecting the sphinx agent into the target environment""" @@ -66,7 +71,7 @@ def resolve( uri: Uri, workspace: Workspace, logger: logging.Logger, - ) -> "Optional[SphinxConfig]": + ) -> Optional[SphinxConfig]: """Resolve the configuration based on user provided values. Parameters @@ -103,6 +108,7 @@ def resolve( return SphinxConfig( enable_dev_tools=self.enable_dev_tools, + config_overrides=self.config_overrides, cwd=cwd, env_passthrough=self.env_passthrough, python_command=self.python_command, @@ -154,7 +160,7 @@ def _resolve_cwd( return None - def _resolve_python_path(self, logger: logging.Logger) -> List[pathlib.Path]: + def _resolve_python_path(self, logger: logging.Logger) -> list[pathlib.Path]: """Return the list of paths to put on the sphinx agent's ``PYTHONPATH`` Using the ``PYTHONPATH`` environment variable, we can inject additional Python @@ -182,7 +188,7 @@ def _resolve_python_path(self, logger: logging.Logger) -> List[pathlib.Path]: python_path = [sphinx_agent] return python_path - def _resolve_build_command(self, uri: Uri, logger: logging.Logger) -> List[str]: + def _resolve_build_command(self, uri: Uri, logger: logging.Logger) -> list[str]: """Return the ``sphinx-build`` command to use. If no command is configured, this will attempt to guess the command to use based diff --git a/lib/esbonio/esbonio/server/features/sphinx_manager/manager.py b/lib/esbonio/esbonio/server/features/sphinx_manager/manager.py index 39fa9ff0..c0246288 100644 --- a/lib/esbonio/esbonio/server/features/sphinx_manager/manager.py +++ b/lib/esbonio/esbonio/server/features/sphinx_manager/manager.py @@ -18,8 +18,6 @@ if typing.TYPE_CHECKING: from typing import Callable - from typing import Dict - from typing import Optional from esbonio.server.features.project_manager import ProjectManager @@ -93,7 +91,7 @@ def __init__( self.project_manager = project_manager """The project manager instance to use.""" - self.clients: Dict[str, Optional[SphinxClient]] = { + self.clients: dict[str, SphinxClient | None] = { # Prevent any clients from being created in the global scope. "": None, } @@ -102,10 +100,10 @@ def __init__( self._events = server.EventSource(self.logger) """The SphinxManager can emit events.""" - self._pending_builds: Dict[str, asyncio.Task] = {} + self._pending_builds: dict[str, asyncio.Task] = {} """Holds tasks that will trigger a build after a given delay if not cancelled.""" - self._progress_tokens: Dict[str, str] = {} + self._progress_tokens: dict[str, str] = {} """Holds work done progress tokens.""" def add_listener(self, event: str, handler): @@ -183,11 +181,11 @@ async def trigger_build(self, uri: Uri): return # Pass through any unsaved content to the Sphinx agent. - content_overrides: Dict[str, str] = {} + content_overrides: dict[str, str] = {} known_src_uris = await project.get_src_uris() for src_uri in known_src_uris: - doc = self.server.workspace.get_document(str(src_uri)) + doc = self.server.workspace.get_text_document(str(src_uri)) doc_version = doc.version or 0 saved_version = getattr(doc, "saved_version", 0) @@ -199,7 +197,9 @@ async def trigger_build(self, uri: Uri): try: result = await client.build(content_overrides=content_overrides) except Exception as exc: - self.server.show_message(f"{exc}", lsp.MessageType.Error) + self.server.window_show_message( + lsp.ShowMessageParams(message=f"{exc}", type=lsp.MessageType.Error) + ) return finally: self.stop_progress(client) @@ -226,7 +226,7 @@ async def restart_client(self, client_id: str): else: self.logger.error(f"No client with id {client_id!r} available to restart") - async def get_client(self, uri: Uri) -> Optional[SphinxClient]: + async def get_client(self, uri: Uri) -> SphinxClient | None: """Given a uri, return the relevant sphinx client instance for it.""" scope = self.server.configuration.scope_for(uri) @@ -270,7 +270,7 @@ async def _create_or_replace_client( # If there was a previous client, stop it. if (previous_client := self.clients.pop(event.scope, None)) is not None: - self.server.lsp.notify( + self.server.protocol.notify( "sphinx/clientDestroyed", ClientDestroyedNotification(id=previous_client.id), ) @@ -284,7 +284,7 @@ async def _create_or_replace_client( self.clients[event.scope] = client = self.client_factory(self, resolved) client.add_listener("state-change", partial(self._on_state_change, event.scope)) - self.server.lsp.notify( + self.server.protocol.notify( "sphinx/clientCreated", ClientCreatedNotification(id=client.id, scope=event.scope, config=resolved), ) @@ -305,7 +305,7 @@ def _on_state_change( if old_state == ClientState.Starting and new_state == ClientState.Running: if (sphinx_info := client.sphinx_info) is not None: self.project_manager.register_project(scope, client.db) - self.server.lsp.notify( + self.server.protocol.notify( "sphinx/appCreated", AppCreatedNotification(id=client.id, application=sphinx_info), ) @@ -320,8 +320,10 @@ def _on_state_change( traceback.format_exception(type(exc), exc, exc.__traceback__) ) - self.server.lsp.show_message(error, lsp.MessageType.Error) - self.server.lsp.notify( + self.server.window_show_message( + lsp.ShowMessageParams(message=error, type=lsp.MessageType.Error) + ) + self.server.protocol.notify( "sphinx/clientErrored", ClientErroredNotification(id=client.id, error=error, detail=detail), ) @@ -333,13 +335,13 @@ async def start_progress(self, client: SphinxClient): self.logger.debug("Starting progress: '%s'", token) try: - await self.server.progress.create_async(token) + await self.server.work_done_progress.create_async(token) except Exception as exc: self.logger.debug("Unable to create progress token: %s", exc) return self._progress_tokens[client.id] = token - self.server.progress.begin( + self.server.work_done_progress.begin( token, lsp.WorkDoneProgressBegin(title="sphinx-build", cancellable=False), ) @@ -348,7 +350,9 @@ def stop_progress(self, client: SphinxClient): if (token := self._progress_tokens.pop(client.id, None)) is None: return - self.server.progress.end(token, lsp.WorkDoneProgressEnd(message="Finished")) + self.server.work_done_progress.end( + token, lsp.WorkDoneProgressEnd(message="Finished") + ) def report_progress(self, client: SphinxClient, progress: types.ProgressParams): """Report progress done for the given client.""" @@ -359,7 +363,7 @@ def report_progress(self, client: SphinxClient, progress: types.ProgressParams): if (token := self._progress_tokens.get(client.id, None)) is None: return - self.server.progress.report( + self.server.work_done_progress.report( token, lsp.WorkDoneProgressReport( message=progress.message, diff --git a/lib/esbonio/esbonio/server/features/sphinx_support/directives.py b/lib/esbonio/esbonio/server/features/sphinx_support/directives.py index 861b19b7..2cd3c101 100644 --- a/lib/esbonio/esbonio/server/features/sphinx_support/directives.py +++ b/lib/esbonio/esbonio/server/features/sphinx_support/directives.py @@ -1,17 +1,11 @@ from __future__ import annotations -import typing - from lsprotocol import types from esbonio import server from esbonio.server.features import directives from esbonio.server.features.project_manager import ProjectManager -if typing.TYPE_CHECKING: - from typing import List - from typing import Optional - class SphinxDirectives(directives.DirectiveProvider): """Support for directives in a sphinx project.""" @@ -21,7 +15,7 @@ def __init__(self, manager: ProjectManager): async def suggest_directives( self, context: server.CompletionContext - ) -> Optional[List[directives.Directive]]: + ) -> list[directives.Directive] | None: """Given a completion context, suggest directives that may be used.""" if (project := self.manager.get_project(context.uri)) is None: @@ -41,7 +35,7 @@ async def suggest_directives( primary_domain = await project.get_config_value("primary_domain") active_domain = default_domain or primary_domain or "py" - result: List[directives.Directive] = [] + result: list[directives.Directive] = [] for name, implementation in await project.get_directives(): # std: directives can be used unqualified if name.startswith("std:"): diff --git a/lib/esbonio/esbonio/server/features/sphinx_support/roles.py b/lib/esbonio/esbonio/server/features/sphinx_support/roles.py index 541fe8b2..bcce5d10 100644 --- a/lib/esbonio/esbonio/server/features/sphinx_support/roles.py +++ b/lib/esbonio/esbonio/server/features/sphinx_support/roles.py @@ -11,9 +11,6 @@ from esbonio.sphinx_agent import types if typing.TYPE_CHECKING: - from typing import List - from typing import Optional - from esbonio.server import Uri from esbonio.server.features.project_manager import Project @@ -41,9 +38,9 @@ async def suggest_targets( # type: ignore[override] self, context: server.CompletionContext, *, - obj_types: List[str], - projects: Optional[List[str]], - ) -> Optional[List[lsp.CompletionItem]]: + obj_types: list[str], + projects: list[str] | None, + ) -> list[lsp.CompletionItem] | None: # TODO: Handle .. currentmodule if (project := self.manager.get_project(context.uri)) is None: @@ -67,9 +64,7 @@ async def suggest_targets( # type: ignore[override] return items - def _prepare_target_query( - self, projects: Optional[List[str]], obj_types: List[str] - ): + def _prepare_target_query(self, projects: list[str] | None, obj_types: list[str]): """Prepare the query to use when looking up targets.""" select = "SELECT name, display, objtype FROM objects" @@ -123,7 +118,7 @@ async def get_default_domain(self, project: Project, uri: Uri) -> str: primary_domain = await project.get_config_value("primary_domain") return default_domain or primary_domain or "py" - async def get_role(self, uri: Uri, name: str) -> Optional[types.Role]: + async def get_role(self, uri: Uri, name: str) -> types.Role | None: """Return the role with the given name.""" if (project := self.manager.get_project(uri)) is None: @@ -140,7 +135,7 @@ async def get_role(self, uri: Uri, name: str) -> Optional[types.Role]: async def suggest_roles( self, context: server.CompletionContext - ) -> Optional[List[types.Role]]: + ) -> list[types.Role] | None: """Given a completion context, suggest roles that may be used.""" if (project := self.manager.get_project(context.uri)) is None: @@ -148,7 +143,7 @@ async def suggest_roles( default_domain = await self.get_default_domain(project, context.uri) - result: List[types.Role] = [] + result: list[types.Role] = [] for name, implementation in await project.get_roles(): # std: directives can be used unqualified if name.startswith("std:"): diff --git a/lib/esbonio/esbonio/server/features/sphinx_support/symbols.py b/lib/esbonio/esbonio/server/features/sphinx_support/symbols.py index 0d39b6a0..f4b4f663 100644 --- a/lib/esbonio/esbonio/server/features/sphinx_support/symbols.py +++ b/lib/esbonio/esbonio/server/features/sphinx_support/symbols.py @@ -1,7 +1,7 @@ +from __future__ import annotations + import asyncio import json -from typing import Dict -from typing import List from typing import Optional from lsprotocol import types @@ -21,7 +21,7 @@ def __init__(self, server: EsbonioLanguageServer, manager: ProjectManager): async def document_symbol( self, params: types.DocumentSymbolParams - ) -> Optional[List[types.DocumentSymbol]]: + ) -> Optional[list[types.DocumentSymbol]]: """Called when a document symbols request is received.""" uri = Uri.parse(params.text_document.uri) @@ -32,8 +32,8 @@ async def document_symbol( if len(symbols) == 0: return None - root: List[types.DocumentSymbol] = [] - index: Dict[int, types.DocumentSymbol] = {} + root: list[types.DocumentSymbol] = [] + index: dict[int, types.DocumentSymbol] = {} for id_, name, kind, detail, range_json, parent_id, _ in symbols: range_ = self.converter.structure(json.loads(range_json), types.Range) @@ -60,7 +60,7 @@ async def document_symbol( async def workspace_symbol( self, params: types.WorkspaceSymbolParams - ) -> Optional[List[types.WorkspaceSymbol]]: + ) -> Optional[list[types.WorkspaceSymbol]]: """Called when a workspace symbol request is received.""" tasks = [] @@ -70,7 +70,7 @@ async def workspace_symbol( ) symbols = await asyncio.gather(*tasks) - result: List[types.WorkspaceSymbol] = [] + result: list[types.WorkspaceSymbol] = [] for batch in symbols: for uri_str, name, kind, detail, range_json, container in batch: diff --git a/lib/esbonio/esbonio/server/server.py b/lib/esbonio/esbonio/server/server.py index 5e2a974d..d97430b5 100644 --- a/lib/esbonio/esbonio/server/server.py +++ b/lib/esbonio/esbonio/server/server.py @@ -13,7 +13,7 @@ import cattrs from lsprotocol import types from pygls.capabilities import get_capability -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer from pygls.workspace import TextDocument from pygls.workspace import Workspace @@ -21,15 +21,9 @@ from ._configuration import Configuration if typing.TYPE_CHECKING: + from collections.abc import Coroutine from typing import Any from typing import Callable - from typing import Coroutine - from typing import Dict - from typing import List - from typing import Optional - from typing import Set - from typing import Tuple - from typing import Type from .feature import LanguageFeature @@ -41,19 +35,19 @@ class EsbonioWorkspace(Workspace): """A modified version of pygls' workspace that ensures uris are always resolved.""" - def get_document(self, doc_uri: str) -> TextDocument: + def get_text_document(self, doc_uri: str) -> TextDocument: uri = str(Uri.parse(doc_uri).resolve()) return super().get_text_document(uri) - def put_document(self, text_document: types.TextDocumentItem): + def put_text_document(self, text_document: types.TextDocumentItem): text_document.uri = str(Uri.parse(text_document.uri).resolve()) return super().put_text_document(text_document) - def remove_document(self, doc_uri: str): + def remove_text_document(self, doc_uri: str): doc_uri = str(Uri.parse(doc_uri).resolve()) return super().remove_text_document(doc_uri) - def update_document( + def update_text_document( self, text_doc: types.VersionedTextDocumentIdentifier, change: types.TextDocumentContentChangeEvent, @@ -65,7 +59,7 @@ def update_document( class EsbonioLanguageServer(LanguageServer): """The Esbonio language server""" - def __init__(self, logger: Optional[logging.Logger] = None, *args, **kwargs): + def __init__(self, logger: logging.Logger | None = None, *args, **kwargs): if "name" not in kwargs: kwargs["name"] = "esbonio" @@ -74,19 +68,19 @@ def __init__(self, logger: Optional[logging.Logger] = None, *args, **kwargs): super().__init__(*args, **kwargs) - self._diagnostics: Dict[Tuple[str, Uri], List[types.Diagnostic]] = {} + self._diagnostics: dict[tuple[str, Uri], list[types.Diagnostic]] = {} """Where we store and manage diagnostics.""" - self._loaded_extensions: Dict[str, Any] = {} + self._loaded_extensions: dict[str, Any] = {} """Record of server modules that have been loaded.""" - self._features: Dict[Type[LanguageFeature], LanguageFeature] = {} + self._features: dict[type[LanguageFeature], LanguageFeature] = {} """The collection of language features registered with the server.""" self._ready: asyncio.Future[bool] = asyncio.Future() """Indicates if the server is ready.""" - self._tasks: Set[asyncio.Task] = set() + self._tasks: set[asyncio.Task] = set() """Used to hold running tasks""" self.logger = logger or logging.getLogger(__name__) @@ -105,7 +99,7 @@ def ready(self) -> asyncio.Future: @property def converter(self) -> cattrs.Converter: """The cattrs converter instance we should use.""" - return self.lsp._converter + return self.protocol._converter def _finish_task(self, task: asyncio.Task[Any]): """Cleanup a finished task.""" @@ -118,7 +112,7 @@ def _finish_task(self, task: asyncio.Task[Any]): traceback.format_exception(type(exc), exc, exc.__traceback__), ) - def run_task(self, coro: Coroutine, *, name: Optional[str] = None) -> asyncio.Task: + def run_task(self, coro: Coroutine, *, name: str | None = None) -> asyncio.Task: """Convert a given coroutine into a task and ensure it is executed.""" task = asyncio.create_task(coro, name=name) @@ -139,7 +133,7 @@ def initialize(self, params: types.InitializeParams): self.logger.info("Language client: %s %s", client.name, client.version) # TODO: Propose patch to pygls for providing custom Workspace implementations. - self.lsp._workspace = EsbonioWorkspace( + self.protocol._workspace = EsbonioWorkspace( self.workspace.root_uri, self.workspace._sync_kind, list(self.workspace.folders.values()), @@ -221,7 +215,7 @@ def add_feature(self, feature: LanguageFeature): self._features[feature_cls] = feature - def get_feature(self, feature_cls: Type[LF]) -> Optional[LF]: + def get_feature(self, feature_cls: type[LF]) -> LF | None: """Returns the requested language feature if it exists, otherwise it returns ``None``. @@ -232,7 +226,7 @@ def get_feature(self, feature_cls: Type[LF]) -> Optional[LF]: """ return self._features.get(feature_cls, None) # type: ignore - def clear_diagnostics(self, source: str, uri: Optional[Uri] = None) -> None: + def clear_diagnostics(self, source: str, uri: Uri | None = None) -> None: """Clear diagnostics from the given source. Parameters @@ -267,7 +261,7 @@ def add_diagnostics(self, source: str, uri: Uri, diagnostic: types.Diagnostic): self._diagnostics.setdefault(key, []).append(diagnostic) def set_diagnostics( - self, source: str, uri: Uri, diagnostics: List[types.Diagnostic] + self, source: str, uri: Uri, diagnostics: list[types.Diagnostic] ) -> None: """Set the diagnostics for the given source and uri. @@ -313,7 +307,9 @@ def sync_diagnostics(self) -> None: for uri, diag_list in diagnostics.items(): self.logger.debug("Publishing %d diagnostics for: %s", len(diag_list), uri) - self.publish_diagnostics(str(uri), diag_list.data) + self.text_document_publish_diagnostics( + types.PublishDiagnosticsParams(uri=str(uri), diagnostics=diag_list.data) + ) async def _register_did_change_watched_files_handler(self): """Register the server's handler for ``workspace/didChangeWatchedFiles``.""" @@ -332,7 +328,7 @@ async def _register_did_change_watched_files_handler(self): return try: - await self.register_capability_async( + await self.client_register_capability_async( types.RegistrationParams( registrations=[ types.Registration( @@ -381,7 +377,7 @@ async def _register_did_change_configuration_handler(self): return try: - await self.register_capability_async( + await self.client_register_capability_async( types.RegistrationParams( registrations=[ types.Registration( @@ -431,7 +427,7 @@ def append(self, item: types.Diagnostic): def _get_setup_arguments( server: EsbonioLanguageServer, setup: Callable, modname: str -) -> Optional[Dict[str, Any]]: +) -> dict[str, Any] | None: """Given a setup function, try to construct the collection of arguments to pass to it. """ diff --git a/lib/esbonio/esbonio/server/setup.py b/lib/esbonio/esbonio/server/setup.py index 38f10cb2..c05c6286 100644 --- a/lib/esbonio/esbonio/server/setup.py +++ b/lib/esbonio/esbonio/server/setup.py @@ -4,12 +4,8 @@ import inspect import pathlib import typing +from collections.abc import Iterable from typing import Any -from typing import Dict -from typing import Iterable -from typing import List -from typing import Set -from typing import Type from lsprotocol import types @@ -20,7 +16,7 @@ def create_language_server( - server_cls: Type[EsbonioLanguageServer], modules: Iterable[str], *args, **kwargs + server_cls: type[EsbonioLanguageServer], modules: Iterable[str], *args, **kwargs ) -> EsbonioLanguageServer: """Create a new language server instance. @@ -88,7 +84,7 @@ async def on_document_save( ls: EsbonioLanguageServer, params: types.DidSaveTextDocumentParams ): # Record the version number of the document - doc = ls.workspace.get_document(params.text_document.uri) + doc = ls.workspace.get_text_document(params.text_document.uri) doc.saved_version = doc.version or 0 await call_features(ls, "document_save", params) @@ -123,7 +119,7 @@ async def on_workspace_diagnostic( ls: EsbonioLanguageServer, params: types.WorkspaceDiagnosticParams ): """Handle a ``workspace/diagnostic`` request.""" - diagnostics: Dict[Uri, List[types.Diagnostic]] = {} + diagnostics: dict[Uri, list[types.Diagnostic]] = {} for (_, uri), diags in ls._diagnostics.items(): diagnostics.setdefault(uri, []).extend(diags) @@ -139,9 +135,7 @@ async def on_workspace_diagnostic( ) ) - # Typing issues should be fixed in a future version of lsprotocol - # see: https://github.com/microsoft/lsprotocol/pull/285 - return types.WorkspaceDiagnosticReport(items=reports) # type: ignore[arg-type] + return types.WorkspaceDiagnosticReport(items=reports) @server.feature(types.TEXT_DOCUMENT_DOCUMENT_SYMBOL) async def on_document_symbol( @@ -180,7 +174,7 @@ async def on_did_change_watched_files( def _configure_completion(server: EsbonioLanguageServer): """Configuration completion handlers.""" - trigger_characters: Set[str] = set() + trigger_characters: set[str] = set() for _, feature in server: if feature.completion_trigger is None: @@ -271,7 +265,7 @@ async def call_features(ls: EsbonioLanguageServer, method: str, *args, **kwargs) async def gather_results(ls: EsbonioLanguageServer, method: str, *args, **kwargs): """Call all features, gathering all results into a list.""" - results: List[Any] = [] + results: list[Any] = [] for cls, feature in ls: try: impl = getattr(feature, method) diff --git a/lib/esbonio/esbonio/sphinx_agent/app.py b/lib/esbonio/esbonio/sphinx_agent/app.py index 6cbff3b6..f0518e42 100644 --- a/lib/esbonio/esbonio/sphinx_agent/app.py +++ b/lib/esbonio/esbonio/sphinx_agent/app.py @@ -16,11 +16,8 @@ if typing.TYPE_CHECKING: from typing import IO from typing import Any - from typing import List - from typing import Optional - from typing import Tuple - RoleDefinition = Tuple[str, Any, List[types.Role.TargetProvider]] + RoleDefinition = tuple[str, Any, list[types.Role.TargetProvider]] sphinx_logger = logging.getLogger(SPHINX_LOG_NAMESPACE) logger = sphinx_logger.getChild("esbonio") @@ -48,14 +45,14 @@ def __init__(self, dbpath: pathlib.Path, app: _Sphinx): self.db = Database(dbpath) self.log = DiagnosticFilter(app) - self._roles: List[RoleDefinition] = [] + self._roles: list[RoleDefinition] = [] """Roles captured during Sphinx startup.""" def add_role( self, name: str, role: Any, - target_providers: Optional[List[types.Role.TargetProvider]] = None, + target_providers: list[types.Role.TargetProvider] | None = None, ): """Register a role with esbonio. diff --git a/lib/esbonio/esbonio/sphinx_agent/config.py b/lib/esbonio/esbonio/sphinx_agent/config.py index 73507581..f4e3262e 100644 --- a/lib/esbonio/esbonio/sphinx_agent/config.py +++ b/lib/esbonio/esbonio/sphinx_agent/config.py @@ -1,10 +1,10 @@ +from __future__ import annotations + import dataclasses import inspect import pathlib import sys from typing import Any -from typing import Dict -from typing import List from typing import Literal from typing import Optional from typing import Union @@ -33,7 +33,7 @@ class SphinxConfig: doctree_dir: str """The directory to write doctrees into.""" - config_overrides: Dict[str, Any] = dataclasses.field(default_factory=dict) + config_overrides: dict[str, Any] = dataclasses.field(default_factory=dict) """Any overrides to configuration values.""" force_full_build: bool = dataclasses.field(default=False) @@ -51,7 +51,7 @@ class SphinxConfig: silent: bool = dataclasses.field(default=False) """Hide all Sphinx output.""" - tags: List[str] = dataclasses.field(default_factory=list) + tags: list[str] = dataclasses.field(default_factory=list) """Tags to enable during a build.""" verbosity: int = dataclasses.field(default=0) @@ -75,7 +75,7 @@ def parallel(self) -> int: return self.num_jobs @classmethod - def fromcli(cls, args: List[str]): + def fromcli(cls, args: list[str]): """Return the ``SphinxConfig`` instance that's equivalent to the given arguments. Parameters @@ -128,7 +128,7 @@ def fromcli(cls, args: List[str]): warning_is_error=sphinx_args.get("warningiserror", False), ) - def to_application_args(self) -> Dict[str, Any]: + def to_application_args(self) -> dict[str, Any]: """Convert this into the equivalent Sphinx application arguments.""" # On OSes like Fedora Silverblue, `/home` is symlinked to `/var/home`. This diff --git a/lib/esbonio/esbonio/sphinx_agent/database.py b/lib/esbonio/esbonio/sphinx_agent/database.py index db86c869..0d15424e 100644 --- a/lib/esbonio/esbonio/sphinx_agent/database.py +++ b/lib/esbonio/esbonio/sphinx_agent/database.py @@ -5,12 +5,7 @@ from dataclasses import dataclass from dataclasses import field from typing import Any -from typing import List from typing import Literal -from typing import Optional -from typing import Set -from typing import Tuple -from typing import Union class Database: @@ -19,7 +14,7 @@ class Column: name: str dtype: str notnull: bool = field(default=False) - default: Optional[Any] = field(default=None) + default: Any | None = field(default=None) pk: int = field(default=0) @property @@ -30,7 +25,7 @@ def definition(self): @dataclass class Table: name: str - columns: List[Database.Column] + columns: list[Database.Column] @property def create_statement(self): @@ -39,7 +34,7 @@ def create_statement(self): columns = ",".join([c.definition for c in self.columns]) return "".join([f"CREATE TABLE {self.name} (", columns, ");"]) - def __init__(self, dbpath: Union[pathlib.Path, Literal[":memory:"]]): + def __init__(self, dbpath: pathlib.Path | Literal[":memory:"]): self.path = dbpath if isinstance(self.path, pathlib.Path) and not self.path.parent.exists(): @@ -50,9 +45,9 @@ def __init__(self, dbpath: Union[pathlib.Path, Literal[":memory:"]]): # Ensure that Write Ahead Logging is enabled. self.db.execute("PRAGMA journal_mode(WAL)") - self._checked_tables: Set[str] = set() + self._checked_tables: set[str] = set() - def _get_table(self, name: str) -> Optional[Table]: + def _get_table(self, name: str) -> Table | None: """Get the table with the given name, if it exists.""" # TODO: SQLite does not seem to like '?' syntax in this statement... cursor = self.db.execute(f"PRAGMA table_info({name});") @@ -89,8 +84,8 @@ def clear_table(self, table: Table, **kwargs): # TODO: Is there a way to pass the table name as a '?' parameter? base_query = f"DELETE FROM {table.name}" # noqa: S608 - where: List[str] = [] - parameters: List[Any] = [] + where: list[str] = [] + parameters: list[Any] = [] for param, value in kwargs.items(): if value is None: @@ -134,7 +129,7 @@ def ensure_table(self, table: Table): self._checked_tables.add(table.name) - def insert_values(self, table: Table, values: List[Tuple]): + def insert_values(self, table: Table, values: list[tuple]): """Insert the given values into the given table.""" if len(values) == 0: diff --git a/lib/esbonio/esbonio/sphinx_agent/handlers/__init__.py b/lib/esbonio/esbonio/sphinx_agent/handlers/__init__.py index 613cad2f..bc1f158e 100644 --- a/lib/esbonio/esbonio/sphinx_agent/handlers/__init__.py +++ b/lib/esbonio/esbonio/sphinx_agent/handlers/__init__.py @@ -1,14 +1,12 @@ +from __future__ import annotations + import inspect import logging import sys import traceback import typing from typing import Callable -from typing import Dict -from typing import List from typing import Optional -from typing import Tuple -from typing import Type import sphinx.application from sphinx import __version__ as __sphinx_version__ @@ -42,12 +40,12 @@ def __init__(self): self.app: Optional[Sphinx] = None """The sphinx application instance""" - self._content_overrides: Dict[Uri, str] = {} + self._content_overrides: dict[Uri, str] = {} """Holds any additional content to inject into a build.""" - self._handlers: Dict[str, Tuple[Type, Callable]] = self._register_handlers() + self._handlers: dict[str, tuple[type, Callable]] = self._register_handlers() - def get(self, method: str) -> Optional[Tuple[Type, Callable]]: + def get(self, method: str) -> Optional[tuple[type, Callable]]: """Return the handler for the given method - if possible. Parameters @@ -67,7 +65,7 @@ def get(self, method: str) -> Optional[Tuple[Type, Callable]]: """ return self._handlers.get(method) - def _register_handlers(self) -> Dict[str, Tuple[Type, Callable]]: + def _register_handlers(self) -> dict[str, tuple[type, Callable]]: """Return a map of all the handlers we provide. A handler @@ -85,7 +83,7 @@ class definition from the ``types`` module. representing the message body, the second element is the method which implements it. """ - handlers: Dict[str, Tuple[Type, Callable]] = {} + handlers: dict[str, tuple[type, Callable]] = {} for name in dir(self): method_func = getattr(self, name) @@ -112,6 +110,7 @@ def create_sphinx_app(self, request: types.CreateApplicationRequest): if sphinx_config is None: raise ValueError("Invalid build command") + sphinx_config.config_overrides.update(request.params.config_overrides) sphinx_args = sphinx_config.to_application_args() self.app = Sphinx(**sphinx_args) @@ -135,7 +134,7 @@ def create_sphinx_app(self, request: types.CreateApplicationRequest): ) send_message(response) - def _cb_env_before_read_docs(self, app: Sphinx, env, docnames: List[str]): + def _cb_env_before_read_docs(self, app: Sphinx, env, docnames: list[str]): """Used to add additional documents to the "to build" list.""" is_building = set(docnames) diff --git a/lib/esbonio/esbonio/sphinx_agent/handlers/directives.py b/lib/esbonio/esbonio/sphinx_agent/handlers/directives.py index 5eb69399..0b3606fa 100644 --- a/lib/esbonio/esbonio/sphinx_agent/handlers/directives.py +++ b/lib/esbonio/esbonio/sphinx_agent/handlers/directives.py @@ -1,8 +1,8 @@ +from __future__ import annotations + import importlib import inspect -from typing import List from typing import Optional -from typing import Type from docutils.parsers.rst import Directive from docutils.parsers.rst import directives as docutils_directives @@ -22,14 +22,14 @@ ) -def get_impl_name(directive: Type[Directive]) -> str: +def get_impl_name(directive: type[Directive]) -> str: try: return f"{directive.__module__}.{directive.__name__}" except AttributeError: return f"{directive.__module__}.{directive.__class__.__name__}" -def get_impl_location(impl: Type[Directive]) -> Optional[str]: +def get_impl_location(impl: type[Directive]) -> Optional[str]: """Get the implementation location of the given directive""" try: @@ -66,7 +66,7 @@ def index_directives(app: Sphinx): first time. """ - directives: List[types.Directive] = [] + directives: list[types.Directive] = [] ignored_directives = {"restructuredtext-test-directive"} found_directives = { diff --git a/lib/esbonio/esbonio/sphinx_agent/handlers/domains.py b/lib/esbonio/esbonio/sphinx_agent/handlers/domains.py index 07d4b58e..d5abcd61 100644 --- a/lib/esbonio/esbonio/sphinx_agent/handlers/domains.py +++ b/lib/esbonio/esbonio/sphinx_agent/handlers/domains.py @@ -10,12 +10,6 @@ from ..util import as_json if typing.TYPE_CHECKING: - from typing import Dict - from typing import List - from typing import Optional - from typing import Set - from typing import Tuple - from sphinx.domains import Domain from sphinx.util.typing import Inventory @@ -50,9 +44,7 @@ class DomainObjects: """Discovers and indexes domain objects.""" def __init__(self, app: Sphinx): - self._info: Dict[ - Tuple[str, str, str, str], Tuple[Optional[str], Optional[str]] - ] = {} + self._info: dict[tuple[str, str, str, str], tuple[str | None, str | None]] = {} # Needs to run late, but before the handler in ./roles.py app.connect("builder-inited", self.init_db, priority=998) @@ -139,7 +131,7 @@ def object_defined( self._info[key] = (description, location) -def index_domain(app: Sphinx, domain: Domain, projects: Optional[List[str]]): +def index_domain(app: Sphinx, domain: Domain, projects: list[str] | None): """Index the roles in the given domain. Parameters @@ -153,7 +145,7 @@ def index_domain(app: Sphinx, domain: Domain, projects: Optional[List[str]]): projects The list of known intersphinx projects """ - target_types: Dict[str, Set[str]] = {} + target_types: dict[str, set[str]] = {} for obj_name, item_type in domain.object_types.items(): for role_name in item_type.roles: @@ -190,7 +182,7 @@ def index_domain(app: Sphinx, domain: Domain, projects: Optional[List[str]]): ) -def index_intersphinx_projects(app: Sphinx) -> List[Tuple[str, str, str, str]]: +def index_intersphinx_projects(app: Sphinx) -> list[tuple[str, str, str, str]]: """Index all the projects known to intersphinx. Parameters @@ -207,7 +199,7 @@ def index_intersphinx_projects(app: Sphinx) -> List[Tuple[str, str, str, str]]: app.esbonio.db.ensure_table(PROJECTS_TABLE) app.esbonio.db.clear_table(PROJECTS_TABLE) - projects: List[Tuple[str, str, str, str]] = [] + projects: list[tuple[str, str, str, str]] = [] objects = [] mapping = getattr(app.config, "intersphinx_mapping", {}) diff --git a/lib/esbonio/esbonio/sphinx_agent/handlers/files.py b/lib/esbonio/esbonio/sphinx_agent/handlers/files.py index eeab0909..4421690c 100644 --- a/lib/esbonio/esbonio/sphinx_agent/handlers/files.py +++ b/lib/esbonio/esbonio/sphinx_agent/handlers/files.py @@ -10,9 +10,6 @@ if typing.TYPE_CHECKING: from typing import Any - from typing import List - from typing import Optional - from typing import Tuple from sphinx.config import Config @@ -47,7 +44,7 @@ def init_db(app: Sphinx, config: Config): app.esbonio.db.ensure_table(CONFIG_TABLE) -def value_to_db(name: str, item: Any) -> Tuple[str, str, Any]: +def value_to_db(name: str, item: Any) -> tuple[str, str, Any]: """Convert a single value to its DB representation""" try: @@ -62,7 +59,7 @@ def dump_config(app: Sphinx, *args): it.""" app.esbonio.db.clear_table(CONFIG_TABLE) - values: List[Tuple[str, str, str]] = [] + values: list[tuple[str, str, str]] = [] config = app.config.__getstate__() # For some reason, most config values are nested under 'values' @@ -89,13 +86,13 @@ def dump_config(app: Sphinx, *args): app.esbonio.db.insert_values(CONFIG_TABLE, values) -def build_file_mapping(app: Sphinx, exc: Optional[Exception]): +def build_file_mapping(app: Sphinx, exc: Exception | None): """Given a Sphinx application, return a mapping of all known source files to their corresponding output files.""" env = app.env builder = app.builder - files: List[Tuple[str, str, str]] = [] + files: list[tuple[str, str, str]] = [] for docname in env.found_docs: uri = Uri.for_file(env.doc2path(docname)).resolve() diff --git a/lib/esbonio/esbonio/sphinx_agent/handlers/roles.py b/lib/esbonio/esbonio/sphinx_agent/handlers/roles.py index 1f96d33b..ad5e3c93 100644 --- a/lib/esbonio/esbonio/sphinx_agent/handlers/roles.py +++ b/lib/esbonio/esbonio/sphinx_agent/handlers/roles.py @@ -1,6 +1,5 @@ import inspect from typing import Any -from typing import Dict from typing import Optional from docutils.parsers.rst import roles as docutils_roles @@ -55,7 +54,7 @@ def get_impl_location(impl: Any) -> Optional[types.Location]: def index_roles(app: Sphinx): """Index all the roles that are available to this app.""" - roles: Dict[str, types.Role] = {} + roles: dict[str, types.Role] = {} # Process the roles registered through Sphinx for name, impl, providers in app.esbonio._roles: diff --git a/lib/esbonio/esbonio/sphinx_agent/handlers/symbols.py b/lib/esbonio/esbonio/sphinx_agent/handlers/symbols.py index 258ef294..b2196bf0 100644 --- a/lib/esbonio/esbonio/sphinx_agent/handlers/symbols.py +++ b/lib/esbonio/esbonio/sphinx_agent/handlers/symbols.py @@ -1,7 +1,6 @@ import logging import typing from typing import IO -from typing import List from docutils import nodes from docutils.core import Publisher @@ -67,7 +66,7 @@ def update_symbols(app: Sphinx, docname: str, source): destination=NullOutput(), ) publisher.settings = settings - publisher.set_source(source="\n".join(source), source_path=filename) + publisher.set_source(source="\n".join(source), source_path=str(filename)) publisher.publish() document = publisher.document @@ -212,13 +211,13 @@ class SymbolVisitor(nodes.NodeVisitor): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.symbols: List[types.Symbol] = [] + self.symbols: list[types.Symbol] = [] """Holds the symbols for the document""" - self.parents: List[int] = [] + self.parents: list[int] = [] """Holds the ids of the current hierarchy.""" - self.order: List[int] = [0] + self.order: list[int] = [0] """Holds the current position at each level of the hierarchy.""" def push_symbol(self, name: str, kind: int, range_: types.Range, detail: str = ""): diff --git a/lib/esbonio/esbonio/sphinx_agent/handlers/webview.py b/lib/esbonio/esbonio/sphinx_agent/handlers/webview.py index 28092141..7bcf87ca 100644 --- a/lib/esbonio/esbonio/sphinx_agent/handlers/webview.py +++ b/lib/esbonio/esbonio/sphinx_agent/handlers/webview.py @@ -11,13 +11,11 @@ from ..log import source_to_uri_and_linum if typing.TYPE_CHECKING: - from typing import Dict - from typing import Tuple - from sphinx.application import Sphinx STATIC_DIR = (pathlib.Path(__file__).parent.parent / "static").resolve() +ALLOWED_MODULES = {"docutils.nodes", "sphinx.addnodes"} def has_source(node): @@ -34,6 +32,16 @@ def has_source(node): if isinstance(node, addnodes.toctree) and version_info[0] < 7: return False + # It's not only limited to `toctreenodes`! + # + # The identical error is thrown when using esbonio with the `ablog` extension + # See: https://github.com/swyddfa/esbonio/issues/874 + # + # I think for now, the safest approach is to only handle nodes defined by Sphinx or + # docutils. + if node.__module__ not in ALLOWED_MODULES: + return False + return (node.line or 0) > 0 and node.source is not None @@ -42,7 +50,7 @@ class source_locations(nodes.General, nodes.Element): def visit_source_locations(self, node): - source_index: Dict[int, Tuple[str, int]] = node["index"] + source_index: dict[int, tuple[str, int]] = node["index"] self.body.append('