// ==UserScript==
// @name Bunpro Toolbox
// @version 1.5.2
// @description Adds various search options from Japanese resources
// @author Ambo100
// @match *bunpro.jp/grammar_points/*
// @match *bunpro.jp/learn*
// @grant none
// @namespace https://greasyfork.org/users/230700
// @changelog Added Bunpro grammar forum link to the toolbar; Added Bunpro Toolbox to the Study page;
// @downloadURL none
// ==/UserScript==
(function() {
'use strict';
var grammarPoint = document.getElementsByClassName("grammar-point__text--main-kanji-new")[0].innerText;
var toolboxDiv;
AddToolbox();
//TOOKBOX SETUP START//
// Dictionaries, References
AddLink("Jisho", "https://jisho.org/search/");
AddLink("Wikitionary", "https://en.wiktionary.org/wiki/","#Japanese");
AddLink("Eijirou", "https://eow.alc.co.jp/search?q=","");
AddDivider();
//YouTube
AddLink("YouGlish", "https://youglish.com/pronounce/","/japanese?");
AddLink("YouTube", "https://www.youtube.com/results?search_query=","+Japanese");
AddDivider();
//Q&A, Communities
AddLink("Stack Exchange", "https://japanese.stackexchange.com/search?q=");
AddLink("HiNative", "https://hinative.com/en-US/search/questions?language_id=45&q=");
AddLink("Reddit", "https://www.reddit.com/r/LearnJapanese/search?q=","&restrict_sr=on&sort=relevance&t=all");
AddLink("WK Forum", "https://community.wanikani.com/search?q=","%20category%3A17");
AddBunproLink("Discussion");
//TOOLBOX SETUP END//
FixBrokenLinks();
function AddToolbox() {
var grammarDiv = document.getElementsByClassName("grammar-point__meaning-new")[0].getElementsByClassName("row")[0];
toolboxDiv = document.createElement("div");
grammarDiv.prepend(toolboxDiv);
//Toolbox styling
toolboxDiv.classList.add('grammar-point__container--section-new');
toolboxDiv.classList.add('col-12-auto');
toolboxDiv.classList.add('d-flex');
}
/**
* @global
* @description This function has three parameters, a link name, prefix (main URL) and an optional suffix parameter. The current grammar point will be placed between the prefix and suffix of the link.
* @param {string} linkName Link Name
* @param {string} urlPrefix URL Prefix
* @param {string} [urlSuffix] Can be used for adding additional search queries
* @example //Search Jisho.org
* AddLink("Jisho", "https://jisho.org/search/");
* @example //Search Wikitionary.org, add #Japanese anchor link
* AddLink("Wikitionary", "https://en.wiktionary.org/wiki/","#Japanese");
*/
function AddLink(linkName, urlPrefix = '', urlSuffix = '') {
toolboxDiv.innerHTML += '' + linkName + '';
}
function AddBunproLink(linkName) {
var bunproGrammaForumLink = document.getElementsByClassName("grammar-point__link--action-new")[0].getAttribute("href");
toolboxDiv.innerHTML += '' + linkName + '';
}
/**
* @global
* @description Adds a vertical divider between links with set spacing.
* @param {int} [padding=10] Measured in pixels (px).
* @param {string} [dividerSymbol=|]
* @example //Standard 10px divider
* AddDivider();
* @example //30px divider with the character "-".
* AddDivider(30, "-");
*/
function AddDivider(padding = '10', dividerSymbol = ' ') {
toolboxDiv.innerHTML += '' + dividerSymbol + '';
}
/**
* @global
* @description Clears all default links and dividers from the toolbox.
*/
function ClearToolbox(){
toolboxDiv.innerHTML = "";
}
/**
* @global
* @description This function has three parameters, a PDF title, local PDF URL and a parameter for optional PDF parameters.
* Warning This feature is experimental, modern browsers will block links to local URLs for security purposes.
* An browser extension, such as this extension for Google Chrome can enable this feature.
* @param {string} pdfTitle The name of the linK, this must match exactly with the names used on Bunpro (excludes non alphanumeric characters).
* @param {string} pdfURL The local URL of your PDF file. Must be preceeded with 'file://'
* @param {string} [pdfParameters] May be used for adding additional PDF parameters
* @example //Adds a link to the PDF that matches 'Genki II 2nd Edition'.
* AddPDFLink("Genki II 2nd Edition","file:///C:/Users/YOUR_USER/Documents/GenkiElementaryII.pdf");
* @example //Adds a link to the PDF that matches 'DAJB'.
* AddPDFLink("DAJG","file:///C:/Users/YOUR_USER/Documents/DAJG.pdf");
* @example //Adds a link to the PDF that matches 'AIAIJ', includes optional query to set zoom level.
* AddPDFLink("AIAIJ","file:///C:/Users/YOUR_USER/Documents/AIAIJ.pdf", "zoom=120");
*/
function AddPDFLink(pdfTitle = '', pdfURL = '', pdfParameters = ''){
var booksDivContainer = document.getElementsByClassName("grammar-point__container--resources-card-main-text-new");
var regexBookTitle = new RegExp('(.*' + pdfTitle + '.*)','i');
var regexPageNumber = new RegExp('Page\\s(\\d+)','i');
for (var i = 0; i < booksDivContainer.length; i++) {
var result = regexBookTitle.exec(booksDivContainer[i].innerText);
if (result != null) {
var bookPageNumberDiv = booksDivContainer[i].parentElement.getElementsByTagName('div')[1].innerText;
var bookPageNumber = regexPageNumber.exec(bookPageNumberDiv);
//Replace book title with link
var pageLink = document.createElement("a");
pageLink.setAttribute('href', pdfURL + "#page=" + bookPageNumber[1] + "&" + pdfParameters);
pageLink.innerText = booksDivContainer[i].innerText.trim();
booksDivContainer[i].textContent = "";
booksDivContainer[i].appendChild(pageLink);
booksDivContainer[i].innerHTML += " ";
//Add link icon
var externalLink = document.createElement("i");
externalLink.classList.add("fas", "fa-external-link-alt");
booksDivContainer[i].appendChild(externalLink);
}
}
}
function FixBrokenLinks() {
var links = document.getElementsByTagName("a");
var regex = /^(http?:\/\/)[^.]+\.(jgram|tanos|99bako)(.+)$/i;
for (var i = 0, iMax = links.length; i < iMax; i++) {
links[i].href = links[i].href.replace(regex, "https://web.archive.org/web/" + links[i].href);
}
}
}
)();