|
|
@@ -0,0 +1,135 @@
|
|
|
+// ==UserScript==
|
|
|
+// @name OceanEngine Document Maker
|
|
|
+// @namespace http://tampermonkey.net/
|
|
|
+// @version 1.0
|
|
|
+// @description Translate document to enumeration and type defintion
|
|
|
+// @author You
|
|
|
+// @match https://open.oceanengine.com/labels/7/docs/*
|
|
|
+// @grant GM_setClipboard
|
|
|
+// @run-at document-start
|
|
|
+// ==/UserScript==
|
|
|
+
|
|
|
+(function() {
|
|
|
+ 'use strict';
|
|
|
+ const convertType = (type) => {
|
|
|
+ const isList = type.endsWith('[]')
|
|
|
+ if (isList) type = type.substring(0, type.length - 2)
|
|
|
+ switch (type.toLowerCase()) {
|
|
|
+ case 'float': type = 'Float'; break
|
|
|
+ case 'double': type = 'Double'; break
|
|
|
+ case 'number':
|
|
|
+ case 'int':
|
|
|
+ case 'long':
|
|
|
+ case 'integer': type = 'Long'; break
|
|
|
+ case 'boolean': type = 'Boolean'; break
|
|
|
+ case 'string': type = 'String'; break
|
|
|
+ case 'json':
|
|
|
+ case 'object': type = 'Object'; break
|
|
|
+ }
|
|
|
+ if (isList) type = `List<${type}>`
|
|
|
+ return type
|
|
|
+ }
|
|
|
+ const parseName = (childNodes) => {
|
|
|
+ if (!childNodes) return
|
|
|
+ for (const node of childNodes) {
|
|
|
+ if (node.nodeType === Node.TEXT_NODE) {
|
|
|
+ const text = node.textContent.trim()
|
|
|
+ if (text) return text
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const parseRow = (row) => {
|
|
|
+ const tds = row.querySelectorAll('td')
|
|
|
+ const name = parseName(tds[0].querySelector('div')?.childNodes)
|
|
|
+ if (!name) return ''
|
|
|
+ const optional = tds[0].querySelector('span.tag')?.innerText?.trim() !== '必填'
|
|
|
+ const type = tds[1].innerText.trim()
|
|
|
+ const comment = tds[2].innerText.trim()
|
|
|
+ return ` val ${name.replace(/\n/g, '')}: ${convertType(type)}${optional ? '? = null' : ''}, // ${comment.replace(/\n/g, ' ')}\n`
|
|
|
+ }
|
|
|
+ const parseRows = (rows) => {
|
|
|
+ if (!rows.length) return
|
|
|
+ let content = `data class Foo (\n`
|
|
|
+ rows.forEach(row => {
|
|
|
+ content += parseRow(row)
|
|
|
+ })
|
|
|
+ content += ')'
|
|
|
+ return content
|
|
|
+ }
|
|
|
+
|
|
|
+ const parseTable = (table, selector, result) => {
|
|
|
+ result.innerText = parseRows(table.querySelectorAll(selector))
|
|
|
+ result.style.display = ''
|
|
|
+ GM_setClipboard(result.innerText)
|
|
|
+ }
|
|
|
+
|
|
|
+ const ENUM_HINT = '允许值'
|
|
|
+
|
|
|
+ const processEnumerationNode = (node) => {
|
|
|
+ if (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'CODE') {
|
|
|
+ if (node.previousSibling?.tagName !== 'BR') node.parentNode.insertBefore(document.createElement('br'), node)
|
|
|
+ node.innerText = node.innerText.replace(/"|'/g, '')
|
|
|
+ } else if (node.nodeType === Node.TEXT_NODE && node.previousSibling?.tagName === 'CODE') {
|
|
|
+ const comment = node.textContent.trim().replace(/、|,|,$/g, '')
|
|
|
+ node.textContent = comment ? `,\u00A0//\u00A0${comment}` : ','
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const formatEnumerations = (table) => {
|
|
|
+ table.querySelectorAll('tr > td:nth-child(3) > div').forEach(div => {
|
|
|
+ if (div.innerText?.includes(ENUM_HINT)) {
|
|
|
+ // 提示模式 允许值:blahblah
|
|
|
+ let started = false
|
|
|
+ let node = div.childNodes[0]
|
|
|
+ while (node) {
|
|
|
+ if (started) {
|
|
|
+ processEnumerationNode(node)
|
|
|
+ } else if (node.nodeType === Node.TEXT_NODE && node.textContent.includes(ENUM_HINT)) {
|
|
|
+ started = true
|
|
|
+ }
|
|
|
+ node = node.nextSibling
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 行首模式
|
|
|
+ let node = div.querySelector('br + code')
|
|
|
+ if (node?.previousSibling?.tagName !== 'BR') return
|
|
|
+ while (node) {
|
|
|
+ processEnumerationNode(node)
|
|
|
+ node = node.nextSibling
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const createButton = (table) => {
|
|
|
+ if (table.dataset.done) return
|
|
|
+ table.dataset.done = true
|
|
|
+ formatEnumerations(table)
|
|
|
+ const levels = Array.from(table.querySelectorAll('tr')).reduce((s, row) => {
|
|
|
+ if (row.className) s.add(row.className)
|
|
|
+ return s
|
|
|
+ }, new Set())
|
|
|
+ const container = document.createElement('div')
|
|
|
+ const result = document.createElement('pre')
|
|
|
+ result.style.display = 'none'
|
|
|
+ table.parentNode.insertBefore(container, table)
|
|
|
+ table.parentNode.insertBefore(result, table)
|
|
|
+ const addBtn = (level) => {
|
|
|
+ const btn = document.createElement('button')
|
|
|
+ btn.append(document.createTextNode(level))
|
|
|
+ btn.addEventListener('click', () => parseTable(table, `tbody > tr.${level}`, result))
|
|
|
+ container.append(btn)
|
|
|
+ }
|
|
|
+ for (const level of levels.values()) addBtn(level)
|
|
|
+ }
|
|
|
+
|
|
|
+ const ob = new MutationObserver(mutations => {
|
|
|
+ mutations.forEach(({ target }) => {
|
|
|
+ if (target?.tagName === 'DIV' && target?.classList?.contains('doc-content-body')) {
|
|
|
+ target.querySelectorAll('table').forEach(createButton)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ ob.observe(document.body, { subtree: true, childList: true })
|
|
|
+
|
|
|
+})();
|