简述
地址:https://greasyfork.org/zh-CN/scripts/441640
导出Hypothesis高亮和注释为markdown文件
功能
在 https://hypothes.is/users/用户名
和 http://hypothes.is/users/用户名
页面适用。
导出用户界面(自己或别人)的所有注释或者个别注释为markdown文件,每个文件名为标注对应的网页的标题或者文件名,文件内标注的顺序按照标注的顺序从上到下。
文件内容包括标注的来源以及每个标注和标注下的注释,效果如下
Hypothesis个人主页内容:
markdown文件内容:
markdown文件渲染效果:
使用
当打开不管是自己还是别人的Hypothesis的用户界面时,页面上出现一个导出全部
按钮以及在每一项的右边有一个 导出
按钮,效果如下:
当点击每一项右边的导出
按钮时会导出对应的markdown文件,当点击导出全部
按钮时会将每个注释都导出为markdown文件。
0.1.0 版本源码
// ==UserScript==
// @name Hypothesis导出插件
// @namespace https://coycs.com/
// @version 0.1.0
// @description 导出Hypothesis高亮和注释为markdown文件
// @author coycs
// @match *://hypothes.is/users/*
// @grant none
// @license MIT
// ==/UserScript==
(function () {
"use strict";
window.onload = function () {
// 添加全部导出按钮
let exportAllBtn = document.createElement("span");
exportAllBtn.textContent = "导出全部";
exportAllBtn.style.cssText = "margin-left: 8px;font-weight: bold;cursor: pointer;";
document.querySelector(".search-results__total").appendChild(exportAllBtn);
exportAllBtn.addEventListener("click", function () {
let exportBtns = document.querySelectorAll("#exportBtn");
exportBtns.forEach(n => {
n.click();
});
});
// 添加导出按钮
const listitems = document.querySelectorAll('li[role="listitem"]');
listitems.forEach(function (e) {
e.style.cssText = "display: flex;";
let bucket = e.querySelector(".search-result-bucket.js-search-bucket");
bucket.style.cssText = "flex: 1;";
let exportBtn = document.createElement("div");
exportBtn.id = "exportBtn";
exportBtn.textContent = "导出";
exportBtn.style.cssText =
"display: flex;align-items: center;justify-content: center;font-weight: bold;color: inherit;cursor: pointer;";
let that = e;
exportBtn.addEventListener("click", function () {
ExportListItem(that);
});
e.appendChild(exportBtn);
});
};
// 导出单个项目
function ExportListItem(listitem) {
const title = listitem.querySelector('a[data-ref="title"]').innerText;
const url_a = listitem.querySelector(
"div.search-bucket-stats__val.search-bucket-stats__url > a"
);
let outcome = new String();
if (url_a) {
const url = url_a.href;
outcome = outcome.concat(`> 来自:${url}\n`);
} else {
outcome = outcome.concat("> 来自:本地文件\n");
}
const annotations = listitem.querySelectorAll("li.annotation-card");
for (let i = annotations.length - 1; i > -1; i--) {
const quote = annotations[i]
.querySelector("blockquote.annotation-card__quote")
.innerText.trim();
const text = annotations[i].querySelector("div.annotation-card__text").innerText.trim();
if (text) {
outcome = outcome + "\n" + "> " + quote + "\n" + "\n" + text + "\n";
} else {
outcome = outcome + "\n" + "> " + quote + "\n";
}
}
// 导出为markdown文件
let blob = new Blob([outcome], { type: "application/md" });
let aTag = document.createElement("a");
aTag.download = title + ".md";
aTag.href = URL.createObjectURL(blob);
aTag.click();
URL.revokeObjectURL(blob);
}
})();