if (Deno.args.length !== 1) {
console.error(`
Usage: deno run --allow-read --allow-write ./fixtures/testgen.js ./commonmark.rs
`)
Deno.exit(1)
}
import testgen from 'npm:markdown-it-testgen@^0.1.6'
function rust_escape(s) {
if (s.match(/( $|\t)/m)) {
return '"' + s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/ $/mg, '\\x20').replace(/\t/g, '\\t') + '"'
}
if (s.match(/#"|"#/)) return 'r##"' + s + '"##'
return 'r#"' + s + '"#'
}
let identmap = new Set()
function ident(str) {
str = str.toLowerCase()
.replace(/[^a-z0-9]+/g, '_')
.replace(/^_+|_+$/g, '')
if (!str) str = 'unnamed'
let result = str
let idx = 0
while (identmap.has(result)) {
result = str + '_' + (++idx)
}
identmap.add(result)
return result
}
function generate(fixture) {
return `
#[test]
fn ${ident(fixture.header)}() {
let input = ${rust_escape(fixture.first.text.replace(/\n$/, ''))};
let output = ${rust_escape(fixture.second.text.replace(/\n$/, ''))};
run(input, output);
}
`.trim()
}
let input_raw = await Deno.readFile(Deno.args[0])
let input = new TextDecoder().decode(input_raw)
let lines = []
let state = 'passthrough'
for (let line of input.split('\n')) {
switch (state) {
case 'passthrough':
lines.push(line)
if (line.match(/^\/{4,}$/)) {
state = 'maybeheader'
}
break
case 'skipping':
if (line.match(/^\/{4,}$/)) {
lines.push(line)
state = 'maybeheader'
}
break
case 'maybeheader':
lines.push(line)
let match = line.match(/^\/{2,}\s+TESTGEN:\s*(.+)\s*$/)
if (match) {
let has_data = false
lines.push('#[rustfmt::skip]')
lines.push(`mod ${ident(match[1])} {`)
lines.push('use super::run;')
lines.push('// this part of the file is auto-generated')
lines.push('// don\'t edit it, otherwise your changes might be lost')
testgen.load(match[1], data => {
data.fixtures.forEach((data, idx) => {
has_data = true
if (idx++ > 0) lines.push('')
let generated = generate(data).replace(/\r?\n$/, '')
lines = lines.concat(generated.split('\n'))
})
})
lines.push('// end of auto-generated module')
lines.push('}')
if (!has_data) throw new Error(`no data found for ${match[1]}`)
state = 'skipping'
}
break
default:
throw Error('unknown state')
}
}
await Deno.rename(Deno.args[0], Deno.args[0] + '.old')
await Deno.writeFile(Deno.args[0], new TextEncoder().encode(lines.join('\n') + '\n'))