- // ==UserScript==
- // @name Wiktionary: Filter & Flags
- // @namespace https://github.com/HatScripts/monolingual-wiktionary
- // @version 1.0.1
- // @license MIT
- // @description Filters languages and shows country flags on Wiktionary
- // @author HatScripts
- // @icon https://en.wiktionary.org/static/favicon/wiktionary/en.ico
- // @match https://en.wiktionary.org/wiki/*
- // @match https://en.wiktionary.org/w/index.php?title=*
- // @grant GM_addStyle
- // @run-at document-start
- // ==/UserScript==
-
- ;(() => {
- 'use strict'
-
- const SHOW_ALL_LANGS_IN_TOC = true
- const LANG_WHITELIST = new Set(['English', 'Translingual'])
- const LANGS_ON_PAGE = new Set(Array.from(document.querySelectorAll('h2 > .mw-headline'))
- .map(el => el.textContent.replaceAll(' ', '_')))
-
- let intersect = new Set([...LANG_WHITELIST].filter(l => LANGS_ON_PAGE.has(l)))
-
- console.log('monowikt: LANGS_ON_PAGE: ', LANGS_ON_PAGE)
- console.log('monowikt: LANG_WHITELIST:', LANG_WHITELIST)
- console.log('monowikt: intersect: ', intersect)
-
- if (intersect.size === 0) {
- LANGS_ON_PAGE.forEach(lang => LANG_WHITELIST.add(lang))
- }
-
- if (document.title.includes(':')) { // Special page
- return
- }
-
- const hashLang = getHashLang()
- if (hashLang) {
- console.log('monowikt: initial hashLang:', hashLang)
- if (hashLang === '*') {
- // Add all languages on the current page to the whitelist
- LANGS_ON_PAGE.forEach(lang => LANG_WHITELIST.add(lang))
- } else if (LANGS_ON_PAGE.has(hashLang)) {
- LANG_WHITELIST.add(hashLang)
- }
- }
-
- function generateLangMap () {
- const langNames = new Intl.DisplayNames(['en'], {type: 'language'})
- const langMap = {}
- for (let i = 0; i < 26; i++) {
- for (let j = 0; j < 26; j++) {
- let code = String.fromCharCode(97 + i) + String.fromCharCode(97 + j)
- let name = langNames.of(code)
- if (name !== code) {
- langMap[name] = code
- }
- }
- }
- const langMap2 = {
- 'Akan': 'ak',
- 'Hebrew': 'he',
- 'Indonesian': 'id',
- 'Javanese': 'jv',
- 'Romanian': 'ro',
- 'Yiddish': 'yi',
- // ---
- 'Tagalog': 'tl',
- // ---
- 'Central Kurdish': 'ckb',
- 'Eastern Mari': 'chm',
- 'Hawaiian': 'haw',
- 'Ilocano': 'ilo',
- 'Krio': 'kri',
- 'Manipuri': 'mni',
- 'Mizo': 'lus',
- 'Old Norse': 'non',
- 'Otomi': 'oto',
- 'Papiamentu': 'pap',
- 'Udmurt': 'udm',
- 'Western Mari': 'mrj',
- 'White Hmong': 'hmn',
- 'Yucatec Maya': 'yua',
- }
- return { ...langMap, ...langMap2 }
- }
-
- const LANG_MAP = generateLangMap()
-
- GM_addStyle('.lang-hidden { display: none !important; }')
- // hide('#p-visibility, #p-lang, #p-coll-print_export, #p-feedback')
-
- function getHashLang () {
- return window.location.hash.replace(/^#/, '')
- }
-
- function slugify (text) {
- return text.toString().toLowerCase()
- .replace(/[\s_]+/g, '-') // Replace all whitespace with '-'
- .replace(/[^\w-]+/g, '') // Remove all non-word chars
- .replace(/-{2,}/g, '-') // Replace multiple '-' with single '-'
- .replace(/^-+|-+$/, '') // Trim '-' from start and end of text
- }
-
- function hide (elem, lang) {
- if (!elem) {
- console.log('monowikt: elem', elem, 'not found')
- return
- }
- elem.classList.add('lang-hidden')
- if (lang) {
- elem.classList.add('lang-' + slugify(lang))
- }
- }
-
- function createFlagImg(langCode, size) {
- const flagImg = document.createElement('img')
- flagImg.src = `https://hatscripts.github.io/circle-flags/flags/language/${langCode}.svg`
- flagImg.alt = ''
- flagImg.width = size
- return flagImg
- }
-
- console.time('monowikt: hide table of contents text')
- document.querySelectorAll('#toc > ul > li.toclevel-1').forEach(li => {
- const span = li.querySelector('a > span.toctext')
- const lang = span.textContent.replaceAll(' ', '_')
- const langCode = LANG_MAP[lang]
- if (langCode) {
- span.textContent = ' ' + span.textContent
- const flagImg = createFlagImg(langCode, 16)
- span.insertBefore(flagImg, span.firstChild)
- }
-
- if (!LANG_WHITELIST.has(lang)) {
- hide(SHOW_ALL_LANGS_IN_TOC ? li.querySelector('ul') : li, lang)
- }
- })
- console.timeEnd('monowikt: hide table of contents text')
-
- console.time('monowikt: hide sections')
- let hideNext = false
- let lang
- let hr
- Array.from(document.querySelector('#mw-content-text > div').children).forEach(el => {
- if (el.nodeName === 'H2') {
- const headline = el.querySelector('.mw-headline')
- lang = headline.textContent.replaceAll(' ', '_')
- console.log('lang:', lang)
- const langCode = LANG_MAP[lang]
- if (langCode) {
- headline.textContent = ' ' + headline.textContent
- const flagImg = createFlagImg(langCode, 32)
- headline.insertBefore(flagImg, headline.firstChild)
- }
- hideNext = !LANG_WHITELIST.has(lang)
- if (hr) {
- hide(hr, lang)
- hr = undefined
- }
- } else if (el.nodeName === 'HR') {
- hr = el
- }
- if (hideNext && !hr) {
- hide(el, lang)
- }
- })
- console.timeEnd('monowikt: hide sections')
-
- console.time('monowikt: hide categories')
- document.querySelectorAll('#mw-normal-catlinks > ul > li').forEach(li => {
- const category = li.textContent
- if (!/^en:|(?<!(Old|Middle) )\bEnglish\b/.test(category) || /(borrowed|derived) from English/.test(category)) {
- hide(li)
- } else {
- // const a = li.querySelector('a')
- // a.textContent = category.replace(/\s*(?:(?<!(Old|Middle) )English|terms)\s*/g, '')
- }
- })
- console.timeEnd('monowikt: hide categories')
-
- const scrollToElem = document.getElementById(hashLang)
- if (scrollToElem) {
- scrollToElem.scrollIntoView()
- }
-
- window.addEventListener('hashchange', () => {
- const hashLang = getHashLang()
- console.log('monowikt: changed hashLang :', hashLang)
- console.log('monowikt: slugify(hashLang):', slugify(hashLang))
- if (LANGS_ON_PAGE.has(hashLang) && !LANG_WHITELIST.has(hashLang)) {
- Array.from(document.getElementsByClassName('lang-' + slugify(hashLang))).forEach(el => {
- el.classList.remove('lang-hidden')
- })
- document.getElementById(hashLang).scrollIntoView()
- }
- }, false)
- })()