Skip to content

Commit 11ff194

Browse files
authored
Automatically generate Web Types for the package based on current documentation (#3071)
1 parent 28b31f2 commit 11ff194

File tree

7 files changed

+637
-91
lines changed

7 files changed

+637
-91
lines changed

editors/jetbrains/htmx.svg

Lines changed: 46 additions & 0 deletions
Loading

editors/jetbrains/htmx.web-types.json

Lines changed: 393 additions & 85 deletions
Large diffs are not rendered by default.

editors/jetbrains/htmx_dark.svg

Lines changed: 46 additions & 0 deletions
Loading

package-lock.json

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

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@
2525
"unpkg": "dist/htmx.min.js",
2626
"web-types": "editors/jetbrains/htmx.web-types.json",
2727
"scripts": {
28-
"dist": "./scripts/dist.sh && npm run types-generate",
29-
"lint": "eslint src/htmx.js test/attributes/ test/core/ test/util/",
30-
"format": "eslint --fix src/htmx.js test/attributes/ test/core/ test/util/",
28+
"dist": "./scripts/dist.sh && npm run types-generate && npm run web-types-generate",
29+
"lint": "eslint src/htmx.js test/attributes/ test/core/ test/util/ scripts/*.mjs",
30+
"format": "eslint --fix src/htmx.js test/attributes/ test/core/ test/util/ scripts/*.mjs",
3131
"types-check": "tsc src/htmx.js --noEmit --checkJs --target es6 --lib dom,dom.iterable",
3232
"types-generate": "tsc dist/htmx.esm.js --declaration --emitDeclarationOnly --allowJs --outDir dist",
33+
"web-types-generate": "node ./scripts/generate-web-types.mjs",
3334
"test": "npm run lint && npm run types-check && mocha-chrome test/index.html",
3435
"www": "bash ./scripts/www.sh",
3536
"sha": "bash ./scripts/sha.sh"

scripts/generate-web-types.mjs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import fs from 'fs'
2+
3+
const classes = []
4+
const attributes = []
5+
const events = []
6+
7+
const rootPath = fs.existsSync('./www') ? './' : '../'
8+
9+
for (const file of fs.readdirSync(rootPath + 'www/content/attributes').sort()) {
10+
if (file.startsWith('hx-') && file.endsWith('.md')) {
11+
const name = file.slice(0, -3)
12+
const info = readAttributeInfo(name, rootPath + 'www/content/attributes/' + file)
13+
attributes.push({
14+
name,
15+
...info,
16+
'doc-url': 'https://htmx.org/attributes/' + name + '/'
17+
})
18+
}
19+
}
20+
21+
readClassInfo()
22+
readEventInfo()
23+
24+
const pkg = JSON.parse(fs.readFileSync(rootPath + 'package.json', { encoding: 'utf8' }))
25+
26+
const webTypes = {
27+
$schema: 'https://json.schemastore.org/web-types',
28+
name: 'htmx',
29+
version: pkg.version,
30+
'default-icon': './htmx.svg',
31+
'js-types-syntax': 'typescript',
32+
'description-markup': 'markdown',
33+
contributions: {
34+
html: {
35+
attributes
36+
},
37+
css: {
38+
classes
39+
},
40+
js: {
41+
events: [
42+
{
43+
name: 'HTMX event',
44+
pattern: {
45+
items: ['/js/htmx-events'],
46+
template: ['htmx:', '$...', '#item:HTMX event']
47+
}
48+
}
49+
],
50+
'htmx-events': events
51+
}
52+
}
53+
}
54+
55+
fs.writeFileSync(rootPath + 'editors/jetbrains/htmx.web-types.json', JSON.stringify(webTypes, null, 2))
56+
57+
function readAttributeInfo(name, file) {
58+
const content = fs.readFileSync(file, { encoding: 'utf8' })
59+
60+
const isInherited = content.indexOf('`' + name + '` is inherited') !== -1
61+
const isNotInherited = content.indexOf('`' + name + '` is not inherited') !== -1
62+
63+
const deprecated = content.indexOf('`' + name + '` has been deprecated') !== -1
64+
65+
const sections = {}
66+
67+
if (isInherited) {
68+
sections.Inherited = ''
69+
} else if (isNotInherited) {
70+
sections['Not Inherited'] = ''
71+
}
72+
73+
const descSections = /\+\+\+\n(?:[^\n]*\n)+\+\+\+\n\n((?:[^\n]+\n)+)(?:\n((?:[^\n]+\n)+))?(?:\n((?:[^\n]+\n)+))?/mg.exec(content)
74+
const para1 = descSections[1].trim()
75+
const para2 = descSections[2]?.trim()
76+
const para3 = descSections[3]?.trim()
77+
78+
let description = para1
79+
if (para2) {
80+
description += '\n\n' + para2
81+
}
82+
if (para2 && para2.endsWith(':') && para3) {
83+
description += '\n\n' + para3
84+
}
85+
86+
let pattern
87+
if (name === 'hx-on') {
88+
pattern = {
89+
or: [
90+
{
91+
items: ['/js/events'],
92+
template: ['hx-on:', '#...', '#item:JS event']
93+
},
94+
{
95+
items: ['/js/htmx-events'],
96+
template: ['hx-on::', '#...', '#item:HTMX event']
97+
}
98+
]
99+
}
100+
}
101+
102+
return {
103+
pattern,
104+
description,
105+
'description-sections': sections,
106+
deprecated: deprecated ? true : undefined
107+
}
108+
}
109+
110+
function readClassInfo() {
111+
const content = fs.readFileSync(rootPath + 'www/content/reference.md', { encoding: 'utf8' })
112+
const start = content.indexOf('| Class | Description |')
113+
const cssTable = content.slice(start, content.indexOf('</div>', start))
114+
const expr = /\| `([^`]+)` \| ([^\n]+)/mg
115+
let match = expr.exec(cssTable)
116+
while (match) {
117+
const name = match[1]
118+
if (name && name.startsWith('htmx-')) {
119+
classes.push({
120+
name,
121+
description: match[2].trim(),
122+
'doc-url': 'https://htmx.org/reference/#classes'
123+
})
124+
}
125+
match = expr.exec(cssTable)
126+
}
127+
}
128+
129+
function readEventInfo() {
130+
const content = fs.readFileSync(rootPath + 'www/content/events.md', { encoding: 'utf8' })
131+
const expr = /### Event - `([^`]+)`[^\n]*\n+((?:(?:[^#\n]|#####)[^\n]*\n+)+)/mg
132+
let match = expr.exec(content)
133+
while (match) {
134+
let name = match[1]
135+
if (name && name.startsWith('htmx:')) {
136+
name = name.slice(5)
137+
events.push({
138+
name,
139+
description: match[2],
140+
'doc-url': 'https://htmx.org/events/#htmx:' + name
141+
})
142+
}
143+
match = expr.exec(content)
144+
}
145+
}

www/content/attributes/hx-disable.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ useful as a backup for HTML escaping, when you include user generated content in
88
prevent malicious scripting attacks.
99

1010
The value of the tag is ignored, and it cannot be reversed by any content beneath it.
11-
11+
1212
## Notes
1313

1414
* `hx-disable` is inherited

0 commit comments

Comments
 (0)