-
Notifications
You must be signed in to change notification settings - Fork 0
/
generate.js
128 lines (105 loc) · 4.05 KB
/
generate.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
const fs = require('fs')
const asciidoctor = require('asciidoctor')()
const camelCase = require('camelcase')
const jsdom = require("jsdom")
const GENERATED_COMMENT = "// This file is generated. Please don't modify it directly."
const ATTRIBUTION_COMMENT = `/**
* This is content from the [aim42 Method Reference](https://aim42.github.io/)
* by [Gernot Starke](https://www.gernotstarke.de/) and [community
* contributors](https://github.com/aim42/aim42/graphs/contributors), used under
* [CC BY-SA](https://creativecommons.org/licenses/by-sa/4.0/). If you distribute
* it, make sure to attribute the original authors.
*/`
function main() {
const doc = asciidoctor.loadFile('aim42/src/main/asciidoc/index.adoc', { safe: "safe" })
processStructuralNode(doc, "src")
}
function processStructuralNode(node, path) {
console.log("Processing structural node: " + path)
if (!fs.existsSync(path)) { fs.mkdirSync(path) }
generateDescriptionFile(node, path)
generateAtomicContentFile(node, path)
node.getSections().forEach(child => processStructuralNode(child, path + "/" + getSlug(child)))
}
function getSlug(section) {
return section.getId().toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/^-/, "")
}
function getRelativePathToRoot(path) {
const distance = path.split("/").length - 1
return distance === 0 ? "./" : "../".repeat(distance)
}
function getPlainText(html) {
const dom = new jsdom.JSDOM("<!DOCTYPE html><body>" + html + "</body>")
return dom.window.document.querySelector("body").textContent.trim();
}
function generateDescriptionFile(node, path) {
const description = generateDescription(node)
const isDocument = description.type === "document"
const type = isDocument ? "Document" : "Section"
const variable = isDocument ? "aim42" : camelCase(description.slug)
const sectionFile = `
${GENERATED_COMMENT}
import { ${type} } from '${getRelativePathToRoot(path)}types'
${ATTRIBUTION_COMMENT}
export const ${variable}: ${type} = ${JSON.stringify(description)}
`
fs.writeFileSync(path + '/index.ts', sectionFile, { flag: 'w' })
}
function generateDescription(node, atomic = false) {
const type = node.getNodeName();
switch (type) {
case "document":
return { type, ...generateStructuralNodeDescription(node, atomic) }
case "section":
return {
type,
slug: getSlug(node),
id: node.getId(),
sectionType: node.getSectionName(),
index: node.getIndex(),
caption: node.getCaption(),
...generateStructuralNodeDescription(node, atomic)
}
// case "image":
// return {
// type,
// id: node.getId(),
// ...generateTitledNodeDescription(node),
// alt: node.getAttribute("alt"),
// src: node.getAttribute("target")
// }
default:
// Note: if we want to divide other types further, "dlist" returns a weird data structure from getBlocks
return { type, content: node.convert() }
}
}
function generateTitledNodeDescription(node) {
return {
title: node.getTitle(),
titlePlain: getPlainText(node.getTitle()),
caption: node.getCaption(),
numeral: typeof node.getNumeral() === "object" ? undefined : node.getNumeral()
}
}
function generateStructuralNodeDescription(node, atomic = false) {
const description = generateTitledNodeDescription(node)
if (atomic) {
description.content = node.getContent()
} else {
description.children = node.getBlocks().map(b => generateDescription(b))
}
return description
}
function generateAtomicContentFile(node, path) {
const isDocument = node.getNodeName() === "document"
const type = isDocument ? "Document" : "Section"
const variable = (isDocument ? "aim42" : camelCase(getSlug(node))) + "Atomic"
const content = `
${GENERATED_COMMENT}
import { Atomic, ${type} } from '${getRelativePathToRoot(path)}types'
${ATTRIBUTION_COMMENT}
export const ${variable}: Atomic<${type}> = ${JSON.stringify(generateDescription(node, true))}
`
fs.writeFileSync(path + "/atomic.ts", content, { flag: 'w' })
}
main();