一键式的以PDF文件形式保存CSDN博客文章内容的火狐扩展

火狐浏览器用户界面上目前没有将网页内容保存为PDF格式文件的功能。但扩展API库中提供了用于实现这一功能的API:

var saving = browser.tabs.saveAsPDF(
  pageSettings   // object
)

这个API可以将整个网页保存为PDF格式文件。并且,它还有一个特别有用的特性,在官方文档中并没有提到,即它可以识别“@media print{}”这个CSS标记。在这个标记中设置CSS样式,就可以对PDF文件内容进行单独的排版,而不影响原来网页的排版显示。有些遗憾的是,目前只有Windows系统下的火狐支持这个API,MAC OS不支持。
扩展API库中还有另外一个很有用的API:

var inserting = browser.tabs.insertCSS(
  tabId,           // optional integer
  details          // object
)

它可以将新的CSS样式注入网页中,取代原来的CSS样式。
利用以上两个API及其它一些技巧,本人编写了一个用于保存CSDN博客文章内容的火狐扩展,并且已经放到火狐官网的组件库中了。下载页面
安装好这个扩展后,当访问CSDN博客文章页面时(https://blog.csdn.net),在浏览器的地址栏中会出现一个PDF图标,用于保存博客文章内容。
扩展源码并不复杂,简单地修改一下,可以用于保存其它网站的博客文章。下面贴出这个扩展的源码:

content.js

(() => {
	function noprint(sel) {
		Array.from(sel.parentNode.children).forEach(e => {
			if (e != sel) {
				if (!e.classList.contains('noprint')) e.classList.add('noprint');
			} else {
				if (!e.classList.contains('print')) e.classList.add('print');
			}
		})
		if (sel.parentNode.tagName != 'HTML') noprint(sel.parentNode);
	}
	let port = browser.runtime.connect({});
	port.onMessage.addListener(async e => {
		try {
			let sel = document.querySelector(".blog-content-box");
			if (sel) {
				window.stop();
				switch (e.command) {
					case "c_css":
						let more = document.querySelector("#btn-readmore");
						if (more) more.click();
						let css = '.noprint{display:none !important}';
						css += '.print{top:0px !important;margin-top:0px !important;left:0px !important;margin-left:0px !important;right:0px !important;margin-right:0px !important;';
						css += 'width:' + sel.offsetWidth + 'px !important;min-width:' + sel.offsetWidth + 'px !important;}';
						css += '.xprint{width:' + sel.offsetWidth + 'px !important;top:0px !important;margin-top:0px !important;margin-left:0px !important;}';
						css += '.xprint code{white-space:pre-wrap !important;word-wrap:break-word !important;}';
						css += 'ol.hljs-ln{width:auto !important;}';
						css += '.hljs-ln-code{height:auto !important}';
						css = '@media print{' + css + '}';// + css;
						await port.postMessage({ css: css, command: "b_css" });
						break;
					case "c_pdf":
						if (!sel.classList.contains('xprint')) sel.classList.add('xprint');
						noprint(sel);
						document.querySelectorAll('.hljs-ln-numbers,.xprint code+ul,td.gutter').forEach(e => {
							if (!e.classList.contains('noprint')) e.classList.add('noprint');

						});
						await port.postMessage({ command: "b_pdf" });
						break;
				}
			}
		} catch (e) {
			console.log(e);
		}
	});
})();

background.js

(() => {
    let port;
    browser.runtime.onConnect.addListener(p => {
        port = p;
        port.onMessage.addListener(async e => {
            try {
                switch (e.command) {
                    case "b_css":
                        await browser.tabs.insertCSS({ code: e.css, cssOrigin: 'user' });
                        await port.postMessage({ command: "c_pdf" });
                        break;
                    case "b_pdf":
                        let res = await browser.tabs.saveAsPDF({ "footerLeft": "", "footerCenter": "&PT", "footerRight": "", "headerLeft": "", "headerCenter": "", "headerRight": "" });
                        if (res == "saved" || res == "replaced") {
                            await browser.notifications.create("pdf", {
                                "type": "basic",
                                "iconUrl": browser.extension.getURL("icons/pdf.svg"),
                                "title": "提示",
                                "message": " PDF文件保存完毕!"
                            });
                        } else {
                            await browser.notifications.create("pdf", {
                                "type": "basic",
                                "iconUrl": browser.extension.getURL("icons/pdf.svg"),
                                "title": "提示",
                                "message": " PDF文件保存失败!"
                            });
                            console.log(res);
                        };
                        await new Promise(res => {
                            setTimeout(() => {
                                browser.notifications.clear("pdf").then(res);
                            }, 3000);
                        });
                        break;
                }
            } catch (e) {
                console.log(e);
            }
        });
    });
    browser.pageAction.onClicked.addListener(async () => {
        try {
            if (port) {
                await port.postMessage({ command: "c_css" });
            }
        } catch (e) {
            console.log(e);
        }
    });
})();

manifest.json

{
    "description": "以PDF文件形式保存CSDN博客的文章内容。",
    "author": "chenjs",
    "manifest_version": 2,
    "name": "PDF Saver For CSDN Blog",
    "version": "1.3",
    "icons": {
        "96": "icons/pdf.svg"
    },
    "background": {
        "scripts": [
            "background.js"
        ]
    },
    "permissions": [
        "tabs",
        "notifications",
        "<all_urls>"
    ],
    "page_action": {
        "default_title": "保存文章内容",
        "default_icon": {
            "96": "icons/pdf.svg"
        },
        "show_matches": [
            "*://blog.csdn.net/*"
        ]
    },
    "applications": {
        "gecko": {
            "id": "{0DCF7DAC-26F3-4ECD-95BB-C2974E5B3041}",
            "strict_min_version": "59.0"
        }
    },
    "content_scripts": [
        {
            "matches": [
                "*://blog.csdn.net/*"
            ],
            "js": [
                "content.js"
            ]
        }
    ]
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值