graphQL-toolkit

graphQL 工具脚本 💪

  1. // ==UserScript==
  2. // @name graphQL-toolkit
  3. // @namespace https://github.com/SublimeCT/greasy_monkey_scripts
  4. // @version 0.0.1
  5. // @description graphQL 工具脚本 💪
  6. // @note v0.0.2 记住上次的搜索内容
  7. // @note v0.0.1 使文档居左
  8. // @author Sven
  9. // @icon https://graphql.cn/img/favicon.png
  10. // @include https://*
  11. // @include http://*
  12. // @grant none
  13. // @run-at document-start
  14. // ==/UserScript==
  15.  
  16. ; (() => {
  17. class ToolkitModule {
  18. constructor() { }
  19. isActive = true
  20. }
  21. class Store {
  22. static getOptions() {
  23. const options = localStorage.getItem('GraphQLToolkit_options')
  24. if (!options) return {}
  25. try {
  26. return JSON.parse(options) || {}
  27. } catch (err) {
  28. console.log(err)
  29. return {}
  30. }
  31. }
  32. static setOption(options) {
  33. localStorage.setItem('GraphQLToolkit_options', JSON.stringify(options))
  34. }
  35. static updateOptions(options) {
  36. const allOptions = Store.getOptions()
  37. Object.assign(allOptions, options)
  38. Store.setOption(allOptions)
  39. }
  40. }
  41. /**
  42. * 使用上次的搜索内容
  43. */
  44. class QueryToolkitModule extends ToolkitModule {
  45. init(ctx) {}
  46. static async addEventListeners() {
  47. let items
  48. for (let times = 20; times--;) {
  49. await Toolkit.delay()
  50. items = document.querySelectorAll('.graphiql-wrapper > div > div')
  51. if (items && items.length) break
  52. }
  53. if (items.length < 2) throw new Error('missing sidebar element')
  54. const sidebar = items[1]
  55. const buttons = sidebar.querySelectorAll('div:nth-child(1) > div')
  56. buttons[0].click()
  57. const apiDoms = items[items.length - 1]
  58. let searchInput
  59. for (let times = 30; times--;) {
  60. await Toolkit.delay()
  61. searchInput = apiDoms.querySelector('input[type="text"]')
  62. if (searchInput) break
  63. }
  64. // 直接使用上次搜索内容
  65. const options = Store.getOptions()
  66. if (options.query) {
  67. searchInput.value = options.query // 填充值
  68. d.setState({ searchValue: options.query }) // 直接搜索
  69. }
  70. // 绑定 input 事件记录输入值
  71. searchInput.addEventListener('input', evt => {
  72. Store.setOption({ query: evt.target.value })
  73. })
  74. }
  75. onload() {
  76. QueryToolkitModule.addEventListeners()
  77. }
  78. }
  79. /**
  80. * 加入自定义样式
  81. */
  82. class SheetsToolkitModule extends ToolkitModule {
  83. static _getSheets() {
  84. return `
  85. /* 布局样式 */
  86. .graphiql-wrapper > div > div:last-of-type {
  87. right: auto;
  88. left: 30vw;
  89. max-width: 70vw !important;
  90. }
  91. `
  92. }
  93. init(ctx) {
  94. // ctx.log('加入自定义样式')
  95. // SheetsToolkitModule.appendSheets()
  96. }
  97. // 通过注入 css 实现隐藏广告并固定布局
  98. static appendSheets() {
  99. const sheet = document.createTextNode(SheetsToolkitModule._getSheets())
  100. const el = document.createElement('style')
  101. el.id = 'handle-sheets'
  102. el.appendChild(sheet)
  103. document.getElementsByTagName('head')[0].appendChild(el)
  104. }
  105. onload(ctx) {
  106. ctx.log('加入自定义样式')
  107. SheetsToolkitModule.appendSheets()
  108. // console.error('onload ????????????????')
  109. }
  110. }
  111. /**
  112. * 工具类
  113. */
  114. class Toolkit {
  115. debug = true
  116. options = {}
  117. users = {}
  118. constructor(options = {}) {
  119. Object.assign(this.options, options)
  120. // 禁用 init, 因为必须要等到 onload 才能确定是否是 GraphQL 页面
  121. // this.emitHook('init')
  122. }
  123. /**
  124. * 工具集
  125. */
  126. static modules = []
  127. /**
  128. * 注册工具模块
  129. */
  130. static use(moduleItem) {
  131. // 禁用未激活的模块
  132. if (!moduleItem.isActive) return
  133. Array.isArray(moduleItem) ? moduleItem.map(item => Toolkit.use(item)) : Toolkit.modules.push(moduleItem)
  134. }
  135. /**
  136. * 触发钩子函数
  137. * @param {string}} hook 钩子函数名
  138. */
  139. emitHook(hook) {
  140. this.log('触发钩子函数: ' + hook, Toolkit.modules.length)
  141. Toolkit.modules.map(module => module[hook] && typeof module[hook] === 'function' && module[hook](this))
  142. }
  143. log(...args) {
  144. console.log('%c[GraphQL Toolkit] LOG: ', 'color:teal', ...args)
  145. }
  146. static delay(timeout = 200) {
  147. return new Promise(resolve => setTimeout(resolve, timeout))
  148. }
  149. }
  150. Toolkit.use(new SheetsToolkitModule())
  151. Toolkit.use(new QueryToolkitModule())
  152. window._$GraphQLToolkit = new Toolkit()
  153. window.addEventListener('DOMContentLoaded', async () => {
  154. for (let times = 10; times--;) {
  155. await Toolkit.delay()
  156. if (window.GraphQLPlayground) break
  157. }
  158. if (!window.GraphQLPlayground) return
  159. // 执行所有模块的钩子函数
  160. window._$GraphQLToolkit.emitHook('onload')
  161. })
  162. })();