Wiktionary: Filter & Flags

Filters languages and shows country flags on Wiktionary

安裝腳本?
作者推薦腳本

您可能也會喜歡 YouTube Auto-Liker

安裝腳本
  1. // ==UserScript==
  2. // @name Wiktionary: Filter & Flags
  3. // @namespace https://github.com/HatScripts/monolingual-wiktionary
  4. // @version 1.0.1
  5. // @license MIT
  6. // @description Filters languages and shows country flags on Wiktionary
  7. // @author HatScripts
  8. // @icon https://en.wiktionary.org/static/favicon/wiktionary/en.ico
  9. // @match https://en.wiktionary.org/wiki/*
  10. // @match https://en.wiktionary.org/w/index.php?title=*
  11. // @grant GM_addStyle
  12. // @run-at document-start
  13. // ==/UserScript==
  14.  
  15. ;(() => {
  16. 'use strict'
  17.  
  18. const SHOW_ALL_LANGS_IN_TOC = true
  19. const LANG_WHITELIST = new Set(['English', 'Translingual'])
  20. const LANGS_ON_PAGE = new Set(Array.from(document.querySelectorAll('h2 > .mw-headline'))
  21. .map(el => el.textContent.replaceAll(' ', '_')))
  22.  
  23. let intersect = new Set([...LANG_WHITELIST].filter(l => LANGS_ON_PAGE.has(l)))
  24.  
  25. console.log('monowikt: LANGS_ON_PAGE: ', LANGS_ON_PAGE)
  26. console.log('monowikt: LANG_WHITELIST:', LANG_WHITELIST)
  27. console.log('monowikt: intersect: ', intersect)
  28.  
  29. if (intersect.size === 0) {
  30. LANGS_ON_PAGE.forEach(lang => LANG_WHITELIST.add(lang))
  31. }
  32.  
  33. if (document.title.includes(':')) { // Special page
  34. return
  35. }
  36.  
  37. const hashLang = getHashLang()
  38. if (hashLang) {
  39. console.log('monowikt: initial hashLang:', hashLang)
  40. if (hashLang === '*') {
  41. // Add all languages on the current page to the whitelist
  42. LANGS_ON_PAGE.forEach(lang => LANG_WHITELIST.add(lang))
  43. } else if (LANGS_ON_PAGE.has(hashLang)) {
  44. LANG_WHITELIST.add(hashLang)
  45. }
  46. }
  47.  
  48. function generateLangMap () {
  49. const langNames = new Intl.DisplayNames(['en'], {type: 'language'})
  50. const langMap = {}
  51. for (let i = 0; i < 26; i++) {
  52. for (let j = 0; j < 26; j++) {
  53. let code = String.fromCharCode(97 + i) + String.fromCharCode(97 + j)
  54. let name = langNames.of(code)
  55. if (name !== code) {
  56. langMap[name] = code
  57. }
  58. }
  59. }
  60. const langMap2 = {
  61. 'Akan': 'ak',
  62. 'Hebrew': 'he',
  63. 'Indonesian': 'id',
  64. 'Javanese': 'jv',
  65. 'Romanian': 'ro',
  66. 'Yiddish': 'yi',
  67. // ---
  68. 'Tagalog': 'tl',
  69. // ---
  70. 'Central Kurdish': 'ckb',
  71. 'Eastern Mari': 'chm',
  72. 'Hawaiian': 'haw',
  73. 'Ilocano': 'ilo',
  74. 'Krio': 'kri',
  75. 'Manipuri': 'mni',
  76. 'Mizo': 'lus',
  77. 'Old Norse': 'non',
  78. 'Otomi': 'oto',
  79. 'Papiamentu': 'pap',
  80. 'Udmurt': 'udm',
  81. 'Western Mari': 'mrj',
  82. 'White Hmong': 'hmn',
  83. 'Yucatec Maya': 'yua',
  84. }
  85. return { ...langMap, ...langMap2 }
  86. }
  87.  
  88. const LANG_MAP = generateLangMap()
  89.  
  90. GM_addStyle('.lang-hidden { display: none !important; }')
  91. // hide('#p-visibility, #p-lang, #p-coll-print_export, #p-feedback')
  92.  
  93. function getHashLang () {
  94. return window.location.hash.replace(/^#/, '')
  95. }
  96.  
  97. function slugify (text) {
  98. return text.toString().toLowerCase()
  99. .replace(/[\s_]+/g, '-') // Replace all whitespace with '-'
  100. .replace(/[^\w-]+/g, '') // Remove all non-word chars
  101. .replace(/-{2,}/g, '-') // Replace multiple '-' with single '-'
  102. .replace(/^-+|-+$/, '') // Trim '-' from start and end of text
  103. }
  104.  
  105. function hide (elem, lang) {
  106. if (!elem) {
  107. console.log('monowikt: elem', elem, 'not found')
  108. return
  109. }
  110. elem.classList.add('lang-hidden')
  111. if (lang) {
  112. elem.classList.add('lang-' + slugify(lang))
  113. }
  114. }
  115.  
  116. function createFlagImg(langCode, size) {
  117. const flagImg = document.createElement('img')
  118. flagImg.src = `https://hatscripts.github.io/circle-flags/flags/language/${langCode}.svg`
  119. flagImg.alt = ''
  120. flagImg.width = size
  121. return flagImg
  122. }
  123.  
  124. console.time('monowikt: hide table of contents text')
  125. document.querySelectorAll('#toc > ul > li.toclevel-1').forEach(li => {
  126. const span = li.querySelector('a > span.toctext')
  127. const lang = span.textContent.replaceAll(' ', '_')
  128. const langCode = LANG_MAP[lang]
  129. if (langCode) {
  130. span.textContent = ' ' + span.textContent
  131. const flagImg = createFlagImg(langCode, 16)
  132. span.insertBefore(flagImg, span.firstChild)
  133. }
  134.  
  135. if (!LANG_WHITELIST.has(lang)) {
  136. hide(SHOW_ALL_LANGS_IN_TOC ? li.querySelector('ul') : li, lang)
  137. }
  138. })
  139. console.timeEnd('monowikt: hide table of contents text')
  140.  
  141. console.time('monowikt: hide sections')
  142. let hideNext = false
  143. let lang
  144. let hr
  145. Array.from(document.querySelector('#mw-content-text > div').children).forEach(el => {
  146. if (el.nodeName === 'H2') {
  147. const headline = el.querySelector('.mw-headline')
  148. lang = headline.textContent.replaceAll(' ', '_')
  149. console.log('lang:', lang)
  150. const langCode = LANG_MAP[lang]
  151. if (langCode) {
  152. headline.textContent = ' ' + headline.textContent
  153. const flagImg = createFlagImg(langCode, 32)
  154. headline.insertBefore(flagImg, headline.firstChild)
  155. }
  156. hideNext = !LANG_WHITELIST.has(lang)
  157. if (hr) {
  158. hide(hr, lang)
  159. hr = undefined
  160. }
  161. } else if (el.nodeName === 'HR') {
  162. hr = el
  163. }
  164. if (hideNext && !hr) {
  165. hide(el, lang)
  166. }
  167. })
  168. console.timeEnd('monowikt: hide sections')
  169.  
  170. console.time('monowikt: hide categories')
  171. document.querySelectorAll('#mw-normal-catlinks > ul > li').forEach(li => {
  172. const category = li.textContent
  173. if (!/^en:|(?<!(Old|Middle) )\bEnglish\b/.test(category) || /(borrowed|derived) from English/.test(category)) {
  174. hide(li)
  175. } else {
  176. // const a = li.querySelector('a')
  177. // a.textContent = category.replace(/\s*(?:(?<!(Old|Middle) )English|terms)\s*/g, '')
  178. }
  179. })
  180. console.timeEnd('monowikt: hide categories')
  181.  
  182. const scrollToElem = document.getElementById(hashLang)
  183. if (scrollToElem) {
  184. scrollToElem.scrollIntoView()
  185. }
  186.  
  187. window.addEventListener('hashchange', () => {
  188. const hashLang = getHashLang()
  189. console.log('monowikt: changed hashLang :', hashLang)
  190. console.log('monowikt: slugify(hashLang):', slugify(hashLang))
  191. if (LANGS_ON_PAGE.has(hashLang) && !LANG_WHITELIST.has(hashLang)) {
  192. Array.from(document.getElementsByClassName('lang-' + slugify(hashLang))).forEach(el => {
  193. el.classList.remove('lang-hidden')
  194. })
  195. document.getElementById(hashLang).scrollIntoView()
  196. }
  197. }, false)
  198. })()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址