VS Code扩展开发:批量替换HTML路径为Django static标签
需求说明
开发VS Code扩展,自动将编辑器打开文件内的静态资源链接转换为Django模板的{% static %}标签格式,预期转换效果如下:
转换前(BEFORE)
<img src="assets/images/avatars/avatar-1.jpg" alt=""> <link rel="stylesheet" href="assets/css/icons.css"> <link rel="stylesheet" href="assets/css/uikit.css"> <link rel="stylesheet" href="assets/css/style.css">
转换后(AFTER)
<img src="{% static 'assets/images/avatars/avatar-1.jpg' %}" alt=""> <link rel="stylesheet" href="{% static 'assets/css/icons.css' %}"> <link rel="stylesheet" href="{% static 'assets/css/uikit.css' %}"> <link rel="stylesheet" href="{% static 'assets/css/style.css' %}">
现有代码问题
当前实现存在两个核心缺陷:
- 正则仅匹配
<img>标签的src属性,无法覆盖<link>标签的href属性,且仅捕获第一个匹配结果,不能批量处理所有资源路径 - 替换逻辑直接将整个选中区域替换为单个转换后的路径,会覆盖选区所有原有内容
原有代码如下:
const vscode = require('vscode'); /** * @param {vscode.ExtensionContext} context */ function activate(context) { let disposable = vscode.commands.registerCommand('auto-django.autoDjango', function () { const editor = vscode.window.activeTextEditor const selection = editor.selection const text = editor.document.getText(selection) var regexp = /<img[^>]+src\s*=\s*['"]([^'"]+)['"][^>]*>/g; var match = regexp.exec(text); var src = match[1]; const newText = `{% static '${src}' %}` editor.edit(builder => builder.replace(selection, newText)) }); context.subscriptions.push(disposable); }
实现方案
调整正则匹配规则和替换逻辑即可,核心修改点:
- 优化正则,同时匹配
src和href属性,增加重复替换校验,避免给已经是{% static %}格式的路径重复套标签 - 用字符串全局替换替代单条匹配,无需逐个计算匹配位置,逻辑更稳定
- 增加边界判断,没有选中文本时默认处理整个当前打开的文档
- 替换时仅替换属性值部分,不改动标签其他属性和结构
修正后的完整代码:
const vscode = require('vscode'); /** * @param {vscode.ExtensionContext} context */ function activate(context) { let disposable = vscode.commands.registerCommand('auto-django.autoDjango', function () { const editor = vscode.window.activeTextEditor; if (!editor) return; // 无选区时默认处理整个文档 const targetRange = editor.selection.isEmpty ? new vscode.Range( editor.document.positionAt(0), editor.document.positionAt(editor.document.getText().length) ) : editor.selection; const sourceText = editor.document.getText(targetRange); // 匹配src/href属性,排除已存在的static标签、外链、根路径绝对路径 const staticPathRegex = /(src|href)\s*=\s*["'](?!{%\s*static|https?:\/\/|\/)([^"']+)["']/g; const processedText = sourceText.replace(staticPathRegex, (match, attrName, filePath) => { return `${attrName}="{% static '${filePath}' %}"`; }); editor.edit(builder => { builder.replace(targetRange, processedText); }); }); context.subscriptions.push(disposable); } module.exports = { activate }
补充说明:
- 正则内置排除规则,不会误改已套
{% static %}的路径、http/https开头的外链、/开头的根路径绝对路径 - 现有正则已自动覆盖
<script>标签的src属性,无需额外修改即可处理JS资源路径 - 基于选区做整体文本替换,不会出现位置偏移导致的替换错位问题
内容的提问来源于stack exchange,提问作者Tomi Tokko
相关产品推荐
相关产品推荐

