Full Code of eclipse-theia/theia-ide for AI

master c5ce2e7120a1 cached
136 files
351.1 KB
91.6k tokens
174 symbols
1 requests
Download .txt
Showing preview only (385K chars total). Download the full file or copy to clipboard to get everything.
Repository: eclipse-theia/theia-ide
Branch: master
Commit: c5ce2e7120a1
Files: 136
Total size: 351.1 KB

Directory structure:
gitextract_jxq8o1lq/

├── .eslintrc.js
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   └── feature_request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── build-next-release.yml
│       ├── build-next.yml
│       ├── build.yml
│       ├── license-check-workflow.yml
│       ├── publish-builder-img.yml
│       └── publish-theia-ide-img.yml
├── .gitignore
├── .vscode/
│   ├── launch.json
│   ├── settings.json
│   └── theia.code-snippets
├── ADOPTER.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── NOTICE.md
├── PUBLISHING.md
├── README.md
├── TheiaIDE logo/
│   └── TheiaIDE.eps
├── applications/
│   ├── browser/
│   │   ├── package.json
│   │   ├── resources/
│   │   │   └── preload.html
│   │   ├── tsconfig.json
│   │   └── webpack.config.js
│   ├── electron/
│   │   ├── .eslintrc.js
│   │   ├── electron-builder.yml
│   │   ├── entitlements.plist
│   │   ├── package.json
│   │   ├── resources/
│   │   │   ├── LICENSE
│   │   │   ├── icon.icns
│   │   │   ├── icons/
│   │   │   │   └── MacLauncherIcons/
│   │   │   │       ├── 512-512-2.icns
│   │   │   │       ├── Theia-16bp-alfa ignored.icns
│   │   │   │       ├── icns-1bit/
│   │   │   │       │   ├── 128-128.icns
│   │   │   │       │   ├── 16-16-1.icns
│   │   │   │       │   ├── 256-256.icns
│   │   │   │       │   ├── 32-32.icns
│   │   │   │       │   ├── 48-48.icns
│   │   │   │       │   └── 512-512-2 copy.icns
│   │   │   │       ├── icns-8bit/
│   │   │   │       │   ├── 128-128.icns
│   │   │   │       │   ├── 16-16.icns
│   │   │   │       │   ├── 256-256.icns
│   │   │   │       │   ├── 32-32.icns
│   │   │   │       │   ├── 48-48.icns
│   │   │   │       │   └── 512-512.icns
│   │   │   │       ├── icon.icns
│   │   │   │       └── icon.icon/
│   │   │   │           └── icon.json
│   │   │   └── preload.html
│   │   ├── scripts/
│   │   │   ├── after-pack.js
│   │   │   ├── appimage-helpers.js
│   │   │   ├── generate-app-update-yml.js
│   │   │   ├── notarize.sh
│   │   │   ├── sign-directory-windows.ts
│   │   │   ├── sign-directory.ts
│   │   │   ├── sign-utils.ts
│   │   │   ├── sign.sh
│   │   │   ├── theia-electron-main.js
│   │   │   ├── update-blockmap.ts
│   │   │   └── update-checksum.ts
│   │   ├── test/
│   │   │   ├── app.spec.js
│   │   │   └── workspace/
│   │   │       └── README.md
│   │   ├── tsconfig.eslint.json
│   │   ├── tsconfig.json
│   │   └── webpack.config.js
│   └── electron-next/
│       ├── .eslintrc.js
│       ├── electron-builder.yml
│       ├── package.json
│       ├── resources/
│       │   ├── LICENSE
│       │   └── preload.html
│       ├── scripts/
│       │   ├── after-pack.js
│       │   ├── appimage-helpers.js
│       │   └── theia-electron-main.js
│       ├── test/
│       │   └── workspace/
│       │       └── README.md
│       ├── tsconfig.eslint.json
│       ├── tsconfig.json
│       └── webpack.config.js
├── browser.Dockerfile
├── cleanup/
│   └── Jenkinsfile
├── configs/
│   ├── base.eslintrc.json
│   ├── base.tsconfig.json
│   ├── build.eslintrc.json
│   ├── errors.eslintrc.json
│   ├── license-check-config.json
│   ├── tsconfig.eslint.json
│   ├── warnings.eslintrc.json
│   └── xss.eslintrc.json
├── docs/
│   └── developing-with-local-theia.md
├── lerna.json
├── next/
│   ├── Jenkinsfile
│   └── NEXT_INTEGRATION_BUILD.md
├── package.json
├── patches/
│   └── @theia+terminal+1.72.0-next.20.patch
├── releng/
│   ├── preview/
│   │   ├── Jenkinsfile.build
│   │   ├── Jenkinsfile.sign
│   │   └── Jenkinsfile.upload
│   └── promote/
│       └── Jenkinsfile
├── scripts/
│   ├── build-with-local-theia.js
│   ├── generate-next-icons.js
│   ├── make-files-writeable.ts
│   └── update-theia-version.ts
├── theia-extensions/
│   ├── launcher/
│   │   ├── .eslintrc.js
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── browser/
│   │   │   │   ├── create-launcher-contribution.ts
│   │   │   │   ├── create-launcher-frontend-module.ts
│   │   │   │   ├── desktopfile-service.ts
│   │   │   │   └── launcher-service.ts
│   │   │   └── node/
│   │   │       ├── desktopfile-endpoint.ts
│   │   │       ├── launcher-backend-module.ts
│   │   │       ├── launcher-endpoint.ts
│   │   │       └── launcher-util.ts
│   │   └── tsconfig.json
│   ├── product/
│   │   ├── .eslintrc.js
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── browser/
│   │   │   │   ├── branding-util.tsx
│   │   │   │   ├── style/
│   │   │   │   │   └── index.css
│   │   │   │   ├── theia-ide-about-dialog.tsx
│   │   │   │   ├── theia-ide-config.ts
│   │   │   │   ├── theia-ide-contribution.tsx
│   │   │   │   ├── theia-ide-frontend-module.ts
│   │   │   │   └── theia-ide-getting-started-widget.tsx
│   │   │   └── electron-main/
│   │   │       ├── icon-contribution.ts
│   │   │       └── theia-ide-main-module.ts
│   │   └── tsconfig.json
│   └── updater/
│       ├── .eslintrc.js
│       ├── package.json
│       ├── src/
│       │   ├── common/
│       │   │   └── updater/
│       │   │       └── theia-updater.ts
│       │   ├── electron-browser/
│       │   │   ├── theia-updater-frontend-module.ts
│       │   │   └── updater/
│       │   │       ├── theia-updater-frontend-contribution.ts
│       │   │       └── theia-updater-preferences.ts
│       │   └── electron-main/
│       │       └── update/
│       │           ├── theia-updater-impl.ts
│       │           └── theia-updater-main-module.ts
│       └── tsconfig.json
└── tsconfig.json

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

================================================
FILE: .eslintrc.js
================================================
/** @type {import('eslint').Linter.Config} */
module.exports = {
    root: true,
    extends: [
        './configs/base.eslintrc.json',
        './configs/warnings.eslintrc.json',
        './configs/errors.eslintrc.json',
        './configs/xss.eslintrc.json'
    ],
    ignorePatterns: [
        '**/{node_modules,lib}',
        'plugins'
    ],
    parserOptions: {
        tsconfigRootDir: __dirname,
        project: ['./configs/tsconfig.eslint.json', './theia-extensions/*/tsconfig.json', 'applications/electron/tsconfig.eslint.json']
    }
};


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug Report
about: Create a report to help us improve
---

<!-- Please provide a detailed description of the bug. -->
### Bug Description:

<!-- Please provide clear steps to reproduce the bug. -->
### Steps to Reproduce:

1.
2.
3.

<!-- Please provide any additional information available. -->
<!-- Additional information can be in the form of logs, screenshots, screencasts. -->

### Additional Information

- Operating System:
- Theia Version:


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Question
    url:  https://github.com/eclipse-theia/theia/discussions
    about: Please ask questions here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature Request
about: Propose an idea for the project
---

<!-- Please fill out the following content for a feature request. -->

<!-- Please provide a clear description of the feature and any relevant information. -->
### Feature Description:


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--
Thank you for your Pull Request. Please provide a description and review
the requirements below.

Contributors guide: https://github.com/theia-ide/theia/blob/master/CONTRIBUTING.md
-->

#### What it does
<!-- Include relevant issues and describe how they are addressed. -->

#### How to test
<!-- Explain how a reviewer can reproduce a bug, test new functionality or verify performance improvements. -->

#### Review checklist

- [ ] as an author, I have thoroughly tested my changes and carefully followed [the review guidelines](https://github.com/theia-ide/theia/blob/master/doc/pull-requests.md#requesting-a-review)

#### Reminder for reviewers

- as a reviewer, I agree to behave in accordance with [the review guidelines](https://github.com/theia-ide/theia/blob/master/doc/pull-requests.md#reviewing)



================================================
FILE: .github/workflows/build-next-release.yml
================================================
name: Build Theia IDE Next Release (Linux)

on:
  workflow_dispatch:
  schedule:
    - cron: "0 2 * * 1-5" # Runs every weekday at 2am UTC

jobs:
  build:
    name: Build Next Release (Linux only)
    runs-on: ubuntu-22.04
    timeout-minutes: 60

    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0

      - name: Use Node.js 24
        uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
        with:
          node-version: 24.x
          registry-url: "https://registry.npmjs.org"

      - name: Use Python 3.13
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: "3.13"

      - name: Export build variables
        shell: bash
        run: |
          THEIA_VERSION=next
          echo "THEIA_VERSION=${THEIA_VERSION}" >> $GITHUB_ENV
          yarn version --minor --no-git-tag-version
          IDE_VERSION=$(jq -r .version package.json)
          echo "THEIA_IDE_VERSION=${IDE_VERSION}-next-$(date +%Y-%m-%d)" >> $GITHUB_ENV

      - name: Build next package
        shell: bash
        run: |
          yarn --skip-integrity-check --network-timeout 100000
          yarn version --new-version $THEIA_IDE_VERSION --no-git-tag-version
          yarn lerna version $THEIA_IDE_VERSION --no-push --no-git-tag-version --yes
          yarn update:theia $THEIA_VERSION && yarn update:theia:children $THEIA_VERSION
          yarn --skip-integrity-check --network-timeout 100000
          yarn build:extensions
          yarn build:applications:next
          yarn download:plugins
          yarn package:applications:next
        env:
          NODE_OPTIONS: --max_old_space_size=4096
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Test (Linux)
        run: xvfb-run -a yarn --cwd applications/electron-next test

      - name: Upload Linux Dist Files
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
        with:
          name: theia-ide-next-linux
          path: |
            applications/electron-next/dist/TheiaIDENext.AppImage
          retention-days: 7

      - name: Publish to rolling next release
        shell: bash
        run: |
          # Delete existing next release if present
          gh release delete next --yes --cleanup-tag 2>/dev/null || true
          # Create a new pre-release with the next tag
          gh release create next \
            --title "Next Build - Ubuntu AppImage (${{ env.THEIA_IDE_VERSION }})" \
            --notes "Automated next build of the Ubuntu AppImage from \`master\` ($(date -u '+%Y-%m-%d %H:%M UTC'))." \
            --prerelease \
            --target ${{ github.sha }} \
            applications/electron-next/dist/TheiaIDENext.AppImage \
            applications/electron-next/dist/latest-linux.yml
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/build-next.yml
================================================
name: Build Theia IDE next version

on:
  workflow_dispatch:
  schedule:
    - cron: "0 3 * * 1" # Runs every monday at 3am
jobs:
  build:
    name: Build ${{ matrix.os }} next
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-22.04, macos-15, macos-15-intel, windows-2022] # macos-15-intel is for x64, macOS-15 is for arm64

    runs-on: ${{ matrix.os }}
    timeout-minutes: 60

    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0 # To fetch all history for all branches and tags. (Will be required for caching with lerna: https://github.com/markuplint/markuplint/pull/111)

      - name: Use Node.js 24
        uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
        with:
          node-version: 24.x
          registry-url: "https://registry.npmjs.org"

      - name: Use Python 3.11
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: "3.13"

      - name: Export build variables
        shell: bash
        run: |
          THEIA_VERSION=next
          echo "THEIA_VERSION=${THEIA_VERSION}" >> $GITHUB_ENV
          yarn version --minor --no-git-tag-version
          echo "THEIA_IDE_VERSION=$(jq -r .version package.json)-${THEIA_VERSION}-$(date +%d-%m-%y)" >> $GITHUB_ENV

      - name: Update electron-builder.yml for macos-15
        if: matrix.os == 'macos-15'
        run: |
          sed -i '' 's|https://download.eclipse.org/theia/ide/latest/macos|https://download.eclipse.org/theia/ide/latest/macos-arm|g' applications/electron/electron-builder.yml

      - name: Build prod package
        shell: bash
        run: |
          yarn --skip-integrity-check --network-timeout 100000
          yarn version --new-version $THEIA_IDE_VERSION --no-git-tag-version
          yarn lerna version $THEIA_IDE_VERSION --no-push --no-git-tag-version --yes
          yarn update:theia $THEIA_VERSION && yarn update:theia:children $THEIA_VERSION
          yarn --skip-integrity-check --network-timeout 100000
          yarn build
          yarn download:plugins
          yarn package:applications
        env:
          NODE_OPTIONS: --max_old_space_size=4096
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9

      - name: Rename AppImage with version
        if: runner.os == 'Linux'
        run: |
          mv applications/electron/dist/TheiaIDE.AppImage applications/electron/dist/TheiaIDE-$THEIA_IDE_VERSION.AppImage

      - name: Upload Linux Dist Files
        if: runner.os == 'Linux'
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
        with:
          name: theia-ide-next-linux
          path: |
            applications/electron/dist/TheiaIDE-${{ env.THEIA_IDE_VERSION }}.AppImage
          retention-days: 7

      - name: Upload Mac Dist Files
        if: runner.os == 'macOS'
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
        with:
          name: ${{ matrix.os == 'macos-15-intel' && 'theia-ide-next-mac-x64' || matrix.os == 'macos-15' && 'theia-ide-next-mac-arm64'}}
          path: applications/electron/dist/*.dmg
          retention-days: 7

      - name: Upload Windows Dist Files
        if: runner.os == 'Windows'
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
        with:
          name: theia-ide-next-windows
          path: applications/electron/dist/*.exe
          retention-days: 7


================================================
FILE: .github/workflows/build.yml
================================================
name: Build, package and test

on:
  push:
    branches:
      - master
    paths-ignore:
      - '**/*.md'
      - 'TheiaIDE logo/**'
  workflow_dispatch:
  pull_request:
    branches:
      - master
    paths-ignore:
      - '**/*.md'
      - 'TheiaIDE logo/**'
  schedule:
    - cron: "0 4 * * *" # Runs every day at 4am: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule

jobs:
  build:
    name: ${{ matrix.os }}, Node.js v${{ matrix.node }}

    strategy:
      fail-fast: false
      matrix:
        os: [windows-2022, ubuntu-22.04, macos-15, macos-15-intel] # macos-15-intel is for x64, macOS-15 is for arm64
        node: ["24.x"]

    runs-on: ${{ matrix.os }}
    timeout-minutes: 60

    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0 # To fetch all history for all branches and tags. (Will be required for caching with lerna: https://github.com/markuplint/markuplint/pull/111)

      - name: Use Node.js ${{ matrix.node }}
        uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
        with:
          node-version: ${{ matrix.node }}
          registry-url: "https://registry.npmjs.org"

      - name: Use Python 3.13
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: "3.13"

      - name: Install dependencies
        shell: bash
        run: yarn --skip-integrity-check --network-timeout 100000
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Lint
        shell: bash
        run: yarn lint

      - name: Build dev package (Windows, Linux)
        if: (runner.os == 'Windows' || runner.os == 'Linux') && github.event_name == 'pull_request'
        shell: bash
        run: |
          yarn build:dev
          yarn download:plugins
          yarn package:applications:preview
        env:
          NODE_OPTIONS: --max_old_space_size=4096
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9

      - name: Build prod package (Windows, Linux)
        if: (runner.os == 'Windows' || runner.os == 'Linux') && github.event_name != 'pull_request'
        shell: bash
        run: |
          yarn build
          yarn download:plugins
          yarn package:applications
        env:
          NODE_OPTIONS: --max_old_space_size=4096
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9

      - name: Update electron-builder.yml for macos-15
        if: matrix.os == 'macos-15'
        run: |
          sed -i '' 's|https://download.eclipse.org/theia/ide/latest/macos|https://download.eclipse.org/theia/ide/latest/macos-arm|g' applications/electron/electron-builder.yml

      - name: Build prod package (Mac)
        if: runner.os == 'macOS'
        shell: bash
        run: |
          yarn build
          yarn download:plugins
          yarn package:applications
        env:
          NODE_OPTIONS: --max_old_space_size=4096
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/microsoft/vscode-ripgrep/issues/9

      - name: Upload Mac Dist Files
        if: runner.os == 'macOS'
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
        with:
          name: ${{ matrix.os == 'macos-15-intel' && 'mac-x64' || matrix.os == 'macos-15' && 'mac-arm64'}}
          path: |
            applications/electron/dist/**
            !applications/electron/dist/mac/**
            !applications/electron/dist/mac-arm64/**
          retention-days: 1

      - name: Upload Windows Dist Files
        if: runner.os == 'Windows' && github.event_name != 'pull_request'
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
        with:
          name: windows
          path: |
            applications/electron/dist/**
          retention-days: 1

      - name: Upload Linux Dist Files
        if: runner.os == 'Linux' && github.event_name != 'pull_request'
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
        with:
          name: linux
          path: |
            applications/electron/dist/**
          retention-days: 1

      - name: Test (Linux)
        if: runner.os == 'Linux'
        run: |
          xvfb-run -a yarn electron test

      - name: Test (Windows)
        if: runner.os == 'Windows'
        shell: bash
        run: |
          yarn electron test

      - name: Test (macOS)
        if: runner.os == 'macOS'
        shell: bash
        run: |
          yarn electron test

      - name: Upload test screenshots
        if: always()
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
        with:
          name: test-screenshots-${{ matrix.os }}
          path: applications/electron/test-screenshots/
          if-no-files-found: ignore
          retention-days: 5


================================================
FILE: .github/workflows/license-check-workflow.yml
================================================
name: 3PP License Check

on:
  push:
    branches:
      - master
    paths:
      - 'yarn.lock'
  workflow_dispatch:
  pull_request:
    branches:
      - master
    paths:
      - 'yarn.lock'
  schedule:
    - cron: '0 4 * * *' # Runs every day at 4am: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule

jobs:
  License-check:
    name: 3PP License Check using dash-licenses

    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest]
        node: [24]
        java: [17]

    runs-on: ${{ matrix.os }}
    timeout-minutes: 60

    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 2

      - name: Use Node.js ${{ matrix.node }}
        uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
        with:
          node-version: ${{ matrix.node }}

      - name: Use Java ${{ matrix.java }}
        uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
        with:
          distribution: 'adopt'
          java-version: ${{ matrix.java }}
      
      - name: Run daily dash-licenses check (non-review mode)
        if: ${{ github.event_name == 'schedule' }}
        shell: bash
        run: |
          yarn --frozen-lockfile --ignore-scripts
          # Workaround: pre-download dash-licenses JAR (see comments in step below)
          DASH_JAR="node_modules/@eclipse-dash/nodejs-wrapper/download/dash-licenses.jar"
          mkdir -p "$(dirname "$DASH_JAR")"
          SNAP_BASE="https://repo.eclipse.org/repository/dash-maven2-snapshots/org/eclipse/dash/org.eclipse.dash.licenses/1.1.1-SNAPSHOT"
          SNAP_JAR=$(curl -s "$SNAP_BASE/maven-metadata.xml" | grep -oP '(?<=<value>)1\.1\.1-[^<]+' | tail -1)
          curl -L "$SNAP_BASE/org.eclipse.dash.licenses-$SNAP_JAR.jar" -o "$DASH_JAR"
          yarn license:check

      - name: Run dash-licenses check in review mode
        if: ${{ github.event_name != 'schedule' }}
        shell: bash
        run: |
          yarn --frozen-lockfile --ignore-scripts
          # Workaround: pre-download dash-licenses JAR since the @eclipse-dash/nodejs-wrapper
          # uses a broken Nexus 2 URL after the repo.eclipse.org upgrade to Nexus 3.
          # We use 1.1.1-SNAPSHOT because 1.0.2 and 1.1.0 incorrectly flag internal
          # workspace packages (link:true with no version) as restricted.
          # See: https://github.com/eclipse-dash/nodejs-wrapper/issues/7
          # See: https://github.com/eclipse-dash/dash-licenses/issues/534
          # TODO: remove this workaround once the nodejs-wrapper is updated (GH-17168)
          DASH_JAR="node_modules/@eclipse-dash/nodejs-wrapper/download/dash-licenses.jar"
          mkdir -p "$(dirname "$DASH_JAR")"
          SNAP_BASE="https://repo.eclipse.org/repository/dash-maven2-snapshots/org/eclipse/dash/org.eclipse.dash.licenses/1.1.1-SNAPSHOT"
          SNAP_JAR=$(curl -s "$SNAP_BASE/maven-metadata.xml" | grep -oP '(?<=<value>)1\.1\.1-[^<]+' | tail -1)
          curl -L "$SNAP_BASE/org.eclipse.dash.licenses-$SNAP_JAR.jar" -o "$DASH_JAR"
          yarn license:check:review
        env:
          DASH_TOKEN: ${{ secrets.DASH_LICENSES_PAT }}

================================================
FILE: .github/workflows/publish-builder-img.yml
================================================
name: Publish builder image

on:
  schedule:
    - cron: "0 0 1 * *" # runs 1st day of every month
  workflow_dispatch:

jobs:
  build:
    name: Build and push builder image to Docker Hub
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # 4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      
      - name: Build and push Docker image
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
        with:
          context: .
          push: true
          tags: eclipsetheia/theia-blueprint:builder

================================================
FILE: .github/workflows/publish-theia-ide-img.yml
================================================
name: Publish Theia IDE Docker Image

on:
  workflow_dispatch:
    inputs:
      tag:
        description: The image's tag
        required: true
        default: next

jobs:
  build:
    name: Build and push Theia IDE image to Github Packages
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
        with:
          install: true
          driver: docker-container
          driver-opts: |
            image=moby/buildkit:latest
            network=host

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # 4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Log in to the Github Container registry
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # 4.1.0
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: List docker buildx available platforms
        shell: bash
        run: |
          docker buildx inspect --bootstrap
      
      - name: Build and push Docker image
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
        with:
          context: .
          file: browser.Dockerfile
          push: true
          tags: |
            ghcr.io/${{ github.repository }}/theia-ide:${{ github.event.inputs.tag }}
            ghcr.io/${{ github.repository }}/theia-ide:latest
          platforms: linux/amd64,linux/arm64


================================================
FILE: .gitignore
================================================
.DS_Store
**/node_modules
**/.browser_modules
**/dist
**/lib
**/src-gen
**/gen-webpack.config.js
**/gen-webpack.node.config.js
**/plugins
**/tsconfig.tsbuildinfo
*.log
license-check-summary.txt*
.theia-ide/chatSessions
.prompts
**/test-screenshots

================================================
FILE: .vscode/launch.json
================================================
{
  // Use IntelliSense to learn about possible Node.js debug attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "attach",
      "name": "Attach by Process ID",
      "processId": "${command:PickProcess}"
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Launch with Node.js",
      "program": "${file}"
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Electron Backend",
      "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
      "windows": {
        "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
      },
      "cwd": "${workspaceFolder}/applications/electron",
      "protocol": "inspector",
      "args": [
        "scripts/theia-electron-main.js",
        "--log-level=debug",
        "--hostname=localhost",
        "--no-cluster",
        "--app-project-path=${workspaceFolder}/applications/electron",
        "--remote-debugging-port=9222",
        "--no-app-auto-install",
        "--plugins=local-dir:../../plugins"
      ],
      "env": {
        "NODE_ENV": "development"
      },
      "sourceMaps": true,
      "outFiles": [
        "${workspaceFolder}/applications/electron/src-gen/**/*.js",
        "${workspaceFolder}/applications/electron/lib/**/*.js",
        "${workspaceFolder}/theia-extensions/*/lib/**/*.js",
        "${workspaceFolder}/node_modules/@theia/*/lib/**/*.js"
      ],
      "smartStep": true,
      "internalConsoleOptions": "openOnSessionStart",
      "outputCapture": "std"
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Browser Backend",
      "program": "${workspaceFolder}/applications/browser/lib/backend/main.js",
      "cwd": "${workspaceFolder}/applications/browser",
      "args": [
        "--hostname=0.0.0.0",
        "--port=3000",
        "--no-cluster",
        "--app-project-path=${workspaceFolder}/applications/browser",
        "--plugins=local-dir:../../plugins",
        "--log-level=debug"
      ],
      "env": {
        "NODE_ENV": "development"
      },
      "sourceMaps": true,
      "outFiles": [
        "${workspaceFolder}/applications/browser/src-gen/**/*.js",
        "${workspaceFolder}/applications/browser/lib/**/*.js",
        "${workspaceFolder}/theia-extensions/**/lib/**/*.js",
        "${workspaceFolder}/node_modules/@theia/*/lib/**/*.js"
      ],
      "smartStep": true,
      "internalConsoleOptions": "openOnSessionStart",
      "outputCapture": "std"
    },
    {
      "type": "node",
      "request": "attach",
      "name": "Attach to Plugin Host",
      "port": 9339,
      "timeout": 60000,
      "stopOnEntry": false,
      "smartStep": true,
      "sourceMaps": true,
      "internalConsoleOptions": "openOnSessionStart",
      "outFiles": [
        "${workspaceFolder}/plugins/**/*.js"
      ]
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Browser Backend (eclipse.jdt.ls)",
      "program": "${workspaceFolder}/applications/browser/lib/backend/main.js",
      "cwd": "${workspaceFolder}/applications/browser",
      "args": [
        "--hostname=0.0.0.0",
        "--port=3000",
        "--no-cluster",
        "--root-dir=${workspaceFolder}/../eclipse.jdt.ls/org.eclipse.jdt.ls.core",
        "--app-project-path=${workspaceFolder}/applications/browser",
        "--plugins=local-dir:../../plugins",
        "--log-level=debug",
        "--no-app-auto-install"
      ],
      "env": {
        "NODE_ENV": "development"
      },
      "sourceMaps": true,
      "outFiles": [
        "${workspaceFolder}/applications/browser/src-gen/**/*.js",
        "${workspaceFolder}/applications/browser/lib/**/*.js",
        "${workspaceFolder}/theia-extensions/**/lib/**/*.js",
        "${workspaceFolder}/node_modules/@theia/*/lib/**/*.js"
      ],
      "smartStep": true,
      "internalConsoleOptions": "openOnSessionStart",
      "outputCapture": "std"
    },
    {
      "type": "node",
      "request": "launch",
      "protocol": "inspector",
      "name": "Run Mocha Tests",
      "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
      "args": [
        "--no-timeouts",
        "--colors",
        "--opts",
        "${workspaceFolder}/configs/mocha.opts",
        "**/${fileBasenameNoExtension}.js"
      ],
      "env": {
        "TS_NODE_PROJECT": "${workspaceFolder}/tsconfig.json"
      },
      "sourceMaps": true,
      "smartStep": true,
      "internalConsoleOptions": "openOnSessionStart",
      "outputCapture": "std"
    },
    {
      "name": "Launch Browser Frontend",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3000/",
      "webRoot": "${workspaceFolder}/applications/browser"
    },
    {
      "type": "chrome",
      "request": "attach",
      "name": "Attach to Electron Frontend",
      "port": 9222,
      "webRoot": "${workspaceFolder}/applications/electron"
    },
    {
      "name": "Launch VS Code Tests",
      "type": "node",
      "request": "launch",
      "args": [
        "${workspaceFolder}/applications/browser/lib/backend/main.js",
        "${workspaceFolder}/plugins/vscode-api-tests/testWorkspace",
        "--port",
        "3030",
        "--hostname",
        "0.0.0.0",
        "--extensionTestsPath=${workspaceFolder}/plugins/vscode-api-tests/out/singlefolder-tests",
        "--hosted-plugin-inspect=9339"
      ],
      "env": {
        "THEIA_DEFAULT_PLUGINS": "local-dir:${workspaceFolder}/plugins"
      },
      "stopOnEntry": false,
      "sourceMaps": true,
      "outFiles": [
        "${workspaceFolder}/../.js"
      ]
    }
  ],
  "compounds": [
    {
      "name": "Launch Electron Backend & Frontend",
      "configurations": [
        "Launch Electron Backend",
        "Attach to Plugin Host",
        "Attach to Electron Frontend"
      ],
      "stopAll": true
    },
    {
      "name": "Launch Browser Backend & Frontend",
      "configurations": [
        "Launch Browser Backend",
        "Attach to Plugin Host",
        "Launch Browser Frontend"
      ],
      "stopAll": true
    }
  ]
}

================================================
FILE: .vscode/settings.json
================================================
{
    "[markdown]": {
        "editor.defaultFormatter": "davidanson.vscode-markdownlint"
    }
}

================================================
FILE: .vscode/theia.code-snippets
================================================
{
    "Copyright-JS/JSX/TS/TSX/CSS": {
        "prefix": [
            "header",
            "copyright"
        ],
        "body": "/********************************************************************************\n * Copyright (C) $CURRENT_YEAR ${YourCompany} and others.\n *\n * This program and the accompanying materials are made available under the\n * terms of the MIT License, which is available in the project root.\n *\n * SPDX-License-Identifier: MIT\n ********************************************************************************/\n\n$0",
        "description": "Adds the copyright...",
        "scope": "javascript,javascriptreact,typescript,typescriptreact,css"
    }
}


================================================
FILE: ADOPTER.md
================================================
# Adopter Guide

This repository serves as a template for building desktop products on the [Eclipse Theia platform](https://theia-ide.org). This guide documents packaging considerations when building your own Theia based applications.

## Electron Packaging and Asar

Electron applications may use [asar archives](https://github.com/electron/asar) to package application source files into a single read only archive. This improves startup performance and avoids path length issues on Windows.

In this repository, asar packaging is enabled via `asar: true` in `applications/electron/electron-builder.yml`. When the application is packaged with `electron-builder`, the contents of the app directory are bundled into an `app.asar` file inside the packaged application's `resources/` folder.

Code that uses `__dirname` to access files, or executes scripts from the filesystem, will fail because asar archives are not real directories. At runtime, `__dirname` resolves to a path inside `app.asar`, but Node's `fs` module and the OS cannot access files inside the archive as regular filesystem entries.

Two categories of files are typically affected:

1. **Native binaries**, `.node` files or prebuilt binaries
2. **Scripts and resources** that must be accessible on the real filesystem

### Mitigation Strategies

#### 1. asarUnpack (electron-builder.yml)

Files matching `asarUnpack` glob patterns are automatically extracted alongside the asar archive during packaging. At runtime, these files live under `app.asar.unpacked/` instead of `app.asar/`.

For example:

```yaml
asarUnpack:
  - "**/lib/backend/native/**"
  - "**/lib/backend/shell-integrations/**"
  - "**/lib/build/Release/**"
  - "**/lib/prebuilds/**"
```

`asarUnpack` only extracts the files to the real filesystem. Code that resolves paths using `__dirname` will still get a path containing `app.asar`, so it must also handle the `.asar.unpacked` path segment for the files to be found.

#### 2. patch-package

When upstream code in `node_modules` needs modification, for example to adjust paths, [patch-package](https://github.com/ds300/patch-package) can apply source level patches after `yarn install`.

* Patches live in the `patches` directory at the repository root
* Patches are applied automatically via the `postinstall` script in `package.json`

#### 3. Webpack Post Processing

Another option is to adjust the bundled code in Webpack.

As an example, the `PatchRipgrepPlugin` in `applications/electron/webpack.config.js` patches the bundled `main.js` after webpack emit to rewrite ripgrep's path resolution from `.asar` to `.asar.unpacked`:

```js
class PatchRipgrepPlugin {
    apply(compiler) {
        compiler.hooks.afterEmit.tapAsync('PatchRipgrepPlugin', (compilation, callback) => {
            // Reads main.js, finds the ripgrep path assignment, and rewrites
            // .asar + path.sep → .asar.unpacked + path.sep
            // ...
        });
    }
}
```


================================================
FILE: CODE_OF_CONDUCT.md
================================================
<div id="theia-logo" align="left">
    <br />
    <img src="https://raw.githubusercontent.com/eclipse-theia/theia/master/logo/EF_GRY-OR_svg.svg?sanitize=true" alt="Eclipse Logo" width="300"/>
</div>

# Community Code of Conduct

Version 1.1

October 21, 2019

## Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment include:

- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at codeofconduct@eclipse.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq

<div id="theia-logo" align="left">
    <br />
    <img src="https://www.eclipse.org/images/Eclipse_Code_of_Conduct.png" alt="Eclipse Logo" width="150"/>
</div>

----
Note: Please see [here](https://www.eclipse.org/org/documents/Community_Code_of_Conduct.php) for the latest version of this document, hosted at the Eclipse Foundation


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Eclipse Theia

Theia is a young open-source project with a modular architecture. One of the
goals is to make sure that we can customize and enhance any Theia application
through extensions.  So while the main Theia repository contains some common
functionality for IDE-like applications, like a file system or a navigator
view, most functionality doesn't necessarily need to be put into the core
repository but can be developed separately.

## How Can I Contribute?

In the following some of the typical ways of contribution are described.

### Asking Questions

It's totally fine to ask questions by opening an issue in the Theia GitHub
repository. We will close it once it's answered and tag it with the 'question'
label. Please check if the question has been asked before there or on [Stack
Overflow](https://stackoverflow.com).

### Reporting Bugs

If you have found a bug, you should first check if it has already been filed
and maybe even fixed. If you find an existing unresolved issue, please add your
case. If you could not find an existing bug report, please file a new one. In
any case, please add all information you can share and that will help to
reproduce and solve the problem.

### Reporting Feature Requests

You may want to see a feature or have an idea. You can file a request and we
can discuss it.  If such a feature request already exists, please add a comment
or some other form of feedback to indicate you are interested too. Also in this
case any concrete use case scenario is appreciated to understand the motivation
behind it.

### Pull Requests

Before you get started investing significant time in something you want to get
merged and maintained as part of Theia, you should talk with the team through
an issue. Simply choose the issue you would want to work on, and tell everyone
that you are willing to do so and how you would approach it. The team will be
happy to guide you and give feedback.

We follow the contributing and reviewing pull request guidelines described
[here](https://github.com/eclipse-theia/theia/blob/master/doc/pull-requests.md).

## Coding Guidelines

We follow the coding guidelines described
[here](https://github.com/eclipse-theia/theia/wiki/Coding-Guidelines).

## Eclipse Contributor Agreement

Before your contribution can be accepted by the project team contributors must
electronically sign the Eclipse Contributor Agreement (ECA).

* https://www.eclipse.org/legal/ECA.php

Commits that are provided by non-committers must have a Signed-off-by field in
the footer indicating that the author is aware of the terms by which the
contribution has been provided to the project. The non-committer must
additionally have an Eclipse Foundation account and must have a signed Eclipse
Contributor Agreement (ECA) on file.

For more information, please see the Eclipse Committer Handbook:
https://www.eclipse.org/projects/handbook/#resources-commit

## Sign your work

The sign-off is a simple line at the end of the explanation for the patch. Your
signature certifies that you wrote the patch or otherwise have the right to
pass it on as an open-source patch. The rules are pretty simple: if you can
certify the below (from
[developercertificate.org](https://developercertificate.org/)):

```
Developer Certificate of Origin
Version 1.1

Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
1 Letterman Drive
Suite D4700
San Francisco, CA, 94129

Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.

Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.
```

Then you just add a line to every git commit message:

    Signed-off-by: Joe Smith <joe.smith@email.com>

Use your real name (sorry, no pseudonyms or anonymous contributions.)

If you set your `user.name` and `user.email` git configs, you can sign your
commit automatically with `git commit -s`.


================================================
FILE: Dockerfile
================================================
# See the associated GitHub workflow, that builds and publishes
# this docker image to Docker Hub:
# .github/workflows/publish-builder-img.yml
# It can be triggered manually from the GitHub project page. 

# We want to support as many Debian versions as possible.
# Therefore, use the oldest Debian release that still provides the desired Node.js version.
FROM node:24-bookworm
RUN dpkg --add-architecture i386 \
 && apt-get update \
 && apt-get install -y --no-install-recommends \
      libxkbfile-dev libsecret-1-dev python3 \
      wine wine32 wine64 \
 && rm -rf /var/lib/apt/lists/*

# UID-agnostic wine tuning. WINEPREFIX is intentionally NOT set here; callers
# must provide a writable path owned by the runtime user.
ENV WINEDLLOVERRIDES="mscoree=;mshtml=" \
    WINEDEBUG=-all


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

Copyright (c) 2020 Eclipse Theia IDE Authors

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

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

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


================================================
FILE: NOTICE.md
================================================
# Notices for Eclipse Theia

This content is produced and maintained by the Eclipse Theia project.

* Project home: https://projects.eclipse.org/projects/ecd.theia

## Trademarks

Eclipse Theia is a trademark of the Eclipse Foundation.

## Copyright

All content is the property of the respective authors or their employers. For
more information regarding authorship of content, please consult the listed
source code repository logs.

## Declared Project Licenses

This program and the accompanying materials are made available under the terms
of the MIT License which is available at https://opensource.org/license/mit/.

SPDX-License-Identifier: MIT

## Source Code

The project maintains the following source code repositories:

* https://github.com/eclipse/theia-generator-plugin
* https://github.com/eclipse/theia-yeoman-plugin
* https://github.com/eclipse/theia-plugin-packager
* https://github.com/eclipse/theia-cpp-extension
* https://github.com/eclipse/theia-python-extension
* https://github.com/eclipse/theia-java-extension

## Third-party Content

This project leverages the following third party content.

chalk (2.4.1)

* License: MIT
* Project: https://github.com/chalk/chalk
* Source: https://github.com/chalk/chalk

code copied from project cortex-debug (0.1.21)

* License: MIT

Code copied from project Microsoft/vscode (1.31.0)

* License: MIT

Code copied from project Microsoft/vscode (1.32.3)

* License: MIT
* Project: https://code.visualstudio.com/
* Source: https://github.com/Microsoft/vscode

Code copied from project Microsoft/vscode (1.33.1)

* License: MIT

code copied from project microsoft/vscode (1.33.1)

* License: MIT

Code copied from VSCode (n/a)

* License: MIT

Copied code from project VSCode (n/a)

* License: MIT

CSS copied from VS Code (n/a)

* License: MIT

dugite (1.52.0)

* License: MIT

Electron (3.1.7)

* License: BSD-2-Clause AND BSD-3-Clause AND (MIT OR GPL-2.0) AND Apache-2.0
   AND (BSD-2-Clause OR MIT OR Apache-2.0) AND ISC AND MIT AND X11 AND
   BSD-2-Clause-FreeBSD AND Public-Domain AND Unlicense AND MPL-2.0 AND
   (BSD-3-Clause OR MPL-2.0) AND CC-BY-3.0 AND (AFL-2.0
* Project: https://electronjs.org/
* Source: https://github.com/electron/electron

electron@2.0.14 (2.0.14)

* License: MIT AND BSD-2-Clause AND Apache-2.0 AND (AFL-2.1 OR BSD-3-Clause)
   AND BSD-3-Clause AND ISC AND X11 AND Public-Domain AND (GPL-2.0 OR MIT) AND
   Unlicense AND IJG AND ICU AND UNICODE-TOU AND NTP AND (MIT OR BSD-3-Clause)
   AND Libpng AND MPL-2.0 AND LGPL-2.1+
* Project: https://github.com/electron/electron
* Source: https://github.com/electron/electron/releases/tag/v2.0.14

getmac (1.4.6)

* License: MIT
* Project: https://github.com/bevry/getmac
* Source: https://github.com/bevry/getmac

GH-3397: Implemented the HTTP-based authentication for Git in Electron. (n/a)

* License: MIT

glob promise (3.4.0)

* License: ISC
* Project: https://github.com/ahmadnassri/glob-promise
* Source: https://github.com/ahmadnassri/glob-promise

Icon configure-inverse.svg (n/a)

* License: MIT
* Project: https://github.com/Microsoft/vscode
* Source:
   https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/contrib/tasks/common/media/configure-inverse.svg#L1

libffmpeg (FFmpeg) Delivered with Electron (3.1.7)

* License: LGPL-2.1+

long.js (3.2.0)

* License: Apache-2.0

micromatch (3.1.10)

* License: MIT
* Project: https://github.com/micromatch/micromatch
* Source: https://github.com/micromatch/micromatch

monaco-typescript (2.3.0)

* License: MIT
* Project: https://github.com/Microsoft/monaco-typescript
* Source: https://github.com/Microsoft/monaco-typescript.git

native-keymap (1.2.5)

* License: Pending
* Project: https://github.com/Microsoft/node-native-keymap
* Source: https://github.com/Microsoft/node-native-keymap

node-oniguruma (n/a)

* License: BSD-2-Clause AND GPL-2.0 WITH Autoconf-exception-2.0 AND
   GPL-2.0-or-later WITH libtool-exception AND X11 AND MIT AND Public-Domain

node.js dependencies for Theia (n/a)

* License: MIT AND BSD-3-Clause AND ISC AND Apache-2.0 AND BSD-2-Clause AND
   Zlib AND X11 AND (BSD-3-Clause OR AFL-2.1) AND CC-By-4.0 AND CC-by-2.5-SA AND
   CC0-1.0 AND (BSD-3-Clause OR MPL-2.0) AND Unlicense AND (MIT OR GPL-3.0) AND
   (MIT OR GPL-2.0) AND (Apache-2.0 OR

ps-list (5.0.1)

* License: MIT
* Project: https://github.com/sindresorhus/ps-list
* Source: https://github.com/sindresorhus/ps-list

read-pkg (4.0.1)

* License: MIT
* Project: https://github.com/sindresorhus/read-pkg
* Source: https://github.com/sindresorhus/read-pkg

regular expressions and helper function copied from microsoft/vscode (1.33.1)

* License: MIT

requestretry (3.1.0)

* License: MIT
* Project: https://github.com/FGRibreau/node-request-retry
* Source: https://github.com/FGRibreau/node-request-retry

rimraf (2.6.2)

* License: ISC

textmate/tcl.tmbundle (n/a)

* License: LicenseRef-Php_Tmbundle

theia npm node (n/a)

* License: BSD-2-Clause OR (MIT OR Apache-2.0) AND (AFL-2.1 OR BSD-3-Clause)
   AND Apache-2.0 AND Artistic-2.0 AND BSD-3-Clause AND (BSD-3-Clause OR MIT)
   AND MPL-2.0 AND CC0-1.0 AND CC-BY-3.0 AND CC-BY-4.0 AND CC-BY-SA-2.5 AND
   GPL-2.0 WITH Autoconf-ex

theia-cpp-extension npm node (n/a)

* License: BSD-2-Clause OR (MIT OR Apache-2.0) AND MIT AND BSD-3-Clause AND
   Zlib AND (MIT OR GPL-3.0) AND OFL-1.1 AND Apache-2.0 AND CC0-1.0 AND
   CC-BY-3.0 AND ISC AND MPL-2.0 AND License-Ref-Public-Domain AND BSL-1.0 AND
   (AFL-2.1 OR BSD-3.0) AND Unlicense AND Artist

tslint (5.10.0)

* License: Apache-2.0 AND MIT
* Project: http://palantir.github.io/tslint/
* Source: https://github.com/palantir/tslint

typefox/monaco-language-client (0.5.0)

* License: MIT

typescript-formatter (7.2.2)

* License: MIT
* Project: https://github.com/vvakame/typescript-formatter
* Source: https://github.com/vvakame/typescript-formatter

VS Code (1.33.0)

* License: MIT

vscode (1.26.0)

* License: MIT AND LicenseRef-Php_Tmbundle

vscode (1.26.0)

* License: MIT

vscode (1.31.0)

* License: MIT

vscode-debugadapter-node (n/a)

* License: MIT

vscode-java (0.36.0)

* License: EPL-1.0

vscode-java (0.44.0)

* License: EPL-1.0

vscode-java-debug (0.15.0)

* License: MIT

when (3.7.8)

* License: MIT
* Project: https://github.com/cujojs/when
* Source: https://github.com/cujojs/when

wjordan/browser-path SHA6719d19077b1454bff8b802f9be79cb1b69ebe7e (n/a)

* License: MIT

xterm.js (3.9.1)

* License: MIT
* Project: https://xtermjs.org/
* Source: https://github.com/xtermjs/xterm.js

yargs (12.0.1)

* License: MIT
* Project: http://yargs.js.org/
* Source: https://github.com/yargs/yargs

yeoman environment (2.3.0)

* License: BSD-2-Clause AND BSD-3-Clause
* Project: https://github.com/yeoman/environment
* Source: https://github.com/yeoman/environment

yeoman generator (3.0.0)

* License: BSD-2-Clause AND BSD-3-Clause
* Project: http://yeoman.io
* Source: https://github.com/yeoman/generator

yeoman-generator (2.0)

* License: BSD-2-Clause
* Project: http://yeoman.io/
* Source: https://github.com/yeoman/generator

yosay (2.0.2)

* License: BSD-2-Clause
* Project: https://github.com/yeoman/yosay
* Source: https://github.com/yeoman/yosay

## Cryptography

Content may contain encryption software. The country in which you are currently
may have restrictions on the import, possession, and use, and/or re-export to
another country, of encryption software. BEFORE using any encryption software,
please check the country's laws, regulations and policies concerning the import,
possession, or use, and re-export of encryption software, to see if this is
permitted.


## Electron

NOTICE:

Please note Electron combines Chromium and Node.js into a single runtime.
While Electron, Chromium and Node.js are generally licensed under very
permissive MIT and BSD-3-Clause licenses, both Electron and Chromium distribute
FFmpeg.  While FFmpeg is under the LGPL-2.1-or-later license it incorporates
several optional parts and optimizations that are covered by the
GPL-2.0-or-later.  We understand both Electron and Chromium do not distribute
versions of FFmpeg with GPL content enabled; however, FFmpeg may be configured
enabled to work with proprietary codecs.  It is our understanding these
proprietary codecs may be patented; and as a result, may be subject to
licensing fees.

We strongly recommend downstream consumers verify the type of FFmpeg support
configured and modify as required.  More information on instructions to verify
can be found here
https://electronjs.org/docs/development/upgrading-chromium#verify-ffmpeg-support




================================================
FILE: PUBLISHING.md
================================================
# Publishing Guide for the Eclipse Theia IDE

This document provides a unified, structured guide for publishing a new version of the Theia IDE. It covers everything from updating package versions, preview testing, releasing, promoting to stable, and other post-release activities.

## Table of Contents

1. [Overview](#1-overview)
2. [Update Package Versions and Theia](#2-update-package-versions-and-theia)
   - [2.1 Install build dependencies](#21-install-build-dependencies)
   - [2.2 Update versions](#22-update-versions)
   - [2.3 Check for mandatory code changes](#23-check-for-mandatory-code-changes)
   - [2.4 Prepare Release PR](#24-prepare-release-pr)
   - [2.5 Mac Artifacts](#25-mac-artifacts)
   - [2.6 Merge Release PR & Trigger Jenkins Build](#26-merge-release-pr--trigger-jenkins-build)
3. [Preview, Testing, and Release Process](#3-preview-testing-and-release-process)
   - [3.1 Confirm the new preview version is published](#31-confirm-the-new-preview-version-is-published-do-not-promote-as-stable-yet)
   - [3.2 Announce Preview Test Phase](#32-announce-preview-test-phase)
   - [3.3 Patch Releases](#33-patch-releases)
4. [Promote IDE from Preview to Stable Channel](#4-promote-ide-from-preview-to-stable-channel)
5. [Tag the Release Commit](#5-tag-the-release-commit)
6. [Publish Docker Image](#6-publish-docker-image)
7. [Snap Update](#7-snap-update)
8. [Upgrade Dependencies](#8-upgrade-dependencies)

## 1. Overview
<!-- release: both -->

Every commit to the master branch is automatically published as a preview version. Official updates require a version change.

This guide differentiates between two version numbers:

- **THEIA_VERSION**: (used variable: {{version}}) The version of Theia used in this release.
- **THEIA_IDE_VERSION**: (used variable: {{ideVersion}}) The Theia IDE release version. Depending on the context:
  - If there was **no** Theia release, increment the patch version by 1 (e.g., 1.47.0 -> 1.47.1 or 1.47.100 -> 1.47.101).
  - For a new Theia *minor* release (e.g., 1.48.0), use the same version as Theia.
  - For a new Theia *patch* release (e.g., 1.48.1), use Theia's patch version multiplied by 100 (e.g., 1.48.100).

## 2. Update Package Versions and Theia
<!-- release: both -->

Follow these steps to update dependencies and package versions:

### 2.1. Install build dependencies
<!-- release: both -->

```sh
yarn
```

### 2.2. Update versions
<!-- release: both -->

1. Update the monorepo version to **THEIA_IDE_VERSION** (without creating a Git tag):

   ```sh
   yarn version --no-git-tag-version --new-version {{ideVersion}}
   ```

2. Optional: If there is a new Theia release to consume, update Theia dependencies to **THEIA_VERSION** :

   ```sh
   yarn update:theia {{version}} && yarn update:theia:children {{version}}
   ```

3. Update all package versions to **THEIA_IDE_VERSION** (select in input prompt):

   ```sh
   yarn lerna version --exact --no-push --no-git-tag-version
   ```

4. Update the yarn lock file:

   ```sh
   yarn
   ```

### 2.3. Check for mandatory code changes
<!-- release: both -->

Update the code to include everything that should be part of the release:

- Implement all tickets that are located in: <https://github.com/eclipse-theia/theia-ide/labels/toDoWithRelease>
- If there was a Theia release:
  - Review breaking changes
  - Check for new built-ins
  - Check sample applications changes
  - Update code as necessary
  - Check for new theia packages to be consumed in the example applications (in case there are no tickets)

### 2.4. Prepare Release PR
<!-- release: both -->

After completing step 2.3, open a PR with your changes <https://github.com/eclipse-theia/theia-ide/compare>

   PR Title:

   ```md
   Update to Theia v{{version}}
   ```

   OR (if it is a pure Theia IDE version update):

   ```md
   Publish Theia IDE {{ideVersion}}
   ```

### 2.5. Mac Artifacts
<!-- release: both -->

- The PR will trigger a verification build that generates two zip files with mac artifacts.
- Download these two zips and replace them in this pre-release: <https://github.com/eclipse-theia/theia-ide/releases/tag/pre-release>.
- These unsigned dmgs will be used as input for the Jenkins build.

### 2.6. Merge Release PR & Trigger Jenkins Build
<!-- release: both -->

1. Merge PR

2. ==> Steps 2.4 and 2.5 need to be complete to proceed!

3. Once [CI checks after merge to master are complete](https://github.com/eclipse-theia/theia-ide/actions), trigger the Jenkins Release Preview <https://ci.eclipse.org/theia/job/theia-ide-release/> job without parameters.

4. Once 3. is successful the notarize job <https://ci.eclipse.org/theia/job/theia-ide-sign-notarize/> is started automatically.

5. Once 4. is successful it starts the upload job <https://ci.eclipse.org/theia/job/theia-ide-upload/>

  *Note*: Please report if upload fails more than 5 times, we need to investigate!

## 3. Preview, Testing, and Release Process
<!-- release: both -->

Once the PR is merged and the preview build is created, follow these steps for testing and eventual release:

### 3.1 Confirm the new preview version is published (do not promote as stable yet)
<!-- release: both -->

- Check if uploaded versions are complete in in download folder <https://download.eclipse.org/theia/ide-preview/{{ideVersion}}/>
  - e.g. check if the latest files are correct and the artifacts are there (in doubt, compare to previous versions)

### 3.2 Announce Preview Test Phase
<!-- release: minor -->

### 3.2.1 GH Discussions
<!-- release: minor -->

- Use GitHub Discussions for the announcement in the [Category Release Announcements](https://github.com/eclipse-theia/theia/discussions/new?category=release-announcements).

   Title:

   ```md
   Theia IDE {{majorMinor}}.x Preview Testing
   ```

   Body:

   ```md
   The new version {{ideVersion}} of the Theia IDE is available on the preview channel now. Please join the preview testing!

   You can download it here:

   - [Linux](https://download.eclipse.org/theia/ide-preview/{{ideVersion}}/linux/TheiaIDE.AppImage)
   - [Mac x86](https://download.eclipse.org/theia/ide-preview/{{ideVersion}}/macos/TheiaIDE.dmg)
   - [Mac ARM](https://download.eclipse.org/theia/ide-preview/{{ideVersion}}/macos-arm/TheiaIDE.dmg)
   - [Windows](https://download.eclipse.org/theia/ide-preview/{{ideVersion}}/windows/TheiaIDESetup.exe)

   Update your existing installation by setting the preference `updates.channel` to `preview`.

   Please respond here when you can test the preview without finding blockers, by commenting with a ✔️.
   If you find any issues, please mention them in this thread and report them as an issue once confirmed by other testers.

   | Phase | Target | Status |
   |:---|:---|:---|
   | {{ideVersion}} preview available | {{releaseDate}} | :white_check_mark: |
   | {{ideVersion}} community preview window | {{previewStart}} → {{previewEnd}} | :hourglass_flowing_sand: |
   | Theia IDE {{majorMinor}}.x Promoted to Stable | {{previewEnd}} + 1 business day |  |
   | Docker image Publish | {{previewEnd}} + 1 business day |  |
   | Snap updated | {{previewEnd}} + 1 business day |  |
   ```

- Pin discussion to the Release Announcement Category

### 3.2.2 theia-dev mailing list
<!-- release: minor -->

- Announce the preview release via email to [the `theia-dev` mailing List](mailto:theia-dev@eclipse.org) with the following template:

   Subject:

   ```md
   Theia IDE {{majorMinor}}.x preview phase
   ```

   Body:

   ```md
   Hi everyone,

   Version {{ideVersion}} of the Theia IDE is now available on the preview channel. Please join the preview test and help us stabilize the release.
   Visit the preview discussion for more information and coordination: https://github.com/eclipse-theia/theia/discussions/{{discussionNumber}}
   ```

### 3.2.3 Eclipse Theia Release discussion
<!-- release: minor -->

- Announce the start of the Theia IDE Preview Test phase in the Theia Release announcement (`Eclipse Theia v{{version}}`) discussion (see <https://github.com/eclipse-theia/theia/discussions/categories/release-announcements>):

   ```md
   The preview test phase for the Theia IDE {{ideVersion}} has started. You can find the details here: 
   
   - https://github.com/eclipse-theia/theia/discussions/{{discussionNumber}}
   ```

### 3.2.4 Optional: Announcement to Theia IDE Preview Testers
<!-- release: minor -->

- Optional: Announce the start of the Theia IDE Preview Test phase to your testers (e.g., via Slack, Teams, E-Mail):

   ```md
   :theia: The Theia IDE preview {{ideVersion}} for Theia version {{version}} is now available!
   Please take a moment to test it and provide feedback - whether you've run into issues or everything works as expected. {{linkToNewPreviewComment}}

   To help us get a quick overview, please react with the emoji for your OS (:ubuntu:, :windows:, :mac_arm:, :mac_x64:) once you updated to the new version.
   Thanks!
   ```

### 3.3 Patch Releases
<!-- release: patch -->

- Address reported blockers and issue patch releases (this process may take 1–2 weeks).

   **Note:** If issues are persistent, or resources are insufficient, the release may be postponed to the next version.

- If a blocker was found add this status to the respective preview window:

   ```md
    :no_entry:  blocker was found 
   ```

### 3.3.1 Update Preview Discussion with new preview
<!-- release: patch -->

- For Patch Releases, use the [Preview discussion](#32-announce-preview-test-phase) and post a comment to announce the patch release of the Theia IDE: <https://github.com/eclipse-theia/theia/discussions/{{discussionNumber}}>

   ```md
   The new version {{ideVersion}} of the Theia IDE is available on the preview channel now. Please join the preview testing!

   You can download it here:

   - [Linux](https://download.eclipse.org/theia/ide-preview/{{ideVersion}}/linux/TheiaIDE.AppImage)
   - [Mac x86](https://download.eclipse.org/theia/ide-preview/{{ideVersion}}/macos/TheiaIDE.dmg)
   - [Mac ARM](https://download.eclipse.org/theia/ide-preview/{{ideVersion}}/macos-arm/TheiaIDE.dmg)
   - [Windows](https://download.eclipse.org/theia/ide-preview/{{ideVersion}}/windows/TheiaIDESetup.exe)

   Update your existing installation by setting the preference `updates.channel` to `preview`.

   Please respond here when you can test the preview without finding blockers, by commenting with a ✔️.
   If you find any issues, please mention them in this thread and report them as an issue once confirmed by other testers.
   ```

### 3.3.2 Update Preview Discussion Table
<!-- release: patch -->

- Adapt the target dates to the planned new preview window and final release dates
- Add comments in the status if necessary
- See example announcements here: <https://github.com/eclipse-theia/theia/discussions/16109>

- Update the discussion's status table with two rows for the current patch release:

   ```md
   | [{{ideVersion}} preview available]({{linkToNewPreviewComment}}) | {{previewStart}} | :white_check_mark: |
   | {{ideVersion}} community preview window | {{previewStart}} → {{previewEnd}} | :hourglass_flowing_sand: |
   ```

- Also adapt the target dates of the remaining entries in table (if not yet promoted)

### 3.3.3 Optional: Internal Slack announcement
<!-- release: patch -->

- Optional: Announce the start of the Theia IDE Preview Test phase in your internal Slack channel:

   ```md
   :theia: The Theia IDE preview {{ideVersion}} for Theia version {{version}} is now available!
   Please take a moment to test it and provide feedback - whether you've run into issues or everything works as expected. {{linkToNewPreviewComment}}

   To help us get a quick overview, please react with the emoji for your OS (:ubuntu:, :windows:, :mac_arm:, :mac_x64:) once you updated to the new version.
   Thanks!
   ```

## 3.4 Optional: Internal Slack - feedback reminder
<!-- release: both -->

- Optional: Schedule a slack reminder close to the preview end:

```md
Quick reminder: We're planning to promote the new IDE version (e.g., tomorrow/on Monday), please share your feedback for the preview {{ideVersion}}!
:point_right: https://github.com/eclipse-theia/theia/discussions/{{discussionNumber}}
Thanks! :thx:
```

## 4. Promote IDE from Preview to Stable Channel
<!-- release: both -->

Promote the IDE using the [Build Job](https://ci.eclipse.org/theia/job/Theia%20-%20Promote%20IDE/).

- Specify the release version in the `VERSION` parameter (e.g., 1.48.0), corresponding to the **THEIA_IDE_VERSION** copied from <https://download.eclipse.org/theia/ide-preview/>.

- Post a comment to announce the official release of the Theia IDE:

   ```md
   {{ideVersion}} has been promoted to stable
   ```

  - Update the [Base Preview discussion](#32-announce-preview-test-phase) status table with a checkmark and the version that has been published.

   ```md
   | [Theia IDE {{majorMinor}}.x Promoted to Stable](https://download.eclipse.org/theia/ide/1.67.100/) | {{today}} | :white_check_mark: |
   ```

  - Mark the message as the answer.

  - Unpin discussion from the Release Announcement Category.

## 5. Tag the Release Commit
<!-- release: both -->

After promoting the release, tag the release commit as follows:

1. Create the tag:

   ```bash
   git tag v{{ideVersion}} ${SHA of release commit}
   ```

2. Push the tag to the repository:

   ```bash
   git push origin v{{ideVersion}}
   ```

## 6. Publish Docker Image
<!-- release: both -->

Publish the Docker image by running the [workflow](https://github.com/eclipse-theia/theia-ide/actions/workflows/publish-theia-ide-img.yml) from the `master` branch. Use **${THEIA_IDE_VERSION}** as the version.
(We do NOT use the v prefix here in this case currently).

- Check the GH package page if the image was published correctly: <https://github.com/eclipse-theia/theia-ide/pkgs/container/theia-ide%2Ftheia-ide>

- Update the [Preview discussion](#32-announce-preview-test-phase) status table

   ```md
   | [Docker image Publish](https://github.com/eclipse-theia/theia-ide/pkgs/container/theia-ide%2Ftheia-ide) | {{today}} | :white_check_mark: |
   ```

## 7. Snap Update
<!-- release: both -->

Can be parallel to step 6.
After the IDE is promoted to stable, perform these steps for the snap update:

1. Run [this workflow](https://github.com/eclipse-theia/theia-ide-snap/actions/workflows/update.yml) from the `master` branch.
2. After the build succeeded, visit <https://github.com/eclipse-theia/theia-ide-snap/pulls> to find the PR that updates to **${THEIA_IDE_VERSION}**.
3. Check out the corresponding branch.
4. Amend the latest commit with your author details:

   ```bash
   git commit --amend --author="Your Name <name@example.com>"
   ```

5. Force push the branch.
6. Verify that all checks pass, and then `rebase and merge`.
7. Confirm the master branch build (Store Publishing) is successful.
8. Check if snap is available <https://snapcraft.io/theia-ide>
9. Update the [Preview discussion](#32-announce-preview-test-phase) status table

   ```md
   | [Snap updated](https://snapcraft.io/theia-ide) | {{today}} | :white_check_mark: |
   ```

## 8. Upgrade Dependencies
<!-- release: both -->

After each release, run the following command to upgrade dependencies:

Keep this upgrade process in a separate PR, as it might require IP Reviews from the Eclipse Foundation and additional time. Also, verify the `electron` version in `yarn.lock` and adjust `electronVersion` in `applications/electron/electron-builder.yml` if it has changed.

To perform the upgrade:

- Run `yarn upgrade` at the root of the repository.
- Fix any compilation errors, typing errors, and failing tests.
- Open a PR with the changes ([example](https://github.com/eclipse-theia/theia-ide/pull/568)).
- The license check review is done via the CI.
- Wait for the "IP Check" to complete ([example](https://gitlab.eclipse.org/eclipsefdn/emo-team/iplab/-/issues/22828)).

Performing this after the release helps us to find issues with the new dependencies and gives time to perform a license check on the dependencies.


================================================
FILE: README.md
================================================
<br/>
<div id="theia-logo" align="center">
    <br />
    <img src="https://raw.githubusercontent.com/eclipse-theia/theia-ide/master/theia-extensions/product/src/browser/icons/TheiaIDE.png" alt="Theia Logo" width="300"/>
    <h3>Eclipse Theia IDE</h3>
</div>

<div id="badges" align="center">

The Eclipse Theia IDE is built with this project.\
Eclipse Theia IDE also serves as a template for building desktop-based products based on the Eclipse Theia platform.

</div>

[![Installers](https://img.shields.io/badge/download-installers-blue.svg?style=flat-curved)](https://theia-ide.org//#theiaidedownload)
[![Build Status](https://ci.eclipse.org/theia/buildStatus/icon?subject=latest&job=Theia2%2Fmaster)](https://ci.eclipse.org/theia/job/Theia2/job/master/)
<!-- currently we have no working next job because next builds are not published -->
<!-- [![Build Status](https://ci.eclipse.org/theia/buildStatus/icon?subject=next&job=theia-next%2Fmaster)](https://ci.eclipse.org/theia/job/theia-next/job/master/) -->

[Main Theia Repository](https://github.com/eclipse-theia/theia)

[Visit the Theia website](http://www.theia-ide.org) for more documentation: [Using the Theia IDE](https://theia-ide.org/docs/user_getting_started/), [Packaging Theia as a Desktop Product](https://theia-ide.org/docs/blueprint_documentation/).

## License

- [MIT](LICENSE)

## Trademark

"Theia" is a trademark of the Eclipse Foundation
<https://www.eclipse.org/theia>

## What is this?

The Eclipse IDE is a modern and open IDE for cloud and desktop. The Theia IDE is based on the [Theia platform](https://theia-ide.org).
The Theia IDE is available as a [downloadable desktop application](https://theia-ide.org//#theiaidedownload). You can also try the latest version of the Theia IDE online. The online test version is limited to 30 minutes per session and hosted via Theia.cloud. Finally, we provide an [experimental Docker image](#docker) for hosting the Theia IDE online.

The Eclipse Theia IDE also serves as a **template** for building desktop-based products based on the Eclipse Theia platform, as well as to showcase Eclipse Theia capabilities. It is made up of a subset of existing Eclipse Theia features and extensions. [Documentation is available](https://theia-ide.org/docs/composing_applications/) to help you customize and build your own Eclipse Theia-based product.

## Theia IDE vs Theia Blueprint

The Theia IDE has been rebranded from its original name “Theia Blueprint”. You can therefore assume the terms “Theia IDE” and “Theia Blueprint” to be synonymous.

## Development

### Requirements

Please check Theia's [prerequisites](https://github.com/eclipse-theia/theia/blob/master/doc/Developing.md#prerequisites), and keep node versions aligned between Theia IDE and that of the referenced Theia version.

### Documentation

Documentation on how to package Theia as a Desktop Product may be found [here](https://theia-ide.org/docs/blueprint_documentation/)

For adopters building their own products based on this template, see the [Adopter Guide](ADOPTER.md) for additional considerations.

### Repository Structure

- Root level configures mono-repo build with lerna
- `applications` groups the different app targets
  - `browser` contains a browser based version of Eclipse Theia IDE that may be packaged as a Docker image
  - `electron` contains the electron app to package, packaging configuration, and E2E tests for the electron target.
- `theia-extensions` groups the various custom theia extensions for the Eclipse Theia IDE
  - `product` contains a Theia extension contributing the product branding (about dialogue and welcome page).
  - `updater` contains a Theia extension contributing the update mechanism and corresponding UI elements (based on the electron updater).
  - `launcher` contains a Theia extension contributing, for AppImage applications, the option to create a script that allows to start the Eclipse Theia IDE from the command line by calling the 'theia' command.
- `patches` contains patches applied to upstream packages

### Build

For development and casual testing of the Eclipse Theia IDE, one can build it in "dev" mode. This permits building the IDE on systems with less resources, like a Raspberry Pi 4B with 4GB of RAM.

NOTE: If manually building after updating dependencies or pulling to a newer commit, run `git clean -xfd` to help avoid runtime conflicts.

```sh
# Build "dev" version of the app. Its quicker, uses less resources, 
# but the front end app is not "minified"
yarn && yarn build:dev && yarn download:plugins
```

Production applications:

```sh
# Build production version of the Eclipse Theia IDE app
yarn && yarn build && yarn download:plugins
```

### Package the Applications

ATM we only produce packages for the Electron application.

_If you are trying to compile for arm on an arm machine, you may want to follow [these steps](https://github.com/eclipse-theia/theia-ide/issues/690#issuecomment-4157768849) before_

```sh
yarn package:applications
# or
yarn electron package
```

The packaged application is located in `applications/electron/dist`.

### Create a Preview Electron Electron Application (without packaging it)

```sh
yarn electron package:preview
```

The packaged application is located in `applications/electron/dist`.

### Running E2E Tests on Electron

The E2E tests basic UI tests of the actual application.
This is done based on the preview of the packaged application.

```sh
yarn electron package:preview
yarn electron test
```

### Running Browser app

The browser app may be started with

```sh
yarn browser start
```

and connect to <http://localhost:3000/>

### Developing with Local Theia Framework

To build and test the Theia IDE against a local development version of the Theia framework, see [docs/developing-with-local-theia.md](docs/developing-with-local-theia.md).

### Troubleshooting

- [_"Don't expect that you can build app for all platforms on one platform."_](https://www.electron.build/multi-platform-build)

### Reporting Feature Requests and Bugs

The features in the Eclipse Theia IDE are based on Theia and the included extensions/plugins. For bugs in Theia please consider opening an issue in the [Theia project on Github](https://github.com/eclipse-theia/theia/issues/new/choose).
The Eclipse Theia IDE only packages existing functionality into a product and installers for the product. If you believe there is a mistake in packaging, something needs to be added to the packaging or the installers do not work properly, please [open an issue on Github](https://github.com/eclipse-theia/theia-ide/issues/new/choose) to let us know.

### Docker

The Docker image of the Theia IDE is currently in _experimental state_. It is built from the same sources and packages as the desktop version, but it is not part of the [preview test](https://github.com/eclipse-theia/theia-ide/blob/master/PUBLISHING.md#preview-testing-and-release-process-for-the-theia-ide).
You can find a prebuilt Docker image of the IDE [here](https://github.com/eclipse-theia/theia-ide/pkgs/container/theia-ide%2Ftheia-ide).

You can also create the Docker image for the Eclipse Theia IDE based on the browser app with the following build command:

```sh
docker build -t theia-ide -f browser.Dockerfile .
```

You may then run this with

```sh
docker run -p=3000:3000 --rm theia-ide
```

and connect to <http://localhost:3000/>


================================================
FILE: applications/browser/package.json
================================================
{
  "private": true,
  "name": "theia-ide-browser-app",
  "description": "Eclipse Theia IDE browser product",
  "productName": "Theia IDE",
  "version": "1.71.100",
  "license": "MIT",
  "author": "Eclipse Theia <theia-dev@eclipse.org>",
  "homepage": "https://github.com/eclipse-theia/theia-ide#readme",
  "bugs": {
    "url": "https://github.com/eclipse-theia/theia/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/eclipse-theia/theia-ide.git"
  },
  "engines": {
    "yarn": ">=1.7.0 <2",
    "node": ">=22"
  },
  "theia": {
    "frontend": {
      "config": {
        "applicationName": "Theia IDE",
        "warnOnPotentiallyInsecureHostPattern": false,
        "preferences": {
          "toolbar.showToolbar": true,
          "files.enableTrash": false,
          "security.workspace.trust.enabled": false
        },
        "reloadOnReconnect": true
      }
    },
    "backend": {
      "config": {
        "warnOnPotentiallyInsecureHostPattern": false,
        "startupTimeout": -1,
        "resolveSystemPlugins": false,
        "configurationFolder": ".theia-ide",
        "frontendConnectionTimeout": 3000
      }
    },
    "generator": {
      "config": {
        "preloadTemplate": "./resources/preload.html"
      }
    }
  },
  "dependencies": {
    "@theia/ai-anthropic": "1.72.0-next.20",
    "@theia/ai-chat": "1.72.0-next.20",
    "@theia/ai-chat-ui": "1.72.0-next.20",
    "@theia/ai-claude-code": "1.72.0-next.20",
    "@theia/ai-code-completion": "1.72.0-next.20",
    "@theia/ai-codex": "1.72.0-next.20",
    "@theia/ai-copilot": "1.72.0-next.20",
    "@theia/ai-core": "1.72.0-next.20",
    "@theia/ai-core-ui": "1.72.0-next.20",
    "@theia/ai-editor": "1.72.0-next.20",
    "@theia/ai-google": "1.72.0-next.20",
    "@theia/ai-history": "1.72.0-next.20",
    "@theia/ai-huggingface": "1.72.0-next.20",
    "@theia/ai-ide": "1.72.0-next.20",
    "@theia/ai-llamafile": "1.72.0-next.20",
    "@theia/ai-mcp": "1.72.0-next.20",
    "@theia/ai-mcp-server": "1.72.0-next.20",
    "@theia/ai-mcp-ui": "1.72.0-next.20",
    "@theia/ai-ollama": "1.72.0-next.20",
    "@theia/ai-openai": "1.72.0-next.20",
    "@theia/ai-scanoss": "1.72.0-next.20",
    "@theia/ai-terminal": "1.72.0-next.20",
    "@theia/ai-vercel-ai": "1.72.0-next.20",
    "@theia/bulk-edit": "1.72.0-next.20",
    "@theia/callhierarchy": "1.72.0-next.20",
    "@theia/collaboration": "1.72.0-next.20",
    "@theia/console": "1.72.0-next.20",
    "@theia/core": "1.72.0-next.20",
    "@theia/debug": "1.72.0-next.20",
    "@theia/dev-container": "1.72.0-next.20",
    "@theia/editor": "1.72.0-next.20",
    "@theia/editor-preview": "1.72.0-next.20",
    "@theia/external-terminal": "1.72.0-next.20",
    "@theia/file-search": "1.72.0-next.20",
    "@theia/filesystem": "1.72.0-next.20",
    "@theia/getting-started": "1.72.0-next.20",
    "@theia/keymaps": "1.72.0-next.20",
    "@theia/markers": "1.72.0-next.20",
    "@theia/memory-inspector": "1.72.0-next.20",
    "@theia/messages": "1.72.0-next.20",
    "@theia/metrics": "1.72.0-next.20",
    "@theia/mini-browser": "1.72.0-next.20",
    "@theia/monaco": "1.72.0-next.20",
    "@theia/navigator": "1.72.0-next.20",
    "@theia/notebook": "1.72.0-next.20",
    "@theia/outline-view": "1.72.0-next.20",
    "@theia/output": "1.72.0-next.20",
    "@theia/plugin-dev": "1.72.0-next.20",
    "@theia/plugin-ext": "1.72.0-next.20",
    "@theia/plugin-ext-vscode": "1.72.0-next.20",
    "@theia/preferences": "1.72.0-next.20",
    "@theia/preview": "1.72.0-next.20",
    "@theia/process": "1.72.0-next.20",
    "@theia/property-view": "1.72.0-next.20",
    "@theia/remote": "1.72.0-next.20",
    "@theia/scanoss": "1.72.0-next.20",
    "@theia/scm": "1.72.0-next.20",
    "@theia/search-in-workspace": "1.72.0-next.20",
    "@theia/secondary-window": "1.72.0-next.20",
    "@theia/task": "1.72.0-next.20",
    "@theia/terminal": "1.72.0-next.20",
    "@theia/terminal-manager": "1.72.0-next.20",
    "@theia/test": "1.72.0-next.20",
    "@theia/timeline": "1.72.0-next.20",
    "@theia/toolbar": "1.72.0-next.20",
    "@theia/typehierarchy": "1.72.0-next.20",
    "@theia/userstorage": "1.72.0-next.20",
    "@theia/variable-resolver": "1.72.0-next.20",
    "@theia/vsx-registry": "1.72.0-next.20",
    "@theia/workspace": "1.72.0-next.20",
    "fs-extra": "^9.1.0",
    "theia-ide-product-ext": "1.71.100"
  },
  "devDependencies": {
    "@theia/cli": "1.72.0-next.20",
    "@theia/bundle-plugin": "1.72.0-next.20"
  },
  "scripts": {
    "clean": "theia clean && rimraf node_modules",
    "build": "yarn -s rebuild && theia build --app-target=\"browser\" --mode development",
    "build:prod": "yarn -s rebuild && theia  build --app-target=\"browser\"",
    "rebuild": "theia rebuild:browser --cacheRoot ../..",
    "start": "theia start --plugins=local-dir:../../plugins",
    "watch": "concurrently --kill-others -n tsc,build -c red,yellow \"tsc -b -w --preserveWatchOutput\" \"yarn -s watch:bundle\"",
    "update:theia": "ts-node ../../scripts/update-theia-version.ts",
    "update:next": "ts-node ../../scripts/update-theia-version.ts next"
  }
}

================================================
FILE: applications/browser/resources/preload.html
================================================
<!DOCTYPE html>
<html lang="en">

<head>
    <style>
        html,
        body {
            background-color: black;
        }

        .theia-preload {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            /* Above styles copied from https://github.com/eclipse-theia/theia/blob/5aeef6c0c683b4e91713ab736957e6655b486adc/packages/core/src/browser/style/index.css#L147-L151 */
            /* Otherwise, there is a flickering when Theia's CSS loads. */

            background-image: none;
        }

        .theia-preload::after {
            /* remove default loading animation */
            content: none;
        }

        .spinner-container {
            display: flex;
            flex-direction: center;
            align-self: center;
            justify-content: center;
            height: 100vh;
            width: 100vw;
        }

        .custom-spinner {
            align-self: center;
        }

        .custom-spinner svg {
            width: 16vw;
            height: 16vh;
            animation-delay: 0;
            animation-duration: 2s;
            animation-iteration-count: infinite;
            animation-name: theia-ide-spinner;
            animation-timing-function: ease;
        }

        @keyframes theia-ide-spinner {
            0% {
                filter: invert(49%) sepia(71%) saturate(5980%) hue-rotate(199deg) brightness(103%) contrast(101%);
                transform: scale(1.0);
            }

            50% {
                filter: invert(57%) sepia(52%) saturate(1900%) hue-rotate(160deg) brightness(100%) contrast(102%);
                transform: scale(0.8);
            }

            100% {
                filter: invert(49%) sepia(71%) saturate(5980%) hue-rotate(199deg) brightness(103%) contrast(101%);
                transform: scale(1.0);
            }
        }
    </style>
</head>

<body>
    <div class='spinner-container'>
        <div class='custom-spinner'>
            <svg id="spinner" version="1.1" xmlns="http://www.w3.org/2000/svg"
                xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" preserveAspectRatio="xMinYMin meet"
                viewBox="0, 0, 1150, 540.6">
                <g id="Layer_1" fill="#FFFFFF">
                    <path
                        d="M880.199,2.8 C1028.1,2.8 1147.9,122.6 1147.9,270.5 C1147.9,418.3 1028.1,538.2 880.2,538.2 L290.1,538.2 C269,538.2 251.9,521.1 251.9,500 C251.9,478.9 269,461.8 290.1,461.8 L427.6,461.8 C448.6,461.8 465.7,444.7 465.7,423.6 C465.7,402.5 448.6,385.4 427.6,385.4 L396.999,385.4 C375.9,385.4 358.8,368.3 358.8,347.2 C358.8,326.1 375.9,309 397,309 L488.703,309 C509.918,308.941 526.373,291.65 526.9,270.8 C526.9,249.7 509.8,232.6 488.7,232.6 L167.8,232.6 C146.7,232.6 129.6,215.5 129.6,194.4 C129.6,173.3 146.7,156.2 167.8,156.2 L404.604,156.2 C425.818,156.141 442.273,138.85 442.8,118 C442.8,96.9 425.7,79.8 404.6,79.8 L351.2,79.8 C330.1,79.8 313,62.7 313,41.6 C313,20.5 330.1,2.4 351.2,2.4 L880.199,2.8 z M837.4,92 L837.4,92 C755.2,92 688.7,158.6 688.7,240.7 L688.7,300.2 C688.7,382.4 755.2,448.9 837.4,448.9 C919.5,448.9 986.1,382.4 986.1,300.2 L986.1,240.7 C986.1,158.6 919.5,92 837.4,92 L837.4,92 z M888.2,232.6 C908,232.6 924.1,248.7 924.1,268.5 L924.1,273.1 C924.1,292.9 908,309 888.2,309 L776.6,309 C756.8,309 740.7,292.9 740.7,273.1 L740.7,268.5 C740.7,248.7 756.8,232.6 776.6,232.6 L888.2,232.6 z" />
                    <path
                        d="M170.1,461.8 C190,461.8 206,477.8 206,497.7 L206,502.3 C206,522.1 190,538.2 170.1,538.2 L38,538.2 C18.2,538.2 2.1,522.1 2.1,502.3 L2.1,497.7 C2.1,477.8 18.2,461.8 38,461.8 L170.1,461.8 z" />
                    <path
                        d="M231.3,3.4 C251.1,3.4 267.1,19.5 267.1,39.3 L267.1,44 C267.1,63.8 251.1,79.8 231.3,79.8 L83.8,79.8 C64,79.8 47.9,63.8 47.9,44 L47.9,39.3 C47.9,19.5 64,3.4 83.8,3.4 L231.3,3.4 z" />
                    <path
                        d="M277.1,309 C296.9,309 313,325.1 313,344.9 L313,349.5 C313,369.3 296.9,385.4 277.1,385.4 L196.1,385.4 C176.3,385.4 160.2,369.3 160.2,349.5 L160.2,344.9 C160.2,325.1 176.3,309 196.1,309 L277.1,309 z" />
                </g>
            </svg>
        </div>
    </div>

    <script>
        if (document.head) {
            let link = document.createElement('link');
            link.rel = 'icon';
            link.href = '/favicon.ico';
            document.head.appendChild(link);
        }
    </script>
</body>

</html>

================================================
FILE: applications/browser/tsconfig.json
================================================
{
    "extends": "../../configs/base.tsconfig",
    "include": [],
    "compilerOptions": {
      "composite": true
    },
    "references": [
      {
        "path": "../../theia-extensions/launcher"
      },
      {
        "path": "../../theia-extensions/product"
      }
    ]
}


================================================
FILE: applications/browser/webpack.config.js
================================================
/**
 * This file can be edited to customize webpack configuration.
 * To reset delete this file and rerun theia build again.
 */
// @ts-check
const configs = require('./gen-webpack.config.js');
const nodeConfig = require('./gen-webpack.node.config.js');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');

/**
 * Expose bundled modules on window.theia.moduleName namespace, e.g.
 * window['theia']['@theia/core/lib/common/uri'].
 * Such syntax can be used by external code, for instance, for testing.
configs[0].module.rules.push({
    test: /\.js$/,
    loader: require.resolve('@theia/application-manager/lib/expose-loader')
}); */

// serve favico from root
// @ts-ignore
configs[0].plugins.push(
    // @ts-ignore
    new CopyWebpackPlugin({
        patterns: [
            {
                context: path.resolve('.', '..', '..', 'applications', 'browser', 'ico'),
                from: '**'
            }
        ]
    })
);

module.exports = [
    ...configs,
    nodeConfig.config
];

================================================
FILE: applications/electron/.eslintrc.js
================================================
/** @type {import('eslint').Linter.Config} */
module.exports = {
    extends: [
        '../../configs/build.eslintrc.json'
    ],
    parserOptions: {
        tsconfigRootDir: __dirname,
        project: 'tsconfig.eslint.json'
    }
};


================================================
FILE: applications/electron/electron-builder.yml
================================================
appId: eclipse.theia
productName: TheiaIDE
copyright: Copyright © 2020-2025 Eclipse Foundation, Inc
electronDist: ../../node_modules/electron/dist
electronVersion: 39.8.7
asar: true
asarUnpack:
  - "**/lib/backend/native/**"
  - "**/lib/backend/shell-integrations/**"
  - "**/lib/build/Release/**"
  - "**/lib/prebuilds/**"
nodeGypRebuild: false
npmRebuild: false

directories:
  buildResources: resources

# node_modules and package.json are copied automatically
# Exclude node_modules manually because electron is copied by electron-builder and we are using a bundled backend
files:
  - src-gen
  - lib
  - resources/icons/WindowIcon/512-512.png
  - resources/TheiaIDESplash.svg
  - scripts
  - "!**node_modules/**"
extraResources:
  - from: ../../plugins
    to: app/plugins

win:
  icon: resources/icons/WindowsLauncherIcons/TheiaIDE.ico
  target:
    - nsis
  publish:
    provider: generic
    url: "https://download.eclipse.org/theia/ide/${version}/windows"
    useMultipleRangeRequest: false
mac:
  icon: resources/icons/MacLauncherIcons/icon.icns
  category: public.app-category.developer-tools
  protocols:
    - name: theia
      schemes:
        - theia
  darkModeSupport: true
  target:
    - dmg
    - zip
  publish:
    provider: generic
    url: "https://download.eclipse.org/theia/ide/latest/macos"
linux:
  icon: resources/icons/LinuxLauncherIcons
  category: Development
  mimeTypes:
    - inode/directory
  vendor: Eclipse Foundation, Inc
  target:
    - deb
    - AppImage
  publish:
    provider: generic
    url: "https://download.eclipse.org/theia/ide/latest/linux"

nsis:
  menuCategory: true
  oneClick: false
  perMachine: false
  installerHeaderIcon: resources/icons/WindowsLauncherIcons/TheiaIDE.ico
  installerIcon: resources/icons/WindowsLauncherIcons/TheiaIDE.ico
  uninstallerIcon: resources/icons/WindowsLauncherIcons/TheiaIDE.ico
  installerSidebar: resources/icons/InstallerSidebarImage/164-314Windows.bmp
  uninstallerSidebar: resources/icons/InstallerSidebarImage/164-314Windows.bmp
  allowToChangeInstallationDirectory: true
  runAfterFinish: false
  artifactName: ${productName}Setup.${ext}
  license: LICENSE
dmg:
  artifactName: ${productName}.${ext}
deb:
  artifactName: ${productName}.${ext}
appImage:
  artifactName: ${productName}.${ext}

afterPack: ./scripts/after-pack.js


================================================
FILE: applications/electron/entitlements.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
    <true/>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
  </dict>
</plist>


================================================
FILE: applications/electron/package.json
================================================
{
  "private": true,
  "name": "theia-ide-electron-app",
  "description": "Eclipse Theia IDE product",
  "productName": "Theia IDE",
  "version": "1.71.100",
  "main": "scripts/theia-electron-main.js",
  "license": "MIT",
  "author": "Eclipse Theia <theia-dev@eclipse.org>",
  "homepage": "https://github.com/eclipse-theia/theia-ide#readme",
  "bugs": {
    "url": "https://github.com/eclipse-theia/theia/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/eclipse-theia/theia-ide.git"
  },
  "engines": {
    "yarn": ">=1.7.0 <2",
    "node": ">=22"
  },
  "theia": {
    "target": "electron",
    "frontend": {
      "config": {
        "applicationName": "Theia IDE",
        "reloadOnReconnect": true,
        "preferences": {
          "toolbar.showToolbar": true
        },
        "electron": {
          "showWindowEarly": false,
          "splashScreenOptions": {
            "content": "resources/TheiaIDESplash.svg",
            "height": 276,
            "width": 446
          }
        }
      }
    },
    "backend": {
      "config": {
        "frontendConnectionTimeout": -1,
        "startupTimeout": -1,
        "resolveSystemPlugins": false,
        "configurationFolder": ".theia-ide"
      }
    },
    "generator": {
      "config": {
        "preloadTemplate": "./resources/preload.html"
      }
    }
  },
  "dependencies": {
    "@theia/ai-anthropic": "1.72.0-next.20",
    "@theia/ai-chat": "1.72.0-next.20",
    "@theia/ai-chat-ui": "1.72.0-next.20",
    "@theia/ai-claude-code": "1.72.0-next.20",
    "@theia/ai-code-completion": "1.72.0-next.20",
    "@theia/ai-codex": "1.72.0-next.20",
    "@theia/ai-copilot": "1.72.0-next.20",
    "@theia/ai-core": "1.72.0-next.20",
    "@theia/ai-core-ui": "1.72.0-next.20",
    "@theia/ai-editor": "1.72.0-next.20",
    "@theia/ai-google": "1.72.0-next.20",
    "@theia/ai-history": "1.72.0-next.20",
    "@theia/ai-huggingface": "1.72.0-next.20",
    "@theia/ai-ide": "1.72.0-next.20",
    "@theia/ai-llamafile": "1.72.0-next.20",
    "@theia/ai-mcp": "1.72.0-next.20",
    "@theia/ai-mcp-server": "1.72.0-next.20",
    "@theia/ai-mcp-ui": "1.72.0-next.20",
    "@theia/ai-ollama": "1.72.0-next.20",
    "@theia/ai-openai": "1.72.0-next.20",
    "@theia/ai-scanoss": "1.72.0-next.20",
    "@theia/ai-terminal": "1.72.0-next.20",
    "@theia/ai-vercel-ai": "1.72.0-next.20",
    "@theia/bulk-edit": "1.72.0-next.20",
    "@theia/callhierarchy": "1.72.0-next.20",
    "@theia/collaboration": "1.72.0-next.20",
    "@theia/console": "1.72.0-next.20",
    "@theia/core": "1.72.0-next.20",
    "@theia/debug": "1.72.0-next.20",
    "@theia/dev-container": "1.72.0-next.20",
    "@theia/editor": "1.72.0-next.20",
    "@theia/editor-preview": "1.72.0-next.20",
    "@theia/electron": "1.72.0-next.20",
    "@theia/external-terminal": "1.72.0-next.20",
    "@theia/file-search": "1.72.0-next.20",
    "@theia/filesystem": "1.72.0-next.20",
    "@theia/getting-started": "1.72.0-next.20",
    "@theia/keymaps": "1.72.0-next.20",
    "@theia/markers": "1.72.0-next.20",
    "@theia/memory-inspector": "1.72.0-next.20",
    "@theia/messages": "1.72.0-next.20",
    "@theia/metrics": "1.72.0-next.20",
    "@theia/mini-browser": "1.72.0-next.20",
    "@theia/monaco": "1.72.0-next.20",
    "@theia/navigator": "1.72.0-next.20",
    "@theia/notebook": "1.72.0-next.20",
    "@theia/outline-view": "1.72.0-next.20",
    "@theia/output": "1.72.0-next.20",
    "@theia/plugin-dev": "1.72.0-next.20",
    "@theia/plugin-ext": "1.72.0-next.20",
    "@theia/plugin-ext-vscode": "1.72.0-next.20",
    "@theia/preferences": "1.72.0-next.20",
    "@theia/preview": "1.72.0-next.20",
    "@theia/process": "1.72.0-next.20",
    "@theia/property-view": "1.72.0-next.20",
    "@theia/remote": "1.72.0-next.20",
    "@theia/remote-wsl": "1.72.0-next.20",
    "@theia/scanoss": "1.72.0-next.20",
    "@theia/scm": "1.72.0-next.20",
    "@theia/search-in-workspace": "1.72.0-next.20",
    "@theia/secondary-window": "1.72.0-next.20",
    "@theia/task": "1.72.0-next.20",
    "@theia/terminal": "1.72.0-next.20",
    "@theia/terminal-manager": "1.72.0-next.20",
    "@theia/test": "1.72.0-next.20",
    "@theia/timeline": "1.72.0-next.20",
    "@theia/toolbar": "1.72.0-next.20",
    "@theia/typehierarchy": "1.72.0-next.20",
    "@theia/userstorage": "1.72.0-next.20",
    "@theia/variable-resolver": "1.72.0-next.20",
    "@theia/vsx-registry": "1.72.0-next.20",
    "@theia/workspace": "1.72.0-next.20",
    "fs-extra": "^9.1.0",
    "theia-ide-launcher-ext": "1.71.100",
    "theia-ide-product-ext": "1.71.100",
    "theia-ide-updater-ext": "1.71.100"
  },
  "devDependencies": {
    "@theia/cli": "1.72.0-next.20",
    "@theia/bundle-plugin": "1.72.0-next.20",
    "@types/js-yaml": "^3.12.10",
    "@types/yargs": "17.0.7",
    "@wdio/cli": "^6.12.1",
    "@wdio/local-runner": "^6.12.1",
    "@wdio/mocha-framework": "^6.11.0",
    "@wdio/spec-reporter": "^6.11.0",
    "app-builder-lib": "26.0.12",
    "chai": "^4.5.0",
    "concurrently": "^3.6.1",
    "electron": "39.8.7",
    "electron-builder": "26.0.12",
    "electron-chromedriver": "^28.3.3",
    "electron-mocha": "^12.3.1",
    "electron-osx-sign": "^0.6.0",
    "js-yaml": "^3.14.2",
    "mocha": "^8.4.0",
    "rimraf": "^2.7.1",
    "ts-node": "^10.9.2",
    "wdio-chromedriver-service": "^6.0.4",
    "webdriverio": "^6.12.1",
    "yargs": "17.2.1"
  },
  "scripts": {
    "clean": "theia clean && rimraf node_modules",
    "clean:dist": "rimraf dist",
    "build": "yarn -s rebuild && theia build --app-target=\"electron\" --mode development",
    "build:prod": "yarn -s rebuild && theia build --app-target=\"electron\"",
    "rebuild": "theia rebuild:electron --cacheRoot ../..",
    "watch": "concurrently -n compile,build \"theiaext watch --preserveWatchOutput\" \"theia build --watch --mode development\"",
    "start": "electron scripts/theia-electron-main.js --plugins=local-dir:../../plugins",
    "start:debug": "yarn start --log-level=debug",
    "package": "yarn clean:dist && yarn rebuild && electron-builder -c.mac.identity=null --publish never",
    "package:prod": "yarn deploy",
    "deploy": "yarn clean:dist && yarn rebuild && electron-builder -c.mac.identity=null --publish always",
    "package:preview": "yarn clean:dist && yarn rebuild && electron-builder -c.mac.identity=null --dir",
    "update:checksum": "ts-node scripts/update-checksum.ts",
    "update:blockmap": "ts-node scripts/update-blockmap.ts",
    "update:theia": "ts-node ../../scripts/update-theia-version.ts",
    "update:next": "ts-node ../../scripts/update-theia-version.ts next",
    "sign:directory": "ts-node scripts/sign-directory.ts",
    "sign:directory:windows": "ts-node scripts/sign-directory-windows.ts",
    "test": "mocha --timeout 60000 \"./test/*.spec.js\"",
    "lint": "eslint --ext js,jsx,ts,tsx scripts && eslint --ext js,jsx,ts,tsx test",
    "lint:fix": "eslint --ext js,jsx,ts,tsx scripts --fix && eslint --ext js,jsx,ts,tsx test -fix"
  }
}

================================================
FILE: applications/electron/resources/LICENSE
================================================
MIT License

Copyright (c) 2020 Eclipse Theia Blueprint Authors

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

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

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


================================================
FILE: applications/electron/resources/icons/MacLauncherIcons/icon.icon/icon.json
================================================
{
  "fill" : {
    "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000"
  },
  "groups" : [
    {
      "layers" : [
        {
          "image-name" : "icon.png",
          "name" : "icon",
          "position" : {
            "scale" : 1.67,
            "translation-in-points" : [
              0,
              0
            ]
          }
        }
      ],
      "name" : "Icon",
      "shadow" : {
        "kind" : "neutral",
        "opacity" : 0.5
      },
      "translucency" : {
        "enabled" : true,
        "value" : 0.5
      }
    },
    {
      "blur-material" : null,
      "hidden" : false,
      "layers" : [
        {
          "image-name" : "Theia Light BG.jpg",
          "name" : "Theia Light BG"
        }
      ],
      "lighting" : "combined",
      "name" : "Light Mode Content",
      "opacity-specializations" : [
        {
          "appearance" : "dark",
          "value" : 0
        }
      ],
      "shadow" : {
        "kind" : "neutral",
        "opacity" : 0.5
      },
      "translucency" : {
        "enabled" : true,
        "value" : 0.5
      }
    },
    {
      "hidden" : false,
      "layers" : [
        {
          "image-name" : "Theia Dark BG.jpg",
          "name" : "Theia Dark BG"
        }
      ],
      "lighting" : "combined",
      "name" : "Dark Mode Content",
      "opacity-specializations" : [
        {
          "value" : 0
        },
        {
          "appearance" : "dark",
          "value" : 1
        }
      ],
      "shadow" : {
        "kind" : "neutral",
        "opacity" : 0.5
      },
      "translucency" : {
        "enabled" : true,
        "value" : 0.5
      }
    }
  ],
  "supported-platforms" : {
    "circles" : [
      "watchOS"
    ],
    "squares" : "shared"
  }
}

================================================
FILE: applications/electron/resources/preload.html
================================================
<!DOCTYPE html>
<html lang="en">

<head>
    <style>
        html,
        body {
            background-color: black;
        }

        .theia-preload {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            /* Above styles copied from https://github.com/eclipse-theia/theia/blob/5aeef6c0c683b4e91713ab736957e6655b486adc/packages/core/src/browser/style/index.css#L147-L151 */
            /* Otherwise, there is a flickering when Theia's CSS loads. */

            background-image: none;
        }

        .theia-preload::after {
            /* remove default loading animation */
            content: none;
        }

        .spinner-container {
            display: flex;
            flex-direction: center;
            align-self: center;
            justify-content: center;
            height: 100vh;
            width: 100vw;
        }

        .custom-spinner {
            align-self: center;
        }

        .custom-spinner svg {
            width: 16vw;
            height: 16vh;
            animation-delay: 0;
            animation-duration: 2s;
            animation-iteration-count: infinite;
            animation-name: theia-ide-spinner;
            animation-timing-function: ease;
        }

        @keyframes theia-ide-spinner {
            0% {
                filter: invert(49%) sepia(71%) saturate(5980%) hue-rotate(199deg) brightness(103%) contrast(101%);
                transform: scale(1.0);
            }

            50% {
                filter: invert(57%) sepia(52%) saturate(1900%) hue-rotate(160deg) brightness(100%) contrast(102%);
                transform: scale(0.8);
            }

            100% {
                filter: invert(49%) sepia(71%) saturate(5980%) hue-rotate(199deg) brightness(103%) contrast(101%);
                transform: scale(1.0);
            }
        }
    </style>
</head>

<body>
    <div class='spinner-container'>
        <div class='custom-spinner'>
            <svg id="spinner" version="1.1" xmlns="http://www.w3.org/2000/svg"
                xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" preserveAspectRatio="xMinYMin meet"
                viewBox="0, 0, 1150, 540.6">
                <g id="Layer_1" fill="#FFFFFF">
                    <path
                        d="M880.199,2.8 C1028.1,2.8 1147.9,122.6 1147.9,270.5 C1147.9,418.3 1028.1,538.2 880.2,538.2 L290.1,538.2 C269,538.2 251.9,521.1 251.9,500 C251.9,478.9 269,461.8 290.1,461.8 L427.6,461.8 C448.6,461.8 465.7,444.7 465.7,423.6 C465.7,402.5 448.6,385.4 427.6,385.4 L396.999,385.4 C375.9,385.4 358.8,368.3 358.8,347.2 C358.8,326.1 375.9,309 397,309 L488.703,309 C509.918,308.941 526.373,291.65 526.9,270.8 C526.9,249.7 509.8,232.6 488.7,232.6 L167.8,232.6 C146.7,232.6 129.6,215.5 129.6,194.4 C129.6,173.3 146.7,156.2 167.8,156.2 L404.604,156.2 C425.818,156.141 442.273,138.85 442.8,118 C442.8,96.9 425.7,79.8 404.6,79.8 L351.2,79.8 C330.1,79.8 313,62.7 313,41.6 C313,20.5 330.1,2.4 351.2,2.4 L880.199,2.8 z M837.4,92 L837.4,92 C755.2,92 688.7,158.6 688.7,240.7 L688.7,300.2 C688.7,382.4 755.2,448.9 837.4,448.9 C919.5,448.9 986.1,382.4 986.1,300.2 L986.1,240.7 C986.1,158.6 919.5,92 837.4,92 L837.4,92 z M888.2,232.6 C908,232.6 924.1,248.7 924.1,268.5 L924.1,273.1 C924.1,292.9 908,309 888.2,309 L776.6,309 C756.8,309 740.7,292.9 740.7,273.1 L740.7,268.5 C740.7,248.7 756.8,232.6 776.6,232.6 L888.2,232.6 z" />
                    <path
                        d="M170.1,461.8 C190,461.8 206,477.8 206,497.7 L206,502.3 C206,522.1 190,538.2 170.1,538.2 L38,538.2 C18.2,538.2 2.1,522.1 2.1,502.3 L2.1,497.7 C2.1,477.8 18.2,461.8 38,461.8 L170.1,461.8 z" />
                    <path
                        d="M231.3,3.4 C251.1,3.4 267.1,19.5 267.1,39.3 L267.1,44 C267.1,63.8 251.1,79.8 231.3,79.8 L83.8,79.8 C64,79.8 47.9,63.8 47.9,44 L47.9,39.3 C47.9,19.5 64,3.4 83.8,3.4 L231.3,3.4 z" />
                    <path
                        d="M277.1,309 C296.9,309 313,325.1 313,344.9 L313,349.5 C313,369.3 296.9,385.4 277.1,385.4 L196.1,385.4 C176.3,385.4 160.2,369.3 160.2,349.5 L160.2,344.9 C160.2,325.1 176.3,309 196.1,309 L277.1,309 z" />
                </g>
            </svg>
        </div>
    </div>
</body>

</html>

================================================
FILE: applications/electron/scripts/after-pack.js
================================================
#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const util = require('util');
const child_process = require('child_process');
const rimraf = require('rimraf');
const sign_util = require('electron-osx-sign/util');
const asyncRimraf = util.promisify(rimraf);

const DELETE_PATHS = [
    'Contents/Resources/app/node_modules/unzip-stream/aa.zip',
    'Contents/Resources/app/node_modules/unzip-stream/testData*'
];

const signCommand = path.join(__dirname, 'sign.sh');
const notarizeCommand = path.join(__dirname, 'notarize.sh');
const entitlements = path.resolve(__dirname, '..', 'entitlements.plist');

const signFile = file => {
    const stat = fs.lstatSync(file);
    const mode = stat.isFile() ? stat.mode : undefined;

    console.log(`Signing ${file}...`);
    child_process.spawnSync(signCommand, [
        path.basename(file),
        entitlements
    ], {
        cwd: path.dirname(file),
        maxBuffer: 1024 * 10000,
        env: process.env,
        stdio: 'inherit',
        encoding: 'utf-8'
    });

    if (mode) {
        console.log(`Setting attributes of ${file}...`);
        fs.chmodSync(file, mode);
    }
};

exports.default = async function (context) {
    await afterPackHook(context);
    const running_ci = process.env.THEIA_IDE_JENKINS_CI === 'true';
    const releaseDryRun = process.env.THEIA_IDE_JENKINS_RELEASE_DRYRUN === 'true';
    const branch = process.env.BRANCH_NAME;
    const running_on_mac = context.packager.platform.name === 'mac';
    const appPath = path.resolve(context.appOutDir, `${context.packager.appInfo.productFilename}.app`);

    // Remove anything we don't want in the final package
    for (const deletePath of DELETE_PATHS) {
        const resolvedPath = path.resolve(appPath, deletePath);
        console.log(`Deleting ${resolvedPath}...`);
        await asyncRimraf(resolvedPath);
    }

    // Only continue for macOS during CI
    if ((( branch === 'master' || releaseDryRun)  && running_ci && running_on_mac)) {
        console.log('Detected Theia IDE Release on Mac ' + releaseDryRun ? ' (dry-run)' : ''
            + ' - proceeding with signing and notarizing');
    } else {
        if (running_on_mac) {
            console.log('Not a release or dry-run requiring signing/notarizing - skipping');
        }
        return;
    }

    // Use app-builder-lib to find all binaries to sign, at this level it will include the final .app
    let childPaths = await sign_util.walkAsync(context.appOutDir);

    // Sign deepest first
    // From https://github.com/electron-userland/electron-builder/blob/master/packages/app-builder-lib/electron-osx-sign/sign.js#L120
    childPaths = childPaths.sort((a, b) => {
        const aDepth = a.split(path.sep).length;
        const bDepth = b.split(path.sep).length;
        return bDepth - aDepth;
    });

    // Sign binaries
    childPaths.forEach(file => signFile(file, context.appOutDir));

    // Notarize app
    child_process.spawnSync(notarizeCommand, [
        path.basename(appPath),
        context.packager.appInfo.info._configuration.appId
    ], {
        cwd: path.dirname(appPath),
        maxBuffer: 1024 * 10000,
        env: process.env,
        stdio: 'inherit',
        encoding: 'utf-8'
    });
};

// taken and modified from: https://github.com/gergof/electron-builder-sandbox-fix/blob/a2251d7d8f22be807d2142da0cf768c78d4cfb0a/lib/index.js
const afterPackHook = async params => {
    if (params.electronPlatformName !== 'linux') {
        // this fix is only required on linux
        return;
    }
    const executable = path.join(
        params.appOutDir,
        params.packager.executableName
    );

    const loaderScript = `#!/usr/bin/env bash
set -u
SCRIPT_DIR="$( cd "$( dirname "\${BASH_SOURCE[0]}" )" && pwd )"
exec "$SCRIPT_DIR/${params.packager.executableName}.bin" "--no-sandbox" "$@"
`;

    try {
        await fs.promises.rename(executable, executable + '.bin');
        await fs.promises.writeFile(executable, loaderScript);
        await fs.promises.chmod(executable, 0o755);
    } catch (e) {
        throw new Error('Failed to create loader for sandbox fix:\n' + e);
    }
};


================================================
FILE: applications/electron/scripts/appimage-helpers.js
================================================
const fs = require('fs');
const path = require('path');

/**
 * Reads the plugin copy metadata file and returns its content.
 * @param metadataPath - Path to the metadata file
 * @returns The metadata object or undefined if not found
 */
function readPluginCopyMetadata(metadataPath) {
    if (!fs.existsSync(metadataPath)) {
        return undefined;
    }
    try {
        return JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
    } catch (err) {
        console.warn('Could not read built-in plugin copy metadata file:', err.message);
        return undefined;
    }
}

/**
 * Writes the plugin copy metadata file with version and timestamp.
 * @param metadataPath - Path to the metadata file
 * @param version - Current version
 */
function writePluginCopyMetadata(metadataPath, version) {
    const metadata = {
        version: version,
        copiedAt: new Date().toISOString()
    };
    fs.writeFileSync(metadataPath, JSON.stringify(metadata, undefined, 2));
}

/**
 * Copies bundled plugins from AppImage to user directory if needed.
 * @param bundledPluginsDir - Path to bundled plugins in AppImage
 * @param userPluginsDir - Path to user built-in plugins directory
 * @param currentVersion - Current Theia IDE version
 * @returns true if the builtins were copied to the user dir, false if there was an error
 */
function copyBundledPlugins(bundledPluginsDir, userPluginsDir, currentVersion) {
    const metadataFile = path.join(userPluginsDir, '.builtInPlugins-metadata');

    // Ensure the user plugins directory exists
    if (!fs.existsSync(userPluginsDir)) {
        fs.mkdirSync(userPluginsDir, { recursive: true });
    }

    // Check if built-in plugins need to be copied
    const metadata = readPluginCopyMetadata(metadataFile);
    let shouldCopy = false;

    if (!metadata) {
        shouldCopy = true;
    } else if (metadata.version !== currentVersion) {
        console.log(`Theia IDE updated from ${metadata.version} to ${currentVersion}. Updating built-in plugins...`);
        shouldCopy = true;
    }

    if (!shouldCopy) {
        console.log('Built-in plugins were already copied.');
        return true;
    }

    console.log(`Copying bundled plugins from AppImage to ${userPluginsDir}...`);
    try {
        // Clean existing plugins directory to remove old/obsolete plugins
        fs.rmSync(userPluginsDir, { recursive: true, force: true });
        fs.mkdirSync(userPluginsDir, { recursive: true });

        const pluginEntries = fs.readdirSync(bundledPluginsDir, { withFileTypes: true });
        for (const entry of pluginEntries) {
            const srcPath = path.join(bundledPluginsDir, entry.name);
            const destPath = path.join(userPluginsDir, entry.name);
            fs.cpSync(srcPath, destPath, { recursive: true });
        }
        writePluginCopyMetadata(metadataFile, currentVersion);
        console.log(`Bundled plugins copied successfully to ${userPluginsDir}.`);
    } catch (err) {
        console.error('Failed to copy bundled plugins:', err.message);
        return false;
    }
    return true;
}

module.exports = {
    copyBundledPlugins,
};


================================================
FILE: applications/electron/scripts/generate-app-update-yml.js
================================================
#!/usr/bin/env node

/********************************************************************************
 * Copyright (C) 2026 STMicroelectronics and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License, which is available in the project root.
 *
 * SPDX-License-Identifier: MIT
 ********************************************************************************/

// Generates app-update.yml for the Windows auto-updater.
//
// The normal electron-builder flow generates this file during afterPack, but
// only when the target is "nsis" or "appx". The Windows CI build splits
// packaging into two steps:
//   1. `electron-builder --dir` (target = "dir") → app-update.yml is skipped
//   2. `electron-builder --prepackaged` → afterPack does not run
//
// This script bridges that gap by writing the file before step 2.

const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');

const electronDir = path.resolve(__dirname, '..');
const pkg = require(path.join(electronDir, 'package.json'));
const builderConfig = yaml.load(fs.readFileSync(path.join(electronDir, 'electron-builder.yml'), 'utf8'));

const winPublish = builderConfig.win.publish;
const version = pkg.version;

// Expand ${version} macro in the URL, matching electron-builder's macro expansion
const url = winPublish.url.replace('${version}', version);

const appUpdateYml = {
    provider: winPublish.provider,
    url,
    ...(winPublish.useMultipleRangeRequest !== undefined && { useMultipleRangeRequest: winPublish.useMultipleRangeRequest }),
    updaterCacheDirName: `${pkg.name}-updater`
};

const outPath = path.join(electronDir, 'dist', 'win-unpacked', 'resources', 'app-update.yml');
fs.writeFileSync(outPath, yaml.dump(appUpdateYml, { lineWidth: -1 }));
console.log(`Generated ${outPath}`);
console.log(fs.readFileSync(outPath, 'utf8'));


================================================
FILE: applications/electron/scripts/notarize.sh
================================================
#!/bin/bash -x

INPUT=$1
APP_ID=$2
NEEDS_UNZIP=false
UUID_REGEX='"uuid"\s*:\s*"([^"]+)'
STATUS_REGEX='"status"\s*:\s*"([^"]+)'

# if folder, zip it
if [ -d "${INPUT}" ]; then
    NEEDS_UNZIP=true
    zip -r -q -y unsigned.zip "${INPUT}"
    rm -rf "${INPUT}"
    INPUT=unsigned.zip
fi

# copy file to storage server
scp -p "${INPUT}" genie.theia@projects-storage.eclipse.org:./
rm -f "${INPUT}"

# name to use on server
REMOTE_NAME=${INPUT##*/}

# notarize over ssh
RESPONSE=$(ssh -q genie.theia@projects-storage.eclipse.org curl -X POST -F file=@"\"${REMOTE_NAME}\"" -F "'options={\"primaryBundleId\": \"${APP_ID}\", \"staple\": true};type=application/json'" https://cbi.eclipse.org/macos/xcrun/notarize)

# fund uuid and status
[[ $RESPONSE =~ $UUID_REGEX ]]
UUID=${BASH_REMATCH[1]}
[[ $RESPONSE =~ $STATUS_REGEX ]]
STATUS=${BASH_REMATCH[1]}

# poll progress
echo "  Progress: $RESPONSE"
while [[ $STATUS == 'IN_PROGRESS' ]]; do
    sleep 120
    RESPONSE=$(ssh -q genie.theia@projects-storage.eclipse.org curl -s https://cbi.eclipse.org/macos/xcrun/${UUID}/status)
    [[ $RESPONSE =~ $STATUS_REGEX ]]
    STATUS=${BASH_REMATCH[1]}
    echo "  Progress: $RESPONSE"
done

if [[ $STATUS != 'COMPLETE' ]]; then
    echo "Notarization failed: $RESPONSE"
    exit 1
fi

# download stapled result
ssh -q genie.theia@projects-storage.eclipse.org curl -o "\"stapled-${REMOTE_NAME}\"" https://cbi.eclipse.org/macos/xcrun/${UUID}/download

# copy stapled file back from server
scp -T -p genie.theia@projects-storage.eclipse.org:"\"./stapled-${REMOTE_NAME}\"" "${INPUT}"

# ensure storage server is clean
ssh -q genie.theia@projects-storage.eclipse.org rm -f "\"${REMOTE_NAME}\"" "\"stapled-${REMOTE_NAME}\"" entitlements.plist

# if unzip needed
if [ "$NEEDS_UNZIP" = true ]; then
    unzip -qq "${INPUT}"

    if [ $? -ne 0 ]; then
        # echo contents if unzip failed
        output=$(cat $INPUT)
        echo "$output"
        exit 1
    fi

    rm -f "${INPUT}"
fi


================================================
FILE: applications/electron/scripts/sign-directory-windows.ts
================================================
/********************************************************************************
 * Copyright (C) 2026 EclipseSource and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License, which is available in the project root.
 *
 * SPDX-License-Identifier: MIT
 ********************************************************************************/

import child_process from 'child_process';
import fs from 'fs';
import path from 'path';
import { hideBin } from 'yargs/helpers';
import yargs from 'yargs/yargs';
import { formatBytes, replaceWithSigned, walkFiles } from './sign-utils';

/**
 * Sign Windows binaries inside an electron-builder `--dir` output (`win-unpacked`) by uploading
 * each `.exe` to the Eclipse Authenticode signing service and writing the signed result back in
 * place. The traversal must mirror the roots that electron-builder's `winPackager.signApp()`
 * would sign: the top level of the unpacked directory, `resources/app.asar.unpacked/` and
 * `swiftshader/`. The filter (`.exe` only) matches electron-builder's default `shouldSignFile`
 * when `win.signExts` is unset.
 */

const DEFAULT_SIGN_URL = 'https://cbi.eclipse.org/authenticode/sign';

const argv = yargs(hideBin(process.argv))
    .option('directory', {
        alias: 'd',
        type: 'string',
        demandOption: true,
        description: 'The electron-builder `--dir` output directory (e.g. dist/win-unpacked) containing the unpacked Windows app'
    })
    .option('url', {
        alias: 'u',
        type: 'string',
        default: DEFAULT_SIGN_URL,
        description: 'The URL of the Authenticode signing service'
    })
    .version(false)
    .wrap(120)
    .parseSync();

function isExeFile(filePath: string): boolean {
    return path.extname(filePath).toLowerCase() === '.exe';
}

/**
 * Collect files to sign by reproducing electron-builder's `winPackager.signApp()` traversal:
 *  1. Top-level files directly under `<dir>/` (no recursion)
 *  2. Recursive walk of `<dir>/resources/app.asar.unpacked/`
 *  3. Recursive walk of `<dir>/swiftshader/` (if present)
 */
function collectFilesToSign(unpackedDir: string): string[] {
    const topLevel = walkFiles(unpackedDir, isExeFile, { shallow: true });
    const asarUnpacked = walkFiles(path.join(unpackedDir, 'resources', 'app.asar.unpacked'), isExeFile);
    const swiftshader = walkFiles(path.join(unpackedDir, 'swiftshader'), isExeFile);
    return [...topLevel, ...asarUnpacked, ...swiftshader];
}

function signFile(file: string, url: string): void {
    const signedPath = `${file}.signed`;
    // Remove any stale signed file from a previous run
    if (fs.existsSync(signedPath)) {
        fs.unlinkSync(signedPath);
    }

    const before = fs.statSync(file);
    console.log(`Signing ${file} (${formatBytes(before.size)})...`);

    const started = Date.now();
    const result = child_process.spawnSync(
        'curl',
        ['-sSf', '-o', signedPath, '-F', `file=@${file}`, url],
        { stdio: ['ignore', 'pipe', 'pipe'], encoding: 'utf-8' }
    );
    const durationMs = Date.now() - started;

    if (result.error) {
        throw new Error(`Failed to invoke curl for ${file}: ${result.error.message}`);
    }
    if (result.status !== 0) {
        // Dump whatever curl produced to help diagnose. If curl wrote a non-binary error payload to
        // `signedPath` (e.g. an HTML/JSON error page from the signing service), log that too.
        if (result.stdout) {
            console.error(`curl stdout:\n${result.stdout}`);
        }
        if (result.stderr) {
            console.error(`curl stderr:\n${result.stderr}`);
        }
        if (fs.existsSync(signedPath)) {
            try {
                const body = fs.readFileSync(signedPath, 'utf-8');
                console.error(`Response body written to ${signedPath}:\n${body}`);
            } catch {
                // Ignore read errors on binary/garbage content
            }
            try {
                fs.unlinkSync(signedPath);
            } catch {
                // Best-effort cleanup
            }
        }
        throw new Error(`Signing failed for ${file}: curl exited with status ${result.status}`);
    }

    if (!fs.existsSync(signedPath)) {
        throw new Error(`Signing failed for ${file}: no output file produced at ${signedPath}`);
    }

    const signedSize = fs.statSync(signedPath).size;
    if (signedSize === 0) {
        fs.unlinkSync(signedPath);
        throw new Error(`Signing failed for ${file}: signed output is empty`);
    }

    replaceWithSigned(file, signedPath);
    console.log(`  -> signed in ${durationMs} ms (${formatBytes(signedSize)})`);
}

function main(): void {
    const directory = path.resolve(argv.directory);
    const url = argv.url;

    if (!fs.existsSync(directory) || !fs.statSync(directory).isDirectory()) {
        console.error(`Directory does not exist or is not a directory: ${directory}`);
        process.exit(1);
    }

    console.log(`sign-directory-windows: directory=${directory}; url=${url}`);

    const files = collectFilesToSign(directory);
    if (files.length === 0) {
        // Having zero files usually means the app layout changed and our walk roots no longer
        // match what electron-builder would sign. Fail so this is caught in CI rather than
        // silently shipping an unsigned binary.
        console.error(
            `No .exe files found under ${directory} in any of the expected roots (top level, ` +
            'resources/app.asar.unpacked, swiftshader). This likely indicates a change in the ' +
            'electron-builder output layout that sign-directory-windows has not been updated for.'
        );
        process.exit(1);
    }

    console.log(`Found ${files.length} file(s) to sign:`);
    for (const file of files) {
        console.log(`  - ${path.relative(directory, file)}`);
    }

    const overallStarted = Date.now();
    for (const file of files) {
        signFile(file, url);
    }
    const overallDuration = Date.now() - overallStarted;

    console.log(`Signed ${files.length} file(s) in ${overallDuration} ms.`);
}

main();


================================================
FILE: applications/electron/scripts/sign-directory.ts
================================================
/********************************************************************************
 * Copyright (C) 2025 EclipseSource and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License, which is available in the project root.
 *
 * SPDX-License-Identifier: MIT
 ********************************************************************************/

import { hideBin } from 'yargs/helpers';
import yargs from 'yargs/yargs';
import path from 'path';
import fs from 'fs';
import child_process from 'child_process';
import { walkFiles } from './sign-utils';

const signCommand = path.join(__dirname, 'sign.sh');
const notarizeCommand = path.join(__dirname, 'notarize.sh');
const entitlements = path.resolve(__dirname, '..', 'entitlements.plist');

// File extensions and patterns that need code signing on macOS
const BINARY_EXTENSIONS = ['.dylib', '.so', '.node', '.framework'];
const BINARY_PATTERNS = [
    /^MacOS\//, // Executable files in MacOS directory
    /^Contents\/MacOS\//, // Executable files in Contents/MacOS directory
];
const EXECUTABLE_NAMES = [
    'node', 'electron', 'rg', 'macos-trash', 'chrome-sandbox'
];

// Function to check if a file is likely a binary that needs signing
function isBinaryFile(filePath: string): boolean {
    const extension = path.extname(filePath);
    const fileName = path.basename(filePath);
    const relativePath = filePath.replace(/^.*?\.app\//, ''); // Get path relative to .app bundle

    // Check by extension
    if (BINARY_EXTENSIONS.includes(extension)) {
        return true;
    }

    // Check by executable name
    if (EXECUTABLE_NAMES.includes(fileName)) {
        return true;
    }

    // Check by pattern
    for (const pattern of BINARY_PATTERNS) {
        if (pattern.test(relativePath)) {
            return true;
        }
    }

    // Check if file is executable (Unix-only check)
    try {
        const stat = fs.statSync(filePath);
        if ((stat.mode & 0o111) !== 0) { // Check if execute bit is set
            // Further verify it's a binary with 'file' command if available
            try {
                const fileType = child_process.execSync(`file "${filePath}"`).toString();
                return fileType.includes('Mach-O') ||
                       fileType.includes('executable') ||
                       fileType.includes('shared library') ||
                       fileType.includes('dynamically linked');
            } catch (e) {
                // If 'file' command fails, fall back to assuming it's a binary if it has execute permission
                return true;
            }
        }
    } catch (e) {
        // If stat fails, skip this check
    }

    return false;
}

// Function to recursively find binaries in a directory
function findBinariesToSign(dirPath: string): string[] {
    const result = walkFiles(dirPath, isBinaryFile, { skipDirs: ['node_modules', '.git'] });

    // Sort by path depth (deepest first) to ensure nested binaries are signed first
    return result.sort((a, b) => {
        const aDepth = a.split(path.sep).length;
        const bDepth = b.split(path.sep).length;
        return bDepth - aDepth;
    });
}

const signFile = (file: string) => {
    const stat = fs.lstatSync(file);
    const mode = stat.isFile() ? stat.mode : undefined;

    // Get SHA hash of file before signing - only for actual files, not directories
    let shaBeforeSigning: string | undefined;
    if (stat.isFile()) {
        shaBeforeSigning = child_process.execSync(`shasum -a 256 "${file}"`).toString().trim();
    }

    console.log(`Signing ${file}...`);
    child_process.spawnSync(signCommand, [
        path.basename(file),
        entitlements
    ], {
        cwd: path.dirname(file),
        maxBuffer: 1024 * 10000,
        env: process.env,
        stdio: 'inherit',
        encoding: 'utf-8'
    });

    // Get SHA hash of file after signing - only for actual files, not directories
    if (stat.isFile()) {
        const shaAfterSigning = child_process.execSync(`shasum -a 256 "${file}"`).toString().trim();
        // Log a warning if the SHA hash hasn't changed after signing
        if (shaBeforeSigning === shaAfterSigning) {
            console.warn(`WARNING: SHA hash did not change after signing for ${file}. This might indicate the file was not properly signed.`);
        }
    }

    if (mode) {
        console.log(`Setting attributes of ${file}...`);
        fs.chmodSync(file, mode);
    }
};

const argv = yargs(hideBin(process.argv))
    .option('directory', { alias: 'd', type: 'string', default: 'dist', description: 'The directory which contains the application to be signed' })
    .version(false)
    .wrap(120)
    .parseSync();

execute();

async function execute(): Promise<void> {
    console.log(`signCommand: ${signCommand}; notarizeCommand: ${notarizeCommand}; entitlements: ${entitlements}; directory: ${argv.directory}`);

    // First sign all individual binaries inside the app bundle
    const binariesToSign = findBinariesToSign(argv.directory);

    for (const binaryPath of binariesToSign) {
        signFile(binaryPath);
    }

    // Then sign the main app bundle
    console.log('Signing main application bundle...');
    signFile(argv.directory);

    // Notarize app
    console.log('Notarizing application...');
    child_process.spawnSync(notarizeCommand, [
        path.basename(argv.directory),
        'eclipse.theia'
    ], {
        cwd: path.dirname(argv.directory),
        maxBuffer: 1024 * 10000,
        env: process.env,
        stdio: 'inherit',
        encoding: 'utf-8'
    });
}


================================================
FILE: applications/electron/scripts/sign-utils.ts
================================================
/********************************************************************************
 * Copyright (C) 2026 EclipseSource and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License, which is available in the project root.
 *
 * SPDX-License-Identifier: MIT
 ********************************************************************************/

import fs from 'fs';
import path from 'path';

export interface WalkOptions {
    /** Directory names to skip entirely while recursing (e.g. `['node_modules', '.git']`). */
    skipDirs?: string[];
    /** If true, do not recurse into subdirectories - only list direct children. Default: false. */
    shallow?: boolean;
}

/**
 * Recursively walks `root` and returns all file paths for which `filter` returns `true`.
 * If `root` does not exist, returns an empty array.
 */
export function walkFiles(root: string, filter: (file: string) => boolean, opts: WalkOptions = {}): string[] {
    const result: string[] = [];
    if (!fs.existsSync(root)) {
        return result;
    }
    const skipDirs = new Set(opts.skipDirs ?? []);

    const visit = (currentPath: string): void => {
        const entries = fs.readdirSync(currentPath, { withFileTypes: true });
        for (const entry of entries) {
            const fullPath = path.join(currentPath, entry.name);
            if (entry.isDirectory()) {
                if (skipDirs.has(entry.name)) {
                    continue;
                }
                if (opts.shallow) {
                    continue;
                }
                visit(fullPath);
            } else if (entry.isFile() && filter(fullPath)) {
                result.push(fullPath);
            }
        }
    };

    visit(root);
    return result;
    }

/**
 * Replaces `originalPath` with `signedPath` on disk, preserving the file mode of the original.
 * On POSIX `renameSync` atomically replaces the destination, so no separate unlink is needed.
 */
export function replaceWithSigned(originalPath: string, signedPath: string): void {
    const originalMode = fs.statSync(originalPath).mode;
    fs.renameSync(signedPath, originalPath);
    fs.chmodSync(originalPath, originalMode);
}

/** Format a byte count as a human-readable string (e.g. `12.3 MB`). */
export function formatBytes(bytes: number): string {
    if (!Number.isFinite(bytes) || bytes < 0) {
        return `${bytes}`;
    }
    const units = ['B', 'KB', 'MB', 'GB', 'TB'];
    let value = bytes;
    let unitIndex = 0;
    while (value >= 1024 && unitIndex < units.length - 1) {
        value /= 1024;
        unitIndex++;
    }
    return `${value.toFixed(unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`;
}


================================================
FILE: applications/electron/scripts/sign.sh
================================================
#!/bin/bash -x

# Enable debug output
set -x

INPUT=$1
ENTITLEMENTS=$2
NEEDS_UNZIP=false

echo "=== DEBUG: Starting signing process for $INPUT ==="

# if folder, zip it
if [ -d "${INPUT}" ]; then
    echo "=== DEBUG: Input is a directory, zipping it ==="
    NEEDS_UNZIP=true
    zip -r -q -y unsigned.zip "${INPUT}"
    rm -rf "${INPUT}"
    INPUT=unsigned.zip
fi

# copy file to storage server
echo "=== DEBUG: Copying $INPUT to storage server ==="
scp -p "${INPUT}" genie.theia@projects-storage.eclipse.org:./
if [ $? -eq 0 ]; then
    echo "=== DEBUG: Successfully copied $INPUT to storage server ==="
else
    echo "=== ERROR: Failed to copy $INPUT to storage server ==="
    exit 1
fi
rm -f "${INPUT}"

# copy entitlements to storage server
echo "=== DEBUG: Copying entitlements file to storage server ==="
scp -p "${ENTITLEMENTS}" genie.theia@projects-storage.eclipse.org:./entitlements.plist
if [ $? -eq 0 ]; then
    echo "=== DEBUG: Successfully copied entitlements to storage server ==="
else
    echo "=== ERROR: Failed to copy entitlements to storage server ==="
    exit 1
fi

# name to use on server
REMOTE_NAME=${INPUT##*/}

# sign over ssh
# https://wiki.eclipse.org/IT_Infrastructure_Doc#Web_service
ssh -q genie.theia@projects-storage.eclipse.org curl -f -o "\"signed-${REMOTE_NAME}\"" -F file=@"\"${REMOTE_NAME}\"" -F entitlements=@entitlements.plist https://cbi.eclipse.org/macos/codesign/sign
if [ $? -eq 0 ]; then
    echo "=== DEBUG: Remote signing completed successfully ==="
else
    echo "=== ERROR: Remote signing failed ==="
    # Try to get error information
    ssh -q genie.theia@projects-storage.eclipse.org "cat \"signed-${REMOTE_NAME}\" || echo 'No output file found'"
    exit 1
fi

# copy signed file back from server
echo "=== DEBUG: Copying signed file back from storage server ==="
scp -T -p genie.theia@projects-storage.eclipse.org:"\"./signed-${REMOTE_NAME}\"" "${INPUT}"
if [ $? -eq 0 ]; then
    echo "=== DEBUG: Successfully retrieved signed file ==="
else
    echo "=== ERROR: Failed to retrieve signed file ==="
    exit 1
fi

# Check if the file was actually signed
echo "=== DEBUG: Verifying if file was signed properly ==="
if [ -f "${INPUT}" ]; then
    # Get file size to verify it's not empty
    FILE_SIZE=$(stat -f%z "${INPUT}" 2>/dev/null || stat -c%s "${INPUT}" 2>/dev/null)
    echo "=== DEBUG: Signed file size: $FILE_SIZE bytes ==="
    
    # On macOS, we can verify code signature
    if [[ "$OSTYPE" == "darwin"* ]]; then
        echo "=== DEBUG: Checking code signature with codesign -vv ==="
        codesign -vv "${INPUT}" || echo "=== WARNING: codesign verification failed ==="
    fi
else
    echo "=== ERROR: Signed file not found ==="
    exit 1
fi

# ensure storage server is clean
echo "=== DEBUG: Cleaning up remote files ==="
ssh -q genie.theia@projects-storage.eclipse.org rm -f "\"${REMOTE_NAME}\"" "\"signed-${REMOTE_NAME}\"" entitlements.plist
echo "=== DEBUG: Remote cleanup completed ==="

# if unzip needed
if [ "$NEEDS_UNZIP" = true ]; then
    echo "=== DEBUG: Unzipping signed archive ==="
    unzip -qq "${INPUT}"

    if [ $? -ne 0 ]; then
        # echo contents if unzip failed
        echo "=== ERROR: Unzip failed, showing file contents ==="
        output=$(cat $INPUT)
        echo "$output"
        exit 1
    fi

    echo "=== DEBUG: Unzip successful, removing zip file ==="
    rm -f "${INPUT}"

    # Perform deep codesign check on the directory if running on macOS
    if [[ "$OSTYPE" == "darwin"* ]]; then
        echo "=== DEBUG: Performing deep codesign verification on directory ==="
        # Check if spctl is available (macOS security assessment tool)
        if command -v spctl &> /dev/null; then
            # Check if the directory is an app bundle
            if [[ -d "$1" && "$1" == *.app ]]; then
                echo "=== DEBUG: Verifying app bundle with spctl --assess --verbose ==="
                spctl --assess --verbose "$1" || echo "=== WARNING: App bundle verification failed, may not pass notarization ==="
            fi
        fi
        
        # Find all binary files and check their signatures
        echo "=== DEBUG: Checking individual binary signatures in $1 ==="
        find "$1" -type f -exec file {} \; | grep -E "Mach-O|dylib" | cut -d: -f1 | while read binary; do
            echo "Checking signature for $binary"
            codesign --verify --deep --strict --verbose=2 "$binary" || echo "=== WARNING: Binary $binary has signature issues, may not pass notarization ==="
            
            # Check for hardened runtime
            codesign -d --verbose=4 "$binary" 2>&1 | grep -q 'Runtime Version=10.0.0' || echo "=== WARNING: Binary $binary may not have hardened runtime enabled ==="
        done
    fi
fi

echo "=== DEBUG: Signing process completed for $1 ==="

================================================
FILE: applications/electron/scripts/theia-electron-main.js
================================================
const path = require('path');
const fs = require('fs');
const os = require('os');
const { copyBundledPlugins } = require('./appimage-helpers');

// Update to override the supported VS Code API version.
// process.env.VSCODE_API_VERSION = '1.50.0'

// Detect if running as AppImage
const isAppImage = !!process.env.APPIMAGE;

// When packaged with asar, __dirname is inside app.asar (e.g., .../app.asar/scripts)
// but plugins are in extraResources at .../app/plugins (outside the asar)
const isInsideAsar = __dirname.includes('.asar');
const bundledPluginsDir = isInsideAsar
    ? path.join(process.resourcesPath, 'app', 'plugins')
    : path.resolve(__dirname, '../', 'plugins');

if (isAppImage) {
    // When running as AppImage, use a user-writable directory for the built-in plugins
    // The AppImage mount point (/tmp/.mount_*) is read-only
    const configDir = process.env.THEIA_CONFIG_DIR || path.join(os.homedir(), '.theia-ide');
    const userPluginsDir = path.join(configDir, 'builtInPlugins');
    const packageJsonPath = path.resolve(__dirname, '../', 'package.json');
    const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
    const currentVersion = packageJson.version;

    // Copy bundled plugins to user directory if needed (first run or version update)
    const useUserDir = copyBundledPlugins(bundledPluginsDir, userPluginsDir, currentVersion);
    // If copying fails, fall back to the read-only bundled directory (will be improved in follow up of GH-630)
    process.env.THEIA_DEFAULT_PLUGINS = `local-dir:${useUserDir ? userPluginsDir : bundledPluginsDir}`;

} else {
    // Use a set of builtin plugins in our application.
    process.env.THEIA_DEFAULT_PLUGINS = `local-dir:${bundledPluginsDir}`;
}

// Handover to the auto-generated electron application handler.
require('../lib/backend/electron-main.js');


================================================
FILE: applications/electron/scripts/update-blockmap.ts
================================================
/********************************************************************************
 * Copyright (C) 2023 EclipseSource and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License, which is available in the project root.
 *
 * SPDX-License-Identifier: MIT
 ********************************************************************************/

import { hideBin } from 'yargs/helpers';
import yargs from 'yargs/yargs';
import { executeAppBuilderAsJson } from 'app-builder-lib/out/util/appBuilder';
// eslint-disable-next-line import/no-extraneous-dependencies
import { BlockMapDataHolder } from 'builder-util-runtime';
import { rmSync } from 'fs';
import * as path from 'path';

const BLOCK_MAP_FILE_SUFFIX = '.blockmap';

const argv = yargs(hideBin(process.argv))
    .option('executable', { alias: 'e', type: 'string', default: 'TheiaIDE.exe', description: 'The executable for which the blockmap needs to be updated' })
    .version(false)
    .wrap(120)
    .parseSync();

execute();

async function execute(): Promise<void> {
    const executable = argv.executable;
    const executablePath = path.resolve(
        __dirname,
        '../dist/',
        executable
    );
    const blockMapFile = `${executablePath}${BLOCK_MAP_FILE_SUFFIX}`;

    console.log(`Exe: ${executablePath}; Blockmap: ${blockMapFile}`);

    rmSync(blockMapFile, {
        force: true,
    });
    await executeAppBuilderAsJson<BlockMapDataHolder>(['blockmap', '--input', executablePath, '--output', blockMapFile]);
};


================================================
FILE: applications/electron/scripts/update-checksum.ts
================================================
/********************************************************************************
 * Copyright (C) 2021 EclipseSource and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License, which is available in the project root.
 *
 * SPDX-License-Identifier: MIT
 ********************************************************************************/
import * as crypto from 'crypto';
import * as fs from 'fs';
import * as jsyaml from 'js-yaml';
import * as path from 'path';
import { hideBin } from 'yargs/helpers';
import yargs from 'yargs/yargs';

const argv = yargs(hideBin(process.argv))
    .option('executable', { alias: 'e', type: 'string', default: 'TheiaIDE.AppImage', description: 'The executable for which the checksum needs to be updated' })
    .option('yaml', { alias: 'y', type: 'string', default: 'latest-linux.yml', description: 'The yaml file where the checksum needs to be updated' })
    .option('platform', { alias: 'p', type: 'string', default: 'linux', description: 'The OS platform' })
    .option('updatepaths', { alias: 'u', type: 'boolean', default: true, description: 'Whether to update the paths from absolute to relative' })
    .option('fileextension', { alias: 'f', type: 'string', default: '.AppImage', description: 'Only paths/urls with this extension will be updated' })
    .version(false)
    .wrap(120)
    .parseSync();

execute();

async function execute(): Promise<void> {
    const executable = argv.executable;
    const yaml = argv.yaml;
    const platform = argv.platform;
    const updatePaths = argv.updatepaths;
    const fileExtension = argv.fileextension;

    const executablePath = path.resolve(
        __dirname,
        '../dist/',
        executable
    );

    const yamlPath = path.resolve(
        __dirname,
        '../dist/',
        yaml
    );

    console.log(`Exe: ${executablePath}; Yaml: ${yamlPath}; Platform: ${platform}; Update Paths: ${updatePaths}; File Extension: ${fileExtension}`);

    const hash = await hashFile(executablePath, 'sha512', 'base64', {});
    const size = fs.statSync(executablePath).size;

    const yamlContents: string = fs.readFileSync(yamlPath, { encoding: 'utf8' });
    console.log(`Initial Yaml Contents: ${yamlContents}`);
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const latestYaml: any = jsyaml.safeLoad(yamlContents);

    if (latestYaml.path.endsWith(fileExtension)) {
        latestYaml.sha512 = hash;
        if (updatePaths) {
            latestYaml.path = updatedPath(latestYaml.path, latestYaml.version, platform);
        }
    }

    for (const file of latestYaml.files) {
        if (file.url.endsWith(fileExtension)) {
            file.sha512 = hash;
            file.size = size;
            if (updatePaths) {
                file.url = updatedPath(file.url, latestYaml.version, platform);
            }
        }
    }

    // line width -1 to avoid adding >- on long strings like a hash
    const newYamlContents = jsyaml.dump(latestYaml, { lineWidth: -1 });
    console.log(`New Yaml Contents: ${newYamlContents}`);
    fs.writeFileSync(yamlPath, newYamlContents);
}

function hashFile(file: fs.PathLike, algorithm = 'sha512', encoding: BufferEncoding = 'base64', options: string | {
    flags?: string;
    encoding?: BufferEncoding;
    fd?: number;
    mode?: number;
    autoClose?: boolean;
    emitClose?: boolean;
    start?: number;
    end?: number;
    highWaterMark?: number;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
}): Promise<any> {
    return new Promise((resolve, reject) => {
        const hash = crypto.createHash(algorithm);
        hash.on('error', reject).setEncoding(encoding);
        fs.createReadStream(
            file,
            Object.assign({}, options, {
                highWaterMark: 1024 * 1024,
            })
        )
            .on('error', reject)
            .on('end', () => {
                hash.end();
                resolve(hash.read());
            })
            .pipe(
                hash,
                {
                    end: false,
                }
            );
    });
}

function updatedPath(toUpdate: string, version: string, platform: string): string {
    const extensionIndex = toUpdate.lastIndexOf('.');
    return '../../' + version + '/' + platform + '/' + toUpdate.substring(0, extensionIndex) + '-' + version + toUpdate.substring(extensionIndex);
}


================================================
FILE: applications/electron/test/app.spec.js
================================================
const os = require('os');
const path = require('path');
const fs = require('fs');
const { execSync } = require('child_process');
const { remote } = require('webdriverio');
const { expect } = require('chai');

const THEIA_LOAD_TIMEOUT = 15000; // 15 seconds

// Set environment variable to disable splash screen (works with asar packaging)
process.env.THEIA_NO_SPLASH = '1';

// Resolve the application directory from cwd so this spec can be shared across products
const appDir = process.cwd();

// Directory for saving screenshots on failure or for debugging
const screenshotDir = path.join(appDir, 'test-screenshots');
if (!fs.existsSync(screenshotDir)) {
  fs.mkdirSync(screenshotDir, { recursive: true });
}

async function saveScreenshot(browser, name) {
  try {
    const filePath = path.join(screenshotDir, `${name}.png`);
    await browser.saveScreenshot(filePath);
    console.log(`Screenshot saved: ${filePath}`);
  } catch (err) {
    console.error(`Failed to save screenshot "${name}":`, err.message);
  }
}
const builderConfig = fs.readFileSync(path.join(appDir, 'electron-builder.yml'), 'utf8');
const productName = builderConfig.match(/^productName:\s*(.+)$/m)[1].trim();
const packageName = require(path.join(appDir, 'package.json')).name;

function isMacArm() {
  if (os.platform() !== 'darwin') {
    return false;
  }
  try {
    // Check the architecture using uname -m
    const arch = execSync('uname -m').toString().trim();
    return arch === 'arm64';
  } catch (error) {
    // Fall back to node's arch property if uname fails
    return os.arch() === 'arm64';
  }
}

function getBinaryPath() {
  const distFolder = path.join(appDir, 'dist');
  switch (os.platform()) {
    case 'linux':
      return path.join(distFolder, 'linux-unpacked', packageName);
    case 'win32':
      return path.join(distFolder, 'win-unpacked', `${productName}.exe`);
    case 'darwin':
      const macFolder = isMacArm() ? 'mac-arm64' : 'mac';
      const binaryPath = path.join(
        distFolder, macFolder, `${productName}.app`, 'Contents', 'MacOS', productName
      );
      console.log(`Using binary path for Mac ${isMacArm() ? 'ARM64' : 'Intel'}: ${binaryPath}`);
      return binaryPath;
    default:
      return undefined;
  }
};

// Utility for keyboard shortcuts that execute commands where
// the key combination is the same on all platforms *except that*
// the Command key is used instead of Control on MacOS. Note that
// sometimes MacOS also uses Control. This is not handled, here
function macSafeKeyCombo(keys) {
  if (os.platform() === 'darwin' && keys.includes('Control')) {
    // Puppeteer calls the Command key "Meta"
    return keys.map(k => k === 'Control' ? 'Meta' : k);
  }
  return keys;
};

describe('Theia App', function () {
  // In mocha, 'this' is a common context between sibling beforeEach, afterEach, it, etc methods within the same describe.
  // Each describe has its own context.
  beforeEach(async function () {

    const binary = getBinaryPath();
    if (!binary) {
      throw new Error('Tests are not supported for this platform.');
    }

    // Start app and store connection in context (this)
    this.browser = await remote({
      // Change to info to get detailed events of webdriverio
      logLevel: 'info',
      capabilities: {
        browserName: 'chrome',
        'goog:chromeOptions': {
          // Path to built and packaged theia
          binary: binary,
          // Hand in workspace to load as runtime parameter
          args: [path.join(appDir, 'test', 'workspace')],
        },
      },
    });

    const appShell = await this.browser.$('#theia-app-shell');

    // mocha waits for returned promise to resolve
    // Theia is loaded once the app shell is present
    await appShell.waitForExist({
      timeout: THEIA_LOAD_TIMEOUT,
      timeoutMsg: 'Theia took too long to load.',
    });

    // If workspace trust dialog appears, trust the workspace
    const dialog = await this.browser.$('.dialogOverlay.workspace-trust-dialog');
    const dialogAppeared = await dialog.waitForExist({ timeout: 5000 }).catch(() => false);

    if (dialogAppeared) {
      // Click the main action button to trust the workspace
      const trustButton = await this.browser.$('.dialogOverlay.workspace-trust-dialog .dialogControl button.theia-button.main');
      const buttonClickable = await trustButton.waitForClickable({ timeout: 2000 }).catch(() => false);
      if (buttonClickable) {
        await trustButton.click();
        // Wait for dialog to close
        await dialog.waitForExist({ timeout: 2000, reverse: true }).catch(() => { });
      }
    }
  });

  afterEach(async function () {
    // Save screenshot on test failure for debugging CI issues
    if (this.currentTest.state === 'failed') {
      const testName = this.currentTest.title.replace(/\s+/g, '-').toLowerCase();
      await saveScreenshot(this.browser, `FAILED-${testName}`);
    }

    const CLOSE_TIMEOUT = 10000; // 10 seconds
    try {
      await Promise.race([
        this.browser.closeWindow(),
        new Promise(resolve => setTimeout(resolve, CLOSE_TIMEOUT))
      ]);
    } catch (err) {
      // Workaround: Puppeteer cannot properly connect to electron and throws an error.
      // However, the window is closed and that's all we want here.
      if (`${err}`.includes('Protocol error (Target.createTarget)')) {
        return;
      }
      // Rethrow for unexpected errors to fail test.
      throw err;
    }
  });

  it('Correct window title', async function () {
    // Wait a bit to make sure workspace is set and title got updated
    await new Promise(r => setTimeout(r, 2000));
    const windowTitle = await this.browser.getTitle();
    expect(windowTitle).to.include('workspace');
  });

  it('Builtin extensions', async function () {
    // Wait a bit to make sure key handlers are registered.
    await new Promise(r => setTimeout(r, 5000));

    // Open extensions view
    await this.browser.keys(macSafeKeyCombo(['Control', 'Shift', 'x']));
    const builtinContainer = await this.browser.$(
      '#vsx-extensions-view-container--vsx-extensions\\:builtin'
    );

    // Expand builtin extensions
    const builtinHeader = await builtinContainer.$('.theia-header.header');
    await builtinHeader.moveTo({ xOffset: 1, yOffset: 1 });
    await builtinHeader.waitForDisplayed();
    await builtinHeader.waitForClickable();
    await builtinHeader.click();

    // Wait for expansion to finish (plugins may take time to scan, especially with asar packaging)
    const builtin = await this.browser.$(
      '#vsx-extensions\\:builtin .theia-TreeContainer'
    );
    await builtin.waitForExist({ timeout: 10000 });

    // Get names of all builtin extensions
    const extensions = await builtin.$$('.theia-vsx-extension .name');
    const extensionNames = await Promise.all(
      extensions.map(e => e.getText())
    );

    // Exemplary check a few extensions
    expect(extensionNames).to.include('Debugger for Java');
    expect(extensionNames).to.include('TypeScript and JavaScript Language Features (built-in)');
  });

  it('Search in workspace', async function () {
    // Wait a bit to make sure key handlers are registered
    await new Promise(r => setTimeout(r, 5000));

    // Open search view (Ctrl+Shift+F)
    await this.browser.keys(macSafeKeyCombo(['Control', 'Shift', 'f']));

    // Wait for search input to appear
    const searchInput = await this.browser.$('#search-input-field');
    await searchInput.waitForExist({ timeout: 5000 });
    await searchInput.waitForDisplayed();

    // Search for text that exists in the test workspace README.md
    await searchInput.setValue('Test Workspace');

    // Wait for search results to appear
    const searchResults = await this.browser.$('.t-siw-search-container .resultLine');
    await searchResults.waitForExist({ timeout: 10000, timeoutMsg: 'Search results did not appear. Ripgrep may not be working correctly with asar packaging.' });

    // Verify we got results
    const resultsText = await searchResults.getText();
    expect(resultsText).to.include('Test Workspace');
  });

  it('Quick file open', async function () {
    // Wait a bit to make sure key handlers are registered
    await new Promise(r => setTimeout(r, 5000));

    // Open quick file picker (Ctrl+P)
    await this.browser.keys(macSafeKeyCombo(['Control', 'p']));

    // Wait for quick input to appear
    const quickInput = await this.browser.$('.quick-input-widget');
    await quickInput.waitForExist({ timeout: 5000 });
    await quickInput.waitForDisplayed();

    // Type filename to search for
    const inputBox = await this.browser.$('.quick-input-box input');
    await inputBox.waitForExist({ timeout: 5000 });
    await inputBox.setValue('README');

    // Wait for file to appear in results
    const fileResult = await this.browser.$('.quick-input-list-row');
    await fileResult.waitForExist({ timeout: 10000, timeoutMsg: 'Quick file open results did not appear. Ripgrep may not be working correctly with asar packaging.' });

    // Verify README.md appears in results
    const resultLabel = await this.browser.$('.quick-input-list-label');
    const labelText = await resultLabel.getText();
    expect(labelText.toLowerCase()).to.include('readme');
  });

  it('Integrated terminal', async function () {
    // Wait a bit to make sure key handlers are registered
    await new Promise(r => setTimeout(r, 5000));

    // Create a new terminal (Ctrl+Shift+`) to ensure it is focused and visible,
    // even when the terminal manager uses tabbed layout in the bottom panel.
    await this.browser.keys(['Control', 'Shift', '`']);

    // Wait for terminal widget to appear
    const terminal = await this.browser.$('.xterm');
    await terminal.waitForExist({ timeout: 10000, timeoutMsg: 'Terminal did not open. PTY may not be working correctly with asar packaging.' });
    await terminal.waitForDisplayed();

    // Verify terminal is visible
    const isDisplayed = await terminal.isDisplayed();
    expect(isDisplayed).to.equal(true);
  });
});


================================================
FILE: applications/electron/test/workspace/README.md
================================================
# Test Workspace

This is the test workspace for E2E tests.


================================================
FILE: applications/electron/tsconfig.eslint.json
================================================
{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "noEmit": true
    },
    "include": [
      "./scripts",
      "./test"
    ]
  }
  

================================================
FILE: applications/electron/tsconfig.json
================================================
{
    "extends": "../../configs/base.tsconfig",
    "include": [],
    "compilerOptions": {
      "composite": true,
      "esModuleInterop": true
    },
    "references": [
      {
        "path": "../../theia-extensions/launcher"
      },
      {
        "path": "../../theia-extensions/product"
      },
      {
        "path": "../../theia-extensions/updater"
      }
    ]
}


================================================
FILE: applications/electron/webpack.config.js
================================================
/**
 * This file can be edited to customize webpack configuration.
 * To reset delete this file and rerun theia build again.
 */
// @ts-check
const configs = require('./gen-webpack.config.js');
const nodeConfig = require('./gen-webpack.node.config.js');
const TerserPlugin = require('terser-webpack-plugin');
const fs = require('fs');
const path = require('path');

/**
 * Webpack plugin to patch the bundled ripgrep path for asar compatibility.
 * When packaged with asar, __dirname resolves inside app.asar but the native binaries
 * are extracted to app.asar.unpacked via asarUnpack.
 *
 * The native-webpack-plugin bundles ripgrep path resolution directly into main.js,
 * so we need to patch the bundle after emit to add asar path rewriting.
 */
class PatchRipgrepPlugin {
    apply(compiler) {
        compiler.hooks.afterEmit.tapAsync('PatchRipgrepPlugin', (compilation, callback) => {
            const mainJsPath = path.join(compiler.outputPath, 'main.js');
            if (fs.existsSync(mainJsPath)) {
                let content = fs.readFileSync(mainJsPath, 'utf8');

                // Match the ripgrep path.join(__dirname, ...) call regardless of how
                // the path module is referenced or how the result is exported.
                // Webpack output varies across modes:
                //   Production (minified):  i.join(__dirname,"./native/rg"+("win32"===...))
                //   Dev (harmony):          (__webpack_require__(/*! path */ "path").join)(__dirname, `./native/rg${...}`)
                //   Dev (CommonJS):         path.join(__dirname, `./native/rg${...}`)
                // The .join call may be direct (EXPR.join(...)) or parenthesized ((EXPR.join)(...)).
                // Both string concat (prod) and template literal (dev) arg forms are matched.
                const rgSuffix = `("win32"===process.platform?".exe":"")`;
                const prodArgs = /["']\.\/native\/rg["']\s*\+\s*\(["']win32["']\s*===\s*process\.platform\s*\?\s*["']\.exe["']\s*:\s*["']["']\s*\)/;
                const devArgs = /`\.\/native\/rg\$\{process\.platform\s*===\s*['"]win32['"]\s*\?\s*['"]\.exe['"]\s*:\s*['"]['"]}\s*`/;
                // Match both EXPR.join(__dirname, ARGS) and (EXPR.join)(__dirname, ARGS)
                // Use [^=,;\n] (not \s) to allow spaces in webpack comments like /*! path */
                const joinCall = (argsPattern) => new RegExp(`\\(?[^=,;\\n]+?\\.join\\)?\\(\\s*__dirname\\s*,\\s*${argsPattern.source}\\s*\\)`, 'g');
                const prodPattern = joinCall(prodArgs);
                const devPattern = joinCall(devArgs);

                let patched = false;
                const patchFn = (match) => {
                    patched = true;
                    return `(()=>{const _p=require("path"),_r=_p.join(__dirname,"./native/rg"+${rgSuffix});return _r.includes(".asar"+_p.sep)?_r.replace(".asar"+_p.sep,".asar.unpacked"+_p.sep):_r})()`;
                };

                let newContent = content.replace(prodPattern, patchFn);
                if (!patched) {
                    newContent = content.replace(devPattern, patchFn);
                }

                if (patched) {
                    fs.writeFileSync(mainJsPath, newContent);
                    console.log('Patched main.js ripgrep path for asar compatibility');
                } else {
                    const idx = content.indexOf('rgPath');
                    if (idx !== -1) {
                        console.error('Could not patch ripgrep path. Context around rgPath:');
                        console.error(content.substring(Math.max(0, idx - 200), idx + 300));
                    }
                    throw new Error('Could not find ripgrep pattern to patch in main.js. The pattern may have changed in @theia/native-webpack-plugin.');
                }
            }
            callback();
        });
    }
}

/**
 * Expose bundled modules on window.theia.moduleName namespace, e.g.
 * window['theia']['@theia/core/lib/common/uri'].
 * Such syntax can be used by external code, for instance, for testing.
configs[0].module.rules.push({
    test: /\.js$/,
    loader: require.resolve('@theia/application-manager/lib/expose-loader')
}); */

/**
 * Do no run TerserPlugin with parallel: true
 * Each spawned node may take the full memory configured via NODE_OPTIONS / --max_old_space_size
 * In total this may lead to OOM issues
 */
if (nodeConfig.config.optimization) {
    nodeConfig.config.optimization.minimizer = [
        new TerserPlugin({
            parallel: false,
            exclude: /^(lib|builtins)\//,
            terserOptions: {
                keep_classnames: /AbortSignal/
            }
        })
    ];
}
for (const config of configs) {
    config.optimization = {
        minimizer: [
            new TerserPlugin({
                parallel: false
            })
        ]
    };
}

// Add the ripgrep patch plugin to the node config
nodeConfig.config.plugins = nodeConfig.config.plugins || [];
nodeConfig.config.plugins.push(new PatchRipgrepPlugin());

module.exports = [
    ...configs,
    nodeConfig.config
];

================================================
FILE: applications/electron-next/.eslintrc.js
================================================
/** @type {import('eslint').Linter.Config} */
module.exports = {
    extends: [
        '../../configs/build.eslintrc.json'
    ],
    parserOptions: {
        tsconfigRootDir: __dirname,
        project: 'tsconfig.eslint.json'
    }
};


================================================
FILE: applications/electron-next/electron-builder.yml
================================================
appId: eclipse.theia.next
productName: TheiaIDENext
copyright: Copyright © 2020-2025 Eclipse Foundation, Inc
electronDist: ../../node_modules/electron/dist
electronVersion: 39.8.7
asar: true
asarUnpack:
  - "**/lib/backend/native/**"
  - "**/lib/backend/shell-integrations/**"
  - "**/lib/build/Release/**"
  - "**/lib/prebuilds/**"
nodeGypRebuild: false
npmRebuild: false

directories:
  buildResources: resources

# node_modules and package.json are copied automatically
# Exclude node_modules manually because electron is copied by electron-builder and we are using a bundled backend
files:
  - src-gen
  - lib
  - resources/icons/WindowIcon/512-512.png
  - resources/TheiaIDENextSplash.svg
  - scripts
  - "!**node_modules/**"
extraResources:
  - from: ../../plugins
    to: app/plugins

linux:
  icon: resources/icons/LinuxLauncherIcons
  category: Development
  mimeTypes:
    - inode/directory
  vendor: Eclipse Foundation, Inc
  target:
    - deb
    - AppImage

deb:
  artifactName: ${productName}.${ext}
appImage:
  artifactName: ${productName}.${ext}

afterPack: ./scripts/after-pack.js


================================================
FILE: applications/electron-next/package.json
================================================
{
  "private": true,
  "name": "theia-ide-next-electron-app",
  "description": "Eclipse Theia IDE Next product",
  "productName": "Theia IDE Next",
  "version": "1.71.100",
  "main": "scripts/theia-electron-main.js",
  "license": "MIT",
  "author": "Eclipse Theia <theia-dev@eclipse.org>",
  "homepage": "https://github.com/eclipse-theia/theia-ide#readme",
  "bugs": {
    "url": "https://github.com/eclipse-theia/theia/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/eclipse-theia/theia-ide.git"
  },
  "engines": {
    "yarn": ">=1.7.0 <2",
    "node": ">=22"
  },
  "theia": {
    "target": "electron",
    "frontend": {
      "config": {
        "applicationName": "Theia IDE Next",
        "brandingVariant": "next",
        "availableUpdateChannels": [
          "next"
        ],
        "reloadOnReconnect": true,
        "preferences": {
          "toolbar.showToolbar": true,
          "updates.channel": "next",
          "ai-features.chat.tokenUsageIndicator.enabled": true
        },
        "electron": {
          "uriScheme": "theia-next",
          "showWindowEarly": false,
          "splashScreenOptions": {
            "content": "resources/TheiaIDENextSplash.svg",
            "height": 276,
            "width": 446
          }
        }
      }
    },
    "backend": {
      "config": {
        "frontendConnectionTimeout": -1,
        "startupTimeout": -1,
        "resolveSystemPlugins": false,
        "configurationFolder": ".theia-ide-next"
      }
    },
    "generator": {
      "config": {
        "preloadTemplate": "./resources/preload.html"
      }
    }
  },
  "dependencies": {
    "@theia/ai-anthropic": "1.72.0-next.20",
    "@theia/ai-chat": "1.72.0-next.20",
    "@theia/ai-chat-ui": "1.72.0-next.20",
    "@theia/ai-claude-code": "1.72.0-next.20",
    "@theia/ai-code-completion": "1.72.0-next.20",
    "@theia/ai-codex": "1.72.0-next.20",
    "@theia/ai-copilot": "1.72.0-next.20",
    "@theia/ai-core": "1.72.0-next.20",
    "@theia/ai-core-ui": "1.72.0-next.20",
    "@theia/ai-editor": "1.72.0-next.20",
    "@theia/ai-google": "1.72.0-next.20",
    "@theia/ai-history": "1.72.0-next.20",
    "@theia/ai-huggingface": "1.72.0-next.20",
    "@theia/ai-ide": "1.72.0-next.20",
    "@theia/ai-llamafile": "1.72.0-next.20",
    "@theia/ai-mcp": "1.72.0-next.20",
    "@theia/ai-mcp-server": "1.72.0-next.20",
    "@theia/ai-mcp-ui": "1.72.0-next.20",
    "@theia/ai-ollama": "1.72.0-next.20",
    "@theia/ai-openai": "1.72.0-next.20",
    "@theia/ai-scanoss": "1.72.0-next.20",
    "@theia/ai-terminal": "1.72.0-next.20",
    "@theia/ai-vercel-ai": "1.72.0-next.20",
    "@theia/bulk-edit": "1.72.0-next.20",
    "@theia/callhierarchy": "1.72.0-next.20",
    "@theia/collaboration": "1.72.0-next.20",
    "@theia/console": "1.72.0-next.20",
    "@theia/core": "1.72.0-next.20",
    "@theia/debug": "1.72.0-next.20",
    "@theia/dev-container": "1.72.0-next.20",
    "@theia/editor": "1.72.0-next.20",
    "@theia/editor-preview": "1.72.0-next.20",
    "@theia/electron": "1.72.0-next.20",
    "@theia/external-terminal": "1.72.0-next.20",
    "@theia/file-search": "1.72.0-next.20",
    "@theia/filesystem": "1.72.0-next.20",
    "@theia/getting-started": "1.72.0-next.20",
    "@theia/keymaps": "1.72.0-next.20",
    "@theia/markers": "1.72.0-next.20",
    "@theia/memory-inspector": "1.72.0-next.20",
    "@theia/messages": "1.72.0-next.20",
    "@theia/metrics": "1.72.0-next.20",
    "@theia/mini-browser": "1.72.0-next.20",
    "@theia/monaco": "1.72.0-next.20",
    "@theia/navigator": "1.72.0-next.20",
    "@theia/notebook": "1.72.0-next.20",
    "@theia/outline-view": "1.72.0-next.20",
    "@theia/output": "1.72.0-next.20",
    "@theia/plugin-dev": "1.72.0-next.20",
    "@theia/plugin-ext": "1.72.0-next.20",
    "@theia/plugin-ext-vscode": "1.72.0-next.20",
    "@theia/preferences": "1.72.0-next.20",
    "@theia/preview": "1.72.0-next.20",
    "@theia/process": "1.72.0-next.20",
    "@theia/property-view": "1.72.0-next.20",
    "@theia/remote": "1.72.0-next.20",
    "@theia/remote-wsl": "1.72.0-next.20",
    "@theia/scanoss": "1.72.0-next.20",
    "@theia/scm": "1.72.0-next.20",
    "@theia/search-in-workspace": "1.72.0-next.20",
    "@theia/secondary-window": "1.72.0-next.20",
    "@theia/task": "1.72.0-next.20",
    "@theia/terminal": "1.72.0-next.20",
    "@theia/terminal-manager": "1.72.0-next.20",
    "@theia/test": "1.72.0-next.20",
    "@theia/timeline": "1.72.0-next.20",
    "@theia/toolbar": "1.72.0-next.20",
    "@theia/typehierarchy": "1.72.0-next.20",
    "@theia/userstorage": "1.72.0-next.20",
    "@theia/variable-resolver": "1.72.0-next.20",
    "@theia/vsx-registry": "1.72.0-next.20",
    "@theia/workspace": "1.72.0-next.20",
    "fs-extra": "^9.1.0",
    "theia-ide-launcher-ext": "1.71.100",
    "theia-ide-product-ext": "1.71.100",
    "theia-ide-updater-ext": "1.71.100"
  },
  "devDependencies": {
    "@theia/cli": "1.72.0-next.20",
    "@theia/bundle-plugin": "1.72.0-next.20",
    "@types/js-yaml": "^3.12.10",
    "@types/yargs": "17.0.7",
    "@wdio/cli": "^6.12.1",
    "@wdio/local-runner": "^6.12.1",
    "@wdio/mocha-framework": "^6.11.0",
    "@wdio/spec-reporter": "^6.11.0",
    "app-builder-lib": "26.0.12",
    "chai": "^4.5.0",
    "concurrently": "^3.6.1",
    "electron": "39.8.7",
    "electron-builder": "26.0.12",
    "electron-chromedriver": "^28.3.3",
    "electron-mocha": "^12.3.1",
    "electron-osx-sign": "^0.6.0",
    "js-yaml": "^3.14.2",
    "mocha": "^8.4.0",
    "rimraf": "^2.7.1",
    "ts-node": "^10.9.2",
    "wdio-chromedriver-service": "^6.0.4",
    "webdriverio": "^6.12.1",
    "yargs": "17.2.1"
  },
  "scripts": {
    "clean": "theia clean && rimraf node_modules",
    "clean:dist": "rimraf dist",
    "build": "yarn -s rebuild && theia build --app-target=\"electron\" --mode development",
    "build:prod": "yarn -s rebuild && theia build --app-target=\"electron\"",
    "rebuild": "theia rebuild:electron --cacheRoot ../..",
    "watch": "concurrently -n compile,build \"theiaext watch --preserveWatchOutput\" \"theia build --watch --mode development\"",
    "start": "electron scripts/theia-electron-main.js --plugins=local-dir:../../plugins",
    "start:debug": "yarn start --log-level=debug",
    "package": "yarn clean:dist && yarn rebuild && electron-builder -c.mac.identity=null --publish never",
    "package:prod": "yarn deploy",
    "deploy": "yarn clean:dist && yarn rebuild && electron-builder -c.mac.identity=null --publish always",
    "package:preview": "yarn clean:dist && yarn rebuild && electron-builder -c.mac.identity=null --dir",
    "update:theia": "ts-node ../../scripts/update-theia-version.ts",
    "update:next": "ts-node ../../scripts/update-theia-version.ts next",
    "test": "mocha --timeout 60000 \"../electron/test/*.spec.js\"",
    "lint": "eslint --ext js,jsx,ts,tsx scripts",
    "lint:fix": "eslint --ext js,jsx,ts,tsx scripts --fix"
  }
}

================================================
FILE: applications/electron-next/resources/LICENSE
================================================
MIT License

Copyright (c) 2026 Eclipse Theia IDE Authors

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

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

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


================================================
FILE: applications/electron-next/resources/preload.html
================================================
<!DOCTYPE html>
<html lang="en">

<head>
    <style>
        html,
        body {
            background-color: black;
        }

        .theia-preload {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            /* Above styles copied from https://github.com/eclipse-theia/theia/blob/5aeef6c0c683b4e91713ab736957e6655b486adc/packages/core/src/browser/style/index.css#L147-L151 */
            /* Otherwise, there is a flickering when Theia's CSS loads. */

            background-image: none;
        }

        .theia-preload::after {
            /* remove default loading animation */
            content: none;
        }

        .spinner-container {
            display: flex;
            flex-direction: center;
            align-self: center;
            justify-content: center;
            height: 100vh;
            width: 100vw;
        }

        .custom-spinner {
            align-self: center;
        }

        .custom-spinner svg {
            width: 16vw;
            height: 16vh;
            animation-delay: 0;
            animation-duration: 2s;
            animation-iteration-count: infinite;
            animation-name: theia-ide-spinner;
            animation-timing-function: ease;
        }

        @keyframes theia-ide-spinner {
            0% {
                filter: brightness(1) saturate(1);
                transform: scale(1.0);
            }

            50% {
                filter: brightness(1.35) saturate(0.75);
                transform: scale(0.8);
            }

            100% {
                filter: brightness(1) saturate(1);
                transform: scale(1.0);
            }
        }
    </style>
</head>

<body>
    <div class='spinner-container'>
        <div class='custom-spinner'>
            <svg id="spinner" version="1.1" xmlns="http://www.w3.org/2000/svg"
                xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" preserveAspectRatio="xMinYMin meet"
                viewBox="0, 0, 1150, 540.6">
                <g id="Layer_1" fill="#8B5CF6">
                    <path
                        d="M880.199,2.8 C1028.1,2.8 1147.9,122.6 1147.9,270.5 C1147.9,418.3 1028.1,538.2 880.2,538.2 L290.1,538.2 C269,538.2 251.9,521.1 251.9,500 C251.9,478.9 269,461.8 290.1,461.8 L427.6,461.8 C448.6,461.8 465.7,444.7 465.7,423.6 C465.7,402.5 448.6,385.4 427.6,385.4 L396.999,385.4 C375.9,385.4 358.8,368.3 358.8,347.2 C358.8,326.1 375.9,309 397,309 L488.703,309 C509.918,308.941 526.373,291.65 526.9,270.8 C526.9,249.7 509.8,232.6 488.7,232.6 L167.8,232.6 C146.7,232.6 129.6,215.5 129.6,194.4 C129.6,173.3 146.7,156.2 167.8,156.2 L404.604,156.2 C425.818,156.141 442.273,138.85 442.8,118 C442.8,96.9 425.7,79.8 404.6,79.8 L351.2,79.8 C330.1,79.8 313,62.7 313,41.6 C313,20.5 330.1,2.4 351.2,2.4 L880.199,2.8 z M837.4,92 L837.4,92 C755.2,92 688.7,158.6 688.7,240.7 L688.7,300.2 C688.7,382.4 755.2,448.9 837.4,448.9 C919.5,448.9 986.1,382.4 986.1,300.2 L986.1,240.7 C986.1,158.6 919.5,92 837.4,92 L837.4,92 z M888.2,232.6 C908,232.6 924.1,248.7 924.1,268.5 L924.1,273.1 C924.1,292.9 908,309 888.2,309 L776.6,309 C756.8,309 740.7,292.9 740.7,273.1 L740.7,268.5 C740.7,248.7 756.8,232.6 776.6,232.6 L888.2,232.6 z" />
                    <path
                        d="M170.1,461.8 C190,461.8 206,477.8 206,497.7 L206,502.3 C206,522.1 190,538.2 170.1,538.2 L38,538.2 C18.2,538.2 2.1,522.1 2.1,502.3 L2.1,497.7 C2.1,477.8 18.2,461.8 38,461.8 L170.1,461.8 z" />
                    <path
                        d="M231.3,3.4 C251.1,3.4 267.1,19.5 267.1,39.3 L267.1,44 C267.1,63.8 251.1,79.8 231.3,79.8 L83.8,79.8 C64,79.8 47.9,63.8 47.9,44 L47.9,39.3 C47.9,19.5 64,3.4 83.8,3.4 L231.3,3.4 z" />
                    <path
                        d="M277.1,309 C296.9,309 313,325.1 313,344.9 L313,349.5 C313,369.3 296.9,385.4 277.1,385.4 L196.1,385.4 C176.3,385.4 160.2,369.3 160.2,349.5 L160.2,344.9 C160.2,325.1 176.3,309 196.1,309 L277.1,309 z" />
                </g>
            </svg>
        </div>
    </div>
</body>

</html>


================================================
FILE: applications/electron-next/scripts/after-pack.js
================================================
#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

// Signing and notarizing are not needed for the Next product
// (it is not built on Jenkins as a full release).
// Only the Linux sandbox fix is required for AppImage builds.

// taken and modified from: https://github.com/gergof/electron-builder-sandbox-fix/blob/a2251d7d8f22be807d2142da0cf768c78d4cfb0a/lib/index.js
exports.default = async function (context) {
    if (context.electronPlatformName !== 'linux') {
        return;
    }
    const executable = path.join(
        context.appOutDir,
        context.packager.executableName
    );

    const loaderScript = `#!/usr/bin/env bash
set -u
SCRIPT_DIR="$( cd "$( dirname "\${BASH_SOURCE[0]}" )" && pwd )"
exec "$SCRIPT_DIR/${context.packager.executableName}.bin" "--no-sandbox" "$@"
`;

    try {
        await fs.promises.rename(executable, executable + '.bin');
        await fs.promises.writeFile(executable, loaderScript);
        await fs.promises.chmod(executable, 0o755);
    } catch (e) {
        throw new Error('Failed to create loader for sandbox fix:\n' + e);
    }
};


================================================
FILE: applications/electron-next/scripts/appimage-helpers.js
================================================
const fs = require('fs');
const path = require('path');

/**
 * Reads the plugin copy metadata file and returns its content.
 * @param metadataPath - Path to the metadata file
 * @returns The metadata object or undefined if not found
 */
function readPluginCopyMetadata(metadataPath) {
    if (!fs.existsSync(metadataPath)) {
        return undefined;
    }
    try {
        return JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
    } catch (err) {
        console.warn('Could not read built-in plugin copy metadata file:', err.message);
        return undefined;
    }
}

/**
 * Writes the plugin copy metadata file with version and timestamp.
 * @param metadataPath - Path to the metadata file
 * @param version - Current version
 */
function writePluginCopyMetadata(metadataPath, version) {
    const metadata = {
        version: version,
        copiedAt: new Date().toISOString()
    };
    fs.writeFileSync(metadataPath, JSON.stringify(metadata, undefined, 2));
}

/**
 * Copies bundled plugins from AppImage to user directory if needed.
 * @param bundledPluginsDir - Path to bundled plugins in AppImage
 * @param userPluginsDir - Path to user built-in plugins directory
 * @param currentVersion - Current Theia IDE version
 * @returns true if the builtins were copied to the user dir, false if there was an error
 */
function copyBundledPlugins(bundledPluginsDir, userPluginsDir, currentVersion) {
    const metadataFile = path.join(userPluginsDir, '.builtInPlugins-metadata');

    // Ensure the user plugins directory exists
    if (!fs.existsSync(userPluginsDir)) {
        fs.mkdirSync(userPluginsDir, { recursive: true });
    }

    // Check if built-in plugins need to be copied
    const metadata = readPluginCopyMetadata(metadataFile);
    let shouldCopy = false;

    if (!metadata) {
        shouldCopy = true;
    } else if (metadata.version !== currentVersion) {
        console.log(`Theia IDE updated from ${metadata.version} to ${currentVersion}. Updating built-in plugins...`);
        shouldCopy = true;
    }

    if (!shouldCopy) {
        console.log('Built-in plugins were already copied.');
        return true;
    }

    console.log(`Copying bundled plugins from AppImage to ${userPluginsDir}...`);
    try {
        // Clean existing plugins directory to remove old/obsolete plugins
        fs.rmSync(userPluginsDir, { recursive: true, force: true });
        fs.mkdirSync(userPluginsDir, { recursive: true });

        const pluginEntries = fs.readdirSync(bundledPluginsDir, { withFileTypes: true });
        for (const entry of pluginEntries) {
            const srcPath = path.join(bundledPluginsDir, entry.name);
            const destPath = path.join(userPluginsDir, entry.name);
            fs.cpSync(srcPath, destPath, { recursive: true });
        }
        writePluginCopyMetadata(metadataFile, currentVersion);
        console.log(`Bundled plugins copied successfully to ${userPluginsDir}.`);
    } catch (err) {
        console.error('Failed to copy bundled plugins:', err.message);
        return false;
    }
    return true;
}

module.exports = {
    copyBundledPlugins,
};


================================================
FILE: applications/electron-next/scripts/theia-electron-main.js
================================================
const path = require('path');
const fs = require('fs');
const os = require('os');
const { copyBundledPlugins } = require('./appimage-helpers');

// Update to override the supported VS Code API version.
// process.env.VSCODE_API_VERSION = '1.50.0'

// Detect if running as AppImage
const isAppImage = !!process.env.APPIMAGE;

// When packaged with asar, __dirname is inside app.asar (e.g., .../app.asar/scripts)
// but plugins are in extraResources at .../app/plugins (outside the asar)
const isInsideAsar = __dirname.includes('.asar');
const bundledPluginsDir = isInsideAsar
    ? path.join(process.resourcesPath, 'app', 'plugins')
    : path.resolve(__dirname, '../', 'plugins');

if (isAppImage) {
    // When running as AppImage, use a user-writable directory for the built-in plugins
    // The AppImage mount point (/tmp/.mount_*) is read-only
    const configDir = process.env.THEIA_CONFIG_DIR || path.join(os.homedir(), '.theia-ide-next');
    const userPluginsDir = path.join(configDir, 'builtInPlugins');
    const packageJsonPath = path.resolve(__dirname, '../', 'package.json');
    const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
    const currentVersion = packageJson.version;

    // Copy bundled plugins to user directory if needed (first run or version update)
    const useUserDir = copyBundledPlugins(bundledPluginsDir, userPluginsDir, currentVersion);
    // If copying fails, fall back to the read-only bundled directory (will be improved in follow up of GH-630)
    process.env.THEIA_DEFAULT_PLUGINS = `local-dir:${useUserDir ? userPluginsDir : bundledPluginsDir}`;

} else {
    // Use a set of builtin plugins in our application.
    process.env.THEIA_DEFAULT_PLUGINS = `local-dir:${bundledPluginsDir}`;
}

// Handover to the auto-generated electron application handler.
require('../lib/backend/electron-main.js');


================================================
FILE: applications/electron-next/test/workspace/README.md
================================================
# Test Workspace

This is the test workspace for E2E tests.


================================================
FILE: applications/electron-next/tsconfig.eslint.json
================================================
{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "noEmit": true
    },
    "include": [
      "./scripts"
    ]
  }


================================================
FILE: applications/electron-next/tsconfig.json
================================================
{
    "extends": "../../configs/base.tsconfig",
    "include": [],
    "compilerOptions": {
      "composite": true,
      "esModuleInterop": true
    },
    "references": [
      {
        "path": "../../theia-extensions/product"
      },
      {
        "path": "../../theia-extensions/updater"
      }
    ]
}


================================================
FILE: applications/electron-next/webpack.config.js
================================================
/**
 * This file can be edited to customize webpack configuration.
 * To reset delete this file and rerun theia build again.
 */
// @ts-check
const configs = require('./gen-webpack.config.js');
const nodeConfig = require('./gen-webpack.node.config.js');
const TerserPlugin = require('terser-webpack-plugin');
const fs = require('fs');
const path = require('path');

/**
 * Webpack plugin to patch the bundled ripgrep path for asar compatibility.
 * When packaged with asar, __dirname resolves inside app.asar but the native binaries
 * are extracted to app.asar.unpacked via asarUnpack.
 *
 * The native-webpack-plugin bundles ripgrep path resolution directly into main.js,
 * so we need to patch the bundle after emit to add asar path rewriting.
 */
class PatchRipgrepPlugin {
    apply(compiler) {
        compiler.hooks.afterEmit.tapAsync('PatchRipgrepPlugin', (compilation, callback) => {
            const mainJsPath = path.join(compiler.outputPath, 'main.js');
            if (fs.existsSync(mainJsPath)) {
                let content = fs.readFileSync(mainJsPath, 'utf8');

                // Match the ripgrep path.join(__dirname, ...) call regardless of how
                // the path module is referenced or how the result is exported.
                // Webpack output varies across modes:
                //   Production (minified):  i.join(__dirname,"./native/rg"+("win32"===...))
                //   Dev (harmony):          (__webpack_require__(/*! path */ "path").join)(__dirname, `./native/rg${...}`)
                //   Dev (CommonJS):         path.join(__dirname, `./native/rg${...}`)
                // The .join call may be direct (EXPR.join(...)) or parenthesized ((EXPR.join)(...)).
                // Both string concat (prod) and template literal (dev) arg forms are matched.
                const rgSuffix = `("win32"===process.platform?".exe":"")`;
                const prodArgs = /["']\.\/native\/rg["']\s*\+\s*\(["']win32["']\s*===\s*process\.platform\s*\?\s*["']\.exe["']\s*:\s*["']["']\s*\)/;
                const devArgs = /`\.\/native\/rg\$\{process\.platform\s*===\s*['"]win32['"]\s*\?\s*['"]\.exe['"]\s*:\s*['"]['"]}\s*`/;
                // Match both EXPR.join(__dirname, ARGS) and (EXPR.join)(__dirname, ARGS)
                // Use [^=,;\n] (not \s) to allow spaces in webpack comments like /*! path */
                const joinCall = (argsPattern) => new RegExp(`\\(?[^=,;\\n]+?\\.join\\)?\\(\\s*__dirname\\s*,\\s*${argsPattern.source}\\s*\\)`, 'g');
                const prodPattern = joinCall(prodArgs);
                const devPattern = joinCall(devArgs);

                let patched = false;
                const patchFn = (match) => {
                    patched = true;
                    return `(()=>{const _p=require("path"),_r=_p.join(__dirname,"./native/rg"+${rgSuffix});return _r.includes(".asar"+_p.sep)?_r.replace(".asar"+_p.sep,".asar.unpacked"+_p.sep):_r})()`;
                };

                let newContent = content.replace(prodPattern, patchFn);
                if (!patched) {
                    newContent = content.replace(devPattern, patchFn);
                }

                if (patched) {
                    fs.writeFileSync(mainJsPath, newContent);
                    console.log('Patched main.js ripgrep path for asar compatibility');
                } else {
                    const idx = content.indexOf('rgPath');
                    if (idx !== -1) {
                        console.error('Could not patch ripgrep path. Context around rgPath:');
                        console.error(content.substring(Math.max(0, idx - 200), idx + 300));
                    }
                    throw new Error('Could not find ripgrep pattern to patch in main.js. The pattern may have changed in @theia/native-webpack-plugin.');
                }
            }
            callback();
        });
    }
}

/**
 * Expose bundled modules on window.theia.moduleName namespace, e.g.
 * window['theia']['@theia/core/lib/common/uri'].
 * Such syntax can be used by external code, for instance, for testing.
configs[0].module.rules.push({
    test: /\.js$/,
    loader: require.resolve('@theia/application-manager/lib/expose-loader')
}); */

/**
 * Do no run TerserPlugin with parallel: true
 * Each spawned node may take the full memory configured via NODE_OPTIONS / --max_old_space_size
 * In total this may lead to OOM issues
 */
if (nodeConfig.config.optimization) {
    nodeConfig.config.optimization.minimizer = [
        new TerserPlugin({
            parallel: false,
            exclude: /^(lib|builtins)\//,
            terserOptions: {
                keep_classnames: /AbortSignal/
            }
        })
    ];
}
for (const config of configs) {
    config.optimization = {
        minimizer: [
            new TerserPlugin({
                parallel: false
            })
        ]
    };
}

// Add the ripgrep patch plugin to the node config
nodeConfig.config.plugins = nodeConfig.config.plugins || [];
nodeConfig.config.plugins.push(new PatchRipgrepPlugin());

module.exports = [
    ...configs,
    nodeConfig.config
];


================================================
FILE: browser.Dockerfile
================================================
# Builder stage
FROM node:24-bookworm AS build-stage

# install required tools to build the application
RUN apt-get update && apt-get install -y libxkbfile-dev libsecret-1-dev

WORKDIR /home/theia

# Copy repository files
COPY . .

# Remove unnecesarry files for the browser application
# Download plugins and build application production mode
# Use yarn autoclean to remove unnecessary files from package dependencies
RUN yarn config set network-timeout 600000 -g && \
    yarn --pure-lockfile && \
    yarn build:extensions && \
    yarn download:plugins && \
    yarn browser build && \
    yarn && \
    yarn autoclean --init && \
    echo *.ts >> .yarnclean && \
    echo *.ts.map >> .yarnclean && \
    echo *.spec.* >> .yarnclean && \
    yarn autoclean --force && \
    yarn cache clean && \
    rm -rf .git applications/electron theia-extensions/launcher theia-extensions/updater node_modules

# Production stage uses a small base image
FROM node:24-bookworm-slim AS production-stage

# Create theia user and directories
# Application will be copied to /home/theia
# Default workspace is located at /home/project
RUN adduser --system --group --home /home/theia theia
RUN chmod g+rw /home && \
    mkdir -p /home/project && \
    chown -R theia:theia /home/theia && \
    chown -R theia:theia /home/project;

# Install required tools for application: Temurin JDK, JDK, SSH, Bash, Maven
# Node is already available in base image
RUN apt-get update && apt-get install -y wget apt-transport-https && \
    apt-get update && apt-get install -y git openssh-client openssh-server bash libsecret-1-0 openjdk-17-jdk maven && \
    apt-get purge -y wget && \
    apt-get clean

ENV HOME=/home/theia
WORKDIR /home/theia

# Copy application from builder-stage
COPY --from=build-stage --chown=theia:theia /home/theia /home/theia

EXPOSE 3000

# Specify default shell for Theia and the Built-In plugins directory
ENV SHELL=/bin/bash \
    THEIA_DEFAULT_PLUGINS=local-dir:/home/theia/plugins

# Use installed git instead of dugite
ENV USE_LOCAL_GIT=true

# Switch to Theia user
USER theia
WORKDIR /home/theia/applications/browser

# Launch the backend application via node
ENTRYPOINT [ "node", "/home/theia/applications/browser/lib/backend/main.js" ]

# Arguments passed to the application
CMD [ "/home/project", "--hostname=0.0.0.0" ]


================================================
FILE: cleanup/Jenkinsfile
================================================
pipeline {
    agent {
        label 'windows'
    }
    triggers { cron('@weekly') }
    options {
        timeout(time: 1, unit: 'HOURS')
        disableConcurrentBuilds()
    }
    stages {
        stage('Cleanup Windows temp directory') {
            steps {
                script {
                    listTemp('before cleanup', '%temp%')
                    cleanFiles('tmp/plugin-download', '%temp%', 'theia-plugin-download**')
                    cleanDirs('tmp/yarn', '%temp%', 'yarn--**')
                    cleanDirs('tmp/lighthouse', '%temp%', 'lighthouse.*')
                    listTemp('after cleanup', '%temp%')
                    cleanDir('appdata/local/electron', '\"%LocalAppData%\"\\electron\\Cache')
                    cleanYarnCache('appdata/local/yarn')
                }
            }
        }
    }
}

Object listTemp(String label, String temp) {
    echo "in listTemp():  ${label}"
    bat "DIR ${temp}"
    return
}

Object cleanFiles(String label, String parent, String pattern) {
    echo "in cleanFile() - clean: ${label} files"
    echo "parent: ${parent}, pattern: ${pattern}"

    // use "returnStatus" option to avoid an exception being thrown if no
    // matching files are found, failing the pipeline
    s = bat(
            script: "FORFILES /p ${parent} /m ${pattern} /C \"cmd /c Del /q @file\"",
            returnStatus: true
        )
    if (s != 0) {
        echo "No ${pattern} file found... Good I guess"
    }
}

Object cleanDirs(String label, String parent, String pattern) {
    echo "Before ${label} Cleanup:"

    bat "FOR /D /R ${parent} %%i in (${pattern}) do echo \"%%i\""
    bat "FOR /D /R ${parent} %%i in (${pattern}) do @rmdir /s /q \"%%i\""

    echo "After ${label} Cleanup:"
    bat "FOR /D /R ${parent} %%i in (${pattern}) do echo \"%%i\""
    return
}

Object cleanDir(String label, String parent) {
    echo "Before ${label} Cleanup:"

    bat "FOR /D /R ${parent} %%i in (*) do echo \"%%i\""
    bat "if exist ${parent} @rmdir /s /q ${parent}"

    echo "After ${label} Cleanup:"
    bat "FOR /D /R ${parent} %%i in (*) do echo \"%%i\""
    return
}

Object cleanYarnCache(String label) {
    echo "Cleaning-up: ${label}"
    sh 'yarn cache clean --all'
    return
}



================================================
FILE: configs/base.eslintrc.json
================================================
{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "sourceType": "module",
    "ecmaVersion": 6,
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "plugins": [
    "@typescript-eslint",
    "@typescript-eslint/tslint",
    "import",
    "no-null"
  ],
  "env": {
    "browser": true,
    "mocha": true,
    "node": true
  },
  "ignorePatterns": [
    "node_modules",
    "lib"
  ]
}


================================================
FILE: configs/base.tsconfig.json
================================================
{
    "compilerOptions": {
        "skipLibCheck": true,
        "declaration": true,
        "declarationMap": true,
        "noImplicitAny": true,
        "noEmitOnError": false,
        "noImplicitThis": true,
        "noUnusedLocals": true,
        "strictNullChecks": true,
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "downlevelIteration": true,
        "resolveJsonModule": true,
        "module": "commonjs",
        "moduleResolution": "node",
        "target": "ES2017",
        "jsx": "react",
        "lib": [
            "ES2017",
            "ES2020.Promise",
            "dom"
        ],
        "sourceMap": true,
        "composite": true
    }
}


================================================
FILE: configs/build.eslintrc.json
================================================
{
  "extends": [
    "./base.eslintrc.json",
    "./errors.eslintrc.json"
  ]
}


================================================
FILE: configs/errors.eslintrc.json
================================================
{
  "$schema": "https://json.schemastore.org/eslintrc",
  "rules": {
    "@typescript-eslint/consistent-type-definitions": "error",
    "@typescript-eslint/indent": "off",
    "@typescript-eslint/no-explicit-any": "error",
    "@typescript-eslint/quotes": [
      "error",
      "single",
      {
        "avoidEscape": true
      }
    ],
    "@typescript-eslint/semi": [
      "error",
      "always"
    ],
    "@typescript-eslint/type-annotation-spacing": "error",
    "arrow-body-style": [
      "error",
      "as-needed"
    ],
    "arrow-parens": [
      "error",
      "as-needed"
    ],
    "camelcase": "off",
    "comma-dangle": "off",
    "curly": "error",
    "eol-last": "error",
    "eqeqeq": [
      "error",
      "smart"
    ],
    "guard-for-in": "error",
    "id-blacklist": "off",
    "id-match": "off",
    "max-len": [
      "error",
      {
        "code": 180
      }
    ],
    "no-magic-numbers": "off",
    "no-multiple-empty-lines": [
      "error",
      {
        "max": 1
      }
    ],
    "no-new-wrappers": "error",
    "no-null/no-null": "error",
    "no-shadow": "off",
    "@typescript-eslint/no-shadow": [
      "error",
      {
        "hoist": "all"
      }
    ],
    "no-tabs": "error",
    "no-throw-literal": "error",
    "no-trailing-spaces": "error",
    "no-underscore-dangle": "off",
    "no-unused-expressions": "error",
    "no-var": "error",
    "no-void": "error",
    "one-var": [
      "error",
      "never"
    ],
    "prefer-const": [
      "error",
      {
        "destructuring": "all"
      }
    ],
    "radix": "off",
    "space-before-function-paren": [
      "error",
      {
        "anonymous": "always",
        "named": "never",
        "asyncArrow": "always"
      }
    ],
    "spaced-comment": [
      "error",
      "always",
      {
        "exceptions": [
          "*",
          "+",
          "-",
          "/"
        ]
      }
    ],
    "@typescript-eslint/tslint/config": [
      "error",
      {
        "rules": {
          "file-header": [
            true,
            "SPDX-License-Identifier: MIT"
          ],
          "jsdoc-format": [
            true,
            "check-multiline-start"
          ],
          "one-line": [
            true,
            "check-open-brace",
            "check-catch",
            "check-else",
            "check-whitespace"
          ],
          "typedef": [
            true,
            "call-signature",
            "property-declaration"
          ],
          "whitespace": [
            true,
            "check-branch",
            "check-decl",
            "check-operator",
            "check-separator",
            "check-type"
          ]
        }
      }
    ],
    "import/no-extraneous-dependencies": "error"
  },
  "overrides": [
    {
      "files": [
        "dev-packages",
        "*.{spec,espec,slow-spec}.{js,ts}"
      ],
      "rules": {
        "import/no-extraneous-dependencies": "off"
      }
    }
  ]
}


================================================
FILE: configs/license-check-config.json
================================================
{
    "project": "ecd.theia",
    "inputFile": "yarn.lock",
    "batch": 50,
    "timeout": 240,
    "summary": "license-check-summary.txt"
}

================================================
FILE: configs/tsconfig.eslint.json
================================================
{
    "extends": "../tsconfig.json",
    "compilerOptions": {
        "noEmit": true
    },
    "include": [
      "../scripts"
    ]
  }
  

================================================
FILE: configs/warnings.eslintrc.json
================================================
{
  "plugins": [
    "deprecation"
  ],
  "rules": {
    "@typescript-eslint/await-thenable": "warn",
    "no-return-await": "warn",
    "deprecation/deprecation": "warn"
  }
}

================================================
FILE: configs/xss.eslintrc.json
================================================
{
  "extends": ["plugin:no-unsanitized/DOM"],
  "plugins": ["no-unsanitized", "react"],
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "rules": {
    "no-unsanitized/method": [
      "warn", {
        "escape": {
          "methods": ["DOMPurify.sanitize"]
        }
      }
    ],
    "no-unsanitized/property
Download .txt
gitextract_jxq8o1lq/

├── .eslintrc.js
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   └── feature_request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── build-next-release.yml
│       ├── build-next.yml
│       ├── build.yml
│       ├── license-check-workflow.yml
│       ├── publish-builder-img.yml
│       └── publish-theia-ide-img.yml
├── .gitignore
├── .vscode/
│   ├── launch.json
│   ├── settings.json
│   └── theia.code-snippets
├── ADOPTER.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── NOTICE.md
├── PUBLISHING.md
├── README.md
├── TheiaIDE logo/
│   └── TheiaIDE.eps
├── applications/
│   ├── browser/
│   │   ├── package.json
│   │   ├── resources/
│   │   │   └── preload.html
│   │   ├── tsconfig.json
│   │   └── webpack.config.js
│   ├── electron/
│   │   ├── .eslintrc.js
│   │   ├── electron-builder.yml
│   │   ├── entitlements.plist
│   │   ├── package.json
│   │   ├── resources/
│   │   │   ├── LICENSE
│   │   │   ├── icon.icns
│   │   │   ├── icons/
│   │   │   │   └── MacLauncherIcons/
│   │   │   │       ├── 512-512-2.icns
│   │   │   │       ├── Theia-16bp-alfa ignored.icns
│   │   │   │       ├── icns-1bit/
│   │   │   │       │   ├── 128-128.icns
│   │   │   │       │   ├── 16-16-1.icns
│   │   │   │       │   ├── 256-256.icns
│   │   │   │       │   ├── 32-32.icns
│   │   │   │       │   ├── 48-48.icns
│   │   │   │       │   └── 512-512-2 copy.icns
│   │   │   │       ├── icns-8bit/
│   │   │   │       │   ├── 128-128.icns
│   │   │   │       │   ├── 16-16.icns
│   │   │   │       │   ├── 256-256.icns
│   │   │   │       │   ├── 32-32.icns
│   │   │   │       │   ├── 48-48.icns
│   │   │   │       │   └── 512-512.icns
│   │   │   │       ├── icon.icns
│   │   │   │       └── icon.icon/
│   │   │   │           └── icon.json
│   │   │   └── preload.html
│   │   ├── scripts/
│   │   │   ├── after-pack.js
│   │   │   ├── appimage-helpers.js
│   │   │   ├── generate-app-update-yml.js
│   │   │   ├── notarize.sh
│   │   │   ├── sign-directory-windows.ts
│   │   │   ├── sign-directory.ts
│   │   │   ├── sign-utils.ts
│   │   │   ├── sign.sh
│   │   │   ├── theia-electron-main.js
│   │   │   ├── update-blockmap.ts
│   │   │   └── update-checksum.ts
│   │   ├── test/
│   │   │   ├── app.spec.js
│   │   │   └── workspace/
│   │   │       └── README.md
│   │   ├── tsconfig.eslint.json
│   │   ├── tsconfig.json
│   │   └── webpack.config.js
│   └── electron-next/
│       ├── .eslintrc.js
│       ├── electron-builder.yml
│       ├── package.json
│       ├── resources/
│       │   ├── LICENSE
│       │   └── preload.html
│       ├── scripts/
│       │   ├── after-pack.js
│       │   ├── appimage-helpers.js
│       │   └── theia-electron-main.js
│       ├── test/
│       │   └── workspace/
│       │       └── README.md
│       ├── tsconfig.eslint.json
│       ├── tsconfig.json
│       └── webpack.config.js
├── browser.Dockerfile
├── cleanup/
│   └── Jenkinsfile
├── configs/
│   ├── base.eslintrc.json
│   ├── base.tsconfig.json
│   ├── build.eslintrc.json
│   ├── errors.eslintrc.json
│   ├── license-check-config.json
│   ├── tsconfig.eslint.json
│   ├── warnings.eslintrc.json
│   └── xss.eslintrc.json
├── docs/
│   └── developing-with-local-theia.md
├── lerna.json
├── next/
│   ├── Jenkinsfile
│   └── NEXT_INTEGRATION_BUILD.md
├── package.json
├── patches/
│   └── @theia+terminal+1.72.0-next.20.patch
├── releng/
│   ├── preview/
│   │   ├── Jenkinsfile.build
│   │   ├── Jenkinsfile.sign
│   │   └── Jenkinsfile.upload
│   └── promote/
│       └── Jenkinsfile
├── scripts/
│   ├── build-with-local-theia.js
│   ├── generate-next-icons.js
│   ├── make-files-writeable.ts
│   └── update-theia-version.ts
├── theia-extensions/
│   ├── launcher/
│   │   ├── .eslintrc.js
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── browser/
│   │   │   │   ├── create-launcher-contribution.ts
│   │   │   │   ├── create-launcher-frontend-module.ts
│   │   │   │   ├── desktopfile-service.ts
│   │   │   │   └── launcher-service.ts
│   │   │   └── node/
│   │   │       ├── desktopfile-endpoint.ts
│   │   │       ├── launcher-backend-module.ts
│   │   │       ├── launcher-endpoint.ts
│   │   │       └── launcher-util.ts
│   │   └── tsconfig.json
│   ├── product/
│   │   ├── .eslintrc.js
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── browser/
│   │   │   │   ├── branding-util.tsx
│   │   │   │   ├── style/
│   │   │   │   │   └── index.css
│   │   │   │   ├── theia-ide-about-dialog.tsx
│   │   │   │   ├── theia-ide-config.ts
│   │   │   │   ├── theia-ide-contribution.tsx
│   │   │   │   ├── theia-ide-frontend-module.ts
│   │   │   │   └── theia-ide-getting-started-widget.tsx
│   │   │   └── electron-main/
│   │   │       ├── icon-contribution.ts
│   │   │       └── theia-ide-main-module.ts
│   │   └── tsconfig.json
│   └── updater/
│       ├── .eslintrc.js
│       ├── package.json
│       ├── src/
│       │   ├── common/
│       │   │   └── updater/
│       │   │       └── theia-updater.ts
│       │   ├── electron-browser/
│       │   │   ├── theia-updater-frontend-module.ts
│       │   │   └── updater/
│       │   │       ├── theia-updater-frontend-contribution.ts
│       │   │       └── theia-updater-preferences.ts
│       │   └── electron-main/
│       │       └── update/
│       │           ├── theia-updater-impl.ts
│       │           └── theia-updater-main-module.ts
│       └── tsconfig.json
└── tsconfig.json
Download .txt
SYMBOL INDEX (174 symbols across 31 files)

FILE: applications/electron-next/scripts/appimage-helpers.js
  function readPluginCopyMetadata (line 9) | function readPluginCopyMetadata(metadataPath) {
  function writePluginCopyMetadata (line 26) | function writePluginCopyMetadata(metadataPath, version) {
  function copyBundledPlugins (line 41) | function copyBundledPlugins(bundledPluginsDir, userPluginsDir, currentVe...

FILE: applications/electron-next/webpack.config.js
  class PatchRipgrepPlugin (line 20) | class PatchRipgrepPlugin {
    method apply (line 21) | apply(compiler) {

FILE: applications/electron/scripts/after-pack.js
  constant DELETE_PATHS (line 11) | const DELETE_PATHS = [

FILE: applications/electron/scripts/appimage-helpers.js
  function readPluginCopyMetadata (line 9) | function readPluginCopyMetadata(metadataPath) {
  function writePluginCopyMetadata (line 26) | function writePluginCopyMetadata(metadataPath, version) {
  function copyBundledPlugins (line 41) | function copyBundledPlugins(bundledPluginsDir, userPluginsDir, currentVe...

FILE: applications/electron/scripts/sign-directory-windows.ts
  constant DEFAULT_SIGN_URL (line 26) | const DEFAULT_SIGN_URL = 'https://cbi.eclipse.org/authenticode/sign';
  function isExeFile (line 45) | function isExeFile(filePath: string): boolean {
  function collectFilesToSign (line 55) | function collectFilesToSign(unpackedDir: string): string[] {
  function signFile (line 62) | function signFile(file: string, url: string): void {
  function main (line 122) | function main(): void {

FILE: applications/electron/scripts/sign-directory.ts
  constant BINARY_EXTENSIONS (line 22) | const BINARY_EXTENSIONS = ['.dylib', '.so', '.node', '.framework'];
  constant BINARY_PATTERNS (line 23) | const BINARY_PATTERNS = [
  constant EXECUTABLE_NAMES (line 27) | const EXECUTABLE_NAMES = [
  function isBinaryFile (line 32) | function isBinaryFile(filePath: string): boolean {
  function findBinariesToSign (line 78) | function findBinariesToSign(dirPath: string): string[] {
  function execute (line 134) | async function execute(): Promise<void> {

FILE: applications/electron/scripts/sign-utils.ts
  type WalkOptions (line 13) | interface WalkOptions {
  function walkFiles (line 24) | function walkFiles(root: string, filter: (file: string) => boolean, opts...
  function replaceWithSigned (line 57) | function replaceWithSigned(originalPath: string, signedPath: string): vo...
  function formatBytes (line 64) | function formatBytes(bytes: number): string {

FILE: applications/electron/scripts/update-blockmap.ts
  constant BLOCK_MAP_FILE_SUFFIX (line 18) | const BLOCK_MAP_FILE_SUFFIX = '.blockmap';
  function execute (line 28) | async function execute(): Promise<void> {

FILE: applications/electron/scripts/update-checksum.ts
  function execute (line 28) | async function execute(): Promise<void> {
  function hashFile (line 80) | function hashFile(file: fs.PathLike, algorithm = 'sha512', encoding: Buf...
  function updatedPath (line 115) | function updatedPath(toUpdate: string, version: string, platform: string...

FILE: applications/electron/test/app.spec.js
  constant THEIA_LOAD_TIMEOUT (line 8) | const THEIA_LOAD_TIMEOUT = 15000;
  function saveScreenshot (line 22) | async function saveScreenshot(browser, name) {
  function isMacArm (line 35) | function isMacArm() {
  function getBinaryPath (line 49) | function getBinaryPath() {
  function macSafeKeyCombo (line 72) | function macSafeKeyCombo(keys) {

FILE: applications/electron/webpack.config.js
  class PatchRipgrepPlugin (line 20) | class PatchRipgrepPlugin {
    method apply (line 21) | apply(compiler) {

FILE: scripts/build-with-local-theia.js
  constant ROOT_DIR (line 31) | const ROOT_DIR = path.resolve(__dirname, '..');
  constant DEFAULT_THEIA_PATH (line 32) | const DEFAULT_THEIA_PATH = path.resolve(ROOT_DIR, '..', 'theia');
  function getArgValue (line 37) | function getArgValue(flag, defaultValue) {
  function run (line 91) | function run(cmd, cwd = ROOT_DIR, description = '') {
  function readJson (line 123) | function readJson(filePath) {
  function getTheiaDependencies (line 130) | function getTheiaDependencies(packageJsonPath) {
  function findTheiaPackages (line 150) | function findTheiaPackages(theiaPath) {
  function collectAllTheiaDependencies (line 177) | function collectAllTheiaDependencies() {
  function buildTheia (line 206) | function buildTheia() {
  function linkTheiaPackages (line 215) | function linkTheiaPackages() {
  function unlinkTheiaPackages (line 275) | function unlinkTheiaPackages() {
  function buildIde (line 305) | function buildIde() {
  function packageApp (line 319) | function packageApp() {
  function main (line 326) | async function main() {

FILE: scripts/generate-next-icons.js
  constant SOURCE_DIR (line 21) | const SOURCE_DIR = path.resolve(__dirname, '../applications/electron/res...
  constant TARGET_DIR (line 22) | const TARGET_DIR = path.resolve(__dirname, '../applications/electron-nex...
  constant ICON_MAPPINGS (line 24) | const ICON_MAPPINGS = [
  constant THEIA_BLUE (line 31) | const THEIA_BLUE = '#00ADEE';
  constant NEXT_PURPLE (line 32) | const NEXT_PURPLE = '#8B5CF6';
  function hasImageMagick (line 34) | function hasImageMagick() {
  function generateWithImageMagick (line 43) | function generateWithImageMagick(srcPath, destPath) {
  function generateWithSharp (line 61) | async function generateWithSharp(srcPath, destPath) {
  function main (line 102) | async function main() {

FILE: scripts/make-files-writeable.ts
  function execute (line 28) | async function execute(): Promise<void> {
  function makeWritable (line 40) | function makeWritable(dir: string): void {

FILE: scripts/update-theia-version.ts
  function execute (line 15) | async function execute(): Promise<void> {
  function updateTheiaVersions (line 44) | function updateTheiaVersions(dependencies: PackageJson.Dependency, theia...

FILE: theia-extensions/launcher/src/browser/create-launcher-contribution.ts
  class CreateLauncherCommandContribution (line 19) | class CreateLauncherCommandContribution implements FrontendApplicationCo...
    method onStart (line 31) | onStart(_app: FrontendApplication): MaybePromise<void> {

FILE: theia-extensions/launcher/src/browser/desktopfile-service.ts
  type DesktopFileOptions (line 13) | interface DesktopFileOptions {
  class DesktopFileService (line 20) | class DesktopFileService {
    method isInitialized (line 22) | async isInitialized(): Promise<boolean> {
    method createOrUpdateDesktopfile (line 30) | async createOrUpdateDesktopfile(create: boolean, options?: DesktopFile...
    method endpoint (line 38) | protected endpoint(): string {

FILE: theia-extensions/launcher/src/browser/launcher-service.ts
  class LauncherService (line 14) | class LauncherService {
    method isInitialized (line 16) | async isInitialized(uriScheme?: string): Promise<boolean> {
    method createLauncher (line 25) | async createLauncher(create: boolean, uriScheme?: string): Promise<voi...
    method endpoint (line 33) | protected endpoint(): string {

FILE: theia-extensions/launcher/src/node/desktopfile-endpoint.ts
  type DesktopFileInformation (line 20) | interface DesktopFileInformation {
  class TheiaDesktopFileServiceEndpoint (line 26) | class TheiaDesktopFileServiceEndpoint implements BackendApplicationContr...
    method configure (line 34) | configure(app: Application): void {
    method isInitialized (line 42) | protected async isInitialized(_request: Request, response: Response): ...
    method readAppImageInformationFromStorage (line 74) | protected async readAppImageInformationFromStorage(storageFile: string...
    method createOrUpdateDesktopfile (line 87) | protected async createOrUpdateDesktopfile(request: Request, response: ...
    method getDesktopFileContents (line 145) | protected getDesktopFileContents(applicationName: string, appImagePath...
    method getDesktopURLFileContents (line 158) | protected getDesktopURLFileContents(applicationName: string, appImageP...

FILE: theia-extensions/launcher/src/node/launcher-endpoint.ts
  type PathEntry (line 21) | interface PathEntry {
  class TheiaLauncherServiceEndpoint (line 27) | class TheiaLauncherServiceEndpoint implements BackendApplicationContribu...
    method configure (line 36) | configure(app: Application): void {
    method isInitialized (line 44) | private async isInitialized(request: Request, response: Response): Pro...
    method readLauncherPathsFromStorage (line 65) | private async readLauncherPathsFromStorage(storageFile: string): Promi...
    method getLogFilePath (line 77) | private async getLogFilePath(): Promise<string> {
    method createLauncher (line 83) | private async createLauncher(request: Request, response: Response): Pr...

FILE: theia-extensions/launcher/src/node/launcher-util.ts
  function getStorageFilePath (line 13) | async function getStorageFilePath(envServer: EnvVariablesServer, fileNam...

FILE: theia-extensions/product/src/browser/branding-util.tsx
  type ExternalBrowserLinkProps (line 14) | interface ExternalBrowserLinkProps {
  function renderProductName (line 20) | function renderProductName(): React.ReactNode {
  function BrowserLink (line 26) | function BrowserLink(props: ExternalBrowserLinkProps): JSX.Element {
  function renderWhatIs (line 37) | function renderWhatIs(windowService: WindowService): React.ReactNode {
  function renderExtendingCustomizing (line 55) | function renderExtendingCustomizing(windowService: WindowService): React...
  function renderSupport (line 73) | function renderSupport(windowService: WindowService): React.ReactNode {
  function renderTickets (line 86) | function renderTickets(windowService: WindowService): React.ReactNode {
  function renderSourceCode (line 107) | function renderSourceCode(windowService: WindowService): React.ReactNode {
  function renderDocumentation (line 120) | function renderDocumentation(windowService: WindowService): React.ReactN...
  function renderCollaboration (line 132) | function renderCollaboration(windowService: WindowService): React.ReactN...
  function renderDownloads (line 147) | function renderDownloads(): React.ReactNode {

FILE: theia-extensions/product/src/browser/theia-ide-about-dialog.tsx
  class TheiaIDEAboutDialog (line 17) | class TheiaIDEAboutDialog extends AboutDialog {
    method constructor (line 27) | constructor(
    method doInit (line 33) | protected async doInit(): Promise<void> {
    method render (line 38) | protected render(): React.ReactNode {
    method renderContent (line 44) | protected renderContent(): React.ReactNode {
    method renderTitle (line 87) | protected renderTitle(): React.ReactNode {
    method renderVersion (line 94) | protected renderVersion(): React.ReactNode {

FILE: theia-extensions/product/src/browser/theia-ide-config.ts
  type BrandingVariant (line 12) | type BrandingVariant = 'stable' | 'next';
  function getBrandingVariant (line 14) | function getBrandingVariant(): BrandingVariant {
  function applyBranding (line 23) | function applyBranding(): void {

FILE: theia-extensions/product/src/browser/theia-ide-contribution.tsx
  class TheiaIDEContribution (line 34) | class TheiaIDEContribution implements CommandContribution, MenuContribut...
    method registerCommands (line 42) | registerCommands(commandRegistry: CommandRegistry): void {
    method registerMenus (line 51) | registerMenus(menus: MenuModelRegistry): void {

FILE: theia-extensions/product/src/browser/theia-ide-getting-started-widget.tsx
  class TheiaIDEGettingStartedWidget (line 24) | class TheiaIDEGettingStartedWidget extends GettingStartedWidget {
    method doInit (line 37) | protected async doInit(): Promise<void> {
    method onActivateRequest (line 44) | protected onActivateRequest(msg: Message): void {
    method render (line 52) | protected render(): React.ReactNode {
    method renderActions (line 119) | protected renderActions(): React.ReactNode {
    method renderHeader (line 144) | protected renderHeader(): React.ReactNode {
    method renderVersion (line 151) | protected renderVersion(): React.ReactNode {
    method renderAIBanner (line 163) | protected renderAIBanner(): React.ReactNode {

FILE: theia-extensions/product/src/electron-main/icon-contribution.ts
  class IconContribution (line 19) | class IconContribution implements ElectronMainApplicationContribution {
    method onStart (line 21) | onStart(application: ElectronMainApplication): void {

FILE: theia-extensions/updater/src/common/updater/theia-updater.ts
  type UpdaterSettings (line 14) | interface UpdaterSettings {
  type TheiaUpdater (line 20) | interface TheiaUpdater extends RpcServer<TheiaUpdaterClient> {
  type UpdaterError (line 31) | interface UpdaterError {
  type UpdateInfo (line 36) | interface UpdateInfo {
  type UpdateAvailabilityInfo (line 40) | interface UpdateAvailabilityInfo {
  type TheiaUpdaterClient (line 45) | interface TheiaUpdaterClient {

FILE: theia-extensions/updater/src/electron-browser/updater/theia-updater-frontend-contribution.ts
  class TheiaUpdaterClientImpl (line 52) | class TheiaUpdaterClientImpl implements TheiaUpdaterClient {
    method notifyReadyToInstall (line 66) | notifyReadyToInstall(): void {
    method updateAvailable (line 70) | updateAvailable(available: boolean, updateInfo?: UpdateInfo): void {
    method reportError (line 74) | reportError(error: UpdaterError): void {
    method reportCancelled (line 78) | reportCancelled(): void {
  class ElectronMenuUpdater (line 86) | class ElectronMenuUpdater {
    method update (line 91) | public update(): void {
    method setMenu (line 95) | private setMenu(): void {
  class TheiaUpdaterFrontendContribution (line 102) | class TheiaUpdaterFrontendContribution implements CommandContribution, M...
    method init (line 129) | protected init(): void {
    method syncUpdaterSettings (line 160) | protected syncUpdaterSettings(): void {
    method registerCommands (line 169) | registerCommands(registry: CommandRegistry): void {
    method registerMenus (line 184) | registerMenus(registry: MenuModelRegistry): void {
    method handleDownloadUpdate (line 193) | protected async handleDownloadUpdate(updateInfo?: UpdateInfo): Promise...
    method handleNoUpdate (line 224) | protected async handleNoUpdate(): Promise<void> {
    method handleUpdatesAvailable (line 228) | protected async handleUpdatesAvailable(): Promise<void> {
    method handleError (line 242) | protected async handleError(error: UpdaterError): Promise<void> {
    method stopProgress (line 257) | private stopProgress(): void {

FILE: theia-extensions/updater/src/electron-browser/updater/theia-updater-preferences.ts
  constant DEFAULT_UPDATE_CHANNELS (line 13) | const DEFAULT_UPDATE_CHANNELS = ['stable', 'preview'];
  function getAvailableUpdateChannels (line 15) | function getAvailableUpdateChannels(): string[] {

FILE: theia-extensions/updater/src/electron-main/update/theia-updater-impl.ts
  constant STABLE_CHANNEL_WINDOWS (line 20) | const STABLE_CHANNEL_WINDOWS = 'https://download.eclipse.org/theia/ide/v...
  constant STABLE_CHANNEL_MACOS (line 21) | const STABLE_CHANNEL_MACOS = 'https://download.eclipse.org/theia/ide/lat...
  constant STABLE_CHANNEL_MACOS_ARM (line 22) | const STABLE_CHANNEL_MACOS_ARM = 'https://download.eclipse.org/theia/ide...
  constant STABLE_CHANNEL_LINUX (line 23) | const STABLE_CHANNEL_LINUX = 'https://download.eclipse.org/theia/ide/lat...
  constant PREVIEW_CHANNEL_WINDOWS (line 25) | const PREVIEW_CHANNEL_WINDOWS = 'https://download.eclipse.org/theia/ide-...
  constant PREVIEW_CHANNEL_MACOS (line 26) | const PREVIEW_CHANNEL_MACOS = 'https://download.eclipse.org/theia/ide-pr...
  constant PREVIEW_CHANNEL_MACOS_ARM (line 27) | const PREVIEW_CHANNEL_MACOS_ARM = 'https://download.eclipse.org/theia/id...
  constant PREVIEW_CHANNEL_LINUX (line 28) | const PREVIEW_CHANNEL_LINUX = 'https://download.eclipse.org/theia/ide-pr...
  constant NEXT_CHANNEL_LINUX (line 32) | const NEXT_CHANNEL_LINUX = 'https://github.com/eclipse-theia/theia-ide/r...
  class TheiaUpdaterImpl (line 40) | class TheiaUpdaterImpl implements TheiaUpdater, ElectronMainApplicationC...
    method constructor (line 54) | constructor() {
    method checkForUpdates (line 87) | checkForUpdates(): void {
    method setUpdaterSettings (line 93) | setUpdaterSettings(settings: UpdaterSettings): void {
    method onRestartToUpdateRequested (line 103) | onRestartToUpdateRequested(): void {
    method cancel (line 107) | cancel(): void {
    method downloadUpdate (line 113) | downloadUpdate(): void {
    method onStart (line 131) | onStart(application: ElectronMainApplication): void {
    method onStop (line 134) | onStop(application: ElectronMainApplication): void {
    method scheduleUpdateChecks (line 138) | private scheduleUpdateChecks(): void {
    method stopUpdateCheckTimer (line 156) | private stopUpdateCheckTimer(): void {
    method setClient (line 163) | setClient(client: TheiaUpdaterClient | undefined): void {
    method getFeedURL (line 173) | protected getFeedURL(channel: string): string {
    method disconnectClient (line 193) | disconnectClient(client: TheiaUpdaterClient): void {
    method dispose (line 200) | dispose(): void {
Condensed preview — 136 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (383K chars).
[
  {
    "path": ".eslintrc.js",
    "chars": 549,
    "preview": "/** @type {import('eslint').Linter.Config} */\nmodule.exports = {\n    root: true,\n    extends: [\n        './configs/base."
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 456,
    "preview": "---\nname: Bug Report\nabout: Create a report to help us improve\n---\n\n<!-- Please provide a detailed description of the bu"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 161,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Question\n    url:  https://github.com/eclipse-theia/theia/discussio"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 255,
    "preview": "---\nname: Feature Request\nabout: Propose an idea for the project\n---\n\n<!-- Please fill out the following content for a f"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 813,
    "preview": "<!--\nThank you for your Pull Request. Please provide a description and review\nthe requirements below.\n\nContributors guid"
  },
  {
    "path": ".github/workflows/build-next-release.yml",
    "chars": 2981,
    "preview": "name: Build Theia IDE Next Release (Linux)\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: \"0 2 * * 1-5\" # Runs every "
  },
  {
    "path": ".github/workflows/build-next.yml",
    "chars": 3629,
    "preview": "name: Build Theia IDE next version\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: \"0 3 * * 1\" # Runs every monday at "
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 5070,
    "preview": "name: Build, package and test\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '**/*.md'\n      - 'The"
  },
  {
    "path": ".github/workflows/license-check-workflow.yml",
    "chars": 3277,
    "preview": "name: 3PP License Check\n\non:\n  push:\n    branches:\n      - master\n    paths:\n      - 'yarn.lock'\n  workflow_dispatch:\n  "
  },
  {
    "path": ".github/workflows/publish-builder-img.yml",
    "chars": 815,
    "preview": "name: Publish builder image\n\non:\n  schedule:\n    - cron: \"0 0 1 * *\" # runs 1st day of every month\n  workflow_dispatch:\n"
  },
  {
    "path": ".github/workflows/publish-theia-ide-img.yml",
    "chars": 1870,
    "preview": "name: Publish Theia IDE Docker Image\n\non:\n  workflow_dispatch:\n    inputs:\n      tag:\n        description: The image's t"
  },
  {
    "path": ".gitignore",
    "chars": 247,
    "preview": ".DS_Store\n**/node_modules\n**/.browser_modules\n**/dist\n**/lib\n**/src-gen\n**/gen-webpack.config.js\n**/gen-webpack.node.con"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 6274,
    "preview": "{\n  // Use IntelliSense to learn about possible Node.js debug attributes.\n  // Hover to view descriptions of existing at"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 97,
    "preview": "{\n    \"[markdown]\": {\n        \"editor.defaultFormatter\": \"davidanson.vscode-markdownlint\"\n    }\n}"
  },
  {
    "path": ".vscode/theia.code-snippets",
    "chars": 687,
    "preview": "{\n    \"Copyright-JS/JSX/TS/TSX/CSS\": {\n        \"prefix\": [\n            \"header\",\n            \"copyright\"\n        ],\n    "
  },
  {
    "path": "ADOPTER.md",
    "chars": 2948,
    "preview": "# Adopter Guide\n\nThis repository serves as a template for building desktop products on the [Eclipse Theia platform](http"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3900,
    "preview": "<div id=\"theia-logo\" align=\"left\">\n    <br />\n    <img src=\"https://raw.githubusercontent.com/eclipse-theia/theia/master"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 4986,
    "preview": "# Contributing to Eclipse Theia\n\nTheia is a young open-source project with a modular architecture. One of the\ngoals is t"
  },
  {
    "path": "Dockerfile",
    "chars": 787,
    "preview": "# See the associated GitHub workflow, that builds and publishes\n# this docker image to Docker Hub:\n# .github/workflows/p"
  },
  {
    "path": "LICENSE",
    "chars": 1082,
    "preview": "MIT License\n\nCopyright (c) 2020 Eclipse Theia IDE Authors\n\nPermission is hereby granted, free of charge, to any person o"
  },
  {
    "path": "NOTICE.md",
    "chars": 8549,
    "preview": "# Notices for Eclipse Theia\n\nThis content is produced and maintained by the Eclipse Theia project.\n\n* Project home: http"
  },
  {
    "path": "PUBLISHING.md",
    "chars": 16067,
    "preview": "# Publishing Guide for the Eclipse Theia IDE\n\nThis document provides a unified, structured guide for publishing a new ve"
  },
  {
    "path": "README.md",
    "chars": 7397,
    "preview": "<br/>\n<div id=\"theia-logo\" align=\"center\">\n    <br />\n    <img src=\"https://raw.githubusercontent.com/eclipse-theia/thei"
  },
  {
    "path": "applications/browser/package.json",
    "chars": 5128,
    "preview": "{\n  \"private\": true,\n  \"name\": \"theia-ide-browser-app\",\n  \"description\": \"Eclipse Theia IDE browser product\",\n  \"product"
  },
  {
    "path": "applications/browser/resources/preload.html",
    "chars": 4491,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <style>\n        html,\n        body {\n            background-color: black;\n "
  },
  {
    "path": "applications/browser/tsconfig.json",
    "chars": 283,
    "preview": "{\n    \"extends\": \"../../configs/base.tsconfig\",\n    \"include\": [],\n    \"compilerOptions\": {\n      \"composite\": true\n    "
  },
  {
    "path": "applications/browser/webpack.config.js",
    "chars": 1028,
    "preview": "/**\n * This file can be edited to customize webpack configuration.\n * To reset delete this file and rerun theia build ag"
  },
  {
    "path": "applications/electron/.eslintrc.js",
    "chars": 237,
    "preview": "/** @type {import('eslint').Linter.Config} */\nmodule.exports = {\n    extends: [\n        '../../configs/build.eslintrc.js"
  },
  {
    "path": "applications/electron/electron-builder.yml",
    "chars": 2320,
    "preview": "appId: eclipse.theia\nproductName: TheiaIDE\ncopyright: Copyright © 2020-2025 Eclipse Foundation, Inc\nelectronDist: ../../"
  },
  {
    "path": "applications/electron/entitlements.plist",
    "chars": 491,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "applications/electron/package.json",
    "chars": 7001,
    "preview": "{\n  \"private\": true,\n  \"name\": \"theia-ide-electron-app\",\n  \"description\": \"Eclipse Theia IDE product\",\n  \"productName\": "
  },
  {
    "path": "applications/electron/resources/LICENSE",
    "chars": 1088,
    "preview": "MIT License\n\nCopyright (c) 2020 Eclipse Theia Blueprint Authors\n\nPermission is hereby granted, free of charge, to any pe"
  },
  {
    "path": "applications/electron/resources/icons/MacLauncherIcons/icon.icon/icon.json",
    "chars": 1778,
    "preview": "{\n  \"fill\" : {\n    \"automatic-gradient\" : \"extended-srgb:0.00000,0.53333,1.00000,1.00000\"\n  },\n  \"groups\" : [\n    {\n    "
  },
  {
    "path": "applications/electron/resources/preload.html",
    "chars": 4253,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <style>\n        html,\n        body {\n            background-color: black;\n "
  },
  {
    "path": "applications/electron/scripts/after-pack.js",
    "chars": 4156,
    "preview": "#!/usr/bin/env node\n\nconst fs = require('fs');\nconst path = require('path');\nconst util = require('util');\nconst child_p"
  },
  {
    "path": "applications/electron/scripts/appimage-helpers.js",
    "chars": 3126,
    "preview": "const fs = require('fs');\nconst path = require('path');\n\n/**\n * Reads the plugin copy metadata file and returns its cont"
  },
  {
    "path": "applications/electron/scripts/generate-app-update-yml.js",
    "chars": 1901,
    "preview": "#!/usr/bin/env node\n\n/********************************************************************************\n * Copyright (C) "
  },
  {
    "path": "applications/electron/scripts/notarize.sh",
    "chars": 1965,
    "preview": "#!/bin/bash -x\n\nINPUT=$1\nAPP_ID=$2\nNEEDS_UNZIP=false\nUUID_REGEX='\"uuid\"\\s*:\\s*\"([^\"]+)'\nSTATUS_REGEX='\"status\"\\s*:\\s*\"(["
  },
  {
    "path": "applications/electron/scripts/sign-directory-windows.ts",
    "chars": 6163,
    "preview": "/********************************************************************************\n * Copyright (C) 2026 EclipseSource an"
  },
  {
    "path": "applications/electron/scripts/sign-directory.ts",
    "chars": 5615,
    "preview": "/********************************************************************************\n * Copyright (C) 2025 EclipseSource an"
  },
  {
    "path": "applications/electron/scripts/sign-utils.ts",
    "chars": 2712,
    "preview": "/********************************************************************************\n * Copyright (C) 2026 EclipseSource an"
  },
  {
    "path": "applications/electron/scripts/sign.sh",
    "chars": 4809,
    "preview": "#!/bin/bash -x\n\n# Enable debug output\nset -x\n\nINPUT=$1\nENTITLEMENTS=$2\nNEEDS_UNZIP=false\n\necho \"=== DEBUG: Starting sign"
  },
  {
    "path": "applications/electron/scripts/theia-electron-main.js",
    "chars": 1859,
    "preview": "const path = require('path');\nconst fs = require('fs');\nconst os = require('os');\nconst { copyBundledPlugins } = require"
  },
  {
    "path": "applications/electron/scripts/update-blockmap.ts",
    "chars": 1551,
    "preview": "/********************************************************************************\n * Copyright (C) 2023 EclipseSource an"
  },
  {
    "path": "applications/electron/scripts/update-checksum.ts",
    "chars": 4440,
    "preview": "/********************************************************************************\n * Copyright (C) 2021 EclipseSource an"
  },
  {
    "path": "applications/electron/test/app.spec.js",
    "chars": 10085,
    "preview": "const os = require('os');\nconst path = require('path');\nconst fs = require('fs');\nconst { execSync } = require('child_pr"
  },
  {
    "path": "applications/electron/test/workspace/README.md",
    "chars": 60,
    "preview": "# Test Workspace\n\nThis is the test workspace for E2E tests.\n"
  },
  {
    "path": "applications/electron/tsconfig.eslint.json",
    "chars": 154,
    "preview": "{\n    \"extends\": \"./tsconfig.json\",\n    \"compilerOptions\": {\n        \"noEmit\": true\n    },\n    \"include\": [\n      \"./scr"
  },
  {
    "path": "applications/electron/tsconfig.json",
    "chars": 380,
    "preview": "{\n    \"extends\": \"../../configs/base.tsconfig\",\n    \"include\": [],\n    \"compilerOptions\": {\n      \"composite\": true,\n   "
  },
  {
    "path": "applications/electron/webpack.config.js",
    "chars": 5108,
    "preview": "/**\n * This file can be edited to customize webpack configuration.\n * To reset delete this file and rerun theia build ag"
  },
  {
    "path": "applications/electron-next/.eslintrc.js",
    "chars": 237,
    "preview": "/** @type {import('eslint').Linter.Config} */\nmodule.exports = {\n    extends: [\n        '../../configs/build.eslintrc.js"
  },
  {
    "path": "applications/electron-next/electron-builder.yml",
    "chars": 1098,
    "preview": "appId: eclipse.theia.next\nproductName: TheiaIDENext\ncopyright: Copyright © 2020-2025 Eclipse Foundation, Inc\nelectronDis"
  },
  {
    "path": "applications/electron-next/package.json",
    "chars": 6947,
    "preview": "{\n  \"private\": true,\n  \"name\": \"theia-ide-next-electron-app\",\n  \"description\": \"Eclipse Theia IDE Next product\",\n  \"prod"
  },
  {
    "path": "applications/electron-next/resources/LICENSE",
    "chars": 1082,
    "preview": "MIT License\n\nCopyright (c) 2026 Eclipse Theia IDE Authors\n\nPermission is hereby granted, free of charge, to any person o"
  },
  {
    "path": "applications/electron-next/resources/preload.html",
    "chars": 4068,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <style>\n        html,\n        body {\n            background-color: black;\n "
  },
  {
    "path": "applications/electron-next/scripts/after-pack.js",
    "chars": 1118,
    "preview": "#!/usr/bin/env node\n\nconst fs = require('fs');\nconst path = require('path');\n\n// Signing and notarizing are not needed f"
  },
  {
    "path": "applications/electron-next/scripts/appimage-helpers.js",
    "chars": 3126,
    "preview": "const fs = require('fs');\nconst path = require('path');\n\n/**\n * Reads the plugin copy metadata file and returns its cont"
  },
  {
    "path": "applications/electron-next/scripts/theia-electron-main.js",
    "chars": 1864,
    "preview": "const path = require('path');\nconst fs = require('fs');\nconst os = require('os');\nconst { copyBundledPlugins } = require"
  },
  {
    "path": "applications/electron-next/test/workspace/README.md",
    "chars": 60,
    "preview": "# Test Workspace\n\nThis is the test workspace for E2E tests.\n"
  },
  {
    "path": "applications/electron-next/tsconfig.eslint.json",
    "chars": 136,
    "preview": "{\n    \"extends\": \"./tsconfig.json\",\n    \"compilerOptions\": {\n        \"noEmit\": true\n    },\n    \"include\": [\n      \"./scr"
  },
  {
    "path": "applications/electron-next/tsconfig.json",
    "chars": 313,
    "preview": "{\n    \"extends\": \"../../configs/base.tsconfig\",\n    \"include\": [],\n    \"compilerOptions\": {\n      \"composite\": true,\n   "
  },
  {
    "path": "applications/electron-next/webpack.config.js",
    "chars": 5109,
    "preview": "/**\n * This file can be edited to customize webpack configuration.\n * To reset delete this file and rerun theia build ag"
  },
  {
    "path": "browser.Dockerfile",
    "chars": 2330,
    "preview": "# Builder stage\nFROM node:24-bookworm AS build-stage\n\n# install required tools to build the application\nRUN apt-get upda"
  },
  {
    "path": "cleanup/Jenkinsfile",
    "chars": 2240,
    "preview": "pipeline {\n    agent {\n        label 'windows'\n    }\n    triggers { cron('@weekly') }\n    options {\n        timeout(time"
  },
  {
    "path": "configs/base.eslintrc.json",
    "chars": 403,
    "preview": "{\n  \"parser\": \"@typescript-eslint/parser\",\n  \"parserOptions\": {\n    \"sourceType\": \"module\",\n    \"ecmaVersion\": 6,\n    \"e"
  },
  {
    "path": "configs/base.tsconfig.json",
    "chars": 706,
    "preview": "{\n    \"compilerOptions\": {\n        \"skipLibCheck\": true,\n        \"declaration\": true,\n        \"declarationMap\": true,\n  "
  },
  {
    "path": "configs/build.eslintrc.json",
    "chars": 80,
    "preview": "{\n  \"extends\": [\n    \"./base.eslintrc.json\",\n    \"./errors.eslintrc.json\"\n  ]\n}\n"
  },
  {
    "path": "configs/errors.eslintrc.json",
    "chars": 2966,
    "preview": "{\n  \"$schema\": \"https://json.schemastore.org/eslintrc\",\n  \"rules\": {\n    \"@typescript-eslint/consistent-type-definitions"
  },
  {
    "path": "configs/license-check-config.json",
    "chars": 141,
    "preview": "{\n    \"project\": \"ecd.theia\",\n    \"inputFile\": \"yarn.lock\",\n    \"batch\": 50,\n    \"timeout\": 240,\n    \"summary\": \"license"
  },
  {
    "path": "configs/tsconfig.eslint.json",
    "chars": 140,
    "preview": "{\n    \"extends\": \"../tsconfig.json\",\n    \"compilerOptions\": {\n        \"noEmit\": true\n    },\n    \"include\": [\n      \"../s"
  },
  {
    "path": "configs/warnings.eslintrc.json",
    "chars": 176,
    "preview": "{\n  \"plugins\": [\n    \"deprecation\"\n  ],\n  \"rules\": {\n    \"@typescript-eslint/await-thenable\": \"warn\",\n    \"no-return-awa"
  },
  {
    "path": "configs/xss.eslintrc.json",
    "chars": 582,
    "preview": "{\n  \"extends\": [\"plugin:no-unsanitized/DOM\"],\n  \"plugins\": [\"no-unsanitized\", \"react\"],\n  \"parserOptions\": {\n    \"ecmaFe"
  },
  {
    "path": "docs/developing-with-local-theia.md",
    "chars": 6056,
    "preview": "# Developing with a Local Theia Framework\n\nThis guide explains how to build and test the Theia IDE against a local devel"
  },
  {
    "path": "lerna.json",
    "chars": 148,
    "preview": "{\n  \"$schema\": \"node_modules/lerna/schemas/lerna-schema.json\",\n  \"version\": \"1.71.100\",\n  \"command\": {\n    \"run\": {\n    "
  },
  {
    "path": "next/Jenkinsfile",
    "chars": 5737,
    "preview": "/**\n * This Jenkinsfile builds Theia Next across the major OS platforms\n */\nimport groovy.json.JsonSlurper\n\ndistFolder ="
  },
  {
    "path": "next/NEXT_INTEGRATION_BUILD.md",
    "chars": 1236,
    "preview": "# Integration build against Theia@next\n\nThe master branch has a script that may be used to update all theia versions to "
  },
  {
    "path": "package.json",
    "chars": 4394,
    "preview": "{\n  \"private\": true,\n  \"version\": \"1.71.100\",\n  \"license\": \"MIT\",\n  \"author\": \"Rob Moran <github@thegecko.org>\",\n  \"home"
  },
  {
    "path": "patches/@theia+terminal+1.72.0-next.20.patch",
    "chars": 751,
    "preview": "diff --git a/node_modules/@theia/terminal/lib/node/shell-integration-injector.js b/node_modules/@theia/terminal/lib/node"
  },
  {
    "path": "releng/preview/Jenkinsfile.build",
    "chars": 15035,
    "preview": "/**\n * This Jenkinsfile builds Theia across the major OS platforms\n * It's designed to be run only manually\n */\n\nimport "
  },
  {
    "path": "releng/preview/Jenkinsfile.sign",
    "chars": 14635,
    "preview": "/**\n * This Jenkinsfile handles signing and notarizing Theia installers\n * It's designed to be run automatically after t"
  },
  {
    "path": "releng/preview/Jenkinsfile.upload",
    "chars": 17028,
    "preview": "/**\n * This Jenkinsfile handles updating metadata and uploading the Theia installers\n * It's designed to be run automati"
  },
  {
    "path": "releng/promote/Jenkinsfile",
    "chars": 4238,
    "preview": "/**\n * This Jenkinsfile promotes a given version of the Theia IDE from /theia/ide-preview to /theia/ide\n */\n\n/* groovyli"
  },
  {
    "path": "scripts/build-with-local-theia.js",
    "chars": 12599,
    "preview": "#!/usr/bin/env node\n\n/**\n * Script to build Theia IDE with a local Theia framework development version.\n *\n * This allow"
  },
  {
    "path": "scripts/generate-next-icons.js",
    "chars": 4401,
    "preview": "#!/usr/bin/env node\n// @ts-check\n\n/**\n * Generates next icons by recoloring the Theia IDE blue (#00ADEE) to\n * next purp"
  },
  {
    "path": "scripts/make-files-writeable.ts",
    "chars": 1999,
    "preview": "/********************************************************************************\n * Copyright (C) 2025 EclipseSource an"
  },
  {
    "path": "scripts/update-theia-version.ts",
    "chars": 1813,
    "preview": "/********************************************************************************\n * Copyright (C) 2021 EclipseSource an"
  },
  {
    "path": "theia-extensions/launcher/.eslintrc.js",
    "chars": 230,
    "preview": "/** @type {import('eslint').Linter.Config} */\nmodule.exports = {\n    extends: [\n        '../../configs/build.eslintrc.js"
  },
  {
    "path": "theia-extensions/launcher/package.json",
    "chars": 1154,
    "preview": "{\n  \"name\": \"theia-ide-launcher-ext\",\n  \"version\": \"1.71.100\",\n  \"keywords\": [\n    \"theia-extension\"\n  ],\n  \"license\": \""
  },
  {
    "path": "theia-extensions/launcher/src/browser/create-launcher-contribution.ts",
    "chars": 4299,
    "preview": "/********************************************************************************\n * Copyright (C) 2022-2024 EclipseSour"
  },
  {
    "path": "theia-extensions/launcher/src/browser/create-launcher-frontend-module.ts",
    "chars": 982,
    "preview": "/********************************************************************************\n * Copyright (C) 2022-2024 EclipseSour"
  },
  {
    "path": "theia-extensions/launcher/src/browser/desktopfile-service.ts",
    "chars": 1469,
    "preview": "/********************************************************************************\n * Copyright (C) 2024 STMicroelectroni"
  },
  {
    "path": "theia-extensions/launcher/src/browser/launcher-service.ts",
    "chars": 1421,
    "preview": "/********************************************************************************\n * Copyright (C) 2022 EclipseSource an"
  },
  {
    "path": "theia-extensions/launcher/src/node/desktopfile-endpoint.ts",
    "chars": 7629,
    "preview": "/********************************************************************************\n * Copyright (C) 2024 STMicroelectroni"
  },
  {
    "path": "theia-extensions/launcher/src/node/launcher-backend-module.ts",
    "chars": 1056,
    "preview": "/********************************************************************************\n * Copyright (C) 2022-2024 EclipseSour"
  },
  {
    "path": "theia-extensions/launcher/src/node/launcher-endpoint.ts",
    "chars": 4649,
    "preview": "/********************************************************************************\n * Copyright (C) 2022-2024 EclipseSour"
  },
  {
    "path": "theia-extensions/launcher/src/node/launcher-util.ts",
    "chars": 923,
    "preview": "/********************************************************************************\n * Copyright (C) 2024 STMicroelectroni"
  },
  {
    "path": "theia-extensions/launcher/tsconfig.json",
    "chars": 188,
    "preview": "{\n  \"extends\": \"../../configs/base.tsconfig\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"outDir\": \"lib\",\n    \"bas"
  },
  {
    "path": "theia-extensions/product/.eslintrc.js",
    "chars": 230,
    "preview": "/** @type {import('eslint').Linter.Config} */\nmodule.exports = {\n    extends: [\n        '../../configs/build.eslintrc.js"
  },
  {
    "path": "theia-extensions/product/package.json",
    "chars": 1349,
    "preview": "{\n  \"private\": true,\n  \"name\": \"theia-ide-product-ext\",\n  \"version\": \"1.71.100\",\n  \"description\": \"Eclipse Theia IDE Pro"
  },
  {
    "path": "theia-extensions/product/src/browser/branding-util.tsx",
    "chars": 7533,
    "preview": "/********************************************************************************\n * Copyright (C) 2020 EclipseSource an"
  },
  {
    "path": "theia-extensions/product/src/browser/style/index.css",
    "chars": 1795,
    "preview": "/********************************************************************************\n * Copyright (C) 2020 EclipseSource an"
  },
  {
    "path": "theia-extensions/product/src/browser/theia-ide-about-dialog.tsx",
    "chars": 3582,
    "preview": "/********************************************************************************\n * Copyright (C) 2020 EclipseSource an"
  },
  {
    "path": "theia-extensions/product/src/browser/theia-ide-config.ts",
    "chars": 1032,
    "preview": "/********************************************************************************\n * Copyright (C) 2026 EclipseSource an"
  },
  {
    "path": "theia-extensions/product/src/browser/theia-ide-contribution.tsx",
    "chars": 2663,
    "preview": "/********************************************************************************\n * Copyright (C) 2021 Ericsson and oth"
  },
  {
    "path": "theia-extensions/product/src/browser/theia-ide-frontend-module.ts",
    "chars": 1912,
    "preview": "/********************************************************************************\n * Copyright (C) 2020 TypeFox, Eclipse"
  },
  {
    "path": "theia-extensions/product/src/browser/theia-ide-getting-started-widget.tsx",
    "chars": 6104,
    "preview": "/********************************************************************************\n * Copyright (C) 2020 EclipseSource an"
  },
  {
    "path": "theia-extensions/product/src/electron-main/icon-contribution.ts",
    "chars": 1706,
    "preview": "/********************************************************************************\n * Copyright (C) 2021 EclipseSource an"
  },
  {
    "path": "theia-extensions/product/src/electron-main/theia-ide-main-module.ts",
    "chars": 809,
    "preview": "/********************************************************************************\n * Copyright (C) 2021 EclipseSource an"
  },
  {
    "path": "theia-extensions/product/tsconfig.json",
    "chars": 227,
    "preview": "{\n    \"extends\": \"../../configs/base.tsconfig\",\n    \"compilerOptions\": {\n        \"rootDir\": \"src\",\n        \"outDir\": \"li"
  },
  {
    "path": "theia-extensions/updater/.eslintrc.js",
    "chars": 230,
    "preview": "/** @type {import('eslint').Linter.Config} */\nmodule.exports = {\n    extends: [\n        '../../configs/build.eslintrc.js"
  },
  {
    "path": "theia-extensions/updater/package.json",
    "chars": 1396,
    "preview": "{\n  \"private\": true,\n  \"name\": \"theia-ide-updater-ext\",\n  \"version\": \"1.71.100\",\n  \"description\": \"Eclipse Theia IDE Upd"
  },
  {
    "path": "theia-extensions/updater/src/common/updater/theia-updater.ts",
    "chars": 1555,
    "preview": "/********************************************************************************\n * Copyright (C) 2020 TypeFox, Eclipse"
  },
  {
    "path": "theia-extensions/updater/src/electron-browser/theia-updater-frontend-module.ts",
    "chars": 1893,
    "preview": "/********************************************************************************\n * Copyright (C) 2020 TypeFox, Eclipse"
  },
  {
    "path": "theia-extensions/updater/src/electron-browser/updater/theia-updater-frontend-contribution.ts",
    "chars": 9645,
    "preview": "/********************************************************************************\n * Copyright (C) 2020 TypeFox, Eclipse"
  },
  {
    "path": "theia-extensions/updater/src/electron-browser/updater/theia-updater-preferences.ts",
    "chars": 1728,
    "preview": "/********************************************************************************\n * Copyright (C) 2020 EclipseSource an"
  },
  {
    "path": "theia-extensions/updater/src/electron-main/update/theia-updater-impl.ts",
    "chars": 7879,
    "preview": "/********************************************************************************\n * Copyright (C) 2020 TypeFox, Eclipse"
  },
  {
    "path": "theia-extensions/updater/src/electron-main/update/theia-updater-main-module.ts",
    "chars": 1585,
    "preview": "/********************************************************************************\n * Copyright (C) 2020 TypeFox, Eclipse"
  },
  {
    "path": "theia-extensions/updater/tsconfig.json",
    "chars": 227,
    "preview": "{\n    \"extends\": \"../../configs/base.tsconfig\",\n    \"compilerOptions\": {\n        \"rootDir\": \"src\",\n        \"outDir\": \"li"
  },
  {
    "path": "tsconfig.json",
    "chars": 423,
    "preview": "{\n  \"extends\": \"./configs/base.tsconfig.json\",\n  \"include\": [],\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"allow"
  }
]

// ... and 17 more files (download for full content)

About this extraction

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

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

Copied to clipboard!