Skip to content

Instantly share code, notes, and snippets.

@stokito
Last active November 19, 2023 10:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stokito/f0770d1967e7000bc0302b5556529fb1 to your computer and use it in GitHub Desktop.
Save stokito/f0770d1967e7000bc0302b5556529fb1 to your computer and use it in GitHub Desktop.
acmish-dnsapi: Parse structural info. License 0BSD
export function parseDnsApiInfoFile(infoFileText) {
let infoTexts = infoFileText.split('\n\n')
let infos = []
for (let infoText of infoTexts) {
let info = parseDnsApiInfo(infoText)
if (info) {
infos.push(info)
}
}
return infos
}
/**
* @param {string} infoText
* @returns {null}
*/
export function parseDnsApiInfo(infoText) {
let lines = infoText.split('\n')
if (lines.length < 2 || !lines[0] || !lines[1]) {
return null
}
let info = {
Domains: '',
Site: '',
Docs: '',
Options: '',
OptionsAlt: '',
Issues: '',
Author: ''
}
info.Id = lines.shift()
info.Name = lines.shift()
info.Description = fieldMultiLines(lines, '').substring(1)
while (lines.length > 0) {
let line = lines.shift()
let pos = line.indexOf(':')
if (pos <= 0) {
continue
}
let field = line.substring(0, pos)
let fieldVal = line.substring(pos + 1)
fieldVal = fieldMultiLines(lines, fieldVal)
info[field] = fieldVal.trim()
}
info.Deprecated = info.Description.includes('Deprecated.')
info.Removed = info.Description.includes('Removed.')
info.Opts = parseOpts(info.Options)
info.OptsAlt = parseOpts(info.OptionsAlt)
return info
}
function fieldMultiLines(lines, fieldVal) {
while (lines.length > 0) {
if (!lines[0].startsWith(' ')) {
break
}
let line = lines.shift()
fieldVal += '\n' + line.trim()
}
return fieldVal
}
/**
* @param {string} options
*/
function parseOpts(options) {
if (!options) {
return []
}
let opts = []
let optLines = options.split('\n')
optLines.shift()
for (let optLine of optLines) {
let posName = optLine.indexOf(' ')
if (posName <= 0) {
continue
}
let opt = {
Optional: false,
Description: '',
Default: ''
}
opt.Name = optLine.substring(0, posName)
let posTitle = optLine.indexOf('.')
if (posTitle <= 0) {
opt.Title = optLine.substring(posName + 1)
} else {
opt.Title = optLine.substring(posName + 1, posTitle)
opt.Description = optLine.substring(posTitle)
if (opt.Description.includes(' Optional.')) {
opt.Optional = true
opt.Description = opt.Description.replace(' Optional.', '')
}
let defaultPos = opt.Description.indexOf(' Default: "')
if (defaultPos >= 0) {
let defaultPosEnd = opt.Description.indexOf('".', defaultPos + 1)
opt.Default = opt.Description.substring(defaultPos + ' Default: "'.length, defaultPosEnd)
opt.Description = opt.Description.substring(0, defaultPos)
}
if (opt.Description.startsWith('. ')) {
opt.Description = opt.Description.substring(2)
} else if (opt.Description == '.') {
opt.Description = ''
}
}
opts.push(opt)
}
return opts
}
import * as fs from 'fs';
import test from 'node:test';
import assert from 'node:assert/strict';
import {parseDnsApiInfo, parseDnsApiInfoFile} from "./dnsapi.mjs";
test('parseDnsApiInfo', (t) => {
let infoText = 'OpenStack Designate API\n' +
' Depends on OpenStackClient and python-desginateclient.\n' +
' You will require Keystone V3 credentials loaded into your environment,\n' +
' which could be either password or v3 application credential type.\n' +
' Deprecated.\n' +
' Removed.\n' +
'Site: https://docs.openstack.org/api-ref/dns/\n' +
'Docs: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_openstack\n' +
'Options: usual\n' +
' OS_AUTH_URL Auth URL\n' +
' OS_AUTH_URL2 Auth URL. E.g. "https://keystone.example.com:5000/"\n' +
' OS_USERNAME Username. Default: "root".\n' +
' OS_PASSWORD Password\n' +
' OS_PASSWORD2 Password. Optional.\n' +
'OptionsAlt: advanced\n' +
' OS_PROJECT_DOMAIN_NAME Project domain name. E.g. "Default".\n' +
' OS_USER_DOMAIN_NAME User domain name. Default: "Default".\n' +
'Issues: https://github.com/acmesh-official/acme.sh/issues/3054\n' +
'Author: Andy Botting <andy@andybotting.com>'
let actual = parseDnsApiInfo(infoText)
assert.deepEqual(actual.Name, 'OpenStack Designate API')
let contents = fs.readFileSync(process.cwd() + "/js/dnsapi.info.txt").toString()
let infos = parseDnsApiInfoFile(contents)
assert.deepEqual(infos[0].Name, '1984.hosting')
})
{
"Name": "OpenStack Designate API",
"Description": "Depends on OpenStackClient and python-desginateclient.\nYou will require Keystone V3 credentials loaded into your environment,\nwhich could be either password or v3 application credential type.\nDeprecated.\nRemoved.",
"Site": "https://docs.openstack.org/api-ref/dns/",
"Docs": "https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_openstack",
"Options": "usual\nOS_AUTH_URL Auth URL\nOS_AUTH_URL2 Auth URL. E.g. \"https://keystone.example.com:5000/\"\nOS_USERNAME Username. Default: \"root\".\nOS_PASSWORD Password\nOS_PASSWORD2 Password. Optional.",
"OptionsAlt": "advanced\nOS_PROJECT_DOMAIN_NAME Project domain name. E.g. \"Default\".\nOS_USER_DOMAIN_NAME User domain name. Default: \"Default\".",
"Issues": "https://github.com/acmesh-official/acme.sh/issues/3054",
"Author": "Andy Botting <andy@andybotting.com>",
"Deprecated": true,
"Removed": true,
"Opts": [
{
"Optional": false,
"Default": "",
"Name": "OS_AUTH_URL",
"Title": "Auth URL"
},
{
"Optional": false,
"Default": "",
"Name": "OS_AUTH_URL2",
"Title": "Auth URL",
"Description": "E.g. \"https://keystone.example.com:5000/\""
},
{
"Optional": false,
"Default": "root",
"Name": "OS_USERNAME",
"Title": "Username",
"Description": ""
},
{
"Optional": false,
"Default": "",
"Name": "OS_PASSWORD",
"Title": "Password"
},
{
"Optional": true,
"Default": "",
"Name": "OS_PASSWORD2",
"Title": "Password",
"Description": ""
}
],
"OptsAlt": [
{
"Optional": false,
"Default": "",
"Name": "OS_PROJECT_DOMAIN_NAME",
"Title": "Project domain name",
"Description": "E.g. \"Default\"."
},
{
"Optional": false,
"Default": "Default",
"Name": "OS_USER_DOMAIN_NAME",
"Title": "User domain name",
"Description": ""
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment