Lumin Blog 复制版权追加功能文档
📌 概述
当读者在文章页面选中文字并执行复制操作(Ctrl+C / Cmd+C)时,系统会自动在剪贴板内容末尾追加版权声明信息,包括作者、文章标题、原文链接和版权声明。此功能无需任何配置即可生效。
🎯 一、功能说明
| 属性 | 说明 |
|---|---|
| 生效范围 | 仅文章详情页(.single-post .post-content 内) |
| 触发方式 | 选中文字后执行复制操作(键盘快捷键 / 右键菜单复制) |
| 最低字数 | 选中文字 ≥ 30 字时才追加(短文本不触发) |
| 输出格式 | 纯文本(text/plain)+ 富文本(text/html)双格式 |
| 配置需求 | 零配置,自动从页面 DOM 提取信息 |
复制效果示例
选中原文:
Hugo 是一个用 Go 语言编写的静态网站生成器,它的构建速度非常快……
粘贴后内容:
Hugo 是一个用 Go 语言编写的静态网站生成器,它的构建速度非常快……
作者:Lumin 文章:Hugo 静态博客搭建指南 链接:https://example.com/posts/hugo-guide/ 声明:本文为原创文章,转载请注明出处。
🏗️ 二、代码结构
2.1 模块定义
定义在 assets/js/main.js 的 CopyCopyright 模块中:
1var CopyCopyright = (function() {
2 var MIN_LENGTH = 30; // 最低触发字数
3
4 function init() {
5 // 仅在文章页生效
6 var article = document.querySelector('.single-post .post-content');
7 if (!article) return;
8
9 document.addEventListener('copy', function(e) {
10 var selection = window.getSelection();
11 if (!selection || selection.rangeCount === 0) return;
12
13 var text = selection.toString();
14 if (text.length < MIN_LENGTH) return;
15
16 // 从页面 DOM 提取文章信息
17 var metaItems = document.querySelectorAll('.post-meta .meta-item');
18 var authorText = '';
19 if (metaItems.length > 0) {
20 authorText = metaItems[0].textContent.trim();
21 }
22 var titleEl = document.querySelector('.post-title');
23 var titleText = titleEl ? titleEl.textContent.trim() : '';
24 var permalink = window.location.href;
25
26 // 构建追加文本
27 var appendix = '\n\n' +
28 '-----------------------\n' +
29 '作者:' + authorText + '\n' +
30 '文章:' + titleText + '\n' +
31 '链接:' + permalink + '\n' +
32 '声明:本文为原创文章,转载请注明出处。';
33
34 // 写入剪贴板(纯文本 + 富文本双格式)
35 if (e.clipboardData && e.clipboardData.setData) {
36 e.preventDefault();
37 e.clipboardData.setData('text/plain', text + appendix);
38
39 var htmlAppendix = '<br><br><hr style="border:none;border-top:1px solid #ddd;margin:12px 0;">' +
40 '<p style="color:#888;font-size:13px;">' +
41 '作者:' + authorText + '<br>' +
42 '文章:<a href="' + permalink + '">' + titleText + '</a><br>' +
43 '声明:本文为原创文章,转载请注明出处。</p>';
44 e.clipboardData.setData('text/html', selection.toString() + htmlAppendix);
45 }
46 });
47 }
48
49 return { init: init };
50})();
2.2 模块注册
在 main.js 的 DOMContentLoaded 初始化列表中注册:
1var coreModules = [
2 // ... 其他模块
3 { name: 'CopyCopyright', fn: CopyCopyright.init }
4];
🔍 三、核心逻辑详解
3.1 触发条件判断
1用户执行复制操作
2 ↓
3检查:当前页面是否为文章页?(.single-post .post-content 存在)
4 ↓ 否 → 不绑定事件,功能不生效
5 ↓ 是
6检查:是否有选中的文字?(window.getSelection())
7 ↓ 否 → 忽略
8 ↓ 是
9检查:选中文字长度 ≥ 30 字?
10 ↓ 否 → 仅复制原文,不追加版权
11 ↓ 是
12拦截 copy 事件 → 追加版权信息到剪贴板
3.2 为什么设置 30 字门槛?
| 场景 | 选中字数 | 是否追加 | 原因 |
|---|---|---|---|
| 复制代码片段 | 5-20 字 | ❌ 不追加 | 代码片段追加版权会破坏代码结构 |
| 复制文章标题 | 5-15 字 | ❌ 不追加 | 标题本身已是引用信息 |
| 复制术语/关键词 | 2-5 字 | ❌ 不追加 | 过短文字追加版权显得突兀 |
| 复制段落/章节 | 30+ 字 | ✅ 追加 | 这才是需要保护的原创内容 |
3.3 双格式输出
剪贴板同时写入两种格式,适配不同的粘贴目标:
text/plain(粘贴到记事本、终端、纯文本编辑器):
1原文内容...
2
3-----------------------
4作者:Lumin
5文章:文章标题
6链接:https://example.com/posts/xxx/
7声明:本文为原创文章,转载请注明出处。
text/html(粘贴到 Word、富文本编辑器、邮件):
原文内容后跟随一条分隔线 + 灰色小字版权信息,链接可点击跳转。
3.4 信息提取来源
| 字段 | DOM 选择器 | 来源说明 |
|---|---|---|
| 作者 | .post-meta .meta-item(第一个) | 文章元数据区的作者项 |
| 标题 | .post-title | 文章标题 <h1> |
| 链接 | window.location.href | 当前页面 URL |
⚙️ 四、自定义配置
4.1 修改最低触发字数
在 CopyCopyright 模块中修改 MIN_LENGTH 值:
1var MIN_LENGTH = 30; // 改为 50 可提高门槛,改为 10 可降低门槛
4.2 修改版权声明文案
在 appendix 变量中修改追加的文本内容:
1var appendix = '\n\n' +
2 '-----------------------\n' +
3 '作者:' + authorText + '\n' +
4 '文章:' + titleText + '\n' +
5 '链接:' + permalink + '\n' +
6 '声明:本文为原创文章,转载请注明出处。'; // 修改此行
4.3 添加许可协议信息
如果站点配置了许可协议(如 CC BY-NC-SA 4.0),可以追加到版权信息中:
1var appendix = '\n\n' +
2 '-----------------------\n' +
3 '作者:' + authorText + '\n' +
4 '文章:' + titleText + '\n' +
5 '链接:' + permalink + '\n' +
6 '许可:CC BY-NC-SA 4.0\n' +
7 '声明:本文为原创文章,转载请注明出处。';
4.4 扩展生效范围
默认仅文章页生效。如需在其他页面也启用,修改 init() 中的选择器判断:
1// 原始:仅文章页
2var article = document.querySelector('.single-post .post-content');
3
4// 扩展:文章页 + 独立页面
5var article = document.querySelector('.single-post .post-content, .page-content');
🛡️ 五、与其他版权功能的协作
Lumin Blog 有三层版权保护机制,各司其职:
| 层级 | 功能 | 触发条件 | 作用 |
|---|---|---|---|
| 1. 复制追加 | CopyCopyright 模块 | 选中 ≥30 字后复制 | 在剪贴板内容中追加版权信息 |
| 2. 底部声明 | 文章页版权声明块 | 文章页底部始终显示 | 明确展示许可协议和转载要求 |
| 3. 代码复制 | CodeBlock 模块 | 点击代码块复制按钮 | 复制代码时显示"复制成功"提示 |
三层机制互补:
- 复制追加:被动保护,读者复制时自动生效
- 底部声明:主动展示,明确告知版权规则
- 代码复制:特殊场景,代码块有独立的复制交互
🐛 六、常见问题
Q1: 复制代码块时也会追加版权吗?
不会。代码块的复制按钮使用 navigator.clipboard.writeText() API 直接写入剪贴板,不触发 copy 事件,因此 CopyCopyright 模块不会介入。而如果用户手动选中代码文字复制,由于代码通常较短(< 30 字),也不会触发追加。
Q2: 在手机浏览器上有效吗?
有效。copy 事件在移动端浏览器上同样触发(长按选中文字 → 复制)。但部分移动端浏览器可能不支持 clipboardData.setData(),此时功能降级为仅复制原文。
Q3: 粘贴到微信/钉钉时格式对吗?
取决于目标应用。微信/钉钉等 IM 工具通常读取 text/html 格式,会显示带样式的版权信息(分隔线 + 灰色小字 + 可点击链接)。部分应用仅读取纯文本格式,则显示纯文本版本的版权信息。
Q4: 如何临时禁用此功能?
在浏览器开发者工具控制台执行:
1document.removeEventListener('copy', CopyCopyright.handler);
📊 七、性能指标
| 指标 | 数值 |
|---|---|
| DOM 查询次数 | 3 次(init 时 1 次 + 每次 copy 时 2 次) |
| 事件监听器 | 1 个(document 级 copy 事件) |
| 单次 copy 回调耗时 | < 0.5ms(字符串拼接 + setData) |
| 内存占用 | ~150 bytes(闭包变量) |
| 对正常复制的影响 | 选中 < 30 字时完全无影响 |
📁 八、相关文件索引
| 文件 | 作用 |
|---|---|
assets/js/main.js CopyCopyright 模块 | 核心逻辑:copy 事件监听 + 版权信息追加 |
layouts/_default/single.html L157-168 | 文章底部版权声明块(视觉展示层) |
layouts/_default/single.html L63-69 | 文章标题和作者元数据(信息提取来源) |
assets/js/main.js CodeBlock 模块 | 代码块复制按钮(独立复制通道,不触发版权追加) |
留言评论
期待你的想法评论加载中