✨ 1. 功能特性
🖼️ 图片尺寸检测
自动读取 background-image 中图片的宽度和高度
📐 单位转换
自动将 px 转换为 rem 单位(基于配置的 font-size)
🎯 居中计算
自动生成 left/top: calc(50% - width/2)
🖼️ Background-size
支持生成 background-size 属性(rem/px/cover/contain)
核心优势
- ✅ 零配置 - 安装即用,默认 font-size: 100px
- ✅ 高效触发 - 输入 wh 开头即触发补全
- ✅ 多单位支持 - rem 和 px 单位可选
- ✅ 多框架支持 - Vue3、React、Angular 等
- ✅ 按需加载 - 只在触发时运行,性能优秀
📁 2. 项目结构
auto-input-width-height/
├── .vscode/ ← ⚠️ 必须!VSCode 配置
│ ├── launch.json ← ⚠️ 必须!调试器配置
│ └── tasks.json ← ⚠️ 必须!编译任务配置
│
├── src/ ← ⚠️ 必须!源代码目录
│ ├── extension.ts ← ⚠️ 必须!插件入口
│ ├── providers/
│ │ └── snippetProvider.ts ← 核心:代码片段提供者
│ └── utils/
│ ├── imageSize.ts ← 图片尺寸检测
│ ├── fontSize.ts ← font-size 配置
│ └── remConverter.ts ← rem 转换逻辑
│
├── out/ ← ⚠️ 必须!编译输出(自动生成)
│ ├── extension.js
│ └── providers/
│ └── snippetProvider.js
│
├── test/ ← 测试文件
│ ├── test.css
│ ├── test.vue
│ └── images/
│ └── test-banner.png
│
├── package.json ← ⚠️ 必须!插件清单
├── tsconfig.json ← ⚠️ 必须!TypeScript 配置
├── .vscodeignore ← 推荐:打包排除配置
├── README.md ← 推荐:说明文档
├── INSTALL.md ← 推荐:安装指南
├── SETUP.md ← 推荐:配置指南
├── deploy.sh ← 推荐:部署脚本
└── DOCS.html ← 本文档
关键点: .vscode 目录是调试插件必须的,缺少会导致无法按 F5 启动调试!
⚠️ 3. 必须文件详解
3.1 .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
"outFiles": ["${workspaceFolder}/out/**/*.js"],
"preLaunchTask": "npm: compile"
}
]
}
3.2 .vscode/tasks.json
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "compile",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": ["$tsc"]
}
]
}
3.3 package.json(关键字段)
{
"name": "auto-width-height-rem",
"displayName": "Auto Width Height Rem",
"description": "Auto generate width/height in rem from background images",
"version": "0.0.1",
"publisher": "your-publisher-name",
"engines": {
"vscode": "^1.74.0"
},
"main": "./out/extension.js",
"categories": ["Programming Languages"],
"activationEvents": [
"onLanguage:css",
"onLanguage:scss",
"onLanguage:sass",
"onLanguage:less",
"onLanguage:vue"
],
"contributes": {
"languages": [
{ "id": "css" },
{ "id": "scss" },
{ "id": "sass" },
{ "id": "less" },
{ "id": "vue" }
],
"configuration": {
"title": "Auto Width Height Rem",
"properties": {
"autoWidthHeightRem.fontSize": {
"type": "number",
"default": 100,
"description": "Base font-size in pixels for rem calculation"
}
}
}
},
"scripts": {
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./"
},
"devDependencies": {
"@types/vscode": "^1.74.0",
"@types/node": "^20.0.0",
"typescript": "^5.0.0"
},
"dependencies": {
"image-size": "^1.0.0"
}
}
3.4 tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "ES2020",
"outDir": "out",
"rootDir": "src",
"lib": ["ES2020", "dom"],
"types": ["node"],
"sourceMap": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"exclude": [
"node_modules",
".vscode-test"
]
}
3.5 src/extension.ts
import * as vscode from 'vscode';
import { WhrCompletionProvider } from './providers/snippetProvider';
export function activate(context: vscode.ExtensionContext) {
console.log('Auto Width Height Rem extension is now active!');
const languages = ['css', 'scss', 'sass', 'less', 'vue'];
const provider = new WhrCompletionProvider();
languages.forEach(language => {
const selector: vscode.DocumentSelector = { language, scheme: 'file' };
const completionProvider = vscode.languages.registerCompletionItemProvider(
selector,
provider,
'w',
'h',
'r',
'p',
'b',
's',
'c',
't',
'a',
'l',
' '
);
context.subscriptions.push(completionProvider);
});
}
export function deactivate() {}
3.6 src/providers/snippetProvider.ts(核心逻辑)
import * as vscode from 'vscode';
import * as path from 'path';
import { getImageSize, ImageDimensions } from '../utils/imageSize';
import { getFontSize } from '../utils/fontSize';
import { pxToRem } from '../utils/remConverter';
export class WhrCompletionProvider implements vscode.CompletionItemProvider {
provideCompletionItems(...): vscode.ProviderResult<vscode.CompletionItem[]> {
const lineText = document.lineAt(position).text;
const textBeforeCursor = lineText.substring(0, position.character);
const trimmedText = textBeforeCursor.trimEnd();
if (!/wh\w*$/i.test(trimmedText)) {
return [];
}
const imageUrl = this.findBackgroundImageUrl(document, position);
return this.createCompletionItems(document, position, imageUrl);
}
private generateSnippets(size, fontSize, imagePath) {
const { width, height } = size;
const widthRem = pxToRem(width, fontSize);
const heightRem = pxToRem(height, fontSize);
const halfWidthRem = pxToRem(width / 2, fontSize);
const halfHeightRem = pxToRem(height / 2, fontSize);
return [
{ label: 'whr', insertText: `width: ${widthRem}rem;\nheight: ${heightRem}rem;` },
{ label: 'whlc', insertText: `left: calc(50% - ${halfWidthRem}rem);` },
];
}
}
3.7 src/utils/imageSize.ts
import * as fs from 'fs';
import { imageSize } from 'image-size';
export interface ImageDimensions {
width: number;
height: number;
}
export function getImageSize(imagePath: string): ImageDimensions | null {
try {
if (!fs.existsSync(imagePath)) {
return null;
}
const buffer = fs.readFileSync(imagePath);
const size = imageSize(buffer);
if (size.width && size.height) {
return { width: size.width, height: size.height };
}
return null;
} catch (error) {
return null;
}
}
3.8 src/utils/fontSize.ts
import * as vscode from 'vscode';
const DEFAULT_FONT_SIZE = 100;
export function getFontSize(): number {
const config = vscode.workspace.getConfiguration('autoWidthHeightRem');
const fontSize = config.get<number>('fontSize', DEFAULT_FONT_SIZE);
if (fontSize <= 0 || !isFinite(fontSize)) {
return DEFAULT_FONT_SIZE;
}
return fontSize;
}
3.9 src/utils/remConverter.ts
export function pxToRem(px: number, fontSize: number): number {
if (fontSize <= 0 || !isFinite(fontSize)) {
fontSize = 100;
}
const rem = px / fontSize;
return Math.round(rem * 100) / 100;
}
export function remToPx(rem: number, fontSize: number): number {
if (fontSize <= 0 || !isFinite(fontSize)) {
fontSize = 100;
}
return rem * fontSize;
}
📦 4. 依赖库
| 库名 |
用途 |
类型 |
必需 |
image-size |
读取图片尺寸(宽度、高度) |
dependencies |
✅ 是 |
@types/vscode |
VSCode API 类型定义 |
devDependencies |
✅ 是 |
@types/node |
Node.js 类型定义 |
devDependencies |
✅ 是 |
typescript |
TypeScript 编译器 |
devDependencies |
✅ 是 |
@vscode/vsce |
VSCode 打包工具 |
全局安装 |
⚠️ 打包时需要 |
安装命令
npm install
npm install -g @vscode/vsce
🌐 5. 支持的语言/框架
| 语言/框架 |
文件类型 |
语言 ID |
支持状态 |
| CSS |
*.css |
css |
✅ 完全支持 |
| SCSS |
*.scss |
scss |
✅ 完全支持 |
| Sass |
*.sass |
sass |
✅ 完全支持 |
| Less |
*.less |
less |
✅ 完全支持 |
| Vue 3 |
*.vue |
vue |
✅ 完全支持 |
| React |
*.css / *.module.css |
css |
✅ 完全支持 |
| Angular |
*.css / *.scss |
css/scss |
✅ 完全支持 |
| Svelte |
<style> 块 |
css/scss |
✅ 完全支持 |
支持的图片格式
PNG, JPEG/JPG, GIF, WebP, BMP, ICO, TIFF, SVG 等
⚙️ 6. 插件执行逻辑
6.1 插件生命周期
VSCode 启动
→
打开 CSS/SCSS/Vue 文件
→
插件激活(一次性)
→
注册 CompletionProvider
→
监听触发字符
6.2 触发时机
"activationEvents": [
"onLanguage:css",
"onLanguage:scss",
"onLanguage:sass",
"onLanguage:less",
"onLanguage:vue"
]
'triggerCharacters': [
'w',
'h',
'r',
'p',
'b',
's',
'c',
't',
'a',
'l',
' '
]
6.3 补全执行流程
用户输入 'w'
→
VSCode 检测到 triggerCharacter
→
调用 provideCompletionItems()
→
正则匹配 'wh*'
查找 background-image URL
→
读取图片尺寸
→
计算 rem 值
→
返回补全选项
6.4 核心代码示例
provideCompletionItems(...) {
const textBeforeCursor = lineText.substring(0, position.character);
if (!/wh\w*$/i.test(trimmedText)) {
return [];
}
const imageUrl = this.findBackgroundImageUrl(document, position);
return this.createCompletionItems(...);
}
export function getFontSize(): number {
const config = vscode.workspace.getConfiguration('autoWidthHeightRem');
return config.get<number>('fontSize', 100);
}
export function pxToRem(px: number, fontSize: number): number {
return Math.round((px / fontSize) * 100) / 100;
}
⌨️ 7. 快捷指令列表
7.1 尺寸指令(width / height)
| 指令 |
功能 |
单位 |
示例输出(750×300px, font-size=100) |
whr |
width + height |
rem |
width: 7.5rem; height: 3rem; |
whrw |
width only |
rem |
width: 7.5rem; |
whrh |
height only |
rem |
height: 3rem; |
whpx |
width + height |
px |
width: 750px; height: 300px; |
whpxw |
width only |
px |
width: 750px; |
whpxh |
height only |
px |
height: 300px; |
7.2 居中定位指令
| 指令 |
功能 |
单位 |
示例输出 |
whlc |
left 居中 |
rem |
left: calc(50% - 3.75rem); |
whtc |
top 居中 |
rem |
top: calc(50% - 1.5rem); |
whcc |
完全居中(left + top) |
rem |
left: calc(50% - 3.75rem); top: calc(50% - 1.5rem); |
whlcpx |
left 居中 |
px |
left: calc(50% - 375px); |
whtcpx |
top 居中 |
px |
top: calc(50% - 150px); |
whccpx |
完全居中(left + top) |
px |
left: calc(50% - 375px); top: calc(50% - 150px); |
7.3 Background-size 指令
| 指令 |
功能 |
单位 |
示例输出 |
whbs |
background-size (w + h) |
rem |
background-size: 7.5rem 3rem; |
whbsw |
background-size (width only) |
rem |
background-size: 7.5rem auto; |
whbsp |
background-size (w + h) |
px |
background-size: 750px 300px; |
whbspw |
background-size (width only) |
px |
background-size: 750px auto; |
whbsc |
background-size: cover |
- |
background-size: cover; |
whbct |
background-size: contain |
- |
background-size: contain; |
7.4 组合指令
| 指令 |
功能 |
单位 |
whall |
width + height + background-size |
rem |
whallpx |
width + height + background-size |
px |
计算公式: rem = px ÷ font-size
例如:750px ÷ 100 = 7.5rem
🧪 8. 测试插件
方法 1:F5 开发模式(推荐)
1
打开终端,进入项目目录
cd /Users/admin/Desktop/VibeCoding/auto-input-width-height
3
按 F5 启动调试
4
会打开一个新的 VSCode 窗口(Extension Development Host)
5
在新窗口中打开测试文件
test/test.css 或 test/test.vue
6
输入以下代码测试:
.test {
background-image: url('./test.png');
whr
}
.box {
background-image: url('./box.png');
whcc
}
方法 2:查看调试日志
1
按 Cmd + Shift + U 打开输出面板
2
在下拉菜单选择 "Auto Width Height Rem"
3
输入 whr 时应该看到日志:
Completion triggered, textBeforeCursor: " whr"
Pattern matched!
Found imageUrl: ./test.png
方法 3:手动触发补全
如果自动补全不显示,可以按 Ctrl + Space(Mac: Ctrl + Space)手动触发
📦 9. 打包插件
方法 1:使用部署脚本(推荐)
1
运行部署脚本
cd /Users/admin/Desktop/VibeCoding/auto-input-width-height
./deploy.sh
方法 2:手动打包
1
安装打包工具(首次需要)
npm install -g @vscode/vsce
2
编译 TypeScript
npm run compile
3
打包成 VSIX 文件
vsce package
4
生成文件
auto-width-height-rem-0.0.1.vsix
生成的 .vsix 文件可以分享给其他人安装使用
💻 10. 本地安装
方法 1:命令行安装(推荐)
code --install-extension auto-width-height-rem-0.0.1.vsix
方法 2:VSCode 界面安装
1
打开 VSCode
2
按 Cmd + Shift + P 打开命令面板
3
输入:Extensions: Install from VSIX...
4
选择生成的 .vsix 文件
5
重启 VSCode:Cmd + Shift + P → Reload Window
卸载插件
code --uninstall-extension auto-width-height-rem
🚀 11. 发布到 VSCode 插件商店
方法 1:网页上传(推荐,最简单)
不需要配置 Personal Access Token,直接在网页上传 VSIX 文件即可!
1
登录 VSCode Marketplace
https://marketplace.visualstudio.com
2
进入 Manage Publishers & Extensions
3
点击 Extensions → Add Extension
4
选择 Upload vsix
5
选择生成的
.vsix 文件
auto-width-height-rem-0.0.1.vsix
6
填写扩展信息(描述、分类、截图等)
7
点击 Publish 发布!
方法 2:命令行发布
前置条件
1
注册 Azure DevOps 账号
https://dev.azure.com
2
创建 Personal Access Token (PAT)
- Organization: All accessible organizations
- Scopes: Custom defined → Marketplace → Manage
发布步骤
1
登录 VSCE
vsce login libufan
2
在 package.json 中添加 publisher
{
"publisher": "libufan"
}
完整发布流程(命令行)
注册 Azure DevOps
→
创建 PAT
→
vsce login
→
vsce publish
→
等待审核(1-3天)
→
上架成功!🎉
注意事项:
- 发布前确保测试通过
- 版本号需要递增(每次发布必须不同)
- README.md 会显示在商店页面
- 图标需要在 package.json 中配置
"icon": "icon.png"
⚠️ 图片链接注意事项(重要)
VSCode Marketplace 不支持本地相对路径图片!
README.md 中的图片必须使用绝对 URL,否则在商店页面不会显示。
❌ 错误写法(不显示)


✅ 正确写法(会显示)


如何获取 GitHub Raw 链接
1
把图片文件上传到 GitHub 仓库
2
在 GitHub 仓库中点击该图片文件
3
点击 Raw 按钮(或右键图片 → 复制链接)
4
复制地址栏中的链接,格式如下:
https://raw.githubusercontent.com/用户名/仓库名/分支名/文件路径
https://raw.githubusercontent.com/libufan/auto-width-height-rem/main/option.gif
推荐的图片托管方式
| 方式 |
优点 |
缺点 |
| GitHub 仓库 ⭐推荐 |
免费、稳定、与项目一起管理 |
需要公开仓库 |
| SM.MS |
免费、无需注册 |
可能过期 |
| Imgur |
免费、速度快 |
可能被墙 |
建议: 把图片放在 GitHub 仓库中统一管理,这样链接永不过期,且与代码版本同步。
⚙️ 12. 配置说明
VSCode 设置
打开设置(Cmd + ,),搜索 autoWidthHeightRem
| 设置项 |
类型 |
默认值 |
说明 |
autoWidthHeightRem.fontSize |
number |
100 |
基准 font-size(px),用于计算 rem |
示例配置
{
"autoWidthHeightRem.fontSize": 100
}
{
"autoWidthHeightRem.fontSize": 50
}
{
"autoWidthHeightRem.fontSize": 16
}
配置示例场景
| 场景 |
fontSize |
750px 转换 |
| 移动端适配(设计稿 750px) |
100 |
7.5rem |
| 移动端适配(设计稿 375px) |
50 |
15rem |
| 桌面端(浏览器默认) |
16 |
46.875rem |
❓ 13. 常见问题
Q: 输入 whr 没有反应?
A: 按 Ctrl + Space 手动触发补全,或检查插件是否启用(Cmd + Shift + X 搜索插件)
Q: 图片路径找不到?
A: 确保使用相对路径(如 ./images/bg.png)或 @/ 别名(如 @/assets/bg.png)
Q: rem 计算不正确?
A: 检查 autoWidthHeightRem.fontSize 设置是否正确。默认是 100,即 1rem = 100px
Q: Vue 文件不支持?
A: 确保 activationEvents 包含 "onLanguage:vue",并安装了 Vue 语言扩展
Q: 如何调试?
A: 按 F5 启动调试,查看输出面板(Cmd + Shift + U)的日志
Q: 插件安装后不生效?
A: 完全退出 VSCode(Cmd + Q)后重新打开,或 Cmd + Shift + P → Reload Window
Q: 支持远程图片吗?
A: 目前只支持本地图片,不支持 http/https 远程图片
Q: 如何查看插件日志?
A: Cmd + Shift + U 打开输出面板,下拉菜单选择 "Auto Width Height Rem"
Q: F5 测试正常,安装 VSIX 后不工作?
A: 这通常是 node_modules 没有打包进去导致的。检查 .vscodeignore 文件:
node_modules/**
node_modules/**
!node_modules/image-size/**
!node_modules/image-size/dist/**
!node_modules/image-size/package.json
重要: 使用 vsce package 打包时,默认会排除 node_modules。如果插件依赖 npm 包,必须在 .vscodeignore 中用 ! 保留需要的依赖。
Q: 如何确认依赖是否打包成功?
A: 打包后查看输出信息,确认 node_modules 包含在内:
INFO Files included in the VSIX:
extension/
├── node_modules/
│ └── image-size/ (116 files) ✅ ← 必须看到这个
Q: 被 GitHub Copilot / CodeGeex 等 AI 补全工具干扰?
AI 代码补全工具(如 GitHub Copilot、CodeGeex、Tabnine 等)会干扰本插件的提示:
问题现象: 输入 whr 后没有弹出补全列表,AI 直接建议补全内容
原因: AI 工具优先级更高,一旦预测了代码,Ctrl + Space / Cmd + Space 手动触发也无效
解决方法: 编写样式时,建议暂时关掉 AI 代码补全工具
重要: AI 工具不知道图片的真实尺寸,生成的 width/height 值几乎都是错的。本插件会读取图片实际尺寸并精确计算,所以请务必使用本插件的补全结果。