news 2026/10/16 7:05:24

深入参与 Simple Video Download Helper 开发:从环境搭建到新增站点解析器的完整贡献指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入参与 Simple Video Download Helper 开发:从环境搭建到新增站点解析器的完整贡献指南
  • 音视频

【免费下载链接】VideoDownloadHelper

Chrome Extension to Help Download Video for Some Video Sites.

项目地址:https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper
点击查看免费下载

本指南以仓库根目录的 CONTRIBUTING.md 为骨架,完整梳理 Simple Video Download Helper(Chrome Manifest V3 视频下载扩展)的贡献流程:从项目布局、开发环境搭建、构建打包,到编码规范、新增站点解析器、翻译维护与 PR 提交流程。读完本文,你将能够在本仓库中独立完成"新增一个视频站点解析器"和"新增一种界面语言"两大典型贡献任务,并理解解析引擎ParseVideo的真实调用链与测试、覆盖率、打包等工具链的底层实现依据。

项目概览:仓库与扩展的边界

Simple Video Download Helper 是一个帮助用户在受支持的视频站点上发现并下载视频的浏览器扩展。整个扩展及其全部工具链都位于仓库的video-url-parser/子目录中,而仓库根目录暴露了与子目录同名的 npm 脚本并**委派(delegate)**到该目录执行,因此开发者既可以在仓库根目录工作,也可以直接进入video-url-parser/工作。这一设计在根 package.json 中体现为:"test": "npm --prefix video-url-parser test"、"build": "npm --prefix video-url-parser run build"等脚本统一使用npm --prefix委派,并通过postinstall(npm --prefix video-url-parser install)在根目录安装依赖时自动联动安装子目录依赖。

项目布局:理解代码放哪里

CONTRIBUTING.md 给出了清晰的目录结构,结合仓库实际内容可进一步细化为:

. ├── package.json # 根脚本,委派进入 video-url-parser/ └── video-url-parser/ # 扩展本体 ├── manifest.json # Manifest V3 定义(权限、action、content scripts 等) ├── js/ │ ├── functions.js # 核心工具函数(单元测试覆盖) │ ├── constants.js # 共享常量(单元测试覆盖) │ ├── parsevideo.js # ParseVideo 解析引擎与站点解析器(单元测试覆盖) │ ├── getPagesSource.js # webpack 打包入口,产出 dist/dist.min.js │ ├── translate.js # 弹窗 UI 的语言切换与文本翻译逻辑 │ └── popup.js / background.js / video.js 等 # 弹窗、后台与页面脚本 ├── lang/ # 弹窗 UI 翻译文件(每种语言一个 .js 文件) ├── _locales/ # Chrome i18n messages(每个 locale 一个文件夹) ├── scripts/package.js # Chrome Web Store 打包脚本 ├── main.html # 弹窗页面,语言下拉框与脚本引用所在 └── test/ # Mocha + Chai 单元测试

其中三个核心、被单测覆盖的库文件正是解析器运行时零依赖原则的落点:

  • js/constants.js:定义max_url_length = 95(长 URL 截断阈值)与steemit_domains域名列表,并通过module.exports导出供其他模块复用;
  • js/functions.js:提供ValidURL(URL 合法性校验)、extractDomain(提取并去除www.前缀的域名)、FixURL(修复http:\/\/转义斜杠与//开头的协议相对地址)、getFileExtension、sanitizeFilename、suggestFilename、getMediaType(按扩展名将 URL 归类为 video/audio/image)、inferMediaExtension、isRestrictedUrl等一整套工具函数;
  • js/parsevideo.js:定义ParseVideo类,包含站点专属解析器与通用提取器链(详见下文"新增站点解析器"章节)。

webpack.config.js以 js/getPagesSource.js 为入口,生产构建输出为video-url-parser/dist/dist.min.js(该产物不入库)。manifest.json采用 Manifest V3,声明permissions为activeTab、storage、scripting、downloads、contextMenus,并通过content_scripts匹配http://*/*与https://*/*(显式排除*.youtube.com/*,见 manifest.json)。

开发环境搭建:三步跑起来

环境要求:Node.js >= 18(根 package.json 与 video-url-parser/package.json 的engines.node均为>=18)。

安装依赖:先将仓库 fork 并 clone 到本地,进入仓库根目录后执行npm install,根目录的postinstall钩子会自动委派安装video-url-parser/下的依赖。

构建生产包并加载到浏览器:

cd video-url-parser npm run build # 产出 dist/dist.min.js(该文件不提交入库)

随后打开chrome://extensions,开启右上角开发者模式(Developer mode),点击加载已解压的扩展程序(Load unpacked),选择video-url-parser/文件夹即可。manifest.json中已配置默认快捷键Alt+Shift+V(commands._execute_action)与默认弹窗main.html,加载后可直接点击工具栏图标或按快捷键唤起。

若要生成可提交 Chrome Web Store 的 zip 包,则在根目录或子目录运行:

npm run package # 构建并在仓库根目录写出 simple-video-download-helper-<version>.zip

打包实现位于 scripts/package.js:它从manifest.json读取version拼出 zip 文件名,将manifest.json置于 zip 顶层,并排除两类内容——按名称匹配任意深度的目录(node_modules、test、coverage、.nyc_output、scripts、.git)以及仅用于开发/工具的根文件(eslint.config.js、webpack.config.js、.prettierrc.json、.prettierignore、.nycrc.json、.mocharc.json、package.json、package-lock.json、todo-urls.txt、some-video-sites.txt等)。若dist/dist.min.js不存在,打包脚本会报错并提示先执行npm run build。

可用脚本:一张表看懂工具链

CONTRIBUTING.md 列出的脚本可在仓库根目录或video-url-parser/任意一处执行(根目录脚本内部委派到子目录):

Script说明
npm test运行 Mocha 单元测试套件
npm run coverage运行测试并强制覆盖率阈值
npm run lint使用 ESLint 检查源码与测试
npm run lint:fix尽可能自动修复 lint 问题
npm run format使用 Prettier 格式化整个代码库
npm run format:check仅校验格式,不写入改动
npm run build产出生产构建包(webpack production)
npm run package构建并生成扩展 zip 到仓库根目录
npm run check依次执行 lint、format check、coverage 与 build

打开 PR 之前,请务必确保npm run check通过。在 video-url-parser/package.json 中,check被定义为npm run lint && npm run format:check && npm run coverage && npm run build,即一条命令串起全部质量关卡。

底层工具链与配置如下(均可在仓库中核实):

  • 测试:Mocha + Chai。.mocharc.json指定spec: "test/*.js"、timeout: 5000、reporter: "spec";
  • 覆盖率:nyc(nyc mocha)。.nycrc.json限定统计范围为js/functions.js、js/constants.js、js/parsevideo.js,并强制阈值:lines、statements、functions均 ≥ 90%,branches≥ 70%,低于阈值即失败;
  • Lint:ESLint 9(flat config,见 eslint.config.js),叠加eqeqeq、no-var、prefer-const等额外规则;
  • 格式化:Prettier(.prettierrc.json),配套.prettierignore维护排除清单;
  • 构建:webpack(webpack.config.js,entry 为js/getPagesSource.js);
  • 打包:adm-zip(scripts/package.js)。

编码规范:范围受限的风格约束

代码风格由ESLint(flat config)与Prettier共同强制:4 空格缩进、双引号、分号、120 字符打印宽度(见.prettierrc.json的tabWidth: 4、singleQuote: false、semi: true、printWidth: 120)。

值得特别注意的是:lint 与格式化工具有意限定作用范围,只覆盖核心库(js/functions.js、js/constants.js、js/parsevideo.js)、测试套件与配置文件。第三方 vendored 库与遗留 UI 脚本被显式排除——在 eslint.config.js 的ignores中可以看到bs/**、images/**、lang/**、_locales/**、test/data/**、js/jquery-3.4.1.min.js、js/jquery-ui.js、js/MD5.js、js/m_inc.js、js/background.js、js/getPagesSource.js、js/popup.js、js/translate.js、js/video.js等均被排除;对应的.prettierignore也维护着同样思路的清单。当你新增文件时,请同步维护这两份忽略清单。

两条硬性约束:

  1. 核心库的新行为必须有单元测试覆盖——这由.nycrc.json的 90%/70% 覆盖率阈值在机制上保证;
  2. 解析器在运行时必须保持零依赖——parsevideo.js只require("../js/functions")内部的工具函数,不依赖任何第三方包(video-url-parser/package.json的dependencies为空,所有工具链依赖均在devDependencies中)。

新增站点解析器:核心贡献路径

这是本项目最重要的贡献类型。要理解怎么做,先理解解析引擎本身。

理解ParseVideo引擎与Parse()调用链

js/parsevideo.js 中的ParseVideo类以constructor(url, html)接收页面 URL 与 HTML 源码,其入口方法Parse()(parsevideo.js#L23-L82)按以下顺序工作:

  1. 用extractDomain(url)提取域名,与一张站点解析器注册表比对:miaopai.com、pearvideo.com、ted.com、msdn.com、weibo.com、xiaokaxiu.com、facebook.com、dailymotion.com、vimeo.com各自对应一个parse_<site>_com(...)静态方法;命中且解析结果通过ValidURL校验则立即返回;
  2. 若没有专属解析器命中,则依次走通用提取器回退链:
    • extract_all_video_urls(匹配页面中"video_url": "..."形式的 JSON 字段);
    • extract_all_mp4_urls(匹配"mp4","url":"..."形式);
    • parse_header_og_video_url(匹配<meta property="og:video:url" content="...">等 Open Graph 标签,对应测试夹具见 test/data/html-header-og-video-url.html);
    • parse_video_tag_in_html(匹配<video src="...">,测试夹具 test/data/html-video-tag.html);
    • extract_all_source_tags(匹配<video>/<audio>下的<source src="...">子标签);
    • extract_all_m3u8_urls(匹配页面内任意 HLS.m3u8播放列表地址);
    • extract_all_media_urls(兜底:匹配页面中任意直链媒体文件,扩展名集合与functions.js共享VIDEO_EXTENSIONS/AUDIO_EXTENSIONS,.m3u8因有专属提取器而被排除)。

所有提取器都遵循同一模式:正则全局匹配 →FixURL修复 →ValidURL校验 →Array.prototype.uniq()去重,最后"0 个返回null,1 个返回字符串,多个返回数组"。

按四步新增一个站点解析器

CONTRIBUTING.md 给出了标准四步:

第 1 步:添加解析函数并注册到Parse()链。

在 js/parsevideo.js 中新增一个parse_<site>_com(url, html)静态方法,并在Parse()方法的handler注册表中加入"<site>.com": ParseVideo.parse_<site>_com条目。参考一个极简范例——parse_miaopai_com(parsevideo.js#L127-L134)直接从 URL 结构推导出视频地址:

// parse miaopai.com video e.g. https://miaopai.com/show/abcde.html static parse_miaopai_com(url, _html) { const re = /.*miaopai\.com\/show\/(.*)\.html?$/i; const found = re.exec(url); if (found !== null) { return "http://gslb.miaopai.com/stream/" + found[1] + ".mp4"; } return null; }

站点专属解析器通常针对页面结构定制正则(如parse_weibo_com匹配video_src=、parse_dailymotion_com匹配播放器元数据 JSON 中的"type":"application/x-mpegURL"与"stream_h264*_url"、parse_vimeo_com提取"progressive":[{...,"url":"...mp4",...}]块),并复用FixURL+ValidURL保证结果可靠。

第 2 步:添加测试 spec 与 HTML 夹具。

在video-url-parser/test/下新增test_parsevideo_<site>.js,并在test/data/放置代表该站点真实页面的 HTML 夹具(现有夹具包括 test/data/pearvideo-1050733.html、test/data/ted-1.html、test/data/vimeo-151712690.html、test/data/weibo-1.html、test/data/xiaokaxiu-1.html 等)。测试写法可参考 test/test_parsevideo.js:

describe("pearvideo", function () { const url = "http://www.pearvideo.com/video_1050733"; it(url, function () { const html = fs.readFileSync("test/data/pearvideo-1050733.html").toString(); const video = new ParseVideo(url, html); assert.equal(video.Parse(), "http://video.pearvideo.com/mp4/short/20170320/cont-1050733-10294549-hd.mp4"); }); });

第 3 步:把验证过的页面加入 tested-urls.txt。该文件同时被manifest.json的web_accessible_resources引用,随扩展发布。

第 4 步:运行npm run check并更新 README 中的"Supported sites"表格。

在 README.md 的受支持站点清单中登记新站点,随后确认npm run check(lint + format + coverage + build)全部通过。

新增或更新翻译:两套机制并行

弹窗 UI 的本地化由两套独立机制共同完成,两者都要维护:

  • video-url-parser/lang/.js:弹窗 UI 字符串。以lang/en-us.js为蓝本复制,翻译每个 value 并保持 key 集合完全一致(现有语言覆盖 zh-cn、zh-tw、de-de、es-sp、fr-fr、it-it、ru-ru、nl-nl、pt-br、pl-pl、ro-ro、tr-tr、ja-jp、ko-kr、ar-sa、hi-in、bn-in、id-id、vi-vn、th-th、uk-ua、cs-cz、el-gr、sv-se 等 20+ 语言);

当你在lang/中新增全新语言时,除了翻译文件本身,还必须完成 CONTRIBUTING.md 指出的三个联动修改:

  1. 在 main.html 中新增<script src="lang/<code>.js"></script>引用;
  2. 在 js/translate.js 的get_lang()中新增case "<code>": return (translation_<name>);分支(现有 24 个分支一一对应lang/下的语言文件);
  3. 在 main.html 的语言<select id="lang">中添加<option value="<code>">Native name</option>选项。

弹窗的翻译执行逻辑集中在translate.js:ui_translate()通过get_lang()依据select#lang当前值选取对应翻译对象,再调用translation(lang)对#text_setting、#text_log、#text_dark_mode等 DOM 元素逐个执行translate_text替换文本。

提交信息与 Pull Request 流程

提交信息遵循简洁、祈使句风格(例如 "Add Vietnamese translation"),需要时可关联 issue(如 "Fixes #123"),并将无关改动拆分为独立 commit/PR。

PR 提交流程五步:

  1. Fork 仓库,从master创建特性分支(topic branch);
  2. 完成改动,并同步补充测试与文档;
  3. 本地确保npm run check通过;
  4. 使用 PR 模板提交 Pull Request,说明改了什么(what)与为什么(why);
  5. 积极回应评审反馈,配合维护者完成合并。

任何类型的贡献都受欢迎——bug 报告、功能请求、文档改进、新站点解析器、翻译与代码。在报告 bug 或请求功能时,请遵循仓库 issue 模板的格式描述问题;参与即默认遵守"互相尊重、无骚扰"的行为准则。

快速自检清单(提交 PR 前对照)

  • npm run check在本机通过(lint、format:check、coverage、build 全绿);
  • 新增的核心库行为有对应单元测试,且未降低 nyc 覆盖率阈值(lines/statements/functions ≥ 90%,branches ≥ 70%);
  • 解析器未引入运行时第三方依赖;
  • 新增文件已同步更新eslint.config.js/.prettierignore的忽略清单(如适用);
  • 新增站点已登记tested-urls.txt并更新 README 的 Supported sites 表格;
  • 新增语言已同步main.html的 script 引用、translate.js的get_lang()分支与<select id="lang">选项;
  • 提交信息清晰、祈使句、按主题拆分,PR 描述包含 what 与 why。

遵循上述约定,你就可以稳定地为 Simple Video Download Helper 贡献新站点解析器、完善测试与覆盖率、扩充多语言支持,并顺利通过npm run check这条质量红线。

  • 音视频

【免费下载链接】VideoDownloadHelper

Chrome Extension to Help Download Video for Some Video Sites.

项目地址:https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper
点击查看免费下载

相关推荐

上一篇:如何使用OpenDrop实现跨平台无线文件传输:终极指南
下一篇:Rufus 制作U盘启动盘在Windows 7打不开:3.22为什么是最后一个版本

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 7:05:12

二自由度车辆动力学模型求解与Simulink仿真实践指南

简介&#xff1a;面向车辆工程学生及使用Simulink的仿真初学者&#xff0c;这份二自由度动力学模型聚焦车辆侧向与垂直运动&#xff0c;忽略俯仰、偏航等复杂维度&#xff0c;适合快速掌握侧滑角、车身姿态等关键特性&#xff0c;可用于课程设计、控制策略验证或稳定性分析。资…

作者头像 李华
网站建设 2026/10/16 7:04:38

TensorFlow多模型加载实战:独立Graph与Session方案

做图像服务的同学应该都遇到过这种需求&#xff1a;两三个模型一起上线&#xff0c;业务要求它们同时常驻内存&#xff0c;随叫随到。我之前写过两篇TensorFlow推理相关的东西&#xff0c;这篇算是第三篇&#xff0c;专门聊一个很实际的问题——同一个进程里&#xff0c;同时加…

作者头像 李华
网站建设 2026/10/16 7:04:30

TCP可靠传输与流量控制:确认重传、滑动窗口与拥塞控制详解

计网学到传输层&#xff0c;TCP的可靠传输和流量控制是绝大多数人绕不过去的两个硬骨头。它们不像下层协议那样只负责“发出去”&#xff0c;TCP的职责是把一段字节流完整、按序、可控地送到对端进程手上。这篇主要围绕可靠传输里的确认与重传、滑动窗口&#xff0c;以及流量控…

作者头像 李华
网站建设 2026/10/16 7:03:49

CTF寒假入门路线:从环境搭建到新手赛完整指南

很多新手在寒假前都会问同样一个问题&#xff1a;CTF到底该怎么学&#xff1f;市面上零零散散的教程不少&#xff0c;但真正能让人从零开始、按节奏走完一个假期的路线图却很少。我自己的看法是&#xff0c;寒假这种整块时间&#xff0c;是入门CTF最好的窗口期&#xff0c;没有…

作者头像 李华
网站建设 2026/10/16 7:03:42

Spring Boot到微服务架构:大厂Java面试高频原理与工程实践拆解

最近几个月&#xff0c;好几个同事和朋友都在准备互联网大厂的Java岗跳槽&#xff0c;来来回回问我同一类问题&#xff1a;Spring Boot到底要准备到什么深度&#xff0c;微服务架构又从哪入手。问的人多了&#xff0c;我发现大多数人不是不会写代码&#xff0c;而是摸不清面试官…

作者头像 李华
网站建设 2026/10/16 7:03:27

剧本杀后台管理系统:从选题到落地的毕业设计完整指南

1. 为什么选剧本杀后台管理系统作为毕设选题1.1 剧本杀行业的真实业务痛点前阵子帮一位正在找毕业设计题目的A同学做选题评估&#xff0c;他前后换了四个题目&#xff1a;先是做图书管理系统&#xff0c;被导师说太老套&#xff1b;又试了在线考试系统&#xff0c;发现网上现成…

作者头像 李华