forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathaddon-verify.mjs
More file actions
executable file
·102 lines (89 loc) · 2.72 KB
/
addon-verify.mjs
File metadata and controls
executable file
·102 lines (89 loc) · 2.72 KB
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
#!/usr/bin/env node
// Extracts C++ addon examples from doc/api/addons.md into numbered test
// directories under test/addons/.
//
// Each code block to extract is preceded by a marker in the markdown:
//
// <!-- addon-verify-file worker_support/addon.cc -->
// ```cpp
// #include <node.h>
// ...
// ```
//
// This produces test/addons/01_worker_support/addon.cc.
// Sections are numbered in order of first appearance.
import { mkdirSync, writeFileSync } from 'node:fs';
import { open } from 'node:fs/promises';
import { join } from 'node:path';
import { parseArgs } from 'node:util';
const { values } = parseArgs({
options: {
input: { type: 'string' },
output: { type: 'string' },
},
});
if (!values.input || !values.output) {
console.error('Usage: addon-verify.mjs --input <file> --output <dir>');
process.exit(1);
}
const src = await open(values.input, 'r');
const MARKER_RE = /^<!--\s*addon-verify-file\s+(\S+?)\/(\S+)\s*-->$/;
const entries = [];
let nextBlockIsAddonVerifyFile = false;
let expectedClosingFenceMarker;
for await (const line of src.readLines()) {
if (expectedClosingFenceMarker) {
// We're inside a Addon snippet
if (line === expectedClosingFenceMarker) {
// End of the snippet
expectedClosingFenceMarker = null;
continue;
}
entries.at(-1).content += `${line}\n`;
}
if (nextBlockIsAddonVerifyFile) {
if (line) {
expectedClosingFenceMarker = line.replace(/\w/g, '');
nextBlockIsAddonVerifyFile = false;
}
continue;
}
const match = MARKER_RE.exec(line);
if (match) {
nextBlockIsAddonVerifyFile = true;
const [, dir, name] = match;
entries.push({ dir, name, content: '' });
}
}
// Collect files grouped by section directory name.
const sections = Map.groupBy(entries, (e) => e.dir);
let idx = 0;
for (const [name, files] of sections) {
const dirName = `${String(++idx).padStart(2, '0')}_${name}`;
const dir = join(values.output, dirName);
mkdirSync(dir, { recursive: true });
for (const file of files) {
let content = file.content;
if (file.name === 'test.js') {
content =
"'use strict';\n" +
"const common = require('../../common');\n" +
content.replace(
"'./build/Release/addon'",
// eslint-disable-next-line no-template-curly-in-string
'`./build/${common.buildType}/addon`',
);
}
writeFileSync(join(dir, file.name), content);
}
// Generate binding.gyp
const names = files.map((f) => f.name);
writeFileSync(join(dir, 'binding.gyp'), JSON.stringify({
targets: [{
target_name: 'addon',
sources: names,
includes: ['../common.gypi'],
}],
}));
console.log(`Generated ${dirName} with files: ${names.join(', ')}`);
}