🎯 Auto Width Height Rem

VSCode 插件 - 自动从背景图片生成 width/height/rem

v0.0.1 VSCode 1.74+ Mac/Windows/Linux

📑 目录

1. 功能特性
2. 项目结构
3. 必须文件
4. 依赖库
5. 支持的语言/框架
6. 插件执行逻辑
7. 快捷指令列表
8. 测试插件
9. 打包插件
10. 本地安装
11. 发布到商店
12. 配置说明
13. 常见问题

✨ 1. 功能特性

🖼️ 图片尺寸检测

自动读取 background-image 中图片的宽度和高度

📐 单位转换

自动将 px 转换为 rem 单位(基于配置的 font-size)

🎯 居中计算

自动生成 left/top: calc(50% - width/2)

🖼️ Background-size

支持生成 background-size 属性(rem/px/cover/contain)

核心优势

📁 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', // Trigger on 'w' 'h', // Trigger on 'h' 'r', // Trigger on 'r' 'p', // Trigger on 'p' (whpx) 'b', // Trigger on 'b' (whbs) 's', // Trigger on 's' (whbs) 'c', // Trigger on 'c' (whbsc, whcc) 't', // Trigger on 't' (whbct, whtc) 'a', // Trigger on 'a' (whall) 'l', // Trigger on 'l' (whlc) ' ' // Trigger on space ); 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(); // 匹配 wh 开头的指令 if (!/wh\w*$/i.test(trimmedText)) { return []; } // 查找 background-image URL 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 [ // rem 单位 { 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: 何时激活插件 "activationEvents": [ "onLanguage:css", // 打开 .css 文件 "onLanguage:scss", // 打开 .scss 文件 "onLanguage:sass", // 打开 .sass 文件 "onLanguage:less", // 打开 .less 文件 "onLanguage:vue" // 打开 .vue 文件 ] // triggerCharacters: 什么字符触发补全 'triggerCharacters': [ 'w', // wh*, whr, whpx, whbs, whall 'h', // wh* 'r', // whr 'p', // whpx 'b', // whbs 's', // whbs 'c', // whbsc, whcc 't', // whbct, whtc 'a', // whall 'l', // whlc ' ' // 空格 ]

6.3 补全执行流程

用户输入 'w'
→
VSCode 检测到 triggerCharacter
→
调用 provideCompletionItems()
→
正则匹配 'wh*'
查找 background-image URL
→
读取图片尺寸
→
计算 rem 值
→
返回补全选项

6.4 核心代码示例

// snippetProvider.ts - 核心逻辑 provideCompletionItems(...) { // 1. 获取光标前的文本 const textBeforeCursor = lineText.substring(0, position.character); // 2. 检查是否匹配 wh* 模式 if (!/wh\w*$/i.test(trimmedText)) { return []; // 不匹配则返回空 } // 3. 查找 background-image const imageUrl = this.findBackgroundImageUrl(document, position); // 4. 读取图片尺寸并生成代码片段 return this.createCompletionItems(...); } // fontSize.ts - 配置读取 export function getFontSize(): number { const config = vscode.workspace.getConfiguration('autoWidthHeightRem'); return config.get<number>('fontSize', 100); } // remConverter.ts - 单位转换 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
2 用 VSCode 打开项目
code .
3 按 F5 启动调试
4 会打开一个新的 VSCode 窗口(Extension Development Host)
5 在新窗口中打开测试文件
test/test.css 或 test/test.vue
6 输入以下代码测试:
/* 测试 CSS */ .test { background-image: url('./test.png'); whr /* ← 输入后应该看到补全选项 */ } /* 测试居中 */ .box { background-image: url('./box.png'); whcc /* ← 生成 left + top 居中 */ }

方法 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 # 或在 VSCode 中 # Cmd + Shift + X → 搜索插件 → 点击卸载

🚀 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" }
3 发布
vsce publish

完整发布流程(命令行)

注册 Azure DevOps
→
创建 PAT
→
vsce login
→
vsce publish
→
等待审核(1-3天)
→
上架成功!🎉
注意事项:
  • 发布前确保测试通过
  • 版本号需要递增(每次发布必须不同)
  • README.md 会显示在商店页面
  • 图标需要在 package.json 中配置 "icon": "icon.png"

⚠️ 图片链接注意事项(重要)

VSCode Marketplace 不支持本地相对路径图片!
README.md 中的图片必须使用绝对 URL,否则在商店页面不会显示。

❌ 错误写法(不显示)

# 本地相对路径 - 不会显示 ![Demo](./option.gif) ![Logo](./images/logo.png)

✅ 正确写法(会显示)

# 绝对 URL - 可以显示 ![Demo](https://raw.githubusercontent.com/用户名/仓库名/main/option.gif) ![Logo](https://raw.githubusercontent.com/用户名/仓库名/main/images/logo.png)

如何获取 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

示例配置

// 如果你的项目 font-size: 100px(推荐) { "autoWidthHeightRem.fontSize": 100 } // 如果你的项目 font-size: 50px { "autoWidthHeightRem.fontSize": 50 } // 如果你的项目 font-size: 16px(浏览器默认) { "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/** !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 值几乎都是错的。本插件会读取图片实际尺寸并精确计算,所以请务必使用本插件的补全结果。