Case-Sensitive Path Guard
Your images work locally, then 404 in production. This extension finds the reason before you deploy.
Windows and macOS treat Icon.png and icon.png as the same file. Linux — which runs Cloudflare Pages, Netlify, Vercel, GitHub Pages and nearly every container — does not. So a reference like src="./assets/icon.png" keeps working on your machine while the real file assets/Icon.png quietly breaks the moment it is served from Linux.
Case-Sensitive Path Guard reads the actual directory listings in your workspace, flags every asset reference whose letter casing does not match the file on disk, and fixes it for you when you save — no clicking required.
What it looks like
You write:
<img src=./assets/icon.png alt="hero" />
The file on disk is assets/Icon.png. The path is underlined in yellow and the Problems panel explains the mismatch. Press Ctrl+S and the reference is rewritten to ./assets/Icon.png before the file reaches the disk. One Ctrl+Z puts it back.
If you would rather apply it by hand, Ctrl+. (Cmd+. on macOS) still offers:
Fix path casing to match disk file → ./assets/Icon.png
No build step, no configuration, no network access.
Features
- Scans the languages you actually ship — HTML, JavaScript, TypeScript, JSX, TSX, Vue, Svelte, Astro, CSS, SCSS, Less, JSON and JSONC.
- Understands real-world reference syntax
- HTML attributes:
src, href, poster, data-src, data-bg, xlink:href
srcset lists, including each candidate and its 1x/2x descriptor
- Module imports:
import … from, import(…), require(…), new URL(…, import.meta.url)
- CSS:
url(…), @import
- DOM-style assignments such as
element.src = "./a.png"
- JSON string values:
"icon": "./assets/icon.png" (object keys are never treated as paths)
- Validates true on-disk casing, not just existence. It walks the path one directory at a time and compares each segment against the real file names, which is the only reliable way:
fs.stat() resolves the wrong casing happily on case-insensitive filesystems.
- Quick fix and fix-all as a single undoable
WorkspaceEdit.
- Automatic correction on save (
caseSensitivePathGuard.autoFixOnSave, on by default), applied to the buffer before the file is written, so nothing broken ever lands on disk.
- Smart fallbacks for web-root references like
/images/hero.png through the pathRoots setting.
- Zero runtime dependencies. Works locally, over Remote-SSH, in dev containers and in Codespaces, because it uses
vscode.workspace.fs.
- Quiet by design. URLs, data URIs, protocol-relative paths, percent-encoded and dynamic (
${…}) references are ignored. When two files differ only by case, it refuses to guess.
Supported references
| Context |
Examples |
| Markup |
<img src>, <source src>, <link href>, <video poster>, srcset |
| Modules |
import logo from './logo.png', require('../img/x.jpg'), new URL('./f.svg', import.meta.url) |
| Styles |
background: url(../img/hero.webp), @import "theme.css" |
| Data |
"icon": "./assets/icon.png", "logos": ["../assets/logo.svg"] |
Default asset extensions: png, jpg, jpeg, gif, svg, webp, avif, ico, bmp, tif, tiff, mp4, webm, ogv, mov, m4v, mp3, wav, ogg, flac, woff, woff2, ttf, otf, eot, pdf.
Settings
| Setting |
Default |
Description |
caseSensitivePathGuard.enable |
true |
Turn scanning on or off. |
caseSensitivePathGuard.autoFixOnSave |
true |
Correct every detected path before the file is saved. Set to false to only see the warning. |
caseSensitivePathGuard.severity |
warning |
error, warning, information or hint. |
caseSensitivePathGuard.fileExtensions |
asset list above |
Extensions (no dot) to validate. |
caseSensitivePathGuard.pathRoots |
["", "public", "src", "static", "assets"] |
How /images/x.png maps to a folder on disk. |
caseSensitivePathGuard.exclude |
node_modules, dist, build, out, .git |
Globs of documents that are never scanned. |
caseSensitivePathGuard.reportMissingFiles |
false |
Also report assets that do not exist at all. |
Web-root references
<img src=/images/hero.png> is a server path, not a filesystem path. The extension tries each entry in pathRoots against every workspace folder, so the reference above is checked against images/hero.png, public/images/hero.png, src/images/hero.png, and so on.
Commands
| Command |
Description |
Path Guard: Fix All Path Casing Issues in File |
Apply every known fix in the active file. |
Path Guard: Re-scan Document for Path Casing Issues |
Force a fresh scan after changing settings or files outside VS Code. |
Limitations
- Only the reference is corrected, never the file. If the file on disk is the thing with the wrong name, rename it yourself — the extension will not touch your assets.
- Dynamic paths are skipped.
${locale}/banner.png, require(name), and anything else that only exists at runtime cannot be validated statically.
- Framework aliases are not resolved.
@/assets/logo.png and ~assets/logo.png are only checked if the same relative path also exists under one of the pathRoots.
- Ambiguous names are ignored. If
Icon.png and icon.png both exist, there is no single correct answer, so no diagnostic is shown.
- In JSON, only string values are checked. Keys are ignored, because a key such as
"assets/icon.png" is a label, not a location.
- Percent-encoded paths are skipped (
my%20file.png) to avoid false positives.
- Non-asset files are not checked by default. Stylesheets and scripts can be added to
fileExtensions if you want them validated too.
- The extension reads directory names, so it needs a filesystem provider that reports real casing. Local, Remote-SSH and container workspaces do; some virtual filesystems may not.
Install
- Open the Extensions view (
Ctrl+Shift+X).
- Search for Case-Sensitive Path Guard.
- Install and open any HTML, JS/TS, Vue, Svelte, Astro or CSS file.
Or from the command line: code --install-extension zaxckheal101.case-sensitive-path-guard
Development
npm install
npm run compile # tsc -> out/
npm run smoke # 42 headless checks: extraction, casing resolution, activation, quick fixes, save hook
Press F5 to launch an Extension Development Host with this folder open. A fixture project lives in demo/; demo/index.html contains intentional mismatches such as ./assets/icon.png where the disk holds assets/Icon.png.
To build a publishable package:
npx @vscode/vsce package
The generated .vsix can be uploaded at https://marketplace.visualstudio.com/manage/publishers/zaxckheal101.
License
MIT
| |