Skip to content

Minor Improvement#3

Open
Asixa wants to merge 24 commits intoTeddy-van-Jerry:masterfrom
Asixa:master
Open

Minor Improvement#3
Asixa wants to merge 24 commits intoTeddy-van-Jerry:masterfrom
Asixa:master

Conversation

@Asixa
Copy link
Copy Markdown

@Asixa Asixa commented Feb 27, 2026

This pull request introduces significant new features and improvements to the LocalLeaf VS Code extension, focusing on enhanced Source Control integration, LaTeX compilation and PDF preview, user interface upgrades, and improved API and collaboration utilities. The update also includes configuration enhancements and dependency updates for better usability and extensibility.

Key highlights:

  • Adds Source Control integration with Overleaf, allowing pull/push actions from the VS Code SCM tab and auto-push after Git commits.
  • Introduces local LaTeX compilation and PDF preview features, with associated commands, menu entries, and configuration options.
  • Improves the user interface with new views, commands, and activity bar integration.
  • Enhances the API and collaboration modules for better extensibility and user feedback.
  • Updates dependencies and configuration for improved compatibility and user experience.

Source Control & Overleaf Integration

  • Added Source Control integration: LocalLeaf now appears in the VS Code Source Control tab, supporting pull/push actions and auto-push to Overleaf after Git commits in manual sync mode. Also updated documentation and configuration to reflect these features. [1] [2] [3] [4] [5]
  • Introduced new configuration options: localleaf.gitCommitAutoPush for auto-pushing after Git commits, and localleaf.syncMode to toggle between manual and real-time sync.

LaTeX Compilation & PDF Preview

  • Added commands and menu entries for compiling LaTeX, toggling auto-compile, selecting compiler, and showing PDF previews, along with related configuration options (localleaf.compiler, localleaf.compileOnSave, etc.). [1] [2]
  • Introduced a new PDF viewer stylesheet (media/pdfViewer.css) for consistent and visually integrated PDF previews.
  • Added pdfjs-dist as a dependency for PDF rendering.

User Interface & UX Improvements

  • Registered new views in the activity bar (Projects, Changes, Tools, Details) and improved command palette entries with icons and context-aware visibility. [1] [2]
  • Updated .vscodeignore to ensure the extension icon is included in the package.
  • Bumped extension version and updated publisher metadata.

API & Collaboration Enhancements

  • Improved the API for document creation to return the created document entity when available, increasing robustness for different Overleaf deployments. [1] [2]
  • Enhanced collaboration utilities: exported getColorForUserId, added a getInitials helper, and extended tracked user decoration types for richer user presence indication. [1] [2] [3]

Permissions & Configuration

  • Added a .claude/settings.local.json file specifying allowed commands and web fetch domains for development or automation tooling.

These changes collectively provide a more powerful, user-friendly, and collaborative LaTeX editing experience in VS Code, tightly integrated with Overleaf and modern development workflows.

Asixa added 24 commits February 25, 2026 23:23
- Introduced ProjectsProvider, ChangesProvider, and DetailsProvider for sidebar functionality.
- Implemented commands for opening projects and managing sync status.
- Enhanced package.json to include new views and commands with appropriate icons.
- Added context management for user login and folder linking states.
- Created a new settings file for local development permissions.
- Implemented a PDF viewer using pdf.js with navigation and zoom functionalities.
- Created a dedicated CSS file for styling the PDF viewer interface.
- Developed an auto compiler that watches for changes in .tex and .bib files, triggering compilation with debouncing.
- Added a LaTeX compiler that detects available compilers and handles compilation errors and warnings.
- Introduced a change tracker to manage local and remote changes for manual sync mode.
- Created a PDF preview panel to display compiled PDFs in a webview.
- Implemented AccountPanel class to handle user authentication state and actions.
- Created webview content for user interaction, including login via browser and cookies.
- Added state management for logged in, expired, and not logged in scenarios.

feat: introduce ProjectsWebviewProvider for project management

- Replaced old TreeDataProvider with ProjectsWebviewProvider for better project handling.
- Implemented state machine to manage view states based on folder and login status.
- Added filtering and sorting capabilities for project lists.
- Enhanced HTML generation for project display and user interaction.
- Removed the old ChangesProvider and replaced it with ChangesWebviewProvider for a more interactive experience.
- Updated package.json to reflect the new webview type for the Changes view.
- Adjusted extension.ts to initialize and manage the new ChangesWebviewProvider.
- Modified syncEngine.ts to support new push and sync logic with confirmation handling.
- Cleaned up sidebarProvider.ts by removing the deprecated ChangesProvider code.
- Implemented inline notifications (toasts) and confirmation dialogs within the webview.
- Enhanced the HTML structure and styling for the new changes view.
…enhance permissions in settings and update .vscodeignore
Copilot AI review requested due to automatic review settings February 27, 2026 23:15
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR significantly expands the LocalLeaf VS Code extension with new UI surfaces (activity bar views + webviews), manual-vs-realtime sync workflows (including SCM integration and a Git commit hook), and local LaTeX compilation with an in-editor PDF preview.

Changes:

  • Introduces new LocalLeaf activity bar container and webview-based Projects/Changes panels (with inline toasts/confirmations and collaborator presence).
  • Adds lightweight SCM provider integration plus Git-commit-triggered auto-push in manual sync mode.
  • Adds local LaTeX compilation (auto-compile on save, compiler selection) and a pdf.js-based PDF preview panel with SyncTeX inverse search.

Reviewed changes

Copilot reviewed 23 out of 28 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
src/views/sidebarProvider.ts Adds Details/Tools TreeDataProviders and shared sidebar helper utilities.
src/views/projectsWebviewProvider.ts New Projects webview with state machine, filtering, sorting, and project open actions.
src/views/pdfPreviewPanel.ts New PDF preview panel using pdf.js with SyncTeX inverse search and refresh flow.
src/views/changesWebviewProvider.ts New Changes webview providing manual-sync change lists, confirmations/toasts, and online users.
src/views/accountPanel.ts New Account webview panel for login/logout flows and session state display.
src/utils/settingsManager.ts Extends project settings with sync mode and compilation-related fields.
src/types/vscode-git.d.ts Adds a minimal typing subset for the VS Code Git extension API.
src/sync/ignoreParser.ts Updates default ignore template (adds *.git).
src/sync/changeTracker.ts Adds change tracking for manual sync (local/remote/conflict sets).
src/scm/localLeafScmBridge.ts Adds SCM provider bridge to surface pull/push actions in the SCM view.
src/integrations/gitCommitHook.ts Adds a single-flight Git commit hook integration using vscode.git API.
src/extension.ts Large integration: registers new views/commands, sync mode behavior, git hook, compile/PDF preview, account panel, and change tracker wiring.
src/consts.ts Adds new commands and updates default ignore patterns.
src/compilation/latexCompiler.ts Implements LaTeX compiler detection/execution, diagnostics, and build output routing.
src/compilation/autoCompiler.ts Adds debounced auto-compilation on relevant file saves.
src/collaboration/cursorTracker.ts Exports color helper, adds initials helper, improves cursor/line decorations, and exposes user-change event.
src/auth/browserCookieLogin.ts Implements Chromium-based cookie capture via DevTools for browser login.
src/api/base.ts Enhances addDoc to return created document entity when available.
package.json Adds activity bar container/views, commands/menus/keybindings/config, bumps version/publisher, adds pdfjs-dist, and declares vscode.git dependency.
media/pdfViewer.js Adds custom pdf.js viewer logic (rendering, zoom, links, SyncTeX click handling).
media/pdfViewer.css Adds styling for the PDF viewer webview UI.
README.md Documents new SCM integration and git auto-push setting.
.vscodeignore Ensures the extension icon SVG is included in the packaged extension.
.claude/settings.local.json Adds local automation/tooling permissions configuration.
Comments suppressed due to low confidence (1)

src/views/accountPanel.ts:289

  • This innerHTML string is missing whitespace between sentences (</strong>Use Browser...), which reads as a typo in the UI. Add a space or line break after the closing </strong> so the message renders correctly.
                    statusEl.innerHTML = '<strong>Not Logged In</strong>Use Browser or Cookies to sign in.';
                }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +29 to 31
"extensionDependencies": [
"vscode.git"
],
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding "vscode.git" as an extensionDependencies hard-requires the Git extension for all users (and can force-enable it), even though the code already handles the Git API being unavailable. If Git integration is optional, consider removing the dependency and letting the feature degrade gracefully, or gate the dependency behind a separate extension pack/optional install to avoid impacting users who don't use Git.

Suggested change
"extensionDependencies": [
"vscode.git"
],

Copilot uses AI. Check for mistakes.
Comment on lines +143 to +145
const proc = spawn('synctex', args, {
cwd: this.workspaceFolder,
shell: true,
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spawn('synctex', ..., { shell: true }) runs through a shell, and the -o page:x:y:file argument includes a path derived from the workspace. With shell: true, special characters in paths can be interpreted by the shell (command injection risk / unexpected failures). Prefer shell: false and pass args directly; if Windows needs .exe resolution, handle that explicitly rather than enabling the shell.

Suggested change
const proc = spawn('synctex', args, {
cwd: this.workspaceFolder,
shell: true,
const synctexCmd = process.platform === 'win32' ? 'synctex.exe' : 'synctex';
const proc = spawn(synctexCmd, args, {
cwd: this.workspaceFolder,
shell: false,

Copilot uses AI. Check for mistakes.
Comment on lines +290 to +303
private wrapHtml(body: string): string {
return /*html*/`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
/* Reset */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

body {
font-family: var(--vscode-font-family);
font-size: var(--vscode-font-size);
color: var(--vscode-foreground);
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Projects webview HTML is rendered without a Content-Security-Policy and relies on inline scripts/handlers. Webviews should set a restrictive CSP (with a nonce for scripts) to reduce XSS risk, especially since project names/IDs are displayed. Align this with the approach used in AccountPanel/PdfPreviewPanel (nonce + CSP meta).

Copilot uses AI. Check for mistakes.
Comment on lines +258 to +262
return /*html*/`
<div class="project-item" onclick="postMessage({type:'openProject',projectId:'${p.id}'})">
<span class="codicon codicon-${icon} project-icon"></span>
<div class="project-info">
<span class="project-name">${escapedName}</span>
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

projectId is interpolated directly into an inline onclick handler. If p.id ever contains quotes or other special characters, it can break out of the string/attribute and enable script injection in the webview. Avoid inline JS and pass IDs via data-* attributes + addEventListener, or at least escape/encode the value before embedding it into HTML.

Copilot uses AI. Check for mistakes.
Comment on lines +1813 to +1818
const mainTex = settings.mainTex || 'main.tex';
const delay = config.get<number>('compileDelay', 1500);
autoCompiler.enable(settingsManager.getWorkspaceFolder(), mainTex, delay);
autoCompiler.onWillCompile(() => handleCompilationStarted());
autoCompiler.onDidCompile(result => handleCompilationResult(result));
vscode.window.setStatusBarMessage('$(check) Auto-compile enabled', 3000);
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When enabling auto-compile here, new onWillCompile/onDidCompile listeners are attached each time without disposing previous ones. Toggling auto-compile on/off multiple times will accumulate listeners and trigger duplicate progress notifications / result handling. Consider registering these listeners once (when AutoCompiler is created) or store the returned disposables and dispose/reuse them when toggling.

Copilot uses AI. Check for mistakes.
*.blg
*.fdb_latexmk
*.fls
*.git
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generated default .leafignore includes *.git, which matches files ending in .git but does not directly ignore the .git/ directory. If the goal is to prevent syncing Git metadata, use an explicit directory pattern such as .git/** (or /.git/**) instead of *.git to avoid also ignoring legitimate files like paper.git.

Suggested change
*.git
.git/**

Copilot uses AI. Check for mistakes.
Comment on lines +96 to +102
updatePdf(pdfPath: string): void {
this.currentPdfPath = pdfPath;
try {
const bytes = fs.readFileSync(pdfPath);
this.panel.webview.postMessage({
type: 'updatePdf',
pdfData: bytes.toString('base64'),
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updatePdf() uses fs.readFileSync, which can block the extension host thread on large PDFs (and this is called on each compilation/update). Consider switching to an async read (vscode.workspace.fs.readFile or fs.promises.readFile) and awaiting it before posting the message, keeping the fallback-to-URL behavior for errors.

Suggested change
updatePdf(pdfPath: string): void {
this.currentPdfPath = pdfPath;
try {
const bytes = fs.readFileSync(pdfPath);
this.panel.webview.postMessage({
type: 'updatePdf',
pdfData: bytes.toString('base64'),
async updatePdf(pdfPath: string): Promise<void> {
this.currentPdfPath = pdfPath;
try {
const bytes = await vscode.workspace.fs.readFile(vscode.Uri.file(pdfPath));
this.panel.webview.postMessage({
type: 'updatePdf',
pdfData: Buffer.from(bytes).toString('base64'),

Copilot uses AI. Check for mistakes.
Comment on lines +344 to +347
// Brief delay to ensure the panel tab is focused before pinning
setTimeout(() => {
vscode.commands.executeCommand('workbench.action.pinEditor');
}, 100);
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pinTab() executes workbench.action.pinEditor after a timeout, which can pin whichever editor is active at that moment (potentially not the PDF preview) if focus changes quickly. Consider pinning immediately after a panel.reveal() that ensures focus, or avoid implicit pinning entirely and leave it user-controlled to prevent pinning the wrong tab.

Suggested change
// Brief delay to ensure the panel tab is focused before pinning
setTimeout(() => {
vscode.commands.executeCommand('workbench.action.pinEditor');
}, 100);
// Ensure this panel is focused before pinning, then pin immediately
this.panel.reveal(undefined, true);
vscode.commands.executeCommand('workbench.action.pinEditor');

Copilot uses AI. Check for mistakes.
Comment on lines +269 to +276
private getHtml(): string {
return /* html */ `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/* ── Reset ─────────────────────────────────────────── */
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Changes webview HTML includes inline <script> but does not define a Content-Security-Policy. Webviews should set a restrictive CSP (nonce-based) to mitigate injection risks, even if most content is rendered via DOM APIs. Consider adding a CSP meta tag and attaching a nonce to the script block(s).

Copilot uses AI. Check for mistakes.
Comment on lines +59 to +63
const cmd = process.platform === 'win32' ? 'where' : 'which';
const proc = spawn(cmd, [command], { stdio: 'pipe', shell: true });
proc.on('close', code => resolve(code === 0));
proc.on('error', () => resolve(false));
setTimeout(() => { proc.kill(); resolve(false); }, 3000);
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isAvailable() can call resolve(false) from the timeout even if the close handler already resolved (and can also resolve again after killing the process). This can lead to racy behavior and orphaned timers. Add a settled guard (as in canExecute()) and clear the timeout on close/error to ensure the Promise resolves exactly once.

Suggested change
const cmd = process.platform === 'win32' ? 'where' : 'which';
const proc = spawn(cmd, [command], { stdio: 'pipe', shell: true });
proc.on('close', code => resolve(code === 0));
proc.on('error', () => resolve(false));
setTimeout(() => { proc.kill(); resolve(false); }, 3000);
let settled = false;
const cmd = process.platform === 'win32' ? 'where' : 'which';
const proc = spawn(cmd, [command], { stdio: 'pipe', shell: true });
const timeout = setTimeout(() => {
if (settled) {
return;
}
settled = true;
proc.kill();
resolve(false);
}, 3000);
proc.on('close', code => {
if (settled) {
return;
}
settled = true;
clearTimeout(timeout);
resolve(code === 0);
});
proc.on('error', () => {
if (settled) {
return;
}
settled = true;
clearTimeout(timeout);
resolve(false);
});

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants