diff --git a/.gitignore b/.gitignore index e6ca6341c84d18fd700bba91eb64a386934f2bad..3b8a5a15a7b1fb8d09e7e105c80f6670ace1c6b5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ out/ +json/ # ide files .project diff --git a/package.json b/package.json index 8f2e7d0712221a42ac81f1bdc4546ce1b9f35c19..0612fc94267b3bfe5bcfaa5837555b3f0191a68b 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,8 @@ "github-slugger": "^1.2.1", "i18n": "^0.8.3", "jasmine-xml-reporter": "^1.2.1", + "jquery": "^3.7.0", + "jsdom": "^22.1.0", "json-pointer": "^0.6.0", "json-schema-faker": "git+https://git@dev.iopsys.eu/fork/json-schema-faker#iopsys", "lodash": "^4.17.15", diff --git a/uci-to-table.js b/uci-to-table.js new file mode 100755 index 0000000000000000000000000000000000000000..3233ebc5bd0d7b3e281e38cf7ba53f7f0bf19fad --- /dev/null +++ b/uci-to-table.js @@ -0,0 +1,198 @@ +#! /usr/bin/env node + +/* eslint-disable */ +const jsdom = require('jsdom'); +const { JSDOM } = jsdom; +const Optimist = require('optimist'); +const path = require('path'); +const readdirp = require('readdirp'); +const fs = require('fs'); +const { argv } = Optimist + .usage('Generate html table documentation from JSON.\n\nUsage: $0') + .demand('d') + .alias('d', 'dir') + .describe('d', 'path to directory containing the JSON files.') + .alias('o', 'output') + .demand('o') + .describe('o', 'path to an output directory.'); + +const dom = new JSDOM('<!DOCTYPE html>'); +const $ = (require('jquery'))(dom.window); + +const { document } = dom.window; + +function isEven(a) { + return a % 2 === 0; +} + +function encodeText(a) { + return $('<div />').text(a).html(); +} + +function isArray(a) { + return Object.prototype.toString.call(a) === '[object Array]'; +} + +function buildTable(a) { + const e = document.createElement('table'); + let d; + let b; + if (isArray(a)) return buildArray(a); + if (a && typeof(a) === 'object') { + Object.keys(a).forEach((c) => { + if (typeof a[c] !== 'object' || isArray(a[c])) { + if (typeof a[c] === 'object' && isArray(a[c])) { + d = e.insertRow(-1); + b = d.insertCell(-1); + b.colSpan = 2; + b.innerHTML = `<div style="font-weight: bold">${encodeText(c)}</div><table style="width:100%">${$(buildArray(a[c]), !1).html()}</table>`; + } else { + d = e.insertRow(-1); + b = d.insertCell(-1); + b.innerHTML = `<div style="font-weight: bold">${encodeText(c)}</div>`; + d = d.insertCell(-1); + d.innerHTML = `<div class='td_row_even'>${encodeText(a[c])}</div>`; + } + } else { + d = e.insertRow(-1); + b = d.insertCell(-1); + b.colSpan = 2; + b.innerHTML = `<div style="font-weight: bold">${encodeText(c)}</div><table style="width:100%">${$(buildTable(a[c]), !1).html()}</table>`; + } + }); + } + + return e; +} + +function buildArray(a) { + const e = document.createElement('table'); + let d; + let b; + let c = !1; + let p = !1; + const m = {}; + let h = -1; + let n = 0; + let l; + + l = ''; + if (a.length === 0) return '<div></div>'; + d = e.insertRow(-1); + for (let f = 0; f < a.length; f += 1) { + if (typeof a[f] !== 'object' || isArray(a[f])) { + if (typeof a[f] === 'object' && isArray(a[f])) { + b = d.insertCell(h); + b.colSpan = 2; + b.innerHTML = `<div></div><table style="width:100%">${$(buildArray(a[f]), !1).html()}</table>`; + c = !0; + } else { + if (!p) { + h += 1; + p = !0; + b = d.insertCell(h); + m.empty = h; + b.innerHTML = '<div> </div>'; + } + } + } else { + Object.keys(a[f]).forEach((k) => { + l = `-${k}`, l in m || (c = !0, h += 1, b = d.insertCell(h), m[l] = h, b.innerHTML = `<div style="font-weight: bold; font-size: 14px">${encodeText(k)}</div>`); + }); + } + } + c || e.deleteRow(0); + n = h + 1; + for (let f = 0; f < a.length; f += 1) { + let tdClass; + + + if (d = e.insertRow(-1), tdClass = isEven(f) ? 'td_row_even' : 'td_row_odd', typeof a[f] !== 'object' || isArray(a[f])) { + if (typeof a[f] === 'object' && isArray(a[f])) { + for (h = m.empty, c = 0; c < n; c += 1) { + b = d.insertCell(c), b.className = tdClass, l = c === h ? `<table style="width:100%">${$(buildArray(a[f]), !1).html()}</table>` : ' ', b.innerHTML = `<div class='${tdClass}'>${encodeText(l) + }</div>`; + } + } else + for (h = m.empty, c = 0; c < n; c += 1) b = d.insertCell(c), l = c === h ? a[f] : ' ', b.className = tdClass, b.innerHTML = `<div class='${tdClass}'>${encodeText(l)}</div>`; + } else { + for (c = 0; c < n; c += 1) b = d.insertCell(c), b.className = tdClass, b.innerHTML = `<div class='${tdClass}'> </div>`; + for (const k in a[f]) { c = a[f], l = `-${k}`, h = m[l], b = d.cells[h], b.className = tdClass, typeof c[k] !== 'object' || isArray(c[k]) ? typeof c[k] === 'object' && isArray(c[k]) ? b.innerHTML = `<table style="width:100%">${$(buildArray(c[k]), !1).html()}</table>` : b.innerHTML = `<div class='${tdClass}'>${encodeText(c[k])}</div>` : b.innerHTML = `<table style="width:100%">${$(buildTable(c[k]), !1).html()}</table>`; } + } + } + return e; +} + +function processJson(elem) { + return buildTable(elem).innerHTML; +} + +const jsonPath = path.resolve(argv.d); +const target = fs.statSync(jsonPath); +const files = []; +const outDir = path.resolve(argv.o); + +function parseJson(json) { + Object.keys(json).forEach((k) => { + let outer = json[k]; + + outer.forEach((elem) => { + elem.options.forEach((e) => { + if (!e.hasOwnProperty("type")) + return; + + if (!e.hasOwnProperty("required")) + e.required = "no" + if (!e.hasOwnProperty("default") || e.default === null ) { + switch (e.type) { + case 'boolean': + e.default = false; + break; + case 'integer': + e.default = 0; + break; + default: + e.default = "null" + break; + } + } + }) + }) + }) + + return json; +} + +function jsonToTable(json, file) { + json = parseJson(json); + const table = processJson(json); + let output = ''; + + if (argv.o) output += `${argv.o}/`; + output += `${path.basename(file).split('.').slice(0, -1).join('.')}.md`; + fs.writeFileSync(output, table); +} + +if (!fs.existsSync(outDir)) { + fs.mkdirSync(outDir); +} + +const outTarget = fs.statSync(outDir); + +if (outTarget.isDirectory()) { + if (target.isDirectory()) { + readdirp(jsonPath, { root: jsonPath, fileFilter: '*.json' }) + .on('data', entry => files.push(entry)) + .on('end', () => { + files.forEach((f) => { + const data = JSON.parse(fs.readFileSync(f.fullPath, 'utf8')); + const output = `${f.basename.split('.').slice(0, -1).join('.')}.md`; + + jsonToTable(data, output); + }); + }); + } else { + const data = JSON.parse(fs.readFileSync(jsonPath, 'utf8')); + jsonToTable(data, jsonPath); + } +} else console.log(`${outDir} is not a directory.`);