Skip to content

EasyFill v1.1.1 发布:全面提升用户体验

版本:v1.1.1

经过两个月的偷懒,EasyFill 迎来了 v1.1.1 版本的重大更新。这次更新主要在匹配算法上进行大幅度优化,全面提升匹配效率

更新概览


全新识别方式

1. 动态 Shadow DOM 支持

我发现有些评论系统通过 Shadow DOM 来实现封装,导致 v1.0 版本无法识别 Shadow DOM 生成的表单。在 v1.1.1 中,EasyFill 新增了对动态创建的 Shadow DOM 的完整支持。

function traverseShadowDOM(root: Document | ShadowRoot | Element) {
const inputs = root.querySelectorAll('input, textarea');
elements.push(...Array.from(inputs));
const allElements = root.querySelectorAll('*');
allElements.forEach(element => {
if (element.shadowRoot) {
logger.info('发现 Shadow DOM,正在遍历', {
tagName: element.tagName,
shadowRootMode: element.shadowRoot.mode
});
traverseShadowDOM(element.shadowRoot);
}
});
}

2. 三种识别方式全覆盖

在 v1.0 版本,EasyFill 只支持 name 字段识别。为了更加准确的匹配字段,引入了全新三种字段识别方式,确保在各种稀奇古怪的表单都可以识别:

Placeholder 识别

通过分析输入框的 placeholder 属性来识别字段类型:

<input placeholder="请输入您的姓名" />
<input placeholder="邮箱地址" />
<input placeholder="个人网站" />

Type 识别

基于 HTML5 标准的 type 属性进行智能识别:

<input type="email" />
<input type="url" />
<input type="text" name="username" />

ID 识别

通过元素的 id 属性进行精确匹配:

<input id="author" />
<input id="email" />
<input id="website" />

匹配策略:

inputs.forEach((input) => {
const typeAttr = (input.getAttribute("type") || "").toLowerCase();
const nameAttr = (input.getAttribute("name") || "").toLowerCase();
const idAttr = (input.getAttribute("id") || "").toLowerCase();
let valueToSet = ""; // 要填充的值
let matchedBy = ""; // 匹配方式(id, name, type)
let fieldType = ""; // 字段类型(name, email, url)
// 匹配 URL 字段
if (keywordSets.url.has(nameAttr) || keywordSets.url.has(`#${idAttr}`)) {
valueToSet = url;
matchedBy = keywordSets.url.has(`#${idAttr}`) ? "id" : "name";
fieldType = "url";
} else if (typeAttr === "url" && url) {
valueToSet = url;
matchedBy = "type";
fieldType = "url";
}
// 匹配 Email 字段
else if (keywordSets.email.has(nameAttr) || keywordSets.email.has(`#${idAttr}`)) {
valueToSet = email;
matchedBy = keywordSets.email.has(`#${idAttr}`) ? "id" : "name";
fieldType = "email";
} else if (typeAttr === "email" && email) {
valueToSet = email;
matchedBy = "type";
fieldType = "email";
}
// 匹配 Name 字段
else if ((keywordSets.name.has(nameAttr) || keywordSets.name.has(`#${idAttr}`)) && name) {
valueToSet = name;
matchedBy = keywordSets.name.has(`#${idAttr}`) ? "id" : "name";
fieldType = "name";
}
// 没有匹配上就跳过
if (!valueToSet) return;
// 设置值并触发事件
(input as HTMLInputElement).value = valueToSet;
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
// 记录日志
logger.info('填充表单字段', {
name: nameAttr || "",
id: idAttr || "",
type: typeAttr || "",
matchedBy,
valueToSet,
inShadowDOM: isInShadowDOM(input)
});
});

数据同步

1. 自定义数据源功能

v1.1.1 版本允许用户完全自定义关键字数据源。

该源来自我的腾讯云 COS,且由腾讯云境内 CDN 加速,基本上无延迟:

https://cos.lhasa.icu/EasyFill/keywords.json

自定义数据源格式示例:

{
"name": ["name", "author", "username", "昵称", "姓名"],
"email": ["email", "mail", "邮箱", "电子邮件"],
"url": ["url", "website", "blog", "网站", "博客"]
}

2. 缓存机制

实现了基于 HTTP 标准的智能缓存系统,大幅减少不必要的网络请求:

ETag 和 Last-Modified 支持:

if (etag && !forceSync) {
headers['If-None-Match'] = etag;
}
if (lastModified && !forceSync) {
headers['If-Modified-Since'] = lastModified;
}

性能优化

1. localStorage 持久化存储

实现 Markdown 内容的持久化机制:

const fetchMarkdown = async (url: string) => {
try {
// 检查 localStorage 是否已有缓存
const cachedMarkdown = localStorage.getItem(url);
if (cachedMarkdown) {
logger.info(`从缓存加载 Markdown 文件: ${url}`);
return cachedMarkdown;
}
// 如果没有缓存,从网络加载
const response = await fetch(url);
const markdown = await response.text();
// 将加载的内容存入 localStorage
localStorage.setItem(url, markdown);
return marked(markdown);
} catch (error) {
logger.error(`加载 Markdown 文件失败: ${url}`, error);
}
};

2. 异步并行加载优化

实现 Markdown 内容的异步并行加载:

const loadContent = async () => {
const [aboutAuthor, recommendedPlugins, updateLog, privacyPolicy] = await Promise.all([
fetchMarkdown('/markdowns/about-author.md'),
fetchMarkdown('/markdowns/recommended-plugins.md'),
fetchMarkdown('/markdowns/UpdateLog.md'),
fetchMarkdown('/markdowns/privacy-policy.md'),
]);
setAboutAuthorContent(aboutAuthor);
setRecommendedPluginsContent(recommendedPlugins);
setUpdateLogContent(updateLog);
setPrivacyPolicyContent(privacyPolicy);
};

日志系统

1. 三级别日志架构

EasyFill v1.1.1 实现了单例日志系统,支持 INFO、WARN、ERROR 三个级别:

export enum LogLevel {
INFO = 'INFO',
WARN = 'WARN',
ERROR = 'ERROR',
}

2. 智能环境适配

日志系统能够根据运行环境自动调整输出策略:

public configureByEnvironment(): Logger {
const isProd = typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'production';
if (isProd) {
// 生产环境:只显示警告和错误
this.setLevel(LogLevel.WARN);
} else {
// 开发环境:显示所有日志,并启用彩色和时间戳
this.setLevel(LogLevel.INFO)
.useColors(true)
.showTimestamp(true);
}
return this;
}

3. 控制台命令

生产状态下,日志默认关闭。所以,增加了命令调试:

// 启用日志系统
EasyFillLogger.enable()
// 关闭日志系统
EasyFillLogger.disable()
// 查看当前状态
EasyFillLogger.status()

命令绑定在全局 window 对象上,重启浏览器仍有效。

在浏览器扩展环境中,使用 chrome.storage.local 来存储,在普通网页环境中,使用 localStorage。

一样的是都用 easyfill_logger_enabled 这个键来存储

4. 链式配置接口

支持灵活的链式配置:

logger
.setLevel(LogLevel.INFO)
.useColors(true)
.showTimestamp(true)
.setPrefix('[EasyFill]')
.setPrefixColor('color: #4CAF50; font-weight: bold');

配置选项:


隐私权政策

v1.1.1 版本对隐私权政策进行了全面更新:

主要更新内容:


界面改进

1. 同步设置

新增了直观的同步设置界面,轻松管理数据同步:

2. 状态反馈优化


短期计划

长远计划


致谢与支持

EasyFill 的每一次进步都离不开用户的支持和反馈。特别感谢:Mainbranch 的反馈与支持

如果您觉得 EasyFill 对您有帮助,欢迎:

请我喝一杯咖啡

立即体验

EasyFill v1.1.1 现已在 Chrome 应用商店正式发布,您可以:

  1. 新用户:直接在 Chrome 应用商店搜索 “EasyFill” 安装
  2. 现有用户:通过梯子 Chrome 扩展将自动更新到最新版本
  3. 开发者:访问 GitHub 仓库 查看源代码

EasyFill - 简易填充,让每一次评论更自然,与你的博友互动无缝连接


二零二五 - 六七月读书随笔
端午骑行:倍鱼线