// ==UserScript==
// @name bilibili笔记-B站笔记导出pdf(原生UI版)
// @namespace http://tampermonkey/
// @version 1.0
// @description 在B站笔记详情页原生添加导出按钮
// @author 十点前睡觉
// @match *://*.bilibili.com/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 核心逻辑
function main() {
// 检测是否在笔记详情页
const noteHeader = document.querySelector('.note-header');
if (!noteHeader) return;
// 查找目标位置和"记笔记"按钮
const noteOperation = noteHeader.querySelector('.note-operation.detail');
if (!noteOperation) return;
// 防止重复创建
if (document.getElementById('bilibili-note-export-btn')) return;
// 创建导出按钮
const exportBtn = document.createElement('div');
exportBtn.id = 'bilibili-note-export-btn';
exportBtn.className = 'note-operation detail'; // 与原生按钮同class
exportBtn.textContent = '导出笔记';
exportBtn.style.cssText = `
margin-left: 12px;
color: #FB7299; /* B站粉色,也可以用#FF4444纯红 */
font-weight: 500;
cursor: pointer;
`;
// 插入到"记笔记"按钮旁边
noteOperation.parentNode.insertBefore(exportBtn, noteOperation.nextSibling);
// 绑定点击事件
exportBtn.addEventListener('click', () => {
executeExportLogic();
});
}
// 原有的导出逻辑
function executeExportLogic() {
// element to string
function e2s(obj) {
let o = document.createElement("div");
o.appendChild(obj);
return o.innerHTML;
}
// second to hh:mm:ss
function s2hms(ss) {
let s = parseInt(ss);
let hour = 0;
let min = 0;
let result;
if (s >= 3600) {
hour = Math.floor(s / 3600);
min = Math.floor((s - hour * 3600) / 60);
s = (s - hour * 3600) % 60;
result = `${hour.toString().padStart(2, "0")}:${min
.toString()
.padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
} else if (s < 3600 && s >= 60) {
min = Math.floor(s / 60);
s = s % 60;
result = `${min.toString().padStart(2, "0")}:${s
.toString()
.padStart(2, "0")}`;
} else {
result = `${min.toString().padStart(2, "0")}:${s
.toString()
.padStart(2, "0")}`;
}
return result;
}
// 放大图片
let qlImagePreview = document.getElementsByClassName("ql-image-preview");
for (let i = 0; i < qlImagePreview.length; i++) {
qlImagePreview[i].style.width = "100%";
}
let imgPreview = document.getElementsByClassName("img-preview");
for (let i = 0; i < imgPreview.length; i++) {
imgPreview[i].style.width = "100%";
}
// 处理时间标签
let note = document.getElementsByClassName("note-single-item--selected");
let url;
if (note.length > 0)
url = "https:" + note[0].getElementsByTagName("a")[0].getAttribute("href");
else url = "https://www.bilibili.com" + window.location.pathname + "?note=open";
const style = `margin-top: 10px;background: #e6f4ff;border-radius: 12px;height: 22px;line-height: 19px;display: inline-block;padding: 0 12px;font-size: 12px;color: #2392e5;border: 1px solid #e6f4ff;cursor: pointer;font-weight: 700;`;
let tags = document.getElementsByClassName("ql-tag-blot");
for (let i = 0; i < tags.length; i++) {
let index = tags[i].getAttribute("data-index");
let t = tags[i].getAttribute("data-seconds");
let tStr = s2hms(t);
let title = tags[i].getAttribute("data-title");
let count = tags[i].getAttribute("data-cid-count");
if (count === "1") {
tags[i].getElementsByClassName("time-tag-item__text")[0].innerHTML = `${tStr}`;
} else {
tags[i].getElementsByClassName("time-tag-item__text")[0].innerHTML = `${title} P${index} - ${tStr}`;
}
}
// 修复高亮缺失
let spans = document.getElementsByTagName("span");
for (let i = 0; i < spans.length; i++) {
if (/ql-bg-*/.test(spans[i].className)) {
spans[i].style = "-webkit-print-color-adjust: exact";
}
}
// 提取笔记并打印
let app = document.getElementById("app");
let divs = document.getElementsByClassName("ql-editor");
if (divs.length > 0) {
app.innerHTML = e2s(divs[0]);
document.body.innerHTML = e2s(app);
window.print();
} else {
alert("未找到可导出的笔记内容");
}
}
// 监听页面变化,因为B站是SPA
const observer = new MutationObserver((mutations) => {
main();
});
// 监听整个文档变化
observer.observe(document.body, {
childList: true,
subtree: true
});
// 初始化一次
main();
})();