OSM diaries TOC

Adds a table of contents to the OpenStreetMap diaries page and highlights new posts and comments.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        OSM diaries TOC
// @namespace   https://github.com/marcows
// @description Adds a table of contents to the OpenStreetMap diaries page and highlights new posts and comments.
// @description:de Fügt ein Inhaltsverzeichnis zur OpenStreetMap Benutzer-Blogs-Seite hinzu und hebt neue Beiträge und Kommentare hervor.
// @include     *://www.openstreetmap.org/diary*
// @include     /^https?://www\.openstreetmap\.org/user/.*/diary[^/]*$/
// @version     3.0.1
// @license     WTFPL
// @icon        http://www.openstreetmap.org/assets/osm_logo.png
// @supportURL  https://github.com/marcows/osm-diaries-toc
// @compatible  firefox
// @compatible  chrome
// @compatible  opera
// @require     https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @grant       GM.getValue
// @grant       GM_getValue
// @grant       GM.setValue
// @grant       GM_setValue
// ==/UserScript==

(async function() {

var contentBox = document.querySelector(".content-body .content-inner");

var diaryPosts = document.querySelectorAll(".diary_post");

var articleLinks = document.querySelectorAll(".diary_post .mb-3 h2 > a");
var commentLinks = document.querySelectorAll(".diary_post .secondary-actions a[href$='#comments']");

var toc = document.createElement("table");
var olderNewer = document.createElement("span");

/* Create table of contents. */
for (var i = 0; i < articleLinks.length && i < commentLinks.length; i++) {
	var articleLink = articleLinks[i].cloneNode(true);
	var commentLink = commentLinks[i].cloneNode(true);

	var tablerow = document.createElement("tr");
	var cell, link;

	// Anchor name of the (original) article if not existing yet
	if (!articleLinks[i].name)
		articleLinks[i].name = "article" + i;

	/* Column 1: anchor link for scrolling down to article */
	link = document.createElement("a");
	link.innerHTML = "&nbsp;&dArr;&nbsp;";
	link.href = "#" + articleLinks[i].name;

	cell = document.createElement("td");
	cell.appendChild(link);
	tablerow.appendChild(cell);

	/* Column 2: link to article in own page */
	cell = document.createElement("td");
	cell.appendChild(articleLink);
	tablerow.appendChild(cell);

	/* Column 3: link to article comments in own page */
	cell = document.createElement("td");
	cell.style.whiteSpace = "nowrap";
	cell.appendChild(commentLink);
	tablerow.appendChild(cell);

	/* Highlighted if changed since last visit (new comments or entire new post) */

	// Diary entry ID:
	var key = commentLink.href.match(/\/([0-9]+)#/)[1];

	// Language dependent text, e.g. "No comments", "1 comment", "2 comments" etc.:
	var newVal = commentLink.textContent;
	var oldVal = await GM.getValue(key);

	if (newVal !== oldVal) {
		// New comment (or new post)
		commentLink.style.color = "red";
		// Add the previous content as link title
		commentLink.title = oldVal ? oldVal : "-";

		if (!oldVal) {
			// New post
			articleLink.style.color = "red";
		}

		GM.setValue(key, newVal);
	}

	toc.appendChild(tablerow);
}

contentBox.insertBefore(toc, diaryPosts[0]);

/* Duplicate the "older/newer entries" links from bottom of page to after the TOC. */
if (diaryPosts.length > 0) {
	var olderNewerNode = diaryPosts[diaryPosts.length - 1];

	while (olderNewerNode.nextSibling) {
		olderNewerNode = olderNewerNode.nextSibling;
		olderNewer.appendChild(olderNewerNode.cloneNode(true));
	}

	contentBox.insertBefore(olderNewer, diaryPosts[0]);
}

})();