import logger from '../lib/logger' import emitter from '../lib/emitter' import Url from 'licia/Url' import now from 'licia/now' import startWith from 'licia/startWith' import $ from 'licia/$' import upperFirst from 'licia/upperFirst' import loadJs from 'licia/loadJs' import trim from 'licia/trim' import LunaModal from 'luna-modal' import { isErudaEl } from '../lib/util' import evalCss from '../lib/evalCss' let style = null export default [ { name: 'すべての境界線', fn() { if (style) { evalCss.remove(style) style = null return } style = evalCss( '* { outline: 2px dashed #707d8b; outline-offset: -3px; }', document.head ) }, desc: 'すべての要素に色の境界線を追加する', }, { name: 'ページを更新', fn() { const url = new Url() url.setQuery('timestamp', now()) window.location.replace(url.toString()) }, desc: 'URLにタイムスタンプを追加して更新する', }, { name: '検索テキスト', fn() { LunaModal.prompt('テキストを入力してください').then((keyword) => { if (!keyword || trim(keyword) === '') { return } search(keyword) }) }, desc: 'ページ上の指定されたテキストを強調表示します', }, { name: 'ページの編集', fn() { const body = document.body body.contentEditable = body.contentEditable !== 'true' }, desc: 'bodyのcontentEditableを切り替える', }, { name: '画面に合わせる', // https://achrafkassioui.com/birdview/ fn() { const body = document.body const html = document.documentElement const $body = $(body) if ($body.data('scaled')) { window.scrollTo(0, +$body.data('scaled')) $body.rmAttr('data-scaled') $body.css('transform', 'none') } else { const documentHeight = Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight ) const viewportHeight = Math.max( document.documentElement.clientHeight, window.innerHeight || 0 ) const scaleVal = viewportHeight / documentHeight $body.css('transform', `scale(${scaleVal})`) $body.data('scaled', window.scrollY) window.scrollTo(0, documentHeight / 2 - viewportHeight / 2) } }, desc: 'ページ全体を画面に合わせて縮小します', }, { name: 'Vueプラグインを読み込む', fn() { loadPlugin('vue') }, desc: 'Vue 開発ツール', }, { name: 'Monitorプラグインを読み込む', fn() { loadPlugin('monitor') }, desc: 'ページのfps、メモリ、DOMノードを表示する', }, { name: 'Featuresプラグインを読み込む', fn() { loadPlugin('features') }, desc: 'ブラウザ機能の検出', }, { name: 'Timingプラグインを読み込む', fn() { loadPlugin('timing') }, desc: 'パフォーマンスとリソースのタイミングを表示する', }, { name: 'Codeプラグインを読み込む', fn() { loadPlugin('code') }, desc: 'JavaScript を編集して実行する', }, { name: 'Benchmarkプラグインを読み込む', fn() { loadPlugin('benchmark') }, desc: 'JavaScriptベンチマークを実行する', }, { name: 'Geolocationプラグインを読み込む', fn() { loadPlugin('geolocation') }, desc: '地理位置情報をテストする', }, { name: 'Orientationプラグインを読み込む', fn() { loadPlugin('orientation') }, desc: 'テストオリエンテーション API', }, { name: 'Touchesプラグインを読み込む', fn() { loadPlugin('touches') }, desc: '画面タッチを視覚化する', }, ] evalCss(require('./searchText.scss'), document.head) function search(text) { const root = document.body const regText = new RegExp(text, 'ig') traverse(root, (node) => { const $node = $(node) if (!$node.hasClass('eruda-search-highlight-block')) return return document.createTextNode($node.text()) }) traverse(root, (node) => { if (node.nodeType !== 3) return let val = node.nodeValue val = val.replace( regText, (match) => `${match}` ) if (val === node.nodeValue) return const $ret = $(document.createElement('div')) $ret.html(val) $ret.addClass('eruda-search-highlight-block') return $ret.get(0) }) } function traverse(root, processor) { const childNodes = root.childNodes if (isErudaEl(root)) return for (let i = 0, len = childNodes.length; i < len; i++) { const newNode = traverse(childNodes[i], processor) if (newNode) root.replaceChild(newNode, childNodes[i]) } return processor(root) } function loadPlugin(name) { const globalName = 'eruda' + upperFirst(name) if (window[globalName]) return let protocol = location.protocol if (!startWith(protocol, 'http')) protocol = 'http:' loadJs( `${protocol}//cdn.jsdelivr.net/npm/eruda-${name}@${pluginVersion[name]}`, (isLoaded) => { if (!isLoaded || !window[globalName]) return logger.error('Fail to load plugin ' + name) emitter.emit(emitter.ADD, window[globalName]) emitter.emit(emitter.SHOW, name) } ) } const pluginVersion = { monitor: '1.1.1', features: '2.1.0', timing: '2.0.1', code: '2.2.0', benchmark: '2.0.1', geolocation: '2.1.0', orientation: '2.1.1', touches: '2.1.0', vue: '1.1.1', }