bare-script 2.3.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -4
- package/bin/bare.js +3 -16
- package/bin/baredoc.js +10 -0
- package/lib/bare.js +87 -84
- package/lib/{bareDoc.js → baredoc.js} +134 -60
- package/lib/data.js +155 -158
- package/lib/library.js +794 -291
- package/lib/model.js +3 -3
- package/lib/options.js +72 -0
- package/lib/optionsNode.js +70 -0
- package/lib/parser.js +72 -70
- package/lib/runtime.js +107 -88
- package/lib/runtimeAsync.js +112 -87
- package/lib/value.js +268 -0
- package/package.json +3 -3
- package/bin/bareDoc.js +0 -23
package/README.md
CHANGED
|
@@ -3,8 +3,22 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/bare-script)
|
|
4
4
|
[](https://github.com/craigahobbs/bare-script/blob/main/LICENSE)
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
[BareScript](https://craigahobbs.github.io/bare-script/language/)
|
|
7
|
+
is a simple, lightweight, and portable programming language. Its Pythonic syntax is influenced by
|
|
8
|
+
JavaScript, C, and the Unix Shell. BareScript also has a
|
|
9
|
+
[library of built-in functions](#the-barescript-library)
|
|
10
|
+
for common programming operations. BareScript can be
|
|
11
|
+
[embedded within applications](#markdownup-a-markdown-viewer-with-barescript)
|
|
12
|
+
or used as a
|
|
13
|
+
stand-alone programming language using the
|
|
14
|
+
[command-line interface](#the-barescript-command-line-interface-cli).
|
|
15
|
+
|
|
16
|
+
There are two implementations of BareScript:
|
|
17
|
+
[BareScript for JavaScript](https://github.com/craigahobbs/bare-script#readme)
|
|
18
|
+
(this package) and
|
|
19
|
+
[BareScript for Python](https://github.com/craigahobbs/bare-script-py#readme).
|
|
20
|
+
Both implementations have 100% unit test coverage with identical unit test suites, so you can be
|
|
21
|
+
confident that BareScript will execute the same regardless of the underlying runtime environment.
|
|
8
22
|
|
|
9
23
|
|
|
10
24
|
## Links
|
|
@@ -70,7 +84,7 @@ import {parseScript} from 'bare-script/lib/parser.js';
|
|
|
70
84
|
// Parse the script
|
|
71
85
|
const script = parseScript(`\
|
|
72
86
|
# Fetch the BareScript library documentation JSON
|
|
73
|
-
docs = systemFetch('https://craigahobbs.github.io/bare-script/library/library.json')
|
|
87
|
+
docs = jsonParse(systemFetch('https://craigahobbs.github.io/bare-script/library/library.json'))
|
|
74
88
|
|
|
75
89
|
# Return the number of library functions
|
|
76
90
|
return 'The BareScript Library has ' + arrayLength(objectGet(docs, 'functions')) + ' functions'
|
|
@@ -83,7 +97,7 @@ console.log(await executeScriptAsync(script, {'fetchFn': fetch}));
|
|
|
83
97
|
This outputs:
|
|
84
98
|
|
|
85
99
|
~~~
|
|
86
|
-
The BareScript Library has
|
|
100
|
+
The BareScript Library has 105 functions
|
|
87
101
|
~~~
|
|
88
102
|
|
|
89
103
|
|
|
@@ -136,6 +150,10 @@ bare script.bare
|
|
|
136
150
|
**Note:** In the BareScript CLI, import statements and the
|
|
137
151
|
[systemFetch](https://craigahobbs.github.io/bare-script/library/#var.vGroup='System'&systemfetch)
|
|
138
152
|
function read non-URL paths from the local file system.
|
|
153
|
+
[systemFetch](https://craigahobbs.github.io/bare-script/library/#var.vGroup='System'&systemfetch)
|
|
154
|
+
calls with a non-URL path and a
|
|
155
|
+
[request body](https://craigahobbs.github.io/bare-script-py/library/model.html#var.vName='SystemFetchRequest')
|
|
156
|
+
write the body to the path.
|
|
139
157
|
|
|
140
158
|
|
|
141
159
|
## MarkdownUp, a Markdown Viewer with BareScript
|
package/bin/bare.js
CHANGED
|
@@ -2,22 +2,9 @@
|
|
|
2
2
|
// Licensed under the MIT License
|
|
3
3
|
// https://github.com/craigahobbs/bare-script/blob/main/LICENSE
|
|
4
4
|
|
|
5
|
-
import {argv, exit
|
|
5
|
+
import {argv, exit} from 'node:process';
|
|
6
|
+
import {fetchReadWrite, logStdout} from '../lib/optionsNode.js';
|
|
6
7
|
import {main} from '../lib/bare.js';
|
|
7
|
-
import {readFile} from 'node:fs/promises';
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
exit(await main({
|
|
12
|
-
argv,
|
|
13
|
-
'fetchFn': (fetchURL, fetchOptions) => {
|
|
14
|
-
if (rURL.test(fetchURL)) {
|
|
15
|
-
return fetch(fetchURL, fetchOptions);
|
|
16
|
-
}
|
|
17
|
-
return {
|
|
18
|
-
'ok': true,
|
|
19
|
-
'text': () => readFile(fetchURL, 'utf-8')
|
|
20
|
-
};
|
|
21
|
-
},
|
|
22
|
-
'logFn': (message) => stdout.write(`${message}\n`)
|
|
23
|
-
}));
|
|
10
|
+
exit(await main({argv, 'fetchFn': fetchReadWrite, 'logFn': logStdout}));
|
package/bin/baredoc.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Licensed under the MIT License
|
|
3
|
+
// https://github.com/craigahobbs/bare-script/blob/main/LICENSE
|
|
4
|
+
|
|
5
|
+
import {argv, exit} from 'node:process';
|
|
6
|
+
import {fetchReadWrite, logStdout} from '../lib/optionsNode.js';
|
|
7
|
+
import {main} from '../lib/baredoc.js';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
exit(await main({argv, 'fetchFn': fetchReadWrite, 'logFn': logStdout}));
|
package/lib/bare.js
CHANGED
|
@@ -5,23 +5,8 @@ import {parseExpression, parseScript} from './parser.js';
|
|
|
5
5
|
import {evaluateExpression} from './runtime.js';
|
|
6
6
|
import {executeScriptAsync} from './runtimeAsync.js';
|
|
7
7
|
import {lintScript} from './model.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// The command-line interface (CLI) help text
|
|
11
|
-
export const helpText = `\
|
|
12
|
-
usage: bare [-h] [-c CODE] [-d] [-v VAR EXPR] [filename ...]
|
|
13
|
-
|
|
14
|
-
The BareScript command-line interface
|
|
15
|
-
|
|
16
|
-
positional arguments:
|
|
17
|
-
filename
|
|
18
|
-
|
|
19
|
-
options:
|
|
20
|
-
-h, --help show this help message and exit
|
|
21
|
-
-c, --code CODE execute the BareScript code
|
|
22
|
-
-d, --debug enable debug mode
|
|
23
|
-
-s, --static perform static analysis
|
|
24
|
-
-v, --var VAR EXPR set a global variable to an expression value`;
|
|
8
|
+
import {urlFileRelative} from './options.js';
|
|
9
|
+
import {valueBoolean} from './value.js';
|
|
25
10
|
|
|
26
11
|
|
|
27
12
|
/**
|
|
@@ -29,8 +14,8 @@ options:
|
|
|
29
14
|
*
|
|
30
15
|
* @typedef {Object} BareOptions
|
|
31
16
|
* @property {string[]} argv - The process command-line arguments
|
|
32
|
-
* @property {function} fetchFn - The [fetch function]{@link module:lib/
|
|
33
|
-
* @property {function} logFn - The [log function]{@link module:lib/
|
|
17
|
+
* @property {function} fetchFn - The [fetch function]{@link module:lib/options~FetchFn}
|
|
18
|
+
* @property {function} logFn - The [log function]{@link module:lib/options~LogFn}
|
|
34
19
|
* @ignore
|
|
35
20
|
*/
|
|
36
21
|
|
|
@@ -43,53 +28,62 @@ options:
|
|
|
43
28
|
* @ignore
|
|
44
29
|
*/
|
|
45
30
|
export async function main(options) {
|
|
31
|
+
// Command line arguments
|
|
32
|
+
let args;
|
|
33
|
+
try {
|
|
34
|
+
args = parseArgs(options.argv);
|
|
35
|
+
} catch ({message}) {
|
|
36
|
+
options.logFn(`error: ${message}`);
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
if (args.help || args.scripts.length === 0) {
|
|
40
|
+
options.logFn(helpText);
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
|
|
46
44
|
let statusCode = 0;
|
|
47
|
-
let
|
|
45
|
+
let inlineCount = 0;
|
|
46
|
+
let errorName = null;
|
|
48
47
|
try {
|
|
49
|
-
|
|
48
|
+
// Evaluate the global variable expression arguments
|
|
49
|
+
const globals = {};
|
|
50
|
+
for (const [varName, varExpr] of Object.entries(args.var)) {
|
|
51
|
+
globals[varName] = evaluateExpression(parseExpression(varExpr));
|
|
52
|
+
}
|
|
50
53
|
|
|
51
|
-
//
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
throw Error(`Failed to load "${url}"`);
|
|
60
|
-
}
|
|
61
|
-
}));
|
|
62
|
-
const files = await Promise.all(responses.map(async (response, ixResponse) => {
|
|
63
|
-
const [url] = args.files[ixResponse];
|
|
64
|
-
let source = null;
|
|
65
|
-
if (response.ok) {
|
|
54
|
+
// Parse and execute all source files in order
|
|
55
|
+
for (const [scriptType, scriptValue] of args.scripts) {
|
|
56
|
+
// Get the script source
|
|
57
|
+
let scriptName;
|
|
58
|
+
let scriptSource;
|
|
59
|
+
if (scriptType === 'file') {
|
|
60
|
+
scriptName = scriptValue;
|
|
61
|
+
scriptSource = null;
|
|
66
62
|
try {
|
|
67
|
-
|
|
63
|
+
const scriptResponse = await options.fetchFn(scriptValue);
|
|
64
|
+
if (scriptResponse.ok) {
|
|
65
|
+
scriptSource = await scriptResponse.text();
|
|
66
|
+
}
|
|
68
67
|
} catch {
|
|
69
|
-
// Do nothing
|
|
68
|
+
// Do nothing...
|
|
70
69
|
}
|
|
70
|
+
if (scriptSource === null) {
|
|
71
|
+
throw Error(`Failed to load "${scriptValue}"`);
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
inlineCount += 1;
|
|
75
|
+
scriptName = `-c ${inlineCount}`;
|
|
76
|
+
scriptSource = scriptValue;
|
|
71
77
|
}
|
|
72
|
-
if (source === null) {
|
|
73
|
-
throw Error(`Failed to load "${url}"`);
|
|
74
|
-
}
|
|
75
|
-
return [url, source];
|
|
76
|
-
}));
|
|
77
|
-
|
|
78
|
-
// Parse the source files
|
|
79
|
-
const scripts = [];
|
|
80
|
-
for (const [file, source] of files) {
|
|
81
|
-
currentFile = file;
|
|
82
|
-
scripts.push([file, parseScript(source)]);
|
|
83
|
-
}
|
|
84
78
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
79
|
+
// Parse the script source
|
|
80
|
+
errorName = scriptName;
|
|
81
|
+
const script = parseScript(scriptSource);
|
|
88
82
|
|
|
89
83
|
// Run the bare-script linter?
|
|
90
84
|
if (args.static || args.debug) {
|
|
91
85
|
const warnings = lintScript(script);
|
|
92
|
-
const warningPrefix = `BareScript: Static analysis "${
|
|
86
|
+
const warningPrefix = `BareScript: Static analysis "${scriptName}" ...`;
|
|
93
87
|
if (warnings.length === 0) {
|
|
94
88
|
options.logFn(`${warningPrefix} OK`);
|
|
95
89
|
} else {
|
|
@@ -98,29 +92,31 @@ export async function main(options) {
|
|
|
98
92
|
options.logFn(`BareScript: ${warning}`);
|
|
99
93
|
}
|
|
100
94
|
if (args.static) {
|
|
101
|
-
|
|
95
|
+
statusCode = 1;
|
|
96
|
+
break;
|
|
102
97
|
}
|
|
103
98
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
99
|
+
}
|
|
100
|
+
if (args.static) {
|
|
101
|
+
continue;
|
|
109
102
|
}
|
|
110
103
|
|
|
111
104
|
// Execute the script
|
|
112
105
|
const timeBegin = performance.now();
|
|
113
|
-
// eslint-disable-next-line no-await-in-loop
|
|
114
106
|
const result = await executeScriptAsync(script, {
|
|
115
107
|
'debug': args.debug ?? false,
|
|
116
108
|
'fetchFn': options.fetchFn,
|
|
117
|
-
'globals':
|
|
118
|
-
'logFn':
|
|
109
|
+
'globals': globals,
|
|
110
|
+
'logFn': options.logFn,
|
|
119
111
|
'systemPrefix': 'https://craigahobbs.github.io/markdown-up/include/',
|
|
120
|
-
'urlFn':
|
|
112
|
+
'urlFn': scriptType === 'file' ? (url) => urlFileRelative(scriptName, url) : null
|
|
121
113
|
|
|
122
114
|
});
|
|
123
|
-
|
|
115
|
+
if (Number.isInteger(result) && result >= 0 && result <= 255) {
|
|
116
|
+
statusCode = result;
|
|
117
|
+
} else {
|
|
118
|
+
statusCode = valueBoolean(result) ? 1 : 0;
|
|
119
|
+
}
|
|
124
120
|
|
|
125
121
|
// Log script execution end with timing
|
|
126
122
|
if (args.debug) {
|
|
@@ -134,8 +130,8 @@ export async function main(options) {
|
|
|
134
130
|
}
|
|
135
131
|
}
|
|
136
132
|
} catch ({message}) {
|
|
137
|
-
if (
|
|
138
|
-
options.logFn(`${
|
|
133
|
+
if (errorName !== null) {
|
|
134
|
+
options.logFn(`${errorName}:`);
|
|
139
135
|
}
|
|
140
136
|
options.logFn(message);
|
|
141
137
|
statusCode = 1;
|
|
@@ -145,10 +141,6 @@ export async function main(options) {
|
|
|
145
141
|
}
|
|
146
142
|
|
|
147
143
|
|
|
148
|
-
// Regex to match a URL
|
|
149
|
-
const rURL = /^[a-z]+:/;
|
|
150
|
-
|
|
151
|
-
|
|
152
144
|
/**
|
|
153
145
|
* Parse the BareScript command-line interface (CLI) arguments
|
|
154
146
|
*
|
|
@@ -158,15 +150,14 @@ const rURL = /^[a-z]+:/;
|
|
|
158
150
|
* @ignore
|
|
159
151
|
*/
|
|
160
152
|
export function parseArgs(argv) {
|
|
161
|
-
const args = {'
|
|
162
|
-
let codeCount = 0;
|
|
153
|
+
const args = {'scripts': [], 'var': {}};
|
|
163
154
|
for (let iArg = 2; iArg < argv.length; iArg++) {
|
|
164
155
|
const arg = argv[iArg];
|
|
165
156
|
if (arg === '-c' || arg === '--code') {
|
|
166
157
|
if (iArg + 1 >= argv.length) {
|
|
167
|
-
throw new Error(
|
|
158
|
+
throw new Error('argument -c/--code: expected one argument');
|
|
168
159
|
}
|
|
169
|
-
args.
|
|
160
|
+
args.scripts.push(['code', argv[iArg + 1]]);
|
|
170
161
|
iArg++;
|
|
171
162
|
} else if (arg === '-d' || arg === '--debug') {
|
|
172
163
|
args.debug = true;
|
|
@@ -176,21 +167,33 @@ export function parseArgs(argv) {
|
|
|
176
167
|
args.static = true;
|
|
177
168
|
} else if (arg === '-v' || arg === '--var') {
|
|
178
169
|
if (iArg + 2 >= argv.length) {
|
|
179
|
-
throw new Error(
|
|
170
|
+
throw new Error('argument -v/--var: expected 2 arguments');
|
|
180
171
|
}
|
|
181
|
-
args.
|
|
172
|
+
args.var[argv[iArg + 1]] = argv[iArg + 2];
|
|
182
173
|
iArg += 2;
|
|
183
174
|
} else if (arg.startsWith('-')) {
|
|
184
|
-
throw new Error(`
|
|
175
|
+
throw new Error(`unrecognized arguments: ${arg}`);
|
|
185
176
|
} else {
|
|
186
|
-
args.
|
|
177
|
+
args.scripts.push(['file', arg]);
|
|
187
178
|
}
|
|
188
179
|
}
|
|
189
180
|
|
|
190
|
-
// Show help, if necessary
|
|
191
|
-
if (args.help || args.files.length === 0) {
|
|
192
|
-
throw new Error(helpText);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
181
|
return args;
|
|
196
182
|
}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
// The command-line interface (CLI) help text
|
|
186
|
+
export const helpText = `\
|
|
187
|
+
usage: bare [-h] [-c CODE] [-d] [-s] [-v VAR EXPR] [file ...]
|
|
188
|
+
|
|
189
|
+
The BareScript command-line interface
|
|
190
|
+
|
|
191
|
+
positional arguments:
|
|
192
|
+
file files to process
|
|
193
|
+
|
|
194
|
+
options:
|
|
195
|
+
-h, --help show this help message and exit
|
|
196
|
+
-c, --code CODE execute the BareScript code
|
|
197
|
+
-d, --debug enable debug mode
|
|
198
|
+
-s, --static perform static analysis
|
|
199
|
+
-v, --var VAR EXPR set a global variable to an expression value`;
|
|
@@ -1,74 +1,62 @@
|
|
|
1
1
|
// Licensed under the MIT License
|
|
2
2
|
// https://github.com/craigahobbs/bare-script/blob/main/LICENSE
|
|
3
3
|
|
|
4
|
+
import {valueJSON} from './value.js';
|
|
5
|
+
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
|
-
* BareScript
|
|
8
|
+
* BareScript documentation tool options
|
|
7
9
|
*
|
|
8
|
-
* @typedef {Object}
|
|
10
|
+
* @typedef {Object} BaredocOptions
|
|
9
11
|
* @property {string[]} argv - The process command-line arguments
|
|
10
|
-
* @property {function} fetchFn - The [fetch function]{@link module:lib/
|
|
11
|
-
* @property {function} logFn - The [log function]{@link module:lib/
|
|
12
|
+
* @property {function} fetchFn - The [fetch function]{@link module:lib/options~FetchFn}
|
|
13
|
+
* @property {function} logFn - The [log function]{@link module:lib/options~LogFn}
|
|
12
14
|
* @ignore
|
|
13
15
|
*/
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
|
-
* BareScript
|
|
19
|
+
* BareScript documentation tool main entry point
|
|
18
20
|
*
|
|
19
|
-
* @param {Object} options - The
|
|
21
|
+
* @param {Object} options - The [baredoc options]{@link module:lib/bare~BaredocOptions}
|
|
20
22
|
* @returns {Number} The exit code
|
|
21
23
|
* @ignore
|
|
22
24
|
*/
|
|
23
25
|
export async function main(options) {
|
|
26
|
+
// Command line arguments
|
|
27
|
+
let args;
|
|
24
28
|
try {
|
|
25
|
-
|
|
26
|
-
const responses = await Promise.all(urls.map(async (url) => {
|
|
27
|
-
try {
|
|
28
|
-
return await options.fetchFn(url);
|
|
29
|
-
} catch {
|
|
30
|
-
throw Error(`Failed to load "${url}"`);
|
|
31
|
-
}
|
|
32
|
-
}));
|
|
33
|
-
const files = await Promise.all(responses.map(async (response, ixResponse) => {
|
|
34
|
-
const url = urls[ixResponse];
|
|
35
|
-
let text = null;
|
|
36
|
-
if (response.ok) {
|
|
37
|
-
try {
|
|
38
|
-
text = await response.text();
|
|
39
|
-
} catch {
|
|
40
|
-
// Do nothing
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
if (text === null) {
|
|
44
|
-
throw Error(`Failed to load "${url}"`);
|
|
45
|
-
}
|
|
46
|
-
return [url, text];
|
|
47
|
-
}));
|
|
48
|
-
options.logFn(JSON.stringify(parseBareDoc(files), null, 4));
|
|
29
|
+
args = parseArgs(options.argv);
|
|
49
30
|
} catch ({message}) {
|
|
50
|
-
options.logFn(message);
|
|
31
|
+
options.logFn(`error: ${message}`);
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
if (args.help || args.files.length === 0) {
|
|
35
|
+
options.logFn(helpText);
|
|
51
36
|
return 1;
|
|
52
37
|
}
|
|
53
38
|
|
|
54
|
-
return 0;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Parse the library source for documentation tags
|
|
60
|
-
*
|
|
61
|
-
* @param {string[][]} files - The list of file name and source tuples
|
|
62
|
-
* @returns {Object} The [library documentation model]{@link https://craigahobbs.github.io/bare-script/library/#var.vDoc=1}
|
|
63
|
-
* @throws {Error}
|
|
64
|
-
* @ignore
|
|
65
|
-
*/
|
|
66
|
-
export function parseBareDoc(files) {
|
|
67
39
|
// Parse each source file line-by-line
|
|
68
40
|
const errors = [];
|
|
69
41
|
const funcs = {};
|
|
70
42
|
let func = null;
|
|
71
|
-
for (const
|
|
43
|
+
for (const file of args.files) {
|
|
44
|
+
// Read the source file
|
|
45
|
+
let source = null;
|
|
46
|
+
try {
|
|
47
|
+
const response = await options.fetchFn(file);
|
|
48
|
+
if (response.ok) {
|
|
49
|
+
source = await response.text();
|
|
50
|
+
}
|
|
51
|
+
} catch {
|
|
52
|
+
// Do nothing...
|
|
53
|
+
}
|
|
54
|
+
if (source === null) {
|
|
55
|
+
errors.push(`Failed to load "${file}"`);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Split the source lines and process documentation comments
|
|
72
60
|
const lines = source.split(rSplit);
|
|
73
61
|
for (const [ixLine, line] of lines.entries()) {
|
|
74
62
|
// function/group/doc/return documentation keywords?
|
|
@@ -137,21 +125,32 @@ export function parseBareDoc(files) {
|
|
|
137
125
|
continue;
|
|
138
126
|
}
|
|
139
127
|
|
|
140
|
-
//
|
|
141
|
-
let
|
|
142
|
-
let
|
|
143
|
-
if (
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
args.push(arg);
|
|
151
|
-
}
|
|
152
|
-
arg.doc.push(text);
|
|
128
|
+
// Get the function argument model, if it exists
|
|
129
|
+
let funcArgs = func.args ?? null;
|
|
130
|
+
let funcArg = null;
|
|
131
|
+
if (funcArgs !== null) {
|
|
132
|
+
funcArg = funcArgs.find((findArg) => findArg.name === name) ?? null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Ignore leading argument documentation blank lines
|
|
136
|
+
if (funcArg === null && textTrim === '') {
|
|
137
|
+
continue;
|
|
153
138
|
}
|
|
154
139
|
|
|
140
|
+
// Add the fuction model arguments member, if necessary
|
|
141
|
+
if (funcArgs === null) {
|
|
142
|
+
funcArgs = [];
|
|
143
|
+
func.args = funcArgs;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Add the function argument model, if necessary
|
|
147
|
+
if (funcArg === null) {
|
|
148
|
+
funcArg = {'name': name, 'doc': []};
|
|
149
|
+
funcArgs.push(funcArg);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Add the function argument documentation line
|
|
153
|
+
funcArg.doc.push(text);
|
|
155
154
|
continue;
|
|
156
155
|
}
|
|
157
156
|
|
|
@@ -188,10 +187,35 @@ export function parseBareDoc(files) {
|
|
|
188
187
|
|
|
189
188
|
// Errors?
|
|
190
189
|
if (errors.length !== 0) {
|
|
191
|
-
|
|
190
|
+
options.logFn(errors.join('\n'));
|
|
191
|
+
return 1;
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
|
|
194
|
+
// JSON-serialize the library documentation model
|
|
195
|
+
const libraryJSON = valueJSON(library);
|
|
196
|
+
|
|
197
|
+
// Output to stdout?
|
|
198
|
+
if (args.output === '-') {
|
|
199
|
+
options.logFn(libraryJSON);
|
|
200
|
+
} else {
|
|
201
|
+
// Output to file
|
|
202
|
+
let success = false;
|
|
203
|
+
try {
|
|
204
|
+
const response = await options.fetchFn(args.output, {'body': libraryJSON});
|
|
205
|
+
if (response.ok) {
|
|
206
|
+
await response.text();
|
|
207
|
+
success = true;
|
|
208
|
+
}
|
|
209
|
+
} catch {
|
|
210
|
+
// Do nothing
|
|
211
|
+
}
|
|
212
|
+
if (!success) {
|
|
213
|
+
options.logFn(`error: Failed to write "${args.output}"`);
|
|
214
|
+
return 1;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return 0;
|
|
195
219
|
}
|
|
196
220
|
|
|
197
221
|
|
|
@@ -200,3 +224,53 @@ const rKey = /^\s*(?:\/\/|#)\s*\$(?<key>function|group|doc|return):\s?(?<text>.*
|
|
|
200
224
|
const rArg = /^\s*(?:\/\/|#)\s*\$arg\s+(?<name>[A-Za-z_][A-Za-z0-9_]*(?:\.\.\.)?):\s?(?<text>.*)$/;
|
|
201
225
|
const rUnknown = /^\s*(?:\/\/|#)\s*\$(?<unknown>[^:]+):/;
|
|
202
226
|
const rSplit = /\r?\n/;
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Parse the baredoc command-line arguments
|
|
231
|
+
*
|
|
232
|
+
* @param {string} argv - The command-line arguments
|
|
233
|
+
* @returns {Object} The arguments object
|
|
234
|
+
* @throws {Error}
|
|
235
|
+
* @ignore
|
|
236
|
+
*/
|
|
237
|
+
export function parseArgs(argv) {
|
|
238
|
+
const args = {'files': [], 'output': '-'};
|
|
239
|
+
for (let iArg = 2; iArg < argv.length; iArg++) {
|
|
240
|
+
const arg = argv[iArg];
|
|
241
|
+
if (arg === '-o') {
|
|
242
|
+
if (iArg + 1 >= argv.length) {
|
|
243
|
+
throw new Error('argument -o: expected one argument');
|
|
244
|
+
}
|
|
245
|
+
args.output = argv[iArg + 1];
|
|
246
|
+
iArg++;
|
|
247
|
+
} else if (arg === '-h' || arg === '--help') {
|
|
248
|
+
args.help = true;
|
|
249
|
+
} else if (arg.startsWith('-')) {
|
|
250
|
+
throw new Error(`unrecognized arguments: ${arg}`);
|
|
251
|
+
} else {
|
|
252
|
+
args.files.push(arg);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Files is required
|
|
257
|
+
if (!args.help && args.files.length === 0) {
|
|
258
|
+
throw new Error('the following arguments are required: file');
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return args;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
// The baredoc command-line help text
|
|
266
|
+
export const helpText = `\
|
|
267
|
+
usage: baredoc [-h] [-o file] file [file ...]
|
|
268
|
+
|
|
269
|
+
The BareScript documentation tool
|
|
270
|
+
|
|
271
|
+
positional arguments:
|
|
272
|
+
file files to process
|
|
273
|
+
|
|
274
|
+
options:
|
|
275
|
+
-h, --help show this help message and exit
|
|
276
|
+
-o file write output to file (default is "-")`;
|