graphQL 工具脚本 💪
// ==UserScript==
// @name graphQL-toolkit
// @namespace https://github.com/SublimeCT/greasy_monkey_scripts
// @version 0.0.1
// @description graphQL 工具脚本 💪
// @note v0.0.2 记住上次的搜索内容
// @note v0.0.1 使文档居左
// @author Sven
// @icon https://graphql.cn/img/favicon.png
// @include https://*
// @include http://*
// @grant none
// @run-at document-start
// ==/UserScript==
; (() => {
class ToolkitModule {
constructor() { }
isActive = true
}
class Store {
static getOptions() {
const options = localStorage.getItem('GraphQLToolkit_options')
if (!options) return {}
try {
return JSON.parse(options) || {}
} catch (err) {
console.log(err)
return {}
}
}
static setOption(options) {
localStorage.setItem('GraphQLToolkit_options', JSON.stringify(options))
}
static updateOptions(options) {
const allOptions = Store.getOptions()
Object.assign(allOptions, options)
Store.setOption(allOptions)
}
}
/**
* 使用上次的搜索内容
*/
class QueryToolkitModule extends ToolkitModule {
init(ctx) {}
static async addEventListeners() {
let items
for (let times = 20; times--;) {
await Toolkit.delay()
items = document.querySelectorAll('.graphiql-wrapper > div > div')
if (items && items.length) break
}
if (items.length < 2) throw new Error('missing sidebar element')
const sidebar = items[1]
const buttons = sidebar.querySelectorAll('div:nth-child(1) > div')
buttons[0].click()
const apiDoms = items[items.length - 1]
let searchInput
for (let times = 30; times--;) {
await Toolkit.delay()
searchInput = apiDoms.querySelector('input[type="text"]')
if (searchInput) break
}
// 直接使用上次搜索内容
const options = Store.getOptions()
if (options.query) {
searchInput.value = options.query // 填充值
d.setState({ searchValue: options.query }) // 直接搜索
}
// 绑定 input 事件记录输入值
searchInput.addEventListener('input', evt => {
Store.setOption({ query: evt.target.value })
})
}
onload() {
QueryToolkitModule.addEventListeners()
}
}
/**
* 加入自定义样式
*/
class SheetsToolkitModule extends ToolkitModule {
static _getSheets() {
return `
/* 布局样式 */
.graphiql-wrapper > div > div:last-of-type {
right: auto;
left: 30vw;
max-width: 70vw !important;
}
`
}
init(ctx) {
// ctx.log('加入自定义样式')
// SheetsToolkitModule.appendSheets()
}
// 通过注入 css 实现隐藏广告并固定布局
static appendSheets() {
const sheet = document.createTextNode(SheetsToolkitModule._getSheets())
const el = document.createElement('style')
el.id = 'handle-sheets'
el.appendChild(sheet)
document.getElementsByTagName('head')[0].appendChild(el)
}
onload(ctx) {
ctx.log('加入自定义样式')
SheetsToolkitModule.appendSheets()
// console.error('onload ????????????????')
}
}
/**
* 工具类
*/
class Toolkit {
debug = true
options = {}
users = {}
constructor(options = {}) {
Object.assign(this.options, options)
// 禁用 init, 因为必须要等到 onload 才能确定是否是 GraphQL 页面
// this.emitHook('init')
}
/**
* 工具集
*/
static modules = []
/**
* 注册工具模块
*/
static use(moduleItem) {
// 禁用未激活的模块
if (!moduleItem.isActive) return
Array.isArray(moduleItem) ? moduleItem.map(item => Toolkit.use(item)) : Toolkit.modules.push(moduleItem)
}
/**
* 触发钩子函数
* @param {string}} hook 钩子函数名
*/
emitHook(hook) {
this.log('触发钩子函数: ' + hook, Toolkit.modules.length)
Toolkit.modules.map(module => module[hook] && typeof module[hook] === 'function' && module[hook](this))
}
log(...args) {
console.log('%c[GraphQL Toolkit] LOG: ', 'color:teal', ...args)
}
static delay(timeout = 200) {
return new Promise(resolve => setTimeout(resolve, timeout))
}
}
Toolkit.use(new SheetsToolkitModule())
Toolkit.use(new QueryToolkitModule())
window._$GraphQLToolkit = new Toolkit()
window.addEventListener('DOMContentLoaded', async () => {
for (let times = 10; times--;) {
await Toolkit.delay()
if (window.GraphQLPlayground) break
}
if (!window.GraphQLPlayground) return
// 执行所有模块的钩子函数
window._$GraphQLToolkit.emitHook('onload')
})
})();