OSM diaries TOC

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

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

You will need to install an extension such as Tampermonkey to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला 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]);
}

})();