Web 无障碍工程化实战:VSCode 扩展 + AI 自动修复全解析

Web 无障碍工程化实战:VSCode 扩展 + AI 自动修复全解析

在大型Web系统开发中,界面是否符合无障碍设计标准,直接影响着不同能力用户的使用体验。

然而在功能复杂、界面繁多的Web系统中,开发团队往往将重心集中在业务逻辑实现和功能完整性上,容易忽视界面的可访问性设计,导致特殊用户群体无法正常使用系统功能。

通过遵循无障碍设计原则,可以确保视觉障碍、听觉障碍、运动障碍等不同需求的用户都能平等地访问和使用Web应用。

本文将从理论到实践,全面阐述无障碍开发的核心概念与实施方案。首先介绍无障碍开发的基本理念和重要意义,然后解析WCAG等主流无障碍规范标准,梳理当前可用的无障碍检测和修复工具生态。最后,本文将通过实现一个功能完整的VSCode扩展插件,为Web开发人员提供集成化的无障碍开发辅助工具,帮助开发团队在日常编码过程中更好地识别和解决无障碍问题。

引言

WCAG(Web Content Accessibility Guidelines) 是由 W3C 的 WAI 组织制定的网络内容无障碍标准。这套指南主要为残障人士提供更好的网络访问体验,同时也能改善所有用户和设备(包括数字助理等受限设备)的使用体验。

目前 WCAG 2.2 是最新的正式版本,而 WCAG 2.1 和 2.0 仍在广泛使用中。

WCAG 3.0 还处于工作草案阶段。新版本并不会取代旧版本,但 WAI 建议开发者优先使用最新版本,以确保网站获得最佳的无障碍访问效果。

无障碍指南:https://www.w3.org/TR/WCAG21/

Web界面案例分析

下图是一个存在多个问题的Web界面和修复后的结果

从直观上看,左侧的web界面给人的印象是模糊混乱的,右侧的web界面给人的印象是简洁美观的。原因在于左侧的web界面没有考虑无障碍指南中提到的多个要点,下面我们将逐一分析界面存在的问题。

以下是左侧界面表格部分源码:

HTML 复制代码
<h2>季度销售表</h2>
<table>
    <tr>
        <th>季度</th>
        <th>销售额</th>
        <th>区域</th>
    </tr>
    <tr>
        <td>Q1</td>
        <td>12000</td>
        <td><a href="#">东部</a></td>
    </tr>
    <tr>
        <td>Q2</td>
        <td>15000</td>
        <td><a href="#">西部</a></td>
    </tr>
    <tr>
        <td>Q3</td>
        <td>9000</td>
        <td><a href="#">南部</a></td>
    </tr>
    <tr>
        <td>Q4</td>
        <td>20000</td>
        <td><a href="#">北部</a></td>
    </tr>
</table>

在设计表格时,由于缺少 标签,表格标题用

写在外面。也没有使用 和 区分表头和数据区域,这将导致屏幕阅读器无法将标题与表格关联。

当表格没有正确标记的表头时,屏幕阅读器只能逐个朗读单元格内容,用户听到的是一串没有上下文的数据,完全不知道每个数据代表什么意思。除此之外,表格的样式设计也存在问题,虽然使用了奇偶行颜色差异,但是色差较小,最终给人的直观印象不够清晰明了

CSS 复制代码
tbody tr:nth-child(even) {
    background: #FAFBFE;
}

修改后的代码如下:

XML 复制代码
<table>
    <caption class="visually-hidden">2025 年各季度按区域的销售额(单位:元)</caption>
    <thead>
        <tr>
            <th scope="col">季度</th>
            <th scope="col">销售额</th>
            <th scope="col">区域</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Q1</td>
            <td>12000</td>
            <td><a href="#">东部</a></td>
        </tr>
        <tr>
            <td>Q2</td>
            <td>15000</td>
            <td><a href="#">西部</a></td>
        </tr>
        <tr>
            <td>Q3</td>
            <td>9000</td>
            <td><a href="#">南部</a></td>
        </tr>
        <tr>
            <td>Q4</td>
            <td>20000</td>
            <td><a href="#">北部</a></td>
        </tr>
    </tbody>
</table>

除此之外,对颜色也做了调整:

CSS 复制代码
tbody tr:nth-child(even) {
    background: #F5F8FF;
}

最终效果如下:

再来观察原界面的表单部分,输入框得到焦点后,样式设计也不够直观。

此外按钮的背景色和前景色的对比度也较小,不够清晰。

CSS 复制代码
:focus {
    outline: none;
    box-shadow: 0 0 0 2px rgba(26, 115, 232, 0.25);
    border-radius: 4px;
}

.btn {
    display: inline-block;
    background: #4A90E2;
    color: #fff;
    padding: 5px;
    border: 0;
    border-radius: 3px;
    cursor: pointer;
}

让我们使用以下代码,修正表单样式,突出文本框得到焦点后的样式,让按钮的对比度更强烈

CSS 复制代码
:focus-visible {
    outline: 3px solid #1A73E8;
    outline-offset: 2px;
}

.btn {
    background: #2F6BC2;
    color: #fff;
    padding: 8px;
    border: 0;
    border-radius: 6px;
    cursor: pointer;
}

修改之后的界面明显更清晰直观。

无障碍指南

基于以上分析,我们了解到web界面存在多种设计细节,每一处缺陷都可能让整个界面的用户体验大打折扣。

那么标准的无障碍指南都制定了那些规范呢?

让我们看看下总结的内容:

1)对比度达标

  • 设计原则1:对比度达标
  • 设计思路1:保证文字和背景有足够的对比度,用户能很容易分辨出页面的组件
  • 代码分析1:
CSS 复制代码
/* ❌ 对比度不足 */
.bad-contrast {
    color: #999999;
    background: #ffffff; /* 对比度约 2.85:1 */
}

/* ✅ 符合 AA 标准 */
.good-contrast {
    color: #595959;
    background: #ffffff; /* 对比度约 4.54:1 */
}

/* ✅ 符合 AAA 标准 */
.excellent-contrast {
    color: #333333;
    background: #ffffff; /* 对比度约 7.73:1 */
}

2)图片设置替代文本

  • 设计原则2:图片设置替代文本
  • 设计思路2:所有非文本内容提供合适的 alt,供读屏器朗读,辅助用户理解含义
  • 代码分析2:
XML 复制代码
<!-- ✅ 描述图片传达的信息 -->
<img src="sales-chart.png" alt="2023年第四季度销售额增长25%">

<!-- ❌ 不设置alt属性 -->
<img src="sales-chart.png">

3)键盘无障碍

  • 设计原则3:键盘无障碍
  • 设计思路3:所有功能可用键盘操作,焦点顺序合理且样式清晰可见
  • 代码分析3:
CSS 复制代码
/* ✅ 清晰的焦点指示 */
button:focus {
    outline: 2px solid #005fcc;
    outline-offset: 2px;
}

/* ✅ 高对比度焦点样式 */
.custom-focus:focus {
    box-shadow: 0 0 0 3px rgba(0, 95, 204, 0.3);
    border: 2px solid #005fcc;
}

/* ❌ 移除焦点样式 */
button:focus {
    outline: none;
}

4)表单可理解

  • 设计原则4:表单可理解
  • 设计思路4:每个输入有 程序化关联,使用aria-describedby属性描述组件的输入信息和错误提示,供读屏器朗读
  • 代码分析4:
XML 复制代码
<!-- ✅ 使用 fieldset 和 legend -->
<fieldset>
    <legend>联系方式</legend>
    <label for="phone">电话</label>
    <input type="tel" id="phone">
    
    <label for="email2">邮箱</label>
    <input type="email" id="email2">
</fieldset>

<!-- ✅ 单选按钮组 -->
<fieldset>
    <legend>选择付款方式</legend>
    <input type="radio" id="credit" name="payment" value="credit">
    <label for="credit">信用卡</label>
    
    <input type="radio" id="paypal" name="payment" value="paypal">
    <label for="paypal">PayPal</label>
</fieldset>

5)语义结构与原生优先

  • 设计原则5:语义结构与原生优先
  • 设计思路5:正确使用标题层级、列表、表格表头/范围;优先使用 / 等原生控件,而不是div代替
  • 代码分析5:
XML 复制代码
<!-- ✅ 使用原生按钮 -->
<button type="button" onclick="submitForm()">提交</button>

<!-- ❌ 用 div 模拟按钮 -->
<div class="fake-button" onclick="submitForm()">提交</div>

<!-- ✅ 原生链接 -->
<a href="/products">查看产品</a>

<!-- ❌ 用其他标签模拟链接 -->
<span class="fake-link" onclick="location.href='/products'">查看产品</span>

6)响应式与可重排

  • 设计原则6:响应式与可重排
  • 设计思路6:在窄屏(如 320px)内容清晰可读、不需水平滚动/ 等原生控件,而不是div代替
  • 代码分析6:
CSS 复制代码
/* ✅ 相对单位确保可缩放 */
body {
    font-size: 1rem; /* 16px */
    line-height: 1.5;
}

h1 {
    font-size: 2rem; /* 32px */
}

/* ✅ 在小屏幕上适当调整 */
@media (max-width: 320px) {
    body {
        font-size: 0.9rem;
    }
    
    h1 {
        font-size: 1.75rem;
    }
}

axe扫描器工具

除了上文详细介绍的各种无障碍界面设计原则,开发中我们可以借用扫描器工具,检查web界面是否存在问题。

axe DevTools 是由 Deque 开发的Chrome 浏览器扩展,专为开发者、测试人员和设计师打造的无障碍检测工具。它基于业界知名的 axe-core 引擎,能够快速、准确地发现并修复网站无障碍问题。

axe DevTools 安装地址:https://chromewebstore.google.com/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd

安装上述扩展后,可以按照如下步骤检测:

首先,打开开发者调试窗口:

找到新增的axe DevTools的tab标签,点击后即可打开axe 工具的界面

框选界面某个部分,即可开始检测。例如下图检测出表单存在一些问题:

VSCode 扩展实现界面无障碍检测

除了使用 axe DevTools工具,我们还可以使用其他工具进行检测

axe-core 是一个专为网站和 HTML 界面设计的无障碍测试引擎,支持 WCAG 2.0、2.1、2.2 各级别标准,具有快速、安全、轻量级的特点,能够无缝集成到现有测试环境中。

下面是一个简单的介绍:

首先安装 axe-core这个npm包:

Bash 复制代码
npm install axe-core --save-dev

axe-core包提供了axe模块,该模块提供了一个run方法,运行之后可以检查出页面所有的无障碍问题,实现的JS代码如下:

JavaScript 复制代码
axe
  .run()
  .then(results => {
    if (results.violations.length) {
      console.log('发现无障碍问题:', results.violations);
      throw new Error('Accessibility issues found');
    } else {
      console.log('未发现无障碍问题!');
    }
  })
  .catch(err => {
    console.error('检测过程中出错:', err.message);
  });

除此之外,我们还可以配置检测的具体规则,以及某条规则检测失败后,如何汇报警告消息

JavaScript 复制代码
// 配置检测规则和级别
axe.configure({
  branding: {
    brand: "测试应用",
    application: "accessibility-checker"
  },
  rules: {
    // 禁用某些规则
    'color-contrast': { enabled: false },
    // 只检查 AA 级别
    'wcag2aa': { enabled: true }
  },
  // 只运行指定标签的规则
  tags: ['wcag2a', 'wcag2aa'] 
});

// 应用中文本地化
axe.configure({
  locale: {
    lang: 'zh',
    rules: {
      'missing-headings': {
        help: '页面应该包含至少一个 h1 标题'
      }
    },
    checks: {
      'color-contrast': {
        fail: '文本颜色与背景颜色对比度不足'
      }
    }
  }
});

基于以上对axe的基本使用,我们可以创建一个vscode扩展用来在编写web界面时检测无障碍问题。

1 使用如下命令搭建环境:

Bash 复制代码
npm install -g yo generator-code

Yeoman 是微软推荐的脚手架工具,它会为我们生成完整的扩展项目结构:

  • yo: Yeoman 命令行工具,用于运行代码生成器
  • generator-code: 微软官方的 VSCode 扩展生成器,包含了扩展开发的最佳实践模板

生成的项目结构包含:

  • src/extension.ts: 扩展的主入口文件,包含 activatedeactivate 函数
  • package.json: 扩展的清单文件,定义扩展的功能、命令、配置等
  • tsconfig.json: TypeScript 编译配置
  • .vscode/: 包含调试配置,让我们能够直接在 VSCode 中调试扩展

2 安装依赖包

运行如下命令

Bash 复制代码
cd accessibility-checker 
npm install axe-core jsdom 
npm install --save-dev @types/vscode
  • axe-core
    • 一个纯 JavaScript 库,可以在任何 JavaScript 环境中运行
    • 包含了 WCAG 2.0/2.1/2.2 的完整规则集,覆盖 A、AA、AAA 三个等级
  • jsdom: Node.js 环境下的 DOM 模拟器
    • 由于 axe-core 需要 DOM 环境才能运行,而 VSCode 扩展运行在 Node.js 中
    • jsdom 创建一个完整的虚拟 DOM 环境,让我们能在后端运行前端代码
    • 支持大部分 Web API,包括 documentwindowElement
  • @types/vscode: VSCode API 的 TypeScript 类型定义
    • 提供完整的 VSCode 扩展 API 类型提示
    • 包含所有命令、事件、UI 组件的类型定义
    • 让我们能够安全地使用 VSCode 的各种功能

3 创建 axe-core 扫描器

axe-core 原本设计在浏览器中运行,需要 DOM 环境,我们需要将浏览器环境下的 axe-core 移植到 VSCode 扩展的 Node.js 环境,将 axe-core 的检测结果映射到 VSCode 的诊断系统。

TypeScript 复制代码
import * as vscode from "vscode";

// 定义数据结构 - 映射 axe-core 的返回结果
export interface AxeResults {
  violations: AxeViolation[];
}

export interface AxeViolation {
  id: string;           // 规则ID,如 'missing-headings'
  help: string;         // 简短的帮助信息
  description: string;  // 详细的问题描述
  nodes: AxeNode[];     // 有问题的 DOM 节点
}

export interface AxeNode {
  html: string;         // 节点的 HTML 源码
  target: string[];     // CSS 选择器路径
  failureSummary?: string; // 失败原因总结
}

export class AxeScanner {
  async scanDocument(doc: vscode.TextDocument): Promise<AxeResults | null> {
    const html = doc.getText();
    
    try {
      const { JSDOM } = await import("jsdom");
      const axe = await import("axe-core");
      // 创建虚拟 DOM 环境
      const { document } = new JSDOM(html).window;
      
      // 运行 axe-core 检测整个页面内容
      const results = await axe.run(document.body as any, {
        rules: {
          "color-contrast": { enabled: false },
        }
      });

      // 数据转换
      // 将 axe-core 结果转换为VSCode中需要的数据结构
      return {
        violations: results.violations.map((v: any) => ({
          id: v.id,
          help: v.help,
          description: v.description,
          nodes: v.nodes.map((n: any) => ({
            html: n.html,
            target: n.target ?? [],
            failureSummary: n.failureSummary,
          }))
        }))
      };
    } catch (error) {
      console.error('扫描过程中发生错误:', error);
      throw error;
    }
  }
}

4 实现扫描功能

JavaScript 复制代码
import * as vscode from "vscode";
import { AxeScanner } from "./axe-scanner";

export async function performScan(
  textEditor: vscode.TextEditor, 
  axeScanner: AxeScanner, 
  context: vscode.ExtensionContext
) {
  const doc = textEditor.document;

  vscode.window.showInformationMessage("开始检测无障碍问题...");

  try {
    // 使用上文中创建的 AxeScanner类进行无障碍检测
    const results = await axeScanner.scanDocument(doc);

    // 处理无问题的情况
    if (!results?.violations.length) {
      vscode.window.showInformationMessage("✅ 未发现无障碍问题!");
      // 清除之前的诊断信息
      const collection = vscode.languages.createDiagnosticCollection("accessibility-checker");
      collection.set(doc.uri, []);
      context.subscriptions.push(collection);
      return;
    }

    // 转换检测结果为 VSCode 诊断格式
    const diagnostics: vscode.Diagnostic[] = [];
    for (const violation of results.violations) {
      for (const node of violation.nodes) {
        // 定位问题在源码中的位置
        const range = findElementRange(doc, node.html);
        
        // 创建诊断对象
        const diagnostic = new vscode.Diagnostic(
          range ?? new vscode.Range(0, 0, 0, 1),  // 默认位置防止错误
          `${violation.help}\n${violation.description}`, // 完整的问题描述
          vscode.DiagnosticSeverity.Warning              // 警告级别
        );
        
        // 添加错误代码和来源信息
        diagnostic.code = violation.id;
        diagnostic.source = 'accessibility-checker';
        
        diagnostics.push(diagnostic);
      }
    }

    // 将诊断信息注册到 VSCode 系统
    const collection = vscode.languages.createDiagnosticCollection("accessibility-checker");
    collection.set(doc.uri, diagnostics);
    context.subscriptions.push(collection);

    // 向用户报告检测结果
    vscode.window.showWarningMessage(
      `⚠️ 发现 ${results.violations.length} 个无障碍问题`,
      '查看问题'
    ).then(selection => {
      if (selection === '查看问题') {
        vscode.commands.executeCommand('workbench.action.problems.focus');
      }
    });
  } catch (error: any) {
    // 错误处理 - 提供有意义的错误信息
    vscode.window.showErrorMessage(`扫描失败: ${error.message}`);
    console.error('扫描失败:', error);
  }
}

// 源码定位算法
function findElementRange(doc: vscode.TextDocument, html: string): vscode.Range | undefined {
  const text = doc.getText();
  const index = text.indexOf(html);
  if (index === -1) return undefined;
  
  // 将字符索引转换为行列位置
  const start = doc.positionAt(index);
  const end = doc.positionAt(index + html.length);
  return new vscode.Range(start, end);
}

5 在入口文件中注册扫描功能

JavaScript 复制代码
export function activate(context: vscode.ExtensionContext) {
  // 创建扫描器实例
  const axeScanner = new AxeScanner();

  // 注册扫描命令
  const scanCommand = vscode.commands.registerTextEditorCommand(
    "accessibility-checker.scan",  
    async (textEditor: vscode.TextEditor) => {
      // 检查是否是 HTML 文件
      if (textEditor.document.languageId !== 'html') {
        vscode.window.showWarningMessage('此功能仅支持 HTML 文件');
        return;
      }

      // 调用扫描函数
      await performScan(textEditor, axeScanner, context);
    }
  );

  // 将命令注册到扩展生命周期中
  context.subscriptions.push(scanCommand);

  // 可选:添加状态栏项
  const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
  statusBarItem.command = 'accessibility-checker.scan';
  statusBarItem.text = '$(accessibility) A11Y';
  statusBarItem.tooltip = '检查无障碍问题 (Ctrl+Alt+A)';
  
  // 只在 HTML 文件中显示状态栏项
  const updateStatusBar = () => {
    const editor = vscode.window.activeTextEditor;
    if (editor && editor.document.languageId === 'html') {
      statusBarItem.show();
    } else {
      statusBarItem.hide();
    }
  };

  // 监听编辑器切换事件
  vscode.window.onDidChangeActiveTextEditor(updateStatusBar);
  updateStatusBar(); // 初始化状态栏

  context.subscriptions.push(statusBarItem);
}

6 在package.json中绑定步骤5的命令

Bash 复制代码
"contributes": {
  "commands": [
    {
      "command": "accessibility-checker.scan",
      "title": "扫描无障碍问题",
      "category": "无障碍检查",
      "icon": "$(accessibility)"
    }
  ],
  "menus": {
    "editor/context": [
      {
        "command": "accessibility-checker.scan",
        "when": "resourceExtname == .html",
        "group": "accessibility@1"
      }
    ],
    "commandPalette": [
      {
        "command": "accessibility-checker.scan",
        "when": "editorLangId == html",
        "title": "无障碍检查: 扫描当前文件"
      }
    ],
    "explorer/context": [
      {
        "command": "accessibility-checker.scan",
        "when": "resourceExtname == .html",
        "group": "accessibility@1"
      }
    ]
  },
  "keybindings": [
    {
      "command": "accessibility-checker.scan",
      "key": "ctrl+alt+a",
      "mac": "cmd+alt+a",
      "when": "editorLangId == html"
    }
  ]
}

最终效果如下:

安装该扩展,打开html文件,在右键菜单中找到无障碍检测

点击该菜单项,启动无障碍检测

检测到该问题后,插件会在响应代码行处添加黄色波浪线

鼠标悬停在某一行,可以看到无障碍问题

AI赋能无障碍检测与修复

由于上述插件仅利用axe工具检测了无障碍问题,开发者需要逐一修复这些问题。

考虑到VSCode提供了AI大语言模型 API ,我们还可以实现了从"发现问题"到"自动解决"的完整闭环。

设计思路如下:

  1. 首先通过 axe-core 引擎扫描当前 HTML 文档,获取具体的无障碍违规项目和详细描述。然后将检测结果与原始源码结合,构建结构化的上下文提示词,为 AI 模型提供完整的问题背景和修复目标。
  2. 利用 VS Code 的语言模型 API 进行异步调用,确保 AI 能够基于具体问题生成针对性的修复方案。
  3. 智能代码提取与格式处理:针对 AI 模型输出的不确定性,设计多重正则表达式匹配策略,能够从不同格式的响应中准确提取 HTML 代码。通过代码清理算法去除多余的标记和格式,确保得到可直接使用的代码。
  4. 应用与状态同步:使用 WorkspaceEdit API 进行文档级别的完整替换操作,确保修复过程的原子性。修复完成后自动清除相关的诊断信息,并通过进度条和通知消息向用户反馈修复状态。

具体思路如下:

JavaScript 复制代码
// AI修复无障碍问题的处理函数
export async function handleFixCommand(
  textEditor: vscode.TextEditor,
  axeScanner: AxeScanner,
  context: vscode.ExtensionContext
) {
  const editor = textEditor;
  if (!editor) {
    vscode.window.showErrorMessage("❌ 请先打开HTML文件");
    return;
  }

  // 检查是否是 HTML 文件
  if (editor.document.languageId !== "html") {
    vscode.window.showWarningMessage("此功能仅支持 HTML 文件");
    return;
  }

  // 显示进度提示
  await vscode.window.withProgress(
    {
      location: vscode.ProgressLocation.Notification,
      title: "AI修复无障碍问题",
      cancellable: false,
    },
    async (progress) => {
      // 第一阶段:问题检测
      progress.report({ increment: 0, message: "🔍 正在扫描问题..." });

      const results = await axeScanner.scanDocument(editor.document);
      if (!results?.violations.length) {
        vscode.window.showInformationMessage("✅ 未发现问题!");
        return;
      }

      progress.report({
        increment: 30,
        message: `发现 ${results.violations.length} 个问题`,
      });

      // 构造修复提示词 - 结合具体问题和源码
      const fixPrompt = `修复以下HTML的无障碍问题:

当前代码:
${editor.document.getText()}

检测到的问题:
${results.violations
  .map((v, i) => `${i + 1}. ${v.help} - ${v.description}`)
  .join("\n")}

请返回修复后的完整HTML代码,只返回代码,不要解释。`;

      // 第二阶段:AI 修复
      progress.report({ increment: 50, message: "🔧 正在AI修复..." });

      try {
        // 获取可用的语言模型
        const models = await vscode.lm.selectChatModels({
          vendor: "copilot",
          family: "gpt-4o",
        });

        if (models.length === 0) {
          vscode.window.showErrorMessage(
            "❌ 未找到可用的AI模型,请确保已登录GitHub Copilot"
          );
          return;
        }

        const model = models[0];
        const messages = [
          vscode.LanguageModelChatMessage.User(A11Y_SYSTEM_PROMPT),
          vscode.LanguageModelChatMessage.User(fixPrompt),
        ];

        // 调用 VSCode 的语言模型 API
        const response = await model.sendRequest(messages, {});
        let fixedCode = "";
        for await (const fragment of response.text) {
          fixedCode += fragment;
        }

        progress.report({ increment: 80, message: "🔧 处理修复结果..." });

        // 代码提取算法 - 处理 AI 返回的格式化内容
        const codeMatch =
          fixedCode.match(/```html\n([\s\S]*?)\n```/) ||
          fixedCode.match(/```\n([\s\S]*?)\n```/);
        const cleanCode = codeMatch ? codeMatch[1].trim() : fixedCode.trim();

        // 第三阶段:应用修复
        progress.report({ increment: 90, message: "✅ 应用修复..." });

        if (cleanCode && cleanCode !== editor.document.getText()) {
          const edit = new vscode.WorkspaceEdit();
          const fullRange = new vscode.Range(
            0,
            0,
            editor.document.lineCount,
            0
          );
          edit.replace(editor.document.uri, fullRange, cleanCode);
          await vscode.workspace.applyEdit(edit);

          // 清除所有诊断信息 - 表示问题已解决
          const collection = vscode.languages.createDiagnosticCollection(
            "accessibility-checker"
          );
          collection.set(editor.document.uri, []);
          context.subscriptions.push(collection);

          progress.report({ increment: 100, message: "✅ 修复完成!" });
          vscode.window.showInformationMessage("✅ 修复完成!问题已自动解决。");
        } else {
          vscode.window.showWarningMessage("❌ 修复失败,请手动检查代码。");
        }
      } catch (error: any) {
        vscode.window.showErrorMessage(`❌ AI修复失败: ${error.message}`);
        console.error("AI修复失败:", error);
      }
    }
  );
}

最终效果如下:

在需要进行无障碍检测的页面右键,选择AI修复无障碍问题

在右下角显示状态和进度

修复完成后,显示提示信息

总结与展望

在本文中,我们学习到了web界面设计中的无障碍功能,同时了解了最基本的无障碍设计原则。通过vscode提供的API,我们可以快速搭建一个扩展应用,辅助开发人员查找界面存在的问题。最后我们借助AI能力,可以自动修复无障碍缺陷。以下是一个本文使用的源码工程:https://gitee.com/GrapeCity/accessibility-checker

相关推荐
G_G#5 分钟前
纯前端js插件实现同一浏览器控制只允许打开一个标签,处理session变更问题
前端·javascript·浏览器标签页通信·只允许一个标签页
wzfj1234510 分钟前
vscode通过remote-ssh快速浏览远程pc的文件
vscode
@大迁世界21 分钟前
TypeScript 的本质并非类型,而是信任
开发语言·前端·javascript·typescript·ecmascript
GIS之路29 分钟前
GDAL 实现矢量裁剪
前端·python·信息可视化
是一个Bug33 分钟前
后端开发者视角的前端开发面试题清单(50道)
前端
Amumu1213835 分钟前
React面向组件编程
开发语言·前端·javascript
持续升级打怪中1 小时前
Vue3 中虚拟滚动与分页加载的实现原理与实践
前端·性能优化
GIS之路1 小时前
GDAL 实现矢量合并
前端
hxjhnct1 小时前
React useContext的缺陷
前端·react.js·前端框架
前端 贾公子1 小时前
从入门到实践:前端 Monorepo 工程化实战(4)
前端