Skip to content

Commit 9917307

Browse files
committed
first. wip.
0 parents  commit 9917307

File tree

11 files changed

+941
-0
lines changed

11 files changed

+941
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/node_modules

README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# SYNOPSIS
2+
A minimal documentation system.
3+
4+
5+
# MOTIVATION
6+
Optimized for being learned, read and maintained. Generate a
7+
machine readable AST first, docs second.
8+
9+
10+
# SYNTAX
11+
Place tripple forward slashes in front of doc lines. See [this][0]
12+
example.
13+
14+
```c++
15+
/// <keyword> ...args
16+
```
17+
18+
19+
# KEYWORDS
20+
21+
#### namespace `name`
22+
Each header defines only one namespace.
23+
24+
#### class `name`
25+
Each class is associated with the last namespace.
26+
27+
#### method `name(...args)`
28+
Each method is associated with the last class.
29+
30+
#### overload `name(...args)`
31+
An overload is a type of method.
32+
33+
#### function `name(...args)`
34+
A function is a
35+
36+
#### return `type`
37+
Each return is associated with the last function, method or overload.
38+
39+
#### param `name` `text...`
40+
Each param is associaated with the last function or method.
41+
42+
#### comment `text...`
43+
Each comment is associated with the last keyword.
44+
45+
46+
# PARSER
47+
Outputs an AST. See [this][1] example.
48+
49+
50+
# COMPILER
51+
Outputs markdown or html.
52+
53+
[0]:/test/fixtures/index.hxx
54+
[1]:/test/fixtures/tree.json

bin/docs

Whitespace-only changes.

compile.js

Whitespace-only changes.

index.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
const fs = require('fs')
2+
const path = require('path')
3+
4+
const parse = require('./parse')
5+
6+
//
7+
// Find all header files except in ./deps or hidden dirs
8+
//
9+
const read = d => {
10+
const files = fs.readdirSync(d)
11+
let paths = files.map(f => path.join(d, f))
12+
13+
let headers = []
14+
15+
for (const i in paths) {
16+
const p = paths[i]
17+
const base = path.basename(p)
18+
19+
if (base[0] === '.' || (base === 'deps')) {
20+
continue
21+
}
22+
23+
const stat = fs.statSync(p)
24+
25+
if (stat.isDirectory()) {
26+
headers.push(...read(p))
27+
} else if (path.extname(p) === '.hxx') {
28+
headers.push(p)
29+
}
30+
}
31+
32+
return headers
33+
}
34+
35+
//
36+
// Find the package.json for any given header file
37+
//
38+
const findPackage = file => {
39+
const dir = path.dirname(file)
40+
const target = path.join(dir, 'package.json')
41+
42+
try {
43+
fs.statSync(target)
44+
} catch (ex) {
45+
return findPackage(path.join(dir, '..'))
46+
}
47+
48+
return require(target)
49+
}
50+
51+
const parseUrl = s => {
52+
let url = s.split('//')[1]
53+
if (!url) url = s.split('@')[1]
54+
55+
return url.replace(':', '/').replace('.git', '')
56+
}
57+
58+
//
59+
// Read all files from a path and parse their headers for docs
60+
//
61+
function main (argv) {
62+
const files = read(argv[0])
63+
64+
for (const file of files) {
65+
const pkg = findPackage(file)
66+
67+
if (!pkg) {
68+
console.error('missing package.json for', file)
69+
continue
70+
}
71+
72+
const s = fs.readFileSync(file, 'utf8')
73+
const output = parse(s)
74+
75+
output.repo = parseUrl(pkg.repository.url)
76+
console.log(JSON.stringify(output, 2, 2))
77+
}
78+
}
79+
80+
main(process.argv.slice(2))

package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "hyper-docs",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"bin": "bin/docs",
7+
"scripts": {
8+
"test": "node test"
9+
},
10+
"repository": {
11+
"type": "git",
12+
"url": "git+https://github.com/datcxx/hyper-docs.git"
13+
},
14+
"author": "",
15+
"license": "ISC",
16+
"bugs": {
17+
"url": "https://github.com/datcxx/hyper-docs/issues"
18+
},
19+
"homepage": "https://github.com/datcxx/hyper-docs#readme",
20+
"dependencies": {
21+
"marked": "^0.6.2"
22+
}
23+
}

parse.js

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//
2+
// Parse each line
3+
//
4+
module.exports = source => {
5+
const DOC_RE = /\/\/\/(.*)[\n|\r]/g
6+
7+
let docr = DOC_RE.exec(source)
8+
let lines = []
9+
10+
if (!docr) {
11+
return {}
12+
}
13+
14+
while (docr) {
15+
if (docr[1]) {
16+
lines.push(docr[1].trim())
17+
}
18+
19+
docr = DOC_RE.exec(source)
20+
}
21+
22+
const output = {
23+
namespace: [],
24+
classes: {},
25+
functions: [],
26+
}
27+
28+
let lastClass = null
29+
let lastMethod = null
30+
let hasConstructor = false
31+
let last = null
32+
33+
//
34+
// Parses all lines of the file, the rule for docs is
35+
// last-one-in-wins like css.
36+
//
37+
const parseLine = line => {
38+
const words = line.split(' ')
39+
const keyword = words.shift()
40+
41+
switch (keyword) {
42+
case 'namespace': {
43+
output.namespace.push(words[0])
44+
break
45+
}
46+
47+
case 'comment': {
48+
if (!last.comment) {
49+
last.comment = ''
50+
}
51+
last.comment += ' ' + words.join(' ')
52+
last.comment = last.comment.trim()
53+
break
54+
}
55+
56+
case 'class': {
57+
lastClass = words.shift()
58+
last = output.classes[lastClass] = []
59+
break
60+
}
61+
62+
case 'operator': {
63+
last = {
64+
operator: words.join(' ')
65+
}
66+
output.classes[lastClass].push(last)
67+
break
68+
}
69+
70+
case 'return': {
71+
const type = words[0]
72+
73+
last = {
74+
type,
75+
reference: type.includes('&'),
76+
pointer: type.includes('*')
77+
}
78+
79+
lastMethod['return'] = last
80+
break
81+
}
82+
83+
case 'param': {
84+
const identifier = words.shift()
85+
86+
if (!last.params[identifier]) {
87+
console.error(`Unknown parameter ${identifier}`)
88+
process.exit(1)
89+
}
90+
91+
last.params[identifier].comment += words.join(' ')
92+
break
93+
}
94+
95+
case 'property': {
96+
last = {
97+
property: words.join(' ')
98+
}
99+
100+
output.classes[lastClass].push(last)
101+
break
102+
}
103+
104+
case 'overload':
105+
case 'constructor':
106+
case 'method': {
107+
let params = {}
108+
109+
line = line.replace(/\((.*)\)/, (_, sig) => {
110+
sig.split(',').filter(Boolean).forEach(param => {
111+
params[param.match(/\w+$/)] = {
112+
const: !!param.match(/\s+const|const\s+/),
113+
reference: !!param.match(/&/),
114+
pointer: !!param.match(/\*/),
115+
comment: ''
116+
}
117+
})
118+
return ''
119+
})
120+
121+
last = lastMethod = {
122+
name: line.split(' ').pop(),
123+
type: 'method',
124+
overload: keyword === 'overload',
125+
params
126+
}
127+
128+
if (keyword === 'constructor' && hasConstructor) {
129+
lastMethod.overload = true
130+
}
131+
132+
if (keyword === 'constructor') {
133+
hasConstructor = true
134+
}
135+
136+
output.classes[lastClass].push(lastMethod)
137+
138+
break
139+
}
140+
}
141+
}
142+
143+
lines.forEach(parseLine)
144+
return output
145+
}

0 commit comments

Comments
 (0)