Skip to content

Tutorial: Adding a feature to HyperCRX

Lam Tang edited this page Mar 26, 2024 · 13 revisions

As discussed in #548 and its related issues, HyperCRX adopts a specifically designed mechanism to load all of its features. The feature loading mechanism is well explained in our latest paper HyperCRX: A Browser Extension for Insights into GitHub Projects and Developers which was accepted by ICSE 2024. So in this tutorial, we will not delve into the details of the feature loading mechanism. If you have any questions about this mechanism, please read the relevant source code and the paper aforenamed.

案例介绍

在这篇教程中,你将通过一个教学案例学会如何为HyperCRX开发一个叫做colorful-calendar的新特性。这个特性用于改变GitHub用户Profile页面的日历图格子的颜色,例如从绿色改成紫色:

image

手把手教程

废话不多说,让我们开始吧!

步骤0. 准备工作

准备好开发环境Node.js Yarn 配置NPM源;如何运行项目;使用Chrome X-lab账号;开发前先创建Git分之;……

步骤1. 为新特性创建一个目录和一个index.tsx文件

在HyperCRX的项目中,src/pages/ContentScripts/features目录包含了所有特性的源码。在该目录下,每个特性都对应着一个目录,并且目录名就是特性的名称。因此,我们要为colorful-calenda这个特性创建一个同名的新目录。

image

创建目录后,我们要在特性目录中创建一个名为index.tsx的新文件,所有特性的目录下都有index.tsx文件,这个文件是特性的入口文件。我们将下面代码填入文件中(对此段代码的解释会在后文中展开):

import features from '../../../../feature-manager';

import * as pageDetect from 'github-url-detection';

const featureId = features.getFeatureID(import.meta.url);

const init = async (): Promise<void> => {
  console.log('init colorful-calendar');
};

const restore = async () => {
  console.log('restore colorful-calendar');
};

features.add(featureId, {
  asLongAs: [pageDetect.isUserProfile],
  awaitDomReady: false,
  init,
  restore,
});

在创建了特性目录和index.tsx文件后,我们在src/pages/ContentScript/index.ts中引入该特性,如下所示:

// 省略其他已有特性的 import
// ...
import './features/colorful-calendar';

在此文件中引入新特性后,需要杀掉开发进程并重新运行yarn run start来生成新的特性列表,因为feature-loader.cjs只会在项目初次构建时运行一次。之后,在浏览器chrome://extensions/页面中点击按钮重载HyperCRX扩展程序,然后打开HyperCRX的选项页面,你将发现colorful-calendar已经出现在特性列表中并处于启用状态:

image

请再访问你的GitHub主页,并打开Chrome DevTools,如果你发现控制台中输出了“init colorful-calendar”,那么恭喜你成功迈出了第一步!

image

温馨提示:刚刚你已经收获了初步的成功,请及时打一个Commit,细粒度的Commit对软件开发是大有裨益的。

步骤2. 对GitHub用户Profile页面的日历元素进行逆向工程

HyperCRX是一款为GitHub量身打造的浏览器扩展,所谓量身打造,就是通过分析GitHub页面DOM元素,寻找突破口,然后通过浏览器扩展Content Script能力操纵宿主DOM达到目的。为了改变日历格子的颜色,我们先要了解日历格子对应的DOM元素。如下图所示,点击Chrome DevTools的Inspect按钮检视日历格子,定位其在DOM树中的位置,发现它是用div元素实现的。在右侧属性面板中,我们可以轻易发现和颜色有关的CSS样式属性,通过与属性面板进行交互,可以确定var(--color-calendar-graph-day-L1/2/3/4-bg)是控制格子颜色的CSS Variables。没错,我们已经找到了突破口。

image

步骤3. 在index.tsx文件中操作DOM改变日历格子颜色

在步骤1中,我们在新建的index.tsx中写了一些代码,现在我通过代码注释的方式对这段代码做些解释:

import features from '../../../../feature-manager'; // 导入特性管理器模块

import * as pageDetect from 'github-url-detection'; // 导入第三方的GitHub页面检测模块

const featureId = features.getFeatureID(import.meta.url); // 通过特性管理器的getFeatureID方法获取当前特性的ID

const init = async (): Promise<void> => { // 该特性的初始化工作都在这里进行
  console.log('init colorful-calendar');
};

const restore = async () => { // 在GitHub的restoration visit后运行,对于此特性可以不需要在该函数中写内容,详见论文
  console.log('restore colorful-calendar');
};

features.add(featureId, {  // 调用特性管理器的add方法添加特性,第一个参数是ID,第二个参数是meta信息配置对象
  asLongAs: [pageDetect.isUserProfile], // 表示“只有当前页面是用户Profile页面时才运行该特性”
  awaitDomReady: false, // 是否等待DOM加载完毕,如无特殊情况,都置为false
  init, // 指明初始化函数,"init,"是"init: init,"的简写,这是ES6的特性
  restore,
});

所以,init函数是我们要写代码的地方。浏览器扩展赋予我们Content Script的能力,该能力允许我们直接访问宿主页面的DOM并进行操作。下面代码通过改变我们在步骤2中确认的相关CSS Variables的值实现了改变日历格子颜色的目的:

const init = async (): Promise<void> => {
  const root = document.documentElement;
  root.style.setProperty('--color-calendar-graph-day-L1-bg', '#ffedf9');
  root.style.setProperty('--color-calendar-graph-day-L2-bg', '#ffc3eb');
  root.style.setProperty('--color-calendar-graph-day-L3-bg', '#ff3ebf');
  root.style.setProperty('--color-calendar-graph-day-L4-bg', '#c70085');
};

保存代码,Webpack增量编译,页面刷新后,我们就可以看到日历格子的颜色被改变了:

image

怎么样,很酷吧~😎不要忘了做个Commit!

步骤4. 提供UI交互从而使用户方便地自定义日历格子的颜色

首先要设计UI交互,放在什么位置以什么形式呈现;然后是实现,需要用到View.tsx;需要在页面上插入新元素;需要用antd的ColorPicker组件;……

步骤5. 创建Pull request

推送分支到origin;向upstream提PR;描述好截图录屏等;等待reviewer意见;成功合入后及时将本地master与upstream的master同步;……

总结

……

Clone this wiki locally