Greasy Fork

Greasy Fork is available in English.

5ch Plus

5ch を拡張します

目前为 2019-09-26 提交的版本,查看 最新版本

// ==UserScript==
// @name 5ch Plus
// @name:ja 5ch プラス
// @description 5ch を拡張します
// @author null-chan <[email protected]>
// @version 0.1.0
// @run-at document-body
// @include http*://*5ch.net/*
// @include http*://imgur.com/*
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js
// @grant none
// @copyright Copyright (c) 2019 null-chan
// @license MIT
// @namespace http://greasyfork.icu/users/379206
// ==/UserScript==

'use strict'

$(window).on('load', () => console.info('window.on(\'load\')'))

const parse_json = object => {
  let x
  let ret = ''
  for (x in object) {
    let y
    let dec = ''
    for (y in object[x]) dec += `${y}:${object[x][y]}!important;`
    ret += `${x}{${dec}}`
  }
  return ret
}
const generateColor = () => {
  // https://stackoverflow.com/questions/1484506/random-color-generator
  const letters = '0123456789abcdef'
  let color = ''
  for (let i = 0; i < 6; i++)
    color += letters[Math.floor(Math.random() * 16)]
  return color
}
const preset = {
  'imgur.com/[a-zA-Z0-9]{7}': {
    script: () => (location.href = $('meta[name="twitter:image"]').attr('content')),
  },
  global: {
    style: {
      html: {
        'font-family': 'メイリオ,Arial',
      },
    },
    script: () => $(window).on('load', () => {
      $('a[href^="https://"],a[href^="http://"],a[href^="/"]').each(function () {
        let href = $(this).attr('href')
        console.info(`Detected link: %c${$(this).html()}%c - %c${href}`, 'text-decoration:underline', '', 'text-decoration:underline')
        if (/^(https?:)?\/\/jump[.]5ch[.]net\/[?]/.test($(this).attr('href'))) href = $(this).text()
        $(this).addClass('rinku')
        $(this).attr({
          href: href,
          rel: 'noreferrer noopener',
          target: '_blank',
          title: 'ページは新しいタブで開かれます (rel="noreferrer noopener")',
        })
      })
      $(document).on('mouseenter', '.thread .rinku:not([data-tooltip])', function () {
        console.info(`Hovered: ${$(this).attr('href')}`)
        if ($(this).hasClass('loadeding')) return
        $(this).addClass('loadeding')
        const uralu = (new RegExp('^(https?:)?//.*5ch[.]net/').test($(this).attr('href')) ? '' : 'https://cors-anywhere.herokuapp.com/') + $(this).attr('href')
        $(this).attr('title', 'Loading...')
        console.log(`Loading: ${uralu}`)
        $.get(uralu, (res, _, xhr) => {
          const type = xhr.getResponseHeader('content-type')
          console.info(`Loaded: ${uralu} - ${type}`)
          let title
          if (type.includes('text/html')) title = $(res).filter('title').text() || 'No title found'
          else title = `The link destination is not HTML  - ${type}`
          $(this).attr('title', title)
          $(this).after(`<br><span style='color:#808080'>${title}</span>`)
        })
      })
    }),
  },
  'http://.*5ch[.]net.*': {
    protocol: true,
    script: () => location.href = location.href.replace(new RegExp('^http://'), 'https://'),
  },
  '.*[^jump][.]5ch[.]net/[a-z]{1,}/(#[0-9]{1,2})?': {
    style: {
      body: {
        background: 'url(https://picsum.photos/1920/1080?blur=5) center no-repeat fixed',
        'background-size': 'cover',
      },
      'div[style="margin: 0; padding: 0 0 0 0.5em; border-top: 0.5em solid #BEB; border-bottom: 0.5em solid #BEB; border-radius: 0.50em / 0.50em; padding: 0 0 1.0em 0.5em; height: 25em; overflow-y: scroll; background: #BEB;"]': {
        height: 'auto',
        'max-height': '25em',
      },
      '.ADVERTISE_AREA,div[style="margin-top:10px;margin-bottom:10px;width:100%;text-align:center;"]': {
        display: 'none',
      },
    },
  },
  '.*[.]5ch[.]net/test/read.cgi/.*': {
    style: {
      '.navbar-fixed-top': {
        background: 'rgba(0, 0, 0, 0.7)',
      },
      '.container_body': {
        background: 'none',
        margin: 0,
        padding: 0,
      },
      '#background': {
        height: '100%',
        width: '100%',
        background: 'url(https://picsum.photos/1920/1080) center no-repeat fixed',
        'background-size': 'cover',
        'z-index': -1,
        position: 'fixed',
        top: 0,
        filter: 'blur(5px)',
        transition: 'all 0.3s linear',
      },
      '#background.cleek': {
        filter: 'blur(0)',
      },
      '#search-text,#search-button': {
        'border-radius': '30px 0 0 30px',
        background: 'none',
        border: '1px solid rgba(255,255,255,0.5)',
        filter: 'invert(0.4)',
      },
      '#search-button': {
        'border-radius': '0 30px 30px 0',
        'border-left': 'none',
        transition: 'all 0.2s ease-in-out',
      },
      '#search-text:focus,#search-button:hover': {
        filter: 'invert(0)',
      },
      '.title': {
        'margin-top': '70px',
        'font-size': '30px',
        color: '#f5f5f5',
        'text-shadow': '0 1px 10px #212121',
      },
      '.stoplight': {
        background: 'rgba(255, 23, 68, 0.6)',
        'margin-bottom': '10px',
        'text-align': 'center',
      },
      '.thread': {
        'margin-left': '30%',
      },
      '.post,.post_hover,.menuitem': {
        'border-radius': '15px',
        background: 'rgba(0, 0, 0, 0.7)',
        'box-shadow': '5px 5px 30px black',
        transition: 'all 0.2s ease-in-out',
      },
      '.post,.post_hover': {
        'margin-bottom': '15px',
        'max-width': '800px',
        padding: 0,
      },
      '.post:hover': {
        transform: 'scale(1.02, 1.02)',
        'box-shadow': 'none',
      },
      '.meta': {
        background: 'rgba(0, 0, 0, 0.4)',
        'border-radius': '15px 15px 0 0',
        padding: '5px 10px 5px 10px',
      },
      '.message': {
        margin: '0 10px',
        padding: '5px 0 10px',
      },
      '.message > .escaped': {
        color: 'white',
      },
      '.message > .escaped > hr': {
        'border-top': '1px solid #616161',
      },
      '.meta > .number,.date': {
        color: '#bdbdbd',
      },
      '.be': {
        'margin-left': '5px',
      },
      '.escaped > a': {
        color: '#42a5f5',
        'text-shadow': '1px 1px 10px white',
        transition: 'all 0.2s ease-in-out',
      },
      '.escaped > a:hover': {
        'text-shadow': 'none',
      },
      '.meta a': {
        color: 'green',
      },
      'br,nav': {
        'user-select': 'none',
      },
      '.menuitem': {
        'box-shadow': '3px 3px 20px black',
      },
      '.menuitem:hover': {
        'box-shadow': '1px 1px 20px black',
      },
      '.footer': {
        padding: '50px 0 20px 0',
      },
      '.search-logo': {
        filter: 'invert(0.5)',
        transition: 'all 0.2s ease-in-out',
      },
      '.search-logo:hover': {
        filter: 'invert(1)',
      },
      '#post-form-inner': {
        background: 'rgba(0, 0, 0, 0.7)',
        border: 'none',
      },
      '.navbar-fixed-top,.pagestats,.menuitem,.topmenu,.bottommenu,.post,.post_hover': {
        border: 'none',
        color: 'white',
      },
      '.socialmedia,#banner,.ad--right,.ad--bottom': {
        display: 'none',
      },
      '.post[data-id="1002"]': {
        display: 'none',
      },
      '.mail_parse': {
        'margin-right': '5px',
      },
    },
    lang: {
      '.menuitem:contains(全部)': 'All',
      '.menuitem:contains(最新50)': 'Latest 50',
      '.menuitem:contains(スマホ版)': 'Mobile (Not Supported)',
      '.menuitem:contains(掲示板に戻る)': 'Back to Board Top',
      '.menuitem:contains(ULA版)': 'ULA (Not Supported)',
      '.metastats:contains(コメント)': ['コメント', ' Comments'],
    },
    script: () => {
      let long_timer
      let long_cleek = false
      $('.container_body').append('<div id="background"></div>')
      $('#background')
        .on('dblclick', () => $('#background').toggleClass('cleek'))
        .on('mouseup', () => {
          if (long_cleek) $('#background').attr('style', `background:url(https://picsum.photos/1920/1080?${new Date().getTime()}) center no-repeat fixed!important`)
          long_cleek = false
          clearTimeout(long_timer)
          return true
        })
        .on('mousedown', () => {
          long_timer = setTimeout(() => long_cleek = true, 500)
          return true
        })
      $(window).on('load', () => {
        const ids = []
        $('.post[data-id="1001"] .name b').text('オーバースレッドゥ')
        $('.uid').each(function () {
          const id = $(this).text().slice(3)
          const ids_ = ids.filter(item => item[0] === id)
          if (!ids_.length) {
            const color = generateColor()
            ids.push([id, color])
            console.log(`ID: ${[id, color]}`)
            $(this).attr('title', `#${color}`)
            return $(this).css('color', `#${color}`)
          }
          $(this).attr('title', `#${ids_[0][1]}`)
          return $(this).css('color', `#${ids_[0][1]}`)
        })
        $('.name b a[href^="mailto:"]').each(function () {
          let supeisharu = ['フメイ', $(this).attr('href').slice(7)]
          if (supeisharu[1] === 'sage') supeisharu[0] = 'サゲ'
          else if (supeisharu[1] === 'age') supeisharu[0] = 'アゲ'
          else if (supeisharu[1].test(/@(yahoo.co.jp)$/)) supeisharu[0] === 'ヤホー'
          else if (supeisharu[1].test(/@(protonmail.com|protonmail.ch|pm.me)$/)) supeisharu[0] === 'プロト'
          $(this).parents('.meta').children('.date').before(`<a class='mail_parse' href='${$(this).attr('href')}' title='${supeisharu[1]}' style='color:#81c784!important'>(${supeisharu[0]})</a>`)
        })
        $('.name a[href^="mailto:"]').each(function () { $(this).removeAttr('href') })
      })
      $('.date').each(function () {
        $(this).html($(this).text().replace(' ', '<span style="margin-right:5px!important"></span>'))
      })
    },
  },
}
$('head').append(`<style type="text/css">${parse_json(preset.global.style)}</style>`)
preset.global.script()
Object.keys(preset).map(item => {
  if (item === 'global') return
  let path = preset[item]
  let url = location.href
  if (!preset[item].protocol) url = location.href.slice(location.protocol.length + 2)
  const match = new RegExp(`^${item}$`).test(url)
  console.info(`${match ? '\x1b[32m' : '\x1b[31m'}Match: ^${item}$ - ${url} - ${match}`)
  if (match) {
    if (typeof path.style === 'object') $('head').append(`<style type="text/css">${parse_json(path.style)}</style>`)
    if (typeof path.lang === 'object') Object.keys(path.lang).map(item => {
      if (typeof path.lang[item] === 'string')
        $(item).text(path.lang[item])
      else if (typeof path.lang[item] === 'object')
        $(item).html($(item).html().replace(path.lang[item][0], path.lang[item][1]))
    })
    if (typeof path.script === 'function') path.script()
  }
})